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}