kwinrules: Use a list of desktop UUIDs to set and store the rules setting

Port the RuleSettings and KCM to store and use a list of virtual desktop
 UUIDs, instead of the previous x11 positional id, continuing the work on
This allows to set a rule with several desktops on Wayland.

On X11 it has no visible change for the user, but internally it uses the
more modern concept, helping to simplify the related code.

The relevant key on kwinrulesrc changes from `desktop` to `desktops`.
A kconf_update script handles the migration.
master
Ismael Asensio 3 years ago
parent 5da8df39a5
commit 9995f984c3

@ -1783,12 +1783,18 @@ void TestXdgShellClientRules::testMaximizeForceTemporarily()
void TestXdgShellClientRules::testDesktopDontAffect() void TestXdgShellClientRules::testDesktopDontAffect()
{ {
// We need at least two virtual desktop for this test.
VirtualDesktopManager::self()->setCount(2);
QCOMPARE(VirtualDesktopManager::self()->count(), 2u);
VirtualDesktopManager::self()->setCurrent(1);
QCOMPARE(VirtualDesktopManager::self()->current(), 1);
// Initialize RuleBook with the test rule. // Initialize RuleBook with the test rule.
auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig);
config->group("General").writeEntry("count", 1); config->group("General").writeEntry("count", 1);
KConfigGroup group = config->group("1"); KConfigGroup group = config->group("1");
group.writeEntry("desktop", 2); group.writeEntry("desktops", {VirtualDesktopManager::self()->desktopForX11Id(2)->id()});
group.writeEntry("desktoprule", int(Rules::DontAffect)); group.writeEntry("desktopsrule", int(Rules::DontAffect));
group.writeEntry("wmclass", "org.kde.foo"); group.writeEntry("wmclass", "org.kde.foo");
group.writeEntry("wmclasscomplete", false); group.writeEntry("wmclasscomplete", false);
group.writeEntry("wmclassmatch", int(Rules::ExactMatch)); group.writeEntry("wmclassmatch", int(Rules::ExactMatch));
@ -1796,12 +1802,6 @@ void TestXdgShellClientRules::testDesktopDontAffect()
RuleBook::self()->setConfig(config); RuleBook::self()->setConfig(config);
workspace()->slotReconfigure(); workspace()->slotReconfigure();
// We need at least two virtual desktop for this test.
VirtualDesktopManager::self()->setCount(2);
QCOMPARE(VirtualDesktopManager::self()->count(), 2u);
VirtualDesktopManager::self()->setCurrent(1);
QCOMPARE(VirtualDesktopManager::self()->current(), 1);
// Create the test client. // Create the test client.
AbstractClient *client; AbstractClient *client;
Surface *surface; Surface *surface;
@ -1821,12 +1821,18 @@ void TestXdgShellClientRules::testDesktopDontAffect()
void TestXdgShellClientRules::testDesktopApply() void TestXdgShellClientRules::testDesktopApply()
{ {
// We need at least two virtual desktop for this test.
VirtualDesktopManager::self()->setCount(2);
QCOMPARE(VirtualDesktopManager::self()->count(), 2u);
VirtualDesktopManager::self()->setCurrent(1);
QCOMPARE(VirtualDesktopManager::self()->current(), 1);
// Initialize RuleBook with the test rule. // Initialize RuleBook with the test rule.
auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig);
config->group("General").writeEntry("count", 1); config->group("General").writeEntry("count", 1);
KConfigGroup group = config->group("1"); KConfigGroup group = config->group("1");
group.writeEntry("desktop", 2); group.writeEntry("desktops", {VirtualDesktopManager::self()->desktopForX11Id(2)->id()});
group.writeEntry("desktoprule", int(Rules::Apply)); group.writeEntry("desktopsrule", int(Rules::Apply));
group.writeEntry("wmclass", "org.kde.foo"); group.writeEntry("wmclass", "org.kde.foo");
group.writeEntry("wmclasscomplete", false); group.writeEntry("wmclasscomplete", false);
group.writeEntry("wmclassmatch", int(Rules::ExactMatch)); group.writeEntry("wmclassmatch", int(Rules::ExactMatch));
@ -1834,12 +1840,6 @@ void TestXdgShellClientRules::testDesktopApply()
RuleBook::self()->setConfig(config); RuleBook::self()->setConfig(config);
workspace()->slotReconfigure(); workspace()->slotReconfigure();
// We need at least two virtual desktop for this test.
VirtualDesktopManager::self()->setCount(2);
QCOMPARE(VirtualDesktopManager::self()->count(), 2u);
VirtualDesktopManager::self()->setCurrent(1);
QCOMPARE(VirtualDesktopManager::self()->current(), 1);
// Create the test client. // Create the test client.
AbstractClient *client; AbstractClient *client;
Surface *surface; Surface *surface;
@ -1875,12 +1875,18 @@ void TestXdgShellClientRules::testDesktopApply()
void TestXdgShellClientRules::testDesktopRemember() void TestXdgShellClientRules::testDesktopRemember()
{ {
// We need at least two virtual desktop for this test.
VirtualDesktopManager::self()->setCount(2);
QCOMPARE(VirtualDesktopManager::self()->count(), 2u);
VirtualDesktopManager::self()->setCurrent(1);
QCOMPARE(VirtualDesktopManager::self()->current(), 1);
// Initialize RuleBook with the test rule. // Initialize RuleBook with the test rule.
auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig);
config->group("General").writeEntry("count", 1); config->group("General").writeEntry("count", 1);
KConfigGroup group = config->group("1"); KConfigGroup group = config->group("1");
group.writeEntry("desktop", 2); group.writeEntry("desktops", {VirtualDesktopManager::self()->desktopForX11Id(2)->id()});
group.writeEntry("desktoprule", int(Rules::Remember)); group.writeEntry("desktopsrule", int(Rules::Remember));
group.writeEntry("wmclass", "org.kde.foo"); group.writeEntry("wmclass", "org.kde.foo");
group.writeEntry("wmclasscomplete", false); group.writeEntry("wmclasscomplete", false);
group.writeEntry("wmclassmatch", int(Rules::ExactMatch)); group.writeEntry("wmclassmatch", int(Rules::ExactMatch));
@ -1888,12 +1894,6 @@ void TestXdgShellClientRules::testDesktopRemember()
RuleBook::self()->setConfig(config); RuleBook::self()->setConfig(config);
workspace()->slotReconfigure(); workspace()->slotReconfigure();
// We need at least two virtual desktop for this test.
VirtualDesktopManager::self()->setCount(2);
QCOMPARE(VirtualDesktopManager::self()->count(), 2u);
VirtualDesktopManager::self()->setCurrent(1);
QCOMPARE(VirtualDesktopManager::self()->current(), 1);
// Create the test client. // Create the test client.
AbstractClient *client; AbstractClient *client;
Surface *surface; Surface *surface;
@ -1925,12 +1925,18 @@ void TestXdgShellClientRules::testDesktopRemember()
void TestXdgShellClientRules::testDesktopForce() void TestXdgShellClientRules::testDesktopForce()
{ {
// We need at least two virtual desktop for this test.
VirtualDesktopManager::self()->setCount(2);
QCOMPARE(VirtualDesktopManager::self()->count(), 2u);
VirtualDesktopManager::self()->setCurrent(1);
QCOMPARE(VirtualDesktopManager::self()->current(), 1);
// Initialize RuleBook with the test rule. // Initialize RuleBook with the test rule.
auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig);
config->group("General").writeEntry("count", 1); config->group("General").writeEntry("count", 1);
KConfigGroup group = config->group("1"); KConfigGroup group = config->group("1");
group.writeEntry("desktop", 2); group.writeEntry("desktops", {VirtualDesktopManager::self()->desktopForX11Id(2)->id()});
group.writeEntry("desktoprule", int(Rules::Force)); group.writeEntry("desktopsrule", int(Rules::Force));
group.writeEntry("wmclass", "org.kde.foo"); group.writeEntry("wmclass", "org.kde.foo");
group.writeEntry("wmclasscomplete", false); group.writeEntry("wmclasscomplete", false);
group.writeEntry("wmclassmatch", int(Rules::ExactMatch)); group.writeEntry("wmclassmatch", int(Rules::ExactMatch));
@ -1938,11 +1944,6 @@ void TestXdgShellClientRules::testDesktopForce()
RuleBook::self()->setConfig(config); RuleBook::self()->setConfig(config);
workspace()->slotReconfigure(); workspace()->slotReconfigure();
// We need at least two virtual desktop for this test.
VirtualDesktopManager::self()->setCount(2);
QCOMPARE(VirtualDesktopManager::self()->count(), 2u);
VirtualDesktopManager::self()->setCurrent(1);
QCOMPARE(VirtualDesktopManager::self()->current(), 1);
// Create the test client. // Create the test client.
AbstractClient *client; AbstractClient *client;
@ -1998,8 +1999,8 @@ void TestXdgShellClientRules::testDesktopApplyNow()
auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig);
config->group("General").writeEntry("count", 1); config->group("General").writeEntry("count", 1);
KConfigGroup group = config->group("1"); KConfigGroup group = config->group("1");
group.writeEntry("desktop", 2); group.writeEntry("desktops", {VirtualDesktopManager::self()->desktopForX11Id(2)->id()});
group.writeEntry("desktoprule", int(Rules::ApplyNow)); group.writeEntry("desktopsrule", int(Rules::ApplyNow));
group.writeEntry("wmclass", "org.kde.foo"); group.writeEntry("wmclass", "org.kde.foo");
group.writeEntry("wmclasscomplete", false); group.writeEntry("wmclasscomplete", false);
group.writeEntry("wmclassmatch", int(Rules::ExactMatch)); group.writeEntry("wmclassmatch", int(Rules::ExactMatch));
@ -2029,12 +2030,18 @@ void TestXdgShellClientRules::testDesktopApplyNow()
void TestXdgShellClientRules::testDesktopForceTemporarily() void TestXdgShellClientRules::testDesktopForceTemporarily()
{ {
// We need at least two virtual desktop for this test.
VirtualDesktopManager::self()->setCount(2);
QCOMPARE(VirtualDesktopManager::self()->count(), 2u);
VirtualDesktopManager::self()->setCurrent(1);
QCOMPARE(VirtualDesktopManager::self()->current(), 1);
// Initialize RuleBook with the test rule. // Initialize RuleBook with the test rule.
auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig);
config->group("General").writeEntry("count", 1); config->group("General").writeEntry("count", 1);
KConfigGroup group = config->group("1"); KConfigGroup group = config->group("1");
group.writeEntry("desktop", 2); group.writeEntry("desktops", {VirtualDesktopManager::self()->desktopForX11Id(2)->id()});
group.writeEntry("desktoprule", int(Rules::ForceTemporarily)); group.writeEntry("desktopsrule", int(Rules::ForceTemporarily));
group.writeEntry("wmclass", "org.kde.foo"); group.writeEntry("wmclass", "org.kde.foo");
group.writeEntry("wmclasscomplete", false); group.writeEntry("wmclasscomplete", false);
group.writeEntry("wmclassmatch", int(Rules::ExactMatch)); group.writeEntry("wmclassmatch", int(Rules::ExactMatch));
@ -2042,12 +2049,6 @@ void TestXdgShellClientRules::testDesktopForceTemporarily()
RuleBook::self()->setConfig(config); RuleBook::self()->setConfig(config);
workspace()->slotReconfigure(); workspace()->slotReconfigure();
// We need at least two virtual desktop for this test.
VirtualDesktopManager::self()->setCount(2);
QCOMPARE(VirtualDesktopManager::self()->count(), 2u);
VirtualDesktopManager::self()->setCurrent(1);
QCOMPARE(VirtualDesktopManager::self()->current(), 1);
// Create the test client. // Create the test client.
AbstractClient *client; AbstractClient *client;
Surface *surface; Surface *surface;

@ -23,3 +23,5 @@ install(FILES kwinrules.upd
DESTINATION ${KDE_INSTALL_KCONFUPDATEDIR}) DESTINATION ${KDE_INSTALL_KCONFUPDATEDIR})
install(PROGRAMS kwinrules-5.19-placement.pl install(PROGRAMS kwinrules-5.19-placement.pl
DESTINATION ${KDE_INSTALL_KCONFUPDATEDIR}) DESTINATION ${KDE_INSTALL_KCONFUPDATEDIR})
install(PROGRAMS kwinrules-5.23-virtual-desktop-ids.py
DESTINATION ${KDE_INSTALL_KCONFUPDATEDIR})

@ -0,0 +1,47 @@
#!/usr/bin/env python3
import fileinput
import configparser
import os.path
import subprocess
# Get the config standard locations
config_locations = subprocess.check_output(['qtpaths', '--paths', 'ConfigLocation']).decode('utf-8').strip().split(':')
config_paths = [os.path.join(folder, 'kwinrc') for folder in config_locations]
# Get the desktops information from `kwinrc` config file
kwinrc = configparser.ConfigParser(strict=False, allow_no_value=True)
kwinrc.read(config_paths)
num_desktops = int(kwinrc.get('Desktops', 'Number', fallback=''))
# Generete the map from x11ids (ennumeration) to UUIDs
desktopUUIDs = { -1: "" } # NET::OnAllDesktops -> Empty string
for i in range(1, num_desktops + 1):
uuid = kwinrc.get('Desktops', f'Id_{i}', fallback='')
desktopUUIDs[i] = str(uuid)
# Apply the conversion to `kwinrulesrc`
for line in fileinput.input():
# Rename key `desktoprule` to `desktopsrule`
if line.startswith("desktoprule="):
value = line[len("desktoprule="):].strip()
print("desktopsrule=" + value)
print("# DELETE desktoprule")
continue
if not line.startswith("desktop="):
print(line.strip())
continue
# Convert key `desktop` (x11id) to `desktops` (list of UUIDs)
try:
value = line[len("desktop="):].strip()
x11id = int(value)
uuid = desktopUUIDs[x11id]
except:
print(line.strip()) # If there is some error, print back the line
continue
print("desktops=" + uuid)
print("# DELETE desktop")

@ -5,3 +5,7 @@ Id=replace-placement-string-to-enum
File=kwinrulesrc File=kwinrulesrc
Script=kwinrules-5.19-placement.pl,perl Script=kwinrules-5.19-placement.pl,perl
# Replace the `desktop` x11id number to `desktops` list of desktop UUIDs
Id=use-virtual-desktop-ids
File=kwinrulesrc
Script=kwinrules-5.23-virtual-desktop-ids.py,python3

@ -497,7 +497,7 @@ void AbstractClient::setDesktops(QVector<VirtualDesktop*> desktops)
doSetDesktop(); doSetDesktop();
FocusChain::self()->update(this, FocusChain::MakeFirst); FocusChain::self()->update(this, FocusChain::MakeFirst);
updateWindowRules(Rules::Desktop); updateWindowRules(Rules::Desktops);
Q_EMIT desktopChanged(); Q_EMIT desktopChanged();
if (wasOnCurrentDesktop != isOnCurrentDesktop()) if (wasOnCurrentDesktop != isOnCurrentDesktop())
@ -572,6 +572,20 @@ QVector<uint> AbstractClient::x11DesktopIds() const
return x11Ids; return x11Ids;
} }
QStringList AbstractClient::desktopIds() const
{
const auto desks = desktops();
QStringList ids;
ids.reserve(desks.count());
std::transform(desks.constBegin(), desks.constEnd(),
std::back_inserter(ids),
[] (const VirtualDesktop *vd) {
return vd->id();
}
);
return ids;
};
ShadeMode AbstractClient::shadeMode() const ShadeMode AbstractClient::shadeMode() const
{ {
return m_shadeMode; return m_shadeMode;

@ -491,6 +491,7 @@ public:
return m_desktops; return m_desktops;
} }
QVector<uint> x11DesktopIds() const; QVector<uint> x11DesktopIds() const;
QStringList desktopIds() const;
void setMinimized(bool set); void setMinimized(bool set);
/** /**

@ -33,6 +33,7 @@ set(kwin_kcm_rules_XCB_LIBS
set(kcm_libs set(kcm_libs
Qt::Quick Qt::Quick
Qt::QuickWidgets Qt::QuickWidgets
Qt::X11Extras
KF5::KCMUtils KF5::KCMUtils
KF5::I18n KF5::I18n

@ -212,6 +212,9 @@ QVariant RuleItem::typedValue(const QVariant &value) const
case Size: case Size:
return value.toSize(); return value.toSize();
case String: case String:
if (value.type() == QVariant::StringList && !value.toStringList().isEmpty()) {
return value.toStringList().at(0).trimmed();
}
return value.toString().trimmed(); return value.toString().trimmed();
case Shortcut: case Shortcut:
return value.toString(); return value.toString();

@ -14,6 +14,7 @@
#include <QIcon> #include <QIcon>
#include <QQmlEngine> #include <QQmlEngine>
#include <QtDBus> #include <QtDBus>
#include <QX11Info>
#include <KColorSchemeManager> #include <KColorSchemeManager>
#include <KConfig> #include <KConfig>
@ -433,14 +434,26 @@ void RulesModel::populateRuleList()
i18n("Maximized vertically"), i18n("Size & Position"), i18n("Maximized vertically"), i18n("Size & Position"),
QIcon::fromTheme("resizerow"))); QIcon::fromTheme("resizerow")));
auto desktop = addRule(new RuleItem(QLatin1String("desktop"), RuleItem *desktops;
RulePolicy::SetRule, RuleItem::Option, if (QX11Info::isPlatformX11()) {
i18n("Virtual Desktop"), i18n("Size & Position"), // Single selection of Virtual Desktop on X11
QIcon::fromTheme("virtual-desktops"))); desktops = new RuleItem(QLatin1String("desktops"),
desktop->setOptionsData(virtualDesktopsModelData()); RulePolicy::SetRule, RuleItem::Option,
i18n("Virtual Desktop"), i18n("Size & Position"),
QIcon::fromTheme("virtual-desktops"));
} else {
// Multiple selection on Wayland
desktops = new RuleItem(QLatin1String("desktops"),
RulePolicy::SetRule, RuleItem::OptionList,
i18n("Virtual Desktops"), i18n("Size & Position"),
QIcon::fromTheme("virtual-desktops"));
}
addRule(desktops);
desktops->setOptionsData(virtualDesktopsModelData());
connect(this, &RulesModel::virtualDesktopsUpdated, connect(this, &RulesModel::virtualDesktopsUpdated,
this, [this] { m_rules["desktop"]->setOptionsData(virtualDesktopsModelData()); }); this, [this] { m_rules["desktops"]->setOptionsData(virtualDesktopsModelData()); });
updateVirtualDesktops(); updateVirtualDesktops();
#ifdef KWIN_BUILD_ACTIVITIES #ifdef KWIN_BUILD_ACTIVITIES
@ -645,7 +658,6 @@ const QHash<QString, QString> RulesModel::x11PropertyHash()
{ "caption", "title" }, { "caption", "title" },
{ "role", "windowrole" }, { "role", "windowrole" },
{ "clientMachine", "clientmachine" }, { "clientMachine", "clientmachine" },
{ "x11DesktopNumber", "desktop" },
{ "maximizeHorizontal", "maximizehoriz" }, { "maximizeHorizontal", "maximizehoriz" },
{ "maximizeVertical", "maximizevert" }, { "maximizeVertical", "maximizevert" },
{ "minimized", "minimize" }, { "minimized", "minimize" },
@ -687,6 +699,18 @@ void RulesModel::setSuggestedProperties(const QVariantMap &info)
m_rules["wmclass"]->setSuggestedValue(wmsimpleclass); m_rules["wmclass"]->setSuggestedValue(wmsimpleclass);
m_rules["wmclasshelper"]->setSuggestedValue(wmcompleteclass); m_rules["wmclasshelper"]->setSuggestedValue(wmcompleteclass);
//TODO: Make the DBus method `queryWindowInfo` return the list of desktop IDs and use them directly
if (info.value("x11DesktopNumber").toInt() == NET::OnAllDesktops) {
m_rules["desktops"]->setSuggestedValue(QStringList());
} else {
for (const auto vd : qAsConst(m_virtualDesktops)) {
if (info.value("x11DesktopNumber").toUInt() == vd.position + 1) {
m_rules["desktops"]->setSuggestedValue(QStringList{ vd.id });
break;
}
}
}
#ifdef KWIN_BUILD_ACTIVITIES #ifdef KWIN_BUILD_ACTIVITIES
const QStringList activities = info.value("activities").toStringList(); const QStringList activities = info.value("activities").toStringList();
m_rules["activity"]->setSuggestedValue(activities.isEmpty() ? QStringList{ Activities::nullUuid() } m_rules["activity"]->setSuggestedValue(activities.isEmpty() ? QStringList{ Activities::nullUuid() }
@ -729,15 +753,14 @@ QList<OptionsModel::Data> RulesModel::windowTypesModelData() const
QList<OptionsModel::Data> RulesModel::virtualDesktopsModelData() const QList<OptionsModel::Data> RulesModel::virtualDesktopsModelData() const
{ {
QList<OptionsModel::Data> modelData; QList<OptionsModel::Data> modelData = { {QString(), i18n("All Desktops"), QIcon::fromTheme("window-pin")} };
for (const DBusDesktopDataStruct &desktop : m_virtualDesktops) { for (const DBusDesktopDataStruct &desktop : m_virtualDesktops) {
modelData << OptionsModel::Data{ modelData << OptionsModel::Data{
desktop.position + 1, // "desktop" setting uses the desktop position (int) starting at 1 desktop.id,
QString::number(desktop.position + 1).rightJustified(2) + QStringLiteral(": ") + desktop.name, QString::number(desktop.position + 1).rightJustified(2) + QStringLiteral(": ") + desktop.name,
QIcon::fromTheme("virtual-desktops") QIcon::fromTheme("virtual-desktops")
}; };
} }
modelData << OptionsModel::Data{ NET::OnAllDesktops, i18n("All Desktops"), QIcon::fromTheme("window-pin") };
return modelData; return modelData;
} }

@ -50,7 +50,7 @@ Rules::Rules()
, opacityactiverule(UnusedForceRule) , opacityactiverule(UnusedForceRule)
, opacityinactiverule(UnusedForceRule) , opacityinactiverule(UnusedForceRule)
, ignoregeometryrule(UnusedSetRule) , ignoregeometryrule(UnusedSetRule)
, desktoprule(UnusedSetRule) , desktopsrule(UnusedSetRule)
, screenrule(UnusedSetRule) , screenrule(UnusedSetRule)
, activityrule(UnusedSetRule) , activityrule(UnusedSetRule)
, typerule(UnusedForceRule) , typerule(UnusedForceRule)
@ -142,7 +142,7 @@ void Rules::readFromSettings(const RuleSettings *settings)
READ_FORCE_RULE(opacityactive,); READ_FORCE_RULE(opacityactive,);
READ_FORCE_RULE(opacityinactive,); READ_FORCE_RULE(opacityinactive,);
READ_SET_RULE(ignoregeometry); READ_SET_RULE(ignoregeometry);
READ_SET_RULE(desktop); READ_SET_RULE(desktops);
READ_SET_RULE(screen); READ_SET_RULE(screen);
READ_SET_RULE(activity); READ_SET_RULE(activity);
READ_FORCE_RULE(type, static_cast<NET::WindowType>); READ_FORCE_RULE(type, static_cast<NET::WindowType>);
@ -222,7 +222,7 @@ void Rules::write(RuleSettings *settings) const
WRITE_FORCE_RULE(opacityactive, Opacityactive,); WRITE_FORCE_RULE(opacityactive, Opacityactive,);
WRITE_FORCE_RULE(opacityinactive, Opacityinactive,); WRITE_FORCE_RULE(opacityinactive, Opacityinactive,);
WRITE_SET_RULE(ignoregeometry, Ignoregeometry,); WRITE_SET_RULE(ignoregeometry, Ignoregeometry,);
WRITE_SET_RULE(desktop, Desktop,); WRITE_SET_RULE(desktops, Desktops,);
WRITE_SET_RULE(screen, Screen,); WRITE_SET_RULE(screen, Screen,);
WRITE_SET_RULE(activity, Activity,); WRITE_SET_RULE(activity, Activity,);
WRITE_FORCE_RULE(type, Type,); WRITE_FORCE_RULE(type, Type,);
@ -274,7 +274,7 @@ bool Rules::isEmpty() const
&& opacityactiverule == UnusedForceRule && opacityactiverule == UnusedForceRule
&& opacityinactiverule == UnusedForceRule && opacityinactiverule == UnusedForceRule
&& ignoregeometryrule == UnusedSetRule && ignoregeometryrule == UnusedSetRule
&& desktoprule == UnusedSetRule && desktopsrule == UnusedSetRule
&& screenrule == UnusedSetRule && screenrule == UnusedSetRule
&& activityrule == UnusedSetRule && activityrule == UnusedSetRule
&& typerule == UnusedForceRule && typerule == UnusedForceRule
@ -445,9 +445,9 @@ bool Rules::update(AbstractClient* c, int selection)
size = new_size; size = new_size;
} }
} }
if NOW_REMEMBER(Desktop, desktop) { if NOW_REMEMBER(Desktops, desktops) {
updated = updated || desktop != c->desktop(); updated = updated || desktops != c->desktopIds();
desktop = c->desktop(); desktops = c->desktopIds();
} }
if NOW_REMEMBER(Screen, screen) { if NOW_REMEMBER(Screen, screen) {
updated = updated || screen != c->screen(); updated = updated || screen != c->screen();
@ -568,20 +568,17 @@ APPLY_RULE(screen, Screen, int)
APPLY_RULE(activity, Activity, QStringList) APPLY_RULE(activity, Activity, QStringList)
APPLY_FORCE_RULE(type, Type, NET::WindowType) APPLY_FORCE_RULE(type, Type, NET::WindowType)
bool Rules::applyDesktops(QVector<VirtualDesktop *> &desktops, bool init) const bool Rules::applyDesktops(QVector<VirtualDesktop *> &vds, bool init) const
{ {
if (checkSetRule(desktoprule, init)) { if (checkSetRule(desktopsrule, init)) {
if (desktop == NET::OnAllDesktops) { vds.clear();
desktops = {}; for (auto id : desktops) {
} else { if (auto vd = VirtualDesktopManager::self()->desktopForId(id)) {
if (auto vd = VirtualDesktopManager::self()->desktopForX11Id(desktop)) { vds << vd;
desktops = {vd};
} else {
desktops = {VirtualDesktopManager::self()->currentDesktop()};
} }
} }
} }
return checkSetStop(desktoprule); return checkSetStop(desktopsrule);
} }
bool Rules::applyMaximizeHoriz(MaximizeMode& mode, bool init) const bool Rules::applyMaximizeHoriz(MaximizeMode& mode, bool init) const
@ -678,7 +675,7 @@ bool Rules::discardUsed(bool withdrawn)
DISCARD_USED_FORCE_RULE(opacityactive); DISCARD_USED_FORCE_RULE(opacityactive);
DISCARD_USED_FORCE_RULE(opacityinactive); DISCARD_USED_FORCE_RULE(opacityinactive);
DISCARD_USED_SET_RULE(ignoregeometry); DISCARD_USED_SET_RULE(ignoregeometry);
DISCARD_USED_SET_RULE(desktop); DISCARD_USED_SET_RULE(desktops);
DISCARD_USED_SET_RULE(screen); DISCARD_USED_SET_RULE(screen);
DISCARD_USED_SET_RULE(activity); DISCARD_USED_SET_RULE(activity);
DISCARD_USED_FORCE_RULE(type); DISCARD_USED_FORCE_RULE(type);

@ -95,7 +95,7 @@ public:
explicit Rules(const RuleSettings*); explicit Rules(const RuleSettings*);
Rules(const QString&, bool temporary); Rules(const QString&, bool temporary);
enum Type { enum Type {
Position = 1<<0, Size = 1<<1, Desktop = 1<<2, Position = 1<<0, Size = 1<<1, Desktops = 1<<2,
MaximizeVert = 1<<3, MaximizeHoriz = 1<<4, Minimize = 1<<5, MaximizeVert = 1<<3, MaximizeHoriz = 1<<4, Minimize = 1<<5,
Shade = 1<<6, SkipTaskbar = 1<<7, SkipPager = 1<<8, Shade = 1<<6, SkipTaskbar = 1<<7, SkipPager = 1<<8,
SkipSwitcher = 1<<9, Above = 1<<10, Below = 1<<11, Fullscreen = 1<<12, SkipSwitcher = 1<<9, Above = 1<<10, Below = 1<<11, Fullscreen = 1<<12,
@ -182,6 +182,9 @@ private:
bool matchRole(const QByteArray& match_role) const; bool matchRole(const QByteArray& match_role) const;
bool matchTitle(const QString& match_title) const; bool matchTitle(const QString& match_title) const;
bool matchClientMachine(const QByteArray& match_machine, bool local) const; bool matchClientMachine(const QByteArray& match_machine, bool local) const;
#ifdef KCMRULES
private:
#endif
void readFromSettings(const RuleSettings *settings); void readFromSettings(const RuleSettings *settings);
static ForceRule convertForceRule(int v); static ForceRule convertForceRule(int v);
static QString getDecoColor(const QString &themeName); static QString getDecoColor(const QString &themeName);
@ -219,8 +222,8 @@ private:
ForceRule opacityinactiverule; ForceRule opacityinactiverule;
bool ignoregeometry; bool ignoregeometry;
SetRule ignoregeometryrule; SetRule ignoregeometryrule;
int desktop; QStringList desktops;
SetRule desktoprule; SetRule desktopsrule;
int screen; int screen;
SetRule screenrule; SetRule screenrule;
QStringList activity; QStringList activity;

@ -147,12 +147,12 @@
<default code="true">Rules::UnusedSetRule</default> <default code="true">Rules::UnusedSetRule</default>
</entry> </entry>
<entry name="desktop" type="Int"> <entry name="desktops" type="StringList">
<label>Desktop number</label> <label>List of Desktop Ids</label>
<default>0</default> <default>{}</default>
</entry> </entry>
<entry name="desktoprule" type="Int"> <entry name="desktopsrule" type="Int">
<label>Desktop number rule type</label> <label>Desktop Ids rule type</label>
<min code="true">Rules::UnusedSetRule</min> <min code="true">Rules::UnusedSetRule</min>
<max code="true">static_cast&lt;Rules::SetRule&gt;(Rules::ForceTemporarily)</max> <max code="true">static_cast&lt;Rules::SetRule&gt;(Rules::ForceTemporarily)</max>
<default code="true">Rules::UnusedSetRule</default> <default code="true">Rules::UnusedSetRule</default>

Loading…
Cancel
Save