Move transients from Client to AbstractClient

Unfortunately introduces a few casts to Client again.
icc-effect-5.14.5
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;
}
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
**/
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
QList<AbstractClient*> 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<AbstractClient*> 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*>& AbstractClient::transients() const
{
return m_transients;
}
}
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());
for (auto it = transients_stacking_order.constBegin();
it != transients_stacking_order.constEnd();
++it)
toggleClientOnActivity(*it, activity, dont_activate);
++it) {
Client *c = dynamic_cast<Client *>(*it);
if (!c) {
continue;
}
toggleClientOnActivity(c, activity, dont_activate);
}
ws->updateClientArea();
}

View File

@ -175,7 +175,6 @@ public:
bool wasOriginallyGroupTransient() const;
QList<AbstractClient*> 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;

View File

@ -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<Client*>(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<Client *>(*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<Client *>(*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()) {

View File

@ -873,9 +873,9 @@ void Client::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)) {
return true;
}

View File

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