1 /*
2     SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
3 
4     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5 */
6 // Qt
7 #include <QtTest>
8 // WaylandServer
9 #include "../../src/server/display.h"
10 #include "../../src/server/keyboard_interface.h"
11 #include "../../src/server/pointer_interface.h"
12 #include "../../src/server/seat_interface.h"
13 
14 using namespace KWaylandServer;
15 
16 class TestWaylandServerSeat : public QObject
17 {
18     Q_OBJECT
19 private Q_SLOTS:
20     void testCapabilities();
21     void testName();
22     void testPointerButton();
23     void testPointerPos();
24     void testRepeatInfo();
25     void testMultiple();
26 };
27 
28 static const QString s_socketName = QStringLiteral("kwin-wayland-server-seat-test-0");
29 
testCapabilities()30 void TestWaylandServerSeat::testCapabilities()
31 {
32     Display display;
33     display.addSocketName(s_socketName);
34     display.start();
35     SeatInterface *seat = new SeatInterface(&display);
36     QVERIFY(!seat->hasKeyboard());
37     QVERIFY(!seat->hasPointer());
38     QVERIFY(!seat->hasTouch());
39 
40     QSignalSpy keyboardSpy(seat, SIGNAL(hasKeyboardChanged(bool)));
41     QVERIFY(keyboardSpy.isValid());
42     seat->setHasKeyboard(true);
43     QCOMPARE(keyboardSpy.count(), 1);
44     QVERIFY(keyboardSpy.last().first().toBool());
45     QVERIFY(seat->hasKeyboard());
46     seat->setHasKeyboard(false);
47     QCOMPARE(keyboardSpy.count(), 2);
48     QVERIFY(!keyboardSpy.last().first().toBool());
49     QVERIFY(!seat->hasKeyboard());
50     seat->setHasKeyboard(false);
51     QCOMPARE(keyboardSpy.count(), 2);
52 
53     QSignalSpy pointerSpy(seat, SIGNAL(hasPointerChanged(bool)));
54     QVERIFY(pointerSpy.isValid());
55     seat->setHasPointer(true);
56     QCOMPARE(pointerSpy.count(), 1);
57     QVERIFY(pointerSpy.last().first().toBool());
58     QVERIFY(seat->hasPointer());
59     seat->setHasPointer(false);
60     QCOMPARE(pointerSpy.count(), 2);
61     QVERIFY(!pointerSpy.last().first().toBool());
62     QVERIFY(!seat->hasPointer());
63     seat->setHasPointer(false);
64     QCOMPARE(pointerSpy.count(), 2);
65 
66     QSignalSpy touchSpy(seat, SIGNAL(hasTouchChanged(bool)));
67     QVERIFY(touchSpy.isValid());
68     seat->setHasTouch(true);
69     QCOMPARE(touchSpy.count(), 1);
70     QVERIFY(touchSpy.last().first().toBool());
71     QVERIFY(seat->hasTouch());
72     seat->setHasTouch(false);
73     QCOMPARE(touchSpy.count(), 2);
74     QVERIFY(!touchSpy.last().first().toBool());
75     QVERIFY(!seat->hasTouch());
76     seat->setHasTouch(false);
77     QCOMPARE(touchSpy.count(), 2);
78 }
79 
testName()80 void TestWaylandServerSeat::testName()
81 {
82     Display display;
83     display.addSocketName(s_socketName);
84     display.start();
85     SeatInterface *seat = new SeatInterface(&display);
86     QCOMPARE(seat->name(), QString());
87 
88     QSignalSpy nameSpy(seat, SIGNAL(nameChanged(QString)));
89     QVERIFY(nameSpy.isValid());
90     const QString name = QStringLiteral("foobar");
91     seat->setName(name);
92     QCOMPARE(seat->name(), name);
93     QCOMPARE(nameSpy.count(), 1);
94     QCOMPARE(nameSpy.first().first().toString(), name);
95     seat->setName(name);
96     QCOMPARE(nameSpy.count(), 1);
97 }
98 
testPointerButton()99 void TestWaylandServerSeat::testPointerButton()
100 {
101     Display display;
102     display.addSocketName(s_socketName);
103     display.start();
104     SeatInterface *seat = new SeatInterface(&display);
105     seat->setHasPointer(true);
106 
107     // no button pressed yet, should be released and no serial
108     QVERIFY(!seat->isPointerButtonPressed(0));
109     QVERIFY(!seat->isPointerButtonPressed(1));
110     QCOMPARE(seat->pointerButtonSerial(0), quint32(0));
111     QCOMPARE(seat->pointerButtonSerial(1), quint32(0));
112 
113     // mark the button as pressed
114     seat->notifyPointerButton(0, PointerButtonState::Pressed);
115     seat->notifyPointerFrame();
116     QVERIFY(seat->isPointerButtonPressed(0));
117     QCOMPARE(seat->pointerButtonSerial(0), display.serial());
118 
119     // other button should still be unpressed
120     QVERIFY(!seat->isPointerButtonPressed(1));
121     QCOMPARE(seat->pointerButtonSerial(1), quint32(0));
122 
123     // release it again
124     seat->notifyPointerButton(0, PointerButtonState::Released);
125     seat->notifyPointerFrame();
126     QVERIFY(!seat->isPointerButtonPressed(0));
127     QCOMPARE(seat->pointerButtonSerial(0), display.serial());
128 }
129 
testPointerPos()130 void TestWaylandServerSeat::testPointerPos()
131 {
132     Display display;
133     display.addSocketName(s_socketName);
134     display.start();
135     SeatInterface *seat = new SeatInterface(&display);
136     seat->setHasPointer(true);
137     QSignalSpy seatPosSpy(seat, SIGNAL(pointerPosChanged(QPointF)));
138     QVERIFY(seatPosSpy.isValid());
139 
140     QCOMPARE(seat->pointerPos(), QPointF());
141 
142     seat->notifyPointerMotion(QPointF(10, 15));
143     seat->notifyPointerFrame();
144     QCOMPARE(seat->pointerPos(), QPointF(10, 15));
145     QCOMPARE(seatPosSpy.count(), 1);
146     QCOMPARE(seatPosSpy.first().first().toPointF(), QPointF(10, 15));
147 
148     seat->notifyPointerMotion(QPointF(10, 15));
149     seat->notifyPointerFrame();
150     QCOMPARE(seatPosSpy.count(), 1);
151 
152     seat->notifyPointerMotion(QPointF(5, 7));
153     seat->notifyPointerFrame();
154     QCOMPARE(seat->pointerPos(), QPointF(5, 7));
155     QCOMPARE(seatPosSpy.count(), 2);
156     QCOMPARE(seatPosSpy.first().first().toPointF(), QPointF(10, 15));
157     QCOMPARE(seatPosSpy.last().first().toPointF(), QPointF(5, 7));
158 }
159 
testRepeatInfo()160 void TestWaylandServerSeat::testRepeatInfo()
161 {
162     Display display;
163     display.addSocketName(s_socketName);
164     display.start();
165     SeatInterface *seat = new SeatInterface(&display);
166     seat->setHasKeyboard(true);
167     QCOMPARE(seat->keyboard()->keyRepeatRate(), 0);
168     QCOMPARE(seat->keyboard()->keyRepeatDelay(), 0);
169     seat->keyboard()->setRepeatInfo(25, 660);
170     QCOMPARE(seat->keyboard()->keyRepeatRate(), 25);
171     QCOMPARE(seat->keyboard()->keyRepeatDelay(), 660);
172     // setting negative values should result in 0
173     seat->keyboard()->setRepeatInfo(-25, -660);
174     QCOMPARE(seat->keyboard()->keyRepeatRate(), 0);
175     QCOMPARE(seat->keyboard()->keyRepeatDelay(), 0);
176 }
177 
testMultiple()178 void TestWaylandServerSeat::testMultiple()
179 {
180     Display display;
181     display.addSocketName(s_socketName);
182     display.start();
183     QVERIFY(display.seats().isEmpty());
184     SeatInterface *seat1 = new SeatInterface(&display);
185     QCOMPARE(display.seats().count(), 1);
186     QCOMPARE(display.seats().at(0), seat1);
187     SeatInterface *seat2 = new SeatInterface(&display);
188     QCOMPARE(display.seats().count(), 2);
189     QCOMPARE(display.seats().at(0), seat1);
190     QCOMPARE(display.seats().at(1), seat2);
191     SeatInterface *seat3 = new SeatInterface(&display);
192     QCOMPARE(display.seats().count(), 3);
193     QCOMPARE(display.seats().at(0), seat1);
194     QCOMPARE(display.seats().at(1), seat2);
195     QCOMPARE(display.seats().at(2), seat3);
196 
197     delete seat3;
198     QCOMPARE(display.seats().count(), 2);
199     QCOMPARE(display.seats().at(0), seat1);
200     QCOMPARE(display.seats().at(1), seat2);
201 
202     delete seat2;
203     QCOMPARE(display.seats().count(), 1);
204     QCOMPARE(display.seats().at(0), seat1);
205 
206     delete seat1;
207     QCOMPARE(display.seats().count(), 0);
208 }
209 
210 QTEST_GUILESS_MAIN(TestWaylandServerSeat)
211 #include "test_seat.moc"
212