Move transients from Client to AbstractClient

Unfortunately introduces a few casts to Client again.
This commit is contained in:
Martin Gräßlin 2015-09-14 10:55:27 +02:00
parent 2da04aa26b
commit 2f7597e522
7 changed files with 80 additions and 42 deletions

View file

@ -861,4 +861,21 @@ bool AbstractClient::isModal() const
return m_modal; 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);
}
} }

View file

@ -268,6 +268,7 @@ public:
* @todo: remove boolean trap * @todo: remove boolean trap
**/ **/
virtual bool hasTransient(const AbstractClient* c, bool indirect) const; virtual bool hasTransient(const AbstractClient* c, bool indirect) const;
const QList<AbstractClient*>& transients() const; // Is not indirect
virtual QList<AbstractClient*> mainClients() const; // Call once before loop , is not indirect virtual QList<AbstractClient*> mainClients() const; // Call once before loop , is not indirect
QList<AbstractClient*> allMainClients() const; // Call once before loop , is indirect QList<AbstractClient*> allMainClients() const; // Call once before loop , is indirect
/** /**
@ -497,6 +498,12 @@ protected:
void updateColorScheme(QString path); void updateColorScheme(QString path);
void setTransientFor(AbstractClient *transientFor); 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: private:
void handlePaletteChange(); void handlePaletteChange();
@ -526,6 +533,7 @@ private:
KWayland::Server::PlasmaWindowInterface *m_windowManagementInterface = nullptr; KWayland::Server::PlasmaWindowInterface *m_windowManagementInterface = nullptr;
AbstractClient *m_transientFor = nullptr; AbstractClient *m_transientFor = nullptr;
QList<AbstractClient*> m_transients;
bool m_modal = false; bool m_modal = false;
}; };
@ -539,6 +547,11 @@ inline void AbstractClient::resizeWithChecks(const QSize& s, AbstractClient::For
resizeWithChecks(s.width(), s.height(), force); resizeWithChecks(s.width(), s.height(), force);
} }
inline const QList<AbstractClient*>& AbstractClient::transients() const
{
return m_transients;
}
} }
Q_DECLARE_METATYPE(KWin::AbstractClient*) Q_DECLARE_METATYPE(KWin::AbstractClient*)

View file

@ -108,8 +108,13 @@ void Activities::toggleClientOnActivity(Client* c, const QString &activity, bool
auto transients_stacking_order = ws->ensureStackingOrder(c->transients()); auto transients_stacking_order = ws->ensureStackingOrder(c->transients());
for (auto it = transients_stacking_order.constBegin(); for (auto it = transients_stacking_order.constBegin();
it != transients_stacking_order.constEnd(); it != transients_stacking_order.constEnd();
++it) ++it) {
toggleClientOnActivity(*it, activity, dont_activate); Client *c = dynamic_cast<Client *>(*it);
if (!c) {
continue;
}
toggleClientOnActivity(c, activity, dont_activate);
}
ws->updateClientArea(); ws->updateClientArea();
} }

View file

@ -175,7 +175,6 @@ public:
bool wasOriginallyGroupTransient() const; bool wasOriginallyGroupTransient() const;
QList<AbstractClient*> mainClients() const override; // Call once before loop , is not indirect QList<AbstractClient*> mainClients() const override; // Call once before loop , is not indirect
bool hasTransient(const AbstractClient* c, bool indirect) const override; bool hasTransient(const AbstractClient* c, bool indirect) const override;
const ClientList& transients() const; // Is not indirect
void checkTransient(xcb_window_t w); void checkTransient(xcb_window_t w);
AbstractClient* findModal(bool allow_itself = false) override; AbstractClient* findModal(bool allow_itself = false) override;
const Group* group() const; const Group* group() const;
@ -700,15 +699,14 @@ private:
void readTransientProperty(Xcb::TransientFor &transientFor); void readTransientProperty(Xcb::TransientFor &transientFor);
void readTransient(); void readTransient();
xcb_window_t verifyTransientFor(xcb_window_t transient_for, bool set); xcb_window_t verifyTransientFor(xcb_window_t transient_for, bool set);
void addTransient(Client* cl); void addTransient(AbstractClient* cl) override;
void removeTransient(Client* cl); void removeTransient(AbstractClient* cl) override;
void removeFromMainClients(); void removeFromMainClients();
void cleanGrouping(); void cleanGrouping();
void checkGroupTransients(); void checkGroupTransients();
void setTransient(xcb_window_t new_transient_for_id); void setTransient(xcb_window_t new_transient_for_id);
xcb_window_t m_transientForId; xcb_window_t m_transientForId;
xcb_window_t m_originalTransientForId; xcb_window_t m_originalTransientForId;
ClientList transients_list; // SELI TODO: Make this ordered in stacking order?
ShadeMode shade_mode; ShadeMode shade_mode;
Client *shade_below; Client *shade_below;
uint deleting : 1; ///< True when doing cleanup and destroying the client 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; return m_transientForId != XCB_WINDOW_NONE;
} }
inline const ClientList& Client::transients() const
{
return transients_list;
}
inline const Group* Client::group() const inline const Group* Client::group() const
{ {
return in_group; return in_group;

View file

@ -96,14 +96,14 @@ bool performTransiencyCheck()
ret = false; ret = false;
continue; 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; kdDebug(1212) << "TC:" << *it1 << " has main client " << *it2 << " but main client does not have it as a transient" << endl;
ret = false; ret = false;
} }
} }
} }
ClientList trans = (*it1)->transients_list; auto trans = (*it1)->transients();
for (ClientList::ConstIterator it2 = trans.constBegin(); for (auto it2 = trans.constBegin();
it2 != trans.constEnd(); it2 != trans.constEnd();
++it2) { ++it2) {
if (transiencyCheckNonExistent if (transiencyCheckNonExistent
@ -342,7 +342,7 @@ Group* Workspace::findClientLeaderGroup(const Client* c) const
return ret; return ret;
} }
void Workspace::updateMinimizedOfTransients(Client* c) void Workspace::updateMinimizedOfTransients(AbstractClient* c)
{ {
// if mainwindow is minimized or shaded, minimize transients too // if mainwindow is minimized or shaded, minimize transients too
if (c->isMinimized()) { if (c->isMinimized()) {
@ -637,12 +637,12 @@ void Client::cleanGrouping()
// it != mains.end(); // it != mains.end();
// ++it ) // ++it )
// qDebug() << "MN2:" << *it; // qDebug() << "MN2:" << *it;
for (ClientList::ConstIterator it = transients_list.constBegin(); for (auto it = transients().constBegin();
it != transients_list.constEnd(); it != transients().constEnd();
) { ) {
if ((*it)->transientFor() == this) { if ((*it)->transientFor() == this) {
removeTransient(*it); 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 } else
++it; ++it;
} }
@ -699,7 +699,7 @@ void Client::checkGroupTransients()
cl = cl->transientFor()) { cl = cl->transientFor()) {
if (cl == *it1) { if (cl == *it1) {
// don't use removeTransient(), that would modify *it2 too // don't use removeTransient(), that would modify *it2 too
(*it2)->transients_list.removeAll(*it1); (*it2)->removeTransientFromList(*it1);
continue; continue;
} }
} }
@ -708,7 +708,7 @@ void Client::checkGroupTransients()
// and should be therefore on top of *it1 // and should be therefore on top of *it1
// TODO This could possibly be optimized, it also requires hasTransient() to check for loops. // 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)) 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 // 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 // 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, // transient for it - the indirect transiency actually shouldn't break anything,
@ -721,9 +721,9 @@ void Client::checkGroupTransients()
continue; continue;
if ((*it2)->hasTransient(*it1, false) && (*it3)->hasTransient(*it1, false)) { if ((*it2)->hasTransient(*it1, false) && (*it3)->hasTransient(*it1, false)) {
if ((*it2)->hasTransient(*it3, true)) if ((*it2)->hasTransient(*it3, true))
(*it2)->transients_list.removeAll(*it1); (*it2)->removeTransientFromList(*it1);
if ((*it3)->hasTransient(*it2, true)) 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; return new_transient_for;
} }
void Client::addTransient(Client* cl) void Client::addTransient(AbstractClient* cl)
{ {
TRANSIENCY_CHECK(this); TRANSIENCY_CHECK(this);
assert(!transients_list.contains(cl)); AbstractClient::addTransient(cl);
// assert( !cl->hasTransient( this, true )); will be fixed in checkGroupTransients()
assert(cl != this);
transients_list.append(cl);
if (workspace()->mostRecentlyActivatedClient() == this && cl->isModal()) if (workspace()->mostRecentlyActivatedClient() == this && cl->isModal())
check_active_modal = true; check_active_modal = true;
// qDebug() << "ADDTRANS:" << this << ":" << cl; // qDebug() << "ADDTRANS:" << this << ":" << cl;
@ -814,19 +811,21 @@ void Client::addTransient(Client* cl)
// qDebug() << "AT:" << (*it); // qDebug() << "AT:" << (*it);
} }
void Client::removeTransient(Client* cl) void Client::removeTransient(AbstractClient* cl)
{ {
TRANSIENCY_CHECK(this); TRANSIENCY_CHECK(this);
// qDebug() << "REMOVETRANS:" << this << ":" << cl; // qDebug() << "REMOVETRANS:" << this << ":" << cl;
// qDebug() << kBacktrace(); // qDebug() << kBacktrace();
transients_list.removeAll(cl);
// cl is transient for this, but this is going away // cl is transient for this, but this is going away
// make cl group transient // make cl group transient
AbstractClient::removeTransient(cl);
if (cl->transientFor() == this) { if (cl->transientFor() == this) {
cl->m_transientForId = XCB_WINDOW_NONE; if (Client *c = dynamic_cast<Client*>(cl)) {
cl->setTransientFor(nullptr); // SELI c->m_transientForId = XCB_WINDOW_NONE;
c->setTransientFor(nullptr); // SELI
// SELI cl->setTransient( rootWindow()); // 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); set.append(this);
for (auto it = transients().constBegin(); for (auto it = transients().constBegin();
it != transients().constEnd(); it != transients().constEnd();
++it) ++it) {
if ((*it)->hasTransientInternal(cl, indirect, set)) Client *c = dynamic_cast<Client *>(*it);
if (!c) {
continue;
}
if (c->hasTransientInternal(cl, indirect, set))
return true; return true;
}
return false; return false;
} }
@ -985,13 +989,19 @@ void Client::checkGroup(Group* set_group, bool force)
} }
} }
if (in_group != old_group || force) { if (in_group != old_group || force) {
for (ClientList::Iterator it = transients_list.begin(); for (auto it = transients().constBegin();
it != transients_list.end(); it != transients().constEnd();
) { ) {
Client *c = dynamic_cast<Client *>(*it);
if (!c) {
++it;
continue;
}
// group transients in the old group are no longer transient for it // group transients in the old group are no longer transient for it
if ((*it)->groupTransient() && (*it)->group() != group()) if (c->groupTransient() && c->group() != group()) {
it = transients_list.erase(it); removeTransientFromList(c);
else it = transients().constBegin(); // restart, just in case something more has changed with the list
} else
++it; ++it;
} }
if (groupTransient()) { if (groupTransient()) {

View file

@ -873,9 +873,9 @@ void Client::updateLayer()
(*it)->updateLayer(); (*it)->updateLayer();
} }
bool rec_checkTransientOnTop(const ClientList &transients, const Client *topmost) bool rec_checkTransientOnTop(const QList<AbstractClient*> &transients, const Client *topmost)
{ {
foreach (const Client *transient, transients) { foreach (const AbstractClient *transient, transients) {
if (transient == topmost || rec_checkTransientOnTop(transient->transients(), topmost)) { if (transient == topmost || rec_checkTransientOnTop(transient->transients(), topmost)) {
return true; return true;
} }

View file

@ -262,7 +262,7 @@ public:
return m_userActionsMenu; return m_userActionsMenu;
} }
void updateMinimizedOfTransients(Client*); void updateMinimizedOfTransients(AbstractClient*);
void updateOnAllDesktopsOfTransients(Client*); void updateOnAllDesktopsOfTransients(Client*);
void checkTransients(xcb_window_t w); void checkTransients(xcb_window_t w);