diff --git a/abstract_client.h b/abstract_client.h
--- a/abstract_client.h
+++ b/abstract_client.h
@@ -753,6 +753,31 @@
return false;
}
+ /**
+ * Default implementation returns @c null.
+ * Mostly intended for X11 clients, from EWMH:
+ *
+ * If the WM_TRANSIENT_FOR property is set to None or Root window, the window should be
+ * treated as a transient for all other windows in the same group. It has been noted that this
+ * is a slight ICCCM violation, but as this behavior is pretty standard for many toolkits and
+ * window managers, and is extremely unlikely to break anything, it seems reasonable to document
+ * it as standard.
+ *
+ **/
+ virtual bool groupTransient() const;
+ /**
+ * Default implementation returns @c null.
+ *
+ * Mostly for X11 clients, holds the client group
+ **/
+ virtual const Group *group() const;
+ /**
+ * Default implementation returns @c null.
+ *
+ * Mostly for X11 clients, holds the client group
+ **/
+ virtual Group *group();
+
public Q_SLOTS:
virtual void closeWindow() = 0;
diff --git a/abstract_client.cpp b/abstract_client.cpp
--- a/abstract_client.cpp
+++ b/abstract_client.cpp
@@ -2015,4 +2015,19 @@
setNoBorder(false);
}
+bool AbstractClient::groupTransient() const
+{
+ return false;
+}
+
+const Group *AbstractClient::group() const
+{
+ return nullptr;
+}
+
+Group *AbstractClient::group()
+{
+ return nullptr;
+}
+
}
diff --git a/client.h b/client.h
--- a/client.h
+++ b/client.h
@@ -93,14 +93,14 @@
virtual xcb_window_t frameId() const override;
bool isTransient() const override;
- bool groupTransient() const;
+ 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;
- Group* group();
+ const Group* group() const override;
+ Group* group() override;
void checkGroup(Group* gr = NULL, bool force = false);
void changeClientLeaderGroup(Group* gr);
void updateWindowRules(Rules::Types selection) override;
diff --git a/deleted.cpp b/deleted.cpp
--- a/deleted.cpp
+++ b/deleted.cpp
@@ -137,8 +137,7 @@
m_wasActive = client->isActive();
- const auto *x11Client = qobject_cast(client);
- m_wasGroupTransient = x11Client && x11Client->groupTransient();
+ m_wasGroupTransient = client->groupTransient();
}
for (auto vd : m_desktops) {
diff --git a/group.cpp b/group.cpp
--- a/group.cpp
+++ b/group.cpp
@@ -839,11 +839,7 @@
for (auto it = transients().constBegin();
it != transients().constEnd();
) {
- Client *c = dynamic_cast(*it);
- if (!c) {
- ++it;
- continue;
- }
+ auto *c = *it;
// group transients in the old group are no longer transient for it
if (c->groupTransient() && c->group() != group()) {
removeTransientFromList(c);
diff --git a/layers.cpp b/layers.cpp
--- a/layers.cpp
+++ b/layers.cpp
@@ -313,8 +313,8 @@
if (!nogroup && c->isTransient()) {
// lower also all windows in the group, in their reversed stacking order
ClientList wins;
- if (Client *client = dynamic_cast(c)) {
- wins = ensureStackingOrder(client->group()->members());
+ if (auto group = c->group()) {
+ wins = ensureStackingOrder(group->members());
}
for (int i = wins.size() - 1;
i >= 0;
@@ -672,10 +672,8 @@
// the mainwindow, but only if they're group transient (since only such dialogs
// have taskbar entry in Kicker). A proper way of doing this (both kwin and kicker)
// needs to be found.
- if (const Client *ct = dynamic_cast(transient)) {
- if (ct->isDialog() && !ct->isModal() && ct->groupTransient())
- return false;
- }
+ if (transient->isDialog() && !transient->isModal() && transient->groupTransient())
+ return false;
// #63223 - don't keep transients above docks, because the dock is kept high,
// and e.g. dialogs for them would be too high too
// ignore this if the transient has a placement hint which indicates it should go above it's parent
diff --git a/workspace.cpp b/workspace.cpp
--- a/workspace.cpp
+++ b/workspace.cpp
@@ -767,35 +767,35 @@
(*it)->hideClient(false);
return;
}
- const Group* group = NULL;
- const Client* client = dynamic_cast(active_client);
+ const Group* group = nullptr;
+ auto client = active_client;
// Go up in transiency hiearchy, if the top is found, only tool transients for the top mainwindow
// will be shown; if a group transient is group, all tools in the group will be shown
- while (client != NULL) {
+ while (client != nullptr) {
if (!client->isTransient())
break;
if (client->groupTransient()) {
group = client->group();
break;
}
- client = dynamic_cast(client->transientFor());
+ client = client->transientFor();
}
// Use stacking order only to reduce flicker, it doesn't matter if block_stacking_updates == 0,
// I.e. if it's not up to date
// SELI TODO: But maybe it should - what if a new client has been added that's not in stacking order yet?
- ClientList to_show, to_hide;
+ QVector to_show, to_hide;
for (ToplevelList::ConstIterator it = stacking_order.constBegin();
it != stacking_order.constEnd();
++it) {
- Client *c = qobject_cast(*it);
+ auto c = qobject_cast(*it);
if (!c) {
continue;
}
if (c->isUtility() || c->isMenu() || c->isToolbar()) {
bool show = true;
if (!c->isTransient()) {
- if (c->group()->members().count() == 1) // Has its own group, keep always visible
+ if (!c->group() || c->group()->members().count() == 1) // Has its own group, keep always visible
show = true;
else if (client != NULL && c->group() == client->group())
show = true;
@@ -834,7 +834,7 @@
// TODO: Since this is in stacking order, the order of taskbar entries changes :(
to_show.at(i)->hideClient(false);
if (also_hide) {
- for (ClientList::ConstIterator it = to_hide.constBegin();
+ for (auto it = to_hide.constBegin();
it != to_hide.constEnd();
++it) // From bottommost
(*it)->hideClient(true);
@@ -1283,8 +1283,8 @@
lowerClient(c);
if (!topDesk)
topDesk = c;
- if (Client *client = qobject_cast(c)) {
- foreach (Client *cm, client->group()->members()) {
+ if (auto group = c->group()) {
+ foreach (Client *cm, group->members()) {
cm->updateLayer();
}
}