1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
//! Virtual key codes corresponded to physical scan codes.

#![allow(missing_docs)]

use std::ffi::{CStr, CString};

use crate::{bind, EnumInt};

use super::scan_code::ScanCode;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum KeyCode {
    Unknown,
    Return,
    Escape,
    Backspace,
    Tab,
    Space,
    Exclaim,
    Quotedbl,
    Hash,
    Percent,
    Dollar,
    Ampersand,
    Quote,
    Leftparen,
    Rightparen,
    Asterisk,
    Plus,
    Comma,
    Minus,
    Period,
    Slash,
    Num0,
    Num1,
    Num2,
    Num3,
    Num4,
    Num5,
    Num6,
    Num7,
    Num8,
    Num9,
    Colon,
    Semicolon,
    Less,
    Equals,
    Greater,
    Question,
    At,
    LeftBracket,
    Backslash,
    RightBracket,
    Caret,
    Underscore,
    Backquote,
    A,
    B,
    C,
    D,
    E,
    F,
    G,
    H,
    I,
    J,
    K,
    L,
    M,
    N,
    O,
    P,
    Q,
    R,
    S,
    T,
    U,
    V,
    W,
    X,
    Y,
    Z,
    CapsLock,
    F1,
    F2,
    F3,
    F4,
    F5,
    F6,
    F7,
    F8,
    F9,
    F10,
    F11,
    F12,
    PrintScreen,
    ScrollLock,
    Pause,
    Insert,
    Home,
    PageUp,
    Delete,
    End,
    PageDown,
    Right,
    Left,
    Down,
    Up,
    NumLockClear,
    KeypadDivide,
    KeypadMultiply,
    KeypadMinus,
    KeypadPlus,
    KeypadEnter,
    Keypad1,
    Keypad2,
    Keypad3,
    Keypad4,
    Keypad5,
    Keypad6,
    Keypad7,
    Keypad8,
    Keypad9,
    Keypad0,
    KeypadPeriod,
    Application,
    Power,
    KeypadEquals,
    F13,
    F14,
    F15,
    F16,
    F17,
    F18,
    F19,
    F20,
    F21,
    F22,
    F23,
    F24,
    Execute,
    Help,
    Menu,
    Select,
    Stop,
    Again,
    Undo,
    Cut,
    Copy,
    Paste,
    Find,
    Mute,
    VolumeUp,
    VolumeDown,
    KeypadComma,
    KeypadEqualsAs400,
    Alterase,
    SysReq,
    Cancel,
    Clear,
    Prior,
    Return2,
    Separator,
    Out,
    Oper,
    ClearAgain,
    CrSel,
    ExSel,
    Keypad00,
    Keypad000,
    ThousandsSeparator,
    DecimalSeparator,
    CurrencyUnit,
    CurrencySubunit,
    KeypadLeftParen,
    KeypadRightParen,
    KeypadLeftBrace,
    KeypadRightBrace,
    KeypadTab,
    KeypadBackspace,
    KeypadA,
    KeypadB,
    KeypadC,
    KeypadD,
    KeypadE,
    KeypadF,
    KeypadXor,
    KeypadPower,
    KeypadPercent,
    KeypadLess,
    KeypadGreater,
    KeypadAmpersand,
    KeypadDblAmpersand,
    KeypadVerticalBar,
    KeypadDblverticalBar,
    KeypadColon,
    KeypadHash,
    KeypadSpace,
    KeypadAt,
    KeypadExclam,
    KeypadMemStore,
    KeypadMemRecall,
    KeypadMemClear,
    KeypadMemAdd,
    KeypadMemSubtract,
    KeypadMemMultiply,
    KeypadMemDivide,
    KeypadPlusMinus,
    KeypadClear,
    KeypadClearEntry,
    KeypadBinary,
    KeypadOctal,
    KeypadDecimal,
    KeypadHexadecimal,
    LCtrl,
    LShift,
    LAlt,
    LGui,
    RCtrl,
    RShift,
    RAlt,
    RGui,
    Mode,
    AudioNext,
    AudioPrev,
    AudioStop,
    AudioPlay,
    AudioMute,
    MediaSelect,
    Www,
    Mail,
    Calculator,
    Computer,
    ApplicationSearch,
    ApplicationHome,
    ApplicationBack,
    ApplicationForward,
    ApplicationStop,
    ApplicationRefresh,
    ApplicationBookmarks,
    BrightnessDown,
    BrightnessUp,
    DisplaySwitch,
    KeyboardIllumToggle,
    KeyboardIllumDown,
    KeyboardIllumUp,
    Eject,
    Sleep,
    App1,
    App2,
    AudioRewind,
    AudioFastForward,
}

impl KeyCode {
    #[must_use]
    pub fn from_name(name: &str) -> Self {
        let c_str = CString::new(name).expect("name must be a valid string");
        unsafe { bind::SDL_GetKeyFromName(c_str.as_ptr()) }.into()
    }

