fix: correct keyboard scancode mapping from KeyTranslator.java
The mapping was built assuming keynr followed physical keyboard order with Escape=0. In reality, KeyTranslator.java maps Java VK_* codes to keynr values with a different layout: - keynr 0 = Backquote (not Escape) - keynr 59 = Escape - keynr 27 = Enter (not 40) - keynr 40 = Backslash (not 42) This caused the number row and QWERTY row to be off by 1 (Escape was inserted at position 0, pushing everything). The home row (CapsLock=28, A=29...L=37) happened to align by coincidence, which is why 'g'(33) worked but 'r'(should be 18, was 19=T) didn't. Also fixes: F1-F12 off by 1, PrintScreen/ScrollLock/Pause off by 1, numpad operator keys swapped with numpad 7/8/9. Corrected both Rust (input.rs) and TypeScript (input.ts) mappings to match the authoritative KeyTranslator.java VK→keynr table. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -49,54 +49,41 @@ pub const HOTKEY_CTRL_ALT_DEL: &str = "36 f0 37 f0 4e";
|
||||
/// Map a JavaScript `KeyboardEvent.code` string to an e-RIC scancode.
|
||||
/// Returns `None` for unmapped keys.
|
||||
pub fn js_code_to_scancode(code: &str) -> Option<u8> {
|
||||
// Mapping derived from KeyTranslator.java line 14 (Java VK_* → keynr table).
|
||||
Some(match code {
|
||||
// Function row
|
||||
"Escape" => 0,
|
||||
"F1" => 59,
|
||||
"F2" => 60,
|
||||
"F3" => 61,
|
||||
"F4" => 62,
|
||||
"F5" => 63,
|
||||
"F6" => 64,
|
||||
"F7" => 65,
|
||||
"F8" => 66,
|
||||
"F9" => 67,
|
||||
"F10" => 68,
|
||||
"F11" => 69,
|
||||
"F12" => 70,
|
||||
// Number row (keynr 0-13)
|
||||
"Backquote" => 0,
|
||||
"Digit1" => 1,
|
||||
"Digit2" => 2,
|
||||
"Digit3" => 3,
|
||||
"Digit4" => 4,
|
||||
"Digit5" => 5,
|
||||
"Digit6" => 6,
|
||||
"Digit7" => 7,
|
||||
"Digit8" => 8,
|
||||
"Digit9" => 9,
|
||||
"Digit0" => 10,
|
||||
"Minus" => 11,
|
||||
"Equal" => 12,
|
||||
"Backspace" => 13,
|
||||
|
||||
// Number row
|
||||
"Backquote" => 1,
|
||||
"Digit1" => 2,
|
||||
"Digit2" => 3,
|
||||
"Digit3" => 4,
|
||||
"Digit4" => 5,
|
||||
"Digit5" => 6,
|
||||
"Digit6" => 7,
|
||||
"Digit7" => 8,
|
||||
"Digit8" => 9,
|
||||
"Digit9" => 10,
|
||||
"Digit0" => 11,
|
||||
"Minus" => 12,
|
||||
"Equal" => 13,
|
||||
"Backspace" => 14,
|
||||
// QWERTY row (keynr 14-27)
|
||||
"Tab" => 14,
|
||||
"KeyQ" => 15,
|
||||
"KeyW" => 16,
|
||||
"KeyE" => 17,
|
||||
"KeyR" => 18,
|
||||
"KeyT" => 19,
|
||||
"KeyY" => 20,
|
||||
"KeyU" => 21,
|
||||
"KeyI" => 22,
|
||||
"KeyO" => 23,
|
||||
"KeyP" => 24,
|
||||
"BracketLeft" => 25,
|
||||
"BracketRight" => 26,
|
||||
"Enter" => 27,
|
||||
|
||||
// QWERTY row
|
||||
"Tab" => 15,
|
||||
"KeyQ" => 16,
|
||||
"KeyW" => 17,
|
||||
"KeyE" => 18,
|
||||
"KeyR" => 19,
|
||||
"KeyT" => 20,
|
||||
"KeyY" => 21,
|
||||
"KeyU" => 22,
|
||||
"KeyI" => 23,
|
||||
"KeyO" => 24,
|
||||
"KeyP" => 25,
|
||||
"BracketLeft" => 26,
|
||||
"BracketRight" => 27,
|
||||
|
||||
// Home row
|
||||
// Home row (keynr 28-40)
|
||||
"CapsLock" => 28,
|
||||
"KeyA" => 29,
|
||||
"KeyS" => 30,
|
||||
@@ -109,11 +96,10 @@ pub fn js_code_to_scancode(code: &str) -> Option<u8> {
|
||||
"KeyL" => 37,
|
||||
"Semicolon" => 38,
|
||||
"Quote" => 39,
|
||||
"Enter" => 40,
|
||||
"Backslash" => 40,
|
||||
|
||||
// Bottom row
|
||||
// Bottom row (keynr 41-53)
|
||||
"ShiftLeft" => 41,
|
||||
"Backslash" => 42,
|
||||
"KeyZ" => 43,
|
||||
"KeyX" => 44,
|
||||
"KeyC" => 45,
|
||||
@@ -126,51 +112,66 @@ pub fn js_code_to_scancode(code: &str) -> Option<u8> {
|
||||
"Slash" => 52,
|
||||
"ShiftRight" => 53,
|
||||
|
||||
// Modifier / bottom row
|
||||
// Modifiers (keynr 54-58)
|
||||
"ControlLeft" => 54,
|
||||
"MetaLeft" => 105,
|
||||
"AltLeft" => 55,
|
||||
"Space" => 56,
|
||||
"AltRight" => 57,
|
||||
"MetaRight" => 106,
|
||||
"ControlRight" => 58,
|
||||
|
||||
// Navigation cluster
|
||||
"PrintScreen" => 71,
|
||||
"ScrollLock" => 72,
|
||||
"Pause" => 73,
|
||||
// Escape + Function keys (keynr 59-71)
|
||||
"Escape" => 59,
|
||||
"F1" => 60,
|
||||
"F2" => 61,
|
||||
"F3" => 62,
|
||||
"F4" => 63,
|
||||
"F5" => 64,
|
||||
"F6" => 65,
|
||||
"F7" => 66,
|
||||
"F8" => 67,
|
||||
"F9" => 68,
|
||||
"F10" => 69,
|
||||
"F11" => 70,
|
||||
"F12" => 71,
|
||||
|
||||
// Navigation cluster (keynr 72-84)
|
||||
"PrintScreen" => 72,
|
||||
"ScrollLock" => 73,
|
||||
"Pause" => 74,
|
||||
"Insert" => 75,
|
||||
"Home" => 76,
|
||||
"PageUp" => 77,
|
||||
"Delete" => 78,
|
||||
"End" => 79,
|
||||
"PageDown" => 80,
|
||||
|
||||
// Arrow keys
|
||||
"ArrowUp" => 81,
|
||||
"ArrowLeft" => 82,
|
||||
"ArrowDown" => 83,
|
||||
"ArrowRight" => 84,
|
||||
|
||||
// Numpad
|
||||
// Numpad (keynr 85-101)
|
||||
"NumLock" => 85,
|
||||
"NumpadDivide" => 86,
|
||||
"NumpadMultiply" => 87,
|
||||
"NumpadSubtract" => 88,
|
||||
"Numpad7" => 86,
|
||||
"Numpad8" => 87,
|
||||
"Numpad9" => 88,
|
||||
"NumpadAdd" => 89,
|
||||
"NumpadEnter" => 98,
|
||||
"Numpad7" => 90,
|
||||
"Numpad8" => 94,
|
||||
"Numpad9" => 99,
|
||||
"NumpadDivide" => 90,
|
||||
"Numpad4" => 91,
|
||||
"Numpad5" => 92,
|
||||
"Numpad6" => 93,
|
||||
"NumpadMultiply" => 94,
|
||||
"Numpad1" => 95,
|
||||
"Numpad2" => 96,
|
||||
"Numpad3" => 97,
|
||||
"NumpadEnter" => 98,
|
||||
"NumpadSubtract" => 99,
|
||||
"Numpad0" => 100,
|
||||
"NumpadDecimal" => 101,
|
||||
|
||||
// Windows/Meta keys (keynr 105-106)
|
||||
"MetaLeft" => 105,
|
||||
"MetaRight" => 106,
|
||||
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
@@ -214,10 +215,20 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_js_code_mapping() {
|
||||
// From KeyTranslator.java: VK_A(65)→29, VK_ESCAPE(27)→59, etc.
|
||||
assert_eq!(js_code_to_scancode("KeyA"), Some(29));
|
||||
assert_eq!(js_code_to_scancode("Escape"), Some(0));
|
||||
assert_eq!(js_code_to_scancode("KeyR"), Some(18));
|
||||
assert_eq!(js_code_to_scancode("KeyG"), Some(33));
|
||||
assert_eq!(js_code_to_scancode("Escape"), Some(59));
|
||||
assert_eq!(js_code_to_scancode("Backspace"), Some(13));
|
||||
assert_eq!(js_code_to_scancode("Enter"), Some(27));
|
||||
assert_eq!(js_code_to_scancode("Backslash"), Some(40));
|
||||
assert_eq!(js_code_to_scancode("Backquote"), Some(0));
|
||||
assert_eq!(js_code_to_scancode("F1"), Some(60));
|
||||
assert_eq!(js_code_to_scancode("ControlLeft"), Some(54));
|
||||
assert_eq!(js_code_to_scancode("Delete"), Some(78));
|
||||
assert_eq!(js_code_to_scancode("Numpad7"), Some(86));
|
||||
assert_eq!(js_code_to_scancode("NumpadMultiply"), Some(94));
|
||||
assert_eq!(js_code_to_scancode("Unknown"), None);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user