From 4eb36873d4ca4b0faf0e54dbeab8f5f6450dd704 Mon Sep 17 00:00:00 2001 From: srdusr <99972264+srdusr@users.noreply.github.com> Date: Fri, 3 Oct 2025 22:59:00 +0200 Subject: Make the secondary-cursor sprite opt-in and expire stale entries Live report: a second cursor appeared uninvited and unusably (frozen, uncontrollable) on screen. Multi-cursor Phase 1 rendered one sprite per physical libinput pointer device that had ever reported a position, with no way to turn it off and no expiry - so a phantom device (a real mouse's side-button/scroll cluster enumerating as its own HID path is a common case) that reports once and never moves again left a frozen ghost sprite with nothing to control or dismiss it. Adds general.multi_cursor (default false, live-settable via `srd set multi_cursor `) and keys secondary_cursors to (Point, Instant) so both the recording side (udev/session.rs) and the render side (udev/render.rs) drop any entry older than SECONDARY_CURSOR_TIMEOUT (1.5s). The "agent controls a window without interrupting the user" use case this report also raised was never gated on this flag - that's Multi-cursor Phase 2's pinned virtual-pointer delivery, which never shows a visible cursor at all. --- crates/platform/src/ipc/dispatch.rs | 9 +++++++++ crates/platform/src/ipc/types.rs | 2 ++ 2 files changed, 11 insertions(+) (limited to 'crates/platform/src/ipc') diff --git a/crates/platform/src/ipc/dispatch.rs b/crates/platform/src/ipc/dispatch.rs index 5a969c7..313a79c 100644 --- a/crates/platform/src/ipc/dispatch.rs +++ b/crates/platform/src/ipc/dispatch.rs @@ -27,6 +27,7 @@ pub(crate) fn handle_request(line: &[u8], wm: &std::rc::Rc` - live equivalent of `general. + // multi_cursor`. See `WindowManager::multi_cursor_enabled`'s own + // doc comment for why this is opt-in rather than always-on. + "multi_cursor" => { + let Some(v) = value.and_then(|v| v.as_bool()) else { return (err("multi_cursor needs a boolean value"), false) }; + wm.borrow_mut().multi_cursor_enabled = v; + (ok(), true) + } "blur" => (err("blur is not supported - no GPU shader path on this compositor's software renderer yet"), false), // The two ported Hyprland `decoration:screen_shader` scripts -- // mutually exclusive by construction (`srdwm_core::ColorFilter` is diff --git a/crates/platform/src/ipc/types.rs b/crates/platform/src/ipc/types.rs index 08c2d7e..1dc95f6 100644 --- a/crates/platform/src/ipc/types.rs +++ b/crates/platform/src/ipc/types.rs @@ -148,6 +148,8 @@ pub(crate) struct SettingsResponse { /// without a second, separate way to ask "is this a phone-shaped /// session". pub(crate) phone_mode: bool, + /// `WindowManager::multi_cursor_enabled`'s own doc comment. + pub(crate) multi_cursor: bool, } /// `"keyboard_layout"`'s one-shot reply shape - the active XKB layout's -- cgit v1.2.3