macOS launcher: handle reopen while already running with no window

Quitting the real GUI binary (Cmd+Q) leaves the launcher itself still
running — that's by design, so it can keep relaying opens for the
session. But reopening the app afterward (Dock icon, double-clicking
it in Finder again) reactivates that same long-lived launcher process
rather than triggering a fresh cold launch, since Launch Services
still considers the bundle running. Neither of the delegate methods
already handled covered that: applicationDidFinishLaunching: only
fires once, at the launcher's own original cold start, and
application:openURLs: only fires when a document was named. The net
effect: the Dock icon would appear, but no window ever showed.

applicationShouldHandleReopen:hasVisibleWindows: is exactly the
callback AppKit fires for this reactivation case. Reproduced and
verified the fix against the real sequence (cold launch, kill only the
GUI process to simulate Cmd+Q, reopen) rather than assuming it from
the delegate method's docs alone.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
Felix RiestraandClaude Sonnet 5 committed 2026-09-07 17:34:57 +02:00
1 parent e767507850
commit 24e9a7663d
1 file changed
+17
+17
View File
@@ -147,6 +147,23 @@ declare_class!(
.collect();
deliver_or_launch(&files);
}
/// Fires when this already-running process is reactivated with no
/// visible windows to show — clicking the Dock icon, or Finder
/// launching the bundle again while Launch Services still considers
/// it running (this launcher's own ASN never dies between opens; see
/// the module doc). Without this, quitting the real GUI window while
/// this relay stays alive left the app in a state where reopening it
/// did nothing: no fresh `applicationDidFinishLaunching:` (that only
/// fires once, at this process's own cold start) and no
/// `application:openURLs:` (no document was named).
#[method(applicationShouldHandleReopen:hasVisibleWindows:)]
fn should_handle_reopen(&self, _sender: &NSApplication, has_visible_windows: bool) -> bool {
if !has_visible_windows {
deliver_or_launch(&[]);
}
true
}
}
);