Skip to content
Merged
Show file tree
Hide file tree
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
12 changes: 12 additions & 0 deletions src/linux/wayland/grab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,18 @@ convert_keys!(
KEY_F8, F8,
KEY_F9, F9,
KEY_F10, F10,
KEY_F13, F13,
KEY_F14, F14,
KEY_F15, F15,
KEY_F16, F16,
KEY_F17, F17,
KEY_F18, F18,
KEY_F19, F19,
KEY_F20, F20,
KEY_F21, F21,
KEY_F22, F22,
KEY_F23, F23,
KEY_F24, F24,
KEY_NUMLOCK, NumLock,
KEY_SCROLLLOCK, ScrollLock,
KEY_KP7, Kp7,
Expand Down
51 changes: 51 additions & 0 deletions src/linux/wayland/keycodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,18 @@ decl_keycodes!(
F10, 68,
F11, 87,
F12, 88,
F13, 183,
F14, 184,
F15, 185,
F16, 186,
F17, 187,
F18, 188,
F19, 189,
F20, 190,
F21, 191,
F22, 192,
F23, 193,
F24, 194,
Home, 102,
LeftArrow, 105,
MetaLeft, 125,
Expand Down Expand Up @@ -234,6 +246,18 @@ decl_keycodes_uinput!(
Key::F8 , UKey::F8,
Key::F9 , UKey::F9,
Key::F10 , UKey::F10,
Key::F13 , UKey::F13,
Key::F14 , UKey::F14,
Key::F15 , UKey::F15,
Key::F16 , UKey::F16,
Key::F17 , UKey::F17,
Key::F18 , UKey::F18,
Key::F19 , UKey::F19,
Key::F20 , UKey::F20,
Key::F21 , UKey::F21,
Key::F22 , UKey::F22,
Key::F23 , UKey::F23,
Key::F24 , UKey::F24,
Key::NumLock , UKey::NumLock,
Key::ScrollLock , UKey::ScrollLock,
Key::Kp7 , UKey::Kp7,
Expand Down Expand Up @@ -281,6 +305,8 @@ decl_keycodes_uinput!(
#[cfg(test)]
mod test {
use super::{UKey, code_from_key, key_from_code, key_from_ukey, ukey_from_key};
use crate::Key;

#[test]
fn test_reversible() {
for code in 0..65636 {
Expand All @@ -292,6 +318,31 @@ mod test {
}
}

#[test]
fn test_extended_function_key_mappings() {
let mappings = [
(Key::F13, 183, UKey::F13),
(Key::F14, 184, UKey::F14),
(Key::F15, 185, UKey::F15),
(Key::F16, 186, UKey::F16),
(Key::F17, 187, UKey::F17),
(Key::F18, 188, UKey::F18),
(Key::F19, 189, UKey::F19),
(Key::F20, 190, UKey::F20),
(Key::F21, 191, UKey::F21),
(Key::F22, 192, UKey::F22),
(Key::F23, 193, UKey::F23),
(Key::F24, 194, UKey::F24),
];

for (key, code, ukey) in mappings {
assert_eq!(code_from_key(key), Some(code));
assert_eq!(key_from_code(code), key);
assert_eq!(ukey_from_key(key), Some(ukey));
assert_eq!(key_from_ukey(ukey), key);
}
}

#[test]
fn test_reversible_uinput() {
for code in 0..u16::MAX {
Expand Down
12 changes: 12 additions & 0 deletions src/linux/x11/grab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,18 @@ convert_keys!(
KEY_F8, F8,
KEY_F9, F9,
KEY_F10, F10,
KEY_F13, F13,
KEY_F14, F14,
KEY_F15, F15,
KEY_F16, F16,
KEY_F17, F17,
KEY_F18, F18,
KEY_F19, F19,
KEY_F20, F20,
KEY_F21, F21,
KEY_F22, F22,
KEY_F23, F23,
KEY_F24, F24,
KEY_NUMLOCK, NumLock,
KEY_SCROLLLOCK, ScrollLock,
KEY_KP7, Kp7,
Expand Down
37 changes: 37 additions & 0 deletions src/linux/x11/keycodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,18 @@ decl_keycodes!(
F10, 76,
F11, 95,
F12, 96,
F13, 191,
F14, 192,
F15, 193,
F16, 194,
F17, 195,
F18, 196,
F19, 197,
F20, 198,
F21, 199,
F22, 200,
F23, 201,
F24, 202,
F2, 68,
F3, 69,
F4, 70,
Expand Down Expand Up @@ -136,6 +148,8 @@ decl_keycodes!(
#[cfg(test)]
mod test {
use super::{code_from_key, key_from_code};
use crate::Key;

#[test]
fn test_reversible() {
for code in 0..65636 {
Expand All @@ -146,4 +160,27 @@ mod test {
}
}
}

#[test]
fn test_extended_function_key_mappings() {
let mappings = [
(Key::F13, 191),
(Key::F14, 192),
(Key::F15, 193),
(Key::F16, 194),
(Key::F17, 195),
(Key::F18, 196),
(Key::F19, 197),
(Key::F20, 198),
(Key::F21, 199),
(Key::F22, 200),
(Key::F23, 201),
(Key::F24, 202),
];

for (key, code) in mappings {
assert_eq!(code_from_key(key), Some(code));
assert_eq!(key_from_code(code), key);
}
}
}
12 changes: 8 additions & 4 deletions src/macos/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::convert::TryInto;
use std::sync::Mutex;
use std::time::SystemTime;

use crate::macos::keycodes::key_from_code;
use crate::macos::keycodes::key_from_code_or_name;

use super::keycodes::key_from_special_key;

Expand Down Expand Up @@ -60,15 +60,19 @@ pub unsafe fn convert(
Some(cg_event.as_ref()),
CGEventField::KeyboardEventKeycode,
);
let key = key_from_code(code.try_into().ok()?);
let flags = CGEvent::flags(Some(cg_event.as_ref()));
let name = keyboard_state.create_string_for_key(code, flags);
let key = key_from_code_or_name(code.try_into().ok()?, name.as_deref());
Some(EventType::KeyPress(key))
}
CGEventType::KeyUp => {
let code = CGEvent::integer_value_field(
Some(cg_event.as_ref()),
CGEventField::KeyboardEventKeycode,
);
let key = key_from_code(code.try_into().ok()?);
let flags = CGEvent::flags(Some(cg_event.as_ref()));
let name = keyboard_state.create_string_for_key(code, flags);
let key = key_from_code_or_name(code.try_into().ok()?, name.as_deref());
Some(EventType::KeyRelease(key))
}
CGEventType::FlagsChanged => {
Expand All @@ -78,7 +82,7 @@ pub unsafe fn convert(
);
let code = code.try_into().ok()?;
let flags = CGEvent::flags(Some(cg_event.as_ref()));
let key = key_from_code(code);
let key = key_from_code_or_name(code, None);

// Determine if this is a press or release based on flag changes
let mut global_flags = LAST_FLAGS.lock().unwrap();
Expand Down
82 changes: 81 additions & 1 deletion src/macos/keycodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ const F1: CGKeyCode = 122;
const F10: CGKeyCode = 109;
const F11: CGKeyCode = 103;
const F12: CGKeyCode = 111;
const F13: CGKeyCode = 105;
const F14: CGKeyCode = 107;
const F15: CGKeyCode = 113;
const F16: CGKeyCode = 106;
const F17: CGKeyCode = 64;
const F18: CGKeyCode = 79;
const F19: CGKeyCode = 80;
const F20: CGKeyCode = 90;
const F2: CGKeyCode = 120;
const F3: CGKeyCode = 99;
const F4: CGKeyCode = 118;
Expand Down Expand Up @@ -98,6 +106,14 @@ pub fn code_from_key(key: Key) -> Option<CGKeyCode> {
Key::F10 => Some(F10),
Key::F11 => Some(F11),
Key::F12 => Some(F12),
Key::F13 => Some(F13),
Key::F14 => Some(F14),
Key::F15 => Some(F15),
Key::F16 => Some(F16),
Key::F17 => Some(F17),
Key::F18 => Some(F18),
Key::F19 => Some(F19),
Key::F20 => Some(F20),
Key::F2 => Some(F2),
Key::F3 => Some(F3),
Key::F4 => Some(F4),
Expand Down Expand Up @@ -182,6 +198,14 @@ pub fn key_from_code(code: CGKeyCode) -> Key {
F10 => Key::F10,
F11 => Key::F11,
F12 => Key::F12,
F13 => Key::F13,
F14 => Key::F14,
F15 => Key::F15,
F16 => Key::F16,
F17 => Key::F17,
F18 => Key::F18,
F19 => Key::F19,
F20 => Key::F20,
F2 => Key::F2,
F3 => Key::F3,
F4 => Key::F4,
Expand Down Expand Up @@ -252,6 +276,28 @@ pub fn key_from_code(code: CGKeyCode) -> Key {
}
}

pub fn key_from_code_or_name(code: CGKeyCode, name: Option<&str>) -> Key {
let key = key_from_code(code);
if !matches!(key, Key::Unknown(_)) {
return key;
}

match name.and_then(extra_function_key_from_name) {
Some(key) => key,
None => key,
}
}

fn extra_function_key_from_name(name: &str) -> Option<Key> {
match name.encode_utf16().next() {
Some(0xf718) => Some(Key::F21),
Some(0xf719) => Some(Key::F22),
Some(0xf71a) => Some(Key::F23),
Some(0xf71b) => Some(Key::F24),
_ => None,
}
}

//https://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-308/IOHIDSystem/IOKit/hidsystem/ev_keymap.h
// https://github.com/acidanthera/MacKernelSDK/blob/master/Headers/IOKit/hidsystem/ev_keymap.h

Expand Down Expand Up @@ -330,7 +376,9 @@ pub fn key_from_special_key(code: u32) -> Option<Key> {

#[cfg(test)]
mod test {
use super::{code_from_key, key_from_code};
use super::{code_from_key, key_from_code, key_from_code_or_name};
use crate::Key;

#[test]
fn test_reversible() {
for code in 0..=65535 {
Expand All @@ -341,4 +389,36 @@ mod test {
}
}
}

#[test]
fn test_extended_function_key_mappings() {
let mappings = [
(Key::F13, 105),
(Key::F14, 107),
(Key::F15, 113),
(Key::F16, 106),
(Key::F17, 64),
(Key::F18, 79),
(Key::F19, 80),
(Key::F20, 90),
];

for (key, code) in mappings {
assert_eq!(code_from_key(key), Some(code));
assert_eq!(key_from_code(code), key);
}

assert_eq!(code_from_key(Key::F21), None);
assert_eq!(code_from_key(Key::F22), None);
assert_eq!(code_from_key(Key::F23), None);
assert_eq!(code_from_key(Key::F24), None);
}

#[test]
fn test_extended_function_key_name_fallback() {
assert_eq!(key_from_code_or_name(0x6c, Some("\u{f718}")), Key::F21);
assert_eq!(key_from_code_or_name(0x6e, Some("\u{f719}")), Key::F22);
assert_eq!(key_from_code_or_name(0x70, Some("\u{f71a}")), Key::F23);
assert_eq!(key_from_code_or_name(0x5e, Some("\u{f71b}")), Key::F24);
}
}
Loading