From f1e0d647321279395fca0189380ce7342bbd275d Mon Sep 17 00:00:00 2001 From: fufesou Date: Sat, 25 Mar 2023 23:44:20 +0800 Subject: [PATCH] refact, sync lock modifiers, macOS, not debug yet Signed-off-by: fufesou --- Cargo.lock | 2 +- src/keyboard.rs | 48 +++++++++++----------- src/server/input_service.rs | 80 +++++++++++++++++++++++-------------- src/ui_session_interface.rs | 10 ++--- 4 files changed, 81 insertions(+), 59 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e632114af..a33e523c2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4674,7 +4674,7 @@ dependencies = [ [[package]] name = "rdev" version = "0.5.0-2" -source = "git+https://github.com/fufesou/rdev#eaa35ff9af22891b4aae3a0a5e83472c16177cd8" +source = "git+https://github.com/fufesou/rdev#cd0d6ad907f8fda5cf77487bc962ef4246221d0c" dependencies = [ "cocoa", "core-foundation 0.9.3", diff --git a/src/keyboard.rs b/src/keyboard.rs index aaddc9e4f..8fec0ec3f 100644 --- a/src/keyboard.rs +++ b/src/keyboard.rs @@ -10,7 +10,7 @@ use crate::ui::CUR_SESSION; #[cfg(not(any(target_os = "android", target_os = "ios")))] use hbb_common::log; use hbb_common::message_proto::*; -use rdev::{Event, EventType, Key}; +use rdev::{Event, EventType, Key, KeyCode}; #[cfg(any(target_os = "windows", target_os = "macos"))] use std::sync::atomic::{AtomicBool, Ordering}; use std::{ @@ -46,26 +46,26 @@ lazy_static::lazy_static! { m.insert(Key::MetaRight, false); Mutex::new(m) }; - static ref NUMPAD_POSITION_CODES: Arc> = { + static ref NUMPAD_POSITION_CODES: Arc> = { let numpad_keys = [ - rdev::Key::KpMinus, - rdev::Key::KpPlus, - rdev::Key::KpMultiply, - rdev::Key::KpDivide, - rdev::Key::KpDecimal, - rdev::Key::KpReturn, - rdev::Key::KpEqual, - rdev::Key::KpComma, - rdev::Key::Kp0, - rdev::Key::Kp1, - rdev::Key::Kp2, - rdev::Key::Kp3, - rdev::Key::Kp4, - rdev::Key::Kp5, - rdev::Key::Kp6, - rdev::Key::Kp7, - rdev::Key::Kp8, - rdev::Key::Kp9, + Key::KpMinus, + Key::KpPlus, + Key::KpMultiply, + Key::KpDivide, + Key::KpDecimal, + Key::KpReturn, + Key::KpEqual, + Key::KpComma, + Key::Kp0, + Key::Kp1, + Key::Kp2, + Key::Kp3, + Key::Kp4, + Key::Kp5, + Key::Kp6, + Key::Kp7, + Key::Kp8, + Key::Kp9, ]; #[cfg(target_os = "windows")] let codes = numpad_keys.iter().filter_map(|k| rdev::win_scancode_from_key(*k)).collect(); @@ -257,7 +257,7 @@ pub fn start_grab_loop() { let mut _keyboard_mode = KeyboardMode::Map; let _scan_code = event.position_code; - let _code = event.platform_code; + let _code = event.platform_code as KeyCode; let res = if KEYBOARD_HOOKED.load(Ordering::SeqCst) { _keyboard_mode = client::process_event(&event, None); if is_press { @@ -293,7 +293,7 @@ pub fn start_grab_loop() { #[cfg(target_os = "macos")] unsafe { - if _code as u32 == rdev::kVK_Option { + if _code == rdev::kVK_Option { IS_LEFT_OPTION_DOWN = is_press; } } @@ -496,7 +496,7 @@ pub fn event_to_key_events( }; if keyboard_mode != KeyboardMode::Translate { - let is_numpad_key = NUMPAD_POSITION_CODES.contains(&event.position_code); + let is_numpad_key = NUMPAD_POSITION_CODES.contains(&(event.position_code as _)); for key_event in &mut key_events { #[cfg(not(any(target_os = "android", target_os = "ios")))] if let Some(lock_modes) = lock_modes { @@ -929,7 +929,7 @@ pub fn translate_keyboard_mode(peer: &str, event: &Event, key_event: KeyEvent) - #[cfg(target_os = "macos")] // ignore right option key - if event.platform_code as u32 == rdev::kVK_RightOption { + if event.platform_code == rdev::kVK_RightOption as u32 { return events; } diff --git a/src/server/input_service.rs b/src/server/input_service.rs index dad98230d..85271f168 100644 --- a/src/server/input_service.rs +++ b/src/server/input_service.rs @@ -5,7 +5,7 @@ use crate::common::IS_X11; use dispatch::Queue; use enigo::{Enigo, Key, KeyboardControllable, MouseButton, MouseControllable}; use hbb_common::{config::COMPRESS_LEVEL, get_time, protobuf::EnumOrUnknown}; -use rdev::{self, EventType, Key as RdevKey, RawKey}; +use rdev::{self, EventType, Key as RdevKey, KeyCode, RawKey}; #[cfg(target_os = "macos")] use rdev::{CGEventSourceStateID, CGEventTapLocation, VirtualInput}; use std::time::Duration; @@ -113,23 +113,32 @@ impl Subscriber for MouseCursorSub { } } +#[cfg(not(target_os = "macos"))] struct LockModesHandler { caps_lock_changed: bool, num_lock_changed: bool, } +#[cfg(target_os = "macos")] +struct LockModesHandler; + impl LockModesHandler { + #[inline] + fn is_modifier_enabled(key_event: &KeyEvent, modifier: ControlKey) { + key_event.modifiers.contains(&modifier.into()); + } + + #[cfg(not(target_os = "macos"))] fn new(key_event: &KeyEvent) -> Self { let mut en = ENIGO.lock().unwrap(); - - let event_caps_enabled = key_event.modifiers.contains(&ControlKey::CapsLock.into()); + let event_caps_enabled = Self::is_modifier_enabled(key_event, ControlKey::CapsLock); let local_caps_enabled = en.get_key_state(enigo::Key::CapsLock); let caps_lock_changed = event_caps_enabled != local_caps_enabled; if caps_lock_changed { - click_capslock(&mut en); + en.key_click(enigo::Key::CapsLock); } - let event_num_enabled = key_event.modifiers.contains(&ControlKey::NumLock.into()); + let event_num_enabled = Self::is_modifier_enabled(key_event, ControlKey::NumLock); let local_num_enabled = en.get_key_state(enigo::Key::NumLock); #[cfg(not(target_os = "windows"))] let disable_numlock = false; @@ -137,7 +146,7 @@ impl LockModesHandler { let disable_numlock = is_numlock_disabled(key_event); let num_lock_changed = event_num_enabled != local_num_enabled && !disable_numlock; if num_lock_changed { - click_numlock(&mut en); + en.key_click(enigo::Key::NumLock); } Self { @@ -145,16 +154,36 @@ impl LockModesHandler { num_lock_changed, } } + + #[cfg(target_os = "macos")] + fn new(key_event: &KeyEvent) -> Self { + let event_caps_enabled = Self::is_modifier_enabled(key_event, ControlKey::CapsLock); + let local_caps_enabled = VirtualInput::get_key_state( + CGEventSourceStateID::CombinedSessionState, + rdev::kVK_CapsLock, + ); + let caps_key = RdevKey::RawKey(rdev::RawKey::MacVirtualKeycode(rdev::kVK_CapsLock)); + if event_caps_enabled && !local_caps_enabled { + simulate_(&EventType::KeyPress(caps_key)); + key_sleep(); + } else if !event_caps_enabled && local_caps_enabled { + simulate_(&EventType::KeyRelease(caps_key)); + key_sleep(); + } + + Self {} + } } +#[cfg(not(target_os = "macos"))] impl Drop for LockModesHandler { fn drop(&mut self) { let mut en = ENIGO.lock().unwrap(); if self.caps_lock_changed { - click_capslock(&mut en); + en.key_click(enigo::Key::CapsLock); } if self.num_lock_changed { - click_numlock(&mut en); + en.key_click(enigo::Key::NumLock); } } } @@ -391,6 +420,12 @@ fn is_pressed(key: &Key, en: &mut Enigo) -> bool { get_modifier_state(key.clone(), en) } +#[inline] +#[cfg(target_os = "macos")] +fn key_sleep() { + std::thread::sleep(Duration::from_millis(20)); +} + #[inline] fn get_modifier_state(key: Key, en: &mut Enigo) -> bool { // https://github.com/rustdesk/rustdesk/issues/332 @@ -459,6 +494,7 @@ pub fn fix_key_down_timeout_at_exit() { log::info!("fix_key_down_timeout_at_exit"); } +#[inline] #[cfg(target_os = "linux")] pub fn clear_remapped_keycode() { ENIGO.lock().unwrap().tfc_clear_remapped(); @@ -792,7 +828,7 @@ 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)); - std::thread::sleep(Duration::from_millis(20)); + key_sleep(); return; } #[cfg(windows)] @@ -800,7 +836,7 @@ pub fn handle_key(evt: &KeyEvent) { #[cfg(not(windows))] handle_key_(evt); #[cfg(target_os = "macos")] - std::thread::sleep(Duration::from_millis(20)); + key_sleep(); } #[cfg(target_os = "macos")] @@ -822,7 +858,7 @@ pub fn reset_input_ondisconn() { } } -fn sim_rdev_rawkey_position(code: u32, keydown: bool) { +fn sim_rdev_rawkey_position(code: KeyCode, keydown: bool) { #[cfg(target_os = "windows")] let rawkey = RawKey::ScanCode(code); #[cfg(target_os = "linux")] @@ -927,20 +963,6 @@ fn is_numlock_disabled(key_event: &KeyEvent) -> bool { } } -fn click_capslock(en: &mut Enigo) { - #[cfg(not(targe_os = "macos"))] - en.key_click(enigo::Key::CapsLock); - #[cfg(target_os = "macos")] - let _ = en.key_down(enigo::Key::CapsLock); -} - -#[inline] -fn click_numlock(_en: &mut Enigo) { - // without numlock in macos - #[cfg(not(target_os = "macos"))] - _en.key_click(enigo::Key::NumLock); -} - fn map_keyboard_mode(evt: &KeyEvent) { #[cfg(windows)] crate::platform::windows::try_change_desktop(); @@ -959,7 +981,7 @@ fn map_keyboard_mode(evt: &KeyEvent) { return; } - sim_rdev_rawkey_position(evt.chr(), evt.down); + sim_rdev_rawkey_position(evt.chr() as _, evt.down); } #[cfg(target_os = "macos")] @@ -1137,7 +1159,7 @@ fn legacy_keyboard_mode(evt: &KeyEvent) { fn translate_process_code(code: u32, down: bool) { crate::platform::windows::try_change_desktop(); match code >> 16 { - 0 => sim_rdev_rawkey_position(code, down), + 0 => sim_rdev_rawkey_position(code as _, down), vk_code => sim_rdev_rawkey_virtual(vk_code, down), }; } @@ -1168,7 +1190,7 @@ fn translate_keyboard_mode(evt: &KeyEvent) { #[cfg(target_os = "windows")] translate_process_code(evt.chr(), evt.down); #[cfg(not(target_os = "windows"))] - sim_rdev_rawkey_position(evt.chr(), evt.down); + sim_rdev_rawkey_position(evt.chr() as _, evt.down); } Some(key_event::Union::Unicode(..)) => { // Do not handle unicode for now. @@ -1187,7 +1209,7 @@ pub fn handle_key_(evt: &KeyEvent) { let _lock_mode_handler = match &evt.union { Some(key_event::Union::Unicode(..)) | Some(key_event::Union::Seq(..)) => { Some(LockModesHandler::new(&evt)) - }, + } _ => { if evt.down { Some(LockModesHandler::new(&evt)) diff --git a/src/ui_session_interface.rs b/src/ui_session_interface.rs index 8a1da6b8f..824f8befa 100644 --- a/src/ui_session_interface.rs +++ b/src/ui_session_interface.rs @@ -10,7 +10,7 @@ use std::time::{Duration, SystemTime}; use async_trait::async_trait; use bytes::Bytes; -use rdev::{Event, EventType::*}; +use rdev::{Event, EventType::*, KeyCode}; use uuid::Uuid; use hbb_common::config::{Config, LocalConfig, PeerConfig}; @@ -421,7 +421,7 @@ impl Session { rdev::win_scancode_from_key(key).unwrap_or_default() } "macos" => { - let key = rdev::macos_key_from_code(code); + let key = rdev::macos_key_from_code(code as _); let key = match key { rdev::Key::ControlLeft => rdev::Key::MetaLeft, rdev::Key::MetaLeft => rdev::Key::ControlLeft, @@ -429,7 +429,7 @@ impl Session { rdev::Key::MetaRight => rdev::Key::ControlLeft, _ => key, }; - rdev::macos_keycode_from_key(key).unwrap_or_default() + rdev::macos_keycode_from_key(key).unwrap_or_default() as _ } _ => { let key = rdev::linux_key_from_code(code); @@ -545,8 +545,8 @@ impl Session { if scancode < 0 || keycode < 0 { return; } - let keycode: u32 = keycode as u32; - let scancode: u32 = scancode as u32; + let keycode: KeyCode = keycode as _; + let scancode: u32 = scancode as _; #[cfg(not(target_os = "windows"))] let key = rdev::key_from_code(keycode) as rdev::Key;