Skip to main content

gtk/subclass/
window.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use glib::translate::*;
4
5use glib::subclass::prelude::*;
6
7use glib::Cast;
8
9use super::bin::BinImpl;
10
11use crate::Widget;
12use crate::Window;
13
14pub trait WindowImpl: WindowImplExt + BinImpl {
15    /// If `focus` is not the current focus widget, and is focusable, sets
16    /// it as the focus widget for the window. If `focus` is [`None`], unsets
17    /// the focus widget for this window. To set the focus to a particular
18    /// widget in the toplevel, it is usually more convenient to use
19    /// [`WidgetExt::grab_focus()`][crate::prelude::WidgetExt::grab_focus()] instead of this function.
20    /// ## `focus`
21    /// widget to be the new focus widget, or [`None`] to unset
22    ///  any focus widget for the toplevel window.
23    fn set_focus(&self, focus: Option<&Widget>) {
24        self.parent_set_focus(focus)
25    }
26
27    fn activate_focus(&self) {
28        self.parent_activate_focus()
29    }
30
31    fn activate_default(&self) {
32        self.parent_activate_default()
33    }
34
35    fn keys_changed(&self) {
36        self.parent_keys_changed()
37    }
38
39    fn enable_debugging(&self, toggle: bool) -> bool {
40        self.parent_enable_debugging(toggle)
41    }
42}
43
44mod sealed {
45    pub trait Sealed {}
46    impl<T: super::WindowImpl> Sealed for T {}
47}
48
49pub trait WindowImplExt: ObjectSubclass + sealed::Sealed {
50    fn parent_set_focus(&self, focus: Option<&Widget>) {
51        unsafe {
52            let data = Self::type_data();
53            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWindowClass;
54            if let Some(f) = (*parent_class).set_focus {
55                f(
56                    self.obj().unsafe_cast_ref::<Window>().to_glib_none().0,
57                    focus.to_glib_none().0,
58                )
59            }
60        }
61    }
62    fn parent_activate_focus(&self) {
63        unsafe {
64            let data = Self::type_data();
65            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWindowClass;
66            if let Some(f) = (*parent_class).activate_focus {
67                f(self.obj().unsafe_cast_ref::<Window>().to_glib_none().0)
68            }
69        }
70    }
71    fn parent_activate_default(&self) {
72        unsafe {
73            let data = Self::type_data();
74            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWindowClass;
75            if let Some(f) = (*parent_class).activate_default {
76                f(self.obj().unsafe_cast_ref::<Window>().to_glib_none().0)
77            }
78        }
79    }
80    fn parent_keys_changed(&self) {
81        unsafe {
82            let data = Self::type_data();
83            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWindowClass;
84            if let Some(f) = (*parent_class).keys_changed {
85                f(self.obj().unsafe_cast_ref::<Window>().to_glib_none().0)
86            }
87        }
88    }
89    fn parent_enable_debugging(&self, toggle: bool) -> bool {
90        unsafe {
91            let data = Self::type_data();
92            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWindowClass;
93            if let Some(f) = (*parent_class).enable_debugging {
94                from_glib(f(
95                    self.obj().unsafe_cast_ref::<Window>().to_glib_none().0,
96                    toggle.into_glib(),
97                ))
98            } else {
99                false
100            }
101        }
102    }
103}
104
105impl<T: WindowImpl> WindowImplExt for T {}
106
107unsafe impl<T: WindowImpl> IsSubclassable<T> for Window {
108    fn class_init(class: &mut ::glib::Class<Self>) {
109        Self::parent_class_init::<T>(class);
110
111        if !crate::rt::is_initialized() {
112            panic!("GTK has to be initialized first");
113        }
114
115        let klass = class.as_mut();
116        klass.set_focus = Some(window_set_focus::<T>);
117        klass.activate_focus = Some(window_activate_focus::<T>);
118        klass.activate_default = Some(window_activate_default::<T>);
119        klass.keys_changed = Some(window_keys_changed::<T>);
120        klass.enable_debugging = Some(window_enable_debugging::<T>);
121    }
122}
123
124unsafe extern "C" fn window_set_focus<T: WindowImpl>(
125    ptr: *mut ffi::GtkWindow,
126    widgetptr: *mut ffi::GtkWidget,
127) {
128    let instance = &*(ptr as *mut T::Instance);
129    let imp = instance.imp();
130    let widget: Borrowed<Option<Widget>> = from_glib_borrow(widgetptr);
131
132    imp.set_focus(widget.as_ref().as_ref())
133}
134
135unsafe extern "C" fn window_activate_focus<T: WindowImpl>(ptr: *mut ffi::GtkWindow) {
136    let instance = &*(ptr as *mut T::Instance);
137    let imp = instance.imp();
138
139    imp.activate_focus()
140}
141
142unsafe extern "C" fn window_activate_default<T: WindowImpl>(ptr: *mut ffi::GtkWindow) {
143    let instance = &*(ptr as *mut T::Instance);
144    let imp = instance.imp();
145
146    imp.activate_default()
147}
148
149unsafe extern "C" fn window_keys_changed<T: WindowImpl>(ptr: *mut ffi::GtkWindow) {
150    let instance = &*(ptr as *mut T::Instance);
151    let imp = instance.imp();
152
153    imp.keys_changed()
154}
155
156unsafe extern "C" fn window_enable_debugging<T: WindowImpl>(
157    ptr: *mut ffi::GtkWindow,
158    toggleptr: glib::ffi::gboolean,
159) -> glib::ffi::gboolean {
160    let instance = &*(ptr as *mut T::Instance);
161    let imp = instance.imp();
162    let toggle: bool = from_glib(toggleptr);
163
164    imp.enable_debugging(toggle).into_glib()
165}