Add native fullscreen for macOS sheet-mode player via in-window overlay

The fullscreen button did nothing in sheet mode: AppKit ignores
toggleFullScreen on a window attached as a sheet, and the old fallback
targeted the key window — the sheet itself. Two other strategies were
ruled out first: fullscreening the sheet's parent is silently refused
while any sheet is attached, and resizing the sheet's backing window to
screen size NaN-asserts inside AppKit's sheet positioning even without
animation.

Working approach: swap the sheet for a plain overlay in the main window
and native-fullscreen the now sheet-free main window.

- isMacPlayerFullScreenOverlay on NavigationCoordinator dismisses the
  sheet (presentation binding excludes it; the setter ignores the
  dismissal write-back) and mounts ExpandedPlayerSheet as a black-backed
  overlay in ContentView
- ExpandedPlayerWindowManager fullscreens the parent after the sheet
  detaches, verifies AppKit accepted it (rolls back if refused), hides
  the window toolbar (NSWindow keeps it as a strip above the overlay
  otherwise) and restores it on exit
- a didExitFullScreen observer restores the sheet on any exit path
  (button, Esc, green button, Window menu); closing the player while
  fullscreen exits the main window's fullscreen too
- scheduleSharedViewAdoptionRetry on entry re-homes the shared render
  view once the dismissing sheet's window loses visibility — its steal
  is declined mid-dismissal and nothing else retried, leaving the
  overlay black until the next video load
This commit is contained in:
Arkadiusz Fal
2026-06-25 21:55:47 +02:00
parent 59cc7a8249
commit 9bcb8e35a6
4 changed files with 174 additions and 5 deletions

View File

@@ -1575,7 +1575,12 @@ extension ExpandedPlayerSheet {
// config first so a pinned window can enter fullscreen)
ExpandedPlayerWindowManager.shared.toggleFullScreen()
},
isFullscreen: NSApp.keyWindow?.styleMask.contains(.fullScreen) == true,
// The coordinator flag covers overlay fullscreen (where the
// main window is the fullscreen one) and, being @Observable,
// refreshes the button icon on toggle; the keyWindow check
// covers the separate-window presentation.
isFullscreen: navigationCoordinator?.isMacPlayerFullScreenOverlay == true
|| NSApp.keyWindow?.styleMask.contains(.fullScreen) == true,
onClose: { [self] in
closeVideo()
},