1use std::{boxed::Box as Box_, collections::HashMap, fmt, future::Future};
7
8use glib::{
9 GString, Variant,
10 clone::Downgrade,
11 property::{Property, PropertyGet},
12 subclass::SignalId,
13 translate::*,
14};
15
16use crate::{
17 AccessibleRole, Buildable, BuilderRustScope, BuilderScope, ConstraintTarget, DirectionType,
18 LayoutManager, Orientation, SizeRequestMode, Snapshot, StateFlags, SystemSetting,
19 TextDirection, Tooltip, Widget, ffi, prelude::*, subclass::prelude::*,
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
32impl WidgetActionIter {
33 pub(crate) fn new(widget_class: *mut ffi::GtkWidgetClass) -> Self {
34 Self(widget_class, 0)
35 }
36}
37
38pub struct WidgetAction(
39 glib::Type,
40 GString,
41 Option<glib::VariantType>,
42 Option<GString>,
43);
44
45impl WidgetAction {
46 pub fn owner(&self) -> glib::Type {
49 self.0
50 }
51
52 pub fn name(&self) -> &str {
55 self.1.as_ref()
56 }
57
58 pub fn parameter_type(&self) -> Option<&glib::VariantType> {
61 self.2.as_ref()
62 }
63
64 pub fn property_name(&self) -> Option<&str> {
67 self.3.as_ref().map(|s| s.as_ref())
68 }
69}
70
71impl fmt::Debug for WidgetAction {
72 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
73 f.debug_struct("WidgetAction")
74 .field("owner", &self.owner())
75 .field("name", &self.name())
76 .field("parameter_type", &self.parameter_type())
77 .field("property_name", &self.property_name())
78 .finish()
79 }
80}
81
82impl Iterator for WidgetActionIter {
83 type Item = WidgetAction;
84
85 fn next(&mut self) -> Option<Self::Item> {
86 unsafe {
87 let mut owner = std::mem::MaybeUninit::uninit();
88 let mut action_name_ptr = std::ptr::null();
89 let mut parameter_type = std::ptr::null();
90 let mut property_name_ptr = std::ptr::null();
91 let found: bool = from_glib(ffi::gtk_widget_class_query_action(
92 self.0,
93 self.1,
94 owner.as_mut_ptr(),
95 &mut action_name_ptr,
96 &mut parameter_type,
97 &mut property_name_ptr,
98 ));
99 if found {
100 self.1 += 1;
101 let property_name: Option<GString> = from_glib_none(property_name_ptr);
102 let action_name: GString = from_glib_none(action_name_ptr);
103
104 Some(WidgetAction(
105 from_glib(owner.assume_init()),
106 action_name,
107 from_glib_none(parameter_type),
108 property_name,
109 ))
110 } else {
111 None
112 }
113 }
114 }
115}
116
117impl std::iter::FusedIterator for WidgetActionIter {}
118
119#[cfg(feature = "v4_10")]
120#[doc(hidden)]
121pub trait WidgetImplBounds:
122 IsA<Widget> + IsA<crate::Accessible> + IsA<Buildable> + IsA<ConstraintTarget>
123{
124}
125#[cfg(feature = "v4_10")]
126impl<T: IsA<Widget> + IsA<crate::Accessible> + IsA<Buildable> + IsA<ConstraintTarget>>
127 WidgetImplBounds for T
128{
129}
130
131#[cfg(not(feature = "v4_10"))]
132#[doc(hidden)]
133pub trait WidgetImplBounds: IsA<Widget> + IsA<Buildable> + IsA<ConstraintTarget> {}
134#[cfg(not(feature = "v4_10"))]
135impl<T: IsA<Widget> + IsA<Buildable> + IsA<ConstraintTarget>> WidgetImplBounds for T {}
136
137pub trait WidgetImpl: ObjectImpl + ObjectSubclass<Type: WidgetImplBounds> {
138 fn compute_expand(&self, hexpand: &mut bool, vexpand: &mut bool) {
141 self.parent_compute_expand(hexpand, vexpand)
142 }
143
144 fn contains(&self, x: f64, y: f64) -> bool {
157 self.parent_contains(x, y)
158 }
159
160 fn direction_changed(&self, previous_direction: TextDirection) {
163 self.parent_direction_changed(previous_direction)
164 }
165
166 fn focus(&self, direction_type: DirectionType) -> bool {
168 self.parent_focus(direction_type)
169 }
170
171 #[doc(alias = "get_request_mode")]
183 fn request_mode(&self) -> SizeRequestMode {
184 self.parent_request_mode()
185 }
186
187 fn grab_focus(&self) -> bool {
201 self.parent_grab_focus()
202 }
203
204 #[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
212 #[allow(deprecated)]
213 fn hide(&self) {
214 self.parent_hide()
215 }
216
217 fn keynav_failed(&self, direction_type: DirectionType) -> bool {
254 self.parent_keynav_failed(direction_type)
255 }
256
257 fn map(&self) {
261 self.parent_map()
262 }
263
264 fn measure(&self, orientation: Orientation, for_size: i32) -> (i32, i32, i32, i32) {
298 self.parent_measure(orientation, for_size)
299 }
300
301 fn mnemonic_activate(&self, group_cycling: bool) -> bool {
309 self.parent_mnemonic_activate(group_cycling)
310 }
311
312 fn move_focus(&self, direction_type: DirectionType) {
314 self.parent_move_focus(direction_type)
315 }
316
317 fn query_tooltip(&self, x: i32, y: i32, keyboard_tooltip: bool, tooltip: &Tooltip) -> bool {
321 self.parent_query_tooltip(x, y, keyboard_tooltip, tooltip)
322 }
323
324 fn realize(&self) {
341 self.parent_realize()
342 }
343
344 fn root(&self) {
347 self.parent_root()
348 }
349
350 fn set_focus_child(&self, child: Option<&Widget>) {
359 self.parent_set_focus_child(child)
360 }
361
362 #[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
377 #[allow(deprecated)]
378 fn show(&self) {
379 self.parent_show()
380 }
381
382 fn size_allocate(&self, width: i32, height: i32, baseline: i32) {
385 self.parent_size_allocate(width, height, baseline)
386 }
387
388 fn snapshot(&self, snapshot: &Snapshot) {
390 self.parent_snapshot(snapshot)
391 }
392
393 fn state_flags_changed(&self, state_flags: &StateFlags) {
396 self.parent_state_flags_changed(state_flags)
397 }
398
399 fn system_setting_changed(&self, settings: &SystemSetting) {
401 self.parent_system_setting_changed(settings)
402 }
403
404 fn unmap(&self) {
408 self.parent_unmap()
409 }
410
411 fn unrealize(&self) {
417 self.parent_unrealize()
418 }
419
420 fn unroot(&self) {
423 self.parent_unroot()
424 }
425}
426
427pub trait WidgetImplExt: WidgetImpl {
428 fn parent_compute_expand(&self, hexpand: &mut bool, vexpand: &mut bool) {
429 unsafe {
430 let data = Self::type_data();
431 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
432 if let Some(f) = (*parent_class).compute_expand {
433 let mut hexpand_glib = hexpand.into_glib();
434 let mut vexpand_glib = vexpand.into_glib();
435 f(
436 self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0,
437 &mut hexpand_glib,
438 &mut vexpand_glib,
439 );
440 *hexpand = from_glib(hexpand_glib);
441 *vexpand = from_glib(vexpand_glib);
442 }
443 }
444 }
445
446 fn parent_contains(&self, x: f64, y: f64) -> bool {
448 unsafe {
449 let data = Self::type_data();
450 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
451 if let Some(f) = (*parent_class).contains {
452 from_glib(f(
453 self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0,
454 x,
455 y,
456 ))
457 } else {
458 false
459 }
460 }
461 }
462
463 fn parent_direction_changed(&self, previous_direction: TextDirection) {
464 unsafe {
465 let data = Self::type_data();
466 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
467 if let Some(f) = (*parent_class).direction_changed {
468 f(
469 self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0,
470 previous_direction.into_glib(),
471 )
472 }
473 }
474 }
475
476 fn parent_focus(&self, direction_type: DirectionType) -> bool {
478 unsafe {
479 let data = Self::type_data();
480 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
481 if let Some(f) = (*parent_class).focus {
482 from_glib(f(
483 self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0,
484 direction_type.into_glib(),
485 ))
486 } else {
487 false
488 }
489 }
490 }
491
492 fn parent_request_mode(&self) -> SizeRequestMode {
493 unsafe {
494 let data = Self::type_data();
495 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
496 let f = (*parent_class)
497 .get_request_mode
498 .expect("No parent class impl for \"get_request_mode\"");
499 from_glib(f(self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0))
500 }
501 }
502
503 fn parent_grab_focus(&self) -> bool {
505 unsafe {
506 let data = Self::type_data();
507 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
508 if let Some(f) = (*parent_class).grab_focus {
509 from_glib(f(self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0))
510 } else {
511 false
512 }
513 }
514 }
515
516 #[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
517 #[allow(deprecated)]
518 fn parent_hide(&self) {
519 unsafe {
520 let data = Self::type_data();
521 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
522 if let Some(f) = (*parent_class).hide {
523 f(self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0)
524 }
525 }
526 }
527
528 fn parent_keynav_failed(&self, direction_type: DirectionType) -> bool {
532 unsafe {
533 let data = Self::type_data();
534 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
535 if let Some(f) = (*parent_class).keynav_failed {
536 from_glib(f(
537 self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0,
538 direction_type.into_glib(),
539 ))
540 } else {
541 false
542 }
543 }
544 }
545
546 fn parent_map(&self) {
547 unsafe {
548 let data = Self::type_data();
549 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
550 if let Some(f) = (*parent_class).map {
551 f(self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0)
552 }
553 }
554 }
555
556 fn parent_measure(&self, orientation: Orientation, for_size: i32) -> (i32, i32, i32, i32) {
557 unsafe {
558 let data = Self::type_data();
559 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
560
561 let f = (*parent_class)
562 .measure
563 .expect("No parent class impl for \"measure\"");
564
565 let mut min = 0;
566 let mut nat = 0;
567 let mut min_base = -1;
568 let mut nat_base = -1;
569 f(
570 self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0,
571 orientation.into_glib(),
572 for_size,
573 &mut min,
574 &mut nat,
575 &mut min_base,
576 &mut nat_base,
577 );
578 (min, nat, min_base, nat_base)
579 }
580 }
581
582 fn parent_mnemonic_activate(&self, group_cycling: bool) -> bool {
584 unsafe {
585 let data = Self::type_data();
586 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
587 if let Some(f) = (*parent_class).mnemonic_activate {
588 from_glib(f(
589 self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0,
590 group_cycling.into_glib(),
591 ))
592 } else {
593 false
594 }
595 }
596 }
597
598 fn parent_move_focus(&self, direction_type: DirectionType) {
599 unsafe {
600 let data = Self::type_data();
601 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
602 if let Some(f) = (*parent_class).move_focus {
603 f(
604 self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0,
605 direction_type.into_glib(),
606 )
607 }
608 }
609 }
610
611 fn parent_query_tooltip(
612 &self,
613 x: i32,
614 y: i32,
615 keyboard_tooltip: bool,
616 tooltip: &Tooltip,
617 ) -> bool {
618 unsafe {
619 let data = Self::type_data();
620 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
621 if let Some(f) = (*parent_class).query_tooltip {
622 from_glib(f(
623 self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0,
624 x,
625 y,
626 keyboard_tooltip.into_glib(),
627 tooltip.to_glib_none().0,
628 ))
629 } else {
630 false
631 }
632 }
633 }
634
635 fn parent_realize(&self) {
636 unsafe {
637 let data = Self::type_data();
638 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
639 if let Some(f) = (*parent_class).realize {
640 f(self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0)
641 }
642 }
643 }
644
645 fn parent_root(&self) {
646 unsafe {
647 let data = Self::type_data();
648 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
649 if let Some(f) = (*parent_class).root {
650 f(self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0)
651 }
652 }
653 }
654
655 fn parent_set_focus_child(&self, child: Option<&Widget>) {
656 unsafe {
657 let data = Self::type_data();
658 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
659 if let Some(f) = (*parent_class).set_focus_child {
660 f(
661 self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0,
662 child.to_glib_none().0,
663 )
664 }
665 }
666 }
667
668 #[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
669 #[allow(deprecated)]
670 fn parent_show(&self) {
671 unsafe {
672 let data = Self::type_data();
673 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
674 if let Some(f) = (*parent_class).show {
675 f(self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0)
676 }
677 }
678 }
679
680 fn parent_size_allocate(&self, width: i32, height: i32, baseline: i32) {
681 unsafe {
682 let data = Self::type_data();
683 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
684 if let Some(f) = (*parent_class).size_allocate {
685 f(
686 self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0,
687 width,
688 height,
689 baseline,
690 )
691 }
692 }
693 }
694
695 fn parent_snapshot(&self, snapshot: &Snapshot) {
696 unsafe {
697 let data = Self::type_data();
698 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
699 if let Some(f) = (*parent_class).snapshot {
700 f(
701 self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0,
702 snapshot.to_glib_none().0,
703 )
704 }
705 }
706 }
707
708 fn parent_state_flags_changed(&self, state_flags: &StateFlags) {
709 unsafe {
710 let data = Self::type_data();
711 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
712 if let Some(f) = (*parent_class).state_flags_changed {
713 f(
714 self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0,
715 state_flags.into_glib(),
716 )
717 }
718 }
719 }
720
721 fn parent_system_setting_changed(&self, settings: &SystemSetting) {
722 unsafe {
723 let data = Self::type_data();
724 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
725 if let Some(f) = (*parent_class).system_setting_changed {
726 f(
727 self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0,
728 settings.into_glib(),
729 )
730 }
731 }
732 }
733
734 fn parent_unmap(&self) {
735 unsafe {
736 let data = Self::type_data();
737 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
738 if let Some(f) = (*parent_class).unmap {
739 f(self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0)
740 }
741 }
742 }
743
744 fn parent_unrealize(&self) {
745 unsafe {
746 let data = Self::type_data();
747 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
748 if let Some(f) = (*parent_class).unrealize {
749 f(self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0)
750 }
751 }
752 }
753
754 fn parent_unroot(&self) {
755 unsafe {
756 let data = Self::type_data();
757 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
758 if let Some(f) = (*parent_class).unroot {
759 f(self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0)
760 }
761 }
762 }
763}
764
765impl<T: WidgetImpl> WidgetImplExt for T {}
766
767unsafe impl<T: WidgetImpl> IsSubclassable<T> for Widget {
768 fn class_init(class: &mut ::glib::Class<Self>) {
769 Self::parent_class_init::<T>(class);
770
771 assert_initialized_main_thread!();
772
773 let klass = class.as_mut();
774 unsafe {
775 let mut data = T::type_data();
776 let data = data.as_mut();
777 data.set_class_data(<T as ObjectSubclassType>::type_(), Internal::default());
779 }
780
781 klass.compute_expand = Some(widget_compute_expand::<T>);
782 klass.contains = Some(widget_contains::<T>);
783 klass.direction_changed = Some(widget_direction_changed::<T>);
784 klass.focus = Some(widget_focus::<T>);
785 klass.get_request_mode = Some(widget_get_request_mode::<T>);
786 klass.grab_focus = Some(widget_grab_focus::<T>);
787 klass.hide = Some(widget_hide::<T>);
788 klass.keynav_failed = Some(widget_keynav_failed::<T>);
789 klass.map = Some(widget_map::<T>);
790 klass.measure = Some(widget_measure::<T>);
791 klass.mnemonic_activate = Some(widget_mnemonic_activate::<T>);
792 klass.move_focus = Some(widget_move_focus::<T>);
793 klass.query_tooltip = Some(widget_query_tooltip::<T>);
794 klass.realize = Some(widget_realize::<T>);
795 klass.root = Some(widget_root::<T>);
796 klass.set_focus_child = Some(widget_set_focus_child::<T>);
797 klass.show = Some(widget_show::<T>);
798 klass.size_allocate = Some(widget_size_allocate::<T>);
799 klass.snapshot = Some(widget_snapshot::<T>);
800 klass.state_flags_changed = Some(widget_state_flags_changed::<T>);
801 klass.system_setting_changed = Some(widget_system_setting_changed::<T>);
802 klass.unmap = Some(widget_unmap::<T>);
803 klass.unrealize = Some(widget_unrealize::<T>);
804 klass.unroot = Some(widget_unroot::<T>);
805 }
806}
807
808unsafe extern "C" fn widget_compute_expand<T: WidgetImpl>(
809 ptr: *mut ffi::GtkWidget,
810 hexpand_ptr: *mut glib::ffi::gboolean,
811 vexpand_ptr: *mut glib::ffi::gboolean,
812) {
813 unsafe {
814 let instance = &*(ptr as *mut T::Instance);
815 let imp = instance.imp();
816
817 let widget = imp.obj();
818 let widget = widget.unsafe_cast_ref::<Widget>();
819 let mut hexpand: bool = if widget.is_hexpand_set() {
820 widget.hexpands()
821 } else {
822 from_glib(*hexpand_ptr)
823 };
824 let mut vexpand: bool = if widget.is_vexpand_set() {
825 widget.vexpands()
826 } else {
827 from_glib(*vexpand_ptr)
828 };
829
830 imp.compute_expand(&mut hexpand, &mut vexpand);
831
832 *hexpand_ptr = hexpand.into_glib();
833 *vexpand_ptr = vexpand.into_glib();
834 }
835}
836
837unsafe extern "C" fn widget_contains<T: WidgetImpl>(
838 ptr: *mut ffi::GtkWidget,
839 x: f64,
840 y: f64,
841) -> glib::ffi::gboolean {
842 unsafe {
843 let instance = &*(ptr as *mut T::Instance);
844 let imp = instance.imp();
845
846 imp.contains(x, y).into_glib()
847 }
848}
849
850unsafe extern "C" fn widget_direction_changed<T: WidgetImpl>(
851 ptr: *mut ffi::GtkWidget,
852 direction_ptr: ffi::GtkTextDirection,
853) {
854 unsafe {
855 let instance = &*(ptr as *mut T::Instance);
856 let imp = instance.imp();
857 let direction_wrap = from_glib(direction_ptr);
858
859 imp.direction_changed(direction_wrap)
860 }
861}
862
863unsafe extern "C" fn widget_focus<T: WidgetImpl>(
864 ptr: *mut ffi::GtkWidget,
865 direction_type_ptr: ffi::GtkDirectionType,
866) -> glib::ffi::gboolean {
867 unsafe {
868 let instance = &*(ptr as *mut T::Instance);
869 let imp = instance.imp();
870 let direction_type = from_glib(direction_type_ptr);
871
872 imp.focus(direction_type).into_glib()
873 }
874}
875
876unsafe extern "C" fn widget_get_request_mode<T: WidgetImpl>(
877 ptr: *mut ffi::GtkWidget,
878) -> ffi::GtkSizeRequestMode {
879 unsafe {
880 let instance = &*(ptr as *mut T::Instance);
881 let imp = instance.imp();
882
883 imp.request_mode().into_glib()
884 }
885}
886
887unsafe extern "C" fn widget_grab_focus<T: WidgetImpl>(
888 ptr: *mut ffi::GtkWidget,
889) -> glib::ffi::gboolean {
890 unsafe {
891 let instance = &*(ptr as *mut T::Instance);
892 let imp = instance.imp();
893
894 imp.grab_focus().into_glib()
895 }
896}
897
898unsafe extern "C" fn widget_hide<T: WidgetImpl>(ptr: *mut ffi::GtkWidget) {
899 unsafe {
900 let instance = &*(ptr as *mut T::Instance);
901 let imp = instance.imp();
902
903 imp.hide()
904 }
905}
906
907unsafe extern "C" fn widget_keynav_failed<T: WidgetImpl>(
908 ptr: *mut ffi::GtkWidget,
909 direction_type_ptr: ffi::GtkDirectionType,
910) -> glib::ffi::gboolean {
911 unsafe {
912 let instance = &*(ptr as *mut T::Instance);
913 let imp = instance.imp();
914 let direction_type = from_glib(direction_type_ptr);
915
916 imp.keynav_failed(direction_type).into_glib()
917 }
918}
919
920unsafe extern "C" fn widget_map<T: WidgetImpl>(ptr: *mut ffi::GtkWidget) {
921 unsafe {
922 let instance = &*(ptr as *mut T::Instance);
923 let imp = instance.imp();
924
925 imp.map()
926 }
927}
928
929unsafe extern "C" fn widget_measure<T: WidgetImpl>(
930 ptr: *mut ffi::GtkWidget,
931 orientation_ptr: ffi::GtkOrientation,
932 for_size: i32,
933 min_ptr: *mut libc::c_int,
934 nat_ptr: *mut libc::c_int,
935 min_base_ptr: *mut libc::c_int,
936 nat_base_ptr: *mut libc::c_int,
937) {
938 unsafe {
939 let instance = &*(ptr as *mut T::Instance);
940 let imp = instance.imp();
941 let orientation = from_glib(orientation_ptr);
942 let (min, nat, min_base, nat_base) = imp.measure(orientation, for_size);
943 if !min_ptr.is_null() {
944 *min_ptr = min;
945 }
946 if !nat_ptr.is_null() {
947 *nat_ptr = nat;
948 }
949 if !min_base_ptr.is_null() {
950 *min_base_ptr = min_base;
951 }
952 if !nat_base_ptr.is_null() {
953 *nat_base_ptr = nat_base;
954 }
955 }
956}
957
958unsafe extern "C" fn widget_mnemonic_activate<T: WidgetImpl>(
959 ptr: *mut ffi::GtkWidget,
960 group_cycling_ptr: glib::ffi::gboolean,
961) -> glib::ffi::gboolean {
962 unsafe {
963 let instance = &*(ptr as *mut T::Instance);
964 let imp = instance.imp();
965 let group_cycling: bool = from_glib(group_cycling_ptr);
966
967 imp.mnemonic_activate(group_cycling).into_glib()
968 }
969}
970
971unsafe extern "C" fn widget_move_focus<T: WidgetImpl>(
972 ptr: *mut ffi::GtkWidget,
973 direction_type_ptr: ffi::GtkDirectionType,
974) {
975 unsafe {
976 let instance = &*(ptr as *mut T::Instance);
977 let imp = instance.imp();
978 let direction_type = from_glib(direction_type_ptr);
979
980 imp.move_focus(direction_type)
981 }
982}
983
984unsafe extern "C" fn widget_query_tooltip<T: WidgetImpl>(
985 ptr: *mut ffi::GtkWidget,
986 x: i32,
987 y: i32,
988 keyboard_tooltip_ptr: glib::ffi::gboolean,
989 tooltip_ptr: *mut ffi::GtkTooltip,
990) -> glib::ffi::gboolean {
991 unsafe {
992 let instance = &*(ptr as *mut T::Instance);
993 let imp = instance.imp();
994
995 let keyboard_tooltip: bool = from_glib(keyboard_tooltip_ptr);
996 let tooltip = from_glib_borrow(tooltip_ptr);
997
998 imp.query_tooltip(x, y, keyboard_tooltip, &tooltip)
999 .into_glib()
1000 }
1001}
1002
1003unsafe extern "C" fn widget_realize<T: WidgetImpl>(ptr: *mut ffi::GtkWidget) {
1004 unsafe {
1005 let instance = &*(ptr as *mut T::Instance);
1006 let imp = instance.imp();
1007
1008 imp.realize()
1009 }
1010}
1011
1012unsafe extern "C" fn widget_root<T: WidgetImpl>(ptr: *mut ffi::GtkWidget) {
1013 unsafe {
1014 let instance = &*(ptr as *mut T::Instance);
1015 let imp = instance.imp();
1016
1017 imp.root()
1018 }
1019}
1020
1021unsafe extern "C" fn widget_set_focus_child<T: WidgetImpl>(
1022 ptr: *mut ffi::GtkWidget,
1023 child_ptr: *mut ffi::GtkWidget,
1024) {
1025 unsafe {
1026 let instance = &*(ptr as *mut T::Instance);
1027 let imp = instance.imp();
1028 let child: Borrowed<Option<Widget>> = from_glib_borrow(child_ptr);
1029
1030 imp.set_focus_child(child.as_ref().as_ref())
1031 }
1032}
1033
1034unsafe extern "C" fn widget_show<T: WidgetImpl>(ptr: *mut ffi::GtkWidget) {
1035 unsafe {
1036 let instance = &*(ptr as *mut T::Instance);
1037 let imp = instance.imp();
1038
1039 imp.show()
1040 }
1041}
1042
1043unsafe extern "C" fn widget_size_allocate<T: WidgetImpl>(
1044 ptr: *mut ffi::GtkWidget,
1045 width: i32,
1046 height: i32,
1047 baseline: i32,
1048) {
1049 unsafe {
1050 let instance = &*(ptr as *mut T::Instance);
1051 let imp = instance.imp();
1052
1053 imp.size_allocate(width, height, baseline)
1054 }
1055}
1056
1057unsafe extern "C" fn widget_snapshot<T: WidgetImpl>(
1058 ptr: *mut ffi::GtkWidget,
1059 snapshot_ptr: *mut ffi::GtkSnapshot,
1060) {
1061 unsafe {
1062 let instance = &*(ptr as *mut T::Instance);
1063 let imp = instance.imp();
1064 let snapshot = from_glib_borrow(snapshot_ptr);
1065
1066 imp.snapshot(&snapshot)
1067 }
1068}
1069
1070unsafe extern "C" fn widget_state_flags_changed<T: WidgetImpl>(
1071 ptr: *mut ffi::GtkWidget,
1072 state_flags_ptr: ffi::GtkStateFlags,
1073) {
1074 unsafe {
1075 let instance = &*(ptr as *mut T::Instance);
1076 let imp = instance.imp();
1077 let state_flags = from_glib(state_flags_ptr);
1078
1079 imp.state_flags_changed(&state_flags)
1080 }
1081}
1082
1083unsafe extern "C" fn widget_system_setting_changed<T: WidgetImpl>(
1084 ptr: *mut ffi::GtkWidget,
1085 settings_ptr: ffi::GtkSystemSetting,
1086) {
1087 unsafe {
1088 let instance = &*(ptr as *mut T::Instance);
1089 let imp = instance.imp();
1090 let settings = from_glib(settings_ptr);
1091
1092 imp.system_setting_changed(&settings)
1093 }
1094}
1095
1096unsafe extern "C" fn widget_unmap<T: WidgetImpl>(ptr: *mut ffi::GtkWidget) {
1097 unsafe {
1098 let instance = &*(ptr as *mut T::Instance);
1099 let imp = instance.imp();
1100
1101 imp.unmap()
1102 }
1103}
1104
1105unsafe extern "C" fn widget_unrealize<T: WidgetImpl>(ptr: *mut ffi::GtkWidget) {
1106 unsafe {
1107 let instance = &*(ptr as *mut T::Instance);
1108 let imp = instance.imp();
1109
1110 imp.unrealize()
1111 }
1112}
1113
1114unsafe extern "C" fn widget_unroot<T: WidgetImpl>(ptr: *mut ffi::GtkWidget) {
1115 unsafe {
1116 let instance = &*(ptr as *mut T::Instance);
1117 let imp = instance.imp();
1118
1119 imp.unroot()
1120 }
1121}
1122
1123#[allow(clippy::missing_safety_doc)]
1124pub unsafe trait WidgetClassExt: ClassStruct {
1125 #[doc(alias = "gtk_widget_class_set_template")]
1126 fn set_template_bytes(&mut self, template: &glib::Bytes) {
1127 unsafe {
1128 let widget_class = self as *mut _ as *mut ffi::GtkWidgetClass;
1129 ffi::gtk_widget_class_set_template(widget_class, template.to_glib_none().0);
1130 }
1131 }
1132
1133 fn set_template(&mut self, template: &[u8]) {
1144 let template_bytes = glib::Bytes::from(template);
1145 self.set_template_bytes(&template_bytes);
1146 }
1147
1148 fn set_template_static(&mut self, template: &'static [u8]) {
1149 let template_bytes = glib::Bytes::from_static(template);
1150 self.set_template_bytes(&template_bytes);
1151 }
1152
1153 #[doc(alias = "gtk_widget_class_set_template_from_resource")]
1162 fn set_template_from_resource(&mut self, resource_name: &str) {
1163 unsafe {
1164 let widget_class = self as *mut _ as *mut ffi::GtkWidgetClass;
1165 ffi::gtk_widget_class_set_template_from_resource(
1166 widget_class,
1167 resource_name.to_glib_none().0,
1168 );
1169 }
1170 }
1171
1172 fn install_action_async<Fut, F>(
1173 &mut self,
1174 action_name: &str,
1175 parameter_type: Option<&glib::VariantTy>,
1176 activate: F,
1177 ) where
1178 F: Fn(
1179 <<Self as ClassStruct>::Type as ObjectSubclass>::Type,
1180 String,
1181 Option<Variant>,
1182 ) -> Fut
1183 + 'static
1184 + Clone,
1185 Fut: Future<Output = ()>,
1186 {
1187 self.install_action(
1188 action_name,
1189 parameter_type,
1190 move |this, action_name, parameter_type| {
1191 let ctx = glib::MainContext::default();
1192 let action_name = action_name.to_owned();
1193 let parameter_type = parameter_type.map(ToOwned::to_owned);
1194 ctx.spawn_local(glib::clone!(
1195 #[strong]
1196 this,
1197 #[strong]
1198 action_name,
1199 #[strong]
1200 parameter_type,
1201 #[strong]
1202 activate,
1203 async move {
1204 activate(this, action_name, parameter_type).await;
1205 }
1206 ));
1207 },
1208 );
1209 }
1210
1211 #[doc(alias = "gtk_widget_class_install_action")]
1225 fn install_action<F>(
1226 &mut self,
1227 action_name: &str,
1228 parameter_type: Option<&glib::VariantTy>,
1229 activate: F,
1230 ) where
1231 F: Fn(&<<Self as ClassStruct>::Type as ObjectSubclass>::Type, &str, Option<&Variant>)
1232 + 'static,
1233 {
1234 unsafe {
1235 let mut data = <Self::Type as ObjectSubclassType>::type_data();
1238 let data = data.as_mut();
1239
1240 let f: Box_<F> = Box_::new(activate);
1241
1242 let internal = data
1243 .class_data_mut::<Internal>(<Self::Type as ObjectSubclassType>::type_())
1244 .expect("Something bad happened at class_init, the internal class_data is missing");
1245 let callback_ptr = Box_::into_raw(f) as glib::ffi::gpointer;
1246 internal
1247 .actions
1248 .insert(action_name.to_string(), callback_ptr);
1249
1250 unsafe extern "C" fn activate_trampoline<F, S>(
1251 this: *mut ffi::GtkWidget,
1252 action_name: *const libc::c_char,
1253 parameter: *mut glib::ffi::GVariant,
1254 ) where
1255 S: ClassStruct,
1256 <S as ClassStruct>::Type: ObjectSubclass,
1257 F: Fn(&<<S as ClassStruct>::Type as ObjectSubclass>::Type, &str, Option<&Variant>)
1258 + 'static,
1259 {
1260 unsafe {
1261 let action_name = GString::from_glib_borrow(action_name);
1262
1263 let data = <S::Type as ObjectSubclassType>::type_data();
1264 let internal = data
1265 .as_ref()
1266 .class_data::<Internal>(<S::Type as ObjectSubclassType>::type_())
1267 .unwrap();
1268 let activate_callback = *internal
1269 .actions
1270 .get(&action_name.to_string())
1271 .unwrap_or_else(|| {
1272 panic!("Action name '{}' was not found", action_name.as_str());
1273 });
1274
1275 let widget = Widget::from_glib_borrow(this);
1276
1277 let f: &F = &*(activate_callback as *const F);
1278 f(
1279 widget.unsafe_cast_ref(),
1280 &action_name,
1281 Option::<Variant>::from_glib_borrow(parameter)
1282 .as_ref()
1283 .as_ref(),
1284 )
1285 }
1286 }
1287 let widget_class = self as *mut _ as *mut ffi::GtkWidgetClass;
1288 let callback = activate_trampoline::<F, Self>;
1289 ffi::gtk_widget_class_install_action(
1290 widget_class,
1291 action_name.to_glib_none().0,
1292 parameter_type.map(|p| p.as_str()).to_glib_none().0,
1293 Some(callback),
1294 );
1295 }
1296 }
1297
1298 #[doc(alias = "gtk_widget_class_set_template_scope")]
1308 fn set_template_scope<S: IsA<BuilderScope>>(&mut self, scope: &S) {
1309 unsafe {
1310 let widget_class = self as *mut _ as *mut ffi::GtkWidgetClass;
1311 ffi::gtk_widget_class_set_template_scope(widget_class, scope.as_ref().to_glib_none().0);
1312 }
1313 }
1314
1315 #[doc(alias = "gtk_widget_class_add_binding")]
1335 fn add_binding<
1336 F: Fn(&<<Self as ClassStruct>::Type as ObjectSubclass>::Type) -> glib::Propagation + 'static,
1337 >(
1338 &mut self,
1339 keyval: gdk::Key,
1340 mods: gdk::ModifierType,
1341 callback: F,
1342 ) {
1343 let shortcut = crate::Shortcut::new(
1344 Some(crate::KeyvalTrigger::new(keyval, mods)),
1345 Some(crate::CallbackAction::new(
1346 move |widget, _| -> glib::Propagation {
1347 unsafe { callback(widget.unsafe_cast_ref()) }
1348 },
1349 )),
1350 );
1351 unsafe {
1352 let widget_class = self as *mut _ as *mut ffi::GtkWidgetClass;
1353 ffi::gtk_widget_class_add_shortcut(widget_class, shortcut.to_glib_none().0);
1354 }
1355 }
1356
1357 #[doc(alias = "gtk_widget_class_add_binding_signal")]
1375 fn add_binding_signal(&mut self, keyval: gdk::Key, mods: gdk::ModifierType, signal_name: &str) {
1376 let type_ = <Self::Type as ObjectSubclassType>::type_();
1377 assert!(
1378 SignalId::lookup(signal_name, type_).is_some(),
1379 "Signal '{signal_name}' doesn't exists for type '{type_}'",
1380 );
1381
1382 let shortcut = crate::Shortcut::new(
1383 Some(crate::KeyvalTrigger::new(keyval, mods)),
1384 Some(crate::SignalAction::new(signal_name)),
1385 );
1386 unsafe {
1387 let widget_class = self as *mut _ as *mut ffi::GtkWidgetClass;
1388 ffi::gtk_widget_class_add_shortcut(widget_class, shortcut.to_glib_none().0);
1389 }
1390 }
1391
1392 #[doc(alias = "gtk_widget_class_set_activate_signal")]
1401 fn set_activate_signal(&mut self, signal_id: SignalId) {
1402 unsafe {
1403 let widget_class = self as *mut _ as *mut ffi::GtkWidgetClass;
1404 ffi::gtk_widget_class_set_activate_signal(widget_class, signal_id.into_glib())
1405 }
1406 }
1407
1408 #[doc(alias = "gtk_widget_class_set_activate_signal_from_name")]
1419 fn set_activate_signal_from_name(&mut self, signal_name: &str) {
1420 let type_ = <Self::Type as ObjectSubclassType>::type_();
1421 assert!(
1422 SignalId::lookup(signal_name, type_).is_some(),
1423 "Signal '{signal_name}' doesn't exists for type '{type_}'",
1424 );
1425
1426 unsafe {
1427 let widget_class = self as *mut _ as *mut ffi::GtkWidgetClass;
1428 ffi::gtk_widget_class_set_activate_signal_from_name(
1429 widget_class,
1430 signal_name.to_glib_none().0,
1431 );
1432 }
1433 }
1434
1435 #[doc(alias = "gtk_widget_class_set_layout_manager_type")]
1446 fn set_layout_manager_type<T: IsA<LayoutManager>>(&mut self) {
1447 unsafe {
1448 let widget_class = self as *mut _ as *mut ffi::GtkWidgetClass;
1449 ffi::gtk_widget_class_set_layout_manager_type(
1450 widget_class,
1451 T::static_type().into_glib(),
1452 );
1453 }
1454 }
1455
1456 #[doc(alias = "gtk_widget_class_set_css_name")]
1464 fn set_css_name(&mut self, name: &str) {
1465 unsafe {
1466 let widget_class = self as *mut _ as *mut ffi::GtkWidgetClass;
1467 ffi::gtk_widget_class_set_css_name(widget_class, name.to_glib_none().0);
1468 }
1469 }
1470
1471 #[doc(alias = "gtk_widget_class_set_accessible_role")]
1478 fn set_accessible_role(&mut self, role: AccessibleRole) {
1479 unsafe {
1480 let widget_class = self as *mut _ as *mut ffi::GtkWidgetClass;
1481 ffi::gtk_widget_class_set_accessible_role(widget_class, role.into_glib());
1482 }
1483 }
1484
1485 #[allow(clippy::missing_safety_doc)]
1486 #[doc(alias = "gtk_widget_class_bind_template_child_full")]
1487 unsafe fn bind_template_child_with_offset<T>(
1488 &mut self,
1489 name: &str,
1490 internal: bool,
1491 offset: field_offset::FieldOffset<Self::Type, TemplateChild<T>>,
1492 ) where
1493 T: ObjectType + FromGlibPtrNone<*mut <T as ObjectType>::GlibType>,
1494 {
1495 unsafe {
1496 let widget_class = self as *mut _ as *mut ffi::GtkWidgetClass;
1497 let private_offset = <Self::Type as ObjectSubclassType>::type_data()
1498 .as_ref()
1499 .impl_offset();
1500 ffi::gtk_widget_class_bind_template_child_full(
1501 widget_class,
1502 name.to_glib_none().0,
1503 internal.into_glib(),
1504 private_offset + (offset.get_byte_offset() as isize),
1505 )
1506 }
1507 }
1508
1509 fn rust_template_scope(&mut self) -> BuilderRustScope {
1510 assert_initialized_main_thread!();
1511 unsafe {
1512 let mut data = <Self::Type as ObjectSubclassType>::type_data();
1513 let internal = data
1514 .as_mut()
1515 .class_data_mut::<Internal>(<Self::Type as ObjectSubclassType>::type_())
1516 .expect("Something bad happened at class_init, the internal class_data is missing");
1517 let scope = internal.scope.get_or_insert_with(|| {
1518 let scope = BuilderRustScope::new();
1519 self.set_template_scope(&scope);
1520 scope.into_glib_ptr()
1521 });
1522 from_glib_none(*scope)
1523 }
1524 }
1525}
1526
1527unsafe impl<T: ClassStruct> WidgetClassExt for T where T::Type: WidgetImpl {}
1528
1529#[derive(Debug, PartialEq, Eq)]
1530#[repr(transparent)]
1531pub struct TemplateChild<T>
1532where
1533 T: ObjectType + FromGlibPtrNone<*mut <T as ObjectType>::GlibType>,
1534{
1535 ptr: *mut <T as ObjectType>::GlibType,
1536}
1537
1538impl<T: Property> Property for TemplateChild<T>
1539where
1540 T: ObjectType + FromGlibPtrNone<*mut <T as ObjectType>::GlibType>,
1541{
1542 type Value = T::Value;
1543}
1544
1545impl<T> Default for TemplateChild<T>
1546where
1547 T: ObjectType + FromGlibPtrNone<*mut <T as ObjectType>::GlibType>,
1548{
1549 fn default() -> Self {
1550 T::static_type();
1551
1552 Self {
1553 ptr: std::ptr::null_mut(),
1554 }
1555 }
1556}
1557
1558impl<T> PropertyGet for TemplateChild<T>
1559where
1560 T: Property + ObjectType + FromGlibPtrNone<*mut <T as ObjectType>::GlibType>,
1561{
1562 type Value = T;
1563
1564 fn get<R, F: Fn(&Self::Value) -> R>(&self, f: F) -> R {
1565 f(&self.get())
1566 }
1567}
1568
1569impl<T> std::ops::Deref for TemplateChild<T>
1570where
1571 T: ObjectType + FromGlibPtrNone<*mut <T as ObjectType>::GlibType>,
1572{
1573 type Target = T;
1574
1575 #[inline]
1576 fn deref(&self) -> &Self::Target {
1577 unsafe {
1578 if !self.is_bound() {
1579 let name = Self::name();
1580 panic!(
1581 "Failed to retrieve template child. Please check that all fields of type `{name}` have been bound and have a #[template_child] attribute."
1582 );
1583 }
1584 &*(&self.ptr as *const _ as *const T)
1585 }
1586 }
1587}
1588
1589impl<T> Downgrade for TemplateChild<T>
1590where
1591 T: ObjectType + FromGlibPtrNone<*mut <T as ObjectType>::GlibType> + Downgrade,
1592{
1593 type Weak = T::Weak;
1594
1595 fn downgrade(&self) -> Self::Weak {
1596 T::downgrade(&self.get())
1597 }
1598}
1599
1600impl<T> TemplateChild<T>
1601where
1602 T: ObjectType + FromGlibPtrNone<*mut <T as ObjectType>::GlibType>,
1603{
1604 pub(crate) fn name<'a>() -> &'a str {
1605 T::static_type().name()
1606 }
1607
1608 #[track_caller]
1609 pub fn get(&self) -> T {
1610 self.try_get()
1611 .unwrap_or_else(|| {
1612 let name = Self::name();
1613 panic!("Failed to retrieve template child. Please check that all fields of type `{name}` have been bound and have a #[template_child] attribute.");
1614 })
1615 }
1616
1617 pub fn is_bound(&self) -> bool {
1621 !self.ptr.is_null()
1622 }
1623
1624 pub fn try_get(&self) -> Option<T> {
1627 unsafe { Option::<T>::from_glib_none(self.ptr) }
1628 }
1629}
1630
1631pub trait CompositeTemplate: WidgetImpl {
1637 fn bind_template(klass: &mut Self::Class);
1638 fn check_template_children(widget: &<Self as ObjectSubclass>::Type);
1639}
1640
1641pub trait CompositeTemplateClass {
1646 fn bind_template(&mut self);
1650}
1651
1652impl<T, U> CompositeTemplateClass for T
1653where
1654 T: ClassStruct<Type = U>,
1655 U: ObjectSubclass<Class = T> + CompositeTemplate,
1656{
1657 fn bind_template(&mut self) {
1658 <U as CompositeTemplate>::bind_template(self);
1659 }
1660}
1661
1662pub type TemplateCallback = (&'static str, fn(&[glib::Value]) -> Option<glib::Value>);
1663
1664pub trait CompositeTemplateCallbacks {
1670 const CALLBACKS: &'static [TemplateCallback];
1671
1672 fn bind_template_callbacks<T: WidgetClassExt>(klass: &mut T) {
1676 Self::add_callbacks_to_scope(&klass.rust_template_scope());
1677 }
1678 fn bind_template_callbacks_prefixed<T: WidgetClassExt>(klass: &mut T, prefix: &str) {
1682 Self::add_callbacks_to_scope_prefixed(&klass.rust_template_scope(), prefix);
1683 }
1684 fn add_callbacks_to_scope(scope: &BuilderRustScope) {
1687 for (name, func) in Self::CALLBACKS {
1688 scope.add_callback(*name, func);
1689 }
1690 }
1691 fn add_callbacks_to_scope_prefixed(scope: &BuilderRustScope, prefix: &str) {
1695 for (name, func) in Self::CALLBACKS {
1696 scope.add_callback(format!("{prefix}{name}"), func);
1697 }
1698 }
1699}
1700
1701pub trait CompositeTemplateCallbacksClass {
1706 fn bind_template_callbacks(&mut self);
1710}
1711
1712impl<T, U> CompositeTemplateCallbacksClass for T
1713where
1714 T: ClassStruct<Type = U> + WidgetClassExt,
1715 U: ObjectSubclass<Class = T> + CompositeTemplateCallbacks,
1716{
1717 fn bind_template_callbacks(&mut self) {
1718 <U as CompositeTemplateCallbacks>::bind_template_callbacks(self);
1719 }
1720}
1721
1722pub trait CompositeTemplateInstanceCallbacksClass {
1728 fn bind_template_instance_callbacks(&mut self);
1732}
1733
1734impl<T, U, V> CompositeTemplateInstanceCallbacksClass for T
1735where
1736 T: ClassStruct<Type = U> + WidgetClassExt,
1737 U: ObjectSubclass<Class = T, Type = V>,
1738 V: CompositeTemplateCallbacks,
1739{
1740 fn bind_template_instance_callbacks(&mut self) {
1741 <V as CompositeTemplateCallbacks>::bind_template_callbacks(self);
1742 }
1743}
1744
1745pub trait CompositeTemplateInitializingExt {
1746 fn init_template(&self);
1747}
1748
1749impl<T: WidgetImpl + CompositeTemplate> CompositeTemplateInitializingExt
1750 for glib::subclass::InitializingObject<T>
1751{
1752 fn init_template(&self) {
1753 unsafe {
1754 let widget = self
1755 .as_ref()
1756 .unsafe_cast_ref::<<T as ObjectSubclass>::Type>();
1757 ffi::gtk_widget_init_template(AsRef::<Widget>::as_ref(widget).to_glib_none().0);
1758
1759 <T as CompositeTemplate>::check_template_children(widget);
1760 }
1761 }
1762}
1763
1764pub trait CompositeTemplateDisposeExt {
1765 #[cfg(feature = "v4_8")]
1766 #[cfg_attr(docsrs, doc(cfg(feature = "v4_8")))]
1767 fn dispose_template(&self);
1768}
1769
1770impl<T: WidgetImpl + CompositeTemplate> CompositeTemplateDisposeExt for T {
1771 #[cfg(feature = "v4_8")]
1772 #[cfg_attr(docsrs, doc(cfg(feature = "v4_8")))]
1773 fn dispose_template(&self) {
1774 unsafe {
1775 ffi::gtk_widget_dispose_template(
1776 self.obj().upcast_ref::<Widget>().to_glib_none().0,
1777 <T as ObjectSubclass>::Type::static_type().into_glib(),
1778 );
1779 }
1780 }
1781}