mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-09-14 00:11:01 +03:00
Report Linux cursor density independently of the host UI
This commit is contained in:
@@ -25,7 +25,7 @@ inline = []
|
||||
use_samplerate = ["samplerate"]
|
||||
use_rubato = ["rubato"]
|
||||
use_dasp = ["dasp"]
|
||||
flutter = ["flutter_rust_bridge", "dep:x11rb"]
|
||||
flutter = ["flutter_rust_bridge"]
|
||||
default = ["use_dasp"]
|
||||
hwcodec = ["scrap/hwcodec"]
|
||||
vram = ["scrap/vram"]
|
||||
@@ -40,7 +40,6 @@ drm-wake = ["drm"]
|
||||
linux-pkg-config = ["magnum-opus/linux-pkg-config", "scrap/linux-pkg-config"]
|
||||
unix-file-copy-paste = [
|
||||
"dep:x11-clipboard",
|
||||
"dep:x11rb",
|
||||
"dep:percent-encoding",
|
||||
"dep:once_cell",
|
||||
"clipboard/unix-file-copy-paste",
|
||||
@@ -191,7 +190,7 @@ evdev = { git="https://github.com/rustdesk-org/evdev" }
|
||||
dbus = "0.9"
|
||||
dbus-crossroads = "0.5"
|
||||
x11-clipboard = {git="https://github.com/clslaid/x11-clipboard", branch = "feat/store-batch", optional = true}
|
||||
x11rb = {version = "0.12", features = ["all-extensions"], optional = true}
|
||||
x11rb = {version = "0.12", features = ["all-extensions"]}
|
||||
percent-encoding = {version = "2.3", optional = true}
|
||||
once_cell = {version = "1.18", optional = true}
|
||||
nix = { version = "0.29", features = ["term", "process"]}
|
||||
|
||||
@@ -35,11 +35,7 @@ use std::{
|
||||
use terminfo::{capability as cap, Database};
|
||||
use wallpaper;
|
||||
|
||||
// Scope density lookup to Flutter host builds to preserve legacy capture
|
||||
// behavior. These builds include density in cursor IDs to refresh on DPI
|
||||
// changes; non-Flutter builds retain original IDs and unknown density.
|
||||
// This gate describes the host binary, not the connected controller's UI.
|
||||
#[cfg(feature = "flutter")]
|
||||
// Cursor density is capture metadata, independent of either endpoint's UI.
|
||||
mod cursor;
|
||||
|
||||
pub const PA_SAMPLE_RATE: u32 = 48000;
|
||||
@@ -577,11 +573,8 @@ pub fn get_cursor() -> ResultType<Option<u64>> {
|
||||
// polled there is a live session, which is the case the latch reads correctly.
|
||||
#[cfg(feature = "drm")]
|
||||
if !is_x11() {
|
||||
#[cfg(feature = "flutter")]
|
||||
let cursor = cursor::drm_snapshot(|c| c.id)?
|
||||
.map(|(id, scale)| cursor::cache_id(id, scale));
|
||||
#[cfg(not(feature = "flutter"))]
|
||||
let cursor = crate::server::drm_capturer::drm_cursor_id();
|
||||
if let Some(id) = cursor {
|
||||
// In a mixed DRM + PipeWire session the DRM streams only cover the DRM-backed displays;
|
||||
// when the pointer sits on a PipeWire-served display every DRM stream reports the hidden
|
||||
@@ -610,7 +603,6 @@ pub fn get_cursor() -> ResultType<Option<u64>> {
|
||||
}
|
||||
}
|
||||
});
|
||||
#[cfg(feature = "flutter")]
|
||||
let res = res.map(cursor::x11_cursor_id);
|
||||
Ok(res)
|
||||
}
|
||||
@@ -624,13 +616,8 @@ pub fn get_cursor_data(hcursor: u64) -> ResultType<CursorData> {
|
||||
// agree anyway, since a caller that took the DRM branch there has to take it here.
|
||||
#[cfg(feature = "drm")]
|
||||
if !is_x11() {
|
||||
#[cfg(feature = "flutter")]
|
||||
let cursor = cursor::drm_snapshot(Clone::clone)?;
|
||||
#[cfg(not(feature = "flutter"))]
|
||||
let cursor = crate::server::drm_capturer::drm_cursor();
|
||||
if let Some(c) = cursor {
|
||||
#[cfg(feature = "flutter")]
|
||||
let (c, scale) = c;
|
||||
if let Some((c, scale)) = cursor {
|
||||
// See get_cursor(): a hidden DRM sentinel is authoritative only in a pure-DRM session. In
|
||||
// a mixed DRM + PipeWire session fall through so the PipeWire display's cursor is served
|
||||
// by the normal path instead of being hidden everywhere.
|
||||
@@ -638,27 +625,19 @@ pub fn get_cursor_data(hcursor: u64) -> ResultType<CursorData> {
|
||||
|| !crate::server::display_service::has_non_drm_backed_display()
|
||||
{
|
||||
let mut cd: CursorData = Default::default();
|
||||
cd.id = c.id;
|
||||
cd.id = cursor::cache_id(c.id, scale);
|
||||
cd.scale = scale;
|
||||
cd.width = c.width;
|
||||
cd.height = c.height;
|
||||
cd.hotx = c.hotx;
|
||||
cd.hoty = c.hoty;
|
||||
cd.colors = c.colors.into();
|
||||
#[cfg(feature = "flutter")]
|
||||
{
|
||||
cd.id = cursor::cache_id(cd.id, scale);
|
||||
cd.scale = scale;
|
||||
}
|
||||
return Ok(cd);
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "flutter")]
|
||||
let scale = cursor::x11_cursor_scale();
|
||||
#[cfg(feature = "flutter")]
|
||||
let matches = |id| cursor::cache_id(id, scale) == hcursor;
|
||||
#[cfg(not(feature = "flutter"))]
|
||||
let matches = |id| id == hcursor;
|
||||
let mut res = None;
|
||||
DISPLAY.with(|conn| {
|
||||
if let Ok(ref mut d) = conn.try_borrow_mut() {
|
||||
@@ -673,10 +652,7 @@ pub fn get_cursor_data(hcursor: u64) -> ResultType<CursorData> {
|
||||
cd.height = (*img).height as _;
|
||||
// to-do: how about if it is 0
|
||||
cd.id = hcursor;
|
||||
#[cfg(feature = "flutter")]
|
||||
{
|
||||
cd.scale = scale;
|
||||
}
|
||||
cd.scale = scale;
|
||||
let pixels =
|
||||
std::slice::from_raw_parts((*img).pixels, (cd.width * cd.height) as _);
|
||||
// cd.colors.resize(pixels.len() * 4, 0);
|
||||
|
||||
@@ -14,7 +14,6 @@ use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::{Arc, Condvar, Mutex};
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
#[cfg(feature = "flutter")]
|
||||
mod cursor_metadata;
|
||||
|
||||
const HANDSHAKE_TIMEOUT_MS: u64 = 3000;
|
||||
@@ -958,26 +957,8 @@ fn fold_cursor_id(id: u64, t: i32) -> u64 {
|
||||
}
|
||||
}
|
||||
|
||||
fn with_drm_cursor<T>(f: impl Fn(&DrmCursorData) -> T) -> Option<T> {
|
||||
let map = DRM_CURSOR.lock().unwrap();
|
||||
map.values()
|
||||
.map(|(_, c)| c)
|
||||
.find(|c| c.id != scrap::drm_reader::HIDDEN_CURSOR_ID)
|
||||
.or_else(|| map.values().map(|(_, c)| c).next())
|
||||
.map(f)
|
||||
}
|
||||
|
||||
pub fn drm_cursor_id() -> Option<u64> {
|
||||
with_drm_cursor(|c| c.id)
|
||||
}
|
||||
|
||||
/// Snapshot of the DRM hardware cursor, or None. The pixels are premultiplied ARGB and are passed
|
||||
/// through as-is, like the XFixes path, so the client sees one cursor format from either backend.
|
||||
pub fn drm_cursor() -> Option<DrmCursorData> {
|
||||
with_drm_cursor(|c| c.clone())
|
||||
}
|
||||
|
||||
#[cfg(feature = "flutter")]
|
||||
/// Snapshot of the DRM hardware cursor and optional display metadata. Pixels retain the
|
||||
/// premultiplied format used by the XFixes path.
|
||||
pub fn drm_cursor_snapshot<T>(
|
||||
f: impl Fn(&DrmCursorData) -> T,
|
||||
) -> Option<(T, Option<base::platform::linux::WaylandDisplayInfo>)> {
|
||||
@@ -1019,7 +1000,6 @@ pub fn drm_cursor_snapshot<T>(
|
||||
Some((value, monitor))
|
||||
}
|
||||
|
||||
#[cfg(feature = "flutter")]
|
||||
fn cursor_monitor(
|
||||
display: usize,
|
||||
state: &ProbeState,
|
||||
@@ -2332,7 +2312,6 @@ mod drm_capturer_tests {
|
||||
assert!(m2[0].is_none() && m2[1].is_none());
|
||||
}
|
||||
|
||||
#[cfg(feature = "flutter")]
|
||||
#[test]
|
||||
fn cursor_monitor_reserves_other_displays_before_guessing_density() {
|
||||
let state = ProbeState::Available(
|
||||
|
||||
Reference in New Issue
Block a user