    #[must_use]
    pub fn name(&self) -> Option<String> {
        let name: String = unsafe { CStr::from_ptr(bind::SDL_GetKeyName(self.as_raw())) }
            .to_str()
            .unwrap()
            .into();
        (!name.is_empty()).then(|| name)
    }

    pub(crate) fn as_raw(self) -> bind::SDL_Keycode {
        (match self {
            KeyCode::Unknown => bind::SDLK_UNKNOWN,
            KeyCode::Return => bind::SDLK_RETURN,
            KeyCode::Escape => bind::SDLK_ESCAPE,
            KeyCode::Backspace => bind::SDLK_BACKSPACE,
            KeyCode::Tab => bind::SDLK_TAB,
            KeyCode::Space => bind::SDLK_SPACE,
            KeyCode::Exclaim => bind::SDLK_EXCLAIM,
            KeyCode::Quotedbl => bind::SDLK_QUOTEDBL,
            KeyCode::Hash => bind::SDLK_HASH,
            KeyCode::Percent => bind::SDLK_PERCENT,
            KeyCode::Dollar => bind::SDLK_DOLLAR,
            KeyCode::Ampersand => bind::SDLK_AMPERSAND,
            KeyCode::Quote => bind::SDLK_QUOTE,
            KeyCode::Leftparen => bind::SDLK_LEFTPAREN,
            KeyCode::Rightparen => bind::SDLK_RIGHTPAREN,
            KeyCode::Asterisk => bind::SDLK_ASTERISK,
            KeyCode::Plus => bind::SDLK_PLUS,
            KeyCode::Comma => bind::SDLK_COMMA,
            KeyCode::Minus => bind::SDLK_MINUS,
            KeyCode::Period => bind::SDLK_PERIOD,
            KeyCode::Slash => bind::SDLK_SLASH,
            KeyCode::Num0 => bind::SDLK_0,
            KeyCode::Num1 => bind::SDLK_1,
            KeyCode::Num2 => bind::SDLK_2,
            KeyCode::Num3 => bind::SDLK_3,
            KeyCode::Num4 => bind::SDLK_4,
            KeyCode::Num5 => bind::SDLK_5,
            KeyCode::Num6 => bind::SDLK_6,
            KeyCode::Num7 => bind::SDLK_7,
            KeyCode::Num8 => bind::SDLK_8,
            KeyCode::Num9 => bind::SDLK_9,
            KeyCode::Colon => bind::SDLK_COLON,
            KeyCode::Semicolon => bind::SDLK_SEMICOLON,
            KeyCode::Less => bind::SDLK_LESS,
            KeyCode::Equals => bind::SDLK_EQUALS,
            KeyCode::Greater => bind::SDLK_GREATER,
            KeyCode::Question => bind::SDLK_QUESTION,
            KeyCode::At => bind::SDLK_AT,
            KeyCode::LeftBracket => bind::SDLK_LEFTBRACKET,
            KeyCode::Backslash => bind::SDLK_BACKSLASH,
            KeyCode::RightBracket => bind::SDLK_RIGHTBRACKET,
            KeyCode::Caret => bind::SDLK_CARET,
            KeyCode::Underscore => bind::SDLK_UNDERSCORE,
            KeyCode::Backquote => bind::SDLK_BACKQUOTE,
            KeyCode::A => bind::SDLK_a,
            KeyCode::B => bind::SDLK_b,
            KeyCode::C => bind::SDLK_c,
            KeyCode::D => bind::SDLK_d,
            KeyCode::E => bind::SDLK_e,
            KeyCode::F => bind::SDLK_f,
            KeyCode::G => bind::SDLK_g,
            KeyCode::H => bind::SDLK_h,
            KeyCode::I => bind::SDLK_i,
            KeyCode::J => bind::SDLK_j,
            KeyCode::K => bind::SDLK_k,
            KeyCode::L => bind::SDLK_l,
            KeyCode::M => bind::SDLK_m,
            KeyCode::N => bind::SDLK_n,
            KeyCode::O => bind::SDLK_o,
            KeyCode::P => bind::SDLK_p,
            KeyCode::Q => bind::SDLK_q,
            KeyCode::R => bind::SDLK_r,
            KeyCode::S => bind::SDLK_s,
            KeyCode::T => bind::SDLK_t,
            KeyCode::U => bind::SDLK_u,
            KeyCode::V => bind::SDLK_v,
            KeyCode::W => bind::SDLK_w,
            KeyCode::X => bind::SDLK_x,
            KeyCode::Y => bind::SDLK_y,
            KeyCode::Z => bind::SDLK_z,
            KeyCode::CapsLock => bind::SDLK_CAPSLOCK,
            KeyCode::F1 => bind::SDLK_F1,
            KeyCode::F2 => bind::SDLK_F2,
            KeyCode::F3 => bind::SDLK_F3,
            KeyCode::F4 => bind::SDLK_F4,
            KeyCode::F5 => bind::SDLK_F5,
            KeyCode::F6 => bind::SDLK_F6,
            KeyCode::F7 => bind::SDLK_F7,
            KeyCode::F8 => bind::SDLK_F8,
            KeyCode::F9 => bind::SDLK_F9,
            KeyCode::F10 => bind::SDLK_F10,
            KeyCode::F11 => bind::SDLK_F11,
            KeyCode::F12 => bind::SDLK_F12,
            KeyCode::PrintScreen => bind::SDLK_PRINTSCREEN,
            KeyCode::ScrollLock => bind::SDLK_SCROLLLOCK,
            KeyCode::Pause => bind::SDLK_PAUSE,
            KeyCode::Insert => bind::SDLK_INSERT,
            KeyCode::Home => bind::SDLK_HOME,
            KeyCode::PageUp => bind::SDLK_PAGEUP,
            KeyCode::Delete => bind::SDLK_DELETE,
            KeyCode::End => bind::SDLK_END,
            KeyCode::PageDown => bind::SDLK_PAGEDOWN,
            KeyCode::Right => bind::SDLK_RIGHT,
            KeyCode::Left => bind::SDLK_LEFT,
            KeyCode::Down => bind::SDLK_DOWN,
            KeyCode::Up => bind::SDLK_UP,
            KeyCode::NumLockClear => bind::SDLK_NUMLOCKCLEAR,
            KeyCode::KeypadDivide => bind::SDLK_KP_DIVIDE,
            KeyCode::KeypadMultiply => bind::SDLK_KP_MULTIPLY,
            KeyCode::KeypadMinus => bind::SDLK_KP_MINUS,
            KeyCode::KeypadPlus => bind::SDLK_KP_PLUS,
            KeyCode::KeypadEnter => bind::SDLK_KP_ENTER,
            KeyCode::Keypad1 => bind::SDLK_KP_1,
            KeyCode::Keypad2 => bind::SDLK_KP_2,
            KeyCode::Keypad3 => bind::SDLK_KP_3,
            KeyCode::Keypad4 => bind::SDLK_KP_4,
            KeyCode::Keypad5 => bind::SDLK_KP_5,
            KeyCode::Keypad6 => bind::SDLK_KP_6,
            KeyCode::Keypad7 => bind::SDLK_KP_7,
            KeyCode::Keypad8 => bind::SDLK_KP_8,
            KeyCode::Keypad9 => bind::SDLK_KP_9,
            KeyCode::Keypad0 => bind::SDLK_KP_0,
            KeyCode::KeypadPeriod => bind::SDLK_KP_PERIOD,
            KeyCode::Application => bind::SDLK_APPLICATION,
            KeyCode::Power => bind::SDLK_POWER,
            KeyCode::KeypadEquals => bind::SDLK_KP_EQUALS,
            KeyCode::F13 => bind::SDLK_F13,
            KeyCode::F14 => bind::SDLK_F14,
            KeyCode::F15 => bind::SDLK_F15,
            KeyCode::F16 => bind::SDLK_F16,
            KeyCode::F17 => bind::SDLK_F17,
            KeyCode::F18 => bind::SDLK_F18,
            KeyCode::F19 => bind::SDLK_F19,
            KeyCode::F20 => bind::SDLK_F20,
            KeyCode::F21 => bind::SDLK_F21,
            KeyCode::F22 => bind::SDLK_F22,
            KeyCode::F23 => bind::SDLK_F23,
            KeyCode::F24 => bind::SDLK_F24,
            KeyCode::Execute => bind::SDLK_EXECUTE,
            KeyCode::Help => bind::SDLK_HELP,
            KeyCode::Menu => bind::SDLK_MENU,
            KeyCode::Select => bind::SDLK_SELECT,
            KeyCode::Stop => bind::SDLK_STOP,
            KeyCode::Again => bind::SDLK_AGAIN,
            KeyCode::Undo => bind::SDLK_UNDO,
            KeyCode::Cut => bind::SDLK_CUT,
            KeyCode::Copy => bind::SDLK_COPY,
            KeyCode::Paste => bind::SDLK_PASTE,
            KeyCode::Find => bind::SDLK_FIND,
            KeyCode::Mute => bind::SDLK_MUTE,
            KeyCode::VolumeUp => bind::SDLK_VOLUMEUP,
            KeyCode::VolumeDown => bind::SDLK_VOLUMEDOWN,
            KeyCode::KeypadComma => bind::SDLK_KP_COMMA,
            KeyCode::KeypadEqualsAs400 => bind::SDLK_KP_EQUALSAS400,
            KeyCode::Alterase => bind::SDLK_ALTERASE,
            KeyCode::SysReq => bind::SDLK_SYSREQ,
            KeyCode::Cancel => bind::SDLK_CANCEL,
            KeyCode::Clear => bind::SDLK_CLEAR,
            KeyCode::Prior => bind::SDLK_PRIOR,
            KeyCode::Return2 => bind::SDLK_RETURN2,
            KeyCode::Separator => bind::SDLK_SEPARATOR,
            KeyCode::Out => bind::SDLK_OUT,
            KeyCode::Oper => bind::SDLK_OPER,
            KeyCode::ClearAgain => bind::SDLK_CLEARAGAIN,
            KeyCode::CrSel => bind::SDLK_CRSEL,
            KeyCode::ExSel => bind::SDLK_EXSEL,
            KeyCode::Keypad00 => bind::SDLK_KP_00,
            KeyCode::Keypad000 => bind::SDLK_KP_000,
            KeyCode::ThousandsSeparator => bind::SDLK_THOUSANDSSEPARATOR,
            KeyCode::DecimalSeparator => bind::SDLK_DECIMALSEPARATOR,
            KeyCode::CurrencyUnit => bind::SDLK_CURRENCYUNIT,
            KeyCode::CurrencySubunit => bind::SDLK_CURRENCYSUBUNIT,
            KeyCode::KeypadLeftParen => bind::SDLK_KP_LEFTPAREN,
            KeyCode::KeypadRightParen => bind::SDLK_KP_RIGHTPAREN,
            KeyCode::KeypadLeftBrace => bind::SDLK_KP_LEFTBRACE,
            KeyCode::KeypadRightBrace => bind::SDLK_KP_RIGHTBRACE,
            KeyCode::KeypadTab => bind::SDLK_KP_TAB,
            KeyCode::KeypadBackspace => bind::SDLK_KP_BACKSPACE,
            KeyCode::KeypadA => bind::SDLK_KP_A,
            KeyCode::KeypadB => bind::SDLK_KP_B,
            KeyCode::KeypadC => bind::SDLK_KP_C,
            KeyCode::KeypadD => bind::SDLK_KP_D,
            KeyCode::KeypadE => bind::SDLK_KP_E,
            KeyCode::KeypadF => bind::SDLK_KP_F,
            KeyCode::KeypadXor => bind::SDLK_KP_XOR,
            KeyCode::KeypadPower => bind::SDLK_KP_POWER,
            KeyCode::KeypadPercent => bind::SDLK_KP_PERCENT,
            KeyCode::KeypadLess => bind::SDLK_KP_LESS,
            KeyCode::KeypadGreater => bind::SDLK_KP_GREATER,
            KeyCode::KeypadAmpersand => bind::SDLK_KP_AMPERSAND,
            KeyCode::KeypadDblAmpersand => bind::SDLK_KP_DBLAMPERSAND,
            KeyCode::KeypadVerticalBar => bind::SDLK_KP_VERTICALBAR,
            KeyCode::KeypadDblverticalBar => bind::SDLK_KP_DBLVERTICALBAR,
            KeyCode::KeypadColon => bind::SDLK_KP_COLON,
            KeyCode::KeypadHash => bind::SDLK_KP_HASH,
            KeyCode::KeypadSpace => bind::SDLK_KP_SPACE,
            KeyCode::KeypadAt => bind::SDLK_KP_AT,
            KeyCode::KeypadExclam => bind::SDLK_KP_EXCLAM,
            KeyCode::KeypadMemStore => bind::SDLK_KP_MEMSTORE,
            KeyCode::KeypadMemRecall => bind::SDLK_KP_MEMRECALL,
            KeyCode::KeypadMemClear => bind::SDLK_KP_MEMCLEAR,
            KeyCode::KeypadMemAdd => bind::SDLK_KP_MEMADD,
            KeyCode::KeypadMemSubtract => bind::SDLK_KP_MEMSUBTRACT,
            KeyCode::KeypadMemMultiply => bind::SDLK_KP_MEMMULTIPLY,
            KeyCode::KeypadMemDivide => bind::SDLK_KP_MEMDIVIDE,
            KeyCode::KeypadPlusMinus => bind::SDLK_KP_PLUSMINUS,
            KeyCode::KeypadClear => bind::SDLK_KP_CLEAR,
            KeyCode::KeypadClearEntry => bind::SDLK_KP_CLEARENTRY,
            KeyCode::KeypadBinary => bind::SDLK_KP_BINARY,
            KeyCode::KeypadOctal => bind::SDLK_KP_OCTAL,
            KeyCode::KeypadDecimal => bind::SDLK_KP_DECIMAL,
            KeyCode::KeypadHexadecimal => bind::SDLK_KP_HEXADECIMAL,
            KeyCode::LCtrl => bind::SDLK_LCTRL,
            KeyCode::LShift => bind::SDLK_LSHIFT,
            KeyCode::LAlt => bind::SDLK_LALT,
            KeyCode::LGui => bind::SDLK_LGUI,
            KeyCode::RCtrl => bind::SDLK_RCTRL,
            KeyCode::RShift => bind::SDLK_RSHIFT,
            KeyCode::RAlt => bind::SDLK_RALT,
            KeyCode::RGui => bind::SDLK_RGUI,
            KeyCode::Mode => bind::SDLK_MODE,
            KeyCode::AudioNext => bind::SDLK_AUDIONEXT,
            KeyCode::AudioPrev => bind::SDLK_AUDIOPREV,
            KeyCode::AudioStop => bind::SDLK_AUDIOSTOP,
            KeyCode::AudioPlay => bind::SDLK_AUDIOPLAY,
            KeyCode::AudioMute => bind::SDLK_AUDIOMUTE,
            KeyCode::MediaSelect => bind::SDLK_MEDIASELECT,
            KeyCode::Www => bind::SDLK_WWW,
            KeyCode::Mail => bind::SDLK_MAIL,
            KeyCode::Calculator => bind::SDLK_CALCULATOR,
            KeyCode::Computer => bind::SDLK_COMPUTER,
            KeyCode::ApplicationSearch => bind::SDLK_AC_SEARCH,
            KeyCode::ApplicationHome => bind::SDLK_AC_HOME,
            KeyCode::ApplicationBack => bind::SDLK_AC_BACK,
            KeyCode::ApplicationForward => bind::SDLK_AC_FORWARD,
            KeyCode::ApplicationStop => bind::SDLK_AC_STOP,
            KeyCode::ApplicationRefresh => bind::SDLK_AC_REFRESH,
            KeyCode::ApplicationBookmarks => bind::SDLK_AC_BOOKMARKS,
            KeyCode::BrightnessDown => bind::SDLK_BRIGHTNESSDOWN,
            KeyCode::BrightnessUp => bind::SDLK_BRIGHTNESSUP,
            KeyCode::DisplaySwitch => bind::SDLK_DISPLAYSWITCH,
            KeyCode::KeyboardIllumToggle => bind::SDLK_KBDILLUMTOGGLE,
            KeyCode::KeyboardIllumDown => bind::SDLK_KBDILLUMDOWN,
            KeyCode::KeyboardIllumUp => bind::SDLK_KBDILLUMUP,
            KeyCode::Eject => bind::SDLK_EJECT,
            KeyCode::Sleep => bind::SDLK_SLEEP,
            KeyCode::App1 => bind::SDLK_APP1,
            KeyCode::App2 => bind::SDLK_APP2,
            KeyCode::AudioRewind => bind::SDLK_AUDIOREWIND,
            KeyCode::AudioFastForward => bind::SDLK_AUDIOFASTFORWARD,
        }) as bind::SDL_Keycode
    }
}

