Port Workspace::clientArea() to VirtualDesktop
This makes Workspace APIs that take virtual desktops more consistent.icc-effect-5.26.4
parent
5b3c87f105
commit
fddbd57d09
|
@ -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
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue