Skip to content

Commit fe03931

Browse files
committed
Make workspace assignment on adding monitors more stable.
Previously, `rearrangeWorkspacesOnMonitors()` mapped new screens to old screens in a greedy fashion. For each new screen, it would assign the closest old screen and remove that old screen from consideration for all subsequent new screens. This can result in suboptimal workspace placement. For example, if `newScreens[1]` is an exact match for a given old screen O, but O also happens to be the closest screen to `newScreens[0]`, then O would be assigned to `newScreens[0]`. This can result in workspaces jumping around unexpectedly when adding a monitor. Fix this by assigning each old screen to the closest new screen, and on collisions, preferring the closest old screen.
1 parent a824164 commit fe03931

File tree

1 file changed

+8
-6
lines changed

1 file changed

+8
-6
lines changed

Sources/AppBundle/tree/Workspace.swift

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -164,15 +164,17 @@ extension CGPoint {
164164

165165
@MainActor
166166
private func rearrangeWorkspacesOnMonitors() {
167-
var oldVisibleScreens: Set<CGPoint> = screenPointToVisibleWorkspace.keys.toSet()
168-
169167
let newScreens = monitors.map(\.rect.topLeftCorner)
170168
var newScreenToOldScreenMapping: [CGPoint: CGPoint] = [:]
171-
for newScreen in newScreens {
172-
if let oldScreen = oldVisibleScreens.minBy({ ($0 - newScreen).vectorLength }) {
173-
check(oldVisibleScreens.remove(oldScreen) != nil)
174-
newScreenToOldScreenMapping[newScreen] = oldScreen
169+
for (oldScreen, _) in screenPointToVisibleWorkspace {
170+
guard let newScreen = newScreens.minBy({ ($0 - oldScreen).vectorLength }) else { continue }
171+
if let prevOldScreen = newScreenToOldScreenMapping[newScreen] {
172+
if (prevOldScreen - newScreen).vectorLength <= (oldScreen - newScreen).vectorLength {
173+
// newScreen has already been assigned to a closer oldScreen.
174+
continue
175+
}
175176
}
177+
newScreenToOldScreenMapping[newScreen] = oldScreen
176178
}
177179

178180
let oldScreenPointToVisibleWorkspace = screenPointToVisibleWorkspace

0 commit comments

Comments
 (0)