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