Warning, file /plasma/kwin/autotests/integration/virtual_desktop_test.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 2017 Martin Flöser <mgraesslin@kde.org>
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 #include "kwin_wayland_test.h"
0010 
0011 #include "core/outputbackend.h"
0012 #include "main.h"
0013 #include "virtualdesktops.h"
0014 #include "wayland_server.h"
0015 #include "window.h"
0016 #include "workspace.h"
0017 
0018 #include <KWayland/Client/surface.h>
0019 
0020 using namespace KWin;
0021 
0022 static const QString s_socketName = QStringLiteral("wayland_test_kwin_virtualdesktop-0");
0023 
0024 class VirtualDesktopTest : public QObject
0025 {
0026     Q_OBJECT
0027 private Q_SLOTS:
0028     void initTestCase();
0029     void init();
0030     void cleanup();
0031 
0032     void testNetCurrentDesktop();
0033     void testLastDesktopRemoved();
0034     void testWindowOnMultipleDesktops();
0035     void testRemoveDesktopWithWindow();
0036 };
0037 
0038 void VirtualDesktopTest::initTestCase()
0039 {
0040     qRegisterMetaType<KWin::Window *>();
0041     QSignalSpy applicationStartedSpy(kwinApp(), &Application::started);
0042     QVERIFY(waylandServer()->init(s_socketName));
0043     QMetaObject::invokeMethod(kwinApp()->outputBackend(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(QVector<QRect>, QVector<QRect>() << QRect(0, 0, 1280, 1024) << QRect(1280, 0, 1280, 1024)));
0044 
0045     kwinApp()->setConfig(KSharedConfig::openConfig(QString(), KConfig::SimpleConfig));
0046     qputenv("KWIN_XKB_DEFAULT_KEYMAP", "1");
0047     qputenv("XKB_DEFAULT_RULES", "evdev");
0048 
0049     kwinApp()->start();
0050     QVERIFY(applicationStartedSpy.wait());
0051 
0052     if (kwinApp()->x11Connection()) {
0053         // verify the current desktop x11 property on startup, see BUG: 391034
0054         Xcb::Atom currentDesktopAtom("_NET_CURRENT_DESKTOP");
0055         QVERIFY(currentDesktopAtom.isValid());
0056         Xcb::Property currentDesktop(0, kwinApp()->x11RootWindow(), currentDesktopAtom, XCB_ATOM_CARDINAL, 0, 1);
0057         bool ok = true;
0058         QCOMPARE(currentDesktop.value(0, &ok), 0);
0059         QVERIFY(ok);
0060     }
0061 }
0062 
0063 void VirtualDesktopTest::init()
0064 {
0065     QVERIFY(Test::setupWaylandConnection());
0066     workspace()->setActiveOutput(QPoint(640, 512));
0067     VirtualDesktopManager::self()->setCount(1);
0068 }
0069 
0070 void VirtualDesktopTest::cleanup()
0071 {
0072     Test::destroyWaylandConnection();
0073 }
0074 
0075 void VirtualDesktopTest::testNetCurrentDesktop()
0076 {
0077     if (!kwinApp()->x11Connection()) {
0078         QSKIP("Skipped on Wayland only");
0079     }
0080     QCOMPARE(VirtualDesktopManager::self()->count(), 1u);
0081     VirtualDesktopManager::self()->setCount(4);
0082     QCOMPARE(VirtualDesktopManager::self()->count(), 4u);
0083 
0084     Xcb::Atom currentDesktopAtom("_NET_CURRENT_DESKTOP");
0085     QVERIFY(currentDesktopAtom.isValid());
0086     Xcb::Property currentDesktop(0, kwinApp()->x11RootWindow(), currentDesktopAtom, XCB_ATOM_CARDINAL, 0, 1);
0087     bool ok = true;
0088     QCOMPARE(currentDesktop.value(0, &ok), 0);
0089     QVERIFY(ok);
0090 
0091     // go to desktop 2
0092     VirtualDesktopManager::self()->setCurrent(2);
0093     currentDesktop = Xcb::Property(0, kwinApp()->x11RootWindow(), currentDesktopAtom, XCB_ATOM_CARDINAL, 0, 1);
0094     QCOMPARE(currentDesktop.value(0, &ok), 1);
0095     QVERIFY(ok);
0096 
0097     // go to desktop 3
0098     VirtualDesktopManager::self()->setCurrent(3);
0099     currentDesktop = Xcb::Property(0, kwinApp()->x11RootWindow(), currentDesktopAtom, XCB_ATOM_CARDINAL, 0, 1);
0100     QCOMPARE(currentDesktop.value(0, &ok), 2);
0101     QVERIFY(ok);
0102 
0103     // go to desktop 4
0104     VirtualDesktopManager::self()->setCurrent(4);
0105     currentDesktop = Xcb::Property(0, kwinApp()->x11RootWindow(), currentDesktopAtom, XCB_ATOM_CARDINAL, 0, 1);
0106     QCOMPARE(currentDesktop.value(0, &ok), 3);
0107     QVERIFY(ok);
0108 
0109     // and back to first
0110     VirtualDesktopManager::self()->setCurrent(1);
0111     currentDesktop = Xcb::Property(0, kwinApp()->x11RootWindow(), currentDesktopAtom, XCB_ATOM_CARDINAL, 0, 1);
0112     QCOMPARE(currentDesktop.value(0, &ok), 0);
0113     QVERIFY(ok);
0114 }
0115 
0116 void VirtualDesktopTest::testLastDesktopRemoved()
0117 {
0118     // first create a new desktop
0119     QCOMPARE(VirtualDesktopManager::self()->count(), 1u);
0120     VirtualDesktopManager::self()->setCount(2);
0121     QCOMPARE(VirtualDesktopManager::self()->count(), 2u);
0122 
0123     // switch to last desktop
0124     VirtualDesktopManager::self()->setCurrent(VirtualDesktopManager::self()->desktops().last());
0125     QCOMPARE(VirtualDesktopManager::self()->current(), 2u);
0126 
0127     // now create a window on this desktop
0128     std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
0129     std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get()));
0130     auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
0131 
0132     QVERIFY(window);
0133     QCOMPARE(window->desktop(), 2);
0134     QSignalSpy desktopPresenceChangedSpy(window, &Window::desktopPresenceChanged);
0135 
0136     QCOMPARE(window->desktops().count(), 1u);
0137     QCOMPARE(VirtualDesktopManager::self()->currentDesktop(), window->desktops().first());
0138 
0139     // and remove last desktop
0140     VirtualDesktopManager::self()->setCount(1);
0141     QCOMPARE(VirtualDesktopManager::self()->count(), 1u);
0142     // now the window should be moved as well
0143     QTRY_COMPARE(desktopPresenceChangedSpy.count(), 1);
0144     QCOMPARE(window->desktop(), 1);
0145 
0146     QCOMPARE(window->desktops().count(), 1u);
0147     QCOMPARE(VirtualDesktopManager::self()->currentDesktop(), window->desktops().first());
0148 }
0149 
0150 void VirtualDesktopTest::testWindowOnMultipleDesktops()
0151 {
0152     // first create two new desktops
0153     QCOMPARE(VirtualDesktopManager::self()->count(), 1u);
0154     VirtualDesktopManager::self()->setCount(3);
0155     QCOMPARE(VirtualDesktopManager::self()->count(), 3u);
0156 
0157     // switch to last desktop
0158     VirtualDesktopManager::self()->setCurrent(VirtualDesktopManager::self()->desktops().last());
0159     QCOMPARE(VirtualDesktopManager::self()->current(), 3u);
0160 
0161     // now create a window on this desktop
0162     std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
0163     std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get()));
0164     auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
0165 
0166     QVERIFY(window);
0167     QCOMPARE(window->desktop(), 3u);
0168     QSignalSpy desktopPresenceChangedSpy(window, &Window::desktopPresenceChanged);
0169 
0170     QCOMPARE(window->desktops().count(), 1u);
0171     QCOMPARE(VirtualDesktopManager::self()->currentDesktop(), window->desktops().first());
0172 
0173     // Set the window on desktop 2 as well
0174     window->enterDesktop(VirtualDesktopManager::self()->desktopForX11Id(2));
0175     QCOMPARE(window->desktops().count(), 2u);
0176     QCOMPARE(VirtualDesktopManager::self()->desktops()[2], window->desktops()[0]);
0177     QCOMPARE(VirtualDesktopManager::self()->desktops()[1], window->desktops()[1]);
0178     QVERIFY(window->isOnDesktop(2));
0179     QVERIFY(window->isOnDesktop(3));
0180 
0181     // leave desktop 3
0182     window->leaveDesktop(VirtualDesktopManager::self()->desktopForX11Id(3));
0183     QCOMPARE(window->desktops().count(), 1u);
0184     // leave desktop 2
0185     window->leaveDesktop(VirtualDesktopManager::self()->desktopForX11Id(2));
0186     QCOMPARE(window->desktops().count(), 0u);
0187     // we should be on all desktops now
0188     QVERIFY(window->isOnAllDesktops());
0189     // put on desktop 1
0190     window->enterDesktop(VirtualDesktopManager::self()->desktopForX11Id(1));
0191     QVERIFY(window->isOnDesktop(1));
0192     QVERIFY(!window->isOnDesktop(2));
0193     QVERIFY(!window->isOnDesktop(3));
0194     QCOMPARE(window->desktops().count(), 1u);
0195     // put on desktop 2
0196     window->enterDesktop(VirtualDesktopManager::self()->desktopForX11Id(2));
0197     QVERIFY(window->isOnDesktop(1));
0198     QVERIFY(window->isOnDesktop(2));
0199     QVERIFY(!window->isOnDesktop(3));
0200     QCOMPARE(window->desktops().count(), 2u);
0201     // put on desktop 3
0202     window->enterDesktop(VirtualDesktopManager::self()->desktopForX11Id(3));
0203     QVERIFY(window->isOnDesktop(1));
0204     QVERIFY(window->isOnDesktop(2));
0205     QVERIFY(window->isOnDesktop(3));
0206     QCOMPARE(window->desktops().count(), 3u);
0207 
0208     // entering twice dooes nothing
0209     window->enterDesktop(VirtualDesktopManager::self()->desktopForX11Id(3));
0210     QCOMPARE(window->desktops().count(), 3u);
0211 
0212     // adding to "all desktops" results in just that one desktop
0213     window->setOnAllDesktops(true);
0214     QCOMPARE(window->desktops().count(), 0u);
0215     window->enterDesktop(VirtualDesktopManager::self()->desktopForX11Id(3));
0216     QVERIFY(window->isOnDesktop(3));
0217     QCOMPARE(window->desktops().count(), 1u);
0218 
0219     // leaving a desktop on "all desktops" puts on everything else
0220     window->setOnAllDesktops(true);
0221     QCOMPARE(window->desktops().count(), 0u);
0222     window->leaveDesktop(VirtualDesktopManager::self()->desktopForX11Id(3));
0223     QVERIFY(window->isOnDesktop(1));
0224     QVERIFY(window->isOnDesktop(2));
0225     QCOMPARE(window->desktops().count(), 2u);
0226 }
0227 
0228 void VirtualDesktopTest::testRemoveDesktopWithWindow()
0229 {
0230     // first create two new desktops
0231     QCOMPARE(VirtualDesktopManager::self()->count(), 1u);
0232     VirtualDesktopManager::self()->setCount(3);
0233     QCOMPARE(VirtualDesktopManager::self()->count(), 3u);
0234 
0235     // switch to last desktop
0236     VirtualDesktopManager::self()->setCurrent(VirtualDesktopManager::self()->desktops().last());
0237     QCOMPARE(VirtualDesktopManager::self()->current(), 3u);
0238 
0239     // now create a window on this desktop
0240     std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
0241     std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get()));
0242     auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
0243 
0244     QVERIFY(window);
0245     QCOMPARE(window->desktop(), 3u);
0246     QSignalSpy desktopPresenceChangedSpy(window, &Window::desktopPresenceChanged);
0247 
0248     QCOMPARE(window->desktops().count(), 1u);
0249     QCOMPARE(VirtualDesktopManager::self()->currentDesktop(), window->desktops().first());
0250 
0251     // Set the window on desktop 2 as well
0252     window->enterDesktop(VirtualDesktopManager::self()->desktops()[1]);
0253     QCOMPARE(window->desktops().count(), 2u);
0254     QCOMPARE(VirtualDesktopManager::self()->desktops()[2], window->desktops()[0]);
0255     QCOMPARE(VirtualDesktopManager::self()->desktops()[1], window->desktops()[1]);
0256     QVERIFY(window->isOnDesktop(2));
0257     QVERIFY(window->isOnDesktop(3));
0258 
0259     // remove desktop 3
0260     VirtualDesktopManager::self()->setCount(2);
0261     QCOMPARE(window->desktops().count(), 1u);
0262     // window is only on desktop 2
0263     QCOMPARE(VirtualDesktopManager::self()->desktops()[1], window->desktops()[0]);
0264 
0265     // Again 3 desktops
0266     VirtualDesktopManager::self()->setCount(3);
0267     // move window to be only on desktop 3
0268     window->enterDesktop(VirtualDesktopManager::self()->desktops()[2]);
0269     window->leaveDesktop(VirtualDesktopManager::self()->desktops()[1]);
0270     QCOMPARE(window->desktops().count(), 1u);
0271     // window is only on desktop 3
0272     QCOMPARE(VirtualDesktopManager::self()->desktops()[2], window->desktops()[0]);
0273 
0274     // remove desktop 3
0275     VirtualDesktopManager::self()->setCount(2);
0276     QCOMPARE(window->desktops().count(), 1u);
0277     // window is only on desktop 2
0278     QCOMPARE(VirtualDesktopManager::self()->desktops()[1], window->desktops()[0]);
0279 }
0280 
0281 WAYLANDTEST_MAIN(VirtualDesktopTest)
0282 #include "virtual_desktop_test.moc"