File indexing completed on 2024-05-05 17:36:00

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 2016 Martin Gräßlin <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 "cursor.h"
0013 #include "input.h"
0014 #include "tabbox/tabbox.h"
0015 #include "wayland_server.h"
0016 #include "window.h"
0017 #include "workspace.h"
0018 
0019 #include <KConfigGroup>
0020 #include <KWayland/Client/surface.h>
0021 
0022 #include <linux/input.h>
0023 
0024 using namespace KWin;
0025 
0026 static const QString s_socketName = QStringLiteral("wayland_test_kwin_tabbox-0");
0027 
0028 class TabBoxTest : public QObject
0029 {
0030     Q_OBJECT
0031 private Q_SLOTS:
0032     void initTestCase();
0033     void init();
0034     void cleanup();
0035 
0036     void testMoveForward();
0037     void testMoveBackward();
0038     void testCapsLock();
0039 };
0040 
0041 void TabBoxTest::initTestCase()
0042 {
0043     qRegisterMetaType<KWin::Window *>();
0044     QSignalSpy applicationStartedSpy(kwinApp(), &Application::started);
0045     QVERIFY(waylandServer()->init(s_socketName));
0046     QMetaObject::invokeMethod(kwinApp()->outputBackend(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(QVector<QRect>, QVector<QRect>() << QRect(0, 0, 1280, 1024) << QRect(1280, 0, 1280, 1024)));
0047 
0048     KSharedConfigPtr c = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig);
0049     c->group("TabBox").writeEntry("ShowTabBox", false);
0050     c->sync();
0051     kwinApp()->setConfig(c);
0052     qputenv("KWIN_XKB_DEFAULT_KEYMAP", "1");
0053 
0054     kwinApp()->start();
0055     QVERIFY(applicationStartedSpy.wait());
0056 }
0057 
0058 void TabBoxTest::init()
0059 {
0060     QVERIFY(Test::setupWaylandConnection());
0061     workspace()->setActiveOutput(QPoint(640, 512));
0062     KWin::Cursors::self()->mouse()->setPos(QPoint(640, 512));
0063 }
0064 
0065 void TabBoxTest::cleanup()
0066 {
0067     Test::destroyWaylandConnection();
0068 }
0069 
0070 void TabBoxTest::testCapsLock()
0071 {
0072     // this test verifies that Alt+tab works correctly also when Capslock is on
0073     // bug 368590
0074 
0075     // first create three windows
0076     std::unique_ptr<KWayland::Client::Surface> surface1(Test::createSurface());
0077     std::unique_ptr<Test::XdgToplevel> shellSurface1(Test::createXdgToplevelSurface(surface1.get()));
0078     auto c1 = Test::renderAndWaitForShown(surface1.get(), QSize(100, 50), Qt::blue);
0079     QVERIFY(c1);
0080     QVERIFY(c1->isActive());
0081     std::unique_ptr<KWayland::Client::Surface> surface2(Test::createSurface());
0082     std::unique_ptr<Test::XdgToplevel> shellSurface2(Test::createXdgToplevelSurface(surface2.get()));
0083     auto c2 = Test::renderAndWaitForShown(surface2.get(), QSize(100, 50), Qt::red);
0084     QVERIFY(c2);
0085     QVERIFY(c2->isActive());
0086     std::unique_ptr<KWayland::Client::Surface> surface3(Test::createSurface());
0087     std::unique_ptr<Test::XdgToplevel> shellSurface3(Test::createXdgToplevelSurface(surface3.get()));
0088     auto c3 = Test::renderAndWaitForShown(surface3.get(), QSize(100, 50), Qt::red);
0089     QVERIFY(c3);
0090     QVERIFY(c3->isActive());
0091 
0092     // Setup tabbox signal spies
0093     QSignalSpy tabboxAddedSpy(workspace()->tabbox(), &TabBox::TabBox::tabBoxAdded);
0094     QSignalSpy tabboxClosedSpy(workspace()->tabbox(), &TabBox::TabBox::tabBoxClosed);
0095 
0096     // enable capslock
0097     quint32 timestamp = 0;
0098     Test::keyboardKeyPressed(KEY_CAPSLOCK, timestamp++);
0099     Test::keyboardKeyReleased(KEY_CAPSLOCK, timestamp++);
0100     QCOMPARE(input()->keyboardModifiers(), Qt::ShiftModifier);
0101 
0102     // press alt+tab
0103     Test::keyboardKeyPressed(KEY_LEFTALT, timestamp++);
0104     QCOMPARE(input()->keyboardModifiers(), Qt::ShiftModifier | Qt::AltModifier);
0105     Test::keyboardKeyPressed(KEY_TAB, timestamp++);
0106     Test::keyboardKeyReleased(KEY_TAB, timestamp++);
0107 
0108     QVERIFY(tabboxAddedSpy.wait());
0109     QVERIFY(workspace()->tabbox()->isGrabbed());
0110 
0111     // release alt
0112     Test::keyboardKeyReleased(KEY_LEFTALT, timestamp++);
0113     QCOMPARE(tabboxClosedSpy.count(), 1);
0114     QCOMPARE(workspace()->tabbox()->isGrabbed(), false);
0115 
0116     // release caps lock
0117     Test::keyboardKeyPressed(KEY_CAPSLOCK, timestamp++);
0118     Test::keyboardKeyReleased(KEY_CAPSLOCK, timestamp++);
0119     QCOMPARE(input()->keyboardModifiers(), Qt::NoModifier);
0120     QCOMPARE(tabboxClosedSpy.count(), 1);
0121     QCOMPARE(workspace()->tabbox()->isGrabbed(), false);
0122     QCOMPARE(workspace()->activeWindow(), c2);
0123 
0124     surface3.reset();
0125     QVERIFY(Test::waitForWindowDestroyed(c3));
0126     surface2.reset();
0127     QVERIFY(Test::waitForWindowDestroyed(c2));
0128     surface1.reset();
0129     QVERIFY(Test::waitForWindowDestroyed(c1));
0130 }
0131 
0132 void TabBoxTest::testMoveForward()
0133 {
0134     // this test verifies that Alt+tab works correctly moving forward
0135 
0136     // first create three windows
0137     std::unique_ptr<KWayland::Client::Surface> surface1(Test::createSurface());
0138     std::unique_ptr<Test::XdgToplevel> shellSurface1(Test::createXdgToplevelSurface(surface1.get()));
0139     auto c1 = Test::renderAndWaitForShown(surface1.get(), QSize(100, 50), Qt::blue);
0140     QVERIFY(c1);
0141     QVERIFY(c1->isActive());
0142     std::unique_ptr<KWayland::Client::Surface> surface2(Test::createSurface());
0143     std::unique_ptr<Test::XdgToplevel> shellSurface2(Test::createXdgToplevelSurface(surface2.get()));
0144     auto c2 = Test::renderAndWaitForShown(surface2.get(), QSize(100, 50), Qt::red);
0145     QVERIFY(c2);
0146     QVERIFY(c2->isActive());
0147     std::unique_ptr<KWayland::Client::Surface> surface3(Test::createSurface());
0148     std::unique_ptr<Test::XdgToplevel> shellSurface3(Test::createXdgToplevelSurface(surface3.get()));
0149     auto c3 = Test::renderAndWaitForShown(surface3.get(), QSize(100, 50), Qt::red);
0150     QVERIFY(c3);
0151     QVERIFY(c3->isActive());
0152 
0153     // Setup tabbox signal spies
0154     QSignalSpy tabboxAddedSpy(workspace()->tabbox(), &TabBox::TabBox::tabBoxAdded);
0155     QSignalSpy tabboxClosedSpy(workspace()->tabbox(), &TabBox::TabBox::tabBoxClosed);
0156 
0157     // press alt+tab
0158     quint32 timestamp = 0;
0159     Test::keyboardKeyPressed(KEY_LEFTALT, timestamp++);
0160     QCOMPARE(input()->keyboardModifiers(), Qt::AltModifier);
0161     Test::keyboardKeyPressed(KEY_TAB, timestamp++);
0162     Test::keyboardKeyReleased(KEY_TAB, timestamp++);
0163 
0164     QVERIFY(tabboxAddedSpy.wait());
0165     QVERIFY(workspace()->tabbox()->isGrabbed());
0166 
0167     // release alt
0168     Test::keyboardKeyReleased(KEY_LEFTALT, timestamp++);
0169     QCOMPARE(tabboxClosedSpy.count(), 1);
0170     QCOMPARE(workspace()->tabbox()->isGrabbed(), false);
0171     QCOMPARE(workspace()->activeWindow(), c2);
0172 
0173     surface3.reset();
0174     QVERIFY(Test::waitForWindowDestroyed(c3));
0175     surface2.reset();
0176     QVERIFY(Test::waitForWindowDestroyed(c2));
0177     surface1.reset();
0178     QVERIFY(Test::waitForWindowDestroyed(c1));
0179 }
0180 
0181 void TabBoxTest::testMoveBackward()
0182 {
0183     // this test verifies that Alt+Shift+tab works correctly moving backward
0184 
0185     // first create three windows
0186     std::unique_ptr<KWayland::Client::Surface> surface1(Test::createSurface());
0187     std::unique_ptr<Test::XdgToplevel> shellSurface1(Test::createXdgToplevelSurface(surface1.get()));
0188     auto c1 = Test::renderAndWaitForShown(surface1.get(), QSize(100, 50), Qt::blue);
0189     QVERIFY(c1);
0190     QVERIFY(c1->isActive());
0191     std::unique_ptr<KWayland::Client::Surface> surface2(Test::createSurface());
0192     std::unique_ptr<Test::XdgToplevel> shellSurface2(Test::createXdgToplevelSurface(surface2.get()));
0193     auto c2 = Test::renderAndWaitForShown(surface2.get(), QSize(100, 50), Qt::red);
0194     QVERIFY(c2);
0195     QVERIFY(c2->isActive());
0196     std::unique_ptr<KWayland::Client::Surface> surface3(Test::createSurface());
0197     std::unique_ptr<Test::XdgToplevel> shellSurface3(Test::createXdgToplevelSurface(surface3.get()));
0198     auto c3 = Test::renderAndWaitForShown(surface3.get(), QSize(100, 50), Qt::red);
0199     QVERIFY(c3);
0200     QVERIFY(c3->isActive());
0201 
0202     // Setup tabbox signal spies
0203     QSignalSpy tabboxAddedSpy(workspace()->tabbox(), &TabBox::TabBox::tabBoxAdded);
0204     QSignalSpy tabboxClosedSpy(workspace()->tabbox(), &TabBox::TabBox::tabBoxClosed);
0205 
0206     // press alt+shift+tab
0207     quint32 timestamp = 0;
0208     Test::keyboardKeyPressed(KEY_LEFTALT, timestamp++);
0209     QCOMPARE(input()->keyboardModifiers(), Qt::AltModifier);
0210     Test::keyboardKeyPressed(KEY_LEFTSHIFT, timestamp++);
0211     QCOMPARE(input()->keyboardModifiers(), Qt::AltModifier | Qt::ShiftModifier);
0212     Test::keyboardKeyPressed(KEY_TAB, timestamp++);
0213     Test::keyboardKeyReleased(KEY_TAB, timestamp++);
0214 
0215     QVERIFY(tabboxAddedSpy.wait());
0216     QVERIFY(workspace()->tabbox()->isGrabbed());
0217 
0218     // release alt
0219     Test::keyboardKeyReleased(KEY_LEFTSHIFT, timestamp++);
0220     QCOMPARE(tabboxClosedSpy.count(), 0);
0221     Test::keyboardKeyReleased(KEY_LEFTALT, timestamp++);
0222     QCOMPARE(tabboxClosedSpy.count(), 1);
0223     QCOMPARE(workspace()->tabbox()->isGrabbed(), false);
0224     QCOMPARE(workspace()->activeWindow(), c1);
0225 
0226     surface3.reset();
0227     QVERIFY(Test::waitForWindowDestroyed(c3));
0228     surface2.reset();
0229     QVERIFY(Test::waitForWindowDestroyed(c2));
0230     surface1.reset();
0231     QVERIFY(Test::waitForWindowDestroyed(c1));
0232 }
0233 
0234 WAYLANDTEST_MAIN(TabBoxTest)
0235 #include "tabbox_test.moc"