18#include <KWayland/Client/compositor.h>
19#include <KWayland/Client/keyboard.h>
20#include <KWayland/Client/pointer.h>
21#include <KWayland/Client/seat.h>
22#include <KWayland/Client/shm_pool.h>
23#include <KWayland/Client/surface.h>
24#include <KWayland/Client/touch.h>
26#include <linux/input.h>
30static const QString s_socketName = QStringLiteral(
"wayland_test_kwin_window_selection-0");
40 void testSelectOnWindowPointer();
41 void testSelectOnWindowKeyboard_data();
42 void testSelectOnWindowKeyboard();
43 void testSelectOnWindowTouch();
44 void testCancelOnWindowPointer();
45 void testCancelOnWindowKeyboard();
47 void testSelectPointPointer();
48 void testSelectPointTouch();
51void TestWindowSelection::initTestCase()
53 qRegisterMetaType<KWin::Window *>();
57 QRect(0, 0, 1280, 1024),
58 QRect(1280, 0, 1280, 1024),
60 qputenv(
"XKB_DEFAULT_RULES",
"evdev");
63 QVERIFY(applicationStartedSpy.wait());
66 QCOMPARE(outputs[0]->geometry(), QRect(0, 0, 1280, 1024));
67 QCOMPARE(outputs[1]->geometry(), QRect(1280, 0, 1280, 1024));
70void TestWindowSelection::init()
79void TestWindowSelection::cleanup()
84void TestWindowSelection::testSelectOnWindowPointer()
89 std::unique_ptr<KWayland::Client::Pointer> pointer(
Test::waylandSeat()->createPointer());
90 std::unique_ptr<KWayland::Client::Keyboard> keyboard(
Test::waylandSeat()->createKeyboard());
91 QSignalSpy pointerEnteredSpy(pointer.get(), &KWayland::Client::Pointer::entered);
92 QSignalSpy pointerLeftSpy(pointer.get(), &KWayland::Client::Pointer::left);
93 QSignalSpy keyboardEnteredSpy(keyboard.get(), &KWayland::Client::Keyboard::entered);
94 QSignalSpy keyboardLeftSpy(keyboard.get(), &KWayland::Client::Keyboard::left);
98 QVERIFY(keyboardEnteredSpy.wait());
100 QCOMPARE(
input()->pointer()->focus(), window);
101 QVERIFY(pointerEnteredSpy.wait());
103 Window *selectedWindow =
nullptr;
104 auto callback = [&selectedWindow](
Window *t) {
109 QCOMPARE(
input()->isSelectingWindow(),
false);
110 kwinApp()->startInteractiveWindowSelection(callback);
111 QCOMPARE(
input()->isSelectingWindow(),
true);
112 QVERIFY(!selectedWindow);
113 QCOMPARE(keyboardLeftSpy.count(), 0);
114 QVERIFY(pointerLeftSpy.wait());
115 if (keyboardLeftSpy.isEmpty()) {
116 QVERIFY(keyboardLeftSpy.wait());
118 QCOMPARE(pointerLeftSpy.count(), 1);
119 QCOMPARE(keyboardLeftSpy.count(), 1);
122 quint32 timestamp = 0;
125 QCOMPARE(
input()->isSelectingWindow(),
true);
126 QVERIFY(!selectedWindow);
127 QVERIFY(!
input()->pointer()->focus());
131 QVERIFY(!
input()->pointer()->focus());
139 QCOMPARE(
input()->isSelectingWindow(),
true);
140 QVERIFY(!selectedWindow);
143 QCOMPARE(
input()->isSelectingWindow(),
false);
144 QCOMPARE(selectedWindow, window);
145 QCOMPARE(
input()->pointer()->focus(), window);
147 QVERIFY(pointerEnteredSpy.wait());
148 if (keyboardEnteredSpy.count() != 2) {
149 QVERIFY(keyboardEnteredSpy.wait());
151 QCOMPARE(pointerLeftSpy.count(), 1);
152 QCOMPARE(keyboardLeftSpy.count(), 1);
153 QCOMPARE(pointerEnteredSpy.count(), 2);
154 QCOMPARE(keyboardEnteredSpy.count(), 2);
157void TestWindowSelection::testSelectOnWindowKeyboard_data()
159 QTest::addColumn<qint32>(
"key");
161 QTest::newRow(
"enter") << KEY_ENTER;
162 QTest::newRow(
"keypad enter") << KEY_KPENTER;
163 QTest::newRow(
"space") << KEY_SPACE;
166void TestWindowSelection::testSelectOnWindowKeyboard()
171 std::unique_ptr<KWayland::Client::Pointer> pointer(
Test::waylandSeat()->createPointer());
172 std::unique_ptr<KWayland::Client::Keyboard> keyboard(
Test::waylandSeat()->createKeyboard());
173 QSignalSpy pointerEnteredSpy(pointer.get(), &KWayland::Client::Pointer::entered);
174 QSignalSpy pointerLeftSpy(pointer.get(), &KWayland::Client::Pointer::left);
175 QSignalSpy keyboardEnteredSpy(keyboard.get(), &KWayland::Client::Keyboard::entered);
176 QSignalSpy keyboardLeftSpy(keyboard.get(), &KWayland::Client::Keyboard::left);
180 QVERIFY(keyboardEnteredSpy.wait());
183 Window *selectedWindow =
nullptr;
184 auto callback = [&selectedWindow](
Window *t) {
189 QCOMPARE(
input()->isSelectingWindow(),
false);
190 kwinApp()->startInteractiveWindowSelection(callback);
191 QCOMPARE(
input()->isSelectingWindow(),
true);
192 QVERIFY(!selectedWindow);
193 QCOMPARE(keyboardLeftSpy.count(), 0);
194 QVERIFY(keyboardLeftSpy.wait());
195 QCOMPARE(pointerLeftSpy.count(), 0);
196 QCOMPARE(keyboardLeftSpy.count(), 1);
199 quint32 timestamp = 0;
201 auto keyPress = [×tamp](qint32 key) {
205 while (
KWin::Cursors::self()->mouse()->pos().x() >= window->frameGeometry().x() + window->frameGeometry().width()) {
214 while (
KWin::Cursors::self()->mouse()->pos().y() >= window->frameGeometry().y() + window->frameGeometry().height()) {
219 QCOMPARE(
input()->isSelectingWindow(),
false);
220 QCOMPARE(selectedWindow, window);
221 QCOMPARE(
input()->pointer()->focus(), window);
223 QVERIFY(pointerEnteredSpy.wait());
224 if (keyboardEnteredSpy.count() != 2) {
225 QVERIFY(keyboardEnteredSpy.wait());
227 QCOMPARE(pointerLeftSpy.count(), 0);
228 QCOMPARE(keyboardLeftSpy.count(), 1);
229 QCOMPARE(pointerEnteredSpy.count(), 1);
230 QCOMPARE(keyboardEnteredSpy.count(), 2);
234void TestWindowSelection::testSelectOnWindowTouch()
237 std::unique_ptr<KWayland::Client::Touch> touch(
Test::waylandSeat()->createTouch());
238 QSignalSpy touchStartedSpy(touch.get(), &KWayland::Client::Touch::sequenceStarted);
239 QSignalSpy touchCanceledSpy(touch.get(), &KWayland::Client::Touch::sequenceCanceled);
245 Window *selectedWindow =
nullptr;
246 auto callback = [&selectedWindow](
Window *t) {
251 QCOMPARE(
input()->isSelectingWindow(),
false);
252 kwinApp()->startInteractiveWindowSelection(callback);
253 QCOMPARE(
input()->isSelectingWindow(),
true);
254 QVERIFY(!selectedWindow);
257 quint32 timestamp = 0;
259 QVERIFY(!selectedWindow);
261 QCOMPARE(
input()->isSelectingWindow(),
false);
262 QCOMPARE(selectedWindow, window);
265 selectedWindow =
nullptr;
266 kwinApp()->startInteractiveWindowSelection(callback);
267 Test::touchDown(0, window->frameGeometry().bottomRight() + QPoint(20, 20), timestamp++);
268 QVERIFY(!selectedWindow);
269 Test::touchMotion(0, window->frameGeometry().bottomRight() - QPoint(1, 1), timestamp++);
270 QVERIFY(!selectedWindow);
272 QCOMPARE(selectedWindow, window);
273 QCOMPARE(
input()->isSelectingWindow(),
false);
277 QVERIFY(touchStartedSpy.wait());
278 selectedWindow =
nullptr;
279 kwinApp()->startInteractiveWindowSelection(callback);
280 QCOMPARE(
input()->isSelectingWindow(),
true);
281 QVERIFY(touchCanceledSpy.wait());
282 QVERIFY(!selectedWindow);
285 QVERIFY(!selectedWindow);
288 QCOMPARE(selectedWindow, window);
289 QCOMPARE(
input()->isSelectingWindow(),
false);
291 QCOMPARE(touchStartedSpy.count(), 1);
292 QCOMPARE(touchCanceledSpy.count(), 1);
295void TestWindowSelection::testCancelOnWindowPointer()
300 std::unique_ptr<KWayland::Client::Pointer> pointer(
Test::waylandSeat()->createPointer());
301 std::unique_ptr<KWayland::Client::Keyboard> keyboard(
Test::waylandSeat()->createKeyboard());
302 QSignalSpy pointerEnteredSpy(pointer.get(), &KWayland::Client::Pointer::entered);
303 QSignalSpy pointerLeftSpy(pointer.get(), &KWayland::Client::Pointer::left);
304 QSignalSpy keyboardEnteredSpy(keyboard.get(), &KWayland::Client::Keyboard::entered);
305 QSignalSpy keyboardLeftSpy(keyboard.get(), &KWayland::Client::Keyboard::left);
309 QVERIFY(keyboardEnteredSpy.wait());
311 QCOMPARE(
input()->pointer()->focus(), window);
312 QVERIFY(pointerEnteredSpy.wait());
314 Window *selectedWindow =
nullptr;
315 auto callback = [&selectedWindow](
Window *t) {
320 QCOMPARE(
input()->isSelectingWindow(),
false);
321 kwinApp()->startInteractiveWindowSelection(callback);
322 QCOMPARE(
input()->isSelectingWindow(),
true);
323 QVERIFY(!selectedWindow);
324 QCOMPARE(keyboardLeftSpy.count(), 0);
325 QVERIFY(pointerLeftSpy.wait());
326 if (keyboardLeftSpy.isEmpty()) {
327 QVERIFY(keyboardLeftSpy.wait());
329 QCOMPARE(pointerLeftSpy.count(), 1);
330 QCOMPARE(keyboardLeftSpy.count(), 1);
333 quint32 timestamp = 0;
336 QCOMPARE(
input()->isSelectingWindow(),
false);
337 QVERIFY(!selectedWindow);
338 QCOMPARE(
input()->pointer()->focus(), window);
340 QVERIFY(pointerEnteredSpy.wait());
341 if (keyboardEnteredSpy.count() != 2) {
342 QVERIFY(keyboardEnteredSpy.wait());
344 QCOMPARE(pointerLeftSpy.count(), 1);
345 QCOMPARE(keyboardLeftSpy.count(), 1);
346 QCOMPARE(pointerEnteredSpy.count(), 2);
347 QCOMPARE(keyboardEnteredSpy.count(), 2);
350void TestWindowSelection::testCancelOnWindowKeyboard()
355 std::unique_ptr<KWayland::Client::Pointer> pointer(
Test::waylandSeat()->createPointer());
356 std::unique_ptr<KWayland::Client::Keyboard> keyboard(
Test::waylandSeat()->createKeyboard());
357 QSignalSpy pointerEnteredSpy(pointer.get(), &KWayland::Client::Pointer::entered);
358 QSignalSpy pointerLeftSpy(pointer.get(), &KWayland::Client::Pointer::left);
359 QSignalSpy keyboardEnteredSpy(keyboard.get(), &KWayland::Client::Keyboard::entered);
360 QSignalSpy keyboardLeftSpy(keyboard.get(), &KWayland::Client::Keyboard::left);
364 QVERIFY(keyboardEnteredSpy.wait());
366 QCOMPARE(
input()->pointer()->focus(), window);
367 QVERIFY(pointerEnteredSpy.wait());
369 Window *selectedWindow =
nullptr;
370 auto callback = [&selectedWindow](
Window *t) {
375 QCOMPARE(
input()->isSelectingWindow(),
false);
376 kwinApp()->startInteractiveWindowSelection(callback);
377 QCOMPARE(
input()->isSelectingWindow(),
true);
378 QVERIFY(!selectedWindow);
379 QCOMPARE(keyboardLeftSpy.count(), 0);
380 QVERIFY(pointerLeftSpy.wait());
381 if (keyboardLeftSpy.isEmpty()) {
382 QVERIFY(keyboardLeftSpy.wait());
384 QCOMPARE(pointerLeftSpy.count(), 1);
385 QCOMPARE(keyboardLeftSpy.count(), 1);
388 quint32 timestamp = 0;
390 QCOMPARE(
input()->isSelectingWindow(),
false);
391 QVERIFY(!selectedWindow);
392 QCOMPARE(
input()->pointer()->focus(), window);
394 QVERIFY(pointerEnteredSpy.wait());
395 if (keyboardEnteredSpy.count() != 2) {
396 QVERIFY(keyboardEnteredSpy.wait());
398 QCOMPARE(pointerLeftSpy.count(), 1);
399 QCOMPARE(keyboardLeftSpy.count(), 1);
400 QCOMPARE(pointerEnteredSpy.count(), 2);
401 QCOMPARE(keyboardEnteredSpy.count(), 2);
405void TestWindowSelection::testSelectPointPointer()
410 std::unique_ptr<KWayland::Client::Pointer> pointer(
Test::waylandSeat()->createPointer());
411 std::unique_ptr<KWayland::Client::Keyboard> keyboard(
Test::waylandSeat()->createKeyboard());
412 QSignalSpy pointerEnteredSpy(pointer.get(), &KWayland::Client::Pointer::entered);
413 QSignalSpy pointerLeftSpy(pointer.get(), &KWayland::Client::Pointer::left);
414 QSignalSpy keyboardEnteredSpy(keyboard.get(), &KWayland::Client::Keyboard::entered);
415 QSignalSpy keyboardLeftSpy(keyboard.get(), &KWayland::Client::Keyboard::left);
419 QVERIFY(keyboardEnteredSpy.wait());
421 QCOMPARE(
input()->pointer()->focus(), window);
422 QVERIFY(pointerEnteredSpy.wait());
425 QCOMPARE(
input()->isSelectingWindow(),
false);
427 kwinApp()->startInteractivePositionSelection([&point](
const QPointF &p) {
430 QCOMPARE(
input()->isSelectingWindow(),
true);
431 QCOMPARE(point, QPoint());
432 QCOMPARE(keyboardLeftSpy.count(), 0);
433 QVERIFY(pointerLeftSpy.wait());
434 if (keyboardLeftSpy.isEmpty()) {
435 QVERIFY(keyboardLeftSpy.wait());
437 QCOMPARE(pointerLeftSpy.count(), 1);
438 QCOMPARE(keyboardLeftSpy.count(), 1);
442 kwinApp()->startInteractivePositionSelection([&point2](
const QPointF &p) {
445 QCOMPARE(point2, QPoint(-1, -1));
448 quint32 timestamp = 0;
451 QCOMPARE(
input()->isSelectingWindow(),
true);
452 QCOMPARE(point, QPoint());
453 QVERIFY(!
input()->pointer()->focus());
457 QVERIFY(!
input()->pointer()->focus());
465 QCOMPARE(
input()->isSelectingWindow(),
true);
466 QCOMPARE(point, QPoint());
469 QCOMPARE(
input()->isSelectingWindow(),
false);
470 QCOMPARE(point,
input()->globalPointer().toPoint());
471 QCOMPARE(
input()->pointer()->focus(), window);
473 QVERIFY(pointerEnteredSpy.wait());
474 if (keyboardEnteredSpy.count() != 2) {
475 QVERIFY(keyboardEnteredSpy.wait());
477 QCOMPARE(pointerLeftSpy.count(), 1);
478 QCOMPARE(keyboardLeftSpy.count(), 1);
479 QCOMPARE(pointerEnteredSpy.count(), 2);
480 QCOMPARE(keyboardEnteredSpy.count(), 2);
483void TestWindowSelection::testSelectPointTouch()
487 QCOMPARE(
input()->isSelectingWindow(),
false);
489 kwinApp()->startInteractivePositionSelection([&point](
const QPointF &p) {
492 QCOMPARE(
input()->isSelectingWindow(),
true);
493 QCOMPARE(point, QPoint());
496 quint32 timestamp = 0;
498 QCOMPARE(
input()->isSelectingWindow(),
true);
500 QCOMPARE(
input()->isSelectingWindow(),
true);
502 QCOMPARE(
input()->isSelectingWindow(),
true);
508 QCOMPARE(
input()->isSelectingWindow(),
true);
510 QCOMPARE(
input()->isSelectingWindow(),
true);
512 QCOMPARE(
input()->isSelectingWindow(),
true);
514 QCOMPARE(
input()->isSelectingWindow(),
false);
515 QCOMPARE(point, QPoint(25, 35));
519#include "window_selection_test.moc"
QList< Output * > outputs() const
void setActiveOutput(Output *output)
#define WAYLANDTEST_MAIN(TestObject)
Window * renderAndWaitForShown(KWayland::Client::Surface *surface, const QSize &size, const QColor &color, const QImage::Format &format=QImage::Format_ARGB32, int timeout=5000)
void keyboardKeyReleased(quint32 key, quint32 time)
void destroyWaylandConnection()
void setOutputConfig(const QList< QRect > &geometries)
void touchDown(qint32 id, const QPointF &pos, quint32 time)
void keyboardKeyPressed(quint32 key, quint32 time)
bool setupWaylandConnection(AdditionalWaylandInterfaces flags=AdditionalWaylandInterfaces())
void touchMotion(qint32 id, const QPointF &pos, quint32 time)
KWayland::Client::Seat * waylandSeat()
void pointerButtonPressed(quint32 button, quint32 time)
QList< KWayland::Client::Output * > outputs
std::unique_ptr< KWayland::Client::Surface > createSurface()
XdgToplevel * createXdgToplevelSurface(KWayland::Client::Surface *surface, QObject *parent=nullptr)
bool waitForWaylandPointer()
void pointerButtonReleased(quint32 button, quint32 time)
void touchUp(qint32 id, quint32 time)
WaylandServer * waylandServer()
InputRedirection * input()