From 7a3e1fe64861b60b545adf7ba7bffedf7d2a0787 Mon Sep 17 00:00:00 2001 From: fufesou <13586388+fufesou@users.noreply.github.com> Date: Thu, 24 Oct 2024 14:33:37 +0800 Subject: [PATCH] fix: ->macos, mouse events, key flags (#9733) * fix: win->macos, mouse events, key flags Signed-off-by: fufesou * comments Signed-off-by: fufesou --------- Signed-off-by: fufesou --- libs/enigo/src/macos/macos_impl.rs | 11 +++++++++- src/server/input_service.rs | 35 ++++++++++++++++++++++++++++-- 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/libs/enigo/src/macos/macos_impl.rs b/libs/enigo/src/macos/macos_impl.rs index a1f5d2e4a..e7d7d9e8d 100644 --- a/libs/enigo/src/macos/macos_impl.rs +++ b/libs/enigo/src/macos/macos_impl.rs @@ -111,11 +111,17 @@ pub struct Enigo { double_click_interval: u32, last_click_time: Option, multiple_click: i64, + ignore_flags: bool, flags: CGEventFlags, char_to_vkey_map: Map>, } impl Enigo { + /// Set if ignore flags when posting events. + pub fn set_ignore_flags(&mut self, ignore: bool) { + self.ignore_flags = ignore; + } + /// pub fn reset_flag(&mut self) { self.flags = CGEventFlags::CGEventFlagNull; @@ -136,7 +142,9 @@ impl Enigo { } fn post(&self, event: CGEvent) { - event.set_flags(self.flags); + if !self.ignore_flags { + event.set_flags(self.flags); + } event.set_integer_value_field(EventField::EVENT_SOURCE_USER_DATA, ENIGO_INPUT_EXTRA_VALUE); event.post(CGEventTapLocation::HID); } @@ -164,6 +172,7 @@ impl Default for Enigo { double_click_interval, multiple_click: 1, last_click_time: None, + ignore_flags: false, flags: CGEventFlags::CGEventFlagNull, char_to_vkey_map: Default::default(), } diff --git a/src/server/input_service.rs b/src/server/input_service.rs index afab184ab..3189520be 100644 --- a/src/server/input_service.rs +++ b/src/server/input_service.rs @@ -453,6 +453,17 @@ const MOUSE_ACTIVE_DISTANCE: i32 = 5; static RECORD_CURSOR_POS_RUNNING: AtomicBool = AtomicBool::new(false); +// https://github.com/rustdesk/rustdesk/issues/9729 +// We need to do some special handling for macOS when using the legacy mode. +#[cfg(target_os = "macos")] +static LAST_KEY_LEGACY_MODE: AtomicBool = AtomicBool::new(false); +// We use enigo to simulate mouse events. Only the legacy mode uses the key flags. +#[inline] +#[cfg(target_os = "macos")] +fn enigo_ignore_flags() -> bool { + !LAST_KEY_LEGACY_MODE.load(Ordering::SeqCst) +} + pub fn try_start_record_cursor_pos() -> Option> { if RECORD_CURSOR_POS_RUNNING.load(Ordering::SeqCst) { return None; @@ -505,6 +516,19 @@ impl VirtualInputState { fn new() -> Option { VirtualInput::new( CGEventSourceStateID::CombinedSessionState, + // Note: `CGEventTapLocation::Session` will be affected by the mouse events. + // When we're simulating key events, then move the physical mouse, the key events will be affected. + // It looks like https://github.com/rustdesk/rustdesk/issues/9729#issuecomment-2432306822 + // 1. Press "Command" key in RustDesk + // 2. Move the physical mouse + // 3. Press "V" key in RustDesk + // Then the controlled side just prints "v" instead of pasting. + // + // Changing `CGEventTapLocation::Session` to `CGEventTapLocation::HID` fixes it. + // But we do not consider this as a bug, because it's not a common case, + // we consider only RustDesk operates the controlled side. + // + // https://developer.apple.com/documentation/coregraphics/cgeventtaplocation/ CGEventTapLocation::Session, ) .map(|virtual_input| Self { @@ -945,6 +969,8 @@ pub fn handle_mouse_(evt: &MouseEvent, conn: i32) { let buttons = evt.mask >> 3; let evt_type = evt.mask & 0x7; let mut en = ENIGO.lock().unwrap(); + #[cfg(target_os = "macos")] + en.set_ignore_flags(enigo_ignore_flags()); #[cfg(not(target_os = "macos"))] let mut to_release = Vec::new(); if evt_type == MOUSE_TYPE_DOWN { @@ -1662,8 +1688,7 @@ pub fn handle_key_(evt: &KeyEvent) { let is_numpad_key = false; #[cfg(any(target_os = "windows", target_os = "linux"))] let is_numpad_key = crate::keyboard::is_numpad_rdev_key(&key); - _lock_mode_handler = - Some(LockModesHandler::new_handler(evt, is_numpad_key)); + _lock_mode_handler = Some(LockModesHandler::new_handler(evt, is_numpad_key)); } } } @@ -1672,12 +1697,18 @@ pub fn handle_key_(evt: &KeyEvent) { match evt.mode.enum_value() { Ok(KeyboardMode::Map) => { + #[cfg(target_os = "macos")] + LAST_KEY_LEGACY_MODE.store(false, Ordering::SeqCst); map_keyboard_mode(evt); } Ok(KeyboardMode::Translate) => { + #[cfg(target_os = "macos")] + LAST_KEY_LEGACY_MODE.store(false, Ordering::SeqCst); translate_keyboard_mode(evt); } _ => { + #[cfg(target_os = "macos")] + LAST_KEY_LEGACY_MODE.store(true, Ordering::SeqCst); legacy_keyboard_mode(evt); } }