Port Workspace::clientArea() to VirtualDesktop

This makes Workspace APIs that take virtual desktops more consistent.
icc-effect-5.26.4
Vlad Zahorodnii 2021-08-21 20:46:51 +03:00
parent 5b3c87f105
commit fddbd57d09
8 changed files with 183 additions and 194 deletions

View File

@ -13,6 +13,7 @@
#include "deleted.h"
#include "screenedge.h"
#include "screens.h"
#include "virtualdesktops.h"
#include "wayland_server.h"
#include "workspace.h"
#include <kwineffects.h>
@ -132,6 +133,9 @@ void StrutsTest::testWaylandStruts()
{
// this test verifies that struts on Wayland panels are handled correctly
using namespace KWayland::Client;
VirtualDesktop *desktop = VirtualDesktopManager::self()->currentDesktop();
// no, struts yet
QVERIFY(waylandServer()->clients().isEmpty());
// first screen
@ -151,7 +155,7 @@ void StrutsTest::testWaylandStruts()
// combined
QCOMPARE(workspace()->clientArea(WorkArea, 0, 1), QRect(0, 0, 2560, 1024));
QCOMPARE(workspace()->clientArea(FullArea, 0, 1), QRect(0, 0, 2560, 1024));
QCOMPARE(workspace()->restrictedMoveArea(-1), QRegion());
QCOMPARE(workspace()->restrictedMoveArea(desktop), QRegion());
QFETCH(QVector<QRect>, windowGeometries);
// create the panels
@ -201,7 +205,7 @@ void StrutsTest::testWaylandStruts()
QTEST(workspace()->clientArea(PlacementArea, 1, 1), "screen1Maximized");
QTEST(workspace()->clientArea(MaximizeArea, 1, 1), "screen1Maximized");
QTEST(workspace()->clientArea(WorkArea, 0, 1), "workArea");
QTEST(workspace()->restrictedMoveArea(-1), "restrictedMoveArea");
QTEST(workspace()->restrictedMoveArea(desktop), "restrictedMoveArea");
// delete all surfaces
for (auto it = clients.begin(); it != clients.end(); it++) {
@ -210,7 +214,7 @@ void StrutsTest::testWaylandStruts()
delete it.key();
QVERIFY(destroyedSpy.wait());
}
QCOMPARE(workspace()->restrictedMoveArea(-1), QRegion());
QCOMPARE(workspace()->restrictedMoveArea(desktop), QRegion());
}
void StrutsTest::testMoveWaylandPanel()
@ -535,6 +539,8 @@ void StrutsTest::testX11Struts()
{
// this test verifies that struts are applied correctly for X11 windows
VirtualDesktop *desktop = VirtualDesktopManager::self()->currentDesktop();
// no, struts yet
// first screen
QCOMPARE(workspace()->clientArea(PlacementArea, 0, 1), QRect(0, 0, 1280, 1024));
@ -553,7 +559,7 @@ void StrutsTest::testX11Struts()
// combined
QCOMPARE(workspace()->clientArea(WorkArea, 0, 1), QRect(0, 0, 2560, 1024));
QCOMPARE(workspace()->clientArea(FullArea, 0, 1), QRect(0, 0, 2560, 1024));
QCOMPARE(workspace()->restrictedMoveArea(-1), QRegion());
QCOMPARE(workspace()->restrictedMoveArea(desktop), QRegion());
// create an xcb window
QScopedPointer<xcb_connection_t, XcbConnectionDeleter> c(xcb_connect(nullptr, nullptr));
@ -636,7 +642,7 @@ void StrutsTest::testX11Struts()
QTEST(workspace()->clientArea(PlacementArea, 1, 1), "screen1Maximized");
QTEST(workspace()->clientArea(MaximizeArea, 1, 1), "screen1Maximized");
QTEST(workspace()->clientArea(WorkArea, 0, 1), "workArea");
QTEST(workspace()->restrictedMoveArea(-1), "restrictedMoveArea");
QTEST(workspace()->restrictedMoveArea(desktop), "restrictedMoveArea");
// and destroy the window again
xcb_unmap_window(c.data(), w);
@ -665,7 +671,7 @@ void StrutsTest::testX11Struts()
// combined
QCOMPARE(workspace()->clientArea(WorkArea, 0, 1), QRect(0, 0, 2560, 1024));
QCOMPARE(workspace()->clientArea(FullArea, 0, 1), QRect(0, 0, 2560, 1024));
QCOMPARE(workspace()->restrictedMoveArea(-1), QRegion());
QCOMPARE(workspace()->restrictedMoveArea(desktop), QRegion());
}
void StrutsTest::test363804()
@ -863,6 +869,8 @@ void StrutsTest::testWindowMoveWithPanelBetweenScreens()
// when moving a window with decorations in a restricted way it should pass from one screen
// to the other even if there is a panel in between.
VirtualDesktop *desktop = VirtualDesktopManager::self()->currentDesktop();
// left screen must be smaller than right screen
const QVector<QRect> geometries{QRect(0, 282, 1366, 768), QRect(1366, 0, 1680, 1050)};
QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs",
@ -926,7 +934,7 @@ void StrutsTest::testWindowMoveWithPanelBetweenScreens()
QCOMPARE(workspace()->clientArea(PlacementArea, 1, 1), QRect(1390, 0, 1656, 1050));
QCOMPARE(workspace()->clientArea(MaximizeArea, 1, 1), QRect(1390, 0, 1656, 1050));
QCOMPARE(workspace()->clientArea(WorkArea, 0, 1), QRect(0, 0, 3046, 1050));
QCOMPARE(workspace()->restrictedMoveArea(-1), QRegion(1366, 0, 24, 1050));
QCOMPARE(workspace()->restrictedMoveArea(desktop), QRegion(1366, 0, 24, 1050));
// create another window and try to move it

