Skip to main content

sdl_keybridge/
scancode.rs

1//! Physical key positions — SDL scancodes.
2//!
3//! A scancode identifies a physical key on the keyboard independently of the
4//! current layout. Values are compatible with both SDL2 and SDL3 (identical
5//! numeric assignments for the keys covered here).
6
7/// A physical key position, wrapping the raw SDL scancode value.
8#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
9#[repr(transparent)]
10pub struct Scancode(pub u32);
11
12impl Scancode {
13    #[inline]
14    pub const fn new(raw: u32) -> Self {
15        Self(raw)
16    }
17
18    #[inline]
19    pub const fn raw(self) -> u32 {
20        self.0
21    }
22}
23
24impl From<u32> for Scancode {
25    #[inline]
26    fn from(value: u32) -> Self {
27        Scancode(value)
28    }
29}
30
31impl From<Scancode> for u32 {
32    #[inline]
33    fn from(value: Scancode) -> Self {
34        value.0
35    }
36}
37
38/// SDL scancode constants — stable across SDL2 and SDL3.
39impl Scancode {
40    pub const UNKNOWN: Scancode = Scancode(0);
41
42    // Letters (USB HID keyboard page, SDL layout).
43    pub const A: Scancode = Scancode(4);
44    pub const B: Scancode = Scancode(5);
45    pub const C: Scancode = Scancode(6);
46    pub const D: Scancode = Scancode(7);
47    pub const E: Scancode = Scancode(8);
48    pub const F: Scancode = Scancode(9);
49    pub const G: Scancode = Scancode(10);
50    pub const H: Scancode = Scancode(11);
51    pub const I: Scancode = Scancode(12);
52    pub const J: Scancode = Scancode(13);
53    pub const K: Scancode = Scancode(14);
54    pub const L: Scancode = Scancode(15);
55    pub const M: Scancode = Scancode(16);
56    pub const N: Scancode = Scancode(17);
57    pub const O: Scancode = Scancode(18);
58    pub const P: Scancode = Scancode(19);
59    pub const Q: Scancode = Scancode(20);
60    pub const R: Scancode = Scancode(21);
61    pub const S: Scancode = Scancode(22);
62    pub const T: Scancode = Scancode(23);
63    pub const U: Scancode = Scancode(24);
64    pub const V: Scancode = Scancode(25);
65    pub const W: Scancode = Scancode(26);
66    pub const X: Scancode = Scancode(27);
67    pub const Y: Scancode = Scancode(28);
68    pub const Z: Scancode = Scancode(29);
69
70    // Top-row digits (1..9 then 0 — SDL layout).
71    pub const NUM_1: Scancode = Scancode(30);
72    pub const NUM_2: Scancode = Scancode(31);
73    pub const NUM_3: Scancode = Scancode(32);
74    pub const NUM_4: Scancode = Scancode(33);
75    pub const NUM_5: Scancode = Scancode(34);
76    pub const NUM_6: Scancode = Scancode(35);
77    pub const NUM_7: Scancode = Scancode(36);
78    pub const NUM_8: Scancode = Scancode(37);
79    pub const NUM_9: Scancode = Scancode(38);
80    pub const NUM_0: Scancode = Scancode(39);
81
82    pub const RETURN: Scancode = Scancode(40);
83    pub const ESCAPE: Scancode = Scancode(41);
84    pub const BACKSPACE: Scancode = Scancode(42);
85    pub const TAB: Scancode = Scancode(43);
86    pub const SPACE: Scancode = Scancode(44);
87
88    pub const MINUS: Scancode = Scancode(45);
89    pub const EQUALS: Scancode = Scancode(46);
90    pub const LEFT_BRACKET: Scancode = Scancode(47);
91    pub const RIGHT_BRACKET: Scancode = Scancode(48);
92    pub const BACKSLASH: Scancode = Scancode(49);
93    pub const NON_US_HASH: Scancode = Scancode(50);
94    pub const SEMICOLON: Scancode = Scancode(51);
95    pub const APOSTROPHE: Scancode = Scancode(52);
96    pub const GRAVE: Scancode = Scancode(53);
97    pub const COMMA: Scancode = Scancode(54);
98    pub const PERIOD: Scancode = Scancode(55);
99    pub const SLASH: Scancode = Scancode(56);
100
101    pub const CAPSLOCK: Scancode = Scancode(57);
102
103    // Function keys F1..F12.
104    pub const F1: Scancode = Scancode(58);
105    pub const F2: Scancode = Scancode(59);
106    pub const F3: Scancode = Scancode(60);
107    pub const F4: Scancode = Scancode(61);
108    pub const F5: Scancode = Scancode(62);
109    pub const F6: Scancode = Scancode(63);
110    pub const F7: Scancode = Scancode(64);
111    pub const F8: Scancode = Scancode(65);
112    pub const F9: Scancode = Scancode(66);
113    pub const F10: Scancode = Scancode(67);
114    pub const F11: Scancode = Scancode(68);
115    pub const F12: Scancode = Scancode(69);
116
117    pub const PRINT_SCREEN: Scancode = Scancode(70);
118    pub const SCROLL_LOCK: Scancode = Scancode(71);
119    pub const PAUSE: Scancode = Scancode(72);
120    pub const INSERT: Scancode = Scancode(73);
121    pub const HOME: Scancode = Scancode(74);
122    pub const PAGE_UP: Scancode = Scancode(75);
123    pub const DELETE: Scancode = Scancode(76);
124    pub const END: Scancode = Scancode(77);
125    pub const PAGE_DOWN: Scancode = Scancode(78);
126    pub const RIGHT: Scancode = Scancode(79);
127    pub const LEFT: Scancode = Scancode(80);
128    pub const DOWN: Scancode = Scancode(81);
129    pub const UP: Scancode = Scancode(82);
130
131    pub const NUM_LOCK_CLEAR: Scancode = Scancode(83);
132
133    // Keypad.
134    pub const KP_DIVIDE: Scancode = Scancode(84);
135    pub const KP_MULTIPLY: Scancode = Scancode(85);
136    pub const KP_MINUS: Scancode = Scancode(86);
137    pub const KP_PLUS: Scancode = Scancode(87);
138    pub const KP_ENTER: Scancode = Scancode(88);
139    pub const KP_1: Scancode = Scancode(89);
140    pub const KP_2: Scancode = Scancode(90);
141    pub const KP_3: Scancode = Scancode(91);
142    pub const KP_4: Scancode = Scancode(92);
143    pub const KP_5: Scancode = Scancode(93);
144    pub const KP_6: Scancode = Scancode(94);
145    pub const KP_7: Scancode = Scancode(95);
146    pub const KP_8: Scancode = Scancode(96);
147    pub const KP_9: Scancode = Scancode(97);
148    pub const KP_0: Scancode = Scancode(98);
149    pub const KP_PERIOD: Scancode = Scancode(99);
150
151    pub const NON_US_BACKSLASH: Scancode = Scancode(100);
152    pub const APPLICATION: Scancode = Scancode(101);
153    pub const POWER: Scancode = Scancode(102);
154    pub const KP_EQUALS: Scancode = Scancode(103);
155
156    pub const F13: Scancode = Scancode(104);
157    pub const F14: Scancode = Scancode(105);
158    pub const F15: Scancode = Scancode(106);
159    pub const F16: Scancode = Scancode(107);
160    pub const F17: Scancode = Scancode(108);
161    pub const F18: Scancode = Scancode(109);
162    pub const F19: Scancode = Scancode(110);
163    pub const F20: Scancode = Scancode(111);
164    pub const F21: Scancode = Scancode(112);
165    pub const F22: Scancode = Scancode(113);
166    pub const F23: Scancode = Scancode(114);
167    pub const F24: Scancode = Scancode(115);
168
169    pub const MENU: Scancode = Scancode(118);
170
171    // International keys — JIS, Korean, Brazilian layouts.
172    pub const INTERNATIONAL1: Scancode = Scancode(135);
173    pub const INTERNATIONAL2: Scancode = Scancode(136);
174    pub const INTERNATIONAL3: Scancode = Scancode(137); // yen
175    pub const INTERNATIONAL4: Scancode = Scancode(138);
176    pub const INTERNATIONAL5: Scancode = Scancode(139);
177    pub const INTERNATIONAL6: Scancode = Scancode(140);
178    pub const INTERNATIONAL7: Scancode = Scancode(141);
179    pub const INTERNATIONAL8: Scancode = Scancode(142);
180    pub const INTERNATIONAL9: Scancode = Scancode(143);
181    pub const LANG1: Scancode = Scancode(144); // Hangul/English toggle
182    pub const LANG2: Scancode = Scancode(145); // Hanja
183    pub const LANG3: Scancode = Scancode(146); // Katakana
184    pub const LANG4: Scancode = Scancode(147); // Hiragana
185    pub const LANG5: Scancode = Scancode(148); // Zenkaku/Hankaku
186
187    // Modifiers.
188    pub const LCTRL: Scancode = Scancode(224);
189    pub const LSHIFT: Scancode = Scancode(225);
190    pub const LALT: Scancode = Scancode(226);
191    pub const LGUI: Scancode = Scancode(227);
192    pub const RCTRL: Scancode = Scancode(228);
193    pub const RSHIFT: Scancode = Scancode(229);
194    pub const RALT: Scancode = Scancode(230);
195    pub const RGUI: Scancode = Scancode(231);
196}
197
198#[cfg(test)]
199mod tests {
200    use super::*;
201
202    #[test]
203    fn stable_scancode_values() {
204        assert_eq!(Scancode::A.raw(), 4);
205        assert_eq!(Scancode::ESCAPE.raw(), 41);
206        assert_eq!(Scancode::SPACE.raw(), 44);
207        assert_eq!(Scancode::NUM_1.raw(), 30);
208        assert_eq!(Scancode::NUM_0.raw(), 39);
209        assert_eq!(Scancode::LSHIFT.raw(), 225);
210        assert_eq!(Scancode::RGUI.raw(), 231);
211    }
212}