From b75f0899811d7cec4dd690247561d2abef333323 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Fri, 13 Aug 2021 11:41:57 +0300 Subject: [PATCH] Port Workspace::topClientOnDesktop() to VirtualDesktop This patch has one behavioral change - raiseOrLowerClient() will not work if the client is not on the current virtual desktop. However, raiseOrLowerClient() can be called only in two cases: * user triggers the raise or lower shortcut for the active client. Since the active client is on the current virtual desktop, it's not an issue * an x11 window restacks itself. It makes no sense if an x11 window restacks itself while it's inactive or not on current virtual desktop. Also, the Opposite restack mode is rarely used, some window managers don't even bother implementing it. So, having such a constraint should not be a problem. The main reason for not allowing raiseOrLowerClient() for windows that are not on the current virtual desktop is that a window can be on multiple virtual desktops. If a window is on A and B virtual desktops, the only logical option is to toggle stacking position if the window is on the current desktop. It's the only viable option as kwin does not maintain per virtual desktop stacking order. --- autotests/integration/pointer_input.cpp | 21 +++++++++++---------- src/abstract_client.cpp | 4 ++-- src/layers.cpp | 9 ++++++--- src/useractions.cpp | 2 +- src/workspace.cpp | 2 +- src/workspace.h | 5 +++-- 6 files changed, 24 insertions(+), 19 deletions(-) diff --git a/autotests/integration/pointer_input.cpp b/autotests/integration/pointer_input.cpp index 7b1f7a27a1..df666b0a93 100644 --- a/autotests/integration/pointer_input.cpp +++ b/autotests/integration/pointer_input.cpp @@ -16,6 +16,7 @@ #include "options.h" #include "screenedge.h" #include "screens.h" +#include "virtualdesktops.h" #include "wayland_server.h" #include "workspace.h" #include "xcursortheme.h" @@ -756,7 +757,7 @@ void PointerInputTest::testFocusFollowsMouse() AbstractClient *window2 = workspace()->activeClient(); QVERIFY(window2); QVERIFY(window1 != window2); - QCOMPARE(workspace()->topClientOnDesktop(1, -1), window2); + QCOMPARE(workspace()->topClientOnDesktop(VirtualDesktopManager::self()->currentDesktop(), -1), window2); // geometry of the two windows should be overlapping QVERIFY(window1->frameGeometry().intersects(window2->frameGeometry())); @@ -775,18 +776,18 @@ void PointerInputTest::testFocusFollowsMouse() Cursors::self()->mouse()->setPos(10, 10); QVERIFY(stackingOrderChangedSpy.wait()); QCOMPARE(stackingOrderChangedSpy.count(), 1); - QCOMPARE(workspace()->topClientOnDesktop(1, -1), window1); + QCOMPARE(workspace()->topClientOnDesktop(VirtualDesktopManager::self()->currentDesktop(), -1), window1); QTRY_VERIFY(window1->isActive()); // move on second window, but move away before active window change delay hits Cursors::self()->mouse()->setPos(810, 810); QVERIFY(stackingOrderChangedSpy.wait()); QCOMPARE(stackingOrderChangedSpy.count(), 2); - QCOMPARE(workspace()->topClientOnDesktop(1, -1), window2); + QCOMPARE(workspace()->topClientOnDesktop(VirtualDesktopManager::self()->currentDesktop(), -1), window2); Cursors::self()->mouse()->setPos(10, 10); QVERIFY(!activeWindowChangedSpy.wait(250)); QVERIFY(window1->isActive()); - QCOMPARE(workspace()->topClientOnDesktop(1, -1), window1); + QCOMPARE(workspace()->topClientOnDesktop(VirtualDesktopManager::self()->currentDesktop(), -1), window1); // as we moved back on window 1 that should been raised in the mean time QCOMPARE(stackingOrderChangedSpy.count(), 3); @@ -842,7 +843,7 @@ void PointerInputTest::testMouseActionInactiveWindow() AbstractClient *window2 = workspace()->activeClient(); QVERIFY(window2); QVERIFY(window1 != window2); - QCOMPARE(workspace()->topClientOnDesktop(1, -1), window2); + QCOMPARE(workspace()->topClientOnDesktop(VirtualDesktopManager::self()->currentDesktop(), -1), window2); // geometry of the two windows should be overlapping QVERIFY(window1->frameGeometry().intersects(window2->frameGeometry())); @@ -871,7 +872,7 @@ void PointerInputTest::testMouseActionInactiveWindow() // should raise window1 and activate it QCOMPARE(stackingOrderChangedSpy.count(), 1); QVERIFY(!activeWindowChangedSpy.isEmpty()); - QCOMPARE(workspace()->topClientOnDesktop(1, -1), window1); + QCOMPARE(workspace()->topClientOnDesktop(VirtualDesktopManager::self()->currentDesktop(), -1), window1); QVERIFY(window1->isActive()); QVERIFY(!window2->isActive()); @@ -936,12 +937,12 @@ void PointerInputTest::testMouseActionActiveWindow() QVERIFY(window1 != window2); QSignalSpy window2DestroyedSpy(window2, &QObject::destroyed); QVERIFY(window2DestroyedSpy.isValid()); - QCOMPARE(workspace()->topClientOnDesktop(1, -1), window2); + QCOMPARE(workspace()->topClientOnDesktop(VirtualDesktopManager::self()->currentDesktop(), -1), window2); // geometry of the two windows should be overlapping QVERIFY(window1->frameGeometry().intersects(window2->frameGeometry())); // lower the currently active window workspace()->lowerClient(window2); - QCOMPARE(workspace()->topClientOnDesktop(1, -1), window1); + QCOMPARE(workspace()->topClientOnDesktop(VirtualDesktopManager::self()->currentDesktop(), -1), window1); // signal spy for stacking order spy QSignalSpy stackingOrderChangedSpy(workspace(), &Workspace::stackingOrderChanged); @@ -959,11 +960,11 @@ void PointerInputTest::testMouseActionActiveWindow() QVERIFY(buttonSpy.wait()); if (clickRaise) { QCOMPARE(stackingOrderChangedSpy.count(), 1); - QTRY_COMPARE_WITH_TIMEOUT(workspace()->topClientOnDesktop(1, -1), window2, 200); + QTRY_COMPARE_WITH_TIMEOUT(workspace()->topClientOnDesktop(VirtualDesktopManager::self()->currentDesktop(), -1), window2, 200); } else { QCOMPARE(stackingOrderChangedSpy.count(), 0); QVERIFY(!stackingOrderChangedSpy.wait(100)); - QCOMPARE(workspace()->topClientOnDesktop(1, -1), window1); + QCOMPARE(workspace()->topClientOnDesktop(VirtualDesktopManager::self()->currentDesktop(), -1), window1); } // release again diff --git a/src/abstract_client.cpp b/src/abstract_client.cpp index be869012e8..3c7d8d2ab9 100644 --- a/src/abstract_client.cpp +++ b/src/abstract_client.cpp @@ -389,7 +389,7 @@ void AbstractClient::autoRaise() bool AbstractClient::isMostRecentlyRaised() const { // The last toplevel in the unconstrained stacking order is the most recently raised one. - return workspace()->topClientOnDesktop(VirtualDesktopManager::self()->current(), -1, true, false) == this; + return workspace()->topClientOnDesktop(VirtualDesktopManager::self()->currentDesktop(), -1, true, false) == this; } bool AbstractClient::wantsTabFocus() const @@ -2525,7 +2525,7 @@ void AbstractClient::enterEvent(const QPoint &globalPos) if (options->isAutoRaise() && !isDesktop() && !isDock() && workspace()->focusChangeEnabled() && globalPos != workspace()->focusMousePosition() && - workspace()->topClientOnDesktop(VirtualDesktopManager::self()->current(), + workspace()->topClientOnDesktop(VirtualDesktopManager::self()->currentDesktop(), options->isSeparateScreenFocus() ? screen() : -1) != this) { startAutoRaise(); } diff --git a/src/layers.cpp b/src/layers.cpp index fea740d0fb..a90b75cc68 100644 --- a/src/layers.cpp +++ b/src/layers.cpp @@ -218,7 +218,7 @@ void Workspace::propagateClients(bool propagate_new_clients) * doesn't accept focus it's excluded. */ // TODO misleading name for this method, too many slightly different ways to use it -AbstractClient* Workspace::topClientOnDesktop(int desktop, int screen, bool unconstrained, bool only_normal) const +AbstractClient *Workspace::topClientOnDesktop(VirtualDesktop *desktop, int screen, bool unconstrained, bool only_normal) const { // TODO Q_ASSERT( block_stacking_updates == 0 ); QList list; @@ -268,9 +268,12 @@ AbstractClient* Workspace::findDesktop(bool topmost, int desktop) const void Workspace::raiseOrLowerClient(AbstractClient *c) { - if (!c) return; + if (!c || !c->isOnCurrentDesktop()) { + return; + } + const AbstractClient *topmost = - topClientOnDesktop(c->isOnAllDesktops() ? VirtualDesktopManager::self()->current() : c->desktop(), + topClientOnDesktop(VirtualDesktopManager::self()->currentDesktop(), options->isSeparateScreenFocus() ? c->screen() : -1); if (c == topmost) diff --git a/src/useractions.cpp b/src/useractions.cpp index 4fa8eed8f2..6785831085 100644 --- a/src/useractions.cpp +++ b/src/useractions.cpp @@ -1425,7 +1425,7 @@ void Workspace::slotWindowLower() if (next && next != active_client) requestFocus(next, false); } else { - activateClient(topClientOnDesktop(VirtualDesktopManager::self()->current(), -1)); + activateClient(topClientOnDesktop(VirtualDesktopManager::self()->currentDesktop(), -1)); } } } diff --git a/src/workspace.cpp b/src/workspace.cpp index 56d1df922a..24feed27e0 100644 --- a/src/workspace.cpp +++ b/src/workspace.cpp @@ -432,7 +432,7 @@ void Workspace::initializeX11() && activeClient() == nullptr && should_get_focus.count() == 0) { // No client activated in manage() if (new_active_client == nullptr) - new_active_client = topClientOnDesktop(VirtualDesktopManager::self()->current(), -1); + new_active_client = topClientOnDesktop(VirtualDesktopManager::self()->currentDesktop(), -1); if (new_active_client == nullptr) new_active_client = findDesktop(true, VirtualDesktopManager::self()->current()); } diff --git a/src/workspace.h b/src/workspace.h index f146602f7e..c0b541e5c2 100644 --- a/src/workspace.h +++ b/src/workspace.h @@ -52,6 +52,7 @@ class ShortcutDialog; class Toplevel; class Unmanaged; class UserActionsMenu; +class VirtualDesktop; class X11Client; class X11EventFilter; enum class Predicate; @@ -274,8 +275,8 @@ public: QList ensureStackingOrder(const QList &clients) const; QList ensureStackingOrder(const QList &clients) const; - AbstractClient* topClientOnDesktop(int desktop, int screen, bool unconstrained = false, - bool only_normal = true) const; + AbstractClient *topClientOnDesktop(VirtualDesktop *desktop, int screen, bool unconstrained = false, + bool only_normal = true) const; AbstractClient* findDesktop(bool topmost, int desktop) const; void sendClientToDesktop(AbstractClient* c, int desktop, bool dont_activate); void windowToPreviousDesktop(AbstractClient* c);