From 6e2d838bf1763aba67cbc8e4a636eacbc27603df Mon Sep 17 00:00:00 2001 From: fufesou Date: Sat, 12 Sep 2026 22:56:13 +0800 Subject: [PATCH] Keep density-aware cursor IDs compatible with legacy Web clients --- src/platform/linux/cursor.rs | 17 +++++++++++++++-- src/platform/macos/cursor.rs | 13 ++++++++++++- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/platform/linux/cursor.rs b/src/platform/linux/cursor.rs index 2a9c1b24f..0b7a9e1a9 100644 --- a/src/platform/linux/cursor.rs +++ b/src/platform/linux/cursor.rs @@ -17,12 +17,14 @@ thread_local! { } pub(super) fn cache_id(id: u64, scale: f64) -> u64 { + // Legacy Web decoders require JS-safe integers; zero is the service's initial ID. + const MAX_CURSOR_ID: u64 = (1 << 53) - 1; if scale == 0.0 { return id; } let mut hash = DefaultHasher::new(); (id, scale.to_bits()).hash(&mut hash); - hash.finish() + hash.finish() % MAX_CURSOR_ID + 1 } pub(super) fn x11_cursor_id(id: u64) -> u64 { @@ -129,10 +131,21 @@ fn wayland_scale(display: &base::platform::linux::WaylandDisplayInfo) -> ResultT Ok(f64::from(width) / f64::from(logical_width)) } -#[cfg(all(test, feature = "drm"))] +#[cfg(test)] mod tests { use super::*; + #[test] + fn cursor_cache_ids_fit_legacy_web_numbers() { + for cursor in [1, 123, u64::MAX] { + assert_eq!(cache_id(cursor, 0.0), cursor); + for scale in [1.0, 1.25, 2.0] { + assert!((1..=9_007_199_254_740_991).contains(&cache_id(cursor, scale))); + } + } + } + + #[cfg(feature = "drm")] #[test] fn cursor_density_tracks_fractional_rotation_and_cache_identity() { let display = base::platform::linux::WaylandDisplayInfo { diff --git a/src/platform/macos/cursor.rs b/src/platform/macos/cursor.rs index 3d50f2cd0..b0e53b4d7 100644 --- a/src/platform/macos/cursor.rs +++ b/src/platform/macos/cursor.rs @@ -40,9 +40,11 @@ pub(super) fn scale() -> ResultType { } pub(super) fn cache_id(cursor: u64, scale: f64) -> u64 { + // Legacy Web decoders require JS-safe integers; zero is the service's initial ID. + const MAX_CURSOR_ID: u64 = (1 << 53) - 1; let mut hash = DefaultHasher::new(); (cursor, scale.to_bits()).hash(&mut hash); - hash.finish() + hash.finish() % MAX_CURSOR_ID + 1 } unsafe fn bitmap(size: NSSize) -> ResultType { @@ -239,4 +241,13 @@ mod tests { fn cursor_cache_changes_with_display_scale() { assert_ne!(cache_id(123, 1.0), cache_id(123, 2.0)); } + + #[test] + fn cursor_cache_ids_fit_legacy_web_numbers() { + for cursor in [1, 123, u64::MAX] { + for scale in [1.0, 1.25, 2.0] { + assert!((1..=9_007_199_254_740_991).contains(&cache_id(cursor, scale))); + } + } + } }