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