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
This commit is contained in:
Vlad Zahorodnii 2021-10-30 13:02:40 +03:00
parent ee41e9b6e7
commit 4928f4db5b

View file

@ -3346,8 +3346,10 @@ void AbstractClient::checkWorkspacePosition(QRect oldGeometry, QRect oldClientGe
} }
enum { Left = 0, Top, Right, Bottom }; enum { Left = 0, Top, Right, Bottom };
const int border[4] = { borderLeft(), borderTop(), borderRight(), borderBottom() }; const int border[4] = { borderLeft(), borderTop(), borderRight(), borderBottom() };
QRect newGeom = moveResizeGeometry();
if( !oldGeometry.isValid()) if( !oldGeometry.isValid())
oldGeometry = moveResizeGeometry(); oldGeometry = newGeom;
if (!oldClientGeometry.isValid()) if (!oldClientGeometry.isValid())
oldClientGeometry = oldGeometry.adjusted(border[Left], border[Top], -border[Right], -border[Bottom]); oldClientGeometry = oldGeometry.adjusted(border[Left], border[Top], -border[Right], -border[Bottom]);
if (isFullScreen()) { 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 // 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. // edge will move when a new strut is placed on the edge.
QRect oldScreenArea; QRect oldScreenArea;
QRect screenArea;
if( workspace()->inUpdateClientArea()) { if( workspace()->inUpdateClientArea()) {
// we need to find the screen area as it was before the change // we need to find the screen area as it was before the change
oldScreenArea = QRect( 0, 0, workspace()->oldDisplayWidth(), workspace()->oldDisplayHeight()); oldScreenArea = workspace()->previousScreenSizes().value(output());
int distance = INT_MAX; if (oldScreenArea.isNull()) {
const auto previousSizes = workspace()->previousScreenSizes(); oldScreenArea = output()->geometry();
for (const QRect &r : previousSizes) {
int d = r.contains( oldGeometry.center()) ? 0 : ( r.center() - oldGeometry.center()).manhattanLength();
if( d < distance ) {
distance = d;
oldScreenArea = r;
}
} }
screenArea = output()->geometry();
newGeom.translate(screenArea.topLeft() - oldScreenArea.topLeft());
} else { } else {
oldScreenArea = workspace()->clientArea(ScreenArea, kwinApp()->platform()->outputAt(oldGeometry.center()), oldDesktop); 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 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 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 oldRightMax = oldScreenArea.x() + oldScreenArea.width();
int oldBottomMax = oldScreenArea.y() + oldScreenArea.height(); int oldBottomMax = oldScreenArea.y() + oldScreenArea.height();
int oldLeftMax = oldScreenArea.x(); int oldLeftMax = oldScreenArea.x();
const QRect screenArea = workspace()->clientArea(ScreenArea, this, frameGeometry().center());
int topMax = screenArea.y(); int topMax = screenArea.y();
int rightMax = screenArea.x() + screenArea.width(); int rightMax = screenArea.x() + screenArea.width();
int bottomMax = screenArea.y() + screenArea.height(); int bottomMax = screenArea.y() + screenArea.height();
int leftMax = screenArea.x(); int leftMax = screenArea.x();
QRect newGeom = frameGeometry();
QRect newClientGeom = newGeom.adjusted(border[Left], border[Top], -border[Right], -border[Bottom]); 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 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 const QRect newGeomWide = QRect(screenArea.x(), newGeom.y(), screenArea.width(), newGeom.height()); // Full screen width