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::keys::Key;
4use crate::Keymap;
5use crate::KeymapKey;
6use crate::ModifierType;
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    /// ## `state`
119    /// pointer to the modifier mask to change
120    #[doc(alias = "gdk_keymap_add_virtual_modifiers")]
121    pub fn add_virtual_modifiers(&self, state: &mut ModifierType) {
122        unsafe {
123            let mut s = state.into_glib();
124            ffi::gdk_keymap_add_virtual_modifiers(self.to_glib_none().0, &mut s);
125            *state = from_glib(s);
126        }
127    }
128
129    /// Maps the virtual modifiers (i.e. Super, Hyper and Meta) which
130    /// are set in `state` to their non-virtual counterparts (i.e. Mod2,
131    /// Mod3,...) and set the corresponding bits in `state`.
132    ///
133    /// This function is useful when matching key events against
134    /// accelerators.
135    /// ## `state`
136    /// pointer to the modifier state to map
137    ///
138    /// # Returns
139    ///
140    /// [`false`] if two virtual modifiers were mapped to the
141    ///  same non-virtual modifier. Note that [`false`] is also returned
142    ///  if a virtual modifier is mapped to a non-virtual modifier that
143    ///  was already set in `state`.
144    #[doc(alias = "gdk_keymap_map_virtual_modifiers")]
145    pub fn map_virtual_modifiers(&self, state: &mut ModifierType) -> bool {
146        unsafe {
147            let mut s = state.into_glib();
148            let ret = from_glib(ffi::gdk_keymap_map_virtual_modifiers(
149                self.to_glib_none().0,
150                &mut s,
151            ));
152            *state = from_glib(s);
153            ret
154        }
155    }
156
157    /// Looks up the keyval mapped to a keycode/group/level triplet.
158    /// If no keyval is bound to `key`, returns 0. For normal user input,
159    /// you want to use [`translate_keyboard_state()`][Self::translate_keyboard_state()] instead of
160    /// this function, since the effective group/level may not be
161    /// the same as the current keyboard state.
162    /// ## `key`
163    /// a [`KeymapKey`][crate::KeymapKey] with keycode, group, and level initialized
164    ///
165    /// # Returns
166    ///
167    /// a keyval, or 0 if none was mapped to the given `key`
168    #[doc(alias = "gdk_keymap_lookup_key")]
169    pub fn lookup_key(&self, key: &KeymapKey) -> Option<Key> {
170        let key =
171            unsafe { ffi::gdk_keymap_lookup_key(self.to_glib_none().0, key.to_glib_none().0) };
172        if key != 0 {
173            Some(Key::from(key))
174        } else {
175            None
176        }
177    }
178}