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
use crate::{
auto::xproto::{KeyButMask, Keycode, Keysym},
display::Display,
};
use gluten_keyboard::Key;
#[cfg(feature = "async")]
use crate::display::AsyncDisplay;
mod convert;
pub use convert::*;
mod xproto;
pub use xproto::*;
pub type DefaultKeymap = XprotoKeymap;
#[derive(Debug, Clone)]
pub struct KeyboardState<Km: ?Sized = DefaultKeymap> {
keymap: Km,
}
impl<Km> KeyboardState<Km> {
#[inline]
pub fn from_keymap(keymap: Km) -> Self {
Self { keymap }
}
}
impl KeyboardState<XprotoKeymap> {
#[inline]
pub fn new<Dpy: Display + ?Sized>(display: &mut Dpy) -> crate::Result<Self> {
Ok(Self::from_keymap(XprotoKeymap::init_from(display)?))
}
#[cfg(feature = "async")]
#[inline]
pub async fn new_async<Dpy: AsyncDisplay + ?Sized>(display: &mut Dpy) -> crate::Result<Self> {
Ok(Self::from_keymap(
XprotoKeymap::init_from_async(display).await?,
))
}
}
impl<Km: Keymap + ?Sized> KeyboardState<Km> {
#[inline]
pub fn lookup_keysyms(&self, keycode: Keycode) -> &[Keysym] {
self.keymap.lookup_keysyms(keycode)
}
#[inline]
pub fn process_keycode(&mut self, keycode: Keycode, modifiers: KeyButMask) -> Option<Key> {
let index = if modifiers.shift() { 1 } else { 0 };
let syms = self.lookup_keysyms(keycode);
if syms.is_empty() {
None
} else if syms.len() == 1 {
keysym_to_key(syms[0])
} else {
keysym_to_key(syms[index])
}
}
}
pub trait Keymap {
fn lookup_keysyms(&self, keycode: Keycode) -> &[Keysym];
}