Make WindowRules::checkDesktop take a list of desktops

This ports relevant apis in WindowRules to the VirtualDesktop class.

If the client has no desktop rule, the desktop list that has been passed
to the checkDesktops() function will be returned.

If the client has a desktop window rule, the checkDesktop() function
will return a list with a single VirtualDesktop object or none if the
window is forced to be on all virtual desktops.
This commit is contained in:
Vlad Zahorodnii 2021-08-13 10:48:52 +03:00
parent 8e8fc55b0b
commit 7f04d730e6
6 changed files with 85 additions and 40 deletions

View file

@ -424,7 +424,6 @@ void AbstractClient::setDesktop(int desktop)
const int numberOfDesktops = VirtualDesktopManager::self()->count();
if (desktop != NET::OnAllDesktops) // Do range check
desktop = qMax(1, qMin(numberOfDesktops, desktop));
desktop = qMin(numberOfDesktops, rules()->checkDesktop(desktop));
QVector<VirtualDesktop *> desktops;
if (desktop != NET::OnAllDesktops) {
@ -440,6 +439,7 @@ void AbstractClient::setDesktops(QVector<VirtualDesktop*> desktops)
desktops = QVector<VirtualDesktop*>({desktops.last()});
}
desktops = rules()->checkDesktops(desktops);
if (desktops == m_desktops) {
return;
}

View file

