Skip to content

Commit

Permalink
Rewrite VirtualKey mapping to correctly handle non-translate (#86)
Browse files Browse the repository at this point in the history
* Fix beauty error

* Rewrite VirtualKey mapping to correctly handle non-translate
  • Loading branch information
Sainan authored Oct 30, 2024
1 parent 5a746bf commit bc31f47
Showing 1 changed file with 172 additions and 53 deletions.
225 changes: 172 additions & 53 deletions wooting-analog-sdk/src/keycode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,139 @@ lazy_static! {
bimap
};

//VirtualKey, Scancode
static ref VIRTUALKEY_OVERRIDE: BiMap<u8, u16> = {
//<HID code, VirtualKey> based on US layout
static ref HID_TO_VK_MAP_US: BiMap<u8, u8> = {
let mut bimap: BiMap<u8, u8> = BiMap::new();
bimap.insert(0x04, 0x41); // US_A
bimap.insert(0x05, 0x42); // US_B
bimap.insert(0x06, 0x43); // US_C
bimap.insert(0x07, 0x44); // US_D
bimap.insert(0x08, 0x45); // US_E
bimap.insert(0x09, 0x46); // US_F
bimap.insert(0x0a, 0x47); // US_G
bimap.insert(0x0b, 0x48); // US_H
bimap.insert(0x0c, 0x49); // US_I
bimap.insert(0x0d, 0x4A); // US_J
bimap.insert(0x0e, 0x4B); // US_K
bimap.insert(0x0f, 0x4C); // US_L
bimap.insert(0x10, 0x4D); // US_M
bimap.insert(0x11, 0x4E); // US_N
bimap.insert(0x12, 0x4F); // US_O
bimap.insert(0x13, 0x50); // US_P
bimap.insert(0x14, 0x51); // US_Q
bimap.insert(0x15, 0x52); // US_R
bimap.insert(0x16, 0x53); // US_S
bimap.insert(0x17, 0x54); // US_T
bimap.insert(0x18, 0x55); // US_U
bimap.insert(0x19, 0x56); // US_V
bimap.insert(0x1a, 0x57); // US_W
bimap.insert(0x1b, 0x58); // US_X
bimap.insert(0x1c, 0x59); // US_Y
bimap.insert(0x1d, 0x5A); // US_Z

bimap.insert(0x1e, 0x31); // DIGIT1
bimap.insert(0x1f, 0x32); // DIGIT2
bimap.insert(0x20, 0x33); // DIGIT3
bimap.insert(0x21, 0x34); // DIGIT4
bimap.insert(0x22, 0x35); // DIGIT5
bimap.insert(0x23, 0x36); // DIGIT6
bimap.insert(0x24, 0x37); // DIGIT7
bimap.insert(0x25, 0x38); // DIGIT8
bimap.insert(0x26, 0x39); // DIGIT9
bimap.insert(0x27, 0x30); // DIGIT0

bimap.insert(0x28, 0x0D); // ENTER
bimap.insert(0x29, 0x1B); // ESCAPE
bimap.insert(0x2a, 0x08); // BACKSPACE
bimap.insert(0x2b, 0x09); // TAB
bimap.insert(0x2c, 0x20); // SPACE
bimap.insert(0x2d, 0xBD); // MINUS
bimap.insert(0x2e, 0xBB); // EQUAL
bimap.insert(0x2f, 0xDB); // BRACKET_LEFT

bimap.insert(0x30, 0xDD); // BRACKET_RIGHT
bimap.insert(0x31, 0xDC); // BACKSLASH

bimap.insert(0x33, 0xBA); // SEMICOLON
bimap.insert(0x34, 0xDE); // QUOTE
bimap.insert(0x35, 0xC0); // BACKQUOTE
bimap.insert(0x36, 0xBC); // COMMA
bimap.insert(0x37, 0xBE); // PERIOD

bimap.insert(0x38, 0xBF); // SLASH
bimap.insert(0x39, 0x14); // CAPS_LOCK

bimap.insert(0x3a, 0x70); // F1
bimap.insert(0x3b, 0x71); // F2
bimap.insert(0x3c, 0x72); // F3
bimap.insert(0x3d, 0x73); // F4
bimap.insert(0x3e, 0x74); // F5
bimap.insert(0x3f, 0x75); // F6
bimap.insert(0x40, 0x76); // F7
bimap.insert(0x41, 0x77); // F8
bimap.insert(0x42, 0x78); // F9
bimap.insert(0x43, 0x79); // F10
bimap.insert(0x44, 0x7A); // F11
bimap.insert(0x45, 0x7B); // F12

bimap.insert(0x46, 0x2C); // PRINT_SCREEN
bimap.insert(0x47, 0x91); // SCROLL_LOCK

bimap.insert(0x48, 0x13); // PAUSE
bimap.insert(0x49, 0x2D); // INSERT
bimap.insert(0x4a, 0x24); // HOME
bimap.insert(0x4b, 0x21); // PAGE_UP
bimap.insert(0x4c, 0x2E); // DELETE
bimap.insert(0x4d, 0x23); // END
bimap.insert(0x4e, 0x22); // PAGE_DOWN

bimap.insert(0x4f, 0x27); // ARROW_RIGHT
bimap.insert(0x50, 0x25); // ARROW_LEFT
bimap.insert(0x51, 0x28); // ARROW_DOWN
bimap.insert(0x52, 0x26); // ARROW_UP

bimap.insert(0x53, 0x90); // NUM_LOCK
bimap.insert(0x54, 0x6F); // NUMPAD_DIVIDE
bimap.insert(0x55, 0x6A); // NUMPAD_MULTIPLY
bimap.insert(0x56, 0x6D); // NUMPAD_SUBTRACT
bimap.insert(0x57, 0x6B); // NUMPAD_ADD
bimap.insert(0x58, 0x0D); // NUMPAD_ENTER
bimap.insert(0x59, 0x61); // NUMPAD1
bimap.insert(0x5a, 0x62); // NUMPAD2
bimap.insert(0x5b, 0x63); // NUMPAD3
bimap.insert(0x5c, 0x64); // NUMPAD4
bimap.insert(0x5d, 0x65); // NUMPAD5
bimap.insert(0x5e, 0x66); // NUMPAD6
bimap.insert(0x5f, 0x67); // NUMPAD7
bimap.insert(0x60, 0x68); // NUMPAD8
bimap.insert(0x61, 0x69); // NUMPAD9
bimap.insert(0x62, 0x60); // NUMPAD0
bimap.insert(0x63, 0x6E); // NUMPAD_DECIMAL

bimap.insert(0x64, 0xE2); // INTL_BACKSLASH
bimap.insert(0x65, 0x5D); // CONTEXT_MENU
bimap.insert(0x67, 0x0B); // NUMPAD_EQUAL

bimap.insert(0x68, 0x7C); // F13
bimap.insert(0x69, 0x7D); // F14
bimap.insert(0x6a, 0x7E); // F15
bimap.insert(0x6b, 0x7F); // F16
bimap.insert(0x6c, 0x80); // F17
bimap.insert(0x6d, 0x81); // F18
bimap.insert(0x6e, 0x82); // F19
bimap.insert(0x6f, 0x83); // F20
bimap.insert(0x70, 0x84); // F21
bimap.insert(0x71, 0x85); // F22
bimap.insert(0x72, 0x86); // F23
bimap.insert(0x73, 0x87); // F24

bimap.insert(0x75, 0x2F); // HELP

bimap
};

//<VirtualKey, Scancode>
static ref VIRTUALKEY_OVERRIDE: BiMap<u8, u16> = {
let mut bimap: BiMap<u8, u16> = BiMap::new();
bimap.insert(0x60, 0x0052); //NUMPAD0
bimap.insert(0x61, 0x004f); //NUMPAD1
Expand All @@ -194,67 +325,59 @@ lazy_static! {
}

#[allow(unused)]
pub fn vk_to_scancode(code: u16, translate: bool) -> Option<u16> {
pub fn vk_to_hid(vk: u16, translate: bool) -> Option<u16> {
#[cfg(windows)]
unsafe {
if let Some(&code) = VIRTUALKEY_OVERRIDE.get_by_left(&(code as u8)) {
return Some(code);
}

use winapi::um::winuser::{
GetForegroundWindow, GetKeyboardLayout, GetWindowThreadProcessId, MapVirtualKeyA,
MapVirtualKeyExA,
};
let scancode: u32;
if translate {
let window_handle = GetForegroundWindow();
let thread = GetWindowThreadProcessId(window_handle, 0 as *mut u32);
let layout = GetKeyboardLayout(thread);
scancode = MapVirtualKeyExA(code.into(), 4, layout);
//println!("Window handle: {:?}, thread: {:?}, layout: {:?}, code: {} scancode: {}", window_handle, thread, layout, code, scancode);
if translate {
let scancode: u16;
if let Some(&code) = VIRTUALKEY_OVERRIDE.get_by_left(&(vk as u8)) {
scancode = code;
} else {
scancode = MapVirtualKeyA(code.into(), 0);
}
use winapi::um::winuser::MapVirtualKeyA;
scancode = unsafe { MapVirtualKeyA(vk.into(), 0) as u16 };

if scancode == 0 {
if scancode == 0 {
return None;
}
}
return scancode_to_hid(scancode);
} else {
if let Some(&hid) = HID_TO_VK_MAP_US.get_by_right(&(vk as u8)) {
return Some(hid as u16);
} else {
return None;
}

return Some(scancode as u16);
}

#[cfg(not(windows))]
None
}

#[allow(unused)]
pub fn scancode_to_vk(code: u16, translate: bool) -> Option<u16> {
pub fn hid_to_vk(hid: u16, translate: bool) -> Option<u16> {
#[cfg(windows)]
unsafe {
if let Some(&code) = VIRTUALKEY_OVERRIDE.get_by_right(&code) {
return Some(code as u16);
}
if translate {
if let Some(scancode) = hid_to_scancode(hid) {
if let Some(&hid) = VIRTUALKEY_OVERRIDE.get_by_right(&scancode) {
return Some(hid as u16);
}

use winapi::um::winuser::MapVirtualKeyA;
let vk: u32 = unsafe { MapVirtualKeyA(scancode.into(), 3) };

use winapi::um::winuser::{
GetForegroundWindow, GetKeyboardLayout, GetWindowThreadProcessId, MapVirtualKeyA,
MapVirtualKeyExA,
};
let scancode: u32;
if translate {
let window_handle = GetForegroundWindow();
let thread = GetWindowThreadProcessId(window_handle, 0 as *mut u32);
let layout = GetKeyboardLayout(thread);
scancode = MapVirtualKeyExA(code.into(), 3, layout);
//println!("Window handle: {:?}, thread: {:?}, layout: {:?}, code: {} scancode: {}", window_handle, thread, layout, code, scancode);
if (vk == 0) {
return None;
}

return Some(vk as u16);
} else {
scancode = MapVirtualKeyA(code.into(), 3);
return None;
}

if scancode == 0 {
} else {
if let Some(&vk) = HID_TO_VK_MAP_US.get_by_left(&(hid as u8)) {
return Some(vk as u16);
} else {
return None;
}

return Some(scancode as u16);
}

#[cfg(not(windows))]
Expand Down Expand Up @@ -302,8 +425,8 @@ pub fn code_to_hid(code: u16, mode: &KeycodeType) -> Option<u16> {
}
}
KeycodeType::ScanCode1 => scancode_to_hid(code),
KeycodeType::VirtualKey => vk_to_scancode(code, false).and_then(scancode_to_hid),
KeycodeType::VirtualKeyTranslate => vk_to_scancode(code, true).and_then(scancode_to_hid),
KeycodeType::VirtualKey => vk_to_hid(code, false),
KeycodeType::VirtualKeyTranslate => vk_to_hid(code, true),
}
}

Expand All @@ -325,12 +448,8 @@ pub fn hid_to_code(code: u16, mode: &KeycodeType) -> Option<u16> {
}
}
KeycodeType::ScanCode1 => hid_to_scancode(code),
KeycodeType::VirtualKey => {
hid_to_scancode(code).and_then(|code| scancode_to_vk(code, false))
}
KeycodeType::VirtualKeyTranslate => {
hid_to_scancode(code).and_then(|code| scancode_to_vk(code, true))
}
KeycodeType::VirtualKey => hid_to_vk(code, false),
KeycodeType::VirtualKeyTranslate => hid_to_vk(code, true),
}
}

Expand Down

0 comments on commit bc31f47

Please sign in to comment.