1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
// Take a look at the license at the top of the repository in the LICENSE file.

use crate::keys::Key;
use crate::Keymap;
use crate::KeymapKey;
use crate::ModifierType;
use glib::translate::*;
use std::mem;
use std::ptr;

impl Keymap {
    /// Returns the keyvals bound to `hardware_keycode`.
    /// The Nth [`KeymapKey`][crate::KeymapKey] in `keys` is bound to the Nth
    /// keyval in `keyvals`. Free the returned arrays with `g_free()`.
    /// When a keycode is pressed by the user, the keyval from
    /// this list of entries is selected by considering the effective
    /// keyboard group and level. See [`translate_keyboard_state()`][Self::translate_keyboard_state()].
    /// ## `hardware_keycode`
    /// a keycode
    ///
    /// # Returns
    ///
    /// [`true`] if there were any entries
    ///
    /// ## `keys`
    /// return
    ///  location for array of [`KeymapKey`][crate::KeymapKey], or [`None`]
    ///
    /// ## `keyvals`
    /// return
    ///  location for array of keyvals, or [`None`]
    #[doc(alias = "gdk_keymap_get_entries_for_keycode")]
    #[doc(alias = "get_entries_for_keycode")]
    pub fn entries_for_keycode(&self, hardware_keycode: u32) -> Vec<(KeymapKey, u32)> {
        unsafe {
            let mut keys = ptr::null_mut();
            let mut keyvals = ptr::null_mut();
            let mut n_entries = mem::MaybeUninit::uninit();
            let ret = from_glib(ffi::gdk_keymap_get_entries_for_keycode(
                self.to_glib_none().0,
                hardware_keycode,
                &mut keys,
                &mut keyvals,
                n_entries.as_mut_ptr(),
            ));
            if ret {
                let n_entries = n_entries.assume_init() as usize;
                let mut entries = Vec::with_capacity(n_entries);
                for i in 0..n_entries {
                    entries.push((from_glib_none(keys.add(i)), ptr::read(keyvals.add(i))));
                }
                glib::ffi::g_free(keys as *mut _);
                glib::ffi::g_free(keyvals as *mut _);
                entries
            } else {
                Vec::new()
            }
        }
    }

    /// Obtains a list of keycode/group/level combinations that will
    /// generate `keyval`. Groups and levels are two kinds of keyboard mode;
    /// in general, the level determines whether the top or bottom symbol
    /// on a key is used, and the group determines whether the left or
    /// right symbol is used. On US keyboards, the shift key changes the
    /// keyboard level, and there are no groups. A group switch key might
    /// convert a keyboard between Hebrew to English modes, for example.
    /// [`EventKey`][crate::EventKey] contains a `group` field that indicates the active
    /// keyboard group. The level is computed from the modifier mask.
    /// The returned array should be freed
    /// with `g_free()`.
    /// ## `keyval`
    /// a keyval, such as `GDK_KEY_a`, `GDK_KEY_Up`, `GDK_KEY_Return`, etc.
    ///
    /// # Returns
    ///
    /// [`true`] if keys were found and returned
    ///
    /// ## `keys`
    /// return location
    ///  for an array of [`KeymapKey`][crate::KeymapKey]
    #[doc(alias = "gdk_keymap_get_entries_for_keyval")]
    #[doc(alias = "get_entries_for_keyval")]
    pub fn entries_for_keyval(&self, keyval: u32) -> Vec<KeymapKey> {
        unsafe {
            let mut keys = ptr::null_mut();
            let mut n_keys = mem::MaybeUninit::uninit();
            let ret = from_glib(ffi::gdk_keymap_get_entries_for_keyval(
                self.to_glib_none().0,
                keyval,
                &mut keys,
                n_keys.as_mut_ptr(),
            ));
            if ret {
                let n_keys = n_keys.assume_init() as usize;
                let mut r_keys = Vec::with_capacity(n_keys);
                for i in 0..n_keys {
                    r_keys.push(from_glib_none(keys.add(i)));
                }
                glib::ffi::g_free(keys as *mut _);
                r_keys
            } else {
                Vec::new()
            }
        }
    }

    /// Maps the non-virtual modifiers (i.e Mod2, Mod3, ...) which are set
    /// in `state` to the virtual modifiers (i.e. Super, Hyper and Meta) and
    /// set the corresponding bits in `state`.
    ///
    /// GDK already does this before delivering key events, but for
    /// compatibility reasons, it only sets the first virtual modifier
    /// it finds, whereas this function sets all matching virtual modifiers.
    ///
    /// This function is useful when matching key events against
    /// accelerators.
    /// ## `state`
    /// pointer to the modifier mask to change
    #[doc(alias = "gdk_keymap_add_virtual_modifiers")]
    pub fn add_virtual_modifiers(&self, state: &mut ModifierType) {
        unsafe {
            let mut s = state.into_glib();
            ffi::gdk_keymap_add_virtual_modifiers(self.to_glib_none().0, &mut s);
            *state = from_glib(s);
        }
    }

    /// Maps the virtual modifiers (i.e. Super, Hyper and Meta) which
    /// are set in `state` to their non-virtual counterparts (i.e. Mod2,
    /// Mod3,...) and set the corresponding bits in `state`.
    ///
    /// This function is useful when matching key events against
    /// accelerators.
    /// ## `state`
    /// pointer to the modifier state to map
    ///
    /// # Returns
    ///
    /// [`false`] if two virtual modifiers were mapped to the
    ///  same non-virtual modifier. Note that [`false`] is also returned
    ///  if a virtual modifier is mapped to a non-virtual modifier that
    ///  was already set in `state`.
    #[doc(alias = "gdk_keymap_map_virtual_modifiers")]
    pub fn map_virtual_modifiers(&self, state: &mut ModifierType) -> bool {
        unsafe {
            let mut s = state.into_glib();
            let ret = from_glib(ffi::gdk_keymap_map_virtual_modifiers(
                self.to_glib_none().0,
                &mut s,
            ));
            *state = from_glib(s);
            ret
        }
    }

    /// Looks up the keyval mapped to a keycode/group/level triplet.
    /// If no keyval is bound to `key`, returns 0. For normal user input,
    /// you want to use [`translate_keyboard_state()`][Self::translate_keyboard_state()] instead of
    /// this function, since the effective group/level may not be
    /// the same as the current keyboard state.
    /// ## `key`
    /// a [`KeymapKey`][crate::KeymapKey] with keycode, group, and level initialized
    ///
    /// # Returns
    ///
    /// a keyval, or 0 if none was mapped to the given `key`
    #[doc(alias = "gdk_keymap_lookup_key")]
    pub fn lookup_key(&self, key: &KeymapKey) -> Option<Key> {
        let key =
            unsafe { ffi::gdk_keymap_lookup_key(self.to_glib_none().0, key.to_glib_none().0) };
        if key != 0 {
            Some(Key::from(key))
        } else {
            None
        }
    }
}