2007-11-27 19:40:25 +00:00
|
|
|
/********************************************************************
|
2007-04-29 17:35:43 +00:00
|
|
|
KWin - the KDE window manager
|
|
|
|
This file is part of the KDE project.
|
|
|
|
|
|
|
|
Copyright (C) 2004 Lubos Lunak <l.lunak@kde.org>
|
|
|
|
|
2007-11-27 19:40:25 +00:00
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*********************************************************************/
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
#include "rules.h"
|
|
|
|
|
|
|
|
#include <fixx11h.h>
|
|
|
|
#include <kconfig.h>
|
2014-03-17 15:24:10 +00:00
|
|
|
#include <KXMessages>
|
2007-04-29 17:35:43 +00:00
|
|
|
#include <QRegExp>
|
2013-08-10 21:19:41 +00:00
|
|
|
#include <QTemporaryFile>
|
2007-04-29 17:35:43 +00:00
|
|
|
#include <QFile>
|
2013-11-05 12:42:33 +00:00
|
|
|
#include <QFileInfo>
|
2013-09-02 11:14:39 +00:00
|
|
|
#include <QDebug>
|
2018-11-08 21:08:06 +00:00
|
|
|
#include <QDir>
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
#ifndef KCMRULES
|
|
|
|
#include "client.h"
|
2013-01-07 07:07:27 +00:00
|
|
|
#include "client_machine.h"
|
2013-04-03 10:19:27 +00:00
|
|
|
#include "screens.h"
|
2007-04-29 17:35:43 +00:00
|
|
|
#include "workspace.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
namespace KWin
|
|
|
|
{
|
|
|
|
|
|
|
|
Rules::Rules()
|
2011-01-30 14:34:42 +00:00
|
|
|
: temporary_state(0)
|
|
|
|
, wmclassmatch(UnimportantMatch)
|
|
|
|
, wmclasscomplete(UnimportantMatch)
|
|
|
|
, windowrolematch(UnimportantMatch)
|
|
|
|
, titlematch(UnimportantMatch)
|
|
|
|
, clientmachinematch(UnimportantMatch)
|
|
|
|
, types(NET::AllTypesMask)
|
|
|
|
, placementrule(UnusedForceRule)
|
|
|
|
, positionrule(UnusedSetRule)
|
|
|
|
, sizerule(UnusedSetRule)
|
|
|
|
, minsizerule(UnusedForceRule)
|
|
|
|
, maxsizerule(UnusedForceRule)
|
|
|
|
, opacityactiverule(UnusedForceRule)
|
|
|
|
, opacityinactiverule(UnusedForceRule)
|
2013-03-24 18:13:00 +00:00
|
|
|
, ignoregeometryrule(UnusedSetRule)
|
2011-01-30 14:34:42 +00:00
|
|
|
, desktoprule(UnusedSetRule)
|
2012-08-24 16:48:50 +00:00
|
|
|
, screenrule(UnusedSetRule)
|
2012-05-17 14:32:06 +00:00
|
|
|
, activityrule(UnusedSetRule)
|
2011-01-30 14:34:42 +00:00
|
|
|
, typerule(UnusedForceRule)
|
|
|
|
, maximizevertrule(UnusedSetRule)
|
|
|
|
, maximizehorizrule(UnusedSetRule)
|
|
|
|
, minimizerule(UnusedSetRule)
|
|
|
|
, shaderule(UnusedSetRule)
|
|
|
|
, skiptaskbarrule(UnusedSetRule)
|
|
|
|
, skippagerrule(UnusedSetRule)
|
|
|
|
, skipswitcherrule(UnusedSetRule)
|
|
|
|
, aboverule(UnusedSetRule)
|
|
|
|
, belowrule(UnusedSetRule)
|
|
|
|
, fullscreenrule(UnusedSetRule)
|
|
|
|
, noborderrule(UnusedSetRule)
|
2013-11-05 12:42:33 +00:00
|
|
|
, decocolorrule(UnusedForceRule)
|
2011-03-20 14:42:05 +00:00
|
|
|
, blockcompositingrule(UnusedForceRule)
|
2011-01-30 14:34:42 +00:00
|
|
|
, fsplevelrule(UnusedForceRule)
|
2015-11-12 23:37:01 +00:00
|
|
|
, fpplevelrule(UnusedForceRule)
|
2011-01-30 14:34:42 +00:00
|
|
|
, acceptfocusrule(UnusedForceRule)
|
|
|
|
, closeablerule(UnusedForceRule)
|
|
|
|
, autogrouprule(UnusedForceRule)
|
|
|
|
, autogroupfgrule(UnusedForceRule)
|
|
|
|
, autogroupidrule(UnusedForceRule)
|
|
|
|
, strictgeometryrule(UnusedForceRule)
|
|
|
|
, shortcutrule(UnusedSetRule)
|
|
|
|
, disableglobalshortcutsrule(UnusedForceRule)
|
2018-03-11 16:13:32 +00:00
|
|
|
, desktopfilerule(UnusedSetRule)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
Rules::Rules(const QString& str, bool temporary)
|
|
|
|
: temporary_state(temporary ? 2 : 0)
|
|
|
|
{
|
2013-08-10 21:19:41 +00:00
|
|
|
QTemporaryFile file;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (file.open()) {
|
2007-04-29 17:35:43 +00:00
|
|
|
QByteArray s = str.toUtf8();
|
2011-01-30 14:34:42 +00:00
|
|
|
file.write(s.data(), s.length());
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
file.flush();
|
2011-01-30 14:34:42 +00:00
|
|
|
KConfig cfg(file.fileName(), KConfig::SimpleConfig);
|
|
|
|
readFromCfg(cfg.group(QString()));
|
|
|
|
if (description.isEmpty())
|
2013-07-23 05:02:52 +00:00
|
|
|
description = QStringLiteral("temporary");
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
#define READ_MATCH_STRING( var, func ) \
|
|
|
|
var = cfg.readEntry( #var ) func; \
|
|
|
|
var##match = (StringMatch) qMax( FirstStringMatch, \
|
2011-01-30 14:34:42 +00:00
|
|
|
qMin( LastStringMatch, static_cast< StringMatch >( cfg.readEntry( #var "match",0 ))));
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
#define READ_SET_RULE( var, func, def ) \
|
|
|
|
var = func ( cfg.readEntry( #var, def)); \
|
2013-07-23 05:02:52 +00:00
|
|
|
var##rule = readSetRule( cfg, QStringLiteral( #var "rule" ) );
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
#define READ_SET_RULE_DEF( var , func, def ) \
|
|
|
|
var = func ( cfg.readEntry( #var, def )); \
|
2013-07-23 05:02:52 +00:00
|
|
|
var##rule = readSetRule( cfg, QStringLiteral( #var "rule" ) );
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
#define READ_FORCE_RULE( var, func, def) \
|
|
|
|
var = func ( cfg.readEntry( #var, def)); \
|
2013-07-23 05:02:52 +00:00
|
|
|
var##rule = readForceRule( cfg, QStringLiteral( #var "rule" ) );
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
#define READ_FORCE_RULE2( var, def, func, funcarg ) \
|
|
|
|
var = func ( cfg.readEntry( #var, def),funcarg ); \
|
2013-07-23 05:02:52 +00:00
|
|
|
var##rule = readForceRule( cfg, QStringLiteral( #var "rule" ) );
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
Rules::Rules(const KConfigGroup& cfg)
|
|
|
|
: temporary_state(0)
|
|
|
|
{
|
|
|
|
readFromCfg(cfg);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int limit0to4(int i)
|
|
|
|
{
|
|
|
|
return qMax(0, qMin(4, i));
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void Rules::readFromCfg(const KConfigGroup& cfg)
|
|
|
|
{
|
|
|
|
description = cfg.readEntry("Description");
|
|
|
|
if (description.isEmpty()) // capitalized first, lowercase for backwards compatibility
|
|
|
|
description = cfg.readEntry("description");
|
|
|
|
READ_MATCH_STRING(wmclass, .toLower().toLatin1());
|
|
|
|
wmclasscomplete = cfg.readEntry("wmclasscomplete" , false);
|
2016-08-25 11:30:25 +00:00
|
|
|
READ_MATCH_STRING(windowrole, .toLower().toLatin1());
|
2011-01-30 14:34:42 +00:00
|
|
|
READ_MATCH_STRING(title,);
|
|
|
|
READ_MATCH_STRING(clientmachine, .toLower().toLatin1());
|
2014-02-03 08:37:08 +00:00
|
|
|
types = NET::WindowTypeMask(cfg.readEntry<uint>("types", NET::AllTypesMask));
|
2011-01-30 14:34:42 +00:00
|
|
|
READ_FORCE_RULE2(placement, QString(), Placement::policyFromString, false);
|
|
|
|
READ_SET_RULE_DEF(position, , invalidPoint);
|
|
|
|
READ_SET_RULE(size, , QSize());
|
|
|
|
if (size.isEmpty() && sizerule != (SetRule)Remember)
|
2007-04-29 17:35:43 +00:00
|
|
|
sizerule = UnusedSetRule;
|
2011-01-30 14:34:42 +00:00
|
|
|
READ_FORCE_RULE(minsize, , QSize());
|
|
|
|
if (!minsize.isValid())
|
|
|
|
minsize = QSize(1, 1);
|
|
|
|
READ_FORCE_RULE(maxsize, , QSize());
|
|
|
|
if (maxsize.isEmpty())
|
|
|
|
maxsize = QSize(32767, 32767);
|
|
|
|
READ_FORCE_RULE(opacityactive, , 0);
|
|
|
|
if (opacityactive < 0 || opacityactive > 100)
|
2007-04-29 17:35:43 +00:00
|
|
|
opacityactive = 100;
|
2011-01-30 14:34:42 +00:00
|
|
|
READ_FORCE_RULE(opacityinactive, , 0);
|
|
|
|
if (opacityinactive < 0 || opacityinactive > 100)
|
2007-04-29 17:35:43 +00:00
|
|
|
opacityinactive = 100;
|
2013-03-24 18:13:00 +00:00
|
|
|
READ_SET_RULE(ignoregeometry, , false);
|
2011-01-30 14:34:42 +00:00
|
|
|
READ_SET_RULE(desktop, , 0);
|
2012-08-24 16:48:50 +00:00
|
|
|
READ_SET_RULE(screen, , 0);
|
2012-05-17 14:32:06 +00:00
|
|
|
READ_SET_RULE(activity, , QString());
|
2013-07-23 05:02:52 +00:00
|
|
|
type = readType(cfg, QStringLiteral("type"));
|
|
|
|
typerule = type != NET::Unknown ? readForceRule(cfg, QStringLiteral("typerule")) : UnusedForceRule;
|
2011-01-30 14:34:42 +00:00
|
|
|
READ_SET_RULE(maximizevert, , false);
|
|
|
|
READ_SET_RULE(maximizehoriz, , false);
|
|
|
|
READ_SET_RULE(minimize, , false);
|
|
|
|
READ_SET_RULE(shade, , false);
|
|
|
|
READ_SET_RULE(skiptaskbar, , false);
|
|
|
|
READ_SET_RULE(skippager, , false);
|
|
|
|
READ_SET_RULE(skipswitcher, , false);
|
|
|
|
READ_SET_RULE(above, , false);
|
|
|
|
READ_SET_RULE(below, , false);
|
|
|
|
READ_SET_RULE(fullscreen, , false);
|
|
|
|
READ_SET_RULE(noborder, , false);
|
2013-11-05 12:42:33 +00:00
|
|
|
decocolor = readDecoColor(cfg);
|
|
|
|
decocolorrule = decocolor.isEmpty() ? UnusedForceRule : readForceRule(cfg, QStringLiteral("decocolorrule"));
|
2011-03-20 14:42:05 +00:00
|
|
|
READ_FORCE_RULE(blockcompositing, , false);
|
2011-01-30 14:34:42 +00:00
|
|
|
READ_FORCE_RULE(fsplevel, limit0to4, 0); // fsp is 0-4
|
2015-11-12 23:37:01 +00:00
|
|
|
READ_FORCE_RULE(fpplevel, limit0to4, 0); // fpp is 0-4
|
2011-01-30 14:34:42 +00:00
|
|
|
READ_FORCE_RULE(acceptfocus, , false);
|
|
|
|
READ_FORCE_RULE(closeable, , false);
|
|
|
|
READ_FORCE_RULE(autogroup, , false);
|
|
|
|
READ_FORCE_RULE(autogroupfg, , true);
|
|
|
|
READ_FORCE_RULE(autogroupid, , QString());
|
|
|
|
READ_FORCE_RULE(strictgeometry, , false);
|
|
|
|
READ_SET_RULE(shortcut, , QString());
|
|
|
|
READ_FORCE_RULE(disableglobalshortcuts, , false);
|
2018-03-11 16:13:32 +00:00
|
|
|
READ_SET_RULE(desktopfile, , QString());
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
#undef READ_MATCH_STRING
|
|
|
|
#undef READ_SET_RULE
|
|
|
|
#undef READ_FORCE_RULE
|
|
|
|
#undef READ_FORCE_RULE2
|
|
|
|
|
2013-07-23 05:02:52 +00:00
|
|
|
#define WRITE_MATCH_STRING( var, force ) \
|
2011-01-30 14:34:42 +00:00
|
|
|
if ( !var.isEmpty() || force ) \
|
|
|
|
{ \
|
2013-07-23 05:02:52 +00:00
|
|
|
cfg.writeEntry( #var, var ); \
|
2007-04-29 17:35:43 +00:00
|
|
|
cfg.writeEntry( #var "match", (int)var##match ); \
|
2011-01-30 14:34:42 +00:00
|
|
|
} \
|
2007-04-29 17:35:43 +00:00
|
|
|
else \
|
2011-01-30 14:34:42 +00:00
|
|
|
{ \
|
2007-04-29 17:35:43 +00:00
|
|
|
cfg.deleteEntry( #var ); \
|
|
|
|
cfg.deleteEntry( #var "match" ); \
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
#define WRITE_SET_RULE( var, func ) \
|
2011-01-30 14:34:42 +00:00
|
|
|
if ( var##rule != UnusedSetRule ) \
|
|
|
|
{ \
|
2007-04-29 17:35:43 +00:00
|
|
|
cfg.writeEntry( #var, func ( var )); \
|
|
|
|
cfg.writeEntry( #var "rule", (int)var##rule ); \
|
2011-01-30 14:34:42 +00:00
|
|
|
} \
|
2007-04-29 17:35:43 +00:00
|
|
|
else \
|
2011-01-30 14:34:42 +00:00
|
|
|
{ \
|
2007-04-29 17:35:43 +00:00
|
|
|
cfg.deleteEntry( #var ); \
|
|
|
|
cfg.deleteEntry( #var "rule" ); \
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
#define WRITE_FORCE_RULE( var, func ) \
|
2011-01-30 14:34:42 +00:00
|
|
|
if ( var##rule != UnusedForceRule ) \
|
|
|
|
{ \
|
2007-04-29 17:35:43 +00:00
|
|
|
cfg.writeEntry( #var, func ( var )); \
|
|
|
|
cfg.writeEntry( #var "rule", (int)var##rule ); \
|
2011-01-30 14:34:42 +00:00
|
|
|
} \
|
2007-04-29 17:35:43 +00:00
|
|
|
else \
|
2011-01-30 14:34:42 +00:00
|
|
|
{ \
|
2007-04-29 17:35:43 +00:00
|
|
|
cfg.deleteEntry( #var ); \
|
|
|
|
cfg.deleteEntry( #var "rule" ); \
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void Rules::write(KConfigGroup& cfg) const
|
|
|
|
{
|
|
|
|
cfg.writeEntry("Description", description);
|
2007-04-29 17:35:43 +00:00
|
|
|
// always write wmclass
|
2013-07-23 05:02:52 +00:00
|
|
|
WRITE_MATCH_STRING(wmclass, true);
|
2011-01-30 14:34:42 +00:00
|
|
|
cfg.writeEntry("wmclasscomplete", wmclasscomplete);
|
2013-07-23 05:02:52 +00:00
|
|
|
WRITE_MATCH_STRING(windowrole, false);
|
|
|
|
WRITE_MATCH_STRING(title, false);
|
|
|
|
WRITE_MATCH_STRING(clientmachine, false);
|
2007-04-29 17:35:43 +00:00
|
|
|
if (types != NET::AllTypesMask)
|
|
|
|
cfg.writeEntry("types", uint(types));
|
|
|
|
else
|
|
|
|
cfg.deleteEntry("types");
|
2011-01-30 14:34:42 +00:00
|
|
|
WRITE_FORCE_RULE(placement, Placement::policyToString);
|
|
|
|
WRITE_SET_RULE(position,);
|
|
|
|
WRITE_SET_RULE(size,);
|
|
|
|
WRITE_FORCE_RULE(minsize,);
|
|
|
|
WRITE_FORCE_RULE(maxsize,);
|
|
|
|
WRITE_FORCE_RULE(opacityactive,);
|
|
|
|
WRITE_FORCE_RULE(opacityinactive,);
|
2013-03-24 18:13:00 +00:00
|
|
|
WRITE_SET_RULE(ignoregeometry,);
|
2011-01-30 14:34:42 +00:00
|
|
|
WRITE_SET_RULE(desktop,);
|
2012-08-24 16:48:50 +00:00
|
|
|
WRITE_SET_RULE(screen,);
|
2012-05-17 14:32:06 +00:00
|
|
|
WRITE_SET_RULE(activity,);
|
2011-01-30 14:34:42 +00:00
|
|
|
WRITE_FORCE_RULE(type, int);
|
|
|
|
WRITE_SET_RULE(maximizevert,);
|
|
|
|
WRITE_SET_RULE(maximizehoriz,);
|
|
|
|
WRITE_SET_RULE(minimize,);
|
|
|
|
WRITE_SET_RULE(shade,);
|
|
|
|
WRITE_SET_RULE(skiptaskbar,);
|
|
|
|
WRITE_SET_RULE(skippager,);
|
|
|
|
WRITE_SET_RULE(skipswitcher,);
|
|
|
|
WRITE_SET_RULE(above,);
|
|
|
|
WRITE_SET_RULE(below,);
|
|
|
|
WRITE_SET_RULE(fullscreen,);
|
|
|
|
WRITE_SET_RULE(noborder,);
|
2014-01-19 15:17:07 +00:00
|
|
|
auto colorToString = [](const QString &value) -> QString {
|
2015-11-05 14:14:06 +00:00
|
|
|
if (value.endsWith(QLatin1String(".colors"))) {
|
2013-11-05 12:42:33 +00:00
|
|
|
return QFileInfo(value).baseName();
|
|
|
|
} else {
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
WRITE_FORCE_RULE(decocolor, colorToString);
|
2011-03-20 14:42:05 +00:00
|
|
|
WRITE_FORCE_RULE(blockcompositing,);
|
2011-01-30 14:34:42 +00:00
|
|
|
WRITE_FORCE_RULE(fsplevel,);
|
2015-11-12 23:37:01 +00:00
|
|
|
WRITE_FORCE_RULE(fpplevel,);
|
2011-01-30 14:34:42 +00:00
|
|
|
WRITE_FORCE_RULE(acceptfocus,);
|
|
|
|
WRITE_FORCE_RULE(closeable,);
|
|
|
|
WRITE_FORCE_RULE(autogroup,);
|
|
|
|
WRITE_FORCE_RULE(autogroupfg,);
|
|
|
|
WRITE_FORCE_RULE(autogroupid,);
|
|
|
|
WRITE_FORCE_RULE(strictgeometry,);
|
|
|
|
WRITE_SET_RULE(shortcut,);
|
|
|
|
WRITE_FORCE_RULE(disableglobalshortcuts,);
|
2018-03-11 16:13:32 +00:00
|
|
|
WRITE_SET_RULE(desktopfile,);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
#undef WRITE_MATCH_STRING
|
|
|
|
#undef WRITE_SET_RULE
|
|
|
|
#undef WRITE_FORCE_RULE
|
|
|
|
|
|
|
|
// returns true if it doesn't affect anything
|
|
|
|
bool Rules::isEmpty() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
return(placementrule == UnusedForceRule
|
|
|
|
&& positionrule == UnusedSetRule
|
|
|
|
&& sizerule == UnusedSetRule
|
|
|
|
&& minsizerule == UnusedForceRule
|
|
|
|
&& maxsizerule == UnusedForceRule
|
|
|
|
&& opacityactiverule == UnusedForceRule
|
|
|
|
&& opacityinactiverule == UnusedForceRule
|
2013-03-24 18:13:00 +00:00
|
|
|
&& ignoregeometryrule == UnusedSetRule
|
2011-01-30 14:34:42 +00:00
|
|
|
&& desktoprule == UnusedSetRule
|
2012-08-24 16:48:50 +00:00
|
|
|
&& screenrule == UnusedSetRule
|
2012-05-17 14:32:06 +00:00
|
|
|
&& activityrule == UnusedSetRule
|
2011-01-30 14:34:42 +00:00
|
|
|
&& typerule == UnusedForceRule
|
|
|
|
&& maximizevertrule == UnusedSetRule
|
|
|
|
&& maximizehorizrule == UnusedSetRule
|
|
|
|
&& minimizerule == UnusedSetRule
|
|
|
|
&& shaderule == UnusedSetRule
|
|
|
|
&& skiptaskbarrule == UnusedSetRule
|
|
|
|
&& skippagerrule == UnusedSetRule
|
|
|
|
&& skipswitcherrule == UnusedSetRule
|
|
|
|
&& aboverule == UnusedSetRule
|
|
|
|
&& belowrule == UnusedSetRule
|
|
|
|
&& fullscreenrule == UnusedSetRule
|
|
|
|
&& noborderrule == UnusedSetRule
|
2013-11-05 12:42:33 +00:00
|
|
|
&& decocolorrule == UnusedForceRule
|
2011-03-20 14:42:05 +00:00
|
|
|
&& blockcompositingrule == UnusedForceRule
|
2011-01-30 14:34:42 +00:00
|
|
|
&& fsplevelrule == UnusedForceRule
|
2015-11-12 23:37:01 +00:00
|
|
|
&& fpplevelrule == UnusedForceRule
|
2011-01-30 14:34:42 +00:00
|
|
|
&& acceptfocusrule == UnusedForceRule
|
|
|
|
&& closeablerule == UnusedForceRule
|
|
|
|
&& autogrouprule == UnusedForceRule
|
|
|
|
&& autogroupfgrule == UnusedForceRule
|
|
|
|
&& autogroupidrule == UnusedForceRule
|
|
|
|
&& strictgeometryrule == UnusedForceRule
|
|
|
|
&& shortcutrule == UnusedSetRule
|
2018-03-11 16:13:32 +00:00
|
|
|
&& disableglobalshortcutsrule == UnusedForceRule
|
|
|
|
&& desktopfilerule == UnusedSetRule);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Rules::SetRule Rules::readSetRule(const KConfigGroup& cfg, const QString& key)
|
|
|
|
{
|
|
|
|
int v = cfg.readEntry(key, 0);
|
|
|
|
if (v >= DontAffect && v <= ForceTemporarily)
|
|
|
|
return static_cast< SetRule >(v);
|
2007-04-29 17:35:43 +00:00
|
|
|
return UnusedSetRule;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
Rules::ForceRule Rules::readForceRule(const KConfigGroup& cfg, const QString& key)
|
|
|
|
{
|
|
|
|
int v = cfg.readEntry(key, 0);
|
|
|
|
if (v == DontAffect || v == Force || v == ForceTemporarily)
|
|
|
|
return static_cast< ForceRule >(v);
|
2007-04-29 17:35:43 +00:00
|
|
|
return UnusedForceRule;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
NET::WindowType Rules::readType(const KConfigGroup& cfg, const QString& key)
|
|
|
|
{
|
|
|
|
int v = cfg.readEntry(key, 0);
|
|
|
|
if (v >= NET::Normal && v <= NET::Splash)
|
|
|
|
return static_cast< NET::WindowType >(v);
|
2007-04-29 17:35:43 +00:00
|
|
|
return NET::Unknown;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2013-11-05 12:42:33 +00:00
|
|
|
QString Rules::readDecoColor(const KConfigGroup &cfg)
|
|
|
|
{
|
|
|
|
QString themeName = cfg.readEntry("decocolor", QString());
|
|
|
|
if (themeName.isEmpty()) {
|
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
// find the actual scheme file
|
|
|
|
return QStandardPaths::locate(QStandardPaths::GenericDataLocation,
|
2015-11-05 14:14:06 +00:00
|
|
|
QLatin1String("color-schemes/") + themeName + QLatin1String(".colors"));
|
2013-11-05 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
bool Rules::matchType(NET::WindowType match_type) const
|
|
|
|
{
|
|
|
|
if (types != NET::AllTypesMask) {
|
|
|
|
if (match_type == NET::Unknown)
|
2007-04-29 17:35:43 +00:00
|
|
|
match_type = NET::Normal; // NET::Unknown->NET::Normal is only here for matching
|
2011-01-30 14:34:42 +00:00
|
|
|
if (!NET::typeMatchesMask(match_type, types))
|
2007-04-29 17:35:43 +00:00
|
|
|
return false;
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
return true;
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
bool Rules::matchWMClass(const QByteArray& match_class, const QByteArray& match_name) const
|
|
|
|
{
|
|
|
|
if (wmclassmatch != UnimportantMatch) {
|
|
|
|
// TODO optimize?
|
2007-04-29 17:35:43 +00:00
|
|
|
QByteArray cwmclass = wmclasscomplete
|
2011-01-30 14:34:42 +00:00
|
|
|
? match_name + ' ' + match_class : match_class;
|
2013-07-23 05:02:52 +00:00
|
|
|
if (wmclassmatch == RegExpMatch && QRegExp(QString::fromUtf8(wmclass)).indexIn(QString::fromUtf8(cwmclass)) == -1)
|
2007-04-29 17:35:43 +00:00
|
|
|
return false;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (wmclassmatch == ExactMatch && wmclass != cwmclass)
|
2007-04-29 17:35:43 +00:00
|
|
|
return false;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (wmclassmatch == SubstringMatch && !cwmclass.contains(wmclass))
|
2007-04-29 17:35:43 +00:00
|
|
|
return false;
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
return true;
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
bool Rules::matchRole(const QByteArray& match_role) const
|
|
|
|
{
|
|
|
|
if (windowrolematch != UnimportantMatch) {
|
2013-07-23 05:02:52 +00:00
|
|
|
if (windowrolematch == RegExpMatch && QRegExp(QString::fromUtf8(windowrole)).indexIn(QString::fromUtf8(match_role)) == -1)
|
2007-04-29 17:35:43 +00:00
|
|
|
return false;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (windowrolematch == ExactMatch && windowrole != match_role)
|
2007-04-29 17:35:43 +00:00
|
|
|
return false;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (windowrolematch == SubstringMatch && !match_role.contains(windowrole))
|
2007-04-29 17:35:43 +00:00
|
|
|
return false;
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
return true;
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
bool Rules::matchTitle(const QString& match_title) const
|
|
|
|
{
|
|
|
|
if (titlematch != UnimportantMatch) {
|
|
|
|
if (titlematch == RegExpMatch && QRegExp(title).indexIn(match_title) == -1)
|
2007-04-29 17:35:43 +00:00
|
|
|
return false;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (titlematch == ExactMatch && title != match_title)
|
2007-04-29 17:35:43 +00:00
|
|
|
return false;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (titlematch == SubstringMatch && !match_title.contains(title))
|
2007-04-29 17:35:43 +00:00
|
|
|
return false;
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
return true;
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2013-01-07 07:07:27 +00:00
|
|
|
bool Rules::matchClientMachine(const QByteArray& match_machine, bool local) const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
if (clientmachinematch != UnimportantMatch) {
|
2007-04-29 17:35:43 +00:00
|
|
|
// if it's localhost, check also "localhost" before checking hostname
|
2013-01-07 07:07:27 +00:00
|
|
|
if (match_machine != "localhost" && local
|
|
|
|
&& matchClientMachine("localhost", true))
|
2007-04-29 17:35:43 +00:00
|
|
|
return true;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (clientmachinematch == RegExpMatch
|
2013-07-23 05:02:52 +00:00
|
|
|
&& QRegExp(QString::fromUtf8(clientmachine)).indexIn(QString::fromUtf8(match_machine)) == -1)
|
2007-04-29 17:35:43 +00:00
|
|
|
return false;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (clientmachinematch == ExactMatch
|
|
|
|
&& clientmachine != match_machine)
|
2007-04-29 17:35:43 +00:00
|
|
|
return false;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (clientmachinematch == SubstringMatch
|
|
|
|
&& !match_machine.contains(clientmachine))
|
2007-04-29 17:35:43 +00:00
|
|
|
return false;
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
return true;
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
#ifndef KCMRULES
|
2017-10-01 14:38:57 +00:00
|
|
|
bool Rules::match(const AbstractClient* c) const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
if (!matchType(c->windowType(true)))
|
2007-04-29 17:35:43 +00:00
|
|
|
return false;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (!matchWMClass(c->resourceClass(), c->resourceName()))
|
2007-04-29 17:35:43 +00:00
|
|
|
return false;
|
2016-08-25 11:30:25 +00:00
|
|
|
if (!matchRole(c->windowRole().toLower()))
|
2007-04-29 17:35:43 +00:00
|
|
|
return false;
|
2013-01-07 07:07:27 +00:00
|
|
|
if (!matchClientMachine(c->clientMachine()->hostName(), c->clientMachine()->isLocal()))
|
2007-04-29 17:35:43 +00:00
|
|
|
return false;
|
2015-09-27 19:15:35 +00:00
|
|
|
if (titlematch != UnimportantMatch) // track title changes to rematch rules
|
2017-10-01 14:38:57 +00:00
|
|
|
QObject::connect(c, &AbstractClient::captionChanged, c, &AbstractClient::evaluateWindowRules,
|
2015-09-27 19:15:35 +00:00
|
|
|
// QueuedConnection, because title may change before
|
|
|
|
// the client is ready (could segfault!)
|
|
|
|
static_cast<Qt::ConnectionType>(Qt::QueuedConnection|Qt::UniqueConnection));
|
2017-08-20 07:35:15 +00:00
|
|
|
if (!matchTitle(c->captionNormal()))
|
2015-09-27 19:15:35 +00:00
|
|
|
return false;
|
2007-04-29 17:35:43 +00:00
|
|
|
return true;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2012-02-05 17:50:23 +00:00
|
|
|
#define NOW_REMEMBER(_T_, _V_) ((selection & _T_) && (_V_##rule == (SetRule)Remember))
|
|
|
|
|
2017-10-01 14:38:57 +00:00
|
|
|
bool Rules::update(AbstractClient* c, int selection)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2007-04-29 17:35:43 +00:00
|
|
|
// TODO check this setting is for this client ?
|
|
|
|
bool updated = false;
|
2012-02-05 17:50:23 +00:00
|
|
|
if NOW_REMEMBER(Position, position) {
|
2011-01-30 14:34:42 +00:00
|
|
|
if (!c->isFullScreen()) {
|
2007-04-29 17:35:43 +00:00
|
|
|
QPoint new_pos = position;
|
|
|
|
// don't use the position in the direction which is maximized
|
2011-01-30 14:34:42 +00:00
|
|
|
if ((c->maximizeMode() & MaximizeHorizontal) == 0)
|
|
|
|
new_pos.setX(c->pos().x());
|
|
|
|
if ((c->maximizeMode() & MaximizeVertical) == 0)
|
|
|
|
new_pos.setY(c->pos().y());
|
2007-04-29 17:35:43 +00:00
|
|
|
updated = updated || position != new_pos;
|
|
|
|
position = new_pos;
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2012-02-05 17:50:23 +00:00
|
|
|
if NOW_REMEMBER(Size, size) {
|
2011-01-30 14:34:42 +00:00
|
|
|
if (!c->isFullScreen()) {
|
2007-04-29 17:35:43 +00:00
|
|
|
QSize new_size = size;
|
|
|
|
// don't use the position in the direction which is maximized
|
2011-01-30 14:34:42 +00:00
|
|
|
if ((c->maximizeMode() & MaximizeHorizontal) == 0)
|
|
|
|
new_size.setWidth(c->size().width());
|
|
|
|
if ((c->maximizeMode() & MaximizeVertical) == 0)
|
|
|
|
new_size.setHeight(c->size().height());
|
2007-04-29 17:35:43 +00:00
|
|
|
updated = updated || size != new_size;
|
|
|
|
size = new_size;
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2012-02-05 17:50:23 +00:00
|
|
|
if NOW_REMEMBER(Desktop, desktop) {
|
2007-04-29 17:35:43 +00:00
|
|
|
updated = updated || desktop != c->desktop();
|
|
|
|
desktop = c->desktop();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2012-08-24 16:48:50 +00:00
|
|
|
if NOW_REMEMBER(Screen, screen) {
|
|
|
|
updated = updated || screen != c->screen();
|
|
|
|
screen = c->screen();
|
|
|
|
}
|
2012-05-17 14:32:06 +00:00
|
|
|
if NOW_REMEMBER(Activity, activity) {
|
|
|
|
// TODO: ivan - multiple activities support
|
2013-07-23 05:02:52 +00:00
|
|
|
const QString & joinedActivities = c->activities().join(QStringLiteral(","));
|
2012-05-17 14:32:06 +00:00
|
|
|
updated = updated || activity != joinedActivities;
|
|
|
|
activity = joinedActivities;
|
|
|
|
}
|
2012-02-05 17:50:23 +00:00
|
|
|
if NOW_REMEMBER(MaximizeVert, maximizevert) {
|
2011-01-30 14:34:42 +00:00
|
|
|
updated = updated || maximizevert != bool(c->maximizeMode() & MaximizeVertical);
|
2007-04-29 17:35:43 +00:00
|
|
|
maximizevert = c->maximizeMode() & MaximizeVertical;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2012-02-05 17:50:23 +00:00
|
|
|
if NOW_REMEMBER(MaximizeHoriz, maximizehoriz) {
|
2011-01-30 14:34:42 +00:00
|
|
|
updated = updated || maximizehoriz != bool(c->maximizeMode() & MaximizeHorizontal);
|
2007-04-29 17:35:43 +00:00
|
|
|
maximizehoriz = c->maximizeMode() & MaximizeHorizontal;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2012-02-05 17:50:23 +00:00
|
|
|
if NOW_REMEMBER(Minimize, minimize) {
|
2007-04-29 17:35:43 +00:00
|
|
|
updated = updated || minimize != c->isMinimized();
|
|
|
|
minimize = c->isMinimized();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2012-02-05 17:50:23 +00:00
|
|
|
if NOW_REMEMBER(Shade, shade) {
|
2011-01-30 14:34:42 +00:00
|
|
|
updated = updated || (shade != (c->shadeMode() != ShadeNone));
|
2007-04-29 17:35:43 +00:00
|
|
|
shade = c->shadeMode() != ShadeNone;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2012-02-05 17:50:23 +00:00
|
|
|
if NOW_REMEMBER(SkipTaskbar, skiptaskbar) {
|
2007-04-29 17:35:43 +00:00
|
|
|
updated = updated || skiptaskbar != c->skipTaskbar();
|
|
|
|
skiptaskbar = c->skipTaskbar();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2012-02-05 17:50:23 +00:00
|
|
|
if NOW_REMEMBER(SkipPager, skippager) {
|
2007-04-29 17:35:43 +00:00
|
|
|
updated = updated || skippager != c->skipPager();
|
|
|
|
skippager = c->skipPager();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2012-02-05 17:50:23 +00:00
|
|
|
if NOW_REMEMBER(SkipSwitcher, skipswitcher) {
|
2010-05-03 20:04:44 +00:00
|
|
|
updated = updated || skipswitcher != c->skipSwitcher();
|
|
|
|
skipswitcher = c->skipSwitcher();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2012-02-05 17:50:23 +00:00
|
|
|
if NOW_REMEMBER(Above, above) {
|
2007-04-29 17:35:43 +00:00
|
|
|
updated = updated || above != c->keepAbove();
|
|
|
|
above = c->keepAbove();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2012-02-05 17:50:23 +00:00
|
|
|
if NOW_REMEMBER(Below, below) {
|
2007-04-29 17:35:43 +00:00
|
|
|
updated = updated || below != c->keepBelow();
|
|
|
|
below = c->keepBelow();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2012-02-05 17:50:23 +00:00
|
|
|
if NOW_REMEMBER(Fullscreen, fullscreen) {
|
2007-04-29 17:35:43 +00:00
|
|
|
updated = updated || fullscreen != c->isFullScreen();
|
|
|
|
fullscreen = c->isFullScreen();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2012-02-05 17:50:23 +00:00
|
|
|
if NOW_REMEMBER(NoBorder, noborder) {
|
2008-03-23 00:12:11 +00:00
|
|
|
updated = updated || noborder != c->noBorder();
|
|
|
|
noborder = c->noBorder();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2018-03-11 16:13:32 +00:00
|
|
|
if NOW_REMEMBER(DesktopFile, desktopfile) {
|
|
|
|
updated = updated || desktopfile != c->desktopFileName();
|
|
|
|
desktopfile = c->desktopFileName();
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
return updated;
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2012-02-05 17:50:23 +00:00
|
|
|
#undef NOW_REMEMBER
|
|
|
|
|
2007-04-29 17:35:43 +00:00
|
|
|
#define APPLY_RULE( var, name, type ) \
|
2011-01-30 14:34:42 +00:00
|
|
|
bool Rules::apply##name( type& arg, bool init ) const \
|
2007-04-29 17:35:43 +00:00
|
|
|
{ \
|
2011-01-30 14:34:42 +00:00
|
|
|
if ( checkSetRule( var##rule, init )) \
|
|
|
|
arg = this->var; \
|
|
|
|
return checkSetStop( var##rule ); \
|
2007-04-29 17:35:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#define APPLY_FORCE_RULE( var, name, type ) \
|
2011-01-30 14:34:42 +00:00
|
|
|
bool Rules::apply##name( type& arg ) const \
|
2007-04-29 17:35:43 +00:00
|
|
|
{ \
|
2011-01-30 14:34:42 +00:00
|
|
|
if ( checkForceRule( var##rule )) \
|
|
|
|
arg = this->var; \
|
|
|
|
return checkForceStop( var##rule ); \
|
2007-04-29 17:35:43 +00:00
|
|
|
}
|
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
APPLY_FORCE_RULE(placement, Placement, Placement::Policy)
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
bool Rules::applyGeometry(QRect& rect, bool init) const
|
|
|
|
{
|
2007-04-29 17:35:43 +00:00
|
|
|
QPoint p = rect.topLeft();
|
|
|
|
QSize s = rect.size();
|
|
|
|
bool ret = false; // no short-circuiting
|
2011-01-30 14:34:42 +00:00
|
|
|
if (applyPosition(p, init)) {
|
|
|
|
rect.moveTopLeft(p);
|
2007-04-29 17:35:43 +00:00
|
|
|
ret = true;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
|
|
|
if (applySize(s, init)) {
|
|
|
|
rect.setSize(s);
|
2007-04-29 17:35:43 +00:00
|
|
|
ret = true;
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
return ret;
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
bool Rules::applyPosition(QPoint& pos, bool init) const
|
|
|
|
{
|
|
|
|
if (this->position != invalidPoint && checkSetRule(positionrule, init))
|
2007-04-29 17:35:43 +00:00
|
|
|
pos = this->position;
|
2011-01-30 14:34:42 +00:00
|
|
|
return checkSetStop(positionrule);
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
bool Rules::applySize(QSize& s, bool init) const
|
|
|
|
{
|
|
|
|
if (this->size.isValid() && checkSetRule(sizerule, init))
|
2007-04-29 17:35:43 +00:00
|
|
|
s = this->size;
|
2011-01-30 14:34:42 +00:00
|
|
|
return checkSetStop(sizerule);
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
APPLY_FORCE_RULE(minsize, MinSize, QSize)
|
|
|
|
APPLY_FORCE_RULE(maxsize, MaxSize, QSize)
|
|
|
|
APPLY_FORCE_RULE(opacityactive, OpacityActive, int)
|
|
|
|
APPLY_FORCE_RULE(opacityinactive, OpacityInactive, int)
|
2013-03-24 18:13:00 +00:00
|
|
|
APPLY_RULE(ignoregeometry, IgnoreGeometry, bool)
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
APPLY_RULE(desktop, Desktop, int)
|
2012-08-24 16:48:50 +00:00
|
|
|
APPLY_RULE(screen, Screen, int)
|
2012-05-17 14:32:06 +00:00
|
|
|
APPLY_RULE(activity, Activity, QString)
|
2011-01-30 14:34:42 +00:00
|
|
|
APPLY_FORCE_RULE(type, Type, NET::WindowType)
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
bool Rules::applyMaximizeHoriz(MaximizeMode& mode, bool init) const
|
|
|
|
{
|
|
|
|
if (checkSetRule(maximizehorizrule, init))
|
|
|
|
mode = static_cast< MaximizeMode >((maximizehoriz ? MaximizeHorizontal : 0) | (mode & MaximizeVertical));
|
|
|
|
return checkSetStop(maximizehorizrule);
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
bool Rules::applyMaximizeVert(MaximizeMode& mode, bool init) const
|
|
|
|
{
|
|
|
|
if (checkSetRule(maximizevertrule, init))
|
|
|
|
mode = static_cast< MaximizeMode >((maximizevert ? MaximizeVertical : 0) | (mode & MaximizeHorizontal));
|
|
|
|
return checkSetStop(maximizevertrule);
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
APPLY_RULE(minimize, Minimize, bool)
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
bool Rules::applyShade(ShadeMode& sh, bool init) const
|
|
|
|
{
|
|
|
|
if (checkSetRule(shaderule, init)) {
|
|
|
|
if (!this->shade)
|
2007-04-29 17:35:43 +00:00
|
|
|
sh = ShadeNone;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (this->shade && sh == ShadeNone)
|
2007-04-29 17:35:43 +00:00
|
|
|
sh = ShadeNormal;
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
return checkSetStop(shaderule);
|
|
|
|
}
|
|
|
|
|
|
|
|
APPLY_RULE(skiptaskbar, SkipTaskbar, bool)
|
|
|
|
APPLY_RULE(skippager, SkipPager, bool)
|
|
|
|
APPLY_RULE(skipswitcher, SkipSwitcher, bool)
|
|
|
|
APPLY_RULE(above, KeepAbove, bool)
|
|
|
|
APPLY_RULE(below, KeepBelow, bool)
|
|
|
|
APPLY_RULE(fullscreen, FullScreen, bool)
|
|
|
|
APPLY_RULE(noborder, NoBorder, bool)
|
2013-11-05 12:42:33 +00:00
|
|
|
APPLY_FORCE_RULE(decocolor, DecoColor, QString)
|
2011-03-20 14:42:05 +00:00
|
|
|
APPLY_FORCE_RULE(blockcompositing, BlockCompositing, bool)
|
2011-01-30 14:34:42 +00:00
|
|
|
APPLY_FORCE_RULE(fsplevel, FSP, int)
|
2015-11-12 23:37:01 +00:00
|
|
|
APPLY_FORCE_RULE(fpplevel, FPP, int)
|
2011-01-30 14:34:42 +00:00
|
|
|
APPLY_FORCE_RULE(acceptfocus, AcceptFocus, bool)
|
|
|
|
APPLY_FORCE_RULE(closeable, Closeable, bool)
|
|
|
|
APPLY_FORCE_RULE(autogroup, Autogrouping, bool)
|
|
|
|
APPLY_FORCE_RULE(autogroupfg, AutogroupInForeground, bool)
|
|
|
|
APPLY_FORCE_RULE(autogroupid, AutogroupById, QString)
|
|
|
|
APPLY_FORCE_RULE(strictgeometry, StrictGeometry, bool)
|
|
|
|
APPLY_RULE(shortcut, Shortcut, QString)
|
|
|
|
APPLY_FORCE_RULE(disableglobalshortcuts, DisableGlobalShortcuts, bool)
|
2018-03-11 16:13:32 +00:00
|
|
|
APPLY_RULE(desktopfile, DesktopFile, QString)
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
|
|
|
|
#undef APPLY_RULE
|
|
|
|
#undef APPLY_FORCE_RULE
|
|
|
|
|
|
|
|
bool Rules::isTemporary() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2007-04-29 17:35:43 +00:00
|
|
|
return temporary_state > 0;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
bool Rules::discardTemporary(bool force)
|
|
|
|
{
|
|
|
|
if (temporary_state == 0) // not temporary
|
2007-04-29 17:35:43 +00:00
|
|
|
return false;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (force || --temporary_state == 0) { // too old
|
2007-04-29 17:35:43 +00:00
|
|
|
delete this;
|
|
|
|
return true;
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
return false;
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
#define DISCARD_USED_SET_RULE( var ) \
|
|
|
|
do { \
|
2018-05-07 19:59:17 +00:00
|
|
|
if ( var##rule == ( SetRule ) ApplyNow || ( withdrawn && var##rule == ( SetRule ) ForceTemporarily )) { \
|
2011-01-30 14:34:42 +00:00
|
|
|
var##rule = UnusedSetRule; \
|
2018-05-07 19:59:17 +00:00
|
|
|
changed = true; \
|
|
|
|
} \
|
2011-01-30 14:34:42 +00:00
|
|
|
} while ( false )
|
2007-04-29 17:35:43 +00:00
|
|
|
#define DISCARD_USED_FORCE_RULE( var ) \
|
|
|
|
do { \
|
2018-05-07 19:59:17 +00:00
|
|
|
if ( withdrawn && var##rule == ( ForceRule ) ForceTemporarily ) { \
|
2011-01-30 14:34:42 +00:00
|
|
|
var##rule = UnusedForceRule; \
|
2018-05-07 19:59:17 +00:00
|
|
|
changed = true; \
|
|
|
|
} \
|
2011-01-30 14:34:42 +00:00
|
|
|
} while ( false )
|
|
|
|
|
2018-05-07 19:59:17 +00:00
|
|
|
bool Rules::discardUsed(bool withdrawn)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2018-05-07 19:59:17 +00:00
|
|
|
bool changed = false;
|
2011-01-30 14:34:42 +00:00
|
|
|
DISCARD_USED_FORCE_RULE(placement);
|
|
|
|
DISCARD_USED_SET_RULE(position);
|
|
|
|
DISCARD_USED_SET_RULE(size);
|
|
|
|
DISCARD_USED_FORCE_RULE(minsize);
|
|
|
|
DISCARD_USED_FORCE_RULE(maxsize);
|
|
|
|
DISCARD_USED_FORCE_RULE(opacityactive);
|
|
|
|
DISCARD_USED_FORCE_RULE(opacityinactive);
|
2013-03-24 18:13:00 +00:00
|
|
|
DISCARD_USED_SET_RULE(ignoregeometry);
|
2011-01-30 14:34:42 +00:00
|
|
|
DISCARD_USED_SET_RULE(desktop);
|
2012-08-24 16:48:50 +00:00
|
|
|
DISCARD_USED_SET_RULE(screen);
|
2012-05-17 14:32:06 +00:00
|
|
|
DISCARD_USED_SET_RULE(activity);
|
2011-01-30 14:34:42 +00:00
|
|
|
DISCARD_USED_FORCE_RULE(type);
|
|
|
|
DISCARD_USED_SET_RULE(maximizevert);
|
|
|
|
DISCARD_USED_SET_RULE(maximizehoriz);
|
|
|
|
DISCARD_USED_SET_RULE(minimize);
|
|
|
|
DISCARD_USED_SET_RULE(shade);
|
|
|
|
DISCARD_USED_SET_RULE(skiptaskbar);
|
|
|
|
DISCARD_USED_SET_RULE(skippager);
|
|
|
|
DISCARD_USED_SET_RULE(skipswitcher);
|
|
|
|
DISCARD_USED_SET_RULE(above);
|
|
|
|
DISCARD_USED_SET_RULE(below);
|
|
|
|
DISCARD_USED_SET_RULE(fullscreen);
|
|
|
|
DISCARD_USED_SET_RULE(noborder);
|
2013-11-05 12:42:33 +00:00
|
|
|
DISCARD_USED_FORCE_RULE(decocolor);
|
2011-03-20 14:42:05 +00:00
|
|
|
DISCARD_USED_FORCE_RULE(blockcompositing);
|
2011-01-30 14:34:42 +00:00
|
|
|
DISCARD_USED_FORCE_RULE(fsplevel);
|
2015-11-12 23:37:01 +00:00
|
|
|
DISCARD_USED_FORCE_RULE(fpplevel);
|
2011-01-30 14:34:42 +00:00
|
|
|
DISCARD_USED_FORCE_RULE(acceptfocus);
|
|
|
|
DISCARD_USED_FORCE_RULE(closeable);
|
|
|
|
DISCARD_USED_FORCE_RULE(autogroup);
|
|
|
|
DISCARD_USED_FORCE_RULE(autogroupfg);
|
|
|
|
DISCARD_USED_FORCE_RULE(autogroupid);
|
|
|
|
DISCARD_USED_FORCE_RULE(strictgeometry);
|
|
|
|
DISCARD_USED_SET_RULE(shortcut);
|
|
|
|
DISCARD_USED_FORCE_RULE(disableglobalshortcuts);
|
2018-03-11 16:13:32 +00:00
|
|
|
DISCARD_USED_SET_RULE(desktopfile);
|
2018-05-07 19:59:17 +00:00
|
|
|
|
|
|
|
return changed;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
#undef DISCARD_USED_SET_RULE
|
|
|
|
#undef DISCARD_USED_FORCE_RULE
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
QDebug& operator<<(QDebug& stream, const Rules* r)
|
|
|
|
{
|
2007-04-29 17:35:43 +00:00
|
|
|
return stream << "[" << r->description << ":" << r->wmclass << "]" ;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
#ifndef KCMRULES
|
|
|
|
void WindowRules::discardTemporary()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2007-04-29 17:35:43 +00:00
|
|
|
QVector< Rules* >::Iterator it2 = rules.begin();
|
2011-01-30 14:34:42 +00:00
|
|
|
for (QVector< Rules* >::Iterator it = rules.begin();
|
|
|
|
it != rules.end();
|
|
|
|
) {
|
|
|
|
if ((*it)->discardTemporary(true))
|
2007-04-29 17:35:43 +00:00
|
|
|
++it;
|
2011-01-30 14:34:42 +00:00
|
|
|
else {
|
2007-04-29 17:35:43 +00:00
|
|
|
*it2++ = *it++;
|
|
|
|
}
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
rules.erase(it2, rules.end());
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2017-10-01 14:38:57 +00:00
|
|
|
void WindowRules::update(AbstractClient* c, int selection)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2007-04-29 17:35:43 +00:00
|
|
|
bool updated = false;
|
2011-01-30 14:34:42 +00:00
|
|
|
for (QVector< Rules* >::ConstIterator it = rules.constBegin();
|
|
|
|
it != rules.constEnd();
|
|
|
|
++it)
|
2012-02-05 17:50:23 +00:00
|
|
|
if ((*it)->update(c, selection)) // no short-circuiting here
|
2007-04-29 17:35:43 +00:00
|
|
|
updated = true;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (updated)
|
2013-04-26 12:40:35 +00:00
|
|
|
RuleBook::self()->requestDiskStorage();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
#define CHECK_RULE( rule, type ) \
|
2011-01-30 14:34:42 +00:00
|
|
|
type WindowRules::check##rule( type arg, bool init ) const \
|
2007-04-29 17:35:43 +00:00
|
|
|
{ \
|
2011-01-30 14:34:42 +00:00
|
|
|
if ( rules.count() == 0 ) \
|
|
|
|
return arg; \
|
|
|
|
type ret = arg; \
|
|
|
|
for ( QVector< Rules* >::ConstIterator it = rules.constBegin(); \
|
|
|
|
it != rules.constEnd(); \
|
|
|
|
++it ) \
|
2007-04-29 17:35:43 +00:00
|
|
|
{ \
|
2011-01-30 14:34:42 +00:00
|
|
|
if ( (*it)->apply##rule( ret, init )) \
|
|
|
|
break; \
|
2007-04-29 17:35:43 +00:00
|
|
|
} \
|
2011-01-30 14:34:42 +00:00
|
|
|
return ret; \
|
2007-04-29 17:35:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#define CHECK_FORCE_RULE( rule, type ) \
|
2011-01-30 14:34:42 +00:00
|
|
|
type WindowRules::check##rule( type arg ) const \
|
2007-04-29 17:35:43 +00:00
|
|
|
{ \
|
2011-01-30 14:34:42 +00:00
|
|
|
if ( rules.count() == 0 ) \
|
|
|
|
return arg; \
|
|
|
|
type ret = arg; \
|
|
|
|
for ( QVector< Rules* >::ConstIterator it = rules.begin(); \
|
|
|
|
it != rules.end(); \
|
|
|
|
++it ) \
|
2007-04-29 17:35:43 +00:00
|
|
|
{ \
|
2011-01-30 14:34:42 +00:00
|
|
|
if ( (*it)->apply##rule( ret )) \
|
|
|
|
break; \
|
2007-04-29 17:35:43 +00:00
|
|
|
} \
|
2011-01-30 14:34:42 +00:00
|
|
|
return ret; \
|
2007-04-29 17:35:43 +00:00
|
|
|
}
|
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
CHECK_FORCE_RULE(Placement, Placement::Policy)
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
QRect WindowRules::checkGeometry(QRect rect, bool init) const
|
|
|
|
{
|
|
|
|
return QRect(checkPosition(rect.topLeft(), init), checkSize(rect.size(), init));
|
|
|
|
}
|
|
|
|
|
|
|
|
CHECK_RULE(Position, QPoint)
|
|
|
|
CHECK_RULE(Size, QSize)
|
|
|
|
CHECK_FORCE_RULE(MinSize, QSize)
|
|
|
|
CHECK_FORCE_RULE(MaxSize, QSize)
|
|
|
|
CHECK_FORCE_RULE(OpacityActive, int)
|
|
|
|
CHECK_FORCE_RULE(OpacityInactive, int)
|
2013-03-24 18:13:00 +00:00
|
|
|
CHECK_RULE(IgnoreGeometry, bool)
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
CHECK_RULE(Desktop, int)
|
2012-05-17 14:32:06 +00:00
|
|
|
CHECK_RULE(Activity, QString)
|
2011-01-30 14:34:42 +00:00
|
|
|
CHECK_FORCE_RULE(Type, NET::WindowType)
|
2014-12-02 12:49:08 +00:00
|
|
|
CHECK_RULE(MaximizeVert, MaximizeMode)
|
|
|
|
CHECK_RULE(MaximizeHoriz, MaximizeMode)
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2014-12-02 12:49:08 +00:00
|
|
|
MaximizeMode WindowRules::checkMaximize(MaximizeMode mode, bool init) const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
bool vert = checkMaximizeVert(mode, init) & MaximizeVertical;
|
|
|
|
bool horiz = checkMaximizeHoriz(mode, init) & MaximizeHorizontal;
|
|
|
|
return static_cast< MaximizeMode >((vert ? MaximizeVertical : 0) | (horiz ? MaximizeHorizontal : 0));
|
|
|
|
}
|
|
|
|
|
2012-08-24 16:48:50 +00:00
|
|
|
int WindowRules::checkScreen(int screen, bool init) const
|
|
|
|
{
|
|
|
|
if ( rules.count() == 0 )
|
|
|
|
return screen;
|
|
|
|
int ret = screen;
|
|
|
|
for ( QVector< Rules* >::ConstIterator it = rules.constBegin(); it != rules.constEnd(); ++it ) {
|
|
|
|
if ( (*it)->applyScreen( ret, init ))
|
|
|
|
break;
|
|
|
|
}
|
2013-04-03 10:19:27 +00:00
|
|
|
if (ret >= Screens::self()->count())
|
2012-08-24 16:48:50 +00:00
|
|
|
ret = screen;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
CHECK_RULE(Minimize, bool)
|
|
|
|
CHECK_RULE(Shade, ShadeMode)
|
|
|
|
CHECK_RULE(SkipTaskbar, bool)
|
|
|
|
CHECK_RULE(SkipPager, bool)
|
|
|
|
CHECK_RULE(SkipSwitcher, bool)
|
|
|
|
CHECK_RULE(KeepAbove, bool)
|
|
|
|
CHECK_RULE(KeepBelow, bool)
|
|
|
|
CHECK_RULE(FullScreen, bool)
|
|
|
|
CHECK_RULE(NoBorder, bool)
|
2013-11-05 12:42:33 +00:00
|
|
|
CHECK_FORCE_RULE(DecoColor, QString)
|
2011-03-20 14:42:05 +00:00
|
|
|
CHECK_FORCE_RULE(BlockCompositing, bool)
|
2011-01-30 14:34:42 +00:00
|
|
|
CHECK_FORCE_RULE(FSP, int)
|
2015-11-12 23:37:01 +00:00
|
|
|
CHECK_FORCE_RULE(FPP, int)
|
2011-01-30 14:34:42 +00:00
|
|
|
CHECK_FORCE_RULE(AcceptFocus, bool)
|
|
|
|
CHECK_FORCE_RULE(Closeable, bool)
|
|
|
|
CHECK_FORCE_RULE(Autogrouping, bool)
|
|
|
|
CHECK_FORCE_RULE(AutogroupInForeground, bool)
|
|
|
|
CHECK_FORCE_RULE(AutogroupById, QString)
|
|
|
|
CHECK_FORCE_RULE(StrictGeometry, bool)
|
|
|
|
CHECK_RULE(Shortcut, QString)
|
|
|
|
CHECK_FORCE_RULE(DisableGlobalShortcuts, bool)
|
2018-03-11 16:13:32 +00:00
|
|
|
CHECK_RULE(DesktopFile, QString)
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
#undef CHECK_RULE
|
|
|
|
#undef CHECK_FORCE_RULE
|
|
|
|
|
|
|
|
// Client
|
|
|
|
|
2017-10-01 14:38:57 +00:00
|
|
|
void AbstractClient::setupWindowRules(bool ignore_temporary)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2017-10-01 14:38:57 +00:00
|
|
|
disconnect(this, &AbstractClient::captionChanged, this, &AbstractClient::evaluateWindowRules);
|
|
|
|
m_rules = RuleBook::self()->find(this, ignore_temporary);
|
2007-04-29 17:35:43 +00:00
|
|
|
// check only after getting the rules, because there may be a rule forcing window type
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
// Applies Force, ForceTemporarily and ApplyNow rules
|
|
|
|
// Used e.g. after the rules have been modified using the kcm.
|
2017-10-01 14:38:57 +00:00
|
|
|
void AbstractClient::applyWindowRules()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2007-04-29 17:35:43 +00:00
|
|
|
// apply force rules
|
|
|
|
// Placement - does need explicit update, just like some others below
|
|
|
|
// Geometry : setGeometry() doesn't check rules
|
2017-10-01 14:38:57 +00:00
|
|
|
auto client_rules = rules();
|
2011-01-30 14:34:42 +00:00
|
|
|
QRect orig_geom = QRect(pos(), sizeForClientSize(clientSize())); // handle shading
|
2017-10-01 14:38:57 +00:00
|
|
|
QRect geom = client_rules->checkGeometry(orig_geom);
|
2011-01-30 14:34:42 +00:00
|
|
|
if (geom != orig_geom)
|
|
|
|
setGeometry(geom);
|
2007-04-29 17:35:43 +00:00
|
|
|
// MinSize, MaxSize handled by Geometry
|
2013-03-24 18:13:00 +00:00
|
|
|
// IgnoreGeometry
|
2011-01-30 14:34:42 +00:00
|
|
|
setDesktop(desktop());
|
2012-08-24 16:48:50 +00:00
|
|
|
workspace()->sendClientToScreen(this, screen());
|
2012-05-17 14:32:06 +00:00
|
|
|
setOnActivities(activities());
|
2007-04-29 17:35:43 +00:00
|
|
|
// Type
|
2011-01-30 14:34:42 +00:00
|
|
|
maximize(maximizeMode());
|
2007-04-29 17:35:43 +00:00
|
|
|
// Minimize : functions don't check, and there are two functions
|
2017-10-01 14:38:57 +00:00
|
|
|
if (client_rules->checkMinimize(isMinimized()))
|
2007-04-29 17:35:43 +00:00
|
|
|
minimize();
|
|
|
|
else
|
|
|
|
unminimize();
|
2011-01-30 14:34:42 +00:00
|
|
|
setShade(shadeMode());
|
2015-06-06 20:08:12 +00:00
|
|
|
setOriginalSkipTaskbar(skipTaskbar());
|
2011-01-30 14:34:42 +00:00
|
|
|
setSkipPager(skipPager());
|
|
|
|
setSkipSwitcher(skipSwitcher());
|
|
|
|
setKeepAbove(keepAbove());
|
|
|
|
setKeepBelow(keepBelow());
|
|
|
|
setFullScreen(isFullScreen(), true);
|
|
|
|
setNoBorder(noBorder());
|
2013-11-05 12:42:33 +00:00
|
|
|
updateColorScheme();
|
2007-04-29 17:35:43 +00:00
|
|
|
// FSP
|
|
|
|
// AcceptFocus :
|
2011-01-30 14:34:42 +00:00
|
|
|
if (workspace()->mostRecentlyActivatedClient() == this
|
2017-10-01 14:38:57 +00:00
|
|
|
&& !client_rules->checkAcceptFocus(true))
|
2011-01-30 14:34:42 +00:00
|
|
|
workspace()->activateNextClient(this);
|
2007-04-29 17:35:43 +00:00
|
|
|
// Closeable
|
|
|
|
QSize s = adjustedSize();
|
2011-01-30 14:34:42 +00:00
|
|
|
if (s != size())
|
|
|
|
resizeWithChecks(s);
|
2009-11-16 11:26:37 +00:00
|
|
|
// Autogrouping : Only checked on window manage
|
2009-11-17 10:41:32 +00:00
|
|
|
// AutogroupInForeground : Only checked on window manage
|
2009-11-16 13:31:02 +00:00
|
|
|
// AutogroupById : Only checked on window manage
|
2007-04-29 17:35:43 +00:00
|
|
|
// StrictGeometry
|
2011-01-30 14:34:42 +00:00
|
|
|
setShortcut(rules()->checkShortcut(shortcut().toString()));
|
2007-04-29 17:35:43 +00:00
|
|
|
// see also Client::setActive()
|
2011-01-30 14:34:42 +00:00
|
|
|
if (isActive()) {
|
|
|
|
setOpacity(rules()->checkOpacityActive(qRound(opacity() * 100.0)) / 100.0);
|
|
|
|
workspace()->disableGlobalShortcutsForClient(rules()->checkDisableGlobalShortcuts(false));
|
|
|
|
} else
|
|
|
|
setOpacity(rules()->checkOpacityInactive(qRound(opacity() * 100.0)) / 100.0);
|
2018-03-11 16:13:32 +00:00
|
|
|
setDesktopFileName(rules()->checkDesktopFile(desktopFileName()).toUtf8());
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2012-02-05 17:50:23 +00:00
|
|
|
void Client::updateWindowRules(Rules::Types selection)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
if (!isManaged()) // not fully setup yet
|
2007-04-29 17:35:43 +00:00
|
|
|
return;
|
2017-10-01 14:38:57 +00:00
|
|
|
AbstractClient::updateWindowRules(selection);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AbstractClient::updateWindowRules(Rules::Types selection)
|
|
|
|
{
|
2013-04-26 12:40:35 +00:00
|
|
|
if (RuleBook::self()->areUpdatesDisabled())
|
2007-04-30 12:24:10 +00:00
|
|
|
return;
|
2017-10-01 14:38:57 +00:00
|
|
|
m_rules.update(this, selection);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2017-10-01 14:38:57 +00:00
|
|
|
void AbstractClient::finishWindowRules()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2012-02-05 17:50:23 +00:00
|
|
|
updateWindowRules(Rules::All);
|
2017-10-01 14:38:57 +00:00
|
|
|
m_rules = WindowRules();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
// Workspace
|
2013-04-26 12:40:35 +00:00
|
|
|
KWIN_SINGLETON_FACTORY(RuleBook)
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2013-04-26 12:40:35 +00:00
|
|
|
RuleBook::RuleBook(QObject *parent)
|
|
|
|
: QObject(parent)
|
|
|
|
, m_updateTimer(new QTimer(this))
|
|
|
|
, m_updatesDisabled(false)
|
2017-09-02 09:09:41 +00:00
|
|
|
, m_temporaryRulesMessages()
|
2013-04-26 12:40:35 +00:00
|
|
|
{
|
2017-09-02 09:09:41 +00:00
|
|
|
initWithX11();
|
|
|
|
connect(kwinApp(), &Application::x11ConnectionChanged, this, &RuleBook::initWithX11);
|
2013-04-26 12:40:35 +00:00
|
|
|
connect(m_updateTimer, SIGNAL(timeout()), SLOT(save()));
|
|
|
|
m_updateTimer->setInterval(1000);
|
|
|
|
m_updateTimer->setSingleShot(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
RuleBook::~RuleBook()
|
|
|
|
{
|
|
|
|
save();
|
|
|
|
deleteAll();
|
|
|
|
}
|
|
|
|
|
2017-09-02 09:09:41 +00:00
|
|
|
void RuleBook::initWithX11()
|
|
|
|
{
|
|
|
|
auto c = kwinApp()->x11Connection();
|
|
|
|
if (!c) {
|
|
|
|
m_temporaryRulesMessages.reset();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
m_temporaryRulesMessages.reset(new KXMessages(c, kwinApp()->x11RootWindow(), "_KDE_NET_WM_TEMPORARY_RULES", nullptr));
|
|
|
|
connect(m_temporaryRulesMessages.data(), SIGNAL(gotMessage(QString)), SLOT(temporaryRulesMessage(QString)));
|
|
|
|
}
|
|
|
|
|
2013-04-26 12:40:35 +00:00
|
|
|
void RuleBook::deleteAll()
|
|
|
|
{
|
|
|
|
qDeleteAll(m_rules);
|
|
|
|
m_rules.clear();
|
|
|
|
}
|
|
|
|
|
2017-10-01 14:38:57 +00:00
|
|
|
WindowRules RuleBook::find(const AbstractClient* c, bool ignore_temporary)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2007-04-29 17:35:43 +00:00
|
|
|
QVector< Rules* > ret;
|
2013-04-26 12:40:35 +00:00
|
|
|
for (QList< Rules* >::Iterator it = m_rules.begin();
|
|
|
|
it != m_rules.end();
|
2011-01-30 14:34:42 +00:00
|
|
|
) {
|
|
|
|
if (ignore_temporary && (*it)->isTemporary()) {
|
2007-04-29 17:35:43 +00:00
|
|
|
++it;
|
|
|
|
continue;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
|
|
|
if ((*it)->match(c)) {
|
2007-04-29 17:35:43 +00:00
|
|
|
Rules* rule = *it;
|
2014-12-05 10:42:15 +00:00
|
|
|
qCDebug(KWIN_CORE) << "Rule found:" << rule << ":" << c;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (rule->isTemporary())
|
2013-04-26 12:40:35 +00:00
|
|
|
it = m_rules.erase(it);
|
2007-04-29 17:35:43 +00:00
|
|
|
else
|
|
|
|
++it;
|
2011-01-30 14:34:42 +00:00
|
|
|
ret.append(rule);
|
2007-04-29 17:35:43 +00:00
|
|
|
continue;
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
++it;
|
2007-04-29 17:35:43 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
return WindowRules(ret);
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2015-03-06 08:33:18 +00:00
|
|
|
void RuleBook::edit(AbstractClient* c, bool whole_app)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2013-04-26 12:40:35 +00:00
|
|
|
save();
|
2007-04-29 17:35:43 +00:00
|
|
|
QStringList args;
|
2018-12-23 07:56:15 +00:00
|
|
|
args << QStringLiteral("--uuid") << c->internalId().toString();
|
2011-01-30 14:34:42 +00:00
|
|
|
if (whole_app)
|
2013-07-23 05:02:52 +00:00
|
|
|
args << QStringLiteral("--whole-app");
|
2015-12-15 09:22:03 +00:00
|
|
|
QProcess *p = new Process(this);
|
2015-07-07 15:35:57 +00:00
|
|
|
p->setArguments(args);
|
|
|
|
p->setProcessEnvironment(kwinApp()->processStartupEnvironment());
|
2018-11-08 21:08:06 +00:00
|
|
|
const QFileInfo buildDirBinary{QDir{QCoreApplication::applicationDirPath()}, QStringLiteral("kwin_rules_dialog")};
|
|
|
|
p->setProgram(buildDirBinary.exists() ? buildDirBinary.absoluteFilePath() : QStringLiteral(KWIN_RULES_DIALOG_BIN));
|
2018-12-23 07:56:15 +00:00
|
|
|
p->setProcessChannelMode(QProcess::MergedChannels);
|
2015-08-11 06:36:36 +00:00
|
|
|
connect(p, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished), p, &QProcess::deleteLater);
|
2015-07-07 15:35:57 +00:00
|
|
|
connect(p, static_cast<void (QProcess::*)(QProcess::ProcessError)>(&QProcess::error), this,
|
|
|
|
[p] (QProcess::ProcessError e) {
|
|
|
|
if (e == QProcess::FailedToStart) {
|
2015-09-30 14:24:25 +00:00
|
|
|
qCDebug(KWIN_CORE) << "Failed to start" << p->program();
|
2015-07-07 15:35:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
p->start();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2013-04-26 12:40:35 +00:00
|
|
|
void RuleBook::load()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2013-04-26 12:40:35 +00:00
|
|
|
deleteAll();
|
2018-02-11 17:27:34 +00:00
|
|
|
if (!m_config) {
|
|
|
|
m_config = KSharedConfig::openConfig(QStringLiteral(KWIN_NAME "rulesrc"), KConfig::NoGlobals);
|
2018-05-05 07:11:34 +00:00
|
|
|
} else {
|
|
|
|
m_config->reparseConfiguration();
|
2018-02-11 17:27:34 +00:00
|
|
|
}
|
|
|
|
int count = m_config->group("General").readEntry("count", 0);
|
2011-01-30 14:34:42 +00:00
|
|
|
for (int i = 1;
|
|
|
|
i <= count;
|
|
|
|
++i) {
|
2018-02-11 17:27:34 +00:00
|
|
|
KConfigGroup cg(m_config, QString::number(i));
|
2011-01-30 14:34:42 +00:00
|
|
|
Rules* rule = new Rules(cg);
|
2013-04-26 12:40:35 +00:00
|
|
|
m_rules.append(rule);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2013-04-26 12:40:35 +00:00
|
|
|
void RuleBook::save()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2013-04-26 12:40:35 +00:00
|
|
|
m_updateTimer->stop();
|
2018-05-07 19:35:34 +00:00
|
|
|
if (!m_config) {
|
|
|
|
qCWarning(KWIN_CORE) << "RuleBook::save invoked without prior invokation of RuleBook::load";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
QStringList groups = m_config->groupList();
|
2011-01-30 14:34:42 +00:00
|
|
|
for (QStringList::ConstIterator it = groups.constBegin();
|
|
|
|
it != groups.constEnd();
|
|
|
|
++it)
|
2018-05-07 19:35:34 +00:00
|
|
|
m_config->deleteGroup(*it);
|
|
|
|
m_config->group("General").writeEntry("count", m_rules.count());
|
2007-04-29 17:35:43 +00:00
|
|
|
int i = 1;
|
2013-04-26 12:40:35 +00:00
|
|
|
for (QList< Rules* >::ConstIterator it = m_rules.constBegin();
|
|
|
|
it != m_rules.constEnd();
|
2011-01-30 14:34:42 +00:00
|
|
|
++it) {
|
|
|
|
if ((*it)->isTemporary())
|
2007-04-29 17:35:43 +00:00
|
|
|
continue;
|
2018-05-07 19:35:34 +00:00
|
|
|
KConfigGroup cg(m_config, QString::number(i));
|
2011-01-30 14:34:42 +00:00
|
|
|
(*it)->write(cg);
|
2007-04-29 17:35:43 +00:00
|
|
|
++i;
|
|
|
|
}
|
2018-11-01 08:28:46 +00:00
|
|
|
m_config->sync();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2013-04-26 12:40:35 +00:00
|
|
|
void RuleBook::temporaryRulesMessage(const QString& message)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2007-04-29 17:35:43 +00:00
|
|
|
bool was_temporary = false;
|
2013-04-26 12:40:35 +00:00
|
|
|
for (QList< Rules* >::ConstIterator it = m_rules.constBegin();
|
|
|
|
it != m_rules.constEnd();
|
2011-01-30 14:34:42 +00:00
|
|
|
++it)
|
|
|
|
if ((*it)->isTemporary())
|
2007-04-29 17:35:43 +00:00
|
|
|
was_temporary = true;
|
2011-01-30 14:34:42 +00:00
|
|
|
Rules* rule = new Rules(message, true);
|
2013-04-26 12:40:35 +00:00
|
|
|
m_rules.prepend(rule); // highest priority first
|
2011-01-30 14:34:42 +00:00
|
|
|
if (!was_temporary)
|
|
|
|
QTimer::singleShot(60000, this, SLOT(cleanupTemporaryRules()));
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2013-04-26 12:40:35 +00:00
|
|
|
void RuleBook::cleanupTemporaryRules()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2007-04-29 17:35:43 +00:00
|
|
|
bool has_temporary = false;
|
2013-04-26 12:40:35 +00:00
|
|
|
for (QList< Rules* >::Iterator it = m_rules.begin();
|
|
|
|
it != m_rules.end();
|
2011-01-30 14:34:42 +00:00
|
|
|
) {
|
2013-05-31 17:14:34 +00:00
|
|
|
if ((*it)->discardTemporary(false)) { // deletes (*it)
|
2013-04-26 12:40:35 +00:00
|
|
|
it = m_rules.erase(it);
|
|
|
|
} else {
|
2011-01-30 14:34:42 +00:00
|
|
|
if ((*it)->isTemporary())
|
2007-04-29 17:35:43 +00:00
|
|
|
has_temporary = true;
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
if (has_temporary)
|
|
|
|
QTimer::singleShot(60000, this, SLOT(cleanupTemporaryRules()));
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2017-10-01 19:37:18 +00:00
|
|
|
void RuleBook::discardUsed(AbstractClient* c, bool withdrawn)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2007-04-29 17:35:43 +00:00
|
|
|
bool updated = false;
|
2013-04-26 12:40:35 +00:00
|
|
|
for (QList< Rules* >::Iterator it = m_rules.begin();
|
|
|
|
it != m_rules.end();
|
2011-01-30 14:34:42 +00:00
|
|
|
) {
|
|
|
|
if (c->rules()->contains(*it)) {
|
2018-05-07 19:59:17 +00:00
|
|
|
if ((*it)->discardUsed(withdrawn)) {
|
|
|
|
updated = true;
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
if ((*it)->isEmpty()) {
|
|
|
|
c->removeRule(*it);
|
2007-04-29 17:35:43 +00:00
|
|
|
Rules* r = *it;
|
2013-04-26 12:40:35 +00:00
|
|
|
it = m_rules.erase(it);
|
2007-04-29 17:35:43 +00:00
|
|
|
delete r;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
++it;
|
2007-04-29 17:35:43 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
if (updated)
|
2013-04-26 12:40:35 +00:00
|
|
|
requestDiskStorage();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2013-04-26 12:40:35 +00:00
|
|
|
void RuleBook::requestDiskStorage()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2013-04-26 12:40:35 +00:00
|
|
|
m_updateTimer->start();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2013-04-26 12:40:35 +00:00
|
|
|
void RuleBook::setUpdatesDisabled(bool disable)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2013-04-26 12:40:35 +00:00
|
|
|
m_updatesDisabled = disable;
|
2012-02-05 17:50:23 +00:00
|
|
|
if (!disable) {
|
2013-04-26 12:40:35 +00:00
|
|
|
foreach (Client * c, Workspace::self()->clientList())
|
2012-02-05 17:50:23 +00:00
|
|
|
c->updateWindowRules(Rules::All);
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-30 12:24:10 +00:00
|
|
|
|
2007-04-29 17:35:43 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
} // namespace
|