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