1use 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 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}