Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite VirtualKey mapping to correctly handle non-translate #86

Merged
merged 2 commits into from
Oct 30, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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