diff --git a/abstract_client.cpp b/abstract_client.cpp index c00121cd57..f095db81c1 100644 --- a/abstract_client.cpp +++ b/abstract_client.cpp @@ -861,4 +861,21 @@ bool AbstractClient::isModal() const return m_modal; } +void AbstractClient::addTransient(AbstractClient *cl) +{ + assert(!m_transients.contains(cl)); + assert(cl != this); + m_transients.append(cl); +} + +void AbstractClient::removeTransient(AbstractClient *cl) +{ + m_transients.removeAll(cl); +} + +void AbstractClient::removeTransientFromList(AbstractClient *cl) +{ + m_transients.removeAll(cl); +} + } diff --git a/abstract_client.h b/abstract_client.h index 1c6356dd4d..d726ebdcea 100644 --- a/abstract_client.h +++ b/abstract_client.h @@ -268,6 +268,7 @@ public: * @todo: remove boolean trap **/ virtual bool hasTransient(const AbstractClient* c, bool indirect) const; + const QList& transients() const; // Is not indirect virtual QList mainClients() const; // Call once before loop , is not indirect QList allMainClients() const; // Call once before loop , is indirect /** @@ -497,6 +498,12 @@ protected: void updateColorScheme(QString path); void setTransientFor(AbstractClient *transientFor); + virtual void addTransient(AbstractClient* cl); + virtual void removeTransient(AbstractClient* cl); + /** + * Just removes the @p cl from the transients without any further checks. + **/ + void removeTransientFromList(AbstractClient* cl); private: void handlePaletteChange(); @@ -526,6 +533,7 @@ private: KWayland::Server::PlasmaWindowInterface *m_windowManagementInterface = nullptr; AbstractClient *m_transientFor = nullptr; + QList m_transients; bool m_modal = false; }; @@ -539,6 +547,11 @@ inline void AbstractClient::resizeWithChecks(const QSize& s, AbstractClient::For resizeWithChecks(s.width(), s.height(), force); } +inline const QList& AbstractClient::transients() const +{ + return m_transients; +} + } Q_DECLARE_METATYPE(KWin::AbstractClient*) diff --git a/activities.cpp b/activities.cpp index ab330d7b6f..42c5db8019 100644 --- a/activities.cpp +++ b/activities.cpp @@ -108,8 +108,13 @@ void Activities::toggleClientOnActivity(Client* c, const QString &activity, bool auto transients_stacking_order = ws->ensureStackingOrder(c->transients()); for (auto it = transients_stacking_order.constBegin(); it != transients_stacking_order.constEnd(); - ++it) - toggleClientOnActivity(*it, activity, dont_activate); + ++it) { + Client *c = dynamic_cast(*it); + if (!c) { + continue; + } + toggleClientOnActivity(c, activity, dont_activate); + } ws->updateClientArea(); } diff --git a/client.h b/client.h index 1948cd2fe3..31aa9e3f83 100644 --- a/client.h +++ b/client.h @@ -175,7 +175,6 @@ public: bool wasOriginallyGroupTransient() const; QList mainClients() const override; // Call once before loop , is not indirect bool hasTransient(const AbstractClient* c, bool indirect) const override; - const ClientList& transients() const; // Is not indirect void checkTransient(xcb_window_t w); AbstractClient* findModal(bool allow_itself = false) override; const Group* group() const; @@ -700,15 +699,14 @@ private: void readTransientProperty(Xcb::TransientFor &transientFor); void readTransient(); xcb_window_t verifyTransientFor(xcb_window_t transient_for, bool set); - void addTransient(Client* cl); - void removeTransient(Client* cl); + void addTransient(AbstractClient* cl) override; + void removeTransient(AbstractClient* cl) override; void removeFromMainClients(); void cleanGrouping(); void checkGroupTransients(); void setTransient(xcb_window_t new_transient_for_id); xcb_window_t m_transientForId; xcb_window_t m_originalTransientForId; - ClientList transients_list; // SELI TODO: Make this ordered in stacking order? ShadeMode shade_mode; Client *shade_below; uint deleting : 1; ///< True when doing cleanup and destroying the client @@ -835,11 +833,6 @@ inline bool Client::isTransient() const return m_transientForId != XCB_WINDOW_NONE; } -inline const ClientList& Client::transients() const -{ - return transients_list; -} - inline const Group* Client::group() const { return in_group; diff --git a/group.cpp b/group.cpp index 5e5fbc8dc2..1d5bfe06b5 100644 --- a/group.cpp +++ b/group.cpp @@ -96,14 +96,14 @@ bool performTransiencyCheck() ret = false; continue; } - if (!(*it2)->transients_list.contains(*it1)) { + if (!(*it2)->transients().contains(*it1)) { kdDebug(1212) << "TC:" << *it1 << " has main client " << *it2 << " but main client does not have it as a transient" << endl; ret = false; } } } - ClientList trans = (*it1)->transients_list; - for (ClientList::ConstIterator it2 = trans.constBegin(); + auto trans = (*it1)->transients(); + for (auto it2 = trans.constBegin(); it2 != trans.constEnd(); ++it2) { if (transiencyCheckNonExistent @@ -342,7 +342,7 @@ Group* Workspace::findClientLeaderGroup(const Client* c) const return ret; } -void Workspace::updateMinimizedOfTransients(Client* c) +void Workspace::updateMinimizedOfTransients(AbstractClient* c) { // if mainwindow is minimized or shaded, minimize transients too if (c->isMinimized()) { @@ -637,12 +637,12 @@ void Client::cleanGrouping() // it != mains.end(); // ++it ) // qDebug() << "MN2:" << *it; - for (ClientList::ConstIterator it = transients_list.constBegin(); - it != transients_list.constEnd(); + for (auto it = transients().constBegin(); + it != transients().constEnd(); ) { if ((*it)->transientFor() == this) { removeTransient(*it); - it = transients_list.constBegin(); // restart, just in case something more has changed with the list + it = transients().constBegin(); // restart, just in case something more has changed with the list } else ++it; } @@ -699,7 +699,7 @@ void Client::checkGroupTransients() cl = cl->transientFor()) { if (cl == *it1) { // don't use removeTransient(), that would modify *it2 too - (*it2)->transients_list.removeAll(*it1); + (*it2)->removeTransientFromList(*it1); continue; } } @@ -708,7 +708,7 @@ void Client::checkGroupTransients() // and should be therefore on top of *it1 // TODO This could possibly be optimized, it also requires hasTransient() to check for loops. if ((*it2)->groupTransient() && (*it1)->hasTransient(*it2, true) && (*it2)->hasTransient(*it1, true)) - (*it2)->transients_list.removeAll(*it1); + (*it2)->removeTransientFromList(*it1); // if there are already windows W1 and W2, W2 being transient for W1, and group transient W3 // is added, make it transient only for W2, not for W1, because it's already indirectly // transient for it - the indirect transiency actually shouldn't break anything, @@ -721,9 +721,9 @@ void Client::checkGroupTransients() continue; if ((*it2)->hasTransient(*it1, false) && (*it3)->hasTransient(*it1, false)) { if ((*it2)->hasTransient(*it3, true)) - (*it2)->transients_list.removeAll(*it1); + (*it2)->removeTransientFromList(*it1); if ((*it3)->hasTransient(*it2, true)) - (*it3)->transients_list.removeAll(*it1); + (*it3)->removeTransientFromList(*it1); } } } @@ -797,13 +797,10 @@ xcb_window_t Client::verifyTransientFor(xcb_window_t new_transient_for, bool set return new_transient_for; } -void Client::addTransient(Client* cl) +void Client::addTransient(AbstractClient* cl) { TRANSIENCY_CHECK(this); - assert(!transients_list.contains(cl)); -// assert( !cl->hasTransient( this, true )); will be fixed in checkGroupTransients() - assert(cl != this); - transients_list.append(cl); + AbstractClient::addTransient(cl); if (workspace()->mostRecentlyActivatedClient() == this && cl->isModal()) check_active_modal = true; // qDebug() << "ADDTRANS:" << this << ":" << cl; @@ -814,19 +811,21 @@ void Client::addTransient(Client* cl) // qDebug() << "AT:" << (*it); } -void Client::removeTransient(Client* cl) +void Client::removeTransient(AbstractClient* cl) { TRANSIENCY_CHECK(this); // qDebug() << "REMOVETRANS:" << this << ":" << cl; // qDebug() << kBacktrace(); - transients_list.removeAll(cl); // cl is transient for this, but this is going away // make cl group transient + AbstractClient::removeTransient(cl); if (cl->transientFor() == this) { - cl->m_transientForId = XCB_WINDOW_NONE; - cl->setTransientFor(nullptr); // SELI + if (Client *c = dynamic_cast(cl)) { + c->m_transientForId = XCB_WINDOW_NONE; + c->setTransientFor(nullptr); // SELI // SELI cl->setTransient( rootWindow()); - cl->setTransient(XCB_WINDOW_NONE); + c->setTransient(XCB_WINDOW_NONE); + } } } @@ -878,9 +877,14 @@ bool Client::hasTransientInternal(const Client* cl, bool indirect, ConstClientLi set.append(this); for (auto it = transients().constBegin(); it != transients().constEnd(); - ++it) - if ((*it)->hasTransientInternal(cl, indirect, set)) + ++it) { + Client *c = dynamic_cast(*it); + if (!c) { + continue; + } + if (c->hasTransientInternal(cl, indirect, set)) return true; + } return false; } @@ -985,13 +989,19 @@ void Client::checkGroup(Group* set_group, bool force) } } if (in_group != old_group || force) { - for (ClientList::Iterator it = transients_list.begin(); - it != transients_list.end(); + for (auto it = transients().constBegin(); + it != transients().constEnd(); ) { + Client *c = dynamic_cast(*it); + if (!c) { + ++it; + continue; + } // group transients in the old group are no longer transient for it - if ((*it)->groupTransient() && (*it)->group() != group()) - it = transients_list.erase(it); - else + if (c->groupTransient() && c->group() != group()) { + removeTransientFromList(c); + it = transients().constBegin(); // restart, just in case something more has changed with the list + } else ++it; } if (groupTransient()) { diff --git a/layers.cpp b/layers.cpp index c4646ffc73..26663593e9 100644 --- a/layers.cpp +++ b/layers.cpp @@ -873,9 +873,9 @@ void Client::updateLayer() (*it)->updateLayer(); } -bool rec_checkTransientOnTop(const ClientList &transients, const Client *topmost) +bool rec_checkTransientOnTop(const QList &transients, const Client *topmost) { - foreach (const Client *transient, transients) { + foreach (const AbstractClient *transient, transients) { if (transient == topmost || rec_checkTransientOnTop(transient->transients(), topmost)) { return true; } diff --git a/workspace.h b/workspace.h index a815d717fb..7b515bb863 100644 --- a/workspace.h +++ b/workspace.h @@ -262,7 +262,7 @@ public: return m_userActionsMenu; } - void updateMinimizedOfTransients(Client*); + void updateMinimizedOfTransients(AbstractClient*); void updateOnAllDesktopsOfTransients(Client*); void checkTransients(xcb_window_t w);