Floating window position outside screen bounds when moving between workspaces#1964
Conversation
|
Based on this discussion 1875, this fix improves the usability, so the floating windows will no longer disappear but they will still change position. The issue I can see is that at some point in I tested adding |
nikitabobko
left a comment
There was a problem hiding this comment.
Thanks! The patch makes sense. Feel free to merge it.
One major comment: please change the commit message so that the title (first line of the message) is one-line concise summarization of the change. Right now, the title of the commit is "Issue:" which def looks odd.
And sorry for the delay. I didn't have a lot of time to work on the project lately, but I am going to have much more time to work on the project starting from April.
| guard let windowRect = try await getAxRect() else { return } | ||
| let currentMonitor = windowRect.center.monitorApproximation | ||
| if workspace != currentMonitor.activeWorkspace { |
There was a problem hiding this comment.
| guard let windowRect = try await getAxRect() else { return } | |
| let currentMonitor = windowRect.center.monitorApproximation | |
| if workspace != currentMonitor.activeWorkspace { | |
| let windowRect = try await getAxRect() // Probably not idempotent | |
| let currentMonitor = windowRect?.center.monitorApproximation | |
| if let currentMonitor, let windowRect, workspace != currentMonitor.activeWorkspace { |
Otherwise, you will skip layoutFullscreen below
| setAxFrame(workspaceRect.topLeftCorner + pointInsideWorkspace, nil) | ||
| var newX = workspaceRect.topLeftX + workspaceRect.width * prevUnhiddenProportionalPositionInsideWorkspaceRect.x | ||
| var newY = workspaceRect.topLeftY + workspaceRect.height * prevUnhiddenProportionalPositionInsideWorkspaceRect.y | ||
| let windowWidth = lastFloatingSize?.width ?? 0 |
There was a problem hiding this comment.
| let windowWidth = lastFloatingSize?.width ?? 0 | |
| // todo we probably should replace lastFloatingSize with proper floating window sizing | |
| // https://github.com/nikitabobko/AeroSpace/issues/1519 | |
| let windowWidth = lastFloatingSize?.width ?? 0 |
…ow and unhideFromCorner calculates the coordinates for the top-left corner of the window. Issue: When moving a floating window to another workspace (potentially on a different monitor with different resolution), the window could end up placed almost completely outside the bounds of the target workspace. This happens because the proportional repositioning logic only remaps the window's top-left corner without considering the window's size, so a window near the edge of a larger monitor gets its top-left mapped to the edge of a smaller monitor, and the window extends almost completely off the screen. Root Cause: When layoutFloatingWindow and unhideFromCorner calculates the coordinates for the top-left corner it does not accommodate for the target workspace's bounds. Fix: layoutFloatingWindow: - Replaced two separate AX calls of `getCenter()` and `getAxTopLeftCorner()` with a single call to `getAxRect()` to get both position and size of the window. - After computing the proportional position on the target workspace, restrict the position using `coerceIn` so the window stays within `workspace.workspaceMonitor.visibleRect`, accounting for the window's width and height unhideFromCorner: - After computing the restored proportional position on the workspace, clamp it within `workspaceRect` using `lastFloatingSize` to account for window dimensions. The restrict logic uses `max(rect.minX, rect.maxX - windowWidth)` as the upper bound, which handles the edge case where the window is larger than the target workspace — in that case, the range collapses to `minX...minX` and the window is pinned to the top-left corner of the workspace (which is the most reasonable behavior). Related discussion: nikitabobko#1875 (with my fix the screen no longer disappear, but it gets re positioned in the screen) Possible related issue: nikitabobko#1519
7bc7205 to
bc80b3c
Compare

Issue:
When moving a floating window to another workspace (potentially on a different monitor with different resolution), the window could end up placed almost completely outside the bounds of the target workspace. This happens because the proportional repositioning logic only remaps the window's top-left corner without considering the window's size, so a window near the edge of a larger monitor gets its top-left mapped to the edge of a smaller monitor, and the window extends almost completely off the screen.
Root Cause:
When layoutFloatingWindow and unhideFromCorner calculates the coordinates for the top-left corner it does not accommodate for the target workspace's bounds.
Fix:
layoutFloatingWindow:
getCenter()andgetAxTopLeftCorner()with a single call togetAxRect()to get both position and size of the window.coerceInso the window stays withinworkspace.workspaceMonitor.visibleRect, accounting for the window's width and heightunhideFromCorner:
workspaceRectusinglastFloatingSizeto account for window dimensions.The restrict logic uses
max(rect.minX, rect.maxX - windowWidth)as the upper bound, which handles the edge case where the window is larger than the target workspace — in that case, the range collapses tominX...minXand the window is pinned to the top-left corner of the workspace (which is the most reasonable behavior).Related discussion: #1875 (with my fix the screen no longer disappear, but it gets re positioned in the screen)
Possible related issue: #1519
PR checklist
./run-tests.shexits with non-zero exit code.Failure to follow the checklist with no apparent reasons will result in silent PR rejection.