impl From<ScanCode> for KeyCode {
    fn from(scan_code: ScanCode) -> Self {
        let raw = scan_code.as_raw();
        unsafe { bind::SDL_GetKeyFromScancode(raw) }.into()
    }
}

impl From<bind::SDL_Keycode> for KeyCode {
    fn from(code: bind::SDL_Keycode) -> Self {
        match code as EnumInt {
            bind::SDLK_RETURN => KeyCode::Return,
            bind::SDLK_ESCAPE => KeyCode::Escape,
            bind::SDLK_BACKSPACE => KeyCode::Backspace,
            bind::SDLK_TAB => KeyCode::Tab,
            bind::SDLK_SPACE => KeyCode::Space,
            bind::SDLK_EXCLAIM => KeyCode::Exclaim,
            bind::SDLK_QUOTEDBL => KeyCode::Quotedbl,
            bind::SDLK_HASH => KeyCode::Hash,
            bind::SDLK_PERCENT => KeyCode::Percent,
            bind::SDLK_DOLLAR => KeyCode::Dollar,
            bind::SDLK_AMPERSAND => KeyCode::Ampersand,
            bind::SDLK_QUOTE => KeyCode::Quote,
            bind::SDLK_LEFTPAREN => KeyCode::Leftparen,
            bind::SDLK_RIGHTPAREN => KeyCode::Rightparen,
            bind::SDLK_ASTERISK => KeyCode::Asterisk,
            bind::SDLK_PLUS => KeyCode::Plus,
            bind::SDLK_COMMA => KeyCode::Comma,
            bind::SDLK_MINUS => KeyCode::Minus,
            bind::SDLK_PERIOD => KeyCode::Period,
            bind::SDLK_SLASH => KeyCode::Slash,
            bind::SDLK_0 => KeyCode::Num0,
            bind::SDLK_1 => KeyCode::Num1,
            bind::SDLK_2 => KeyCode::Num2,
            bind::SDLK_3 => KeyCode::Num3,
            bind::SDLK_4 => KeyCode::Num4,
            bind::SDLK_5 => KeyCode::Num5,
            bind::SDLK_6 => KeyCode::Num6,
            bind::SDLK_7 => KeyCode::Num7,
            bind::SDLK_8 => KeyCode::Num8,
            bind::SDLK_9 => KeyCode::Num9,
            bind::SDLK_COLON => KeyCode::Colon,
            bind::SDLK_SEMICOLON => KeyCode::Semicolon,
            bind::SDLK_LESS => KeyCode::Less,
            bind::SDLK_EQUALS => KeyCode::Equals,
            bind::SDLK_GREATER => KeyCode::Greater,
            bind::SDLK_QUESTION => KeyCode::Question,
            bind::SDLK_AT => KeyCode::At,
            bind::SDLK_LEFTBRACKET => KeyCode::LeftBracket,
            bind::SDLK_BACKSLASH => KeyCode::Backslash,
            bind::SDLK_RIGHTBRACKET => KeyCode::RightBracket,
            bind::SDLK_CARET => KeyCode::Caret,
            bind::SDLK_UNDERSCORE => KeyCode::Underscore,
            bind::SDLK_BACKQUOTE => KeyCode::Backquote,
            bind::SDLK_a => KeyCode::A,
            bind::SDLK_b => KeyCode::B,
            bind::SDLK_c => KeyCode::C,
            bind::SDLK_d => KeyCode::D,
            bind::SDLK_e => KeyCode::E,
            bind::SDLK_f => KeyCode::F,
            bind::SDLK_g => KeyCode::G,
            bind::SDLK_h => KeyCode::H,
            bind::SDLK_i => KeyCode::I,
            bind::SDLK_j => KeyCode::J,
            bind::SDLK_k => KeyCode::K,
            bind::SDLK_l => KeyCode::L,
            bind::SDLK_m => KeyCode::M,
            bind::SDLK_n => KeyCode::N,
            bind::SDLK_o => KeyCode::O,
            bind::SDLK_p => KeyCode::P,
            bind::SDLK_q => KeyCode::Q,
            bind::SDLK_r => KeyCode::R,
            bind::SDLK_s => KeyCode::S,
            bind::SDLK_t => KeyCode::T,
            bind::SDLK_u => KeyCode::U,
            bind::SDLK_v => KeyCode::V,
            bind::SDLK_w => KeyCode::W,
            bind::SDLK_x => KeyCode::X,
            bind::SDLK_y => KeyCode::Y,
            bind::SDLK_z => KeyCode::Z,
            bind::SDLK_CAPSLOCK => KeyCode::CapsLock,
            bind::SDLK_F1 => KeyCode::F1,
            bind::SDLK_F2 => KeyCode::F2,
            bind::SDLK_F3 => KeyCode::F3,
            bind::SDLK_F4 => KeyCode::F4,
            bind::SDLK_F5 => KeyCode::F5,
            bind::SDLK_F6 => KeyCode::F6,
            bind::SDLK_F7 => KeyCode::F7,
            bind::SDLK_F8 => KeyCode::F8,
            bind::SDLK_F9 => KeyCode::F9,
            bind::SDLK_F10 => KeyCode::F10,
            bind::SDLK_F11 => KeyCode::F11,
            bind::SDLK_F12 => KeyCode::F12,
            bind::SDLK_PRINTSCREEN => KeyCode::PrintScreen,
            bind::SDLK_SCROLLLOCK => KeyCode::ScrollLock,
            bind::SDLK_PAUSE => KeyCode::Pause,
            bind::SDLK_INSERT => KeyCode::Insert,
            bind::SDLK_HOME => KeyCode::Home,
            bind::SDLK_PAGEUP => KeyCode::PageUp,
            bind::SDLK_DELETE => KeyCode::Delete,
            bind::SDLK_END => KeyCode::End,
            bind::SDLK_PAGEDOWN => KeyCode::PageDown,
            bind::SDLK_RIGHT => KeyCode::Right,
            bind::SDLK_LEFT => KeyCode::Left,
            bind::SDLK_DOWN => KeyCode::Down,
            bind::SDLK_UP => KeyCode::Up,
            bind::SDLK_NUMLOCKCLEAR => KeyCode::NumLockClear,
            bind::SDLK_KP_DIVIDE => KeyCode::KeypadDivide,
            bind::SDLK_KP_MULTIPLY => KeyCode::KeypadMultiply,
            bind::SDLK_KP_MINUS => KeyCode::KeypadMinus,
            bind::SDLK_KP_PLUS => KeyCode::KeypadPlus,
            bind::SDLK_KP_ENTER => KeyCode::KeypadEnter,
            bind::SDLK_KP_1 => KeyCode::Keypad1,
            bind::SDLK_KP_2 => KeyCode::Keypad2,
            bind::SDLK_KP_3 => KeyCode::Keypad3,
            bind::SDLK_KP_4 => KeyCode::Keypad4,
            bind::SDLK_KP_5 => KeyCode::Keypad5,
            bind::SDLK_KP_6 => KeyCode::Keypad6,
            bind::SDLK_KP_7 => KeyCode::Keypad7,
            bind::SDLK_KP_8 => KeyCode::Keypad8,
            bind::SDLK_KP_9 => KeyCode::Keypad9,
            bind::SDLK_KP_0 => KeyCode::Keypad0,
            bind::SDLK_KP_PERIOD => KeyCode::KeypadPeriod,
            bind::SDLK_APPLICATION => KeyCode::Application,
            bind::SDLK_POWER => KeyCode::Power,
            bind::SDLK_KP_EQUALS => KeyCode::KeypadEquals,
            bind::SDLK_F13 => KeyCode::F13,
            bind::SDLK_F14 => KeyCode::F14,
            bind::SDLK_F15 => KeyCode::F15,
            bind::SDLK_F16 => KeyCode::F16,
            bind::SDLK_F17 => KeyCode::F17,
            bind::SDLK_F18 => KeyCode::F18,
            bind::SDLK_F19 => KeyCode::F19,
            bind::SDLK_F20 => KeyCode::F20,
            bind::SDLK_F21 => KeyCode::F21,
            bind::SDLK_F22 => KeyCode::F22,
            bind::SDLK_F23 => KeyCode::F23,
            bind::SDLK_F24 => KeyCode::F24,
            bind::SDLK_EXECUTE => KeyCode::Execute,
            bind::SDLK_HELP => KeyCode::Help,
            bind::SDLK_MENU => KeyCode::Menu,
            bind::SDLK_SELECT => KeyCode::Select,
            bind::SDLK_STOP => KeyCode::Stop,
            bind::SDLK_AGAIN => KeyCode::Again,
            bind::SDLK_UNDO => KeyCode::Undo,
            bind::SDLK_CUT => KeyCode::Cut,
            bind::SDLK_COPY => KeyCode::Copy,
            bind::SDLK_PASTE => KeyCode::Paste,
            bind::SDLK_FIND => KeyCode::Find,
            bind::SDLK_MUTE => KeyCode::Mute,
            bind::SDLK_VOLUMEUP => KeyCode::VolumeUp,
            bind::SDLK_VOLUMEDOWN => KeyCode::VolumeDown,
            bind::SDLK_KP_COMMA => KeyCode::KeypadComma,
            bind::SDLK_KP_EQUALSAS400 => KeyCode::KeypadEqualsAs400,
            bind::SDLK_ALTERASE => KeyCode::Alterase,
            bind::SDLK_SYSREQ => KeyCode::SysReq,
            bind::SDLK_CANCEL => KeyCode::Cancel,
            bind::SDLK_CLEAR => KeyCode::Clear,
            bind::SDLK_PRIOR => KeyCode::Prior,
            bind::SDLK_RETURN2 => KeyCode::Return2,
            bind::SDLK_SEPARATOR => KeyCode::Separator,
            bind::SDLK_OUT => KeyCode::Out,
            bind::SDLK_OPER => KeyCode::Oper,
            bind::SDLK_CLEARAGAIN => KeyCode::ClearAgain,
            bind::SDLK_CRSEL => KeyCode::CrSel,
            bind::SDLK_EXSEL => KeyCode::ExSel,
            bind::SDLK_KP_00 => KeyCode::Keypad00,
            bind::SDLK_KP_000 => KeyCode::Keypad000,
            bind::SDLK_THOUSANDSSEPARATOR => KeyCode::ThousandsSeparator,
            bind::SDLK_DECIMALSEPARATOR => KeyCode::DecimalSeparator,
            bind::SDLK_CURRENCYUNIT => KeyCode::CurrencyUnit,
            bind::SDLK_CURRENCYSUBUNIT => KeyCode::CurrencySubunit,
            bind::SDLK_KP_LEFTPAREN => KeyCode::KeypadLeftParen,
            bind::SDLK_KP_RIGHTPAREN => KeyCode::KeypadRightParen,
            bind::SDLK_KP_LEFTBRACE => KeyCode::KeypadLeftBrace,
            bind::SDLK_KP_RIGHTBRACE => KeyCode::KeypadRightBrace,
            bind::SDLK_KP_TAB => KeyCode::KeypadTab,
            bind::SDLK_KP_BACKSPACE => KeyCode::KeypadBackspace,
            bind::SDLK_KP_A => KeyCode::KeypadA,
            bind::SDLK_KP_B => KeyCode::KeypadB,
            bind::SDLK_KP_C => KeyCode::KeypadC,
            bind::SDLK_KP_D => KeyCode::KeypadD,
            bind::SDLK_KP_E => KeyCode::KeypadE,
            bind::SDLK_KP_F => KeyCode::KeypadF,
            bind::SDLK_KP_XOR => KeyCode::KeypadXor,
            bind::SDLK_KP_POWER => KeyCode::KeypadPower,
            bind::SDLK_KP_PERCENT => KeyCode::KeypadPercent,
            bind::SDLK_KP_LESS => KeyCode::KeypadLess,
            bind::SDLK_KP_GREATER => KeyCode::KeypadGreater,
            bind::SDLK_KP_AMPERSAND => KeyCode::KeypadAmpersand,
            bind::SDLK_KP_DBLAMPERSAND => KeyCode::KeypadDblAmpersand,
            bind::SDLK_KP_VERTICALBAR => KeyCode::KeypadVerticalBar,
            bind::SDLK_KP_DBLVERTICALBAR => KeyCode::KeypadDblverticalBar,
            bind::SDLK_KP_COLON => KeyCode::KeypadColon,
            bind::SDLK_KP_HASH => KeyCode::KeypadHash,
            bind::SDLK_KP_SPACE => KeyCode::KeypadSpace,
            bind::SDLK_KP_AT => KeyCode::KeypadAt,
            bind::SDLK_KP_EXCLAM => KeyCode::KeypadExclam,
            bind::SDLK_KP_MEMSTORE => KeyCode::KeypadMemStore,
            bind::SDLK_KP_MEMRECALL => KeyCode::KeypadMemRecall,
            bind::SDLK_KP_MEMCLEAR => KeyCode::KeypadMemClear,
            bind::SDLK_KP_MEMADD => KeyCode::KeypadMemAdd,
            bind::SDLK_KP_MEMSUBTRACT => KeyCode::KeypadMemSubtract,
            bind::SDLK_KP_MEMMULTIPLY => KeyCode::KeypadMemMultiply,
            bind::SDLK_KP_MEMDIVIDE => KeyCode::KeypadMemDivide,
            bind::SDLK_KP_PLUSMINUS => KeyCode::KeypadPlusMinus,
            bind::SDLK_KP_CLEAR => KeyCode::KeypadClear,
            bind::SDLK_KP_CLEARENTRY => KeyCode::KeypadClearEntry,
            bind::SDLK_KP_BINARY => KeyCode::KeypadBinary,
            bind::SDLK_KP_OCTAL => KeyCode::KeypadOctal,
            bind::SDLK_KP_DECIMAL => KeyCode::KeypadDecimal,
            bind::SDLK_KP_HEXADECIMAL => KeyCode::KeypadHexadecimal,
            bind::SDLK_LCTRL => KeyCode::LCtrl,
            bind::SDLK_LSHIFT => KeyCode::LShift,
            bind::SDLK_LALT => KeyCode::LAlt,
            bind::SDLK_LGUI => KeyCode::LGui,
            bind::SDLK_RCTRL => KeyCode::RCtrl,
            bind::SDLK_RSHIFT => KeyCode::RShift,
            bind::SDLK_RALT => KeyCode::RAlt,
            bind::SDLK_RGUI => KeyCode::RGui,
            bind::SDLK_MODE => KeyCode::Mode,
            bind::SDLK_AUDIONEXT => KeyCode::AudioNext,
            bind::SDLK_AUDIOPREV => KeyCode::AudioPrev,
            bind::SDLK_AUDIOSTOP => KeyCode::AudioStop,
            bind::SDLK_AUDIOPLAY => KeyCode::AudioPlay,
            bind::SDLK_AUDIOMUTE => KeyCode::AudioMute,
            bind::SDLK_MEDIASELECT => KeyCode::MediaSelect,
            bind::SDLK_WWW => KeyCode::Www,
            bind::SDLK_MAIL => KeyCode::Mail,
            bind::SDLK_CALCULATOR => KeyCode::Calculator,
            bind::SDLK_COMPUTER => KeyCode::Computer,
            bind::SDLK_AC_SEARCH => KeyCode::ApplicationSearch,
            bind::SDLK_AC_HOME => KeyCode::ApplicationHome,
            bind::SDLK_AC_BACK => KeyCode::ApplicationBack,
            bind::SDLK_AC_FORWARD => KeyCode::ApplicationForward,
            bind::SDLK_AC_STOP => KeyCode::ApplicationStop,
            bind::SDLK_AC_REFRESH => KeyCode::ApplicationRefresh,
            bind::SDLK_AC_BOOKMARKS => KeyCode::ApplicationBookmarks,
            bind::SDLK_BRIGHTNESSDOWN => KeyCode::BrightnessDown,
            bind::SDLK_BRIGHTNESSUP => KeyCode::BrightnessUp,
            bind::SDLK_DISPLAYSWITCH => KeyCode::DisplaySwitch,
            bind::SDLK_KBDILLUMTOGGLE => KeyCode::KeyboardIllumToggle,
            bind::SDLK_KBDILLUMDOWN => KeyCode::KeyboardIllumDown,
            bind::SDLK_KBDILLUMUP => KeyCode::KeyboardIllumUp,
            bind::SDLK_EJECT => KeyCode::Eject,
            bind::SDLK_SLEEP => KeyCode::Sleep,
            bind::SDLK_APP1 => KeyCode::App1,
            bind::SDLK_APP2 => KeyCode::App2,
            bind::SDLK_AUDIOREWIND => KeyCode::AudioRewind,
            bind::SDLK_AUDIOFASTFORWARD => KeyCode::AudioFastForward,
            _ => KeyCode::Unknown,
        }
    }
}