Skip to content

macOS: optionally route native Quit through CloseRequested - #4692

Open
crmne wants to merge 1 commit into
rust-windowing:v0.30.xfrom
crmne:macos-quit-as-close
Open

crmne wants to merge 1 commit into
rust-windowing:v0.30.xfrom
crmne:macos-quit-as-close

Conversation

@crmne

@crmne crmne commented Sep 14, 2026

Copy link
Copy Markdown

Native macOS Quit currently terminates the process without giving window close handlers a chance to review unsaved work. It also prevents run_app_on_demand from returning to code that owns cleanup guards. This adds an opt-in macos-quit-as-close feature on the 0.30 maintenance branch; default behavior stays unchanged.

applicationShouldTerminate: returns NSTerminateCancel, records one coalesced request and wakes the run loop. At the next boundary, after initial window creation and outside application callbacks, Winit emits CloseRequested for its own windows. Applications can decline the request or close normally and exit their event loop. With no Winit windows, the event loop exits normally. Native panels retain their own lifetime.

The opt-in choice preserves the existing termination policy discussed in #2221. This is application-level close review, not a replacement for signal handling or forced termination. Immediate cancellation may also cancel a system logout/shutdown attempt. Multi-window applications remain responsible for coordinating a single decision; Cargo feature unification enables this for the whole process. Those limits are documented.

The standalone macos_quit example uses hidden windows with activation prohibited and no input automation. On an Apple Silicon Mac, the feature-disabled baseline exits 0 without reaching its final marker. With the feature enabled, all three modes pass: Keep open followed by a second Quit, coalesced early requests before initial window creation, and no-window exit. Each verifies return from the event loop and local cleanup. Native Clippy passes for the library and example with warnings denied. The Linux library suite passes all 8 tests; changed Rust files pass the project's nightly rustfmt configuration.

cargo run --example macos_quit -- keep-open
cargo run --features macos-quit-as-close --example macos_quit -- keep-open
cargo run --features macos-quit-as-close --example macos_quit -- early
cargo run --features macos-quit-as-close --example macos_quit -- no-window

Only the feature-enabled runs should print Returned:. The example has a ten-second failure watchdog; exit status 0 alone is not acceptance. This does not claim native menu/panel visual testing or OS logout testing.

  • Tested on all platforms changed
  • Added a changelog entry
  • Updated documentation, including platform-specific behavior
  • Added a standalone reproduction/regression example
  • Updated the feature matrix

@crmne
crmne requested a review from madsmtm as a code owner September 14, 2026 13:21
@crmne

crmne commented Sep 14, 2026

Copy link
Copy Markdown
Author

The hosted run is blocked before compilation by an existing lockfile-generation issue: cargo update -p syn --precise 2.0.114 is now ambiguous between syn@2.0.119 and syn@3.0.5. I reproduced that exact error in a clean archive of the unchanged base e9809ef54b18499bb4f2cac945719ecc2a61061b; this PR adds no dependency requirements. Qualifying the selector as syn@2 appears to be the first CI repair needed, separately from this change.

The cargo-deny failures concern resolved third-party dependency duplicates, packaged scripts in libc/android-activity, and the ttf-parser unmaintained advisory. I have not changed the deny policy or suppressed those findings. Formatting, typos, JavaScript minimization and Windows cargo-deny passed.

Independent checks remain green: native macOS library/example Clippy, feature-disabled reproduction, all three feature-enabled Quit modes, and the Linux library suite. A downstream application also fetched this exact public fork commit and passed the three native modes with its pinned dependency lock and strict Clippy. Hosted cross-platform compilation is still unverified because of the lockfile step above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant