diff --git a/src/server/connection.rs b/src/server/connection.rs index 3d419ef08..f63cd6066 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -541,7 +541,9 @@ impl Connection { conn.reset_resolution(); ALIVE_CONNS.lock().unwrap().retain(|&c| c != id); if let Some(s) = conn.server.upgrade() { - s.write().unwrap().remove_connection(&conn.inner); + let mut s = s.write().unwrap(); + s.remove_connection(&conn.inner); + try_stop_record_cursor_pos(); } log::info!("#{} connection loop exited", id); } @@ -948,9 +950,9 @@ impl Connection { if !self.audio_enabled() { noperms.push(super::audio_service::NAME); } - s.write() - .unwrap() - .add_connection(self.inner.clone(), &noperms); + let mut s = s.write().unwrap(); + s.add_connection(self.inner.clone(), &noperms); + try_start_record_cursor_pos(); } } } diff --git a/src/server/input_service.rs b/src/server/input_service.rs index 917a815bb..1d6d9422c 100644 --- a/src/server/input_service.rs +++ b/src/server/input_service.rs @@ -13,7 +13,8 @@ use std::{ convert::TryFrom, ops::Sub, sync::atomic::{AtomicBool, Ordering}, - time::Instant, + thread, + time::{self, Instant}, }; const INVALID_CURSOR_POS: i32 = i32::MIN; @@ -128,6 +129,7 @@ pub fn new_pos() -> GenericService { sp } +#[inline] fn update_last_cursor_pos(x: i32, y: i32) { let mut lock = LATEST_SYS_CURSOR_POS.lock().unwrap(); if lock.1 .0 != x || lock.1 .1 != y { @@ -136,28 +138,29 @@ fn update_last_cursor_pos(x: i32, y: i32) { } 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.is_moved(x, y) { - let mut msg_out = Message::new(); - msg_out.set_cursor_position(CursorPosition { - x, - y, - ..Default::default() - }); - let exclude = { - let now = get_time(); - let lock = LATEST_PEER_INPUT_CURSOR.lock().unwrap(); - if now - lock.time < 300 { - lock.conn - } else { - 0 - } - }; - sp.send_without(msg_out, exclude); - } - state.cursor_pos = (x, y); + let (_, (x, y)) = *LATEST_SYS_CURSOR_POS.lock().unwrap(); + if state.is_moved(x, y) { + let mut msg_out = Message::new(); + msg_out.set_cursor_position(CursorPosition { + x, + y, + ..Default::default() + }); + let exclude = { + let now = get_time(); + let lock = LATEST_PEER_INPUT_CURSOR.lock().unwrap(); + if now - lock.time < 300 { + lock.conn + } else { + 0 + } + }; + sp.send_without(msg_out, exclude); + } else if x == 0 && y == 0 { + // Early return if cursor retains origin. + return Ok(()); } + state.cursor_pos = (x, y); sp.snapshot(|sps| { let mut msg_out = Message::new(); @@ -221,6 +224,44 @@ const MOUSE_MOVE_PROTECTION_TIMEOUT: Duration = Duration::from_millis(1_000); // Actual diff of (x,y) is (1,1) here. But 5 may be tolerant. const MOUSE_ACTIVE_DISTANCE: i32 = 5; +static RECORD_CURSOR_POS_RUNNING: AtomicBool = AtomicBool::new(false); + +pub fn try_start_record_cursor_pos() { + if RECORD_CURSOR_POS_RUNNING.load(Ordering::SeqCst) { + return; + } + if *CONN_COUNT.lock().unwrap() == 0 { + return; + } + + RECORD_CURSOR_POS_RUNNING.store(true, Ordering::SeqCst); + thread::spawn(|| { + let interval = time::Duration::from_millis(33); + loop { + if !RECORD_CURSOR_POS_RUNNING.load(Ordering::SeqCst) { + break; + } + + let now = time::Instant::now(); + if let Some((x, y)) = crate::get_cursor_pos() { + update_last_cursor_pos(x, y); + } + let elapsed = now.elapsed(); + if elapsed < interval { + thread::sleep(interval - elapsed); + } + } + }); +} + +pub fn try_stop_record_cursor_pos() { + let count_lock = CONN_COUNT.lock().unwrap(); + if *count_lock > 0 { + return; + } + RECORD_CURSOR_POS_RUNNING.store(false, Ordering::SeqCst); +} + // mac key input must be run in main thread, otherwise crash on >= osx 10.15 #[cfg(target_os = "macos")] lazy_static::lazy_static! { @@ -717,11 +758,8 @@ pub fn handle_key(evt: &KeyEvent) { fn reset_input() { unsafe { let _lock = VIRTUAL_INPUT_MTX.lock(); - VIRTUAL_INPUT = VirtualInput::new( - CGEventSourceStateID::Private, - CGEventTapLocation::Session, - ) - .ok(); + VIRTUAL_INPUT = + VirtualInput::new(CGEventSourceStateID::Private, CGEventTapLocation::Session).ok(); } } @@ -1095,8 +1133,7 @@ fn translate_keyboard_mode(evt: &KeyEvent) { Some(key_event::Union::Seq(seq)) => { ENIGO.lock().unwrap().key_sequence(seq); } - Some(key_event::Union::Chr(..)) => - { + Some(key_event::Union::Chr(..)) => { #[cfg(target_os = "windows")] translate_process_code(evt.chr(), evt.down); #[cfg(not(target_os = "windows"))]