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