Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file removed .gitmodules
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ struct PaddingConfiguration: Codable, Defaults.Serializable, Hashable {
if let resolvedWindowProperties, !resolvedWindowProperties.isResizable {
let centeredFrame = resolvedWindowProperties.frame.size
.center(inside: result)
.pushInside(bounds)
Comment thread
mrkai77 marked this conversation as resolved.

return centeredFrame
}
Expand Down
50 changes: 46 additions & 4 deletions Loop/Window Management/Window Manipulation/WindowEngine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -198,18 +198,60 @@ enum WindowEngine {
try Task.checkCancellation()
}

handleSizeConstrainedWindow(window: window, bounds: bounds)
handleSizeConstrainedWindow(window: window, targetFrame: targetFrame, bounds: bounds)
}

// MARK: - Size Constraints

private static func handleSizeConstrainedWindow(window: Window, bounds: CGRect) {
private static func handleSizeConstrainedWindow(window: Window, targetFrame: CGRect, bounds: CGRect) {
guard !window.isOwnWindow, bounds != .zero else { return }

var windowFrame = window.frame
if windowFrame.maxX > bounds.maxX { windowFrame.origin.x = bounds.maxX - windowFrame.width }
if windowFrame.maxY > bounds.maxY { windowFrame.origin.y = bounds.maxY - windowFrame.height }
let targetEdges = targetFrame.getEdgesTouchingBounds(bounds)

// Some windows have size constraints such as fixed aspect ratios, fixed width,
// fixed height, etc. When that happens, preserve the intended anchor by
// re-positioning the resulting frame after the resize completes.
if !windowFrame.size.approximatelyEqual(to: targetFrame.size, tolerance: 2) {
windowFrame = anchoredFrame(
for: windowFrame.size,
within: targetFrame,
targetEdges: targetEdges,
bounds: bounds
)
}

window.setPosition(windowFrame.origin)
}

static func anchoredFrame(
for actualSize: CGSize,
within requestedFrame: CGRect,
targetEdges: Edge.Set,
bounds: CGRect
) -> CGRect {
var frame = CGRect(origin: requestedFrame.origin, size: actualSize)

if targetEdges.contains(.leading), targetEdges.contains(.trailing) {
frame.origin.x = requestedFrame.midX - actualSize.width / 2
} else if targetEdges.contains(.leading) {
frame.origin.x = requestedFrame.minX
} else if targetEdges.contains(.trailing) {
frame.origin.x = requestedFrame.maxX - actualSize.width
} else {
frame.origin.x = requestedFrame.midX - actualSize.width / 2
}

if targetEdges.contains(.top), targetEdges.contains(.bottom) {
frame.origin.y = requestedFrame.midY - actualSize.height / 2
} else if targetEdges.contains(.top) {
frame.origin.y = requestedFrame.minY
} else if targetEdges.contains(.bottom) {
frame.origin.y = requestedFrame.maxY - actualSize.height
} else {
frame.origin.y = requestedFrame.midY - actualSize.height / 2
}

return frame.pushInside(bounds)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ final class WindowTransformAnimation: NSAnimation {
private let window: Window
private let bounds: CGRect
private let shouldSetSize: Bool
private let targetEdges: Edge.Set
private var didCallCompletionHandler: Bool = false
private let completionHandler: (Error?) -> ()

Expand All @@ -36,6 +37,7 @@ final class WindowTransformAnimation: NSAnimation {
self.window = window
self.bounds = bounds
self.shouldSetSize = shouldSetSize
self.targetEdges = newRect.getEdgesTouchingBounds(bounds)
self.completionHandler = completionHandler
super.init(duration: 0.3, animationCurve: .easeOut)
self.frameRate = Float(NSScreen.main?.displayMode?.refreshRate ?? 60.0)
Expand Down Expand Up @@ -93,36 +95,32 @@ final class WindowTransformAnimation: NSAnimation {
private func apply(progress: Float) {
let value = CGFloat(1.0 - pow(1.0 - progress, 3))

var newFrame = CGRect(
let requestedFrame = CGRect(
x: round(originalFrame.origin.x + value * (targetFrame.origin.x - originalFrame.origin.x)),
y: round(originalFrame.origin.y + value * (targetFrame.origin.y - originalFrame.origin.y)),
width: round(originalFrame.size.width + value * (targetFrame.size.width - originalFrame.size.width)),
height: round(originalFrame.size.height + value * (targetFrame.size.height - originalFrame.size.height))
)

// Keep the window inside the bounds
if bounds != .zero {
let xDiff = lastWindowFrame.width - newFrame.width
if newFrame.maxX + xDiff > lastWindowFrame.maxX || currentValue >= 0.5,
newFrame.maxX + xDiff > bounds.maxX {
newFrame.origin.x = bounds.maxX - lastWindowFrame.width
}

let yDiff = lastWindowFrame.height - newFrame.height
if newFrame.maxY + yDiff > lastWindowFrame.maxY || currentValue >= 0.5,
newFrame.maxY + yDiff > bounds.maxY {
newFrame.origin.y = bounds.maxY - lastWindowFrame.height
}
var newFrame = requestedFrame

if shouldSetSize, lastWindowFrame.size != requestedFrame.size {
window.setSize(requestedFrame.size)
let actualFrame = window.frame
newFrame = WindowEngine.anchoredFrame(
for: actualFrame.size,
within: requestedFrame,
targetEdges: targetEdges,
bounds: bounds
)
Comment thread
mrkai77 marked this conversation as resolved.
Outdated
} else if bounds != .zero {
newFrame = newFrame.pushInside(bounds)
}

if lastWindowFrame.origin != newFrame.origin {
window.setPosition(newFrame.origin)
}

if shouldSetSize, lastWindowFrame.size != newFrame.size {
window.setSize(newFrame.size)
}

lastWindowFrame = window.frame
}
}
Loading