Skip to content

Commit 2c3fac2

Browse files
committed
Fix macos.
1 parent 52edfb5 commit 2c3fac2

File tree

5 files changed

+285
-274
lines changed

5 files changed

+285
-274
lines changed

src/macos/common.rs

Lines changed: 108 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ pub const kCGEventMaskForAllEvents: u64 = (1 << CGEventType::LeftMouseDown as u6
5656

5757
#[cfg(target_os = "macos")]
5858
#[link(name = "Cocoa", kind = "framework")]
59-
extern "C" {
59+
unsafe extern "C" {
6060
#[allow(improper_ctypes)]
6161
pub fn CGEventTapCreate(
6262
tap: CGEventTapLocation,
@@ -100,118 +100,120 @@ pub unsafe fn convert(
100100
cg_event: &CGEvent,
101101
keyboard_state: &mut Keyboard,
102102
) -> Option<Event> {
103-
let option_type = match _type {
104-
CGEventType::LeftMouseDown => Some(EventType::ButtonPress(Button::Left)),
105-
CGEventType::LeftMouseUp => Some(EventType::ButtonRelease(Button::Left)),
106-
CGEventType::RightMouseDown => Some(EventType::ButtonPress(Button::Right)),
107-
CGEventType::RightMouseUp => Some(EventType::ButtonRelease(Button::Right)),
108-
CGEventType::MouseMoved => {
109-
let point = cg_event.location();
110-
Some(EventType::MouseMove {
111-
x: point.x,
112-
y: point.y,
113-
})
114-
}
115-
CGEventType::LeftMouseDragged => {
116-
let point = cg_event.location();
117-
Some(EventType::MouseMove {
118-
x: point.x,
119-
y: point.y,
120-
})
121-
}
122-
CGEventType::RightMouseDragged => {
123-
let point = cg_event.location();
124-
Some(EventType::MouseMove {
125-
x: point.x,
126-
y: point.y,
127-
})
128-
}
129-
CGEventType::KeyDown => {
130-
let code = cg_event.get_integer_value_field(EventField::KEYBOARD_EVENT_KEYCODE);
131-
let key = key_from_code(code.try_into().ok()?);
132-
Some(EventType::KeyPress(key))
133-
}
134-
CGEventType::KeyUp => {
135-
let code = cg_event.get_integer_value_field(EventField::KEYBOARD_EVENT_KEYCODE);
136-
let key = key_from_code(code.try_into().ok()?);
137-
Some(EventType::KeyRelease(key))
138-
}
139-
CGEventType::FlagsChanged => {
140-
let code = cg_event.get_integer_value_field(EventField::KEYBOARD_EVENT_KEYCODE);
141-
let code = code.try_into().ok()?;
142-
let flags = cg_event.get_flags();
143-
let key = key_from_code(code);
144-
145-
// Determine if this is a press or release based on flag changes
146-
let mut global_flags = LAST_FLAGS.lock().unwrap();
147-
if flags.contains(CGEventFlags::CGEventFlagShift)
148-
&& !global_flags.contains(CGEventFlags::CGEventFlagShift)
149-
{
150-
*global_flags = flags;
151-
Some(EventType::KeyPress(key))
152-
} else if !flags.contains(CGEventFlags::CGEventFlagShift)
153-
&& global_flags.contains(CGEventFlags::CGEventFlagShift)
154-
{
155-
*global_flags = flags;
156-
Some(EventType::KeyRelease(key))
157-
} else if flags.contains(CGEventFlags::CGEventFlagControl)
158-
&& !global_flags.contains(CGEventFlags::CGEventFlagControl)
159-
{
160-
*global_flags = flags;
161-
Some(EventType::KeyPress(key))
162-
} else if !flags.contains(CGEventFlags::CGEventFlagControl)
163-
&& global_flags.contains(CGEventFlags::CGEventFlagControl)
164-
{
165-
*global_flags = flags;
166-
Some(EventType::KeyRelease(key))
167-
} else if flags.contains(CGEventFlags::CGEventFlagAlternate)
168-
&& !global_flags.contains(CGEventFlags::CGEventFlagAlternate)
169-
{
170-
*global_flags = flags;
171-
Some(EventType::KeyPress(key))
172-
} else if !flags.contains(CGEventFlags::CGEventFlagAlternate)
173-
&& global_flags.contains(CGEventFlags::CGEventFlagAlternate)
174-
{
175-
*global_flags = flags;
176-
Some(EventType::KeyRelease(key))
177-
} else if flags.contains(CGEventFlags::CGEventFlagCommand)
178-
&& !global_flags.contains(CGEventFlags::CGEventFlagCommand)
179-
{
180-
*global_flags = flags;
103+
unsafe {
104+
let option_type = match _type {
105+
CGEventType::LeftMouseDown => Some(EventType::ButtonPress(Button::Left)),
106+
CGEventType::LeftMouseUp => Some(EventType::ButtonRelease(Button::Left)),
107+
CGEventType::RightMouseDown => Some(EventType::ButtonPress(Button::Right)),
108+
CGEventType::RightMouseUp => Some(EventType::ButtonRelease(Button::Right)),
109+
CGEventType::MouseMoved => {
110+
let point = cg_event.location();
111+
Some(EventType::MouseMove {
112+
x: point.x,
113+
y: point.y,
114+
})
115+
}
116+
CGEventType::LeftMouseDragged => {
117+
let point = cg_event.location();
118+
Some(EventType::MouseMove {
119+
x: point.x,
120+
y: point.y,
121+
})
122+
}
123+
CGEventType::RightMouseDragged => {
124+
let point = cg_event.location();
125+
Some(EventType::MouseMove {
126+
x: point.x,
127+
y: point.y,
128+
})
129+
}
130+
CGEventType::KeyDown => {
131+
let code = cg_event.get_integer_value_field(EventField::KEYBOARD_EVENT_KEYCODE);
132+
let key = key_from_code(code.try_into().ok()?);
181133
Some(EventType::KeyPress(key))
182-
} else if !flags.contains(CGEventFlags::CGEventFlagCommand)
183-
&& global_flags.contains(CGEventFlags::CGEventFlagCommand)
184-
{
185-
*global_flags = flags;
134+
}
135+
CGEventType::KeyUp => {
136+
let code = cg_event.get_integer_value_field(EventField::KEYBOARD_EVENT_KEYCODE);
137+
let key = key_from_code(code.try_into().ok()?);
186138
Some(EventType::KeyRelease(key))
187-
} else {
188-
None
189139
}
190-
}
191-
CGEventType::ScrollWheel => {
192-
let delta_y =
193-
cg_event.get_integer_value_field(EventField::SCROLL_WHEEL_EVENT_POINT_DELTA_AXIS_1);
194-
let delta_x =
195-
cg_event.get_integer_value_field(EventField::SCROLL_WHEEL_EVENT_POINT_DELTA_AXIS_2);
196-
Some(EventType::Wheel { delta_x, delta_y })
197-
}
198-
_ => None,
199-
};
200-
if let Some(event_type) = option_type {
201-
let name = match event_type {
202-
EventType::KeyPress(_) => {
203-
let code =
204-
cg_event.get_integer_value_field(EventField::KEYBOARD_EVENT_KEYCODE) as u32;
140+
CGEventType::FlagsChanged => {
141+
let code = cg_event.get_integer_value_field(EventField::KEYBOARD_EVENT_KEYCODE);
142+
let code = code.try_into().ok()?;
205143
let flags = cg_event.get_flags();
206-
keyboard_state.create_string_for_key(code, flags)
144+
let key = key_from_code(code);
145+
146+
// Determine if this is a press or release based on flag changes
147+
let mut global_flags = LAST_FLAGS.lock().unwrap();
148+
if flags.contains(CGEventFlags::CGEventFlagShift)
149+
&& !global_flags.contains(CGEventFlags::CGEventFlagShift)
150+
{
151+
*global_flags = flags;
152+
Some(EventType::KeyPress(key))
153+
} else if !flags.contains(CGEventFlags::CGEventFlagShift)
154+
&& global_flags.contains(CGEventFlags::CGEventFlagShift)
155+
{
156+
*global_flags = flags;
157+
Some(EventType::KeyRelease(key))
158+
} else if flags.contains(CGEventFlags::CGEventFlagControl)
159+
&& !global_flags.contains(CGEventFlags::CGEventFlagControl)
160+
{
161+
*global_flags = flags;
162+
Some(EventType::KeyPress(key))
163+
} else if !flags.contains(CGEventFlags::CGEventFlagControl)
164+
&& global_flags.contains(CGEventFlags::CGEventFlagControl)
165+
{
166+
*global_flags = flags;
167+
Some(EventType::KeyRelease(key))
168+
} else if flags.contains(CGEventFlags::CGEventFlagAlternate)
169+
&& !global_flags.contains(CGEventFlags::CGEventFlagAlternate)
170+
{
171+
*global_flags = flags;
172+
Some(EventType::KeyPress(key))
173+
} else if !flags.contains(CGEventFlags::CGEventFlagAlternate)
174+
&& global_flags.contains(CGEventFlags::CGEventFlagAlternate)
175+
{
176+
*global_flags = flags;
177+
Some(EventType::KeyRelease(key))
178+
} else if flags.contains(CGEventFlags::CGEventFlagCommand)
179+
&& !global_flags.contains(CGEventFlags::CGEventFlagCommand)
180+
{
181+
*global_flags = flags;
182+
Some(EventType::KeyPress(key))
183+
} else if !flags.contains(CGEventFlags::CGEventFlagCommand)
184+
&& global_flags.contains(CGEventFlags::CGEventFlagCommand)
185+
{
186+
*global_flags = flags;
187+
Some(EventType::KeyRelease(key))
188+
} else {
189+
None
190+
}
191+
}
192+
CGEventType::ScrollWheel => {
193+
let delta_y = cg_event
194+
.get_integer_value_field(EventField::SCROLL_WHEEL_EVENT_POINT_DELTA_AXIS_1);
195+
let delta_x = cg_event
196+
.get_integer_value_field(EventField::SCROLL_WHEEL_EVENT_POINT_DELTA_AXIS_2);
197+
Some(EventType::Wheel { delta_x, delta_y })
207198
}
208199
_ => None,
209200
};
210-
return Some(Event {
211-
event_type,
212-
time: SystemTime::now(),
213-
name,
214-
});
201+
if let Some(event_type) = option_type {
202+
let name = match event_type {
203+
EventType::KeyPress(_) => {
204+
let code =
205+
cg_event.get_integer_value_field(EventField::KEYBOARD_EVENT_KEYCODE) as u32;
206+
let flags = cg_event.get_flags();
207+
keyboard_state.create_string_for_key(code, flags)
208+
}
209+
_ => None,
210+
};
211+
return Some(Event {
212+
event_type,
213+
time: SystemTime::now(),
214+
name,
215+
});
216+
}
215217
}
216218
None
217219
}

src/macos/grab.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,25 @@ use std::os::raw::c_void;
99
static mut GLOBAL_CALLBACK: Option<Box<dyn FnMut(Event) -> Option<Event>>> = None;
1010

1111
#[link(name = "Cocoa", kind = "framework")]
12-
extern "C" {}
12+
unsafe extern "C" {}
1313

1414
unsafe extern "C" fn raw_callback(
1515
_proxy: CGEventTapProxy,
1616
_type: CGEventType,
1717
cg_event: CGEventRef,
1818
_user_info: *mut c_void,
1919
) -> CGEventRef {
20-
// println!("Event ref {:?}", cg_event_ptr);
21-
// let cg_event: CGEvent = transmute_copy::<*mut c_void, CGEvent>(&cg_event_ptr);
2220
let opt = KEYBOARD_STATE.lock();
2321
if let Ok(mut keyboard) = opt {
24-
if let Some(event) = convert(_type, &cg_event, &mut keyboard) {
25-
// Reborrowing the global callback pointer.
26-
// Totally UB. but not sure there's a great alternative.
27-
let ptr = &raw mut GLOBAL_CALLBACK;
28-
if let Some(callback) = &mut *ptr {
29-
if callback(event).is_none() {
30-
cg_event.set_type(CGEventType::Null);
22+
unsafe {
23+
if let Some(event) = convert(_type, &cg_event, &mut keyboard) {
24+
// Reborrowing the global callback pointer.
25+
// Totally UB. but not sure there's a great alternative.
26+
let ptr = &raw mut GLOBAL_CALLBACK;
27+
if let Some(callback) = &mut *ptr {
28+
if callback(event).is_none() {
29+
cg_event.set_type(CGEventType::Null);
30+
}
3131
}
3232
}
3333
}

src/macos/keyboard.rs

Lines changed: 42 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ lazy_static::lazy_static! {
3939
#[allow(clippy::duplicated_attributes)]
4040
#[link(name = "Cocoa", kind = "framework")]
4141
#[link(name = "Carbon", kind = "framework")]
42-
extern "C" {
42+
unsafe extern "C" {
4343
fn TISCopyCurrentKeyboardLayoutInputSource() -> TISInputSourceRef;
4444
fn TISCopyCurrentKeyboardInputSource() -> TISInputSourceRef;
4545
fn TISGetInputSourceProperty(source: TISInputSourceRef, property: *mut c_void) -> CFDataRef;
@@ -81,27 +81,25 @@ impl Keyboard {
8181
}
8282

8383
fn modifier_state(&self) -> ModifierState {
84-
if self.caps_lock || self.shift {
85-
2
86-
} else {
87-
0
88-
}
84+
if self.caps_lock || self.shift { 2 } else { 0 }
8985
}
9086

9187
pub(crate) unsafe fn create_string_for_key(
9288
&mut self,
9389
code: u32,
9490
flags: CGEventFlags,
9591
) -> Option<String> {
96-
let modifier_state = flags_to_state(flags.bits());
92+
unsafe {
93+
let modifier_state = flags_to_state(flags.bits());
9794

98-
if self.is_main_thread {
99-
self.string_from_code(code, modifier_state)
100-
} else {
101-
QUEUE.exec_sync(move || {
102-
// ignore all modifiers for name
95+
if self.is_main_thread {
10396
self.string_from_code(code, modifier_state)
104-
})
97+
} else {
98+
QUEUE.exec_sync(move || {
99+
// ignore all modifiers for name
100+
self.string_from_code(code, modifier_state)
101+
})
102+
}
105103
}
106104
}
107105

@@ -110,38 +108,40 @@ impl Keyboard {
110108
code: u32,
111109
modifier_state: ModifierState,
112110
) -> Option<String> {
113-
let mut keyboard = TISCopyCurrentKeyboardInputSource();
114-
let mut layout = TISGetInputSourceProperty(keyboard, kTISPropertyUnicodeKeyLayoutData);
115-
116-
if layout.is_null() {
117-
// TISGetInputSourceProperty returns NULL when using CJK input methods,
118-
// using TISCopyCurrentKeyboardLayoutInputSource to fix it.
119-
keyboard = TISCopyCurrentKeyboardLayoutInputSource();
120-
layout = TISGetInputSourceProperty(keyboard, kTISPropertyUnicodeKeyLayoutData);
111+
unsafe {
112+
let mut keyboard = TISCopyCurrentKeyboardInputSource();
113+
let mut layout = TISGetInputSourceProperty(keyboard, kTISPropertyUnicodeKeyLayoutData);
114+
121115
if layout.is_null() {
122-
return None;
116+
// TISGetInputSourceProperty returns NULL when using CJK input methods,
117+
// using TISCopyCurrentKeyboardLayoutInputSource to fix it.
118+
keyboard = TISCopyCurrentKeyboardLayoutInputSource();
119+
layout = TISGetInputSourceProperty(keyboard, kTISPropertyUnicodeKeyLayoutData);
120+
if layout.is_null() {
121+
return None;
122+
}
123123
}
124+
let layout_ptr = CFDataGetBytePtr(layout);
125+
126+
let mut buff = [0_u16; BUF_LEN];
127+
let kb_type = LMGetKbdType();
128+
let mut length = 0;
129+
let _retval = UCKeyTranslate(
130+
layout_ptr,
131+
code.try_into().ok()?,
132+
kUCKeyActionDown,
133+
modifier_state,
134+
kb_type,
135+
kUCKeyTranslateDeadKeysBit,
136+
&mut self.dead_state, // deadKeyState
137+
BUF_LEN, // max string length
138+
&mut length as *mut UniCharCount, // actual string length
139+
&mut buff as *mut [UniChar; BUF_LEN], // unicode string
140+
);
141+
CFRelease(keyboard);
142+
143+
String::from_utf16(&buff[..length]).ok()
124144
}
125-
let layout_ptr = CFDataGetBytePtr(layout);
126-
127-
let mut buff = [0_u16; BUF_LEN];
128-
let kb_type = LMGetKbdType();
129-
let mut length = 0;
130-
let _retval = UCKeyTranslate(
131-
layout_ptr,
132-
code.try_into().ok()?,
133-
kUCKeyActionDown,
134-
modifier_state,
135-
kb_type,
136-
kUCKeyTranslateDeadKeysBit,
137-
&mut self.dead_state, // deadKeyState
138-
BUF_LEN, // max string length
139-
&mut length as *mut UniCharCount, // actual string length
140-
&mut buff as *mut [UniChar; BUF_LEN], // unicode string
141-
);
142-
CFRelease(keyboard);
143-
144-
String::from_utf16(&buff[..length]).ok()
145145
}
146146
}
147147

0 commit comments

Comments
 (0)