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
29impl_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 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 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 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 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 Backspace if location == Numpad => Keycode::NumpadBackspace,
475 Clear if location == Numpad => Keycode::NumpadClear,
476 Enter if location == Numpad => Keycode::NumpadEnter,
481 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 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 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}