KWin
Loading...
Searching...
No Matches
fakeinput_test.cpp
Go to the documentation of this file.
1/*
2 SPDX-FileCopyrightText: 2016 Martin Gräßlin <mgraesslin@kde.org>
3 SPDX-FileCopyrightText: 2023 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
4
5 SPDX-License-Identifier: GPL-2.0-or-later
6*/
7
8#include "kwin_wayland_test.h"
9
10#include "core/inputdevice.h"
11#include "input.h"
12#include "main.h"
13#include "wayland_server.h"
14
15#include <linux/input-event-codes.h>
16
17namespace KWin
18{
19
20static const QString s_socketName = QStringLiteral("wayland_test_kwin_fakeinput-0");
21
22class FakeInputTest : public QObject
23{
24 Q_OBJECT
25
26private Q_SLOTS:
27 void initTestCase();
28 void init();
29 void cleanup();
30 void testPointerMotion();
31 void testMotionAbsolute();
32 void testPointerButton_data();
33 void testPointerButton();
34 void testPointerVerticalAxis();
35 void testPointerHorizontalAxis();
36 void testTouch();
37 void testKeyboardKey_data();
38 void testKeyboardKey();
39
40private:
41 InputDevice *m_inputDevice = nullptr;
42};
43
44void FakeInputTest::initTestCase()
45{
46 QSignalSpy applicationStartedSpy(kwinApp(), &Application::started);
47 QVERIFY(waylandServer()->init(s_socketName));
49 QRect(0, 0, 1280, 1024),
50 QRect(1280, 0, 1280, 1024),
51 });
52
53 kwinApp()->start();
54 QVERIFY(applicationStartedSpy.wait());
55}
56
57void FakeInputTest::init()
58{
59 QSignalSpy deviceAddedSpy(input(), &InputRedirection::deviceAdded);
61
62 QVERIFY(deviceAddedSpy.wait());
63 m_inputDevice = deviceAddedSpy.last().at(0).value<InputDevice *>();
64}
65
66void FakeInputTest::cleanup()
67{
69}
70
71void FakeInputTest::testPointerMotion()
72{
74
75 // without an authentication we shouldn't get the signals
76 QSignalSpy pointerMotionSpy(m_inputDevice, &InputDevice::pointerMotion);
77 fakeInput->pointer_motion(wl_fixed_from_double(1), wl_fixed_from_double(2));
78 QVERIFY(Test::waylandSync());
79 QVERIFY(pointerMotionSpy.isEmpty());
80
81 // now let's authenticate the interface
82 fakeInput->authenticate(QStringLiteral("org.kde.foobar"), QStringLiteral("foobar"));
83 fakeInput->pointer_motion(wl_fixed_from_double(1), wl_fixed_from_double(2));
84 QVERIFY(pointerMotionSpy.wait());
85 QCOMPARE(pointerMotionSpy.last().first().toPointF(), QPointF(1, 2));
86
87 // just for the fun: once more
88 fakeInput->pointer_motion(wl_fixed_from_double(0), wl_fixed_from_double(0));
89 QVERIFY(pointerMotionSpy.wait());
90 QCOMPARE(pointerMotionSpy.last().first().toPointF(), QPointF(0, 0));
91}
92
93void FakeInputTest::testMotionAbsolute()
94{
96
97 // without an authentication we shouldn't get the signals
98 QSignalSpy pointerMotionAbsoluteSpy(m_inputDevice, &InputDevice::pointerMotionAbsolute);
99 fakeInput->pointer_motion_absolute(wl_fixed_from_double(1), wl_fixed_from_double(2));
100 QVERIFY(Test::waylandSync());
101 QVERIFY(pointerMotionAbsoluteSpy.isEmpty());
102
103 // now let's authenticate the interface
104 fakeInput->authenticate(QStringLiteral("org.kde.foobar"), QStringLiteral("foobar"));
105 fakeInput->pointer_motion_absolute(wl_fixed_from_double(1), wl_fixed_from_double(2));
106 QVERIFY(pointerMotionAbsoluteSpy.wait());
107 QCOMPARE(pointerMotionAbsoluteSpy.last().first().toPointF(), QPointF(1, 2));
108}
109
110void FakeInputTest::testPointerButton_data()
111{
112 QTest::addColumn<quint32>("linuxButton");
113
114 QTest::newRow("left") << quint32(BTN_LEFT);
115 QTest::newRow("right") << quint32(BTN_RIGHT);
116 QTest::newRow("middle") << quint32(BTN_MIDDLE);
117 QTest::newRow("side") << quint32(BTN_SIDE);
118 QTest::newRow("extra") << quint32(BTN_EXTRA);
119 QTest::newRow("forward") << quint32(BTN_FORWARD);
120 QTest::newRow("back") << quint32(BTN_BACK);
121 QTest::newRow("task") << quint32(BTN_TASK);
122}
123
124void FakeInputTest::testPointerButton()
125{
127
128 // without an authentication we shouldn't get the signals
129 QSignalSpy pointerButtonSpy(m_inputDevice, &InputDevice::pointerButtonChanged);
130 QFETCH(quint32, linuxButton);
131 fakeInput->button(linuxButton, WL_POINTER_BUTTON_STATE_PRESSED);
132 QVERIFY(Test::waylandSync());
133 QVERIFY(pointerButtonSpy.isEmpty());
134
135 // now authenticate
136 fakeInput->authenticate(QStringLiteral("org.kde.foobar"), QStringLiteral("foobar"));
137 fakeInput->button(linuxButton, WL_POINTER_BUTTON_STATE_PRESSED);
138 QVERIFY(pointerButtonSpy.wait());
139 QCOMPARE(pointerButtonSpy.last().at(0).value<quint32>(), linuxButton);
140 QCOMPARE(pointerButtonSpy.last().at(1).value<InputRedirection::PointerButtonState>(), InputRedirection::PointerButtonPressed);
141
142 // and release
143 fakeInput->button(linuxButton, WL_POINTER_BUTTON_STATE_RELEASED);
144 QVERIFY(pointerButtonSpy.wait());
145 QCOMPARE(pointerButtonSpy.last().at(0).value<quint32>(), linuxButton);
146 QCOMPARE(pointerButtonSpy.last().at(1).value<InputRedirection::PointerButtonState>(), InputRedirection::PointerButtonReleased);
147}
148
149void FakeInputTest::testPointerVerticalAxis()
150{
152
153 // without an authentication we shouldn't get the signals
154 QSignalSpy pointerAxisSpy(m_inputDevice, &InputDevice::pointerAxisChanged);
155 fakeInput->axis(WL_POINTER_AXIS_VERTICAL_SCROLL, wl_fixed_from_double(15));
156 QVERIFY(Test::waylandSync());
157 QVERIFY(pointerAxisSpy.isEmpty());
158
159 // now authenticate
160 fakeInput->authenticate(QStringLiteral("org.kde.foobar"), QStringLiteral("foobar"));
161 fakeInput->axis(WL_POINTER_AXIS_VERTICAL_SCROLL, wl_fixed_from_double(15));
162 QVERIFY(pointerAxisSpy.wait());
163 QCOMPARE(pointerAxisSpy.last().at(0).value<InputRedirection::PointerAxis>(), InputRedirection::PointerAxisVertical);
164 QCOMPARE(pointerAxisSpy.last().at(1).value<qreal>(), 15);
165}
166
167void FakeInputTest::testPointerHorizontalAxis()
168{
170
171 // without an authentication we shouldn't get the signals
172 QSignalSpy pointerAxisSpy(m_inputDevice, &InputDevice::pointerAxisChanged);
173 fakeInput->axis(WL_POINTER_AXIS_HORIZONTAL_SCROLL, wl_fixed_from_double(15));
174 QVERIFY(Test::waylandSync());
175 QVERIFY(pointerAxisSpy.isEmpty());
176
177 // now authenticate
178 fakeInput->authenticate(QStringLiteral("org.kde.foobar"), QStringLiteral("foobar"));
179 fakeInput->axis(WL_POINTER_AXIS_HORIZONTAL_SCROLL, wl_fixed_from_double(15));
180 QVERIFY(pointerAxisSpy.wait());
181 QCOMPARE(pointerAxisSpy.last().at(0).value<InputRedirection::PointerAxis>(), InputRedirection::PointerAxisHorizontal);
182 QCOMPARE(pointerAxisSpy.last().at(1).value<qreal>(), 15);
183}
184
185void FakeInputTest::testTouch()
186{
188
189 // without an authentication we shouldn't get the signals
190 QSignalSpy touchDownSpy(m_inputDevice, &InputDevice::touchDown);
191 QSignalSpy touchUpSpy(m_inputDevice, &InputDevice::touchUp);
192 QSignalSpy touchMotionSpy(m_inputDevice, &InputDevice::touchMotion);
193 QSignalSpy touchFrameSpy(m_inputDevice, &InputDevice::touchFrame);
194 QSignalSpy touchCanceledSpy(m_inputDevice, &InputDevice::touchCanceled);
195 fakeInput->touch_down(0, wl_fixed_from_double(1), wl_fixed_from_double(2));
196 QVERIFY(Test::waylandSync());
197 QVERIFY(touchDownSpy.isEmpty());
198
199 fakeInput->touch_motion(0, wl_fixed_from_double(3), wl_fixed_from_double(4));
200 QVERIFY(Test::waylandSync());
201 QVERIFY(touchMotionSpy.isEmpty());
202
203 fakeInput->touch_up(0);
204 QVERIFY(Test::waylandSync());
205 QVERIFY(touchUpSpy.isEmpty());
206
207 fakeInput->touch_down(1, wl_fixed_from_double(5), wl_fixed_from_double(6));
208 QVERIFY(Test::waylandSync());
209 QVERIFY(touchDownSpy.isEmpty());
210
211 fakeInput->touch_frame();
212 QVERIFY(Test::waylandSync());
213 QVERIFY(touchFrameSpy.isEmpty());
214
215 fakeInput->touch_cancel();
216 QVERIFY(Test::waylandSync());
217 QVERIFY(touchCanceledSpy.isEmpty());
218
219 // now let's authenticate the interface
220 fakeInput->authenticate(QStringLiteral("org.kde.foobar"), QStringLiteral("foobar"));
221 fakeInput->touch_down(0, wl_fixed_from_double(1), wl_fixed_from_double(2));
222 QVERIFY(touchDownSpy.wait());
223 QCOMPARE(touchDownSpy.count(), 1);
224 QCOMPARE(touchDownSpy.last().at(0).value<quint32>(), quint32(0));
225 QCOMPARE(touchDownSpy.last().at(1).toPointF(), QPointF(1, 2));
226
227 // Same id should not trigger another touchDown.
228 fakeInput->touch_down(0, wl_fixed_from_double(5), wl_fixed_from_double(6));
229 QVERIFY(Test::waylandSync());
230 QCOMPARE(touchDownSpy.count(), 1);
231
232 fakeInput->touch_motion(0, wl_fixed_from_double(3), wl_fixed_from_double(4));
233 QVERIFY(touchMotionSpy.wait());
234 QCOMPARE(touchMotionSpy.count(), 1);
235 QCOMPARE(touchMotionSpy.last().at(0).value<quint32>(), quint32(0));
236 QCOMPARE(touchMotionSpy.last().at(1).toPointF(), QPointF(3, 4));
237
238 // touchMotion with bogus id should not trigger signal.
239 fakeInput->touch_motion(1, wl_fixed_from_double(3), wl_fixed_from_double(4));
240 QVERIFY(Test::waylandSync());
241 QCOMPARE(touchMotionSpy.count(), 1);
242
243 fakeInput->touch_up(0);
244 QVERIFY(touchUpSpy.wait());
245 QCOMPARE(touchUpSpy.count(), 1);
246 QCOMPARE(touchUpSpy.last().at(0).value<quint32>(), quint32(0));
247
248 // touchUp with bogus id should not trigger signal.
249 fakeInput->touch_up(1);
250 QVERIFY(Test::waylandSync());
251 QCOMPARE(touchUpSpy.count(), 1);
252
253 fakeInput->touch_down(1, wl_fixed_from_double(5), wl_fixed_from_double(6));
254 QVERIFY(touchDownSpy.wait());
255 QCOMPARE(touchDownSpy.count(), 2);
256 QCOMPARE(touchDownSpy.last().at(0).value<quint32>(), quint32(1));
257 QCOMPARE(touchDownSpy.last().at(1).toPointF(), QPointF(5, 6));
258
259 fakeInput->touch_frame();
260 QVERIFY(touchFrameSpy.wait());
261 QCOMPARE(touchFrameSpy.count(), 1);
262
263 fakeInput->touch_cancel();
264 QVERIFY(touchCanceledSpy.wait());
265 QCOMPARE(touchCanceledSpy.count(), 1);
266}
267
268void FakeInputTest::testKeyboardKey_data()
269{
270 QTest::addColumn<quint32>("linuxKey");
271
272 QTest::newRow("A") << quint32(KEY_A);
273 QTest::newRow("S") << quint32(KEY_S);
274 QTest::newRow("D") << quint32(KEY_D);
275 QTest::newRow("F") << quint32(KEY_F);
276}
277
278void FakeInputTest::testKeyboardKey()
279{
281
282 // without an authentication we shouldn't get the signals
283 QSignalSpy keyboardKeySpy(m_inputDevice, &InputDevice::keyChanged);
284 QFETCH(quint32, linuxKey);
285 fakeInput->keyboard_key(linuxKey, WL_KEYBOARD_KEY_STATE_PRESSED);
286 QVERIFY(Test::waylandSync());
287 QVERIFY(keyboardKeySpy.isEmpty());
288
289 // now authenticate
290 fakeInput->authenticate(QStringLiteral("org.kde.foobar"), QStringLiteral("foobar"));
291 fakeInput->keyboard_key(linuxKey, WL_KEYBOARD_KEY_STATE_PRESSED);
292 QVERIFY(keyboardKeySpy.wait());
293 QCOMPARE(keyboardKeySpy.last().at(0).value<quint32>(), linuxKey);
294 QCOMPARE(keyboardKeySpy.last().at(1).value<InputRedirection::KeyboardKeyState>(), InputRedirection::KeyboardKeyPressed);
295
296 // and release
297 fakeInput->keyboard_key(linuxKey, WL_KEYBOARD_KEY_STATE_RELEASED);
298 QVERIFY(keyboardKeySpy.wait());
299 QCOMPARE(keyboardKeySpy.last().at(0).value<quint32>(), linuxKey);
300 QCOMPARE(keyboardKeySpy.last().at(1).value<InputRedirection::KeyboardKeyState>(), InputRedirection::KeyboardKeyReleased);
301}
302
303} // namespace KWin
304
306#include "fakeinput_test.moc"
void touchFrame(InputDevice *device)
void touchMotion(qint32 id, const QPointF &absolutePos, std::chrono::microseconds time, InputDevice *device)
void touchCanceled(InputDevice *device)
void pointerMotion(const QPointF &delta, const QPointF &deltaNonAccelerated, std::chrono::microseconds time, InputDevice *device)
void pointerButtonChanged(quint32 button, InputRedirection::PointerButtonState state, std::chrono::microseconds time, InputDevice *device)
void touchDown(qint32 id, const QPointF &absolutePos, std::chrono::microseconds time, InputDevice *device)
void pointerMotionAbsolute(const QPointF &position, std::chrono::microseconds time, InputDevice *device)
void keyChanged(quint32 key, InputRedirection::KeyboardKeyState, std::chrono::microseconds time, InputDevice *device)
void touchUp(qint32 id, std::chrono::microseconds time, InputDevice *device)
void pointerAxisChanged(InputRedirection::PointerAxis axis, qreal delta, qint32 deltaV120, InputRedirection::PointerAxisSource source, std::chrono::microseconds time, InputDevice *device)
void deviceAdded(InputDevice *device)
#define WAYLANDTEST_MAIN(TestObject)
void destroyWaylandConnection()
void setOutputConfig(const QList< QRect > &geometries)
FakeInput * fakeInput
bool setupWaylandConnection(AdditionalWaylandInterfaces flags=AdditionalWaylandInterfaces())
bool waylandSync()
FakeInput * waylandFakeInput()
WaylandServer * waylandServer()
InputRedirection * input()
Definition input.h:549