Skip to content

fix(plugins): hide the window before running quit hooks (#94) - #97

Merged
kipavy merged 1 commit into
devfrom
fix/close-hide-window-94
Aug 10, 2026
Merged

fix(plugins): hide the window before running quit hooks (#94)#97
kipavy merged 1 commit into
devfrom
fix/close-hide-window-94

Conversation

@kipavy

@kipavy kipavy commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Fixes #94. Based on @Flash303's diagnosis and patch in #95 — the approach here is theirs, with two extra safety fixes.

Cause

ensureQuitHandler() (src/plugins/runtime.ts) intercepts onCloseRequested, calls preventDefault(), and then awaits every plugin onBeforeQuit callback (capped at 5s) before triggering the Rust-side exit. The window stays on screen for that entire wait. The gist-sync plugin pushes to GitHub in its quit hook, so closing the app looked frozen for ~2s. With no plugin registering a quit hook the handler is never installed at all, which is why this only reproduces with a plugin like gist-sync enabled.

Change

  • Hide the window before awaiting the hooks, so the wait is invisible and the app appears to close instantly. Requires the core:window:allow-hide capability (not part of core:default).
  • Only hide when a quit hook is actually registered; with none, close immediately as before.
  • Arm the Rust-side exit up front with a fallback timer and call it from a finally block. Without this, a throwing hook or an invoke that never lands would leave a hidden window over a live process — worse than a slow close.
  • Wrap hook invocation in an async function so a synchronous throw becomes a rejection instead of escaping the handler.

Tests

New src/plugins/runtime.quitHandler.test.ts covers: hide precedes the hook, no hide when there are zero hooks, exit still happens when a hook throws, and exit on the 5s cap with the fallback timer disarmed (force_quit invoked exactly once). pnpm tsc --noEmit clean; pnpm vitest run src/plugins green (73 files, 593 tests).

Live verification

Debug build driven under Xvfb/WebKitGTK through tauri-driver, with a test plugin whose quit hook runs for ~2.4s:

  • Close fired, hook ran, plugin:window|is_visible sampled from inside the hook: false at every sample from 303ms onward through 2429ms — the window is gone while the sync is still running.
  • Process exited 2.97s after the close was fired, i.e. right after the hook finished, not on the 6s fallback.
  • With the hook unregistered, the process exited 240ms after the close was fired (that figure includes the harness round-trip), and no hide occurred.

Not verified on Windows — no Windows machine here. The mechanism is platform-independent, but @Flash303 confirmed the original symptom and fix on Windows 11.

Closing kept the window on screen for as long as the slowest plugin
onBeforeQuit callback took — gist-sync pushes to GitHub on exit, so the
app looked frozen for ~2s. Hide the window first so the wait is
invisible, and only when a hook is actually registered.

Arm the Rust-side exit up front with a fallback timer and quit from a
finally block, so a throwing hook or a failed invoke can never leave a
hidden window over a live process.
@kipavy
kipavy merged commit 26e0438 into dev Aug 10, 2026
3 of 4 checks passed
@kipavy
kipavy deleted the fix/close-hide-window-94 branch August 10, 2026 16:28
@Flash303

Copy link
Copy Markdown

Not verified on Windows — no Windows machine here. The mechanism is platform-independent, but @Flash303 confirmed the original symptom and fix on Windows 11.

Works well on Windows, thanks and waiting for the release !!

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.

2 participants