Add corner player layout on iPad and macOS

Preset-selected two-region layout: video in the top-left, a resizable
side column, and an optional region below the video. Pages are assigned
to regions per preset (Location picker in the page editor); the layout
falls back to the stacked widescreen layout below 900pt width, so Split
View and narrow windows degrade automatically.

- CornerPlayerLayout hosts the shared playerAreaForWidescreen builder,
  so the MPV hosting path is identical to the stacked layout
- Layout resolver in ExpandedPlayerSheet picks corner per layout pass;
  NavigationCoordinator.isCornerLayoutActive feeds the macOS window
  manager, which drops the aspect-ratio lock and auto-fit while corner
  is active (and restores them on exit, incl. fullscreen replay and
  window re-mounts)
- Side column width persisted via new cornerPanelColumnWidth setting
  (280-560pt, video column kept >= 480pt)
- Settings: layout mode picker (iPad/macOS) with automatic-fallback
  footer, per-page region picker when corner is on, region shown in
  the pages list
This commit is contained in:
Arkadiusz Fal
2026-09-21 23:52:09 +02:00
parent c33d125553
commit a6d989c7af
14 changed files with 582 additions and 12 deletions

View File

@@ -176,7 +176,11 @@ final class ExpandedPlayerWindowManager: NSObject {
// Lock manual resize to the video aspect ratio. Seeded with the real ratio
// when known (else 16:9); updated as soon as the real ratio is known.
Self.applyAspectRatioConstraint(seedAspect, to: window)
// Corner layout (already active on a window re-mount, e.g. switching
// from the inline overlay) keeps the window unconstrained.
if appEnvironment.navigationCoordinator.isCornerLayoutActive != true {
Self.applyAspectRatioConstraint(seedAspect, to: window)
}
// Force the intended size. Assigning `contentViewController` above resizes
// the window to the hosting controller's fitting size — and the lightweight
@@ -588,6 +592,17 @@ final class ExpandedPlayerWindowManager: NSObject {
Self.applyAspectRatioConstraint(aspectRatio, to: window)
}
/// Removes the window's aspect-ratio resize constraint so it resizes
/// freely. Used by the corner layout, where the window frames the whole
/// video-plus-panels arrangement rather than the video alone. The size
/// floor stays enforced by `windowWillResize(_:to:)`.
func unlockAspectRatio() {
guard let window = playerWindow else { return }
pendingFullScreenAspectRatio = nil
window.contentAspectRatio = .zero
LoggingService.shared.debug("unlockAspectRatio (corner layout)", category: .player)
}
// MARK: - Private Helpers
/// Sets `contentAspectRatio` and a ratio-consistent minimum content size on
@@ -813,6 +828,8 @@ extension ExpandedPlayerWindowManager: NSWindowDelegate {
// exactly what the aspect-change handler would have done windowed.
if let ratio = pendingFullScreenAspectRatio {
pendingFullScreenAspectRatio = nil
// Corner layout keeps the window unconstrained.
guard appEnvironment?.navigationCoordinator.isCornerLayoutActive != true else { return }
Self.applyAspectRatioConstraint(ratio, to: window)
if appEnvironment?.settingsManager.playerSheetAutoResize == true {
resizeToFitAspectRatio(ratio, animated: false)