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 {
242 self.parent_keynav_failed(direction_type)
243 }
244
245 fn map(&self) {
249 self.parent_map()
250 }
251
252 fn measure(&self, orientation: Orientation, for_size: i32) -> (i32, i32, i32, i32) {
280 self.parent_measure(orientation, for_size)
281 }
282
283 fn mnemonic_activate(&self, group_cycling: bool) -> bool {
291 self.parent_mnemonic_activate(group_cycling)
292 }
293
294 fn move_focus(&self, direction_type: DirectionType) {
296 self.parent_move_focus(direction_type)
297 }
298
299 fn query_tooltip(&self, x: i32, y: i32, keyboard_tooltip: bool, tooltip: &Tooltip) -> bool {
302 self.parent_query_tooltip(x, y, keyboard_tooltip, tooltip)
303 }
304
305 fn realize(&self) {
310 self.parent_realize()
311 }
312
313 fn root(&self) {
316 self.parent_root()
317 }
318
319 fn set_focus_child(&self, child: Option<&Widget>) {
328 self.parent_set_focus_child(child)
329 }
330
331 #[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
344 #[allow(deprecated)]
345 fn show(&self) {
346 self.parent_show()
347 }
348
349 fn size_allocate(&self, width: i32, height: i32, baseline: i32) {
352 self.parent_size_allocate(width, height, baseline)
353 }
354
355 fn snapshot(&self, snapshot: &Snapshot) {
357 self.parent_snapshot(snapshot)
358 }
359
360 fn state_flags_changed(&self, state_flags: &StateFlags) {
363 self.parent_state_flags_changed(state_flags)
364 }
365
366 fn system_setting_changed(&self, settings: &SystemSetting) {
368 self.parent_system_setting_changed(settings)
369 }
370
371 fn unmap(&self) {
375 self.parent_unmap()
376 }
377
378 fn unrealize(&self) {
384 self.parent_unrealize()
385 }
386
387 fn unroot(&self) {
390 self.parent_unroot()
391 }
392}
393
394pub trait WidgetImplExt: WidgetImpl {
395 fn parent_compute_expand(&self, hexpand: &mut bool, vexpand: &mut bool) {
396 unsafe {
397 let data = Self::type_data();
398 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
399 if let Some(f) = (*parent_class).compute_expand {
400 let mut hexpand_glib = hexpand.into_glib();
401 let mut vexpand_glib = vexpand.into_glib();
402 f(
403 self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0,
404 &mut hexpand_glib,
405 &mut vexpand_glib,
406 );
407 *hexpand = from_glib(hexpand_glib);
408 *vexpand = from_glib(vexpand_glib);
409 }
410 }
411 }
412
413 fn parent_contains(&self, x: f64, y: f64) -> bool {
415 unsafe {
416 let data = Self::type_data();
417 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
418 if let Some(f) = (*parent_class).contains {
419 from_glib(f(
420 self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0,
421 x,
422 y,
423 ))
424 } else {
425 false
426 }
427 }
428 }
429
430 fn parent_direction_changed(&self, previous_direction: TextDirection) {
431 unsafe {
432 let data = Self::type_data();
433 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
434 if let Some(f) = (*parent_class).direction_changed {
435 f(
436 self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0,
437 previous_direction.into_glib(),
438 )
439 }
440 }
441 }
442
443 fn parent_focus(&self, direction_type: DirectionType) -> bool {
445 unsafe {
446 let data = Self::type_data();
447 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
448 if let Some(f) = (*parent_class).focus {
449 from_glib(f(
450 self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0,
451 direction_type.into_glib(),
452 ))
453 } else {
454 false
455 }
456 }
457 }
458
459 fn parent_request_mode(&self) -> SizeRequestMode {
460 unsafe {
461 let data = Self::type_data();
462 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
463 let f = (*parent_class)
464 .get_request_mode
465 .expect("No parent class impl for \"get_request_mode\"");
466 from_glib(f(self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0))
467 }
468 }
469
470 fn parent_grab_focus(&self) -> bool {
472 unsafe {
473 let data = Self::type_data();
474 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
475 if let Some(f) = (*parent_class).grab_focus {
476 from_glib(f(self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0))
477 } else {
478 false
479 }
480 }
481 }
482
483 #[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
484 #[allow(deprecated)]
485 fn parent_hide(&self) {
486 unsafe {
487 let data = Self::type_data();
488 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
489 if let Some(f) = (*parent_class).hide {
490 f(self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0)
491 }
492 }
493 }
494
495 fn parent_keynav_failed(&self, direction_type: DirectionType) -> bool {
499 unsafe {
500 let data = Self::type_data();
501 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
502 if let Some(f) = (*parent_class).keynav_failed {
503 from_glib(f(
504 self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0,
505 direction_type.into_glib(),
506 ))
507 } else {
508 false
509 }
510 }
511 }
512
513 fn parent_map(&self) {
514 unsafe {
515 let data = Self::type_data();
516 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
517 if let Some(f) = (*parent_class).map {
518 f(self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0)
519 }
520 }
521 }
522
523 fn parent_measure(&self, orientation: Orientation, for_size: i32) -> (i32, i32, i32, i32) {
524 unsafe {
525 let data = Self::type_data();
526 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
527
528 let f = (*parent_class)
529 .measure
530 .expect("No parent class impl for \"measure\"");
531
532 let mut min = 0;
533 let mut nat = 0;
534 let mut min_base = -1;
535 let mut nat_base = -1;
536 f(
537 self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0,
538 orientation.into_glib(),
539 for_size,
540 &mut min,
541 &mut nat,
542 &mut min_base,
543 &mut nat_base,
544 );
545 (min, nat, min_base, nat_base)
546 }
547 }
548
549 fn parent_mnemonic_activate(&self, group_cycling: bool) -> bool {
551 unsafe {
552 let data = Self::type_data();
553 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
554 if let Some(f) = (*parent_class).mnemonic_activate {
555 from_glib(f(
556 self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0,
557 group_cycling.into_glib(),
558 ))
559 } else {
560 false
561 }
562 }
563 }
564
565 fn parent_move_focus(&self, direction_type: DirectionType) {
566 unsafe {
567 let data = Self::type_data();
568 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
569 if let Some(f) = (*parent_class).move_focus {
570 f(
571 self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0,
572 direction_type.into_glib(),
573 )
574 }
575 }
576 }
577
578 fn parent_query_tooltip(
579 &self,
580 x: i32,
581 y: i32,
582 keyboard_tooltip: bool,
583 tooltip: &Tooltip,
584 ) -> bool {
585 unsafe {
586 let data = Self::type_data();
587 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
588 if let Some(f) = (*parent_class).query_tooltip {
589 from_glib(f(
590 self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0,
591 x,
592 y,
593 keyboard_tooltip.into_glib(),
594 tooltip.to_glib_none().0,
595 ))
596 } else {
597 false
598 }
599 }
600 }
601
602 fn parent_realize(&self) {
603 unsafe {
604 let data = Self::type_data();
605 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
606 if let Some(f) = (*parent_class).realize {
607 f(self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0)
608 }
609 }
610 }
611
612 fn parent_root(&self) {
613 unsafe {
614 let data = Self::type_data();
615 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
616 if let Some(f) = (*parent_class).root {
617 f(self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0)
618 }
619 }
620 }
621
622 fn parent_set_focus_child(&self, child: Option<&Widget>) {
623 unsafe {
624 let data = Self::type_data();
625 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
626 if let Some(f) = (*parent_class).set_focus_child {
627 f(
628 self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0,
629 child.to_glib_none().0,
630 )
631 }
632 }
633 }
634
635 #[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
636 #[allow(deprecated)]
637 fn parent_show(&self) {
638 unsafe {
639 let data = Self::type_data();
640 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
641 if let Some(f) = (*parent_class).show {
642 f(self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0)
643 }
644 }
645 }
646
647 fn parent_size_allocate(&self, width: i32, height: i32, baseline: i32) {
648 unsafe {
649 let data = Self::type_data();
650 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
651 if let Some(f) = (*parent_class).size_allocate {
652 f(
653 self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0,
654 width,
655 height,
656 baseline,
657 )
658 }
659 }
660 }
661
662 fn parent_snapshot(&self, snapshot: &Snapshot) {
663 unsafe {
664 let data = Self::type_data();
665 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
666 if let Some(f) = (*parent_class).snapshot {
667 f(
668 self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0,
669 snapshot.to_glib_none().0,
670 )
671 }
672 }
673 }
674
675 fn parent_state_flags_changed(&self, state_flags: &StateFlags) {
676 unsafe {
677 let data = Self::type_data();
678 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
679 if let Some(f) = (*parent_class).state_flags_changed {
680 f(
681 self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0,
682 state_flags.into_glib(),
683 )
684 }
685 }
686 }
687
688 fn parent_system_setting_changed(&self, settings: &SystemSetting) {
689 unsafe {
690 let data = Self::type_data();
691 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
692 if let Some(f) = (*parent_class).system_setting_changed {
693 f(
694 self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0,
695 settings.into_glib(),
696 )
697 }
698 }
699 }
700
701 fn parent_unmap(&self) {
702 unsafe {
703 let data = Self::type_data();
704 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
705 if let Some(f) = (*parent_class).unmap {
706 f(self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0)
707 }
708 }
709 }
710
711 fn parent_unrealize(&self) {
712 unsafe {
713 let data = Self::type_data();
714 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWidgetClass;
715 if let Some(f) = (*parent_class).unrealize {
716 f(self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0)
717 }
718 }
719 }
720
721 fn parent_unroot(&self) {
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).unroot {
726 f(self.obj().unsafe_cast_ref::<Widget>().to_glib_none().0)
727 }
728 }
729 }
730}
731
732impl<T: WidgetImpl> WidgetImplExt for T {}
733
734unsafe impl<T: WidgetImpl> IsSubclassable<T> for Widget {
735 fn class_init(class: &mut ::glib::Class<Self>) {
736 Self::parent_class_init::<T>(class);
737
738 assert_initialized_main_thread!();
739
740 let klass = class.as_mut();
741 unsafe {
742 let mut data = T::type_data();
743 let data = data.as_mut();
744 data.set_class_data(<T as ObjectSubclassType>::type_(), Internal::default());
746 }
747
748 klass.compute_expand = Some(widget_compute_expand::<T>);
749 klass.contains = Some(widget_contains::<T>);
750 klass.direction_changed = Some(widget_direction_changed::<T>);
751 klass.focus = Some(widget_focus::<T>);
752 klass.get_request_mode = Some(widget_get_request_mode::<T>);
753 klass.grab_focus = Some(widget_grab_focus::<T>);
754 klass.hide = Some(widget_hide::<T>);
755 klass.keynav_failed = Some(widget_keynav_failed::<T>);
756 klass.map = Some(widget_map::<T>);
757 klass.measure = Some(widget_measure::<T>);
758 klass.mnemonic_activate = Some(widget_mnemonic_activate::<T>);
759 klass.move_focus = Some(widget_move_focus::<T>);
760 klass.query_tooltip = Some(widget_query_tooltip::<T>);
761 klass.realize = Some(widget_realize::<T>);
762 klass.root = Some(widget_root::<T>);
763 klass.set_focus_child = Some(widget_set_focus_child::<T>);
764 klass.show = Some(widget_show::<T>);
765 klass.size_allocate = Some(widget_size_allocate::<T>);
766 klass.snapshot = Some(widget_snapshot::<T>);
767 klass.state_flags_changed = Some(widget_state_flags_changed::<T>);
768 klass.system_setting_changed = Some(widget_system_setting_changed::<T>);
769 klass.unmap = Some(widget_unmap::<T>);
770 klass.unrealize = Some(widget_unrealize::<T>);
771 klass.unroot = Some(widget_unroot::<T>);
772 }
773}
774
775unsafe extern "C" fn widget_compute_expand<T: WidgetImpl>(
776 ptr: *mut ffi::GtkWidget,
777 hexpand_ptr: *mut glib::ffi::gboolean,
778 vexpand_ptr: *mut glib::ffi::gboolean,
779) {
780 unsafe {
781 let instance = &*(ptr as *mut T::Instance);
782 let imp = instance.imp();
783
784 let widget = imp.obj();
785 let widget = widget.unsafe_cast_ref::<Widget>();
786 let mut hexpand: bool = if widget.is_hexpand_set() {
787 widget.hexpands()
788 } else {
789 from_glib(*hexpand_ptr)
790 };
791 let mut vexpand: bool = if widget.is_vexpand_set() {
792 widget.vexpands()
793 } else {
794 from_glib(*vexpand_ptr)
795 };
796
797 imp.compute_expand(&mut hexpand, &mut vexpand);
798
799 *hexpand_ptr = hexpand.into_glib();
800 *vexpand_ptr = vexpand.into_glib();
801 }
802}
803
804unsafe extern "C" fn widget_contains<T: WidgetImpl>(
805 ptr: *mut ffi::GtkWidget,
806 x: f64,
807 y: f64,
808) -> glib::ffi::gboolean {
809 unsafe {
810 let instance = &*(ptr as *mut T::Instance);
811 let imp = instance.imp();
812
813 imp.contains(x, y).into_glib()
814 }
815}
816
817unsafe extern "C" fn widget_direction_changed<T: WidgetImpl>(
818 ptr: *mut ffi::GtkWidget,
819 direction_ptr: ffi::GtkTextDirection,
820) {
821 unsafe {
822 let instance = &*(ptr as *mut T::Instance);
823 let imp = instance.imp();
824 let direction_wrap = from_glib(direction_ptr);
825
826 imp.direction_changed(direction_wrap)
827 }
828}
829
830unsafe extern "C" fn widget_focus<T: WidgetImpl>(
831 ptr: *mut ffi::GtkWidget,
832 direction_type_ptr: ffi::GtkDirectionType,
833) -> glib::ffi::gboolean {
834 unsafe {
835 let instance = &*(ptr as *mut T::Instance);
836 let imp = instance.imp();
837 let direction_type = from_glib(direction_type_ptr);
838
839 imp.focus(direction_type).into_glib()
840 }
841}
842
843unsafe extern "C" fn widget_get_request_mode<T: WidgetImpl>(
844 ptr: *mut ffi::GtkWidget,
845) -> ffi::GtkSizeRequestMode {
846 unsafe {
847 let instance = &*(ptr as *mut T::Instance);
848 let imp = instance.imp();
849
850 imp.request_mode().into_glib()
851 }
852}
853
854unsafe extern "C" fn widget_grab_focus<T: WidgetImpl>(
855 ptr: *mut ffi::GtkWidget,
856) -> glib::ffi::gboolean {
857 unsafe {
858 let instance = &*(ptr as *mut T::Instance);
859 let imp = instance.imp();
860
861 imp.grab_focus().into_glib()
862 }
863}
864
865unsafe extern "C" fn widget_hide<T: WidgetImpl>(ptr: *mut ffi::GtkWidget) {
866 unsafe {
867 let instance = &*(ptr as *mut T::Instance);
868 let imp = instance.imp();
869
870 imp.hide()
871 }
872}
873
874unsafe extern "C" fn widget_keynav_failed<T: WidgetImpl>(
875 ptr: *mut ffi::GtkWidget,
876 direction_type_ptr: ffi::GtkDirectionType,
877) -> glib::ffi::gboolean {
878 unsafe {
879 let instance = &*(ptr as *mut T::Instance);
880 let imp = instance.imp();
881 let direction_type = from_glib(direction_type_ptr);
882
883 imp.keynav_failed(direction_type).into_glib()
884 }
885}
886
887unsafe extern "C" fn widget_map<T: WidgetImpl>(ptr: *mut ffi::GtkWidget) {
888 unsafe {
889 let instance = &*(ptr as *mut T::Instance);
890 let imp = instance.imp();
891
892 imp.map()
893 }
894}
895
896unsafe extern "C" fn widget_measure<T: WidgetImpl>(
897 ptr: *mut ffi::GtkWidget,
898 orientation_ptr: ffi::GtkOrientation,
899 for_size: i32,
900 min_ptr: *mut libc::c_int,
901 nat_ptr: *mut libc::c_int,
902 min_base_ptr: *mut libc::c_int,
903 nat_base_ptr: *mut libc::c_int,
904) {
905 unsafe {
906 let instance = &*(ptr as *mut T::Instance);
907 let imp = instance.imp();
908 let orientation = from_glib(orientation_ptr);
909 let (min, nat, min_base, nat_base) = imp.measure(orientation, for_size);
910 if !min_ptr.is_null() {
911 *min_ptr = min;
912 }
913 if !nat_ptr.is_null() {
914 *nat_ptr = nat;
915 }
916 if !min_base_ptr.is_null() {
917 *min_base_ptr = min_base;
918 }
919 if !nat_base_ptr.is_null() {
920 *nat_base_ptr = nat_base;
921 }
922 }
923}
924
925unsafe extern "C" fn widget_mnemonic_activate<T: WidgetImpl>(
926 ptr: *mut ffi::GtkWidget,
927 group_cycling_ptr: glib::ffi::gboolean,
928) -> glib::ffi::gboolean {
929 unsafe {
930 let instance = &*(ptr as *mut T::Instance);
931 let imp = instance.imp();
932 let group_cycling: bool = from_glib(group_cycling_ptr);
933
934 imp.mnemonic_activate(group_cycling).into_glib()
935 }
936}
937
938unsafe extern "C" fn widget_move_focus<T: WidgetImpl>(
939 ptr: *mut ffi::GtkWidget,
940 direction_type_ptr: ffi::GtkDirectionType,
941) {
942 unsafe {
943 let instance = &*(ptr as *mut T::Instance);
944 let imp = instance.imp();
945 let direction_type = from_glib(direction_type_ptr);
946
947 imp.move_focus(direction_type)
948 }
949}
950
951unsafe extern "C" fn widget_query_tooltip<T: WidgetImpl>(
952 ptr: *mut ffi::GtkWidget,
953 x: i32,
954 y: i32,
955 keyboard_tooltip_ptr: glib::ffi::gboolean,
956 tooltip_ptr: *mut ffi::GtkTooltip,
957) -> glib::ffi::gboolean {
958 unsafe {
959 let instance = &*(ptr as *mut T::Instance);
960 let imp = instance.imp();
961
962 let keyboard_tooltip: bool = from_glib(keyboard_tooltip_ptr);
963 let tooltip = from_glib_borrow(tooltip_ptr);
964
965 imp.query_tooltip(x, y, keyboard_tooltip, &tooltip)
966 .into_glib()
967 }
968}
969
970unsafe extern "C" fn widget_realize<T: WidgetImpl>(ptr: *mut ffi::GtkWidget) {
971 unsafe {
972 let instance = &*(ptr as *mut T::Instance);
973 let imp = instance.imp();
974
975 imp.realize()
976 }
977}
978
979unsafe extern "C" fn widget_root<T: WidgetImpl>(ptr: *mut ffi::GtkWidget) {
980 unsafe {
981 let instance = &*(ptr as *mut T::Instance);
982 let imp = instance.imp();
983
984 imp.root()
985 }
986}
987
988unsafe extern "C" fn widget_set_focus_child<T: WidgetImpl>(
989 ptr: *mut ffi::GtkWidget,
990 child_ptr: *mut ffi::GtkWidget,
991) {
992 unsafe {
993 let instance = &*(ptr as *mut T::Instance);
994 let imp = instance.imp();
995 let child: Borrowed<Option<Widget>> = from_glib_borrow(child_ptr);
996
997 imp.set_focus_child(child.as_ref().as_ref())
998 }
999}
1000
1001unsafe extern "C" fn widget_show<T: WidgetImpl>(ptr: *mut ffi::GtkWidget) {
1002 unsafe {
1003 let instance = &*(ptr as *mut T::Instance);
1004 let imp = instance.imp();
1005
1006 imp.show()
1007 }
1008}
1009
1010unsafe extern "C" fn widget_size_allocate<T: WidgetImpl>(
1011 ptr: *mut ffi::GtkWidget,
1012 width: i32,
1013 height: i32,
1014 baseline: i32,
1015) {
1016 unsafe {
1017 let instance = &*(ptr as *mut T::Instance);
1018 let imp = instance.imp();
1019
1020 imp.size_allocate(width, height, baseline)
1021 }
1022}
1023
1024unsafe extern "C" fn widget_snapshot<T: WidgetImpl>(
1025 ptr: *mut ffi::GtkWidget,
1026 snapshot_ptr: *mut ffi::GtkSnapshot,
1027) {
1028 unsafe {
1029 let instance = &*(ptr as *mut T::Instance);
1030 let imp = instance.imp();
1031 let snapshot = from_glib_borrow(snapshot_ptr);
1032
1033 imp.snapshot(&snapshot)
1034 }
1035}
1036
1037unsafe extern "C" fn widget_state_flags_changed<T: WidgetImpl>(
1038 ptr: *mut ffi::GtkWidget,
1039 state_flags_ptr: ffi::GtkStateFlags,
1040) {
1041 unsafe {
1042 let instance = &*(ptr as *mut T::Instance);
1043 let imp = instance.imp();
1044 let state_flags = from_glib(state_flags_ptr);
1045
1046 imp.state_flags_changed(&state_flags)
1047 }
1048}
1049
1050unsafe extern "C" fn widget_system_setting_changed<T: WidgetImpl>(
1051 ptr: *mut ffi::GtkWidget,
1052 settings_ptr: ffi::GtkSystemSetting,
1053) {
1054 unsafe {
1055 let instance = &*(ptr as *mut T::Instance);
1056 let imp = instance.imp();
1057 let settings = from_glib(settings_ptr);
1058
1059 imp.system_setting_changed(&settings)
1060 }
1061}
1062
1063unsafe extern "C" fn widget_unmap<T: WidgetImpl>(ptr: *mut ffi::GtkWidget) {
1064 unsafe {
1065 let instance = &*(ptr as *mut T::Instance);
1066 let imp = instance.imp();
1067
1068 imp.unmap()
1069 }
1070}
1071
1072unsafe extern "C" fn widget_unrealize<T: WidgetImpl>(ptr: *mut ffi::GtkWidget) {
1073 unsafe {
1074 let instance = &*(ptr as *mut T::Instance);
1075 let imp = instance.imp();
1076
1077 imp.unrealize()
1078 }
1079}
1080
1081unsafe extern "C" fn widget_unroot<T: WidgetImpl>(ptr: *mut ffi::GtkWidget) {
1082 unsafe {
1083 let instance = &*(ptr as *mut T::Instance);
1084 let imp = instance.imp();
1085
1086 imp.unroot()
1087 }
1088}
1089
1090#[allow(clippy::missing_safety_doc)]
1091pub unsafe trait WidgetClassExt: ClassStruct {
1092 #[doc(alias = "gtk_widget_class_set_template")]
1093 fn set_template_bytes(&mut self, template: &glib::Bytes) {
1094 unsafe {
1095 let widget_class = self as *mut _ as *mut ffi::GtkWidgetClass;
1096 ffi::gtk_widget_class_set_template(widget_class, template.to_glib_none().0);
1097 }
1098 }
1099
1100 fn set_template(&mut self, template: &[u8]) {
1104 let template_bytes = glib::Bytes::from(template);
1105 self.set_template_bytes(&template_bytes);
1106 }
1107
1108 fn set_template_static(&mut self, template: &'static [u8]) {
1109 let template_bytes = glib::Bytes::from_static(template);
1110 self.set_template_bytes(&template_bytes);
1111 }
1112
1113 #[doc(alias = "gtk_widget_class_set_template_from_resource")]
1118 fn set_template_from_resource(&mut self, resource_name: &str) {
1119 unsafe {
1120 let widget_class = self as *mut _ as *mut ffi::GtkWidgetClass;
1121 ffi::gtk_widget_class_set_template_from_resource(
1122 widget_class,
1123 resource_name.to_glib_none().0,
1124 );
1125 }
1126 }
1127
1128 fn install_action_async<Fut, F>(
1129 &mut self,
1130 action_name: &str,
1131 parameter_type: Option<&glib::VariantTy>,
1132 activate: F,
1133 ) where
1134 F: Fn(
1135 <<Self as ClassStruct>::Type as ObjectSubclass>::Type,
1136 String,
1137 Option<Variant>,
1138 ) -> Fut
1139 + 'static
1140 + Clone,
1141 Fut: Future<Output = ()>,
1142 {
1143 self.install_action(
1144 action_name,
1145 parameter_type,
1146 move |this, action_name, parameter_type| {
1147 let ctx = glib::MainContext::default();
1148 let action_name = action_name.to_owned();
1149 let parameter_type = parameter_type.map(ToOwned::to_owned);
1150 ctx.spawn_local(glib::clone!(
1151 #[strong]
1152 this,
1153 #[strong]
1154 action_name,
1155 #[strong]
1156 parameter_type,
1157 #[strong]
1158 activate,
1159 async move {
1160 activate(this, action_name, parameter_type).await;
1161 }
1162 ));
1163 },
1164 );
1165 }
1166
1167 #[doc(alias = "gtk_widget_class_install_action")]
1181 fn install_action<F>(
1182 &mut self,
1183 action_name: &str,
1184 parameter_type: Option<&glib::VariantTy>,
1185 activate: F,
1186 ) where
1187 F: Fn(&<<Self as ClassStruct>::Type as ObjectSubclass>::Type, &str, Option<&Variant>)
1188 + 'static,
1189 {
1190 unsafe {
1191 let mut data = <Self::Type as ObjectSubclassType>::type_data();
1194 let data = data.as_mut();
1195
1196 let f: Box_<F> = Box_::new(activate);
1197
1198 let internal = data
1199 .class_data_mut::<Internal>(<Self::Type as ObjectSubclassType>::type_())
1200 .expect("Something bad happened at class_init, the internal class_data is missing");
1201 let callback_ptr = Box_::into_raw(f) as glib::ffi::gpointer;
1202 internal
1203 .actions
1204 .insert(action_name.to_string(), callback_ptr);
1205
1206 unsafe extern "C" fn activate_trampoline<F, S>(
1207 this: *mut ffi::GtkWidget,
1208 action_name: *const libc::c_char,
1209 parameter: *mut glib::ffi::GVariant,
1210 ) where
1211 S: ClassStruct,
1212 <S as ClassStruct>::Type: ObjectSubclass,
1213 F: Fn(&<<S as ClassStruct>::Type as ObjectSubclass>::Type, &str, Option<&Variant>)
1214 + 'static,
1215 {
1216 unsafe {
1217 let action_name = GString::from_glib_borrow(action_name);
1218
1219 let data = <S::Type as ObjectSubclassType>::type_data();
1220 let internal = data
1221 .as_ref()
1222 .class_data::<Internal>(<S::Type as ObjectSubclassType>::type_())
1223 .unwrap();
1224 let activate_callback = *internal
1225 .actions
1226 .get(&action_name.to_string())
1227 .unwrap_or_else(|| {
1228 panic!("Action name '{}' was not found", action_name.as_str());
1229 });
1230
1231 let widget = Widget::from_glib_borrow(this);
1232
1233 let f: &F = &*(activate_callback as *const F);
1234 f(
1235 widget.unsafe_cast_ref(),
1236 &action_name,
1237 Option::<Variant>::from_glib_borrow(parameter)
1238 .as_ref()
1239 .as_ref(),
1240 )
1241 }
1242 }
1243 let widget_class = self as *mut _ as *mut ffi::GtkWidgetClass;
1244 let callback = activate_trampoline::<F, Self>;
1245 ffi::gtk_widget_class_install_action(
1246 widget_class,
1247 action_name.to_glib_none().0,
1248 parameter_type.map(|p| p.as_str()).to_glib_none().0,
1249 Some(callback),
1250 );
1251 }
1252 }
1253
1254 #[doc(alias = "gtk_widget_class_set_template_scope")]
1264 fn set_template_scope<S: IsA<BuilderScope>>(&mut self, scope: &S) {
1265 unsafe {
1266 let widget_class = self as *mut _ as *mut ffi::GtkWidgetClass;
1267 ffi::gtk_widget_class_set_template_scope(widget_class, scope.as_ref().to_glib_none().0);
1268 }
1269 }
1270
1271 #[doc(alias = "gtk_widget_class_add_binding")]
1296 fn add_binding<
1297 F: Fn(&<<Self as ClassStruct>::Type as ObjectSubclass>::Type) -> glib::Propagation + 'static,
1298 >(
1299 &mut self,
1300 keyval: gdk::Key,
1301 mods: gdk::ModifierType,
1302 callback: F,
1303 ) {
1304 let shortcut = crate::Shortcut::new(
1305 Some(crate::KeyvalTrigger::new(keyval, mods)),
1306 Some(crate::CallbackAction::new(
1307 move |widget, _| -> glib::Propagation {
1308 unsafe { callback(widget.unsafe_cast_ref()) }
1309 },
1310 )),
1311 );
1312 unsafe {
1313 let widget_class = self as *mut _ as *mut ffi::GtkWidgetClass;
1314 ffi::gtk_widget_class_add_shortcut(widget_class, shortcut.to_glib_none().0);
1315 }
1316 }
1317
1318 #[doc(alias = "gtk_widget_class_add_binding_signal")]
1341 fn add_binding_signal(&mut self, keyval: gdk::Key, mods: gdk::ModifierType, signal_name: &str) {
1342 let type_ = <Self::Type as ObjectSubclassType>::type_();
1343 assert!(
1344 SignalId::lookup(signal_name, type_).is_some(),
1345 "Signal '{signal_name}' doesn't exists for type '{type_}'",
1346 );
1347
1348 let shortcut = crate::Shortcut::new(
1349 Some(crate::KeyvalTrigger::new(keyval, mods)),
1350 Some(crate::SignalAction::new(signal_name)),
1351 );
1352 unsafe {
1353 let widget_class = self as *mut _ as *mut ffi::GtkWidgetClass;
1354 ffi::gtk_widget_class_add_shortcut(widget_class, shortcut.to_glib_none().0);
1355 }
1356 }
1357
1358 #[doc(alias = "gtk_widget_class_set_activate_signal")]
1367 fn set_activate_signal(&mut self, signal_id: SignalId) {
1368 unsafe {
1369 let widget_class = self as *mut _ as *mut ffi::GtkWidgetClass;
1370 ffi::gtk_widget_class_set_activate_signal(widget_class, signal_id.into_glib())
1371 }
1372 }
1373
1374 #[doc(alias = "gtk_widget_class_set_activate_signal_from_name")]
1385 fn set_activate_signal_from_name(&mut self, signal_name: &str) {
1386 let type_ = <Self::Type as ObjectSubclassType>::type_();
1387 assert!(
1388 SignalId::lookup(signal_name, type_).is_some(),
1389 "Signal '{signal_name}' doesn't exists for type '{type_}'",
1390 );
1391
1392 unsafe {
1393 let widget_class = self as *mut _ as *mut ffi::GtkWidgetClass;
1394 ffi::gtk_widget_class_set_activate_signal_from_name(
1395 widget_class,
1396 signal_name.to_glib_none().0,
1397 );
1398 }
1399 }
1400
1401 #[doc(alias = "gtk_widget_class_set_layout_manager_type")]
1412 fn set_layout_manager_type<T: IsA<LayoutManager>>(&mut self) {
1413 unsafe {
1414 let widget_class = self as *mut _ as *mut ffi::GtkWidgetClass;
1415 ffi::gtk_widget_class_set_layout_manager_type(
1416 widget_class,
1417 T::static_type().into_glib(),
1418 );
1419 }
1420 }
1421
1422 #[doc(alias = "gtk_widget_class_set_css_name")]
1430 fn set_css_name(&mut self, name: &str) {
1431 unsafe {
1432 let widget_class = self as *mut _ as *mut ffi::GtkWidgetClass;
1433 ffi::gtk_widget_class_set_css_name(widget_class, name.to_glib_none().0);
1434 }
1435 }
1436
1437 #[doc(alias = "gtk_widget_class_set_accessible_role")]
1444 fn set_accessible_role(&mut self, role: AccessibleRole) {
1445 unsafe {
1446 let widget_class = self as *mut _ as *mut ffi::GtkWidgetClass;
1447 ffi::gtk_widget_class_set_accessible_role(widget_class, role.into_glib());
1448 }
1449 }
1450
1451 #[allow(clippy::missing_safety_doc)]
1452 #[doc(alias = "gtk_widget_class_bind_template_child_full")]
1453 unsafe fn bind_template_child_with_offset<T>(
1454 &mut self,
1455 name: &str,
1456 internal: bool,
1457 offset: field_offset::FieldOffset<Self::Type, TemplateChild<T>>,
1458 ) where
1459 T: ObjectType + FromGlibPtrNone<*mut <T as ObjectType>::GlibType>,
1460 {
1461 unsafe {
1462 let widget_class = self as *mut _ as *mut ffi::GtkWidgetClass;
1463 let private_offset = <Self::Type as ObjectSubclassType>::type_data()
1464 .as_ref()
1465 .impl_offset();
1466 ffi::gtk_widget_class_bind_template_child_full(
1467 widget_class,
1468 name.to_glib_none().0,
1469 internal.into_glib(),
1470 private_offset + (offset.get_byte_offset() as isize),
1471 )
1472 }
1473 }
1474
1475 fn rust_template_scope(&mut self) -> BuilderRustScope {
1476 assert_initialized_main_thread!();
1477 unsafe {
1478 let mut data = <Self::Type as ObjectSubclassType>::type_data();
1479 let internal = data
1480 .as_mut()
1481 .class_data_mut::<Internal>(<Self::Type as ObjectSubclassType>::type_())
1482 .expect("Something bad happened at class_init, the internal class_data is missing");
1483 let scope = internal.scope.get_or_insert_with(|| {
1484 let scope = BuilderRustScope::new();
1485 self.set_template_scope(&scope);
1486 scope.into_glib_ptr()
1487 });
1488 from_glib_none(*scope)
1489 }
1490 }
1491}
1492
1493unsafe impl<T: ClassStruct> WidgetClassExt for T where T::Type: WidgetImpl {}
1494
1495#[derive(Debug, PartialEq, Eq)]
1496#[repr(transparent)]
1497pub struct TemplateChild<T>
1498where
1499 T: ObjectType + FromGlibPtrNone<*mut <T as ObjectType>::GlibType>,
1500{
1501 ptr: *mut <T as ObjectType>::GlibType,
1502}
1503
1504impl<T: Property> Property for TemplateChild<T>
1505where
1506 T: ObjectType + FromGlibPtrNone<*mut <T as ObjectType>::GlibType>,
1507{
1508 type Value = T::Value;
1509}
1510
1511impl<T> Default for TemplateChild<T>
1512where
1513 T: ObjectType + FromGlibPtrNone<*mut <T as ObjectType>::GlibType>,
1514{
1515 fn default() -> Self {
1516 T::static_type();
1517
1518 Self {
1519 ptr: std::ptr::null_mut(),
1520 }
1521 }
1522}
1523
1524impl<T> PropertyGet for TemplateChild<T>
1525where
1526 T: Property + ObjectType + FromGlibPtrNone<*mut <T as ObjectType>::GlibType>,
1527{
1528 type Value = T;
1529
1530 fn get<R, F: Fn(&Self::Value) -> R>(&self, f: F) -> R {
1531 f(&self.get())
1532 }
1533}
1534
1535impl<T> std::ops::Deref for TemplateChild<T>
1536where
1537 T: ObjectType + FromGlibPtrNone<*mut <T as ObjectType>::GlibType>,
1538{
1539 type Target = T;
1540
1541 #[inline]
1542 fn deref(&self) -> &Self::Target {
1543 unsafe {
1544 if !self.is_bound() {
1545 let name = Self::name();
1546 panic!(
1547 "Failed to retrieve template child. Please check that all fields of type `{name}` have been bound and have a #[template_child] attribute."
1548 );
1549 }
1550 &*(&self.ptr as *const _ as *const T)
1551 }
1552 }
1553}
1554
1555impl<T> Downgrade for TemplateChild<T>
1556where
1557 T: ObjectType + FromGlibPtrNone<*mut <T as ObjectType>::GlibType> + Downgrade,
1558{
1559 type Weak = T::Weak;
1560
1561 fn downgrade(&self) -> Self::Weak {
1562 T::downgrade(&self.get())
1563 }
1564}
1565
1566impl<T> TemplateChild<T>
1567where
1568 T: ObjectType + FromGlibPtrNone<*mut <T as ObjectType>::GlibType>,
1569{
1570 pub(crate) fn name<'a>() -> &'a str {
1571 T::static_type().name()
1572 }
1573
1574 #[track_caller]
1575 pub fn get(&self) -> T {
1576 self.try_get()
1577 .unwrap_or_else(|| {
1578 let name = Self::name();
1579 panic!("Failed to retrieve template child. Please check that all fields of type `{name}` have been bound and have a #[template_child] attribute.");
1580 })
1581 }
1582
1583 pub fn is_bound(&self) -> bool {
1587 !self.ptr.is_null()
1588 }
1589
1590 pub fn try_get(&self) -> Option<T> {
1593 unsafe { Option::<T>::from_glib_none(self.ptr) }
1594 }
1595}
1596
1597pub trait CompositeTemplate: WidgetImpl {
1603 fn bind_template(klass: &mut Self::Class);
1604 fn check_template_children(widget: &<Self as ObjectSubclass>::Type);
1605}
1606
1607pub trait CompositeTemplateClass {
1612 fn bind_template(&mut self);
1616}
1617
1618impl<T, U> CompositeTemplateClass for T
1619where
1620 T: ClassStruct<Type = U>,
1621 U: ObjectSubclass<Class = T> + CompositeTemplate,
1622{
1623 fn bind_template(&mut self) {
1624 <U as CompositeTemplate>::bind_template(self);
1625 }
1626}
1627
1628pub type TemplateCallback = (&'static str, fn(&[glib::Value]) -> Option<glib::Value>);
1629
1630pub trait CompositeTemplateCallbacks {
1636 const CALLBACKS: &'static [TemplateCallback];
1637
1638 fn bind_template_callbacks<T: WidgetClassExt>(klass: &mut T) {
1642 Self::add_callbacks_to_scope(&klass.rust_template_scope());
1643 }
1644 fn bind_template_callbacks_prefixed<T: WidgetClassExt>(klass: &mut T, prefix: &str) {
1648 Self::add_callbacks_to_scope_prefixed(&klass.rust_template_scope(), prefix);
1649 }
1650 fn add_callbacks_to_scope(scope: &BuilderRustScope) {
1653 for (name, func) in Self::CALLBACKS {
1654 scope.add_callback(*name, func);
1655 }
1656 }
1657 fn add_callbacks_to_scope_prefixed(scope: &BuilderRustScope, prefix: &str) {
1661 for (name, func) in Self::CALLBACKS {
1662 scope.add_callback(format!("{prefix}{name}"), func);
1663 }
1664 }
1665}
1666
1667pub trait CompositeTemplateCallbacksClass {
1672 fn bind_template_callbacks(&mut self);
1676}
1677
1678impl<T, U> CompositeTemplateCallbacksClass for T
1679where
1680 T: ClassStruct<Type = U> + WidgetClassExt,
1681 U: ObjectSubclass<Class = T> + CompositeTemplateCallbacks,
1682{
1683 fn bind_template_callbacks(&mut self) {
1684 <U as CompositeTemplateCallbacks>::bind_template_callbacks(self);
1685 }
1686}
1687
1688pub trait CompositeTemplateInstanceCallbacksClass {
1694 fn bind_template_instance_callbacks(&mut self);
1698}
1699
1700impl<T, U, V> CompositeTemplateInstanceCallbacksClass for T
1701where
1702 T: ClassStruct<Type = U> + WidgetClassExt,
1703 U: ObjectSubclass<Class = T, Type = V>,
1704 V: CompositeTemplateCallbacks,
1705{
1706 fn bind_template_instance_callbacks(&mut self) {
1707 <V as CompositeTemplateCallbacks>::bind_template_callbacks(self);
1708 }
1709}
1710
1711pub trait CompositeTemplateInitializingExt {
1712 fn init_template(&self);
1713}
1714
1715impl<T: WidgetImpl + CompositeTemplate> CompositeTemplateInitializingExt
1716 for glib::subclass::InitializingObject<T>
1717{
1718 fn init_template(&self) {
1719 unsafe {
1720 let widget = self
1721 .as_ref()
1722 .unsafe_cast_ref::<<T as ObjectSubclass>::Type>();
1723 ffi::gtk_widget_init_template(AsRef::<Widget>::as_ref(widget).to_glib_none().0);
1724
1725 <T as CompositeTemplate>::check_template_children(widget);
1726 }
1727 }
1728}
1729
1730pub trait CompositeTemplateDisposeExt {
1731 #[cfg(feature = "v4_8")]
1732 #[cfg_attr(docsrs, doc(cfg(feature = "v4_8")))]
1733 fn dispose_template(&self);
1734}
1735
1736impl<T: WidgetImpl + CompositeTemplate> CompositeTemplateDisposeExt for T {
1737 #[cfg(feature = "v4_8")]
1738 #[cfg_attr(docsrs, doc(cfg(feature = "v4_8")))]
1739 fn dispose_template(&self) {
1740 unsafe {
1741 ffi::gtk_widget_dispose_template(
1742 self.obj().upcast_ref::<Widget>().to_glib_none().0,
1743 <T as ObjectSubclass>::Type::static_type().into_glib(),
1744 );
1745 }
1746 }
1747}