File indexing completed on 2024-05-05 17:35:43

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 2019 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 
0010 #include "kwin_wayland_test.h"
0011 
0012 #include "core/output.h"
0013 #include "core/outputbackend.h"
0014 #include "cursor.h"
0015 #include "wayland_server.h"
0016 #include "window.h"
0017 #include "workspace.h"
0018 
0019 #include <KWayland/Client/surface.h>
0020 
0021 namespace KWin
0022 {
0023 
0024 static const QString s_socketName = QStringLiteral("wayland_test_activation-0");
0025 
0026 class ActivationTest : public QObject
0027 {
0028     Q_OBJECT
0029 
0030 private Q_SLOTS:
0031     void initTestCase();
0032     void init();
0033     void cleanup();
0034 
0035     void testSwitchToWindowToLeft();
0036     void testSwitchToWindowToRight();
0037     void testSwitchToWindowAbove();
0038     void testSwitchToWindowBelow();
0039     void testSwitchToWindowMaximized();
0040     void testSwitchToWindowFullScreen();
0041 
0042 private:
0043     void stackScreensHorizontally();
0044     void stackScreensVertically();
0045 };
0046 
0047 void ActivationTest::initTestCase()
0048 {
0049     qRegisterMetaType<Window *>();
0050 
0051     QSignalSpy applicationStartedSpy(kwinApp(), &Application::started);
0052     QVERIFY(waylandServer()->init(s_socketName));
0053     QMetaObject::invokeMethod(kwinApp()->outputBackend(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(QVector<QRect>, QVector<QRect>() << QRect(0, 0, 1280, 1024) << QRect(1280, 0, 1280, 1024)));
0054 
0055     kwinApp()->start();
0056     QVERIFY(applicationStartedSpy.wait());
0057     const auto outputs = workspace()->outputs();
0058     QCOMPARE(outputs.count(), 2);
0059     QCOMPARE(outputs[0]->geometry(), QRect(0, 0, 1280, 1024));
0060     QCOMPARE(outputs[1]->geometry(), QRect(1280, 0, 1280, 1024));
0061 }
0062 
0063 void ActivationTest::init()
0064 {
0065     QVERIFY(Test::setupWaylandConnection());
0066 
0067     workspace()->setActiveOutput(QPoint(640, 512));
0068     Cursors::self()->mouse()->setPos(QPoint(640, 512));
0069 }
0070 
0071 void ActivationTest::cleanup()
0072 {
0073     Test::destroyWaylandConnection();
0074 
0075     stackScreensHorizontally();
0076 }
0077 
0078 void ActivationTest::testSwitchToWindowToLeft()
0079 {
0080     // This test verifies that "Switch to Window to the Left" shortcut works.
0081 
0082     // Prepare the test environment.
0083     stackScreensHorizontally();
0084 
0085     // Create several windows on the left screen.
0086     std::unique_ptr<KWayland::Client::Surface> surface1(Test::createSurface());
0087     std::unique_ptr<Test::XdgToplevel> shellSurface1(Test::createXdgToplevelSurface(surface1.get()));
0088     Window *window1 = Test::renderAndWaitForShown(surface1.get(), QSize(100, 50), Qt::blue);
0089     QVERIFY(window1);
0090     QVERIFY(window1->isActive());
0091 
0092     std::unique_ptr<KWayland::Client::Surface> surface2(Test::createSurface());
0093     std::unique_ptr<Test::XdgToplevel> shellSurface2(Test::createXdgToplevelSurface(surface2.get()));
0094     Window *window2 = Test::renderAndWaitForShown(surface2.get(), QSize(100, 50), Qt::blue);
0095     QVERIFY(window2);
0096     QVERIFY(window2->isActive());
0097 
0098     window1->move(QPoint(300, 200));
0099     window2->move(QPoint(500, 200));
0100 
0101     // Create several windows on the right screen.
0102     std::unique_ptr<KWayland::Client::Surface> surface3(Test::createSurface());
0103     std::unique_ptr<Test::XdgToplevel> shellSurface3(Test::createXdgToplevelSurface(surface3.get()));
0104     Window *window3 = Test::renderAndWaitForShown(surface3.get(), QSize(100, 50), Qt::blue);
0105     QVERIFY(window3);
0106     QVERIFY(window3->isActive());
0107 
0108     std::unique_ptr<KWayland::Client::Surface> surface4(Test::createSurface());
0109     std::unique_ptr<Test::XdgToplevel> shellSurface4(Test::createXdgToplevelSurface(surface4.get()));
0110     Window *window4 = Test::renderAndWaitForShown(surface4.get(), QSize(100, 50), Qt::blue);
0111     QVERIFY(window4);
0112     QVERIFY(window4->isActive());
0113 
0114     window3->move(QPoint(1380, 200));
0115     window4->move(QPoint(1580, 200));
0116 
0117     // Switch to window to the left.
0118     workspace()->switchWindow(Workspace::DirectionWest);
0119     QVERIFY(window3->isActive());
0120 
0121     // Switch to window to the left.
0122     workspace()->switchWindow(Workspace::DirectionWest);
0123     QVERIFY(window2->isActive());
0124 
0125     // Switch to window to the left.
0126     workspace()->switchWindow(Workspace::DirectionWest);
0127     QVERIFY(window1->isActive());
0128 
0129     // Switch to window to the left.
0130     workspace()->switchWindow(Workspace::DirectionWest);
0131     QVERIFY(window4->isActive());
0132 
0133     // Destroy all windows.
0134     shellSurface1.reset();
0135     QVERIFY(Test::waitForWindowDestroyed(window1));
0136     shellSurface2.reset();
0137     QVERIFY(Test::waitForWindowDestroyed(window2));
0138     shellSurface3.reset();
0139     QVERIFY(Test::waitForWindowDestroyed(window3));
0140     shellSurface4.reset();
0141     QVERIFY(Test::waitForWindowDestroyed(window4));
0142 }
0143 
0144 void ActivationTest::testSwitchToWindowToRight()
0145 {
0146     // This test verifies that "Switch to Window to the Right" shortcut works.
0147 
0148     // Prepare the test environment.
0149     stackScreensHorizontally();
0150 
0151     // Create several windows on the left screen.
0152     std::unique_ptr<KWayland::Client::Surface> surface1(Test::createSurface());
0153     std::unique_ptr<Test::XdgToplevel> shellSurface1(Test::createXdgToplevelSurface(surface1.get()));
0154     Window *window1 = Test::renderAndWaitForShown(surface1.get(), QSize(100, 50), Qt::blue);
0155     QVERIFY(window1);
0156     QVERIFY(window1->isActive());
0157 
0158     std::unique_ptr<KWayland::Client::Surface> surface2(Test::createSurface());
0159     std::unique_ptr<Test::XdgToplevel> shellSurface2(Test::createXdgToplevelSurface(surface2.get()));
0160     Window *window2 = Test::renderAndWaitForShown(surface2.get(), QSize(100, 50), Qt::blue);
0161     QVERIFY(window2);
0162     QVERIFY(window2->isActive());
0163 
0164     window1->move(QPoint(300, 200));
0165     window2->move(QPoint(500, 200));
0166 
0167     // Create several windows on the right screen.
0168     std::unique_ptr<KWayland::Client::Surface> surface3(Test::createSurface());
0169     std::unique_ptr<Test::XdgToplevel> shellSurface3(Test::createXdgToplevelSurface(surface3.get()));
0170     Window *window3 = Test::renderAndWaitForShown(surface3.get(), QSize(100, 50), Qt::blue);
0171     QVERIFY(window3);
0172     QVERIFY(window3->isActive());
0173 
0174     std::unique_ptr<KWayland::Client::Surface> surface4(Test::createSurface());
0175     std::unique_ptr<Test::XdgToplevel> shellSurface4(Test::createXdgToplevelSurface(surface4.get()));
0176     Window *window4 = Test::renderAndWaitForShown(surface4.get(), QSize(100, 50), Qt::blue);
0177     QVERIFY(window4);
0178     QVERIFY(window4->isActive());
0179 
0180     window3->move(QPoint(1380, 200));
0181     window4->move(QPoint(1580, 200));
0182 
0183     // Switch to window to the right.
0184     workspace()->switchWindow(Workspace::DirectionEast);
0185     QVERIFY(window1->isActive());
0186 
0187     // Switch to window to the right.
0188     workspace()->switchWindow(Workspace::DirectionEast);
0189     QVERIFY(window2->isActive());
0190 
0191     // Switch to window to the right.
0192     workspace()->switchWindow(Workspace::DirectionEast);
0193     QVERIFY(window3->isActive());
0194 
0195     // Switch to window to the right.
0196     workspace()->switchWindow(Workspace::DirectionEast);
0197     QVERIFY(window4->isActive());
0198 
0199     // Destroy all windows.
0200     shellSurface1.reset();
0201     QVERIFY(Test::waitForWindowDestroyed(window1));
0202     shellSurface2.reset();
0203     QVERIFY(Test::waitForWindowDestroyed(window2));
0204     shellSurface3.reset();
0205     QVERIFY(Test::waitForWindowDestroyed(window3));
0206     shellSurface4.reset();
0207     QVERIFY(Test::waitForWindowDestroyed(window4));
0208 }
0209 
0210 void ActivationTest::testSwitchToWindowAbove()
0211 {
0212     // This test verifies that "Switch to Window Above" shortcut works.
0213 
0214     // Prepare the test environment.
0215     stackScreensVertically();
0216 
0217     // Create several windows on the top screen.
0218     std::unique_ptr<KWayland::Client::Surface> surface1(Test::createSurface());
0219     std::unique_ptr<Test::XdgToplevel> shellSurface1(Test::createXdgToplevelSurface(surface1.get()));
0220     Window *window1 = Test::renderAndWaitForShown(surface1.get(), QSize(100, 50), Qt::blue);
0221     QVERIFY(window1);
0222     QVERIFY(window1->isActive());
0223 
0224     std::unique_ptr<KWayland::Client::Surface> surface2(Test::createSurface());
0225     std::unique_ptr<Test::XdgToplevel> shellSurface2(Test::createXdgToplevelSurface(surface2.get()));
0226     Window *window2 = Test::renderAndWaitForShown(surface2.get(), QSize(100, 50), Qt::blue);
0227     QVERIFY(window2);
0228     QVERIFY(window2->isActive());
0229 
0230     window1->move(QPoint(200, 300));
0231     window2->move(QPoint(200, 500));
0232 
0233     // Create several windows on the bottom screen.
0234     std::unique_ptr<KWayland::Client::Surface> surface3(Test::createSurface());
0235     std::unique_ptr<Test::XdgToplevel> shellSurface3(Test::createXdgToplevelSurface(surface3.get()));
0236     Window *window3 = Test::renderAndWaitForShown(surface3.get(), QSize(100, 50), Qt::blue);
0237     QVERIFY(window3);
0238     QVERIFY(window3->isActive());
0239 
0240     std::unique_ptr<KWayland::Client::Surface> surface4(Test::createSurface());
0241     std::unique_ptr<Test::XdgToplevel> shellSurface4(Test::createXdgToplevelSurface(surface4.get()));
0242     Window *window4 = Test::renderAndWaitForShown(surface4.get(), QSize(100, 50), Qt::blue);
0243     QVERIFY(window4);
0244     QVERIFY(window4->isActive());
0245 
0246     window3->move(QPoint(200, 1224));
0247     window4->move(QPoint(200, 1424));
0248 
0249     // Switch to window above.
0250     workspace()->switchWindow(Workspace::DirectionNorth);
0251     QVERIFY(window3->isActive());
0252 
0253     // Switch to window above.
0254     workspace()->switchWindow(Workspace::DirectionNorth);
0255     QVERIFY(window2->isActive());
0256 
0257     // Switch to window above.
0258     workspace()->switchWindow(Workspace::DirectionNorth);
0259     QVERIFY(window1->isActive());
0260 
0261     // Switch to window above.
0262     workspace()->switchWindow(Workspace::DirectionNorth);
0263     QVERIFY(window4->isActive());
0264 
0265     // Destroy all windows.
0266     shellSurface1.reset();
0267     QVERIFY(Test::waitForWindowDestroyed(window1));
0268     shellSurface2.reset();
0269     QVERIFY(Test::waitForWindowDestroyed(window2));
0270     shellSurface3.reset();
0271     QVERIFY(Test::waitForWindowDestroyed(window3));
0272     shellSurface4.reset();
0273     QVERIFY(Test::waitForWindowDestroyed(window4));
0274 }
0275 
0276 void ActivationTest::testSwitchToWindowBelow()
0277 {
0278     // This test verifies that "Switch to Window Bottom" shortcut works.
0279 
0280     // Prepare the test environment.
0281     stackScreensVertically();
0282 
0283     // Create several windows on the top screen.
0284     std::unique_ptr<KWayland::Client::Surface> surface1(Test::createSurface());
0285     std::unique_ptr<Test::XdgToplevel> shellSurface1(Test::createXdgToplevelSurface(surface1.get()));
0286     Window *window1 = Test::renderAndWaitForShown(surface1.get(), QSize(100, 50), Qt::blue);
0287     QVERIFY(window1);
0288     QVERIFY(window1->isActive());
0289 
0290     std::unique_ptr<KWayland::Client::Surface> surface2(Test::createSurface());
0291     std::unique_ptr<Test::XdgToplevel> shellSurface2(Test::createXdgToplevelSurface(surface2.get()));
0292     Window *window2 = Test::renderAndWaitForShown(surface2.get(), QSize(100, 50), Qt::blue);
0293     QVERIFY(window2);
0294     QVERIFY(window2->isActive());
0295 
0296     window1->move(QPoint(200, 300));
0297     window2->move(QPoint(200, 500));
0298 
0299     // Create several windows on the bottom screen.
0300     std::unique_ptr<KWayland::Client::Surface> surface3(Test::createSurface());
0301     std::unique_ptr<Test::XdgToplevel> shellSurface3(Test::createXdgToplevelSurface(surface3.get()));
0302     Window *window3 = Test::renderAndWaitForShown(surface3.get(), QSize(100, 50), Qt::blue);
0303     QVERIFY(window3);
0304     QVERIFY(window3->isActive());
0305 
0306     std::unique_ptr<KWayland::Client::Surface> surface4(Test::createSurface());
0307     std::unique_ptr<Test::XdgToplevel> shellSurface4(Test::createXdgToplevelSurface(surface4.get()));
0308     Window *window4 = Test::renderAndWaitForShown(surface4.get(), QSize(100, 50), Qt::blue);
0309     QVERIFY(window4);
0310     QVERIFY(window4->isActive());
0311 
0312     window3->move(QPoint(200, 1224));
0313     window4->move(QPoint(200, 1424));
0314 
0315     // Switch to window below.
0316     workspace()->switchWindow(Workspace::DirectionSouth);
0317     QVERIFY(window1->isActive());
0318 
0319     // Switch to window below.
0320     workspace()->switchWindow(Workspace::DirectionSouth);
0321     QVERIFY(window2->isActive());
0322 
0323     // Switch to window below.
0324     workspace()->switchWindow(Workspace::DirectionSouth);
0325     QVERIFY(window3->isActive());
0326 
0327     // Switch to window below.
0328     workspace()->switchWindow(Workspace::DirectionSouth);
0329     QVERIFY(window4->isActive());
0330 
0331     // Destroy all windows.
0332     shellSurface1.reset();
0333     QVERIFY(Test::waitForWindowDestroyed(window1));
0334     shellSurface2.reset();
0335     QVERIFY(Test::waitForWindowDestroyed(window2));
0336     shellSurface3.reset();
0337     QVERIFY(Test::waitForWindowDestroyed(window3));
0338     shellSurface4.reset();
0339     QVERIFY(Test::waitForWindowDestroyed(window4));
0340 }
0341 
0342 void ActivationTest::testSwitchToWindowMaximized()
0343 {
0344     // This test verifies that we switch to the top-most maximized window, i.e.
0345     // the one that user sees at the moment. See bug 411356.
0346 
0347     // Prepare the test environment.
0348     stackScreensHorizontally();
0349 
0350     // Create several maximized windows on the left screen.
0351     std::unique_ptr<KWayland::Client::Surface> surface1(Test::createSurface());
0352     std::unique_ptr<Test::XdgToplevel> shellSurface1(Test::createXdgToplevelSurface(surface1.get()));
0353     QSignalSpy toplevelConfigureRequestedSpy1(shellSurface1.get(), &Test::XdgToplevel::configureRequested);
0354     QSignalSpy surfaceConfigureRequestedSpy1(shellSurface1->xdgSurface(), &Test::XdgSurface::configureRequested);
0355     Window *window1 = Test::renderAndWaitForShown(surface1.get(), QSize(100, 50), Qt::blue);
0356     QVERIFY(window1);
0357     QVERIFY(window1->isActive());
0358     QVERIFY(surfaceConfigureRequestedSpy1.wait()); // Wait for the configure event with the activated state.
0359     workspace()->slotWindowMaximize();
0360     QVERIFY(surfaceConfigureRequestedSpy1.wait());
0361     QSignalSpy frameGeometryChangedSpy1(window1, &Window::frameGeometryChanged);
0362     shellSurface1->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy1.last().at(0).value<quint32>());
0363     Test::render(surface1.get(), toplevelConfigureRequestedSpy1.last().at(0).toSize(), Qt::red);
0364     QVERIFY(frameGeometryChangedSpy1.wait());
0365 
0366     std::unique_ptr<KWayland::Client::Surface> surface2(Test::createSurface());
0367     std::unique_ptr<Test::XdgToplevel> shellSurface2(Test::createXdgToplevelSurface(surface2.get()));
0368     QSignalSpy toplevelConfigureRequestedSpy2(shellSurface2.get(), &Test::XdgToplevel::configureRequested);
0369     QSignalSpy surfaceConfigureRequestedSpy2(shellSurface2->xdgSurface(), &Test::XdgSurface::configureRequested);
0370     Window *window2 = Test::renderAndWaitForShown(surface2.get(), QSize(100, 50), Qt::blue);
0371     QVERIFY(window2);
0372     QVERIFY(window2->isActive());
0373     QVERIFY(surfaceConfigureRequestedSpy2.wait()); // Wait for the configure event with the activated state.
0374     workspace()->slotWindowMaximize();
0375     QVERIFY(surfaceConfigureRequestedSpy2.wait());
0376     QSignalSpy frameGeometryChangedSpy2(window2, &Window::frameGeometryChanged);
0377     shellSurface2->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy2.last().at(0).value<quint32>());
0378     Test::render(surface2.get(), toplevelConfigureRequestedSpy2.last().at(0).toSize(), Qt::red);
0379     QVERIFY(frameGeometryChangedSpy2.wait());
0380 
0381     const QList<Window *> stackingOrder = workspace()->stackingOrder();
0382     QVERIFY(stackingOrder.indexOf(window1) < stackingOrder.indexOf(window2));
0383     QCOMPARE(window1->maximizeMode(), MaximizeFull);
0384     QCOMPARE(window2->maximizeMode(), MaximizeFull);
0385 
0386     // Create several windows on the right screen.
0387     std::unique_ptr<KWayland::Client::Surface> surface3(Test::createSurface());
0388     std::unique_ptr<Test::XdgToplevel> shellSurface3(Test::createXdgToplevelSurface(surface3.get()));
0389     Window *window3 = Test::renderAndWaitForShown(surface3.get(), QSize(100, 50), Qt::blue);
0390     QVERIFY(window3);
0391     QVERIFY(window3->isActive());
0392 
0393     std::unique_ptr<KWayland::Client::Surface> surface4(Test::createSurface());
0394     std::unique_ptr<Test::XdgToplevel> shellSurface4(Test::createXdgToplevelSurface(surface4.get()));
0395     Window *window4 = Test::renderAndWaitForShown(surface4.get(), QSize(100, 50), Qt::blue);
0396     QVERIFY(window4);
0397     QVERIFY(window4->isActive());
0398 
0399     window3->move(QPoint(1380, 200));
0400     window4->move(QPoint(1580, 200));
0401 
0402     // Switch to window to the left.
0403     workspace()->switchWindow(Workspace::DirectionWest);
0404     QVERIFY(window3->isActive());
0405 
0406     // Switch to window to the left.
0407     workspace()->switchWindow(Workspace::DirectionWest);
0408     QVERIFY(window2->isActive());
0409 
0410     // Switch to window to the left.
0411     workspace()->switchWindow(Workspace::DirectionWest);
0412     QVERIFY(window4->isActive());
0413 
0414     // Destroy all windows.
0415     shellSurface1.reset();
0416     QVERIFY(Test::waitForWindowDestroyed(window1));
0417     shellSurface2.reset();
0418     QVERIFY(Test::waitForWindowDestroyed(window2));
0419     shellSurface3.reset();
0420     QVERIFY(Test::waitForWindowDestroyed(window3));
0421     shellSurface4.reset();
0422     QVERIFY(Test::waitForWindowDestroyed(window4));
0423 }
0424 
0425 void ActivationTest::testSwitchToWindowFullScreen()
0426 {
0427     // This test verifies that we switch to the top-most fullscreen window, i.e.
0428     // the one that user sees at the moment. See bug 411356.
0429 
0430     // Prepare the test environment.
0431     stackScreensVertically();
0432 
0433     // Create several maximized windows on the top screen.
0434     std::unique_ptr<KWayland::Client::Surface> surface1(Test::createSurface());
0435     std::unique_ptr<Test::XdgToplevel> shellSurface1(Test::createXdgToplevelSurface(surface1.get()));
0436     QSignalSpy toplevelConfigureRequestedSpy1(shellSurface1.get(), &Test::XdgToplevel::configureRequested);
0437     QSignalSpy surfaceConfigureRequestedSpy1(shellSurface1->xdgSurface(), &Test::XdgSurface::configureRequested);
0438     Window *window1 = Test::renderAndWaitForShown(surface1.get(), QSize(100, 50), Qt::blue);
0439     QVERIFY(window1);
0440     QVERIFY(window1->isActive());
0441     QVERIFY(surfaceConfigureRequestedSpy1.wait()); // Wait for the configure event with the activated state.
0442     workspace()->slotWindowFullScreen();
0443     QVERIFY(surfaceConfigureRequestedSpy1.wait());
0444     QSignalSpy frameGeometryChangedSpy1(window1, &Window::frameGeometryChanged);
0445     shellSurface1->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy1.last().at(0).value<quint32>());
0446     Test::render(surface1.get(), toplevelConfigureRequestedSpy1.last().at(0).toSize(), Qt::red);
0447     QVERIFY(frameGeometryChangedSpy1.wait());
0448 
0449     std::unique_ptr<KWayland::Client::Surface> surface2(Test::createSurface());
0450     std::unique_ptr<Test::XdgToplevel> shellSurface2(Test::createXdgToplevelSurface(surface2.get()));
0451     QSignalSpy toplevelConfigureRequestedSpy2(shellSurface2.get(), &Test::XdgToplevel::configureRequested);
0452     QSignalSpy surfaceConfigureRequestedSpy2(shellSurface2->xdgSurface(), &Test::XdgSurface::configureRequested);
0453     Window *window2 = Test::renderAndWaitForShown(surface2.get(), QSize(100, 50), Qt::blue);
0454     QVERIFY(window2);
0455     QVERIFY(window2->isActive());
0456     QVERIFY(surfaceConfigureRequestedSpy2.wait()); // Wait for the configure event with the activated state.
0457     workspace()->slotWindowFullScreen();
0458     QVERIFY(surfaceConfigureRequestedSpy2.wait());
0459     QSignalSpy frameGeometryChangedSpy2(window2, &Window::frameGeometryChanged);
0460     shellSurface2->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy2.last().at(0).value<quint32>());
0461     Test::render(surface2.get(), toplevelConfigureRequestedSpy2.last().at(0).toSize(), Qt::red);
0462     QVERIFY(frameGeometryChangedSpy2.wait());
0463 
0464     const QList<Window *> stackingOrder = workspace()->stackingOrder();
0465     QVERIFY(stackingOrder.indexOf(window1) < stackingOrder.indexOf(window2));
0466     QVERIFY(window1->isFullScreen());
0467     QVERIFY(window2->isFullScreen());
0468 
0469     // Create several windows on the bottom screen.
0470     std::unique_ptr<KWayland::Client::Surface> surface3(Test::createSurface());
0471     std::unique_ptr<Test::XdgToplevel> shellSurface3(Test::createXdgToplevelSurface(surface3.get()));
0472     Window *window3 = Test::renderAndWaitForShown(surface3.get(), QSize(100, 50), Qt::blue);
0473     QVERIFY(window3);
0474     QVERIFY(window3->isActive());
0475 
0476     std::unique_ptr<KWayland::Client::Surface> surface4(Test::createSurface());
0477     std::unique_ptr<Test::XdgToplevel> shellSurface4(Test::createXdgToplevelSurface(surface4.get()));
0478     Window *window4 = Test::renderAndWaitForShown(surface4.get(), QSize(100, 50), Qt::blue);
0479     QVERIFY(window4);
0480     QVERIFY(window4->isActive());
0481 
0482     window3->move(QPoint(200, 1224));
0483     window4->move(QPoint(200, 1424));
0484 
0485     // Switch to window above.
0486     workspace()->switchWindow(Workspace::DirectionNorth);
0487     QVERIFY(window3->isActive());
0488 
0489     // Switch to window above.
0490     workspace()->switchWindow(Workspace::DirectionNorth);
0491     QVERIFY(window2->isActive());
0492 
0493     // Switch to window above.
0494     workspace()->switchWindow(Workspace::DirectionNorth);
0495     QVERIFY(window4->isActive());
0496 
0497     // Destroy all windows.
0498     shellSurface1.reset();
0499     QVERIFY(Test::waitForWindowDestroyed(window1));
0500     shellSurface2.reset();
0501     QVERIFY(Test::waitForWindowDestroyed(window2));
0502     shellSurface3.reset();
0503     QVERIFY(Test::waitForWindowDestroyed(window3));
0504     shellSurface4.reset();
0505     QVERIFY(Test::waitForWindowDestroyed(window4));
0506 }
0507 
0508 void ActivationTest::stackScreensHorizontally()
0509 {
0510     // Process pending wl_output bind requests before destroying all outputs.
0511     QTest::qWait(1);
0512 
0513     const QVector<QRect> screenGeometries{
0514         QRect(0, 0, 1280, 1024),
0515         QRect(1280, 0, 1280, 1024),
0516     };
0517 
0518     QMetaObject::invokeMethod(kwinApp()->outputBackend(),
0519                               "setVirtualOutputs",
0520                               Qt::DirectConnection,
0521                               Q_ARG(QVector<QRect>, screenGeometries));
0522 }
0523 
0524 void ActivationTest::stackScreensVertically()
0525 {
0526     // Process pending wl_output bind requests before destroying all outputs.
0527     QTest::qWait(1);
0528 
0529     const QVector<QRect> screenGeometries{
0530         QRect(0, 0, 1280, 1024),
0531         QRect(0, 1024, 1280, 1024),
0532     };
0533 
0534     QMetaObject::invokeMethod(kwinApp()->outputBackend(),
0535                               "setVirtualOutputs",
0536                               Qt::DirectConnection,
0537                               Q_ARG(QVector<QRect>, screenGeometries));
0538 }
0539 
0540 }
0541 
0542 WAYLANDTEST_MAIN(KWin::ActivationTest)
0543 #include "activation_test.moc"