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}