Skip to main content

oxstack_input/
key.rs

1/// A physical key, named after its primary legend.
2///
3/// The discriminants are dense (`0..Key::COUNT`) so a set of held keys fits
4/// in one `u64`.
5#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
6#[cfg_attr(feature = "defmt", derive(defmt::Format))]
7#[repr(u8)]
8#[allow(missing_docs)]
9pub enum Key {
10    // Row 0
11    Grave,
12    Num1,
13    Num2,
14    Num3,
15    Num4,
16    Num5,
17    Num6,
18    Num7,
19    Num8,
20    Num9,
21    Num0,
22    Minus,
23    Equal,
24    Backspace,
25    // Row 1
26    Tab,
27    Q,
28    W,
29    E,
30    R,
31    T,
32    Y,
33    U,
34    I,
35    O,
36    P,
37    LeftBracket,
38    RightBracket,
39    Backslash,
40    // Row 2
41    Fn,
42    Shift,
43    A,
44    S,
45    D,
46    F,
47    G,
48    H,
49    J,
50    K,
51    L,
52    Semicolon,
53    Quote,
54    Enter,
55    // Row 3
56    Ctrl,
57    Opt,
58    Alt,
59    Z,
60    X,
61    C,
62    V,
63    B,
64    N,
65    M,
66    Comma,
67    Period,
68    Slash,
69    Space,
70}
71
72impl Key {
73    /// Number of keys.
74    pub const COUNT: usize = Key::Space as usize + 1;
75
76    /// Unshifted and shifted characters printed on the key, for keys that
77    /// type a character.
78    pub const fn legend(self) -> Option<(char, char)> {
79        use Key::*;
80        Some(match self {
81            Grave => ('`', '~'),
82            Num1 => ('1', '!'),
83            Num2 => ('2', '@'),
84            Num3 => ('3', '#'),
85            Num4 => ('4', '$'),
86            Num5 => ('5', '%'),
87            Num6 => ('6', '^'),
88            Num7 => ('7', '&'),
89            Num8 => ('8', '*'),
90            Num9 => ('9', '('),
91            Num0 => ('0', ')'),
92            Minus => ('-', '_'),
93            Equal => ('=', '+'),
94            Q => ('q', 'Q'),
95            W => ('w', 'W'),
96            E => ('e', 'E'),
97            R => ('r', 'R'),
98            T => ('t', 'T'),
99            Y => ('y', 'Y'),
100            U => ('u', 'U'),
101            I => ('i', 'I'),
102            O => ('o', 'O'),
103            P => ('p', 'P'),
104            LeftBracket => ('[', '{'),
105            RightBracket => (']', '}'),
106            Backslash => ('\\', '|'),
107            A => ('a', 'A'),
108            S => ('s', 'S'),
109            D => ('d', 'D'),
110            F => ('f', 'F'),
111            G => ('g', 'G'),
112            H => ('h', 'H'),
113            J => ('j', 'J'),
114            K => ('k', 'K'),
115            L => ('l', 'L'),
116            Semicolon => (';', ':'),
117            Quote => ('\'', '"'),
118            Z => ('z', 'Z'),
119            X => ('x', 'X'),
120            C => ('c', 'C'),
121            V => ('v', 'V'),
122            B => ('b', 'B'),
123            N => ('n', 'N'),
124            M => ('m', 'M'),
125            Comma => (',', '<'),
126            Period => ('.', '>'),
127            Slash => ('/', '?'),
128            Space => (' ', ' '),
129            Backspace | Tab | Fn | Shift | Enter | Ctrl | Opt | Alt => return None,
130        })
131    }
132
133    /// The modifier this key holds down, if it is a modifier key.
134    pub const fn modifier(self) -> Option<Modifiers> {
135        match self {
136            Key::Shift => Some(Modifiers::SHIFT),
137            Key::Ctrl => Some(Modifiers::CTRL),
138            Key::Alt => Some(Modifiers::ALT),
139            Key::Opt => Some(Modifiers::OPT),
140            Key::Fn => Some(Modifiers::FN),
141            _ => None,
142        }
143    }
144
145    pub(crate) const fn bit(self) -> u64 {
146        1 << self as u8
147    }
148}
149
150/// Held modifier keys, as a bit set.
151#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
152#[cfg_attr(feature = "defmt", derive(defmt::Format))]
153pub struct Modifiers(u8);
154
155impl Modifiers {
156    /// No modifiers.
157    pub const NONE: Self = Self(0);
158    /// Shift.
159    pub const SHIFT: Self = Self(1 << 0);
160    /// Ctrl.
161    pub const CTRL: Self = Self(1 << 1);
162    /// Alt.
163    pub const ALT: Self = Self(1 << 2);
164    /// Opt (the Cardputer's fourth modifier).
165    pub const OPT: Self = Self(1 << 3);
166    /// Fn (selects the orange legends).
167    pub const FN: Self = Self(1 << 4);
168
169    /// Whether every modifier in `other` is held.
170    pub const fn contains(self, other: Self) -> bool {
171        self.0 & other.0 == other.0
172    }
173
174    /// Union of two sets.
175    pub const fn union(self, other: Self) -> Self {
176        Self(self.0 | other.0)
177    }
178
179    /// Whether no modifier is held.
180    pub const fn is_empty(self) -> bool {
181        self.0 == 0
182    }
183}
184
185impl core::ops::BitOr for Modifiers {
186    type Output = Self;
187    fn bitor(self, rhs: Self) -> Self {
188        self.union(rhs)
189    }
190}
191
192/// What a key press means once legends and layers are applied.
193#[derive(Clone, Copy, Debug, PartialEq, Eq)]
194#[cfg_attr(feature = "defmt", derive(defmt::Format))]
195pub enum Action {
196    /// A printable character.
197    Char(char),
198    /// Enter / Return.
199    Enter,
200    /// Delete the character before the cursor.
201    Backspace,
202    /// Delete the character after the cursor (Fn + Backspace).
203    Delete,
204    /// Tab.
205    Tab,
206    /// Escape (Fn + `).
207    Escape,
208    /// Cursor up (Fn + ;).
209    Up,
210    /// Cursor down (Fn + .).
211    Down,
212    /// Cursor left (Fn + ,).
213    Left,
214    /// Cursor right (Fn + /).
215    Right,
216    /// Function key `F1..=F12` (Fn + 1 … Fn + =).
217    F(u8),
218}