mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-09-17 18:01:06 +03:00
Keep one macOS cursor density snapshot and retry failed captures
This commit is contained in:
@@ -37,6 +37,9 @@ use std::{
|
|||||||
|
|
||||||
mod cursor;
|
mod cursor;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod cursor_poll_tests;
|
||||||
|
|
||||||
// macOS boolean_t is defined as `int` in <mach/boolean.h>
|
// macOS boolean_t is defined as `int` in <mach/boolean.h>
|
||||||
type BooleanT = hbb_common::libc::c_int;
|
type BooleanT = hbb_common::libc::c_int;
|
||||||
|
|
||||||
@@ -567,10 +570,10 @@ fn unsafe_get_cursor() -> ResultType<Option<u64>> {
|
|||||||
if seed == LATEST_SEED {
|
if seed == LATEST_SEED {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
let c = get_cursor_id(seed.1)?;
|
||||||
LATEST_SEED = seed;
|
LATEST_SEED = seed;
|
||||||
|
Ok(Some(c.1))
|
||||||
}
|
}
|
||||||
let c = get_cursor_id()?;
|
|
||||||
Ok(Some(c.1))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset_input_cache() {
|
pub fn reset_input_cache() {
|
||||||
@@ -579,7 +582,7 @@ pub fn reset_input_cache() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_cursor_id() -> ResultType<(id, u64, f64)> {
|
fn get_cursor_id(scale: f64) -> ResultType<(id, u64)> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let c: id = msg_send![class!(NSCursor), currentSystemCursor];
|
let c: id = msg_send![class!(NSCursor), currentSystemCursor];
|
||||||
if c == nil {
|
if c == nil {
|
||||||
@@ -622,19 +625,25 @@ fn get_cursor_id() -> ResultType<(id, u64, f64)> {
|
|||||||
hcursor += (r + g + b + a) * (255 << i) as f64;
|
hcursor += (r + g + b + a) * (255 << i) as f64;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let scale = cursor::scale()?;
|
Ok((c, cursor::cache_id(hcursor as _, scale)))
|
||||||
Ok((c, cursor::cache_id(hcursor as _, scale), scale))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_cursor_data(hcursor: u64) -> ResultType<CursorData> {
|
pub fn get_cursor_data(hcursor: u64) -> ResultType<CursorData> {
|
||||||
autoreleasepool(|| unsafe_get_cursor_data(hcursor))
|
let result = autoreleasepool(|| unsafe_get_cursor_data(hcursor));
|
||||||
|
if result.is_err() {
|
||||||
|
// A failed capture must be retried even if the seed and density stay unchanged.
|
||||||
|
reset_input_cache();
|
||||||
|
}
|
||||||
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/stweil/OSXvnc/blob/master/OSXvnc-server/mousecursor.c
|
// https://github.com/stweil/OSXvnc/blob/master/OSXvnc-server/mousecursor.c
|
||||||
fn unsafe_get_cursor_data(hcursor: u64) -> ResultType<CursorData> {
|
fn unsafe_get_cursor_data(hcursor: u64) -> ResultType<CursorData> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let (c, hcursor2, scale) = get_cursor_id()?;
|
// Keep the poll's density if the pointer crosses displays before capture.
|
||||||
|
let scale = LATEST_SEED.1;
|
||||||
|
let (c, hcursor2) = get_cursor_id(scale)?;
|
||||||
if hcursor != hcursor2 {
|
if hcursor != hcursor2 {
|
||||||
bail!("cursor changed");
|
bail!("cursor changed");
|
||||||
}
|
}
|
||||||
|
|||||||
17
src/platform/macos/cursor_poll_tests.rs
Normal file
17
src/platform/macos/cursor_poll_tests.rs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn capture_failure_invalidates_the_density_poll() {
|
||||||
|
let previous = unsafe { LATEST_SEED };
|
||||||
|
unsafe {
|
||||||
|
LATEST_SEED = (1, 2.0);
|
||||||
|
}
|
||||||
|
// Zero cannot be a macOS cursor ID, even if AppKit has no current cursor.
|
||||||
|
let result = get_cursor_data(0);
|
||||||
|
let after_failure = unsafe { LATEST_SEED };
|
||||||
|
unsafe {
|
||||||
|
LATEST_SEED = previous;
|
||||||
|
}
|
||||||
|
assert!(result.is_err());
|
||||||
|
assert_eq!(after_failure, (0, 0.0));
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user