visionOS 26: is there any way yet to distinguish a user-initiated window close from system out-of-FoV backgrounding

This was confirmed as a framework gap in an accepted answer from an Apple Vision Pro engineer in June 2024 (https://developer.apple.com/forums/thread/758014?answerId=792769022#792769022): .background fires identically whether the user taps a window's close button or the system backgrounds a window that's been out of the field of view for ~61 seconds, and there's no app-visible signal that distinguishes the two. The recommendation at the time was to use a gesture/affordance to reopen the window, and to file an enhancement request.

Two years on, with the window-management APIs that have shipped since, I want to confirm whether the situation has changed as of visionOS 26.

My case: VisionBlazer, a native spatial 3D creation tool (TestFlight beta, August 2026 launch). Users routinely work with several SwiftUI WindowGroup tool windows open at once — drawing tools, materials, timeline, properties, lighting — parked spatially around an ImmersiveSpace. Parking a window behind or beside you is core to the workflow. The app should terminate when the user closes the primary window, but must not terminate when a secondary window (or the primary) is simply parked out of view.

What I've verified on-device (visionOS 26.5):

scenePhase == .background fires identically for a user close tap and for the ~61s out-of-FoV backgrounding (SurfBoard: "…is out of FOV after 60.99 seconds. Backgrounding"). The phase sequence (active → inactive → background) and timing (~0.2–0.4s gap) are indistinguishable between the two cases. scenePhase on visionOS reflects visibility, not focus — a parked window stays .active while the user edits elsewhere, until the out-of-FoV timer fires. The session identifier reachable from the window's view hierarchy (view.window!.windowScene.session.persistentIdentifier) never matches the identifier reported by application(_:didDiscardSceneSessions:) or UIScene.didDisconnectNotification for that same close. The view-visible session stays in UIApplication.shared.openSessions indefinitely after the close. Those disconnect/discard callbacks arrive ~10–15s late and only ever carry foreign session identifiers, so they can't be attributed to a specific window. Stale-session discards from prior launches pollute the signal further. onDisappear does not fire on user close.

Five strategies tried, all failed: (1) scene-object identity captured at didMoveToWindow; (2) session.persistentIdentifier matching against openSessions; (3) live re-capture of scene/session from the view hierarchy on every lifecycle change; (4) temporal correlation of didEnterBackground/didDisconnect; (5) a focus-recency heuristic on scenePhase transitions. All fail on the identifier mismatch and the visibility-not-focus semantics above.

Questions:

As of visionOS 26, is there now any supported way to detect that the user intentionally closed a specific window, distinct from system backgrounding? Is there a SwiftUI or scene-delegate callback tied to a window's own scene that fires only on user close? Is there a dismissalReason (or equivalent) anywhere on the close path? If none of the above exists, is an explicit in-app Quit button still the intended pattern for "quit when the main window is closed"?

I have a focused test project reproducing all of this and can link it. Thanks.

visionOS 26: is there any way yet to distinguish a user-initiated window close from system out-of-FoV backgrounding
 
 
Q