View File

@ -19,6 +19,7 @@
#include "effects.h"
#include "focuschain.h"
#include "outline.h"
#include "platform.h"
#include "screens.h"
#ifdef KWIN_BUILD_TABBOX
#include "tabbox.h"
@ -1222,7 +1223,7 @@ void AbstractClient::handleInteractiveMoveResize(int x, int y, int x_root, int y
// the other directions. If not visible enough, move the window to the closest valid
// point. We bruteforce this by slowly moving the window back to its previous position
QRegion availableArea(workspace()->clientArea(FullArea, this, -1)); // On the screen
availableArea -= workspace()->restrictedMoveArea(desktop()); // Strut areas
availableArea -= workspace()->restrictedMoveArea(VirtualDesktopManager::self()->currentDesktop());
bool transposed = false;
int requiredPixels;
QRect bTitleRect = titleBarRect(transposed, requiredPixels);
@ -1348,7 +1349,7 @@ void AbstractClient::handleInteractiveMoveResize(int x, int y, int x_root, int y
setMoveResizeGeometry(moveResizeGeom);
if (!isUnrestrictedInteractiveMoveResize()) {
const QRegion strut = workspace()->restrictedMoveArea(desktop()); // Strut areas
const QRegion strut = workspace()->restrictedMoveArea(VirtualDesktopManager::self()->currentDesktop());
QRegion availableArea(workspace()->clientArea(FullArea, this, -1)); // On the screen
availableArea -= strut; // Strut areas
bool transposed = false;
@ -3321,7 +3322,7 @@ void AbstractClient::updateGeometryRestoresForFullscreen(int screen)
setGeometryRestore(newGeometryRestore);
}
void AbstractClient::checkWorkspacePosition(QRect oldGeometry, int oldDesktop, QRect oldClientGeometry)
void AbstractClient::checkWorkspacePosition(QRect oldGeometry, QRect oldClientGeometry, const VirtualDesktop *oldDesktop)
{
if (isDock() || isDesktop() || !isPlaceable()) {
return;
@ -3330,8 +3331,6 @@ void AbstractClient::checkWorkspacePosition(QRect oldGeometry, int oldDesktop, Q
const int border[4] = { borderLeft(), borderTop(), borderRight(), borderBottom() };
if( !oldGeometry.isValid())
oldGeometry = moveResizeGeometry();
if( oldDesktop == -2 )
oldDesktop = desktop();
if (!oldClientGeometry.isValid())
oldClientGeometry = oldGeometry.adjusted(border[Left], border[Top], -border[Right], -border[Bottom]);
if (isFullScreen()) {
@ -3362,6 +3361,11 @@ void AbstractClient::checkWorkspacePosition(QRect oldGeometry, int oldDesktop, Q
if (!workspace() || workspace()->initializing())
return;
VirtualDesktop *desktop = !isOnCurrentDesktop() ? desktops().constLast() : VirtualDesktopManager::self()->currentDesktop();
if (!oldDesktop) {
oldDesktop = desktop;
}
// If the window was touching an edge before but not now move it so it is again.
// Old and new maximums have different starting values so windows on the screen
// edge will move when a new strut is placed on the edge.
@ -3378,7 +3382,8 @@ void AbstractClient::checkWorkspacePosition(QRect oldGeometry, int oldDesktop, Q
}
}
} else {
oldScreenArea = workspace()->clientArea(ScreenArea, oldGeometry.center(), oldDesktop);
const int oldScreen = screens()->number(oldGeometry.center());
oldScreenArea = workspace()->clientArea(ScreenArea, kwinApp()->platform()->findOutput(oldScreen), oldDesktop);
}
const QRect oldGeomTall = QRect(oldGeometry.x(), oldScreenArea.y(), oldGeometry.width(), oldScreenArea.height()); // Full screen height
const QRect oldGeomWide = QRect(oldScreenArea.x(), oldGeometry.y(), oldScreenArea.width(), oldGeometry.height()); // Full screen width
@ -3425,22 +3430,22 @@ void AbstractClient::checkWorkspacePosition(QRect oldGeometry, int oldDesktop, Q
}
// These 4 compute new bounds
for (const QRect &r : workspace()->restrictedMoveArea(desktop(), StrutAreaTop)) {
for (const QRect &r : workspace()->restrictedMoveArea(desktop, StrutAreaTop)) {
QRect rect = r & newGeomTall;
if (!rect.isEmpty())
topMax = qMax(topMax, rect.y() + rect.height());
}
for (const QRect &r : workspace()->restrictedMoveArea(desktop(), StrutAreaRight)) {
for (const QRect &r : workspace()->restrictedMoveArea(desktop, StrutAreaRight)) {
QRect rect = r & newGeomWide;
if (!rect.isEmpty())
rightMax = qMin(rightMax, rect.x());
}
for (const QRect &r : workspace()->restrictedMoveArea(desktop(), StrutAreaBottom)) {
for (const QRect &r : workspace()->restrictedMoveArea(desktop, StrutAreaBottom)) {
QRect rect = r & newGeomTall;
if (!rect.isEmpty())
bottomMax = qMin(bottomMax, rect.y());
}
for (const QRect &r : workspace()->restrictedMoveArea(desktop(), StrutAreaLeft)) {
for (const QRect &r : workspace()->restrictedMoveArea(desktop, StrutAreaLeft)) {
QRect rect = r & newGeomWide;
if (!rect.isEmpty())
leftMax = qMax(leftMax, rect.x() + rect.width());

View File

@ -579,7 +579,7 @@ public:
* The default implementation returns @c false.
*/
virtual bool dockWantsInput() const;
void checkWorkspacePosition(QRect oldGeometry = QRect(), int oldDesktop = -2, QRect oldClientGeometry = QRect());
void checkWorkspacePosition(QRect oldGeometry = QRect(), QRect oldClientGeometry = QRect(), const VirtualDesktop *oldDesktop = nullptr);
virtual xcb_timestamp_t userTime() const;
virtual void updateWindowRules(Rules::Types selection);

View File

@ -316,7 +316,7 @@ void InternalClient::updateDecoration(bool check_workspace_pos, bool force)
updateShadow();
if (check_workspace_pos) {
checkWorkspacePosition(oldFrameGeometry, -2, oldClientGeometry);
checkWorkspacePosition(oldFrameGeometry, oldClientGeometry);
}
}

View File

@ -209,7 +209,6 @@ void Workspace::init()
KSharedConfigPtr config = kwinApp()->config();
Screens *screens = Screens::self();
// get screen support
connect(screens, &Screens::changed, this, &Workspace::desktopResized);
screens->setConfig(config);
screens->reconfigure();
connect(options, &Options::configChanged, screens, &Screens::reconfigure);
@ -223,30 +222,25 @@ void Workspace::init()
FocusChain *focusChain = FocusChain::create(this);
connect(this, &Workspace::clientRemoved, focusChain, &FocusChain::remove);
connect(this, &Workspace::clientActivated, focusChain, &FocusChain::setActiveClient);
connect(VirtualDesktopManager::self(), &VirtualDesktopManager::desktopCreated, focusChain, &FocusChain::addDesktop);
connect(VirtualDesktopManager::self(), &VirtualDesktopManager::desktopRemoved, focusChain, &FocusChain::removeDesktop);
connect(VirtualDesktopManager::self(), &VirtualDesktopManager::currentChanged, focusChain, [focusChain]() {
focusChain->setCurrentDesktop(VirtualDesktopManager::self()->currentDesktop());
});
connect(options, &Options::separateScreenFocusChanged, focusChain, &FocusChain::setSeparateScreenFocus);
focusChain->setSeparateScreenFocus(options->isSeparateScreenFocus());
Platform *platform = kwinApp()->platform();
connect(platform, &Platform::outputEnabled, this, &Workspace::slotOutputEnabled);
connect(platform, &Platform::outputDisabled, this, &Workspace::slotOutputDisabled);
const QVector<AbstractOutput *> outputs = platform->enabledOutputs();
for (AbstractOutput *output : outputs) {
slotOutputEnabled(output);
}
// create VirtualDesktopManager and perform dependency injection
VirtualDesktopManager *vds = VirtualDesktopManager::self();
connect(vds, &VirtualDesktopManager::desktopRemoved, this, [this](VirtualDesktop *desktop) {
for (auto it = m_allClients.constBegin(); it != m_allClients.constEnd(); ++it) {
if (!(*it)->desktops().contains(desktop)) {
continue;
}
if ((*it)->desktops().count() > 1) {
(*it)->leaveDesktop(desktop);
} else {
sendClientToDesktop(*it, qMin(desktop->x11DesktopNumber(), VirtualDesktopManager::self()->count()), true);
}
}
});
connect(vds, &VirtualDesktopManager::countChanged, this, &Workspace::slotDesktopCountChanged);
connect(vds, &VirtualDesktopManager::desktopCreated, this, &Workspace::slotDesktopAdded);
connect(vds, &VirtualDesktopManager::desktopRemoved, this, &Workspace::slotDesktopRemoved);
connect(vds, &VirtualDesktopManager::currentChanged, this, &Workspace::slotCurrentDesktopChanged);
vds->setNavigationWrappingAround(options->isRollOverDesktops());
connect(options, &Options::rollOverDesktopsChanged, vds, &VirtualDesktopManager::setNavigationWrappingAround);
@ -1211,24 +1205,42 @@ void Workspace::updateCurrentActivity(const QString &new_activity)
#endif
}
void Workspace::slotDesktopCountChanged(uint previousCount, uint newCount)
void Workspace::slotOutputEnabled(AbstractOutput *output)
{
Q_UNUSED(previousCount)
Placement::self()->reinitCascading(0);
resetClientAreas(newCount);
connect(output, &AbstractOutput::geometryChanged, this, &Workspace::desktopResized);
desktopResized();
}
void Workspace::resetClientAreas(uint desktopCount)
void Workspace::slotOutputDisabled(AbstractOutput *output)
{
// Make it +1, so that it can be accessed as [1..numberofdesktops]
workarea.clear();
workarea.resize(desktopCount + 1);
restrictedmovearea.clear();
restrictedmovearea.resize(desktopCount + 1);
screenarea.clear();
// TODO: Send clients on the given output to other outputs.
disconnect(output, &AbstractOutput::geometryChanged, this, &Workspace::desktopResized);
desktopResized();
}
updateClientArea(true);
void Workspace::slotDesktopAdded(VirtualDesktop *desktop)
{
FocusChain::self()->addDesktop(desktop);
Placement::self()->reinitCascading(0);
updateClientArea();
}
void Workspace::slotDesktopRemoved(VirtualDesktop *desktop)
{
for (auto it = m_allClients.constBegin(); it != m_allClients.constEnd(); ++it) {
if (!(*it)->desktops().contains(desktop)) {
continue;
}
if ((*it)->desktops().count() > 1) {
(*it)->leaveDesktop(desktop);
} else {
sendClientToDesktop(*it, qMin(desktop->x11DesktopNumber(), VirtualDesktopManager::self()->count()), true);
}
}
updateClientArea();
Placement::self()->reinitCascading(0);
FocusChain::self()->removeDesktop(desktop);
}
void Workspace::selectWmInputEventMask()
@ -1277,7 +1289,7 @@ void Workspace::sendClientToDesktop(AbstractClient* c, int desk, bool dont_activ
} else
raiseClient(c);
c->checkWorkspacePosition( QRect(), old_desktop );
c->checkWorkspacePosition( QRect(), QRect(), VirtualDesktopManager::self()->desktopForX11Id(old_desktop) );
auto transients_stacking_order = ensureStackingOrder(c->transients());
for (auto it = transients_stacking_order.constBegin();
@ -2156,42 +2168,34 @@ QRect Workspace::adjustClientArea(AbstractClient *client, const QRect &area) con
/**
* Updates the current client areas according to the current clients.
*
* If the area changes or force is @c true, the new areas are propagated to the world.
*
* The client area is the area that is available for clients (that
* which is not taken by windows like panels, the top-of-screen menu
* etc).
*
* @see clientArea()
*/
void Workspace::updateClientArea(bool force)
void Workspace::updateClientArea()
{
const Screens *s = Screens::self();
int nscreens = s->count();
const int numberOfDesktops = VirtualDesktopManager::self()->count();
QVector< QRect > new_wareas(numberOfDesktops + 1);
QVector< StrutRects > new_rmoveareas(numberOfDesktops + 1);
QVector< QVector< QRect > > new_sareas(numberOfDesktops + 1);
QVector< QRect > screens(nscreens);
const QVector<AbstractOutput *> outputs = kwinApp()->platform()->enabledOutputs();
const QVector<VirtualDesktop *> desktops = VirtualDesktopManager::self()->desktops();
QHash<const VirtualDesktop *, QRect> workAreas;
QHash<const VirtualDesktop *, StrutRects> restrictedAreas;
QHash<const VirtualDesktop *, QHash<const AbstractOutput *, QRect>> screenAreas;
QRect desktopArea;
for (int i = 0; i < nscreens; i++) {
desktopArea |= s->geometry(i);
for (const AbstractOutput *output : outputs) {
desktopArea |= output->geometry();
}
for (int iS = 0;
iS < nscreens;
iS ++) {
screens [iS] = s->geometry(iS);
}
for (int i = 1;
i <= numberOfDesktops;
++i) {
new_wareas[ i ] = desktopArea;
new_sareas[ i ].resize(nscreens);
for (int iS = 0;
iS < nscreens;
iS ++)
new_sareas[ i ][ iS ] = screens[ iS ];
for (const VirtualDesktop *desktop : desktops) {
workAreas[desktop] = desktopArea;
for (const AbstractOutput *output : outputs) {
screenAreas[desktop][output] = output->geometry();
}
}
for (AbstractClient *client : qAsConst(m_allClients)) {
if (!client->hasStrut()) {
continue;
@ -2226,77 +2230,38 @@ void Workspace::updateClientArea(bool force)
// or having some content appear offscreen (Relatively rare compared to other).
bool hasOffscreenStrut = hasOffscreenXineramaStrut(client);
if (client->isOnAllDesktops()) {
for (int i = 1;
i <= numberOfDesktops;
++i) {
if (!hasOffscreenStrut)
new_wareas[ i ] = new_wareas[ i ].intersected(r);
new_rmoveareas[ i ] += strutRegion;
for (int iS = 0;
iS < nscreens;
iS ++) {
const auto geo = new_sareas[ i ][ iS ].intersected(
adjustClientArea(client, screens[ iS ]));
// ignore the geometry if it results in the screen getting removed completely
if (!geo.isEmpty()) {
new_sareas[ i ][ iS ] = geo;
}
}
const auto vds = client->isOnAllDesktops() ? desktops : client->desktops();
for (VirtualDesktop *vd : vds) {
if (!hasOffscreenStrut) {
workAreas[vd] &= r;
}
} else {
if (!hasOffscreenStrut)
new_wareas[client->desktop()] = new_wareas[client->desktop()].intersected(r);
new_rmoveareas[client->desktop()] += strutRegion;
for (int iS = 0;
iS < nscreens;
iS ++) {
// qDebug() << "adjusting new_sarea: " << screens[ iS ];
const auto geo = new_sareas[client->desktop()][ iS ].intersected(
adjustClientArea(client, screens[ iS ]));
restrictedAreas[vd] += strutRegion;
for (AbstractOutput *output : outputs) {
const auto geo = screenAreas[vd][output].intersected(adjustClientArea(client, output->geometry()));
// ignore the geometry if it results in the screen getting removed completely
if (!geo.isEmpty()) {
new_sareas[client->desktop()][ iS ] = geo;
screenAreas[vd][output] = geo;
}
}
}
}
#if 0
for (int i = 1;
i <= numberOfDesktops();
++i) {
for (int iS = 0;
iS < nscreens;
iS ++)
qCDebug(KWIN_CORE) << "new_sarea: " << new_sareas[ i ][ iS ];
}
#endif
bool changed = force || screenarea.isEmpty();
for (int i = 1;
!changed && i <= numberOfDesktops;
++i) {
changed |= workarea[i] != new_wareas[i];
changed |= restrictedmovearea[i] != new_rmoveareas[i];
changed |= screenarea[i].size() != new_sareas[i].size();
for (int iS = 0; !changed && iS < nscreens; iS++) {
changed |= new_sareas[i][iS] != screenarea[i][iS];
}
}
if (m_workAreas != workAreas || m_restrictedAreas != restrictedAreas || m_screenAreas != screenAreas) {
m_workAreas = workAreas;
m_screenAreas = screenAreas;
m_oldRestrictedAreas = m_restrictedAreas;
m_restrictedAreas = restrictedAreas;
if (changed) {
workarea = new_wareas;
oldrestrictedmovearea = restrictedmovearea;
restrictedmovearea = new_rmoveareas;
screenarea = new_sareas;
if (rootInfo()) {
NETRect r;
for (int i = 1; i <= numberOfDesktops; i++) {
r.pos.x = workarea[ i ].x();
r.pos.y = workarea[ i ].y();
r.size.width = workarea[ i ].width();
r.size.height = workarea[ i ].height();
rootInfo()->setWorkArea(i, r);
for (VirtualDesktop *desktop : desktops) {
const QRect &workArea = m_workAreas[desktop];
r.pos.x = workArea.x();
r.pos.y = workArea.y();
r.size.width = workArea.width();
r.size.height = workArea.height();
rootInfo()->setWorkArea(desktop->x11DesktopNumber(), r);
}
}
@ -2306,70 +2271,83 @@ void Workspace::updateClientArea(bool force)
(*it)->checkWorkspacePosition();
}
oldrestrictedmovearea.clear(); // reset, no longer valid or needed
m_oldRestrictedAreas.clear(); // reset, no longer valid or needed
}
}
void Workspace::updateClientArea()
{
updateClientArea(false);
}
/**
* Returns the area available for clients. This is the desktop
* geometry minus windows on the dock. Placement algorithms should
* refer to this rather than Screens::geometry.
*/
QRect Workspace::clientArea(clientAreaOption opt, int screen, int desktop) const
QRect Workspace::clientArea(clientAreaOption opt, const AbstractOutput *output, const VirtualDesktop *desktop) const
{
if (desktop == NETWinInfo::OnAllDesktops || desktop == 0)
desktop = VirtualDesktopManager::self()->current();
if (screen == -1)
screen = screens()->current();
const QSize displaySize = screens()->displaySize();
QRect workArea;
QRect sarea, warea;
const AbstractOutput *effectiveOutput = output;
if (is_multihead) {
effectiveOutput = kwinApp()->platform()->findOutput(screen_number);
}
QRect screenArea = m_screenAreas[desktop][effectiveOutput];
if (screenArea.isNull()) { // screens may be missing during KWin initialization or screen config changes
screenArea = effectiveOutput->geometry();
}
if (is_multihead) {
sarea = (!screenarea.isEmpty()
&& screen < screenarea[ desktop ].size()) // screens may be missing during KWin initialization or screen config changes
? screenarea[ desktop ][ screen_number ]
: screens()->geometry(screen_number);
warea = workarea[ desktop ].isNull()
? screens()->geometry(screen_number)
: workarea[ desktop ];
workArea = m_workAreas[desktop];
if (workArea.isNull()) {
workArea = effectiveOutput->geometry();
}
} else {
sarea = (!screenarea.isEmpty()
&& screen < screenarea[ desktop ].size()) // screens may be missing during KWin initialization or screen config changes
? screenarea[ desktop ][ screen ]
: screens()->geometry(screen);
warea = workarea[ desktop ].isNull()
? QRect(0, 0, displaySize.width(), displaySize.height())
: workarea[ desktop ];
workArea = m_workAreas[desktop];
if (workArea.isNull()) {
workArea = QRect(0, 0, displaySize.width(), displaySize.height());
}
}
switch(opt) {
case MaximizeArea:
case PlacementArea:
return sarea;
return screenArea;
case MaximizeFullArea:
case FullScreenArea:
case MovementArea:
case ScreenArea:
if (is_multihead)
return screens()->geometry(screen_number);
else
return screens()->geometry(screen);
return effectiveOutput->geometry();
case WorkArea:
if (is_multihead)
return sarea;
return screenArea;
else
return warea;
return workArea;
case FullArea:
return QRect(0, 0, displaySize.width(), displaySize.height());
default:
Q_UNREACHABLE();
}
abort();
}
QRect Workspace::clientArea(clientAreaOption opt, int screen, int desktop) const
{
VirtualDesktop *virtualDesktop;
AbstractOutput *output;
if (desktop == NETWinInfo::OnAllDesktops || desktop == 0) {
virtualDesktop = VirtualDesktopManager::self()->currentDesktop();
} else {
virtualDesktop = VirtualDesktopManager::self()->desktopForX11Id(desktop);
Q_ASSERT(virtualDesktop);
}
if (screen == -1) {
screen = screens()->current();
}
output = kwinApp()->platform()->findOutput(screen);
Q_ASSERT(output);
return clientArea(opt, output, virtualDesktop);
}
QRect Workspace::clientArea(clientAreaOption opt, const AbstractOutput *output, int desktop) const
@ -2402,13 +2380,10 @@ QRect Workspace::clientArea(clientAreaOption opt, const AbstractClient *client,
return clientArea(opt, client, screens()->number(pos));
}
static QRegion strutsToRegion(int desktop, StrutAreas areas, const QVector<StrutRects> &struts)
static QRegion strutsToRegion(StrutAreas areas, const StrutRects &strut)
{
if (desktop == NETWinInfo::OnAllDesktops || desktop == 0)
desktop = VirtualDesktopManager::self()->current();
QRegion region;
const StrutRects &rects = struts[desktop];
for (const StrutRect &rect : rects) {
for (const StrutRect &rect : strut) {
if (areas & rect.area()) {
region += rect;
}
@ -2416,19 +2391,19 @@ static QRegion strutsToRegion(int desktop, StrutAreas areas, const QVector<Strut
return region;
}
QRegion Workspace::restrictedMoveArea(int desktop, StrutAreas areas) const
QRegion Workspace::restrictedMoveArea(const VirtualDesktop *desktop, StrutAreas areas) const
{
return strutsToRegion(desktop, areas, restrictedmovearea);
return strutsToRegion(areas, m_restrictedAreas[desktop]);
}
bool Workspace::inUpdateClientArea() const
{
return !oldrestrictedmovearea.isEmpty();
return !m_oldRestrictedAreas.isEmpty();
}
QRegion Workspace::previousRestrictedMoveArea(int desktop, StrutAreas areas) const
QRegion Workspace::previousRestrictedMoveArea(const VirtualDesktop *desktop, StrutAreas areas) const
{
return strutsToRegion(desktop, areas, oldrestrictedmovearea);
return strutsToRegion(areas, m_oldRestrictedAreas[desktop]);
}
QVector< QRect > Workspace::previousScreenSizes() const

View File

@ -140,6 +140,7 @@ public:
*/
Toplevel *findInternal(QWindow *w) const;
QRect clientArea(clientAreaOption, const AbstractOutput *output, const VirtualDesktop *desktop) const;
QRect clientArea(clientAreaOption, const QPoint& p, int desktop) const;
QRect clientArea(clientAreaOption, const AbstractClient* c) const;
QRect clientArea(clientAreaOption, const AbstractClient *client, const AbstractOutput *output) const;
@ -148,7 +149,7 @@ public:
QRect clientArea(clientAreaOption, int screen, int desktop) const;
QRect clientArea(clientAreaOption, const AbstractOutput *output, int desktop) const;
QRegion restrictedMoveArea(int desktop, StrutAreas areas = StrutAreaAll) const;
QRegion restrictedMoveArea(const VirtualDesktop *desktop, StrutAreas areas = StrutAreaAll) const;
bool initializing() const;
@ -264,7 +265,7 @@ public:
// True when performing Workspace::updateClientArea().
// The calls below are valid only in that case.
bool inUpdateClientArea() const;
QRegion previousRestrictedMoveArea(int desktop, StrutAreas areas = StrutAreaAll) const;
QRegion previousRestrictedMoveArea(const VirtualDesktop *desktop, StrutAreas areas = StrutAreaAll) const;
QVector< QRect > previousScreenSizes() const;
int oldDisplayWidth() const;
int oldDisplayHeight() const;
@ -480,8 +481,11 @@ private Q_SLOTS:
void slotReloadConfig();
void updateCurrentActivity(const QString &new_activity);
// virtual desktop handling
void slotDesktopCountChanged(uint previousCount, uint newCount);
void slotCurrentDesktopChanged(uint oldDesktop, uint newDesktop);
void slotDesktopAdded(VirtualDesktop *desktop);
void slotDesktopRemoved(VirtualDesktop *desktop);
void slotOutputEnabled(AbstractOutput *output);
void slotOutputDisabled(AbstractOutput *output);
Q_SIGNALS:
/**
@ -559,8 +563,6 @@ private:
//---------------------------------------------------------------------
void closeActivePopup();
void updateClientArea(bool force);
void resetClientAreas(uint desktopCount);
void updateClientVisibilityOnDesktopChange(VirtualDesktop *newDesktop);
void activateClientOnNewDesktop(VirtualDesktop *desktop);
AbstractClient *findClientToActivateOnDesktop(VirtualDesktop *desktop);
@ -652,14 +654,13 @@ private:
QScopedPointer<KStartupInfo> m_startup;
QScopedPointer<ColorMapper> m_colorMapper;
QVector<QRect> workarea; // Array of workareas for virtual desktops
// Array of restricted areas that window cannot be moved into
QVector<StrutRects> restrictedmovearea;
// Array of the previous restricted areas that window cannot be moved into
QVector<StrutRects> oldrestrictedmovearea;
QVector< QVector<QRect> > screenarea; // Array of workareas per xinerama screen for all virtual desktops
QHash<const VirtualDesktop *, QRect> m_workAreas;
QHash<const VirtualDesktop *, StrutRects> m_restrictedAreas;
QHash<const VirtualDesktop *, QHash<const AbstractOutput *, QRect>> m_screenAreas;
QVector< QRect > oldscreensizes; // array of previous sizes of xinerama screens
QSize olddisplaysize; // previous sizes od displayWidth()/displayHeight()
QHash<const VirtualDesktop *, StrutRects> m_oldRestrictedAreas;
int set_active_client_recursion;
int block_stacking_updates; // When > 0, stacking updates are temporarily disabled

View File

@ -1100,7 +1100,7 @@ void X11Client::updateDecoration(bool check_workspace_pos, bool force)
destroyDecoration();
updateShadow();
if (check_workspace_pos)
checkWorkspacePosition(oldgeom, -2, oldClientGeom);
checkWorkspacePosition(oldgeom, oldClientGeom);
updateInputWindow();
blockGeometryUpdates(false);
updateFrameExtents();

View File

@ -638,7 +638,7 @@ void XdgToplevelClient::updateDecoration(bool check_workspace_pos, bool force)
if (check_workspace_pos) {
const QRect oldGeometryRestore = geometryRestore();
setGeometryRestore(frameGeometry());
checkWorkspacePosition(oldFrameGeometry, -2, oldClientGeometry);
checkWorkspacePosition(oldFrameGeometry, oldClientGeometry);
setGeometryRestore(oldGeometryRestore);
}
}