feat: default compact mode to the top-right corner
This commit is contained in:
@@ -69,10 +69,10 @@ struct CompactWindowChecks {
|
|||||||
|
|
||||||
let usableScreen = NSRect(x: -1_200, y: 50, width: 1_200, height: 800)
|
let usableScreen = NSRect(x: -1_200, y: 50, width: 1_200, height: 800)
|
||||||
let landscape = CompactWindowController.initialFrame(aspect: 16.0 / 9.0, visibleFrame: usableScreen)
|
let landscape = CompactWindowController.initialFrame(aspect: 16.0 / 9.0, visibleFrame: usableScreen)
|
||||||
try require(sameFrame(landscape, NSRect(x: -336, y: 66, width: 320, height: 180)),
|
try require(sameFrame(landscape, NSRect(x: -336, y: 654, width: 320, height: 180)),
|
||||||
"16:9 enters at bottom right with 320pt width and 16pt inset")
|
"16:9 enters at top right with 320pt width and 16pt inset")
|
||||||
let portrait = CompactWindowController.initialFrame(aspect: 9.0 / 16.0, visibleFrame: usableScreen)
|
let portrait = CompactWindowController.initialFrame(aspect: 9.0 / 16.0, visibleFrame: usableScreen)
|
||||||
try require(sameFrame(portrait, NSRect(x: -336, y: 66, width: 320, height: 5_120.0 / 9.0)),
|
try require(sameFrame(portrait, NSRect(x: -336, y: 834 - 5_120.0 / 9.0, width: 320, height: 5_120.0 / 9.0)),
|
||||||
"portrait preserves exact aspect when it fits")
|
"portrait preserves exact aspect when it fits")
|
||||||
for aspect in [16.0 / 9.0, 9.0 / 16.0, 100.0, 0.01] {
|
for aspect in [16.0 / 9.0, 9.0 / 16.0, 100.0, 0.01] {
|
||||||
let frame = CompactWindowController.initialFrame(aspect: aspect, visibleFrame: usableScreen)
|
let frame = CompactWindowController.initialFrame(aspect: aspect, visibleFrame: usableScreen)
|
||||||
@@ -84,12 +84,12 @@ struct CompactWindowChecks {
|
|||||||
try require(frame.minX >= usableScreen.minX + 16 && frame.minY >= usableScreen.minY + 16
|
try require(frame.minX >= usableScreen.minX + 16 && frame.minY >= usableScreen.minY + 16
|
||||||
&& frame.maxX <= usableScreen.maxX - 16 && frame.maxY <= usableScreen.maxY - 16,
|
&& frame.maxX <= usableScreen.maxX - 16 && frame.maxY <= usableScreen.maxY - 16,
|
||||||
"aspect \(aspect) stays inside inset usable screen")
|
"aspect \(aspect) stays inside inset usable screen")
|
||||||
try require(close(frame.maxX, usableScreen.maxX - 16) && close(frame.minY, usableScreen.minY + 16),
|
try require(close(frame.maxX, usableScreen.maxX - 16) && close(frame.maxY, usableScreen.maxY - 16),
|
||||||
"aspect \(aspect) stays anchored bottom right")
|
"aspect \(aspect) stays anchored top right")
|
||||||
}
|
}
|
||||||
let smallScreen = NSRect(x: 0, y: 0, width: 300, height: 400)
|
let smallScreen = NSRect(x: 0, y: 0, width: 300, height: 400)
|
||||||
let bounded = CompactWindowController.initialFrame(aspect: 16.0 / 9.0, visibleFrame: smallScreen)
|
let bounded = CompactWindowController.initialFrame(aspect: 16.0 / 9.0, visibleFrame: smallScreen)
|
||||||
try require(sameFrame(bounded, NSRect(x: 16, y: 16, width: 268, height: 150.75)),
|
try require(sameFrame(bounded, NSRect(x: 16, y: 233.25, width: 268, height: 150.75)),
|
||||||
"target width shrinks to usable bounds without distorting ordinary aspect")
|
"target width shrinks to usable bounds without distorting ordinary aspect")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,9 +171,9 @@ struct CompactWindowChecks {
|
|||||||
|
|
||||||
let visible = (window.screen ?? screen).visibleFrame
|
let visible = (window.screen ?? screen).visibleFrame
|
||||||
try require(close(window.frame.maxX, visible.maxX - 16)
|
try require(close(window.frame.maxX, visible.maxX - 16)
|
||||||
&& close(window.frame.minY, visible.minY + 16)
|
&& close(window.frame.maxY, visible.maxY - 16)
|
||||||
&& close(window.frame.width / window.frame.height, 16.0 / 9.0),
|
&& close(window.frame.width / window.frame.height, 16.0 / 9.0),
|
||||||
"actual compact window enters at inset bottom right with playback aspect")
|
"actual compact window enters at inset top right with playback aspect")
|
||||||
let nearEdge = NSRect(x: visible.minX + 26, y: visible.minY + 27,
|
let nearEdge = NSRect(x: visible.minX + 26, y: visible.minY + 27,
|
||||||
width: window.frame.width, height: window.frame.height)
|
width: window.frame.width, height: window.frame.height)
|
||||||
window.setFrame(nearEdge, display: false)
|
window.setFrame(nearEdge, display: false)
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ The layout follows [IINA's video-first window](https://iina.io/img/screenshot.pn
|
|||||||
|
|
||||||
Opening video fits the window to its display aspect ratio, including non-square pixels, and constrains subsequent window resizing. Fullscreen retains the normal letterboxed renderer; audio-only playback and close release the aspect constraint. Extreme ratios that cannot fit both the screen and usable controls keep a freely resizable letterboxed window.
|
Opening video fits the window to its display aspect ratio, including non-square pixels, and constrains subsequent window resizing. Fullscreen retains the normal letterboxed renderer; audio-only playback and close release the aspect constraint. Extreme ratios that cannot fit both the screen and usable controls keep a freely resizable letterboxed window.
|
||||||
|
|
||||||
**Compact mode** uses the same window, Metal view, and playback session—not a second window or macOS system PiP. Use the PiP-shaped button in the normal playback controls, **⌃⌘P**, or **Playback Actions → Enter Compact Mode**. The compact-mode button replaces the fullscreen button; fullscreen remains available through its menu, keyboard shortcuts, and double-clicking normal-mode video. Compact mode starts at the current screen's bottom-right corner with a 16-point inset and a preferred width of 320 points, preserving display aspect where usable screen bounds and the 160 × 90-point minimum allow; extreme ratios retain letterboxing. Compact mode floats above ordinary windows, joins all Spaces, and is configured to join eligible other-app fullscreen spaces and Stage Manager sets. Small hover controls provide play/pause, restore, and Playback Actions; keyboard playback controls remain available.
|
**Compact mode** uses the same window, Metal view, and playback session—not a second window or macOS system PiP. Use the PiP-shaped button in the normal playback controls, **⌃⌘P**, or **Playback Actions → Enter Compact Mode**. The compact-mode button replaces the fullscreen button; fullscreen remains available through its menu, keyboard shortcuts, and double-clicking normal-mode video. Compact mode starts at the current screen's top-right corner with a 16-point inset and a preferred width of 320 points, preserving display aspect where usable screen bounds and the 160 × 90-point minimum allow; extreme ratios retain letterboxing. Compact mode floats above ordinary windows, joins all Spaces, and is configured to join eligible other-app fullscreen spaces and Stage Manager sets. Small hover controls provide play/pause, restore, and Playback Actions; keyboard playback controls remain available.
|
||||||
|
|
||||||
Drag the compact video to move the window; on release, each axis snaps independently when within 24 points of an inset usable-screen edge. **Snap to Screen Edges** is enabled by default and remembers its toggle across launches. Disabling snapping permits free placement. Exiting compact mode restores the previous normal geometry and window behavior, including keep-on-top; entry from fullscreen waits for the native exit animation, and restoring that session returns to fullscreen. Double-clicking compact video also restores the previous mode. Video replacement updates the compact aspect; audio-only replacement, playback errors, and closing the file leave compact mode. Closing the window still quits the app.
|
Drag the compact video to move the window; on release, each axis snaps independently when within 24 points of an inset usable-screen edge. **Snap to Screen Edges** is enabled by default and remembers its toggle across launches. Disabling snapping permits free placement. Exiting compact mode restores the previous normal geometry and window behavior, including keep-on-top; entry from fullscreen waits for the native exit animation, and restoring that session returns to fullscreen. Double-clicking compact video also restores the previous mode. Video replacement updates the compact aspect; audio-only replacement, playback errors, and closing the file leave compact mode. Closing the window still quits the app.
|
||||||
|
|
||||||
|
|||||||
@@ -333,7 +333,7 @@ final class CompactWindowController: NSObject {
|
|||||||
nonisolated static func initialFrame(aspect: Double, visibleFrame: NSRect) -> NSRect {
|
nonisolated static func initialFrame(aspect: Double, visibleFrame: NSRect) -> NSRect {
|
||||||
let usable = usableFrame(visibleFrame)
|
let usable = usableFrame(visibleFrame)
|
||||||
let size = compactSize(aspect: aspect, width: 320, available: usable.size)
|
let size = compactSize(aspect: aspect, width: 320, available: usable.size)
|
||||||
return NSRect(x: usable.maxX - size.width, y: usable.minY, width: size.width, height: size.height)
|
return NSRect(x: usable.maxX - size.width, y: usable.maxY - size.height, width: size.width, height: size.height)
|
||||||
}
|
}
|
||||||
|
|
||||||
nonisolated static func snappedFrame(_ frame: NSRect, visibleFrame: NSRect) -> NSRect {
|
nonisolated static func snappedFrame(_ frame: NSRect, visibleFrame: NSRect) -> NSRect {
|
||||||
|
|||||||
Reference in New Issue
Block a user