livesplit_hotkey/
key_code.rs

1use crate::{Hook, Hotkey, Modifiers};
2use alloc::borrow::Cow;
3use core::{fmt, str::FromStr};
4use serde::{Deserialize, Serialize};
5
6// This is based on the web KeyboardEvent code Values specification and the
7// individual mappings are based on the following sources:
8//
9// USB HID:
10// https://usb.org/sites/default/files/hut1_4.pdf
11//
12// MDN, but it turns out to be wrong in many ways:
13// https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code/code_values
14//
15// Chromium's sources:
16// https://github.com/chromium/chromium/blob/5af3e41ce69e2e18b899589b46540e4360527733/ui/events/keycodes/dom/dom_code_data.inc
17//
18// Firefox's sources:
19// https://github.com/mozilla/gecko-dev/blob/25002b534963ad95ff0c1a3dd0f906ba023ddc8e/widget/NativeKeyToDOMCodeName.h
20//
21// Safari's sources:
22// Windows:
23// https://github.com/WebKit/WebKit/blob/8afe31a018b11741abdf9b4d5bb973d7c1d9ff05/Source/WebCore/platform/win/WindowsKeyNames.cpp
24// macOS:
25// https://github.com/WebKit/WebKit/blob/main/Source/WebCore/platform/mac/PlatformEventFactoryMac.mm
26// Linux GTK:
27// https://github.com/WebKit/WebKit/blob/8afe31a018b11741abdf9b4d5bb973d7c1d9ff05/Source/WebCore/platform/gtk/PlatformKeyboardEventGtk.cpp
28// WPE:
29// https://github.com/WebKit/WebKit/blob/8afe31a018b11741abdf9b4d5bb973d7c1d9ff05/Source/WebCore/platform/libwpe/PlatformKeyboardEventLibWPE.cpp
30
31/// A key code represents a physical key on a keyboard and is independent of the
32/// keyboard layout. The values are based on the [`UI Events KeyboardEvent code
33/// Values`](https://www.w3.org/TR/uievents-code/) specification. There are some
34/// additional values for Gamepad support and some browser specific values.
35#[derive(Eq, PartialEq, Hash, Copy, Clone)]
36#[non_exhaustive]
37pub enum KeyCode {
38    /// `Backtick` and `~` on a US keyboard. This is the `半角/全角/漢字`
39    /// (`hankaku/zenkaku/kanji`) key on Japanese keyboards
40    ///
41    /// USB HID:
42    ///  - `Keyboard Grave Accent and Tilde` `Keyboard Page 0x35`
43    Backquote,
44    /// Used for both the US `\|` (on the 101-key layout) and also for the key
45    /// located between the `"` and `Enter` keys on row C of the 102-, 104- and
46    /// 106-key layouts. Labelled `#~` on a UK (102) keyboard.
47    ///
48    /// USB HID:
49    ///  - `Keyboard \ and |` `Keyboard Page 0x31`
50    ///  - `Keyboard Non-US # and ~` `Keyboard Page 0x32`
51    Backslash,
52    /// `[{` on a US keyboard.
53    ///
54    /// USB HID:
55    ///  - `Keyboard [ and {` `Keyboard Page 0x2f`
56    BracketLeft,
57    /// `]}` on a US keyboard.
58    ///
59    /// USB HID:
60    ///  - `Keyboard ] and }` `Keyboard Page 0x30`
61    BracketRight,
62    /// `,<` on a US keyboard.
63    ///
64    /// USB HID:
65    ///  - `Keyboard , and <` `Keyboard Page 0x36`
66    Comma,
67    /// `0)` on a US keyboard.
68    ///
69    /// USB HID:
70    ///  - `Keyboard 0 and )` `Keyboard Page 0x27`
71    Digit0,
72    /// `1!` on a US keyboard.
73    ///
74    /// USB HID:
75    ///  - `Keyboard 1 and !` `Keyboard Page 0x1e`
76    Digit1,
77    /// `2@` on a US keyboard.
78    ///
79    /// USB HID:
80    ///  - `Keyboard 2 and @` `Keyboard Page 0x1f`
81    Digit2,
82    /// `3#` on a US keyboard.
83    ///
84    /// USB HID:
85    ///  - `Keyboard 3 and #` `Keyboard Page 0x20`
86    Digit3,
87    /// `4$` on a US keyboard.
88    ///
89    /// USB HID:
90    ///  - `Keyboard 4 and $` `Keyboard Page 0x21`
91    Digit4,
92    /// `5%` on a US keyboard.
93    ///
94    /// USB HID:
95    ///  - `Keyboard 5 and %` `Keyboard Page 0x22`
96    Digit5,
97    /// `6^` on a US keyboard.
98    ///
99    /// USB HID:
100    ///  - `Keyboard 6 and ^` `Keyboard Page 0x23`
101    Digit6,
102    /// `7&` on a US keyboard.
103    ///
104    /// USB HID:
105    ///  - `Keyboard 7 and &` `Keyboard Page 0x24`
106    Digit7,
107    /// `8*` on a US keyboard.
108    ///
109    /// USB HID:
110    ///  - `Keyboard 8 and *` `Keyboard Page 0x25`
111    Digit8,
112    /// `9(` on a US keyboard.
113    ///
114    /// USB HID:
115    ///  - `Keyboard 9 and (` `Keyboard Page 0x26`
116    Digit9,
117    /// `=+` on a US keyboard.
118    ///
119    /// USB HID:
120    ///  - `Keyboard = and +` `Keyboard Page 0x2e`
121    Equal,
122    /// Located between the left `Shift` and `Z` keys. Labelled `\|` on a UK
123    /// keyboard.
124    ///
125    /// USB HID:
126    ///  - `Keyboard Non-US \ and |` `Keyboard Page 0x64`
127    IntlBackslash,
128    /// Located between the `/` and right `Shift` keys. Labelled `\ろ` (`ro`) on
129    /// a Japanese keyboard.
130    ///
131    /// USB HID:
132    ///  - `Keyboard International1` `Keyboard Page 0x87`
133    IntlRo,
134    /// Located between the `=` and `Backspace` keys. Labelled `¥` (`yen`) on a
135    /// Japanese keyboard. `\/` on a Russian keyboard.
136    ///
137    /// USB HID:
138    ///  - `Keyboard International3` `Keyboard Page 0x89`
139    IntlYen,
140    /// `a` on a US keyboard. Labelled `q` on an AZERTY (e.g., French) keyboard.
141    ///
142    /// USB HID:
143    ///  - `Keyboard a and A` `Keyboard Page 0x4`
144    KeyA,
145    /// `b` on a US keyboard.
146    ///
147    /// USB HID:
148    ///  - `Keyboard b and B` `Keyboard Page 0x5`
149    KeyB,
150    /// `c` on a US keyboard.
151    ///
152    /// USB HID:
153    ///  - `Keyboard c and C` `Keyboard Page 0x6`
154    KeyC,
155    /// `d` on a US keyboard.
156    ///
157    /// USB HID:
158    ///  - `Keyboard d and D` `Keyboard Page 0x7`
159    KeyD,
160    /// `e` on a US keyboard.
161    ///
162    /// USB HID:
163    ///  - `Keyboard e and E` `Keyboard Page 0x8`
164    KeyE,
165    /// `f` on a US keyboard.
166    ///
167    /// USB HID:
168    ///  - `Keyboard f and F` `Keyboard Page 0x9`
169    KeyF,
170    /// `g` on a US keyboard.
171    ///
172    /// USB HID:
173    ///  - `Keyboard g and G` `Keyboard Page 0xa`
174    KeyG,
175    /// `h` on a US keyboard.
176    ///
177    /// USB HID:
178    ///  - `Keyboard h and H` `Keyboard Page 0xb`
179    KeyH,
180    /// `i` on a US keyboard.
181    ///
182    /// USB HID:
183    ///  - `Keyboard i and I` `Keyboard Page 0xc`
184    KeyI,
185    /// `j` on a US keyboard.
186    ///
187    /// USB HID:
188    ///  - `Keyboard j and J` `Keyboard Page 0xd`
189    KeyJ,
190    /// `k` on a US keyboard.
191    ///
192    /// USB HID:
193    ///  - `Keyboard k and K` `Keyboard Page 0xe`
194    KeyK,
195    /// `l` on a US keyboard.
196    ///
197    /// USB HID:
198    ///  - `Keyboard l and L` `Keyboard Page 0xf`
199    KeyL,
200    /// `m` on a US keyboard.
201    ///
202    /// USB HID:
203    ///  - `Keyboard m and M` `Keyboard Page 0x10`
204    KeyM,
205    /// `n` on a US keyboard.
206    ///
207    /// USB HID:
208    ///  - `Keyboard n and N` `Keyboard Page 0x11`
209    KeyN,
210    /// `o` on a US keyboard.
211    ///
212    /// USB HID:
213    ///  - `Keyboard o and O` `Keyboard Page 0x12`
214    KeyO,
215    /// `p` on a US keyboard.
216    ///
217    /// USB HID:
218    ///  - `Keyboard p and P` `Keyboard Page 0x13`
219    KeyP,
220    /// `q` on a US keyboard. Labelled `a` on an AZERTY (e.g., French) keyboard.
221    ///
222    /// USB HID:
223    ///  - `Keyboard q and Q` `Keyboard Page 0x14`
224    KeyQ,
225    /// `r` on a US keyboard.
226    ///
227    /// USB HID:
228    ///  - `Keyboard r and R` `Keyboard Page 0x15`
229    KeyR,
230    /// `s` on a US keyboard.
231    ///
232    /// USB HID:
233    ///  - `Keyboard s and S` `Keyboard Page 0x16`
234    KeyS,
235    /// `t` on a US keyboard.
236    ///
237    /// USB HID:
238    ///  - `Keyboard t and T` `Keyboard Page 0x17`
239    KeyT,
240    /// `u` on a US keyboard.
241    ///
242    /// USB HID:
243    ///  - `Keyboard u and U` `Keyboard Page 0x18`
244    KeyU,
245    /// `v` on a US keyboard.
246    ///
247    /// USB HID:
248    ///  - `Keyboard v and V` `Keyboard Page 0x19`
249    KeyV,
250    /// `w` on a US keyboard. Labelled `z` on an AZERTY (e.g., French) keyboard.
251    ///
252    /// USB HID:
253    ///  - `Keyboard w and W` `Keyboard Page 0x1a`
254    KeyW,
255    /// `x` on a US keyboard.
256    ///
257    /// USB HID:
258    ///  - `Keyboard x and X` `Keyboard Page 0x1b`
259    KeyX,
260    /// `y` on a US keyboard. Labelled `z` on a QWERTZ (e.g., German) keyboard.
261    ///
262    /// USB HID:
263    ///  - `Keyboard y and Y` `Keyboard Page 0x1c`
264    KeyY,
265    /// `z` on a US keyboard. Labelled `w` on an AZERTY (e.g., French) keyboard,
266    /// and `y` on a QWERTZ (e.g., German) keyboard.
267    ///
268    /// USB HID:
269    ///  - `Keyboard z and Z` `Keyboard Page 0x1d`
270    KeyZ,
271    /// `-_` on a US keyboard.
272    ///
273    /// USB HID:
274    ///  - `Keyboard - and (underscore)` `Keyboard Page 0x2d`
275    Minus,
276    /// `.>` on a US keyboard.
277    ///
278    /// USB HID:
279    ///  - `Keyboard . and >` `Keyboard Page 0x37`
280    Period,
281    /// `'"` on a US keyboard.
282    ///
283    /// USB HID:
284    ///  - `Keyboard ‘ and “` `Keyboard Page 0x34`
285    Quote,
286    /// `;:` on a US keyboard.
287    ///
288    /// USB HID:
289    ///  - `Keyboard ; and :` `Keyboard Page 0x33`
290    Semicolon,
291    /// `/?` on a US keyboard.
292    ///
293    /// USB HID:
294    ///  - `Keyboard / and ?` `Keyboard Page 0x38`
295    Slash,
296
297    /// `Alt`, `Option` or
298    /// `⌥`.
299    ///
300    /// USB HID:
301    ///  - `Keyboard LeftAlt` `Keyboard Page 0xe2`
302    AltLeft,
303    /// `Alt`, `Option` or `⌥`. This is labelled `AltGr` key on many keyboard
304    /// layouts.
305    ///
306    /// USB HID:
307    ///  - `Keyboard RightAlt` `Keyboard Page 0xe6`
308    AltRight,
309    /// `Backspace` or `⌫`. Labelled `Delete` on Apple keyboards.
310    ///
311    /// USB HID:
312    ///  - `Keyboard DELETE (Backspace)` `Keyboard Page 0x2a`
313    Backspace,
314    /// `CapsLock` or `⇪`
315    ///
316    /// USB HID:
317    ///  - `Keyboard Caps Lock` `Keyboard Page 0x39`
318    CapsLock,
319    /// The application context menu key, which is typically found between the
320    /// right `Meta` key and the right `Control` key.
321    ///
322    /// USB HID:
323    ///  - `Keyboard Application` `Keyboard Page 0x65`
324    ContextMenu,
325    /// `Control` or `⌃`
326    ///
327    /// USB HID:
328    ///  - `Keyboard LeftControl` `Keyboard Page 0xe0`
329    ControlLeft,
330    /// `Control` or `⌃`
331    ///
332    /// USB HID:
333    ///  - `Keyboard RightControl` `Keyboard Page 0xe4`
334    ControlRight,
335    /// `Enter` or `↵`. Labelled `Return` on Apple keyboards.
336    ///
337    /// USB HID:
338    ///  - `Keyboard Return (ENTER)` `Keyboard Page 0x28`
339    ///  - `Enter Channel` `Consumer Page 0x84`
340    Enter,
341    /// The Windows, `⌘`, `Command` or other OS symbol key.
342    ///
343    /// USB HID:
344    ///  - `Keyboard Left GUI` `Keyboard Page 0xe3`
345    MetaLeft,
346    /// The Windows, `⌘`, `Command` or other OS symbol key.
347    ///
348    /// USB HID:
349    ///  - `Keyboard Right GUI` `Keyboard Page 0xe7`
350    MetaRight,
351    /// `Shift` or `⇧`
352    ///
353    /// USB HID:
354    ///  - `Keyboard LeftShift` `Keyboard Page 0xe1`
355    ShiftLeft,
356    /// `Shift` or `⇧`
357    ///
358    /// USB HID:
359    ///  - `Keyboard RightShift` `Keyboard Page 0xe5`
360    ShiftRight,
361    /// ` ` (space)
362    ///
363    /// USB HID:
364    ///  - `Keyboard Spacebar` `Keyboard Page 0x2c`
365    Space,
366    /// `Tab` or `⇥`
367    ///
368    /// USB HID:
369    ///  - `Keyboard Tab` `Keyboard Page 0x2b`
370    Tab,
371
372    /// Japanese: `変換` (`henkan`)
373    ///
374    /// USB HID:
375    ///  - `Keyboard International4` `Keyboard Page 0x8a`
376    Convert,
377    /// Japanese: `カタカナ/ひらがな/ローマ字` (`katakana/hiragana/romaji`)
378    ///
379    /// USB HID:
380    ///  - `Keyboard International2` `Keyboard Page 0x88`
381    KanaMode,
382    /// Korean: HangulMode `한/영` (`han/yeong`)
383    ///
384    /// Japanese (Mac keyboard): `かな` (`kana`)
385    ///
386    /// USB HID:
387    ///  - `Keyboard LANG1` `Keyboard Page 0x90`
388    Lang1,
389    /// Korean: Hanja `한자` (`hanja`)
390    ///
391    /// Japanese (Mac keyboard): `英数` (`eisu`)
392    ///
393    /// USB HID:
394    ///  - `Keyboard LANG2` `Keyboard Page 0x91`
395    Lang2,
396    /// Japanese (word-processing keyboard): Katakana
397    ///
398    /// USB HID:
399    ///  - `Keyboard LANG3` `Keyboard Page 0x92`
400    Lang3,
401    /// Japanese (word-processing keyboard): Hiragana
402    ///
403    /// USB HID:
404    ///  - `Keyboard LANG4` `Keyboard Page 0x93`
405    Lang4,
406    /// Japanese (word-processing keyboard): Zenkaku/Hankaku
407    ///
408    /// USB HID:
409    ///  - `Keyboard LANG5` `Keyboard Page 0x94`
410    Lang5,
411    /// Japanese: `無変換` (`muhenkan`)
412    ///
413    /// USB HID:
414    ///  - `Keyboard International5` `Keyboard Page 0x8b`
415    NonConvert,
416
417    /// `⌦`. The forward delete key. Note that on Apple keyboards, the key
418    /// labelled `Delete` on the main part of the keyboard should be encoded as
419    /// `"Backspace"`.
420    ///
421    /// USB HID:
422    ///  - `Keyboard Delete Forward` `Keyboard Page 0x4c`
423    ///  - `Keyboard Clear` `Keyboard Page 0x9c`
424    ///  - `Keypad Clear` `Keyboard Page 0xd8`
425    ///  - `AC Delete` `Consumer Page 0x26a`
426    Delete,
427    /// `Page Down`, `End` or `↘`
428    ///
429    /// USB HID:
430    ///  - `Keyboard End` `Keyboard Page 0x4d`
431    End,
432    /// `Help`. Not present on standard PC keyboards.
433    ///
434    /// USB HID:
435    ///  - `Keyboard Help` `Keyboard Page 0x75`
436    ///  - `Help` `Consumer Page 0x95`
437    ///  - `AL Integrated Help Center` `Consumer Page 0x1a6`
438    Help,
439    /// `Home` or `↖`
440    ///
441    /// USB HID:
442    ///  - `Keyboard Home` `Keyboard Page 0x4a`
443    Home,
444    /// `Insert` or `Ins`. Not present on Apple keyboards.
445    ///
446    /// USB HID:
447    ///  - `Keyboard Insert` `Keyboard Page 0x49`
448    ///  - `AC Insert Mode` `Consumer Page 0x269`
449    Insert,
450    /// `Page Down`, `PgDn` or `⇟`
451    ///
452    /// USB HID:
453    ///  - `Keyboard PageDown` `Keyboard Page 0x4e`
454    PageDown,
455    /// `Page Up`, `PgUp` or
456    /// `⇞`
457    ///
458    /// USB HID:
459    ///  - `Keyboard PageUp` `Keyboard Page 0x4b`
460    PageUp,
461
462    /// `↓`
463    ///
464    /// USB HID:
465    ///  - `Keyboard DownArrow` `Keyboard Page 0x51`
466    ///  - `Menu Down` `Consumer Page 0x43`
467    ArrowDown,
468    /// `←`
469    ///
470    /// USB HID:
471    ///  - `Keyboard LeftArrow` `Keyboard Page 0x50`
472    ///  - `Menu Left` `Consumer Page 0x44`
473    ArrowLeft,
474    /// `→`
475    ///
476    /// USB HID:
477    ///  - `Keyboard RightArrow` `Keyboard Page 0x4f`
478    ///  - `Menu Right` `Consumer Page 0x45`
479    ArrowRight,
480    /// `↑`
481    ///
482    /// USB HID:
483    ///  - `Keyboard UpArrow` `Keyboard Page 0x52`
484    ///  - `Menu Up` `Consumer Page 0x42`
485    ArrowUp,
486
487    /// On the Mac, the `"NumLock"` code should be used for the numpad `Clear`
488    /// key.
489    ///
490    /// USB HID:
491    ///  - `Keypad Num Lock and Clear` `Keyboard Page 0x53`
492    NumLock,
493    /// `0 Ins` on a keyboard
494    ///
495    /// `0` on a phone or remote control
496    ///
497    /// USB HID:
498    ///  - `Keypad 0 and Insert` `Keyboard Page 0x62`
499    ///  - `Phone Key 0` `Telephony Device Page 0xb0`
500    Numpad0,
501    /// `1 End` on a keyboard
502    ///
503    /// `1` or `1 QZ` on a phone or remote control
504    ///
505    /// USB HID:
506    ///  - `Keypad 1 and End` `Keyboard Page 0x59`
507    ///  - `Phone Key 1` `Telephony Device Page 0xb1`
508    Numpad1,
509    /// `2 ↓` on a keyboard
510    ///
511    /// `2 ABC` on a phone or remote control
512    ///
513    /// USB HID:
514    ///  - `Keypad 2 and Down Arrow` `Keyboard Page 0x5a`
515    ///  - `Phone Key 2` `Telephony Device Page 0xb2`
516    Numpad2,
517    /// `3 PgDn` on a keyboard
518    ///
519    /// `3 DEF` on a phone or remote control
520    ///
521    /// USB HID:
522    ///  - `Keypad 3 and PageDn` `Keyboard Page 0x5b`
523    ///  - `Phone Key 3` `Telephony Device Page 0xb3`
524    Numpad3,
525    /// `4 ←` on a keyboard
526    ///
527    /// `4 GHI` on a phone or remote control
528    ///
529    /// USB HID:
530    ///  - `Keypad 4 and Left Arrow` `Keyboard Page 0x5c`
531    ///  - `Phone Key 4` `Telephony Device Page 0xb4`
532    Numpad4,
533    /// `5` on a keyboard
534    ///
535    /// `5 JKL` on a phone or remote control
536    ///
537    /// USB HID:
538    ///  - `Keypad 5` `Keyboard Page 0x5d`
539    ///  - `Phone Key 5` `Telephony Device Page 0xb5`
540    Numpad5,
541    /// `6 →` on a keyboard
542    ///
543    /// `6 MNO` on a phone or remote control
544    ///
545    /// USB HID:
546    ///  - `Keypad 6 and Right Arrow` `Keyboard Page 0x5e`
547    ///  - `Phone Key 6` `Telephony Device Page 0xb6`
548    Numpad6,
549    /// `7 Home` on a keyboard
550    ///
551    /// `7 PQRS` or `7 PRS` on a phone or remote control
552    ///
553    /// USB HID:
554    ///  - `Keypad 7 and Home` `Keyboard Page 0x5f`
555    ///  - `Phone Key 7` `Telephony Device Page 0xb7`
556    Numpad7,
557    /// `8 ↑` on a keyboard
558    ///
559    /// `8 TUV` on a phone or remote control
560    ///
561    /// USB HID:
562    ///  - `Keypad 8 and Up Arrow` `Keyboard Page 0x60`
563    ///  - `Phone Key 8` `Telephony Device Page 0xb8`
564    Numpad8,
565    /// `9 PgUp` on a keyboard
566    ///
567    /// `9 WXYZ` or `9 WXY` on a phone or remote control
568    ///
569    /// USB HID:
570    ///  - `Keypad 9 and PageUp` `Keyboard Page 0x61`
571    ///  - `Phone Key 9` `Telephony Device Page 0xb9`
572    Numpad9,
573    /// `+`
574    ///
575    /// USB HID:
576    ///  - `Keypad +` `Keyboard Page 0x57`
577    ///  - `Menu Value Increase` `Consumer Page 0x47`
578    NumpadAdd,
579    /// Found on the Microsoft Natural Keyboard.
580    ///
581    /// USB HID:
582    ///  - `Keypad Backspace` `Keyboard Page 0xbb`
583    NumpadBackspace,
584    /// `C` or `AC` (All Clear). Also for use with numpads that have a `Clear`
585    /// key that is separate from the `NumLock` key. On the Mac, the numpad
586    /// `Clear` key should always be encoded as `"NumLock"`.
587    ///
588    /// USB HID:
589    ///  - `Keypad Clear` `Keyboard Page 0xd8`
590    NumpadClear,
591    /// `CE` (Clear Entry)
592    ///
593    /// USB HID:
594    ///  - `Keypad Clear Entry` `Keyboard Page 0xd9`
595    NumpadClearEntry,
596    /// `,` (thousands separator). For locales where the thousands separator is
597    /// a "." (e.g., Brazil), this key may generate a `.`.
598    ///
599    /// USB HID:
600    ///  - `Keypad Comma` `Keyboard Page 0x85`
601    NumpadComma,
602    /// `. Del`. For locales where the decimal separator is "," (e.g., Brazil),
603    /// this key may generate a `,`.
604    ///
605    /// USB HID:
606    ///  - `Keypad . and Delete` `Keyboard Page 0x63`
607    NumpadDecimal,
608    /// `/`
609    ///
610    /// USB HID:
611    ///  - `Keypad /` `Keyboard Page 0x54`
612    NumpadDivide,
613    /// USB HID:
614    ///  - `Keypad ENTER` `Keyboard Page 0x58`
615    NumpadEnter,
616    /// `=`
617    ///
618    /// USB HID:
619    ///  - `Keypad =` `Keyboard Page 0x67`
620    NumpadEqual,
621    /// `#` on a phone or remote control device. This key is typically found
622    /// below the `9` key and to the right of the `0` key.
623    ///
624    /// USB HID:
625    ///  - `Phone Key Pound` `Telephony Device Page 0xbb`
626    NumpadHash,
627    /// `M+` Add current entry to the value stored in memory.
628    ///
629    /// USB HID:
630    ///  - `Keypad Memory Add` `Keyboard Page 0xd3`
631    NumpadMemoryAdd,
632    /// `MC` Clear the value stored in memory.
633    ///
634    /// USB HID:
635    ///  - `Keypad Memory Clear` `Keyboard Page 0xd2`
636    NumpadMemoryClear,
637    /// `MR` Replace the current entry with the value stored in memory.
638    ///
639    /// USB HID:
640    ///  - `Keypad Memory Recall` `Keyboard Page 0xd1`
641    NumpadMemoryRecall,
642    /// `MS` Replace the value stored in memory with the current entry.
643    ///
644    /// USB HID:
645    ///  - `Keypad Memory Store` `Keyboard Page 0xd0`
646    NumpadMemoryStore,
647    /// `M-` Subtract current entry from the value
648    /// stored in memory.
649    ///
650    /// USB HID:
651    ///  - `Keypad Memory Subtract` `Keyboard Page 0xd4`
652    NumpadMemorySubtract,
653    /// `*` on a keyboard. For use with numpads that provide mathematical
654    /// operations (`+`, `-`, `*` and `/`).
655    ///
656    /// Use [`KeyCode::NumpadStar`] for the `*` key on phones and remote controls.
657    ///
658    /// USB HID:
659    ///  - `Keypad *` `Keyboard Page 0x55`
660    NumpadMultiply,
661    /// `(` Found on the Microsoft Natural Keyboard.
662    ///
663    /// USB HID:
664    ///  - `Keypad (` `Keyboard Page 0xb6`
665    NumpadParenLeft,
666    /// `)` Found on the Microsoft Natural Keyboard.
667    ///
668    /// USB HID:
669    ///  - `Keypad )` `Keyboard Page 0xb7`
670    NumpadParenRight,
671    /// `*` on a phone or remote control device. This key is typically found
672    /// below the `7` key and to the left of the `0` key.
673    ///
674    /// Use [`KeyCode::NumpadMultiply`] for the `*` key on numeric keypads.
675    ///
676    /// USB HID:
677    ///  - `Phone Key Star` `Telephony Device Page 0xba`
678    NumpadStar,
679    /// `-`
680    ///
681    /// USB HID:
682    ///  - `Keypad -` `Keyboard Page 0x56`
683    ///  - `Menu Value Decrease` `Consumer Page 0x48`
684    NumpadSubtract,
685
686    /// `Esc` or `⎋`
687    ///
688    /// USB HID:
689    ///  - `Keyboard ESCAPE` `Keyboard Page 0x29`
690    ///  - `Menu Escape` `Consumer Page 0x46`
691    Escape,
692    /// `F1`
693    ///
694    /// USB HID:
695    ///  - `Keyboard F1` `Keyboard Page 0x3a`
696    F1,
697    /// `F2`
698    ///
699    /// USB HID:
700    ///  - `Keyboard F2` `Keyboard Page 0x3b`
701    F2,
702    /// `F3`
703    ///
704    /// USB HID:
705    ///  - `Keyboard F3` `Keyboard Page 0x3c`
706    F3,
707    /// `F4`
708    ///
709    /// USB HID:
710    ///  - `Keyboard F4` `Keyboard Page 0x3d`
711    F4,
712    /// `F5`
713    ///
714    /// USB HID:
715    ///  - `Keyboard F5` `Keyboard Page 0x3e`
716    F5,
717    /// `F6`
718    ///
719    /// USB HID:
720    ///  - `Keyboard F6` `Keyboard Page 0x3f`
721    F6,
722    /// `F7`
723    ///
724    /// USB HID:
725    ///  - `Keyboard F7` `Keyboard Page 0x40`
726    F7,
727    /// `F8`
728    ///
729    /// USB HID:
730    ///  - `Keyboard F8` `Keyboard Page 0x41`
731    F8,
732    /// `F9`
733    ///
734    /// USB HID:
735    ///  - `Keyboard F9` `Keyboard Page 0x42`
736    F9,
737    /// `F10`
738    ///
739    /// USB HID:
740    ///  - `Keyboard F10` `Keyboard Page 0x43`
741    F10,
742    /// `F11`
743    ///
744    /// USB HID:
745    ///  - `Keyboard F11` `Keyboard Page 0x44`
746    F11,
747    /// `F12`
748    ///
749    /// USB HID:
750    ///  - `Keyboard F12` `Keyboard Page 0x45`
751    F12,
752    /// `F13`
753    ///
754    /// USB HID:
755    ///  - `Keyboard F13` `Keyboard Page 0x68`
756    F13,
757    /// `F14`
758    ///
759    /// USB HID:
760    ///  - `Keyboard F14` `Keyboard Page 0x69`
761    F14,
762    /// `F15`
763    ///
764    /// USB HID:
765    ///  - `Keyboard F15` `Keyboard Page 0x6a`
766    F15,
767    /// `F16`
768    ///
769    /// USB HID:
770    ///  - `Keyboard F16` `Keyboard Page 0x6b`
771    F16,
772    /// `F17`
773    ///
774    /// USB HID:
775    ///  - `Keyboard F17` `Keyboard Page 0x6c`
776    F17,
777    /// `F18`
778    ///
779    /// USB HID:
780    ///  - `Keyboard F18` `Keyboard Page 0x6d`
781    F18,
782    /// `F19`
783    ///
784    /// USB HID:
785    ///  - `Keyboard F19` `Keyboard Page 0x6e`
786    F19,
787    /// `F20`
788    ///
789    /// USB HID:
790    ///  - `Keyboard F20` `Keyboard Page 0x6f`
791    F20,
792    /// `F21`
793    ///
794    /// USB HID:
795    ///  - `Keyboard F21` `Keyboard Page 0x70`
796    F21,
797    /// `F22`
798    ///
799    /// USB HID:
800    ///  - `Keyboard F22` `Keyboard Page 0x71`
801    F22,
802    /// `F23`
803    ///
804    /// USB HID:
805    ///  - `Keyboard F23` `Keyboard Page 0x72`
806    F23,
807    /// `F24`
808    ///
809    /// USB HID:
810    ///  - `Keyboard F24` `Keyboard Page 0x73`
811    F24,
812    /// `Fn` This is typically a hardware key that does not generate a separate
813    /// code. Most keyboards do not place this key in the function section, but
814    /// it is included here to keep it with related keys.
815    ///
816    /// USB HID:
817    ///
818    Fn,
819    /// `FLock` or `FnLock`. Function Lock key. Found on the Microsoft Natural
820    /// Keyboard.
821    ///
822    /// USB HID:
823    ///
824    FnLock,
825    /// `PrtScr SysRq` or `Print Screen`
826    ///
827    /// USB HID:
828    ///  - `Keyboard PrintScreen` `Keyboard Page 0x46`
829    PrintScreen,
830    /// `Scroll Lock`
831    ///
832    /// USB HID:
833    ///  - `Keyboard Scroll Lock` `Keyboard Page 0x47`
834    ScrollLock,
835    /// `Pause Break`
836    ///
837    /// USB HID:
838    ///  - `Keyboard Pause` `Keyboard Page 0x48`
839    ///  - `Pause` `Consumer Page 0xb1`
840    Pause,
841
842    /// Some laptops place this key to the left of the `↑` key.
843    ///
844    /// USB HID:
845    ///  - `Reserved` `Keyboard Page 0xf1`
846    ///  - `AC Back` `Consumer Page 0x224`
847    BrowserBack,
848    /// USB HID:
849    ///  - `AL Programmable Button Configuration` `Consumer Page 0x182`
850    ///  - `AC Bookmarks` `Consumer Page 0x22a`
851    BrowserFavorites,
852    /// Some laptops place this key to the right of the `↑` key.
853    ///
854    /// USB HID:
855    ///  - `Reserved` `Keyboard Page 0xf2`
856    ///  - `AC Forward` `Consumer Page 0x225`
857    BrowserForward,
858    /// USB HID:
859    ///  - `AC Home` `Consumer Page 0x223`
860    BrowserHome,
861    /// USB HID:
862    ///  - `Reserved` `Keyboard Page 0xfa`
863    ///  - `AC Refresh` `Consumer Page 0x227`
864    BrowserRefresh,
865    /// USB HID:
866    ///  - `AC Search` `Consumer Page 0x221`
867    BrowserSearch,
868    /// USB HID:
869    ///  - `Keyboard Stop` `Keyboard Page 0x78`
870    ///  - `Reserved` `Keyboard Page 0xf3`
871    ///  - `AC Stop` `Consumer Page 0x226`
872    BrowserStop,
873    /// `Eject` or `⏏`. This key is placed in the function section on some Apple
874    /// keyboards.
875    ///
876    /// USB HID:
877    ///  - `Reserved` `Keyboard Page 0xec`
878    ///  - `Eject` `Consumer Page 0xb8`
879    Eject,
880    /// Sometimes labelled `My Computer` on the keyboard
881    ///
882    /// USB HID:
883    ///  - `AL Local Machine Browser` `Consumer Page 0x194`
884    ///  - `AL File Browser` `Consumer Page 0x1b4`
885    LaunchApp1,
886    /// Sometimes labelled `Calculator` on the keyboard
887    ///
888    /// USB HID:
889    ///  - `Reserved` `Keyboard Page 0xfb`
890    ///  - `AL Calculator` `Consumer Page 0x192`
891    LaunchApp2,
892    /// USB HID:
893    ///  - `AL Email Reader` `Consumer Page 0x18a`
894    LaunchMail,
895    /// USB HID:
896    ///  - `Reserved` `Keyboard Page 0xe8`
897    ///  - `Play/Pause` `Consumer Page 0xcd`
898    MediaPlayPause,
899    /// USB HID:
900    ///  - `AL Consumer Control Configuration` `Consumer Page 0x183`
901    MediaSelect,
902    /// USB HID:
903    ///  - `Reserved` `Keyboard Page 0xe9`
904    ///  - `Stop` `Consumer Page 0xb7`
905    MediaStop,
906    /// USB HID:
907    ///  - `Reserved` `Keyboard Page 0xeb`
908    ///  - `Scan Next Track` `Consumer Page 0xb5`
909    MediaTrackNext,
910    /// USB HID:
911    ///  - `Reserved` `Keyboard Page 0xea`
912    ///  - `Scan Previous Track` `Consumer Page 0xb6`
913    MediaTrackPrevious,
914    /// This key is placed in the function section on some Apple keyboards,
915    /// replacing the `Eject` key.
916    ///
917    /// USB HID:
918    ///  - `Keyboard Power` `Keyboard Page 0x66`
919    ///  - `Power` `Consumer Page 0x30`
920    Power,
921    /// USB HID:
922    ///  - `Reserved` `Keyboard Page 0xf8`
923    ///  - `Sleep` `Consumer Page 0x32`
924    ///  - `Sleep Mode` `Consumer Page 0x34`
925    Sleep,
926    /// USB HID:
927    ///  - `Keyboard Volume Down` `Keyboard Page 0x81`
928    ///  - `Reserved` `Keyboard Page 0xee`
929    ///  - `Volume Decrement` `Consumer Page 0xea`
930    AudioVolumeDown,
931    /// USB HID:
932    ///  - `Keyboard Mute` `Keyboard Page 0x7f`
933    ///  - `Reserved` `Keyboard Page 0xef`
934    ///  - `Mute` `Consumer Page 0xe2`
935    AudioVolumeMute,
936    /// USB HID:
937    ///  - `Keyboard Volume Up` `Keyboard Page 0x80`
938    ///  - `Reserved` `Keyboard Page 0xed`
939    ///  - `Volume Increment` `Consumer Page 0xe9`
940    AudioVolumeUp,
941    /// USB HID:
942    ///  - `System Wake Up` `Generic Desktop Page 0x83`
943    WakeUp,
944
945    /// Found on Sun’s USB keyboard.
946    ///
947    /// USB HID:
948    ///  - `Keyboard Again` `Keyboard Page 0x79`
949    Again,
950    /// Found on Sun’s USB keyboard.
951    ///
952    /// USB HID:
953    ///  - `Keyboard Copy` `Keyboard Page 0x7c`
954    ///  - `AC Copy` `Consumer Page 0x21b`
955    Copy,
956    /// Found on Sun’s USB keyboard.
957    ///
958    /// USB HID:
959    ///  - `Keyboard Cut` `Keyboard Page 0x7b`
960    ///  - `AC Cut` `Consumer Page 0x21c`
961    Cut,
962    /// Found on Sun’s USB keyboard.
963    ///
964    /// USB HID:
965    ///  - `Keyboard Find` `Keyboard Page 0x7e`
966    ///  - `Reserved` `Keyboard Page 0xf4`
967    ///  - `AC Find` `Consumer Page 0x21f`
968    Find,
969    /// Found on Sun’s USB keyboard.
970    ///
971    /// USB HID:
972    ///  - `Keyboard Execute` `Keyboard Page 0x74`
973    ///  - `AC Open` `Consumer Page 0x202`
974    Open,
975    /// Found on Sun’s USB keyboard.
976    ///
977    /// USB HID:
978    ///  - `Keyboard Paste` `Keyboard Page 0x7d`
979    ///  - `AC Paste` `Consumer Page 0x21d`
980    Paste,
981    /// Found on Sun’s USB keyboard.
982    ///
983    /// USB HID:
984    ///  - `Keyboard Menu` `Keyboard Page 0x76`
985    ///  - `AC Properties` `Consumer Page 0x209`
986    Props,
987    /// Found on Sun’s USB keyboard.
988    ///
989    /// USB HID:
990    ///  - `Keyboard Select` `Keyboard Page 0x77`
991    Select,
992    /// Found on Sun’s USB keyboard.
993    ///
994    /// USB HID:
995    ///  - `Keyboard Undo` `Keyboard Page 0x7a`
996    ///  - `AC Undo` `Consumer Page 0x21a`
997    Undo,
998
999    /// USB HID:
1000    ///  - `Button 1 (primary/trigger)` `Button Page 0x1`
1001    Gamepad0,
1002    /// USB HID:
1003    ///  - `Button 2 (secondary)` `Button Page 0x2`
1004    Gamepad1,
1005    /// USB HID:
1006    ///  - `Button 3 (tertiary)` `Button Page 0x3`
1007    Gamepad2,
1008    /// USB HID:
1009    ///  - `Button 4` `Button Page 0x4`
1010    Gamepad3,
1011    /// USB HID:
1012    ///  - `Button 5` `Button Page 0x5`
1013    Gamepad4,
1014    /// USB HID:
1015    ///  - `Button 6` `Button Page 0x6`
1016    Gamepad5,
1017    /// USB HID:
1018    ///  - `Button 7` `Button Page 0x7`
1019    Gamepad6,
1020    /// USB HID:
1021    ///  - `Button 8` `Button Page 0x8`
1022    Gamepad7,
1023    /// USB HID:
1024    ///  - `Button 9` `Button Page 0x9`
1025    Gamepad8,
1026    /// USB HID:
1027    ///  - `Button 10` `Button Page 0xa`
1028    Gamepad9,
1029    /// USB HID:
1030    ///  - `Button 11` `Button Page 0xb`
1031    Gamepad10,
1032    /// USB HID:
1033    ///  - `Button 12` `Button Page 0xc`
1034    Gamepad11,
1035    /// USB HID:
1036    ///  - `Button 13` `Button Page 0xd`
1037    Gamepad12,
1038    /// USB HID:
1039    ///  - `Button 14` `Button Page 0xe`
1040    Gamepad13,
1041    /// USB HID:
1042    ///  - `Button 15` `Button Page 0xf`
1043    Gamepad14,
1044    /// USB HID:
1045    ///  - `Button 16` `Button Page 0x10`
1046    Gamepad15,
1047    /// USB HID:
1048    ///  - `Button 17` `Button Page 0x11`
1049    Gamepad16,
1050    /// USB HID:
1051    ///  - `Button 18` `Button Page 0x12`
1052    Gamepad17,
1053    /// USB HID:
1054    ///  - `Button 19` `Button Page 0x13`
1055    Gamepad18,
1056    /// USB HID:
1057    ///  - `Button 20` `Button Page 0x14`
1058    Gamepad19,
1059
1060    /// Non-standard code value supported by Chromium.
1061    ///
1062    /// USB HID:
1063    ///  - `Display Brightness Decrement` `Consumer Page 0x70`
1064    BrightnessDown,
1065    /// Non-standard code value supported by Chromium.
1066    ///
1067    /// USB HID:
1068    ///  - `Display Brightness Increment` `Consumer Page 0x6f`
1069    BrightnessUp,
1070    /// Non-standard code value supported by Chromium.
1071    ///
1072    /// USB HID:
1073    ///  - `System Display Toggle Int/Ext Mode` `Generic Desktop Page 0xb5`
1074    DisplayToggleIntExt,
1075    /// Non-standard code value supported by Chromium.
1076    ///
1077    /// USB HID:
1078    ///  - `AC Next Keyboard Layout Select` `Consumer Page 0x29d`
1079    KeyboardLayoutSelect,
1080    /// Non-standard code value supported by Chromium.
1081    ///
1082    /// USB HID:
1083    ///  - `AL Context-aware Desktop Assistant` `Consumer Page 0x1cb`
1084    LaunchAssistant,
1085    /// Non-standard code value supported by Chromium.
1086    ///
1087    /// USB HID:
1088    ///  - `AL Control Panel` `Consumer Page 0x19f`
1089    LaunchControlPanel,
1090    /// Non-standard code value supported by Chromium.
1091    ///
1092    /// USB HID:
1093    ///  - `AL Screen Saver` `Consumer Page 0x1b1`
1094    LaunchScreenSaver,
1095    /// Non-standard code value supported by Chromium.
1096    ///
1097    /// USB HID:
1098    ///  - `AC Forward Msg` `Consumer Page 0x28b`
1099    MailForward,
1100    /// Non-standard code value supported by Chromium.
1101    ///
1102    /// USB HID:
1103    ///  - `AC Reply` `Consumer Page 0x289`
1104    MailReply,
1105    /// Non-standard code value supported by Chromium.
1106    ///
1107    /// USB HID:
1108    ///  - `AC Send` `Consumer Page 0x28c`
1109    MailSend,
1110    /// Non-standard code value supported by Chromium.
1111    ///
1112    /// USB HID:
1113    ///  - `Fast Forward` `Consumer Page 0xb3`
1114    MediaFastForward,
1115    /// Non-standard code value supported by Chromium.
1116    ///
1117    /// USB HID:
1118    ///  - `Play` `Consumer Page 0xb0`
1119    MediaPlay,
1120    /// Non-standard code value supported by Chromium.
1121    ///
1122    /// USB HID:
1123    ///  - `Pause` `Consumer Page 0xb1`
1124    MediaPause,
1125    /// Non-standard code value supported by Chromium.
1126    ///
1127    /// USB HID:
1128    ///  - `Record` `Consumer Page 0xb2`
1129    MediaRecord,
1130    /// Non-standard code value supported by Chromium.
1131    ///
1132    /// USB HID:
1133    ///  - `Rewind` `Consumer Page 0xb4`
1134    MediaRewind,
1135    /// Non-standard code value supported by Chromium.
1136    ///
1137    /// USB HID:
1138    ///  - `Phone Mute` `Telephony Device Page 0x2f`
1139    MicrophoneMuteToggle,
1140    /// Non-standard code value supported by Chromium.
1141    ///
1142    /// USB HID:
1143    ///  - `Privacy Screen Toggle` `Consumer Page 0x2d0`
1144    PrivacyScreenToggle,
1145    /// Non-standard code value supported by Chromium.
1146    ///
1147    /// USB HID:
1148    ///  - `AL Select Task/Application` `Consumer Page 0x1a2`
1149    SelectTask,
1150    /// Non-standard code value supported by Chromium.
1151    ///
1152    /// USB HID:
1153    ///  - `AC Desktop Show All Windows` `Consumer Page 0x29f`
1154    ShowAllWindows,
1155    /// Non-standard code value supported by Chromium.
1156    ///
1157    /// USB HID:
1158    ///  - `AC View Toggle` `Consumer Page 0x232`
1159    ZoomToggle,
1160}
1161
1162impl fmt::Debug for KeyCode {
1163    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1164        f.write_str(self.name())
1165    }
1166}
1167
1168impl Serialize for KeyCode {
1169    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1170    where
1171        S: serde::Serializer,
1172    {
1173        serializer.serialize_str(self.name())
1174    }
1175}
1176
1177impl<'de> Deserialize<'de> for KeyCode {
1178    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1179    where
1180        D: serde::Deserializer<'de>,
1181    {
1182        deserializer.deserialize_str(KeyCodeVisitor)
1183    }
1184}
1185
1186struct KeyCodeVisitor;
1187
1188impl serde::de::Visitor<'_> for KeyCodeVisitor {
1189    type Value = KeyCode;
1190
1191    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1192        formatter.write_str("a valid key code")
1193    }
1194
1195    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
1196    where
1197        E: serde::de::Error,
1198    {
1199        KeyCode::from_str(v).map_err(|()| serde::de::Error::custom("invalid key code"))
1200    }
1201}
1202
1203/// Every [`KeyCode`] is grouped into one of these classes.
1204#[derive(Debug, Eq, PartialEq, Hash, Copy, Clone)]
1205pub enum KeyCodeClass {
1206    /// The *writing system keys* are those that change meaning (i.e., they
1207    /// produce different key values) based on the current locale and keyboard
1208    /// layout.
1209    WritingSystem,
1210    /// The *functional keys* (not to be confused with the [function
1211    /// keys](KeyCodeClass::Function) described later) are those keys in the
1212    /// alphanumeric section that provide general editing functions that are
1213    /// common to all locales (like `Shift`, `Tab`, `Enter` and `Backspace`).
1214    /// With a few exceptions, these keys do not change meaning based on the
1215    /// current keyboard layout.
1216    Functional,
1217    /// The *control pad* section of the keyboard is the set of (usually 6) keys
1218    /// that perform navigating and editing operations, for example, `Home`,
1219    /// `PageUp` and `Insert`.
1220    ControlPad,
1221    /// The *arrow pad* contains the 4 arrow keys. The keys are commonly
1222    /// arranged in an "upside-down T" configuration.
1223    ArrowPad,
1224    /// The *numpad section* is the set of keys on the keyboard arranged in a
1225    /// grid like a calculator or mobile phone. This section contains numeric
1226    /// and mathematical operator keys. Often this section will contain a
1227    /// `NumLock` key which causes the keys to switch between the standard
1228    /// numeric functions and mimicking the keys of the [control
1229    /// pad](KeyCodeClass::ControlPad) and arrow pad. Laptop computers and
1230    /// compact keyboards will commonly omit these keys to save space.
1231    Numpad,
1232    /// The *function section* runs along the top of the keyboard (above the
1233    /// alphanumeric section) and contains the function keys and a few
1234    /// additional special keys (for example, `Esc` and `Print Screen`).
1235    Function,
1236    /// *Media keys* are extra keys added to a keyboard that provide media related
1237    /// functionality like play, pause or volume control. These keys do not have
1238    /// a standard location on the keyboard so keyboards from different
1239    /// manufacturers are likely to have a different arrangement of keys or a
1240    /// completely different sets of keys.
1241    Media,
1242    /// These keys are not found on modern standard keyboards. They are listed
1243    /// here for reference purposes.
1244    Legacy,
1245    /// These buttons are found on gamepads.
1246    Gamepad,
1247    /// These keys are supported by some browsers.
1248    NonStandard,
1249}
1250
1251impl KeyCodeClass {
1252    /// Returns the name of the key code.
1253    pub const fn name(self) -> &'static str {
1254        match self {
1255            Self::WritingSystem => "WritingSystem",
1256            Self::Functional => "Functional",
1257            Self::ControlPad => "ControlPad",
1258            Self::ArrowPad => "ArrowPad",
1259            Self::Numpad => "Numpad",
1260            Self::Function => "Function",
1261            Self::Media => "Media",
1262            Self::Legacy => "Legacy",
1263            Self::Gamepad => "Gamepad",
1264            Self::NonStandard => "NonStandard",
1265        }
1266    }
1267}
1268
1269impl FromStr for KeyCodeClass {
1270    type Err = ();
1271    fn from_str(s: &str) -> Result<Self, Self::Err> {
1272        Ok(match s {
1273            "WritingSystem" => Self::WritingSystem,
1274            "Functional" => Self::Functional,
1275            "ControlPad" => Self::ControlPad,
1276            "ArrowPad" => Self::ArrowPad,
1277            "Numpad" => Self::Numpad,
1278            "Function" => Self::Function,
1279            "Media" => Self::Media,
1280            "Legacy" => Self::Legacy,
1281            "Gamepad" => Self::Gamepad,
1282            "NonStandard" => Self::NonStandard,
1283            _ => return Err(()),
1284        })
1285    }
1286}
1287
1288impl Serialize for KeyCodeClass {
1289    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1290    where
1291        S: serde::Serializer,
1292    {
1293        serializer.serialize_str(self.name())
1294    }
1295}
1296
1297impl<'de> Deserialize<'de> for KeyCodeClass {
1298    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1299    where
1300        D: serde::Deserializer<'de>,
1301    {
1302        deserializer.deserialize_str(KeyCodeClassVisitor)
1303    }
1304}
1305
1306struct KeyCodeClassVisitor;
1307
1308impl serde::de::Visitor<'_> for KeyCodeClassVisitor {
1309    type Value = KeyCodeClass;
1310
1311    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1312        formatter.write_str("a valid key code class")
1313    }
1314
1315    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
1316    where
1317        E: serde::de::Error,
1318    {
1319        KeyCodeClass::from_str(v).map_err(|()| serde::de::Error::custom("invalid key code class"))
1320    }
1321}
1322
1323impl KeyCode {
1324    /// Combines the key code with the modifiers to form a [`Hotkey`].
1325    pub fn with_modifiers(self, modifiers: Modifiers) -> Hotkey {
1326        Hotkey {
1327            key_code: self,
1328            modifiers,
1329        }
1330    }
1331
1332    /// Returns the name of the key code.
1333    pub const fn name(self) -> &'static str {
1334        match self {
1335            Self::Backquote => "Backquote",
1336            Self::Backslash => "Backslash",
1337            Self::BracketLeft => "BracketLeft",
1338            Self::BracketRight => "BracketRight",
1339            Self::Comma => "Comma",
1340            Self::Digit0 => "Digit0",
1341            Self::Digit1 => "Digit1",
1342            Self::Digit2 => "Digit2",
1343            Self::Digit3 => "Digit3",
1344            Self::Digit4 => "Digit4",
1345            Self::Digit5 => "Digit5",
1346            Self::Digit6 => "Digit6",
1347            Self::Digit7 => "Digit7",
1348            Self::Digit8 => "Digit8",
1349            Self::Digit9 => "Digit9",
1350            Self::Equal => "Equal",
1351            Self::IntlBackslash => "IntlBackslash",
1352            Self::IntlRo => "IntlRo",
1353            Self::IntlYen => "IntlYen",
1354            Self::KeyA => "KeyA",
1355            Self::KeyB => "KeyB",
1356            Self::KeyC => "KeyC",
1357            Self::KeyD => "KeyD",
1358            Self::KeyE => "KeyE",
1359            Self::KeyF => "KeyF",
1360            Self::KeyG => "KeyG",
1361            Self::KeyH => "KeyH",
1362            Self::KeyI => "KeyI",
1363            Self::KeyJ => "KeyJ",
1364            Self::KeyK => "KeyK",
1365            Self::KeyL => "KeyL",
1366            Self::KeyM => "KeyM",
1367            Self::KeyN => "KeyN",
1368            Self::KeyO => "KeyO",
1369            Self::KeyP => "KeyP",
1370            Self::KeyQ => "KeyQ",
1371            Self::KeyR => "KeyR",
1372            Self::KeyS => "KeyS",
1373            Self::KeyT => "KeyT",
1374            Self::KeyU => "KeyU",
1375            Self::KeyV => "KeyV",
1376            Self::KeyW => "KeyW",
1377            Self::KeyX => "KeyX",
1378            Self::KeyY => "KeyY",
1379            Self::KeyZ => "KeyZ",
1380            Self::Minus => "Minus",
1381            Self::Period => "Period",
1382            Self::Quote => "Quote",
1383            Self::Semicolon => "Semicolon",
1384            Self::Slash => "Slash",
1385            Self::AltLeft => "AltLeft",
1386            Self::AltRight => "AltRight",
1387            Self::Backspace => "Backspace",
1388            Self::CapsLock => "CapsLock",
1389            Self::ContextMenu => "ContextMenu",
1390            Self::ControlLeft => "ControlLeft",
1391            Self::ControlRight => "ControlRight",
1392            Self::Enter => "Enter",
1393            Self::MetaLeft => "MetaLeft",
1394            Self::MetaRight => "MetaRight",
1395            Self::ShiftLeft => "ShiftLeft",
1396            Self::ShiftRight => "ShiftRight",
1397            Self::Space => "Space",
1398            Self::Tab => "Tab",
1399            Self::Convert => "Convert",
1400            Self::KanaMode => "KanaMode",
1401            Self::Lang1 => "Lang1",
1402            Self::Lang2 => "Lang2",
1403            Self::Lang3 => "Lang3",
1404            Self::Lang4 => "Lang4",
1405            Self::Lang5 => "Lang5",
1406            Self::NonConvert => "NonConvert",
1407            Self::Delete => "Delete",
1408            Self::End => "End",
1409            Self::Help => "Help",
1410            Self::Home => "Home",
1411            Self::Insert => "Insert",
1412            Self::PageDown => "PageDown",
1413            Self::PageUp => "PageUp",
1414            Self::ArrowDown => "ArrowDown",
1415            Self::ArrowLeft => "ArrowLeft",
1416            Self::ArrowRight => "ArrowRight",
1417            Self::ArrowUp => "ArrowUp",
1418            Self::NumLock => "NumLock",
1419            Self::Numpad0 => "Numpad0",
1420            Self::Numpad1 => "Numpad1",
1421            Self::Numpad2 => "Numpad2",
1422            Self::Numpad3 => "Numpad3",
1423            Self::Numpad4 => "Numpad4",
1424            Self::Numpad5 => "Numpad5",
1425            Self::Numpad6 => "Numpad6",
1426            Self::Numpad7 => "Numpad7",
1427            Self::Numpad8 => "Numpad8",
1428            Self::Numpad9 => "Numpad9",
1429            Self::NumpadAdd => "NumpadAdd",
1430            Self::NumpadBackspace => "NumpadBackspace",
1431            Self::NumpadClear => "NumpadClear",
1432            Self::NumpadClearEntry => "NumpadClearEntry",
1433            Self::NumpadComma => "NumpadComma",
1434            Self::NumpadDecimal => "NumpadDecimal",
1435            Self::NumpadDivide => "NumpadDivide",
1436            Self::NumpadEnter => "NumpadEnter",
1437            Self::NumpadEqual => "NumpadEqual",
1438            Self::NumpadHash => "NumpadHash",
1439            Self::NumpadMemoryAdd => "NumpadMemoryAdd",
1440            Self::NumpadMemoryClear => "NumpadMemoryClear",
1441            Self::NumpadMemoryRecall => "NumpadMemoryRecall",
1442            Self::NumpadMemoryStore => "NumpadMemoryStore",
1443            Self::NumpadMemorySubtract => "NumpadMemorySubtract",
1444            Self::NumpadMultiply => "NumpadMultiply",
1445            Self::NumpadParenLeft => "NumpadParenLeft",
1446            Self::NumpadParenRight => "NumpadParenRight",
1447            Self::NumpadStar => "NumpadStar",
1448            Self::NumpadSubtract => "NumpadSubtract",
1449            Self::Escape => "Escape",
1450            Self::F1 => "F1",
1451            Self::F2 => "F2",
1452            Self::F3 => "F3",
1453            Self::F4 => "F4",
1454            Self::F5 => "F5",
1455            Self::F6 => "F6",
1456            Self::F7 => "F7",
1457            Self::F8 => "F8",
1458            Self::F9 => "F9",
1459            Self::F10 => "F10",
1460            Self::F11 => "F11",
1461            Self::F12 => "F12",
1462            Self::F13 => "F13",
1463            Self::F14 => "F14",
1464            Self::F15 => "F15",
1465            Self::F16 => "F16",
1466            Self::F17 => "F17",
1467            Self::F18 => "F18",
1468            Self::F19 => "F19",
1469            Self::F20 => "F20",
1470            Self::F21 => "F21",
1471            Self::F22 => "F22",
1472            Self::F23 => "F23",
1473            Self::F24 => "F24",
1474            Self::Fn => "Fn",
1475            Self::FnLock => "FnLock",
1476            Self::PrintScreen => "PrintScreen",
1477            Self::ScrollLock => "ScrollLock",
1478            Self::Pause => "Pause",
1479            Self::BrowserBack => "BrowserBack",
1480            Self::BrowserFavorites => "BrowserFavorites",
1481            Self::BrowserForward => "BrowserForward",
1482            Self::BrowserHome => "BrowserHome",
1483            Self::BrowserRefresh => "BrowserRefresh",
1484            Self::BrowserSearch => "BrowserSearch",
1485            Self::BrowserStop => "BrowserStop",
1486            Self::Eject => "Eject",
1487            Self::LaunchApp1 => "LaunchApp1",
1488            Self::LaunchApp2 => "LaunchApp2",
1489            Self::LaunchMail => "LaunchMail",
1490            Self::MediaPlayPause => "MediaPlayPause",
1491            Self::MediaSelect => "MediaSelect",
1492            Self::MediaStop => "MediaStop",
1493            Self::MediaTrackNext => "MediaTrackNext",
1494            Self::MediaTrackPrevious => "MediaTrackPrevious",
1495            Self::Power => "Power",
1496            Self::Sleep => "Sleep",
1497            Self::AudioVolumeDown => "AudioVolumeDown",
1498            Self::AudioVolumeMute => "AudioVolumeMute",
1499            Self::AudioVolumeUp => "AudioVolumeUp",
1500            Self::WakeUp => "WakeUp",
1501            Self::Again => "Again",
1502            Self::Copy => "Copy",
1503            Self::Cut => "Cut",
1504            Self::Find => "Find",
1505            Self::Open => "Open",
1506            Self::Paste => "Paste",
1507            Self::Props => "Props",
1508            Self::Select => "Select",
1509            Self::Undo => "Undo",
1510            Self::Gamepad0 => "Gamepad0",
1511            Self::Gamepad1 => "Gamepad1",
1512            Self::Gamepad2 => "Gamepad2",
1513            Self::Gamepad3 => "Gamepad3",
1514            Self::Gamepad4 => "Gamepad4",
1515            Self::Gamepad5 => "Gamepad5",
1516            Self::Gamepad6 => "Gamepad6",
1517            Self::Gamepad7 => "Gamepad7",
1518            Self::Gamepad8 => "Gamepad8",
1519            Self::Gamepad9 => "Gamepad9",
1520            Self::Gamepad10 => "Gamepad10",
1521            Self::Gamepad11 => "Gamepad11",
1522            Self::Gamepad12 => "Gamepad12",
1523            Self::Gamepad13 => "Gamepad13",
1524            Self::Gamepad14 => "Gamepad14",
1525            Self::Gamepad15 => "Gamepad15",
1526            Self::Gamepad16 => "Gamepad16",
1527            Self::Gamepad17 => "Gamepad17",
1528            Self::Gamepad18 => "Gamepad18",
1529            Self::Gamepad19 => "Gamepad19",
1530            Self::BrightnessDown => "BrightnessDown",
1531            Self::BrightnessUp => "BrightnessUp",
1532            Self::DisplayToggleIntExt => "DisplayToggleIntExt",
1533            Self::KeyboardLayoutSelect => "KeyboardLayoutSelect",
1534            Self::LaunchAssistant => "LaunchAssistant",
1535            Self::LaunchControlPanel => "LaunchControlPanel",
1536            Self::LaunchScreenSaver => "LaunchScreenSaver",
1537            Self::MailForward => "MailForward",
1538            Self::MailReply => "MailReply",
1539            Self::MailSend => "MailSend",
1540            Self::MediaFastForward => "MediaFastForward",
1541            Self::MediaPlay => "MediaPlay",
1542            Self::MediaPause => "MediaPause",
1543            Self::MediaRecord => "MediaRecord",
1544            Self::MediaRewind => "MediaRewind",
1545            Self::MicrophoneMuteToggle => "MicrophoneMuteToggle",
1546            Self::PrivacyScreenToggle => "PrivacyScreenToggle",
1547            Self::SelectTask => "SelectTask",
1548            Self::ShowAllWindows => "ShowAllWindows",
1549            Self::ZoomToggle => "ZoomToggle",
1550        }
1551    }
1552
1553    /// Resolve the KeyCode according to the standard US layout.
1554    pub const fn resolve_en_us(self) -> &'static str {
1555        use self::KeyCode::*;
1556        match self {
1557            Backquote => "`",
1558            Backslash => r"\",
1559            BracketLeft => "[",
1560            BracketRight => "]",
1561            Comma => ",",
1562            Digit0 => "0",
1563            Digit1 => "1",
1564            Digit2 => "2",
1565            Digit3 => "3",
1566            Digit4 => "4",
1567            Digit5 => "5",
1568            Digit6 => "6",
1569            Digit7 => "7",
1570            Digit8 => "8",
1571            Digit9 => "9",
1572            Equal => "=",
1573            IntlBackslash => r"International Backslash",
1574            IntlRo => "ろ",
1575            IntlYen => "¥",
1576            KeyA => "A",
1577            KeyB => "B",
1578            KeyC => "C",
1579            KeyD => "D",
1580            KeyE => "E",
1581            KeyF => "F",
1582            KeyG => "G",
1583            KeyH => "H",
1584            KeyI => "I",
1585            KeyJ => "J",
1586            KeyK => "K",
1587            KeyL => "L",
1588            KeyM => "M",
1589            KeyN => "N",
1590            KeyO => "O",
1591            KeyP => "P",
1592            KeyQ => "Q",
1593            KeyR => "R",
1594            KeyS => "S",
1595            KeyT => "T",
1596            KeyU => "U",
1597            KeyV => "V",
1598            KeyW => "W",
1599            KeyX => "X",
1600            KeyY => "Y",
1601            KeyZ => "Z",
1602            Minus => "-",
1603            Period => ".",
1604            Quote => "'",
1605            Semicolon => ";",
1606            Slash => "/",
1607            AltLeft => "Alt Left",
1608            AltRight => "Alt Right",
1609            Backspace => "⌫",
1610            CapsLock => "⇪",
1611            ContextMenu => "Context Menu",
1612            ControlLeft => "Control Left",
1613            ControlRight => "Control Right",
1614            Enter => "↵",
1615            MetaLeft => "⌘ Left",
1616            MetaRight => "⌘ Right",
1617            ShiftLeft => "⇧ Left",
1618            ShiftRight => "⇧ Right",
1619            Space => "Space",
1620            Tab => "⇥",
1621            Convert => "変換",
1622            KanaMode => "カタカナ/ひらがな/ローマ字",
1623            Lang1 => "한/영 かな",
1624            Lang2 => "한자 英数",
1625            Lang3 => "カタカナ",
1626            Lang4 => "ひらがな",
1627            Lang5 => "半角/全角/漢字",
1628            NonConvert => "無変換",
1629            Delete => "Delete",
1630            End => "End",
1631            Help => "Help",
1632            Home => "Home",
1633            Insert => "Insert",
1634            PageDown => "Page Down",
1635            PageUp => "Page Up",
1636            ArrowDown => "↓",
1637            ArrowLeft => "←",
1638            ArrowRight => "→",
1639            ArrowUp => "↑",
1640            NumLock => "Num Lock",
1641            Numpad0 => "Numpad 0",
1642            Numpad1 => "Numpad 1",
1643            Numpad2 => "Numpad 2",
1644            Numpad3 => "Numpad 3",
1645            Numpad4 => "Numpad 4",
1646            Numpad5 => "Numpad 5",
1647            Numpad6 => "Numpad 6",
1648            Numpad7 => "Numpad 7",
1649            Numpad8 => "Numpad 8",
1650            Numpad9 => "Numpad 9",
1651            NumpadAdd => "Numpad +",
1652            NumpadBackspace => "Numpad ⌫",
1653            NumpadClear => "Numpad C",
1654            NumpadClearEntry => "Numpad CE",
1655            NumpadComma => "Numpad ,",
1656            NumpadDecimal => "Numpad .",
1657            NumpadDivide => "Numpad /",
1658            NumpadEnter => "Numpad ↵",
1659            NumpadEqual => "Numpad =",
1660            NumpadHash => "Numpad #",
1661            NumpadMemoryAdd => "Numpad M+",
1662            NumpadMemoryClear => "Numpad MC",
1663            NumpadMemoryRecall => "Numpad MR",
1664            NumpadMemoryStore => "Numpad MS",
1665            NumpadMemorySubtract => "Numpad M-",
1666            NumpadMultiply => "Numpad *",
1667            NumpadParenLeft => "Numpad (",
1668            NumpadParenRight => "Numpad )",
1669            NumpadStar => "Numpad * (Star)",
1670            NumpadSubtract => "Numpad -",
1671            Escape => "Escape",
1672            F1 => "F1",
1673            F2 => "F2",
1674            F3 => "F3",
1675            F4 => "F4",
1676            F5 => "F5",
1677            F6 => "F6",
1678            F7 => "F7",
1679            F8 => "F8",
1680            F9 => "F9",
1681            F10 => "F10",
1682            F11 => "F11",
1683            F12 => "F12",
1684            F13 => "F13",
1685            F14 => "F14",
1686            F15 => "F15",
1687            F16 => "F16",
1688            F17 => "F17",
1689            F18 => "F18",
1690            F19 => "F19",
1691            F20 => "F20",
1692            F21 => "F21",
1693            F22 => "F22",
1694            F23 => "F23",
1695            F24 => "F24",
1696            Fn => "Fn",
1697            FnLock => "FnLock",
1698            PrintScreen => "Print Screen",
1699            ScrollLock => "Scroll Lock",
1700            Pause => "Pause Break",
1701            BrowserBack => "Browser ⏮",
1702            BrowserFavorites => "Browser Favorites",
1703            BrowserForward => "Browser ⏭",
1704            BrowserHome => "Browser 🏠",
1705            BrowserRefresh => "Browser Refresh",
1706            BrowserSearch => "Browser Search",
1707            BrowserStop => "Browser Stop",
1708            Eject => "⏏",
1709            LaunchApp1 => "Launch App 1",
1710            LaunchApp2 => "Launch App 2",
1711            LaunchMail => "Launch Mail",
1712            MediaPlayPause => "⏯",
1713            MediaSelect => "Media Select",
1714            MediaStop => "◼",
1715            MediaTrackNext => "⏭",
1716            MediaTrackPrevious => "⏮",
1717            Power => "Power",
1718            Sleep => "Sleep",
1719            AudioVolumeDown => "🔉",
1720            AudioVolumeMute => "🔇",
1721            AudioVolumeUp => "🔊",
1722            WakeUp => "Wake Up",
1723            Again => "Again",
1724            Copy => "Copy",
1725            Cut => "Cut",
1726            Find => "Find",
1727            Open => "Open",
1728            Paste => "Paste",
1729            Props => "Props",
1730            Select => "Select",
1731            Undo => "Undo",
1732            Gamepad0 => "Gamepad 0",
1733            Gamepad1 => "Gamepad 1",
1734            Gamepad2 => "Gamepad 2",
1735            Gamepad3 => "Gamepad 3",
1736            Gamepad4 => "Gamepad 4",
1737            Gamepad5 => "Gamepad 5",
1738            Gamepad6 => "Gamepad 6",
1739            Gamepad7 => "Gamepad 7",
1740            Gamepad8 => "Gamepad 8",
1741            Gamepad9 => "Gamepad 9",
1742            Gamepad10 => "Gamepad 10",
1743            Gamepad11 => "Gamepad 11",
1744            Gamepad12 => "Gamepad 12",
1745            Gamepad13 => "Gamepad 13",
1746            Gamepad14 => "Gamepad 14",
1747            Gamepad15 => "Gamepad 15",
1748            Gamepad16 => "Gamepad 16",
1749            Gamepad17 => "Gamepad 17",
1750            Gamepad18 => "Gamepad 18",
1751            Gamepad19 => "Gamepad 19",
1752            BrightnessDown => "Brightness Down",
1753            BrightnessUp => "Brightness Up",
1754            DisplayToggleIntExt => "Display Toggle Intern / Extern",
1755            KeyboardLayoutSelect => "Keyboard Layout Select",
1756            LaunchAssistant => "Launch Assistant",
1757            LaunchControlPanel => "Launch Control Panel",
1758            LaunchScreenSaver => "Launch Screen Saver",
1759            MailForward => "Mail Forward",
1760            MailReply => "Mail Reply",
1761            MailSend => "Mail Send",
1762            MediaFastForward => "⏩",
1763            MediaPause => "⏸",
1764            MediaPlay => "▶",
1765            MediaRecord => "⏺",
1766            MediaRewind => "⏪",
1767            MicrophoneMuteToggle => "Microphone Mute Toggle",
1768            PrivacyScreenToggle => "Privacy Screen Toggle",
1769            SelectTask => "Select Task",
1770            ShowAllWindows => "Show All Windows",
1771            ZoomToggle => "Zoom Toggle",
1772        }
1773    }
1774
1775    /// Classifies a key based on its grouping on the Keyboard.
1776    pub const fn classify(self) -> KeyCodeClass {
1777        use self::KeyCode::*;
1778        match self {
1779            // Writing System Keys
1780            Backquote | Backslash | BracketLeft | BracketRight | Comma | Digit0 | Digit1
1781            | Digit2 | Digit3 | Digit4 | Digit5 | Digit6 | Digit7 | Digit8 | Digit9 | Equal
1782            | IntlBackslash | IntlRo | IntlYen | KeyA | KeyB | KeyC | KeyD | KeyE | KeyF | KeyG
1783            | KeyH | KeyI | KeyJ | KeyK | KeyL | KeyM | KeyN | KeyO | KeyP | KeyQ | KeyR | KeyS
1784            | KeyT | KeyU | KeyV | KeyW | KeyX | KeyY | KeyZ | Minus | Period | Quote
1785            | Semicolon | Slash => KeyCodeClass::WritingSystem,
1786
1787            // Functional Keys
1788            AltLeft | AltRight | Backspace | CapsLock | ContextMenu | ControlLeft
1789            | ControlRight | Enter | MetaLeft | MetaRight | ShiftLeft | ShiftRight | Space
1790            | Tab | Convert | KanaMode | Lang1 | Lang2 | Lang3 | Lang4 | Lang5 | NonConvert => {
1791                KeyCodeClass::Functional
1792            }
1793
1794            // Control Pad Section
1795            Delete | End | Help | Home | Insert | PageDown | PageUp => KeyCodeClass::ControlPad,
1796
1797            // Arrow Pad Section
1798            ArrowDown | ArrowLeft | ArrowRight | ArrowUp => KeyCodeClass::ArrowPad,
1799
1800            // Numpad Section
1801            NumLock | Numpad0 | Numpad1 | Numpad2 | Numpad3 | Numpad4 | Numpad5 | Numpad6
1802            | Numpad7 | Numpad8 | Numpad9 | NumpadAdd | NumpadBackspace | NumpadClear
1803            | NumpadClearEntry | NumpadComma | NumpadDecimal | NumpadDivide | NumpadEnter
1804            | NumpadEqual | NumpadHash | NumpadMemoryAdd | NumpadMemoryClear
1805            | NumpadMemoryRecall | NumpadMemoryStore | NumpadMemorySubtract | NumpadMultiply
1806            | NumpadParenLeft | NumpadParenRight | NumpadStar | NumpadSubtract => {
1807                KeyCodeClass::Numpad
1808            }
1809
1810            // Function Section
1811            Escape | F1 | F2 | F3 | F4 | F5 | F6 | F7 | F8 | F9 | F10 | F11 | F12 | F13 | F14
1812            | F15 | F16 | F17 | F18 | F19 | F20 | F21 | F22 | F23 | F24 | Fn | FnLock
1813            | PrintScreen | ScrollLock | Pause => KeyCodeClass::Function,
1814
1815            // Media Keys
1816            BrowserBack | BrowserFavorites | BrowserForward | BrowserHome | BrowserRefresh
1817            | BrowserSearch | BrowserStop | Eject | LaunchApp1 | LaunchApp2 | LaunchMail
1818            | MediaPlayPause | MediaSelect | MediaStop | MediaTrackNext | MediaTrackPrevious
1819            | Power | Sleep | AudioVolumeDown | AudioVolumeMute | AudioVolumeUp | WakeUp => {
1820                KeyCodeClass::Media
1821            }
1822
1823            // Legacy, Non-Standard and Special Keys
1824            Again | Copy | Cut | Find | Open | Paste | Props | Select | Undo => {
1825                KeyCodeClass::Legacy
1826            }
1827
1828            // Gamepad Keys
1829            Gamepad0 | Gamepad1 | Gamepad2 | Gamepad3 | Gamepad4 | Gamepad5 | Gamepad6
1830            | Gamepad7 | Gamepad8 | Gamepad9 | Gamepad10 | Gamepad11 | Gamepad12 | Gamepad13
1831            | Gamepad14 | Gamepad15 | Gamepad16 | Gamepad17 | Gamepad18 | Gamepad19 => {
1832                KeyCodeClass::Gamepad
1833            }
1834
1835            // Browser specific Keys
1836            BrightnessDown | BrightnessUp | DisplayToggleIntExt | KeyboardLayoutSelect
1837            | LaunchAssistant | LaunchControlPanel | LaunchScreenSaver | MailForward
1838            | MailReply | MailSend | MediaFastForward | MediaPause | MediaPlay | MediaRecord
1839            | MediaRewind | MicrophoneMuteToggle | PrivacyScreenToggle | SelectTask
1840            | ShowAllWindows | ZoomToggle => KeyCodeClass::NonStandard,
1841        }
1842    }
1843
1844    /// Resolves the key according to the current keyboard layout.
1845    pub fn resolve(self, hook: &Hook) -> Cow<'static, str> {
1846        let class = self.classify();
1847        if class == KeyCodeClass::WritingSystem {
1848            if let Some(resolved) = hook.0.try_resolve(self) {
1849                let uppercase = if resolved != "ß" {
1850                    resolved.to_uppercase()
1851                } else {
1852                    resolved
1853                };
1854                return uppercase.into();
1855            }
1856        }
1857        self.resolve_en_us().into()
1858    }
1859}
1860
1861impl FromStr for KeyCode {
1862    type Err = ();
1863    fn from_str(s: &str) -> Result<Self, Self::Err> {
1864        use self::KeyCode::*;
1865        Ok(match s {
1866            // Writing System Keys
1867            "Backquote" => Backquote,
1868            "Backslash" => Backslash,
1869            "BracketLeft" => BracketLeft,
1870            "BracketRight" => BracketRight,
1871            "Comma" => Comma,
1872            "Digit0" | "0" => Digit0,
1873            "Digit1" | "1" => Digit1,
1874            "Digit2" | "2" => Digit2,
1875            "Digit3" | "3" => Digit3,
1876            "Digit4" | "4" => Digit4,
1877            "Digit5" | "5" => Digit5,
1878            "Digit6" | "6" => Digit6,
1879            "Digit7" | "7" => Digit7,
1880            "Digit8" | "8" => Digit8,
1881            "Digit9" | "9" => Digit9,
1882            "Equal" => Equal,
1883            "IntlBackslash" => IntlBackslash,
1884            "IntlRo" => IntlRo,
1885            "IntlYen" => IntlYen,
1886            "KeyA" | "A" => KeyA,
1887            "KeyB" | "B" => KeyB,
1888            "KeyC" | "C" => KeyC,
1889            "KeyD" | "D" => KeyD,
1890            "KeyE" | "E" => KeyE,
1891            "KeyF" | "F" => KeyF,
1892            "KeyG" | "G" => KeyG,
1893            "KeyH" | "H" => KeyH,
1894            "KeyI" | "I" => KeyI,
1895            "KeyJ" | "J" => KeyJ,
1896            "KeyK" | "K" => KeyK,
1897            "KeyL" | "L" => KeyL,
1898            "KeyM" | "M" => KeyM,
1899            "KeyN" | "N" => KeyN,
1900            "KeyO" | "O" => KeyO,
1901            "KeyP" | "P" => KeyP,
1902            "KeyQ" | "Q" => KeyQ,
1903            "KeyR" | "R" => KeyR,
1904            "KeyS" | "S" => KeyS,
1905            "KeyT" | "T" => KeyT,
1906            "KeyU" | "U" => KeyU,
1907            "KeyV" | "V" => KeyV,
1908            "KeyW" | "W" => KeyW,
1909            "KeyX" | "X" => KeyX,
1910            "KeyY" | "Y" => KeyY,
1911            "KeyZ" | "Z" => KeyZ,
1912            "Minus" => Minus,
1913            "Period" => Period,
1914            "Quote" => Quote,
1915            "Semicolon" => Semicolon,
1916            "Slash" => Slash,
1917
1918            // Functional Keys
1919            "AltLeft" => AltLeft,
1920            "AltRight" => AltRight,
1921            "Backspace" => Backspace,
1922            "CapsLock" => CapsLock,
1923            "ContextMenu" => ContextMenu,
1924            "ControlLeft" => ControlLeft,
1925            "ControlRight" => ControlRight,
1926            "Enter" => Enter,
1927            // OS is used instead of Meta in all Firefox versions, Chrome <52
1928            // and all Safari GTK and WPE versions.
1929            // Firefox Tracking Issue: https://bugzilla.mozilla.org/show_bug.cgi?id=1595863
1930            "MetaLeft" | "OSLeft" => MetaLeft,
1931            "MetaRight" | "OSRight" => MetaRight,
1932            "ShiftLeft" => ShiftLeft,
1933            "ShiftRight" => ShiftRight,
1934            "Space" => Space,
1935            "Tab" => Tab,
1936
1937            // Functional Keys found on Japanese and Korean keyboards
1938            "Convert" => Convert,
1939            "KanaMode" => KanaMode,
1940            "Lang1" => Lang1, // MDN claims Chrome uses `HangulMode` but it's not true
1941            "Lang2" => Lang2, // MDN claims Chrome uses `Hanja` but it's not true
1942            "Lang3" => Lang3,
1943            "Lang4" => Lang4,
1944            "Lang5" => Lang5,
1945            "NonConvert" => NonConvert,
1946
1947            // Control Pad Section
1948            "Delete" => Delete,
1949            "End" => End,
1950            "Help" => Help,
1951            "Home" => Home,
1952            "Insert" => Insert,
1953            "PageDown" => PageDown,
1954            "PageUp" => PageUp,
1955
1956            // Arrow Pad Section
1957            "ArrowDown" => ArrowDown,
1958            "ArrowLeft" => ArrowLeft,
1959            "ArrowRight" => ArrowRight,
1960            "ArrowUp" => ArrowUp,
1961
1962            // Numpad Section
1963            "NumLock" => NumLock,
1964            "Numpad0" => Numpad0,
1965            "Numpad1" => Numpad1,
1966            "Numpad2" => Numpad2,
1967            "Numpad3" => Numpad3,
1968            "Numpad4" => Numpad4,
1969            "Numpad5" => Numpad5,
1970            "Numpad6" => Numpad6,
1971            "Numpad7" => Numpad7,
1972            "Numpad8" => Numpad8,
1973            "Numpad9" => Numpad9,
1974            "NumpadAdd" => NumpadAdd,
1975            "NumpadBackspace" => NumpadBackspace, // Not exposed by any OS.
1976            "NumpadClear" => NumpadClear,         // Not exposed by any OS.
1977            "NumpadClearEntry" => NumpadClearEntry, // Not exposed by any OS.
1978            "NumpadComma" => NumpadComma,
1979            "NumpadDecimal" => NumpadDecimal,
1980            "NumpadDivide" => NumpadDivide,
1981            "NumpadEnter" => NumpadEnter,
1982            "NumpadEqual" => NumpadEqual,
1983            "NumpadHash" => NumpadHash, // Not exposed by any OS.
1984            "NumpadMemoryAdd" => NumpadMemoryAdd, // Not exposed by any OS.
1985            "NumpadMemoryClear" => NumpadMemoryClear, // Not exposed by any OS.
1986            "NumpadMemoryRecall" => NumpadMemoryRecall, // Not exposed by any OS.
1987            "NumpadMemoryStore" => NumpadMemoryStore, // Not exposed by any OS.
1988            "NumpadMemorySubtract" => NumpadMemorySubtract, // Not exposed by any OS.
1989            "NumpadMultiply" => NumpadMultiply,
1990            "NumpadParenLeft" => NumpadParenLeft,
1991            "NumpadParenRight" => NumpadParenRight,
1992            "NumpadStar" => NumpadStar, // Not exposed by any OS.
1993            "NumpadSubtract" => NumpadSubtract,
1994
1995            // Function Section
1996            "Escape" => Escape,
1997            "F1" => F1,
1998            "F2" => F2,
1999            "F3" => F3,
2000            "F4" => F4,
2001            "F5" => F5,
2002            "F6" => F6,
2003            "F7" => F7,
2004            "F8" => F8,
2005            "F9" => F9,
2006            "F10" => F10,
2007            "F11" => F11,
2008            "F12" => F12,
2009            "F13" => F13,
2010            "F14" => F14,
2011            "F15" => F15,
2012            "F16" => F16,
2013            "F17" => F17,
2014            "F18" => F18,
2015            "F19" => F19,
2016            "F20" => F20,
2017            "F21" => F21,
2018            "F22" => F22,
2019            "F23" => F23,
2020            "F24" => F24,
2021            "Fn" => Fn,
2022            "FnLock" => FnLock, // Not exposed by any OS.
2023            "PrintScreen" => PrintScreen,
2024            "ScrollLock" => ScrollLock,
2025            "Pause" => Pause,
2026
2027            // Media Keys
2028            "BrowserBack" => BrowserBack,
2029            "BrowserFavorites" => BrowserFavorites,
2030            "BrowserForward" => BrowserForward,
2031            "BrowserHome" => BrowserHome,
2032            "BrowserRefresh" => BrowserRefresh,
2033            "BrowserSearch" => BrowserSearch,
2034            "BrowserStop" => BrowserStop, // MDN claims it is `Cancel` in Chrome, but it never even was.
2035            "Eject" => Eject,
2036            "LaunchApp1" => LaunchApp1,
2037            "LaunchApp2" => LaunchApp2,
2038            "LaunchMail" => LaunchMail,
2039            "MediaPlayPause" => MediaPlayPause,
2040            // According to MDN some versions of Firefox use `LaunchMediaPlayer`
2041            // here, but that's wrong. However Safari GTK and WPE use this value.
2042            "MediaSelect" | "LaunchMediaPlayer" => MediaSelect,
2043            "MediaStop" => MediaStop,
2044            "MediaTrackNext" => MediaTrackNext,
2045            "MediaTrackPrevious" => MediaTrackPrevious,
2046            "Power" => Power,
2047            "Sleep" => Sleep,
2048            // Wrong Volume* names in Firefox are tracked here: https://bugzilla.mozilla.org/show_bug.cgi?id=1272579
2049            "AudioVolumeDown" | "VolumeDown" => AudioVolumeDown, // VolumeDown in old browsers, sometimes even new ones
2050            "AudioVolumeMute" | "VolumeMute" => AudioVolumeMute, // VolumeMute in old browsers, sometimes even new ones
2051            "AudioVolumeUp" | "VolumeUp" => AudioVolumeUp, // VolumeUp in old browsers, sometimes even new ones
2052            "WakeUp" => WakeUp,
2053
2054            // Legacy, Non-Standard and Special Keys
2055            "Again" => Again,
2056            "Copy" => Copy,
2057            "Cut" => Cut,
2058            "Find" => Find,
2059            "Open" => Open,
2060            "Paste" => Paste,
2061            "Props" => Props,
2062            "Select" => Select,
2063            "Undo" => Undo,
2064
2065            // Gamepad Keys
2066            "Gamepad0" => Gamepad0,
2067            "Gamepad1" => Gamepad1,
2068            "Gamepad2" => Gamepad2,
2069            "Gamepad3" => Gamepad3,
2070            "Gamepad4" => Gamepad4,
2071            "Gamepad5" => Gamepad5,
2072            "Gamepad6" => Gamepad6,
2073            "Gamepad7" => Gamepad7,
2074            "Gamepad8" => Gamepad8,
2075            "Gamepad9" => Gamepad9,
2076            "Gamepad10" => Gamepad10,
2077            "Gamepad11" => Gamepad11,
2078            "Gamepad12" => Gamepad12,
2079            "Gamepad13" => Gamepad13,
2080            "Gamepad14" => Gamepad14,
2081            "Gamepad15" => Gamepad15,
2082            "Gamepad16" => Gamepad16,
2083            "Gamepad17" => Gamepad17,
2084            "Gamepad18" => Gamepad18,
2085            "Gamepad19" => Gamepad19,
2086
2087            // Browser specific Keys
2088            "BrightnessDown" => BrightnessDown,
2089            "BrightnessUp" => BrightnessUp,
2090            "DisplayToggleIntExt" => DisplayToggleIntExt,
2091            "KeyboardLayoutSelect" => KeyboardLayoutSelect,
2092            "LaunchAssistant" => LaunchAssistant,
2093            "LaunchControlPanel" => LaunchControlPanel,
2094            "LaunchScreenSaver" => LaunchScreenSaver,
2095            "MailForward" => MailForward,
2096            "MailReply" => MailReply,
2097            "MailSend" => MailSend,
2098            "MediaFastForward" => MediaFastForward,
2099            "MediaPause" => MediaPause,
2100            "MediaPlay" => MediaPlay,
2101            "MediaRecord" => MediaRecord,
2102            "MediaRewind" => MediaRewind,
2103            "MicrophoneMuteToggle" => MicrophoneMuteToggle,
2104            "PrivacyScreenToggle" => PrivacyScreenToggle,
2105            "SelectTask" => SelectTask,
2106            "ShowAllWindows" => ShowAllWindows,
2107            "ZoomToggle" => ZoomToggle,
2108            _ => return Err(()),
2109        })
2110    }
2111}