1use glib::{ControlFlow, WeakRef, subclass::SignalId, translate::*};
4
5use crate::{
6 AccessibleRole, Shortcut, Widget, ffi, prelude::*, subclass::widget::WidgetActionIter,
7};
8
9pub trait WidgetExtManual: IsA<Widget> + 'static {
12 #[doc(alias = "gtk_widget_add_tick_callback")]
38 fn add_tick_callback<P: Fn(&Self, &gdk::FrameClock) -> ControlFlow + 'static>(
39 &self,
40 callback: P,
41 ) -> TickCallbackId {
42 let callback_data: Box<P> = Box::new(callback);
43
44 unsafe extern "C" fn callback_func<
45 O: IsA<Widget>,
46 P: Fn(&O, &gdk::FrameClock) -> ControlFlow + 'static,
47 >(
48 widget: *mut ffi::GtkWidget,
49 frame_clock: *mut gdk::ffi::GdkFrameClock,
50 user_data: glib::ffi::gpointer,
51 ) -> glib::ffi::gboolean {
52 unsafe {
53 let widget: Borrowed<Widget> = from_glib_borrow(widget);
54 let frame_clock = from_glib_borrow(frame_clock);
55 let callback: &P = &*(user_data as *mut _);
56 let res = (*callback)(widget.unsafe_cast_ref(), &frame_clock);
57 res.into_glib()
58 }
59 }
60 let callback = Some(callback_func::<Self, P> as _);
61
62 unsafe extern "C" fn notify_func<
63 O: IsA<Widget>,
64 P: Fn(&O, &gdk::FrameClock) -> ControlFlow + 'static,
65 >(
66 data: glib::ffi::gpointer,
67 ) {
68 unsafe {
69 let _callback: Box<P> = Box::from_raw(data as *mut _);
70 }
71 }
72 let destroy_call = Some(notify_func::<Self, P> as _);
73
74 let id = unsafe {
75 ffi::gtk_widget_add_tick_callback(
76 self.as_ref().to_glib_none().0,
77 callback,
78 Box::into_raw(callback_data) as *mut _,
79 destroy_call,
80 )
81 };
82 TickCallbackId {
83 id,
84 widget: self.upcast_ref().downgrade(),
85 }
86 }
87}
88
89impl<O: IsA<Widget>> WidgetExtManual for O {}
90
91#[derive(Debug)]
92pub struct TickCallbackId {
93 id: u32,
94 widget: WeakRef<Widget>,
95}
96
97impl PartialEq for TickCallbackId {
98 #[inline]
99 fn eq(&self, other: &Self) -> bool {
100 self.id == other.id
101 }
102}
103
104impl TickCallbackId {
105 #[doc(alias = "gtk_widget_remove_tick_callback")]
110 #[doc(alias = "remove_tick_callback")]
111 pub fn remove(self) {
112 if let Some(widget) = self.widget.upgrade() {
113 unsafe {
114 ffi::gtk_widget_remove_tick_callback(widget.to_glib_none().0, self.id);
115 }
116 }
117 }
118}
119
120pub trait WidgetClassManualExt {
139 #[doc(alias = "gtk_widget_class_add_shortcut")]
140 fn add_shortcut(&self, shortcut: &Shortcut);
141
142 #[doc(alias = "gtk_widget_class_add_binding_action")]
143 fn add_binding_action(&self, keyval: gdk::Key, mods: gdk::ModifierType, action_name: &str);
144
145 #[doc(alias = "gtk_widget_class_install_property_action")]
146 fn install_property_action(&self, action_name: &str, property_name: &str);
147
148 #[doc(alias = "gtk_widget_class_query_action")]
149 fn query_action(&self) -> WidgetActionIter;
150
151 #[doc(alias = "gtk_widget_class_get_activate_signal")]
152 #[doc(alias = "get_activate_signal")]
153 fn activate_signal(&self) -> Option<SignalId>;
154
155 #[doc(alias = "gtk_widget_class_get_layout_manager_type")]
156 #[doc(alias = "get_layout_manager_type")]
157 fn layout_manager_type(&self) -> glib::Type;
158
159 #[doc(alias = "gtk_widget_class_get_css_name")]
160 #[doc(alias = "get_css_name")]
161 fn css_name(&self) -> glib::GString;
162
163 #[doc(alias = "gtk_widget_class_get_accessible_role")]
164 #[doc(alias = "get_accessible_role")]
165 fn accessible_role(&self) -> AccessibleRole;
166}
167
168impl<T: IsA<Widget> + glib::object::IsClass> WidgetClassManualExt for glib::Class<T> {
169 fn add_shortcut(&self, shortcut: &Shortcut) {
170 unsafe {
171 let widget_class = self as *const Self as *mut ffi::GtkWidgetClass;
172 ffi::gtk_widget_class_add_shortcut(widget_class, shortcut.to_glib_none().0);
173 }
174 }
175
176 fn add_binding_action(&self, keyval: gdk::Key, mods: gdk::ModifierType, action_name: &str) {
177 let shortcut = Shortcut::new(
178 Some(crate::KeyvalTrigger::new(keyval, mods)),
179 Some(crate::NamedAction::new(action_name)),
180 );
181 self.add_shortcut(&shortcut);
182 }
183
184 fn install_property_action(&self, action_name: &str, property_name: &str) {
185 unsafe {
186 let widget_class = self as *const Self as *mut ffi::GtkWidgetClass;
187 ffi::gtk_widget_class_install_property_action(
188 widget_class,
189 action_name.to_glib_none().0,
190 property_name.to_glib_none().0,
191 );
192 }
193 }
194
195 fn query_action(&self) -> WidgetActionIter {
196 let widget_class = self as *const Self as *mut ffi::GtkWidgetClass;
197 WidgetActionIter::new(widget_class)
198 }
199
200 fn activate_signal(&self) -> Option<SignalId> {
201 unsafe {
202 let widget_class = self as *const Self as *mut ffi::GtkWidgetClass;
203 let signal_id = ffi::gtk_widget_class_get_activate_signal(widget_class);
204 if signal_id == 0 {
205 None
206 } else {
207 Some(from_glib(signal_id))
208 }
209 }
210 }
211
212 fn layout_manager_type(&self) -> glib::Type {
213 unsafe {
214 let widget_class = self as *const Self as *mut ffi::GtkWidgetClass;
215 from_glib(ffi::gtk_widget_class_get_layout_manager_type(widget_class))
216 }
217 }
218
219 fn css_name(&self) -> glib::GString {
220 unsafe {
221 let widget_class = self as *const Self as *mut ffi::GtkWidgetClass;
222 from_glib_none(ffi::gtk_widget_class_get_css_name(widget_class))
223 }
224 }
225
226 fn accessible_role(&self) -> AccessibleRole {
227 unsafe {
228 let widget_class = self as *const Self as *mut ffi::GtkWidgetClass;
229 from_glib(ffi::gtk_widget_class_get_accessible_role(widget_class))
230 }
231 }
232}