Skip to main content

furmint_input/
keyboard.rs

1//! Keyboard input handling
2
3use std::collections::HashSet;
4
5/// Represents a physical keyboard key.
6///
7/// Taken from <https://docs.rs/winit/latest/src/winit/keyboard.rs.html#296-740>
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
9#[non_exhaustive]
10pub enum KeyCode {
11    /// <kbd>`</kbd> on a US keyboard. This is also called a backtick or grave.
12    /// This is the <kbd>半角</kbd>/<kbd>全角</kbd>/<kbd>漢字</kbd>
13    /// (hankaku/zenkaku/kanji) key on Japanese keyboards
14    Backquote,
15    /// Used for both the US <kbd>\\</kbd> (on the 101-key layout) and also for the key
16    /// located between the <kbd>"</kbd> and <kbd>Enter</kbd> keys on row C of the 102-,
17    /// 104- and 106-key layouts.
18    /// Labeled <kbd>#</kbd> on a UK (102) keyboard.
19    Backslash,
20    /// <kbd>[</kbd> on a US keyboard.
21    BracketLeft,
22    /// <kbd>]</kbd> on a US keyboard.
23    BracketRight,
24    /// <kbd>,</kbd> on a US keyboard.
25    Comma,
26    /// <kbd>0</kbd> on a US keyboard.
27    Digit0,
28    /// <kbd>1</kbd> on a US keyboard.
29    Digit1,
30    /// <kbd>2</kbd> on a US keyboard.
31    Digit2,
32    /// <kbd>3</kbd> on a US keyboard.
33    Digit3,
34    /// <kbd>4</kbd> on a US keyboard.
35    Digit4,
36    /// <kbd>5</kbd> on a US keyboard.
37    Digit5,
38    /// <kbd>6</kbd> on a US keyboard.
39    Digit6,
40    /// <kbd>7</kbd> on a US keyboard.
41    Digit7,
42    /// <kbd>8</kbd> on a US keyboard.
43    Digit8,
44    /// <kbd>9</kbd> on a US keyboard.
45    Digit9,
46    /// <kbd>=</kbd> on a US keyboard.
47    Equal,
48    /// Located between the left <kbd>Shift</kbd> and <kbd>Z</kbd> keys.
49    /// Labeled <kbd>\\</kbd> on a UK keyboard.
50    IntlBackslash,
51    /// Located between the <kbd>/</kbd> and right <kbd>Shift</kbd> keys.
52    /// Labeled <kbd>\\</kbd> (ro) on a Japanese keyboard.
53    IntlRo,
54    /// Located between the <kbd>=</kbd> and <kbd>Backspace</kbd> keys.
55    /// Labeled <kbd>¥</kbd> (yen) on a Japanese keyboard. <kbd>\\</kbd> on a
56    /// Russian keyboard.
57    IntlYen,
58    /// <kbd>a</kbd> on a US keyboard.
59    /// Labeled <kbd>q</kbd> on an AZERTY (e.g., French) keyboard.
60    KeyA,
61    /// <kbd>b</kbd> on a US keyboard.
62    KeyB,
63    /// <kbd>c</kbd> on a US keyboard.
64    KeyC,
65    /// <kbd>d</kbd> on a US keyboard.
66    KeyD,
67    /// <kbd>e</kbd> on a US keyboard.
68    KeyE,
69    /// <kbd>f</kbd> on a US keyboard.
70    KeyF,
71    /// <kbd>g</kbd> on a US keyboard.
72    KeyG,
73    /// <kbd>h</kbd> on a US keyboard.
74    KeyH,
75    /// <kbd>i</kbd> on a US keyboard.
76    KeyI,
77    /// <kbd>j</kbd> on a US keyboard.
78    KeyJ,
79    /// <kbd>k</kbd> on a US keyboard.
80    KeyK,
81    /// <kbd>l</kbd> on a US keyboard.
82    KeyL,
83    /// <kbd>m</kbd> on a US keyboard.
84    KeyM,
85    /// <kbd>n</kbd> on a US keyboard.
86    KeyN,
87    /// <kbd>o</kbd> on a US keyboard.
88    KeyO,
89    /// <kbd>p</kbd> on a US keyboard.
90    KeyP,
91    /// <kbd>q</kbd> on a US keyboard.
92    /// Labeled <kbd>a</kbd> on an AZERTY (e.g., French) keyboard.
93    KeyQ,
94    /// <kbd>r</kbd> on a US keyboard.
95    KeyR,
96    /// <kbd>s</kbd> on a US keyboard.
97    KeyS,
98    /// <kbd>t</kbd> on a US keyboard.
99    KeyT,
100    /// <kbd>u</kbd> on a US keyboard.
101    KeyU,
102    /// <kbd>v</kbd> on a US keyboard.
103    KeyV,
104    /// <kbd>w</kbd> on a US keyboard.
105    /// Labeled <kbd>z</kbd> on an AZERTY (e.g., French) keyboard.
106    KeyW,
107    /// <kbd>x</kbd> on a US keyboard.
108    KeyX,
109    /// <kbd>y</kbd> on a US keyboard.
110    /// Labeled <kbd>z</kbd> on a QWERTZ (e.g., German) keyboard.
111    KeyY,
112    /// <kbd>z</kbd> on a US keyboard.
113    /// Labeled <kbd>w</kbd> on an AZERTY (e.g., French) keyboard, and <kbd>y</kbd> on a
114    /// QWERTZ (e.g., German) keyboard.
115    KeyZ,
116    /// <kbd>-</kbd> on a US keyboard.
117    Minus,
118    /// <kbd>.</kbd> on a US keyboard.
119    Period,
120    /// <kbd>'</kbd> on a US keyboard.
121    Quote,
122    /// <kbd>;</kbd> on a US keyboard.
123    Semicolon,
124    /// <kbd>/</kbd> on a US keyboard.
125    Slash,
126    /// <kbd>Alt</kbd>, <kbd>Option</kbd>, or <kbd>⌥</kbd>.
127    AltLeft,
128    /// <kbd>Alt</kbd>, <kbd>Option</kbd>, or <kbd>⌥</kbd>.
129    /// This is labeled <kbd>AltGr</kbd> on many keyboard layouts.
130    AltRight,
131    /// <kbd>Backspace</kbd> or <kbd>⌫</kbd>.
132    /// Labeled <kbd>Delete</kbd> on Apple keyboards.
133    Backspace,
134    /// <kbd>CapsLock</kbd> or <kbd>⇪</kbd>
135    CapsLock,
136    /// The application context menu key, which is typically found between the right
137    /// <kbd>Super</kbd> key and the right <kbd>Control</kbd> key.
138    ContextMenu,
139    /// <kbd>Control</kbd> or <kbd>⌃</kbd>
140    ControlLeft,
141    /// <kbd>Control</kbd> or <kbd>⌃</kbd>
142    ControlRight,
143    /// <kbd>Enter</kbd> or <kbd>↵</kbd>. Labeled <kbd>Return</kbd> on Apple keyboards.
144    Enter,
145    /// The Windows, <kbd>⌘</kbd>, <kbd>Command</kbd>, or other OS symbol key.
146    SuperLeft,
147    /// The Windows, <kbd>⌘</kbd>, <kbd>Command</kbd>, or other OS symbol key.
148    SuperRight,
149    /// <kbd>Shift</kbd> or <kbd>⇧</kbd>
150    ShiftLeft,
151    /// <kbd>Shift</kbd> or <kbd>⇧</kbd>
152    ShiftRight,
153    /// <kbd> </kbd> (space)
154    Space,
155    /// <kbd>Tab</kbd> or <kbd>⇥</kbd>
156    Tab,
157    /// Japanese: <kbd>変</kbd> (henkan)
158    Convert,
159    /// Japanese: <kbd>カタカナ</kbd>/<kbd>ひらがな</kbd>/<kbd>ローマ字</kbd>
160    /// (katakana/hiragana/romaji)
161    KanaMode,
162    /// Korean: HangulMode <kbd>한/영</kbd> (han/yeong)
163    ///
164    /// Japanese (Mac keyboard): <kbd>か</kbd> (kana)
165    Lang1,
166    /// Korean: Hanja <kbd>한</kbd> (hanja)
167    ///
168    /// Japanese (Mac keyboard): <kbd>英</kbd> (eisu)
169    Lang2,
170    /// Japanese (word-processing keyboard): Katakana
171    Lang3,
172    /// Japanese (word-processing keyboard): Hiragana
173    Lang4,
174    /// Japanese (word-processing keyboard): Zenkaku/Hankaku
175    Lang5,
176    /// Japanese: <kbd>無変換</kbd> (muhenkan)
177    NonConvert,
178    /// <kbd>⌦</kbd>. The forward delete key.
179    /// Note that on Apple keyboards, the key labelled <kbd>Delete</kbd> on the main part of
180    /// the keyboard is encoded as [`Backspace`].
181    ///
182    /// [`Backspace`]: Self::Backspace
183    Delete,
184    /// <kbd>Page Down</kbd>, <kbd>End</kbd>, or <kbd>↘</kbd>
185    End,
186    /// <kbd>Help</kbd>. Not present on standard PC keyboards.
187    Help,
188    /// <kbd>Home</kbd> or <kbd>↖</kbd>
189    Home,
190    /// <kbd>Insert</kbd> or <kbd>Ins</kbd>. Not present on Apple keyboards.
191    Insert,
192    /// <kbd>Page Down</kbd>, <kbd>PgDn</kbd>, or <kbd>⇟</kbd>
193    PageDown,
194    /// <kbd>Page Up</kbd>, <kbd>PgUp</kbd>, or <kbd>⇞</kbd>
195    PageUp,
196    /// <kbd>↓</kbd>
197    ArrowDown,
198    /// <kbd>←</kbd>
199    ArrowLeft,
200    /// <kbd>→</kbd>
201    ArrowRight,
202    /// <kbd>↑</kbd>
203    ArrowUp,
204    /// On the Mac, this is used for the numpad <kbd>Clear</kbd> key.
205    NumLock,
206    /// <kbd>0 Ins</kbd> on a keyboard. <kbd>0</kbd> on a phone or remote control
207    Numpad0,
208    /// <kbd>1 End</kbd> on a keyboard. <kbd>1</kbd> or <kbd>1 QZ</kbd> on a phone or remote
209    /// control
210    Numpad1,
211    /// <kbd>2 ↓</kbd> on a keyboard. <kbd>2 ABC</kbd> on a phone or remote control
212    Numpad2,
213    /// <kbd>3 PgDn</kbd> on a keyboard. <kbd>3 DEF</kbd> on a phone or remote control
214    Numpad3,
215    /// <kbd>4 ←</kbd> on a keyboard. <kbd>4 GHI</kbd> on a phone or remote control
216    Numpad4,
217    /// <kbd>5</kbd> on a keyboard. <kbd>5 JKL</kbd> on a phone or remote control
218    Numpad5,
219    /// <kbd>6 →</kbd> on a keyboard. <kbd>6 MNO</kbd> on a phone or remote control
220    Numpad6,
221    /// <kbd>7 Home</kbd> on a keyboard. <kbd>7 PQRS</kbd> or <kbd>7 PRS</kbd> on a phone
222    /// or remote control
223    Numpad7,
224    /// <kbd>8 ↑</kbd> on a keyboard. <kbd>8 TUV</kbd> on a phone or remote control
225    Numpad8,
226    /// <kbd>9 PgUp</kbd> on a keyboard. <kbd>9 WXYZ</kbd> or <kbd>9 WXY</kbd> on a phone
227    /// or remote control
228    Numpad9,
229    /// <kbd>+</kbd>
230    NumpadAdd,
231    /// Found on the Microsoft Natural Keyboard.
232    NumpadBackspace,
233    /// <kbd>C</kbd> or <kbd>A</kbd> (All Clear). Also for use with numpads that have a
234    /// <kbd>Clear</kbd> key that is separate from the <kbd>NumLock</kbd> key. On the Mac, the
235    /// numpad <kbd>Clear</kbd> key is encoded as [`NumLock`].
236    ///
237    /// [`NumLock`]: Self::NumLock
238    NumpadClear,
239    /// <kbd>C</kbd> (Clear Entry)
240    NumpadClearEntry,
241    /// <kbd>,</kbd> (thousands separator). For locales where the thousands separator
242    /// is a "." (e.g., Brazil), this key may generate a <kbd>.</kbd>.
243    NumpadComma,
244    /// <kbd>. Del</kbd>. For locales where the decimal separator is "," (e.g.,
245    /// Brazil), this key may generate a <kbd>,</kbd>.
246    NumpadDecimal,
247    /// <kbd>/</kbd>
248    NumpadDivide,
249    /// Numpad enter button
250    NumpadEnter,
251    /// <kbd>=</kbd>
252    NumpadEqual,
253    /// <kbd>#</kbd> on a phone or remote control device. This key is typically found
254    /// below the <kbd>9</kbd> key and to the right of the <kbd>0</kbd> key.
255    NumpadHash,
256    /// <kbd>M</kbd> Add current entry to the value stored in memory.
257    NumpadMemoryAdd,
258    /// <kbd>M</kbd> Clear the value stored in memory.
259    NumpadMemoryClear,
260    /// <kbd>M</kbd> Replace the current entry with the value stored in memory.
261    NumpadMemoryRecall,
262    /// <kbd>M</kbd> Replace the value stored in memory with the current entry.
263    NumpadMemoryStore,
264    /// <kbd>M</kbd> Subtract current entry from the value stored in memory.
265    NumpadMemorySubtract,
266    /// <kbd>*</kbd> on a keyboard. For use with numpads that provide mathematical
267    /// operations (<kbd>+</kbd>, <kbd>-</kbd> <kbd>*</kbd> and <kbd>/</kbd>).
268    ///
269    /// Use `NumpadStar` for the <kbd>*</kbd> key on phones and remote controls.
270    NumpadMultiply,
271    /// <kbd>(</kbd> Found on the Microsoft Natural Keyboard.
272    NumpadParenLeft,
273    /// <kbd>)</kbd> Found on the Microsoft Natural Keyboard.
274    NumpadParenRight,
275    /// <kbd>*</kbd> on a phone or remote control device.
276    ///
277    /// This key is typically found below the <kbd>7</kbd> key and to the left of
278    /// the <kbd>0</kbd> key.
279    ///
280    /// Use <kbd>"NumpadMultiply"</kbd> for the <kbd>*</kbd> key on
281    /// numeric keypads.
282    NumpadStar,
283    /// <kbd>-</kbd>
284    NumpadSubtract,
285    /// <kbd>Esc</kbd> or <kbd>⎋</kbd>
286    Escape,
287    /// <kbd>Fn</kbd> This is typically a hardware key that does not generate a separate code.
288    Fn,
289    /// <kbd>FLock</kbd> or <kbd>FnLock</kbd>. Function Lock key. Found on the Microsoft
290    /// Natural Keyboard.
291    FnLock,
292    /// <kbd>PrtScr SysRq</kbd> or <kbd>Print Screen</kbd>
293    PrintScreen,
294    /// <kbd>Scroll Lock</kbd>
295    ScrollLock,
296    /// <kbd>Pause Break</kbd>
297    Pause,
298    /// Some laptops place this key to the left of the <kbd>↑</kbd> key.
299    ///
300    /// This also the "back" button (triangle) on Android.
301    BrowserBack,
302    /// Some laptops place this key to the right of the <kbd>↑</kbd> key.
303    BrowserForward,
304    /// The "home" button on Android.
305    BrowserHome,
306    /// <kbd>Eject</kbd> or <kbd>⏏</kbd>. This key is placed in the function section on some Apple
307    /// keyboards.
308    Eject,
309    /// Sometimes labelled <kbd>My Computer</kbd> on the keyboard
310    LaunchApp1,
311    /// Sometimes labelled <kbd>Calculator</kbd> on the keyboard
312    LaunchApp2,
313    /// This key is placed in the function section on some Apple keyboards, replacing the
314    /// <kbd>Eject</kbd> key.
315    Power,
316    /// Legacy modifier key. Also called "Super" in certain places.
317    Meta,
318    /// Legacy modifier key.
319    Hyper,
320    /// Found on Sun’s USB keyboard.
321    Again,
322    /// Found on Sun’s USB keyboard.
323    Copy,
324    /// Found on Sun’s USB keyboard.
325    Cut,
326    /// Found on Sun’s USB keyboard.
327    Find,
328    /// Found on Sun’s USB keyboard.
329    Open,
330    /// Found on Sun’s USB keyboard.
331    Paste,
332    /// Found on Sun’s USB keyboard.
333    Props,
334    /// Found on Sun’s USB keyboard.
335    Select,
336    /// Found on Sun’s USB keyboard.
337    Undo,
338    /// Use for dedicated <kbd>ひらがな</kbd> key found on some Japanese word processing keyboards.
339    Hiragana,
340    /// Use for dedicated <kbd>カタカナ</kbd> key found on some Japanese word processing keyboards.
341    Katakana,
342    /// General-purpose function key.
343    /// Usually found at the top of the keyboard.
344    F1,
345    /// General-purpose function key.
346    /// Usually found at the top of the keyboard.
347    F2,
348    /// General-purpose function key.
349    /// Usually found at the top of the keyboard.
350    F3,
351    /// General-purpose function key.
352    /// Usually found at the top of the keyboard.
353    F4,
354    /// General-purpose function key.
355    /// Usually found at the top of the keyboard.
356    F5,
357    /// General-purpose function key.
358    /// Usually found at the top of the keyboard.
359    F6,
360    /// General-purpose function key.
361    /// Usually found at the top of the keyboard.
362    F7,
363    /// General-purpose function key.
364    /// Usually found at the top of the keyboard.
365    F8,
366    /// General-purpose function key.
367    /// Usually found at the top of the keyboard.
368    F9,
369    /// General-purpose function key.
370    /// Usually found at the top of the keyboard.
371    F10,
372    /// General-purpose function key.
373    /// Usually found at the top of the keyboard.
374    F11,
375    /// General-purpose function key.
376    /// Usually found at the top of the keyboard.
377    F12,
378    /// General-purpose function key.
379    /// Usually found at the top of the keyboard.
380    F13,
381    /// General-purpose function key.
382    /// Usually found at the top of the keyboard.
383    F14,
384    /// General-purpose function key.
385    /// Usually found at the top of the keyboard.
386    F15,
387    /// General-purpose function key.
388    /// Usually found at the top of the keyboard.
389    F16,
390    /// General-purpose function key.
391    /// Usually found at the top of the keyboard.
392    F17,
393    /// General-purpose function key.
394    /// Usually found at the top of the keyboard.
395    F18,
396    /// General-purpose function key.
397    /// Usually found at the top of the keyboard.
398    F19,
399    /// General-purpose function key.
400    /// Usually found at the top of the keyboard.
401    F20,
402    /// General-purpose function key.
403    /// Usually found at the top of the keyboard.
404    F21,
405    /// General-purpose function key.
406    /// Usually found at the top of the keyboard.
407    F22,
408    /// General-purpose function key.
409    /// Usually found at the top of the keyboard.
410    F23,
411    /// General-purpose function key.
412    /// Usually found at the top of the keyboard.
413    F24,
414    /// General-purpose function key.
415    F25,
416    /// General-purpose function key.
417    F26,
418    /// General-purpose function key.
419    F27,
420    /// General-purpose function key.
421    F28,
422    /// General-purpose function key.
423    F29,
424    /// General-purpose function key.
425    F30,
426    /// General-purpose function key.
427    F31,
428    /// General-purpose function key.
429    F32,
430    /// General-purpose function key.
431    F33,
432    /// General-purpose function key.
433    F34,
434    /// General-purpose function key.
435    F35,
436}
437
438/// Stores the current keyboard state
439#[derive(Debug, Default)]
440pub struct KeyboardInput {
441    pressed: HashSet<KeyCode>,
442    just_pressed: HashSet<KeyCode>,
443    just_released: HashSet<KeyCode>,
444}
445
446impl KeyboardInput {
447    /// Marks a key as pressed
448    pub fn press(&mut self, key: KeyCode) {
449        if self.pressed.insert(key) {
450            self.just_pressed.insert(key);
451        }
452    }
453
454    /// Marks a key as released
455    pub fn release(&mut self, key: KeyCode) {
456        if self.pressed.remove(&key) {
457            self.just_released.insert(key);
458        }
459    }
460
461    /// Returns `true` if the key is currently held down
462    pub fn pressed(&self, key: KeyCode) -> bool {
463        self.pressed.contains(&key)
464    }
465
466    /// Returns `true` if the key was pressed during this frame
467    pub fn just_pressed(&self, key: KeyCode) -> bool {
468        self.just_pressed.contains(&key)
469    }
470
471    /// Returns `true` if the key was released during this frame
472    pub fn just_released(&self, key: KeyCode) -> bool {
473        self.just_released.contains(&key)
474    }
475
476    /// Clears the state
477    pub fn clear(&mut self) {
478        self.just_pressed.clear();
479        self.just_released.clear();
480    }
481}
482
483impl KeyCode {
484    /// Is this key a modifier?
485    pub fn is_modifier(self) -> bool {
486        matches!(
487            self,
488            KeyCode::ShiftLeft
489                | KeyCode::ShiftRight
490                | KeyCode::ControlLeft
491                | KeyCode::ControlRight
492                | KeyCode::AltLeft
493                | KeyCode::AltRight
494                | KeyCode::SuperLeft
495                | KeyCode::SuperRight
496        )
497    }
498}