gooey/interface/view/input/button/
keycode.rs

1use std::convert::TryFrom;
2use parse_display::FromStr;
3use strum::{EnumCount, FromRepr};
4use crate::interface::view::input::Modifiers;
5
6#[cfg(feature = "opengl")] use nsys::gl::winit;
7
8macro_rules! impl_keycode {
9  ($($winit : ident => $keycode : ident),+) => {
10    #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, EnumCount,
11      FromRepr, FromStr)]
12    pub enum Keycode {
13      $($keycode),+
14    }
15
16    #[cfg(feature = "opengl")]
17    #[cfg_attr(docsrs, doc(cfg(feature="opengl")))]
18    impl From <winit::keyboard::KeyCode> for Keycode {
19      fn from (keycode : winit::keyboard::KeyCode) -> Self {
20        match keycode {
21          $(winit::keyboard::KeyCode::$winit => Keycode::$keycode),+,
22          _ => unimplemented!("unimplemented keycode conversion: {:?}", keycode)
23        }
24      }
25    }
26  }
27}
28
29// The following keycodes are meant to correspond 1:1 with glutin keycodes, but
30// to implement `From <winit::event::VirtualKeyCode>` requires the `opengl`
31// feature to be enabled.
32impl_keycode! {
33  Backquote            => Grave,
34  Backslash            => Backslash,
35  BracketLeft          => LBracket,
36  BracketRight         => RBracket,
37  Comma                => Comma,
38  Digit0               => Key0,
39  Digit1               => Key1,
40  Digit2               => Key2,
41  Digit3               => Key3,
42  Digit4               => Key4,
43  Digit5               => Key5,
44  Digit6               => Key6,
45  Digit7               => Key7,
46  Digit8               => Key8,
47  Digit9               => Key9,
48  Equal                => Equal,
49  IntlBackslash        => IntlBackslash,
50  IntlRo               => IntlRo,
51  IntlYen              => IntlYen,
52  KeyA                 => A,
53  KeyB                 => B,
54  KeyC                 => C,
55  KeyD                 => D,
56  KeyE                 => E,
57  KeyF                 => F,
58  KeyG                 => G,
59  KeyH                 => H,
60  KeyI                 => I,
61  KeyJ                 => J,
62  KeyK                 => K,
63  KeyL                 => L,
64  KeyM                 => M,
65  KeyN                 => N,
66  KeyO                 => O,
67  KeyP                 => P,
68  KeyQ                 => Q,
69  KeyR                 => R,
70  KeyS                 => S,
71  KeyT                 => T,
72  KeyU                 => U,
73  KeyV                 => V,
74  KeyW                 => W,
75  KeyX                 => X,
76  KeyY                 => Y,
77  KeyZ                 => Z,
78  Minus                => Minus,
79  Period               => Period,
80  Quote                => Quote,
81  Semicolon            => Semicolon,
82  Slash                => Slash,
83  AltLeft              => LAlt,
84  AltRight             => RAlt,
85  Backspace            => Backspace,
86  CapsLock             => CapsLock,
87  ContextMenu          => ContextMenu,
88  ControlLeft          => LControl,
89  ControlRight         => RControl,
90  Enter                => Enter,
91  SuperLeft            => LWin,
92  SuperRight           => RWin,
93  ShiftLeft            => LShift,
94  ShiftRight           => RShift,
95  Space                => Space,
96  Tab                  => Tab,
97  Convert              => Convert,
98  KanaMode             => KanaMode,
99  Lang1                => Lang1,
100  Lang2                => Lang2,
101  Lang3                => Lang3,
102  Lang4                => Lang4,
103  Lang5                => Lang5,
104  NonConvert           => NonConvert,
105  Delete               => Delete,
106  End                  => End,
107  Help                 => Help,
108  Home                 => Home,
109  Insert               => Insert,
110  PageDown             => PageDown,
111  PageUp               => PageUp,
112  ArrowDown            => Down,
113  ArrowLeft            => Left,
114  ArrowRight           => Right,
115  ArrowUp              => Up,
116  NumLock              => NumLock,
117  Numpad0              => Numpad0,
118  Numpad1              => Numpad1,
119  Numpad2              => Numpad2,
120  Numpad3              => Numpad3,
121  Numpad4              => Numpad4,
122  Numpad5              => Numpad5,
123  Numpad6              => Numpad6,
124  Numpad7              => Numpad7,
125  Numpad8              => Numpad8,
126  Numpad9              => Numpad9,
127  NumpadAdd            => NumpadAdd,
128  NumpadBackspace      => NumpadBackspace,
129  NumpadClear          => NumpadClear,
130  NumpadClearEntry     => NumpadClearEntry,
131  NumpadComma          => NumpadComma,
132  NumpadDecimal        => NumpadDecimal,
133  NumpadDivide         => NumpadDivide,
134  NumpadEnter          => NumpadEnter,
135  NumpadEqual          => NumpadEqual,
136  NumpadHash           => NumpadHash,
137  NumpadMemoryAdd      => NumpadMemoryAdd,
138  NumpadMemoryClear    => NumpadMemoryClear,
139  NumpadMemoryRecall   => NumpadMemoryRecall,
140  NumpadMemoryStore    => NumpadMemoryStore,
141  NumpadMemorySubtract => NumpadMemorySubtract,
142  NumpadMultiply       => NumpadMultiply,
143  NumpadParenLeft      => NumpadLParen,
144  NumpadParenRight     => NumpadRParen,
145  NumpadStar           => NumpadStar,
146  NumpadSubtract       => NumpadSubtract,
147  Escape               => Escape,
148  Fn                   => Fn,
149  FnLock               => FnLock,
150  PrintScreen          => PrintScreen,
151  ScrollLock           => ScrollLock,
152  Pause                => Pause,
153  BrowserBack          => BrowserBack,
154  BrowserFavorites     => BrowserFavorites,
155  BrowserForward       => BrowserForward,
156  BrowserHome          => BrowserHome,
157  BrowserRefresh       => BrowserRefresh,
158  BrowserSearch        => BrowserSearch,
159  BrowserStop          => BrowserStop,
160  Eject                => Eject,
161  LaunchApp1           => LaunchApp1,
162  LaunchApp2           => LaunchApp2,
163  LaunchMail           => LaunchMail,
164  MediaPlayPause       => MediaPlayPause,
165  MediaSelect          => MediaSelect,
166  MediaStop            => MediaStop,
167  MediaTrackNext       => MediaTrackNext,
168  MediaTrackPrevious   => MediaTrackPrevious,
169  Power                => Power,
170  Sleep                => Sleep,
171  AudioVolumeDown      => AudioVolumeDown,
172  AudioVolumeMute      => AudioVolumeMute,
173  AudioVolumeUp        => AudioVolumeUp,
174  WakeUp               => WakeUp,
175  Meta                 => Meta,
176  Hyper                => Hyper,
177  Turbo                => Turbo,
178  Abort                => Abort,
179  Resume               => Resume,
180  Suspend              => Suspend,
181  Again                => Again,
182  Copy                 => Copy,
183  Cut                  => Cut,
184  Find                 => Find,
185  Open                 => Open,
186  Paste                => Paste,
187  Props                => Props,
188  Select               => Select,
189  Undo                 => Undo,
190  Hiragana             => Hiragana,
191  Katakana             => Katakana,
192  F1                   => F1,
193  F2                   => F2,
194  F3                   => F3,
195  F4                   => F4,
196  F5                   => F5,
197  F6                   => F6,
198  F7                   => F7,
199  F8                   => F8,
200  F9                   => F9,
201  F10                  => F10,
202  F11                  => F11,
203  F12                  => F12,
204  F13                  => F13,
205  F14                  => F14,
206  F15                  => F15,
207  F16                  => F16,
208  F17                  => F17,
209  F18                  => F18,
210  F19                  => F19,
211  F20                  => F20,
212  F21                  => F21,
213  F22                  => F22,
214  F23                  => F23,
215  F24                  => F24,
216  F25                  => F25,
217  F26                  => F26,
218  F27                  => F27,
219  F28                  => F28,
220  F29                  => F29,
221  F30                  => F30,
222  F31                  => F31,
223  F32                  => F32,
224  F33                  => F33,
225  F34                  => F34,
226  F35                  => F35
227}
228
229impl Keycode {
230  /// Space, alphanumeric, punctuation keys
231  pub const fn is_printable (self) -> bool {
232    use Keycode::*;
233    matches!(self,
234      Space | Grave |
235      Key1 | Key2 | Key3 | Key4 | Key5 | Key6 | Key7 | Key8 | Key9 | Key0 |
236      Minus | Equal | LBracket | RBracket | Backslash | Semicolon | Quote | Comma |
237      Period | Slash |
238      A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | 
239      U | V | W | X | Y | Z
240    )
241  }
242
243  pub fn to_char (self, modifiers : Modifiers) -> Option <char> {
244    use Keycode::*;
245    if modifiers .intersects (Modifiers::ALT | Modifiers::CTRL | Modifiers::SUPER) {
246      return None
247    }
248    let shift = modifiers.contains (Modifiers::SHIFT);
249    let ch    = match self {
250      Space     => ' ',
251      // TODO: see if keys with modifiers still produce return, tab events
252      Enter     => if !shift { '\n' } else { return None },
253      Tab       => if !shift { '\t' } else { return None },
254      Grave     => if !shift { '`'  } else { '~' },
255      Key1      => if !shift { '1'  } else { '!' },
256      Key2      => if !shift { '2'  } else { '@' },
257      Key3      => if !shift { '3'  } else { '#' },
258      Key4      => if !shift { '4'  } else { '$' },
259      Key5      => if !shift { '5'  } else { '%' },
260      Key6      => if !shift { '6'  } else { '^' },
261      Key7      => if !shift { '7'  } else { '&' },
262      Key8      => if !shift { '8'  } else { '*' },
263      Key9      => if !shift { '9'  } else { '(' },
264      Key0      => if !shift { '0'  } else { ')' },
265      Minus     => if !shift { '-'  } else { '_' },
266      Equal     => if !shift { '='  } else { '+' },
267      LBracket  => if !shift { '['  } else { '{' },
268      RBracket  => if !shift { ']'  } else { '}' },
269      Backslash => if !shift { '\\' } else { '|' },
270      Semicolon => if !shift { ';'  } else { ':' },
271      Quote     => if !shift { '\'' } else { '"' },
272      Comma     => if !shift { ','  } else { '<' },
273      Period    => if !shift { '.'  } else { '>' },
274      Slash     => if !shift { '/'  } else { '?' },
275      A         => if !shift { 'a' } else { 'A' },
276      B         => if !shift { 'b' } else { 'B' },
277      C         => if !shift { 'c' } else { 'C' },
278      D         => if !shift { 'd' } else { 'D' },
279      E         => if !shift { 'e' } else { 'E' },
280      F         => if !shift { 'f' } else { 'F' },
281      G         => if !shift { 'g' } else { 'G' },
282      H         => if !shift { 'h' } else { 'H' },
283      I         => if !shift { 'i' } else { 'I' },
284      J         => if !shift { 'j' } else { 'J' },
285      K         => if !shift { 'k' } else { 'K' },
286      L         => if !shift { 'l' } else { 'L' },
287      M         => if !shift { 'm' } else { 'M' },
288      N         => if !shift { 'n' } else { 'N' },
289      O         => if !shift { 'o' } else { 'O' },
290      P         => if !shift { 'p' } else { 'P' },
291      Q         => if !shift { 'q' } else { 'Q' },
292      R         => if !shift { 'r' } else { 'R' },
293      S         => if !shift { 's' } else { 'S' },
294      T         => if !shift { 't' } else { 'T' },
295      U         => if !shift { 'u' } else { 'U' },
296      V         => if !shift { 'v' } else { 'V' },
297      W         => if !shift { 'w' } else { 'W' },
298      X         => if !shift { 'x' } else { 'X' },
299      Y         => if !shift { 'y' } else { 'Y' },
300      Z         => if !shift { 'z' } else { 'Z' },
301      _         => return None
302    };
303    Some (ch)
304  }
305}
306
307impl TryFrom <char> for Keycode {
308  type Error = ();
309  fn try_from (ch : char) -> Result <Self, Self::Error> {
310    use Keycode::*;
311    let keycode = match ch {
312      ' '        => Space,
313      '\n'       => Enter,
314      '\t'       => Tab,
315      '`' | '~'  => Grave,
316      '1' | '!'  => Key1,
317      '2' | '@'  => Key2,
318      '3' | '#'  => Key3,
319      '4' | '$'  => Key4,
320      '5' | '%'  => Key5,
321      '6' | '^'  => Key6,
322      '7' | '&'  => Key7,
323      '8' | '*'  => Key8,
324      '9' | '('  => Key9,
325      '0' | ')'  => Key0,
326      '-' | '_'  => Minus,
327      '=' | '+'  => Equal,
328      '[' | '{'  => LBracket,
329      ']' | '}'  => RBracket,
330      '|' | '\\' => Backslash,
331      ';' | ':'  => Semicolon,
332      '\'' | '"' => Quote,
333      ',' | '<'  => Comma,
334      '.' | '>'  => Period,
335      '/' | '?'  => Slash,
336      'a' | 'A'  => A,
337      'b' | 'B'  => B,
338      'c' | 'C'  => C,
339      'd' | 'D'  => D,
340      'e' | 'E'  => E,
341      'f' | 'F'  => F,
342      'g' | 'G'  => G,
343      'h' | 'H'  => H,
344      'i' | 'I'  => I,
345      'j' | 'J'  => J,
346      'k' | 'K'  => K,
347      'l' | 'L'  => L,
348      'm' | 'M'  => M,
349      'n' | 'N'  => N,
350      'o' | 'O'  => O,
351      'p' | 'P'  => P,
352      'q' | 'Q'  => Q,
353      'r' | 'R'  => R,
354      's' | 'S'  => S,
355      't' | 'T'  => T,
356      'u' | 'U'  => U,
357      'v' | 'V'  => V,
358      'w' | 'W'  => W,
359      'x' | 'X'  => X,
360      'y' | 'Y'  => Y,
361      'z' | 'Z'  => Z,
362      _ => return Err(())
363    };
364    Ok (keycode)
365  }
366}
367
368#[cfg(feature = "opengl")]
369#[cfg_attr(docsrs, doc(cfg(feature="opengl")))]
370impl From <(winit::keyboard::NamedKey, winit::keyboard::KeyLocation)>
371  for Keycode
372{
373  fn from (
374    (key, location) : (winit::keyboard::NamedKey, winit::keyboard::KeyLocation)
375  ) -> Self {
376    use winit::keyboard::NamedKey::*;
377    use winit::keyboard::KeyLocation::*;
378    match key {
379      //Backquote                     => Keycode::Backquote,
380      //Backslash                     => Keycode::Backslash,
381      //BracketLeft                   => Keycode::BracketLeft,
382      //BracketRight                  => Keycode::BracketRight,
383      //Comma                         => Keycode::Comma,
384      //Digit0                        => Keycode::Digit0,
385      //Digit1                        => Keycode::Digit1,
386      //Digit2                        => Keycode::Digit2,
387      //Digit3                        => Keycode::Digit3,
388      //Digit4                        => Keycode::Digit4,
389      //Digit5                        => Keycode::Digit5,
390      //Digit6                        => Keycode::Digit6,
391      //Digit7                        => Keycode::Digit7,
392      //Digit8                        => Keycode::Digit8,
393      //Digit9                        => Keycode::Digit9,
394      //Equal                         => Keycode::Equal,
395      //IntlBackslash                 => Keycode::IntlBackslash,
396      //IntlRo                        => Keycode::IntlRo,
397      //IntlYen                       => Keycode::IntlYen,
398      //KeyA                          => Keycode::KeyA,
399      //KeyB                          => Keycode::KeyB,
400      //KeyC                          => Keycode::KeyC,
401      //KeyD                          => Keycode::KeyD,
402      //KeyE                          => Keycode::KeyE,
403      //KeyF                          => Keycode::KeyF,
404      //KeyG                          => Keycode::KeyG,
405      //KeyH                          => Keycode::KeyH,
406      //KeyI                          => Keycode::KeyI,
407      //KeyJ                          => Keycode::KeyJ,
408      //KeyK                          => Keycode::KeyK,
409      //KeyL                          => Keycode::KeyL,
410      //KeyM                          => Keycode::KeyM,
411      //KeyN                          => Keycode::KeyN,
412      //KeyO                          => Keycode::KeyO,
413      //KeyP                          => Keycode::KeyP,
414      //KeyQ                          => Keycode::KeyQ,
415      //KeyR                          => Keycode::KeyR,
416      //KeyS                          => Keycode::KeyS,
417      //KeyT                          => Keycode::KeyT,
418      //KeyU                          => Keycode::KeyU,
419      //KeyV                          => Keycode::KeyV,
420      //KeyW                          => Keycode::KeyW,
421      //KeyX                          => Keycode::KeyX,
422      //KeyY                          => Keycode::KeyY,
423      //KeyZ                          => Keycode::KeyZ,
424      //Minus                         => Keycode::Minus,
425      //Period                        => Keycode::Period,
426      //Quote                         => Keycode::Quote,
427      //Semicolon                     => Keycode::Semicolon,
428      //Slash                         => Keycode::Slash,
429      Alt if location == Left         => Keycode::LAlt,
430      Alt if location == Right        => Keycode::RAlt,
431      Backspace if location != Numpad => Keycode::Backspace,
432      CapsLock                        => Keycode::CapsLock,
433      ContextMenu                     => Keycode::ContextMenu,
434      Control if location == Left     => Keycode::LControl,
435      Control if location == Right    => Keycode::RControl,
436      Enter if location != Numpad     => Keycode::Enter,
437      Super if location == Left       => Keycode::LWin,
438      Super if location == Right      => Keycode::RWin,
439      Shift if location == Left       => Keycode::LShift,
440      Shift if location == Right      => Keycode::RShift,
441      Space                           => Keycode::Space,
442      Tab                             => Keycode::Tab,
443      Convert                         => Keycode::Convert,
444      KanaMode                        => Keycode::KanaMode,
445      //Lang1                         => Keycode::Lang1,
446      //Lang2                         => Keycode::Lang2,
447      //Lang3                         => Keycode::Lang3,
448      //Lang4                         => Keycode::Lang4,
449      //Lang5                         => Keycode::Lang5,
450      NonConvert                      => Keycode::NonConvert,
451      Delete                          => Keycode::Delete,
452      End                             => Keycode::End,
453      Help                            => Keycode::Help,
454      Home                            => Keycode::Home,
455      Insert                          => Keycode::Insert,
456      PageDown                        => Keycode::PageDown,
457      PageUp                          => Keycode::PageUp,
458      ArrowDown                       => Keycode::Down,
459      ArrowLeft                       => Keycode::Left,
460      ArrowRight                      => Keycode::Right,
461      ArrowUp                         => Keycode::Up,
462      NumLock                         => Keycode::NumLock,
463      //Numpad0                       => Keycode::Numpad0,
464      //Numpad1                       => Keycode::Numpad1,
465      //Numpad2                       => Keycode::Numpad2,
466      //Numpad3                       => Keycode::Numpad3,
467      //Numpad4                       => Keycode::Numpad4,
468      //Numpad5                       => Keycode::Numpad5,
469      //Numpad6                       => Keycode::Numpad6,
470      //Numpad7                       => Keycode::Numpad7,
471      //Numpad8                       => Keycode::Numpad8,
472      //Numpad9                       => Keycode::Numpad9,
473      //NumpadAdd                     => Keycode::NumpadAdd,
474      Backspace if location == Numpad => Keycode::NumpadBackspace,
475      Clear if location == Numpad     => Keycode::NumpadClear,
476      //NumpadClearEntry              => Keycode::NumpadClearEntry,
477      //NumpadComma                   => Keycode::NumpadComma,
478      //NumpadDecimal                 => Keycode::NumpadDecimal,
479      //NumpadDivide                  => Keycode::NumpadDivide,
480      Enter if location == Numpad     => Keycode::NumpadEnter,
481      //NumpadEqual                   => Keycode::NumpadEqual,
482      //NumpadHash                    => Keycode::NumpadHash,
483      //NumpadMemoryAdd               => Keycode::NumpadMemoryAdd,
484      //NumpadMemoryClear             => Keycode::NumpadMemoryClear,
485      //NumpadMemoryRecall            => Keycode::NumpadMemoryRecall,
486      //NumpadMemoryStore             => Keycode::NumpadMemoryStore,
487      //NumpadMemorySubtract          => Keycode::NumpadMemorySubtract,
488      //NumpadMultiply                => Keycode::NumpadMultiply,
489      //NumpadParenLeft               => Keycode::NumpadParenLeft,
490      //NumpadParenRight              => Keycode::NumpadParenRight,
491      //NumpadStar                    => Keycode::NumpadStar,
492      //NumpadSubtract                => Keycode::NumpadSubtract,
493      Escape                          => Keycode::Escape,
494      Fn                              => Keycode::Fn,
495      FnLock                          => Keycode::FnLock,
496      PrintScreen                     => Keycode::PrintScreen,
497      ScrollLock                      => Keycode::ScrollLock,
498      Pause                           => Keycode::Pause,
499      BrowserBack                     => Keycode::BrowserBack,
500      BrowserFavorites                => Keycode::BrowserFavorites,
501      BrowserForward                  => Keycode::BrowserForward,
502      BrowserHome                     => Keycode::BrowserHome,
503      BrowserRefresh                  => Keycode::BrowserRefresh,
504      BrowserSearch                   => Keycode::BrowserSearch,
505      BrowserStop                     => Keycode::BrowserStop,
506      Eject                           => Keycode::Eject,
507      LaunchApplication1              => Keycode::LaunchApp1,
508      LaunchApplication2              => Keycode::LaunchApp2,
509      LaunchMail                      => Keycode::LaunchMail,
510      MediaPlayPause                  => Keycode::MediaPlayPause,
511      //MediaSelect                   => Keycode::MediaSelect,
512      MediaStop                       => Keycode::MediaStop,
513      MediaTrackNext                  => Keycode::MediaTrackNext,
514      MediaTrackPrevious              => Keycode::MediaTrackPrevious,
515      Power                           => Keycode::Power,
516      Standby                         => Keycode::Sleep,
517      AudioVolumeDown                 => Keycode::AudioVolumeDown,
518      AudioVolumeMute                 => Keycode::AudioVolumeMute,
519      AudioVolumeUp                   => Keycode::AudioVolumeUp,
520      WakeUp                          => Keycode::WakeUp,
521      Meta                            => Keycode::Meta,
522      Hyper                           => Keycode::Hyper,
523      //Turbo                         => Keycode::Turbo,
524      //Abort                         => Keycode::Abort,
525      //Resume                        => Keycode::Resume,
526      //Suspend                       => Keycode::Suspend,
527      Again                           => Keycode::Again,
528      Copy                            => Keycode::Copy,
529      Cut                             => Keycode::Cut,
530      Find                            => Keycode::Find,
531      Open                            => Keycode::Open,
532      Paste                           => Keycode::Paste,
533      Props                           => Keycode::Props,
534      Select                          => Keycode::Select,
535      Undo                            => Keycode::Undo,
536      Hiragana                        => Keycode::Hiragana,
537      Katakana                        => Keycode::Katakana,
538      F1                              => Keycode::F1,
539      F2                              => Keycode::F2,
540      F3                              => Keycode::F3,
541      F4                              => Keycode::F4,
542      F5                              => Keycode::F5,
543      F6                              => Keycode::F6,
544      F7                              => Keycode::F7,
545      F8                              => Keycode::F8,
546      F9                              => Keycode::F9,
547      F10                             => Keycode::F10,
548      F11                             => Keycode::F11,
549      F12                             => Keycode::F12,
550      F13                             => Keycode::F13,
551      F14                             => Keycode::F14,
552      F15                             => Keycode::F15,
553      F16                             => Keycode::F16,
554      F17                             => Keycode::F17,
555      F18                             => Keycode::F18,
556      F19                             => Keycode::F19,
557      F20                             => Keycode::F20,
558      F21                             => Keycode::F21,
559      F22                             => Keycode::F22,
560      F23                             => Keycode::F23,
561      F24                             => Keycode::F24,
562      F25                             => Keycode::F25,
563      F26                             => Keycode::F26,
564      F27                             => Keycode::F27,
565      F28                             => Keycode::F28,
566      F29                             => Keycode::F29,
567      F30                             => Keycode::F30,
568      F31                             => Keycode::F31,
569      F32                             => Keycode::F32,
570      F33                             => Keycode::F33,
571      F34                             => Keycode::F34,
572      F35                             => Keycode::F35,
573      _ => unimplemented!("unimplemented named key conversion: {:?}",
574        (key, location))
575    }
576  }
577}