From 24e9a7663d56de64bd959a29949f0fb19addf00f Mon Sep 17 00:00:00 2001 From: Felix Riestra Date: Mon, 7 Sep 2026 17:34:57 +0200 Subject: [PATCH] macOS launcher: handle reopen while already running with no window MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- src/bin/ocs_launcher.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/bin/ocs_launcher.rs b/src/bin/ocs_launcher.rs index 7f538b68e..9e2c4aab7 100644 --- a/src/bin/ocs_launcher.rs +++ b/src/bin/ocs_launcher.rs @@ -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 + } } );