11#![ allow( improper_ctypes_definitions) ]
22use crate :: macos:: common:: * ;
33use crate :: rdev:: { Event , GrabError } ;
4- use cocoa:: base:: nil;
5- use cocoa:: foundation:: NSAutoreleasePool ;
6- use core_graphics:: event:: { CGEventTapLocation , CGEventType } ;
4+ use objc2_core_foundation:: { CFMachPort , CFRunLoop , kCFRunLoopCommonModes} ;
5+ use objc2_core_graphics:: {
6+ CGEvent , CGEventTapCallBack , CGEventTapLocation , CGEventTapOptions , CGEventTapPlacement ,
7+ CGEventTapProxy , CGEventType , kCGEventMaskForAllEvents,
8+ } ;
9+ use objc2_foundation:: NSAutoreleasePool ;
710use std:: os:: raw:: c_void;
11+ use std:: ptr:: { NonNull , null_mut} ;
812
913static mut GLOBAL_CALLBACK : Option < Box < dyn FnMut ( Event ) -> Option < Event > > > = None ;
1014
1115#[ link( name = "Cocoa" , kind = "framework" ) ]
1216unsafe extern "C" { }
1317
14- unsafe extern "C" fn raw_callback (
18+ unsafe extern "C-unwind " fn raw_callback (
1519 _proxy : CGEventTapProxy ,
1620 _type : CGEventType ,
17- cg_event : CGEventRef ,
21+ cg_event : NonNull < CGEvent > ,
1822 _user_info : * mut c_void ,
19- ) -> CGEventRef {
23+ ) -> * mut CGEvent {
2024 let opt = KEYBOARD_STATE . lock ( ) ;
2125 if let Ok ( mut keyboard) = opt {
2226 unsafe {
23- if let Some ( event) = convert ( _type, & cg_event, & mut keyboard) {
27+ if let Some ( event) = convert ( _type, cg_event, & mut keyboard) {
2428 // Reborrowing the global callback pointer.
2529 // Totally UB. but not sure there's a great alternative.
2630 let ptr = & raw mut GLOBAL_CALLBACK ;
2731 if let Some ( callback) = & mut * ptr {
2832 if callback ( event) . is_none ( ) {
29- cg_event. set_type ( CGEventType :: Null ) ;
33+ CGEvent :: set_type ( Some ( cg_event. as_ref ( ) ) , CGEventType :: Null )
3034 }
3135 }
3236 }
3337 }
3438 }
35- cg_event
39+ cg_event. as_ptr ( )
3640}
3741
3842pub fn grab < T > ( callback : T ) -> Result < ( ) , GrabError >
@@ -41,28 +45,25 @@ where
4145{
4246 unsafe {
4347 GLOBAL_CALLBACK = Some ( Box :: new ( callback) ) ;
44- let _pool = NSAutoreleasePool :: new ( nil) ;
45- let tap = CGEventTapCreate (
46- CGEventTapLocation :: HID , // HID, Session, AnnotatedSession,
47- kCGHeadInsertEventTap,
48- CGEventTapOption :: Default ,
49- kCGEventMaskForAllEvents,
50- raw_callback,
51- nil,
52- ) ;
53- if tap. is_null ( ) {
54- return Err ( GrabError :: EventTapError ) ;
55- }
56- let _loop = CFMachPortCreateRunLoopSource ( nil, tap, 0 ) ;
57- if _loop. is_null ( ) {
58- return Err ( GrabError :: LoopSourceError ) ;
59- }
48+ let _pool = NSAutoreleasePool :: new ( ) ;
49+ let callback: CGEventTapCallBack = Some ( raw_callback) ;
50+ let tap = CGEvent :: tap_create (
51+ CGEventTapLocation :: HIDEventTap , // HID, Session, AnnotatedSession,
52+ CGEventTapPlacement :: HeadInsertEventTap ,
53+ CGEventTapOptions :: Default ,
54+ kCGEventMaskForAllEvents. into ( ) ,
55+ callback,
56+ null_mut ( ) ,
57+ )
58+ . ok_or ( GrabError :: EventTapError ) ?;
59+ let loop_ = CFMachPort :: new_run_loop_source ( None , Some ( & tap) , 0 )
60+ . ok_or ( GrabError :: LoopSourceError ) ?;
6061
61- let current_loop = CFRunLoopGetCurrent ( ) ;
62- CFRunLoopAddSource ( current_loop, _loop , kCFRunLoopCommonModes) ;
62+ let current_loop = CFRunLoop :: current ( ) . unwrap ( ) ;
63+ current_loop. add_source ( Some ( & loop_ ) , kCFRunLoopCommonModes) ;
6364
64- CGEventTapEnable ( tap, true ) ;
65- CFRunLoopRun ( ) ;
65+ CGEvent :: tap_enable ( & tap, true ) ;
66+ CFRunLoop :: run ( ) ;
6667 }
6768 Ok ( ( ) )
6869}
0 commit comments