Move groupTransient and group from Client to AbstractClient as virtual

Summary:
The default implementations just return false/nullptr. The advantage of
having this in AbstractClient is that we can reduce the needed casts
from AbstractClient to Client in core as can be seen in this change.

There are more cases which can be improved thanks to this refactoring
which will follow in dedicated commits.

Test Plan: ctest passes

Reviewers: #kwin

Subscribers: kwin

Tags: #kwin

Differential Revision: https://phabricator.kde.org/D17890
icc-effect-5.17.5
Martin Flöser 2018-12-31 18:57:13 +01:00
parent 548626bb4c
commit 2799f69533
7 changed files with 59 additions and 26 deletions

View File

@ -2015,4 +2015,19 @@ void AbstractClient::checkNoBorder()
setNoBorder(false);
}
bool AbstractClient::groupTransient() const
{
return false;
}
const Group *AbstractClient::group() const
{
return nullptr;
}
Group *AbstractClient::group()
{
return nullptr;
}
}

View File

@ -753,6 +753,31 @@ public:
return false;
}
/**
* Default implementation returns @c null.
* Mostly intended for X11 clients, from EWMH:
* <quote>
* 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.
* </quote>
**/
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;

View File

@ -93,14 +93,14 @@ public:
virtual xcb_window_t frameId() const override;
bool isTransient() const override;
bool groupTransient() const;
bool groupTransient() const override;
bool wasOriginallyGroupTransient() const;
QList<AbstractClient*> 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;

View File

@ -137,8 +137,7 @@ void Deleted::copyToDeleted(Toplevel* c)
m_wasActive = client->isActive();
const auto *x11Client = qobject_cast<Client *>(client);
m_wasGroupTransient = x11Client && x11Client->groupTransient();
m_wasGroupTransient = client->groupTransient();
}
for (auto vd : m_desktops) {

View File

@ -839,11 +839,7 @@ void Client::checkGroup(Group* set_group, bool force)
for (auto it = transients().constBegin();
it != transients().constEnd();
) {
Client *c = dynamic_cast<Client *>(*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);

View File

@ -313,8 +313,8 @@ void Workspace::lowerClient(AbstractClient* c, bool nogroup)
if (!nogroup && c->isTransient()) {
// lower also all windows in the group, in their reversed stacking order
ClientList wins;
if (Client *client = dynamic_cast<Client*>(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 @@ bool Workspace::keepTransientAbove(const AbstractClient* mainwindow, const Abstr
// 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<const Client*>(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

View File

@ -767,35 +767,35 @@ void Workspace::updateToolWindows(bool also_hide)
(*it)->hideClient(false);
return;
}
const Group* group = NULL;
const Client* client = dynamic_cast<Client*>(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<const Client*>(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<AbstractClient*> to_show, to_hide;
for (ToplevelList::ConstIterator it = stacking_order.constBegin();
it != stacking_order.constEnd();
++it) {
Client *c = qobject_cast<Client*>(*it);
auto c = qobject_cast<AbstractClient*>(*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 @@ void Workspace::updateToolWindows(bool also_hide)
// 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 @@ void Workspace::setShowingDesktop(bool showing)
lowerClient(c);
if (!topDesk)
topDesk = c;
if (Client *client = qobject_cast<Client*>(c)) {
foreach (Client *cm, client->group()->members()) {
if (auto group = c->group()) {
foreach (Client *cm, group->members()) {
cm->updateLayer();
}
}