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::{ffi, prelude::*, Display, Key, KeymapKey, ModifierType};
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 /// Translates the contents of a `GdkEventKey` into a keyval, effective group,
58 /// and level.
59 ///
60 /// Modifiers that affected the translation and are thus unavailable for
61 /// application use are returned in @consumed_modifiers.
62 ///
63 /// The @effective_group is the group that was actually used for the
64 /// translation; some keys such as Enter are not affected by the active
65 /// keyboard group. The @level is derived from @state.
66 ///
67 /// @consumed_modifiers gives modifiers that should be masked out
68 /// from @state when comparing this key press to a keyboard shortcut.
69 /// For instance, on a US keyboard, the `plus` symbol is shifted, so
70 /// when comparing a key press to a `<Control>plus` accelerator `<Shift>`
71 /// should be masked out.
72 ///
73 /// This function should rarely be needed, since `GdkEventKey` already
74 /// contains the translated keyval. It is exported for the benefit of
75 /// virtualized test environments.
76 /// ## `keycode`
77 /// a keycode
78 /// ## `state`
79 /// a modifier state
80 /// ## `group`
81 /// active keyboard group
82 ///
83 /// # Returns
84 ///
85 /// [`true`] if there was a keyval bound to keycode/state/group.
86 ///
87 /// ## `keyval`
88 /// return location for keyval
89 ///
90 /// ## `effective_group`
91 /// return location for effective group
92 ///
93 /// ## `level`
94 /// return location for level
95 ///
96 /// ## `consumed`
97 /// return location for modifiers that were used
98 /// to determine the group or level
99 #[doc(alias = "gdk_display_translate_key")]
100 fn translate_key(
101 &self,
102 keycode: u32,
103 state: ModifierType,
104 group: i32,
105 ) -> Option<(Key, i32, i32, ModifierType)> {
106 unsafe {
107 let mut keyval = std::mem::MaybeUninit::uninit();
108 let mut effective_group = std::mem::MaybeUninit::uninit();
109 let mut level = std::mem::MaybeUninit::uninit();
110 let mut consumed = std::mem::MaybeUninit::uninit();
111 let ret = from_glib(ffi::gdk_display_translate_key(
112 self.as_ref().to_glib_none().0,
113 keycode,
114 state.into_glib(),
115 group,
116 keyval.as_mut_ptr(),
117 effective_group.as_mut_ptr(),
118 level.as_mut_ptr(),
119 consumed.as_mut_ptr(),
120 ));
121 if ret {
122 let keyval = keyval.assume_init();
123 let effective_group = effective_group.assume_init();
124 let level = level.assume_init();
125 let consumed = consumed.assume_init();
126 Some((
127 from_glib(keyval),
128 effective_group,
129 level,
130 from_glib(consumed),
131 ))
132 } else {
133 None
134 }
135 }
136 }
137
138 /// Retrieves a desktop-wide setting such as double-click time
139 /// for the @self.
140 /// ## `name`
141 /// the name of the setting
142 /// ## `value`
143 /// location to store the value of the setting
144 ///
145 /// # Returns
146 ///
147 /// [`true`] if the setting existed and a value was stored
148 /// in @value, [`false`] otherwise
149 #[doc(alias = "gdk_display_get_setting")]
150 fn get_setting(&self, name: impl IntoGStr) -> Option<glib::Value> {
151 unsafe {
152 name.run_with_gstr(|name| {
153 let mut value = glib::Value::uninitialized();
154 let ret = ffi::gdk_display_get_setting(
155 self.as_ref().to_glib_none().0,
156 name.as_ptr(),
157 value.to_glib_none_mut().0,
158 );
159 if from_glib(ret) {
160 Some(value)
161 } else {
162 None
163 }
164 })
165 }
166 }
167
168 /// Obtains a list of keycode/group/level combinations that will
169 /// generate @keyval.
170 ///
171 /// Groups and levels are two kinds of keyboard mode; in general, the level
172 /// determines whether the top or bottom symbol on a key is used, and the
173 /// group determines whether the left or right symbol is used.
174 ///
175 /// On US keyboards, the shift key changes the keyboard level, and there
176 /// are no groups. A group switch key might convert a keyboard between
177 /// Hebrew to English modes, for example.
178 ///
179 /// `GdkEventKey` contains a `group` field that indicates the active
180 /// keyboard group. The level is computed from the modifier mask.
181 ///
182 /// The returned array should be freed with g_free().
183 /// ## `keyval`
184 /// a keyval, such as `GDK_KEY_a`, `GDK_KEY_Up`, `GDK_KEY_Return`, etc.
185 ///
186 /// # Returns
187 ///
188 /// [`true`] if keys were found and returned
189 ///
190 /// ## `keys`
191 /// return location
192 /// for an array of [`KeymapKey`][crate::KeymapKey]
193 #[doc(alias = "gdk_display_map_keyval")]
194 fn map_keyval(&self, keyval: Key) -> Option<Vec<KeymapKey>> {
195 unsafe {
196 let mut keys = std::ptr::null_mut();
197 let mut n_keys = std::mem::MaybeUninit::uninit();
198 let ret = from_glib(ffi::gdk_display_map_keyval(
199 self.as_ref().to_glib_none().0,
200 keyval.into_glib(),
201 &mut keys,
202 n_keys.as_mut_ptr(),
203 ));
204 if ret {
205 Some(FromGlibContainer::from_glib_full_num(
206 keys,
207 n_keys.assume_init() as usize,
208 ))
209 } else {
210 None
211 }
212 }
213 }
214
215 /// Returns the keyvals bound to @keycode.
216 ///
217 /// The Nth [`KeymapKey`][crate::KeymapKey] in @keys is bound to the Nth keyval in @keyvals.
218 ///
219 /// When a keycode is pressed by the user, the keyval from
220 /// this list of entries is selected by considering the effective
221 /// keyboard group and level.
222 ///
223 /// Free the returned arrays with g_free().
224 /// ## `keycode`
225 /// a keycode
226 ///
227 /// # Returns
228 ///
229 /// [`true`] if there were any entries
230 ///
231 /// ## `keys`
232 /// return
233 /// location for array of [`KeymapKey`][crate::KeymapKey]
234 ///
235 /// ## `keyvals`
236 /// return
237 /// location for array of keyvals
238 #[doc(alias = "gdk_display_map_keycode")]
239 fn map_keycode(&self, keycode: u32) -> Option<Vec<(KeymapKey, Key)>> {
240 unsafe {
241 let mut keys = std::ptr::null_mut();
242 let mut keyvals = std::ptr::null_mut();
243 let mut n_entries = std::mem::MaybeUninit::uninit();
244 let ret = from_glib(ffi::gdk_display_map_keycode(
245 self.as_ref().to_glib_none().0,
246 keycode,
247 &mut keys,
248 &mut keyvals,
249 n_entries.as_mut_ptr(),
250 ));
251 if ret {
252 let n_keys = n_entries.assume_init() as usize;
253 let keyvals: Vec<u32> = FromGlibContainer::from_glib_full_num(keyvals, n_keys);
254 let keyvals = keyvals.into_iter().map(|k| from_glib(k));
255 let keys: Vec<KeymapKey> = FromGlibContainer::from_glib_full_num(keys, n_keys);
256
257 Some(keys.into_iter().zip(keyvals).collect())
258 } else {
259 None
260 }
261 }
262 }
263
264 // rustdoc-stripper-ignore-next
265 /// Get the currently used display backend
266 fn backend(&self) -> Backend {
267 match self.as_ref().type_().name() {
268 "GdkWaylandDisplay" => Backend::Wayland,
269 "GdkX11Display" => Backend::X11,
270 "GdkMacosDisplay" => Backend::MacOS,
271 "GdkWin32Display" => Backend::Win32,
272 "GdkBroadwayDisplay" => Backend::Broadway,
273 e => panic!("Unsupported display backend {e}"),
274 }
275 }
276}
277
278impl<O: IsA<Display>> DisplayExtManual for O {}