Index: abstract_client.h =================================================================== --- abstract_client.h +++ abstract_client.h @@ -408,7 +408,7 @@ * or recursively the transient_for window * @todo: remove boolean trap **/ - virtual bool hasTransient(const AbstractClient* c, bool indirect) const; + bool hasTransient(const AbstractClient* c, bool indirect) const; const QList& transients() const; // Is not indirect virtual void removeTransient(AbstractClient* cl); virtual QList mainClients() const; // Call once before loop , is not indirect @@ -1131,6 +1131,7 @@ private: void handlePaletteChange(); + bool hasTransientInternal(const AbstractClient* c, bool indirect, QVector &set) const; QSharedPointer m_tabBoxClient; bool m_firstInTabBox = false; bool m_skipTaskbar = false; Index: abstract_client.cpp =================================================================== --- abstract_client.cpp +++ abstract_client.cpp @@ -1287,10 +1287,46 @@ return QRect(); } -bool AbstractClient::hasTransient(const AbstractClient *c, bool indirect) const +// returns true if cl is the transient_for window for this client, +// or recursively the transient_for window +bool AbstractClient::hasTransient(const AbstractClient* cl, bool indirect) const { - Q_UNUSED(indirect); - return c->transientFor() == this; + // checkGroupTransients() uses this to break loops, so hasTransient() must detect them + QVector set; + return hasTransientInternal(cl, indirect, set); +} + +bool AbstractClient::hasTransientInternal(const AbstractClient* cl, bool indirect, QVector& set) const +{ + if (const auto *t = cl->transientFor()) { + if (t == this) + return true; + if (!indirect) + return false; + if (set.contains(cl)) + return false; + set.append(cl); + return hasTransientInternal(t, indirect, set); + } + if (!cl->isTransient()) + return false; + if (group() != cl->group()) + return false; + // cl is group transient, search from top + if (transients().contains(const_cast< AbstractClient* >(cl))) + return true; + if (!indirect) + return false; + if (set.contains(this)) + return false; + set.append(this); + for (auto it = transients().constBegin(); + it != transients().constEnd(); + ++it) { + if ((*it)->hasTransientInternal(cl, indirect, set)) + return true; + } + return false; } QList< AbstractClient* > AbstractClient::mainClients() const Index: client.h =================================================================== --- client.h +++ client.h @@ -96,7 +96,6 @@ bool groupTransient() const override; bool wasOriginallyGroupTransient() const; QList mainClients() const override; // Call once before loop , is not indirect - bool hasTransient(const AbstractClient* c, bool indirect) const override; void checkTransient(xcb_window_t w); AbstractClient* findModal(bool allow_itself = false) override; const Group* group() const override; @@ -415,7 +414,6 @@ void fetchIconicName(); QString readName() const; void setCaption(const QString& s, bool force = false); - bool hasTransientInternal(const Client* c, bool indirect, ConstClientList& set) const; void setShortcutInternal() override; void configureRequest(int value_mask, int rx, int ry, int rw, int rh, int gravity, bool from_tool); Index: group.cpp =================================================================== --- group.cpp +++ group.cpp @@ -687,55 +687,6 @@ setTransient(w); } -// returns true if cl is the transient_for window for this client, -// or recursively the transient_for window -bool Client::hasTransient(const AbstractClient* cl, bool indirect) const -{ - if (const Client *c = dynamic_cast(cl)) { - // checkGroupTransients() uses this to break loops, so hasTransient() must detect them - ConstClientList set; - return hasTransientInternal(c, indirect, set); - } - return false; -} - -bool Client::hasTransientInternal(const Client* cl, bool indirect, ConstClientList& set) const -{ - if (const Client *t = dynamic_cast(cl->transientFor())) { - if (t == this) - return true; - if (!indirect) - return false; - if (set.contains(cl)) - return false; - set.append(cl); - return hasTransientInternal(t, indirect, set); - } - if (!cl->isTransient()) - return false; - if (group() != cl->group()) - return false; - // cl is group transient, search from top - if (transients().contains(const_cast< Client* >(cl))) - return true; - if (!indirect) - return false; - if (set.contains(this)) - return false; - set.append(this); - for (auto it = transients().constBegin(); - it != transients().constEnd(); - ++it) { - const Client *c = qobject_cast(*it); - if (!c) { - continue; - } - if (c->hasTransientInternal(cl, indirect, set)) - return true; - } - return false; -} - QList Client::mainClients() const { if (!isTransient())