gdk4/display.rs
1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use glib::translate::*;
4
5use crate::{Display, Key, KeymapKey, ModifierType, ffi, prelude::*};
6
7#[derive(Debug, PartialEq, Eq, Ord, PartialOrd)]
8pub enum Backend {
9 Wayland,
10 X11,
11 Win32,
12 MacOS,
13 Broadway,
14}
15
16impl Backend {
17 // rustdoc-stripper-ignore-next
18 /// Equivalent to the C macro `GDK_IS_WAYLAND_DISPLAY`
19 #[doc(alias = "GDK_IS_WAYLAND_DISPLAY")]
20 pub fn is_wayland(&self) -> bool {
21 matches!(self, Self::Wayland)
22 }
23
24 // rustdoc-stripper-ignore-next
25 /// Equivalent to the C macro `GDK_IS_X11_DISPLAY`
26 #[doc(alias = "GDK_IS_X11_DISPLAY")]
27 pub fn is_x11(&self) -> bool {
28 matches!(self, Self::X11)
29 }
30
31 // rustdoc-stripper-ignore-next
32 /// Equivalent to the C macro `GDK_IS_WIN32_DISPLAY`
33 #[doc(alias = "GDK_IS_WIN32_DISPLAY")]
34 pub fn is_win32(&self) -> bool {
35 matches!(self, Self::Win32)
36 }
37
38 // rustdoc-stripper-ignore-next
39 /// Equivalent to the C macro `GDK_IS_MACOS_DISPLAY`
40 #[doc(alias = "GDK_IS_MACOS_DISPLAY")]
41 pub fn is_macos(&self) -> bool {
42 matches!(self, Self::MacOS)
43 }
44
45 // rustdoc-stripper-ignore-next
46 /// Equivalent to the C macro `GDK_IS_BROADWAY_DISPLAY`
47 #[doc(alias = "GDK_IS_BROADWAY_DISPLAY")]
48 pub fn is_broadway(&self) -> bool {
49 matches!(self, Self::Broadway)
50 }
51}
52
53// rustdoc-stripper-ignore-next
54/// Trait containing manually implemented methods of
55/// [`Display`](crate::Display).
56pub trait DisplayExtManual: IsA<Display> + 'static {
57 /// `
58 /// should be masked out.
59 ///
60 /// This function should rarely be needed, since `GdkEventKey` already
61 /// contains the translated keyval. It is exported for the benefit of
62 /// virtualized test environments.
63 /// ## `keycode`
64 /// a keycode
65 /// ## `state`
66 /// a modifier state
67 /// ## `group`
68 /// active keyboard group
69 ///
70 /// # Returns
71 ///
72 /// [`true`] if there was a keyval bound to keycode/state/group.
73 ///
74 /// ## `keyval`
75 /// return location for keyval
76 ///
77 /// ## `effective_group`
78 /// return location for effective group
79 ///
80 /// ## `level`
81 /// return location for level
82 ///
83 /// ## `consumed`
84 /// return location for modifiers that were used
85 /// to determine the group or level
86 #[doc(alias = "gdk_display_translate_key")]
87 fn translate_key(
88 &self,
89 keycode: u32,
90 state: ModifierType,
91 group: i32,
92 ) -> Option<(Key, i32, i32, ModifierType)> {
93 unsafe {
94 let mut keyval = std::mem::MaybeUninit::uninit();
95 let mut effective_group = std::mem::MaybeUninit::uninit();
96 let mut level = std::mem::MaybeUninit::uninit();
97 let mut consumed = std::mem::MaybeUninit::uninit();
98 let ret = from_glib(ffi::gdk_display_translate_key(
99 self.as_ref().to_glib_none().0,
100 keycode,
101 state.into_glib(),
102 group,
103 keyval.as_mut_ptr(),
104 effective_group.as_mut_ptr(),
105 level.as_mut_ptr(),
106 consumed.as_mut_ptr(),
107 ));
108 if ret {
109 let keyval = keyval.assume_init();
110 let effective_group = effective_group.assume_init();
111 let level = level.assume_init();
112 let consumed = consumed.assume_init();
113 Some((
114 from_glib(keyval),
115 effective_group,
116 level,
117 from_glib(consumed),
118 ))
119 } else {
120 None
121 }
122 }
123 }
124
125 /// Retrieves a desktop-wide setting such as double-click time
126 /// for the @self.
127 /// ## `name`
128 /// the name of the setting
129 /// ## `value`
130 /// location to store the value of the setting
131 ///
132 /// # Returns
133 ///
134 /// [`true`] if the setting existed and a value was stored
135 /// in @value, [`false`] otherwise
136 #[doc(alias = "gdk_display_get_setting")]
137 fn get_setting(&self, name: impl IntoGStr) -> Option<glib::Value> {
138 unsafe {
139 name.run_with_gstr(|name| {
140 let mut value = glib::Value::uninitialized();
141 let ret = ffi::gdk_display_get_setting(
142 self.as_ref().to_glib_none().0,
143 name.as_ptr(),
144 value.to_glib_none_mut().0,
145 );
146 if from_glib(ret) { Some(value) } else { None }
147 })
148 }
149 }
150
151 /// Obtains a list of keycode/group/level combinations that will
152 /// generate @keyval.
153 ///
154 /// Groups and levels are two kinds of keyboard mode; in general, the level
155 /// determines whether the top or bottom symbol on a key is used, and the
156 /// group determines whether the left or right symbol is used.
157 ///
158 /// On US keyboards, the shift key changes the keyboard level, and there
159 /// are no groups. A group switch key might convert a keyboard between
160 /// Hebrew to English modes, for example.
161 ///
162 /// `GdkEventKey` contains a `group` field that indicates the active
163 /// keyboard group. The level is computed from the modifier mask.
164 ///
165 /// The returned array should be freed with g_free().
166 /// ## `keyval`
167 /// a keyval, such as `GDK_KEY_a`, `GDK_KEY_Up`, `GDK_KEY_Return`, etc.
168 ///
169 /// # Returns
170 ///
171 /// [`true`] if keys were found and returned
172 ///
173 /// ## `keys`
174 /// return location
175 /// for an array of [`KeymapKey`][crate::KeymapKey]
176 #[doc(alias = "gdk_display_map_keyval")]
177 fn map_keyval(&self, keyval: Key) -> Option<Vec<KeymapKey>> {
178 unsafe {
179 let mut keys = std::ptr::null_mut();
180 let mut n_keys = std::mem::MaybeUninit::uninit();
181 let ret = from_glib(ffi::gdk_display_map_keyval(
182 self.as_ref().to_glib_none().0,
183 keyval.into_glib(),
184 &mut keys,
185 n_keys.as_mut_ptr(),
186 ));
187 if ret {
188 Some(FromGlibContainer::from_glib_full_num(
189 keys,
190 n_keys.assume_init() as usize,
191 ))
192 } else {
193 None
194 }
195 }
196 }
197
198 /// Returns the keyvals bound to @keycode.
199 ///
200 /// The Nth [`KeymapKey`][crate::KeymapKey] in @keys is bound to the Nth keyval in @keyvals.
201 ///
202 /// When a keycode is pressed by the user, the keyval from
203 /// this list of entries is selected by considering the effective
204 /// keyboard group and level.
205 ///
206 /// Free the returned arrays with g_free().
207 /// ## `keycode`
208 /// a keycode
209 ///
210 /// # Returns
211 ///
212 /// [`true`] if there were any entries
213 ///
214 /// ## `keys`
215 /// return
216 /// location for array of [`KeymapKey`][crate::KeymapKey]
217 ///
218 /// ## `keyvals`
219 /// return
220 /// location for array of keyvals
221 #[doc(alias = "gdk_display_map_keycode")]
222 fn map_keycode(&self, keycode: u32) -> Option<Vec<(KeymapKey, Key)>> {
223 unsafe {
224 let mut keys = std::ptr::null_mut();
225 let mut keyvals = std::ptr::null_mut();
226 let mut n_entries = std::mem::MaybeUninit::uninit();
227 let ret = from_glib(ffi::gdk_display_map_keycode(
228 self.as_ref().to_glib_none().0,
229 keycode,
230 &mut keys,
231 &mut keyvals,
232 n_entries.as_mut_ptr(),
233 ));
234 if ret {
235 let n_keys = n_entries.assume_init() as usize;
236 let keyvals: Vec<u32> = FromGlibContainer::from_glib_full_num(keyvals, n_keys);
237 let keyvals = keyvals.into_iter().map(|k| from_glib(k));
238 let keys: Vec<KeymapKey> = FromGlibContainer::from_glib_full_num(keys, n_keys);
239
240 Some(keys.into_iter().zip(keyvals).collect())
241 } else {
242 None
243 }
244 }
245 }
246
247 // rustdoc-stripper-ignore-next
248 /// Get the currently used display backend
249 fn backend(&self) -> Backend {
250 match self.as_ref().type_().name() {
251 "GdkWaylandDisplay" => Backend::Wayland,
252 "GdkX11Display" => Backend::X11,
253 "GdkMacosDisplay" => Backend::MacOS,
254 "GdkWin32Display" => Backend::Win32,
255 "GdkBroadwayDisplay" => Backend::Broadway,
256 e => panic!("Unsupported display backend {e}"),
257 }
258 }
259}
260
261impl<O: IsA<Display>> DisplayExtManual for O {}