forked from chiehw/rdev
-
Notifications
You must be signed in to change notification settings - Fork 49
Expand file tree
/
Copy pathgrab.rs
More file actions
87 lines (78 loc) · 2.4 KB
/
Copy pathgrab.rs
File metadata and controls
87 lines (78 loc) · 2.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#![allow(improper_ctypes_definitions)]
use crate::macos::common::*;
use crate::rdev::{Event, GrabError};
use cocoa::base::nil;
use cocoa::foundation::NSAutoreleasePool;
use core_graphics::event::{CGEventTapLocation, CGEventType};
use std::os::raw::c_void;
static mut GLOBAL_CALLBACK: Option<Box<dyn FnMut(Event) -> Option<Event>>> = None;
unsafe extern "C" fn raw_callback(
_proxy: CGEventTapProxy,
_type: CGEventType,
cg_event: CGEventRef,
_user_info: *mut c_void,
) -> CGEventRef {
// println!("Event ref {:?}", cg_event_ptr);
// let cg_event: CGEvent = transmute_copy::<*mut c_void, CGEvent>(&cg_event_ptr);
if let Ok(mut state) = KEYBOARD_STATE.lock() {
if let Some(keyboard) = state.as_mut() {
if let Some(event) = convert(_type, &cg_event, keyboard) {
if let Some(callback) = &mut GLOBAL_CALLBACK {
if callback(event).is_none() {
cg_event.set_type(CGEventType::Null);
}
}
}
}
}
cg_event
}
static mut CUR_LOOP: CFRunLoopSourceRef = std::ptr::null_mut();
#[inline]
pub fn is_grabbed() -> bool {
unsafe {
!CUR_LOOP.is_null()
}
}
pub fn grab<T>(callback: T) -> Result<(), GrabError>
where
T: FnMut(Event) -> Option<Event> + 'static,
{
if is_grabbed() {
return Ok(());
}
unsafe {
GLOBAL_CALLBACK = Some(Box::new(callback));
let _pool = NSAutoreleasePool::new(nil);
let tap = CGEventTapCreate(
CGEventTapLocation::Session, // HID, Session, AnnotatedSession,
kCGHeadInsertEventTap,
CGEventTapOption::Default,
kCGEventMaskForAllEvents,
raw_callback,
nil,
);
if tap.is_null() {
return Err(GrabError::EventTapError);
}
let _loop = CFMachPortCreateRunLoopSource(nil, tap, 0);
if _loop.is_null() {
return Err(GrabError::LoopSourceError);
}
CUR_LOOP = CFRunLoopGetCurrent() as _;
CFRunLoopAddSource(CUR_LOOP, _loop, kCFRunLoopCommonModes);
CGEventTapEnable(tap, true);
CFRunLoopRun();
}
Ok(())
}
pub fn exit_grab() -> Result<(), GrabError> {
unsafe {
if !CUR_LOOP.is_null() {
CFRunLoopStop(CUR_LOOP);
CUR_LOOP = std::ptr::null_mut();
}
GLOBAL_CALLBACK = None;
}
Ok(())
}