File indexing completed on 2024-05-12 05:30:32

0001 /*
0002     SPDX-FileCopyrightText: 2016 Martin Gräßlin <mgraesslin@kde.org>
0003     SPDX-FileCopyrightText: 2023 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #include "kwin_wayland_test.h"
0009 
0010 #include "core/inputdevice.h"
0011 #include "input.h"
0012 #include "main.h"
0013 #include "wayland_server.h"
0014 
0015 #include <linux/input-event-codes.h>
0016 
0017 namespace KWin
0018 {
0019 
0020 static const QString s_socketName = QStringLiteral("wayland_test_kwin_fakeinput-0");
0021 
0022 class FakeInputTest : public QObject
0023 {
0024     Q_OBJECT
0025 
0026 private Q_SLOTS:
0027     void initTestCase();
0028     void init();
0029     void cleanup();
0030     void testPointerMotion();
0031     void testMotionAbsolute();
0032     void testPointerButton_data();
0033     void testPointerButton();
0034     void testPointerVerticalAxis();
0035     void testPointerHorizontalAxis();
0036     void testTouch();
0037     void testKeyboardKey_data();
0038     void testKeyboardKey();
0039 
0040 private:
0041     InputDevice *m_inputDevice = nullptr;
0042 };
0043 
0044 void FakeInputTest::initTestCase()
0045 {
0046     QSignalSpy applicationStartedSpy(kwinApp(), &Application::started);
0047     QVERIFY(waylandServer()->init(s_socketName));
0048     Test::setOutputConfig({
0049         QRect(0, 0, 1280, 1024),
0050         QRect(1280, 0, 1280, 1024),
0051     });
0052 
0053     kwinApp()->start();
0054     QVERIFY(applicationStartedSpy.wait());
0055 }
0056 
0057 void FakeInputTest::init()
0058 {
0059     QSignalSpy deviceAddedSpy(input(), &InputRedirection::deviceAdded);
0060     QVERIFY(Test::setupWaylandConnection(Test::AdditionalWaylandInterface::FakeInput));
0061 
0062     QVERIFY(deviceAddedSpy.wait());
0063     m_inputDevice = deviceAddedSpy.last().at(0).value<InputDevice *>();
0064 }
0065 
0066 void FakeInputTest::cleanup()
0067 {
0068     Test::destroyWaylandConnection();
0069 }
0070 
0071 void FakeInputTest::testPointerMotion()
0072 {
0073     Test::FakeInput *fakeInput = Test::waylandFakeInput();
0074 
0075     // without an authentication we shouldn't get the signals
0076     QSignalSpy pointerMotionSpy(m_inputDevice, &InputDevice::pointerMotion);
0077     fakeInput->pointer_motion(wl_fixed_from_double(1), wl_fixed_from_double(2));
0078     QVERIFY(Test::waylandSync());
0079     QVERIFY(pointerMotionSpy.isEmpty());
0080 
0081     // now let's authenticate the interface
0082     fakeInput->authenticate(QStringLiteral("org.kde.foobar"), QStringLiteral("foobar"));
0083     fakeInput->pointer_motion(wl_fixed_from_double(1), wl_fixed_from_double(2));
0084     QVERIFY(pointerMotionSpy.wait());
0085     QCOMPARE(pointerMotionSpy.last().first().toPointF(), QPointF(1, 2));
0086 
0087     // just for the fun: once more
0088     fakeInput->pointer_motion(wl_fixed_from_double(0), wl_fixed_from_double(0));
0089     QVERIFY(pointerMotionSpy.wait());
0090     QCOMPARE(pointerMotionSpy.last().first().toPointF(), QPointF(0, 0));
0091 }
0092 
0093 void FakeInputTest::testMotionAbsolute()
0094 {
0095     Test::FakeInput *fakeInput = Test::waylandFakeInput();
0096 
0097     // without an authentication we shouldn't get the signals
0098     QSignalSpy pointerMotionAbsoluteSpy(m_inputDevice, &InputDevice::pointerMotionAbsolute);
0099     fakeInput->pointer_motion_absolute(wl_fixed_from_double(1), wl_fixed_from_double(2));
0100     QVERIFY(Test::waylandSync());
0101     QVERIFY(pointerMotionAbsoluteSpy.isEmpty());
0102 
0103     // now let's authenticate the interface
0104     fakeInput->authenticate(QStringLiteral("org.kde.foobar"), QStringLiteral("foobar"));
0105     fakeInput->pointer_motion_absolute(wl_fixed_from_double(1), wl_fixed_from_double(2));
0106     QVERIFY(pointerMotionAbsoluteSpy.wait());
0107     QCOMPARE(pointerMotionAbsoluteSpy.last().first().toPointF(), QPointF(1, 2));
0108 }
0109 
0110 void FakeInputTest::testPointerButton_data()
0111 {
0112     QTest::addColumn<quint32>("linuxButton");
0113 
0114     QTest::newRow("left") << quint32(BTN_LEFT);
0115     QTest::newRow("right") << quint32(BTN_RIGHT);
0116     QTest::newRow("middle") << quint32(BTN_MIDDLE);
0117     QTest::newRow("side") << quint32(BTN_SIDE);
0118     QTest::newRow("extra") << quint32(BTN_EXTRA);
0119     QTest::newRow("forward") << quint32(BTN_FORWARD);
0120     QTest::newRow("back") << quint32(BTN_BACK);
0121     QTest::newRow("task") << quint32(BTN_TASK);
0122 }
0123 
0124 void FakeInputTest::testPointerButton()
0125 {
0126     Test::FakeInput *fakeInput = Test::waylandFakeInput();
0127 
0128     // without an authentication we shouldn't get the signals
0129     QSignalSpy pointerButtonSpy(m_inputDevice, &InputDevice::pointerButtonChanged);
0130     QFETCH(quint32, linuxButton);
0131     fakeInput->button(linuxButton, WL_POINTER_BUTTON_STATE_PRESSED);
0132     QVERIFY(Test::waylandSync());
0133     QVERIFY(pointerButtonSpy.isEmpty());
0134 
0135     // now authenticate
0136     fakeInput->authenticate(QStringLiteral("org.kde.foobar"), QStringLiteral("foobar"));
0137     fakeInput->button(linuxButton, WL_POINTER_BUTTON_STATE_PRESSED);
0138     QVERIFY(pointerButtonSpy.wait());
0139     QCOMPARE(pointerButtonSpy.last().at(0).value<quint32>(), linuxButton);
0140     QCOMPARE(pointerButtonSpy.last().at(1).value<InputRedirection::PointerButtonState>(), InputRedirection::PointerButtonPressed);
0141 
0142     // and release
0143     fakeInput->button(linuxButton, WL_POINTER_BUTTON_STATE_RELEASED);
0144     QVERIFY(pointerButtonSpy.wait());
0145     QCOMPARE(pointerButtonSpy.last().at(0).value<quint32>(), linuxButton);
0146     QCOMPARE(pointerButtonSpy.last().at(1).value<InputRedirection::PointerButtonState>(), InputRedirection::PointerButtonReleased);
0147 }
0148 
0149 void FakeInputTest::testPointerVerticalAxis()
0150 {
0151     Test::FakeInput *fakeInput = Test::waylandFakeInput();
0152 
0153     // without an authentication we shouldn't get the signals
0154     QSignalSpy pointerAxisSpy(m_inputDevice, &InputDevice::pointerAxisChanged);
0155     fakeInput->axis(WL_POINTER_AXIS_VERTICAL_SCROLL, wl_fixed_from_double(15));
0156     QVERIFY(Test::waylandSync());
0157     QVERIFY(pointerAxisSpy.isEmpty());
0158 
0159     // now authenticate
0160     fakeInput->authenticate(QStringLiteral("org.kde.foobar"), QStringLiteral("foobar"));
0161     fakeInput->axis(WL_POINTER_AXIS_VERTICAL_SCROLL, wl_fixed_from_double(15));
0162     QVERIFY(pointerAxisSpy.wait());
0163     QCOMPARE(pointerAxisSpy.last().at(0).value<InputRedirection::PointerAxis>(), InputRedirection::PointerAxisVertical);
0164     QCOMPARE(pointerAxisSpy.last().at(1).value<qreal>(), 15);
0165 }
0166 
0167 void FakeInputTest::testPointerHorizontalAxis()
0168 {
0169     Test::FakeInput *fakeInput = Test::waylandFakeInput();
0170 
0171     // without an authentication we shouldn't get the signals
0172     QSignalSpy pointerAxisSpy(m_inputDevice, &InputDevice::pointerAxisChanged);
0173     fakeInput->axis(WL_POINTER_AXIS_HORIZONTAL_SCROLL, wl_fixed_from_double(15));
0174     QVERIFY(Test::waylandSync());
0175     QVERIFY(pointerAxisSpy.isEmpty());
0176 
0177     // now authenticate
0178     fakeInput->authenticate(QStringLiteral("org.kde.foobar"), QStringLiteral("foobar"));
0179     fakeInput->axis(WL_POINTER_AXIS_HORIZONTAL_SCROLL, wl_fixed_from_double(15));
0180     QVERIFY(pointerAxisSpy.wait());
0181     QCOMPARE(pointerAxisSpy.last().at(0).value<InputRedirection::PointerAxis>(), InputRedirection::PointerAxisHorizontal);
0182     QCOMPARE(pointerAxisSpy.last().at(1).value<qreal>(), 15);
0183 }
0184 
0185 void FakeInputTest::testTouch()
0186 {
0187     Test::FakeInput *fakeInput = Test::waylandFakeInput();
0188 
0189     // without an authentication we shouldn't get the signals
0190     QSignalSpy touchDownSpy(m_inputDevice, &InputDevice::touchDown);
0191     QSignalSpy touchUpSpy(m_inputDevice, &InputDevice::touchUp);
0192     QSignalSpy touchMotionSpy(m_inputDevice, &InputDevice::touchMotion);
0193     QSignalSpy touchFrameSpy(m_inputDevice, &InputDevice::touchFrame);
0194     QSignalSpy touchCanceledSpy(m_inputDevice, &InputDevice::touchCanceled);
0195     fakeInput->touch_down(0, wl_fixed_from_double(1), wl_fixed_from_double(2));
0196     QVERIFY(Test::waylandSync());
0197     QVERIFY(touchDownSpy.isEmpty());
0198 
0199     fakeInput->touch_motion(0, wl_fixed_from_double(3), wl_fixed_from_double(4));
0200     QVERIFY(Test::waylandSync());
0201     QVERIFY(touchMotionSpy.isEmpty());
0202 
0203     fakeInput->touch_up(0);
0204     QVERIFY(Test::waylandSync());
0205     QVERIFY(touchUpSpy.isEmpty());
0206 
0207     fakeInput->touch_down(1, wl_fixed_from_double(5), wl_fixed_from_double(6));
0208     QVERIFY(Test::waylandSync());
0209     QVERIFY(touchDownSpy.isEmpty());
0210 
0211     fakeInput->touch_frame();
0212     QVERIFY(Test::waylandSync());
0213     QVERIFY(touchFrameSpy.isEmpty());
0214 
0215     fakeInput->touch_cancel();
0216     QVERIFY(Test::waylandSync());
0217     QVERIFY(touchCanceledSpy.isEmpty());
0218 
0219     // now let's authenticate the interface
0220     fakeInput->authenticate(QStringLiteral("org.kde.foobar"), QStringLiteral("foobar"));
0221     fakeInput->touch_down(0, wl_fixed_from_double(1), wl_fixed_from_double(2));
0222     QVERIFY(touchDownSpy.wait());
0223     QCOMPARE(touchDownSpy.count(), 1);
0224     QCOMPARE(touchDownSpy.last().at(0).value<quint32>(), quint32(0));
0225     QCOMPARE(touchDownSpy.last().at(1).toPointF(), QPointF(1, 2));
0226 
0227     // Same id should not trigger another touchDown.
0228     fakeInput->touch_down(0, wl_fixed_from_double(5), wl_fixed_from_double(6));
0229     QVERIFY(Test::waylandSync());
0230     QCOMPARE(touchDownSpy.count(), 1);
0231 
0232     fakeInput->touch_motion(0, wl_fixed_from_double(3), wl_fixed_from_double(4));
0233     QVERIFY(touchMotionSpy.wait());
0234     QCOMPARE(touchMotionSpy.count(), 1);
0235     QCOMPARE(touchMotionSpy.last().at(0).value<quint32>(), quint32(0));
0236     QCOMPARE(touchMotionSpy.last().at(1).toPointF(), QPointF(3, 4));
0237 
0238     // touchMotion with bogus id should not trigger signal.
0239     fakeInput->touch_motion(1, wl_fixed_from_double(3), wl_fixed_from_double(4));
0240     QVERIFY(Test::waylandSync());
0241     QCOMPARE(touchMotionSpy.count(), 1);
0242 
0243     fakeInput->touch_up(0);
0244     QVERIFY(touchUpSpy.wait());
0245     QCOMPARE(touchUpSpy.count(), 1);
0246     QCOMPARE(touchUpSpy.last().at(0).value<quint32>(), quint32(0));
0247 
0248     // touchUp with bogus id should not trigger signal.
0249     fakeInput->touch_up(1);
0250     QVERIFY(Test::waylandSync());
0251     QCOMPARE(touchUpSpy.count(), 1);
0252 
0253     fakeInput->touch_down(1, wl_fixed_from_double(5), wl_fixed_from_double(6));
0254     QVERIFY(touchDownSpy.wait());
0255     QCOMPARE(touchDownSpy.count(), 2);
0256     QCOMPARE(touchDownSpy.last().at(0).value<quint32>(), quint32(1));
0257     QCOMPARE(touchDownSpy.last().at(1).toPointF(), QPointF(5, 6));
0258 
0259     fakeInput->touch_frame();
0260     QVERIFY(touchFrameSpy.wait());
0261     QCOMPARE(touchFrameSpy.count(), 1);
0262 
0263     fakeInput->touch_cancel();
0264     QVERIFY(touchCanceledSpy.wait());
0265     QCOMPARE(touchCanceledSpy.count(), 1);
0266 }
0267 
0268 void FakeInputTest::testKeyboardKey_data()
0269 {
0270     QTest::addColumn<quint32>("linuxKey");
0271 
0272     QTest::newRow("A") << quint32(KEY_A);
0273     QTest::newRow("S") << quint32(KEY_S);
0274     QTest::newRow("D") << quint32(KEY_D);
0275     QTest::newRow("F") << quint32(KEY_F);
0276 }
0277 
0278 void FakeInputTest::testKeyboardKey()
0279 {
0280     Test::FakeInput *fakeInput = Test::waylandFakeInput();
0281 
0282     // without an authentication we shouldn't get the signals
0283     QSignalSpy keyboardKeySpy(m_inputDevice, &InputDevice::keyChanged);
0284     QFETCH(quint32, linuxKey);
0285     fakeInput->keyboard_key(linuxKey, WL_KEYBOARD_KEY_STATE_PRESSED);
0286     QVERIFY(Test::waylandSync());
0287     QVERIFY(keyboardKeySpy.isEmpty());
0288 
0289     // now authenticate
0290     fakeInput->authenticate(QStringLiteral("org.kde.foobar"), QStringLiteral("foobar"));
0291     fakeInput->keyboard_key(linuxKey, WL_KEYBOARD_KEY_STATE_PRESSED);
0292     QVERIFY(keyboardKeySpy.wait());
0293     QCOMPARE(keyboardKeySpy.last().at(0).value<quint32>(), linuxKey);
0294     QCOMPARE(keyboardKeySpy.last().at(1).value<InputRedirection::KeyboardKeyState>(), InputRedirection::KeyboardKeyPressed);
0295 
0296     // and release
0297     fakeInput->keyboard_key(linuxKey, WL_KEYBOARD_KEY_STATE_RELEASED);
0298     QVERIFY(keyboardKeySpy.wait());
0299     QCOMPARE(keyboardKeySpy.last().at(0).value<quint32>(), linuxKey);
0300     QCOMPARE(keyboardKeySpy.last().at(1).value<InputRedirection::KeyboardKeyState>(), InputRedirection::KeyboardKeyReleased);
0301 }
0302 
0303 } // namespace KWin
0304 
0305 WAYLANDTEST_MAIN(KWin::FakeInputTest)
0306 #include "fakeinput_test.moc"