@ -22,6 +22,7 @@
#include "x11client.h"
#include "client_machine.h"
#include "screens.h"
#include "virtualdesktops.h"
#include "workspace.h"
#endif
@ -561,11 +562,26 @@ APPLY_FORCE_RULE(opacityactive, OpacityActive, int)
APPLY_FORCE_RULE(opacityinactive, OpacityInactive, int)
APPLY_RULE(ignoregeometry, IgnoreGeometry, bool)
APPLY_RULE(desktop, Desktop, int)
APPLY_RULE(screen, Screen, int)
APPLY_RULE(activity, Activity, QStringList)
APPLY_FORCE_RULE(type, Type, NET::WindowType)
bool Rules::applyDesktops(QVector<VirtualDesktop *> &desktops, bool init) const
{
if (checkSetRule(desktoprule, init)) {
if (desktop == NET::OnAllDesktops) {
desktops = {};
} else {
if (auto vd = VirtualDesktopManager::self()->desktopForX11Id(desktop)) {
desktops = {vd};
} else {
desktops = {VirtualDesktopManager::self()->currentDesktop()};
}
}
}
return checkSetStop(desktoprule);
}
bool Rules::applyMaximizeHoriz(MaximizeMode& mode, bool init) const
{
if (checkSetRule(maximizehorizrule, init))
@ -776,7 +792,7 @@ CHECK_FORCE_RULE(OpacityActive, int)
CHECK_FORCE_RULE(OpacityInactive, int)
CHECK_RULE(IgnoreGeometry, bool)
CHECK_RULE(Desktop, int)
CHECK_RULE(Desktops, QVector<VirtualDesktop *>)
CHECK_RULE(Activity, QStringList)
CHECK_FORCE_RULE(Type, NET::WindowType)
CHECK_RULE(MaximizeVert, MaximizeMode)
@ -852,7 +868,7 @@ void AbstractClient::applyWindowRules()
moveResize(geom);
// MinSize, MaxSize handled by Geometry
// IgnoreGeometry
setDesktop(desktop());
setDesktops(desktops());
workspace()->sendClientToScreen(this, screen());
setOnActivities(activities());
// Type

View file

@ -29,6 +29,7 @@ namespace KWin
class AbstractClient;
class Rules;
class RuleSettings;
class VirtualDesktop;
#ifndef KCMRULES // only for kwin core
@ -51,7 +52,7 @@ public:
int checkOpacityActive(int s) const;
int checkOpacityInactive(int s) const;
bool checkIgnoreGeometry(bool ignore, bool init = false) const;
int checkDesktop(int desktop, bool init = false) const;
QVector<VirtualDesktop *> checkDesktops(QVector<VirtualDesktop *> desktops, bool init = false) const;
int checkScreen(int screen, bool init = false) const;
QStringList checkActivity(QStringList activity, bool init = false) const;
NET::WindowType checkType(NET::WindowType type) const;
@ -145,7 +146,7 @@ public:
bool applyOpacityActive(int& s) const;
bool applyOpacityInactive(int& s) const;
bool applyIgnoreGeometry(bool& ignore, bool init) const;
bool applyDesktop(int& desktop, bool init) const;
bool applyDesktops(QVector<VirtualDesktop *> &desktops, bool init) const;
bool applyScreen(int& desktop, bool init) const;
bool applyActivity(QStringList& activity, bool init) const;
bool applyType(NET::WindowType& type) const;

View file

@ -398,41 +398,46 @@ void Edge::switchDesktop(const QPoint &cursorPos)
{
QPoint pos(cursorPos);
VirtualDesktopManager *vds = VirtualDesktopManager::self();
const uint oldDesktop = vds->current();
uint desktop = oldDesktop;
VirtualDesktop *oldDesktop = vds->currentDesktop();
VirtualDesktop *desktop = oldDesktop;
const int OFFSET = 2;
if (isLeft()) {
const uint interimDesktop = desktop;
const VirtualDesktop *interimDesktop = desktop;
desktop = vds->toLeft(desktop, vds->isNavigationWrappingAround());
if (desktop != interimDesktop)
if (desktop != interimDesktop) {
pos.setX(screens()->size().width() - 1 - OFFSET);
}
} else if (isRight()) {
const uint interimDesktop = desktop;
const VirtualDesktop *interimDesktop = desktop;
desktop = vds->toRight(desktop, vds->isNavigationWrappingAround());
if (desktop != interimDesktop)
if (desktop != interimDesktop) {
pos.setX(OFFSET);
}
}
if (isTop()) {
const uint interimDesktop = desktop;
const VirtualDesktop *interimDesktop = desktop;
desktop = vds->above(desktop, vds->isNavigationWrappingAround());
if (desktop != interimDesktop)
if (desktop != interimDesktop) {
pos.setY(screens()->size().height() - 1 - OFFSET);
}
} else if (isBottom()) {
const uint interimDesktop = desktop;
const VirtualDesktop *interimDesktop = desktop;
desktop = vds->below(desktop, vds->isNavigationWrappingAround());
if (desktop != interimDesktop)
if (desktop != interimDesktop) {
pos.setY(OFFSET);
}
}
#ifndef KWIN_UNIT_TEST
if (AbstractClient *c = Workspace::self()->moveResizeClient()) {
if (c->rules()->checkDesktop(desktop) != int(desktop)) {
const QVector<VirtualDesktop *> desktops{desktop};
if (c->rules()->checkDesktops(desktops) != desktops) {
// user attempts to move a client to another desktop where it is ruleforced to not be
return;
}
}
#endif
vds->setCurrent(desktop);
if (vds->current() != oldDesktop) {
if (vds->currentDesktop() != oldDesktop) {
m_pushBackBlocked = true;
Cursors::self()->mouse()->setPos(pos);
QSharedPointer<QMetaObject::Connection> me(new QMetaObject::Connection);

View file

@ -499,11 +499,16 @@ bool X11Client::manage(xcb_window_t w, bool isMapped)
readActivities(activitiesCookie);
// Initial desktop placement
int desk = 0;
std::optional<QVector<VirtualDesktop *>> initialDesktops;
if (session) {
desk = session->desktop;
if (session->onAllDesktops)
desk = NET::OnAllDesktops;
if (session->onAllDesktops) {
initialDesktops = QVector<VirtualDesktop *>{};
} else {
VirtualDesktop *desktop = VirtualDesktopManager::self()->desktopForX11Id(session->desktop);
if (desktop) {
initialDesktops = QVector<VirtualDesktop *>{desktop};
}
}
setOnActivities(session->activities);
} else {
// If this window is transient, ensure that it is opened on the
@ -528,20 +533,34 @@ bool X11Client::manage(xcb_window_t w, bool isMapped)
if ((*it)->isOnAllDesktops())
on_all = true;
}
if (on_all)
desk = NET::OnAllDesktops;
else if (on_current)
desk = VirtualDesktopManager::self()->current();
else if (maincl != nullptr)
desk = maincl->desktop();
if (on_all) {
initialDesktops = QVector<VirtualDesktop *>{};
} else if (on_current) {
initialDesktops = QVector<VirtualDesktop *>{VirtualDesktopManager::self()->currentDesktop()};
} else if (maincl) {
initialDesktops = maincl->desktops();
}
if (maincl)
setOnActivities(maincl->activities());
} else { // a transient shall appear on its leader and not drag that around
if (info->desktop())
desk = info->desktop(); // Window had the initial desktop property, force it
if (desktop() == 0 && asn_valid && asn_data.desktop() != 0)
desk = asn_data.desktop();
int desktopId = 0;
if (info->desktop()) {
desktopId = info->desktop(); // Window had the initial desktop property, force it
}
if (desktop() == 0 && asn_valid && asn_data.desktop() != 0) {
desktopId = asn_data.desktop();
}
if (desktopId) {
if (desktopId == NET::OnAllDesktops) {
initialDesktops = QVector<VirtualDesktop *>{};
} else {
VirtualDesktop *desktop = VirtualDesktopManager::self()->desktopForX11Id(desktopId);
if (desktop) {
initialDesktops = QVector<VirtualDesktop *>{desktop};
}
}
}
}
#ifdef KWIN_BUILD_ACTIVITIES
if (Activities::self() && !isMapped && !skipTaskbar() && isNormalWindow() && !activitiesDefined) {
@ -557,13 +576,17 @@ bool X11Client::manage(xcb_window_t w, bool isMapped)
#endif
}
if (desk == 0) // Assume window wants to be visible on the current desktop
desk = isDesktop() ? static_cast<int>(NET::OnAllDesktops) : VirtualDesktopManager::self()->current();
desk = rules()->checkDesktop(desk, !isMapped);
if (desk != NET::OnAllDesktops) // Do range check
desk = qBound(1, desk, static_cast<int>(VirtualDesktopManager::self()->count()));
setDesktop(desk);
info->setDesktop(desk);
// If initialDesktops has no value, it means that the client doesn't prefer any
// desktop so place it on the current virtual desktop.
if (!initialDesktops.has_value()) {
if (isDesktop()) {
initialDesktops = QVector<VirtualDesktop *>{};
} else {
initialDesktops = QVector<VirtualDesktop *>{VirtualDesktopManager::self()->currentDesktop()};
}
}
setDesktops(rules()->checkDesktops(*initialDesktops, !isMapped));
info->setDesktop(desktop());
workspace()->updateOnAllDesktopsOfTransients(this); // SELI TODO
//onAllDesktopsChange(); // Decoration doesn't exist here yet

View file

@ -1205,7 +1205,7 @@ void XdgToplevelClient::initialize()
maximize(rules()->checkMaximize(initialMaximizeMode(), true));
setFullScreen(rules()->checkFullScreen(initialFullScreenMode(), true), false);
setOnActivities(rules()->checkActivity(activities(), true));
setDesktop(rules()->checkDesktop(desktop(), true));
setDesktops(rules()->checkDesktops(desktops(), true));
setDesktopFileName(rules()->checkDesktopFile(desktopFileName(), true).toUtf8());
if (rules()->checkMinimize(isMinimized(), true)) {
minimize(true); // No animation.