1use glib::translate::*;
4
5use glib::object::IsA;
6use glib::subclass::prelude::*;
7
8use glib::object::Cast;
9
10use super::bin::BinImpl;
11
12use crate::Window;
13use crate::{Widget, ffi};
14
15pub trait WindowImpl: BinImpl + ObjectSubclass<Type: IsA<Window>> {
16 fn set_focus(&self, focus: Option<&Widget>) {
25 self.parent_set_focus(focus)
26 }
27
28 fn activate_focus(&self) {
30 self.parent_activate_focus()
31 }
32
33 fn activate_default(&self) {
35 self.parent_activate_default()
36 }
37
38 fn keys_changed(&self) {
41 self.parent_keys_changed()
42 }
43
44 fn enable_debugging(&self, toggle: bool) -> bool {
47 self.parent_enable_debugging(toggle)
48 }
49}
50
51pub trait WindowImplExt: WindowImpl {
52 fn parent_set_focus(&self, focus: Option<&Widget>) {
53 unsafe {
54 let data = Self::type_data();
55 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWindowClass;
56 if let Some(f) = (*parent_class).set_focus {
57 f(
58 self.obj().unsafe_cast_ref::<Window>().to_glib_none().0,
59 focus.to_glib_none().0,
60 )
61 }
62 }
63 }
64 fn parent_activate_focus(&self) {
65 unsafe {
66 let data = Self::type_data();
67 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWindowClass;
68 if let Some(f) = (*parent_class).activate_focus {
69 f(self.obj().unsafe_cast_ref::<Window>().to_glib_none().0)
70 }
71 }
72 }
73 fn parent_activate_default(&self) {
74 unsafe {
75 let data = Self::type_data();
76 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWindowClass;
77 if let Some(f) = (*parent_class).activate_default {
78 f(self.obj().unsafe_cast_ref::<Window>().to_glib_none().0)
79 }
80 }
81 }
82 fn parent_keys_changed(&self) {
83 unsafe {
84 let data = Self::type_data();
85 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWindowClass;
86 if let Some(f) = (*parent_class).keys_changed {
87 f(self.obj().unsafe_cast_ref::<Window>().to_glib_none().0)
88 }
89 }
90 }
91 fn parent_enable_debugging(&self, toggle: bool) -> bool {
92 unsafe {
93 let data = Self::type_data();
94 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkWindowClass;
95 if let Some(f) = (*parent_class).enable_debugging {
96 from_glib(f(
97 self.obj().unsafe_cast_ref::<Window>().to_glib_none().0,
98 toggle.into_glib(),
99 ))
100 } else {
101 false
102 }
103 }
104 }
105}
106
107impl<T: WindowImpl> WindowImplExt for T {}
108
109unsafe impl<T: WindowImpl> IsSubclassable<T> for Window {
110 fn class_init(class: &mut ::glib::Class<Self>) {
111 Self::parent_class_init::<T>(class);
112
113 if !crate::rt::is_initialized() {
114 panic!("GTK has to be initialized first");
115 }
116
117 let klass = class.as_mut();
118 klass.set_focus = Some(window_set_focus::<T>);
119 klass.activate_focus = Some(window_activate_focus::<T>);
120 klass.activate_default = Some(window_activate_default::<T>);
121 klass.keys_changed = Some(window_keys_changed::<T>);
122 klass.enable_debugging = Some(window_enable_debugging::<T>);
123 }
124}
125
126unsafe extern "C" fn window_set_focus<T: WindowImpl>(
127 ptr: *mut ffi::GtkWindow,
128 widgetptr: *mut ffi::GtkWidget,
129) {
130 unsafe {
131 let instance = &*(ptr as *mut T::Instance);
132 let imp = instance.imp();
133 let widget: Borrowed<Option<Widget>> = from_glib_borrow(widgetptr);
134
135 imp.set_focus(widget.as_ref().as_ref())
136 }
137}
138
139unsafe extern "C" fn window_activate_focus<T: WindowImpl>(ptr: *mut ffi::GtkWindow) {
140 unsafe {
141 let instance = &*(ptr as *mut T::Instance);
142 let imp = instance.imp();
143
144 imp.activate_focus()
145 }
146}
147
148unsafe extern "C" fn window_activate_default<T: WindowImpl>(ptr: *mut ffi::GtkWindow) {
149 unsafe {
150 let instance = &*(ptr as *mut T::Instance);
151 let imp = instance.imp();
152
153 imp.activate_default()
154 }
155}
156
157unsafe extern "C" fn window_keys_changed<T: WindowImpl>(ptr: *mut ffi::GtkWindow) {
158 unsafe {
159 let instance = &*(ptr as *mut T::Instance);
160 let imp = instance.imp();
161
162 imp.keys_changed()
163 }
164}
165
166unsafe extern "C" fn window_enable_debugging<T: WindowImpl>(
167 ptr: *mut ffi::GtkWindow,
168 toggleptr: glib::ffi::gboolean,
169) -> glib::ffi::gboolean {
170 unsafe {
171 let instance = &*(ptr as *mut T::Instance);
172 let imp = instance.imp();
173 let toggle: bool = from_glib(toggleptr);
174
175 imp.enable_debugging(toggle).into_glib()
176 }
177}