Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ impl RenderStateCore {
let palette = cfg.palette();
let motion = cfg.motion.clone();
let shape = cfg.shape.clone();
let visible = cfg.enabled;
Self {
Comment on lines +99 to 100

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Keep cfg.enabled and visible in sync to avoid stale enablement checks.

RenderStateCore::new now initializes visible from cfg.enabled, but runtime toggles (OverlayCommand::SetEnabled) still mutate only visible. Since animate_cursor_to gates on rs.core.cfg.enabled in platform-macos/src/cursor/overlay.rs (Line 308), enable/disable state can diverge and break animation gating after toggles.

Suggested fix
diff --git a/libs/cua-driver/rust/crates/cursor-overlay/src/render_state.rs b/libs/cua-driver/rust/crates/cursor-overlay/src/render_state.rs
@@
             OverlayCommand::SetEnabled(v) => {
                 self.visible = v;
+                self.cfg.enabled = v;
                 true
             }

Also applies to: 115-115

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@libs/cua-driver/rust/crates/cursor-overlay/src/render_state.rs` around lines
99 - 100, The issue is that visible and cfg.enabled can diverge after
initialization. While RenderStateCore::new initializes visible from cfg.enabled,
the OverlayCommand::SetEnabled handler only mutates visible without updating
cfg.enabled. This causes the animation gating check in animate_cursor_to (which
uses cfg.enabled) to become stale after toggles. Fix this by ensuring that
whenever the enabled state is toggled in the SetEnabled handler at line 115,
both visible and cfg.enabled are updated together to keep them synchronized.

cfg,
palette,
Expand All @@ -111,7 +112,7 @@ impl RenderStateCore {
spring_tgt: None,
click_t: None,
pressed: false,
visible: true,
visible, // was hardcoded true — respect config.enabled (#1777)
idle_secs: 0.0,
idle_alpha: 1.0,
pinned_wid: None,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,10 @@ pub fn init(cfg: CursorConfig) {
*CMD_RX_CELL.lock().unwrap() = Some(rx);
*ARRIVAL_TX.lock().unwrap() = Some(HashMap::new());
let mut cursors = IndexMap::new();
cursors.insert("default".to_owned(), RenderState::new(cfg.clone()));
// Default cursor starts disabled — see state.rs:new() and #1777.
let mut default_cfg = cfg.clone();
default_cfg.enabled = false;
cursors.insert("default".to_owned(), RenderState::new(default_cfg));
*RENDER.lock().unwrap() = Some(RenderMap {
cursors,
win_w: 0.0,
Expand Down
25 changes: 18 additions & 7 deletions libs/cua-driver/rust/crates/platform-macos/src/cursor/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,17 @@ pub struct CursorRegistry {
impl CursorRegistry {
pub fn new() -> Self {
let mut map = HashMap::new();
let default_cfg = CursorConfig {
// Default cursor starts DISABLED. The anonymous / non-session
// path must never render a cursor — the documented contract is
// "without a session, actions run cursor-less." A session's
// first enable/start_session call activates its own cursor.
// See #1777.
enabled: false,
..CursorConfig::default()
};
let default = CursorState {
config: CursorConfig::default(),
config: default_cfg,
position: None,
};
map.insert("default".into(), default);
Expand Down Expand Up @@ -203,15 +212,17 @@ mod tests {
}

#[test]
fn default_cursor_unaffected_by_guard() {
// "default" is seeded and is never tombstoned — its mutators still work.
fn default_cursor_starts_disabled() {
// Default cursor is seeded disabled — anonymous calls must be
// cursor-less per the documented contract. See #1777.
let reg = CursorRegistry::new();
assert!(!cua_driver_core::session::is_session_ended("default"));
reg.set_enabled("default", false);
reg.update_position("default", 1.0, 2.0);
let s = reg.get("default").expect("default cursor always present");
assert!(!s.config.enabled);
assert_eq!(s.position.as_ref().map(|p| (p.x, p.y)), Some((1.0, 2.0)));
assert!(!s.config.enabled, "default cursor must start disabled");
// But mutators still work — a session that enables it should succeed.
reg.set_enabled("default", true);
let s2 = reg.get("default").unwrap();
assert!(s2.config.enabled);
}

#[test]
Expand Down