diff --git a/deleted.h b/deleted.h --- a/deleted.h +++ b/deleted.h @@ -77,6 +77,15 @@ QList mainClients() const { return m_mainClients; } + bool wasTransient() const { + return m_transientFor != nullptr; + } + Toplevel *wasTransientFor() const { + return m_transientFor; + } + DeletedList transients() const { + return m_transients; + } NET::WindowType windowType(bool direct = false, int supported_types = 0) const; bool wasClient() const { return m_wasClient; @@ -111,6 +120,9 @@ private: Deleted(); // use create() void copyToDeleted(Toplevel* c); + void addTransient(Deleted *transient); + void removeTransient(Deleted *transient); + void setWasTransientFor(Deleted *transientFor); virtual ~Deleted(); // deleted only using unrefWindow() int delete_refcount; double window_opacity; @@ -140,6 +152,8 @@ bool m_keepAbove; bool m_keepBelow; QString m_caption; + Toplevel *m_transientFor = nullptr; + DeletedList m_transients; }; inline void Deleted::refWindow() diff --git a/deleted.cpp b/deleted.cpp --- a/deleted.cpp +++ b/deleted.cpp @@ -57,6 +57,12 @@ if (workspace()) { workspace()->removeDeleted(this); } + if (auto *transientFor = qobject_cast(m_transientFor)) { + transientFor->removeTransient(this); + } + for (Deleted *deleted : qAsConst(m_transients)) { + deleted->setWasTransientFor(nullptr); + } deleteEffectWindow(); } @@ -117,9 +123,37 @@ m_keepAbove = client->keepAbove(); m_keepBelow = client->keepBelow(); m_caption = client->caption(); + + m_transientFor = client->transientFor(); + if (m_transientFor != nullptr) { + connect(m_transientFor, &Toplevel::windowClosed, this, + [this](Toplevel *toplevel, Deleted *deleted) { + Q_UNUSED(toplevel) + m_transientFor = deleted; + if (deleted != nullptr) { + deleted->addTransient(this); + } + } + ); + } } } +void Deleted::addTransient(Deleted *transient) +{ + m_transients.append(transient); +} + +void Deleted::removeTransient(Deleted *transient) +{ + m_transients.removeAll(transient); +} + +void Deleted::setWasTransientFor(Deleted *transientFor) +{ + m_transientFor = transientFor; +} + void Deleted::unrefWindow() { if (--delete_refcount > 0) diff --git a/layers.cpp b/layers.cpp --- a/layers.cpp +++ b/layers.cpp @@ -528,57 +528,78 @@ for (int i = stacking.size() - 1; i >= 0; ) { - AbstractClient *current = qobject_cast(stacking[i]); - if (!current || !current->isTransient()) { - --i; - continue; - } int i2 = -1; - Client *ccurrent = qobject_cast(current); - if (ccurrent && ccurrent->groupTransient()) { - if (ccurrent->group()->members().count() > 0) { - // find topmost client this one is transient for - for (i2 = stacking.size() - 1; - i2 >= 0; - --i2) { - if (stacking[ i2 ] == stacking[ i ]) { - i2 = -1; // don't reorder, already the topmost in the group - break; + bool hasTransients = false; + + if (auto *current = qobject_cast(stacking[i])) { + if (current->isTransient()) { + Client *ccurrent = qobject_cast(current); + if (ccurrent && ccurrent->groupTransient()) { + if (ccurrent->group()->members().count() > 0) { + // find topmost client this one is transient for + for (i2 = stacking.size() - 1; + i2 >= 0; + --i2) { + if (stacking[ i2 ] == stacking[ i ]) { + i2 = -1; // don't reorder, already the topmost in the group + break; + } + AbstractClient *c2 = qobject_cast(stacking[ i2 ]); + if (!c2) { + continue; + } + if (c2->hasTransient(current, true) + && keepTransientAbove(c2, current)) + break; + } + } // else i2 remains pointing at -1 + } else { + for (i2 = stacking.size() - 1; + i2 >= 0; + --i2) { + AbstractClient *c2 = qobject_cast(stacking[ i2 ]); + if (!c2) { + continue; + } + if (c2 == current) { + i2 = -1; // don't reorder, already on top of its mainwindow + break; + } + if (c2 == current->transientFor() + && keepTransientAbove(c2, current)) + break; } - AbstractClient *c2 = qobject_cast(stacking[ i2 ]); - if (!c2) { - continue; + } + hasTransients = !current->transients().isEmpty(); + } + } else if (auto *deleted = qobject_cast(stacking[i])) { + if (deleted->wasTransient()) { + for (i2 = stacking.size() - 1; i2 >= 0; --i2) { + const Toplevel *toplevel = stacking[i2]; + + if (toplevel == deleted) { + i2 = -1; + break; } - if (c2->hasTransient(current, true) - && keepTransientAbove(c2, current)) + + // TODO: Check whether we have to keep the transient above? + if (toplevel == deleted->wasTransientFor()) { break; + } } - } // else i2 remains pointing at -1 - } else { - for (i2 = stacking.size() - 1; - i2 >= 0; - --i2) { - AbstractClient *c2 = qobject_cast(stacking[ i2 ]); - if (!c2) { - continue; - } - if (c2 == current) { - i2 = -1; // don't reorder, already on top of its mainwindow - break; - } - if (c2 == current->transientFor() - && keepTransientAbove(c2, current)) - break; + + hasTransients = !deleted->transients().isEmpty(); } } if (i2 == -1) { --i; continue; } + Toplevel *current = stacking[i]; stacking.removeAt(i); --i; // move onto the next item (for next for () iteration) --i2; // adjust index of the mainwindow after the remove above - if (!current->transients().isEmpty()) // this one now can be possibly above its transients, + if (hasTransients) // this one now can be possibly above its transients, i = i2; // so go again higher in the stack order and possibly move those transients again ++i2; // insert after (on top of) the mainwindow, it's ok if it2 is now stacking.end() stacking.insert(i2, current);