Preserve stacking order constraints when closing a window

When closing a window, we may need to change parent-child relationship
between windows, but we need to preserve stacking order constraints so
dialogs are placed above their parents when they're closed.
This commit is contained in:
Vlad Zahorodnii 2023-03-23 10:19:12 +02:00
parent 2510bf0439
commit 5454cc47c3
3 changed files with 31 additions and 22 deletions

View file

@ -221,16 +221,18 @@ void WaylandWindow::doSetActive()
void WaylandWindow::cleanGrouping()
{
// We want to break parent-child relationships, but preserve stacking
// order constraints at the same time for window closing animations.
if (transientFor()) {
transientFor()->removeTransient(this);
transientFor()->removeTransientFromList(this);
setTransientFor(nullptr);
}
for (auto it = transients().constBegin(); it != transients().constEnd();) {
if ((*it)->transientFor() == this) {
removeTransient(*it);
it = transients().constBegin(); // restart, just in case something more has changed with the list
} else {
++it;
}
const auto children = transients();
for (Window *transient : children) {
removeTransientFromList(transient);
transient->setTransientFor(nullptr);
}
}

View file

@ -925,6 +925,7 @@ public:
virtual QRectF transientPlacement(const QRectF &bounds) const;
const Window *transientFor() const;
Window *transientFor();
void setTransientFor(Window *transientFor);
/**
* @returns @c true if transient is the transient_for window for this window,
* or recursively the transient_for window
@ -934,6 +935,7 @@ public:
const QList<Window *> &transients() const; // Is not indirect
virtual void addTransient(Window *transient);
virtual void removeTransient(Window *transient);
void removeTransientFromList(Window *cl);
virtual QList<Window *> mainWindows() const; // Call once before loop , is not indirect
QList<Window *> allMainWindows() const; // Call once before loop , is indirect
/**
@ -1623,11 +1625,6 @@ protected:
void setupWindowManagementInterface();
void updateColorScheme();
void ensurePalette();
void setTransientFor(Window *transientFor);
/**
* Just removes the @p cl from the transients without any further checks.
*/
void removeTransientFromList(Window *cl);
virtual Layer belongsToLayer() const;
virtual bool belongsToDesktop() const;

View file

@ -3076,19 +3076,29 @@ void X11Window::removeFromMainClients()
// related lists.
void X11Window::cleanGrouping()
{
removeFromMainClients();
group()->removeMember(this);
in_group = nullptr;
// We want to break parent-child relationships, but preserve stacking
// order constraints at the same time for window closing animations.
for (auto it = transients().constBegin(); it != transients().constEnd();) {
if ((*it)->transientFor() == this) {
removeTransient(*it);
it = transients().constBegin(); // restart, just in case something more has changed with the list
} else {
++it;
if (transientFor()) {
transientFor()->removeTransientFromList(this);
setTransientFor(nullptr);
}
if (groupTransient()) {
const auto members = group()->members();
for (Window *member : members) {
member->removeTransientFromList(this);
}
}
const auto children = transients();
for (Window *transient : children) {
removeTransientFromList(transient);
transient->setTransientFor(nullptr);
}
group()->removeMember(this);
in_group = nullptr;
m_transientForId = XCB_WINDOW_NONE;
}