mirror of
https://github.com/yattee/yattee.git
synced 2026-10-23 21:22:53 +00:00
Fix macOS corner layout window resize and re-lock the aspect ratio when panels hide
Entering the corner layout cleared the window's aspect-ratio lock by setting contentAspectRatio to zero. That doesn't remove the constraint: AppKit keeps its aspect-ratio resize handler active with a degenerate 0:0 ratio, so every interactive resize resolved to the current size and the window couldn't be resized at all. Reset contentResizeIncrements to 1x1 instead, the supported way back to free resizing (aspect ratio and resize increments are mutually exclusive). Free resize now also requires the corner panels to be visible. With the panels hidden only the video remains, so the window follows the ratio lock (and auto-fit, when on) exactly like the stacked layout. The new AppEnvironment.isCornerPanelLayoutActive gate covers the layout-change handler, window creation, and the fullscreen-exit replay.
This commit is contained in:
@@ -875,9 +875,11 @@ private struct PlayerMacOSEventHandlersModifier: ViewModifier {
|
||||
|
||||
var playerState: PlayerState? { appEnvironment?.playerService.state }
|
||||
|
||||
/// Corner layout resizes the window freely: no aspect lock, no auto-fit.
|
||||
/// Corner layout with its panels visible resizes the window freely: no
|
||||
/// aspect lock, no auto-fit. With the panels hidden only the video is
|
||||
/// left, so the window follows the ratio lock like the stacked layout.
|
||||
private var isCornerLayoutActive: Bool {
|
||||
appEnvironment?.navigationCoordinator.isCornerLayoutActive == true
|
||||
appEnvironment?.isCornerPanelLayoutActive == true
|
||||
}
|
||||
|
||||
func body(content: Content) -> some View {
|
||||
@@ -895,7 +897,7 @@ private struct PlayerMacOSEventHandlersModifier: ViewModifier {
|
||||
.onChange(of: playerState?.currentVideo?.id) { oldValue, newValue in
|
||||
handleVideoChangeForResize(oldValue: oldValue, newValue: newValue)
|
||||
}
|
||||
.onChange(of: appEnvironment?.navigationCoordinator.isCornerLayoutActive) { _, isCorner in
|
||||
.onChange(of: appEnvironment?.isCornerPanelLayoutActive) { _, isCorner in
|
||||
handleCornerLayoutChange(isCorner: isCorner == true)
|
||||
}
|
||||
.onAppear {
|
||||
@@ -903,9 +905,10 @@ private struct PlayerMacOSEventHandlersModifier: ViewModifier {
|
||||
}
|
||||
}
|
||||
|
||||
/// Entering corner mode drops the window's aspect-ratio constraint so it
|
||||
/// resizes freely; leaving it restores the lock (and auto-fit, when on)
|
||||
/// exactly as the aspect-change handler would have applied it.
|
||||
/// Entering corner mode with panels shown drops the window's aspect-ratio
|
||||
/// constraint so it resizes freely; leaving it (stacked layout, or corner
|
||||
/// panels hidden) restores the lock (and auto-fit, when on) exactly as the
|
||||
/// aspect-change handler would have applied it.
|
||||
private func handleCornerLayoutChange(isCorner: Bool) {
|
||||
if isCorner {
|
||||
ExpandedPlayerWindowManager.shared.unlockAspectRatio()
|
||||
|
||||
@@ -176,9 +176,10 @@ 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.
|
||||
// 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 {
|
||||
// Corner layout with its panels visible (already active on a window
|
||||
// re-mount, e.g. switching from the inline overlay) keeps the window
|
||||
// unconstrained.
|
||||
if !appEnvironment.isCornerPanelLayoutActive {
|
||||
Self.applyAspectRatioConstraint(seedAspect, to: window)
|
||||
}
|
||||
|
||||
@@ -599,8 +600,17 @@ final class ExpandedPlayerWindowManager: NSObject {
|
||||
func unlockAspectRatio() {
|
||||
guard let window = playerWindow else { return }
|
||||
pendingFullScreenAspectRatio = nil
|
||||
window.contentAspectRatio = .zero
|
||||
LoggingService.shared.debug("unlockAspectRatio (corner layout)", category: .player)
|
||||
// `aspectRatio` and `resizeIncrements` are mutually exclusive: setting
|
||||
// one resets the other. Assigning a zero aspect ratio does NOT clear the
|
||||
// lock — it leaves AppKit's aspect handler active with a degenerate 0:0
|
||||
// ratio, which makes interactive resize a no-op (the window can't be
|
||||
// resized at all). Resetting the increments to 1×1 is the supported way
|
||||
// to return to free resizing.
|
||||
window.contentResizeIncrements = NSSize(width: 1, height: 1)
|
||||
LoggingService.shared.debug(
|
||||
"unlockAspectRatio (corner layout) aspect=\(window.contentAspectRatio) increments=\(window.contentResizeIncrements)",
|
||||
category: .player
|
||||
)
|
||||
}
|
||||
|
||||
// MARK: - Private Helpers
|
||||
@@ -828,8 +838,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 }
|
||||
// Corner layout with visible panels keeps the window unconstrained.
|
||||
guard appEnvironment?.isCornerPanelLayoutActive != true else { return }
|
||||
Self.applyAspectRatioConstraint(ratio, to: window)
|
||||
if appEnvironment?.settingsManager.playerSheetAutoResize == true {
|
||||
resizeToFitAspectRatio(ratio, animated: false)
|
||||
@@ -839,6 +849,19 @@ extension ExpandedPlayerWindowManager: NSWindowDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Free-Resize Gate
|
||||
|
||||
extension AppEnvironment {
|
||||
/// Whether the player window should resize freely instead of following
|
||||
/// the video aspect ratio: the corner layout is resolved AND its panel
|
||||
/// regions are shown, so the window frames video plus panels. Hiding the
|
||||
/// panels in corner mode leaves only the video, which follows the ratio
|
||||
/// lock (and auto-fit) exactly like the stacked layout.
|
||||
var isCornerPanelLayoutActive: Bool {
|
||||
navigationCoordinator.isCornerLayoutActive && settingsManager.landscapeDetailsPanelVisible
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Two-Phase Window Root
|
||||
|
||||
/// Root view hosted in the expanded player window.
|
||||
|
||||
Reference in New Issue
Block a user