Move WindowRules from Client to AbstractClient

Summary:
So far window rule specific functionality was only implemented in Client
and in ShellClient there was only a dummy implementation. This change
moves the client_rules member variable from Client to AbstractClient.
Areas which would not compile anymore are adjusted.

This is a first step to get window rule support for Wayland windows.

Reviewers: #kwin, #plasma

Subscribers: plasma-devel, kwin

Tags: #kwin

Differential Revision: https://phabricator.kde.org/D8090
This commit is contained in:
Martin Flöser 2017-10-01 16:38:57 +02:00
parent 07d1cb1191
commit 0372fdaf92
9 changed files with 80 additions and 65 deletions

View file

@ -1776,4 +1776,25 @@ QString AbstractClient::caption() const
return cap;
}
void AbstractClient::removeRule(Rules* rule)
{
m_rules.remove(rule);
}
void AbstractClient::discardTemporaryRules()
{
m_rules.discardTemporary();
}
void AbstractClient::evaluateWindowRules()
{
setupWindowRules(true);
applyWindowRules();
}
void AbstractClient::setOnActivities(QStringList newActivitiesList)
{
Q_UNUSED(newActivitiesList)
}
}

View file

@ -460,8 +460,15 @@ public:
virtual QRect iconGeometry() const;
virtual bool userCanSetFullScreen() const = 0;
virtual bool userCanSetNoBorder() const = 0;
virtual void setOnActivities(QStringList newActivitiesList);
virtual void setOnAllActivities(bool set) = 0;
virtual const WindowRules* rules() const = 0;
const WindowRules* rules() const {
return &m_rules;
}
void removeRule(Rules* r);
void setupWindowRules(bool ignore_temporary);
void evaluateWindowRules();
void applyWindowRules();
virtual void takeFocus() = 0;
virtual bool wantsInput() const = 0;
/**
@ -478,7 +485,7 @@ public:
virtual bool dockWantsInput() const;
void checkWorkspacePosition(QRect oldGeometry = QRect(), int oldDesktop = -2, QRect oldClientGeometry = QRect());
virtual xcb_timestamp_t userTime() const;
virtual void updateWindowRules(Rules::Types selection) = 0;
virtual void updateWindowRules(Rules::Types selection);
void growHorizontal();
void shrinkHorizontal();
@ -775,6 +782,7 @@ protected:
void destroyWindowManagementInterface();
void updateColorScheme(QString path);
virtual void updateColorScheme() = 0;
void setTransientFor(AbstractClient *transientFor);
virtual void addTransient(AbstractClient* cl);
@ -1009,6 +1017,9 @@ protected:
**/
AbstractClient *findClientWithSameCaption() const;
void finishWindowRules();
void discardTemporaryRules();
private:
void handlePaletteChange();
QSharedPointer<TabBox::TabBoxClientImpl> m_tabBoxClient;
@ -1085,6 +1096,8 @@ private:
QKeySequence _shortcut;
WindowRules m_rules;
static bool s_haveResizeEffect;
};

View file

