File indexing completed on 2024-11-10 04:55:58
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"