From d916c540295081fc688fcd11bae1c06ed8a6817e Mon Sep 17 00:00:00 2001 From: fufesou Date: Fri, 9 Dec 2022 21:16:09 +0800 Subject: [PATCH 1/3] fix sciter keyboard Signed-off-by: fufesou --- src/flutter.rs | 2 ++ src/flutter_ffi.rs | 4 +--- src/keyboard.rs | 27 ++++++++++++++++----------- src/ui.rs | 7 +++++-- src/ui/remote.rs | 15 +++++++++++++++ src/ui_session_interface.rs | 6 ++++-- 6 files changed, 43 insertions(+), 18 deletions(-) diff --git a/src/flutter.rs b/src/flutter.rs index 2bb7a9faf..788a9f540 100644 --- a/src/flutter.rs +++ b/src/flutter.rs @@ -324,6 +324,8 @@ impl InvokeUiSession for FlutterHandler { ); } + fn on_connected(&self, _conn_type: ConnType) {} + fn msgbox(&self, msgtype: &str, title: &str, text: &str, link: &str, retry: bool) { let has_retry = if retry { "true" } else { "" }; self.push_event( diff --git a/src/flutter_ffi.rs b/src/flutter_ffi.rs index 0c90c3131..ddfaad06d 100644 --- a/src/flutter_ffi.rs +++ b/src/flutter_ffi.rs @@ -17,8 +17,6 @@ use hbb_common::{ use crate::flutter::{self, SESSIONS}; use crate::ui_interface::{self, *}; -#[cfg(not(any(target_os = "android", target_os = "ios")))] -use crate::keyboard::CUR_SESSION; use crate::{ client::file_trait::FileManager, flutter::{make_fd_to_json, session_add, session_start_}, @@ -293,7 +291,7 @@ pub fn session_enter_or_leave(id: String, enter: bool) { #[cfg(not(any(target_os = "android", target_os = "ios")))] if let Some(session) = SESSIONS.read().unwrap().get(&id) { if enter { - *CUR_SESSION.lock().unwrap() = Some(session.clone()); + crate::keyboard::set_cur_session(session.clone()); session.enter(); } else { session.leave(); diff --git a/src/keyboard.rs b/src/keyboard.rs index f0c14a1e9..eb39301f3 100644 --- a/src/keyboard.rs +++ b/src/keyboard.rs @@ -8,29 +8,31 @@ use crate::ui::remote::SciterHandler; use crate::ui_session_interface::Session; use hbb_common::{log, message_proto::*}; use rdev::{Event, EventType, Key}; -use std::collections::{HashMap, HashSet}; -use std::sync::atomic::AtomicBool; -#[cfg(any(target_os = "windows", target_os = "macos"))] -use std::sync::atomic::Ordering; -use std::sync::{mpsc, Arc, Mutex}; -use std::thread; -use std::time::SystemTime; +use std::{ + collections::{HashMap, HashSet}, + sync::{ + atomic::{AtomicBool, Ordering}, + mpsc, Arc, Mutex, + }, + thread, + time::SystemTime, +}; static mut IS_ALT_GR: bool = false; -pub static KEYBOARD_HOOKED: AtomicBool = AtomicBool::new(false); +static KEYBOARD_HOOKED: AtomicBool = AtomicBool::new(false); lazy_static::lazy_static! { - pub static ref GRAB_SENDER: Arc>>> = Default::default(); + static ref GRAB_SENDER: Arc>>> = Default::default(); } #[cfg(feature = "flutter")] lazy_static::lazy_static! { - pub static ref CUR_SESSION: Arc>>> = Default::default(); + static ref CUR_SESSION: Arc>>> = Default::default(); } #[cfg(not(feature = "flutter"))] lazy_static::lazy_static! { - pub static ref CUR_SESSION: Arc>>> = Default::default(); + static ref CUR_SESSION: Arc>>> = Default::default(); } lazy_static::lazy_static! { @@ -47,7 +49,10 @@ lazy_static::lazy_static! { m.insert(Key::MetaRight, false); Mutex::new(m) }; +} +pub fn set_cur_session(session: Session) { + *CUR_SESSION.lock().unwrap() = Some(session); } pub mod client { diff --git a/src/ui.rs b/src/ui.rs index e282d19c4..921c137ec 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -124,12 +124,15 @@ pub fn start(args: &mut [String]) { let args: Vec = iter.map(|x| x.clone()).collect(); frame.set_title(&id); frame.register_behavior("native-remote", move || { - Box::new(remote::SciterSession::new( + let handler = remote::SciterSession::new( cmd.clone(), id.clone(), pass.clone(), args.clone(), - )) + ); + let inner = handler.inner(); + crate::keyboard::set_cur_session(inner); + Box::new(handler) }); page = "remote.html"; } else { diff --git a/src/ui/remote.rs b/src/ui/remote.rs index 3d209a71c..29b1a9eee 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -231,6 +231,17 @@ impl InvokeUiSession for SciterHandler { self.call("updatePi", &make_args!(pi_sciter)); } + fn on_connected(&self, conn_type: ConnType) { + match conn_type { + ConnType::RDP => {}, + ConnType::PORT_FORWARD => {}, + ConnType::FILE_TRANSFER => {}, + ConnType::DEFAULT_CONN => { + crate::keyboard::client::start_grab_loop(); + }, + } + } + fn msgbox(&self, msgtype: &str, title: &str, text: &str, link: &str, retry: bool) { self.call2( "msgbox_retry", @@ -434,6 +445,10 @@ impl SciterSession { Self(session) } + pub fn inner(&self) -> Session { + self.0.clone() + } + 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() { diff --git a/src/ui_session_interface.rs b/src/ui_session_interface.rs index 6bdf88b11..e594ac94b 100644 --- a/src/ui_session_interface.rs +++ b/src/ui_session_interface.rs @@ -5,6 +5,7 @@ use crate::client::{ QualityStatus, KEY_MAP, }; use crate::common::GrabState; +use crate::keyboard; use crate::{client::Data, client::Interface}; use async_trait::async_trait; use hbb_common::config::{Config, LocalConfig, PeerConfig}; @@ -12,12 +13,11 @@ use hbb_common::rendezvous_proto::ConnType; use hbb_common::tokio::{self, sync::mpsc}; use hbb_common::{allow_err, message_proto::*}; use hbb_common::{fs, get_version_number, log, Stream}; +use rdev::{Event, EventType::*}; use std::collections::HashMap; use std::ops::{Deref, DerefMut}; use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; use std::sync::{Arc, Mutex, RwLock}; -use crate::keyboard; -use rdev::{Event, EventType::*}; pub static IS_IN: AtomicBool = AtomicBool::new(false); #[derive(Clone, Default)] @@ -580,6 +580,7 @@ pub trait InvokeUiSession: Send + Sync + Clone + 'static + Sized + Default { fn set_display(&self, x: i32, y: i32, w: i32, h: i32, cursor_embeded: bool); fn switch_display(&self, display: &SwitchDisplay); fn set_peer_info(&self, peer_info: &PeerInfo); // flutter + fn on_connected(&self, conn_type: ConnType); fn update_privacy_mode(&self); fn set_permission(&self, name: &str, value: bool); fn close_success(&self); @@ -712,6 +713,7 @@ impl Interface for Session { "", ); } + self.on_connected(self.lc.read().unwrap().conn_type); #[cfg(windows)] { let mut path = std::env::temp_dir(); From aa5debe986c874abf64fb8d997f9616db1b0ebc0 Mon Sep 17 00:00:00 2001 From: fufesou Date: Fri, 9 Dec 2022 21:42:26 +0800 Subject: [PATCH 2/3] remove unused logic Signed-off-by: fufesou --- src/keyboard.rs | 126 +++++++++++++++++++++--------------------------- 1 file changed, 54 insertions(+), 72 deletions(-) diff --git a/src/keyboard.rs b/src/keyboard.rs index eb39301f3..a6e1a8ee9 100644 --- a/src/keyboard.rs +++ b/src/keyboard.rs @@ -12,7 +12,7 @@ use std::{ collections::{HashMap, HashSet}, sync::{ atomic::{AtomicBool, Ordering}, - mpsc, Arc, Mutex, + Arc, Mutex, }, thread, time::SystemTime, @@ -21,10 +21,6 @@ use std::{ static mut IS_ALT_GR: bool = false; static KEYBOARD_HOOKED: AtomicBool = AtomicBool::new(false); -lazy_static::lazy_static! { - static ref GRAB_SENDER: Arc>>> = Default::default(); -} - #[cfg(feature = "flutter")] lazy_static::lazy_static! { static ref CUR_SESSION: Arc>>> = Default::default(); @@ -67,20 +63,32 @@ pub mod client { } pub fn start_grab_loop() { - let (sender, receiver) = mpsc::channel::(); - - grab_loop(receiver); - *GRAB_SENDER.lock().unwrap() = Some(sender); - - change_grab_status(GrabState::Ready); + thread::spawn(grab_loop); } pub fn change_grab_status(state: GrabState) { - if GrabState::Wait == state { - release_remote_keys(); - } - if let Some(sender) = &*GRAB_SENDER.lock().unwrap() { - sender.send(state).ok(); + match state { + GrabState::Ready => {} + GrabState::Run => { + #[cfg(any(target_os = "windows", target_os = "macos"))] + KEYBOARD_HOOKED.swap(true, Ordering::SeqCst); + + #[cfg(target_os = "linux")] + rdev::enable_grab().ok(); + } + GrabState::Wait => { + release_remote_keys(); + + #[cfg(any(target_os = "windows", target_os = "macos"))] + KEYBOARD_HOOKED.swap(false, Ordering::SeqCst); + + #[cfg(target_os = "linux")] + rdev::disable_grab().ok(); + } + GrabState::Exit => { + #[cfg(target_os = "linux")] + rdev::exit_grab_listen().ok(); + } } } @@ -171,67 +179,41 @@ pub mod client { } } -pub fn grab_loop(recv: mpsc::Receiver) { - thread::spawn(move || loop { - if let Some(state) = recv.recv().ok() { - match state { - GrabState::Ready => { - #[cfg(any(target_os = "windows", target_os = "macos"))] - std::thread::spawn(move || { - let func = move |event: Event| match event.event_type { - EventType::KeyPress(key) | EventType::KeyRelease(key) => { - // fix #2211:CAPS LOCK don't work - if key == Key::CapsLock || key == Key::NumLock { - return Some(event); - } - if KEYBOARD_HOOKED.load(Ordering::SeqCst) { - client::process_event(event); - return None; - } else { - return Some(event); - } - } - _ => Some(event), - }; - if let Err(error) = rdev::grab(func) { - log::error!("rdev Error: {:?}", error) - } - }); - - #[cfg(target_os = "linux")] - rdev::start_grab_listen(move |event: Event| match event.event_type { - EventType::KeyPress(key) | EventType::KeyRelease(key) => { - if let Key::Unknown(keycode) = key { - log::error!("rdev get unknown key, keycode is : {:?}", keycode); - } else { - client::process_event(event); - } - None - } - _ => Some(event), - }); +pub fn grab_loop() { + #[cfg(any(target_os = "windows", target_os = "macos"))] + std::thread::spawn(move || { + let func = move |event: Event| match event.event_type { + EventType::KeyPress(key) | EventType::KeyRelease(key) => { + // fix #2211:CAPS LOCK don't work + if key == Key::CapsLock || key == Key::NumLock { + return Some(event); } - GrabState::Run => { - #[cfg(any(target_os = "windows", target_os = "macos"))] - KEYBOARD_HOOKED.swap(true, Ordering::SeqCst); - - #[cfg(target_os = "linux")] - rdev::enable_grab().ok(); - } - GrabState::Wait => { - #[cfg(any(target_os = "windows", target_os = "macos"))] - KEYBOARD_HOOKED.swap(false, Ordering::SeqCst); - - #[cfg(target_os = "linux")] - rdev::disable_grab().ok(); - } - GrabState::Exit => { - #[cfg(target_os = "linux")] - rdev::exit_grab_listen().ok(); + if KEYBOARD_HOOKED.load(Ordering::SeqCst) { + client::process_event(event); + return None; + } else { + return Some(event); } } + _ => Some(event), + }; + if let Err(error) = rdev::grab(func) { + log::error!("rdev Error: {:?}", error) } }); + + #[cfg(target_os = "linux")] + rdev::start_grab_listen(move |event: Event| match event.event_type { + EventType::KeyPress(key) | EventType::KeyRelease(key) => { + if let Key::Unknown(keycode) = key { + log::error!("rdev get unknown key, keycode is : {:?}", keycode); + } else { + client::process_event(event); + } + None + } + _ => Some(event), + }); } pub fn is_long_press(event: &Event) -> bool { From 1e8e1700df4c6a78f616a29e78b6e660c4c446e4 Mon Sep 17 00:00:00 2001 From: fufesou Date: Fri, 9 Dec 2022 22:33:50 +0800 Subject: [PATCH 3/3] simplify logic Signed-off-by: fufesou --- src/keyboard.rs | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/keyboard.rs b/src/keyboard.rs index a6e1a8ee9..740afaf8f 100644 --- a/src/keyboard.rs +++ b/src/keyboard.rs @@ -14,7 +14,6 @@ use std::{ atomic::{AtomicBool, Ordering}, Arc, Mutex, }, - thread, time::SystemTime, }; @@ -63,7 +62,7 @@ pub mod client { } pub fn start_grab_loop() { - thread::spawn(grab_loop); + super::start_grab_loop(); } pub fn change_grab_status(state: GrabState) { @@ -179,7 +178,7 @@ pub mod client { } } -pub fn grab_loop() { +pub fn start_grab_loop() { #[cfg(any(target_os = "windows", target_os = "macos"))] std::thread::spawn(move || { let func = move |event: Event| match event.event_type { @@ -233,10 +232,9 @@ pub fn is_long_press(event: &Event) -> bool { pub fn release_remote_keys() { // todo!: client quit suddenly, how to release keys? - let to_release = TO_RELEASE.lock().unwrap(); - let keys = to_release.iter().map(|&key| key).collect::>(); - drop(to_release); - for key in keys { + let to_release = TO_RELEASE.lock().unwrap().clone(); + TO_RELEASE.lock().unwrap().clear(); + for key in to_release { let event_type = EventType::KeyRelease(key); let event = event_type_to_event(event_type); client::process_event(event); @@ -304,17 +302,15 @@ pub fn event_to_key_event(event: &Event) -> KeyEvent { let mut key_event = KeyEvent::new(); update_modifiers_state(event); - let mut to_release = TO_RELEASE.lock().unwrap(); match event.event_type { EventType::KeyPress(key) => { - to_release.insert(key); + TO_RELEASE.lock().unwrap().insert(key); } EventType::KeyRelease(key) => { - to_release.remove(&key); + TO_RELEASE.lock().unwrap().remove(&key); } _ => {} } - drop(to_release); let keyboard_mode = get_keyboard_mode_enum(); key_event.mode = keyboard_mode.into();