File indexing completed on 2024-11-10 04:56:07

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