From f9fd0313cb0cea6c9f1bba1cd14da43b98ab405b Mon Sep 17 00:00:00 2001 From: Max <112043822+Maxaubert@users.noreply.github.com> Date: Sat, 7 Nov 2026 12:24:35 +0100 Subject: [PATCH] mac: fix the drawn cursor stuck on a stale shape after zoom-in ClearCursor.start took the current system cursor as the drawn shape but kept the pixel key from the last session. When the pointer sat on text at zoom-in (I-beam) and the last session ended on an arrow, the next arrow read matched that old key, counted as a repeat, and the I-beam stayed until zoom-out. start now clears the key with the new shape. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01SkyGaTQ1FTFz3Zwo4nohwd --- mac/Sources/Wind/ClearCursor.swift | 4 +++- mac/VERSION | 2 +- mac/docs/architecture.md | 4 +++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/mac/Sources/Wind/ClearCursor.swift b/mac/Sources/Wind/ClearCursor.swift index ff38e64c..966682af 100644 --- a/mac/Sources/Wind/ClearCursor.swift +++ b/mac/Sources/Wind/ClearCursor.swift @@ -101,7 +101,9 @@ final class ClearCursor: @unchecked Sendable { let first = NSCursor.currentSystem lock.lock() active = true; stalled = false; session += 1 - if let c = first, !isClear(c) { appCursor = c; shapeGen += 1 } + // The key goes with the shape: a key left from the last session (an arrow) made the next arrow read + // a repeat, and a first-frame I-beam was drawn until Wind zoomed out (owner 2026-11-07). + if let c = first, !isClear(c) { appCursor = c; appKey = nil; shapeGen += 1 } beat = CACurrentMediaTime() let s = session lock.unlock() diff --git a/mac/VERSION b/mac/VERSION index d1d899fa..b49b2533 100644 --- a/mac/VERSION +++ b/mac/VERSION @@ -1 +1 @@ -0.5.5 +0.5.6 diff --git a/mac/docs/architecture.md b/mac/docs/architecture.md index 10551b1b..30951e33 100644 --- a/mac/docs/architecture.md +++ b/mac/docs/architecture.md @@ -767,7 +767,9 @@ through) and macOS zoom itself are not involved (research/wind-mac/re/2026-11-02 unless the cursor seed moved since, and Wind's transparent set moves it, so at 1x those sets cost nothing (0 seed bumps) and zoomed each one showed the real cursor until the poll's re-set (owner 2026-11-04, ChatGPT: flicker while moving). `ClearCursor` reads the same shape (pixels) set twice within - 1 s as that signature: for 0.5 s after each such set the poll thread also hides the real cursor, which no + 1 s as that signature (the pixel key is cleared with each new shape `start` takes: a key left from the + last session made the next arrow a "repeat" and a first-frame I-beam stuck until zoom-out, owner + 2026-11-07): for 0.5 s after each such set the poll thread also hides the real cursor, which no set shows through. It hides on that thread with its own balanced hide count (per process): on the main thread each hide stopped the tick 10-30 ms. The poll keeps re-setting the transparent image meanwhile: an app switch force-shows even a hidden cursor (the poll re-hides it). Hover arriving during the hide is ignored, and