Skip to main content

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 {}