Skip to main content

gdk/
keymap.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use crate::KeymapKey;
4use crate::ModifierType;
5use crate::keys::Key;
6use crate::{Keymap, ffi};
7use glib::translate::*;
8use std::mem;
9use std::ptr;
10
11impl Keymap {
12    /// Returns the keyvals bound to `hardware_keycode`.
13    /// The Nth [`KeymapKey`][crate::KeymapKey] in `keys` is bound to the Nth
14    /// keyval in `keyvals`. Free the returned arrays with `g_free()`.
15    /// When a keycode is pressed by the user, the keyval from
16    /// this list of entries is selected by considering the effective
17    /// keyboard group and level. See [`translate_keyboard_state()`][Self::translate_keyboard_state()].
18    /// ## `hardware_keycode`
19    /// a keycode
20    ///
21    /// # Returns
22    ///
23    /// [`true`] if there were any entries
24    ///
25    /// ## `keys`
26    /// return
27    ///  location for array of [`KeymapKey`][crate::KeymapKey], or [`None`]
28    ///
29    /// ## `keyvals`
30    /// return
31    ///  location for array of keyvals, or [`None`]
32    #[doc(alias = "gdk_keymap_get_entries_for_keycode")]
33    #[doc(alias = "get_entries_for_keycode")]
34    pub fn entries_for_keycode(&self, hardware_keycode: u32) -> Vec<(KeymapKey, u32)> {
35        unsafe {
36            let mut keys = ptr::null_mut();
37            let mut keyvals = ptr::null_mut();
38            let mut n_entries = mem::MaybeUninit::uninit();
39            let ret = from_glib(ffi::gdk_keymap_get_entries_for_keycode(
40                self.to_glib_none().0,
41                hardware_keycode,
42                &mut keys,
43                &mut keyvals,
44                n_entries.as_mut_ptr(),
45            ));
46            if ret {
47                let n_entries = n_entries.assume_init() as usize;
48                let mut entries = Vec::with_capacity(n_entries);
49                for i in 0..n_entries {
50                    entries.push((from_glib_none(keys.add(i)), ptr::read(keyvals.add(i))));
51                }
52                glib::ffi::g_free(keys as *mut _);
53                glib::ffi::g_free(keyvals as *mut _);
54                entries
55            } else {
56                Vec::new()
57            }
58        }
59    }
60
61    /// Obtains a list of keycode/group/level combinations that will
62    /// generate `keyval`. Groups and levels are two kinds of keyboard mode;
63    /// in general, the level determines whether the top or bottom symbol
64    /// on a key is used, and the group determines whether the left or
65    /// right symbol is used. On US keyboards, the shift key changes the
66    /// keyboard level, and there are no groups. A group switch key might
67    /// convert a keyboard between Hebrew to English modes, for example.
68    /// [`EventKey`][crate::EventKey] contains a `group` field that indicates the active
69    /// keyboard group. The level is computed from the modifier mask.
70    /// The returned array should be freed
71    /// with `g_free()`.
72    /// ## `keyval`
73    /// a keyval, such as `GDK_KEY_a`, `GDK_KEY_Up`, `GDK_KEY_Return`, etc.
74    ///
75    /// # Returns
76    ///
77    /// [`true`] if keys were found and returned
78    ///
79    /// ## `keys`
80    /// return location
81    ///  for an array of [`KeymapKey`][crate::KeymapKey]
82    #[doc(alias = "gdk_keymap_get_entries_for_keyval")]
83    #[doc(alias = "get_entries_for_keyval")]
84    pub fn entries_for_keyval(&self, keyval: u32) -> Vec<KeymapKey> {
85        unsafe {
86            let mut keys = ptr::null_mut();
87            let mut n_keys = mem::MaybeUninit::uninit();
88            let ret = from_glib(ffi::gdk_keymap_get_entries_for_keyval(
89                self.to_glib_none().0,
90                keyval,
91                &mut keys,
92                n_keys.as_mut_ptr(),
93            ));
94            if ret {
95                let n_keys = n_keys.assume_init() as usize;
96                let mut r_keys = Vec::with_capacity(n_keys);
97                for i in 0..n_keys {
98                    r_keys.push(from_glib_none(keys.add(i)));
99                }
100                glib::ffi::g_free(keys as *mut _);
101                r_keys
102            } else {
103                Vec::new()
104            }
105        }
106    }
107
108    /// Maps the non-virtual modifiers (i.e Mod2, Mod3, ...) which are set
109    /// in `state` to the virtual modifiers (i.e. Super, Hyper and Meta) and
110    /// set the corresponding bits in `state`.
111    ///
112    /// GDK already does this before delivering key events, but for
113    /// compatibility reasons, it only sets the first virtual modifier
114    /// it finds, whereas this function sets all matching virtual modifiers.
115    ///
116    /// This function is useful when matching key events against
117    /// accelerators.
118    ///
119    /// # Returns
120    ///
121    ///
122    /// ## `state`
123    /// pointer to the modifier mask to change
124    #[doc(alias = "gdk_keymap_add_virtual_modifiers")]
125    pub fn add_virtual_modifiers(&self, state: &mut ModifierType) {
126        unsafe {
127            let mut s = state.into_glib();
128            ffi::gdk_keymap_add_virtual_modifiers(self.to_glib_none().0, &mut s);
129            *state = from_glib(s);
130        }
131    }
132
133    /// Maps the virtual modifiers (i.e. Super, Hyper and Meta) which
134    /// are set in `state` to their non-virtual counterparts (i.e. Mod2,
135    /// Mod3,...) and set the corresponding bits in `state`.
136    ///
137    /// This function is useful when matching key events against
138    /// accelerators.
139    ///
140    /// # Returns
141    ///
142    /// [`false`] if two virtual modifiers were mapped to the
143    ///  same non-virtual modifier. Note that [`false`] is also returned
144    ///  if a virtual modifier is mapped to a non-virtual modifier that
145    ///  was already set in `state`.
146    ///
147    /// ## `state`
148    /// pointer to the modifier state to map
149    #[doc(alias = "gdk_keymap_map_virtual_modifiers")]
150    pub fn map_virtual_modifiers(&self, state: &mut ModifierType) -> bool {
151        unsafe {
152            let mut s = state.into_glib();
153            let ret = from_glib(ffi::gdk_keymap_map_virtual_modifiers(
154                self.to_glib_none().0,
155                &mut s,
156            ));
157            *state = from_glib(s);
158            ret
159        }
160    }
161
162    /// Looks up the keyval mapped to a keycode/group/level triplet.
163    /// If no keyval is bound to `key`, returns 0. For normal user input,
164    /// you want to use [`translate_keyboard_state()`][Self::translate_keyboard_state()] instead of
165    /// this function, since the effective group/level may not be
166    /// the same as the current keyboard state.
167    /// ## `key`
168    /// a [`KeymapKey`][crate::KeymapKey] with keycode, group, and level initialized
169    ///
170    /// # Returns
171    ///
172    /// a keyval, or 0 if none was mapped to the given `key`
173    #[doc(alias = "gdk_keymap_lookup_key")]
174    pub fn lookup_key(&self, key: &KeymapKey) -> Option<Key> {
175        let key =
176            unsafe { ffi::gdk_keymap_lookup_key(self.to_glib_none().0, key.to_glib_none().0) };
177        if key != 0 { Some(Key::from(key)) } else { None }
178    }
179}