mirror of
https://github.com/yattee/yattee.git
synced 2026-05-12 18:35:05 +00:00
Lock macOS player window resize to video aspect ratio
This commit is contained in:
@@ -953,6 +953,11 @@ private struct PlayerMacOSEventHandlersModifier: ViewModifier {
|
|||||||
|
|
||||||
private func handleAspectRatioChange(oldValue: Double?, newValue: Double?) {
|
private func handleAspectRatioChange(oldValue: Double?, newValue: Double?) {
|
||||||
guard let newValue, newValue > 0 else { return }
|
guard let newValue, newValue > 0 else { return }
|
||||||
|
|
||||||
|
// Always keep the manual-resize aspect lock in sync, regardless of the
|
||||||
|
// auto-resize setting — the user always wants resize to be ratio-locked.
|
||||||
|
ExpandedPlayerWindowManager.shared.lockAspectRatio(newValue)
|
||||||
|
|
||||||
guard appEnvironment?.settingsManager.playerSheetAutoResize == true else { return }
|
guard appEnvironment?.settingsManager.playerSheetAutoResize == true else { return }
|
||||||
|
|
||||||
let shouldAnimate = oldValue != nil
|
let shouldAnimate = oldValue != nil
|
||||||
@@ -982,9 +987,12 @@ private struct PlayerMacOSEventHandlersModifier: ViewModifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func handleMacOSAppear() {
|
private func handleMacOSAppear() {
|
||||||
if appEnvironment?.settingsManager.playerSheetAutoResize == true,
|
guard let aspectRatio = playerState?.videoAspectRatio, aspectRatio > 0 else { return }
|
||||||
let aspectRatio = playerState?.videoAspectRatio,
|
|
||||||
aspectRatio > 0 {
|
// Lock aspect ratio for manual resize unconditionally.
|
||||||
|
ExpandedPlayerWindowManager.shared.lockAspectRatio(aspectRatio)
|
||||||
|
|
||||||
|
if appEnvironment?.settingsManager.playerSheetAutoResize == true {
|
||||||
ExpandedPlayerWindowManager.shared.resizeToFitAspectRatio(aspectRatio, animated: false)
|
ExpandedPlayerWindowManager.shared.resizeToFitAspectRatio(aspectRatio, animated: false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,9 +21,10 @@ final class ExpandedPlayerWindowManager: NSObject {
|
|||||||
|
|
||||||
// Configuration
|
// Configuration
|
||||||
private let minWidth: CGFloat = 640
|
private let minWidth: CGFloat = 640
|
||||||
private let minHeight: CGFloat = 480
|
private let minHeight: CGFloat = 360
|
||||||
private let maxScreenRatio: CGFloat = 0.7
|
private let maxScreenRatio: CGFloat = 0.7
|
||||||
private let targetVideoHeight: CGFloat = 720
|
private let targetVideoHeight: CGFloat = 720
|
||||||
|
private let defaultAspectRatio: Double = 16.0 / 9.0
|
||||||
|
|
||||||
var isPresented: Bool {
|
var isPresented: Bool {
|
||||||
playerWindow != nil
|
playerWindow != nil
|
||||||
@@ -89,9 +90,12 @@ final class ExpandedPlayerWindowManager: NSObject {
|
|||||||
window.titleVisibility = .hidden
|
window.titleVisibility = .hidden
|
||||||
window.isMovableByWindowBackground = true
|
window.isMovableByWindowBackground = true
|
||||||
window.backgroundColor = NSColor.windowBackgroundColor
|
window.backgroundColor = NSColor.windowBackgroundColor
|
||||||
window.minSize = NSSize(width: minWidth, height: minHeight)
|
|
||||||
window.contentViewController = hostingController
|
window.contentViewController = hostingController
|
||||||
|
|
||||||
|
// Lock manual resize to the video aspect ratio. Seeded with 16:9 here;
|
||||||
|
// updated as soon as the real video aspect ratio is known.
|
||||||
|
applyAspectRatioConstraint(defaultAspectRatio, to: window)
|
||||||
|
|
||||||
// Set up window delegate for close handling
|
// Set up window delegate for close handling
|
||||||
// Make ExpandedPlayerWindowManager itself the delegate to avoid lifecycle issues
|
// Make ExpandedPlayerWindowManager itself the delegate to avoid lifecycle issues
|
||||||
window.delegate = self
|
window.delegate = self
|
||||||
@@ -256,6 +260,9 @@ final class ExpandedPlayerWindowManager: NSObject {
|
|||||||
guard let window = playerWindow else { return }
|
guard let window = playerWindow else { return }
|
||||||
guard aspectRatio > 0 else { return }
|
guard aspectRatio > 0 else { return }
|
||||||
|
|
||||||
|
// Always update the aspect-ratio lock, even if we end up not resizing here.
|
||||||
|
applyAspectRatioConstraint(aspectRatio, to: window)
|
||||||
|
|
||||||
// Get screen bounds
|
// Get screen bounds
|
||||||
guard let screen = window.screen ?? NSScreen.main else { return }
|
guard let screen = window.screen ?? NSScreen.main else { return }
|
||||||
let screenFrame = screen.visibleFrame
|
let screenFrame = screen.visibleFrame
|
||||||
@@ -278,8 +285,32 @@ final class ExpandedPlayerWindowManager: NSObject {
|
|||||||
window.setFrame(adjustedFrame, display: true, animate: animated)
|
window.setFrame(adjustedFrame, display: true, animate: animated)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Locks the window's resize behavior to the given aspect ratio without
|
||||||
|
/// changing the current frame. Use this when the auto-resize setting is
|
||||||
|
/// disabled but we still want manual resizing to be ratio-locked.
|
||||||
|
func lockAspectRatio(_ aspectRatio: Double) {
|
||||||
|
guard let window = playerWindow else { return }
|
||||||
|
guard aspectRatio > 0 else { return }
|
||||||
|
applyAspectRatioConstraint(aspectRatio, to: window)
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - Private Helpers
|
// MARK: - Private Helpers
|
||||||
|
|
||||||
|
/// Sets `contentAspectRatio` and a ratio-consistent `minSize` on the window
|
||||||
|
/// so that interactive resize couples width and height proportionally.
|
||||||
|
private func applyAspectRatioConstraint(_ aspectRatio: Double, to window: NSWindow) {
|
||||||
|
guard aspectRatio > 0 else { return }
|
||||||
|
|
||||||
|
// contentAspectRatio is expressed as a ratio; using (aspectRatio, 1) keeps it exact.
|
||||||
|
window.contentAspectRatio = NSSize(width: aspectRatio, height: 1)
|
||||||
|
|
||||||
|
// Derive a minimum size that lies on the same ratio so the lower bound
|
||||||
|
// doesn't force the window off-ratio (which would re-introduce bars).
|
||||||
|
// Anchor on minHeight and scale width by aspect.
|
||||||
|
let derivedMinWidth = max(minHeight * CGFloat(aspectRatio), 320)
|
||||||
|
window.minSize = NSSize(width: derivedMinWidth, height: minHeight)
|
||||||
|
}
|
||||||
|
|
||||||
private func configureWindowLevel(_ window: NSWindow, floating: Bool) {
|
private func configureWindowLevel(_ window: NSWindow, floating: Bool) {
|
||||||
if floating {
|
if floating {
|
||||||
window.level = .floating
|
window.level = .floating
|
||||||
|
|||||||
Reference in New Issue
Block a user