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")]
48 fn add_tick_callback<P: Fn(&Self, &gdk::FrameClock) -> ControlFlow + 'static>(
49 &self,
50 callback: P,
51 ) -> TickCallbackId {
52 let callback_data: Box<P> = Box::new(callback);
53
54 unsafe extern "C" fn callback_func<
55 O: IsA<Widget>,
56 P: Fn(&O, &gdk::FrameClock) -> ControlFlow + 'static,
57 >(
58 widget: *mut ffi::GtkWidget,
59 frame_clock: *mut gdk::ffi::GdkFrameClock,
60 user_data: glib::ffi::gpointer,
61 ) -> glib::ffi::gboolean {
62 unsafe {
63 let widget: Borrowed<Widget> = from_glib_borrow(widget);
64 let frame_clock = from_glib_borrow(frame_clock);
65 let callback: &P = &*(user_data as *mut _);
66 let res = (*callback)(widget.unsafe_cast_ref(), &frame_clock);
67 res.into_glib()
68 }
69 }
70 let callback = Some(callback_func::<Self, P> as _);
71
72 unsafe extern "C" fn notify_func<
73 O: IsA<Widget>,
74 P: Fn(&O, &gdk::FrameClock) -> ControlFlow + 'static,
75 >(
76 data: glib::ffi::gpointer,
77 ) {
78 unsafe {
79 let _callback: Box<P> = Box::from_raw(data as *mut _);
80 }
81 }
82 let destroy_call = Some(notify_func::<Self, P> as _);
83
84 let id = unsafe {
85 ffi::gtk_widget_add_tick_callback(
86 self.as_ref().to_glib_none().0,
87 callback,
88 Box::into_raw(callback_data) as *mut _,
89 destroy_call,
90 )
91 };
92 TickCallbackId {
93 id,
94 widget: self.upcast_ref().downgrade(),
95 }
96 }
97}
98
99impl<O: IsA<Widget>> WidgetExtManual for O {}
100
101#[derive(Debug)]
102pub struct TickCallbackId {
103 id: u32,
104 widget: WeakRef<Widget>,
105}
106
107impl PartialEq for TickCallbackId {
108 #[inline]
109 fn eq(&self, other: &Self) -> bool {
110 self.id == other.id
111 }
112}
113
114impl TickCallbackId {
115 #[doc(alias = "gtk_widget_remove_tick_callback")]
120 #[doc(alias = "remove_tick_callback")]
121 pub fn remove(self) {
122 if let Some(widget) = self.widget.upgrade() {
123 unsafe {
124 ffi::gtk_widget_remove_tick_callback(widget.to_glib_none().0, self.id);
125 }
126 }
127 }
128}
129
130pub trait WidgetClassManualExt {
156 #[doc(alias = "gtk_widget_class_add_shortcut")]
157 fn add_shortcut(&self, shortcut: &Shortcut);
158
159 #[doc(alias = "gtk_widget_class_add_binding_action")]
160 fn add_binding_action(&self, keyval: gdk::Key, mods: gdk::ModifierType, action_name: &str);
161
162 #[doc(alias = "gtk_widget_class_install_property_action")]
163 fn install_property_action(&self, action_name: &str, property_name: &str);
164
165 #[doc(alias = "gtk_widget_class_query_action")]
166 fn query_action(&self) -> WidgetActionIter;
167
168 #[doc(alias = "gtk_widget_class_get_activate_signal")]
169 #[doc(alias = "get_activate_signal")]
170 fn activate_signal(&self) -> Option<SignalId>;
171
172 #[doc(alias = "gtk_widget_class_get_layout_manager_type")]
173 #[doc(alias = "get_layout_manager_type")]
174 fn layout_manager_type(&self) -> glib::Type;
175
176 #[doc(alias = "gtk_widget_class_get_css_name")]
177 #[doc(alias = "get_css_name")]
178 fn css_name(&self) -> glib::GString;
179
180 #[doc(alias = "gtk_widget_class_get_accessible_role")]
181 #[doc(alias = "get_accessible_role")]
182 fn accessible_role(&self) -> AccessibleRole;
183}
184
185impl<T: IsA<Widget> + glib::object::IsClass> WidgetClassManualExt for glib::Class<T> {
186 fn add_shortcut(&self, shortcut: &Shortcut) {
187 unsafe {
188 let widget_class = self as *const Self as *mut ffi::GtkWidgetClass;
189 ffi::gtk_widget_class_add_shortcut(widget_class, shortcut.to_glib_none().0);
190 }
191 }
192
193 fn add_binding_action(&self, keyval: gdk::Key, mods: gdk::ModifierType, action_name: &str) {
194 let shortcut = Shortcut::new(
195 Some(crate::KeyvalTrigger::new(keyval, mods)),
196 Some(crate::NamedAction::new(action_name)),
197 );
198 self.add_shortcut(&shortcut);
199 }
200
201 fn install_property_action(&self, action_name: &str, property_name: &str) {
202 unsafe {
203 let widget_class = self as *const Self as *mut ffi::GtkWidgetClass;
204 ffi::gtk_widget_class_install_property_action(
205 widget_class,
206 action_name.to_glib_none().0,
207 property_name.to_glib_none().0,
208 );
209 }
210 }
211
212 fn query_action(&self) -> WidgetActionIter {
213 let widget_class = self as *const Self as *mut ffi::GtkWidgetClass;
214 WidgetActionIter::new(widget_class)
215 }
216
217 fn activate_signal(&self) -> Option<SignalId> {
218 unsafe {
219 let widget_class = self as *const Self as *mut ffi::GtkWidgetClass;
220 let signal_id = ffi::gtk_widget_class_get_activate_signal(widget_class);
221 if signal_id == 0 {
222 None
223 } else {
224 Some(from_glib(signal_id))
225 }
226 }
227 }
228
229 fn layout_manager_type(&self) -> glib::Type {
230 unsafe {
231 let widget_class = self as *const Self as *mut ffi::GtkWidgetClass;
232 from_glib(ffi::gtk_widget_class_get_layout_manager_type(widget_class))
233 }
234 }
235
236 fn css_name(&self) -> glib::GString {
237 unsafe {
238 let widget_class = self as *const Self as *mut ffi::GtkWidgetClass;
239 from_glib_none(ffi::gtk_widget_class_get_css_name(widget_class))
240 }
241 }
242
243 fn accessible_role(&self) -> AccessibleRole {
244 unsafe {
245 let widget_class = self as *const Self as *mut ffi::GtkWidgetClass;
246 from_glib(ffi::gtk_widget_class_get_accessible_role(widget_class))
247 }
248 }
249}