1use crate::error::{InputError, Result};
7use std::collections::HashMap;
8
9pub mod keycodes {
11 pub const KEY_ESC: u32 = 1;
13 pub const KEY_1: u32 = 2;
14 pub const KEY_2: u32 = 3;
15 pub const KEY_3: u32 = 4;
16 pub const KEY_4: u32 = 5;
17 pub const KEY_5: u32 = 6;
18 pub const KEY_6: u32 = 7;
19 pub const KEY_7: u32 = 8;
20 pub const KEY_8: u32 = 9;
21 pub const KEY_9: u32 = 10;
22 pub const KEY_0: u32 = 11;
23 pub const KEY_MINUS: u32 = 12;
24 pub const KEY_EQUAL: u32 = 13;
25 pub const KEY_BACKSPACE: u32 = 14;
26 pub const KEY_TAB: u32 = 15;
27 pub const KEY_Q: u32 = 16;
28 pub const KEY_W: u32 = 17;
29 pub const KEY_E: u32 = 18;
30 pub const KEY_R: u32 = 19;
31 pub const KEY_T: u32 = 20;
32 pub const KEY_Y: u32 = 21;
33 pub const KEY_U: u32 = 22;
34 pub const KEY_I: u32 = 23;
35 pub const KEY_O: u32 = 24;
36 pub const KEY_P: u32 = 25;
37 pub const KEY_LEFTBRACE: u32 = 26;
38 pub const KEY_RIGHTBRACE: u32 = 27;
39 pub const KEY_ENTER: u32 = 28;
40 pub const KEY_LEFTCTRL: u32 = 29;
41 pub const KEY_A: u32 = 30;
42 pub const KEY_S: u32 = 31;
43 pub const KEY_D: u32 = 32;
44 pub const KEY_F: u32 = 33;
45 pub const KEY_G: u32 = 34;
46 pub const KEY_H: u32 = 35;
47 pub const KEY_J: u32 = 36;
48 pub const KEY_K: u32 = 37;
49 pub const KEY_L: u32 = 38;
50 pub const KEY_SEMICOLON: u32 = 39;
51 pub const KEY_APOSTROPHE: u32 = 40;
52 pub const KEY_GRAVE: u32 = 41;
53 pub const KEY_LEFTSHIFT: u32 = 42;
54 pub const KEY_BACKSLASH: u32 = 43;
55 pub const KEY_Z: u32 = 44;
56 pub const KEY_X: u32 = 45;
57 pub const KEY_C: u32 = 46;
58 pub const KEY_V: u32 = 47;
59 pub const KEY_B: u32 = 48;
60 pub const KEY_N: u32 = 49;
61 pub const KEY_M: u32 = 50;
62 pub const KEY_COMMA: u32 = 51;
63 pub const KEY_DOT: u32 = 52;
64 pub const KEY_SLASH: u32 = 53;
65 pub const KEY_RIGHTSHIFT: u32 = 54;
66 pub const KEY_KPASTERISK: u32 = 55;
67 pub const KEY_LEFTALT: u32 = 56;
68 pub const KEY_SPACE: u32 = 57;
69 pub const KEY_CAPSLOCK: u32 = 58;
70
71 pub const KEY_F1: u32 = 59;
73 pub const KEY_F2: u32 = 60;
74 pub const KEY_F3: u32 = 61;
75 pub const KEY_F4: u32 = 62;
76 pub const KEY_F5: u32 = 63;
77 pub const KEY_F6: u32 = 64;
78 pub const KEY_F7: u32 = 65;
79 pub const KEY_F8: u32 = 66;
80 pub const KEY_F9: u32 = 67;
81 pub const KEY_F10: u32 = 68;
82 pub const KEY_NUMLOCK: u32 = 69;
83 pub const KEY_SCROLLLOCK: u32 = 70;
84
85 pub const KEY_KP7: u32 = 71;
87 pub const KEY_KP8: u32 = 72;
88 pub const KEY_KP9: u32 = 73;
89 pub const KEY_KPMINUS: u32 = 74;
90 pub const KEY_KP4: u32 = 75;
91 pub const KEY_KP5: u32 = 76;
92 pub const KEY_KP6: u32 = 77;
93 pub const KEY_KPPLUS: u32 = 78;
94 pub const KEY_KP1: u32 = 79;
95 pub const KEY_KP2: u32 = 80;
96 pub const KEY_KP3: u32 = 81;
97 pub const KEY_KP0: u32 = 82;
98 pub const KEY_KPDOT: u32 = 83;
99
100 pub const KEY_102ND: u32 = 86;
101 pub const KEY_F11: u32 = 87;
102 pub const KEY_F12: u32 = 88;
103 pub const KEY_RO: u32 = 89;
104 pub const KEY_KATAKANAHIRAGANA: u32 = 90;
105 pub const KEY_HENKAN: u32 = 92;
106 pub const KEY_MUHENKAN: u32 = 94;
107 pub const KEY_KPENTER: u32 = 96;
108 pub const KEY_RIGHTCTRL: u32 = 97;
109 pub const KEY_KPSLASH: u32 = 98;
110 pub const KEY_SYSRQ: u32 = 99;
111 pub const KEY_RIGHTALT: u32 = 100;
112 pub const KEY_HOME: u32 = 102;
113 pub const KEY_UP: u32 = 103;
114 pub const KEY_PAGEUP: u32 = 104;
115 pub const KEY_LEFT: u32 = 105;
116 pub const KEY_RIGHT: u32 = 106;
117 pub const KEY_END: u32 = 107;
118 pub const KEY_DOWN: u32 = 108;
119 pub const KEY_PAGEDOWN: u32 = 109;
120 pub const KEY_INSERT: u32 = 110;
121 pub const KEY_DELETE: u32 = 111;
122 pub const KEY_MUTE: u32 = 113;
123 pub const KEY_VOLUMEDOWN: u32 = 114;
124 pub const KEY_VOLUMEUP: u32 = 115;
125 pub const KEY_POWER: u32 = 116;
126 pub const KEY_KPEQUAL: u32 = 117;
127 pub const KEY_PAUSE: u32 = 119;
128 pub const KEY_KPCOMMA: u32 = 121;
129 pub const KEY_HANGEUL: u32 = 122;
130 pub const KEY_HANJA: u32 = 123;
131 pub const KEY_YEN: u32 = 124;
132 pub const KEY_LEFTMETA: u32 = 125;
133 pub const KEY_RIGHTMETA: u32 = 126;
134 pub const KEY_COMPOSE: u32 = 127;
135 pub const KEY_STOP: u32 = 128;
136 pub const KEY_AGAIN: u32 = 129;
137 pub const KEY_PROPS: u32 = 130;
138 pub const KEY_UNDO: u32 = 131;
139 pub const KEY_FRONT: u32 = 132;
140 pub const KEY_COPY: u32 = 133;
141 pub const KEY_OPEN: u32 = 134;
142 pub const KEY_PASTE: u32 = 135;
143 pub const KEY_FIND: u32 = 136;
144 pub const KEY_CUT: u32 = 137;
145 pub const KEY_HELP: u32 = 138;
146 pub const KEY_MENU: u32 = 139;
147 pub const KEY_CALC: u32 = 140;
148 pub const KEY_SLEEP: u32 = 142;
149 pub const KEY_WAKEUP: u32 = 143;
150 pub const KEY_WWW: u32 = 150;
151 pub const KEY_MAIL: u32 = 155;
152 pub const KEY_BOOKMARKS: u32 = 156;
153 pub const KEY_COMPUTER: u32 = 157;
154 pub const KEY_BACK: u32 = 158;
155 pub const KEY_FORWARD: u32 = 159;
156 pub const KEY_EJECTCD: u32 = 161;
157 pub const KEY_NEXTSONG: u32 = 163;
158 pub const KEY_PLAYPAUSE: u32 = 164;
159 pub const KEY_PREVIOUSSONG: u32 = 165;
160 pub const KEY_STOPCD: u32 = 166;
161 pub const KEY_REFRESH: u32 = 173;
162 pub const KEY_F13: u32 = 183;
163 pub const KEY_F14: u32 = 184;
164 pub const KEY_F15: u32 = 185;
165 pub const KEY_F16: u32 = 186;
166 pub const KEY_F17: u32 = 187;
167 pub const KEY_F18: u32 = 188;
168 pub const KEY_F19: u32 = 189;
169 pub const KEY_F20: u32 = 190;
170 pub const KEY_F21: u32 = 191;
171 pub const KEY_F22: u32 = 192;
172 pub const KEY_F23: u32 = 193;
173 pub const KEY_F24: u32 = 194;
174 pub const KEY_MEDIA: u32 = 226;
175 pub const KEY_SEARCH: u32 = 217;
176 pub const KEY_HOMEPAGE: u32 = 172;
177 pub const KEY_BREAK: u32 = 411;
178 pub const KEY_PRINT: u32 = 210;
179}
180
181#[allow(clippy::wildcard_imports)]
182use keycodes::*;
183
184pub struct ScancodeMapper {
186 primary_map: HashMap<u16, u32>,
188
189 extended_map: HashMap<u16, u32>,
191
192 e1_map: HashMap<u32, u32>,
194
195 reverse_map: HashMap<u32, u16>,
197
198 layout_overrides: HashMap<String, HashMap<u16, u32>>,
200
201 current_layout: String,
203}
204
205impl ScancodeMapper {
206 pub fn new() -> Self {
208 let mut mapper = Self {
209 primary_map: HashMap::new(),
210 extended_map: HashMap::new(),
211 e1_map: HashMap::new(),
212 reverse_map: HashMap::new(),
213 layout_overrides: HashMap::new(),
214 current_layout: "us".to_string(),
215 };
216
217 mapper.initialize_mappings();
218 mapper
219 }
220
221 fn initialize_mappings(&mut self) {
223 self.initialize_primary_map();
224 self.initialize_extended_map();
225 self.initialize_e1_map();
226 self.build_reverse_map();
227 self.load_layout_overrides();
228 }
229
230 fn initialize_primary_map(&mut self) {
232 let mappings = vec![
233 (0x01, KEY_ESC),
234 (0x02, KEY_1),
235 (0x03, KEY_2),
236 (0x04, KEY_3),
237 (0x05, KEY_4),
238 (0x06, KEY_5),
239 (0x07, KEY_6),
240 (0x08, KEY_7),
241 (0x09, KEY_8),
242 (0x0A, KEY_9),
243 (0x0B, KEY_0),
244 (0x0C, KEY_MINUS),
245 (0x0D, KEY_EQUAL),
246 (0x0E, KEY_BACKSPACE),
247 (0x0F, KEY_TAB),
248 (0x10, KEY_Q),
249 (0x11, KEY_W),
250 (0x12, KEY_E),
251 (0x13, KEY_R),
252 (0x14, KEY_T),
253 (0x15, KEY_Y),
254 (0x16, KEY_U),
255 (0x17, KEY_I),
256 (0x18, KEY_O),
257 (0x19, KEY_P),
258 (0x1A, KEY_LEFTBRACE),
259 (0x1B, KEY_RIGHTBRACE),
260 (0x1C, KEY_ENTER),
261 (0x1D, KEY_LEFTCTRL),
262 (0x1E, KEY_A),
263 (0x1F, KEY_S),
264 (0x20, KEY_D),
265 (0x21, KEY_F),
266 (0x22, KEY_G),
267 (0x23, KEY_H),
268 (0x24, KEY_J),
269 (0x25, KEY_K),
270 (0x26, KEY_L),
271 (0x27, KEY_SEMICOLON),
272 (0x28, KEY_APOSTROPHE),
273 (0x29, KEY_GRAVE),
274 (0x2A, KEY_LEFTSHIFT),
275 (0x2B, KEY_BACKSLASH),
276 (0x2C, KEY_Z),
277 (0x2D, KEY_X),
278 (0x2E, KEY_C),
279 (0x2F, KEY_V),
280 (0x30, KEY_B),
281 (0x31, KEY_N),
282 (0x32, KEY_M),
283 (0x33, KEY_COMMA),
284 (0x34, KEY_DOT),
285 (0x35, KEY_SLASH),
286 (0x36, KEY_RIGHTSHIFT),
287 (0x37, KEY_KPASTERISK),
288 (0x38, KEY_LEFTALT),
289 (0x39, KEY_SPACE),
290 (0x3A, KEY_CAPSLOCK),
291 (0x3B, KEY_F1),
292 (0x3C, KEY_F2),
293 (0x3D, KEY_F3),
294 (0x3E, KEY_F4),
295 (0x3F, KEY_F5),
296 (0x40, KEY_F6),
297 (0x41, KEY_F7),
298 (0x42, KEY_F8),
299 (0x43, KEY_F9),
300 (0x44, KEY_F10),
301 (0x45, KEY_NUMLOCK),
302 (0x46, KEY_SCROLLLOCK),
303 (0x47, KEY_KP7),
304 (0x48, KEY_KP8),
305 (0x49, KEY_KP9),
306 (0x4A, KEY_KPMINUS),
307 (0x4B, KEY_KP4),
308 (0x4C, KEY_KP5),
309 (0x4D, KEY_KP6),
310 (0x4E, KEY_KPPLUS),
311 (0x4F, KEY_KP1),
312 (0x50, KEY_KP2),
313 (0x51, KEY_KP3),
314 (0x52, KEY_KP0),
315 (0x53, KEY_KPDOT),
316 (0x54, KEY_SYSRQ),
317 (0x56, KEY_102ND),
318 (0x57, KEY_F11),
319 (0x58, KEY_F12),
320 (0x59, KEY_KPEQUAL),
321 (0x5A, KEY_F13),
322 (0x5B, KEY_F14),
323 (0x5C, KEY_F15),
324 (0x5D, KEY_F16),
325 (0x5E, KEY_F17),
326 (0x5F, KEY_F18),
327 (0x60, KEY_F19),
328 (0x61, KEY_F20),
329 (0x62, KEY_F21),
330 (0x63, KEY_F22),
331 (0x64, KEY_F23),
332 (0x65, KEY_F24),
333 (0x70, KEY_KATAKANAHIRAGANA),
334 (0x71, KEY_MUHENKAN),
335 (0x72, KEY_HENKAN),
336 (0x73, KEY_RO),
337 (0x74, KEY_YEN),
338 (0x75, KEY_HANGEUL),
339 (0x76, KEY_HANJA),
340 (0x77, KEY_LEFTMETA),
341 (0x78, KEY_RIGHTMETA),
342 (0x79, KEY_COMPOSE),
343 (0x7A, KEY_STOP),
344 (0x7B, KEY_AGAIN),
345 (0x7C, KEY_PROPS),
346 (0x7D, KEY_UNDO),
347 (0x7E, KEY_FRONT),
348 (0x7F, KEY_COPY),
349 ];
350
351 for (scancode, keycode) in mappings {
352 self.primary_map.insert(scancode, keycode);
353 }
354 }
355
356 fn initialize_extended_map(&mut self) {
358 let mappings = vec![
359 (0xE01C, KEY_KPENTER),
360 (0xE01D, KEY_RIGHTCTRL),
361 (0xE020, KEY_MUTE),
362 (0xE021, KEY_CALC),
363 (0xE022, KEY_PLAYPAUSE),
364 (0xE024, KEY_STOPCD),
365 (0xE02E, KEY_VOLUMEDOWN),
366 (0xE030, KEY_VOLUMEUP),
367 (0xE032, KEY_HOMEPAGE),
368 (0xE035, KEY_KPSLASH),
369 (0xE037, KEY_PRINT),
370 (0xE038, KEY_RIGHTALT),
371 (0xE045, KEY_PAUSE),
372 (0xE047, KEY_HOME),
373 (0xE048, KEY_UP),
374 (0xE049, KEY_PAGEUP),
375 (0xE04B, KEY_LEFT),
376 (0xE04D, KEY_RIGHT),
377 (0xE04F, KEY_END),
378 (0xE050, KEY_DOWN),
379 (0xE051, KEY_PAGEDOWN),
380 (0xE052, KEY_INSERT),
381 (0xE053, KEY_DELETE),
382 (0xE05B, KEY_LEFTMETA),
383 (0xE05C, KEY_RIGHTMETA),
384 (0xE05D, KEY_MENU),
385 (0xE05E, KEY_POWER),
386 (0xE05F, KEY_SLEEP),
387 (0xE063, KEY_WAKEUP),
388 (0xE065, KEY_SEARCH),
389 (0xE066, KEY_BOOKMARKS),
390 (0xE067, KEY_REFRESH),
391 (0xE068, KEY_STOP),
392 (0xE069, KEY_FORWARD),
393 (0xE06A, KEY_BACK),
394 (0xE06B, KEY_COMPUTER),
395 (0xE06C, KEY_MAIL),
396 (0xE06D, KEY_MEDIA),
397 (0xE010, KEY_PREVIOUSSONG),
398 (0xE019, KEY_NEXTSONG),
399 (0xE02C, KEY_EJECTCD),
400 ];
401
402 for (scancode, keycode) in mappings {
403 self.extended_map.insert(scancode, keycode);
404 }
405 }
406
407 fn initialize_e1_map(&mut self) {
409 self.e1_map.insert(0xE11D45, KEY_PAUSE);
410 self.e1_map.insert(0xE11D46, KEY_BREAK);
411 }
412
413 fn build_reverse_map(&mut self) {
415 for (&scancode, &keycode) in &self.primary_map {
416 self.reverse_map.insert(keycode, scancode);
417 }
418 for (&scancode, &keycode) in &self.extended_map {
419 self.reverse_map.insert(keycode, scancode);
420 }
421 }
422
423 fn load_layout_overrides(&mut self) {
425 let mut de_overrides = HashMap::new();
427 de_overrides.insert(0x15, KEY_Z); de_overrides.insert(0x2C, KEY_Y); self.layout_overrides.insert("de".to_string(), de_overrides);
430
431 let mut fr_overrides = HashMap::new();
433 fr_overrides.insert(0x10, KEY_A); fr_overrides.insert(0x1E, KEY_Q); fr_overrides.insert(0x11, KEY_Z); fr_overrides.insert(0x2C, KEY_W); self.layout_overrides.insert("fr".to_string(), fr_overrides);
438 }
439
440 pub fn translate_scancode(&self, scancode: u32, extended: bool, e1_prefix: bool) -> Result<u32> {
442 if e1_prefix {
443 self.e1_map
445 .get(&scancode)
446 .copied()
447 .ok_or(InputError::UnknownScancode(scancode as u16))
448 } else if extended {
449 let extended_scan = 0xE000 | (scancode as u16 & 0xFF);
451 self.extended_map
452 .get(&extended_scan)
453 .or_else(|| self.primary_map.get(&(scancode as u16)))
454 .copied()
455 .ok_or(InputError::UnknownScancode(extended_scan))
456 } else {
457 if let Some(overrides) = self.layout_overrides.get(&self.current_layout) {
459 if let Some(keycode) = overrides.get(&(scancode as u16)) {
460 return Ok(*keycode);
461 }
462 }
463 self.primary_map
465 .get(&(scancode as u16))
466 .copied()
467 .ok_or(InputError::UnknownScancode(scancode as u16))
468 }
469 }
470
471 pub fn translate_keycode(&self, keycode: u32) -> Result<u16> {
473 self.reverse_map
474 .get(&keycode)
475 .copied()
476 .ok_or(InputError::UnknownKeycode(keycode))
477 }
478
479 pub fn set_layout(&mut self, layout: &str) {
481 self.current_layout = layout.to_string();
482 }
483
484 pub fn layout(&self) -> &str {
486 &self.current_layout
487 }
488
489 pub fn is_mapped(&self, scancode: u16, extended: bool) -> bool {
491 if extended {
492 let extended_scan = 0xE000 | (scancode & 0xFF);
493 self.extended_map.contains_key(&extended_scan)
494 } else {
495 self.primary_map.contains_key(&scancode)
496 }
497 }
498
499 pub fn mapped_key_count(&self) -> usize {
501 self.primary_map.len() + self.extended_map.len() + self.e1_map.len()
502 }
503}
504
505impl Default for ScancodeMapper {
506 fn default() -> Self {
507 Self::new()
508 }
509}
510
511#[cfg(test)]
512mod tests {
513 use super::*;
514
515 #[test]
516 fn test_scancode_mapper_creation() {
517 let mapper = ScancodeMapper::new();
518 assert!(mapper.mapped_key_count() >= 150);
520 }
521
522 #[test]
523 fn test_primary_scancode_mapping() {
524 let mapper = ScancodeMapper::new();
525
526 assert_eq!(mapper.translate_scancode(0x1E, false, false).unwrap(), KEY_A);
528 assert_eq!(mapper.translate_scancode(0x2C, false, false).unwrap(), KEY_Z);
529
530 assert_eq!(mapper.translate_scancode(0x02, false, false).unwrap(), KEY_1);
532 assert_eq!(mapper.translate_scancode(0x0B, false, false).unwrap(), KEY_0);
533
534 assert_eq!(mapper.translate_scancode(0x3B, false, false).unwrap(), KEY_F1);
536 assert_eq!(mapper.translate_scancode(0x58, false, false).unwrap(), KEY_F12);
537 }
538
539 #[test]
540 fn test_extended_scancode_mapping() {
541 let mapper = ScancodeMapper::new();
542
543 assert_eq!(mapper.translate_scancode(0x47, true, false).unwrap(), KEY_HOME);
545 assert_eq!(mapper.translate_scancode(0x4F, true, false).unwrap(), KEY_END);
546 assert_eq!(mapper.translate_scancode(0x48, true, false).unwrap(), KEY_UP);
547 assert_eq!(mapper.translate_scancode(0x50, true, false).unwrap(), KEY_DOWN);
548 assert_eq!(mapper.translate_scancode(0x4B, true, false).unwrap(), KEY_LEFT);
549 assert_eq!(mapper.translate_scancode(0x4D, true, false).unwrap(), KEY_RIGHT);
550
551 assert_eq!(mapper.translate_scancode(0x22, true, false).unwrap(), KEY_PLAYPAUSE);
553 assert_eq!(mapper.translate_scancode(0x24, true, false).unwrap(), KEY_STOPCD);
554 }
555
556 #[test]
557 fn test_bidirectional_mapping() {
558 let mapper = ScancodeMapper::new();
559
560 let test_keys = vec![KEY_A, KEY_Z, KEY_ENTER, KEY_SPACE, KEY_F1, KEY_F12];
562
563 for keycode in test_keys {
564 let scancode = mapper.translate_keycode(keycode).unwrap();
565 let translated = mapper.translate_scancode(scancode as u32, false, false).unwrap();
566 assert_eq!(translated, keycode);
567 }
568 }
569
570 #[test]
571 fn test_layout_override() {
572 let mut mapper = ScancodeMapper::new();
573
574 assert_eq!(mapper.translate_scancode(0x15, false, false).unwrap(), KEY_Y);
576
577 mapper.set_layout("de");
579 assert_eq!(mapper.translate_scancode(0x15, false, false).unwrap(), KEY_Z);
580
581 mapper.set_layout("fr");
583 assert_eq!(mapper.translate_scancode(0x10, false, false).unwrap(), KEY_A);
584 }
585
586 #[test]
587 fn test_unknown_scancode() {
588 let mapper = ScancodeMapper::new();
589
590 let result = mapper.translate_scancode(0xFF, false, false);
592 assert!(result.is_err());
593 match result {
594 Err(InputError::UnknownScancode(_)) => {}
595 _ => panic!("Expected UnknownScancode error"),
596 }
597 }
598
599 #[test]
600 fn test_unknown_keycode() {
601 let mapper = ScancodeMapper::new();
602
603 let result = mapper.translate_keycode(9999);
605 assert!(result.is_err());
606 match result {
607 Err(InputError::UnknownKeycode(_)) => {}
608 _ => panic!("Expected UnknownKeycode error"),
609 }
610 }
611
612 #[test]
613 fn test_is_mapped() {
614 let mapper = ScancodeMapper::new();
615
616 assert!(mapper.is_mapped(0x1E, false)); assert!(mapper.is_mapped(0x47, true)); assert!(!mapper.is_mapped(0xFF, false)); }
620
621 #[test]
622 fn test_all_primary_keys_mapped() {
623 let mapper = ScancodeMapper::new();
624
625 for scancode in 0x01..=0x58 {
627 if scancode == 0x00 || scancode == 0x55 {
628 continue; }
630 assert!(
631 mapper.is_mapped(scancode, false),
632 "Scancode 0x{:02X} not mapped",
633 scancode
634 );
635 }
636 }
637
638 #[test]
639 fn test_function_keys_f13_to_f24() {
640 let mapper = ScancodeMapper::new();
641
642 assert_eq!(mapper.translate_scancode(0x5A, false, false).unwrap(), KEY_F13);
643 assert_eq!(mapper.translate_scancode(0x65, false, false).unwrap(), KEY_F24);
644 }
645
646 #[test]
647 fn test_multimedia_keys() {
648 let mapper = ScancodeMapper::new();
649
650 assert_eq!(mapper.translate_scancode(0x20, true, false).unwrap(), KEY_MUTE);
651 assert_eq!(mapper.translate_scancode(0x2E, true, false).unwrap(), KEY_VOLUMEDOWN);
652 assert_eq!(mapper.translate_scancode(0x30, true, false).unwrap(), KEY_VOLUMEUP);
653 }
654
655 #[test]
656 fn test_japanese_keys() {
657 let mapper = ScancodeMapper::new();
658
659 assert_eq!(
660 mapper.translate_scancode(0x70, false, false).unwrap(),
661 KEY_KATAKANAHIRAGANA
662 );
663 assert_eq!(mapper.translate_scancode(0x71, false, false).unwrap(), KEY_MUHENKAN);
664 assert_eq!(mapper.translate_scancode(0x72, false, false).unwrap(), KEY_HENKAN);
665 }
666
667 #[test]
668 fn test_korean_keys() {
669 let mapper = ScancodeMapper::new();
670
671 assert_eq!(mapper.translate_scancode(0x75, false, false).unwrap(), KEY_HANGEUL);
672 assert_eq!(mapper.translate_scancode(0x76, false, false).unwrap(), KEY_HANJA);
673 }
674}