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
use glib::translate::*;
use std::mem;
use std::ptr;
use Keymap;
use KeymapKey;
use ModifierType;

impl Keymap {
    /// Returns the keyvals bound to `hardware_keycode`.
    /// The Nth `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 `Keymap::translate_keyboard_state`.
    /// ## `hardware_keycode`
    /// a keycode
    /// ## `keys`
    /// return
    ///  location for array of `KeymapKey`, or `None`
    /// ## `keyvals`
    /// return
    ///  location for array of keyvals, or `None`
    /// ## `n_entries`
    /// length of `keys` and `keyvals`
    ///
    /// # Returns
    ///
    /// `true` if there were any entries
    pub fn get_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(gdk_sys::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_sys::g_free(keys as *mut _);
                glib_sys::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` 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.
    /// ## `keys`
    /// return location
    ///  for an array of `KeymapKey`
    /// ## `n_keys`
    /// return location for number of elements in returned array
    ///
    /// # Returns
    ///
    /// `true` if keys were found and returned
    pub fn get_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(gdk_sys::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_sys::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
    pub fn add_virtual_modifiers(&self, state: &mut ModifierType) {
        unsafe {
            let mut s = state.to_glib();
            gdk_sys::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`.
    pub fn map_virtual_modifiers(&self, state: &mut ModifierType) -> bool {
        unsafe {
            let mut s = state.to_glib();
            let ret = from_glib(gdk_sys::gdk_keymap_map_virtual_modifiers(
                self.to_glib_none().0,
                &mut s,
            ));
            *state = from_glib(s);
            ret
        }
    }
}