/* KWin - the KDE window manager This file is part of the KDE project. SPDX-FileCopyrightText: 2024 Aleix Pol Gonzalez SPDX-License-Identifier: GPL-2.0-or-later */ #include "kwin_wayland_test.h" #include "pointer_input.h" #include "wayland_server.h" #include "workspace.h" #include #include #include #include using namespace KWin; static const QString s_socketName = QStringLiteral("wayland_test_kwin_buttonrebind-0"); class TestButtonRebind : public QObject { Q_OBJECT private Q_SLOTS: void init(); void cleanup(); void initTestCase(); void testKey_data(); void testKey(); void testMouse_data(); void testMouse(); private: quint32 timestamp = 1; }; void TestButtonRebind::init() { QVERIFY(Test::setupWaylandConnection(Test::AdditionalWaylandInterface::Seat)); QVERIFY(Test::waitForWaylandPointer()); } void TestButtonRebind::cleanup() { Test::destroyWaylandConnection(); QVERIFY(QFile::remove(QStandardPaths::locate(QStandardPaths::ConfigLocation, QStringLiteral("kcminputrc")))); } void TestButtonRebind::initTestCase() { qRegisterMetaType(); QSignalSpy applicationStartedSpy(kwinApp(), &Application::started); QVERIFY(waylandServer()->init(s_socketName)); Test::setOutputConfig({ QRect(0, 0, 1280, 1024), QRect(1280, 0, 1280, 1024), }); kwinApp()->start(); QVERIFY(applicationStartedSpy.wait()); } void TestButtonRebind::testKey_data() { QTest::addColumn("boundKeys"); QTest::addColumn>("expectedKeys"); QTest::newRow("single key") << QKeySequence(Qt::Key_A) << QList{KEY_A}; QTest::newRow("single modifier") << QKeySequence(Qt::Key_Control) << QList{KEY_LEFTCTRL}; QTest::newRow("single modifier plus key") << QKeySequence(Qt::ControlModifier | Qt::Key_N) << QList{KEY_LEFTCTRL, KEY_N}; QTest::newRow("multiple modifiers plus key") << QKeySequence(Qt::ControlModifier | Qt::MetaModifier | Qt::Key_Y) << QList{KEY_LEFTCTRL, KEY_LEFTMETA, KEY_Y}; QTest::newRow("delete") << QKeySequence(Qt::Key_Delete) << QList{KEY_DELETE}; QTest::newRow("keypad delete") << QKeySequence(Qt::KeypadModifier | Qt::Key_Delete) << QList{KEY_KPDOT}; QTest::newRow("keypad enter") << QKeySequence(Qt::KeypadModifier | Qt::Key_Enter) << QList{KEY_KPENTER}; } void TestButtonRebind::testKey() { KConfigGroup buttonGroup = KSharedConfig::openConfig(QStringLiteral("kcminputrc"))->group(QStringLiteral("ButtonRebinds")).group(QStringLiteral("Mouse")); QFETCH(QKeySequence, boundKeys); buttonGroup.writeEntry("ExtraButton7", QStringList{"Key", boundKeys.toString(QKeySequence::PortableText)}, KConfig::Notify); buttonGroup.sync(); std::unique_ptr surface = Test::createSurface(); std::unique_ptr shellSurface = Test::createXdgToplevelSurface(surface.get()); Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue); std::unique_ptr keyboard(Test::waylandSeat()->createKeyboard()); QSignalSpy enteredSpy(keyboard.get(), &KWayland::Client::Keyboard::entered); QSignalSpy keyChangedSpy(keyboard.get(), &KWayland::Client::Keyboard::keyChanged); QVERIFY(enteredSpy.wait()); // 0x119 is Qt::ExtraButton7 Test::pointerButtonPressed(0x119, timestamp++); QVERIFY(keyChangedSpy.wait()); QFETCH(QList, expectedKeys); QCOMPARE(keyChangedSpy.count(), expectedKeys.count()); for (int i = 0; i < keyChangedSpy.count(); i++) { QCOMPARE(keyChangedSpy.at(i).at(0).value(), expectedKeys.at(i)); QCOMPARE(keyChangedSpy.at(i).at(1).value(), KWayland::Client::Keyboard::KeyState::Pressed); } Test::pointerButtonReleased(0x119, timestamp++); } void TestButtonRebind::testMouse_data() { QTest::addColumn("mouseButton"); QTest::newRow("left button") << BTN_LEFT; QTest::newRow("middle button") << BTN_MIDDLE; QTest::newRow("right button") << BTN_RIGHT; } void TestButtonRebind::testMouse() { KConfigGroup buttonGroup = KSharedConfig::openConfig(QStringLiteral("kcminputrc"))->group(QStringLiteral("ButtonRebinds")).group(QStringLiteral("Mouse")); QFETCH(int, mouseButton); buttonGroup.writeEntry("ExtraButton7", QStringList{"MouseButton", QString::number(mouseButton)}, KConfig::Notify); buttonGroup.sync(); std::unique_ptr surface = Test::createSurface(); std::unique_ptr shellSurface = Test::createXdgToplevelSurface(surface.get()); auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue); std::unique_ptr pointer(Test::waylandSeat()->createPointer()); QSignalSpy enteredSpy(pointer.get(), &KWayland::Client::Pointer::entered); QSignalSpy buttonChangedSpy(pointer.get(), &KWayland::Client::Pointer::buttonStateChanged); const QRectF startGeometry = window->frameGeometry(); input()->pointer()->warp(startGeometry.center()); QVERIFY(enteredSpy.wait()); // 0x119 is Qt::ExtraButton7 Test::pointerButtonPressed(0x119, timestamp++); QVERIFY(buttonChangedSpy.wait()); QCOMPARE(buttonChangedSpy.count(), 1); QCOMPARE(buttonChangedSpy.at(0).at(2).value(), mouseButton); Test::pointerButtonReleased(0x119, timestamp++); } WAYLANDTEST_MAIN(TestButtonRebind) #include "buttonrebind_test.moc"