From 234b8df41717b9c92fd7d16965b61edfd5c2439f Mon Sep 17 00:00:00 2001 From: Asura Date: Mon, 4 Jul 2022 08:08:43 -0700 Subject: [PATCH 01/57] fix(pynput): Add dead key conversion rules to support Czech keyboard --- pynput_service.py | 6 +++++- src/ui/remote.rs | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pynput_service.py b/pynput_service.py index c51e9a524..5aca57986 100644 --- a/pynput_service.py +++ b/pynput_service.py @@ -145,7 +145,11 @@ class MyController(Controller): or (keycode_flag == False and keycode == list(keycode_set)[0] and len(keycode_set) == 1): deakkey_chr = str(key).replace("'", '') keysym = DEAD_KEYS[deakkey_chr] - keycode, shift_state = self.keyboard_mapping[keysym][0] + # shift_state = 0 + keycode, shift_state = list( + filter(lambda x: x[1] == 0, + self.keyboard_mapping[keysym]) + )[0] # If the key has a virtual key code, use that immediately with # fake_input; fake input,being an X server extension, has access to diff --git a/src/ui/remote.rs b/src/ui/remote.rs index 5917314ca..8aa0bccb1 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -276,7 +276,7 @@ impl Handler { KeyRelease(k) => (k, 0), _ => return, }; - log::debug!("{:?}", key); + log::debug!("{:?}", key);a let alt = get_key_state(enigo::Key::Alt); #[cfg(windows)] let ctrl = { From 9237ae30dc200caededbe8e1648f3d1bdd398839 Mon Sep 17 00:00:00 2001 From: Asura Date: Mon, 4 Jul 2022 08:18:58 -0700 Subject: [PATCH 02/57] fix(pynput): Add dead key conversion rules to support Czech keyboard --- pynput_service.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pynput_service.py b/pynput_service.py index c51e9a524..5aca57986 100644 --- a/pynput_service.py +++ b/pynput_service.py @@ -145,7 +145,11 @@ class MyController(Controller): or (keycode_flag == False and keycode == list(keycode_set)[0] and len(keycode_set) == 1): deakkey_chr = str(key).replace("'", '') keysym = DEAD_KEYS[deakkey_chr] - keycode, shift_state = self.keyboard_mapping[keysym][0] + # shift_state = 0 + keycode, shift_state = list( + filter(lambda x: x[1] == 0, + self.keyboard_mapping[keysym]) + )[0] # If the key has a virtual key code, use that immediately with # fake_input; fake input,being an X server extension, has access to From e82e0bf69706914a57b16fba945fb29c2d17e370 Mon Sep 17 00:00:00 2001 From: Asura Date: Mon, 11 Jul 2022 03:26:12 -0700 Subject: [PATCH 03/57] feat: Add new simulate key method --- Cargo.lock | 19 +++++++++++- libs/enigo/Cargo.toml | 3 +- libs/enigo/src/linux.rs | 65 +++++++++++++++++++++++++++++++++++++---- 3 files changed, 80 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7e679ef91..bdf981356 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1317,6 +1317,7 @@ dependencies = [ "log", "objc", "pkg-config", + "rdev 0.5.1", "serde 1.0.137", "serde_derive", "unicode-segmentation", @@ -3836,6 +3837,22 @@ dependencies = [ "x11", ] +[[package]] +name = "rdev" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7336f02e29f34e9a7186ccf87051f6a5697536195569012e076e18a4efddcede" +dependencies = [ + "cocoa 0.22.0", + "core-foundation 0.7.0", + "core-foundation-sys 0.7.0", + "core-graphics 0.19.2", + "lazy_static", + "libc", + "winapi 0.3.9", + "x11", +] + [[package]] name = "rdrand" version = "0.4.0" @@ -4076,7 +4093,7 @@ dependencies = [ "num_cpus", "objc", "parity-tokio-ipc", - "rdev", + "rdev 0.5.0", "repng", "reqwest", "rpassword 6.0.1", diff --git a/libs/enigo/Cargo.toml b/libs/enigo/Cargo.toml index 6842dab56..29d7ee87f 100644 --- a/libs/enigo/Cargo.toml +++ b/libs/enigo/Cargo.toml @@ -21,7 +21,8 @@ appveyor = { repository = "pythoneer/enigo-85xiy" } [dependencies] serde = { version = "1.0", optional = true } serde_derive = { version = "1.0", optional = true } -log = "0.4" +log = "0.4.17" +rdev = "0.5.1" [features] with_serde = ["serde", "serde_derive"] diff --git a/libs/enigo/src/linux.rs b/libs/enigo/src/linux.rs index adfe9507c..ee27e06cf 100644 --- a/libs/enigo/src/linux.rs +++ b/libs/enigo/src/linux.rs @@ -3,8 +3,8 @@ use libc; use crate::{Key, KeyboardControllable, MouseButton, MouseControllable}; use self::libc::{c_char, c_int, c_void, useconds_t}; -use std::{borrow::Cow, ffi::CString, io::prelude::*, ptr, sync::mpsc}; - +use rdev::{simulate, EventType, EventType::*, Key as RdevKey, SimulateError}; +use std::{borrow::Cow, ffi::CString, io::prelude::*, ptr, sync::mpsc, thread, time}; const CURRENT_WINDOW: c_int = 0; const DEFAULT_DELAY: u64 = 12000; type Window = c_int; @@ -103,6 +103,30 @@ impl Enigo { pub fn reset(&mut self) { self.tx.send((PyMsg::Char('\0'), true)).ok(); } + + fn send_rdev(&mut self, key: &Key, is_press: bool) -> bool { + log::info!("{:?} {:?}", key, is_press); + + if let Key::Raw(keycode) = key { + let event_type = match is_press { + // todo: Acccodding to client type + true => Box::leak(Box::new(EventType::KeyPress(RdevKey::Unknown( + (*keycode).into(), + )))), + false => Box::leak(Box::new(EventType::KeyRelease(RdevKey::Unknown( + (*keycode).into(), + )))), + }; + + match simulate(event_type) { + Ok(()) => true, + Err(SimulateError) => false, + } + } else { + false + } + } + #[inline] fn send_pynput(&mut self, key: &Key, is_press: bool) -> bool { if unsafe { PYNPUT_EXIT || !PYNPUT_REDAY } { @@ -111,8 +135,15 @@ impl Enigo { if let Key::Layout(c) = key { return self.tx.send((PyMsg::Char(*c), is_press)).is_ok(); } - if let Key::Raw(_) = key { - return false; + if let Key::Raw(chr) = key { + fn string_to_static_str(s: String) -> &'static str { + Box::leak(s.into_boxed_str()) + } + dbg!(chr.to_string()); + return self + .tx + .send((PyMsg::Str(string_to_static_str(chr.to_string())), is_press)) + .is_ok(); } #[allow(deprecated)] let s = match key { @@ -431,6 +462,9 @@ impl KeyboardControllable for Enigo { if self.xdo.is_null() { return Ok(()); } + if self.send_rdev(&key, true) { + return Ok(()); + } if self.send_pynput(&key, true) { return Ok(()); } @@ -449,6 +483,11 @@ impl KeyboardControllable for Enigo { if self.xdo.is_null() { return; } + // todo + let keyboard_mode = 1; + if keyboard_mode == 1 && self.send_rdev(&key, false) { + return; + } if self.send_pynput(&key, false) { return; } @@ -478,6 +517,21 @@ impl KeyboardControllable for Enigo { } } } + + fn key_sequence_parse(&mut self, sequence: &str) + where + Self: Sized, + { + self.key_sequence_parse_try(sequence) + .expect("Could not parse sequence"); + } + + fn key_sequence_parse_try(&mut self, sequence: &str) -> Result<(), crate::dsl::ParseError> + where + Self: Sized, + { + crate::dsl::eval(self, sequence) + } } static mut PYNPUT_EXIT: bool = false; @@ -492,7 +546,8 @@ fn start_pynput_service(rx: mpsc::Receiver<(PyMsg, bool)>) { py = "/usr/lib/rustdesk/pynput_service.py".to_owned(); if !std::path::Path::new(&py).exists() { // enigo libs, not rustdesk root project, so skip using appimage features - py = std::env::var("APPDIR").unwrap_or("".to_string()) + "/usr/lib/rustdesk/pynput_service.py"; + py = std::env::var("APPDIR").unwrap_or("".to_string()) + + "/usr/lib/rustdesk/pynput_service.py"; if !std::path::Path::new(&py).exists() { log::error!("{} not exists", py); } From 956cef4a1c6eac44a06500e268f30224448c9833 Mon Sep 17 00:00:00 2001 From: Asura Date: Mon, 11 Jul 2022 08:14:57 -0700 Subject: [PATCH 04/57] refactor: Use new keyboard mode --- src/server/connection.rs | 3 ++- src/server/input_service.rs | 13 +++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/server/connection.rs b/src/server/connection.rs index 304b20655..40b541c99 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -421,7 +421,8 @@ impl Connection { msg.down = true; } handle_key(&msg); - if press { + let keyboard_mode = 1; + if press && keyboard_mode != 1{ msg.down = false; handle_key(&msg); } diff --git a/src/server/input_service.rs b/src/server/input_service.rs index 8c5f3060b..a8fd5fbbb 100644 --- a/src/server/input_service.rs +++ b/src/server/input_service.rs @@ -585,6 +585,19 @@ fn handle_key_(evt: &KeyEvent) { #[cfg(windows)] crate::platform::windows::try_change_desktop(); let mut en = ENIGO.lock().unwrap(); + let keyboard_mode = 1; + if keyboard_mode == 1 { + if let Some(key_event::Union::chr(chr)) = evt.union { + if evt.down { + println!("key down: {:?}", chr); + en.key_down(Key::Raw(chr.try_into().unwrap())); + } else { + println!("key up: {:?}", chr); + en.key_up(Key::Raw(chr.try_into().unwrap())); + } + } + return; + } // disable numlock if press home etc when numlock is on, // because we will get numpad value (7,8,9 etc) if not #[cfg(windows)] From 9837c9b89305b7ec924fd47003f29a40e906cda7 Mon Sep 17 00:00:00 2001 From: Asura Date: Tue, 12 Jul 2022 00:33:20 -0700 Subject: [PATCH 05/57] Use map mode when keyboard monitor --- src/ui/remote.rs | 491 +++++++++++++++++++++++++++-------------------- 1 file changed, 283 insertions(+), 208 deletions(-) diff --git a/src/ui/remote.rs b/src/ui/remote.rs index f85e37d04..0b73ee504 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -289,219 +289,294 @@ impl Handler { std::thread::spawn(move || { // This will block. std::env::set_var("KEYBOARD_ONLY", "y"); // pass to rdev - use rdev::{EventType::*, *}; - let func = move |evt: Event| { - if !IS_IN.load(Ordering::SeqCst) || !SERVER_KEYBOARD_ENABLED.load(Ordering::SeqCst) - { - return; - } - let (key, down) = match evt.event_type { - KeyPress(k) => (k, 1), - KeyRelease(k) => (k, 0), - _ => return, - }; - let alt = get_key_state(enigo::Key::Alt); - #[cfg(windows)] - let ctrl = { - let mut tmp = get_key_state(enigo::Key::Control); - unsafe { - if IS_ALT_GR { - if alt || key == Key::AltGr { - if tmp { - tmp = false; - } - } else { - IS_ALT_GR = false; - } - } - } - tmp - }; - #[cfg(not(windows))] - let ctrl = get_key_state(enigo::Key::Control); - let shift = get_key_state(enigo::Key::Shift); - #[cfg(windows)] - let command = crate::platform::windows::get_win_key_state(); - #[cfg(not(windows))] - let command = get_key_state(enigo::Key::Meta); - let control_key = match key { - Key::Alt => Some(ControlKey::Alt), - Key::AltGr => Some(ControlKey::RAlt), - Key::Backspace => Some(ControlKey::Backspace), - Key::ControlLeft => { - // when pressing AltGr, an extra VK_LCONTROL with a special - // scancode with bit 9 set is sent, let's ignore this. - #[cfg(windows)] - if evt.scan_code & 0x200 != 0 { - unsafe { - IS_ALT_GR = true; - } - return; - } - Some(ControlKey::Control) - } - Key::ControlRight => Some(ControlKey::RControl), - Key::DownArrow => Some(ControlKey::DownArrow), - Key::Escape => Some(ControlKey::Escape), - Key::F1 => Some(ControlKey::F1), - Key::F10 => Some(ControlKey::F10), - Key::F11 => Some(ControlKey::F11), - Key::F12 => Some(ControlKey::F12), - Key::F2 => Some(ControlKey::F2), - Key::F3 => Some(ControlKey::F3), - Key::F4 => Some(ControlKey::F4), - Key::F5 => Some(ControlKey::F5), - Key::F6 => Some(ControlKey::F6), - Key::F7 => Some(ControlKey::F7), - Key::F8 => Some(ControlKey::F8), - Key::F9 => Some(ControlKey::F9), - Key::LeftArrow => Some(ControlKey::LeftArrow), - Key::MetaLeft => Some(ControlKey::Meta), - Key::MetaRight => Some(ControlKey::RWin), - Key::Return => Some(ControlKey::Return), - Key::RightArrow => Some(ControlKey::RightArrow), - Key::ShiftLeft => Some(ControlKey::Shift), - Key::ShiftRight => Some(ControlKey::RShift), - Key::Space => Some(ControlKey::Space), - Key::Tab => Some(ControlKey::Tab), - Key::UpArrow => Some(ControlKey::UpArrow), - Key::Delete => { - if is_win && ctrl && alt { - me.ctrl_alt_del(); - return; - } - Some(ControlKey::Delete) - } - Key::Apps => Some(ControlKey::Apps), - Key::Cancel => Some(ControlKey::Cancel), - Key::Clear => Some(ControlKey::Clear), - Key::Kana => Some(ControlKey::Kana), - Key::Hangul => Some(ControlKey::Hangul), - Key::Junja => Some(ControlKey::Junja), - Key::Final => Some(ControlKey::Final), - Key::Hanja => Some(ControlKey::Hanja), - Key::Hanji => Some(ControlKey::Hanja), - Key::Convert => Some(ControlKey::Convert), - Key::Print => Some(ControlKey::Print), - Key::Select => Some(ControlKey::Select), - Key::Execute => Some(ControlKey::Execute), - Key::PrintScreen => Some(ControlKey::Snapshot), - Key::Help => Some(ControlKey::Help), - Key::Sleep => Some(ControlKey::Sleep), - Key::Separator => Some(ControlKey::Separator), - Key::KpReturn => Some(ControlKey::NumpadEnter), - Key::Kp0 => Some(ControlKey::Numpad0), - Key::Kp1 => Some(ControlKey::Numpad1), - Key::Kp2 => Some(ControlKey::Numpad2), - Key::Kp3 => Some(ControlKey::Numpad3), - Key::Kp4 => Some(ControlKey::Numpad4), - Key::Kp5 => Some(ControlKey::Numpad5), - Key::Kp6 => Some(ControlKey::Numpad6), - Key::Kp7 => Some(ControlKey::Numpad7), - Key::Kp8 => Some(ControlKey::Numpad8), - Key::Kp9 => Some(ControlKey::Numpad9), - Key::KpDivide => Some(ControlKey::Divide), - Key::KpMultiply => Some(ControlKey::Multiply), - Key::KpDecimal => Some(ControlKey::Decimal), - Key::KpMinus => Some(ControlKey::Subtract), - Key::KpPlus => Some(ControlKey::Add), - Key::CapsLock | Key::NumLock | Key::ScrollLock => { - return; - } - Key::Home => Some(ControlKey::Home), - Key::End => Some(ControlKey::End), - Key::Insert => Some(ControlKey::Insert), - Key::PageUp => Some(ControlKey::PageUp), - Key::PageDown => Some(ControlKey::PageDown), - Key::Pause => Some(ControlKey::Pause), - _ => None, - }; - let mut key_event = KeyEvent::new(); - if let Some(k) = control_key { - key_event.set_control_key(k); - } else { - let mut chr = match evt.name { - Some(ref s) => { - if s.len() <= 2 { - // exclude chinese characters - s.chars().next().unwrap_or('\0') - } else { - '\0' - } - } - _ => '\0', + let keyboard_mode = 1; + if keyboard_mode == 1 { + use rdev::{Event, EventType::*, Key as RdevKey}; + lazy_static::lazy_static! { + static ref MUTEX_SPECIAL_KEYS: Mutex> = { + let mut m = HashMap::new(); + // m.insert(RdevKey::PrintScreen, false); // TODO + m.insert(RdevKey::ShiftLeft, false); + m.insert(RdevKey::ShiftRight, false); + m.insert(RdevKey::ControlLeft, false); + m.insert(RdevKey::ControlRight, false); + m.insert(RdevKey::Alt, false); + m.insert(RdevKey::AltGr, false); + Mutex::new(m) }; - if chr == '·' { - // special for Chinese - chr = '`'; - } - if chr == '\0' { - chr = match key { - Key::Num1 => '1', - Key::Num2 => '2', - Key::Num3 => '3', - Key::Num4 => '4', - Key::Num5 => '5', - Key::Num6 => '6', - Key::Num7 => '7', - Key::Num8 => '8', - Key::Num9 => '9', - Key::Num0 => '0', - Key::KeyA => 'a', - Key::KeyB => 'b', - Key::KeyC => 'c', - Key::KeyD => 'd', - Key::KeyE => 'e', - Key::KeyF => 'f', - Key::KeyG => 'g', - Key::KeyH => 'h', - Key::KeyI => 'i', - Key::KeyJ => 'j', - Key::KeyK => 'k', - Key::KeyL => 'l', - Key::KeyM => 'm', - Key::KeyN => 'n', - Key::KeyO => 'o', - Key::KeyP => 'p', - Key::KeyQ => 'q', - Key::KeyR => 'r', - Key::KeyS => 's', - Key::KeyT => 't', - Key::KeyU => 'u', - Key::KeyV => 'v', - Key::KeyW => 'w', - Key::KeyX => 'x', - Key::KeyY => 'y', - Key::KeyZ => 'z', - Key::Comma => ',', - Key::Dot => '.', - Key::SemiColon => ';', - Key::Quote => '\'', - Key::LeftBracket => '[', - Key::RightBracket => ']', - Key::BackSlash => '\\', - Key::Minus => '-', - Key::Equal => '=', - Key::BackQuote => '`', - _ => '\0', - } - } - if chr != '\0' { - if chr == 'l' && is_win && command { - me.lock_screen(); - return; - } - key_event.set_chr(chr as _); - } else { - log::error!("Unknown key {:?}", evt); + } + // todo: auto change paltform + let func = move |evt: Event| { + if !IS_IN.load(Ordering::SeqCst) + || !SERVER_KEYBOARD_ENABLED.load(Ordering::SeqCst) + { return; } + let (key, down) = match evt.event_type { + KeyPress(k) => { + // keyboard long press + if MUTEX_SPECIAL_KEYS.lock().unwrap().contains_key(&k) { + if *MUTEX_SPECIAL_KEYS.lock().unwrap().get(&k).unwrap() { + return; + } + MUTEX_SPECIAL_KEYS.lock().unwrap().insert(k, true); + } + println!("keydown {:?} {:?} {:?}", k, evt.code, evt.scan_code); + (k, 1) + } + KeyRelease(k) => { + // keyboard long press + if MUTEX_SPECIAL_KEYS.lock().unwrap().contains_key(&k) { + MUTEX_SPECIAL_KEYS.lock().unwrap().insert(k, false); + } + println!("keyup {:?} {:?} {:?}", k, evt.code, evt.scan_code); + (k, 0) + } + _ => return, + }; + + // todo: clear key + #[cfg(target_os = "windows")] + let key = rdev::get_win_key(evt.code.into(), evt.scan_code); + + // todo: up down left right in numpad + // #[cfg(target_os = "linux")] + dbg!(key); + println!("--------------"); + + let mut key_event = KeyEvent::new(); + // According to peer platform. + if peer == "linux" { + let keycode: u32 = rdev::linux_keycode_from_key(key).unwrap().into(); + key_event.set_chr(keycode); + } else if peer == "Windows" { + let keycode: u32 = rdev::win_keycode_from_key(key).unwrap().into(); + key_event.set_chr(keycode); + } else if peer == "Mac OS" { + let keycode: u32 = rdev::macos_keycode_from_key(key).unwrap().into(); + key_event.set_chr(keycode); + } + me.key_down_or_up(down, key_event, false, false, false, false); + }; + if let Err(error) = rdev::listen(func) { + log::error!("rdev: {:?}", error); + } + } else { + use rdev::{EventType::*, *}; + let func = move |evt: Event| { + if !IS_IN.load(Ordering::SeqCst) + || !SERVER_KEYBOARD_ENABLED.load(Ordering::SeqCst) + { + return; + } + let (key, down) = match evt.event_type { + KeyPress(k) => (k, 1), + KeyRelease(k) => (k, 0), + _ => return, + }; + let alt = get_key_state(enigo::Key::Alt); + #[cfg(windows)] + let ctrl = { + let mut tmp = get_key_state(enigo::Key::Control); + unsafe { + if IS_ALT_GR { + if alt || key == Key::AltGr { + if tmp { + tmp = false; + } + } else { + IS_ALT_GR = false; + } + } + } + tmp + }; + #[cfg(not(windows))] + let ctrl = get_key_state(enigo::Key::Control); + let shift = get_key_state(enigo::Key::Shift); + #[cfg(windows)] + let command = crate::platform::windows::get_win_key_state(); + #[cfg(not(windows))] + let command = get_key_state(enigo::Key::Meta); + let control_key = match key { + Key::Alt => Some(ControlKey::Alt), + Key::AltGr => Some(ControlKey::RAlt), + Key::Backspace => Some(ControlKey::Backspace), + Key::ControlLeft => { + // when pressing AltGr, an extra VK_LCONTROL with a special + // scancode with bit 9 set is sent, let's ignore this. + #[cfg(windows)] + if evt.scan_code & 0x200 != 0 { + unsafe { + IS_ALT_GR = true; + } + return; + } + Some(ControlKey::Control) + } + Key::ControlRight => Some(ControlKey::RControl), + Key::DownArrow => Some(ControlKey::DownArrow), + Key::Escape => Some(ControlKey::Escape), + Key::F1 => Some(ControlKey::F1), + Key::F10 => Some(ControlKey::F10), + Key::F11 => Some(ControlKey::F11), + Key::F12 => Some(ControlKey::F12), + Key::F2 => Some(ControlKey::F2), + Key::F3 => Some(ControlKey::F3), + Key::F4 => Some(ControlKey::F4), + Key::F5 => Some(ControlKey::F5), + Key::F6 => Some(ControlKey::F6), + Key::F7 => Some(ControlKey::F7), + Key::F8 => Some(ControlKey::F8), + Key::F9 => Some(ControlKey::F9), + Key::LeftArrow => Some(ControlKey::LeftArrow), + Key::MetaLeft => Some(ControlKey::Meta), + Key::MetaRight => Some(ControlKey::RWin), + Key::Return => Some(ControlKey::Return), + Key::RightArrow => Some(ControlKey::RightArrow), + Key::ShiftLeft => Some(ControlKey::Shift), + Key::ShiftRight => Some(ControlKey::RShift), + Key::Space => Some(ControlKey::Space), + Key::Tab => Some(ControlKey::Tab), + Key::UpArrow => Some(ControlKey::UpArrow), + Key::Delete => { + if is_win && ctrl && alt { + me.ctrl_alt_del(); + return; + } + Some(ControlKey::Delete) + } + Key::Apps => Some(ControlKey::Apps), + Key::Cancel => Some(ControlKey::Cancel), + Key::Clear => Some(ControlKey::Clear), + Key::Kana => Some(ControlKey::Kana), + Key::Hangul => Some(ControlKey::Hangul), + Key::Junja => Some(ControlKey::Junja), + Key::Final => Some(ControlKey::Final), + Key::Hanja => Some(ControlKey::Hanja), + Key::Hanji => Some(ControlKey::Hanja), + Key::Convert => Some(ControlKey::Convert), + Key::Print => Some(ControlKey::Print), + Key::Select => Some(ControlKey::Select), + Key::Execute => Some(ControlKey::Execute), + Key::PrintScreen => Some(ControlKey::Snapshot), + Key::Help => Some(ControlKey::Help), + Key::Sleep => Some(ControlKey::Sleep), + Key::Separator => Some(ControlKey::Separator), + Key::KpReturn => Some(ControlKey::NumpadEnter), + Key::Kp0 => Some(ControlKey::Numpad0), + Key::Kp1 => Some(ControlKey::Numpad1), + Key::Kp2 => Some(ControlKey::Numpad2), + Key::Kp3 => Some(ControlKey::Numpad3), + Key::Kp4 => Some(ControlKey::Numpad4), + Key::Kp5 => Some(ControlKey::Numpad5), + Key::Kp6 => Some(ControlKey::Numpad6), + Key::Kp7 => Some(ControlKey::Numpad7), + Key::Kp8 => Some(ControlKey::Numpad8), + Key::Kp9 => Some(ControlKey::Numpad9), + Key::KpDivide => Some(ControlKey::Divide), + Key::KpMultiply => Some(ControlKey::Multiply), + Key::KpDecimal => Some(ControlKey::Decimal), + Key::KpMinus => Some(ControlKey::Subtract), + Key::KpPlus => Some(ControlKey::Add), + Key::CapsLock | Key::NumLock | Key::ScrollLock => { + return; + } + Key::Home => Some(ControlKey::Home), + Key::End => Some(ControlKey::End), + Key::Insert => Some(ControlKey::Insert), + Key::PageUp => Some(ControlKey::PageUp), + Key::PageDown => Some(ControlKey::PageDown), + Key::Pause => Some(ControlKey::Pause), + _ => None, + }; + let mut key_event = KeyEvent::new(); + if let Some(k) = control_key { + key_event.set_control_key(k); + } else { + let mut chr = match evt.name { + Some(ref s) => { + if s.len() <= 2 { + // exclude chinese characters + s.chars().next().unwrap_or('\0') + } else { + '\0' + } + } + _ => '\0', + }; + if chr == '·' { + // special for Chinese + chr = '`'; + } + if chr == '\0' { + chr = match key { + Key::Num1 => '1', + Key::Num2 => '2', + Key::Num3 => '3', + Key::Num4 => '4', + Key::Num5 => '5', + Key::Num6 => '6', + Key::Num7 => '7', + Key::Num8 => '8', + Key::Num9 => '9', + Key::Num0 => '0', + Key::KeyA => 'a', + Key::KeyB => 'b', + Key::KeyC => 'c', + Key::KeyD => 'd', + Key::KeyE => 'e', + Key::KeyF => 'f', + Key::KeyG => 'g', + Key::KeyH => 'h', + Key::KeyI => 'i', + Key::KeyJ => 'j', + Key::KeyK => 'k', + Key::KeyL => 'l', + Key::KeyM => 'm', + Key::KeyN => 'n', + Key::KeyO => 'o', + Key::KeyP => 'p', + Key::KeyQ => 'q', + Key::KeyR => 'r', + Key::KeyS => 's', + Key::KeyT => 't', + Key::KeyU => 'u', + Key::KeyV => 'v', + Key::KeyW => 'w', + Key::KeyX => 'x', + Key::KeyY => 'y', + Key::KeyZ => 'z', + Key::Comma => ',', + Key::Dot => '.', + Key::SemiColon => ';', + Key::Quote => '\'', + Key::LeftBracket => '[', + Key::RightBracket => ']', + Key::BackSlash => '\\', + Key::Minus => '-', + Key::Equal => '=', + Key::BackQuote => '`', + _ => '\0', + } + } + if chr != '\0' { + if chr == 'l' && is_win && command { + me.lock_screen(); + return; + } + key_event.set_chr(chr as _); + } else { + log::error!("Unknown key {:?}", evt); + return; + } + } + me.key_down_or_up(down, key_event, alt, ctrl, shift, command); + }; + if let Err(error) = rdev::listen(func) { + log::error!("rdev: {:?}", error); } - me.key_down_or_up(down, key_event, alt, ctrl, shift, command); }; - if let Err(error) = rdev::listen(func) { - log::error!("rdev: {:?}", error); - } }); } From 1cc6c7e167f2f9ce9b86879fabea47071325dd24 Mon Sep 17 00:00:00 2001 From: Asura Date: Tue, 12 Jul 2022 04:27:27 -0700 Subject: [PATCH 06/57] Use map mode when Windows are simulated --- libs/enigo/src/win/win_impl.rs | 42 ++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/libs/enigo/src/win/win_impl.rs b/libs/enigo/src/win/win_impl.rs index ea1543faa..d0d97ecee 100644 --- a/libs/enigo/src/win/win_impl.rs +++ b/libs/enigo/src/win/win_impl.rs @@ -1,9 +1,9 @@ -use winapi; - use self::winapi::ctypes::c_int; use self::winapi::shared::{basetsd::ULONG_PTR, minwindef::*, windef::*}; use self::winapi::um::winbase::*; use self::winapi::um::winuser::*; +use rdev::{simulate, EventType, EventType::*, Key as RdevKey, SimulateError}; +use winapi; use crate::win::keycodes::*; use crate::{Key, KeyboardControllable, MouseButton, MouseControllable}; @@ -198,9 +198,14 @@ impl KeyboardControllable for Enigo { } fn key_down(&mut self, key: Key) -> crate::ResultType { + let keyboard_mode = 1; + if keyboard_mode == 1 { + self.send_rdev(&key, true); + return Ok(()); + }; let code = self.key_to_keycode(key); if code == 0 || code == 65535 { - return Err("".into()); + return Err("".into()); } let res = keybd_event(0, code, 0); if res == 0 { @@ -213,6 +218,11 @@ impl KeyboardControllable for Enigo { } fn key_up(&mut self, key: Key) { + let keyboard_mode = 1; + if keyboard_mode == 1 { + self.send_rdev(&key, false); + return; + }; keybd_event(KEYEVENTF_KEYUP, self.key_to_keycode(key), 0); } @@ -227,7 +237,8 @@ impl KeyboardControllable for Enigo { } impl Enigo { - /// Gets the (width, height) of the main display in screen coordinates (pixels). + /// Gets the (width, height) of the main display in screen coordinates + /// (pixels). /// /// # Example /// @@ -272,6 +283,29 @@ impl Enigo { keybd_event(KEYEVENTF_UNICODE | KEYEVENTF_KEYUP, 0, unicode_char); } + fn send_rdev(&mut self, key: &Key, is_press: bool) -> bool { + log::info!("{:?} {:?}", key, is_press); + + if let Key::Raw(keycode) = key { + let event_type = match is_press { + // todo: Acccodding to client type + true => Box::leak(Box::new(EventType::KeyPress(RdevKey::Unknown( + (*keycode).into(), + )))), + false => Box::leak(Box::new(EventType::KeyRelease(RdevKey::Unknown( + (*keycode).into(), + )))), + }; + + match simulate(event_type) { + Ok(()) => true, + Err(SimulateError) => false, + } + } else { + false + } + } + fn key_to_keycode(&self, key: Key) -> u16 { unsafe { LAYOUT = std::ptr::null_mut(); From a6f9c16d50eae2b3978c169ebc448181ed21aecc Mon Sep 17 00:00:00 2001 From: Asura Date: Tue, 12 Jul 2022 04:29:32 -0700 Subject: [PATCH 07/57] fix: Correct the string corresponding to the platform --- src/ui/remote.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui/remote.rs b/src/ui/remote.rs index 0b73ee504..5bef6579c 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -346,7 +346,7 @@ impl Handler { let mut key_event = KeyEvent::new(); // According to peer platform. - if peer == "linux" { + if peer == "Linux" { let keycode: u32 = rdev::linux_keycode_from_key(key).unwrap().into(); key_event.set_chr(keycode); } else if peer == "Windows" { From 7395f1a7557a123269b028cd7800d84069e0d693 Mon Sep 17 00:00:00 2001 From: Asura Date: Tue, 12 Jul 2022 04:40:38 -0700 Subject: [PATCH 08/57] ci: Change source of lib --- Cargo.lock | 30 +++++++++++++++++++++++++----- Cargo.toml | 2 +- libs/enigo/Cargo.toml | 2 +- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 17832eb8b..6f3895c1c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1317,13 +1317,33 @@ dependencies = [ "log", "objc", "pkg-config", - "rdev 0.5.1", + "rdev 0.5.0 (git+https://github.com/asur4s/rdev)", "serde 1.0.137", "serde_derive", "unicode-segmentation", "winapi 0.3.9", ] +[[package]] +name = "enum-map" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ddfe61e8040145222887d0d32a939c70c8cae681490d72fb868305e9b40ced8" +dependencies = [ + "enum-map-derive", +] + +[[package]] +name = "enum-map-derive" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00d1c54e25a57236a790ecf051c2befbb57740c9b86c4273eac378ba84d620d6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "enum_dispatch" version = "0.3.8" @@ -3838,12 +3858,12 @@ dependencies = [ [[package]] name = "rdev" version = "0.5.0" -source = "git+https://github.com/open-trade/rdev#fbbefd0b5d87095a7349965aec9ecd33de7035ac" dependencies = [ "cocoa 0.22.0", "core-foundation 0.7.0", "core-foundation-sys 0.7.0", "core-graphics 0.19.2", + "enum-map", "lazy_static", "libc", "winapi 0.3.9", @@ -3852,14 +3872,14 @@ dependencies = [ [[package]] name = "rdev" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7336f02e29f34e9a7186ccf87051f6a5697536195569012e076e18a4efddcede" +version = "0.5.0" +source = "git+https://github.com/asur4s/rdev#83d998895677129f0ba8fc2ada4cddd1e0df418f" dependencies = [ "cocoa 0.22.0", "core-foundation 0.7.0", "core-foundation-sys 0.7.0", "core-graphics 0.19.2", + "enum-map", "lazy_static", "libc", "winapi 0.3.9", diff --git a/Cargo.toml b/Cargo.toml index f270f7b30..39789c772 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -69,7 +69,7 @@ sciter-rs = { git = "https://github.com/open-trade/rust-sciter", branch = "dyn" sys-locale = "0.2" enigo = { path = "libs/enigo" } clipboard = { path = "libs/clipboard" } -rdev = { git = "https://github.com/open-trade/rdev" } +rdev = { path = "../rdev" } ctrlc = "3.2" arboard = "2.0" #minreq = { version = "2.4", features = ["punycode", "https-native"] } diff --git a/libs/enigo/Cargo.toml b/libs/enigo/Cargo.toml index 29d7ee87f..b1c57ca92 100644 --- a/libs/enigo/Cargo.toml +++ b/libs/enigo/Cargo.toml @@ -22,7 +22,7 @@ appveyor = { repository = "pythoneer/enigo-85xiy" } serde = { version = "1.0", optional = true } serde_derive = { version = "1.0", optional = true } log = "0.4.17" -rdev = "0.5.1" +rdev = { git = "https://github.com/asur4s/rdev" } [features] with_serde = ["serde", "serde_derive"] From fa8595b77d5a22f3213937cb7efbad6a0c1146ce Mon Sep 17 00:00:00 2001 From: Asura Date: Tue, 12 Jul 2022 08:36:45 -0700 Subject: [PATCH 09/57] Supports Mac OS simulate input by scancode --- Cargo.lock | 21 +++--------------- Cargo.toml | 2 +- libs/enigo/src/macos/macos_impl.rs | 35 +++++++++++++++++++++++++++++- 3 files changed, 38 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6f3895c1c..f2db3ff15 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1317,7 +1317,7 @@ dependencies = [ "log", "objc", "pkg-config", - "rdev 0.5.0 (git+https://github.com/asur4s/rdev)", + "rdev", "serde 1.0.137", "serde_derive", "unicode-segmentation", @@ -3858,22 +3858,7 @@ dependencies = [ [[package]] name = "rdev" version = "0.5.0" -dependencies = [ - "cocoa 0.22.0", - "core-foundation 0.7.0", - "core-foundation-sys 0.7.0", - "core-graphics 0.19.2", - "enum-map", - "lazy_static", - "libc", - "winapi 0.3.9", - "x11", -] - -[[package]] -name = "rdev" -version = "0.5.0" -source = "git+https://github.com/asur4s/rdev#83d998895677129f0ba8fc2ada4cddd1e0df418f" +source = "git+https://github.com/asur4s/rdev#e0ed6e08b7fb7e8ac80b2ef6e710ba1db9fe0751" dependencies = [ "cocoa 0.22.0", "core-foundation 0.7.0", @@ -4126,7 +4111,7 @@ dependencies = [ "num_cpus", "objc", "parity-tokio-ipc", - "rdev 0.5.0", + "rdev", "repng", "reqwest", "rpassword 6.0.1", diff --git a/Cargo.toml b/Cargo.toml index 39789c772..264c82940 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -69,7 +69,7 @@ sciter-rs = { git = "https://github.com/open-trade/rust-sciter", branch = "dyn" sys-locale = "0.2" enigo = { path = "libs/enigo" } clipboard = { path = "libs/clipboard" } -rdev = { path = "../rdev" } +rdev = { git = "https://github.com/asur4s/rdev" } ctrlc = "3.2" arboard = "2.0" #minreq = { version = "2.4", features = ["punycode", "https-native"] } diff --git a/libs/enigo/src/macos/macos_impl.rs b/libs/enigo/src/macos/macos_impl.rs index 28c9362ed..6cae30984 100644 --- a/libs/enigo/src/macos/macos_impl.rs +++ b/libs/enigo/src/macos/macos_impl.rs @@ -1,5 +1,5 @@ use core_graphics; - +use rdev::{simulate, EventType, EventType::*, Key as RdevKey, SimulateError}; // TODO(dustin): use only the things i need use self::core_graphics::display::*; @@ -354,6 +354,11 @@ impl KeyboardControllable for Enigo { } fn key_down(&mut self, key: Key) -> crate::ResultType { + let keyboard_mode = 1; + if keyboard_mode == 1 { + self.send_rdev(&key, true); + return Ok(()); + }; let code = self.key_to_keycode(key); if code == u16::MAX { return Err("".into()); @@ -369,6 +374,11 @@ impl KeyboardControllable for Enigo { } fn key_up(&mut self, key: Key) { + let keyboard_mode = 1; + if keyboard_mode == 1 { + self.send_rdev(&key, true); + return Ok(()); + }; 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) @@ -421,6 +431,29 @@ impl Enigo { (x, (display_height as i32) - y_inv) } + fn send_rdev(&mut self, key: &Key, is_press: bool) -> bool { + log::info!("{:?} {:?}", key, is_press); + + if let Key::Raw(keycode) = key { + let event_type = match is_press { + // todo: Acccodding to client type + true => Box::leak(Box::new(EventType::KeyPress(RdevKey::Unknown( + (*keycode).into(), + )))), + false => Box::leak(Box::new(EventType::KeyRelease(RdevKey::Unknown( + (*keycode).into(), + )))), + }; + + match simulate(event_type) { + Ok(()) => true, + Err(SimulateError) => false, + } + } else { + false + } + } + fn key_to_keycode(&mut self, key: Key) -> CGKeyCode { #[allow(deprecated)] // I mean duh, we still need to support deprecated keys until they're removed From 7b3b9007647ccd1b3ed4aefc9ca21c0368ba036d Mon Sep 17 00:00:00 2001 From: Asura Date: Tue, 12 Jul 2022 18:56:08 -0700 Subject: [PATCH 10/57] Update rdev dependency version --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f2db3ff15..056c14ae7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3857,8 +3857,8 @@ dependencies = [ [[package]] name = "rdev" -version = "0.5.0" -source = "git+https://github.com/asur4s/rdev#e0ed6e08b7fb7e8ac80b2ef6e710ba1db9fe0751" +version = "0.5.0-2" +source = "git+https://github.com/asur4s/rdev#95cecfd1b0f0b20c6cd728afca859107b911f3b8" dependencies = [ "cocoa 0.22.0", "core-foundation 0.7.0", From 7fe2609ffb4598d4bc666af0395fc89a7bf3eaba Mon Sep 17 00:00:00 2001 From: Asura Date: Wed, 13 Jul 2022 02:14:32 -0700 Subject: [PATCH 11/57] feat: Support new keyboard mode --- libs/enigo/src/linux.rs | 3 --- libs/enigo/src/macos/macos_impl.rs | 2 -- libs/enigo/src/win/win_impl.rs | 2 -- src/server/input_service.rs | 2 -- src/ui/remote.rs | 7 ------- 5 files changed, 16 deletions(-) diff --git a/libs/enigo/src/linux.rs b/libs/enigo/src/linux.rs index ee27e06cf..7f2afc3dc 100644 --- a/libs/enigo/src/linux.rs +++ b/libs/enigo/src/linux.rs @@ -105,8 +105,6 @@ impl Enigo { } fn send_rdev(&mut self, key: &Key, is_press: bool) -> bool { - log::info!("{:?} {:?}", key, is_press); - if let Key::Raw(keycode) = key { let event_type = match is_press { // todo: Acccodding to client type @@ -139,7 +137,6 @@ impl Enigo { fn string_to_static_str(s: String) -> &'static str { Box::leak(s.into_boxed_str()) } - dbg!(chr.to_string()); return self .tx .send((PyMsg::Str(string_to_static_str(chr.to_string())), is_press)) diff --git a/libs/enigo/src/macos/macos_impl.rs b/libs/enigo/src/macos/macos_impl.rs index 6cae30984..df494b9cb 100644 --- a/libs/enigo/src/macos/macos_impl.rs +++ b/libs/enigo/src/macos/macos_impl.rs @@ -432,8 +432,6 @@ impl Enigo { } fn send_rdev(&mut self, key: &Key, is_press: bool) -> bool { - log::info!("{:?} {:?}", key, is_press); - if let Key::Raw(keycode) = key { let event_type = match is_press { // todo: Acccodding to client type diff --git a/libs/enigo/src/win/win_impl.rs b/libs/enigo/src/win/win_impl.rs index d0d97ecee..0967d07c9 100644 --- a/libs/enigo/src/win/win_impl.rs +++ b/libs/enigo/src/win/win_impl.rs @@ -284,8 +284,6 @@ impl Enigo { } fn send_rdev(&mut self, key: &Key, is_press: bool) -> bool { - log::info!("{:?} {:?}", key, is_press); - if let Key::Raw(keycode) = key { let event_type = match is_press { // todo: Acccodding to client type diff --git a/src/server/input_service.rs b/src/server/input_service.rs index a8fd5fbbb..8e8e2abb4 100644 --- a/src/server/input_service.rs +++ b/src/server/input_service.rs @@ -589,10 +589,8 @@ fn handle_key_(evt: &KeyEvent) { if keyboard_mode == 1 { if let Some(key_event::Union::chr(chr)) = evt.union { if evt.down { - println!("key down: {:?}", chr); en.key_down(Key::Raw(chr.try_into().unwrap())); } else { - println!("key up: {:?}", chr); en.key_up(Key::Raw(chr.try_into().unwrap())); } } diff --git a/src/ui/remote.rs b/src/ui/remote.rs index 5bef6579c..cc2ce8154 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -321,7 +321,6 @@ impl Handler { } MUTEX_SPECIAL_KEYS.lock().unwrap().insert(k, true); } - println!("keydown {:?} {:?} {:?}", k, evt.code, evt.scan_code); (k, 1) } KeyRelease(k) => { @@ -329,7 +328,6 @@ impl Handler { if MUTEX_SPECIAL_KEYS.lock().unwrap().contains_key(&k) { MUTEX_SPECIAL_KEYS.lock().unwrap().insert(k, false); } - println!("keyup {:?} {:?} {:?}", k, evt.code, evt.scan_code); (k, 0) } _ => return, @@ -339,11 +337,6 @@ impl Handler { #[cfg(target_os = "windows")] let key = rdev::get_win_key(evt.code.into(), evt.scan_code); - // todo: up down left right in numpad - // #[cfg(target_os = "linux")] - dbg!(key); - println!("--------------"); - let mut key_event = KeyEvent::new(); // According to peer platform. if peer == "Linux" { From 7c24f6bb12964df3d152b2518fb299fe85d0233c Mon Sep 17 00:00:00 2001 From: Asura Date: Sun, 17 Jul 2022 14:14:51 -0700 Subject: [PATCH 12/57] Refactor listening keyboard to support switching keyboard modes --- libs/enigo/src/win/win_impl.rs | 2 +- libs/hbb_common/protos/message.proto | 1 + src/ui/remote.rs | 600 ++++++++++++++------------- 3 files changed, 306 insertions(+), 297 deletions(-) diff --git a/libs/enigo/src/win/win_impl.rs b/libs/enigo/src/win/win_impl.rs index 0967d07c9..b8f3d0fa3 100644 --- a/libs/enigo/src/win/win_impl.rs +++ b/libs/enigo/src/win/win_impl.rs @@ -2,7 +2,7 @@ use self::winapi::ctypes::c_int; use self::winapi::shared::{basetsd::ULONG_PTR, minwindef::*, windef::*}; use self::winapi::um::winbase::*; use self::winapi::um::winuser::*; -use rdev::{simulate, EventType, EventType::*, Key as RdevKey, SimulateError}; +use rdev::{simulate, EventType, Key as RdevKey, SimulateError}; use winapi; use crate::win::keycodes::*; diff --git a/libs/hbb_common/protos/message.proto b/libs/hbb_common/protos/message.proto index 0538f1aef..645930eb4 100644 --- a/libs/hbb_common/protos/message.proto +++ b/libs/hbb_common/protos/message.proto @@ -190,6 +190,7 @@ message KeyEvent { string seq = 6; } repeated ControlKey modifiers = 8; + uint32 mode = 9; } message CursorData { diff --git a/src/ui/remote.rs b/src/ui/remote.rs index cc2ce8154..8ebced2c4 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -43,6 +43,7 @@ use hbb_common::{ Stream, }; use hbb_common::{config::TransferSerde, fs::TransferJobMeta}; +use rdev::{Event, EventType::*, Key as RdevKey}; #[cfg(windows)] use crate::clipboard_file::*; @@ -288,288 +289,54 @@ impl Handler { crate::platform::windows::enable_lowlevel_keyboard(std::ptr::null_mut() as _); std::thread::spawn(move || { // This will block. - std::env::set_var("KEYBOARD_ONLY", "y"); // pass to rdev - let keyboard_mode = 1; - if keyboard_mode == 1 { - use rdev::{Event, EventType::*, Key as RdevKey}; - lazy_static::lazy_static! { - static ref MUTEX_SPECIAL_KEYS: Mutex> = { - let mut m = HashMap::new(); - // m.insert(RdevKey::PrintScreen, false); // TODO - m.insert(RdevKey::ShiftLeft, false); - m.insert(RdevKey::ShiftRight, false); - m.insert(RdevKey::ControlLeft, false); - m.insert(RdevKey::ControlRight, false); - m.insert(RdevKey::Alt, false); - m.insert(RdevKey::AltGr, false); - Mutex::new(m) - }; - } - // todo: auto change paltform - let func = move |evt: Event| { - if !IS_IN.load(Ordering::SeqCst) - || !SERVER_KEYBOARD_ENABLED.load(Ordering::SeqCst) - { - return; - } - let (key, down) = match evt.event_type { - KeyPress(k) => { - // keyboard long press - if MUTEX_SPECIAL_KEYS.lock().unwrap().contains_key(&k) { - if *MUTEX_SPECIAL_KEYS.lock().unwrap().get(&k).unwrap() { - return; - } - MUTEX_SPECIAL_KEYS.lock().unwrap().insert(k, true); - } - (k, 1) - } - KeyRelease(k) => { - // keyboard long press - if MUTEX_SPECIAL_KEYS.lock().unwrap().contains_key(&k) { - MUTEX_SPECIAL_KEYS.lock().unwrap().insert(k, false); - } - (k, 0) - } - _ => return, - }; - - // todo: clear key - #[cfg(target_os = "windows")] - let key = rdev::get_win_key(evt.code.into(), evt.scan_code); - - let mut key_event = KeyEvent::new(); - // According to peer platform. - if peer == "Linux" { - let keycode: u32 = rdev::linux_keycode_from_key(key).unwrap().into(); - key_event.set_chr(keycode); - } else if peer == "Windows" { - let keycode: u32 = rdev::win_keycode_from_key(key).unwrap().into(); - key_event.set_chr(keycode); - } else if peer == "Mac OS" { - let keycode: u32 = rdev::macos_keycode_from_key(key).unwrap().into(); - key_event.set_chr(keycode); - } - me.key_down_or_up(down, key_event, false, false, false, false); + std::env::set_var("KEYBOARD_ONLY", "y"); + lazy_static::lazy_static! { + static ref MUTEX_SPECIAL_KEYS: Mutex> = { + let mut m = HashMap::new(); + m.insert(RdevKey::ShiftLeft, false); + m.insert(RdevKey::ShiftRight, false); + m.insert(RdevKey::ControlLeft, false); + m.insert(RdevKey::ControlRight, false); + m.insert(RdevKey::Alt, false); + m.insert(RdevKey::AltGr, false); + Mutex::new(m) }; - if let Err(error) = rdev::listen(func) { - log::error!("rdev: {:?}", error); + } + + let func = move |evt: Event| { + if !IS_IN.load(Ordering::SeqCst) || !SERVER_KEYBOARD_ENABLED.load(Ordering::SeqCst) + { + return; } - } else { - use rdev::{EventType::*, *}; - let func = move |evt: Event| { - if !IS_IN.load(Ordering::SeqCst) - || !SERVER_KEYBOARD_ENABLED.load(Ordering::SeqCst) - { - return; + let (key, down) = match evt.event_type { + KeyPress(k) => { + // keyboard long press + if MUTEX_SPECIAL_KEYS.lock().unwrap().contains_key(&k) { + if *MUTEX_SPECIAL_KEYS.lock().unwrap().get(&k).unwrap() { + return; + } + MUTEX_SPECIAL_KEYS.lock().unwrap().insert(k, true); + } + (k, true) } - let (key, down) = match evt.event_type { - KeyPress(k) => (k, 1), - KeyRelease(k) => (k, 0), - _ => return, - }; - let alt = get_key_state(enigo::Key::Alt); - #[cfg(windows)] - let ctrl = { - let mut tmp = get_key_state(enigo::Key::Control); - unsafe { - if IS_ALT_GR { - if alt || key == Key::AltGr { - if tmp { - tmp = false; - } - } else { - IS_ALT_GR = false; - } - } - } - tmp - }; - #[cfg(not(windows))] - let ctrl = get_key_state(enigo::Key::Control); - let shift = get_key_state(enigo::Key::Shift); - #[cfg(windows)] - let command = crate::platform::windows::get_win_key_state(); - #[cfg(not(windows))] - let command = get_key_state(enigo::Key::Meta); - let control_key = match key { - Key::Alt => Some(ControlKey::Alt), - Key::AltGr => Some(ControlKey::RAlt), - Key::Backspace => Some(ControlKey::Backspace), - Key::ControlLeft => { - // when pressing AltGr, an extra VK_LCONTROL with a special - // scancode with bit 9 set is sent, let's ignore this. - #[cfg(windows)] - if evt.scan_code & 0x200 != 0 { - unsafe { - IS_ALT_GR = true; - } - return; - } - Some(ControlKey::Control) - } - Key::ControlRight => Some(ControlKey::RControl), - Key::DownArrow => Some(ControlKey::DownArrow), - Key::Escape => Some(ControlKey::Escape), - Key::F1 => Some(ControlKey::F1), - Key::F10 => Some(ControlKey::F10), - Key::F11 => Some(ControlKey::F11), - Key::F12 => Some(ControlKey::F12), - Key::F2 => Some(ControlKey::F2), - Key::F3 => Some(ControlKey::F3), - Key::F4 => Some(ControlKey::F4), - Key::F5 => Some(ControlKey::F5), - Key::F6 => Some(ControlKey::F6), - Key::F7 => Some(ControlKey::F7), - Key::F8 => Some(ControlKey::F8), - Key::F9 => Some(ControlKey::F9), - Key::LeftArrow => Some(ControlKey::LeftArrow), - Key::MetaLeft => Some(ControlKey::Meta), - Key::MetaRight => Some(ControlKey::RWin), - Key::Return => Some(ControlKey::Return), - Key::RightArrow => Some(ControlKey::RightArrow), - Key::ShiftLeft => Some(ControlKey::Shift), - Key::ShiftRight => Some(ControlKey::RShift), - Key::Space => Some(ControlKey::Space), - Key::Tab => Some(ControlKey::Tab), - Key::UpArrow => Some(ControlKey::UpArrow), - Key::Delete => { - if is_win && ctrl && alt { - me.ctrl_alt_del(); - return; - } - Some(ControlKey::Delete) - } - Key::Apps => Some(ControlKey::Apps), - Key::Cancel => Some(ControlKey::Cancel), - Key::Clear => Some(ControlKey::Clear), - Key::Kana => Some(ControlKey::Kana), - Key::Hangul => Some(ControlKey::Hangul), - Key::Junja => Some(ControlKey::Junja), - Key::Final => Some(ControlKey::Final), - Key::Hanja => Some(ControlKey::Hanja), - Key::Hanji => Some(ControlKey::Hanja), - Key::Convert => Some(ControlKey::Convert), - Key::Print => Some(ControlKey::Print), - Key::Select => Some(ControlKey::Select), - Key::Execute => Some(ControlKey::Execute), - Key::PrintScreen => Some(ControlKey::Snapshot), - Key::Help => Some(ControlKey::Help), - Key::Sleep => Some(ControlKey::Sleep), - Key::Separator => Some(ControlKey::Separator), - Key::KpReturn => Some(ControlKey::NumpadEnter), - Key::Kp0 => Some(ControlKey::Numpad0), - Key::Kp1 => Some(ControlKey::Numpad1), - Key::Kp2 => Some(ControlKey::Numpad2), - Key::Kp3 => Some(ControlKey::Numpad3), - Key::Kp4 => Some(ControlKey::Numpad4), - Key::Kp5 => Some(ControlKey::Numpad5), - Key::Kp6 => Some(ControlKey::Numpad6), - Key::Kp7 => Some(ControlKey::Numpad7), - Key::Kp8 => Some(ControlKey::Numpad8), - Key::Kp9 => Some(ControlKey::Numpad9), - Key::KpDivide => Some(ControlKey::Divide), - Key::KpMultiply => Some(ControlKey::Multiply), - Key::KpDecimal => Some(ControlKey::Decimal), - Key::KpMinus => Some(ControlKey::Subtract), - Key::KpPlus => Some(ControlKey::Add), - Key::CapsLock | Key::NumLock | Key::ScrollLock => { - return; - } - Key::Home => Some(ControlKey::Home), - Key::End => Some(ControlKey::End), - Key::Insert => Some(ControlKey::Insert), - Key::PageUp => Some(ControlKey::PageUp), - Key::PageDown => Some(ControlKey::PageDown), - Key::Pause => Some(ControlKey::Pause), - _ => None, - }; - let mut key_event = KeyEvent::new(); - if let Some(k) = control_key { - key_event.set_control_key(k); - } else { - let mut chr = match evt.name { - Some(ref s) => { - if s.len() <= 2 { - // exclude chinese characters - s.chars().next().unwrap_or('\0') - } else { - '\0' - } - } - _ => '\0', - }; - if chr == '·' { - // special for Chinese - chr = '`'; - } - if chr == '\0' { - chr = match key { - Key::Num1 => '1', - Key::Num2 => '2', - Key::Num3 => '3', - Key::Num4 => '4', - Key::Num5 => '5', - Key::Num6 => '6', - Key::Num7 => '7', - Key::Num8 => '8', - Key::Num9 => '9', - Key::Num0 => '0', - Key::KeyA => 'a', - Key::KeyB => 'b', - Key::KeyC => 'c', - Key::KeyD => 'd', - Key::KeyE => 'e', - Key::KeyF => 'f', - Key::KeyG => 'g', - Key::KeyH => 'h', - Key::KeyI => 'i', - Key::KeyJ => 'j', - Key::KeyK => 'k', - Key::KeyL => 'l', - Key::KeyM => 'm', - Key::KeyN => 'n', - Key::KeyO => 'o', - Key::KeyP => 'p', - Key::KeyQ => 'q', - Key::KeyR => 'r', - Key::KeyS => 's', - Key::KeyT => 't', - Key::KeyU => 'u', - Key::KeyV => 'v', - Key::KeyW => 'w', - Key::KeyX => 'x', - Key::KeyY => 'y', - Key::KeyZ => 'z', - Key::Comma => ',', - Key::Dot => '.', - Key::SemiColon => ';', - Key::Quote => '\'', - Key::LeftBracket => '[', - Key::RightBracket => ']', - Key::BackSlash => '\\', - Key::Minus => '-', - Key::Equal => '=', - Key::BackQuote => '`', - _ => '\0', - } - } - if chr != '\0' { - if chr == 'l' && is_win && command { - me.lock_screen(); - return; - } - key_event.set_chr(chr as _); - } else { - log::error!("Unknown key {:?}", evt); - return; + KeyRelease(k) => { + // keyboard long press + if MUTEX_SPECIAL_KEYS.lock().unwrap().contains_key(&k) { + MUTEX_SPECIAL_KEYS.lock().unwrap().insert(k, false); } + (k, false) } - me.key_down_or_up(down, key_event, alt, ctrl, shift, command); + _ => return, }; - if let Err(error) = rdev::listen(func) { - log::error!("rdev: {:?}", error); - } + + #[cfg(target_os = "windows")] + let key = rdev::get_win_key(evt.code.into(), evt.scan_code); + + me.key_down_or_up(down, key, evt); }; + if let Err(error) = rdev::listen(func) { + log::error!("rdev: {:?}", error); + } }); } @@ -1150,18 +917,19 @@ impl Handler { if self.peer_platform() == "Windows" { let mut key_event = KeyEvent::new(); key_event.set_control_key(ControlKey::CtrlAltDel); - self.key_down_or_up(1, key_event, false, false, false, false); + // todo + self.send_key_event(key_event, 2); } else { let mut key_event = KeyEvent::new(); key_event.set_control_key(ControlKey::Delete); - self.key_down_or_up(3, key_event, true, true, false, false); + // self.key_down_or_up(3, key_event, true, true, false, false); } } fn lock_screen(&mut self) { let mut key_event = KeyEvent::new(); key_event.set_control_key(ControlKey::LockScreen); - self.key_down_or_up(1, key_event, false, false, false, false); + // self.key_down_or_up(1, key_event, false, false, false, false); } fn transfer_file(&mut self) { @@ -1180,16 +948,246 @@ impl Handler { } } - fn key_down_or_up( - &mut self, - down_or_up: i32, - evt: KeyEvent, - alt: bool, - ctrl: bool, - shift: bool, - command: bool, - ) { - let mut key_event = evt; + fn send_key_event(&mut self, mut evt: KeyEvent, keyboard_mode: u32) { + // mode: map(1), translate(2), legacy(3), auto(4) + evt.mode = keyboard_mode; + let mut msg_out = Message::new(); + msg_out.set_key_event(evt); + log::info!("{:?}", msg_out); + self.send(Data::Message(msg_out)); + } + + fn map_keyboard_mode(&mut self, down_or_up: bool, key: RdevKey) { + // map mode(1): Send keycode according to the peer platform. + let peer = self.peer_platform(); + + let mut key_event = KeyEvent::new(); + // According to peer platform. + if peer == "Linux" { + let keycode: u32 = rdev::linux_keycode_from_key(key).unwrap_or_default().into(); + key_event.set_chr(keycode); + } else if peer == "Windows" { + let keycode: u32 = rdev::win_keycode_from_key(key).unwrap_or_default().into(); + key_event.set_chr(keycode); + } else if peer == "Mac OS" { + let keycode: u32 = rdev::macos_keycode_from_key(key).unwrap_or_default().into(); + key_event.set_chr(keycode); + } + if down_or_up == true { + key_event.down = true; + } else if down_or_up == true { + key_event.press = true; + } + self.send_key_event(key_event, 1); + } + + fn translate_keyboard_mode(&mut self, down_or_up: bool, key: RdevKey) { + // translate mode(2): locally generated characters are send to the peer. + } + + fn legacy_keyboard_mode(&mut self, down_or_up: bool, key: RdevKey, evt: Event) { + // legacy mode(3): Generate characters locally, look for keycode on other side. + println!("legacy_keyboard_mode {:?}", key); + let peer = self.peer_platform(); + let is_win = peer == "Windows"; + + let alt = get_key_state(enigo::Key::Alt); + #[cfg(windows)] + let ctrl = { + let mut tmp = get_key_state(enigo::Key::Control); + unsafe { + if IS_ALT_GR { + if alt || key == RdevKey::AltGr { + if tmp { + tmp = false; + } + } else { + IS_ALT_GR = false; + } + } + } + tmp + }; + #[cfg(not(windows))] + let ctrl = get_key_state(enigo::Key::Control); + let shift = get_key_state(enigo::Key::Shift); + #[cfg(windows)] + let command = crate::platform::windows::get_win_key_state(); + #[cfg(not(windows))] + let command = get_key_state(enigo::Key::Meta); + let control_key = match key { + RdevKey::Alt => Some(ControlKey::Alt), + RdevKey::AltGr => Some(ControlKey::RAlt), + RdevKey::Backspace => Some(ControlKey::Backspace), + RdevKey::ControlLeft => { + // when pressing AltGr, an extra VK_LCONTROL with a special + // scancode with bit 9 set is sent, let's ignore this. + #[cfg(windows)] + if evt.scan_code & 0x200 != 0 { + unsafe { + IS_ALT_GR = true; + } + return; + } + Some(ControlKey::Control) + } + RdevKey::ControlRight => Some(ControlKey::RControl), + RdevKey::DownArrow => Some(ControlKey::DownArrow), + RdevKey::Escape => Some(ControlKey::Escape), + RdevKey::F1 => Some(ControlKey::F1), + RdevKey::F10 => Some(ControlKey::F10), + RdevKey::F11 => Some(ControlKey::F11), + RdevKey::F12 => Some(ControlKey::F12), + RdevKey::F2 => Some(ControlKey::F2), + RdevKey::F3 => Some(ControlKey::F3), + RdevKey::F4 => Some(ControlKey::F4), + RdevKey::F5 => Some(ControlKey::F5), + RdevKey::F6 => Some(ControlKey::F6), + RdevKey::F7 => Some(ControlKey::F7), + RdevKey::F8 => Some(ControlKey::F8), + RdevKey::F9 => Some(ControlKey::F9), + RdevKey::LeftArrow => Some(ControlKey::LeftArrow), + RdevKey::MetaLeft => Some(ControlKey::Meta), + RdevKey::MetaRight => Some(ControlKey::RWin), + RdevKey::Return => Some(ControlKey::Return), + RdevKey::RightArrow => Some(ControlKey::RightArrow), + RdevKey::ShiftLeft => Some(ControlKey::Shift), + RdevKey::ShiftRight => Some(ControlKey::RShift), + RdevKey::Space => Some(ControlKey::Space), + RdevKey::Tab => Some(ControlKey::Tab), + RdevKey::UpArrow => Some(ControlKey::UpArrow), + RdevKey::Delete => { + if is_win && ctrl && alt { + self.ctrl_alt_del(); + return; + } + Some(ControlKey::Delete) + } + RdevKey::Apps => Some(ControlKey::Apps), + RdevKey::Cancel => Some(ControlKey::Cancel), + RdevKey::Clear => Some(ControlKey::Clear), + RdevKey::Kana => Some(ControlKey::Kana), + RdevKey::Hangul => Some(ControlKey::Hangul), + RdevKey::Junja => Some(ControlKey::Junja), + RdevKey::Final => Some(ControlKey::Final), + RdevKey::Hanja => Some(ControlKey::Hanja), + RdevKey::Hanji => Some(ControlKey::Hanja), + RdevKey::Convert => Some(ControlKey::Convert), + RdevKey::Print => Some(ControlKey::Print), + RdevKey::Select => Some(ControlKey::Select), + RdevKey::Execute => Some(ControlKey::Execute), + RdevKey::PrintScreen => Some(ControlKey::Snapshot), + RdevKey::Help => Some(ControlKey::Help), + RdevKey::Sleep => Some(ControlKey::Sleep), + RdevKey::Separator => Some(ControlKey::Separator), + RdevKey::KpReturn => Some(ControlKey::NumpadEnter), + RdevKey::Kp0 => Some(ControlKey::Numpad0), + RdevKey::Kp1 => Some(ControlKey::Numpad1), + RdevKey::Kp2 => Some(ControlKey::Numpad2), + RdevKey::Kp3 => Some(ControlKey::Numpad3), + RdevKey::Kp4 => Some(ControlKey::Numpad4), + RdevKey::Kp5 => Some(ControlKey::Numpad5), + RdevKey::Kp6 => Some(ControlKey::Numpad6), + RdevKey::Kp7 => Some(ControlKey::Numpad7), + RdevKey::Kp8 => Some(ControlKey::Numpad8), + RdevKey::Kp9 => Some(ControlKey::Numpad9), + RdevKey::KpDivide => Some(ControlKey::Divide), + RdevKey::KpMultiply => Some(ControlKey::Multiply), + RdevKey::KpDecimal => Some(ControlKey::Decimal), + RdevKey::KpMinus => Some(ControlKey::Subtract), + RdevKey::KpPlus => Some(ControlKey::Add), + RdevKey::CapsLock | RdevKey::NumLock | RdevKey::ScrollLock => { + return; + } + RdevKey::Home => Some(ControlKey::Home), + RdevKey::End => Some(ControlKey::End), + RdevKey::Insert => Some(ControlKey::Insert), + RdevKey::PageUp => Some(ControlKey::PageUp), + RdevKey::PageDown => Some(ControlKey::PageDown), + RdevKey::Pause => Some(ControlKey::Pause), + _ => None, + }; + let mut key_event = KeyEvent::new(); + if let Some(k) = control_key { + key_event.set_control_key(k); + } else { + let mut chr = match evt.name { + Some(ref s) => { + if s.len() <= 2 { + // exclude chinese characters + s.chars().next().unwrap_or('\0') + } else { + '\0' + } + } + _ => '\0', + }; + if chr == '·' { + // special for Chinese + chr = '`'; + } + if chr == '\0' { + chr = match key { + RdevKey::Num1 => '1', + RdevKey::Num2 => '2', + RdevKey::Num3 => '3', + RdevKey::Num4 => '4', + RdevKey::Num5 => '5', + RdevKey::Num6 => '6', + RdevKey::Num7 => '7', + RdevKey::Num8 => '8', + RdevKey::Num9 => '9', + RdevKey::Num0 => '0', + RdevKey::KeyA => 'a', + RdevKey::KeyB => 'b', + RdevKey::KeyC => 'c', + RdevKey::KeyD => 'd', + RdevKey::KeyE => 'e', + RdevKey::KeyF => 'f', + RdevKey::KeyG => 'g', + RdevKey::KeyH => 'h', + RdevKey::KeyI => 'i', + RdevKey::KeyJ => 'j', + RdevKey::KeyK => 'k', + RdevKey::KeyL => 'l', + RdevKey::KeyM => 'm', + RdevKey::KeyN => 'n', + RdevKey::KeyO => 'o', + RdevKey::KeyP => 'p', + RdevKey::KeyQ => 'q', + RdevKey::KeyR => 'r', + RdevKey::KeyS => 's', + RdevKey::KeyT => 't', + RdevKey::KeyU => 'u', + RdevKey::KeyV => 'v', + RdevKey::KeyW => 'w', + RdevKey::KeyX => 'x', + RdevKey::KeyY => 'y', + RdevKey::KeyZ => 'z', + RdevKey::Comma => ',', + RdevKey::Dot => '.', + RdevKey::SemiColon => ';', + RdevKey::Quote => '\'', + RdevKey::LeftBracket => '[', + RdevKey::RightBracket => ']', + RdevKey::BackSlash => '\\', + RdevKey::Minus => '-', + RdevKey::Equal => '=', + RdevKey::BackQuote => '`', + _ => '\0', + } + } + if chr != '\0' { + if chr == 'l' && is_win && command { + self.lock_screen(); + return; + } + key_event.set_chr(chr as _); + } else { + log::error!("Unknown key {:?}", evt); + return; + } + } if alt && !crate::is_control_key(&key_event, &ControlKey::Alt) @@ -1223,15 +1221,25 @@ impl Handler { key_event.modifiers.push(ControlKey::NumLock.into()); } } - if down_or_up == 1 { + if down_or_up == true { key_event.down = true; - } else if down_or_up == 3 { - key_event.press = true; } - let mut msg_out = Message::new(); - msg_out.set_key_event(key_event); - log::debug!("{:?}", msg_out); - self.send(Data::Message(msg_out)); + dbg!(&key_event); + self.send_key_event(key_event, 2) + } + + fn key_down_or_up(&mut self, down_or_up: bool, key: RdevKey, evt: Event) { + // Call different functions according to keyboard mode. + let mode = std::env::var("KEYBOARD_MOAD").unwrap_or(String::from("map")); + match mode.as_str() { + "map" => { + self.map_keyboard_mode(down_or_up, key); + } + "legacy" => self.legacy_keyboard_mode(down_or_up, key, evt), + _ => { + self.map_keyboard_mode(down_or_up, key); + } + } } #[inline] @@ -2692,4 +2700,4 @@ impl Handler { async fn send_note(url: String, id: String, conn_id: i32, note: String) { let body = serde_json::json!({ "id": id, "Id": conn_id, "note": note }); allow_err!(crate::post_request(url, body.to_string(), "").await); -} +} \ No newline at end of file From 5dab7bd9a218caf48ae2ae9f1fa63a827e19d8c1 Mon Sep 17 00:00:00 2001 From: Asura Date: Sun, 17 Jul 2022 20:34:08 -0700 Subject: [PATCH 13/57] Refactor simulate to support switching keyboard modes --- libs/enigo/src/linux.rs | 43 +++----------- libs/enigo/src/macos/macos_impl.rs | 32 ----------- libs/enigo/src/win/win_impl.rs | 32 ----------- src/server/connection.rs | 9 +-- src/server/input_service.rs | 90 +++++++++++++++++++++++++----- 5 files changed, 84 insertions(+), 122 deletions(-) diff --git a/libs/enigo/src/linux.rs b/libs/enigo/src/linux.rs index 7f2afc3dc..67af71a62 100644 --- a/libs/enigo/src/linux.rs +++ b/libs/enigo/src/linux.rs @@ -3,7 +3,6 @@ use libc; use crate::{Key, KeyboardControllable, MouseButton, MouseControllable}; use self::libc::{c_char, c_int, c_void, useconds_t}; -use rdev::{simulate, EventType, EventType::*, Key as RdevKey, SimulateError}; use std::{borrow::Cow, ffi::CString, io::prelude::*, ptr, sync::mpsc, thread, time}; const CURRENT_WINDOW: c_int = 0; const DEFAULT_DELAY: u64 = 12000; @@ -104,27 +103,7 @@ impl Enigo { self.tx.send((PyMsg::Char('\0'), true)).ok(); } - fn send_rdev(&mut self, key: &Key, is_press: bool) -> bool { - if let Key::Raw(keycode) = key { - let event_type = match is_press { - // todo: Acccodding to client type - true => Box::leak(Box::new(EventType::KeyPress(RdevKey::Unknown( - (*keycode).into(), - )))), - false => Box::leak(Box::new(EventType::KeyRelease(RdevKey::Unknown( - (*keycode).into(), - )))), - }; - - match simulate(event_type) { - Ok(()) => true, - Err(SimulateError) => false, - } - } else { - false - } - } - + #[inline] fn send_pynput(&mut self, key: &Key, is_press: bool) -> bool { if unsafe { PYNPUT_EXIT || !PYNPUT_REDAY } { @@ -459,12 +438,9 @@ impl KeyboardControllable for Enigo { if self.xdo.is_null() { return Ok(()); } - if self.send_rdev(&key, true) { - return Ok(()); - } - if self.send_pynput(&key, true) { - return Ok(()); - } + // if self.send_pynput(&key, true) { + // return Ok(()); + // } let string = CString::new(&*keysequence(key))?; unsafe { xdo_send_keysequence_window_down( @@ -480,14 +456,9 @@ impl KeyboardControllable for Enigo { if self.xdo.is_null() { return; } - // todo - let keyboard_mode = 1; - if keyboard_mode == 1 && self.send_rdev(&key, false) { - return; - } - if self.send_pynput(&key, false) { - return; - } + // if self.send_pynput(&key, false) { + // return; + // } if let Ok(string) = CString::new(&*keysequence(key)) { unsafe { xdo_send_keysequence_window_up( diff --git a/libs/enigo/src/macos/macos_impl.rs b/libs/enigo/src/macos/macos_impl.rs index df494b9cb..520c9dca1 100644 --- a/libs/enigo/src/macos/macos_impl.rs +++ b/libs/enigo/src/macos/macos_impl.rs @@ -1,5 +1,4 @@ use core_graphics; -use rdev::{simulate, EventType, EventType::*, Key as RdevKey, SimulateError}; // TODO(dustin): use only the things i need use self::core_graphics::display::*; @@ -354,11 +353,6 @@ impl KeyboardControllable for Enigo { } fn key_down(&mut self, key: Key) -> crate::ResultType { - let keyboard_mode = 1; - if keyboard_mode == 1 { - self.send_rdev(&key, true); - return Ok(()); - }; let code = self.key_to_keycode(key); if code == u16::MAX { return Err("".into()); @@ -374,11 +368,6 @@ impl KeyboardControllable for Enigo { } fn key_up(&mut self, key: Key) { - let keyboard_mode = 1; - if keyboard_mode == 1 { - self.send_rdev(&key, true); - return Ok(()); - }; 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) @@ -431,27 +420,6 @@ impl Enigo { (x, (display_height as i32) - y_inv) } - fn send_rdev(&mut self, key: &Key, is_press: bool) -> bool { - if let Key::Raw(keycode) = key { - let event_type = match is_press { - // todo: Acccodding to client type - true => Box::leak(Box::new(EventType::KeyPress(RdevKey::Unknown( - (*keycode).into(), - )))), - false => Box::leak(Box::new(EventType::KeyRelease(RdevKey::Unknown( - (*keycode).into(), - )))), - }; - - match simulate(event_type) { - Ok(()) => true, - Err(SimulateError) => false, - } - } else { - false - } - } - fn key_to_keycode(&mut self, key: Key) -> CGKeyCode { #[allow(deprecated)] // I mean duh, we still need to support deprecated keys until they're removed diff --git a/libs/enigo/src/win/win_impl.rs b/libs/enigo/src/win/win_impl.rs index b8f3d0fa3..56fc4caef 100644 --- a/libs/enigo/src/win/win_impl.rs +++ b/libs/enigo/src/win/win_impl.rs @@ -2,7 +2,6 @@ use self::winapi::ctypes::c_int; use self::winapi::shared::{basetsd::ULONG_PTR, minwindef::*, windef::*}; use self::winapi::um::winbase::*; use self::winapi::um::winuser::*; -use rdev::{simulate, EventType, Key as RdevKey, SimulateError}; use winapi; use crate::win::keycodes::*; @@ -198,11 +197,6 @@ impl KeyboardControllable for Enigo { } fn key_down(&mut self, key: Key) -> crate::ResultType { - let keyboard_mode = 1; - if keyboard_mode == 1 { - self.send_rdev(&key, true); - return Ok(()); - }; let code = self.key_to_keycode(key); if code == 0 || code == 65535 { return Err("".into()); @@ -218,11 +212,6 @@ impl KeyboardControllable for Enigo { } fn key_up(&mut self, key: Key) { - let keyboard_mode = 1; - if keyboard_mode == 1 { - self.send_rdev(&key, false); - return; - }; keybd_event(KEYEVENTF_KEYUP, self.key_to_keycode(key), 0); } @@ -283,27 +272,6 @@ impl Enigo { keybd_event(KEYEVENTF_UNICODE | KEYEVENTF_KEYUP, 0, unicode_char); } - fn send_rdev(&mut self, key: &Key, is_press: bool) -> bool { - if let Key::Raw(keycode) = key { - let event_type = match is_press { - // todo: Acccodding to client type - true => Box::leak(Box::new(EventType::KeyPress(RdevKey::Unknown( - (*keycode).into(), - )))), - false => Box::leak(Box::new(EventType::KeyRelease(RdevKey::Unknown( - (*keycode).into(), - )))), - }; - - match simulate(event_type) { - Ok(()) => true, - Err(SimulateError) => false, - } - } else { - false - } - } - fn key_to_keycode(&self, key: Key) -> u16 { unsafe { LAYOUT = std::ptr::null_mut(); diff --git a/src/server/connection.rs b/src/server/connection.rs index 682c7d928..48fab0c2d 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -419,15 +419,8 @@ impl Connection { handle_mouse(&msg, id); } MessageInput::Key((mut msg, press)) => { - if press { - msg.down = true; - } + // todo: press and down have similar meanings. handle_key(&msg); - let keyboard_mode = 1; - if press && keyboard_mode != 1{ - msg.down = false; - handle_key(&msg); - } } MessageInput::BlockOn => { if crate::platform::block_input(true) { diff --git a/src/server/input_service.rs b/src/server/input_service.rs index 8e8e2abb4..f041b7e86 100644 --- a/src/server/input_service.rs +++ b/src/server/input_service.rs @@ -3,6 +3,7 @@ use super::*; use dispatch::Queue; use enigo::{Enigo, Key, KeyboardControllable, MouseButton, MouseControllable}; use hbb_common::{config::COMPRESS_LEVEL, protobuf::ProtobufEnumOrUnknown}; +use rdev::{simulate, EventType, EventType::*, Key as RdevKey, SimulateError}; use std::{ convert::TryFrom, sync::atomic::{AtomicBool, Ordering}, @@ -578,24 +579,27 @@ pub fn handle_key(evt: &KeyEvent) { handle_key_(evt); } -fn handle_key_(evt: &KeyEvent) { - if EXITING.load(Ordering::SeqCst) { - return; +fn map_keyboard_map(evt: &KeyEvent) { + // map mode(1): Send keycode according to the peer platform. + let event_type = match evt.down { + true => EventType::KeyPress(RdevKey::Unknown(evt.get_chr())), + false => EventType::KeyRelease(RdevKey::Unknown(evt.get_chr())), + }; + + match simulate(&event_type) { + Ok(()) => (), + Err(_simulate_error) => { + // todo + log::error!("rdev could not send {:?}", event_type); + } } + return; +} + +fn legacy_keyboard_map(evt: &KeyEvent) { #[cfg(windows)] crate::platform::windows::try_change_desktop(); let mut en = ENIGO.lock().unwrap(); - let keyboard_mode = 1; - if keyboard_mode == 1 { - if let Some(key_event::Union::chr(chr)) = evt.union { - if evt.down { - en.key_down(Key::Raw(chr.try_into().unwrap())); - } else { - en.key_up(Key::Raw(chr.try_into().unwrap())); - } - } - return; - } // disable numlock if press home etc when numlock is on, // because we will get numpad value (7,8,9 etc) if not #[cfg(windows)] @@ -740,9 +744,67 @@ fn handle_key_(evt: &KeyEvent) { } } +fn handle_key_(evt: &KeyEvent) { + if EXITING.load(Ordering::SeqCst) { + return; + } + + match evt.mode { + 1 => { + map_keyboard_map(evt); + } + 3 => { + legacy_keyboard_map(evt); + } + _ => { + map_keyboard_map(evt); + } + } +} + #[tokio::main(flavor = "current_thread")] async fn send_sas() -> ResultType<()> { let mut stream = crate::ipc::connect(1000, crate::POSTFIX_SERVICE).await?; timeout(1000, stream.send(&crate::ipc::Data::SAS)).await??; Ok(()) } + +#[cfg(test)] +mod test { + use super::*; + use rdev::{listen, simulate, Event, EventType, Key}; + use std::sync::mpsc; + use std::thread; + + #[test] + fn test_handle_key() { + // listen + let (tx, rx) = mpsc::channel(); + std::thread::spawn(move || { + std::env::set_var("KEYBOARD_ONLY", "y"); + let func = move |event: Event| { + tx.send(event).ok(); + }; + if let Err(error) = listen(func) { + println!("Error: {:?}", error); + } + }); + // set key/char base on char + let mut evt = KeyEvent::new(); + evt.set_chr(49); + evt.mode = 3; + + // press + evt.down = true; + handle_key(&evt); + if let Ok(listen_evt) = rx.recv() { + assert_eq!(listen_evt.event_type, EventType::KeyPress(Key::Num1)) + } + // release + evt.down = false; + handle_key(&evt); + if let Ok(listen_evt) = rx.recv() { + assert_eq!(listen_evt.event_type, EventType::KeyRelease(Key::Num1)) + } + } +} From 3c61773d75375b493c10f83dd967683a84bbad45 Mon Sep 17 00:00:00 2001 From: Asura Date: Sun, 17 Jul 2022 20:59:14 -0700 Subject: [PATCH 14/57] Recover legacy keyboard mode when simulate --- libs/enigo/src/linux.rs | 12 ++++++------ src/server/connection.rs | 7 +++++++ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/libs/enigo/src/linux.rs b/libs/enigo/src/linux.rs index 67af71a62..6b4c99a1b 100644 --- a/libs/enigo/src/linux.rs +++ b/libs/enigo/src/linux.rs @@ -438,9 +438,9 @@ impl KeyboardControllable for Enigo { if self.xdo.is_null() { return Ok(()); } - // if self.send_pynput(&key, true) { - // return Ok(()); - // } + if self.send_pynput(&key, true) { + return Ok(()); + } let string = CString::new(&*keysequence(key))?; unsafe { xdo_send_keysequence_window_down( @@ -456,9 +456,9 @@ impl KeyboardControllable for Enigo { if self.xdo.is_null() { return; } - // if self.send_pynput(&key, false) { - // return; - // } + if self.send_pynput(&key, false) { + return; + } if let Ok(string) = CString::new(&*keysequence(key)) { unsafe { xdo_send_keysequence_window_up( diff --git a/src/server/connection.rs b/src/server/connection.rs index 48fab0c2d..dd5b32fe9 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -420,7 +420,14 @@ impl Connection { } MessageInput::Key((mut msg, press)) => { // todo: press and down have similar meanings. + if press && msg.mode == 3 { + msg.down = true; + } handle_key(&msg); + if press && msg.mode == 3 { + msg.down = false; + handle_key(&msg); + } } MessageInput::BlockOn => { if crate::platform::block_input(true) { From 7ae065739cb7dae729676466c0adf6e69c6e03d9 Mon Sep 17 00:00:00 2001 From: Asura Date: Mon, 18 Jul 2022 12:51:17 +0800 Subject: [PATCH 15/57] Recover legacy keyboard mode when listen --- src/ui/remote.rs | 91 +++++++++++++++++++++++++++--------------------- 1 file changed, 51 insertions(+), 40 deletions(-) diff --git a/src/ui/remote.rs b/src/ui/remote.rs index 8ebced2c4..2175cd06b 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -918,18 +918,24 @@ impl Handler { let mut key_event = KeyEvent::new(); key_event.set_control_key(ControlKey::CtrlAltDel); // todo - self.send_key_event(key_event, 2); + key_event.down = true; + self.send_key_event(key_event, 3); } else { let mut key_event = KeyEvent::new(); key_event.set_control_key(ControlKey::Delete); - // self.key_down_or_up(3, key_event, true, true, false, false); + self.legacy_modifiers(&mut key_event, true, true, false, false); + // todo + key_event.press = true; + self.send_key_event(key_event, 3); } } fn lock_screen(&mut self) { let mut key_event = KeyEvent::new(); key_event.set_control_key(ControlKey::LockScreen); - // self.key_down_or_up(1, key_event, false, false, false, false); + // todo + key_event.down = true; + self.send_key_event(key_event, 3); } fn transfer_file(&mut self) { @@ -975,14 +981,49 @@ impl Handler { } if down_or_up == true { key_event.down = true; - } else if down_or_up == true { - key_event.press = true; + } else { + key_event.down = false; } self.send_key_event(key_event, 1); } - fn translate_keyboard_mode(&mut self, down_or_up: bool, key: RdevKey) { - // translate mode(2): locally generated characters are send to the peer. + // fn translate_keyboard_mode(&mut self, down_or_up: bool, key: RdevKey) { + // // translate mode(2): locally generated characters are send to the peer. + // } + + fn legacy_modifiers(&self, key_event: &mut KeyEvent, alt: bool, ctrl: bool, shift: bool, command: bool){ + if alt + && !crate::is_control_key(&key_event, &ControlKey::Alt) + && !crate::is_control_key(&key_event, &ControlKey::RAlt) + { + key_event.modifiers.push(ControlKey::Alt.into()); + } + if shift + && !crate::is_control_key(&key_event, &ControlKey::Shift) + && !crate::is_control_key(&key_event, &ControlKey::RShift) + { + key_event.modifiers.push(ControlKey::Shift.into()); + } + if ctrl + && !crate::is_control_key(&key_event, &ControlKey::Control) + && !crate::is_control_key(&key_event, &ControlKey::RControl) + { + key_event.modifiers.push(ControlKey::Control.into()); + } + if command + && !crate::is_control_key(&key_event, &ControlKey::Meta) + && !crate::is_control_key(&key_event, &ControlKey::RWin) + { + key_event.modifiers.push(ControlKey::Meta.into()); + } + if get_key_state(enigo::Key::CapsLock) { + key_event.modifiers.push(ControlKey::CapsLock.into()); + } + if self.peer_platform() != "Mac OS" { + if get_key_state(enigo::Key::NumLock) && common::valid_for_numlock(&key_event) { + key_event.modifiers.push(ControlKey::NumLock.into()); + } + } } fn legacy_keyboard_mode(&mut self, down_or_up: bool, key: RdevKey, evt: Event) { @@ -1189,38 +1230,8 @@ impl Handler { } } - if alt - && !crate::is_control_key(&key_event, &ControlKey::Alt) - && !crate::is_control_key(&key_event, &ControlKey::RAlt) - { - key_event.modifiers.push(ControlKey::Alt.into()); - } - if shift - && !crate::is_control_key(&key_event, &ControlKey::Shift) - && !crate::is_control_key(&key_event, &ControlKey::RShift) - { - key_event.modifiers.push(ControlKey::Shift.into()); - } - if ctrl - && !crate::is_control_key(&key_event, &ControlKey::Control) - && !crate::is_control_key(&key_event, &ControlKey::RControl) - { - key_event.modifiers.push(ControlKey::Control.into()); - } - if command - && !crate::is_control_key(&key_event, &ControlKey::Meta) - && !crate::is_control_key(&key_event, &ControlKey::RWin) - { - key_event.modifiers.push(ControlKey::Meta.into()); - } - if get_key_state(enigo::Key::CapsLock) { - key_event.modifiers.push(ControlKey::CapsLock.into()); - } - if self.peer_platform() != "Mac OS" { - if get_key_state(enigo::Key::NumLock) && common::valid_for_numlock(&key_event) { - key_event.modifiers.push(ControlKey::NumLock.into()); - } - } + self.legacy_modifiers(&mut key_event, alt, ctrl, shift, command); + if down_or_up == true { key_event.down = true; } @@ -2700,4 +2711,4 @@ impl Handler { async fn send_note(url: String, id: String, conn_id: i32, note: String) { let body = serde_json::json!({ "id": id, "Id": conn_id, "note": note }); allow_err!(crate::post_request(url, body.to_string(), "").await); -} \ No newline at end of file +} From 828795b4370937c328c3a15e464bced10685cda2 Mon Sep 17 00:00:00 2001 From: Asura Date: Mon, 18 Jul 2022 01:54:54 -0700 Subject: [PATCH 16/57] Sync Caps status --- src/server/input_service.rs | 48 +++++++++++++++++++++++++++++-------- src/ui/remote.rs | 7 +++++- 2 files changed, 44 insertions(+), 11 deletions(-) diff --git a/src/server/input_service.rs b/src/server/input_service.rs index f041b7e86..eac11a743 100644 --- a/src/server/input_service.rs +++ b/src/server/input_service.rs @@ -579,20 +579,46 @@ pub fn handle_key(evt: &KeyEvent) { handle_key_(evt); } -fn map_keyboard_map(evt: &KeyEvent) { - // map mode(1): Send keycode according to the peer platform. - let event_type = match evt.down { - true => EventType::KeyPress(RdevKey::Unknown(evt.get_chr())), - false => EventType::KeyRelease(RdevKey::Unknown(evt.get_chr())), - }; - - match simulate(&event_type) { +fn rdev_simulate(event_type: &EventType) { + let delay = std::time::Duration::from_millis(20); + match simulate(event_type) { Ok(()) => (), Err(_simulate_error) => { // todo log::error!("rdev could not send {:?}", event_type); } } + // Let ths OS catchup (at least MacOS) + std::thread::sleep(delay); +} + +fn map_keyboard_map(evt: &KeyEvent) { + // map mode(1): Send keycode according to the peer platform. + let mut en = ENIGO.lock().unwrap(); + // sync CAPS status + let caps_locking = evt + .modifiers + .iter() + .position(|&r| r == ControlKey::CapsLock.into()) + .is_some(); + println!("[*] remote, client: {:?} {:?}", caps_locking, en.get_key_state(enigo::Key::CapsLock)); + if caps_locking && !en.get_key_state(enigo::Key::CapsLock) + { + println!("[*]: Changing status"); + rdev_simulate(&EventType::KeyPress(RdevKey::CapsLock)); + rdev_simulate(&EventType::KeyRelease(RdevKey::CapsLock)); + }else if !caps_locking && en.get_key_state(enigo::Key::CapsLock){ + println!("[*]: Changing status"); + rdev_simulate(&EventType::KeyPress(RdevKey::CapsLock)); + rdev_simulate(&EventType::KeyRelease(RdevKey::CapsLock)); + }; + + let event_type = match evt.down { + true => EventType::KeyPress(RdevKey::Unknown(evt.get_chr())), + false => EventType::KeyRelease(RdevKey::Unknown(evt.get_chr())), + }; + + rdev_simulate(&event_type); return; } @@ -791,8 +817,10 @@ mod test { }); // set key/char base on char let mut evt = KeyEvent::new(); - evt.set_chr(49); - evt.mode = 3; + evt.set_chr(66); + evt.mode = 1; + + evt.modifiers.push(ControlKey::CapsLock.into()); // press evt.down = true; diff --git a/src/ui/remote.rs b/src/ui/remote.rs index 2175cd06b..a230e50fb 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -984,6 +984,11 @@ impl Handler { } else { key_event.down = false; } + + if get_key_state(enigo::Key::CapsLock) { + key_event.modifiers.push(ControlKey::CapsLock.into()); + } + self.send_key_event(key_event, 1); } @@ -1236,7 +1241,7 @@ impl Handler { key_event.down = true; } dbg!(&key_event); - self.send_key_event(key_event, 2) + self.send_key_event(key_event, 3) } fn key_down_or_up(&mut self, down_or_up: bool, key: RdevKey, evt: Event) { From e0a7238cc1d5856cafcc0bc05c80e6ffc6cdcbd3 Mon Sep 17 00:00:00 2001 From: Asura Date: Mon, 18 Jul 2022 02:09:32 -0700 Subject: [PATCH 17/57] Refactor rdev simulate --- src/server/input_service.rs | 42 +++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/src/server/input_service.rs b/src/server/input_service.rs index eac11a743..2061c909d 100644 --- a/src/server/input_service.rs +++ b/src/server/input_service.rs @@ -579,21 +579,23 @@ pub fn handle_key(evt: &KeyEvent) { handle_key_(evt); } -fn rdev_simulate(event_type: &EventType) { +fn rdev_key_down_or_up(key: RdevKey, down_or_up: bool) { + let event_type = match down_or_up { + true => EventType::KeyPress(key), + false => EventType::KeyRelease(key), + }; let delay = std::time::Duration::from_millis(20); - match simulate(event_type) { + match simulate(&event_type) { Ok(()) => (), Err(_simulate_error) => { - // todo - log::error!("rdev could not send {:?}", event_type); + println!("We could not send {:?}", &event_type); } } // Let ths OS catchup (at least MacOS) std::thread::sleep(delay); } -fn map_keyboard_map(evt: &KeyEvent) { - // map mode(1): Send keycode according to the peer platform. +fn sync_status(evt: &KeyEvent) { let mut en = ENIGO.lock().unwrap(); // sync CAPS status let caps_locking = evt @@ -601,24 +603,24 @@ fn map_keyboard_map(evt: &KeyEvent) { .iter() .position(|&r| r == ControlKey::CapsLock.into()) .is_some(); - println!("[*] remote, client: {:?} {:?}", caps_locking, en.get_key_state(enigo::Key::CapsLock)); - if caps_locking && !en.get_key_state(enigo::Key::CapsLock) + println!( + "[*] remote, client: {:?} {:?}", + caps_locking, + en.get_key_state(enigo::Key::CapsLock) + ); + if (caps_locking && !en.get_key_state(enigo::Key::CapsLock)) + || (!caps_locking && en.get_key_state(enigo::Key::CapsLock)) { println!("[*]: Changing status"); - rdev_simulate(&EventType::KeyPress(RdevKey::CapsLock)); - rdev_simulate(&EventType::KeyRelease(RdevKey::CapsLock)); - }else if !caps_locking && en.get_key_state(enigo::Key::CapsLock){ - println!("[*]: Changing status"); - rdev_simulate(&EventType::KeyPress(RdevKey::CapsLock)); - rdev_simulate(&EventType::KeyRelease(RdevKey::CapsLock)); + rdev_key_down_or_up(RdevKey::CapsLock, true); + rdev_key_down_or_up(RdevKey::CapsLock, false); }; +} - let event_type = match evt.down { - true => EventType::KeyPress(RdevKey::Unknown(evt.get_chr())), - false => EventType::KeyRelease(RdevKey::Unknown(evt.get_chr())), - }; - - rdev_simulate(&event_type); +fn map_keyboard_map(evt: &KeyEvent) { + // map mode(1): Send keycode according to the peer platform. + sync_status(evt); + rdev_key_down_or_up(RdevKey::Unknown(evt.get_chr()), evt.down); return; } From 72273f454639ac07efaeb8a2c19cdff08389e42e Mon Sep 17 00:00:00 2001 From: Asura Date: Mon, 18 Jul 2022 02:19:33 -0700 Subject: [PATCH 18/57] Sync Numpad status --- src/server/input_service.rs | 22 +++++++++++++++------- src/ui/remote.rs | 12 +++++++++++- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/server/input_service.rs b/src/server/input_service.rs index 2061c909d..f54290d42 100644 --- a/src/server/input_service.rs +++ b/src/server/input_service.rs @@ -597,24 +597,32 @@ fn rdev_key_down_or_up(key: RdevKey, down_or_up: bool) { fn sync_status(evt: &KeyEvent) { let mut en = ENIGO.lock().unwrap(); - // sync CAPS status + + // remote caps status let caps_locking = evt .modifiers .iter() .position(|&r| r == ControlKey::CapsLock.into()) .is_some(); - println!( - "[*] remote, client: {:?} {:?}", - caps_locking, - en.get_key_state(enigo::Key::CapsLock) - ); + // remote numpad status + let num_locking = evt + .modifiers + .iter() + .position(|&r| r == ControlKey::NumLock.into()) + .is_some(); + if (caps_locking && !en.get_key_state(enigo::Key::CapsLock)) || (!caps_locking && en.get_key_state(enigo::Key::CapsLock)) { - println!("[*]: Changing status"); rdev_key_down_or_up(RdevKey::CapsLock, true); rdev_key_down_or_up(RdevKey::CapsLock, false); }; + if (num_locking && !en.get_key_state(enigo::Key::NumLock)) + || (!num_locking && en.get_key_state(enigo::Key::NumLock)) + { + rdev_key_down_or_up(RdevKey::NumLock, true); + rdev_key_down_or_up(RdevKey::NumLock, false); + }; } fn map_keyboard_map(evt: &KeyEvent) { diff --git a/src/ui/remote.rs b/src/ui/remote.rs index a230e50fb..c00d4579d 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -988,6 +988,9 @@ impl Handler { if get_key_state(enigo::Key::CapsLock) { key_event.modifiers.push(ControlKey::CapsLock.into()); } + if get_key_state(enigo::Key::NumLock) { + key_event.modifiers.push(ControlKey::NumLock.into()); + } self.send_key_event(key_event, 1); } @@ -996,7 +999,14 @@ impl Handler { // // translate mode(2): locally generated characters are send to the peer. // } - fn legacy_modifiers(&self, key_event: &mut KeyEvent, alt: bool, ctrl: bool, shift: bool, command: bool){ + fn legacy_modifiers( + &self, + key_event: &mut KeyEvent, + alt: bool, + ctrl: bool, + shift: bool, + command: bool, + ) { if alt && !crate::is_control_key(&key_event, &ControlKey::Alt) && !crate::is_control_key(&key_event, &ControlKey::RAlt) From 80b01a96dbe38cc8bf6d18f5bf11a7825ce6cd11 Mon Sep 17 00:00:00 2001 From: Asura Date: Mon, 18 Jul 2022 17:42:02 +0800 Subject: [PATCH 19/57] Refactor to remove warning --- src/server/input_service.rs | 2 +- src/ui/remote.rs | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/server/input_service.rs b/src/server/input_service.rs index f54290d42..81bfcd06f 100644 --- a/src/server/input_service.rs +++ b/src/server/input_service.rs @@ -3,7 +3,7 @@ use super::*; use dispatch::Queue; use enigo::{Enigo, Key, KeyboardControllable, MouseButton, MouseControllable}; use hbb_common::{config::COMPRESS_LEVEL, protobuf::ProtobufEnumOrUnknown}; -use rdev::{simulate, EventType, EventType::*, Key as RdevKey, SimulateError}; +use rdev::{simulate, EventType, Key as RdevKey}; use std::{ convert::TryFrom, sync::atomic::{AtomicBool, Ordering}, diff --git a/src/ui/remote.rs b/src/ui/remote.rs index c00d4579d..f6031a425 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -283,8 +283,6 @@ impl Handler { } log::info!("keyboard hooked"); let mut me = self.clone(); - let peer = self.peer_platform(); - let is_win = peer == "Windows"; #[cfg(windows)] crate::platform::windows::enable_lowlevel_keyboard(std::ptr::null_mut() as _); std::thread::spawn(move || { @@ -308,7 +306,7 @@ impl Handler { { return; } - let (key, down) = match evt.event_type { + let (_key, down) = match evt.event_type { KeyPress(k) => { // keyboard long press if MUTEX_SPECIAL_KEYS.lock().unwrap().contains_key(&k) { @@ -330,9 +328,9 @@ impl Handler { }; #[cfg(target_os = "windows")] - let key = rdev::get_win_key(evt.code.into(), evt.scan_code); + let _key = rdev::get_win_key(evt.code.into(), evt.scan_code); - me.key_down_or_up(down, key, evt); + me.key_down_or_up(down, _key, evt); }; if let Err(error) = rdev::listen(func) { log::error!("rdev: {:?}", error); From a2d8c31e856a54eb6ba551d3adefdbbe5135512f Mon Sep 17 00:00:00 2001 From: Asura Date: Mon, 18 Jul 2022 22:01:08 +0800 Subject: [PATCH 20/57] Auto release key --- src/ui/remote.rs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/ui/remote.rs b/src/ui/remote.rs index f6031a425..44e7d705f 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -1,5 +1,5 @@ use std::{ - collections::HashMap, + collections::{HashMap, HashSet}, ops::Deref, sync::{ atomic::{AtomicBool, AtomicUsize, Ordering}, @@ -57,6 +57,7 @@ type Video = AssetPtr; lazy_static::lazy_static! { static ref ENIGO: Arc> = Arc::new(Mutex::new(Enigo::new())); static ref VIDEO: Arc>> = Default::default(); + static ref TO_RELEASE: Arc>> = Arc::new(Mutex::new(HashSet::::new())); } fn get_key_state(key: enigo::Key) -> bool { @@ -732,6 +733,9 @@ impl Handler { } fn leave(&mut self) { + for key in TO_RELEASE.lock().unwrap().iter() { + self.map_keyboard_mode(false, *key) + } #[cfg(windows)] crate::platform::windows::stop_system_key_propagate(false); IS_IN.store(false, Ordering::SeqCst); @@ -986,8 +990,10 @@ impl Handler { if get_key_state(enigo::Key::CapsLock) { key_event.modifiers.push(ControlKey::CapsLock.into()); } - if get_key_state(enigo::Key::NumLock) { - key_event.modifiers.push(ControlKey::NumLock.into()); + if self.peer_platform() != "Mac OS" { + if get_key_state(enigo::Key::NumLock) && common::valid_for_numlock(&key_event) { + key_event.modifiers.push(ControlKey::NumLock.into()); + } } self.send_key_event(key_event, 1); @@ -1257,6 +1263,11 @@ impl Handler { let mode = std::env::var("KEYBOARD_MOAD").unwrap_or(String::from("map")); match mode.as_str() { "map" => { + if down_or_up == true { + TO_RELEASE.lock().unwrap().insert(key); + } else { + TO_RELEASE.lock().unwrap().remove(&key); + } self.map_keyboard_mode(down_or_up, key); } "legacy" => self.legacy_keyboard_mode(down_or_up, key, evt), From a8e4591217c478b62c2b93df4795b5edd4e2c596 Mon Sep 17 00:00:00 2001 From: Asura Date: Mon, 18 Jul 2022 07:38:05 -0700 Subject: [PATCH 21/57] Fix lock_screen and ctrl_alt_del --- libs/enigo/Cargo.toml | 2 +- libs/enigo/src/linux.rs | 11 ++--------- src/server/input_service.rs | 2 ++ 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/libs/enigo/Cargo.toml b/libs/enigo/Cargo.toml index b1c57ca92..e97f000a6 100644 --- a/libs/enigo/Cargo.toml +++ b/libs/enigo/Cargo.toml @@ -21,7 +21,7 @@ appveyor = { repository = "pythoneer/enigo-85xiy" } [dependencies] serde = { version = "1.0", optional = true } serde_derive = { version = "1.0", optional = true } -log = "0.4.17" +log = "0.4" rdev = { git = "https://github.com/asur4s/rdev" } [features] diff --git a/libs/enigo/src/linux.rs b/libs/enigo/src/linux.rs index 6b4c99a1b..30c49c014 100644 --- a/libs/enigo/src/linux.rs +++ b/libs/enigo/src/linux.rs @@ -103,7 +103,6 @@ impl Enigo { self.tx.send((PyMsg::Char('\0'), true)).ok(); } - #[inline] fn send_pynput(&mut self, key: &Key, is_press: bool) -> bool { if unsafe { PYNPUT_EXIT || !PYNPUT_REDAY } { @@ -112,14 +111,8 @@ impl Enigo { if let Key::Layout(c) = key { return self.tx.send((PyMsg::Char(*c), is_press)).is_ok(); } - if let Key::Raw(chr) = key { - fn string_to_static_str(s: String) -> &'static str { - Box::leak(s.into_boxed_str()) - } - return self - .tx - .send((PyMsg::Str(string_to_static_str(chr.to_string())), is_press)) - .is_ok(); + if let Key::Raw(_) = key { + return false; } #[allow(deprecated)] let s = match key { diff --git a/src/server/input_service.rs b/src/server/input_service.rs index 81bfcd06f..aadb957a3 100644 --- a/src/server/input_service.rs +++ b/src/server/input_service.rs @@ -450,6 +450,7 @@ pub fn lock_screen() { key_event.down = true; key_event.set_chr('l' as _); key_event.modifiers.push(ControlKey::Meta.into()); + key_event.mode = 3; handle_key(&key_event); key_event.down = false; handle_key(&key_event); @@ -462,6 +463,7 @@ pub fn lock_screen() { key_event.set_chr('q' as _); key_event.modifiers.push(ControlKey::Meta.into()); key_event.modifiers.push(ControlKey::Control.into()); + key_event.mode = 3; handle_key(&key_event); key_event.down = false; handle_key(&key_event); From a118056c304c6919ff9aaa10769bd4d78809b7e9 Mon Sep 17 00:00:00 2001 From: Asura Date: Mon, 18 Jul 2022 23:04:04 +0800 Subject: [PATCH 22/57] Fix sync Numpad status --- src/server/input_service.rs | 11 +++++++++-- src/ui/remote.rs | 6 ++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/server/input_service.rs b/src/server/input_service.rs index aadb957a3..a116bbbfc 100644 --- a/src/server/input_service.rs +++ b/src/server/input_service.rs @@ -810,9 +810,8 @@ async fn send_sas() -> ResultType<()> { #[cfg(test)] mod test { use super::*; - use rdev::{listen, simulate, Event, EventType, Key}; + use rdev::{listen, Event, EventType, Key}; use std::sync::mpsc; - use std::thread; #[test] fn test_handle_key() { @@ -847,4 +846,12 @@ mod test { assert_eq!(listen_evt.event_type, EventType::KeyRelease(Key::Num1)) } } + #[test] + fn test_get_key_state() { + let mut en = ENIGO.lock().unwrap(); + println!( + "[*] test_get_key_state: {:?}", + en.get_key_state(enigo::Key::NumLock) + ); + } } diff --git a/src/ui/remote.rs b/src/ui/remote.rs index 44e7d705f..a0aa5d381 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -990,10 +990,8 @@ impl Handler { if get_key_state(enigo::Key::CapsLock) { key_event.modifiers.push(ControlKey::CapsLock.into()); } - if self.peer_platform() != "Mac OS" { - if get_key_state(enigo::Key::NumLock) && common::valid_for_numlock(&key_event) { - key_event.modifiers.push(ControlKey::NumLock.into()); - } + if get_key_state(enigo::Key::NumLock) { + key_event.modifiers.push(ControlKey::NumLock.into()); } self.send_key_event(key_event, 1); From 48466bfe37824536c4b0b55bed9580dd999c6eb9 Mon Sep 17 00:00:00 2001 From: Asura Date: Tue, 19 Jul 2022 09:35:39 +0800 Subject: [PATCH 23/57] Numpad when linux -> windows --- src/ui/remote.rs | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/src/ui/remote.rs b/src/ui/remote.rs index a0aa5d381..7c05c4407 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -965,22 +965,42 @@ impl Handler { self.send(Data::Message(msg_out)); } + fn convert_numpad_keys(&mut self, key: &RdevKey) -> &RdevKey { + if get_key_state(enigo::Key::NumLock) { + return; + } + match key { + &RdevKey::Num0 => &RdevKey::Insert, + &RdevKey::KpDecimal => &RdevKey::Delete, + &RdevKey::Num1 => &RdevKey::End, + &RdevKey::Num2 => &RdevKey::DownArrow, + &RdevKey::Num3 => &RdevKey::PageDown, + &RdevKey::Num4 => &RdevKey::LeftArrow, + &RdevKey::Num5 => &RdevKey::Clear, + &RdevKey::Num6 => &RdevKey::RightArrow, + &RdevKey::Num7 => &RdevKey::Home, + &RdevKey::Num8 => &RdevKey::UpArrow, + &RdevKey::Num9 => &RdevKey::PageUp, + } + } + fn map_keyboard_mode(&mut self, down_or_up: bool, key: RdevKey) { // map mode(1): Send keycode according to the peer platform. let peer = self.peer_platform(); let mut key_event = KeyEvent::new(); // According to peer platform. - if peer == "Linux" { - let keycode: u32 = rdev::linux_keycode_from_key(key).unwrap_or_default().into(); - key_event.set_chr(keycode); + let keycode: u32 = if peer == "Linux" { + rdev::linux_keycode_from_key(key).unwrap_or_default().into() } else if peer == "Windows" { - let keycode: u32 = rdev::win_keycode_from_key(key).unwrap_or_default().into(); - key_event.set_chr(keycode); + #[cfg(not(windows))] + self.convert_numpad_keys(&key); + rdev::win_keycode_from_key(key).unwrap_or_default().into() } else if peer == "Mac OS" { - let keycode: u32 = rdev::macos_keycode_from_key(key).unwrap_or_default().into(); - key_event.set_chr(keycode); - } + rdev::macos_keycode_from_key(key).unwrap_or_default().into() + }; + key_event.set_chr(keycode); + if down_or_up == true { key_event.down = true; } else { From a77d64d18184bd7287475f7558121c6092c5e551 Mon Sep 17 00:00:00 2001 From: Asura Date: Mon, 18 Jul 2022 18:47:38 -0700 Subject: [PATCH 24/57] Remove log --- libs/enigo/src/linux.rs | 2 +- src/ui/remote.rs | 32 ++++++++++++++++---------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/libs/enigo/src/linux.rs b/libs/enigo/src/linux.rs index 30c49c014..de06923f3 100644 --- a/libs/enigo/src/linux.rs +++ b/libs/enigo/src/linux.rs @@ -3,7 +3,7 @@ use libc; use crate::{Key, KeyboardControllable, MouseButton, MouseControllable}; use self::libc::{c_char, c_int, c_void, useconds_t}; -use std::{borrow::Cow, ffi::CString, io::prelude::*, ptr, sync::mpsc, thread, time}; +use std::{borrow::Cow, ffi::CString, io::prelude::*, ptr, sync::mpsc}; const CURRENT_WINDOW: c_int = 0; const DEFAULT_DELAY: u64 = 12000; type Window = c_int; diff --git a/src/ui/remote.rs b/src/ui/remote.rs index 7c05c4407..f051663f6 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -965,22 +965,23 @@ impl Handler { self.send(Data::Message(msg_out)); } - fn convert_numpad_keys(&mut self, key: &RdevKey) -> &RdevKey { + fn convert_numpad_keys(&mut self, key: RdevKey) -> RdevKey { if get_key_state(enigo::Key::NumLock) { - return; + return key; } match key { - &RdevKey::Num0 => &RdevKey::Insert, - &RdevKey::KpDecimal => &RdevKey::Delete, - &RdevKey::Num1 => &RdevKey::End, - &RdevKey::Num2 => &RdevKey::DownArrow, - &RdevKey::Num3 => &RdevKey::PageDown, - &RdevKey::Num4 => &RdevKey::LeftArrow, - &RdevKey::Num5 => &RdevKey::Clear, - &RdevKey::Num6 => &RdevKey::RightArrow, - &RdevKey::Num7 => &RdevKey::Home, - &RdevKey::Num8 => &RdevKey::UpArrow, - &RdevKey::Num9 => &RdevKey::PageUp, + RdevKey::Kp0 => RdevKey::Insert, + RdevKey::KpDecimal => RdevKey::Delete, + RdevKey::Kp1 => RdevKey::End, + RdevKey::Kp2 => RdevKey::DownArrow, + RdevKey::Kp3 => RdevKey::PageDown, + RdevKey::Kp4 => RdevKey::LeftArrow, + RdevKey::Kp5 => RdevKey::Clear, + RdevKey::Kp6 => RdevKey::RightArrow, + RdevKey::Kp7 => RdevKey::Home, + RdevKey::Kp8 => RdevKey::UpArrow, + RdevKey::Kp9 => RdevKey::PageUp, + _ => key, } } @@ -994,9 +995,9 @@ impl Handler { rdev::linux_keycode_from_key(key).unwrap_or_default().into() } else if peer == "Windows" { #[cfg(not(windows))] - self.convert_numpad_keys(&key); + let key = self.convert_numpad_keys(key); rdev::win_keycode_from_key(key).unwrap_or_default().into() - } else if peer == "Mac OS" { + } else { rdev::macos_keycode_from_key(key).unwrap_or_default().into() }; key_event.set_chr(keycode); @@ -1065,7 +1066,6 @@ impl Handler { fn legacy_keyboard_mode(&mut self, down_or_up: bool, key: RdevKey, evt: Event) { // legacy mode(3): Generate characters locally, look for keycode on other side. - println!("legacy_keyboard_mode {:?}", key); let peer = self.peer_platform(); let is_win = peer == "Windows"; From 19ebbb145a753e9090b387258dd4746627f4ff05 Mon Sep 17 00:00:00 2001 From: Asura Date: Mon, 18 Jul 2022 23:45:54 -0700 Subject: [PATCH 25/57] Compatible with legacy mode in remote --- src/server/connection.rs | 4 ++-- src/server/input_service.rs | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/server/connection.rs b/src/server/connection.rs index dd5b32fe9..854191c95 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -420,11 +420,11 @@ impl Connection { } MessageInput::Key((mut msg, press)) => { // todo: press and down have similar meanings. - if press && msg.mode == 3 { + if press && msg.mode == 0 { msg.down = true; } handle_key(&msg); - if press && msg.mode == 3 { + if press && msg.mode == 0 { msg.down = false; handle_key(&msg); } diff --git a/src/server/input_service.rs b/src/server/input_service.rs index a116bbbfc..4563ef465 100644 --- a/src/server/input_service.rs +++ b/src/server/input_service.rs @@ -450,7 +450,7 @@ pub fn lock_screen() { key_event.down = true; key_event.set_chr('l' as _); key_event.modifiers.push(ControlKey::Meta.into()); - key_event.mode = 3; + key_event.mode = 0; handle_key(&key_event); key_event.down = false; handle_key(&key_event); @@ -463,7 +463,7 @@ pub fn lock_screen() { key_event.set_chr('q' as _); key_event.modifiers.push(ControlKey::Meta.into()); key_event.modifiers.push(ControlKey::Control.into()); - key_event.mode = 3; + key_event.mode = 0; handle_key(&key_event); key_event.down = false; handle_key(&key_event); @@ -788,14 +788,14 @@ fn handle_key_(evt: &KeyEvent) { } match evt.mode { + 0 => { + legacy_keyboard_map(evt); + } 1 => { map_keyboard_map(evt); } - 3 => { - legacy_keyboard_map(evt); - } _ => { - map_keyboard_map(evt); + legacy_keyboard_map(evt); } } } From 0bacc1c250192ccd4ec424f04b97b1c6feb44c63 Mon Sep 17 00:00:00 2001 From: Asura Date: Tue, 19 Jul 2022 15:09:45 +0800 Subject: [PATCH 26/57] Compatible with legacy mode in client --- src/ui/remote.rs | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/src/ui/remote.rs b/src/ui/remote.rs index f051663f6..0b96b3c26 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -921,14 +921,14 @@ impl Handler { key_event.set_control_key(ControlKey::CtrlAltDel); // todo key_event.down = true; - self.send_key_event(key_event, 3); + self.send_key_event(key_event, 0); } else { let mut key_event = KeyEvent::new(); key_event.set_control_key(ControlKey::Delete); self.legacy_modifiers(&mut key_event, true, true, false, false); // todo key_event.press = true; - self.send_key_event(key_event, 3); + self.send_key_event(key_event, 0); } } @@ -937,7 +937,7 @@ impl Handler { key_event.set_control_key(ControlKey::LockScreen); // todo key_event.down = true; - self.send_key_event(key_event, 3); + self.send_key_event(key_event, 0); } fn transfer_file(&mut self) { @@ -965,6 +965,7 @@ impl Handler { self.send(Data::Message(msg_out)); } + #[allow(dead_code)] fn convert_numpad_keys(&mut self, key: RdevKey) -> RdevKey { if get_key_state(enigo::Key::NumLock) { return key; @@ -1000,13 +1001,9 @@ impl Handler { } else { rdev::macos_keycode_from_key(key).unwrap_or_default().into() }; - key_event.set_chr(keycode); - if down_or_up == true { - key_event.down = true; - } else { - key_event.down = false; - } + key_event.set_chr(keycode); + key_event.down = down_or_up; if get_key_state(enigo::Key::CapsLock) { key_event.modifiers.push(ControlKey::CapsLock.into()); @@ -1065,7 +1062,7 @@ impl Handler { } fn legacy_keyboard_mode(&mut self, down_or_up: bool, key: RdevKey, evt: Event) { - // legacy mode(3): Generate characters locally, look for keycode on other side. + // legacy mode(0): Generate characters locally, look for keycode on other side. let peer = self.peer_platform(); let is_win = peer == "Windows"; @@ -1273,12 +1270,12 @@ impl Handler { key_event.down = true; } dbg!(&key_event); - self.send_key_event(key_event, 3) + self.send_key_event(key_event, 0) } fn key_down_or_up(&mut self, down_or_up: bool, key: RdevKey, evt: Event) { // Call different functions according to keyboard mode. - let mode = std::env::var("KEYBOARD_MOAD").unwrap_or(String::from("map")); + let mode = std::env::var("KEYBOARD_MOAD").unwrap_or(String::from("legacy")); match mode.as_str() { "map" => { if down_or_up == true { @@ -1289,9 +1286,7 @@ impl Handler { self.map_keyboard_mode(down_or_up, key); } "legacy" => self.legacy_keyboard_mode(down_or_up, key, evt), - _ => { - self.map_keyboard_mode(down_or_up, key); - } + _ => self.legacy_keyboard_mode(down_or_up, key, evt), } } From 02b4d7f1d9dc755d4e55f403479dbb76b4a82f5c Mon Sep 17 00:00:00 2001 From: Asura Date: Tue, 19 Jul 2022 15:43:13 +0800 Subject: [PATCH 27/57] Refactor keyboard mode by enum --- libs/hbb_common/protos/message.proto | 9 +++++++- src/server/connection.rs | 4 ++-- src/server/input_service.rs | 10 ++++---- src/ui/remote.rs | 34 +++++++++++++++++----------- 4 files changed, 36 insertions(+), 21 deletions(-) diff --git a/libs/hbb_common/protos/message.proto b/libs/hbb_common/protos/message.proto index 645930eb4..2282bf43a 100644 --- a/libs/hbb_common/protos/message.proto +++ b/libs/hbb_common/protos/message.proto @@ -97,6 +97,13 @@ message MouseEvent { repeated ControlKey modifiers = 4; } +enum KeyboardMode{ + Legacy = 0; + Map = 1; + Translate = 2; + Auto = 3; +} + enum ControlKey { Unknown = 0; Alt = 1; @@ -190,7 +197,7 @@ message KeyEvent { string seq = 6; } repeated ControlKey modifiers = 8; - uint32 mode = 9; + KeyboardMode mode = 9; } message CursorData { diff --git a/src/server/connection.rs b/src/server/connection.rs index 854191c95..fdeaac106 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -420,11 +420,11 @@ impl Connection { } MessageInput::Key((mut msg, press)) => { // todo: press and down have similar meanings. - if press && msg.mode == 0 { + if press && msg.mode.unwrap() == KeyboardMode::Legacy { msg.down = true; } handle_key(&msg); - if press && msg.mode == 0 { + if press && msg.mode.unwrap() == KeyboardMode::Legacy { msg.down = false; handle_key(&msg); } diff --git a/src/server/input_service.rs b/src/server/input_service.rs index 4563ef465..02f50abff 100644 --- a/src/server/input_service.rs +++ b/src/server/input_service.rs @@ -450,7 +450,7 @@ pub fn lock_screen() { key_event.down = true; key_event.set_chr('l' as _); key_event.modifiers.push(ControlKey::Meta.into()); - key_event.mode = 0; + key_event.mode = KeyboardMode::Legacy; handle_key(&key_event); key_event.down = false; handle_key(&key_event); @@ -463,7 +463,7 @@ pub fn lock_screen() { key_event.set_chr('q' as _); key_event.modifiers.push(ControlKey::Meta.into()); key_event.modifiers.push(ControlKey::Control.into()); - key_event.mode = 0; + key_event.mode = KeyboardMode::Legacy; handle_key(&key_event); key_event.down = false; handle_key(&key_event); @@ -787,11 +787,11 @@ fn handle_key_(evt: &KeyEvent) { return; } - match evt.mode { - 0 => { + match evt.mode.unwrap() { + KeyboardMode::Legacy => { legacy_keyboard_map(evt); } - 1 => { + KeyboardMode::Map => { map_keyboard_map(evt); } _ => { diff --git a/src/ui/remote.rs b/src/ui/remote.rs index 0b96b3c26..4deaf05d8 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -41,6 +41,7 @@ use hbb_common::{ time::{self, Duration, Instant, Interval}, }, Stream, + protobuf::ProtobufEnumOrUnknown, }; use hbb_common::{config::TransferSerde, fs::TransferJobMeta}; use rdev::{Event, EventType::*, Key as RdevKey}; @@ -921,14 +922,14 @@ impl Handler { key_event.set_control_key(ControlKey::CtrlAltDel); // todo key_event.down = true; - self.send_key_event(key_event, 0); + self.send_key_event(key_event, KeyboardMode::Legacy); } else { let mut key_event = KeyEvent::new(); key_event.set_control_key(ControlKey::Delete); self.legacy_modifiers(&mut key_event, true, true, false, false); // todo key_event.press = true; - self.send_key_event(key_event, 0); + self.send_key_event(key_event, KeyboardMode::Legacy); } } @@ -937,7 +938,7 @@ impl Handler { key_event.set_control_key(ControlKey::LockScreen); // todo key_event.down = true; - self.send_key_event(key_event, 0); + self.send_key_event(key_event, KeyboardMode::Legacy); } fn transfer_file(&mut self) { @@ -956,9 +957,9 @@ impl Handler { } } - fn send_key_event(&mut self, mut evt: KeyEvent, keyboard_mode: u32) { - // mode: map(1), translate(2), legacy(3), auto(4) - evt.mode = keyboard_mode; + fn send_key_event(&mut self, mut evt: KeyEvent, keyboard_mode: KeyboardMode) { + // mode: legacy(0), map(1), translate(2), auto(3) + evt.mode = ProtobufEnumOrUnknown::new(keyboard_mode); let mut msg_out = Message::new(); msg_out.set_key_event(evt); log::info!("{:?}", msg_out); @@ -1012,7 +1013,7 @@ impl Handler { key_event.modifiers.push(ControlKey::NumLock.into()); } - self.send_key_event(key_event, 1); + self.send_key_event(key_event, KeyboardMode::Map); } // fn translate_keyboard_mode(&mut self, down_or_up: bool, key: RdevKey) { @@ -1269,15 +1270,22 @@ impl Handler { if down_or_up == true { key_event.down = true; } - dbg!(&key_event); - self.send_key_event(key_event, 0) + self.send_key_event(key_event, KeyboardMode::Legacy) } fn key_down_or_up(&mut self, down_or_up: bool, key: RdevKey, evt: Event) { // Call different functions according to keyboard mode. - let mode = std::env::var("KEYBOARD_MOAD").unwrap_or(String::from("legacy")); - match mode.as_str() { - "map" => { + let mode = match std::env::var("KEYBOARD_MOAD") + .unwrap_or(String::from("legacy")) + .as_str() + { + "map" => KeyboardMode::Map, + "legacy" => KeyboardMode::Legacy, + _ => KeyboardMode::Legacy, + }; + + match mode { + KeyboardMode::Map => { if down_or_up == true { TO_RELEASE.lock().unwrap().insert(key); } else { @@ -1285,7 +1293,7 @@ impl Handler { } self.map_keyboard_mode(down_or_up, key); } - "legacy" => self.legacy_keyboard_mode(down_or_up, key, evt), + KeyboardMode::Legacy => self.legacy_keyboard_mode(down_or_up, key, evt), _ => self.legacy_keyboard_mode(down_or_up, key, evt), } } From cbdc28ee2055453ea35fdc52661ef9fc06b0d17f Mon Sep 17 00:00:00 2001 From: Asura Date: Tue, 19 Jul 2022 01:04:23 -0700 Subject: [PATCH 28/57] Fix compiler error --- src/server/input_service.rs | 15 ++++++++++----- src/ui/remote.rs | 3 +-- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/server/input_service.rs b/src/server/input_service.rs index 02f50abff..b20cad35e 100644 --- a/src/server/input_service.rs +++ b/src/server/input_service.rs @@ -447,11 +447,14 @@ pub fn lock_screen() { // loginctl lock-session also not work, they both work run rustdesk from cmd std::thread::spawn(|| { let mut key_event = KeyEvent::new(); - key_event.down = true; + key_event.set_chr('l' as _); key_event.modifiers.push(ControlKey::Meta.into()); - key_event.mode = KeyboardMode::Legacy; + key_event.mode = KeyboardMode::Legacy.into(); + + key_event.down = true; handle_key(&key_event); + key_event.down = false; handle_key(&key_event); }); @@ -459,11 +462,13 @@ pub fn lock_screen() { // CGSession -suspend not real lock screen, it is user switch std::thread::spawn(|| { let mut key_event = KeyEvent::new(); - key_event.down = true; + key_event.set_chr('q' as _); key_event.modifiers.push(ControlKey::Meta.into()); key_event.modifiers.push(ControlKey::Control.into()); - key_event.mode = KeyboardMode::Legacy; + key_event.mode = KeyboardMode::Legacy.into(); + + key_event.down = true; handle_key(&key_event); key_event.down = false; handle_key(&key_event); @@ -829,7 +834,7 @@ mod test { // set key/char base on char let mut evt = KeyEvent::new(); evt.set_chr(66); - evt.mode = 1; + evt.mode = ProtobufEnum::new(KeyboardMode::Legacy); evt.modifiers.push(ControlKey::CapsLock.into()); diff --git a/src/ui/remote.rs b/src/ui/remote.rs index 4deaf05d8..4a33be574 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -41,7 +41,6 @@ use hbb_common::{ time::{self, Duration, Instant, Interval}, }, Stream, - protobuf::ProtobufEnumOrUnknown, }; use hbb_common::{config::TransferSerde, fs::TransferJobMeta}; use rdev::{Event, EventType::*, Key as RdevKey}; @@ -959,7 +958,7 @@ impl Handler { fn send_key_event(&mut self, mut evt: KeyEvent, keyboard_mode: KeyboardMode) { // mode: legacy(0), map(1), translate(2), auto(3) - evt.mode = ProtobufEnumOrUnknown::new(keyboard_mode); + evt.mode = keyboard_mode.into(); let mut msg_out = Message::new(); msg_out.set_key_event(evt); log::info!("{:?}", msg_out); From d07ef7af8af6bf88d6b740bce1b778f5448a3ebc Mon Sep 17 00:00:00 2001 From: Asura Date: Tue, 19 Jul 2022 16:15:57 +0800 Subject: [PATCH 29/57] Fix compile error of testcase --- src/server/input_service.rs | 2 +- src/ui/remote.rs | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/server/input_service.rs b/src/server/input_service.rs index b20cad35e..252139adb 100644 --- a/src/server/input_service.rs +++ b/src/server/input_service.rs @@ -834,7 +834,7 @@ mod test { // set key/char base on char let mut evt = KeyEvent::new(); evt.set_chr(66); - evt.mode = ProtobufEnum::new(KeyboardMode::Legacy); + evt.mode = KeyboardMode::Legacy.into(); evt.modifiers.push(ControlKey::CapsLock.into()); diff --git a/src/ui/remote.rs b/src/ui/remote.rs index 4a33be574..3688a7d75 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -961,7 +961,6 @@ impl Handler { evt.mode = keyboard_mode.into(); let mut msg_out = Message::new(); msg_out.set_key_event(evt); - log::info!("{:?}", msg_out); self.send(Data::Message(msg_out)); } @@ -1274,7 +1273,7 @@ impl Handler { fn key_down_or_up(&mut self, down_or_up: bool, key: RdevKey, evt: Event) { // Call different functions according to keyboard mode. - let mode = match std::env::var("KEYBOARD_MOAD") + let mode = match std::env::var("KEYBOARD_MODE") .unwrap_or(String::from("legacy")) .as_str() { From 669e8b98b233b9918e1e88a05b01941c5dcc8da1 Mon Sep 17 00:00:00 2001 From: Asura Date: Tue, 19 Jul 2022 16:24:19 +0800 Subject: [PATCH 30/57] Update Cargo.toml about rdev --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 056c14ae7..6a32a7a89 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3858,7 +3858,7 @@ dependencies = [ [[package]] name = "rdev" version = "0.5.0-2" -source = "git+https://github.com/asur4s/rdev#95cecfd1b0f0b20c6cd728afca859107b911f3b8" +source = "git+https://github.com/asur4s/rdev#548d1194dd6863ab004d59299b995eb64cf21c3d" dependencies = [ "cocoa 0.22.0", "core-foundation 0.7.0", From fe9923109092827f543560a7af42dff6c3135117 Mon Sep 17 00:00:00 2001 From: Asura Date: Tue, 19 Jul 2022 16:49:05 +0800 Subject: [PATCH 31/57] Make case insensitive of keyboard_mode --- src/ui/remote.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui/remote.rs b/src/ui/remote.rs index 3688a7d75..c8ce5d724 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -1274,7 +1274,7 @@ impl Handler { fn key_down_or_up(&mut self, down_or_up: bool, key: RdevKey, evt: Event) { // Call different functions according to keyboard mode. let mode = match std::env::var("KEYBOARD_MODE") - .unwrap_or(String::from("legacy")) + .unwrap_or(String::from("legacy")).to_lowercase() .as_str() { "map" => KeyboardMode::Map, From 3a0c10bdb183e4ac6298239f0797902664171d36 Mon Sep 17 00:00:00 2001 From: Asura Date: Wed, 20 Jul 2022 20:31:17 -0700 Subject: [PATCH 32/57] Refactor for compiler in linux --- libs/enigo/src/lib.rs | 6 +++--- libs/enigo/src/linux/xdo.rs | 2 +- src/server/input_service.rs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libs/enigo/src/lib.rs b/libs/enigo/src/lib.rs index 164fb1c17..01e9b67d2 100644 --- a/libs/enigo/src/lib.rs +++ b/libs/enigo/src/lib.rs @@ -257,7 +257,7 @@ pub enum Key { Backspace, /// caps lock key CapsLock, - #[deprecated(since = "0.0.12", note = "now renamed to Meta")] + // #[deprecated(since = "0.0.12", note = "now renamed to Meta")] /// command key on macOS (super key on Linux, windows key on Windows) Command, /// control key @@ -314,14 +314,14 @@ pub enum Key { Shift, /// space key Space, - #[deprecated(since = "0.0.12", note = "now renamed to Meta")] + // #[deprecated(since = "0.0.12", note = "now renamed to Meta")] /// super key on linux (command key on macOS, windows key on Windows) Super, /// tab key (tabulator) Tab, /// up arrow key UpArrow, - #[deprecated(since = "0.0.12", note = "now renamed to Meta")] + // #[deprecated(since = "0.0.12", note = "now renamed to Meta")] /// windows key on Windows (super key on Linux, command key on macOS) Windows, /// diff --git a/libs/enigo/src/linux/xdo.rs b/libs/enigo/src/linux/xdo.rs index 541dbe81f..ff687eee2 100644 --- a/libs/enigo/src/linux/xdo.rs +++ b/libs/enigo/src/linux/xdo.rs @@ -3,7 +3,7 @@ use libc; use crate::{Key, KeyboardControllable, MouseButton, MouseControllable}; use self::libc::{c_char, c_int, c_void, useconds_t}; -use std::{borrow::Cow, ffi::CString, io::prelude::*, ptr, sync::mpsc}; +use std::{borrow::Cow, ffi::CString, ptr}; const CURRENT_WINDOW: c_int = 0; const DEFAULT_DELAY: u64 = 12000; diff --git a/src/server/input_service.rs b/src/server/input_service.rs index 6103274ee..5532967ca 100644 --- a/src/server/input_service.rs +++ b/src/server/input_service.rs @@ -2,7 +2,7 @@ use super::*; #[cfg(target_os = "macos")] use dispatch::Queue; use enigo::{Enigo, Key, KeyboardControllable, MouseButton, MouseControllable}; -use hbb_common::{config::COMPRESS_LEVEL, protobuf::ProtobufEnumOrUnknown, protobuf::EnumOrUnknown}; +use hbb_common::{config::COMPRESS_LEVEL, protobuf::EnumOrUnknown}; use rdev::{simulate, EventType, Key as RdevKey}; use std::{ convert::TryFrom, @@ -654,7 +654,7 @@ fn sync_status(evt: &KeyEvent) { fn map_keyboard_map(evt: &KeyEvent) { // map mode(1): Send keycode according to the peer platform. sync_status(evt); - rdev_key_down_or_up(RdevKey::Unknown(evt.get_chr()), evt.down); + rdev_key_down_or_up(RdevKey::Unknown(evt.chr()), evt.down); return; } From 25c7bbd96fb55a8a31b3ee3f22786b555440db19 Mon Sep 17 00:00:00 2001 From: Asura Date: Thu, 21 Jul 2022 12:46:19 +0800 Subject: [PATCH 33/57] Fix numpad error --- libs/enigo/src/linux/pynput.rs | 20 ++++++++++---------- rust-toolchain.toml | 2 -- 2 files changed, 10 insertions(+), 12 deletions(-) delete mode 100644 rust-toolchain.toml diff --git a/libs/enigo/src/linux/pynput.rs b/libs/enigo/src/linux/pynput.rs index 748b30105..7868b7f6f 100644 --- a/libs/enigo/src/linux/pynput.rs +++ b/libs/enigo/src/linux/pynput.rs @@ -67,16 +67,16 @@ impl EnigoPynput { Key::Space => "space", Key::Tab => "Tab", Key::UpArrow => "Up", - Key::Numpad0 => "0", - Key::Numpad1 => "1", - Key::Numpad2 => "2", - Key::Numpad3 => "3", - Key::Numpad4 => "4", - Key::Numpad5 => "5", - Key::Numpad6 => "6", - Key::Numpad7 => "7", - Key::Numpad8 => "8", - Key::Numpad9 => "9", + Key::Numpad0 => "KP_0", + Key::Numpad1 => "KP_1", + Key::Numpad2 => "KP_2", + Key::Numpad3 => "KP_3", + Key::Numpad4 => "KP_4", + Key::Numpad5 => "KP_5", + Key::Numpad6 => "KP_6", + Key::Numpad7 => "KP_7", + Key::Numpad8 => "KP_8", + Key::Numpad9 => "KP_9", Key::Decimal => "KP_Decimal", Key::Cancel => "Cancel", Key::Clear => "Clear", diff --git a/rust-toolchain.toml b/rust-toolchain.toml deleted file mode 100644 index 05dfa3270..000000000 --- a/rust-toolchain.toml +++ /dev/null @@ -1,2 +0,0 @@ -[toolchain] -channel = "1.62.0" From 1b0fb5132c2dc00a38ce43efe19029301756f575 Mon Sep 17 00:00:00 2001 From: Asura Date: Sat, 23 Jul 2022 20:51:01 +0800 Subject: [PATCH 34/57] Support switching keyboard mode by UI --- src/lang/cn.rs | 2 ++ src/ui/common.tis | 90 +++++++++++++++++++++++++++++++++++++++++++++++ src/ui/header.tis | 31 ++++++++++++++++ src/ui/remote.rs | 17 ++++++--- 4 files changed, 136 insertions(+), 4 deletions(-) diff --git a/src/lang/cn.rs b/src/lang/cn.rs index 6e3d4d067..c1ee5d305 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -300,5 +300,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Activate onetime password", "激活一次性访问功能"), ("Set security password", "设置安全密码"), ("Connection not allowed", "对方不允许连接"), + ("Legacy mode", "传统模式"), + ("Map mode", "1:1传输"), ].iter().cloned().collect(); } diff --git a/src/ui/common.tis b/src/ui/common.tis index aae950c2d..8a0beef98 100644 --- a/src/ui/common.tis +++ b/src/ui/common.tis @@ -155,6 +155,96 @@ var svg_send = var svg_chat = ; +var svg_keyboard = + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +; function scrollToBottom(el) { var y = el.box(#height, #content) - el.box(#height, #client); diff --git a/src/ui/header.tis b/src/ui/header.tis index 35a132c90..8cce3e18a 100644 --- a/src/ui/header.tis +++ b/src/ui/header.tis @@ -139,11 +139,22 @@ class Header: Reactor.Component { {svg_chat} {svg_action} {svg_display} + {svg_keyboard} + {this.renderKeyboardPop()} {this.renderDisplayPop()} {this.renderActionPop()} ; } + function renderKeyboardPop(){ + return + +
  • {svg_checkmark}{translate('Legacy mode')}
  • +
  • {svg_checkmark}{translate('Map mode')}
  • + +
    ; + } + function renderDisplayPop() { return @@ -252,6 +263,11 @@ class Header: Reactor.Component { me.popup(menu); } + event click $(#keyboard) (_, me) { + var menu = $(menu#keyboard-options); + me.popup(menu); + } + event click $(#screen) (_, me) { if (pi.current_display == me.index) return; handler.switch_display(me.index); @@ -332,6 +348,16 @@ class Header: Reactor.Component { toggleMenuState(); } } + + event click $(menu#keyboard-options>li) (_, me) { + stdout.println(me.id); + if (me.id == "legacy") { + handler.save_keyboard_mode("legacy"); + } else if (me.id == "map") { + handler.save_keyboard_mode("map"); + } + toggleMenuState() + } } function handle_custom_image_quality() { @@ -355,9 +381,14 @@ function toggleMenuState() { var s = handler.get_view_style(); if (!s) s = "original"; values.push(s); + var k = handler.get_keyboard_mode(); + values.push(k); for (var el in $$(menu#display-options>li)) { el.attributes.toggleClass("selected", values.indexOf(el.id) >= 0); } + for (var el in $$(menu#keyboard-options>li)) { + el.attributes.toggleClass("selected", values.indexOf(el.id) >= 0); + } for (var id in ["show-remote-cursor", "show-quality-monitor", "disable-audio", "enable-file-transfer", "disable-clipboard", "lock-after-session-end"]) { var el = self.select('#' + id); if (el) { diff --git a/src/ui/remote.rs b/src/ui/remote.rs index ef14ef42e..f68d76e1b 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -233,6 +233,8 @@ impl sciter::EventHandler for Handler { fn get_remember(); fn peer_platform(); fn set_write_override(i32, i32, bool, bool, bool); + fn get_keyboard_mode(); + fn save_keyboard_mode(String); } } @@ -347,6 +349,16 @@ impl Handler { return self.lc.read().unwrap().image_quality.clone(); } + fn get_keyboard_mode(&mut self) -> String { + return std::env::var("KEYBOARD_MODE") + .unwrap_or(String::from("legacy")) + .to_lowercase(); + } + + fn save_keyboard_mode(&mut self, value: String) { + std::env::set_var("KEYBOARD_MODE", value); + } + fn get_custom_image_quality(&mut self) -> Value { let mut v = Value::array(0); for x in self.lc.read().unwrap().custom_image_quality.iter() { @@ -1273,10 +1285,7 @@ impl Handler { fn key_down_or_up(&mut self, down_or_up: bool, key: RdevKey, evt: Event) { // Call different functions according to keyboard mode. - let mode = match std::env::var("KEYBOARD_MODE") - .unwrap_or(String::from("legacy")).to_lowercase() - .as_str() - { + let mode = match self.get_keyboard_mode().as_str() { "map" => KeyboardMode::Map, "legacy" => KeyboardMode::Legacy, _ => KeyboardMode::Legacy, From b3b97ee69a62ca4471699f387a89550d3359e73d Mon Sep 17 00:00:00 2001 From: Asura Date: Sat, 23 Jul 2022 21:45:00 +0800 Subject: [PATCH 35/57] Remove log info --- libs/enigo/src/linux/pynput.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/enigo/src/linux/pynput.rs b/libs/enigo/src/linux/pynput.rs index 7868b7f6f..836c645fe 100644 --- a/libs/enigo/src/linux/pynput.rs +++ b/libs/enigo/src/linux/pynput.rs @@ -110,7 +110,6 @@ impl EnigoPynput { return true; } }; - log::info!("send pynput: {:?}", &s); return self.tx.send((PyMsg::Str(s), is_press)).is_ok(); } } From 1caee4e30678ba6d784689920ecd83ed2af3293a Mon Sep 17 00:00:00 2001 From: Asura Date: Sat, 23 Jul 2022 08:20:39 -0700 Subject: [PATCH 36/57] Sync CapsLock and NumLock status in legacy mode. --- libs/enigo/src/linux/nix_impl.rs | 10 ++----- src/server/input_service.rs | 47 ++++++++++++++++++++------------ src/ui/header.tis | 1 - src/ui/remote.rs | 2 +- 4 files changed, 34 insertions(+), 26 deletions(-) diff --git a/libs/enigo/src/linux/nix_impl.rs b/libs/enigo/src/linux/nix_impl.rs index 840290b2b..c660bd08c 100644 --- a/libs/enigo/src/linux/nix_impl.rs +++ b/libs/enigo/src/linux/nix_impl.rs @@ -156,6 +156,7 @@ impl KeyboardControllable for Enigo { } fn key_up(&mut self, key: Key) { if self.is_x11 { + dbg!(key); if self.pynput.send_pynput(&key, false) { return; } @@ -167,12 +168,7 @@ impl KeyboardControllable for Enigo { } } fn key_click(&mut self, key: Key) { - if self.is_x11 { - self.xdo.key_click(key) - } else { - if let Some(keyboard) = &mut self.uinput_keyboard { - keyboard.key_click(key) - } - } + self.key_down(key).ok(); + self.key_up(key); } } diff --git a/src/server/input_service.rs b/src/server/input_service.rs index 01b049ddb..d8d4287fc 100644 --- a/src/server/input_service.rs +++ b/src/server/input_service.rs @@ -146,7 +146,8 @@ fn run_cursor(sp: MouseCursorService, state: &mut StateCursor) -> ResultType<()> msg = cached.clone(); } else { let mut data = crate::get_cursor_data(hcursor)?; - data.colors = hbb_common::compress::compress(&data.colors[..], COMPRESS_LEVEL).into(); + data.colors = + hbb_common::compress::compress(&data.colors[..], COMPRESS_LEVEL).into(); let mut tmp = Message::new(); tmp.set_cursor_data(data); msg = Arc::new(tmp); @@ -467,7 +468,7 @@ pub async fn lock_screen() { // loginctl lock-session also not work, they both work run rustdesk from cmd std::thread::spawn(|| { let mut key_event = KeyEvent::new(); - + key_event.set_chr('l' as _); key_event.modifiers.push(ControlKey::Meta.into()); key_event.mode = KeyboardMode::Legacy.into(); @@ -482,7 +483,7 @@ pub async fn lock_screen() { // CGSession -suspend not real lock screen, it is user switch std::thread::spawn(|| { let mut key_event = KeyEvent::new(); - + key_event.set_chr('q' as _); key_event.modifiers.push(ControlKey::Meta.into()); key_event.modifiers.push(ControlKey::Control.into()); @@ -621,7 +622,12 @@ fn rdev_key_down_or_up(key: RdevKey, down_or_up: bool) { std::thread::sleep(delay); } -fn sync_status(evt: &KeyEvent) { +fn rdev_key_click(key: RdevKey) { + rdev_key_down_or_up(key, true); + rdev_key_down_or_up(key, false); +} + +fn sync_status(evt: &KeyEvent) -> (bool, bool) { let mut en = ENIGO.lock().unwrap(); // remote caps status @@ -637,31 +643,38 @@ fn sync_status(evt: &KeyEvent) { .position(|&r| r == ControlKey::NumLock.into()) .is_some(); - if (caps_locking && !en.get_key_state(enigo::Key::CapsLock)) - || (!caps_locking && en.get_key_state(enigo::Key::CapsLock)) - { - rdev_key_down_or_up(RdevKey::CapsLock, true); - rdev_key_down_or_up(RdevKey::CapsLock, false); - }; - if (num_locking && !en.get_key_state(enigo::Key::NumLock)) - || (!num_locking && en.get_key_state(enigo::Key::NumLock)) - { - rdev_key_down_or_up(RdevKey::NumLock, true); - rdev_key_down_or_up(RdevKey::NumLock, false); - }; + let click_capslock = (caps_locking && !en.get_key_state(enigo::Key::CapsLock)) + || (!caps_locking && en.get_key_state(enigo::Key::CapsLock)); + let click_numlock = (num_locking && !en.get_key_state(enigo::Key::NumLock)) + || (!num_locking && en.get_key_state(enigo::Key::NumLock)); + return (click_capslock, click_numlock); } fn map_keyboard_map(evt: &KeyEvent) { // map mode(1): Send keycode according to the peer platform. - sync_status(evt); + let (click_capslock, click_numlock) = sync_status(evt); + if click_capslock { + rdev_key_click(RdevKey::CapsLock); + } + if click_numlock { + rdev_key_click(RdevKey::NumLock); + } rdev_key_down_or_up(RdevKey::Unknown(evt.chr()), evt.down); return; } fn legacy_keyboard_map(evt: &KeyEvent) { + let (click_capslock, click_numlock) = sync_status(evt); + #[cfg(windows)] crate::platform::windows::try_change_desktop(); let mut en = ENIGO.lock().unwrap(); + if click_capslock { + en.key_click(Key::CapsLock); + } + if click_numlock { + en.key_click(Key::NumLock); + } // disable numlock if press home etc when numlock is on, // because we will get numpad value (7,8,9 etc) if not #[cfg(windows)] diff --git a/src/ui/header.tis b/src/ui/header.tis index 0ef473124..def2ab9f7 100644 --- a/src/ui/header.tis +++ b/src/ui/header.tis @@ -363,7 +363,6 @@ class Header: Reactor.Component { } event click $(menu#keyboard-options>li) (_, me) { - stdout.println(me.id); if (me.id == "legacy") { handler.save_keyboard_mode("legacy"); } else if (me.id == "map") { diff --git a/src/ui/remote.rs b/src/ui/remote.rs index 69153bedc..9338b90d4 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -1105,7 +1105,7 @@ impl Handler { key_event.modifiers.push(ControlKey::CapsLock.into()); } if self.peer_platform() != "Mac OS" { - if get_key_state(enigo::Key::NumLock) && common::valid_for_numlock(&key_event) { + if get_key_state(enigo::Key::NumLock) { key_event.modifiers.push(ControlKey::NumLock.into()); } } From 6a3d527f93af7ff5173de9e3fdd9b1ee9556d80d Mon Sep 17 00:00:00 2001 From: Asura Date: Mon, 25 Jul 2022 19:30:26 -0700 Subject: [PATCH 37/57] Refactor: function name --- src/server/input_service.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/server/input_service.rs b/src/server/input_service.rs index d8d4287fc..c350e8d04 100644 --- a/src/server/input_service.rs +++ b/src/server/input_service.rs @@ -615,7 +615,7 @@ fn rdev_key_down_or_up(key: RdevKey, down_or_up: bool) { match simulate(&event_type) { Ok(()) => (), Err(_simulate_error) => { - println!("We could not send {:?}", &event_type); + log::error!("Could not send {:?}", &event_type); } } // Let ths OS catchup (at least MacOS) @@ -650,7 +650,7 @@ fn sync_status(evt: &KeyEvent) -> (bool, bool) { return (click_capslock, click_numlock); } -fn map_keyboard_map(evt: &KeyEvent) { +fn map_keyboard_mode(evt: &KeyEvent) { // map mode(1): Send keycode according to the peer platform. let (click_capslock, click_numlock) = sync_status(evt); if click_capslock { @@ -663,7 +663,7 @@ fn map_keyboard_map(evt: &KeyEvent) { return; } -fn legacy_keyboard_map(evt: &KeyEvent) { +fn legacy_keyboard_mode(evt: &KeyEvent) { let (click_capslock, click_numlock) = sync_status(evt); #[cfg(windows)] @@ -819,6 +819,7 @@ fn legacy_keyboard_map(evt: &KeyEvent) { } } + fn handle_key_(evt: &KeyEvent) { if EXITING.load(Ordering::SeqCst) { return; @@ -826,13 +827,13 @@ fn handle_key_(evt: &KeyEvent) { match evt.mode.unwrap() { KeyboardMode::Legacy => { - legacy_keyboard_map(evt); + legacy_keyboard_mode(evt); } KeyboardMode::Map => { - map_keyboard_map(evt); + map_keyboard_mode(evt); } _ => { - legacy_keyboard_map(evt); + legacy_keyboard_mode(evt); } } } From d08931c3171f5695e3f58d18eafc15260df1e1d5 Mon Sep 17 00:00:00 2001 From: Asura Date: Wed, 27 Jul 2022 07:36:50 -0700 Subject: [PATCH 38/57] Doc: update lang for keyboard mode --- src/lang/cs.rs | 2 ++ src/lang/da.rs | 2 ++ src/lang/de.rs | 2 ++ src/lang/eo.rs | 2 ++ src/lang/es.rs | 2 ++ src/lang/fr.rs | 2 ++ src/lang/hu.rs | 2 ++ src/lang/id.rs | 2 ++ src/lang/it.rs | 2 ++ src/lang/ptbr.rs | 2 ++ src/lang/ru.rs | 2 ++ src/lang/sk.rs | 2 ++ src/lang/template.rs | 2 ++ src/lang/tr.rs | 2 ++ src/lang/tw.rs | 2 ++ 15 files changed, 30 insertions(+) diff --git a/src/lang/cs.rs b/src/lang/cs.rs index d9ff10416..bb5304aa6 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -300,5 +300,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Activate onetime password", ""), ("Set security password", ""), ("Connection not allowed", ""), + ("Legacy mode", ""), + ("Map mode", ""), ].iter().cloned().collect(); } diff --git a/src/lang/da.rs b/src/lang/da.rs index f9776e687..4a4310ae0 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -300,5 +300,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Activate onetime password", ""), ("Set security password", ""), ("Connection not allowed", ""), + ("Legacy mode", ""), + ("Map mode", ""), ].iter().cloned().collect(); } diff --git a/src/lang/de.rs b/src/lang/de.rs index 671bcae98..c64bdec3d 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -300,5 +300,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Activate onetime password", "Einmal-Passwort aktivieren"), ("Set security password", "Sicheres Passwort setzen"), ("Connection not allowed", "Verbindung abgelehnt"), + ("Legacy mode", ""), + ("Map mode", ""), ].iter().cloned().collect(); } diff --git a/src/lang/eo.rs b/src/lang/eo.rs index a21833559..bd4d4bdc0 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -300,5 +300,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Activate onetime password", ""), ("Set security password", ""), ("Connection not allowed", ""), + ("Legacy mode", ""), + ("Map mode", ""), ].iter().cloned().collect(); } diff --git a/src/lang/es.rs b/src/lang/es.rs index 14ba0ab57..fe627713c 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -300,5 +300,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Activate onetime password", ""), ("Set security password", ""), ("Connection not allowed", ""), + ("Legacy mode", ""), + ("Map mode", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fr.rs b/src/lang/fr.rs index f387b550b..1142f85a8 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -300,5 +300,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Activate onetime password", ""), ("Set security password", ""), ("Connection not allowed", ""), + ("Legacy mode", ""), + ("Map mode", ""), ].iter().cloned().collect(); } diff --git a/src/lang/hu.rs b/src/lang/hu.rs index e35ab8195..b95dce235 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -300,5 +300,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Activate onetime password", ""), ("Set security password", ""), ("Connection not allowed", ""), + ("Legacy mode", ""), + ("Map mode", ""), ].iter().cloned().collect(); } diff --git a/src/lang/id.rs b/src/lang/id.rs index 6bf69e476..e6fefe77d 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -300,5 +300,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Activate onetime password", ""), ("Set security password", ""), ("Connection not allowed", ""), + ("Legacy mode", ""), + ("Map mode", ""), ].iter().cloned().collect(); } diff --git a/src/lang/it.rs b/src/lang/it.rs index 778313d5b..8fa3b77bb 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -300,5 +300,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Activate onetime password", ""), ("Set security password", ""), ("Connection not allowed", ""), + ("Legacy mode", ""), + ("Map mode", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index 176833501..5d653550b 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -300,5 +300,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Activate onetime password", ""), ("Set security password", ""), ("Connection not allowed", ""), + ("Legacy mode", ""), + ("Map mode", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ru.rs b/src/lang/ru.rs index 55d33c7b3..edb31a7d1 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -300,5 +300,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Activate onetime password", "Активировать одноразовый пароль"), ("Set security password", "Задать пароль безопасности"), ("Connection not allowed", "Подключение не разрешено"), + ("Legacy mode", ""), + ("Map mode", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sk.rs b/src/lang/sk.rs index 332336007..f31c31d27 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -300,5 +300,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Activate onetime password", ""), ("Set security password", ""), ("Connection not allowed", ""), + ("Legacy mode", ""), + ("Map mode", ""), ].iter().cloned().collect(); } diff --git a/src/lang/template.rs b/src/lang/template.rs index 7b39a2876..a211ef398 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -300,5 +300,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Activate onetime password", ""), ("Set security password", ""), ("Connection not allowed", ""), + ("Legacy mode", ""), + ("Map mode", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tr.rs b/src/lang/tr.rs index 02468201e..f45622c1a 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -300,5 +300,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Activate onetime password", ""), ("Set security password", ""), ("Connection not allowed", ""), + ("Legacy mode", ""), + ("Map mode", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tw.rs b/src/lang/tw.rs index ea94d159c..0e7d0d573 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -300,5 +300,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Activate onetime password", "激活一次性訪問功能"), ("Set security password", "設置安全密碼"), ("Connection not allowed", "對方不允許連接"), + ("Legacy mode", "傳統模式"), + ("Map mode", "1:1傳輸"), ].iter().cloned().collect(); } From d5ac305e5717cf2144228ca1962b23d35cab14f2 Mon Sep 17 00:00:00 2001 From: Asura Date: Thu, 28 Jul 2022 11:00:01 +0800 Subject: [PATCH 39/57] Add translate mode in remote --- Cargo.lock | 110 +++++++++++++++++++++++++++++++---------------- src/ui/remote.rs | 41 ++++++++++++++++-- 2 files changed, 112 insertions(+), 39 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ecbf1646f..833cbe12a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -638,21 +638,6 @@ dependencies = [ "cc", ] -[[package]] -name = "cocoa" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "667fdc068627a2816b9ff831201dd9864249d6ee8d190b9532357f1fc0f61ea7" -dependencies = [ - "bitflags", - "block", - "core-foundation 0.9.3", - "core-graphics 0.21.0", - "foreign-types", - "libc", - "objc", -] - [[package]] name = "cocoa" version = "0.24.0" @@ -770,18 +755,6 @@ dependencies = [ "libc", ] -[[package]] -name = "core-graphics" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52a67c4378cf203eace8fb6567847eb641fd6ff933c1145a115c6ee820ebb978" -dependencies = [ - "bitflags", - "core-foundation 0.9.3", - "foreign-types", - "libc", -] - [[package]] name = "core-graphics" version = "0.22.3" @@ -1336,6 +1309,16 @@ dependencies = [ "termcolor", ] +[[package]] +name = "epoll" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20df693c700404f7e19d4d6fae6b15215d2913c27955d2b9d6f2c0f537511cd0" +dependencies = [ + "bitflags", + "libc", +] + [[package]] name = "err-derive" version = "0.3.1" @@ -1370,6 +1353,29 @@ dependencies = [ "nix 0.23.1", ] +[[package]] +name = "evdev-rs" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7db51abf6b3205a6e6e8dd68d7a5414d7c50d61736a6f4c9b97df86ef5567cf" +dependencies = [ + "bitflags", + "evdev-sys", + "libc", + "log", +] + +[[package]] +name = "evdev-sys" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14ead42b547b15d47089c1243d907bcf0eb94e457046d3b315a26ac9c9e9ea6d" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + [[package]] name = "event-listener" version = "2.5.2" @@ -2342,6 +2348,28 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "inotify" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abf888f9575c290197b2c948dc9e9ff10bd1a39ad1ea8585f734585fa6b9d3f9" +dependencies = [ + "bitflags", + "futures-core", + "inotify-sys", + "libc", + "tokio", +] + +[[package]] +name = "inotify-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" +dependencies = [ + "libc", +] + [[package]] name = "instant" version = "0.1.12" @@ -3767,15 +3795,19 @@ dependencies = [ [[package]] name = "rdev" version = "0.5.0-2" -source = "git+https://github.com/asur4s/rdev#548d1194dd6863ab004d59299b995eb64cf21c3d" +source = "git+https://github.com/asur4s/rdev#c3a896bcb4a10d171dee1aa685c90abadf8946d2" dependencies = [ - "cocoa 0.22.0", - "core-foundation 0.7.0", - "core-foundation-sys 0.7.0", - "core-graphics 0.19.2", + "cocoa", + "core-foundation 0.9.3", + "core-foundation-sys 0.8.3", + "core-graphics 0.22.3", "enum-map", + "epoll", + "evdev-rs", + "inotify", "lazy_static", "libc", + "widestring 1.0.2", "winapi 0.3.9", "x11", ] @@ -3994,7 +4026,7 @@ dependencies = [ "cfg-if 1.0.0", "clap 3.2.12", "clipboard", - "cocoa 0.24.0", + "cocoa", "core-foundation 0.9.3", "core-graphics 0.22.3", "cpal", @@ -4936,7 +4968,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76863575f7842ed64fda361f417a787efa82811b4617267709066969cd4ccf3b" dependencies = [ - "cocoa 0.24.0", + "cocoa", "core-graphics 0.22.3", "gtk", "libappindicator", @@ -5348,6 +5380,12 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c" +[[package]] +name = "widestring" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8" + [[package]] name = "winapi" version = "0.2.8" @@ -5421,7 +5459,7 @@ checksum = "0c643e10139d127d30d6d753398c8a6f0a43532e8370f6c9d29ebbff29b984ab" dependencies = [ "bitflags", "err-derive", - "widestring", + "widestring 0.4.3", "winapi 0.3.9", ] @@ -5548,7 +5586,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b43cc931d58b99461188607efd7acb2a093e65fc621f54cad78517a6063e73a" dependencies = [ "bitflags", - "cocoa 0.24.0", + "cocoa", "core-foundation 0.9.3", "core-graphics 0.22.3", "core-video-sys", diff --git a/src/ui/remote.rs b/src/ui/remote.rs index 9338b90d4..1b5331609 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -1065,9 +1065,40 @@ impl Handler { self.send_key_event(key_event, KeyboardMode::Map); } - // fn translate_keyboard_mode(&mut self, down_or_up: bool, key: RdevKey) { - // // translate mode(2): locally generated characters are send to the peer. - // } + fn translate_keyboard_mode(&mut self, down_or_up: bool, key: RdevKey, evt: Event) { + // translate mode(2): locally generated characters are send to the peer. + let string = evt.name.unwrap_or_default(); + + let chars = if string == "" { + None + } else { + let chars: Vec = string.chars().collect(); + Some(chars) + }; + + if let Some(chars) = chars { + for chr in chars { + dbg!(chr); + + let mut key_event = KeyEvent::new(); + key_event.set_chr(chr as _); + key_event.down = true; + self.send_key_event(key_event, KeyboardMode::Translate); + + let mut key_event = KeyEvent::new(); + key_event.set_chr(chr as _); + key_event.down = false; + self.send_key_event(key_event, KeyboardMode::Translate); + } + } else { + if down_or_up == true { + TO_RELEASE.lock().unwrap().insert(key); + } else { + TO_RELEASE.lock().unwrap().remove(&key); + } + self.map_keyboard_mode(down_or_up, key); + } + } fn legacy_modifiers( &self, @@ -1327,6 +1358,7 @@ impl Handler { let mode = match self.get_keyboard_mode().as_str() { "map" => KeyboardMode::Map, "legacy" => KeyboardMode::Legacy, + "translate" => KeyboardMode::Translate, _ => KeyboardMode::Legacy, }; @@ -1340,6 +1372,9 @@ impl Handler { self.map_keyboard_mode(down_or_up, key); } KeyboardMode::Legacy => self.legacy_keyboard_mode(down_or_up, key, evt), + KeyboardMode::Translate => { + self.translate_keyboard_mode(down_or_up, key, evt); + } _ => self.legacy_keyboard_mode(down_or_up, key, evt), } } From 25525cda3f2ee4a05e63f41c602a41c41092bddc Mon Sep 17 00:00:00 2001 From: Asura Date: Wed, 27 Jul 2022 20:01:42 -0700 Subject: [PATCH 40/57] Add translte mode in input_service --- Cargo.lock | 110 +++++++++++++++++++++---------- libs/enigo/src/linux/nix_impl.rs | 1 - src/server/input_service.rs | 8 +++ 3 files changed, 82 insertions(+), 37 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ecbf1646f..833cbe12a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -638,21 +638,6 @@ dependencies = [ "cc", ] -[[package]] -name = "cocoa" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "667fdc068627a2816b9ff831201dd9864249d6ee8d190b9532357f1fc0f61ea7" -dependencies = [ - "bitflags", - "block", - "core-foundation 0.9.3", - "core-graphics 0.21.0", - "foreign-types", - "libc", - "objc", -] - [[package]] name = "cocoa" version = "0.24.0" @@ -770,18 +755,6 @@ dependencies = [ "libc", ] -[[package]] -name = "core-graphics" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52a67c4378cf203eace8fb6567847eb641fd6ff933c1145a115c6ee820ebb978" -dependencies = [ - "bitflags", - "core-foundation 0.9.3", - "foreign-types", - "libc", -] - [[package]] name = "core-graphics" version = "0.22.3" @@ -1336,6 +1309,16 @@ dependencies = [ "termcolor", ] +[[package]] +name = "epoll" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20df693c700404f7e19d4d6fae6b15215d2913c27955d2b9d6f2c0f537511cd0" +dependencies = [ + "bitflags", + "libc", +] + [[package]] name = "err-derive" version = "0.3.1" @@ -1370,6 +1353,29 @@ dependencies = [ "nix 0.23.1", ] +[[package]] +name = "evdev-rs" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7db51abf6b3205a6e6e8dd68d7a5414d7c50d61736a6f4c9b97df86ef5567cf" +dependencies = [ + "bitflags", + "evdev-sys", + "libc", + "log", +] + +[[package]] +name = "evdev-sys" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14ead42b547b15d47089c1243d907bcf0eb94e457046d3b315a26ac9c9e9ea6d" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + [[package]] name = "event-listener" version = "2.5.2" @@ -2342,6 +2348,28 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "inotify" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abf888f9575c290197b2c948dc9e9ff10bd1a39ad1ea8585f734585fa6b9d3f9" +dependencies = [ + "bitflags", + "futures-core", + "inotify-sys", + "libc", + "tokio", +] + +[[package]] +name = "inotify-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" +dependencies = [ + "libc", +] + [[package]] name = "instant" version = "0.1.12" @@ -3767,15 +3795,19 @@ dependencies = [ [[package]] name = "rdev" version = "0.5.0-2" -source = "git+https://github.com/asur4s/rdev#548d1194dd6863ab004d59299b995eb64cf21c3d" +source = "git+https://github.com/asur4s/rdev#c3a896bcb4a10d171dee1aa685c90abadf8946d2" dependencies = [ - "cocoa 0.22.0", - "core-foundation 0.7.0", - "core-foundation-sys 0.7.0", - "core-graphics 0.19.2", + "cocoa", + "core-foundation 0.9.3", + "core-foundation-sys 0.8.3", + "core-graphics 0.22.3", "enum-map", + "epoll", + "evdev-rs", + "inotify", "lazy_static", "libc", + "widestring 1.0.2", "winapi 0.3.9", "x11", ] @@ -3994,7 +4026,7 @@ dependencies = [ "cfg-if 1.0.0", "clap 3.2.12", "clipboard", - "cocoa 0.24.0", + "cocoa", "core-foundation 0.9.3", "core-graphics 0.22.3", "cpal", @@ -4936,7 +4968,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76863575f7842ed64fda361f417a787efa82811b4617267709066969cd4ccf3b" dependencies = [ - "cocoa 0.24.0", + "cocoa", "core-graphics 0.22.3", "gtk", "libappindicator", @@ -5348,6 +5380,12 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c" +[[package]] +name = "widestring" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8" + [[package]] name = "winapi" version = "0.2.8" @@ -5421,7 +5459,7 @@ checksum = "0c643e10139d127d30d6d753398c8a6f0a43532e8370f6c9d29ebbff29b984ab" dependencies = [ "bitflags", "err-derive", - "widestring", + "widestring 0.4.3", "winapi 0.3.9", ] @@ -5548,7 +5586,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b43cc931d58b99461188607efd7acb2a093e65fc621f54cad78517a6063e73a" dependencies = [ "bitflags", - "cocoa 0.24.0", + "cocoa", "core-foundation 0.9.3", "core-graphics 0.22.3", "core-video-sys", diff --git a/libs/enigo/src/linux/nix_impl.rs b/libs/enigo/src/linux/nix_impl.rs index c660bd08c..7a8f6668e 100644 --- a/libs/enigo/src/linux/nix_impl.rs +++ b/libs/enigo/src/linux/nix_impl.rs @@ -156,7 +156,6 @@ impl KeyboardControllable for Enigo { } fn key_up(&mut self, key: Key) { if self.is_x11 { - dbg!(key); if self.pynput.send_pynput(&key, false) { return; } diff --git a/src/server/input_service.rs b/src/server/input_service.rs index c350e8d04..629ed17e4 100644 --- a/src/server/input_service.rs +++ b/src/server/input_service.rs @@ -819,6 +819,11 @@ fn legacy_keyboard_mode(evt: &KeyEvent) { } } +fn translate_keyboard_mode(evt: &KeyEvent) { + dbg!(evt.chr()); + let chr = char::from_u32(evt.chr()).unwrap_or_default(); + rdev::simulate_char(chr, evt.down); +} fn handle_key_(evt: &KeyEvent) { if EXITING.load(Ordering::SeqCst) { @@ -832,6 +837,9 @@ fn handle_key_(evt: &KeyEvent) { KeyboardMode::Map => { map_keyboard_mode(evt); } + KeyboardMode::Translate => { + translate_keyboard_mode(evt); + } _ => { legacy_keyboard_mode(evt); } From 92c4ee15608d2b6eea0e7c6b1159ddee2f124989 Mon Sep 17 00:00:00 2001 From: Asura Date: Mon, 1 Aug 2022 00:52:07 +0800 Subject: [PATCH 41/57] Fix character generation, altgr only takes effect locally --- Cargo.lock | 2 +- src/ui/remote.rs | 41 ++++++++++++++++++++++++++++++++--------- 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 833cbe12a..9d807f12e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3795,7 +3795,7 @@ dependencies = [ [[package]] name = "rdev" version = "0.5.0-2" -source = "git+https://github.com/asur4s/rdev#c3a896bcb4a10d171dee1aa685c90abadf8946d2" +source = "git+https://github.com/asur4s/rdev#d009906ba983f26c7b6f6f1a5e3c76bf43164294" dependencies = [ "cocoa", "core-foundation 0.9.3", diff --git a/src/ui/remote.rs b/src/ui/remote.rs index 1b5331609..213158bfc 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -43,7 +43,7 @@ use hbb_common::{ Stream, }; use hbb_common::{config::TransferSerde, fs::TransferJobMeta}; -use rdev::{Event, EventType::*, Key as RdevKey}; +use rdev::{Event, EventType::*, Key as RdevKey, Keyboard as RdevKeyboard, KeyboardState}; #[cfg(windows)] use crate::clipboard_file::*; @@ -58,6 +58,7 @@ lazy_static::lazy_static! { static ref ENIGO: Arc> = Arc::new(Mutex::new(Enigo::new())); static ref VIDEO: Arc>> = Default::default(); static ref TO_RELEASE: Arc>> = Arc::new(Mutex::new(HashSet::::new())); + static ref KEYBOARD: Arc> = Arc::new(Mutex::new(RdevKeyboard::new().unwrap())); } fn get_key_state(key: enigo::Key) -> bool { @@ -333,9 +334,6 @@ impl Handler { _ => return, }; - #[cfg(target_os = "windows")] - let _key = rdev::get_win_key(evt.code.into(), evt.scan_code); - me.key_down_or_up(down, _key, evt); }; if let Err(error) = rdev::listen(func) { @@ -785,7 +783,7 @@ impl Handler { fn leave(&mut self) { for key in TO_RELEASE.lock().unwrap().iter() { - self.map_keyboard_mode(false, *key) + self.map_keyboard_mode(false, *key, None) } #[cfg(windows)] crate::platform::windows::stop_system_key_propagate(false); @@ -1036,8 +1034,15 @@ impl Handler { } } - fn map_keyboard_mode(&mut self, down_or_up: bool, key: RdevKey) { + fn map_keyboard_mode(&mut self, down_or_up: bool, key: RdevKey, evt: Option) { // map mode(1): Send keycode according to the peer platform. + #[cfg(target_os = "windows")] + let key = if let Some(e) = evt { + rdev::get_win_key(e.code.into(), e.scan_code) + } else { + key + }; + let peer = self.peer_platform(); let mut key_event = KeyEvent::new(); @@ -1067,8 +1072,20 @@ impl Handler { fn translate_keyboard_mode(&mut self, down_or_up: bool, key: RdevKey, evt: Event) { // translate mode(2): locally generated characters are send to the peer. - let string = evt.name.unwrap_or_default(); + // get char + let string = match KEYBOARD.lock() { + Ok(mut keyboard) => { + let string = keyboard.add(&evt.event_type).unwrap_or_default(); + if keyboard.last_is_dead && string == "" { + return; + } + string + } + Err(_) => "".to_owned(), + }; + + // maybe two string let chars = if string == "" { None } else { @@ -1096,7 +1113,13 @@ impl Handler { } else { TO_RELEASE.lock().unwrap().remove(&key); } - self.map_keyboard_mode(down_or_up, key); + // algr without action + // Control left + if key == RdevKey::AltGr || evt.scan_code == 541 { + return; + } + dbg!(key); + self.map_keyboard_mode(down_or_up, key, None); } } @@ -1369,7 +1392,7 @@ impl Handler { } else { TO_RELEASE.lock().unwrap().remove(&key); } - self.map_keyboard_mode(down_or_up, key); + self.map_keyboard_mode(down_or_up, key, Some(evt)); } KeyboardMode::Legacy => self.legacy_keyboard_mode(down_or_up, key, evt), KeyboardMode::Translate => { From 7775a14c9e9ad7e231b317372f6830e20b714902 Mon Sep 17 00:00:00 2001 From: Asura Date: Tue, 2 Aug 2022 03:47:29 -0700 Subject: [PATCH 42/57] Use keycode mapping table --- Cargo.lock | 11 +++++++++++ Cargo.toml | 3 +++ src/server/input_service.rs | 9 +++++++-- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 833cbe12a..e341ff459 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4053,6 +4053,7 @@ dependencies = [ "mouce", "num_cpus", "objc", + "once_cell", "parity-tokio-ipc", "rdev", "repng", @@ -4071,6 +4072,7 @@ dependencies = [ "simple_rc", "sys-locale", "sysinfo", + "tfc", "tray-item", "trayicon", "uuid", @@ -4755,6 +4757,15 @@ version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" +[[package]] +name = "tfc" +version = "0.6.1" +source = "git+https://github.com/asur4s/The-Fat-Controller#35ed0bc8dd8516bdb99e45ebfc94409637a92c6b" +dependencies = [ + "core-graphics 0.22.3", + "unicode-segmentation", +] + [[package]] name = "thiserror" version = "1.0.31" diff --git a/Cargo.toml b/Cargo.toml index 825f0d739..20ec129ef 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -73,6 +73,8 @@ sys-locale = "0.2" enigo = { path = "libs/enigo", features = [ "with_serde" ] } clipboard = { path = "libs/clipboard" } rdev = { git = "https://github.com/asur4s/rdev" } +tfc = { git = "https://github.com/asur4s/The-Fat-Controller" } +once_cell = "1.13.0" ctrlc = "3.2" arboard = "2.0" #minreq = { version = "2.4", features = ["punycode", "https-native"] } @@ -103,6 +105,7 @@ async-process = "1.3" mouce = { git="https://github.com/fufesou/mouce.git" } evdev = { git="https://github.com/fufesou/evdev" } + [target.'cfg(target_os = "android")'.dependencies] android_logger = "0.11" jni = "0.19" diff --git a/src/server/input_service.rs b/src/server/input_service.rs index 629ed17e4..e3ac41a59 100644 --- a/src/server/input_service.rs +++ b/src/server/input_service.rs @@ -9,6 +9,7 @@ use std::{ sync::atomic::{AtomicBool, Ordering}, time::Instant, }; +use tfc::{traits::*, Context}; #[derive(Default)] struct StateCursor { @@ -179,6 +180,7 @@ lazy_static::lazy_static! { }; static ref KEYS_DOWN: Arc>> = Default::default(); static ref LATEST_INPUT: Arc> = Default::default(); + static ref KBD_CONTEXT: Mutex = Mutex::new(Context::new().expect("kbd context error")); } static EXITING: AtomicBool = AtomicBool::new(false); @@ -820,9 +822,12 @@ fn legacy_keyboard_mode(evt: &KeyEvent) { } fn translate_keyboard_mode(evt: &KeyEvent) { - dbg!(evt.chr()); let chr = char::from_u32(evt.chr()).unwrap_or_default(); - rdev::simulate_char(chr, evt.down); + if evt.down { + KBD_CONTEXT.lock().unwrap().unicode_char_down(chr).expect("unicode_char_down error"); + } else { + KBD_CONTEXT.lock().unwrap().unicode_char_up(chr).expect("unicode_char_up error"); + } } fn handle_key_(evt: &KeyEvent) { From 5dfc41a7b8c462f0d1e952098ef37e0186990bfd Mon Sep 17 00:00:00 2001 From: Asura Date: Tue, 2 Aug 2022 06:07:44 -0700 Subject: [PATCH 43/57] Ignore dead keys in Linux --- Cargo.lock | 2 +- src/ui/remote.rs | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7d4131d41..24418f0a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3795,7 +3795,7 @@ dependencies = [ [[package]] name = "rdev" version = "0.5.0-2" -source = "git+https://github.com/asur4s/rdev#d009906ba983f26c7b6f6f1a5e3c76bf43164294" +source = "git+https://github.com/asur4s/rdev#c1175a394d811473e87ea79cb9a511a0f9b71764" dependencies = [ "cocoa", "core-foundation 0.9.3", diff --git a/src/ui/remote.rs b/src/ui/remote.rs index 213158bfc..203a20614 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -1077,7 +1077,17 @@ impl Handler { let string = match KEYBOARD.lock() { Ok(mut keyboard) => { let string = keyboard.add(&evt.event_type).unwrap_or_default(); - if keyboard.last_is_dead && string == "" { + #[cfg(target_os = "windows")] + let is_dead = keyboard.last_is_dead; + #[cfg(target_os = "linux")] + let is_dead = unsafe { + CStr::from_ptr(XKeysymToString(*keyboard.keysym)) + .to_str() + .unwrap_or_default() + .to_owned() + .starts_with("dead") + }; + if is_dead && string == "" { return; } string From 90b36795ea7545254fdda34cfdfeb9c51d08bd61 Mon Sep 17 00:00:00 2001 From: Asura Date: Tue, 2 Aug 2022 10:48:56 -0700 Subject: [PATCH 44/57] Listening for char in Linux --- Cargo.lock | 5 +++-- src/ui/remote.rs | 12 +++--------- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 24418f0a5..af872e57d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3795,7 +3795,7 @@ dependencies = [ [[package]] name = "rdev" version = "0.5.0-2" -source = "git+https://github.com/asur4s/rdev#c1175a394d811473e87ea79cb9a511a0f9b71764" +source = "git+https://github.com/asur4s/rdev#d6499d2e582bf3549aa4ba33cfd3fbbdfce10947" dependencies = [ "cocoa", "core-foundation 0.9.3", @@ -4760,10 +4760,11 @@ checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" [[package]] name = "tfc" version = "0.6.1" -source = "git+https://github.com/asur4s/The-Fat-Controller#35ed0bc8dd8516bdb99e45ebfc94409637a92c6b" +source = "git+https://github.com/asur4s/The-Fat-Controller#6587681075fa312a0d69587721d1ff84d8fa2970" dependencies = [ "core-graphics 0.22.3", "unicode-segmentation", + "winapi 0.3.9", ] [[package]] diff --git a/src/ui/remote.rs b/src/ui/remote.rs index 203a20614..994cd04b2 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -1034,10 +1034,10 @@ impl Handler { } } - fn map_keyboard_mode(&mut self, down_or_up: bool, key: RdevKey, evt: Option) { + fn map_keyboard_mode(&mut self, down_or_up: bool, key: RdevKey, _evt: Option) { // map mode(1): Send keycode according to the peer platform. #[cfg(target_os = "windows")] - let key = if let Some(e) = evt { + let key = if let Some(e) = _evt { rdev::get_win_key(e.code.into(), e.scan_code) } else { key @@ -1080,13 +1080,7 @@ impl Handler { #[cfg(target_os = "windows")] let is_dead = keyboard.last_is_dead; #[cfg(target_os = "linux")] - let is_dead = unsafe { - CStr::from_ptr(XKeysymToString(*keyboard.keysym)) - .to_str() - .unwrap_or_default() - .to_owned() - .starts_with("dead") - }; + let is_dead = keyboard.is_dead(); if is_dead && string == "" { return; } From 0695d50b9f0317a314942d8e2593152b284a2b38 Mon Sep 17 00:00:00 2001 From: Asura Date: Tue, 2 Aug 2022 11:04:36 -0700 Subject: [PATCH 45/57] Fix Shift release failed --- src/ui/remote.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui/remote.rs b/src/ui/remote.rs index 994cd04b2..dad3e9ae0 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -1081,7 +1081,7 @@ impl Handler { let is_dead = keyboard.last_is_dead; #[cfg(target_os = "linux")] let is_dead = keyboard.is_dead(); - if is_dead && string == "" { + if is_dead && string == "" && down_or_up == true { return; } string From d0702ddfd90ce467fd12fee1a9fceafe50e9a7d5 Mon Sep 17 00:00:00 2001 From: Asura Date: Wed, 3 Aug 2022 14:34:05 +0800 Subject: [PATCH 46/57] Add translate mode in UI --- src/ui/header.tis | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ui/header.tis b/src/ui/header.tis index def2ab9f7..3d8510f80 100644 --- a/src/ui/header.tis +++ b/src/ui/header.tis @@ -151,6 +151,7 @@ class Header: Reactor.Component {
  • {svg_checkmark}{translate('Legacy mode')}
  • {svg_checkmark}{translate('Map mode')}
  • +
  • {svg_checkmark}{translate('Translate mode')}
  • ; } @@ -367,6 +368,8 @@ class Header: Reactor.Component { handler.save_keyboard_mode("legacy"); } else if (me.id == "map") { handler.save_keyboard_mode("map"); + } else if (me.id == "translate") { + handler.save_keyboard_mode("translate"); } toggleMenuState() } From b3b50829f53c4bb33a0cffacc08102224958549e Mon Sep 17 00:00:00 2001 From: Asura Date: Wed, 3 Aug 2022 14:52:08 +0800 Subject: [PATCH 47/57] Fix sycn of CapsLock --- src/server/input_service.rs | 5 +++++ src/ui/remote.rs | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/src/server/input_service.rs b/src/server/input_service.rs index e3ac41a59..0154da085 100644 --- a/src/server/input_service.rs +++ b/src/server/input_service.rs @@ -822,6 +822,11 @@ fn legacy_keyboard_mode(evt: &KeyEvent) { } fn translate_keyboard_mode(evt: &KeyEvent) { + // Caps affects the keycode map of the peer system(Linux). + let mut en = ENIGO.lock().unwrap(); + if en.get_key_state(Key::CapsLock){ + rdev_key_click(RdevKey::CapsLock); + } let chr = char::from_u32(evt.chr()).unwrap_or_default(); if evt.down { KBD_CONTEXT.lock().unwrap().unicode_char_down(chr).expect("unicode_char_down error"); diff --git a/src/ui/remote.rs b/src/ui/remote.rs index dad3e9ae0..6625c83fa 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -1122,6 +1122,10 @@ impl Handler { if key == RdevKey::AltGr || evt.scan_code == 541 { return; } + // Caps affects the keycode map of the peer system(Linux). + if key == RdevKey::CapsLock { + return; + } dbg!(key); self.map_keyboard_mode(down_or_up, key, None); } From 12129ebf3e5128838c4bc7e2c91429920ca171f9 Mon Sep 17 00:00:00 2001 From: Asura Date: Wed, 3 Aug 2022 15:33:16 +0800 Subject: [PATCH 48/57] Update dependencies --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index af872e57d..98623611b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4760,7 +4760,7 @@ checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" [[package]] name = "tfc" version = "0.6.1" -source = "git+https://github.com/asur4s/The-Fat-Controller#6587681075fa312a0d69587721d1ff84d8fa2970" +source = "git+https://github.com/asur4s/The-Fat-Controller#14d49063c8fc9a02c68c0dc842e8d6bb6c5e7713" dependencies = [ "core-graphics 0.22.3", "unicode-segmentation", From 05b157af455f09175f8fe2acf2aa7e222ff536bf Mon Sep 17 00:00:00 2001 From: Asura Date: Thu, 4 Aug 2022 17:26:06 +0800 Subject: [PATCH 49/57] Fix right ctrl #1166 --- src/server/connection.rs | 2 +- src/ui/cm.rs | 1 - src/ui/remote.rs | 7 ++++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/server/connection.rs b/src/server/connection.rs index f68c13895..90548afc7 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -6,7 +6,7 @@ use crate::common::update_clipboard; use crate::video_service; #[cfg(any(target_os = "android", target_os = "ios"))] use crate::{common::MOBILE_INFO2, mobile::connection_manager::start_channel}; -use crate::{ipc, VERSION}; +use crate::{ipc}; use hbb_common::{ config::Config, fs, diff --git a/src/ui/cm.rs b/src/ui/cm.rs index 38bfc9359..e2d912c63 100644 --- a/src/ui/cm.rs +++ b/src/ui/cm.rs @@ -1,5 +1,4 @@ use crate::ipc::{self, new_listener, Connection, Data}; -use crate::VERSION; #[cfg(windows)] use clipboard::{ create_cliprdr_context, empty_clipboard, get_rx_clip_client, server_clip_file, set_conn_enabled, diff --git a/src/ui/remote.rs b/src/ui/remote.rs index bccd6ad79..9bf125cc0 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -1189,7 +1189,7 @@ impl Handler { let alt = get_key_state(enigo::Key::Alt); #[cfg(windows)] let ctrl = { - let mut tmp = get_key_state(enigo::Key::Control); + let mut tmp = get_key_state(enigo::Key::Control) || get_key_state(enigo::Key::RightControl); unsafe { if IS_ALT_GR { if alt || key == RdevKey::AltGr { @@ -1204,8 +1204,8 @@ impl Handler { tmp }; #[cfg(not(windows))] - let ctrl = get_key_state(enigo::Key::Control); - let shift = get_key_state(enigo::Key::Shift); + let ctrl = get_key_state(enigo::Key::Control) || get_key_state(enigo::Key::RightControl); + let shift = get_key_state(enigo::Key::Shift) || get_key_state(enigo::Key::RightShift); #[cfg(windows)] let command = crate::platform::windows::get_win_key_state(); #[cfg(not(windows))] @@ -1389,6 +1389,7 @@ impl Handler { if down_or_up == true { key_event.down = true; } + dbg!(&key_event); self.send_key_event(key_event, KeyboardMode::Legacy) } From 2d0cdd83a27a83d47f57d2537e6b8a7b9bce0ac4 Mon Sep 17 00:00:00 2001 From: Asura Date: Thu, 4 Aug 2022 21:02:00 +0800 Subject: [PATCH 50/57] Update lang for keyboard mode --- src/lang/cn.rs | 1 + src/lang/cs.rs | 1 + src/lang/da.rs | 1 + src/lang/de.rs | 1 + src/lang/eo.rs | 1 + src/lang/es.rs | 1 + src/lang/fr.rs | 1 + src/lang/hu.rs | 1 + src/lang/id.rs | 1 + src/lang/it.rs | 1 + src/lang/ja.rs | 3 +++ src/lang/ptbr.rs | 1 + src/lang/ru.rs | 1 + src/lang/sk.rs | 1 + src/lang/template.rs | 1 + src/lang/tr.rs | 1 + src/lang/tw.rs | 1 + src/lang/vn.rs | 3 +++ 18 files changed, 22 insertions(+) diff --git a/src/lang/cn.rs b/src/lang/cn.rs index f433ab4d0..9a5a76250 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -290,6 +290,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Connection not allowed", "对方不允许连接"), ("Legacy mode", "传统模式"), ("Map mode", "1:1传输"), + ("Translate mode", "翻译模式"), ("Use temporary password", "使用临时密码"), ("Use permanent password", "使用固定密码"), ("Use both passwords", "同时使用两种密码"), diff --git a/src/lang/cs.rs b/src/lang/cs.rs index 6007c5de9..aa03e1d23 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -290,6 +290,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Connection not allowed", ""), ("Legacy mode", ""), ("Map mode", ""), + ("Translate mode", ""), ("Use temporary password", ""), ("Use permanent password", ""), ("Use both passwords", ""), diff --git a/src/lang/da.rs b/src/lang/da.rs index 0981d432e..364e552a3 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -290,6 +290,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Connection not allowed", ""), ("Legacy mode", ""), ("Map mode", ""), + ("Translate mode", ""), ("Use temporary password", ""), ("Use permanent password", ""), ("Use both passwords", ""), diff --git a/src/lang/de.rs b/src/lang/de.rs index f5c8bb2dd..f9558bed9 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -290,6 +290,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Connection not allowed", "Verbindung abgelehnt"), ("Legacy mode", ""), ("Map mode", ""), + ("Translate mode", ""), ("Use temporary password", "Temporäres Passwort verwenden"), ("Use permanent password", "Dauerhaftes Passwort verwenden"), ("Use both passwords", "Beide Passwörter verwenden"), diff --git a/src/lang/eo.rs b/src/lang/eo.rs index 67d08c5c2..ad4a2f93a 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -290,6 +290,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Connection not allowed", ""), ("Legacy mode", ""), ("Map mode", ""), + ("Translate mode", ""), ("Use temporary password", ""), ("Use permanent password", ""), ("Use both passwords", ""), diff --git a/src/lang/es.rs b/src/lang/es.rs index e34757b8c..73a38dacd 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -302,6 +302,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Connection not allowed", ""), ("Legacy mode", ""), ("Map mode", ""), + ("Translate mode", ""), ("Connection not allowed", "Conexión no disponible"), ("Use temporary password", "Usar contraseña temporal"), ("Use permanent password", "Usar contraseña permamente"), diff --git a/src/lang/fr.rs b/src/lang/fr.rs index 81c039c0a..3553a5b17 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -290,6 +290,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Connection not allowed", ""), ("Legacy mode", ""), ("Map mode", ""), + ("Translate mode", ""), ("Use temporary password", ""), ("Use permanent password", ""), ("Use both passwords", ""), diff --git a/src/lang/hu.rs b/src/lang/hu.rs index 432b88115..8a57378ea 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -290,6 +290,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Connection not allowed", ""), ("Legacy mode", ""), ("Map mode", ""), + ("Translate mode", ""), ("Use temporary password", ""), ("Use permanent password", ""), ("Use both passwords", ""), diff --git a/src/lang/id.rs b/src/lang/id.rs index 4b1de4330..422851c77 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -302,6 +302,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Connection not allowed", ""), ("Legacy mode", ""), ("Map mode", ""), + ("Translate mode", ""), ("Connection not allowed", "Koneksi tidak dijinkan"), ("Use temporary password", "Gunakan kata sandi sementara"), ("Use permanent password", "Gunakan kata sandi permanaen"), diff --git a/src/lang/it.rs b/src/lang/it.rs index 661feec02..c98c53100 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -290,6 +290,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Connection not allowed", ""), ("Legacy mode", ""), ("Map mode", ""), + ("Translate mode", ""), ("Use temporary password", ""), ("Use permanent password", ""), ("Use both passwords", ""), diff --git a/src/lang/ja.rs b/src/lang/ja.rs index 5c6ba1da7..82d91993e 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -288,6 +288,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Ignore Battery Optimizations", "バッテリーの最適化を無効にする"), ("android_open_battery_optimizations_tip", "この機能を使わない場合は、次のRestDeskアプリ設定ページから「バッテリー」に進み、「制限なし」の選択を外してください"), ("Connection not allowed", "接続が許可されていません"), + ("Legacy mode", ""), + ("Map mode", ""), + ("Translate mode", ""), ("Use temporary password", "使い捨てのパスワードを使用"), ("Use permanent password", "固定のパスワードを使用"), ("Use both passwords", "どちらのパスワードも使用"), diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index 821429389..dea8197b2 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -290,6 +290,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Connection not allowed", ""), ("Legacy mode", ""), ("Map mode", ""), + ("Translate mode", ""), ("Use temporary password", ""), ("Use permanent password", ""), ("Use both passwords", ""), diff --git a/src/lang/ru.rs b/src/lang/ru.rs index 74536cd23..490fb32e0 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -290,6 +290,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Connection not allowed", "Подключение не разрешено"), ("Legacy mode", ""), ("Map mode", ""), + ("Translate mode", ""), ("Use temporary password", "Использовать временный пароль"), ("Use permanent password", "Использовать постоянный пароль"), ("Use both passwords", "Использовать оба пароля"), diff --git a/src/lang/sk.rs b/src/lang/sk.rs index 23b5bacf7..7a78e2090 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -290,6 +290,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Connection not allowed", ""), ("Legacy mode", ""), ("Map mode", ""), + ("Translate mode", ""), ("Use temporary password", ""), ("Use permanent password", ""), ("Use both passwords", ""), diff --git a/src/lang/template.rs b/src/lang/template.rs index 9a24d6d42..f37d84b60 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -290,6 +290,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Connection not allowed", ""), ("Legacy mode", ""), ("Map mode", ""), + ("Translate mode", ""), ("Use temporary password", ""), ("Use permanent password", ""), ("Use both passwords", ""), diff --git a/src/lang/tr.rs b/src/lang/tr.rs index 85f7b13fc..4b0d6ccb3 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -302,6 +302,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Connection not allowed", ""), ("Legacy mode", ""), ("Map mode", ""), + ("Translate mode", ""), ("Connection not allowed", "bağlantıya izin verilmedi"), ("Use temporary password", "Geçici şifre kullan"), ("Use permanent password", "Kalıcı şifre kullan"), diff --git a/src/lang/tw.rs b/src/lang/tw.rs index bcf4e2800..a294acac2 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -290,6 +290,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Connection not allowed", "對方不允許連接"), ("Legacy mode", "傳統模式"), ("Map mode", "1:1傳輸"), + ("Translate mode", "翻譯模式"), ("Use temporary password", "使用臨時密碼"), ("Use permanent password", "使用固定密碼"), ("Use both passwords", "同時使用兩種密碼"), diff --git a/src/lang/vn.rs b/src/lang/vn.rs index 014dcb20e..55570dc40 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -288,6 +288,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Ignore Battery Optimizations", "Bỏ qua các tối ưu pin"), ("android_open_battery_optimizations_tip", "Nếu bạn muốn tắt tính năng này, vui lòng chuyển đến trang cài đặt ứng dụng RustDesk tiếp theo, tìm và nhập [Pin], Bỏ chọn [Không hạn chế]"), ("Connection not allowed", "Kết nối không đuợc phép"), + ("Legacy mode", ""), + ("Map mode", ""), + ("Translate mode", ""), ("Use temporary password", "Sử dụng mật khẩu tạm thời"), ("Use permanent password", "Sử dụng mật khẩu vĩnh viễn"), ("Use both passwords", "Sử dụng cả hai mật khẩu"), From b2cf11f2df89a7a0a6b38d29f91cc3f5b494a826 Mon Sep 17 00:00:00 2001 From: Asura Date: Sun, 7 Aug 2022 10:50:31 +0800 Subject: [PATCH 51/57] Send caps lock key --- src/ui/remote.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/ui/remote.rs b/src/ui/remote.rs index 9bf125cc0..3a694dd50 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -1125,16 +1125,10 @@ impl Handler { } else { TO_RELEASE.lock().unwrap().remove(&key); } - // algr without action - // Control left + // AltGr && LeftControl(SpecialKey) without action if key == RdevKey::AltGr || evt.scan_code == 541 { return; } - // Caps affects the keycode map of the peer system(Linux). - if key == RdevKey::CapsLock { - return; - } - dbg!(key); self.map_keyboard_mode(down_or_up, key, None); } } From dde6df82e8b67f1c3a74104d3185f320a702e947 Mon Sep 17 00:00:00 2001 From: Asura Date: Sun, 7 Aug 2022 18:52:32 +0800 Subject: [PATCH 52/57] Refector: handline dead keys in translation mode --- Cargo.lock | 60 +----------------------------------------------- src/ui/remote.rs | 6 +---- 2 files changed, 2 insertions(+), 64 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ca3c29392..09ac0686d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1309,16 +1309,6 @@ dependencies = [ "termcolor", ] -[[package]] -name = "epoll" -version = "4.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20df693c700404f7e19d4d6fae6b15215d2913c27955d2b9d6f2c0f537511cd0" -dependencies = [ - "bitflags", - "libc", -] - [[package]] name = "err-derive" version = "0.3.1" @@ -1353,29 +1343,6 @@ dependencies = [ "nix 0.23.1", ] -[[package]] -name = "evdev-rs" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7db51abf6b3205a6e6e8dd68d7a5414d7c50d61736a6f4c9b97df86ef5567cf" -dependencies = [ - "bitflags", - "evdev-sys", - "libc", - "log", -] - -[[package]] -name = "evdev-sys" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14ead42b547b15d47089c1243d907bcf0eb94e457046d3b315a26ac9c9e9ea6d" -dependencies = [ - "cc", - "libc", - "pkg-config", -] - [[package]] name = "event-listener" version = "2.5.2" @@ -2348,28 +2315,6 @@ dependencies = [ "hashbrown", ] -[[package]] -name = "inotify" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abf888f9575c290197b2c948dc9e9ff10bd1a39ad1ea8585f734585fa6b9d3f9" -dependencies = [ - "bitflags", - "futures-core", - "inotify-sys", - "libc", - "tokio", -] - -[[package]] -name = "inotify-sys" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" -dependencies = [ - "libc", -] - [[package]] name = "instant" version = "0.1.12" @@ -3795,16 +3740,13 @@ dependencies = [ [[package]] name = "rdev" version = "0.5.0-2" -source = "git+https://github.com/asur4s/rdev#d6499d2e582bf3549aa4ba33cfd3fbbdfce10947" +source = "git+https://github.com/asur4s/rdev#3b440f7ff9d622b08eb83146ea3e5e529769a6c2" dependencies = [ "cocoa", "core-foundation 0.9.3", "core-foundation-sys 0.8.3", "core-graphics 0.22.3", "enum-map", - "epoll", - "evdev-rs", - "inotify", "lazy_static", "libc", "widestring 1.0.2", diff --git a/src/ui/remote.rs b/src/ui/remote.rs index 3a694dd50..e6c4109a6 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -1085,11 +1085,7 @@ impl Handler { let string = match KEYBOARD.lock() { Ok(mut keyboard) => { let string = keyboard.add(&evt.event_type).unwrap_or_default(); - #[cfg(target_os = "windows")] - let is_dead = keyboard.last_is_dead; - #[cfg(target_os = "linux")] - let is_dead = keyboard.is_dead(); - if is_dead && string == "" && down_or_up == true { + if keyboard.is_dead() && string == "" && down_or_up == true { return; } string From 577cce549f93d8174ef8a920738f26e0c4243c67 Mon Sep 17 00:00:00 2001 From: Asura Date: Mon, 8 Aug 2022 15:48:11 +0800 Subject: [PATCH 53/57] Update Cargo.lock --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 09ac0686d..6d1878ddb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4712,7 +4712,7 @@ checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" [[package]] name = "tfc" version = "0.6.1" -source = "git+https://github.com/asur4s/The-Fat-Controller#14d49063c8fc9a02c68c0dc842e8d6bb6c5e7713" +source = "git+https://github.com/asur4s/The-Fat-Controller#34ee2472e6a88dd8f0e28113d50130d93cf8a572" dependencies = [ "core-graphics 0.22.3", "unicode-segmentation", From b916ef36599f15248133bb30596d2777cfd5f8cd Mon Sep 17 00:00:00 2001 From: Asura Date: Thu, 11 Aug 2022 23:59:18 -0700 Subject: [PATCH 54/57] Refactor translate mode --- Cargo.lock | 4 ++-- src/server/input_service.rs | 12 +++--------- src/ui/remote.rs | 7 ++----- 3 files changed, 7 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6d1878ddb..8ad3970d3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3740,7 +3740,7 @@ dependencies = [ [[package]] name = "rdev" version = "0.5.0-2" -source = "git+https://github.com/asur4s/rdev#3b440f7ff9d622b08eb83146ea3e5e529769a6c2" +source = "git+https://github.com/asur4s/rdev#895c8fb1a6106714793e8877d35d2b7a1c57ce9c" dependencies = [ "cocoa", "core-foundation 0.9.3", @@ -4712,7 +4712,7 @@ checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" [[package]] name = "tfc" version = "0.6.1" -source = "git+https://github.com/asur4s/The-Fat-Controller#34ee2472e6a88dd8f0e28113d50130d93cf8a572" +source = "git+https://github.com/asur4s/The-Fat-Controller#25bfa7ef1cb0bd0b522cc4155dea6b99673bcfd4" dependencies = [ "core-graphics 0.22.3", "unicode-segmentation", diff --git a/src/server/input_service.rs b/src/server/input_service.rs index 0154da085..2093395c8 100644 --- a/src/server/input_service.rs +++ b/src/server/input_service.rs @@ -822,16 +822,10 @@ fn legacy_keyboard_mode(evt: &KeyEvent) { } fn translate_keyboard_mode(evt: &KeyEvent) { - // Caps affects the keycode map of the peer system(Linux). - let mut en = ENIGO.lock().unwrap(); - if en.get_key_state(Key::CapsLock){ - rdev_key_click(RdevKey::CapsLock); - } let chr = char::from_u32(evt.chr()).unwrap_or_default(); - if evt.down { - KBD_CONTEXT.lock().unwrap().unicode_char_down(chr).expect("unicode_char_down error"); - } else { - KBD_CONTEXT.lock().unwrap().unicode_char_up(chr).expect("unicode_char_up error"); + // down(true)->press && press(false)-> release + if evt.down && !evt.press { + KBD_CONTEXT.lock().unwrap().unicode_char(chr).expect("unicode_char_down error"); } } diff --git a/src/ui/remote.rs b/src/ui/remote.rs index e6c4109a6..f26150f31 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -1108,11 +1108,8 @@ impl Handler { let mut key_event = KeyEvent::new(); key_event.set_chr(chr as _); key_event.down = true; - self.send_key_event(key_event, KeyboardMode::Translate); - - let mut key_event = KeyEvent::new(); - key_event.set_chr(chr as _); - key_event.down = false; + key_event.press = false; + self.send_key_event(key_event, KeyboardMode::Translate); } } else { From 8310f38c15bdfcb9c8a8af94cfa84819ed07f2ee Mon Sep 17 00:00:00 2001 From: Asura Date: Fri, 12 Aug 2022 00:05:31 -0700 Subject: [PATCH 55/57] Fix repeatedly releasing keys without char --- src/ui/remote.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/ui/remote.rs b/src/ui/remote.rs index f26150f31..3d90ac73f 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -1113,16 +1113,19 @@ impl Handler { self.send_key_event(key_event, KeyboardMode::Translate); } } else { - if down_or_up == true { - TO_RELEASE.lock().unwrap().insert(key); + let success = if down_or_up == true { + TO_RELEASE.lock().unwrap().insert(key) } else { - TO_RELEASE.lock().unwrap().remove(&key); - } + TO_RELEASE.lock().unwrap().remove(&key) + }; + // AltGr && LeftControl(SpecialKey) without action if key == RdevKey::AltGr || evt.scan_code == 541 { return; } - self.map_keyboard_mode(down_or_up, key, None); + if success{ + self.map_keyboard_mode(down_or_up, key, None); + } } } From e7e846cd42a1297f5ecd31ba1b4167f17e9dbfc7 Mon Sep 17 00:00:00 2001 From: Asura Date: Fri, 12 Aug 2022 19:32:42 +0800 Subject: [PATCH 56/57] Fix mouse input error #1032 --- src/ui/remote.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ui/remote.rs b/src/ui/remote.rs index 3d90ac73f..bcb79c522 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -301,6 +301,8 @@ impl Handler { m.insert(RdevKey::ControlRight, false); m.insert(RdevKey::Alt, false); m.insert(RdevKey::AltGr, false); + m.insert(RdevKey::MetaLeft, false); + m.insert(RdevKey::MetaRight, false); Mutex::new(m) }; } @@ -816,7 +818,7 @@ impl Handler { command = true; } } - + send_mouse(mask, x, y, alt, ctrl, shift, command, self); // on macos, ctrl + left button down = right button down, up won't emit, so we need to // emit up myself if peer is not macos @@ -1379,7 +1381,6 @@ impl Handler { if down_or_up == true { key_event.down = true; } - dbg!(&key_event); self.send_key_event(key_event, KeyboardMode::Legacy) } From 48ab5e502402ff83e6882ada59bb2324993405ee Mon Sep 17 00:00:00 2001 From: Asura Date: Sat, 13 Aug 2022 08:12:45 +0800 Subject: [PATCH 57/57] Fix command+tab #1032 --- src/server/input_service.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/server/input_service.rs b/src/server/input_service.rs index 2093395c8..c01212184 100644 --- a/src/server/input_service.rs +++ b/src/server/input_service.rs @@ -683,6 +683,14 @@ fn legacy_keyboard_mode(evt: &KeyEvent) { let mut disable_numlock = false; #[cfg(target_os = "macos")] en.reset_flag(); + // When long-pressed the command key, then press and release + // the Tab key, there should be CGEventFlagCommand in the flag. + #[cfg(target_os = "macos")] + for ck in evt.modifiers.iter(){ + if let Some(key) = KEY_MAP.get(&ck.value()){ + en.add_flag(key); + } + } #[cfg(not(target_os = "macos"))] let mut to_release = Vec::new(); #[cfg(not(target_os = "macos"))] @@ -710,8 +718,6 @@ fn legacy_keyboard_mode(evt: &KeyEvent) { continue; } } - #[cfg(target_os = "macos")] - en.add_flag(key); #[cfg(not(target_os = "macos"))] { if key == &Key::CapsLock {