diff --git a/Cargo.toml b/Cargo.toml index 6f378640..e6c2627e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,10 +22,10 @@ serialize = ["serde"] unstable_grab = ["evdev-rs", "epoll", "inotify"] [target.'cfg(target_os = "macos")'.dependencies] -cocoa = "0.22" -core-graphics = {version = "0.19.0", features = ["highsierra"]} -core-foundation = {version = "0.7"} -core-foundation-sys = {version = "0.7"} +cocoa = "0.26.0" +core-graphics = {version = "0.24.0", features = ["highsierra"] } +core-foundation = {version = "0.10.0" } +core-foundation-sys = {version = "0.8.7" } [target.'cfg(target_os = "linux")'.dependencies] diff --git a/src/macos/common.rs b/src/macos/common.rs index 6c837ab0..75a8620d 100644 --- a/src/macos/common.rs +++ b/src/macos/common.rs @@ -9,7 +9,7 @@ use std::os::raw::c_void; use std::sync::Mutex; use std::time::SystemTime; -use crate::macos::keycodes::key_from_code; +use crate::macos::keycodes::{key_from_code, key_from_special_key}; pub type CFMachPortRef = *const c_void; pub type CFIndex = u64; @@ -135,7 +135,41 @@ pub unsafe fn convert( cg_event.get_integer_value_field(EventField::SCROLL_WHEEL_EVENT_POINT_DELTA_AXIS_2); Some(EventType::Wheel { delta_x, delta_y }) } - _ => None, + o => { + // Core graphics doesnt support NX_SYSDEFINED yet + let int_type = o as u32; + + const NX_SYSDEFINED: u32 = 14; + + if int_type == NX_SYSDEFINED { + let subtype = cg_event.get_integer_value_field(99); + let data1 = cg_event.get_integer_value_field(149); + let key_flags = data1 & 0x0000ffff; + let key_pressed = ((key_flags & 0xff00) >> 8) == 0xa; + let _key_repeat = (key_flags & 0x1) == 0x1; + let key_code = (data1 & 0xffff0000) >> 16; + + // Mouse buttons like middle click/back/forward are subtype 7 + // Subtype 8 means keyboard event + if subtype != 8 { + return None; + } + + if let Some(code) = key_from_special_key(key_code.try_into().ok()?) { + if key_pressed { + Some(EventType::KeyPress(code)) + } else { + Some(EventType::KeyRelease(code)) + } + } else { + // If we don't handle the key avoid creating an event since it can create duplicates with other keys + None + } + } else { + //println!("Unknown event type: {:?}", o as i32); + None + } + } }; if let Some(event_type) = option_type { let name = match event_type { diff --git a/src/macos/grab.rs b/src/macos/grab.rs index dd8de0fd..4807c63e 100644 --- a/src/macos/grab.rs +++ b/src/macos/grab.rs @@ -39,24 +39,29 @@ where unsafe { GLOBAL_CALLBACK = Some(Box::new(callback)); let _pool = NSAutoreleasePool::new(nil); + + // To capture media keys + const NX_SYSDEFINED: i64 = 14; + let tap = CGEventTapCreate( CGEventTapLocation::HID, // HID, Session, AnnotatedSession, kCGHeadInsertEventTap, CGEventTapOption::Default, - kCGEventMaskForAllEvents, + (1 << NX_SYSDEFINED) | kCGEventMaskForAllEvents, raw_callback, nil, ); if tap.is_null() { return Err(GrabError::EventTapError); } - let _loop = CFMachPortCreateRunLoopSource(nil, tap, 0); - if _loop.is_null() { + + let source = CFMachPortCreateRunLoopSource(nil, tap, 0); + if source.is_null() { return Err(GrabError::LoopSourceError); } let current_loop = CFRunLoopGetCurrent(); - CFRunLoopAddSource(current_loop, _loop, kCFRunLoopCommonModes); + CFRunLoopAddSource(current_loop, source, kCFRunLoopCommonModes); CGEventTapEnable(tap, true); CFRunLoopRun(); diff --git a/src/macos/keycodes.rs b/src/macos/keycodes.rs index eeb6f98e..10bb4546 100644 --- a/src/macos/keycodes.rs +++ b/src/macos/keycodes.rs @@ -251,6 +251,65 @@ pub fn key_from_code(code: CGKeyCode) -> Key { } } +//https://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-308/IOHIDSystem/IOKit/hidsystem/ev_keymap.h + +/* + * Special keys currently known to and understood by the system. + * If new specialty keys are invented, extend this list as appropriate. + * The presence of these keys in a particular implementation is not + * guaranteed. + */ +const NX_NOSPECIALKEY: u32 = 0xFFFF; +const NX_KEYTYPE_SOUND_UP: u32 = 0; +const NX_KEYTYPE_SOUND_DOWN: u32 = 1; +const NX_KEYTYPE_BRIGHTNESS_UP: u32 = 2; +const NX_KEYTYPE_BRIGHTNESS_DOWN: u32 = 3; +const NX_KEYTYPE_CAPS_LOCK: u32 = 4; +const NX_KEYTYPE_HELP: u32 = 5; +const NX_POWER_KEY: u32 = 6; +const NX_KEYTYPE_MUTE: u32 = 7; +const NX_UP_ARROW_KEY: u32 = 8; +const NX_DOWN_ARROW_KEY: u32 = 9; +const NX_KEYTYPE_NUM_LOCK: u32 = 10; + +const NX_KEYTYPE_CONTRAST_UP: u32 = 11; +const NX_KEYTYPE_CONTRAST_DOWN: u32 = 12; +const NX_KEYTYPE_LAUNCH_PANEL: u32 = 13; +const NX_KEYTYPE_EJECT: u32 = 14; +const NX_KEYTYPE_VIDMIRROR: u32 = 15; + +const NX_KEYTYPE_PLAY: u32 = 16; +const NX_KEYTYPE_NEXT: u32 = 17; +const NX_KEYTYPE_PREVIOUS: u32 = 18; +const NX_KEYTYPE_FAST: u32 = 19; +const NX_KEYTYPE_REWIND: u32 = 20; + +const NX_KEYTYPE_ILLUMINATION_UP: u32 = 21; +const NX_KEYTYPE_ILLUMINATION_DOWN: u32 = 22; +const NX_KEYTYPE_ILLUMINATION_TOGGLE: u32 = 23; + +const NX_NUMSPECIALKEYS: u32 = 24; /* Maximum number of special keys */ +const NX_NUM_SCANNED_SPECIALKEYS: u32 = 24; /* First 24 special keys are */ +/* actively scanned in kernel */ + +pub fn key_from_special_key(code: u32) -> Option { + match code { + NX_KEYTYPE_SOUND_UP => Some(Key::VolumeUp), + NX_KEYTYPE_SOUND_DOWN => Some(Key::VolumeDown), + NX_KEYTYPE_MUTE => Some(Key::VolumeMute), + NX_KEYTYPE_BRIGHTNESS_UP => Some(Key::BrightnessUp), + NX_KEYTYPE_BRIGHTNESS_DOWN => Some(Key::BrightnessDown), + NX_KEYTYPE_PLAY => Some(Key::PlayPause), + NX_KEYTYPE_NEXT => Some(Key::NextTrack), + NX_KEYTYPE_PREVIOUS => Some(Key::PreviousTrack), + NX_KEYTYPE_CAPS_LOCK => Some(Key::CapsLock), + NX_UP_ARROW_KEY => Some(Key::UpArrow), + NX_DOWN_ARROW_KEY => Some(Key::DownArrow), + NX_KEYTYPE_NUM_LOCK => Some(Key::NumLock), + _ => None, + } +} + #[cfg(test)] mod test { use super::{code_from_key, key_from_code}; diff --git a/src/rdev.rs b/src/rdev.rs index 277be3b0..a7737c7c 100644 --- a/src/rdev.rs +++ b/src/rdev.rs @@ -208,6 +208,14 @@ pub enum Key { Kp9, KpDelete, Function, + VolumeUp, + VolumeDown, + VolumeMute, + BrightnessUp, + BrightnessDown, + PreviousTrack, + PlayPause, + NextTrack, Unknown(u32), } diff --git a/src/windows/keycodes.rs b/src/windows/keycodes.rs index c3707f76..b3d1e1b9 100644 --- a/src/windows/keycodes.rs +++ b/src/windows/keycodes.rs @@ -132,7 +132,13 @@ decl_keycodes! { Kp7, 103, Kp8, 104, Kp9, 105, - KpDelete, 110 + KpDelete, 110, + VolumeMute, 173, + VolumeDown, 174, + VolumeUp, 175, + NextTrack, 176, + PreviousTrack, 177, + PlayPause, 179 } #[cfg(test)]