egui/data/
key.rs

1/// Keyboard keys.
2///
3/// egui usually uses logical keys, i.e. after applying any user keymap.\
4// See comment at the end of `Key { … }` on how to add new keys.
5#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)]
6#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
7pub enum Key {
8    // ----------------------------------------------
9    // Commands:
10    ArrowDown,
11    ArrowLeft,
12    ArrowRight,
13    ArrowUp,
14
15    Escape,
16    Tab,
17    Backspace,
18    Enter,
19    Space,
20
21    Insert,
22    Delete,
23    Home,
24    End,
25    PageUp,
26    PageDown,
27
28    Copy,
29    Cut,
30    Paste,
31
32    // ----------------------------------------------
33    // Punctuation:
34    /// `:`
35    Colon,
36
37    /// `,`
38    Comma,
39
40    /// `\`
41    Backslash,
42
43    /// `/`
44    Slash,
45
46    /// `|`, a vertical bar
47    Pipe,
48
49    /// `?`
50    Questionmark,
51
52    // '!'
53    Exclamationmark,
54
55    // `[`
56    OpenBracket,
57
58    // `]`
59    CloseBracket,
60
61    // `{`
62    OpenCurlyBracket,
63
64    // `}`
65    CloseCurlyBracket,
66
67    /// Also known as "backquote" or "grave"
68    Backtick,
69
70    /// `-`
71    Minus,
72
73    /// `.`
74    Period,
75
76    /// `+`
77    Plus,
78
79    /// `=`
80    Equals,
81
82    /// `;`
83    Semicolon,
84
85    /// `'`
86    Quote,
87
88    // ----------------------------------------------
89    // Digits:
90    /// `0` (from main row or numpad)
91    Num0,
92
93    /// `1` (from main row or numpad)
94    Num1,
95
96    /// `2` (from main row or numpad)
97    Num2,
98
99    /// `3` (from main row or numpad)
100    Num3,
101
102    /// `4` (from main row or numpad)
103    Num4,
104
105    /// `5` (from main row or numpad)
106    Num5,
107
108    /// `6` (from main row or numpad)
109    Num6,
110
111    /// `7` (from main row or numpad)
112    Num7,
113
114    /// `8` (from main row or numpad)
115    Num8,
116
117    /// `9` (from main row or numpad)
118    Num9,
119
120    // ----------------------------------------------
121    // Letters:
122    A, // Used for cmd+A (select All)
123    B,
124    C, // |CMD COPY|
125    D, // |CMD BOOKMARK|
126    E, // |CMD SEARCH|
127    F, // |CMD FIND firefox & chrome|
128    G, // |CMD FIND chrome|
129    H, // |CMD History|
130    I, // italics
131    J, // |CMD SEARCH firefox/DOWNLOAD chrome|
132    K, // Used for ctrl+K (delete text after cursor)
133    L,
134    M,
135    N,
136    O, // |CMD OPEN|
137    P, // |CMD PRINT|
138    Q,
139    R, // |CMD REFRESH|
140    S, // |CMD SAVE|
141    T, // |CMD TAB|
142    U, // Used for ctrl+U (delete text before cursor)
143    V, // |CMD PASTE|
144    W, // Used for ctrl+W (delete previous word)
145    X, // |CMD CUT|
146    Y,
147    Z, // |CMD UNDO|
148
149    // ----------------------------------------------
150    // Function keys:
151    F1,
152    F2,
153    F3,
154    F4,
155    F5, // |CMD REFRESH|
156    F6,
157    F7,
158    F8,
159    F9,
160    F10,
161    F11,
162    F12,
163    F13,
164    F14,
165    F15,
166    F16,
167    F17,
168    F18,
169    F19,
170    F20,
171    F21,
172    F22,
173    F23,
174    F24,
175    F25,
176    F26,
177    F27,
178    F28,
179    F29,
180    F30,
181    F31,
182    F32,
183    F33,
184    F34,
185    F35,
186    // When adding keys, remember to also update:
187    // * crates/egui-winit/src/lib.rs
188    // * Key::ALL
189    // * Key::from_name
190    // You should test that it works using the "Input Event History" window in the egui demo app.
191    // Make sure to test both natively and on web!
192    // Also: don't add keys last; add them to the group they best belong to.
193}
194
195impl Key {
196    /// All egui keys
197    pub const ALL: &'static [Self] = &[
198        // Commands:
199        Self::ArrowDown,
200        Self::ArrowLeft,
201        Self::ArrowRight,
202        Self::ArrowUp,
203        Self::Escape,
204        Self::Tab,
205        Self::Backspace,
206        Self::Enter,
207        Self::Insert,
208        Self::Delete,
209        Self::Home,
210        Self::End,
211        Self::PageUp,
212        Self::PageDown,
213        Self::Copy,
214        Self::Cut,
215        Self::Paste,
216        // Punctuation:
217        Self::Space,
218        Self::Colon,
219        Self::Comma,
220        Self::Minus,
221        Self::Period,
222        Self::Plus,
223        Self::Equals,
224        Self::Semicolon,
225        Self::OpenBracket,
226        Self::CloseBracket,
227        Self::OpenCurlyBracket,
228        Self::CloseCurlyBracket,
229        Self::Backtick,
230        Self::Backslash,
231        Self::Slash,
232        Self::Pipe,
233        Self::Questionmark,
234        Self::Exclamationmark,
235        Self::Quote,
236        // Digits:
237        Self::Num0,
238        Self::Num1,
239        Self::Num2,
240        Self::Num3,
241        Self::Num4,
242        Self::Num5,
243        Self::Num6,
244        Self::Num7,
245        Self::Num8,
246        Self::Num9,
247        // Letters:
248        Self::A,
249        Self::B,
250        Self::C,
251        Self::D,
252        Self::E,
253        Self::F,
254        Self::G,
255        Self::H,
256        Self::I,
257        Self::J,
258        Self::K,
259        Self::L,
260        Self::M,
261        Self::N,
262        Self::O,
263        Self::P,
264        Self::Q,
265        Self::R,
266        Self::S,
267        Self::T,
268        Self::U,
269        Self::V,
270        Self::W,
271        Self::X,
272        Self::Y,
273        Self::Z,
274        // Function keys:
275        Self::F1,
276        Self::F2,
277        Self::F3,
278        Self::F4,
279        Self::F5,
280        Self::F6,
281        Self::F7,
282        Self::F8,
283        Self::F9,
284        Self::F10,
285        Self::F11,
286        Self::F12,
287        Self::F13,
288        Self::F14,
289        Self::F15,
290        Self::F16,
291        Self::F17,
292        Self::F18,
293        Self::F19,
294        Self::F20,
295        Self::F21,
296        Self::F22,
297        Self::F23,
298        Self::F24,
299        Self::F25,
300        Self::F26,
301        Self::F27,
302        Self::F28,
303        Self::F29,
304        Self::F30,
305        Self::F31,
306        Self::F32,
307        Self::F33,
308        Self::F34,
309        Self::F35,
310    ];
311
312    /// Converts `"A"` to `Key::A`, `Space` to `Key::Space`, etc.
313    ///
314    /// Makes sense for logical keys.
315    ///
316    /// This will parse the output of both [`Self::name`] and [`Self::symbol_or_name`],
317    /// but will also parse single characters, so that both `"-"` and `"Minus"` will return `Key::Minus`.
318    ///
319    /// This should support both the names generated in a web browser,
320    /// and by winit. Please test on both with `eframe`.
321    pub fn from_name(key: &str) -> Option<Self> {
322        Some(match key {
323            "⏷" | "ArrowDown" | "Down" => Self::ArrowDown,
324            "⏴" | "ArrowLeft" | "Left" => Self::ArrowLeft,
325            "⏵" | "ArrowRight" | "Right" => Self::ArrowRight,
326            "⏶" | "ArrowUp" | "Up" => Self::ArrowUp,
327
328            "Escape" | "Esc" => Self::Escape,
329            "Tab" => Self::Tab,
330            "Backspace" => Self::Backspace,
331            "Enter" | "Return" => Self::Enter,
332
333            "Help" | "Insert" => Self::Insert,
334            "Delete" => Self::Delete,
335            "Home" => Self::Home,
336            "End" => Self::End,
337            "PageUp" => Self::PageUp,
338            "PageDown" => Self::PageDown,
339
340            "Copy" => Self::Copy,
341            "Cut" => Self::Cut,
342            "Paste" => Self::Paste,
343
344            " " | "Space" => Self::Space,
345            ":" | "Colon" => Self::Colon,
346            "," | "Comma" => Self::Comma,
347            "-" | "−" | "Minus" => Self::Minus,
348            "." | "Period" => Self::Period,
349            "+" | "Plus" => Self::Plus,
350            "=" | "Equal" | "Equals" | "NumpadEqual" => Self::Equals,
351            ";" | "Semicolon" => Self::Semicolon,
352            "\\" | "Backslash" => Self::Backslash,
353            "/" | "Slash" => Self::Slash,
354            "|" | "Pipe" => Self::Pipe,
355            "?" | "Questionmark" => Self::Questionmark,
356            "!" | "Exclamationmark" => Self::Exclamationmark,
357            "[" | "OpenBracket" => Self::OpenBracket,
358            "]" | "CloseBracket" => Self::CloseBracket,
359            "{" | "OpenCurlyBracket" => Self::OpenCurlyBracket,
360            "}" | "CloseCurlyBracket" => Self::CloseCurlyBracket,
361            "`" | "Backtick" | "Backquote" | "Grave" => Self::Backtick,
362            "'" | "Quote" => Self::Quote,
363
364            "0" | "Digit0" | "Numpad0" => Self::Num0,
365            "1" | "Digit1" | "Numpad1" => Self::Num1,
366            "2" | "Digit2" | "Numpad2" => Self::Num2,
367            "3" | "Digit3" | "Numpad3" => Self::Num3,
368            "4" | "Digit4" | "Numpad4" => Self::Num4,
369            "5" | "Digit5" | "Numpad5" => Self::Num5,
370            "6" | "Digit6" | "Numpad6" => Self::Num6,
371            "7" | "Digit7" | "Numpad7" => Self::Num7,
372            "8" | "Digit8" | "Numpad8" => Self::Num8,
373            "9" | "Digit9" | "Numpad9" => Self::Num9,
374
375            "a" | "A" => Self::A,
376            "b" | "B" => Self::B,
377            "c" | "C" => Self::C,
378            "d" | "D" => Self::D,
379            "e" | "E" => Self::E,
380            "f" | "F" => Self::F,
381            "g" | "G" => Self::G,
382            "h" | "H" => Self::H,
383            "i" | "I" => Self::I,
384            "j" | "J" => Self::J,
385            "k" | "K" => Self::K,
386            "l" | "L" => Self::L,
387            "m" | "M" => Self::M,
388            "n" | "N" => Self::N,
389            "o" | "O" => Self::O,
390            "p" | "P" => Self::P,
391            "q" | "Q" => Self::Q,
392            "r" | "R" => Self::R,
393            "s" | "S" => Self::S,
394            "t" | "T" => Self::T,
395            "u" | "U" => Self::U,
396            "v" | "V" => Self::V,
397            "w" | "W" => Self::W,
398            "x" | "X" => Self::X,
399            "y" | "Y" => Self::Y,
400            "z" | "Z" => Self::Z,
401
402            "F1" => Self::F1,
403            "F2" => Self::F2,
404            "F3" => Self::F3,
405            "F4" => Self::F4,
406            "F5" => Self::F5,
407            "F6" => Self::F6,
408            "F7" => Self::F7,
409            "F8" => Self::F8,
410            "F9" => Self::F9,
411            "F10" => Self::F10,
412            "F11" => Self::F11,
413            "F12" => Self::F12,
414            "F13" => Self::F13,
415            "F14" => Self::F14,
416            "F15" => Self::F15,
417            "F16" => Self::F16,
418            "F17" => Self::F17,
419            "F18" => Self::F18,
420            "F19" => Self::F19,
421            "F20" => Self::F20,
422            "F21" => Self::F21,
423            "F22" => Self::F22,
424            "F23" => Self::F23,
425            "F24" => Self::F24,
426            "F25" => Self::F25,
427            "F26" => Self::F26,
428            "F27" => Self::F27,
429            "F28" => Self::F28,
430            "F29" => Self::F29,
431            "F30" => Self::F30,
432            "F31" => Self::F31,
433            "F32" => Self::F32,
434            "F33" => Self::F33,
435            "F34" => Self::F34,
436            "F35" => Self::F35,
437
438            _ => return None,
439        })
440    }
441
442    /// Emoji or name representing the key
443    pub fn symbol_or_name(self) -> &'static str {
444        // TODO(emilk): add support for more unicode symbols (see for instance https://wincent.com/wiki/Unicode_representations_of_modifier_keys).
445        // Before we do we must first make sure they are supported in `Fonts` though,
446        // so perhaps this functions needs to take a `supports_character: impl Fn(char) -> bool` or something.
447        match self {
448            Self::ArrowDown => "⏷",
449            Self::ArrowLeft => "⏴",
450            Self::ArrowRight => "⏵",
451            Self::ArrowUp => "⏶",
452
453            Self::Colon => ":",
454            Self::Comma => ",",
455            Self::Minus => crate::MINUS_CHAR_STR,
456            Self::Period => ".",
457            Self::Plus => "+",
458            Self::Equals => "=",
459            Self::Semicolon => ";",
460            Self::Backslash => "\\",
461            Self::Slash => "/",
462            Self::Pipe => "|",
463            Self::Questionmark => "?",
464            Self::Exclamationmark => "!",
465            Self::OpenBracket => "[",
466            Self::CloseBracket => "]",
467            Self::OpenCurlyBracket => "{",
468            Self::CloseCurlyBracket => "}",
469            Self::Backtick => "`",
470
471            _ => self.name(),
472        }
473    }
474
475    /// Human-readable English name.
476    pub fn name(self) -> &'static str {
477        match self {
478            Self::ArrowDown => "Down",
479            Self::ArrowLeft => "Left",
480            Self::ArrowRight => "Right",
481            Self::ArrowUp => "Up",
482
483            Self::Escape => "Escape",
484            Self::Tab => "Tab",
485            Self::Backspace => "Backspace",
486            Self::Enter => "Enter",
487
488            Self::Insert => "Insert",
489            Self::Delete => "Delete",
490            Self::Home => "Home",
491            Self::End => "End",
492            Self::PageUp => "PageUp",
493            Self::PageDown => "PageDown",
494
495            Self::Copy => "Copy",
496            Self::Cut => "Cut",
497            Self::Paste => "Paste",
498
499            Self::Space => "Space",
500            Self::Colon => "Colon",
501            Self::Comma => "Comma",
502            Self::Minus => "Minus",
503            Self::Period => "Period",
504            Self::Plus => "Plus",
505            Self::Equals => "Equals",
506            Self::Semicolon => "Semicolon",
507            Self::Backslash => "Backslash",
508            Self::Slash => "Slash",
509            Self::Pipe => "Pipe",
510            Self::Questionmark => "Questionmark",
511            Self::Exclamationmark => "Exclamationmark",
512            Self::OpenBracket => "OpenBracket",
513            Self::CloseBracket => "CloseBracket",
514            Self::OpenCurlyBracket => "OpenCurlyBracket",
515            Self::CloseCurlyBracket => "CloseCurlyBracket",
516            Self::Backtick => "Backtick",
517            Self::Quote => "Quote",
518
519            Self::Num0 => "0",
520            Self::Num1 => "1",
521            Self::Num2 => "2",
522            Self::Num3 => "3",
523            Self::Num4 => "4",
524            Self::Num5 => "5",
525            Self::Num6 => "6",
526            Self::Num7 => "7",
527            Self::Num8 => "8",
528            Self::Num9 => "9",
529
530            Self::A => "A",
531            Self::B => "B",
532            Self::C => "C",
533            Self::D => "D",
534            Self::E => "E",
535            Self::F => "F",
536            Self::G => "G",
537            Self::H => "H",
538            Self::I => "I",
539            Self::J => "J",
540            Self::K => "K",
541            Self::L => "L",
542            Self::M => "M",
543            Self::N => "N",
544            Self::O => "O",
545            Self::P => "P",
546            Self::Q => "Q",
547            Self::R => "R",
548            Self::S => "S",
549            Self::T => "T",
550            Self::U => "U",
551            Self::V => "V",
552            Self::W => "W",
553            Self::X => "X",
554            Self::Y => "Y",
555            Self::Z => "Z",
556            Self::F1 => "F1",
557            Self::F2 => "F2",
558            Self::F3 => "F3",
559            Self::F4 => "F4",
560            Self::F5 => "F5",
561            Self::F6 => "F6",
562            Self::F7 => "F7",
563            Self::F8 => "F8",
564            Self::F9 => "F9",
565            Self::F10 => "F10",
566            Self::F11 => "F11",
567            Self::F12 => "F12",
568            Self::F13 => "F13",
569            Self::F14 => "F14",
570            Self::F15 => "F15",
571            Self::F16 => "F16",
572            Self::F17 => "F17",
573            Self::F18 => "F18",
574            Self::F19 => "F19",
575            Self::F20 => "F20",
576            Self::F21 => "F21",
577            Self::F22 => "F22",
578            Self::F23 => "F23",
579            Self::F24 => "F24",
580            Self::F25 => "F25",
581            Self::F26 => "F26",
582            Self::F27 => "F27",
583            Self::F28 => "F28",
584            Self::F29 => "F29",
585            Self::F30 => "F30",
586            Self::F31 => "F31",
587            Self::F32 => "F32",
588            Self::F33 => "F33",
589            Self::F34 => "F34",
590            Self::F35 => "F35",
591        }
592    }
593}
594
595#[test]
596fn test_key_from_name() {
597    assert_eq!(
598        Key::ALL.len(),
599        Key::F35 as usize + 1,
600        "Some keys are missing in Key::ALL"
601    );
602
603    for &key in Key::ALL {
604        let name = key.name();
605        assert_eq!(
606            Key::from_name(name),
607            Some(key),
608            "Failed to roundtrip {key:?} from name {name:?}"
609        );
610
611        let symbol = key.symbol_or_name();
612        assert_eq!(
613            Key::from_name(symbol),
614            Some(key),
615            "Failed to roundtrip {key:?} from symbol {symbol:?}"
616        );
617    }
618}