winit/platform_impl/linux/x11/util/
keys.rs

1use std::iter::Enumerate;
2use std::slice::Iter;
3
4use super::*;
5
6pub struct Keymap {
7    keys: [u8; 32],
8}
9
10pub struct KeymapIter<'a> {
11    iter: Enumerate<Iter<'a, u8>>,
12    index: usize,
13    item: Option<u8>,
14}
15
16impl Keymap {
17    pub fn iter(&self) -> KeymapIter<'_> {
18        KeymapIter { iter: self.keys.iter().enumerate(), index: 0, item: None }
19    }
20}
21
22impl<'a> IntoIterator for &'a Keymap {
23    type IntoIter = KeymapIter<'a>;
24    type Item = ffi::KeyCode;
25
26    fn into_iter(self) -> Self::IntoIter {
27        self.iter()
28    }
29}
30
31impl Iterator for KeymapIter<'_> {
32    type Item = ffi::KeyCode;
33
34    fn next(&mut self) -> Option<ffi::KeyCode> {
35        if self.item.is_none() {
36            for (index, &item) in self.iter.by_ref() {
37                if item != 0 {
38                    self.index = index;
39                    self.item = Some(item);
40                    break;
41                }
42            }
43        }
44
45        self.item.take().map(|item| {
46            debug_assert!(item != 0);
47
48            let bit = first_bit(item);
49
50            if item != bit {
51                // Remove the first bit; save the rest for further iterations
52                self.item = Some(item ^ bit);
53            }
54
55            let shift = bit.trailing_zeros() + (self.index * 8) as u32;
56            shift as ffi::KeyCode
57        })
58    }
59}
60
61impl XConnection {
62    pub fn query_keymap(&self) -> Keymap {
63        let mut keys = [0; 32];
64
65        unsafe {
66            (self.xlib.XQueryKeymap)(self.display, keys.as_mut_ptr() as *mut c_char);
67        }
68
69        Keymap { keys }
70    }
71}
72
73fn first_bit(b: u8) -> u8 {
74    1 << b.trailing_zeros()
75}