kbrd/
lib.rs

1//! Rust library for sending and receiving asynchronous keyboard events.
2
3mod key;
4
5pub use self::key::Key;
6use whisk::Channel;
7use pasts::prelude::*;
8
9/// Keyboard modifiers
10#[derive(Copy, Clone, Default, Debug)]
11pub struct Mods(u8);
12
13impl Mods {
14    const COMPOSING: u8 = 0b1000_0000;
15    const GRAPH: u8 = 0b0100_0000;
16    const APP: u8 = 0b0010_0000;
17    const PRG: u8 = 0b0001_0000;
18    const SHIFT: u8 = 0b0000_1000;
19    const EMOJI: u8 = 0b0000_0100;
20    const LTB: u8 = 0b0000_0010; // Left thumb button
21    const RTB: u8 = 0b0000_0001; // Right thumb button
22  
23    fn set(&mut self, what: u8, to: bool) {
24        if to {
25            self.0 |= what;
26        } else {
27            self.0 &= !what;
28        }
29    }
30
31    fn get(&self, what: u8) -> bool {
32        self.0 & what != 0
33    }
34
35    /// Create a new modifier state
36    pub fn new() -> Self {
37        Self::default()
38    }
39
40    /// Set composing
41    pub fn set_composing(&mut self, value: bool) {
42        self.set(Self::COMPOSING, value)
43    }
44
45    /// Set Graph / AltGr (linux/windows) / Option (mac) key
46    pub fn set_graph(&mut self, value: bool) {
47        self.set(Self::GRAPH, value)
48    }
49
50    /// Set Application / Ctrl (linux/windows) / Command (mac) key
51    pub fn set_app(&mut self, value: bool) {
52        self.set(Self::APP, value)
53    }
54
55    /// Set Program / Alt (linux/windows) / Control (mac) key
56    pub fn set_prg(&mut self, value: bool) {
57        self.set(Self::PRG, value)
58    }
59
60    /// Set Shift key
61    pub fn set_shift(&mut self, value: bool) {
62        self.set(Self::SHIFT, value)
63    }
64
65    /// Set Emoji key (Space key)
66    pub fn set_emoji(&mut self, value: bool) {
67        self.set(Self::EMOJI, value)
68    }
69
70    /// Set Left Thumb Button key
71    pub fn set_ltb(&mut self, value: bool) {
72        self.set(Self::LTB, value)
73    }
74
75    /// Set Right Thumb Button key
76    pub fn set_rtb(&mut self, value: bool) {
77        self.set(Self::RTB, value)
78    }
79
80    /// Get composing
81    pub fn composing(&self) -> bool {
82        self.get(Self::COMPOSING)
83    }
84
85    /// Get Graph / AltGr (linux/windows) / Option (mac) key
86    pub fn graph(&self) -> bool {
87        self.get(Self::GRAPH)
88    }
89
90    /// Get Application / Ctrl (linux/windows) / Command (mac) key
91    pub fn app(&self) -> bool {
92        self.get(Self::APP)
93    }
94
95    /// Get Program / Alt (linux/windows) / Control (mac) key
96    pub fn prg(&self) -> bool {
97        self.get(Self::PRG)
98    }
99
100    /// Get Shift key
101    pub fn shift(&self) -> bool {
102        self.get(Self::SHIFT)
103    }
104
105    /// Get Emoji key (Space key)
106    pub fn emoji(&self) -> bool {
107        self.get(Self::EMOJI)
108    }
109
110    /// Get Left Thumb Button key
111    pub fn ltb(&self) -> bool {
112        self.get(Self::LTB)
113    }
114
115    /// Get Right Thumb Button key
116    pub fn rtb(&self) -> bool {
117        self.get(Self::RTB)
118    }
119}
120
121/// Source of keyboard events
122#[derive(Clone, Debug)]
123pub struct Typer(Channel<TypeInternal>);
124
125impl Typer {
126    /// Send a keyboard type event
127    pub fn send(&self, typed: Type) -> impl Future<Output = ()> + Send + Unpin {
128        self.0.send(typed.into())
129    }
130}
131
132/// Keyboard handle
133#[derive(Debug, Default)]
134pub struct Keyboard {
135    state: [u64; 4],
136    channel: Channel<TypeInternal>,
137}
138
139impl Keyboard {
140    /// Create a new keyboard
141    pub fn new() -> Self {
142        Self::default()
143    }
144
145    /// Create a new typer
146    pub fn typer(&self) -> Typer {
147        Typer(self.channel.clone())
148    }
149}
150
151impl Notifier for Keyboard {
152    type Event = Type;
153
154    fn poll_next(mut self: Pin<&mut Self>, exec: &mut Exec<'_>) -> Poll<Type> {
155        if let Ready(typed) = Pin::new(&mut self.channel).poll_next(exec) {
156            let typed = typed.try_into().unwrap();
157            // De-duplication
158            match typed {
159                Type::Press(key, _) => {
160                    let key = key as u8;
161                    let lvl = key / 64;
162                    let key = key % 64;
163                    if self.state[usize::from(lvl)] & (1 << key) != 0 {
164                        return Pending;
165                    } else {
166                        self.state[usize::from(lvl)] |= 1 << key;
167                    }
168                }
169                Type::Release(key, _) => {
170                    let key = key as u8;
171                    let lvl = key / 64;
172                    let key = key % 64;
173                    if self.state[usize::from(lvl)] & (1 << key) == 0 {
174                        return Pending;
175                    } else {
176                        self.state[usize::from(lvl)] &= !(1 << key);
177                    }
178                }
179                Type::Char(_) => {},
180            }
181            Ready(typed)
182        } else {
183            Pending
184        }
185    }
186}
187
188/// A keyboard typing event
189#[repr(C, packed)]
190#[derive(Debug)]
191struct TypeInternal([u8; 4]);
192
193impl TypeInternal {
194    pub fn new(key: Key, state: bool, mods: Mods) -> Self {
195        Self([0xFF, key as u8, state as u8, mods.0])
196    }
197}
198
199impl TryFrom<TypeInternal> for Type {
200    type Error = core::str::Utf8Error;
201
202    fn try_from(other: TypeInternal) -> Result<Self, Self::Error> {
203        let type_ = match other.0 {
204            [0xFF, key, 0, mods] => Self::Release(Key::from(key), Mods(mods)),
205            [0xFF, key, 1, mods] => Self::Press(Key::from(key), Mods(mods)),
206            utf8 => Self::Char(std::str::from_utf8(&utf8)?.chars().next().unwrap()),
207        };
208        Ok(type_)
209    }
210}
211
212/// A typing event
213pub enum Type {
214    Char(char),
215    Press(Key, Mods),
216    Release(Key, Mods),
217}
218
219impl From<Type> for TypeInternal {
220    fn from(other: Type) -> Self {
221        match other {
222            Type::Char(other) => {
223                let mut unicode = [0; 4];
224                other.encode_utf8(unicode.as_mut_slice());
225                Self(unicode)
226            }
227            Type::Press(key, mods) => {
228                Self::new(key, true, mods)
229            }
230            Type::Release(key, mods) => {
231                Self::new(key, false, mods)
232            }
233        }
234    }
235}