Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,13 @@ final class ResizeContext {
}

private func recomputeTargetFrame() {
// Clear the recompute guard *before* resolving so this method is re-entrancy safe:
// if `WindowFrameResolver.getFrame` ever reads `getTargetFrame()` on this same
// context while it is still being computed, the guard is already clear and the
// re-entrant call returns the cached frame instead of recomputing and recursing
// until the stack overflows.
needsRecompute = false

let result = WindowFrameResolver.getFrame(resizeContext: self)

let normalized = CGRect(
Expand All @@ -152,7 +159,6 @@ final class ResizeContext {
normalized: normalized,
padded: paddedFrame
)
needsRecompute = false

log.info("Computed target frame - raw: \(cachedTargetFrame.raw), normalized: \(cachedTargetFrame.normalized) padded: \(cachedTargetFrame.padded), for action: \(action)")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,12 @@ extension WindowFrameResolver {
)

} else if direction.willMove {
let frameToResizeFrom = context.getTargetFrame().raw
// Read the last applied frame (falling back to the cached target) instead of
// `context.getTargetFrame()`. `getTargetFrame()` would recompute this very
// context and re-enter here, recursing until the stack overflows. Matching the
// grow/shrink branches above also keeps moves anchored to the window's actual
// position rather than a theoretical (possibly clamped-away) target frame.
let frameToResizeFrom = context.lastAppliedFrame ?? context.cachedTargetFrame.raw

result = calculatePositionAdjustment(for: action, frameToResizeFrom: frameToResizeFrom)

Expand Down
Loading