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/D17890icc-effect-5.17.5
parent
548626bb4c
commit
2799f69533
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
6
client.h
6
client.h
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
10
layers.cpp
10
layers.cpp
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue