The held window chrome survives detach — toolbars and the board-info widget render again

No board window has shown its NSToolbar or the titlebar board-info
chevron since m6: on macOS 26, SwiftUI stages a scene's content
against a provisional window, then dismantles and re-makes the
window-sensing background view while moving content into the real
window. HostedWindowController.detach() treated that dismantle as the
window's death and discarded the held titlebar accessory and toolbar
controller — so the real window attached moments later to empty slots.
Observed live via instrumented launch: install arrives with no window,
detach follows (slots cleared), then the real window attaches.

detach() now removes the chrome from the window but retains the slots
— their lifetime is the controller's, not the sensing view's — and
attach() reinstalls whatever is held. Verified on a fixture launch:
the board window carries its toolbar and the leading accessory.

Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
This commit is contained in:
2026-07-29 21:32:20 -04:00
parent 566deab506
commit bebbc877db
+11 -6
View File
@@ -113,15 +113,20 @@ final class HostedWindowController: NSObject, NSWindowDelegate {
applyToolbarIfPossible()
}
/// Puts the previous delegate back, and takes the titlebar accessory and toolbar back out.
/// Called when the hosting view goes away; the delegate half is a no-op if something else has
/// since taken the delegate, because stomping a third party's would be the bug this whole file
/// exists to avoid.
/// Puts the previous delegate back and takes the titlebar accessory and toolbar off the window
/// **without discarding them**. The delegate half is a no-op if something else has since taken
/// the delegate, because stomping a third party's would be the bug this whole file exists to
/// avoid.
///
/// The held chrome survives a detach deliberately: its lifetime is this controller's, not the
/// sensing view's. SwiftUI dismantles and re-makes the background representable while it moves a
/// scene's content into its final window (observed on macOS 26: install arrives before any
/// window, a dismantle follows, and only *then* does the real window attach) so chrome
/// discarded here would never reach the window it was made for. `attach` reinstalls whatever is
/// held; a controller that is genuinely done takes its slots down with it.
func detach() {
removeTitlebarAccessory()
titlebarAccessory = nil
removeToolbar()
toolbarController = nil
guard let window, window.delegate === self else { return }
window.delegate = previousDelegate
self.window = nil