Skip to content

Fix hotkey not reliably summoning the palette (v0.1.15)#19

Merged
archdex-art merged 1 commit into
mainfrom
fix/hotkey-reliability
Jul 17, 2026
Merged

Fix hotkey not reliably summoning the palette (v0.1.15)#19
archdex-art merged 1 commit into
mainfrom
fix/hotkey-reliability

Conversation

@archdex-art

Copy link
Copy Markdown
Owner

Investigation

User reported the global hotkey "not triggering most of the times" after resolving an unrelated port-5173 conflict with cargo tauri dev. Traced to three separate, factually-confirmed issues rather than assumed OS flakiness:

  1. ps aux showed two live supersearch-app processes running concurrently (a leftover /Applications install alongside the dev session). Each process loads its own SettingsStore once at its own boot and independently registers the same global hotkey — two processes racing for one OS-level hotkey means summoning "the palette" nondeterministically shows either one's window.
  2. grep-confirmed absence of any NSApplication/activateIgnoringOtherApps: call anywhere in the codebase. The palette runs under ActivationPolicy::Accessory (no Dock icon) — the one case where WebviewWindow::set_focus() alone is known-unreliable on macOS: it calls makeKeyAndOrderFront: on the window but never activates the process. Summoned via a background hotkey while a different app holds focus, the window can end up shown but never actually key — silently swallows all keyboard input, indistinguishable from "the hotkey did nothing."
  3. closingRef read a stale value across a real timing gap. It mirrored closing React state via a useEffect, which only runs after React commits the next render — a hotkey re-summon landing in that gap (e.g. right after hide_on_blur starts a close) read the previous value and took the wrong branch, calling hide() again (a no-op) instead of cancelling the close and reopening.

Fix

  • Added tauri-plugin-single-instance, registered first (Tauri's required order). A second launch now re-summons the one running instance's palette instead of starting a competing process.
  • show_palette now calls activateIgnoringOtherApps: on NSApplication (via the same objc2 FFI pattern already used for enable_fullscreen_overlay) before focusing the window.
  • closingRef is now updated synchronously at the same call site as setClosing (via a new setClosingBoth helper), eliminating the effect-timing gap entirely instead of narrowing it.

Verification

  • cargo check/cargo test (17/17) clean, tsc --noEmit clean.
  • Single-instance: built the binary, launched it twice, confirmed via ps that the second process exits cleanly (defunct, exit status 0) and exactly one process stays alive.
  • Killed the two actually-running duplicate processes on this machine as part of the investigation.
  • Could not get a conclusive live GUI confirmation of the activation fix in this sandbox — it has no attached display/WindowServer session (screencapture fails outright, and System Events GUI-scripting queries were flaky/inconsistent even for basic window-count checks). The fix itself is grounded in a directly-confirmed gap (grep found zero activation calls) and a well-documented AppKit behavior, not a guess, but flagging that I could not visually reproduce-then-confirm-fixed on real hardware from here.
  • Bumped src-tauri/tauri.conf.json + Cargo.toml/Cargo.lock to 0.1.15, added CHANGELOG entry.

Three fixes found while tracing 'hotkey doesn't trigger most of the time'
back to real, factually-confirmed causes:

- Two competing processes could run simultaneously (a stray /Applications
  install alongside a cargo tauri dev session), each with its own
  independently-cached SettingsStore and its own attempt at registering the
  same global hotkey — confirmed via ps aux showing both alive at once.
  Added tauri-plugin-single-instance so a second launch just re-summons the
  running instance's palette instead of starting a competing process.
  Verified live: launching the built binary twice leaves exactly one
  process alive, confirmed via ps that the second exits (defunct, status 0).

- The palette runs under ActivationPolicy::Accessory (no Dock icon) — the
  one case where WebviewWindow::set_focus() alone is unreliable on macOS.
  It calls makeKeyAndOrderFront: on the window but never activates the
  process; summoned via a background hotkey while another app holds focus,
  the window could end up shown but not actually key, silently swallowing
  keyboard input. Confirmed via grep that this codebase never called
  NSApplication activateIgnoringOtherApps: anywhere. Added it to
  show_palette.

- closingRef (lets the toggle-hotkey listener tell 'idle' apart from
  'mid-close-animation') was mirrored from React state via a useEffect,
  which only runs after React commits — a hotkey press landing in that gap
  read a stale value and silently no-op'd instead of cancelling the close
  and reopening. Now updated synchronously at the same call site as
  setClosing.

Bump to v0.1.15, changelog entry.
@archdex-art
archdex-art merged commit 8db7b0a into main Jul 17, 2026
4 checks passed
@archdex-art
archdex-art deleted the fix/hotkey-reliability branch July 17, 2026 08:30
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