1use glib::{translate::*, GString};
7use pango::AttrList;
8
9use crate::{ffi, prelude::*, subclass::prelude::*, IMContext, Widget};
10
11#[allow(clippy::upper_case_acronyms)]
12pub trait IMContextImpl: IMContextImplExt + ObjectImpl {
13 fn commit(&self, string: &str) {
15 self.parent_commit(string)
16 }
17 fn delete_surrounding(&self, offset: i32, n_chars: i32) -> bool {
44 self.parent_delete_surrounding(offset, n_chars)
45 }
46 fn filter_keypress(&self, event: &gdk::Event) -> bool {
58 self.parent_filter_keypress(event)
59 }
60 fn focus_in(&self) {
66 self.parent_focus_in()
67 }
68 fn focus_out(&self) {
74 self.parent_focus_out()
75 }
76 #[doc(alias = "get_preedit_string")]
97 fn preedit_string(&self) -> (GString, AttrList, i32) {
98 self.parent_preedit_string()
99 }
100 #[doc(alias = "get_surrounding")]
135 fn surrounding(&self) -> Option<(GString, i32)> {
136 self.parent_surrounding()
137 }
138 fn preedit_changed(&self) {
141 self.parent_preedit_changed()
142 }
143 fn preedit_end(&self) {
145 self.parent_preedit_end()
146 }
147 fn preedit_start(&self) {
149 self.parent_preedit_start()
150 }
151 fn reset(&self) {
156 self.parent_reset()
157 }
158 fn retrieve_surrounding(&self) -> bool {
161 self.parent_retrieve_surrounding()
162 }
163 fn set_client_widget<P: IsA<Widget>>(&self, widget: Option<&P>) {
172 self.parent_set_client_widget(widget)
173 }
174 fn set_cursor_location(&self, area: &gdk::Rectangle) {
181 self.parent_set_cursor_location(area)
182 }
183 #[cfg_attr(feature = "v4_2", deprecated = "Since 4.2")]
201 #[allow(deprecated)]
202 fn set_surrounding(&self, text: &str, cursor_index: i32) {
203 self.parent_set_surrounding(text, cursor_index)
204 }
205 fn set_use_preedit(&self, use_preedit: bool) {
214 self.parent_set_use_preedit(use_preedit)
215 }
216 #[cfg(feature = "v4_10")]
217 #[cfg_attr(docsrs, doc(cfg(feature = "v4_10")))]
218 fn activate_osk(&self) {
219 self.parent_activate_osk()
220 }
221 #[cfg(feature = "v4_14")]
222 #[cfg_attr(docsrs, doc(cfg(feature = "v4_14")))]
223 fn activate_osk_with_event(&self, event: Option<&gdk::Event>) -> bool {
224 self.parent_activate_osk_with_event(event)
225 }
226}
227
228mod sealed {
229 pub trait Sealed {}
230 impl<T: super::IMContextImplExt> Sealed for T {}
231}
232
233#[allow(clippy::upper_case_acronyms)]
234pub trait IMContextImplExt: sealed::Sealed + ObjectSubclass {
235 fn parent_commit(&self, string: &str) {
236 unsafe {
237 let data = Self::type_data();
238 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkIMContextClass;
239 if let Some(f) = (*parent_class).commit {
240 f(
241 self.obj().unsafe_cast_ref::<IMContext>().to_glib_none().0,
242 string.to_glib_none().0,
243 );
244 }
245 }
246 }
247
248 fn parent_delete_surrounding(&self, offset: i32, n_chars: i32) -> bool {
250 unsafe {
251 let data = Self::type_data();
252 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkIMContextClass;
253 if let Some(f) = (*parent_class).delete_surrounding {
254 from_glib(f(
255 self.obj().unsafe_cast_ref::<IMContext>().to_glib_none().0,
256 offset,
257 n_chars,
258 ))
259 } else {
260 false
261 }
262 }
263 }
264
265 fn parent_filter_keypress(&self, event: &gdk::Event) -> bool {
267 unsafe {
268 let data = Self::type_data();
269 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkIMContextClass;
270 if let Some(f) = (*parent_class).filter_keypress {
271 from_glib(f(
272 self.obj().unsafe_cast_ref::<IMContext>().to_glib_none().0,
273 event.to_glib_none().0,
274 ))
275 } else {
276 false
277 }
278 }
279 }
280
281 fn parent_focus_in(&self) {
282 unsafe {
283 let data = Self::type_data();
284 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkIMContextClass;
285 if let Some(f) = (*parent_class).focus_in {
286 f(self.obj().unsafe_cast_ref::<IMContext>().to_glib_none().0)
287 }
288 }
289 }
290
291 fn parent_focus_out(&self) {
292 unsafe {
293 let data = Self::type_data();
294 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkIMContextClass;
295 if let Some(f) = (*parent_class).focus_out {
296 f(self.obj().unsafe_cast_ref::<IMContext>().to_glib_none().0)
297 }
298 }
299 }
300
301 fn parent_surrounding(&self) -> Option<(GString, i32)> {
302 unsafe {
303 let data = Self::type_data();
304 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkIMContextClass;
305 if let Some(f) = (*parent_class).get_surrounding {
306 let mut text = std::ptr::null_mut();
307 let mut cursor_index = std::mem::MaybeUninit::uninit();
308 let ret = from_glib(f(
309 self.obj().unsafe_cast_ref::<IMContext>().to_glib_none().0,
310 &mut text,
311 cursor_index.as_mut_ptr(),
312 ));
313 if ret {
314 return Some((from_glib_full(text), cursor_index.assume_init()));
315 }
316 }
317 None
318 }
319 }
320
321 fn parent_preedit_string(&self) -> (GString, AttrList, i32) {
322 unsafe {
323 let data = Self::type_data();
324 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkIMContextClass;
325 let f = (*parent_class)
326 .get_preedit_string
327 .expect("No parent class impl for \"get_preedit_string\"");
328 let mut string = std::ptr::null_mut();
329 let mut attrs = std::ptr::null_mut();
330 let mut cursor_pos = std::mem::MaybeUninit::uninit();
331 f(
332 self.obj().unsafe_cast_ref::<IMContext>().to_glib_none().0,
333 &mut string,
334 &mut attrs,
335 cursor_pos.as_mut_ptr(),
336 );
337 (
338 from_glib_full(string),
339 from_glib_full(attrs),
340 cursor_pos.assume_init(),
341 )
342 }
343 }
344
345 fn parent_preedit_changed(&self) {
346 unsafe {
347 let data = Self::type_data();
348 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkIMContextClass;
349 if let Some(f) = (*parent_class).preedit_changed {
350 f(self.obj().unsafe_cast_ref::<IMContext>().to_glib_none().0)
351 }
352 }
353 }
354
355 fn parent_preedit_end(&self) {
356 unsafe {
357 let data = Self::type_data();
358 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkIMContextClass;
359 if let Some(f) = (*parent_class).preedit_end {
360 f(self.obj().unsafe_cast_ref::<IMContext>().to_glib_none().0)
361 }
362 }
363 }
364
365 fn parent_preedit_start(&self) {
366 unsafe {
367 let data = Self::type_data();
368 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkIMContextClass;
369 if let Some(f) = (*parent_class).preedit_start {
370 f(self.obj().unsafe_cast_ref::<IMContext>().to_glib_none().0)
371 }
372 }
373 }
374
375 fn parent_reset(&self) {
376 unsafe {
377 let data = Self::type_data();
378 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkIMContextClass;
379 if let Some(f) = (*parent_class).reset {
380 f(self.obj().unsafe_cast_ref::<IMContext>().to_glib_none().0)
381 }
382 }
383 }
384
385 fn parent_retrieve_surrounding(&self) -> bool {
387 unsafe {
388 let data = Self::type_data();
389 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkIMContextClass;
390 if let Some(f) = (*parent_class).retrieve_surrounding {
391 from_glib(f(self
392 .obj()
393 .unsafe_cast_ref::<IMContext>()
394 .to_glib_none()
395 .0))
396 } else {
397 false
398 }
399 }
400 }
401
402 fn parent_set_client_widget<P: IsA<Widget>>(&self, widget: Option<&P>) {
403 unsafe {
404 let data = Self::type_data();
405 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkIMContextClass;
406 if let Some(f) = (*parent_class).set_client_widget {
407 f(
408 self.obj().unsafe_cast_ref::<IMContext>().to_glib_none().0,
409 widget.map(|p| p.as_ref()).to_glib_none().0,
410 )
411 }
412 }
413 }
414
415 fn parent_set_cursor_location(&self, area: &gdk::Rectangle) {
416 unsafe {
417 let data = Self::type_data();
418 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkIMContextClass;
419 if let Some(f) = (*parent_class).set_cursor_location {
420 f(
421 self.obj().unsafe_cast_ref::<IMContext>().to_glib_none().0,
422 area.to_glib_none().0 as *mut _,
423 );
424 }
425 }
426 }
427
428 #[cfg_attr(feature = "v4_2", deprecated = "Since 4.2")]
429 #[allow(deprecated)]
430 fn parent_set_surrounding(&self, text: &str, cursor_index: i32) {
431 unsafe {
432 let data = Self::type_data();
433 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkIMContextClass;
434 if let Some(f) = (*parent_class).set_surrounding {
435 f(
436 self.obj().unsafe_cast_ref::<IMContext>().to_glib_none().0,
437 text.to_glib_none().0,
438 text.len() as i32,
439 cursor_index,
440 )
441 }
442 }
443 }
444
445 fn parent_set_use_preedit(&self, use_preedit: bool) {
446 unsafe {
447 let data = Self::type_data();
448 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkIMContextClass;
449 if let Some(f) = (*parent_class).set_use_preedit {
450 f(
451 self.obj().unsafe_cast_ref::<IMContext>().to_glib_none().0,
452 use_preedit.into_glib(),
453 )
454 }
455 }
456 }
457
458 #[cfg(feature = "v4_10")]
459 #[cfg_attr(docsrs, doc(cfg(feature = "v4_10")))]
460 fn parent_activate_osk(&self) {
461 unsafe {
462 let data = Self::type_data();
463 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkIMContextClass;
464 if let Some(f) = (*parent_class).activate_osk {
465 f(self.obj().unsafe_cast_ref::<IMContext>().to_glib_none().0)
466 }
467 }
468 }
469
470 #[cfg(feature = "v4_14")]
471 #[cfg_attr(docsrs, doc(cfg(feature = "v4_14")))]
472 fn parent_activate_osk_with_event(&self, event: Option<&gdk::Event>) -> bool {
473 unsafe {
474 let data = Self::type_data();
475 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkIMContextClass;
476 if let Some(f) = (*parent_class).activate_osk_with_event {
477 from_glib(f(
478 self.obj().unsafe_cast_ref::<IMContext>().to_glib_none().0,
479 event.to_glib_none().0,
480 ))
481 } else {
482 false
483 }
484 }
485 }
486}
487
488impl<T: IMContextImpl> IMContextImplExt for T {}
489
490unsafe impl<T: IMContextImpl> IsSubclassable<T> for IMContext {
491 fn class_init(class: &mut glib::Class<Self>) {
492 Self::parent_class_init::<T>(class);
493
494 assert_initialized_main_thread!();
495
496 let klass = class.as_mut();
497 klass.commit = Some(im_context_commit::<T>);
498 klass.delete_surrounding = Some(im_context_delete_surrounding::<T>);
499 klass.filter_keypress = Some(im_context_filter_keypress::<T>);
500 klass.focus_in = Some(im_context_focus_in::<T>);
501 klass.focus_out = Some(im_context_focus_out::<T>);
502 klass.get_preedit_string = Some(im_context_get_preedit_string::<T>);
503 klass.get_surrounding = Some(im_context_get_surrounding::<T>);
504 klass.preedit_changed = Some(im_context_preedit_changed::<T>);
505 klass.preedit_end = Some(im_context_preedit_end::<T>);
506 klass.preedit_start = Some(im_context_preedit_start::<T>);
507 klass.reset = Some(im_context_reset::<T>);
508 klass.retrieve_surrounding = Some(im_context_retrieve_surrounding::<T>);
509 klass.set_client_widget = Some(im_context_set_client_widget::<T>);
510 klass.set_cursor_location = Some(im_context_set_cursor_location::<T>);
511 klass.set_surrounding = Some(im_context_set_surrounding::<T>);
512 klass.set_use_preedit = Some(im_context_set_use_preedit::<T>);
513 #[cfg(feature = "v4_10")]
514 #[cfg_attr(docsrs, doc(cfg(feature = "v4_10")))]
515 {
516 klass.activate_osk = Some(im_context_activate_osk::<T>);
517 };
518 #[cfg(feature = "v4_14")]
519 #[cfg_attr(docsrs, doc(cfg(feature = "v4_14")))]
520 {
521 klass.activate_osk_with_event = Some(im_context_activate_osk_with_event::<T>);
522 };
523 }
524}
525
526unsafe extern "C" fn im_context_commit<T: IMContextImpl>(
527 ptr: *mut ffi::GtkIMContext,
528 stringptr: *const libc::c_char,
529) {
530 let instance = &*(ptr as *mut T::Instance);
531 let imp = instance.imp();
532 let string: Borrowed<GString> = from_glib_borrow(stringptr);
533
534 imp.commit(string.as_str())
535}
536
537unsafe extern "C" fn im_context_delete_surrounding<T: IMContextImpl>(
538 ptr: *mut ffi::GtkIMContext,
539 offset: i32,
540 n_chars: i32,
541) -> glib::ffi::gboolean {
542 let instance = &*(ptr as *mut T::Instance);
543 let imp = instance.imp();
544
545 imp.delete_surrounding(offset, n_chars).into_glib()
546}
547
548unsafe extern "C" fn im_context_filter_keypress<T: IMContextImpl>(
549 ptr: *mut ffi::GtkIMContext,
550 eventptr: *mut gdk::ffi::GdkEvent,
551) -> glib::ffi::gboolean {
552 let instance = &*(ptr as *mut T::Instance);
553 let imp = instance.imp();
554 let event: Borrowed<gdk::Event> = from_glib_borrow(eventptr);
555 imp.filter_keypress(&event).into_glib()
556}
557
558unsafe extern "C" fn im_context_focus_in<T: IMContextImpl>(ptr: *mut ffi::GtkIMContext) {
559 let instance = &*(ptr as *mut T::Instance);
560 let imp = instance.imp();
561
562 imp.focus_in()
563}
564
565unsafe extern "C" fn im_context_focus_out<T: IMContextImpl>(ptr: *mut ffi::GtkIMContext) {
566 let instance = &*(ptr as *mut T::Instance);
567 let imp = instance.imp();
568
569 imp.focus_out()
570}
571
572unsafe extern "C" fn im_context_get_preedit_string<T: IMContextImpl>(
573 ptr: *mut ffi::GtkIMContext,
574 text_ptr: *mut *mut libc::c_char,
575 attrs_ptr: *mut *mut pango::ffi::PangoAttrList,
576 cursor_index_ptr: *mut libc::c_int,
577) {
578 let instance = &*(ptr as *mut T::Instance);
579 let imp = instance.imp();
580
581 let (text, attrs, cursor_idx) = imp.preedit_string();
582
583 *text_ptr = text.into_glib_ptr();
584 *cursor_index_ptr = cursor_idx;
585 *attrs_ptr = attrs.into_glib_ptr();
586}
587
588unsafe extern "C" fn im_context_get_surrounding<T: IMContextImpl>(
589 ptr: *mut ffi::GtkIMContext,
590 text_ptr: *mut *mut libc::c_char,
591 cursor_index_ptr: *mut libc::c_int,
592) -> glib::ffi::gboolean {
593 let instance = &*(ptr as *mut T::Instance);
594 let imp = instance.imp();
595
596 if let Some((text, cursor_idx)) = imp.surrounding() {
597 *text_ptr = text.into_glib_ptr();
598 *cursor_index_ptr = cursor_idx;
599 true.into_glib()
600 } else {
601 *text_ptr = std::ptr::null_mut();
602 *cursor_index_ptr = 0;
603 false.into_glib()
604 }
605}
606
607unsafe extern "C" fn im_context_preedit_changed<T: IMContextImpl>(ptr: *mut ffi::GtkIMContext) {
608 let instance = &*(ptr as *mut T::Instance);
609 let imp = instance.imp();
610
611 imp.preedit_changed()
612}
613
614unsafe extern "C" fn im_context_preedit_end<T: IMContextImpl>(ptr: *mut ffi::GtkIMContext) {
615 let instance = &*(ptr as *mut T::Instance);
616 let imp = instance.imp();
617
618 imp.preedit_end()
619}
620
621unsafe extern "C" fn im_context_preedit_start<T: IMContextImpl>(ptr: *mut ffi::GtkIMContext) {
622 let instance = &*(ptr as *mut T::Instance);
623 let imp = instance.imp();
624
625 imp.preedit_start()
626}
627
628unsafe extern "C" fn im_context_reset<T: IMContextImpl>(ptr: *mut ffi::GtkIMContext) {
629 let instance = &*(ptr as *mut T::Instance);
630 let imp = instance.imp();
631
632 imp.reset()
633}
634
635unsafe extern "C" fn im_context_retrieve_surrounding<T: IMContextImpl>(
636 ptr: *mut ffi::GtkIMContext,
637) -> glib::ffi::gboolean {
638 let instance = &*(ptr as *mut T::Instance);
639 let imp = instance.imp();
640
641 imp.retrieve_surrounding().into_glib()
642}
643
644unsafe extern "C" fn im_context_set_client_widget<T: IMContextImpl>(
645 ptr: *mut ffi::GtkIMContext,
646 widgetptr: *mut ffi::GtkWidget,
647) {
648 let instance = &*(ptr as *mut T::Instance);
649 let imp = instance.imp();
650 let widget: Borrowed<Option<Widget>> = from_glib_borrow(widgetptr);
651
652 imp.set_client_widget(widget.as_ref().as_ref());
653}
654
655unsafe extern "C" fn im_context_set_cursor_location<T: IMContextImpl>(
656 ptr: *mut ffi::GtkIMContext,
657 areaptr: *mut gdk::ffi::GdkRectangle,
658) {
659 let instance = &*(ptr as *mut T::Instance);
660 let imp = instance.imp();
661 let area = from_glib_borrow(areaptr);
662
663 imp.set_cursor_location(&area);
664}
665
666unsafe extern "C" fn im_context_set_surrounding<T: IMContextImpl>(
667 ptr: *mut ffi::GtkIMContext,
668 textptr: *const libc::c_char,
669 length: i32,
670 cursor_index: i32,
671) {
672 let instance = &*(ptr as *mut T::Instance);
673 let imp = instance.imp();
674 let text: Borrowed<GString> = from_glib_borrow(textptr);
675
676 let text = if length == -1 {
678 &text[..]
679 } else {
680 &text[0..(length as usize)]
681 };
682
683 imp.set_surrounding(text, cursor_index)
684}
685
686unsafe extern "C" fn im_context_set_use_preedit<T: IMContextImpl>(
687 ptr: *mut ffi::GtkIMContext,
688 use_preedit: glib::ffi::gboolean,
689) {
690 let instance = &*(ptr as *mut T::Instance);
691 let imp = instance.imp();
692
693 imp.set_use_preedit(from_glib(use_preedit))
694}
695
696#[cfg(feature = "v4_10")]
697#[cfg_attr(docsrs, doc(cfg(feature = "v4_10")))]
698unsafe extern "C" fn im_context_activate_osk<T: IMContextImpl>(ptr: *mut ffi::GtkIMContext) {
699 let instance = &*(ptr as *mut T::Instance);
700 let imp = instance.imp();
701
702 imp.activate_osk()
703}
704
705#[cfg(feature = "v4_14")]
706#[cfg_attr(docsrs, doc(cfg(feature = "v4_14")))]
707unsafe extern "C" fn im_context_activate_osk_with_event<T: IMContextImpl>(
708 ptr: *mut ffi::GtkIMContext,
709 eventptr: *mut gdk::ffi::GdkEvent,
710) -> glib::ffi::gboolean {
711 let instance = &*(ptr as *mut T::Instance);
712 let imp = instance.imp();
713
714 let event: Borrowed<Option<gdk::Event>> = from_glib_borrow(eventptr);
715
716 imp.activate_osk_with_event(event.as_ref().as_ref())
717 .into_glib()
718}