@ -1487,12 +1487,6 @@ void Client::updateCaption()
setCaption(cap_normal, true);
}
void Client::evaluateWindowRules()
{
setupWindowRules(true);
applyWindowRules();
}
void Client::fetchIconicName()
{
QString s;
@ -1987,7 +1981,7 @@ NET::WindowType Client::windowType(bool direct, int supportedTypes) const
if (direct) {
return wt;
}
NET::WindowType wt2 = client_rules.checkType(wt);
NET::WindowType wt2 = rules()->checkType(wt);
if (wt != wt2) {
wt = wt2;
info->setWindowType(wt); // force hint change

View file

@ -109,10 +109,6 @@ public:
Group* group();
void checkGroup(Group* gr = NULL, bool force = false);
void changeClientLeaderGroup(Group* gr);
const WindowRules* rules() const override;
void removeRule(Rules* r);
void setupWindowRules(bool ignore_temporary);
void applyWindowRules();
void updateWindowRules(Rules::Types selection) override;
void updateFullscreenMonitors(NETFullscreenMonitors topology);
@ -135,7 +131,7 @@ public:
virtual QStringList activities() const;
void setOnActivity(const QString &activity, bool enable);
void setOnAllActivities(bool set) override;
void setOnActivities(QStringList newActivitiesList);
void setOnActivities(QStringList newActivitiesList) override;
void updateActivities(bool includeTransients);
void blockActivityUpdates(bool b = true) override;
@ -315,7 +311,7 @@ public:
void updateFirstInTabBox();
Xcb::StringProperty fetchColorScheme() const;
void readColorScheme(Xcb::StringProperty &property);
void updateColorScheme();
void updateColorScheme() override;
//sets whether the client should be faked as being on all activities (and be shown during session save)
void setSessionActivityOverride(bool needed);
@ -345,7 +341,6 @@ public:
public Q_SLOTS:
void closeWindow() override;
void updateCaption() override;
void evaluateWindowRules();
private Q_SLOTS:
void shadeHover();
@ -450,7 +445,6 @@ private:
QString readName() const;
void setCaption(const QString& s, bool force = false);
bool hasTransientInternal(const Client* c, bool indirect, ConstClientList& set) const;
void finishWindowRules();
void setShortcutInternal() override;
void configureRequest(int value_mask, int rx, int ry, int rw, int rh, int gravity, bool from_tool);
@ -547,7 +541,6 @@ private:
uint app_noborder : 1; ///< App requested no border via window type, shape extension, etc.
uint ignore_focus_stealing : 1; ///< Don't apply focus stealing prevention to this client
bool blocks_compositing;
WindowRules client_rules;
// DON'T reorder - Saved to config files !!!
enum FullScreenMode {
FullScreenNone,
@ -727,21 +720,11 @@ inline bool Client::hasUserTimeSupport() const
return info->userTime() != -1U;
}
inline const WindowRules* Client::rules() const
{
return &client_rules;
}
inline xcb_window_t Client::moveResizeGrabWindow() const
{
return m_moveResizeGrabWindow;
}
inline void Client::removeRule(Rules* rule)
{
client_rules.remove(rule);
}
inline bool Client::hiddenPreview() const
{
return mapping_state == Kept;

View file

@ -641,7 +641,7 @@ bool Client::manage(xcb_window_t w, bool isMapped)
delete session;
client_rules.discardTemporary();
discardTemporaryRules();
applyWindowRules(); // Just in case
RuleBook::self()->discardUsed(this, false); // Remove ApplyNow rules
updateWindowRules(Rules::All); // Was blocked while !isManaged()

View file

@ -445,7 +445,7 @@ bool Rules::matchClientMachine(const QByteArray& match_machine, bool local) cons
}
#ifndef KCMRULES
bool Rules::match(const Client* c) const
bool Rules::match(const AbstractClient* c) const
{
if (!matchType(c->windowType(true)))
return false;
@ -456,7 +456,7 @@ bool Rules::match(const Client* c) const
if (!matchClientMachine(c->clientMachine()->hostName(), c->clientMachine()->isLocal()))
return false;
if (titlematch != UnimportantMatch) // track title changes to rematch rules
QObject::connect(c, &Client::captionChanged, c, &Client::evaluateWindowRules,
QObject::connect(c, &AbstractClient::captionChanged, c, &AbstractClient::evaluateWindowRules,
// QueuedConnection, because title may change before
// the client is ready (could segfault!)
static_cast<Qt::ConnectionType>(Qt::QueuedConnection|Qt::UniqueConnection));
@ -467,7 +467,7 @@ bool Rules::match(const Client* c) const
#define NOW_REMEMBER(_T_, _V_) ((selection & _T_) && (_V_##rule == (SetRule)Remember))
bool Rules::update(Client* c, int selection)
bool Rules::update(AbstractClient* c, int selection)
{
// TODO check this setting is for this client ?
bool updated = false;
@ -759,7 +759,7 @@ void WindowRules::discardTemporary()
rules.erase(it2, rules.end());
}
void WindowRules::update(Client* c, int selection)
void WindowRules::update(AbstractClient* c, int selection)
{
bool updated = false;
for (QVector< Rules* >::ConstIterator it = rules.constBegin();
@ -872,22 +872,23 @@ CHECK_FORCE_RULE(DisableGlobalShortcuts, bool)
// Client
void Client::setupWindowRules(bool ignore_temporary)
void AbstractClient::setupWindowRules(bool ignore_temporary)
{
disconnect(this, &Client::captionChanged, this, &Client::evaluateWindowRules);
client_rules = RuleBook::self()->find(this, ignore_temporary);
disconnect(this, &AbstractClient::captionChanged, this, &AbstractClient::evaluateWindowRules);
m_rules = RuleBook::self()->find(this, ignore_temporary);
// check only after getting the rules, because there may be a rule forcing window type
}
// Applies Force, ForceTemporarily and ApplyNow rules
// Used e.g. after the rules have been modified using the kcm.
void Client::applyWindowRules()
void AbstractClient::applyWindowRules()
{
// apply force rules
// Placement - does need explicit update, just like some others below
// Geometry : setGeometry() doesn't check rules
auto client_rules = rules();
QRect orig_geom = QRect(pos(), sizeForClientSize(clientSize())); // handle shading
QRect geom = client_rules.checkGeometry(orig_geom);
QRect geom = client_rules->checkGeometry(orig_geom);
if (geom != orig_geom)
setGeometry(geom);
// MinSize, MaxSize handled by Geometry
@ -898,7 +899,7 @@ void Client::applyWindowRules()
// Type
maximize(maximizeMode());
// Minimize : functions don't check, and there are two functions
if (client_rules.checkMinimize(isMinimized()))
if (client_rules->checkMinimize(isMinimized()))
minimize();
else
unminimize();
@ -914,7 +915,7 @@ void Client::applyWindowRules()
// FSP
// AcceptFocus :
if (workspace()->mostRecentlyActivatedClient() == this
&& !client_rules.checkAcceptFocus(true))
&& !client_rules->checkAcceptFocus(true))
workspace()->activateNextClient(this);
// Closeable
QSize s = adjustedSize();
@ -937,15 +938,20 @@ void Client::updateWindowRules(Rules::Types selection)
{
if (!isManaged()) // not fully setup yet
return;
if (RuleBook::self()->areUpdatesDisabled())
return;
client_rules.update(this, selection);
AbstractClient::updateWindowRules(selection);
}
void Client::finishWindowRules()
void AbstractClient::updateWindowRules(Rules::Types selection)
{
if (RuleBook::self()->areUpdatesDisabled())
return;
m_rules.update(this, selection);
}
void AbstractClient::finishWindowRules()
{
updateWindowRules(Rules::All);
client_rules = WindowRules();
m_rules = WindowRules();
}
// Workspace
@ -987,7 +993,7 @@ void RuleBook::deleteAll()
m_rules.clear();
}
WindowRules RuleBook::find(const Client* c, bool ignore_temporary)
WindowRules RuleBook::find(const AbstractClient* c, bool ignore_temporary)
{
QVector< Rules* > ret;
for (QList< Rules* >::Iterator it = m_rules.begin();

View file

@ -49,7 +49,7 @@ class WindowRules
public:
explicit WindowRules(const QVector< Rules* >& rules);
WindowRules();
void update(Client*, int selection);
void update(AbstractClient*, int selection);
void discardTemporary();
bool contains(const Rules* rule) const;
void remove(Rules* rule);
@ -116,8 +116,8 @@ public:
bool isEmpty() const;
#ifndef KCMRULES
void discardUsed(bool withdrawn);
bool match(const Client* c) const;
bool update(Client*, int selection);
bool match(const AbstractClient* c) const;
bool update(AbstractClient*, int selection);
bool isTemporary() const;
bool discardTemporary(bool force); // removes if temporary and forced or too old
bool applyPlacement(Placement::Policy& placement) const;
@ -292,7 +292,7 @@ class KWIN_EXPORT RuleBook : public QObject
Q_OBJECT
public:
virtual ~RuleBook();
WindowRules find(const Client*, bool);
WindowRules find(const AbstractClient*, bool);
void discardUsed(Client* c, bool withdraw);
void setUpdatesDisabled(bool disable);
bool areUpdatesDisabled() const;

View file

@ -321,7 +321,7 @@ void ShellClient::init()
installServerSideDecoration(deco);
}
updateColorScheme(QString());
AbstractClient::updateColorScheme(QString());
updateApplicationMenu();
}
@ -866,12 +866,6 @@ bool ShellClient::noBorder() const
return true;
}
const WindowRules *ShellClient::rules() const
{
static WindowRules s_rules;
return &s_rules;
}
void ShellClient::setFullScreen(bool set, bool user)
{
Q_UNUSED(set)
@ -934,11 +928,6 @@ void ShellClient::doSetActive()
workspace()->focusToNull();
}
void ShellClient::updateWindowRules(Rules::Types selection)
{
Q_UNUSED(selection)
}
bool ShellClient::userCanSetFullScreen() const
{
return false;
@ -1334,7 +1323,7 @@ bool ShellClient::eventFilter(QObject *watched, QEvent *event)
if (watched == m_qtExtendedSurface.data() && event->type() == QEvent::DynamicPropertyChange) {
QDynamicPropertyChangeEvent *pe = static_cast<QDynamicPropertyChangeEvent*>(event);
if (pe->propertyName() == s_schemePropertyName) {
updateColorScheme(rules()->checkDecoColor(m_qtExtendedSurface->property(pe->propertyName().constData()).toString()));
AbstractClient::updateColorScheme(rules()->checkDecoColor(m_qtExtendedSurface->property(pe->propertyName().constData()).toString()));
} else if (pe->propertyName() == s_appMenuServiceNamePropertyName) {
updateApplicationMenuServiceName(m_qtExtendedSurface->property(pe->propertyName().constData()).toString());
} else if (pe->propertyName() == s_appMenuObjectPathPropertyName) {
@ -1350,6 +1339,15 @@ bool ShellClient::eventFilter(QObject *watched, QEvent *event)
return false;
}
void ShellClient::updateColorScheme()
{
if (m_qtExtendedSurface) {
AbstractClient::updateColorScheme(rules()->checkDecoColor(m_qtExtendedSurface->property(s_schemePropertyName.constData()).toString()));
} else {
AbstractClient::updateColorScheme(rules()->checkDecoColor(QString()));
}
}
bool ShellClient::hasStrut() const
{
if (!isShown(true)) {

View file

@ -97,13 +97,11 @@ public:
return m_geomMaximizeRestore;
}
bool noBorder() const override;
const WindowRules *rules() const override;
void setFullScreen(bool set, bool user = true) override;
void setNoBorder(bool set) override;
void updateDecoration(bool check_workspace_pos, bool force = false) override;
void setOnAllActivities(bool set) override;
void takeFocus() override;
void updateWindowRules(Rules::Types selection) override;
bool userCanSetFullScreen() const override;
bool userCanSetNoBorder() const override;
bool wantsInput() const override;
@ -162,6 +160,8 @@ public:
bool hasPopupGrab() const override;
void popupDone() override;
void updateColorScheme() override;
protected:
void addDamage(const QRegion &damage) override;
bool belongsToSameApplication(const AbstractClient *other, bool active_hack) const override;