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