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: 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 let instance = &*(ptr as *mut T::Instance);
555 let imp = instance.imp();
556 let string: Borrowed<GString> = from_glib_borrow(stringptr);
557
558 imp.commit(string.as_str())
559}
560
561unsafe extern "C" fn im_context_delete_surrounding<T: IMContextImpl>(
562 ptr: *mut ffi::GtkIMContext,
563 offset: i32,
564 n_chars: i32,
565) -> glib::ffi::gboolean {
566 let instance = &*(ptr as *mut T::Instance);
567 let imp = instance.imp();
568
569 imp.delete_surrounding(offset, n_chars).into_glib()
570}
571
572unsafe extern "C" fn im_context_filter_keypress<T: IMContextImpl>(
573 ptr: *mut ffi::GtkIMContext,
574 eventptr: *mut gdk::ffi::GdkEvent,
575) -> glib::ffi::gboolean {
576 let instance = &*(ptr as *mut T::Instance);
577 let imp = instance.imp();
578 let event: Borrowed<gdk::Event> = from_glib_borrow(eventptr);
579 imp.filter_keypress(&event).into_glib()
580}
581
582unsafe extern "C" fn im_context_focus_in<T: IMContextImpl>(ptr: *mut ffi::GtkIMContext) {
583 let instance = &*(ptr as *mut T::Instance);
584 let imp = instance.imp();
585
586 imp.focus_in()
587}
588
589unsafe extern "C" fn im_context_focus_out<T: IMContextImpl>(ptr: *mut ffi::GtkIMContext) {
590 let instance = &*(ptr as *mut T::Instance);
591 let imp = instance.imp();
592
593 imp.focus_out()
594}
595
596unsafe extern "C" fn im_context_get_preedit_string<T: IMContextImpl>(
597 ptr: *mut ffi::GtkIMContext,
598 text_ptr: *mut *mut libc::c_char,
599 attrs_ptr: *mut *mut pango::ffi::PangoAttrList,
600 cursor_index_ptr: *mut libc::c_int,
601) {
602 let instance = &*(ptr as *mut T::Instance);
603 let imp = instance.imp();
604
605 let (text, attrs, cursor_idx) = imp.preedit_string();
606
607 *text_ptr = text.into_glib_ptr();
608 *cursor_index_ptr = cursor_idx;
609 *attrs_ptr = attrs.into_glib_ptr();
610}
611
612unsafe extern "C" fn im_context_get_surrounding<T: IMContextImpl>(
613 ptr: *mut ffi::GtkIMContext,
614 text_ptr: *mut *mut libc::c_char,
615 cursor_index_ptr: *mut libc::c_int,
616) -> glib::ffi::gboolean {
617 let instance = &*(ptr as *mut T::Instance);
618 let imp = instance.imp();
619
620 if let Some((text, cursor_idx)) = imp.surrounding() {
621 *text_ptr = text.into_glib_ptr();
622 *cursor_index_ptr = cursor_idx;
623 true.into_glib()
624 } else {
625 *text_ptr = std::ptr::null_mut();
626 *cursor_index_ptr = 0;
627 false.into_glib()
628 }
629}
630
631unsafe extern "C" fn im_context_preedit_changed<T: IMContextImpl>(ptr: *mut ffi::GtkIMContext) {
632 let instance = &*(ptr as *mut T::Instance);
633 let imp = instance.imp();
634
635 imp.preedit_changed()
636}
637
638unsafe extern "C" fn im_context_preedit_end<T: IMContextImpl>(ptr: *mut ffi::GtkIMContext) {
639 let instance = &*(ptr as *mut T::Instance);
640 let imp = instance.imp();
641
642 imp.preedit_end()
643}
644
645unsafe extern "C" fn im_context_preedit_start<T: IMContextImpl>(ptr: *mut ffi::GtkIMContext) {
646 let instance = &*(ptr as *mut T::Instance);
647 let imp = instance.imp();
648
649 imp.preedit_start()
650}
651
652unsafe extern "C" fn im_context_reset<T: IMContextImpl>(ptr: *mut ffi::GtkIMContext) {
653 let instance = &*(ptr as *mut T::Instance);
654 let imp = instance.imp();
655
656 imp.reset()
657}
658
659unsafe extern "C" fn im_context_retrieve_surrounding<T: IMContextImpl>(
660 ptr: *mut ffi::GtkIMContext,
661) -> glib::ffi::gboolean {
662 let instance = &*(ptr as *mut T::Instance);
663 let imp = instance.imp();
664
665 imp.retrieve_surrounding().into_glib()
666}
667
668unsafe extern "C" fn im_context_set_client_widget<T: IMContextImpl>(
669 ptr: *mut ffi::GtkIMContext,
670 widgetptr: *mut ffi::GtkWidget,
671) {
672 let instance = &*(ptr as *mut T::Instance);
673 let imp = instance.imp();
674 let widget: Borrowed<Option<Widget>> = from_glib_borrow(widgetptr);
675
676 imp.set_client_widget(widget.as_ref().as_ref());
677}
678
679unsafe extern "C" fn im_context_set_cursor_location<T: IMContextImpl>(
680 ptr: *mut ffi::GtkIMContext,
681 areaptr: *mut gdk::ffi::GdkRectangle,
682) {
683 let instance = &*(ptr as *mut T::Instance);
684 let imp = instance.imp();
685 let area = from_glib_borrow(areaptr);
686
687 imp.set_cursor_location(&area);
688}
689
690unsafe extern "C" fn im_context_set_surrounding<T: IMContextImpl>(
691 ptr: *mut ffi::GtkIMContext,
692 textptr: *const libc::c_char,
693 length: i32,
694 cursor_index: i32,
695) {
696 let instance = &*(ptr as *mut T::Instance);
697 let imp = instance.imp();
698 let text: Borrowed<GString> = from_glib_borrow(textptr);
699
700 let text = if length == -1 {
702 &text[..]
703 } else {
704 &text[0..(length as usize)]
705 };
706
707 imp.set_surrounding(text, cursor_index)
708}
709
710unsafe extern "C" fn im_context_set_use_preedit<T: IMContextImpl>(
711 ptr: *mut ffi::GtkIMContext,
712 use_preedit: glib::ffi::gboolean,
713) {
714 let instance = &*(ptr as *mut T::Instance);
715 let imp = instance.imp();
716
717 imp.set_use_preedit(from_glib(use_preedit))
718}
719
720#[cfg(feature = "v4_10")]
721unsafe extern "C" fn im_context_activate_osk<T: IMContextImpl>(ptr: *mut ffi::GtkIMContext) {
722 let instance = &*(ptr as *mut T::Instance);
723 let imp = instance.imp();
724
725 imp.activate_osk()
726}
727
728#[cfg(feature = "v4_14")]
729unsafe extern "C" fn im_context_activate_osk_with_event<T: IMContextImpl>(
730 ptr: *mut ffi::GtkIMContext,
731 eventptr: *mut gdk::ffi::GdkEvent,
732) -> glib::ffi::gboolean {
733 let instance = &*(ptr as *mut T::Instance);
734 let imp = instance.imp();
735
736 let event: Borrowed<Option<gdk::Event>> = from_glib_borrow(eventptr);
737
738 imp.activate_osk_with_event(event.as_ref().as_ref())
739 .into_glib()
740}
741
742#[cfg(feature = "v4_22")]
743unsafe extern "C" fn im_context_invalid_composition<T: IMContextImpl>(
744 ptr: *mut ffi::GtkIMContext,
745 stringptr: *const libc::c_char,
746) -> glib::ffi::gboolean {
747 let instance = &*(ptr as *mut T::Instance);
748 let imp = instance.imp();
749 let text: Borrowed<GString> = from_glib_borrow(stringptr);
750
751 imp.invalid_composition(&text).into_glib()
752}