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:
@@ -1,47 +1,59 @@
|
|||||||
// JavaScript KeyboardEvent.code → e-RIC scancode (KbdLayout_104pc)
|
// JavaScript KeyboardEvent.code → e-RIC scancode (KbdLayout_104pc)
|
||||||
|
// Derived from KeyTranslator.java line 14 (Java VK_* → keynr table).
|
||||||
// Must match crates/ericrfb/src/input.rs js_code_to_scancode()
|
// Must match crates/ericrfb/src/input.rs js_code_to_scancode()
|
||||||
|
|
||||||
const KEY_MAP: Record<string, number> = {
|
const KEY_MAP: Record<string, number> = {
|
||||||
Escape: 0,
|
// Number row (keynr 0-13)
|
||||||
F1: 59, F2: 60, F3: 61, F4: 62, F5: 63, F6: 64,
|
Backquote: 0,
|
||||||
F7: 65, F8: 66, F9: 67, F10: 68, F11: 69, F12: 70,
|
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,
|
||||||
|
|
||||||
Backquote: 1,
|
// QWERTY row (keynr 14-27)
|
||||||
Digit1: 2, Digit2: 3, Digit3: 4, Digit4: 5, Digit5: 6,
|
Tab: 14,
|
||||||
Digit6: 7, Digit7: 8, Digit8: 9, Digit9: 10, Digit0: 11,
|
KeyQ: 15, KeyW: 16, KeyE: 17, KeyR: 18, KeyT: 19,
|
||||||
Minus: 12, Equal: 13, Backspace: 14,
|
KeyY: 20, KeyU: 21, KeyI: 22, KeyO: 23, KeyP: 24,
|
||||||
|
BracketLeft: 25, BracketRight: 26, Enter: 27,
|
||||||
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 (keynr 28-40)
|
||||||
CapsLock: 28,
|
CapsLock: 28,
|
||||||
KeyA: 29, KeyS: 30, KeyD: 31, KeyF: 32, KeyG: 33,
|
KeyA: 29, KeyS: 30, KeyD: 31, KeyF: 32, KeyG: 33,
|
||||||
KeyH: 34, KeyJ: 35, KeyK: 36, KeyL: 37,
|
KeyH: 34, KeyJ: 35, KeyK: 36, KeyL: 37,
|
||||||
Semicolon: 38, Quote: 39, Enter: 40,
|
Semicolon: 38, Quote: 39, Backslash: 40,
|
||||||
|
|
||||||
ShiftLeft: 41, Backslash: 42,
|
// Bottom row (keynr 41-53)
|
||||||
|
ShiftLeft: 41,
|
||||||
KeyZ: 43, KeyX: 44, KeyC: 45, KeyV: 46, KeyB: 47,
|
KeyZ: 43, KeyX: 44, KeyC: 45, KeyV: 46, KeyB: 47,
|
||||||
KeyN: 48, KeyM: 49, Comma: 50, Period: 51, Slash: 52,
|
KeyN: 48, KeyM: 49, Comma: 50, Period: 51, Slash: 52,
|
||||||
ShiftRight: 53,
|
ShiftRight: 53,
|
||||||
|
|
||||||
ControlLeft: 54, MetaLeft: 105, AltLeft: 55,
|
// Modifiers (keynr 54-58)
|
||||||
Space: 56,
|
ControlLeft: 54, AltLeft: 55, Space: 56,
|
||||||
AltRight: 57, MetaRight: 106, ControlRight: 58,
|
AltRight: 57, ControlRight: 58,
|
||||||
|
|
||||||
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,
|
Insert: 75, Home: 76, PageUp: 77,
|
||||||
Delete: 78, End: 79, PageDown: 80,
|
Delete: 78, End: 79, PageDown: 80,
|
||||||
|
|
||||||
ArrowUp: 81, ArrowLeft: 82, ArrowDown: 83, ArrowRight: 84,
|
ArrowUp: 81, ArrowLeft: 82, ArrowDown: 83, ArrowRight: 84,
|
||||||
|
|
||||||
NumLock: 85, NumpadDivide: 86, NumpadMultiply: 87, NumpadSubtract: 88,
|
// Numpad (keynr 85-101)
|
||||||
NumpadAdd: 89, NumpadEnter: 98,
|
NumLock: 85,
|
||||||
Numpad7: 90, Numpad8: 94, Numpad9: 99,
|
Numpad7: 86, Numpad8: 87, Numpad9: 88,
|
||||||
|
NumpadAdd: 89, NumpadDivide: 90,
|
||||||
Numpad4: 91, Numpad5: 92, Numpad6: 93,
|
Numpad4: 91, Numpad5: 92, Numpad6: 93,
|
||||||
|
NumpadMultiply: 94,
|
||||||
Numpad1: 95, Numpad2: 96, Numpad3: 97,
|
Numpad1: 95, Numpad2: 96, Numpad3: 97,
|
||||||
|
NumpadEnter: 98, NumpadSubtract: 99,
|
||||||
Numpad0: 100, NumpadDecimal: 101,
|
Numpad0: 100, NumpadDecimal: 101,
|
||||||
|
|
||||||
|
// Windows/Meta keys (keynr 105-106)
|
||||||
|
MetaLeft: 105, MetaRight: 106,
|
||||||
}
|
}
|
||||||
|
|
||||||
export function codeToScancode(code: string): number | undefined {
|
export function codeToScancode(code: string): number | undefined {
|
||||||
|
|||||||
@@ -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.
|
/// Map a JavaScript `KeyboardEvent.code` string to an e-RIC scancode.
|
||||||
/// Returns `None` for unmapped keys.
|
/// Returns `None` for unmapped keys.
|
||||||
pub fn js_code_to_scancode(code: &str) -> Option<u8> {
|
pub fn js_code_to_scancode(code: &str) -> Option<u8> {
|
||||||
|
// Mapping derived from KeyTranslator.java line 14 (Java VK_* → keynr table).
|
||||||
Some(match code {
|
Some(match code {
|
||||||
// Function row
|
// Number row (keynr 0-13)
|
||||||
"Escape" => 0,
|
"Backquote" => 0,
|
||||||
"F1" => 59,
|
"Digit1" => 1,
|
||||||
"F2" => 60,
|
"Digit2" => 2,
|
||||||
"F3" => 61,
|
"Digit3" => 3,
|
||||||
"F4" => 62,
|
"Digit4" => 4,
|
||||||
"F5" => 63,
|
"Digit5" => 5,
|
||||||
"F6" => 64,
|
"Digit6" => 6,
|
||||||
"F7" => 65,
|
"Digit7" => 7,
|
||||||
"F8" => 66,
|
"Digit8" => 8,
|
||||||
"F9" => 67,
|
"Digit9" => 9,
|
||||||
"F10" => 68,
|
"Digit0" => 10,
|
||||||
"F11" => 69,
|
"Minus" => 11,
|
||||||
"F12" => 70,
|
"Equal" => 12,
|
||||||
|
"Backspace" => 13,
|
||||||
|
|
||||||
// Number row
|
// QWERTY row (keynr 14-27)
|
||||||
"Backquote" => 1,
|
"Tab" => 14,
|
||||||
"Digit1" => 2,
|
"KeyQ" => 15,
|
||||||
"Digit2" => 3,
|
"KeyW" => 16,
|
||||||
"Digit3" => 4,
|
"KeyE" => 17,
|
||||||
"Digit4" => 5,
|
"KeyR" => 18,
|
||||||
"Digit5" => 6,
|
"KeyT" => 19,
|
||||||
"Digit6" => 7,
|
"KeyY" => 20,
|
||||||
"Digit7" => 8,
|
"KeyU" => 21,
|
||||||
"Digit8" => 9,
|
"KeyI" => 22,
|
||||||
"Digit9" => 10,
|
"KeyO" => 23,
|
||||||
"Digit0" => 11,
|
"KeyP" => 24,
|
||||||
"Minus" => 12,
|
"BracketLeft" => 25,
|
||||||
"Equal" => 13,
|
"BracketRight" => 26,
|
||||||
"Backspace" => 14,
|
"Enter" => 27,
|
||||||
|
|
||||||
// QWERTY row
|
// Home row (keynr 28-40)
|
||||||
"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
|
|
||||||
"CapsLock" => 28,
|
"CapsLock" => 28,
|
||||||
"KeyA" => 29,
|
"KeyA" => 29,
|
||||||
"KeyS" => 30,
|
"KeyS" => 30,
|
||||||
@@ -109,11 +96,10 @@ pub fn js_code_to_scancode(code: &str) -> Option<u8> {
|
|||||||
"KeyL" => 37,
|
"KeyL" => 37,
|
||||||
"Semicolon" => 38,
|
"Semicolon" => 38,
|
||||||
"Quote" => 39,
|
"Quote" => 39,
|
||||||
"Enter" => 40,
|
"Backslash" => 40,
|
||||||
|
|
||||||
// Bottom row
|
// Bottom row (keynr 41-53)
|
||||||
"ShiftLeft" => 41,
|
"ShiftLeft" => 41,
|
||||||
"Backslash" => 42,
|
|
||||||
"KeyZ" => 43,
|
"KeyZ" => 43,
|
||||||
"KeyX" => 44,
|
"KeyX" => 44,
|
||||||
"KeyC" => 45,
|
"KeyC" => 45,
|
||||||
@@ -126,51 +112,66 @@ pub fn js_code_to_scancode(code: &str) -> Option<u8> {
|
|||||||
"Slash" => 52,
|
"Slash" => 52,
|
||||||
"ShiftRight" => 53,
|
"ShiftRight" => 53,
|
||||||
|
|
||||||
// Modifier / bottom row
|
// Modifiers (keynr 54-58)
|
||||||
"ControlLeft" => 54,
|
"ControlLeft" => 54,
|
||||||
"MetaLeft" => 105,
|
|
||||||
"AltLeft" => 55,
|
"AltLeft" => 55,
|
||||||
"Space" => 56,
|
"Space" => 56,
|
||||||
"AltRight" => 57,
|
"AltRight" => 57,
|
||||||
"MetaRight" => 106,
|
|
||||||
"ControlRight" => 58,
|
"ControlRight" => 58,
|
||||||
|
|
||||||
// Navigation cluster
|
// Escape + Function keys (keynr 59-71)
|
||||||
"PrintScreen" => 71,
|
"Escape" => 59,
|
||||||
"ScrollLock" => 72,
|
"F1" => 60,
|
||||||
"Pause" => 73,
|
"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,
|
"Insert" => 75,
|
||||||
"Home" => 76,
|
"Home" => 76,
|
||||||
"PageUp" => 77,
|
"PageUp" => 77,
|
||||||
"Delete" => 78,
|
"Delete" => 78,
|
||||||
"End" => 79,
|
"End" => 79,
|
||||||
"PageDown" => 80,
|
"PageDown" => 80,
|
||||||
|
|
||||||
// Arrow keys
|
|
||||||
"ArrowUp" => 81,
|
"ArrowUp" => 81,
|
||||||
"ArrowLeft" => 82,
|
"ArrowLeft" => 82,
|
||||||
"ArrowDown" => 83,
|
"ArrowDown" => 83,
|
||||||
"ArrowRight" => 84,
|
"ArrowRight" => 84,
|
||||||
|
|
||||||
// Numpad
|
// Numpad (keynr 85-101)
|
||||||
"NumLock" => 85,
|
"NumLock" => 85,
|
||||||
"NumpadDivide" => 86,
|
"Numpad7" => 86,
|
||||||
"NumpadMultiply" => 87,
|
"Numpad8" => 87,
|
||||||
"NumpadSubtract" => 88,
|
"Numpad9" => 88,
|
||||||
"NumpadAdd" => 89,
|
"NumpadAdd" => 89,
|
||||||
"NumpadEnter" => 98,
|
"NumpadDivide" => 90,
|
||||||
"Numpad7" => 90,
|
|
||||||
"Numpad8" => 94,
|
|
||||||
"Numpad9" => 99,
|
|
||||||
"Numpad4" => 91,
|
"Numpad4" => 91,
|
||||||
"Numpad5" => 92,
|
"Numpad5" => 92,
|
||||||
"Numpad6" => 93,
|
"Numpad6" => 93,
|
||||||
|
"NumpadMultiply" => 94,
|
||||||
"Numpad1" => 95,
|
"Numpad1" => 95,
|
||||||
"Numpad2" => 96,
|
"Numpad2" => 96,
|
||||||
"Numpad3" => 97,
|
"Numpad3" => 97,
|
||||||
|
"NumpadEnter" => 98,
|
||||||
|
"NumpadSubtract" => 99,
|
||||||
"Numpad0" => 100,
|
"Numpad0" => 100,
|
||||||
"NumpadDecimal" => 101,
|
"NumpadDecimal" => 101,
|
||||||
|
|
||||||
|
// Windows/Meta keys (keynr 105-106)
|
||||||
|
"MetaLeft" => 105,
|
||||||
|
"MetaRight" => 106,
|
||||||
|
|
||||||
_ => return None,
|
_ => return None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -214,10 +215,20 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_js_code_mapping() {
|
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("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("ControlLeft"), Some(54));
|
||||||
assert_eq!(js_code_to_scancode("Delete"), Some(78));
|
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);
|
assert_eq!(js_code_to_scancode("Unknown"), None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user