From 4928f4db5b810969c70d549729c23ff95d1a6781 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Sat, 30 Oct 2021 13:02:40 +0300 Subject: [PATCH] Try to preserve window position relative to their outputs during hotplug Currently, if an output is hotplugged, all windows will be scrambled, which is highly annoying. With this change, windows will stick to their outputs if an output has been connected or disconnected. BUG: 296673 BUG: 378896 BUG: 412703 BUG: 443698 --- src/abstract_client.cpp | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/abstract_client.cpp b/src/abstract_client.cpp index cccee90a17..5f306970db 100644 --- a/src/abstract_client.cpp +++ b/src/abstract_client.cpp @@ -3346,8 +3346,10 @@ void AbstractClient::checkWorkspacePosition(QRect oldGeometry, QRect oldClientGe } enum { Left = 0, Top, Right, Bottom }; const int border[4] = { borderLeft(), borderTop(), borderRight(), borderBottom() }; + + QRect newGeom = moveResizeGeometry(); if( !oldGeometry.isValid()) - oldGeometry = moveResizeGeometry(); + oldGeometry = newGeom; if (!oldClientGeometry.isValid()) oldClientGeometry = oldGeometry.adjusted(border[Left], border[Top], -border[Right], -border[Bottom]); if (isFullScreen()) { @@ -3387,20 +3389,18 @@ void AbstractClient::checkWorkspacePosition(QRect oldGeometry, QRect oldClientGe // Old and new maximums have different starting values so windows on the screen // edge will move when a new strut is placed on the edge. QRect oldScreenArea; + QRect screenArea; if( workspace()->inUpdateClientArea()) { // we need to find the screen area as it was before the change - oldScreenArea = QRect( 0, 0, workspace()->oldDisplayWidth(), workspace()->oldDisplayHeight()); - int distance = INT_MAX; - const auto previousSizes = workspace()->previousScreenSizes(); - for (const QRect &r : previousSizes) { - int d = r.contains( oldGeometry.center()) ? 0 : ( r.center() - oldGeometry.center()).manhattanLength(); - if( d < distance ) { - distance = d; - oldScreenArea = r; - } + oldScreenArea = workspace()->previousScreenSizes().value(output()); + if (oldScreenArea.isNull()) { + oldScreenArea = output()->geometry(); } + screenArea = output()->geometry(); + newGeom.translate(screenArea.topLeft() - oldScreenArea.topLeft()); } else { oldScreenArea = workspace()->clientArea(ScreenArea, kwinApp()->platform()->outputAt(oldGeometry.center()), oldDesktop); + screenArea = workspace()->clientArea(ScreenArea, this, newGeom.center()); } const QRect oldGeomTall = QRect(oldGeometry.x(), oldScreenArea.y(), oldGeometry.width(), oldScreenArea.height()); // Full screen height const QRect oldGeomWide = QRect(oldScreenArea.x(), oldGeometry.y(), oldScreenArea.width(), oldGeometry.height()); // Full screen width @@ -3408,12 +3408,10 @@ void AbstractClient::checkWorkspacePosition(QRect oldGeometry, QRect oldClientGe int oldRightMax = oldScreenArea.x() + oldScreenArea.width(); int oldBottomMax = oldScreenArea.y() + oldScreenArea.height(); int oldLeftMax = oldScreenArea.x(); - const QRect screenArea = workspace()->clientArea(ScreenArea, this, frameGeometry().center()); int topMax = screenArea.y(); int rightMax = screenArea.x() + screenArea.width(); int bottomMax = screenArea.y() + screenArea.height(); int leftMax = screenArea.x(); - QRect newGeom = frameGeometry(); QRect newClientGeom = newGeom.adjusted(border[Left], border[Top], -border[Right], -border[Bottom]); const QRect newGeomTall = QRect(newGeom.x(), screenArea.y(), newGeom.width(), screenArea.height()); // Full screen height const QRect newGeomWide = QRect(screenArea.x(), newGeom.y(), screenArea.width(), newGeom.height()); // Full screen width