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 fn is_printable (self) -> bool {
232 use Keycode::*;
233 match self {
234 Space | Grave |
235 Key1 | Key2 | Key3 | Key4 | Key5 | Key6 | Key7 | Key8 | Key9 | Key0 |
236 Minus | Equal | LBracket | RBracket | Backslash | Semicolon | Quote |
237 Comma | Period | Slash |
238 A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R |
239 S | T | U | V | W | X | Y | Z => true,
240 _ => false
241 }
242 }
243
244 pub fn to_char (self, modifiers : Modifiers) -> Option <char> {
245 use Keycode::*;
246 if modifiers
247 .intersects (Modifiers::ALT | Modifiers::CTRL | Modifiers::SUPER)
248 {
249 return None
250 }
251 let shift = modifiers.contains (Modifiers::SHIFT);
252 let ch = match self {
253 Space => ' ',
254 Enter => if !shift { '\n' } else { return None },
256 Tab => if !shift { '\t' } else { return None },
257 Grave => if !shift { '`' } else { '~' },
258 Key1 => if !shift { '1' } else { '!' },
259 Key2 => if !shift { '2' } else { '@' },
260 Key3 => if !shift { '3' } else { '#' },
261 Key4 => if !shift { '4' } else { '$' },
262 Key5 => if !shift { '5' } else { '%' },
263 Key6 => if !shift { '6' } else { '^' },
264 Key7 => if !shift { '7' } else { '&' },
265 Key8 => if !shift { '8' } else { '*' },
266 Key9 => if !shift { '9' } else { '(' },
267 Key0 => if !shift { '0' } else { ')' },
268 Minus => if !shift { '-' } else { '_' },
269 Equal => if !shift { '=' } else { '+' },
270 LBracket => if !shift { '[' } else { '{' },
271 RBracket => if !shift { ']' } else { '}' },
272 Backslash => if !shift { '\\' } else { '|' },
273 Semicolon => if !shift { ';' } else { ':' },
274 Quote => if !shift { '\'' } else { '"' },
275 Comma => if !shift { ',' } else { '<' },
276 Period => if !shift { '.' } else { '>' },
277 Slash => if !shift { '/' } else { '?' },
278 A => if !shift { 'a' } else { 'A' },
279 B => if !shift { 'b' } else { 'B' },
280 C => if !shift { 'c' } else { 'C' },
281 D => if !shift { 'd' } else { 'D' },
282 E => if !shift { 'e' } else { 'E' },
283 F => if !shift { 'f' } else { 'F' },
284 G => if !shift { 'g' } else { 'G' },
285 H => if !shift { 'h' } else { 'H' },
286 I => if !shift { 'i' } else { 'I' },
287 J => if !shift { 'j' } else { 'J' },
288 K => if !shift { 'k' } else { 'K' },
289 L => if !shift { 'l' } else { 'L' },
290 M => if !shift { 'm' } else { 'M' },
291 N => if !shift { 'n' } else { 'N' },
292 O => if !shift { 'o' } else { 'O' },
293 P => if !shift { 'p' } else { 'P' },
294 Q => if !shift { 'q' } else { 'Q' },
295 R => if !shift { 'r' } else { 'R' },
296 S => if !shift { 's' } else { 'S' },
297 T => if !shift { 't' } else { 'T' },
298 U => if !shift { 'u' } else { 'U' },
299 V => if !shift { 'v' } else { 'V' },
300 W => if !shift { 'w' } else { 'W' },
301 X => if !shift { 'x' } else { 'X' },
302 Y => if !shift { 'y' } else { 'Y' },
303 Z => if !shift { 'z' } else { 'Z' },
304 _ => return None
305 };
306 Some (ch)
307 }
308}
309
310impl TryFrom <char> for Keycode {
311 type Error = ();
312 fn try_from (ch : char) -> Result <Self, Self::Error> {
313 use Keycode::*;
314 let keycode = match ch {
315 ' ' => Space,
316 '\n' => Enter,
317 '\t' => Tab,
318 '`' | '~' => Grave,
319 '1' | '!' => Key1,
320 '2' | '@' => Key2,
321 '3' | '#' => Key3,
322 '4' | '$' => Key4,
323 '5' | '%' => Key5,
324 '6' | '^' => Key6,
325 '7' | '&' => Key7,
326 '8' | '*' => Key8,
327 '9' | '(' => Key9,
328 '0' | ')' => Key0,
329 '-' | '_' => Minus,
330 '=' | '+' => Equal,
331 '[' | '{' => LBracket,
332 ']' | '}' => RBracket,
333 '|' | '\\' => Backslash,
334 ';' | ':' => Semicolon,
335 '\'' | '"' => Quote,
336 ',' | '<' => Comma,
337 '.' | '>' => Period,
338 '/' | '?' => Slash,
339 'a' | 'A' => A,
340 'b' | 'B' => B,
341 'c' | 'C' => C,
342 'd' | 'D' => D,
343 'e' | 'E' => E,
344 'f' | 'F' => F,
345 'g' | 'G' => G,
346 'h' | 'H' => H,
347 'i' | 'I' => I,
348 'j' | 'J' => J,
349 'k' | 'K' => K,
350 'l' | 'L' => L,
351 'm' | 'M' => M,
352 'n' | 'N' => N,
353 'o' | 'O' => O,
354 'p' | 'P' => P,
355 'q' | 'Q' => Q,
356 'r' | 'R' => R,
357 's' | 'S' => S,
358 't' | 'T' => T,
359 'u' | 'U' => U,
360 'v' | 'V' => V,
361 'w' | 'W' => W,
362 'x' | 'X' => X,
363 'y' | 'Y' => Y,
364 'z' | 'Z' => Z,
365 _ => return Err(())
366 };
367 Ok (keycode)
368 }
369}
370
371#[cfg(feature = "opengl")]
372#[cfg_attr(docsrs, doc(cfg(feature="opengl")))]
373impl From <(winit::keyboard::NamedKey, winit::keyboard::KeyLocation)>
374 for Keycode
375{
376 fn from (
377 (key, location) : (winit::keyboard::NamedKey, winit::keyboard::KeyLocation)
378 ) -> Self {
379 use winit::keyboard::NamedKey::*;
380 use winit::keyboard::KeyLocation::*;
381 match key {
382 Alt if location == Left => Keycode::LAlt,
433 Alt if location == Right => Keycode::RAlt,
434 Backspace if location != Numpad => Keycode::Backspace,
435 CapsLock => Keycode::CapsLock,
436 ContextMenu => Keycode::ContextMenu,
437 Control if location == Left => Keycode::LControl,
438 Control if location == Right => Keycode::RControl,
439 Enter if location != Numpad => Keycode::Enter,
440 Super if location == Left => Keycode::LWin,
441 Super if location == Right => Keycode::RWin,
442 Shift if location == Left => Keycode::LShift,
443 Shift if location == Right => Keycode::RShift,
444 Space => Keycode::Space,
445 Tab => Keycode::Tab,
446 Convert => Keycode::Convert,
447 KanaMode => Keycode::KanaMode,
448 NonConvert => Keycode::NonConvert,
454 Delete => Keycode::Delete,
455 End => Keycode::End,
456 Help => Keycode::Help,
457 Home => Keycode::Home,
458 Insert => Keycode::Insert,
459 PageDown => Keycode::PageDown,
460 PageUp => Keycode::PageUp,
461 ArrowDown => Keycode::Down,
462 ArrowLeft => Keycode::Left,
463 ArrowRight => Keycode::Right,
464 ArrowUp => Keycode::Up,
465 NumLock => Keycode::NumLock,
466 Backspace if location == Numpad => Keycode::NumpadBackspace,
478 Clear if location == Numpad => Keycode::NumpadClear,
479 Enter if location == Numpad => Keycode::NumpadEnter,
484 Escape => Keycode::Escape,
497 Fn => Keycode::Fn,
498 FnLock => Keycode::FnLock,
499 PrintScreen => Keycode::PrintScreen,
500 ScrollLock => Keycode::ScrollLock,
501 Pause => Keycode::Pause,
502 BrowserBack => Keycode::BrowserBack,
503 BrowserFavorites => Keycode::BrowserFavorites,
504 BrowserForward => Keycode::BrowserForward,
505 BrowserHome => Keycode::BrowserHome,
506 BrowserRefresh => Keycode::BrowserRefresh,
507 BrowserSearch => Keycode::BrowserSearch,
508 BrowserStop => Keycode::BrowserStop,
509 Eject => Keycode::Eject,
510 LaunchApplication1 => Keycode::LaunchApp1,
511 LaunchApplication2 => Keycode::LaunchApp2,
512 LaunchMail => Keycode::LaunchMail,
513 MediaPlayPause => Keycode::MediaPlayPause,
514 MediaStop => Keycode::MediaStop,
516 MediaTrackNext => Keycode::MediaTrackNext,
517 MediaTrackPrevious => Keycode::MediaTrackPrevious,
518 Power => Keycode::Power,
519 Standby => Keycode::Sleep,
520 AudioVolumeDown => Keycode::AudioVolumeDown,
521 AudioVolumeMute => Keycode::AudioVolumeMute,
522 AudioVolumeUp => Keycode::AudioVolumeUp,
523 WakeUp => Keycode::WakeUp,
524 Meta => Keycode::Meta,
525 Hyper => Keycode::Hyper,
526 Again => Keycode::Again,
531 Copy => Keycode::Copy,
532 Cut => Keycode::Cut,
533 Find => Keycode::Find,
534 Open => Keycode::Open,
535 Paste => Keycode::Paste,
536 Props => Keycode::Props,
537 Select => Keycode::Select,
538 Undo => Keycode::Undo,
539 Hiragana => Keycode::Hiragana,
540 Katakana => Keycode::Katakana,
541 F1 => Keycode::F1,
542 F2 => Keycode::F2,
543 F3 => Keycode::F3,
544 F4 => Keycode::F4,
545 F5 => Keycode::F5,
546 F6 => Keycode::F6,
547 F7 => Keycode::F7,
548 F8 => Keycode::F8,
549 F9 => Keycode::F9,
550 F10 => Keycode::F10,
551 F11 => Keycode::F11,
552 F12 => Keycode::F12,
553 F13 => Keycode::F13,
554 F14 => Keycode::F14,
555 F15 => Keycode::F15,
556 F16 => Keycode::F16,
557 F17 => Keycode::F17,
558 F18 => Keycode::F18,
559 F19 => Keycode::F19,
560 F20 => Keycode::F20,
561 F21 => Keycode::F21,
562 F22 => Keycode::F22,
563 F23 => Keycode::F23,
564 F24 => Keycode::F24,
565 F25 => Keycode::F25,
566 F26 => Keycode::F26,
567 F27 => Keycode::F27,
568 F28 => Keycode::F28,
569 F29 => Keycode::F29,
570 F30 => Keycode::F30,
571 F31 => Keycode::F31,
572 F32 => Keycode::F32,
573 F33 => Keycode::F33,
574 F34 => Keycode::F34,
575 F35 => Keycode::F35,
576 _ => unimplemented!("unimplemented named key conversion: {:?}",
577 (key, location))
578 }
579 }
580}