1use std::{boxed::Box as Box_, collections::HashMap, fmt, future::Future};
7
8use glib::{
9    clone::Downgrade,
10    property::{Property, PropertyGet},
11    subclass::SignalId,
12    translate::*,
13    GString, Variant,
14};
15
16use crate::{
17    ffi, prelude::*, subclass::prelude::*, Accessible, AccessibleRole, Buildable, BuilderRustScope,
18    BuilderScope, ConstraintTarget, DirectionType, LayoutManager, Orientation, Shortcut,
19    SizeRequestMode, Snapshot, StateFlags, SystemSetting, TextDirection, Tooltip, Widget,
20};
21
22#[derive(Debug, Default)]
23struct Internal {
24    pub(crate) actions: HashMap<String, glib::ffi::gpointer>,
25    pub(crate) scope: Option<*mut <<BuilderRustScope as glib::object::ObjectSubclassIs>::Subclass as ObjectSubclass>::Instance>,
26}
27unsafe impl Sync for Internal {}
28unsafe impl Send for Internal {}
29
30pub struct WidgetActionIter(*mut ffi::GtkWidgetClass, u32);
31
32pub struct WidgetAction(
33    glib::Type,
34    GString,
35    Option<glib::VariantType>,
36    Option<GString>,
37);
38
39impl WidgetAction {
40    pub fn owner(&self) -> glib::Type {
43        self.0
44    }
45
46    pub fn name(&self) -> &str {
49        self.1.as_ref()
50    }
51
52    pub fn parameter_type(&self) -> Option<&glib::VariantType> {
55        self.2.as_ref()
56    }
57
58    pub fn property_name(&self) -> Option<&str> {
61        self.3.as_ref().map(|s| s.as_ref())
62    }
63}
64
65impl fmt::Debug for WidgetAction {
66    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67        f.debug_struct("WidgetAction")
68            .field("owner", &self.owner())
69            .field("name", &self.name())
70            .field("parameter_type", &self.parameter_type())
71            .field("property_name", &self.property_name())
72            .finish()
73    }
74}
75
76impl Iterator for WidgetActionIter {
77    type Item = WidgetAction;
78
79    fn next(&mut self) -> Option<Self::Item> {
80        unsafe {
81            let mut owner = std::mem::MaybeUninit::uninit();
82            let mut action_name_ptr = std::ptr::null();
83            let mut parameter_type = std::ptr::null();
84            let mut property_name_ptr = std::ptr::null();
85            let found: bool = from_glib(ffi::gtk_widget_class_query_action(
86                self.0,
87                self.1,
88                owner.as_mut_ptr(),
89                &mut action_name_ptr,
90                &mut parameter_type,
91                &mut property_name_ptr,
92            ));
93            if found {
94                self.1 += 1;
95                let property_name: Option<GString> = from_glib_none(property_name_ptr);
96                let action_name: GString = from_glib_none(action_name_ptr);
97
98                Some(WidgetAction(
99                    from_glib(owner.assume_init()),
100                    action_name,
101                    from_glib_none(parameter_type),
102                    property_name,
103                ))
104            } else {
105                None
106            }
107        }
108    }
109}
110
111impl std::iter::FusedIterator for WidgetActionIter {}
112
113pub trait WidgetImpl:
114    ObjectImpl
115    + ObjectSubclass<Type: IsA<Widget> + IsA<Accessible> + IsA<Buildable> + IsA<ConstraintTarget>>
116{
117    fn compute_expand(&self, hexpand: &mut bool, vexpand: &mut bool) {
120        self.parent_compute_expand(hexpand, vexpand)
121    }
122
123    fn contains(&self, x: f64, y: f64) -> bool {
136        self.parent_contains(x, y)
137    }
138
139    fn direction_changed(&self, previous_direction: TextDirection) {
142        self.parent_direction_changed(previous_direction)
143    }
144
145    fn focus(&self, direction_type: DirectionType) -> bool {
147        self.parent_focus(direction_type)
148    }
149
150    #[doc(alias = "get_request_mode")]
162    fn request_mode(&self) -> SizeRequestMode {
163        self.parent_request_mode()
164    }
165
166    fn grab_focus(&self) -> bool {
180        self.parent_grab_focus()
181    }
182
183    #[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
191    #[allow(deprecated)]
192    fn hide(&self) {
193        self.parent_hide()
194    }
195
196    fn keynav_failed(&self, direction_type: DirectionType) -> bool {
233        self.parent_keynav_failed(direction_type)
234    }
235
236    fn map(&self) {
240        self.parent_map()
241    }
242
243    fn measure(&self, orientation: Orientation, for_size: i32) -> (i32, i32, i32, i32) {
277        self.parent_measure(orientation, for_size)
278    }
279
280    fn mnemonic_activate(&self, group_cycling: bool) -> bool {
288        self.parent_mnemonic_activate(group_cycling)
289    }
290
291    fn move_focus(&self, direction_type: DirectionType) {
293        self.parent_move_focus(direction_type)
294    }
295
296    fn query_tooltip(&self, x: i32, y: i32, keyboard_tooltip: bool, tooltip: &Tooltip) -> bool {
300        self.parent_query_tooltip(x, y, keyboard_tooltip, tooltip)
301    }
302
303    fn realize(&self) {
320        self.parent_realize()
321    }
322
323    fn root(&self) {
326        self.parent_root()
327    }
328
329    fn set_focus_child(&self, child: Option<&Widget>) {
338        self.parent_set_focus_child(child)
339    }
340
341    #[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
356    #[allow(deprecated)]
357    fn show(&self) {
358        self.parent_show()
359    }
360
361    fn size_allocate(&self, width: i32, height: i32, baseline: i32) {
364        self.parent_size_allocate(width, height, baseline)
365    }
366
367    fn snapshot(&self, snapshot: &Snapshot) {
369        self.parent_snapshot(snapshot)
370    }
371
372    fn state_flags_changed(&self, state_flags: &StateFlags) {
375        self.parent_state_flags_changed(state_flags)
376    }
377
378    fn system_setting_changed(&self, settings: &SystemSetting) {
380        self.parent_system_setting_changed(settings)
381    }
382
383    fn unmap(&self) {
387        self.parent_unmap()
388    }
389
390    fn unrealize(&self) {
396        self.parent_unrealize()
397    }
398
399    fn unroot(&self) {
402        self.parent_unroot()
403    }
404}
405
406pub trait WidgetImplExt: WidgetImpl {
407    fn parent_compute_expand(&self, hexpand: &mut bool, vexpand: &mut bool) {
408        unsafe {
409            let data = Self::type_data();
410            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
411            if let Some(f) = (*parent_class).compute_expand {
412                let mut hexpand_glib = hexpand.into_glib();
413                let mut vexpand_glib = vexpand.into_glib();
414                f(
415                    self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0,
416                    &mut hexpand_glib,
417                    &mut vexpand_glib,
418                );
419                *hexpand = from_glib(hexpand_glib);
420                *vexpand = from_glib(vexpand_glib);
421            }
422        }
423    }
424
425    fn parent_contains(&self, x: f64, y: f64) -> bool {
427        unsafe {
428            let data = Self::type_data();
429            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
430            if let Some(f) = (*parent_class).contains {
431                from_glib(f(
432                    self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0,
433                    x,
434                    y,
435                ))
436            } else {
437                false
438            }
439        }
440    }
441
442    fn parent_direction_changed(&self, previous_direction: TextDirection) {
443        unsafe {
444            let data = Self::type_data();
445            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
446            if let Some(f) = (*parent_class).direction_changed {
447                f(
448                    self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0,
449                    previous_direction.into_glib(),
450                )
451            }
452        }
453    }
454
455    fn parent_focus(&self, direction_type: DirectionType) -> bool {
457        unsafe {
458            let data = Self::type_data();
459            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
460            if let Some(f) = (*parent_class).focus {
461                from_glib(f(
462                    self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0,
463                    direction_type.into_glib(),
464                ))
465            } else {
466                false
467            }
468        }
469    }
470
471    fn parent_request_mode(&self) -> SizeRequestMode {
472        unsafe {
473            let data = Self::type_data();
474            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
475            let f = (*parent_class)
476                .get_request_mode
477                .expect("No parent class impl for \"get_request_mode\"");
478            from_glib(f(self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0))
479        }
480    }
481
482    fn parent_grab_focus(&self) -> bool {
484        unsafe {
485            let data = Self::type_data();
486            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
487            if let Some(f) = (*parent_class).grab_focus {
488                from_glib(f(self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0))
489            } else {
490                false
491            }
492        }
493    }
494
495    #[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
496    #[allow(deprecated)]
497    fn parent_hide(&self) {
498        unsafe {
499            let data = Self::type_data();
500            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
501            if let Some(f) = (*parent_class).hide {
502                f(self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0)
503            }
504        }
505    }
506
507    fn parent_keynav_failed(&self, direction_type: DirectionType) -> bool {
511        unsafe {
512            let data = Self::type_data();
513            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
514            if let Some(f) = (*parent_class).keynav_failed {
515                from_glib(f(
516                    self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0,
517                    direction_type.into_glib(),
518                ))
519            } else {
520                false
521            }
522        }
523    }
524
525    fn parent_map(&self) {
526        unsafe {
527            let data = Self::type_data();
528            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
529            if let Some(f) = (*parent_class).map {
530                f(self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0)
531            }
532        }
533    }
534
535    fn parent_measure(&self, orientation: Orientation, for_size: i32) -> (i32, i32, i32, i32) {
536        unsafe {
537            let data = Self::type_data();
538            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
539
540            let f = (*parent_class)
541                .measure
542                .expect("No parent class impl for \"measure\"");
543
544            let mut min = 0;
545            let mut nat = 0;
546            let mut min_base = -1;
547            let mut nat_base = -1;
548            f(
549                self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0,
550                orientation.into_glib(),
551                for_size,
552                &mut min,
553                &mut nat,
554                &mut min_base,
555                &mut nat_base,
556            );
557            (min, nat, min_base, nat_base)
558        }
559    }
560
561    fn parent_mnemonic_activate(&self, group_cycling: bool) -> bool {
563        unsafe {
564            let data = Self::type_data();
565            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
566            if let Some(f) = (*parent_class).mnemonic_activate {
567                from_glib(f(
568                    self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0,
569                    group_cycling.into_glib(),
570                ))
571            } else {
572                false
573            }
574        }
575    }
576
577    fn parent_move_focus(&self, direction_type: DirectionType) {
578        unsafe {
579            let data = Self::type_data();
580            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
581            if let Some(f) = (*parent_class).move_focus {
582                f(
583                    self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0,
584                    direction_type.into_glib(),
585                )
586            }
587        }
588    }
589
590    fn parent_query_tooltip(
591        &self,
592        x: i32,
593        y: i32,
594        keyboard_tooltip: bool,
595        tooltip: &Tooltip,
596    ) -> bool {
597        unsafe {
598            let data = Self::type_data();
599            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
600            if let Some(f) = (*parent_class).query_tooltip {
601                from_glib(f(
602                    self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0,
603                    x,
604                    y,
605                    keyboard_tooltip.into_glib(),
606                    tooltip.to_glib_none().0,
607                ))
608            } else {
609                false
610            }
611        }
612    }
613
614    fn parent_realize(&self) {
615        unsafe {
616            let data = Self::type_data();
617            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
618            if let Some(f) = (*parent_class).realize {
619                f(self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0)
620            }
621        }
622    }
623
624    fn parent_root(&self) {
625        unsafe {
626            let data = Self::type_data();
627            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
628            if let Some(f) = (*parent_class).root {
629                f(self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0)
630            }
631        }
632    }
633
634    fn parent_set_focus_child(&self, child: Option<&Widget>) {
635        unsafe {
636            let data = Self::type_data();
637            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
638            if let Some(f) = (*parent_class).set_focus_child {
639                f(
640                    self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0,
641                    child.to_glib_none().0,
642                )
643            }
644        }
645    }
646
647    #[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
648    #[allow(deprecated)]
649    fn parent_show(&self) {
650        unsafe {
651            let data = Self::type_data();
652            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
653            if let Some(f) = (*parent_class).show {
654                f(self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0)
655            }
656        }
657    }
658
659    fn parent_size_allocate(&self, width: i32, height: i32, baseline: i32) {
660        unsafe {
661            let data = Self::type_data();
662            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
663            if let Some(f) = (*parent_class).size_allocate {
664                f(
665                    self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0,
666                    width,
667                    height,
668                    baseline,
669                )
670            }
671        }
672    }
673
674    fn parent_snapshot(&self, snapshot: &Snapshot) {
675        unsafe {
676            let data = Self::type_data();
677            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
678            if let Some(f) = (*parent_class).snapshot {
679                f(
680                    self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0,
681                    snapshot.to_glib_none().0,
682                )
683            }
684        }
685    }
686
687    fn parent_state_flags_changed(&self, state_flags: &StateFlags) {
688        unsafe {
689            let data = Self::type_data();
690            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
691            if let Some(f) = (*parent_class).state_flags_changed {
692                f(
693                    self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0,
694                    state_flags.into_glib(),
695                )
696            }
697        }
698    }
699
700    fn parent_system_setting_changed(&self, settings: &SystemSetting) {
701        unsafe {
702            let data = Self::type_data();
703            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
704            if let Some(f) = (*parent_class).system_setting_changed {
705                f(
706                    self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0,
707                    settings.into_glib(),
708                )
709            }
710        }
711    }
712
713    fn parent_unmap(&self) {
714        unsafe {
715            let data = Self::type_data();
716            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
717            if let Some(f) = (*parent_class).unmap {
718                f(self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0)
719            }
720        }
721    }
722
723    fn parent_unrealize(&self) {
724        unsafe {
725            let data = Self::type_data();
726            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
727            if let Some(f) = (*parent_class).unrealize {
728                f(self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0)
729            }
730        }
731    }
732
733    fn parent_unroot(&self) {
734        unsafe {
735            let data = Self::type_data();
736            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
737            if let Some(f) = (*parent_class).unroot {
738                f(self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0)
739            }
740        }
741    }
742}
743
744impl<T: WidgetImpl> WidgetImplExt for T {}
745
746unsafe impl<T: WidgetImpl> IsSubclassable<T> for Widget {
747    fn class_init(class: &mut ::glib::Class<Self>) {
748        Self::parent_class_init::<T>(class);
749
750        assert_initialized_main_thread!();
751
752        let klass = class.as_mut();
753        unsafe {
754            let mut data = T::type_data();
755            let data = data.as_mut();
756            data.set_class_data(<T as ObjectSubclassType>::type_(), Internal::default());
758        }
759
760        klass.compute_expand = Some(widget_compute_expand::<T>);
761        klass.contains = Some(widget_contains::<T>);
762        klass.direction_changed = Some(widget_direction_changed::<T>);
763        klass.focus = Some(widget_focus::<T>);
764        klass.get_request_mode = Some(widget_get_request_mode::<T>);
765        klass.grab_focus = Some(widget_grab_focus::<T>);
766        klass.hide = Some(widget_hide::<T>);
767        klass.keynav_failed = Some(widget_keynav_failed::<T>);
768        klass.map = Some(widget_map::<T>);
769        klass.measure = Some(widget_measure::<T>);
770        klass.mnemonic_activate = Some(widget_mnemonic_activate::<T>);
771        klass.move_focus = Some(widget_move_focus::<T>);
772        klass.query_tooltip = Some(widget_query_tooltip::<T>);
773        klass.realize = Some(widget_realize::<T>);
774        klass.root = Some(widget_root::<T>);
775        klass.set_focus_child = Some(widget_set_focus_child::<T>);
776        klass.show = Some(widget_show::<T>);
777        klass.size_allocate = Some(widget_size_allocate::<T>);
778        klass.snapshot = Some(widget_snapshot::<T>);
779        klass.state_flags_changed = Some(widget_state_flags_changed::<T>);
780        klass.system_setting_changed = Some(widget_system_setting_changed::<T>);
781        klass.unmap = Some(widget_unmap::<T>);
782        klass.unrealize = Some(widget_unrealize::<T>);
783        klass.unroot = Some(widget_unroot::<T>);
784    }
785}
786
787unsafe extern "C" fn widget_compute_expand<T: WidgetImpl>(
788    ptr: *mut ffi::GtkWidget,
789    hexpand_ptr: *mut glib::ffi::gboolean,
790    vexpand_ptr: *mut glib::ffi::gboolean,
791) {
792    let instance = &*(ptr as *mut T::Instance);
793    let imp = instance.imp();
794
795    let widget = imp.obj();
796    let widget = widget.unsafe_cast_ref::<Widget>();
797    let mut hexpand: bool = if widget.is_hexpand_set() {
798        widget.hexpands()
799    } else {
800        from_glib(*hexpand_ptr)
801    };
802    let mut vexpand: bool = if widget.is_vexpand_set() {
803        widget.vexpands()
804    } else {
805        from_glib(*vexpand_ptr)
806    };
807
808    imp.compute_expand(&mut hexpand, &mut vexpand);
809
810    *hexpand_ptr = hexpand.into_glib();
811    *vexpand_ptr = vexpand.into_glib();
812}
813
814unsafe extern "C" fn widget_contains<T: WidgetImpl>(
815    ptr: *mut ffi::GtkWidget,
816    x: f64,
817    y: f64,
818) -> glib::ffi::gboolean {
819    let instance = &*(ptr as *mut T::Instance);
820    let imp = instance.imp();
821
822    imp.contains(x, y).into_glib()
823}
824
825unsafe extern "C" fn widget_direction_changed<T: WidgetImpl>(
826    ptr: *mut ffi::GtkWidget,
827    direction_ptr: ffi::GtkTextDirection,
828) {
829    let instance = &*(ptr as *mut T::Instance);
830    let imp = instance.imp();
831    let direction_wrap = from_glib(direction_ptr);
832
833    imp.direction_changed(direction_wrap)
834}
835
836unsafe extern "C" fn widget_focus<T: WidgetImpl>(
837    ptr: *mut ffi::GtkWidget,
838    direction_type_ptr: ffi::GtkDirectionType,
839) -> glib::ffi::gboolean {
840    let instance = &*(ptr as *mut T::Instance);
841    let imp = instance.imp();
842    let direction_type = from_glib(direction_type_ptr);
843
844    imp.focus(direction_type).into_glib()
845}
846
847unsafe extern "C" fn widget_get_request_mode<T: WidgetImpl>(
848    ptr: *mut ffi::GtkWidget,
849) -> ffi::GtkSizeRequestMode {
850    let instance = &*(ptr as *mut T::Instance);
851    let imp = instance.imp();
852
853    imp.request_mode().into_glib()
854}
855
856unsafe extern "C" fn widget_grab_focus<T: WidgetImpl>(
857    ptr: *mut ffi::GtkWidget,
858) -> glib::ffi::gboolean {
859    let instance = &*(ptr as *mut T::Instance);
860    let imp = instance.imp();
861
862    imp.grab_focus().into_glib()
863}
864
865unsafe extern "C" fn widget_hide<T: WidgetImpl>(ptr: *mut ffi::GtkWidget) {
866    let instance = &*(ptr as *mut T::Instance);
867    let imp = instance.imp();
868
869    imp.hide()
870}
871
872unsafe extern "C" fn widget_keynav_failed<T: WidgetImpl>(
873    ptr: *mut ffi::GtkWidget,
874    direction_type_ptr: ffi::GtkDirectionType,
875) -> glib::ffi::gboolean {
876    let instance = &*(ptr as *mut T::Instance);
877    let imp = instance.imp();
878    let direction_type = from_glib(direction_type_ptr);
879
880    imp.keynav_failed(direction_type).into_glib()
881}
882
883unsafe extern "C" fn widget_map<T: WidgetImpl>(ptr: *mut ffi::GtkWidget) {
884    let instance = &*(ptr as *mut T::Instance);
885    let imp = instance.imp();
886
887    imp.map()
888}
889
890unsafe extern "C" fn widget_measure<T: WidgetImpl>(
891    ptr: *mut ffi::GtkWidget,
892    orientation_ptr: ffi::GtkOrientation,
893    for_size: i32,
894    min_ptr: *mut libc::c_int,
895    nat_ptr: *mut libc::c_int,
896    min_base_ptr: *mut libc::c_int,
897    nat_base_ptr: *mut libc::c_int,
898) {
899    let instance = &*(ptr as *mut T::Instance);
900    let imp = instance.imp();
901    let orientation = from_glib(orientation_ptr);
902    let (min, nat, min_base, nat_base) = imp.measure(orientation, for_size);
903    if !min_ptr.is_null() {
904        *min_ptr = min;
905    }
906    if !nat_ptr.is_null() {
907        *nat_ptr = nat;
908    }
909    if !min_base_ptr.is_null() {
910        *min_base_ptr = min_base;
911    }
912    if !nat_base_ptr.is_null() {
913        *nat_base_ptr = nat_base;
914    }
915}
916
917unsafe extern "C" fn widget_mnemonic_activate<T: WidgetImpl>(
918    ptr: *mut ffi::GtkWidget,
919    group_cycling_ptr: glib::ffi::gboolean,
920) -> glib::ffi::gboolean {
921    let instance = &*(ptr as *mut T::Instance);
922    let imp = instance.imp();
923    let group_cycling: bool = from_glib(group_cycling_ptr);
924
925    imp.mnemonic_activate(group_cycling).into_glib()
926}
927
928unsafe extern "C" fn widget_move_focus<T: WidgetImpl>(
929    ptr: *mut ffi::GtkWidget,
930    direction_type_ptr: ffi::GtkDirectionType,
931) {
932    let instance = &*(ptr as *mut T::Instance);
933    let imp = instance.imp();
934    let direction_type = from_glib(direction_type_ptr);
935
936    imp.move_focus(direction_type)
937}
938
939unsafe extern "C" fn widget_query_tooltip<T: WidgetImpl>(
940    ptr: *mut ffi::GtkWidget,
941    x: i32,
942    y: i32,
943    keyboard_tooltip_ptr: glib::ffi::gboolean,
944    tooltip_ptr: *mut ffi::GtkTooltip,
945) -> glib::ffi::gboolean {
946    let instance = &*(ptr as *mut T::Instance);
947    let imp = instance.imp();
948
949    let keyboard_tooltip: bool = from_glib(keyboard_tooltip_ptr);
950    let tooltip = from_glib_borrow(tooltip_ptr);
951
952    imp.query_tooltip(x, y, keyboard_tooltip, &tooltip)
953        .into_glib()
954}
955
956unsafe extern "C" fn widget_realize<T: WidgetImpl>(ptr: *mut ffi::GtkWidget) {
957    let instance = &*(ptr as *mut T::Instance);
958    let imp = instance.imp();
959
960    imp.realize()
961}
962
963unsafe extern "C" fn widget_root<T: WidgetImpl>(ptr: *mut ffi::GtkWidget) {
964    let instance = &*(ptr as *mut T::Instance);
965    let imp = instance.imp();
966
967    imp.root()
968}
969
970unsafe extern "C" fn widget_set_focus_child<T: WidgetImpl>(
971    ptr: *mut ffi::GtkWidget,
972    child_ptr: *mut ffi::GtkWidget,
973) {
974    let instance = &*(ptr as *mut T::Instance);
975    let imp = instance.imp();
976    let child: Borrowed<Option<Widget>> = from_glib_borrow(child_ptr);
977
978    imp.set_focus_child(child.as_ref().as_ref())
979}
980
981unsafe extern "C" fn widget_show<T: WidgetImpl>(ptr: *mut ffi::GtkWidget) {
982    let instance = &*(ptr as *mut T::Instance);
983    let imp = instance.imp();
984
985    imp.show()
986}
987
988unsafe extern "C" fn widget_size_allocate<T: WidgetImpl>(
989    ptr: *mut ffi::GtkWidget,
990    width: i32,
991    height: i32,
992    baseline: i32,
993) {
994    let instance = &*(ptr as *mut T::Instance);
995    let imp = instance.imp();
996
997    imp.size_allocate(width, height, baseline)
998}
999
1000unsafe extern "C" fn widget_snapshot<T: WidgetImpl>(
1001    ptr: *mut ffi::GtkWidget,
1002    snapshot_ptr: *mut ffi::GtkSnapshot,
1003) {
1004    let instance = &*(ptr as *mut T::Instance);
1005    let imp = instance.imp();
1006    let snapshot = from_glib_borrow(snapshot_ptr);
1007
1008    imp.snapshot(&snapshot)
1009}
1010
1011unsafe extern "C" fn widget_state_flags_changed<T: WidgetImpl>(
1012    ptr: *mut ffi::GtkWidget,
1013    state_flags_ptr: ffi::GtkStateFlags,
1014) {
1015    let instance = &*(ptr as *mut T::Instance);
1016    let imp = instance.imp();
1017    let state_flags = from_glib(state_flags_ptr);
1018
1019    imp.state_flags_changed(&state_flags)
1020}
1021
1022unsafe extern "C" fn widget_system_setting_changed<T: WidgetImpl>(
1023    ptr: *mut ffi::GtkWidget,
1024    settings_ptr: ffi::GtkSystemSetting,
1025) {
1026    let instance = &*(ptr as *mut T::Instance);
1027    let imp = instance.imp();
1028    let settings = from_glib(settings_ptr);
1029
1030    imp.system_setting_changed(&settings)
1031}
1032
1033unsafe extern "C" fn widget_unmap<T: WidgetImpl>(ptr: *mut ffi::GtkWidget) {
1034    let instance = &*(ptr as *mut T::Instance);
1035    let imp = instance.imp();
1036
1037    imp.unmap()
1038}
1039
1040unsafe extern "C" fn widget_unrealize<T: WidgetImpl>(ptr: *mut ffi::GtkWidget) {
1041    let instance = &*(ptr as *mut T::Instance);
1042    let imp = instance.imp();
1043
1044    imp.unrealize()
1045}
1046
1047unsafe extern "C" fn widget_unroot<T: WidgetImpl>(ptr: *mut ffi::GtkWidget) {
1048    let instance = &*(ptr as *mut T::Instance);
1049    let imp = instance.imp();
1050
1051    imp.unroot()
1052}
1053
1054#[allow(clippy::missing_safety_doc)]
1055pub unsafe trait WidgetClassExt: ClassStruct {
1056    #[doc(alias = "gtk_widget_class_set_template")]
1057    fn set_template_bytes(&mut self, template: &glib::Bytes) {
1058        unsafe {
1059            let widget_class = self as *mut _ as *mut ffi::GtkWidgetClass;
1060            ffi::gtk_widget_class_set_template(widget_class, template.to_glib_none().0);
1061        }
1062    }
1063
1064    fn set_template(&mut self, template: &[u8]) {
1075        let template_bytes = glib::Bytes::from(template);
1076        self.set_template_bytes(&template_bytes);
1077    }
1078
1079    fn set_template_static(&mut self, template: &'static [u8]) {
1080        let template_bytes = glib::Bytes::from_static(template);
1081        self.set_template_bytes(&template_bytes);
1082    }
1083
1084    #[doc(alias = "gtk_widget_class_set_template_from_resource")]
1093    fn set_template_from_resource(&mut self, resource_name: &str) {
1094        unsafe {
1095            let widget_class = self as *mut _ as *mut ffi::GtkWidgetClass;
1096            ffi::gtk_widget_class_set_template_from_resource(
1097                widget_class,
1098                resource_name.to_glib_none().0,
1099            );
1100        }
1101    }
1102
1103    fn install_action_async<Fut, F>(
1104        &mut self,
1105        action_name: &str,
1106        parameter_type: Option<&glib::VariantTy>,
1107        activate: F,
1108    ) where
1109        F: Fn(
1110                <<Self as ClassStruct>::Type as ObjectSubclass>::Type,
1111                String,
1112                Option<Variant>,
1113            ) -> Fut
1114            + 'static
1115            + Clone,
1116        Fut: Future<Output = ()>,
1117    {
1118        self.install_action(
1119            action_name,
1120            parameter_type,
1121            move |this, action_name, parameter_type| {
1122                let ctx = glib::MainContext::default();
1123                let action_name = action_name.to_owned();
1124                let parameter_type = parameter_type.map(ToOwned::to_owned);
1125                ctx.spawn_local(glib::clone!(
1126                    #[strong]
1127                    this,
1128                    #[strong]
1129                    action_name,
1130                    #[strong]
1131                    parameter_type,
1132                    #[strong]
1133                    activate,
1134                    async move {
1135                        activate(this, action_name, parameter_type).await;
1136                    }
1137                ));
1138            },
1139        );
1140    }
1141
1142    #[doc(alias = "gtk_widget_class_install_action")]
1156    fn install_action<F>(
1157        &mut self,
1158        action_name: &str,
1159        parameter_type: Option<&glib::VariantTy>,
1160        activate: F,
1161    ) where
1162        F: Fn(&<<Self as ClassStruct>::Type as ObjectSubclass>::Type, &str, Option<&Variant>)
1163            + 'static,
1164    {
1165        unsafe {
1166            let mut data = <Self::Type as ObjectSubclassType>::type_data();
1169            let data = data.as_mut();
1170
1171            let f: Box_<F> = Box_::new(activate);
1172
1173            let internal = data
1174                .class_data_mut::<Internal>(<Self::Type as ObjectSubclassType>::type_())
1175                .expect("Something bad happened at class_init, the internal class_data is missing");
1176            let callback_ptr = Box_::into_raw(f) as glib::ffi::gpointer;
1177            internal
1178                .actions
1179                .insert(action_name.to_string(), callback_ptr);
1180
1181            unsafe extern "C" fn activate_trampoline<F, S>(
1182                this: *mut ffi::GtkWidget,
1183                action_name: *const libc::c_char,
1184                parameter: *mut glib::ffi::GVariant,
1185            ) where
1186                S: ClassStruct,
1187                <S as ClassStruct>::Type: ObjectSubclass,
1188                F: Fn(&<<S as ClassStruct>::Type as ObjectSubclass>::Type, &str, Option<&Variant>)
1189                    + 'static,
1190            {
1191                let action_name = GString::from_glib_borrow(action_name);
1192
1193                let data = <S::Type as ObjectSubclassType>::type_data();
1194                let internal = data
1195                    .as_ref()
1196                    .class_data::<Internal>(<S::Type as ObjectSubclassType>::type_())
1197                    .unwrap();
1198                let activate_callback = *internal
1199                    .actions
1200                    .get(&action_name.to_string())
1201                    .unwrap_or_else(|| {
1202                        panic!("Action name '{}' was not found", action_name.as_str());
1203                    });
1204
1205                let widget = Widget::from_glib_borrow(this);
1206
1207                let f: &F = &*(activate_callback as *const F);
1208                f(
1209                    widget.unsafe_cast_ref(),
1210                    &action_name,
1211                    Option::<Variant>::from_glib_borrow(parameter)
1212                        .as_ref()
1213                        .as_ref(),
1214                )
1215            }
1216            let widget_class = self as *mut _ as *mut ffi::GtkWidgetClass;
1217            let callback = activate_trampoline::<F, Self>;
1218            ffi::gtk_widget_class_install_action(
1219                widget_class,
1220                action_name.to_glib_none().0,
1221                parameter_type.map(|p| p.as_str()).to_glib_none().0,
1222                Some(callback),
1223            );
1224        }
1225    }
1226
1227    #[doc(alias = "gtk_widget_class_query_action")]
1255    fn query_action(&self) -> WidgetActionIter {
1256        let widget_class = self as *const _ as *mut ffi::GtkWidgetClass;
1257        WidgetActionIter(widget_class, 0)
1258    }
1259
1260    #[doc(alias = "gtk_widget_class_set_template_scope")]
1270    fn set_template_scope<S: IsA<BuilderScope>>(&mut self, scope: &S) {
1271        unsafe {
1272            let widget_class = self as *mut _ as *mut ffi::GtkWidgetClass;
1273            ffi::gtk_widget_class_set_template_scope(widget_class, scope.as_ref().to_glib_none().0);
1274        }
1275    }
1276
1277    #[doc(alias = "gtk_widget_class_add_binding")]
1297    fn add_binding<
1298        F: Fn(&<<Self as ClassStruct>::Type as ObjectSubclass>::Type) -> glib::Propagation + 'static,
1299    >(
1300        &mut self,
1301        keyval: gdk::Key,
1302        mods: gdk::ModifierType,
1303        callback: F,
1304    ) {
1305        let shortcut = crate::Shortcut::new(
1306            Some(crate::KeyvalTrigger::new(keyval, mods)),
1307            Some(crate::CallbackAction::new(
1308                move |widget, _| -> glib::Propagation {
1309                    unsafe { callback(widget.unsafe_cast_ref()) }
1310                },
1311            )),
1312        );
1313        self.add_shortcut(&shortcut);
1314    }
1315
1316    #[doc(alias = "gtk_widget_class_add_binding_action")]
1334    fn add_binding_action(&mut self, keyval: gdk::Key, mods: gdk::ModifierType, action_name: &str) {
1335        let shortcut = crate::Shortcut::new(
1336            Some(crate::KeyvalTrigger::new(keyval, mods)),
1337            Some(crate::NamedAction::new(action_name)),
1338        );
1339        self.add_shortcut(&shortcut);
1340    }
1341
1342    #[doc(alias = "gtk_widget_class_add_binding_signal")]
1360    fn add_binding_signal(&mut self, keyval: gdk::Key, mods: gdk::ModifierType, signal_name: &str) {
1361        let type_ = <Self::Type as ObjectSubclassType>::type_();
1362        assert!(
1363            SignalId::lookup(signal_name, type_).is_some(),
1364            "Signal '{signal_name}' doesn't exists for type '{type_}'",
1365        );
1366
1367        let shortcut = crate::Shortcut::new(
1368            Some(crate::KeyvalTrigger::new(keyval, mods)),
1369            Some(crate::SignalAction::new(signal_name)),
1370        );
1371        self.add_shortcut(&shortcut);
1372    }
1373
1374    #[doc(alias = "gtk_widget_class_add_shortcut")]
1387    fn add_shortcut(&mut self, shortcut: &Shortcut) {
1388        unsafe {
1389            let widget_class = self as *mut _ as *mut ffi::GtkWidgetClass;
1390            ffi::gtk_widget_class_add_shortcut(widget_class, shortcut.to_glib_none().0);
1391        }
1392    }
1393
1394    #[doc(alias = "gtk_widget_class_install_property_action")]
1415    fn install_property_action(&mut self, action_name: &str, property_name: &str) {
1416        unsafe {
1417            let widget_class = self as *mut _ as *mut ffi::GtkWidgetClass;
1418            ffi::gtk_widget_class_install_property_action(
1419                widget_class,
1420                action_name.to_glib_none().0,
1421                property_name.to_glib_none().0,
1422            );
1423        }
1424    }
1425
1426    #[doc(alias = "gtk_widget_class_get_activate_signal")]
1436    #[doc(alias = "get_activate_signal")]
1437    fn activate_signal(&self) -> Option<SignalId> {
1438        unsafe {
1439            let widget_class = self as *const _ as *mut ffi::GtkWidgetClass;
1440            let signal_id = ffi::gtk_widget_class_get_activate_signal(widget_class);
1441            if signal_id == 0 {
1442                None
1443            } else {
1444                Some(from_glib(signal_id))
1445            }
1446        }
1447    }
1448
1449    #[doc(alias = "gtk_widget_class_set_activate_signal")]
1458    fn set_activate_signal(&mut self, signal_id: SignalId) {
1459        unsafe {
1460            let widget_class = self as *mut _ as *mut ffi::GtkWidgetClass;
1461            ffi::gtk_widget_class_set_activate_signal(widget_class, signal_id.into_glib())
1462        }
1463    }
1464
1465    #[doc(alias = "gtk_widget_class_set_activate_signal_from_name")]
1476    fn set_activate_signal_from_name(&mut self, signal_name: &str) {
1477        let type_ = <Self::Type as ObjectSubclassType>::type_();
1478        assert!(
1479            SignalId::lookup(signal_name, type_).is_some(),
1480            "Signal '{signal_name}' doesn't exists for type '{type_}'",
1481        );
1482
1483        unsafe {
1484            let widget_class = self as *mut _ as *mut ffi::GtkWidgetClass;
1485            ffi::gtk_widget_class_set_activate_signal_from_name(
1486                widget_class,
1487                signal_name.to_glib_none().0,
1488            );
1489        }
1490    }
1491
1492    #[doc(alias = "gtk_widget_class_set_layout_manager_type")]
1503    fn set_layout_manager_type<T: IsA<LayoutManager>>(&mut self) {
1504        unsafe {
1505            let widget_class = self as *mut _ as *mut ffi::GtkWidgetClass;
1506            ffi::gtk_widget_class_set_layout_manager_type(
1507                widget_class,
1508                T::static_type().into_glib(),
1509            );
1510        }
1511    }
1512
1513    #[doc(alias = "gtk_widget_class_get_layout_manager_type")]
1522    #[doc(alias = "get_layout_manager_type")]
1523    fn layout_manager_type(&self) -> glib::Type {
1524        unsafe {
1525            let widget_class = self as *const _ as *mut ffi::GtkWidgetClass;
1526            from_glib(ffi::gtk_widget_class_get_layout_manager_type(widget_class))
1527        }
1528    }
1529
1530    #[doc(alias = "gtk_widget_class_set_css_name")]
1538    fn set_css_name(&mut self, name: &str) {
1539        unsafe {
1540            let widget_class = self as *mut _ as *mut ffi::GtkWidgetClass;
1541            ffi::gtk_widget_class_set_css_name(widget_class, name.to_glib_none().0);
1542        }
1543    }
1544
1545    #[doc(alias = "gtk_widget_class_get_css_name")]
1553    #[doc(alias = "get_css_name")]
1554    fn css_name(&self) -> glib::GString {
1555        unsafe {
1556            let widget_class = self as *const _ as *mut ffi::GtkWidgetClass;
1557            from_glib_none(ffi::gtk_widget_class_get_css_name(widget_class))
1558        }
1559    }
1560
1561    #[doc(alias = "gtk_widget_class_set_accessible_role")]
1568    fn set_accessible_role(&mut self, role: AccessibleRole) {
1569        unsafe {
1570            let widget_class = self as *mut _ as *mut ffi::GtkWidgetClass;
1571            ffi::gtk_widget_class_set_accessible_role(widget_class, role.into_glib());
1572        }
1573    }
1574
1575    #[doc(alias = "gtk_widget_class_get_accessible_role")]
1586    #[doc(alias = "get_accessible_role")]
1587    fn accessible_role(&self) -> AccessibleRole {
1588        unsafe {
1589            let widget_class = self as *const _ as *mut ffi::GtkWidgetClass;
1590            from_glib(ffi::gtk_widget_class_get_accessible_role(widget_class))
1591        }
1592    }
1593
1594    #[allow(clippy::missing_safety_doc)]
1595    #[doc(alias = "gtk_widget_class_bind_template_child_full")]
1596    unsafe fn bind_template_child_with_offset<T>(
1597        &mut self,
1598        name: &str,
1599        internal: bool,
1600        offset: field_offset::FieldOffset<Self::Type, TemplateChild<T>>,
1601    ) where
1602        T: ObjectType + FromGlibPtrNone<*mut <T as ObjectType>::GlibType>,
1603    {
1604        let widget_class = self as *mut _ as *mut ffi::GtkWidgetClass;
1605        let private_offset = <Self::Type as ObjectSubclassType>::type_data()
1606            .as_ref()
1607            .impl_offset();
1608        ffi::gtk_widget_class_bind_template_child_full(
1609            widget_class,
1610            name.to_glib_none().0,
1611            internal.into_glib(),
1612            private_offset + (offset.get_byte_offset() as isize),
1613        )
1614    }
1615
1616    fn rust_template_scope(&mut self) -> BuilderRustScope {
1617        assert_initialized_main_thread!();
1618        unsafe {
1619            let mut data = <Self::Type as ObjectSubclassType>::type_data();
1620            let internal = data
1621                .as_mut()
1622                .class_data_mut::<Internal>(<Self::Type as ObjectSubclassType>::type_())
1623                .expect("Something bad happened at class_init, the internal class_data is missing");
1624            let scope = internal.scope.get_or_insert_with(|| {
1625                let scope = BuilderRustScope::new();
1626                self.set_template_scope(&scope);
1627                scope.into_glib_ptr()
1628            });
1629            from_glib_none(*scope)
1630        }
1631    }
1632}
1633
1634unsafe impl<T: ClassStruct> WidgetClassExt for T where T::Type: WidgetImpl {}
1635
1636#[derive(Debug, PartialEq, Eq)]
1637#[repr(transparent)]
1638pub struct TemplateChild<T>
1639where
1640    T: ObjectType + FromGlibPtrNone<*mut <T as ObjectType>::GlibType>,
1641{
1642    ptr: *mut <T as ObjectType>::GlibType,
1643}
1644
1645impl<T: Property> Property for TemplateChild<T>
1646where
1647    T: ObjectType + FromGlibPtrNone<*mut <T as ObjectType>::GlibType>,
1648{
1649    type Value = T::Value;
1650}
1651
1652impl<T> Default for TemplateChild<T>
1653where
1654    T: ObjectType + FromGlibPtrNone<*mut <T as ObjectType>::GlibType>,
1655{
1656    fn default() -> Self {
1657        T::static_type();
1658
1659        Self {
1660            ptr: std::ptr::null_mut(),
1661        }
1662    }
1663}
1664
1665impl<T> PropertyGet for TemplateChild<T>
1666where
1667    T: Property + ObjectType + FromGlibPtrNone<*mut <T as ObjectType>::GlibType>,
1668{
1669    type Value = T;
1670
1671    fn get<R, F: Fn(&Self::Value) -> R>(&self, f: F) -> R {
1672        f(&self.get())
1673    }
1674}
1675
1676impl<T> std::ops::Deref for TemplateChild<T>
1677where
1678    T: ObjectType + FromGlibPtrNone<*mut <T as ObjectType>::GlibType>,
1679{
1680    type Target = T;
1681
1682    #[inline]
1683    fn deref(&self) -> &Self::Target {
1684        unsafe {
1685            if !self.is_bound() {
1686                let name = Self::name();
1687                panic!("Failed to retrieve template child. Please check that all fields of type `{name}` have been bound and have a #[template_child] attribute.");
1688            }
1689            &*(&self.ptr as *const _ as *const T)
1690        }
1691    }
1692}
1693
1694impl<T> Downgrade for TemplateChild<T>
1695where
1696    T: ObjectType + FromGlibPtrNone<*mut <T as ObjectType>::GlibType> + Downgrade,
1697{
1698    type Weak = T::Weak;
1699
1700    fn downgrade(&self) -> Self::Weak {
1701        T::downgrade(&self.get())
1702    }
1703}
1704
1705impl<T> TemplateChild<T>
1706where
1707    T: ObjectType + FromGlibPtrNone<*mut <T as ObjectType>::GlibType>,
1708{
1709    pub(crate) fn name<'a>() -> &'a str {
1710        T::static_type().name()
1711    }
1712
1713    #[track_caller]
1714    pub fn get(&self) -> T {
1715        self.try_get()
1716            .unwrap_or_else(|| {
1717                let name = Self::name();
1718                panic!("Failed to retrieve template child. Please check that all fields of type `{name}` have been bound and have a #[template_child] attribute.");
1719            })
1720    }
1721
1722    pub fn is_bound(&self) -> bool {
1726        !self.ptr.is_null()
1727    }
1728
1729    pub fn try_get(&self) -> Option<T> {
1732        unsafe { Option::<T>::from_glib_none(self.ptr) }
1733    }
1734}
1735
1736pub trait CompositeTemplate: WidgetImpl {
1742    fn bind_template(klass: &mut Self::Class);
1743    fn check_template_children(widget: &<Self as ObjectSubclass>::Type);
1744}
1745
1746pub trait CompositeTemplateClass {
1751    fn bind_template(&mut self);
1755}
1756
1757impl<T, U> CompositeTemplateClass for T
1758where
1759    T: ClassStruct<Type = U>,
1760    U: ObjectSubclass<Class = T> + CompositeTemplate,
1761{
1762    fn bind_template(&mut self) {
1763        <U as CompositeTemplate>::bind_template(self);
1764    }
1765}
1766
1767pub type TemplateCallback = (&'static str, fn(&[glib::Value]) -> Option<glib::Value>);
1768
1769pub trait CompositeTemplateCallbacks {
1775    const CALLBACKS: &'static [TemplateCallback];
1776
1777    fn bind_template_callbacks<T: WidgetClassExt>(klass: &mut T) {
1781        Self::add_callbacks_to_scope(&klass.rust_template_scope());
1782    }
1783    fn bind_template_callbacks_prefixed<T: WidgetClassExt>(klass: &mut T, prefix: &str) {
1787        Self::add_callbacks_to_scope_prefixed(&klass.rust_template_scope(), prefix);
1788    }
1789    fn add_callbacks_to_scope(scope: &BuilderRustScope) {
1792        for (name, func) in Self::CALLBACKS {
1793            scope.add_callback(*name, func);
1794        }
1795    }
1796    fn add_callbacks_to_scope_prefixed(scope: &BuilderRustScope, prefix: &str) {
1800        for (name, func) in Self::CALLBACKS {
1801            scope.add_callback(format!("{prefix}{name}"), func);
1802        }
1803    }
1804}
1805
1806pub trait CompositeTemplateCallbacksClass {
1811    fn bind_template_callbacks(&mut self);
1815}
1816
1817impl<T, U> CompositeTemplateCallbacksClass for T
1818where
1819    T: ClassStruct<Type = U> + WidgetClassExt,
1820    U: ObjectSubclass<Class = T> + CompositeTemplateCallbacks,
1821{
1822    fn bind_template_callbacks(&mut self) {
1823        <U as CompositeTemplateCallbacks>::bind_template_callbacks(self);
1824    }
1825}
1826
1827pub trait CompositeTemplateInstanceCallbacksClass {
1833    fn bind_template_instance_callbacks(&mut self);
1837}
1838
1839impl<T, U, V> CompositeTemplateInstanceCallbacksClass for T
1840where
1841    T: ClassStruct<Type = U> + WidgetClassExt,
1842    U: ObjectSubclass<Class = T, Type = V>,
1843    V: CompositeTemplateCallbacks,
1844{
1845    fn bind_template_instance_callbacks(&mut self) {
1846        <V as CompositeTemplateCallbacks>::bind_template_callbacks(self);
1847    }
1848}
1849
1850pub trait CompositeTemplateInitializingExt {
1851    fn init_template(&self);
1852}
1853
1854impl<T: WidgetImpl + CompositeTemplate> CompositeTemplateInitializingExt
1855    for glib::subclass::InitializingObject<T>
1856{
1857    fn init_template(&self) {
1858        unsafe {
1859            let widget = self
1860                .as_ref()
1861                .unsafe_cast_ref::<<T as ObjectSubclass>::Type>();
1862            ffi::gtk_widget_init_template(AsRef::<Widget>::as_ref(widget).to_glib_none().0);
1863
1864            <T as CompositeTemplate>::check_template_children(widget);
1865        }
1866    }
1867}
1868
1869pub trait CompositeTemplateDisposeExt {
1870    #[cfg(feature = "v4_8")]
1871    #[cfg_attr(docsrs, doc(cfg(feature = "v4_8")))]
1872    fn dispose_template(&self);
1873}
1874
1875impl<T: WidgetImpl + CompositeTemplate> CompositeTemplateDisposeExt for T {
1876    #[cfg(feature = "v4_8")]
1877    #[cfg_attr(docsrs, doc(cfg(feature = "v4_8")))]
1878    fn dispose_template(&self) {
1879        unsafe {
1880            ffi::gtk_widget_dispose_template(
1881                self.obj().upcast_ref::<Widget>().to_glib_none().0,
1882                <T as ObjectSubclass>::Type::static_type().into_glib(),
1883            );
1884        }
1885    }
1886}