Skip to content

fix(macos): restore the Dock presence only when it is gone (#1305) - #1309

Merged
eneskirca merged 1 commit into
mainfrom
fix/dock-duplicate-icon
Oct 26, 2026
Merged

eneskirca merged 1 commit into
mainfrom
fix/dock-duplicate-icon

Conversation

@eneskirca

Copy link
Copy Markdown
Owner

Addresses #1305: on macOS, nodeterm can show twice in the Dock. The pinned tile has no running dot, and a second tile in the "recent apps" section is the instance that is actually running. Clicking the pinned tile looks like it opens a new instance.

What changed

assertRegularDockPresence (added in v0.2.25 so the focusable:false Notch HUD panel cannot cost the app its Dock tile) called setActivationPolicy('regular') and app.dock.show() unconditionally. It ran on every main-window show, on HUD creation and on HUD load, and its comment called this idempotent. It is not: Electron's dock.show() calls TransformProcessType every time, and transforming an app that is already a foreground app is a known way to get a duplicate Dock tile.

The decision moved to the Electron-free src/main/dock-presence.ts. It now acts only when app.dock.isVisible() (the current activation policy is Regular) says the tile is really gone, or when that read fails. The case the HUD fix exists for is unchanged.

How it was checked

  • On an affected machine (macOS 27.0, nodeterm 0.4.5): one running process, but the Dock plist holds nodeterm in both persistent-apps and recent-apps, both pointing at the same /Applications/nodeterm.app and com.nodeterm.app, with bookmarks that resolve and are not stale. So the Dock fails to match the running app to its pinned tile; it is not a second instance and not a path mismatch.
  • New unit tests (dock-presence.test.ts): already visible means no calls; dropped means restore; a failed read means restore; no dock API; non-macOS is a no-op.
  • window-raise.guard.test.ts: the dock.show() allowlist entry moved from notch-hud.ts to dock-presence.ts with the same reason.
  • npm run typecheck, plus the notch-hud and raise-guard suites.

Not verified

  • The cause is a strong hypothesis, not proven. I did not reproduce the duplicate tile on demand: that needs a pinned Dock tile, and I did not change the Dock of the machine I measured on. This code dates from July, while the reports say "a few updates ago", so a macOS change (27.0 here) may be what made it visible.
  • Device check after install: quit fully, open from the pinned tile, then (1) close the window and bring it back from the Dock, and (2) let the Notch HUD open and close. The recent-apps duplicate must not come back, and the HUD must still not drop the Dock icon.

🤖 Generated with Claude Code

https://claude.ai/code/session_013CkS8j5hok95yvLSB16R3f

assertRegularDockPresence called app.dock.show() on every main-window
show and on every HUD create/load, on the claim that it was idempotent.
Electron's dock.show() calls TransformProcessType each time, and
transforming an app that is already a foreground app can leave the Dock
showing it twice: the pinned tile without a running dot, plus a "recent
apps" tile that is the running one. Clicking the pinned tile then reads
as opening a second instance.

The decision now lives in the Electron-free dock-presence.ts and acts
only when app.dock.isVisible() says the app is not a regular Dock app
(or the read fails), which is the case the HUD fix was written for.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013CkS8j5hok95yvLSB16R3f
@eneskirca
eneskirca merged commit 57f3249 into main Oct 26, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant