From 60e8dd840f0008190a80f76e4357166b1ee89fa7 Mon Sep 17 00:00:00 2001 From: fufesou Date: Wed, 9 Nov 2022 15:04:24 +0800 Subject: [PATCH] Remote side has a higher priority on mouse control Signed-off-by: fufesou --- src/hbbs_http.rs | 6 +-- src/server/input_service.rs | 74 +++++++++++++++++++++++++++++-------- src/tray.rs | 7 +++- src/ui_interface.rs | 7 +++- src/ui_session_interface.rs | 3 +- 5 files changed, 72 insertions(+), 25 deletions(-) diff --git a/src/hbbs_http.rs b/src/hbbs_http.rs index 4360b6e8c..ceb3a6081 100644 --- a/src/hbbs_http.rs +++ b/src/hbbs_http.rs @@ -1,12 +1,8 @@ -use hbb_common::{ - anyhow::{self, bail}, - tokio, ResultType, -}; use reqwest::blocking::Response; use serde::de::DeserializeOwned; -use serde_derive::Deserialize; use serde_json::{Map, Value}; +#[cfg(feature = "flutter")] pub mod account; #[derive(Debug)] diff --git a/src/server/input_service.rs b/src/server/input_service.rs index d91e9a799..9b43c5850 100644 --- a/src/server/input_service.rs +++ b/src/server/input_service.rs @@ -1,4 +1,5 @@ use super::*; +#[cfg(target_os = "linux")] use crate::common::IS_X11; #[cfg(target_os = "macos")] use dispatch::Queue; @@ -7,6 +8,7 @@ use hbb_common::{config::COMPRESS_LEVEL, get_time, protobuf::EnumOrUnknown}; use rdev::{simulate, EventType, Key as RdevKey}; use std::{ convert::TryFrom, + ops::Sub, sync::atomic::{AtomicBool, Ordering}, time::Instant, }; @@ -100,8 +102,16 @@ pub fn new_pos() -> GenericService { sp } +fn update_last_cursor_pos(x: i32, y: i32) { + let mut lock = LATEST_CURSOR_POS.lock().unwrap(); + if lock.1 .0 != x || lock.1 .1 != y { + (lock.0, lock.1) = (Instant::now(), (x, y)) + } +} + fn run_pos(sp: GenericService, state: &mut StatePos) -> ResultType<()> { if let Some((x, y)) = crate::get_cursor_pos() { + update_last_cursor_pos(x, y); if state.cursor_pos.0 != x || state.cursor_pos.1 != y { state.cursor_pos = (x, y); let mut msg_out = Message::new(); @@ -112,7 +122,7 @@ fn run_pos(sp: GenericService, state: &mut StatePos) -> ResultType<()> { }); let exclude = { let now = get_time(); - let lock = LATEST_INPUT.lock().unwrap(); + let lock = LATEST_INPUT_CURSOR.lock().unwrap(); if now - lock.time < 300 { lock.conn } else { @@ -170,10 +180,15 @@ lazy_static::lazy_static! { Arc::new(Mutex::new(Enigo::new())) }; static ref KEYS_DOWN: Arc>> = Default::default(); - static ref LATEST_INPUT: Arc> = Default::default(); + static ref LATEST_INPUT_CURSOR: Arc> = Default::default(); + static ref LATEST_INPUT_CURSOR_POS: Arc>> = Default::default(); + static ref LATEST_CURSOR_POS: Arc> = Arc::new(Mutex::new((Instant::now().sub(MOUSE_MOVE_PROTECTION_TIMEOUT), (0, 0)))); } static EXITING: AtomicBool = AtomicBool::new(false); +const MOUSE_MOVE_PROTECTION_TIMEOUT: Duration = Duration::from_millis(1_000); +const MOUSE_ACTIVE_DISTANCE: i32 = 5; + // mac key input must be run in main thread, otherwise crash on >= osx 10.15 #[cfg(target_os = "macos")] lazy_static::lazy_static! { @@ -357,17 +372,43 @@ fn fix_modifiers(modifiers: &[EnumOrUnknown], en: &mut Enigo, ck: i3 } } +fn is_mouse_active_by_conn(conn: i32) -> bool { + if LATEST_CURSOR_POS.lock().unwrap().0.elapsed() > MOUSE_MOVE_PROTECTION_TIMEOUT { + return true; + } + + match LATEST_INPUT_CURSOR_POS.lock().unwrap().get(&conn) { + Some((x, y)) => match crate::get_cursor_pos() { + Some((x2, y2)) => { + (x - x2).abs() < MOUSE_ACTIVE_DISTANCE && (y - y2).abs() < MOUSE_ACTIVE_DISTANCE + } + None => true, + }, + None => true, + } +} + fn handle_mouse_(evt: &MouseEvent, conn: i32) { if EXITING.load(Ordering::SeqCst) { return; } + + if !is_mouse_active_by_conn(conn) { + return; + } + #[cfg(windows)] crate::platform::windows::try_change_desktop(); let buttons = evt.mask >> 3; let evt_type = evt.mask & 0x7; if evt_type == 0 { let time = get_time(); - *LATEST_INPUT.lock().unwrap() = Input { time, conn }; + *LATEST_INPUT_CURSOR.lock().unwrap() = Input { time, conn }; + + LATEST_INPUT_CURSOR_POS + .lock() + .unwrap() + .insert(conn, (evt.x, evt.y)); } let mut en = ENIGO.lock().unwrap(); #[cfg(not(target_os = "macos"))] @@ -432,7 +473,10 @@ fn handle_mouse_(evt: &MouseEvent, conn: i32) { // fix shift + scroll(down/up) #[cfg(target_os = "macos")] - if evt.modifiers.contains(&EnumOrUnknown::new(ControlKey::Shift)){ + if evt + .modifiers + .contains(&EnumOrUnknown::new(ControlKey::Shift)) + { x = y; y = 0; } @@ -653,19 +697,19 @@ fn sync_status(evt: &KeyEvent) -> (bool, bool) { let code = evt.chr(); let key = rdev::get_win_key(code, 0); match key { - RdevKey::Home | - RdevKey::UpArrow | - RdevKey::PageUp | - RdevKey::LeftArrow | - RdevKey::RightArrow | - RdevKey::End | - RdevKey::DownArrow | - RdevKey::PageDown | - RdevKey::Insert | - RdevKey::Delete => en.get_key_state(enigo::Key::NumLock), + RdevKey::Home + | RdevKey::UpArrow + | RdevKey::PageUp + | RdevKey::LeftArrow + | RdevKey::RightArrow + | RdevKey::End + | RdevKey::DownArrow + | RdevKey::PageDown + | RdevKey::Insert + | RdevKey::Delete => en.get_key_state(enigo::Key::NumLock), _ => click_numlock, } - }; + }; return (click_capslock, click_numlock); } diff --git a/src/tray.rs b/src/tray.rs index 8e9092fbf..80647fa17 100644 --- a/src/tray.rs +++ b/src/tray.rs @@ -1,10 +1,13 @@ -use hbb_common::log::{debug, error, info}; +use hbb_common::log::debug; +#[cfg(target_os = "linux")] +use hbb_common::log::{error, info}; #[cfg(target_os = "linux")] use libappindicator::AppIndicator; +#[cfg(target_os = "linux")] use std::env::temp_dir; use std::{ collections::HashMap, - sync::{Arc, Mutex, RwLock}, + sync::{Arc, Mutex}, }; #[cfg(target_os = "windows")] use trayicon::{MenuBuilder, TrayIconBuilder}; diff --git a/src/ui_interface.rs b/src/ui_interface.rs index 92c63e310..29b09addc 100644 --- a/src/ui_interface.rs +++ b/src/ui_interface.rs @@ -20,7 +20,9 @@ use hbb_common::{ tokio::{self, sync::mpsc, time}, }; -use crate::{common::SOFTWARE_UPDATE_URL, hbbs_http::account, ipc, platform}; +use crate::{common::SOFTWARE_UPDATE_URL, ipc, platform}; +#[cfg(feature = "flutter")] +use crate::hbbs_http::account; type Message = RendezvousMessage; @@ -844,14 +846,17 @@ pub(crate) fn check_connect_status(reconnect: bool) -> mpsc::UnboundedSender String { serde_json::to_string(&account::OidcSession::get_result()).unwrap_or_default() } diff --git a/src/ui_session_interface.rs b/src/ui_session_interface.rs index 2f5543ead..bf03ed2d3 100644 --- a/src/ui_session_interface.rs +++ b/src/ui_session_interface.rs @@ -22,7 +22,6 @@ use std::collections::{HashMap, HashSet}; use std::ops::{Deref, DerefMut}; use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; use std::sync::{Arc, Mutex, RwLock}; -use std::time::Duration; /// IS_IN KEYBOARD_HOOKED sciter only pub static IS_IN: AtomicBool = AtomicBool::new(false); @@ -1323,7 +1322,7 @@ impl Session { #[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) => { + EventType::KeyPress(..) | EventType::KeyRelease(..) => { // grab all keys if !IS_IN.load(Ordering::SeqCst) || !SERVER_KEYBOARD_ENABLED.load(Ordering::SeqCst)