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
187    /// Back navigation key from multimedia keyboard.
188    /// Android sends this key on Back button press.
189    /// Does not work on Web.
190    BrowserBack,
191    // When adding keys, remember to also update:
192    // * crates/egui-winit/src/lib.rs
193    // * Key::ALL
194    // * Key::from_name
195    // You should test that it works using the "Input Event History" window in the egui demo app.
196    // Make sure to test both natively and on web!
197    // Also: don't add keys last; add them to the group they best belong to.
198}
199
200impl Key {
201    /// All egui keys
202    pub const ALL: &'static [Self] = &[
203        // Commands:
204        Self::ArrowDown,
205        Self::ArrowLeft,
206        Self::ArrowRight,
207        Self::ArrowUp,
208        Self::Escape,
209        Self::Tab,
210        Self::Backspace,
211        Self::Enter,
212        Self::Insert,
213        Self::Delete,
214        Self::Home,
215        Self::End,
216        Self::PageUp,
217        Self::PageDown,
218        Self::Copy,
219        Self::Cut,
220        Self::Paste,
221        // Punctuation:
222        Self::Space,
223        Self::Colon,
224        Self::Comma,
225        Self::Minus,
226        Self::Period,
227        Self::Plus,
228        Self::Equals,
229        Self::Semicolon,
230        Self::OpenBracket,
231        Self::CloseBracket,
232        Self::OpenCurlyBracket,
233        Self::CloseCurlyBracket,
234        Self::Backtick,
235        Self::Backslash,
236        Self::Slash,
237        Self::Pipe,
238        Self::Questionmark,
239        Self::Exclamationmark,
240        Self::Quote,
241        // Digits:
242        Self::Num0,
243        Self::Num1,
244        Self::Num2,
245        Self::Num3,
246        Self::Num4,
247        Self::Num5,
248        Self::Num6,
249        Self::Num7,
250        Self::Num8,
251        Self::Num9,
252        // Letters:
253        Self::A,
254        Self::B,
255        Self::C,
256        Self::D,
257        Self::E,
258        Self::F,
259        Self::G,
260        Self::H,
261        Self::I,
262        Self::J,
263        Self::K,
264        Self::L,
265        Self::M,
266        Self::N,
267        Self::O,
268        Self::P,
269        Self::Q,
270        Self::R,
271        Self::S,
272        Self::T,
273        Self::U,
274        Self::V,
275        Self::W,
276        Self::X,
277        Self::Y,
278        Self::Z,
279        // Function keys:
280        Self::F1,
281        Self::F2,
282        Self::F3,
283        Self::F4,
284        Self::F5,
285        Self::F6,
286        Self::F7,
287        Self::F8,
288        Self::F9,
289        Self::F10,
290        Self::F11,
291        Self::F12,
292        Self::F13,
293        Self::F14,
294        Self::F15,
295        Self::F16,
296        Self::F17,
297        Self::F18,
298        Self::F19,
299        Self::F20,
300        Self::F21,
301        Self::F22,
302        Self::F23,
303        Self::F24,
304        Self::F25,
305        Self::F26,
306        Self::F27,
307        Self::F28,
308        Self::F29,
309        Self::F30,
310        Self::F31,
311        Self::F32,
312        Self::F33,
313        Self::F34,
314        Self::F35,
315        // Navigation keys:
316        Self::BrowserBack,
317    ];
318
319    /// Converts `"A"` to `Key::A`, `Space` to `Key::Space`, etc.
320    ///
321    /// Makes sense for logical keys.
322    ///
323    /// This will parse the output of both [`Self::name`] and [`Self::symbol_or_name`],
324    /// but will also parse single characters, so that both `"-"` and `"Minus"` will return `Key::Minus`.
325    ///
326    /// This should support both the names generated in a web browser,
327    /// and by winit. Please test on both with `eframe`.
328    pub fn from_name(key: &str) -> Option<Self> {
329        Some(match key {
330            "⏷" | "ArrowDown" | "Down" => Self::ArrowDown,
331            "⏴" | "ArrowLeft" | "Left" => Self::ArrowLeft,
332            "⏵" | "ArrowRight" | "Right" => Self::ArrowRight,
333            "⏶" | "ArrowUp" | "Up" => Self::ArrowUp,
334
335            "Escape" | "Esc" => Self::Escape,
336            "Tab" => Self::Tab,
337            "Backspace" => Self::Backspace,
338            "Enter" | "Return" => Self::Enter,
339
340            "Help" | "Insert" => Self::Insert,
341            "Delete" => Self::Delete,
342            "Home" => Self::Home,
343            "End" => Self::End,
344            "PageUp" => Self::PageUp,
345            "PageDown" => Self::PageDown,
346
347            "Copy" => Self::Copy,
348            "Cut" => Self::Cut,
349            "Paste" => Self::Paste,
350
351            " " | "Space" => Self::Space,
352            ":" | "Colon" => Self::Colon,
353            "," | "Comma" => Self::Comma,
354            "-" | "−" | "Minus" => Self::Minus,
355            "." | "Period" => Self::Period,
356            "+" | "Plus" => Self::Plus,
357            "=" | "Equal" | "Equals" | "NumpadEqual" => Self::Equals,
358            ";" | "Semicolon" => Self::Semicolon,
359            "\\" | "Backslash" => Self::Backslash,
360            "/" | "Slash" => Self::Slash,
361            "|" | "Pipe" => Self::Pipe,
362            "?" | "Questionmark" => Self::Questionmark,
363            "!" | "Exclamationmark" => Self::Exclamationmark,
364            "[" | "OpenBracket" => Self::OpenBracket,
365            "]" | "CloseBracket" => Self::CloseBracket,
366            "{" | "OpenCurlyBracket" => Self::OpenCurlyBracket,
367            "}" | "CloseCurlyBracket" => Self::CloseCurlyBracket,
368            "`" | "Backtick" | "Backquote" | "Grave" => Self::Backtick,
369            "'" | "Quote" => Self::Quote,
370
371            "0" | "Digit0" | "Numpad0" => Self::Num0,
372            "1" | "Digit1" | "Numpad1" => Self::Num1,
373            "2" | "Digit2" | "Numpad2" => Self::Num2,
374            "3" | "Digit3" | "Numpad3" => Self::Num3,
375            "4" | "Digit4" | "Numpad4" => Self::Num4,
376            "5" | "Digit5" | "Numpad5" => Self::Num5,
377            "6" | "Digit6" | "Numpad6" => Self::Num6,
378            "7" | "Digit7" | "Numpad7" => Self::Num7,
379            "8" | "Digit8" | "Numpad8" => Self::Num8,
380            "9" | "Digit9" | "Numpad9" => Self::Num9,
381
382            "a" | "A" => Self::A,
383            "b" | "B" => Self::B,
384            "c" | "C" => Self::C,
385            "d" | "D" => Self::D,
386            "e" | "E" => Self::E,
387            "f" | "F" => Self::F,
388            "g" | "G" => Self::G,
389            "h" | "H" => Self::H,
390            "i" | "I" => Self::I,
391            "j" | "J" => Self::J,
392            "k" | "K" => Self::K,
393            "l" | "L" => Self::L,
394            "m" | "M" => Self::M,
395            "n" | "N" => Self::N,
396            "o" | "O" => Self::O,
397            "p" | "P" => Self::P,
398            "q" | "Q" => Self::Q,
399            "r" | "R" => Self::R,
400            "s" | "S" => Self::S,
401            "t" | "T" => Self::T,
402            "u" | "U" => Self::U,
403            "v" | "V" => Self::V,
404            "w" | "W" => Self::W,
405            "x" | "X" => Self::X,
406            "y" | "Y" => Self::Y,
407            "z" | "Z" => Self::Z,
408
409            "F1" => Self::F1,
410            "F2" => Self::F2,
411            "F3" => Self::F3,
412            "F4" => Self::F4,
413            "F5" => Self::F5,
414            "F6" => Self::F6,
415            "F7" => Self::F7,
416            "F8" => Self::F8,
417            "F9" => Self::F9,
418            "F10" => Self::F10,
419            "F11" => Self::F11,
420            "F12" => Self::F12,
421            "F13" => Self::F13,
422            "F14" => Self::F14,
423            "F15" => Self::F15,
424            "F16" => Self::F16,
425            "F17" => Self::F17,
426            "F18" => Self::F18,
427            "F19" => Self::F19,
428            "F20" => Self::F20,
429            "F21" => Self::F21,
430            "F22" => Self::F22,
431            "F23" => Self::F23,
432            "F24" => Self::F24,
433            "F25" => Self::F25,
434            "F26" => Self::F26,
435            "F27" => Self::F27,
436            "F28" => Self::F28,
437            "F29" => Self::F29,
438            "F30" => Self::F30,
439            "F31" => Self::F31,
440            "F32" => Self::F32,
441            "F33" => Self::F33,
442            "F34" => Self::F34,
443            "F35" => Self::F35,
444
445            "BrowserBack" => Self::BrowserBack,
446
447            _ => return None,
448        })
449    }
450
451    /// Emoji or name representing the key
452    pub fn symbol_or_name(self) -> &'static str {
453        // TODO(emilk): add support for more unicode symbols (see for instance https://wincent.com/wiki/Unicode_representations_of_modifier_keys).
454        // Before we do we must first make sure they are supported in `Fonts` though,
455        // so perhaps this functions needs to take a `supports_character: impl Fn(char) -> bool` or something.
456        match self {
457            Self::ArrowDown => "⏷",
458            Self::ArrowLeft => "⏴",
459            Self::ArrowRight => "⏵",
460            Self::ArrowUp => "⏶",
461
462            Self::Colon => ":",
463            Self::Comma => ",",
464            Self::Minus => crate::MINUS_CHAR_STR,
465            Self::Period => ".",
466            Self::Plus => "+",
467            Self::Equals => "=",
468            Self::Semicolon => ";",
469            Self::Backslash => "\\",
470            Self::Slash => "/",
471            Self::Pipe => "|",
472            Self::Questionmark => "?",
473            Self::Exclamationmark => "!",
474            Self::OpenBracket => "[",
475            Self::CloseBracket => "]",
476            Self::OpenCurlyBracket => "{",
477            Self::CloseCurlyBracket => "}",
478            Self::Backtick => "`",
479
480            _ => self.name(),
481        }
482    }
483
484    /// Human-readable English name.
485    pub fn name(self) -> &'static str {
486        match self {
487            Self::ArrowDown => "Down",
488            Self::ArrowLeft => "Left",
489            Self::ArrowRight => "Right",
490            Self::ArrowUp => "Up",
491
492            Self::Escape => "Escape",
493            Self::Tab => "Tab",
494            Self::Backspace => "Backspace",
495            Self::Enter => "Enter",
496
497            Self::Insert => "Insert",
498            Self::Delete => "Delete",
499            Self::Home => "Home",
500            Self::End => "End",
501            Self::PageUp => "PageUp",
502            Self::PageDown => "PageDown",
503
504            Self::Copy => "Copy",
505            Self::Cut => "Cut",
506            Self::Paste => "Paste",
507
508            Self::Space => "Space",
509            Self::Colon => "Colon",
510            Self::Comma => "Comma",
511            Self::Minus => "Minus",
512            Self::Period => "Period",
513            Self::Plus => "Plus",
514            Self::Equals => "Equals",
515            Self::Semicolon => "Semicolon",
516            Self::Backslash => "Backslash",
517            Self::Slash => "Slash",
518            Self::Pipe => "Pipe",
519            Self::Questionmark => "Questionmark",
520            Self::Exclamationmark => "Exclamationmark",
521            Self::OpenBracket => "OpenBracket",
522            Self::CloseBracket => "CloseBracket",
523            Self::OpenCurlyBracket => "OpenCurlyBracket",
524            Self::CloseCurlyBracket => "CloseCurlyBracket",
525            Self::Backtick => "Backtick",
526            Self::Quote => "Quote",
527
528            Self::Num0 => "0",
529            Self::Num1 => "1",
530            Self::Num2 => "2",
531            Self::Num3 => "3",
532            Self::Num4 => "4",
533            Self::Num5 => "5",
534            Self::Num6 => "6",
535            Self::Num7 => "7",
536            Self::Num8 => "8",
537            Self::Num9 => "9",
538
539            Self::A => "A",
540            Self::B => "B",
541            Self::C => "C",
542            Self::D => "D",
543            Self::E => "E",
544            Self::F => "F",
545            Self::G => "G",
546            Self::H => "H",
547            Self::I => "I",
548            Self::J => "J",
549            Self::K => "K",
550            Self::L => "L",
551            Self::M => "M",
552            Self::N => "N",
553            Self::O => "O",
554            Self::P => "P",
555            Self::Q => "Q",
556            Self::R => "R",
557            Self::S => "S",
558            Self::T => "T",
559            Self::U => "U",
560            Self::V => "V",
561            Self::W => "W",
562            Self::X => "X",
563            Self::Y => "Y",
564            Self::Z => "Z",
565            Self::F1 => "F1",
566            Self::F2 => "F2",
567            Self::F3 => "F3",
568            Self::F4 => "F4",
569            Self::F5 => "F5",
570            Self::F6 => "F6",
571            Self::F7 => "F7",
572            Self::F8 => "F8",
573            Self::F9 => "F9",
574            Self::F10 => "F10",
575            Self::F11 => "F11",
576            Self::F12 => "F12",
577            Self::F13 => "F13",
578            Self::F14 => "F14",
579            Self::F15 => "F15",
580            Self::F16 => "F16",
581            Self::F17 => "F17",
582            Self::F18 => "F18",
583            Self::F19 => "F19",
584            Self::F20 => "F20",
585            Self::F21 => "F21",
586            Self::F22 => "F22",
587            Self::F23 => "F23",
588            Self::F24 => "F24",
589            Self::F25 => "F25",
590            Self::F26 => "F26",
591            Self::F27 => "F27",
592            Self::F28 => "F28",
593            Self::F29 => "F29",
594            Self::F30 => "F30",
595            Self::F31 => "F31",
596            Self::F32 => "F32",
597            Self::F33 => "F33",
598            Self::F34 => "F34",
599            Self::F35 => "F35",
600
601            Self::BrowserBack => "BrowserBack",
602        }
603    }
604}
605
606#[test]
607fn test_key_from_name() {
608    assert_eq!(
609        Key::ALL.len(),
610        Key::BrowserBack as usize + 1,
611        "Some keys are missing in Key::ALL"
612    );
613
614    for &key in Key::ALL {
615        let name = key.name();
616        assert_eq!(
617            Key::from_name(name),
618            Some(key),
619            "Failed to roundtrip {key:?} from name {name:?}"
620        );
621
622        let symbol = key.symbol_or_name();
623        assert_eq!(
624            Key::from_name(symbol),
625            Some(key),
626            "Failed to roundtrip {key:?} from symbol {symbol:?}"
627        );
628    }
629}