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
45 changes: 31 additions & 14 deletions libs/enigo/src/macos/macos_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,27 @@ impl Enigo {
self.flags |= flag;
}

fn post(&self, event: CGEvent) {
// event.set_flags(CGEventFlags::CGEventFlagNull); will cause `F11` not working. no idea why.
if !self.ignore_flags && self.flags != CGEventFlags::CGEventFlagNull {
// Just check F11 for minimal changes.
// Since enigo (legacy mode) is deprecated, it is currently in maintenance only.
fn post(&self, event: CGEvent, keycode: Option<u16>) {
if keycode == Some(kVK_F11) {
// Some key events require the flags to work.
// We can't simply set the flag to `CGEventFlags::CGEventFlagNull`.
// eg. `F11` requires flags `CGEventFlags::CGEventFlagSecondaryFn | 0x20000000` to work.
self.post_event(event, false);
} else {
// macOS system may use the previous event flag to generate the next event.
// Only found this issue when locking the screen.
// When we use enigo to lock the screen, the next mouse event will have the flag
// `CGEventFlagControl | CGEventFlagCommand | 0x20000000`.
// The key event will also have the flag `CGEventFlagControl | CGEventFlagCommand | 0x20000000`.
// Therefore, we need to set the flag to `event.set_flags(self.flags)` to avoid this.
self.post_event(event, true);
}
}

fn post_event(&self, event: CGEvent, force_flags: bool) {
if !self.ignore_flags && (force_flags || self.flags != CGEventFlags::CGEventFlagNull) {
event.set_flags(self.flags);
}
event.set_integer_value_field(EventField::EVENT_SOURCE_USER_DATA, ENIGO_INPUT_EXTRA_VALUE);
Expand Down Expand Up @@ -205,7 +223,7 @@ impl MouseControllable for Enigo {
if let Ok(event) =
CGEvent::new_mouse_event(src.clone(), event_type, dest, CGMouseButton::Left)
{
self.post(event);
self.post(event, None);
}
}
}
Expand Down Expand Up @@ -270,7 +288,7 @@ impl MouseControllable for Enigo {
if let Some(v) = btn_value {
event.set_integer_value_field(EventField::MOUSE_EVENT_BUTTON_NUMBER, v);
}
self.post(event);
self.post(event, None);
}
}
Ok(())
Expand Down Expand Up @@ -309,7 +327,7 @@ impl MouseControllable for Enigo {
if let Some(v) = btn_value {
event.set_integer_value_field(EventField::MOUSE_EVENT_BUTTON_NUMBER, v);
}
self.post(event);
self.post(event, None);
}
}
}
Expand Down Expand Up @@ -395,7 +413,7 @@ impl KeyboardControllable for Enigo {
if let Some(src) = self.event_source.as_ref() {
if let Ok(event) = CGEvent::new_keyboard_event(src.clone(), 0, true) {
event.set_string(cluster);
self.post(event);
self.post(event, None);
}
}
}
Expand All @@ -409,11 +427,11 @@ impl KeyboardControllable for Enigo {

if let Some(src) = self.event_source.as_ref() {
if let Ok(event) = CGEvent::new_keyboard_event(src.clone(), keycode, true) {
self.post(event);
self.post(event, Some(keycode));
}

if let Ok(event) = CGEvent::new_keyboard_event(src.clone(), keycode, false) {
self.post(event);
self.post(event, Some(keycode));
}
}
}
Expand All @@ -425,18 +443,17 @@ impl KeyboardControllable for Enigo {
}
if let Some(src) = self.event_source.as_ref() {
if let Ok(event) = CGEvent::new_keyboard_event(src.clone(), code, true) {
self.post(event);
self.post(event, Some(code));
}
}
Ok(())
}

fn key_up(&mut self, key: Key) {
let code = self.key_to_keycode(key);
if let Some(src) = self.event_source.as_ref() {
if let Ok(event) =
CGEvent::new_keyboard_event(src.clone(), self.key_to_keycode(key), false)
{
self.post(event);
if let Ok(event) = CGEvent::new_keyboard_event(src.clone(), code, false) {
self.post(event, Some(code));
}
}
}
Expand Down
11 changes: 9 additions & 2 deletions src/server/input_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,8 @@ fn is_pressed(key: &Key, en: &mut Enigo) -> bool {
get_modifier_state(key.clone(), en)
}

// Sleep for 8ms is enough in my tests, but we sleep 12ms to be safe.
// sleep 12ms In my test, the characters are already output in real time.
#[inline]
#[cfg(target_os = "macos")]
fn key_sleep() {
Expand All @@ -673,8 +675,6 @@ fn key_sleep() {
// `std::thread::sleep(Duration::from_millis(20));` may sleep 90ms or more.
// Though `/Applications/RustDesk.app/Contents/MacOS/rustdesk --server` in terminal is ok.
let now = Instant::now();
// This workaround results `21~24ms` sleep time in my tests.
// But it works well in my tests.
while now.elapsed() < Duration::from_millis(12) {
std::thread::sleep(Duration::from_millis(1));
}
Expand Down Expand Up @@ -1201,6 +1201,13 @@ pub fn handle_key(evt: &KeyEvent) {
// having GUI, run main GUI thread, otherwise crash
let evt = evt.clone();
QUEUE.exec_async(move || handle_key_(&evt));
// Key sleep is required for macOS.
// If we don't sleep, the key press/release events may not take effect.
//
// For example, the controlled side osx `12.7.6` or `15.1.1`
// If we input characters quickly and continuously, and press or release "Shift" for a short period of time,
// it is possible that after releasing "Shift", the controlled side will still print uppercase characters.
// Though it is not very easy to reproduce.
key_sleep();
}

Expand Down
Loading