mirror of
https://github.com/weyne85/rustdesk.git
synced 2025-10-29 17:00:05 +00:00
Merge branch 'master' into dev
This commit is contained in:
@@ -13,6 +13,8 @@ use std::{
|
||||
time::Instant,
|
||||
};
|
||||
|
||||
const INVALID_CURSOR_POS: i32 = i32::MIN;
|
||||
|
||||
#[derive(Default)]
|
||||
struct StateCursor {
|
||||
hcursor: u64,
|
||||
@@ -28,14 +30,33 @@ impl super::service::Reset for StateCursor {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct StatePos {
|
||||
cursor_pos: (i32, i32),
|
||||
}
|
||||
|
||||
impl Default for StatePos {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
cursor_pos: (INVALID_CURSOR_POS, INVALID_CURSOR_POS),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl super::service::Reset for StatePos {
|
||||
fn reset(&mut self) {
|
||||
self.cursor_pos = (0, 0);
|
||||
self.cursor_pos = (INVALID_CURSOR_POS, INVALID_CURSOR_POS);
|
||||
}
|
||||
}
|
||||
|
||||
impl StatePos {
|
||||
#[inline]
|
||||
fn is_valid(&self) -> bool {
|
||||
self.cursor_pos.0 != INVALID_CURSOR_POS
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_moved(&self, x: i32, y: i32) -> bool {
|
||||
self.is_valid() && (self.cursor_pos.0 != x || self.cursor_pos.1 != y)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,7 +126,7 @@ pub fn new_pos() -> GenericService {
|
||||
}
|
||||
|
||||
fn update_last_cursor_pos(x: i32, y: i32) {
|
||||
let mut lock = LATEST_CURSOR_POS.lock().unwrap();
|
||||
let mut lock = LATEST_SYS_CURSOR_POS.lock().unwrap();
|
||||
if lock.1 .0 != x || lock.1 .1 != y {
|
||||
(lock.0, lock.1) = (Instant::now(), (x, y))
|
||||
}
|
||||
@@ -114,8 +135,7 @@ 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.cursor_pos.0 != x || state.cursor_pos.1 != y {
|
||||
state.cursor_pos = (x, y);
|
||||
if state.is_moved(x, y) {
|
||||
let mut msg_out = Message::new();
|
||||
msg_out.set_cursor_position(CursorPosition {
|
||||
x,
|
||||
@@ -124,7 +144,7 @@ fn run_pos(sp: GenericService, state: &mut StatePos) -> ResultType<()> {
|
||||
});
|
||||
let exclude = {
|
||||
let now = get_time();
|
||||
let lock = LATEST_INPUT_CURSOR.lock().unwrap();
|
||||
let lock = LATEST_PEER_INPUT_CURSOR.lock().unwrap();
|
||||
if now - lock.time < 300 {
|
||||
lock.conn
|
||||
} else {
|
||||
@@ -133,6 +153,7 @@ fn run_pos(sp: GenericService, state: &mut StatePos) -> ResultType<()> {
|
||||
};
|
||||
sp.send_without(msg_out, exclude);
|
||||
}
|
||||
state.cursor_pos = (x, y);
|
||||
}
|
||||
|
||||
sp.snapshot(|sps| {
|
||||
@@ -182,12 +203,13 @@ lazy_static::lazy_static! {
|
||||
Arc::new(Mutex::new(Enigo::new()))
|
||||
};
|
||||
static ref KEYS_DOWN: Arc<Mutex<HashMap<u64, Instant>>> = Default::default();
|
||||
static ref LATEST_INPUT_CURSOR: Arc<Mutex<Input>> = Default::default();
|
||||
static ref LATEST_CURSOR_POS: Arc<Mutex<(Instant, (i32, i32))>> = Arc::new(Mutex::new((Instant::now().sub(MOUSE_MOVE_PROTECTION_TIMEOUT), (0, 0))));
|
||||
static ref LATEST_PEER_INPUT_CURSOR: Arc<Mutex<Input>> = Default::default();
|
||||
static ref LATEST_SYS_CURSOR_POS: Arc<Mutex<(Instant, (i32, i32))>> = 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);
|
||||
// Actual diff of (x,y) is (1,1) here. But 5 may be tolerant.
|
||||
const MOUSE_ACTIVE_DISTANCE: i32 = 5;
|
||||
|
||||
// mac key input must be run in main thread, otherwise crash on >= osx 10.15
|
||||
@@ -258,14 +280,30 @@ fn get_modifier_state(key: Key, en: &mut Enigo) -> bool {
|
||||
}
|
||||
|
||||
pub fn handle_mouse(evt: &MouseEvent, conn: i32) {
|
||||
if !active_mouse_(conn) {
|
||||
return;
|
||||
}
|
||||
let evt_type = evt.mask & 0x7;
|
||||
if evt_type == 0 {
|
||||
let time = get_time();
|
||||
*LATEST_PEER_INPUT_CURSOR.lock().unwrap() = Input {
|
||||
time,
|
||||
conn,
|
||||
x: evt.x,
|
||||
y: evt.y,
|
||||
};
|
||||
}
|
||||
#[cfg(target_os = "macos")]
|
||||
if !*IS_SERVER {
|
||||
// having GUI, run main GUI thread, otherwise crash
|
||||
let evt = evt.clone();
|
||||
QUEUE.exec_async(move || handle_mouse_(&evt, conn));
|
||||
QUEUE.exec_async(move || handle_mouse_(&evt));
|
||||
return;
|
||||
}
|
||||
handle_mouse_(evt, conn);
|
||||
#[cfg(windows)]
|
||||
crate::portable_service::client::handle_mouse(evt);
|
||||
#[cfg(not(windows))]
|
||||
handle_mouse_(evt);
|
||||
}
|
||||
|
||||
pub fn fix_key_down_timeout_loop() {
|
||||
@@ -373,55 +411,58 @@ fn fix_modifiers(modifiers: &[EnumOrUnknown<ControlKey>], en: &mut Enigo, ck: i3
|
||||
}
|
||||
}
|
||||
|
||||
fn is_mouse_active_by_conn(conn: i32) -> bool {
|
||||
fn active_mouse_(conn: i32) -> bool {
|
||||
// out of time protection
|
||||
if LATEST_CURSOR_POS.lock().unwrap().0.elapsed() > MOUSE_MOVE_PROTECTION_TIMEOUT {
|
||||
if LATEST_SYS_CURSOR_POS.lock().unwrap().0.elapsed() > MOUSE_MOVE_PROTECTION_TIMEOUT {
|
||||
return true;
|
||||
}
|
||||
|
||||
let mut last_input = LATEST_INPUT_CURSOR.lock().unwrap();
|
||||
// last conn input may be protected
|
||||
if last_input.conn != conn {
|
||||
if LATEST_PEER_INPUT_CURSOR.lock().unwrap().conn != conn {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check if input is in valid range
|
||||
let in_actived_dist = |a: i32, b: i32| -> bool { (a - b).abs() < MOUSE_ACTIVE_DISTANCE };
|
||||
|
||||
// Check if input is in valid range
|
||||
match crate::get_cursor_pos() {
|
||||
Some((x, y)) => {
|
||||
let is_same_input = (last_input.x - x).abs() < MOUSE_ACTIVE_DISTANCE
|
||||
&& (last_input.y - y).abs() < MOUSE_ACTIVE_DISTANCE;
|
||||
if !is_same_input {
|
||||
last_input.x = -MOUSE_ACTIVE_DISTANCE * 2;
|
||||
last_input.y = -MOUSE_ACTIVE_DISTANCE * 2;
|
||||
let (last_in_x, last_in_y) = {
|
||||
let lock = LATEST_PEER_INPUT_CURSOR.lock().unwrap();
|
||||
(lock.x, lock.y)
|
||||
};
|
||||
let mut can_active = in_actived_dist(last_in_x, x) && in_actived_dist(last_in_y, y);
|
||||
// The cursor may not have been moved to last input position if system is busy now.
|
||||
// While this is not a common case, we check it again after some time later.
|
||||
if !can_active {
|
||||
// 10 micros may be enough for system to move cursor.
|
||||
// We do not care about the situation which system is too slow(more than 10 micros is required).
|
||||
std::thread::sleep(std::time::Duration::from_micros(10));
|
||||
// Sleep here can also somehow suppress delay accumulation.
|
||||
if let Some((x2, y2)) = crate::get_cursor_pos() {
|
||||
can_active = in_actived_dist(last_in_x, x2) && in_actived_dist(last_in_y, y2);
|
||||
}
|
||||
}
|
||||
is_same_input
|
||||
if !can_active {
|
||||
let mut lock = LATEST_PEER_INPUT_CURSOR.lock().unwrap();
|
||||
lock.x = INVALID_CURSOR_POS / 2;
|
||||
lock.y = INVALID_CURSOR_POS / 2;
|
||||
}
|
||||
can_active
|
||||
}
|
||||
None => true,
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_mouse_(evt: &MouseEvent, conn: i32) {
|
||||
pub fn handle_mouse_(evt: &MouseEvent) {
|
||||
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_CURSOR.lock().unwrap() = Input {
|
||||
time,
|
||||
conn,
|
||||
x: evt.x,
|
||||
y: evt.y,
|
||||
};
|
||||
}
|
||||
let mut en = ENIGO.lock().unwrap();
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
let mut to_release = Vec::new();
|
||||
@@ -677,6 +718,9 @@ pub fn handle_key(evt: &KeyEvent) {
|
||||
QUEUE.exec_async(move || handle_key_(&evt));
|
||||
return;
|
||||
}
|
||||
#[cfg(windows)]
|
||||
crate::portable_service::client::handle_key(evt);
|
||||
#[cfg(not(windows))]
|
||||
handle_key_(evt);
|
||||
}
|
||||
|
||||
@@ -928,7 +972,7 @@ fn legacy_keyboard_mode(evt: &KeyEvent) {
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_key_(evt: &KeyEvent) {
|
||||
pub fn handle_key_(evt: &KeyEvent) {
|
||||
if EXITING.load(Ordering::SeqCst) {
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user