Fix placement of windows on disconnected outputs

If an output is disconnected, the Workspace will update the
Toplevel.output property for all windows that are on that output, then
it will call AbstractClient::checkWorkspacePosition() to fix window
position.

That may result in some windows partially sticking outside visible area
because AbstractClient::checkWorkspacePosition() has no idea what output
the window was.

This change addresses that problem by delaying updating the
Toplevel.output property so AbstractClient::checkWorkspacePosition()
could pick better window placement.
This commit is contained in:
Vlad Zahorodnii 2021-10-30 17:04:21 +03:00
parent 954151ca97
commit f70c745ac0
2 changed files with 11 additions and 6 deletions

View file

@ -3389,13 +3389,18 @@ void AbstractClient::checkWorkspacePosition(QRect oldGeometry, QRect oldClientGe
// edge will move when a new strut is placed on the edge.
QRect oldScreenArea;
QRect screenArea;
if( workspace()->inUpdateClientArea()) {
if (workspace()->inUpdateClientArea()) {
// check if the window is on an about to be destroyed output
AbstractOutput *newOutput = output();
if (!kwinApp()->platform()->enabledOutputs().contains(newOutput)) {
newOutput = kwinApp()->platform()->outputAt(newGeom.center());
}
// we need to find the screen area as it was before the change
oldScreenArea = workspace()->previousScreenSizes().value(output());
if (oldScreenArea.isNull()) {
oldScreenArea = output()->geometry();
oldScreenArea = newOutput->geometry();
}
screenArea = output()->geometry();
screenArea = newOutput->geometry();
newGeom.translate(screenArea.topLeft() - oldScreenArea.topLeft());
} else {
oldScreenArea = workspace()->clientArea(ScreenArea, kwinApp()->platform()->outputAt(oldGeometry.center()), oldDesktop);

View file

@ -1214,15 +1214,15 @@ void Workspace::slotOutputDisabled(AbstractOutput *output)
m_activeOutput = kwinApp()->platform()->outputAt(output->geometry().center());
}
disconnect(output, &AbstractOutput::geometryChanged, this, &Workspace::desktopResized);
desktopResized();
const auto stack = xStackingOrder();
for (Toplevel *toplevel : stack) {
if (toplevel->output() == output) {
toplevel->setOutput(kwinApp()->platform()->outputAt(toplevel->frameGeometry().center()));
}
}
disconnect(output, &AbstractOutput::geometryChanged, this, &Workspace::desktopResized);
desktopResized();
}
void Workspace::slotDesktopAdded(VirtualDesktop *desktop)