File indexing completed on 2024-11-10 04:56:19
0001 /* 0002 SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 // Qt 0007 #include <QMimeType> 0008 #include <QSignalSpy> 0009 #include <QTest> 0010 // KWin 0011 #include "wayland/compositor.h" 0012 #include "wayland/datadevicemanager.h" 0013 #include "wayland/datasource.h" 0014 #include "wayland/display.h" 0015 #include "wayland/keyboard.h" 0016 #include "wayland/pointer.h" 0017 #include "wayland/pointergestures_v1.h" 0018 #include "wayland/relativepointer_v1.h" 0019 #include "wayland/seat.h" 0020 #include "wayland/subcompositor.h" 0021 #include "wayland/surface.h" 0022 0023 #include "KWayland/Client/compositor.h" 0024 #include "KWayland/Client/connection_thread.h" 0025 #include "KWayland/Client/datadevice.h" 0026 #include "KWayland/Client/datadevicemanager.h" 0027 #include "KWayland/Client/datasource.h" 0028 #include "KWayland/Client/event_queue.h" 0029 #include "KWayland/Client/keyboard.h" 0030 #include "KWayland/Client/pointer.h" 0031 #include "KWayland/Client/pointergestures.h" 0032 #include "KWayland/Client/registry.h" 0033 #include "KWayland/Client/relativepointer.h" 0034 #include "KWayland/Client/seat.h" 0035 #include "KWayland/Client/shm_pool.h" 0036 #include "KWayland/Client/subcompositor.h" 0037 #include "KWayland/Client/subsurface.h" 0038 #include "KWayland/Client/surface.h" 0039 #include "KWayland/Client/touch.h" 0040 0041 // Wayland 0042 #include "qwayland-pointer-gestures-unstable-v1.h" 0043 #include <wayland-client-protocol.h> 0044 0045 #include <linux/input.h> 0046 // System 0047 #include <fcntl.h> 0048 #include <unistd.h> 0049 0050 using namespace std::literals; 0051 0052 class WaylandSyncPoint : public QObject 0053 { 0054 Q_OBJECT 0055 0056 public: 0057 explicit WaylandSyncPoint(KWayland::Client::ConnectionThread *connection, KWayland::Client::EventQueue *eventQueue) 0058 { 0059 static const wl_callback_listener listener = { 0060 .done = [](void *data, wl_callback *callback, uint32_t callback_data) { 0061 auto syncPoint = static_cast<WaylandSyncPoint *>(data); 0062 Q_EMIT syncPoint->done(); 0063 }, 0064 }; 0065 0066 m_callback = wl_display_sync(connection->display()); 0067 eventQueue->addProxy(m_callback); 0068 wl_callback_add_listener(m_callback, &listener, this); 0069 } 0070 0071 ~WaylandSyncPoint() override 0072 { 0073 wl_callback_destroy(m_callback); 0074 } 0075 0076 Q_SIGNALS: 0077 void done(); 0078 0079 private: 0080 wl_callback *m_callback; 0081 }; 0082 0083 class TestWaylandSeat : public QObject 0084 { 0085 Q_OBJECT 0086 public: 0087 explicit TestWaylandSeat(QObject *parent = nullptr); 0088 private Q_SLOTS: 0089 void init(); 0090 void cleanup(); 0091 0092 void testName(); 0093 void testCapabilities_data(); 0094 void testCapabilities(); 0095 void testPointer(); 0096 void testPointerTransformation_data(); 0097 void testPointerTransformation(); 0098 void testPointerButton_data(); 0099 void testPointerButton(); 0100 void testPointerSubSurfaceTree(); 0101 void testPointerSwipeGesture_data(); 0102 void testPointerSwipeGesture(); 0103 void testPointerPinchGesture_data(); 0104 void testPointerPinchGesture(); 0105 void testPointerHoldGesture_data(); 0106 void testPointerHoldGesture(); 0107 void testPointerAxis(); 0108 void testCursor(); 0109 void testKeyboard(); 0110 void testSelection(); 0111 void testDataDeviceForKeyboardSurface(); 0112 void testTouch(); 0113 void testKeymap(); 0114 0115 private: 0116 bool sync(); 0117 0118 KWin::Display *m_display; 0119 KWin::CompositorInterface *m_compositorInterface; 0120 KWin::SeatInterface *m_seatInterface; 0121 KWin::SubCompositorInterface *m_subCompositorInterface; 0122 KWin::RelativePointerManagerV1Interface *m_relativePointerManagerV1Interface; 0123 KWin::PointerGesturesV1Interface *m_pointerGesturesV1Interface; 0124 KWayland::Client::ConnectionThread *m_connection; 0125 KWayland::Client::Compositor *m_compositor; 0126 KWayland::Client::Seat *m_seat; 0127 KWayland::Client::ShmPool *m_shm; 0128 KWayland::Client::SubCompositor *m_subCompositor; 0129 KWayland::Client::RelativePointerManager *m_relativePointerManager; 0130 KWayland::Client::PointerGestures *m_pointerGestures; 0131 KWayland::Client::EventQueue *m_queue; 0132 QThread *m_thread; 0133 }; 0134 0135 static const QString s_socketName = QStringLiteral("kwin-test-wayland-seat-0"); 0136 0137 TestWaylandSeat::TestWaylandSeat(QObject *parent) 0138 : QObject(parent) 0139 , m_display(nullptr) 0140 , m_compositorInterface(nullptr) 0141 , m_seatInterface(nullptr) 0142 , m_subCompositorInterface(nullptr) 0143 , m_relativePointerManagerV1Interface(nullptr) 0144 , m_pointerGesturesV1Interface(nullptr) 0145 , m_connection(nullptr) 0146 , m_compositor(nullptr) 0147 , m_seat(nullptr) 0148 , m_shm(nullptr) 0149 , m_subCompositor(nullptr) 0150 , m_relativePointerManager(nullptr) 0151 , m_pointerGestures(nullptr) 0152 , m_queue(nullptr) 0153 , m_thread(nullptr) 0154 { 0155 } 0156 0157 void TestWaylandSeat::init() 0158 { 0159 using namespace KWin; 0160 delete m_display; 0161 m_display = new KWin::Display(this); 0162 m_display->addSocketName(s_socketName); 0163 m_display->start(); 0164 QVERIFY(m_display->isRunning()); 0165 m_display->createShm(); 0166 0167 m_compositorInterface = new CompositorInterface(m_display, m_display); 0168 m_subCompositorInterface = new SubCompositorInterface(m_display, m_display); 0169 QVERIFY(m_subCompositorInterface); 0170 0171 m_relativePointerManagerV1Interface = new RelativePointerManagerV1Interface(m_display, m_display); 0172 m_pointerGesturesV1Interface = new PointerGesturesV1Interface(m_display, m_display); 0173 0174 // setup connection 0175 m_connection = new KWayland::Client::ConnectionThread; 0176 QSignalSpy connectedSpy(m_connection, &KWayland::Client::ConnectionThread::connected); 0177 m_connection->setSocketName(s_socketName); 0178 0179 m_thread = new QThread(this); 0180 m_connection->moveToThread(m_thread); 0181 m_thread->start(); 0182 0183 m_connection->initConnection(); 0184 QVERIFY(connectedSpy.wait()); 0185 0186 m_queue = new KWayland::Client::EventQueue(this); 0187 m_queue->setup(m_connection); 0188 0189 KWayland::Client::Registry registry; 0190 QSignalSpy compositorSpy(®istry, &KWayland::Client::Registry::compositorAnnounced); 0191 QSignalSpy seatSpy(®istry, &KWayland::Client::Registry::seatAnnounced); 0192 QSignalSpy shmSpy(®istry, &KWayland::Client::Registry::shmAnnounced); 0193 registry.setEventQueue(m_queue); 0194 registry.create(m_connection->display()); 0195 QVERIFY(registry.isValid()); 0196 registry.setup(); 0197 QVERIFY(compositorSpy.wait()); 0198 0199 m_seatInterface = new SeatInterface(m_display, m_display); 0200 QVERIFY(m_seatInterface); 0201 m_seatInterface->setName(QStringLiteral("seat0")); 0202 QVERIFY(seatSpy.wait()); 0203 0204 m_compositor = new KWayland::Client::Compositor(this); 0205 m_compositor->setup(registry.bindCompositor(compositorSpy.first().first().value<quint32>(), compositorSpy.first().last().value<quint32>())); 0206 QVERIFY(m_compositor->isValid()); 0207 0208 m_seat = registry.createSeat(seatSpy.first().first().value<quint32>(), seatSpy.first().last().value<quint32>(), this); 0209 QSignalSpy nameSpy(m_seat, &KWayland::Client::Seat::nameChanged); 0210 QVERIFY(nameSpy.wait()); 0211 0212 m_shm = new KWayland::Client::ShmPool(this); 0213 m_shm->setup(registry.bindShm(shmSpy.first().first().value<quint32>(), shmSpy.first().last().value<quint32>())); 0214 QVERIFY(m_shm->isValid()); 0215 0216 m_subCompositor = registry.createSubCompositor(registry.interface(KWayland::Client::Registry::Interface::SubCompositor).name, 0217 registry.interface(KWayland::Client::Registry::Interface::SubCompositor).version, 0218 this); 0219 QVERIFY(m_subCompositor->isValid()); 0220 0221 m_relativePointerManager = 0222 registry.createRelativePointerManager(registry.interface(KWayland::Client::Registry::Interface::RelativePointerManagerUnstableV1).name, 0223 registry.interface(KWayland::Client::Registry::Interface::RelativePointerManagerUnstableV1).version, 0224 this); 0225 QVERIFY(m_relativePointerManager->isValid()); 0226 0227 m_pointerGestures = registry.createPointerGestures(registry.interface(KWayland::Client::Registry::Interface::PointerGesturesUnstableV1).name, 0228 registry.interface(KWayland::Client::Registry::Interface::PointerGesturesUnstableV1).version, 0229 this); 0230 QVERIFY(m_pointerGestures->isValid()); 0231 } 0232 0233 void TestWaylandSeat::cleanup() 0234 { 0235 if (m_pointerGestures) { 0236 delete m_pointerGestures; 0237 m_pointerGestures = nullptr; 0238 } 0239 if (m_relativePointerManager) { 0240 delete m_relativePointerManager; 0241 m_relativePointerManager = nullptr; 0242 } 0243 if (m_subCompositor) { 0244 delete m_subCompositor; 0245 m_subCompositor = nullptr; 0246 } 0247 if (m_shm) { 0248 delete m_shm; 0249 m_shm = nullptr; 0250 } 0251 if (m_seat) { 0252 delete m_seat; 0253 m_seat = nullptr; 0254 } 0255 if (m_compositor) { 0256 delete m_compositor; 0257 m_compositor = nullptr; 0258 } 0259 if (m_queue) { 0260 delete m_queue; 0261 m_queue = nullptr; 0262 } 0263 if (m_connection) { 0264 m_connection->deleteLater(); 0265 m_connection = nullptr; 0266 } 0267 if (m_thread) { 0268 m_thread->quit(); 0269 m_thread->wait(); 0270 delete m_thread; 0271 m_thread = nullptr; 0272 } 0273 0274 delete m_display; 0275 m_display = nullptr; 0276 0277 // these are the children of the display 0278 m_compositorInterface = nullptr; 0279 m_seatInterface = nullptr; 0280 m_subCompositorInterface = nullptr; 0281 m_relativePointerManagerV1Interface = nullptr; 0282 m_pointerGesturesV1Interface = nullptr; 0283 } 0284 0285 bool TestWaylandSeat::sync() 0286 { 0287 WaylandSyncPoint syncPoint(m_connection, m_queue); 0288 QSignalSpy doneSpy(&syncPoint, &WaylandSyncPoint::done); 0289 return doneSpy.wait(); 0290 } 0291 0292 void TestWaylandSeat::testName() 0293 { 0294 // no name set yet 0295 QCOMPARE(m_seat->name(), QStringLiteral("seat0")); 0296 0297 QSignalSpy spy(m_seat, &KWayland::Client::Seat::nameChanged); 0298 0299 const QString name = QStringLiteral("foobar"); 0300 m_seatInterface->setName(name); 0301 QVERIFY(spy.wait()); 0302 QCOMPARE(m_seat->name(), name); 0303 QCOMPARE(spy.count(), 1); 0304 QCOMPARE(spy.first().first().toString(), name); 0305 } 0306 0307 void TestWaylandSeat::testCapabilities_data() 0308 { 0309 QTest::addColumn<bool>("pointer"); 0310 QTest::addColumn<bool>("keyboard"); 0311 QTest::addColumn<bool>("touch"); 0312 0313 QTest::newRow("none") << false << false << false; 0314 QTest::newRow("pointer") << true << false << false; 0315 QTest::newRow("keyboard") << false << true << false; 0316 QTest::newRow("touch") << false << false << true; 0317 QTest::newRow("pointer/keyboard") << true << true << false; 0318 QTest::newRow("pointer/touch") << true << false << true; 0319 QTest::newRow("keyboard/touch") << false << true << true; 0320 QTest::newRow("all") << true << true << true; 0321 } 0322 0323 void TestWaylandSeat::testCapabilities() 0324 { 0325 QVERIFY(!m_seat->hasPointer()); 0326 QVERIFY(!m_seat->hasKeyboard()); 0327 QVERIFY(!m_seat->hasTouch()); 0328 0329 QFETCH(bool, pointer); 0330 QFETCH(bool, keyboard); 0331 QFETCH(bool, touch); 0332 0333 QSignalSpy pointerSpy(m_seat, &KWayland::Client::Seat::hasPointerChanged); 0334 QSignalSpy keyboardSpy(m_seat, &KWayland::Client::Seat::hasKeyboardChanged); 0335 QSignalSpy touchSpy(m_seat, &KWayland::Client::Seat::hasTouchChanged); 0336 0337 m_seatInterface->setHasPointer(pointer); 0338 m_seatInterface->setHasKeyboard(keyboard); 0339 m_seatInterface->setHasTouch(touch); 0340 0341 QVERIFY(sync()); 0342 0343 // do processing 0344 QCOMPARE(pointerSpy.isEmpty(), !pointer); 0345 if (!pointerSpy.isEmpty()) { 0346 QCOMPARE(pointerSpy.first().first().toBool(), pointer); 0347 } 0348 0349 QCOMPARE(keyboardSpy.isEmpty(), !keyboard); 0350 if (!keyboardSpy.isEmpty()) { 0351 QCOMPARE(keyboardSpy.first().first().toBool(), keyboard); 0352 } 0353 0354 QCOMPARE(touchSpy.isEmpty(), !touch); 0355 if (!touchSpy.isEmpty()) { 0356 QCOMPARE(touchSpy.first().first().toBool(), touch); 0357 } 0358 0359 QCOMPARE(m_seat->hasPointer(), pointer); 0360 QCOMPARE(m_seat->hasKeyboard(), keyboard); 0361 QCOMPARE(m_seat->hasTouch(), touch); 0362 } 0363 0364 void TestWaylandSeat::testPointer() 0365 { 0366 using namespace KWin; 0367 0368 QSignalSpy pointerSpy(m_seat, &KWayland::Client::Seat::hasPointerChanged); 0369 m_seatInterface->setHasPointer(true); 0370 QVERIFY(pointerSpy.wait()); 0371 0372 QSignalSpy surfaceCreatedSpy(m_compositorInterface, &KWin::CompositorInterface::surfaceCreated); 0373 KWayland::Client::Surface *s = m_compositor->createSurface(m_compositor); 0374 QVERIFY(surfaceCreatedSpy.wait()); 0375 SurfaceInterface *serverSurface = surfaceCreatedSpy.first().first().value<KWin::SurfaceInterface *>(); 0376 QVERIFY(serverSurface); 0377 0378 QImage image(QSize(100, 100), QImage::Format_ARGB32_Premultiplied); 0379 image.fill(Qt::black); 0380 s->attachBuffer(m_shm->createBuffer(image)); 0381 s->damage(image.rect()); 0382 s->commit(KWayland::Client::Surface::CommitFlag::None); 0383 QSignalSpy committedSpy(serverSurface, &KWin::SurfaceInterface::committed); 0384 QVERIFY(committedSpy.wait()); 0385 0386 m_seatInterface->notifyPointerEnter(serverSurface, QPointF(20, 18), QPointF(10, 15)); 0387 0388 KWayland::Client::Pointer *p = m_seat->createPointer(m_seat); 0389 QSignalSpy frameSpy(p, &KWayland::Client::Pointer::frame); 0390 const KWayland::Client::Pointer &cp = *p; 0391 QVERIFY(p->isValid()); 0392 std::unique_ptr<KWayland::Client::RelativePointer> relativePointer(m_relativePointerManager->createRelativePointer(p)); 0393 QVERIFY(relativePointer->isValid()); 0394 QVERIFY(frameSpy.wait()); 0395 QCOMPARE(frameSpy.count(), 1); 0396 0397 m_seatInterface->notifyPointerLeave(); 0398 serverSurface->client()->flush(); 0399 QVERIFY(frameSpy.wait()); 0400 QCOMPARE(frameSpy.count(), 2); 0401 0402 QSignalSpy enteredSpy(p, &KWayland::Client::Pointer::entered); 0403 0404 QSignalSpy leftSpy(p, &KWayland::Client::Pointer::left); 0405 0406 QSignalSpy motionSpy(p, &KWayland::Client::Pointer::motion); 0407 0408 QSignalSpy axisSpy(p, &KWayland::Client::Pointer::axisChanged); 0409 0410 QSignalSpy buttonSpy(p, &KWayland::Client::Pointer::buttonStateChanged); 0411 0412 QSignalSpy relativeMotionSpy(relativePointer.get(), &KWayland::Client::RelativePointer::relativeMotion); 0413 0414 QVERIFY(!p->enteredSurface()); 0415 QVERIFY(!cp.enteredSurface()); 0416 uint32_t serial = m_display->serial(); 0417 m_seatInterface->notifyPointerEnter(serverSurface, QPointF(20, 18), QPointF(10, 15)); 0418 QCOMPARE(m_seatInterface->focusedPointerSurface(), serverSurface); 0419 QVERIFY(enteredSpy.wait()); 0420 QCOMPARE_GT(enteredSpy.first().first().value<quint32>(), serial); 0421 QCOMPARE(enteredSpy.first().last().toPoint(), QPoint(10, 3)); 0422 QCOMPARE(frameSpy.count(), 3); 0423 QCOMPARE(p->enteredSurface(), s); 0424 QCOMPARE(cp.enteredSurface(), s); 0425 0426 auto timestamp = 1ms; 0427 // test motion 0428 m_seatInterface->setTimestamp(timestamp++); 0429 m_seatInterface->notifyPointerMotion(QPoint(10, 16)); 0430 m_seatInterface->notifyPointerFrame(); 0431 QVERIFY(motionSpy.wait()); 0432 QCOMPARE(frameSpy.count(), 4); 0433 QCOMPARE(motionSpy.first().first().toPoint(), QPoint(0, 1)); 0434 QCOMPARE(motionSpy.first().last().value<quint32>(), quint32(1)); 0435 0436 // test relative motion 0437 m_seatInterface->relativePointerMotion(QPointF(1, 2), QPointF(3, 4), 1234us); 0438 m_seatInterface->notifyPointerFrame(); 0439 QVERIFY(relativeMotionSpy.wait()); 0440 QCOMPARE(relativeMotionSpy.count(), 1); 0441 QCOMPARE(frameSpy.count(), 5); 0442 QCOMPARE(relativeMotionSpy.first().at(0).toSizeF(), QSizeF(1, 2)); 0443 QCOMPARE(relativeMotionSpy.first().at(1).toSizeF(), QSizeF(3, 4)); 0444 QCOMPARE(relativeMotionSpy.first().at(2).value<quint64>(), 1234); 0445 0446 // test axis 0447 m_seatInterface->setTimestamp(timestamp++); 0448 m_seatInterface->notifyPointerAxis(Qt::Horizontal, 10, 120, PointerAxisSource::Wheel); 0449 m_seatInterface->notifyPointerFrame(); 0450 QVERIFY(axisSpy.wait()); 0451 QCOMPARE(frameSpy.count(), 6); 0452 m_seatInterface->setTimestamp(timestamp++); 0453 m_seatInterface->notifyPointerAxis(Qt::Vertical, 20, 240, PointerAxisSource::Wheel); 0454 m_seatInterface->notifyPointerFrame(); 0455 QVERIFY(axisSpy.wait()); 0456 QCOMPARE(frameSpy.count(), 7); 0457 QCOMPARE(axisSpy.first().at(0).value<quint32>(), quint32(2)); 0458 QCOMPARE(axisSpy.first().at(1).value<KWayland::Client::Pointer::Axis>(), KWayland::Client::Pointer::Axis::Horizontal); 0459 QCOMPARE(axisSpy.first().at(2).value<qreal>(), qreal(10)); 0460 0461 QCOMPARE(axisSpy.last().at(0).value<quint32>(), quint32(3)); 0462 QCOMPARE(axisSpy.last().at(1).value<KWayland::Client::Pointer::Axis>(), KWayland::Client::Pointer::Axis::Vertical); 0463 QCOMPARE(axisSpy.last().at(2).value<qreal>(), qreal(20)); 0464 0465 // test button 0466 m_seatInterface->setTimestamp(timestamp++); 0467 m_seatInterface->notifyPointerButton(1, PointerButtonState::Pressed); 0468 m_seatInterface->notifyPointerFrame(); 0469 QVERIFY(buttonSpy.wait()); 0470 QCOMPARE(frameSpy.count(), 8); 0471 QCOMPARE(buttonSpy.at(0).at(0).value<quint32>(), m_display->serial()); 0472 m_seatInterface->setTimestamp(timestamp++); 0473 m_seatInterface->notifyPointerButton(2, PointerButtonState::Pressed); 0474 m_seatInterface->notifyPointerFrame(); 0475 QVERIFY(buttonSpy.wait()); 0476 QCOMPARE(frameSpy.count(), 9); 0477 QCOMPARE(buttonSpy.at(1).at(0).value<quint32>(), m_display->serial()); 0478 m_seatInterface->setTimestamp(timestamp++); 0479 m_seatInterface->notifyPointerButton(2, PointerButtonState::Released); 0480 m_seatInterface->notifyPointerFrame(); 0481 QVERIFY(buttonSpy.wait()); 0482 QCOMPARE(frameSpy.count(), 10); 0483 QCOMPARE(buttonSpy.at(2).at(0).value<quint32>(), m_display->serial()); 0484 m_seatInterface->setTimestamp(timestamp++); 0485 m_seatInterface->notifyPointerButton(1, PointerButtonState::Released); 0486 m_seatInterface->notifyPointerFrame(); 0487 QVERIFY(buttonSpy.wait()); 0488 QCOMPARE(frameSpy.count(), 11); 0489 QCOMPARE(buttonSpy.count(), 4); 0490 0491 // timestamp 0492 QCOMPARE(buttonSpy.at(0).at(1).value<quint32>(), quint32(4)); 0493 // button 0494 QCOMPARE(buttonSpy.at(0).at(2).value<quint32>(), quint32(1)); 0495 QCOMPARE(buttonSpy.at(0).at(3).value<KWayland::Client::Pointer::ButtonState>(), KWayland::Client::Pointer::ButtonState::Pressed); 0496 0497 // timestamp 0498 QCOMPARE(buttonSpy.at(1).at(1).value<quint32>(), quint32(5)); 0499 // button 0500 QCOMPARE(buttonSpy.at(1).at(2).value<quint32>(), quint32(2)); 0501 QCOMPARE(buttonSpy.at(1).at(3).value<KWayland::Client::Pointer::ButtonState>(), KWayland::Client::Pointer::ButtonState::Pressed); 0502 0503 QCOMPARE(buttonSpy.at(2).at(0).value<quint32>(), m_seatInterface->pointerButtonSerial(2)); 0504 // timestamp 0505 QCOMPARE(buttonSpy.at(2).at(1).value<quint32>(), quint32(6)); 0506 // button 0507 QCOMPARE(buttonSpy.at(2).at(2).value<quint32>(), quint32(2)); 0508 QCOMPARE(buttonSpy.at(2).at(3).value<KWayland::Client::Pointer::ButtonState>(), KWayland::Client::Pointer::ButtonState::Released); 0509 0510 QCOMPARE(buttonSpy.at(3).at(0).value<quint32>(), m_seatInterface->pointerButtonSerial(1)); 0511 // timestamp 0512 QCOMPARE(buttonSpy.at(3).at(1).value<quint32>(), quint32(7)); 0513 // button 0514 QCOMPARE(buttonSpy.at(3).at(2).value<quint32>(), quint32(1)); 0515 QCOMPARE(buttonSpy.at(3).at(3).value<KWayland::Client::Pointer::ButtonState>(), KWayland::Client::Pointer::ButtonState::Released); 0516 0517 // leave the surface 0518 serial = m_display->serial(); 0519 m_seatInterface->notifyPointerLeave(); 0520 QVERIFY(leftSpy.wait()); 0521 QCOMPARE(frameSpy.count(), 12); 0522 QCOMPARE_GT(leftSpy.first().first().value<quint32>(), serial); 0523 QVERIFY(!p->enteredSurface()); 0524 QVERIFY(!cp.enteredSurface()); 0525 0526 // now a relative motion should not be sent to the relative pointer 0527 m_seatInterface->relativePointerMotion(QPointF(1, 2), QPointF(3, 4), std::chrono::milliseconds::zero()); 0528 QVERIFY(sync()); 0529 QCOMPARE(relativeMotionSpy.count(), 1); 0530 0531 // enter it again 0532 m_seatInterface->notifyPointerEnter(serverSurface, QPointF(10, 16), QPointF(0, 0)); 0533 QVERIFY(enteredSpy.wait()); 0534 QCOMPARE(frameSpy.count(), 13); 0535 QCOMPARE(p->enteredSurface(), s); 0536 QCOMPARE(cp.enteredSurface(), s); 0537 0538 // send another relative motion event 0539 m_seatInterface->relativePointerMotion(QPointF(4, 5), QPointF(6, 7), 1234us); 0540 QVERIFY(relativeMotionSpy.wait()); 0541 QCOMPARE(relativeMotionSpy.count(), 2); 0542 QCOMPARE(relativeMotionSpy.last().at(0).toSizeF(), QSizeF(4, 5)); 0543 QCOMPARE(relativeMotionSpy.last().at(1).toSizeF(), QSizeF(6, 7)); 0544 QCOMPARE(relativeMotionSpy.last().at(2).value<quint64>(), 1234); 0545 } 0546 0547 void TestWaylandSeat::testPointerTransformation_data() 0548 { 0549 QTest::addColumn<QMatrix4x4>("enterTransformation"); 0550 // global position at 20/18 0551 QTest::addColumn<QPointF>("expectedEnterPoint"); 0552 // global position at 10/16 0553 QTest::addColumn<QPointF>("expectedMovePoint"); 0554 0555 QMatrix4x4 tm; 0556 tm.translate(-10, -15); 0557 QTest::newRow("translation") << tm << QPointF(10, 3) << QPointF(0, 1); 0558 QMatrix4x4 sm; 0559 sm.scale(2, 2); 0560 QTest::newRow("scale") << sm << QPointF(40, 36) << QPointF(20, 32); 0561 QMatrix4x4 rotate; 0562 rotate.rotate(90, 0, 0, 1); 0563 QTest::newRow("rotate") << rotate << QPointF(-18, 20) << QPointF(-16, 10); 0564 } 0565 0566 void TestWaylandSeat::testPointerTransformation() 0567 { 0568 using namespace KWin; 0569 0570 QSignalSpy pointerSpy(m_seat, &KWayland::Client::Seat::hasPointerChanged); 0571 m_seatInterface->setHasPointer(true); 0572 QVERIFY(pointerSpy.wait()); 0573 0574 QSignalSpy surfaceCreatedSpy(m_compositorInterface, &CompositorInterface::surfaceCreated); 0575 KWayland::Client::Surface *s = m_compositor->createSurface(m_compositor); 0576 QVERIFY(surfaceCreatedSpy.wait()); 0577 SurfaceInterface *serverSurface = surfaceCreatedSpy.first().first().value<KWin::SurfaceInterface *>(); 0578 QVERIFY(serverSurface); 0579 0580 QImage image(QSize(100, 100), QImage::Format_ARGB32_Premultiplied); 0581 image.fill(Qt::black); 0582 s->attachBuffer(m_shm->createBuffer(image)); 0583 s->damage(image.rect()); 0584 s->commit(KWayland::Client::Surface::CommitFlag::None); 0585 QSignalSpy committedSpy(serverSurface, &KWin::SurfaceInterface::committed); 0586 QVERIFY(committedSpy.wait()); 0587 0588 KWayland::Client::Pointer *p = m_seat->createPointer(m_seat); 0589 QVERIFY(p->isValid()); 0590 const KWayland::Client::Pointer &cp = *p; 0591 0592 QSignalSpy enteredSpy(p, &KWayland::Client::Pointer::entered); 0593 QSignalSpy leftSpy(p, &KWayland::Client::Pointer::left); 0594 QSignalSpy motionSpy(p, &KWayland::Client::Pointer::motion); 0595 0596 QVERIFY(!p->enteredSurface()); 0597 QVERIFY(!cp.enteredSurface()); 0598 uint32_t serial = m_display->serial(); 0599 QFETCH(QMatrix4x4, enterTransformation); 0600 m_seatInterface->notifyPointerEnter(serverSurface, QPointF(20, 18), enterTransformation); 0601 QCOMPARE(m_seatInterface->focusedPointerSurface(), serverSurface); 0602 QVERIFY(enteredSpy.wait()); 0603 QCOMPARE_GT(enteredSpy.first().first().value<quint32>(), serial); 0604 QTEST(enteredSpy.first().last().toPointF(), "expectedEnterPoint"); 0605 QCOMPARE(p->enteredSurface(), s); 0606 QCOMPARE(cp.enteredSurface(), s); 0607 0608 // test motion 0609 m_seatInterface->setTimestamp(std::chrono::milliseconds(1)); 0610 m_seatInterface->notifyPointerMotion(QPoint(10, 16)); 0611 m_seatInterface->notifyPointerFrame(); 0612 QVERIFY(motionSpy.wait()); 0613 QTEST(motionSpy.first().first().toPointF(), "expectedMovePoint"); 0614 QCOMPARE(motionSpy.first().last().value<quint32>(), quint32(1)); 0615 0616 // leave the surface 0617 serial = m_display->serial(); 0618 m_seatInterface->notifyPointerLeave(); 0619 QVERIFY(leftSpy.wait()); 0620 QCOMPARE_GT(leftSpy.first().first().value<quint32>(), serial); 0621 QVERIFY(!p->enteredSurface()); 0622 QVERIFY(!cp.enteredSurface()); 0623 0624 // enter it again 0625 m_seatInterface->notifyPointerEnter(serverSurface, QPointF(10, 16)); 0626 QVERIFY(enteredSpy.wait()); 0627 QCOMPARE(p->enteredSurface(), s); 0628 QCOMPARE(cp.enteredSurface(), s); 0629 0630 QSignalSpy serverSurfaceDestroyedSpy(serverSurface, &QObject::destroyed); 0631 delete s; 0632 QVERIFY(serverSurfaceDestroyedSpy.wait()); 0633 QVERIFY(!m_seatInterface->focusedPointerSurface()); 0634 } 0635 0636 Q_DECLARE_METATYPE(Qt::MouseButton) 0637 0638 void TestWaylandSeat::testPointerButton_data() 0639 { 0640 QTest::addColumn<Qt::MouseButton>("qtButton"); 0641 QTest::addColumn<quint32>("waylandButton"); 0642 0643 QTest::newRow("left") << Qt::LeftButton << quint32(BTN_LEFT); 0644 QTest::newRow("right") << Qt::RightButton << quint32(BTN_RIGHT); 0645 QTest::newRow("middle") << Qt::MiddleButton << quint32(BTN_MIDDLE); 0646 QTest::newRow("back") << Qt::BackButton << quint32(BTN_BACK); 0647 QTest::newRow("x1") << Qt::XButton1 << quint32(BTN_BACK); 0648 QTest::newRow("extra1") << Qt::ExtraButton1 << quint32(BTN_BACK); 0649 QTest::newRow("forward") << Qt::ForwardButton << quint32(BTN_FORWARD); 0650 QTest::newRow("x2") << Qt::XButton2 << quint32(BTN_FORWARD); 0651 QTest::newRow("extra2") << Qt::ExtraButton2 << quint32(BTN_FORWARD); 0652 QTest::newRow("task") << Qt::TaskButton << quint32(BTN_TASK); 0653 QTest::newRow("extra3") << Qt::ExtraButton3 << quint32(BTN_TASK); 0654 QTest::newRow("extra4") << Qt::ExtraButton4 << quint32(BTN_EXTRA); 0655 QTest::newRow("extra5") << Qt::ExtraButton5 << quint32(BTN_SIDE); 0656 QTest::newRow("extra6") << Qt::ExtraButton6 << quint32(0x118); 0657 QTest::newRow("extra7") << Qt::ExtraButton7 << quint32(0x119); 0658 QTest::newRow("extra8") << Qt::ExtraButton8 << quint32(0x11a); 0659 QTest::newRow("extra9") << Qt::ExtraButton9 << quint32(0x11b); 0660 QTest::newRow("extra10") << Qt::ExtraButton10 << quint32(0x11c); 0661 QTest::newRow("extra11") << Qt::ExtraButton11 << quint32(0x11d); 0662 QTest::newRow("extra12") << Qt::ExtraButton12 << quint32(0x11e); 0663 QTest::newRow("extra13") << Qt::ExtraButton13 << quint32(0x11f); 0664 } 0665 0666 void TestWaylandSeat::testPointerButton() 0667 { 0668 using namespace KWin; 0669 0670 QSignalSpy pointerSpy(m_seat, &KWayland::Client::Seat::hasPointerChanged); 0671 m_seatInterface->setHasPointer(true); 0672 QVERIFY(pointerSpy.wait()); 0673 0674 QSignalSpy surfaceCreatedSpy(m_compositorInterface, &KWin::CompositorInterface::surfaceCreated); 0675 KWayland::Client::Surface *s = m_compositor->createSurface(m_compositor); 0676 QVERIFY(surfaceCreatedSpy.wait()); 0677 SurfaceInterface *serverSurface = surfaceCreatedSpy.first().first().value<KWin::SurfaceInterface *>(); 0678 QVERIFY(serverSurface); 0679 0680 QImage image(QSize(100, 100), QImage::Format_ARGB32_Premultiplied); 0681 image.fill(Qt::black); 0682 s->attachBuffer(m_shm->createBuffer(image)); 0683 s->damage(image.rect()); 0684 s->commit(KWayland::Client::Surface::CommitFlag::None); 0685 QSignalSpy committedSpy(serverSurface, &KWin::SurfaceInterface::committed); 0686 QVERIFY(committedSpy.wait()); 0687 0688 std::unique_ptr<KWayland::Client::Pointer> p(m_seat->createPointer()); 0689 QVERIFY(p->isValid()); 0690 QSignalSpy buttonChangedSpy(p.get(), &KWayland::Client::Pointer::buttonStateChanged); 0691 wl_display_flush(m_connection->display()); 0692 QCoreApplication::processEvents(); 0693 0694 m_seatInterface->notifyPointerEnter(serverSurface, QPointF(20, 18), QPointF(10, 15)); 0695 QVERIFY(m_seatInterface->focusedPointerSurface()); 0696 0697 QCoreApplication::processEvents(); 0698 0699 QFETCH(Qt::MouseButton, qtButton); 0700 QFETCH(quint32, waylandButton); 0701 std::chrono::milliseconds timestamp(1); 0702 QCOMPARE(m_seatInterface->isPointerButtonPressed(waylandButton), false); 0703 QCOMPARE(m_seatInterface->isPointerButtonPressed(qtButton), false); 0704 m_seatInterface->setTimestamp(timestamp); 0705 m_seatInterface->notifyPointerButton(qtButton, PointerButtonState::Pressed); 0706 m_seatInterface->notifyPointerFrame(); 0707 QCOMPARE(m_seatInterface->isPointerButtonPressed(waylandButton), true); 0708 QCOMPARE(m_seatInterface->isPointerButtonPressed(qtButton), true); 0709 QVERIFY(buttonChangedSpy.wait()); 0710 QCOMPARE(buttonChangedSpy.count(), 1); 0711 QCOMPARE(buttonChangedSpy.last().at(0).value<quint32>(), m_seatInterface->pointerButtonSerial(waylandButton)); 0712 QCOMPARE(buttonChangedSpy.last().at(0).value<quint32>(), m_seatInterface->pointerButtonSerial(qtButton)); 0713 QCOMPARE(buttonChangedSpy.last().at(1).value<quint32>(), timestamp.count()); 0714 QCOMPARE(buttonChangedSpy.last().at(2).value<quint32>(), waylandButton); 0715 QCOMPARE(buttonChangedSpy.last().at(3).value<KWayland::Client::Pointer::ButtonState>(), KWayland::Client::Pointer::ButtonState::Pressed); 0716 timestamp++; 0717 m_seatInterface->setTimestamp(timestamp); 0718 m_seatInterface->notifyPointerButton(qtButton, PointerButtonState::Released); 0719 m_seatInterface->notifyPointerFrame(); 0720 QCOMPARE(m_seatInterface->isPointerButtonPressed(waylandButton), false); 0721 QCOMPARE(m_seatInterface->isPointerButtonPressed(qtButton), false); 0722 QVERIFY(buttonChangedSpy.wait()); 0723 QCOMPARE(buttonChangedSpy.count(), 2); 0724 QCOMPARE(buttonChangedSpy.last().at(0).value<quint32>(), m_seatInterface->pointerButtonSerial(waylandButton)); 0725 QCOMPARE(buttonChangedSpy.last().at(0).value<quint32>(), m_seatInterface->pointerButtonSerial(qtButton)); 0726 QCOMPARE(buttonChangedSpy.last().at(1).value<quint32>(), timestamp.count()); 0727 QCOMPARE(buttonChangedSpy.last().at(2).value<quint32>(), waylandButton); 0728 QCOMPARE(buttonChangedSpy.last().at(3).value<KWayland::Client::Pointer::ButtonState>(), KWayland::Client::Pointer::ButtonState::Released); 0729 } 0730 0731 void TestWaylandSeat::testPointerSubSurfaceTree() 0732 { 0733 // this test verifies that pointer motion on a surface with sub-surfaces sends motion enter/leave to the sub-surface 0734 using namespace KWin; 0735 0736 // first create the pointer 0737 QSignalSpy hasPointerChangedSpy(m_seat, &KWayland::Client::Seat::hasPointerChanged); 0738 m_seatInterface->setHasPointer(true); 0739 QVERIFY(hasPointerChangedSpy.wait()); 0740 std::unique_ptr<KWayland::Client::Pointer> pointer(m_seat->createPointer()); 0741 0742 // create a sub surface tree 0743 // parent surface (100, 100) with one sub surface taking the half of it's size (50, 100) 0744 // which has two further children (50, 50) which are overlapping 0745 QSignalSpy surfaceCreatedSpy(m_compositorInterface, &CompositorInterface::surfaceCreated); 0746 std::unique_ptr<KWayland::Client::Surface> parentSurface(m_compositor->createSurface()); 0747 std::unique_ptr<KWayland::Client::Surface> childSurface(m_compositor->createSurface()); 0748 std::unique_ptr<KWayland::Client::Surface> grandChild1Surface(m_compositor->createSurface()); 0749 std::unique_ptr<KWayland::Client::Surface> grandChild2Surface(m_compositor->createSurface()); 0750 std::unique_ptr<KWayland::Client::SubSurface> childSubSurface(m_subCompositor->createSubSurface(childSurface.get(), parentSurface.get())); 0751 std::unique_ptr<KWayland::Client::SubSurface> grandChild1SubSurface(m_subCompositor->createSubSurface(grandChild1Surface.get(), childSurface.get())); 0752 std::unique_ptr<KWayland::Client::SubSurface> grandChild2SubSurface(m_subCompositor->createSubSurface(grandChild2Surface.get(), childSurface.get())); 0753 grandChild2SubSurface->setPosition(QPoint(0, 25)); 0754 0755 // let's map the surfaces 0756 auto render = [this](KWayland::Client::Surface *s, const QSize &size) { 0757 QImage image(size, QImage::Format_ARGB32_Premultiplied); 0758 image.fill(Qt::black); 0759 s->attachBuffer(m_shm->createBuffer(image)); 0760 s->damage(QRect(QPoint(0, 0), size)); 0761 s->commit(KWayland::Client::Surface::CommitFlag::None); 0762 }; 0763 render(grandChild2Surface.get(), QSize(50, 50)); 0764 render(grandChild1Surface.get(), QSize(50, 50)); 0765 render(childSurface.get(), QSize(50, 100)); 0766 render(parentSurface.get(), QSize(100, 100)); 0767 0768 QVERIFY(surfaceCreatedSpy.wait()); 0769 auto serverSurface = surfaceCreatedSpy.first().first().value<SurfaceInterface *>(); 0770 QVERIFY(serverSurface->isMapped()); 0771 0772 // send in pointer events 0773 QSignalSpy enteredSpy(pointer.get(), &KWayland::Client::Pointer::entered); 0774 QSignalSpy leftSpy(pointer.get(), &KWayland::Client::Pointer::left); 0775 QSignalSpy motionSpy(pointer.get(), &KWayland::Client::Pointer::motion); 0776 // first to the grandChild2 in the overlapped area 0777 std::chrono::milliseconds timestamp(1); 0778 m_seatInterface->setTimestamp(timestamp++); 0779 m_seatInterface->notifyPointerEnter(serverSurface, QPointF(25, 50)); 0780 QVERIFY(enteredSpy.wait()); 0781 QCOMPARE(enteredSpy.count(), 1); 0782 QCOMPARE(leftSpy.count(), 0); 0783 QCOMPARE(motionSpy.count(), 0); 0784 QCOMPARE(enteredSpy.last().last().toPointF(), QPointF(25, 25)); 0785 QCOMPARE(pointer->enteredSurface(), grandChild2Surface.get()); 0786 // a motion on grandchild2 0787 m_seatInterface->setTimestamp(timestamp++); 0788 m_seatInterface->notifyPointerMotion(QPointF(25, 60)); 0789 m_seatInterface->notifyPointerFrame(); 0790 QVERIFY(motionSpy.wait()); 0791 QCOMPARE(enteredSpy.count(), 1); 0792 QCOMPARE(leftSpy.count(), 0); 0793 QCOMPARE(motionSpy.count(), 1); 0794 QCOMPARE(motionSpy.last().first().toPointF(), QPointF(25, 35)); 0795 // motion which changes to childSurface 0796 m_seatInterface->setTimestamp(timestamp++); 0797 m_seatInterface->notifyPointerMotion(QPointF(25, 80)); 0798 m_seatInterface->notifyPointerFrame(); 0799 QVERIFY(enteredSpy.wait()); 0800 QCOMPARE(enteredSpy.count(), 2); 0801 QCOMPARE(leftSpy.count(), 1); 0802 QCOMPARE(motionSpy.count(), 2); 0803 QCOMPARE(enteredSpy.last().last().toPointF(), QPointF(25, 80)); 0804 QCOMPARE(pointer->enteredSurface(), childSurface.get()); 0805 // a leave for the whole surface 0806 m_seatInterface->setTimestamp(timestamp++); 0807 m_seatInterface->notifyPointerLeave(); 0808 QVERIFY(leftSpy.wait()); 0809 QCOMPARE(enteredSpy.count(), 2); 0810 QCOMPARE(leftSpy.count(), 2); 0811 QCOMPARE(motionSpy.count(), 2); 0812 // a new enter on the main surface 0813 m_seatInterface->setTimestamp(timestamp++); 0814 m_seatInterface->notifyPointerEnter(serverSurface, QPointF(75, 50)); 0815 QVERIFY(enteredSpy.wait()); 0816 QCOMPARE(enteredSpy.count(), 3); 0817 QCOMPARE(leftSpy.count(), 2); 0818 QCOMPARE(motionSpy.count(), 2); 0819 QCOMPARE(enteredSpy.last().last().toPointF(), QPointF(75, 50)); 0820 QCOMPARE(pointer->enteredSurface(), parentSurface.get()); 0821 } 0822 0823 void TestWaylandSeat::testPointerSwipeGesture_data() 0824 { 0825 QTest::addColumn<bool>("cancel"); 0826 QTest::addColumn<int>("expectedEndCount"); 0827 QTest::addColumn<int>("expectedCancelCount"); 0828 0829 QTest::newRow("end") << false << 1 << 0; 0830 QTest::newRow("cancel") << true << 0 << 1; 0831 } 0832 0833 void TestWaylandSeat::testPointerSwipeGesture() 0834 { 0835 using namespace KWin; 0836 0837 // first create the pointer and pointer swipe gesture 0838 QSignalSpy hasPointerChangedSpy(m_seat, &KWayland::Client::Seat::hasPointerChanged); 0839 m_seatInterface->setHasPointer(true); 0840 QVERIFY(hasPointerChangedSpy.wait()); 0841 std::unique_ptr<KWayland::Client::Pointer> pointer(m_seat->createPointer()); 0842 std::unique_ptr<KWayland::Client::PointerSwipeGesture> gesture(m_pointerGestures->createSwipeGesture(pointer.get())); 0843 QVERIFY(gesture); 0844 QVERIFY(gesture->isValid()); 0845 QVERIFY(gesture->surface().isNull()); 0846 QCOMPARE(gesture->fingerCount(), 0u); 0847 0848 QSignalSpy startSpy(gesture.get(), &KWayland::Client::PointerSwipeGesture::started); 0849 QSignalSpy updateSpy(gesture.get(), &KWayland::Client::PointerSwipeGesture::updated); 0850 QSignalSpy endSpy(gesture.get(), &KWayland::Client::PointerSwipeGesture::ended); 0851 QSignalSpy cancelledSpy(gesture.get(), &KWayland::Client::PointerSwipeGesture::cancelled); 0852 0853 // now create a surface 0854 QSignalSpy surfaceCreatedSpy(m_compositorInterface, &CompositorInterface::surfaceCreated); 0855 std::unique_ptr<KWayland::Client::Surface> surface(m_compositor->createSurface()); 0856 QVERIFY(surfaceCreatedSpy.wait()); 0857 auto serverSurface = surfaceCreatedSpy.first().first().value<SurfaceInterface *>(); 0858 QVERIFY(serverSurface); 0859 0860 QImage image(QSize(100, 100), QImage::Format_ARGB32_Premultiplied); 0861 image.fill(Qt::black); 0862 surface->attachBuffer(m_shm->createBuffer(image)); 0863 surface->damage(image.rect()); 0864 surface->commit(KWayland::Client::Surface::CommitFlag::None); 0865 QSignalSpy committedSpy(serverSurface, &KWin::SurfaceInterface::committed); 0866 QVERIFY(committedSpy.wait()); 0867 0868 m_seatInterface->notifyPointerEnter(serverSurface, QPointF(0, 0)); 0869 QCOMPARE(m_seatInterface->focusedPointerSurface(), serverSurface); 0870 QVERIFY(m_seatInterface->pointer()); 0871 0872 // send in the start 0873 std::chrono::milliseconds timestamp(1); 0874 m_seatInterface->setTimestamp(timestamp++); 0875 m_seatInterface->startPointerSwipeGesture(2); 0876 QVERIFY(startSpy.wait()); 0877 QCOMPARE(startSpy.count(), 1); 0878 QCOMPARE(startSpy.first().at(0).value<quint32>(), m_display->serial()); 0879 QCOMPARE(startSpy.first().at(1).value<quint32>(), 1u); 0880 QCOMPARE(gesture->fingerCount(), 2u); 0881 QCOMPARE(gesture->surface().data(), surface.get()); 0882 0883 // another start should not be possible 0884 m_seatInterface->startPointerSwipeGesture(2); 0885 QVERIFY(sync()); 0886 QCOMPARE(startSpy.count(), 1); 0887 0888 // send in some updates 0889 m_seatInterface->setTimestamp(timestamp++); 0890 m_seatInterface->updatePointerSwipeGesture(QPointF(2, 3)); 0891 QVERIFY(updateSpy.wait()); 0892 m_seatInterface->setTimestamp(timestamp++); 0893 m_seatInterface->updatePointerSwipeGesture(QPointF(4, 5)); 0894 QVERIFY(updateSpy.wait()); 0895 QCOMPARE(updateSpy.count(), 2); 0896 QCOMPARE(updateSpy.at(0).at(0).toSizeF(), QSizeF(2, 3)); 0897 QCOMPARE(updateSpy.at(0).at(1).value<quint32>(), 2u); 0898 QCOMPARE(updateSpy.at(1).at(0).toSizeF(), QSizeF(4, 5)); 0899 QCOMPARE(updateSpy.at(1).at(1).value<quint32>(), 3u); 0900 0901 // now end or cancel 0902 QFETCH(bool, cancel); 0903 QSignalSpy *spy; 0904 m_seatInterface->setTimestamp(timestamp++); 0905 if (cancel) { 0906 m_seatInterface->cancelPointerSwipeGesture(); 0907 spy = &cancelledSpy; 0908 } else { 0909 m_seatInterface->endPointerSwipeGesture(); 0910 spy = &endSpy; 0911 } 0912 QVERIFY(spy->wait()); 0913 QFETCH(int, expectedEndCount); 0914 QCOMPARE(endSpy.count(), expectedEndCount); 0915 QFETCH(int, expectedCancelCount); 0916 QCOMPARE(cancelledSpy.count(), expectedCancelCount); 0917 QCOMPARE(spy->count(), 1); 0918 QCOMPARE(spy->first().at(0).value<quint32>(), m_display->serial()); 0919 QCOMPARE(spy->first().at(1).value<quint32>(), 4u); 0920 0921 QCOMPARE(gesture->fingerCount(), 0u); 0922 QVERIFY(gesture->surface().isNull()); 0923 0924 // now a start should be possible again 0925 m_seatInterface->setTimestamp(timestamp++); 0926 m_seatInterface->startPointerSwipeGesture(2); 0927 QVERIFY(startSpy.wait()); 0928 0929 // unsetting the focused pointer surface should not change anything 0930 m_seatInterface->notifyPointerLeave(); 0931 m_seatInterface->setTimestamp(timestamp++); 0932 m_seatInterface->updatePointerSwipeGesture(QPointF(6, 7)); 0933 QVERIFY(updateSpy.wait()); 0934 // and end 0935 m_seatInterface->setTimestamp(timestamp++); 0936 if (cancel) { 0937 m_seatInterface->cancelPointerSwipeGesture(); 0938 } else { 0939 m_seatInterface->endPointerSwipeGesture(); 0940 } 0941 QVERIFY(spy->wait()); 0942 } 0943 0944 void TestWaylandSeat::testPointerPinchGesture_data() 0945 { 0946 QTest::addColumn<bool>("cancel"); 0947 QTest::addColumn<int>("expectedEndCount"); 0948 QTest::addColumn<int>("expectedCancelCount"); 0949 0950 QTest::newRow("end") << false << 1 << 0; 0951 QTest::newRow("cancel") << true << 0 << 1; 0952 } 0953 0954 void TestWaylandSeat::testPointerPinchGesture() 0955 { 0956 using namespace KWin; 0957 0958 // first create the pointer and pointer swipe gesture 0959 QSignalSpy hasPointerChangedSpy(m_seat, &KWayland::Client::Seat::hasPointerChanged); 0960 m_seatInterface->setHasPointer(true); 0961 QVERIFY(hasPointerChangedSpy.wait()); 0962 std::unique_ptr<KWayland::Client::Pointer> pointer(m_seat->createPointer()); 0963 std::unique_ptr<KWayland::Client::PointerPinchGesture> gesture(m_pointerGestures->createPinchGesture(pointer.get())); 0964 QVERIFY(gesture); 0965 QVERIFY(gesture->isValid()); 0966 QVERIFY(gesture->surface().isNull()); 0967 QCOMPARE(gesture->fingerCount(), 0u); 0968 0969 QSignalSpy startSpy(gesture.get(), &KWayland::Client::PointerPinchGesture::started); 0970 QSignalSpy updateSpy(gesture.get(), &KWayland::Client::PointerPinchGesture::updated); 0971 QSignalSpy endSpy(gesture.get(), &KWayland::Client::PointerPinchGesture::ended); 0972 QSignalSpy cancelledSpy(gesture.get(), &KWayland::Client::PointerPinchGesture::cancelled); 0973 0974 // now create a surface 0975 QSignalSpy surfaceCreatedSpy(m_compositorInterface, &CompositorInterface::surfaceCreated); 0976 std::unique_ptr<KWayland::Client::Surface> surface(m_compositor->createSurface()); 0977 QVERIFY(surfaceCreatedSpy.wait()); 0978 auto serverSurface = surfaceCreatedSpy.first().first().value<SurfaceInterface *>(); 0979 QVERIFY(serverSurface); 0980 0981 QImage image(QSize(100, 100), QImage::Format_ARGB32_Premultiplied); 0982 image.fill(Qt::black); 0983 surface->attachBuffer(m_shm->createBuffer(image)); 0984 surface->damage(image.rect()); 0985 surface->commit(KWayland::Client::Surface::CommitFlag::None); 0986 QSignalSpy committedSpy(serverSurface, &KWin::SurfaceInterface::committed); 0987 QVERIFY(committedSpy.wait()); 0988 0989 m_seatInterface->notifyPointerEnter(serverSurface, QPointF(0, 0)); 0990 QCOMPARE(m_seatInterface->focusedPointerSurface(), serverSurface); 0991 QVERIFY(m_seatInterface->pointer()); 0992 0993 // send in the start 0994 std::chrono::milliseconds timestamp(1); 0995 m_seatInterface->setTimestamp(timestamp++); 0996 m_seatInterface->startPointerPinchGesture(3); 0997 QVERIFY(startSpy.wait()); 0998 QCOMPARE(startSpy.count(), 1); 0999 QCOMPARE(startSpy.first().at(0).value<quint32>(), m_display->serial()); 1000 QCOMPARE(startSpy.first().at(1).value<quint32>(), 1u); 1001 QCOMPARE(gesture->fingerCount(), 3u); 1002 QCOMPARE(gesture->surface().data(), surface.get()); 1003 1004 // another start should not be possible 1005 m_seatInterface->startPointerPinchGesture(3); 1006 QVERIFY(sync()); 1007 QCOMPARE(startSpy.count(), 1); 1008 1009 // send in some updates 1010 m_seatInterface->setTimestamp(timestamp++); 1011 m_seatInterface->updatePointerPinchGesture(QPointF(2, 3), 2, 45); 1012 QVERIFY(updateSpy.wait()); 1013 m_seatInterface->setTimestamp(timestamp++); 1014 m_seatInterface->updatePointerPinchGesture(QPointF(4, 5), 1, 90); 1015 QVERIFY(updateSpy.wait()); 1016 QCOMPARE(updateSpy.count(), 2); 1017 QCOMPARE(updateSpy.at(0).at(0).toSizeF(), QSizeF(2, 3)); 1018 QCOMPARE(updateSpy.at(0).at(1).value<quint32>(), 2u); 1019 QCOMPARE(updateSpy.at(0).at(2).value<quint32>(), 45u); 1020 QCOMPARE(updateSpy.at(0).at(3).value<quint32>(), 2u); 1021 QCOMPARE(updateSpy.at(1).at(0).toSizeF(), QSizeF(4, 5)); 1022 QCOMPARE(updateSpy.at(1).at(1).value<quint32>(), 1u); 1023 QCOMPARE(updateSpy.at(1).at(2).value<quint32>(), 90u); 1024 QCOMPARE(updateSpy.at(1).at(3).value<quint32>(), 3u); 1025 1026 // now end or cancel 1027 QFETCH(bool, cancel); 1028 QSignalSpy *spy; 1029 m_seatInterface->setTimestamp(timestamp++); 1030 if (cancel) { 1031 m_seatInterface->cancelPointerPinchGesture(); 1032 spy = &cancelledSpy; 1033 } else { 1034 m_seatInterface->endPointerPinchGesture(); 1035 spy = &endSpy; 1036 } 1037 QVERIFY(spy->wait()); 1038 QFETCH(int, expectedEndCount); 1039 QCOMPARE(endSpy.count(), expectedEndCount); 1040 QFETCH(int, expectedCancelCount); 1041 QCOMPARE(cancelledSpy.count(), expectedCancelCount); 1042 QCOMPARE(spy->count(), 1); 1043 QCOMPARE(spy->first().at(0).value<quint32>(), m_display->serial()); 1044 QCOMPARE(spy->first().at(1).value<quint32>(), 4u); 1045 1046 QCOMPARE(gesture->fingerCount(), 0u); 1047 QVERIFY(gesture->surface().isNull()); 1048 1049 // now a start should be possible again 1050 m_seatInterface->setTimestamp(timestamp++); 1051 m_seatInterface->startPointerPinchGesture(3); 1052 QVERIFY(startSpy.wait()); 1053 1054 // unsetting the focused pointer surface should not change anything 1055 m_seatInterface->notifyPointerLeave(); 1056 m_seatInterface->setTimestamp(timestamp++); 1057 m_seatInterface->updatePointerPinchGesture(QPointF(6, 7), 2, -45); 1058 QVERIFY(updateSpy.wait()); 1059 // and end 1060 m_seatInterface->setTimestamp(timestamp++); 1061 if (cancel) { 1062 m_seatInterface->cancelPointerPinchGesture(); 1063 } else { 1064 m_seatInterface->endPointerPinchGesture(); 1065 } 1066 QVERIFY(spy->wait()); 1067 } 1068 1069 void TestWaylandSeat::testPointerHoldGesture_data() 1070 { 1071 QTest::addColumn<bool>("cancel"); 1072 QTest::addColumn<int>("expectedEndCount"); 1073 QTest::addColumn<int>("expectedCancelCount"); 1074 1075 QTest::newRow("end") << false << 1 << 0; 1076 QTest::newRow("cancel") << true << 0 << 1; 1077 } 1078 1079 class PointerHoldGesture : public QObject, public QtWayland::zwp_pointer_gesture_hold_v1 1080 { 1081 using zwp_pointer_gesture_hold_v1::zwp_pointer_gesture_hold_v1; 1082 Q_OBJECT 1083 void zwp_pointer_gesture_hold_v1_begin(uint32_t serial, uint32_t time, wl_surface *surface, uint32_t fingers) override 1084 { 1085 Q_EMIT started(serial, time, surface, fingers); 1086 } 1087 1088 void zwp_pointer_gesture_hold_v1_end(uint32_t serial, uint32_t time, int32_t cancelled) override 1089 { 1090 cancelled ? Q_EMIT this->cancelled(serial, time) : Q_EMIT ended(serial, time); 1091 } 1092 Q_SIGNALS: 1093 void started(quint32 serial, quint32 time, void *surface, quint32 fingers); 1094 void ended(quint32 serial, quint32 time); 1095 void cancelled(quint32 serial, quint32 time); 1096 }; 1097 1098 void TestWaylandSeat::testPointerHoldGesture() 1099 { 1100 using namespace KWin; 1101 1102 // first create the pointer and pointer swipe gesture 1103 QSignalSpy hasPointerChangedSpy(m_seat, &KWayland::Client::Seat::hasPointerChanged); 1104 m_seatInterface->setHasPointer(true); 1105 QVERIFY(hasPointerChangedSpy.wait()); 1106 std::unique_ptr<KWayland::Client::Pointer> pointer(m_seat->createPointer()); 1107 KWayland::Client::Registry registry; 1108 QSignalSpy gesturesAnnoucedSpy(®istry, &KWayland::Client::Registry::pointerGesturesUnstableV1Announced); 1109 registry.create(m_connection); 1110 registry.setup(); 1111 QVERIFY(gesturesAnnoucedSpy.wait()); 1112 QtWayland::zwp_pointer_gestures_v1 gestures(registry, gesturesAnnoucedSpy.first().at(0).value<int>(), gesturesAnnoucedSpy.first().at(1).value<int>()); 1113 PointerHoldGesture gesture(gestures.get_hold_gesture(*pointer)); 1114 QVERIFY(gesture.isInitialized()); 1115 1116 QSignalSpy startSpy(&gesture, &PointerHoldGesture::started); 1117 QSignalSpy endSpy(&gesture, &PointerHoldGesture::ended); 1118 QSignalSpy cancelledSpy(&gesture, &PointerHoldGesture::cancelled); 1119 1120 // now create a surface 1121 QSignalSpy surfaceCreatedSpy(m_compositorInterface, &CompositorInterface::surfaceCreated); 1122 std::unique_ptr<KWayland::Client::Surface> surface(m_compositor->createSurface()); 1123 QVERIFY(surfaceCreatedSpy.wait()); 1124 auto serverSurface = surfaceCreatedSpy.first().first().value<SurfaceInterface *>(); 1125 QVERIFY(serverSurface); 1126 1127 QImage image(QSize(100, 100), QImage::Format_ARGB32_Premultiplied); 1128 image.fill(Qt::black); 1129 surface->attachBuffer(m_shm->createBuffer(image)); 1130 surface->damage(image.rect()); 1131 surface->commit(KWayland::Client::Surface::CommitFlag::None); 1132 QSignalSpy committedSpy(serverSurface, &KWin::SurfaceInterface::committed); 1133 QVERIFY(committedSpy.wait()); 1134 1135 m_seatInterface->notifyPointerEnter(serverSurface, QPointF(0, 0)); 1136 QCOMPARE(m_seatInterface->focusedPointerSurface(), serverSurface); 1137 QVERIFY(m_seatInterface->pointer()); 1138 1139 // send in the start 1140 std::chrono::milliseconds timestamp(1); 1141 m_seatInterface->setTimestamp(timestamp++); 1142 m_seatInterface->startPointerHoldGesture(3); 1143 QVERIFY(startSpy.wait()); 1144 QCOMPARE(startSpy.count(), 1); 1145 QCOMPARE(startSpy.first().at(0).value<quint32>(), m_display->serial()); 1146 QCOMPARE(startSpy.first().at(1).value<quint32>(), 1u); 1147 QCOMPARE(startSpy.first().at(2).value<void *>(), *surface.get()); 1148 QCOMPARE(startSpy.first().at(3).value<quint32>(), 3); 1149 1150 // another start should not be possible 1151 m_seatInterface->startPointerPinchGesture(3); 1152 QVERIFY(sync()); 1153 QCOMPARE(startSpy.count(), 1); 1154 1155 // now end or cancel 1156 QFETCH(bool, cancel); 1157 QSignalSpy *spy; 1158 m_seatInterface->setTimestamp(timestamp++); 1159 if (cancel) { 1160 m_seatInterface->cancelPointerHoldGesture(); 1161 spy = &cancelledSpy; 1162 } else { 1163 m_seatInterface->endPointerHoldGesture(); 1164 spy = &endSpy; 1165 } 1166 QVERIFY(spy->wait()); 1167 QFETCH(int, expectedEndCount); 1168 QCOMPARE(endSpy.count(), expectedEndCount); 1169 QFETCH(int, expectedCancelCount); 1170 QCOMPARE(cancelledSpy.count(), expectedCancelCount); 1171 QCOMPARE(spy->count(), 1); 1172 QCOMPARE(spy->first().at(0).value<quint32>(), m_display->serial()); 1173 QCOMPARE(spy->first().at(1).value<quint32>(), 2); 1174 1175 // now a start should be possible again 1176 m_seatInterface->setTimestamp(timestamp++); 1177 m_seatInterface->startPointerHoldGesture(3); 1178 QVERIFY(startSpy.wait()); 1179 1180 // and end 1181 m_seatInterface->setTimestamp(timestamp++); 1182 if (cancel) { 1183 m_seatInterface->cancelPointerHoldGesture(); 1184 } else { 1185 m_seatInterface->endPointerHoldGesture(); 1186 } 1187 QVERIFY(spy->wait()); 1188 } 1189 1190 void TestWaylandSeat::testPointerAxis() 1191 { 1192 using namespace KWin; 1193 1194 // first create the pointer 1195 QSignalSpy hasPointerChangedSpy(m_seat, &KWayland::Client::Seat::hasPointerChanged); 1196 m_seatInterface->setHasPointer(true); 1197 QVERIFY(hasPointerChangedSpy.wait()); 1198 std::unique_ptr<KWayland::Client::Pointer> pointer(m_seat->createPointer()); 1199 QVERIFY(pointer); 1200 1201 // now create a surface 1202 QSignalSpy surfaceCreatedSpy(m_compositorInterface, &CompositorInterface::surfaceCreated); 1203 std::unique_ptr<KWayland::Client::Surface> surface(m_compositor->createSurface()); 1204 QVERIFY(surfaceCreatedSpy.wait()); 1205 auto serverSurface = surfaceCreatedSpy.first().first().value<SurfaceInterface *>(); 1206 QVERIFY(serverSurface); 1207 1208 QImage image(QSize(100, 100), QImage::Format_ARGB32_Premultiplied); 1209 image.fill(Qt::black); 1210 surface->attachBuffer(m_shm->createBuffer(image)); 1211 surface->damage(image.rect()); 1212 surface->commit(KWayland::Client::Surface::CommitFlag::None); 1213 QSignalSpy committedSpy(serverSurface, &KWin::SurfaceInterface::committed); 1214 QVERIFY(committedSpy.wait()); 1215 1216 m_seatInterface->notifyPointerEnter(serverSurface, QPointF(0, 0)); 1217 QCOMPARE(m_seatInterface->focusedPointerSurface(), serverSurface); 1218 QSignalSpy frameSpy(pointer.get(), &KWayland::Client::Pointer::frame); 1219 QVERIFY(frameSpy.wait()); 1220 QCOMPARE(frameSpy.count(), 1); 1221 1222 // let's scroll vertically 1223 QSignalSpy axisSourceSpy(pointer.get(), &KWayland::Client::Pointer::axisSourceChanged); 1224 QSignalSpy axisSpy(pointer.get(), &KWayland::Client::Pointer::axisChanged); 1225 QSignalSpy axisDiscreteSpy(pointer.get(), &KWayland::Client::Pointer::axisDiscreteChanged); 1226 QSignalSpy axisStoppedSpy(pointer.get(), &KWayland::Client::Pointer::axisStopped); 1227 1228 std::chrono::milliseconds timestamp(1); 1229 m_seatInterface->setTimestamp(timestamp++); 1230 m_seatInterface->notifyPointerAxis(Qt::Vertical, 10, 120, PointerAxisSource::Wheel); 1231 m_seatInterface->notifyPointerFrame(); 1232 QVERIFY(frameSpy.wait()); 1233 QCOMPARE(frameSpy.count(), 2); 1234 QCOMPARE(axisSourceSpy.count(), 1); 1235 QCOMPARE(axisSourceSpy.last().at(0).value<KWayland::Client::Pointer::AxisSource>(), KWayland::Client::Pointer::AxisSource::Wheel); 1236 QCOMPARE(axisDiscreteSpy.count(), 1); 1237 QCOMPARE(axisDiscreteSpy.last().at(0).value<KWayland::Client::Pointer::Axis>(), KWayland::Client::Pointer::Axis::Vertical); 1238 QCOMPARE(axisDiscreteSpy.last().at(1).value<qint32>(), 1); 1239 QCOMPARE(axisSpy.count(), 1); 1240 QCOMPARE(axisSpy.last().at(0).value<quint32>(), quint32(1)); 1241 QCOMPARE(axisSpy.last().at(1).value<KWayland::Client::Pointer::Axis>(), KWayland::Client::Pointer::Axis::Vertical); 1242 QCOMPARE(axisSpy.last().at(2).value<qreal>(), 10.0); 1243 QCOMPARE(axisStoppedSpy.count(), 0); 1244 1245 // let's scroll using fingers 1246 m_seatInterface->setTimestamp(timestamp++); 1247 m_seatInterface->notifyPointerAxis(Qt::Horizontal, 42, 0, PointerAxisSource::Finger); 1248 m_seatInterface->notifyPointerFrame(); 1249 QVERIFY(frameSpy.wait()); 1250 QCOMPARE(frameSpy.count(), 3); 1251 QCOMPARE(axisSourceSpy.count(), 2); 1252 QCOMPARE(axisSourceSpy.last().at(0).value<KWayland::Client::Pointer::AxisSource>(), KWayland::Client::Pointer::AxisSource::Finger); 1253 QCOMPARE(axisDiscreteSpy.count(), 1); 1254 QCOMPARE(axisSpy.count(), 2); 1255 QCOMPARE(axisSpy.last().at(0).value<quint32>(), quint32(2)); 1256 QCOMPARE(axisSpy.last().at(1).value<KWayland::Client::Pointer::Axis>(), KWayland::Client::Pointer::Axis::Horizontal); 1257 QCOMPARE(axisSpy.last().at(2).value<qreal>(), 42.0); 1258 QCOMPARE(axisStoppedSpy.count(), 0); 1259 1260 // lift the fingers off the device 1261 m_seatInterface->setTimestamp(timestamp++); 1262 m_seatInterface->notifyPointerAxis(Qt::Horizontal, 0, 0, PointerAxisSource::Finger); 1263 m_seatInterface->notifyPointerFrame(); 1264 QVERIFY(frameSpy.wait()); 1265 QCOMPARE(frameSpy.count(), 4); 1266 QCOMPARE(axisSourceSpy.count(), 3); 1267 QCOMPARE(axisSourceSpy.last().at(0).value<KWayland::Client::Pointer::AxisSource>(), KWayland::Client::Pointer::AxisSource::Finger); 1268 QCOMPARE(axisDiscreteSpy.count(), 1); 1269 QCOMPARE(axisSpy.count(), 2); 1270 QCOMPARE(axisStoppedSpy.count(), 1); 1271 QCOMPARE(axisStoppedSpy.last().at(0).value<quint32>(), 3); 1272 QCOMPARE(axisStoppedSpy.last().at(1).value<KWayland::Client::Pointer::Axis>(), KWayland::Client::Pointer::Axis::Horizontal); 1273 1274 // if the device is unknown, no axis_source event should be sent 1275 m_seatInterface->setTimestamp(timestamp++); 1276 m_seatInterface->notifyPointerAxis(Qt::Horizontal, 42, 120, PointerAxisSource::Unknown); 1277 m_seatInterface->notifyPointerFrame(); 1278 QVERIFY(frameSpy.wait()); 1279 QCOMPARE(frameSpy.count(), 5); 1280 QCOMPARE(axisSourceSpy.count(), 3); 1281 QCOMPARE(axisDiscreteSpy.count(), 2); 1282 QCOMPARE(axisDiscreteSpy.last().at(0).value<KWayland::Client::Pointer::Axis>(), KWayland::Client::Pointer::Axis::Horizontal); 1283 QCOMPARE(axisDiscreteSpy.last().at(1).value<qint32>(), 1); 1284 QCOMPARE(axisSpy.count(), 3); 1285 QCOMPARE(axisSpy.last().at(0).value<quint32>(), quint32(4)); 1286 QCOMPARE(axisSpy.last().at(1).value<KWayland::Client::Pointer::Axis>(), KWayland::Client::Pointer::Axis::Horizontal); 1287 QCOMPARE(axisSpy.last().at(2).value<qreal>(), 42.0); 1288 QCOMPARE(axisStoppedSpy.count(), 1); 1289 } 1290 1291 void TestWaylandSeat::testCursor() 1292 { 1293 using namespace KWin; 1294 1295 QSignalSpy pointerSpy(m_seat, &KWayland::Client::Seat::hasPointerChanged); 1296 m_seatInterface->setHasPointer(true); 1297 QVERIFY(pointerSpy.wait()); 1298 1299 QSignalSpy surfaceCreatedSpy(m_compositorInterface, &KWin::CompositorInterface::surfaceCreated); 1300 KWayland::Client::Surface *surface = m_compositor->createSurface(m_compositor); 1301 QVERIFY(surfaceCreatedSpy.wait()); 1302 SurfaceInterface *serverSurface = surfaceCreatedSpy.first().first().value<KWin::SurfaceInterface *>(); 1303 QVERIFY(serverSurface); 1304 1305 QImage image(QSize(100, 100), QImage::Format_ARGB32_Premultiplied); 1306 image.fill(Qt::black); 1307 surface->attachBuffer(m_shm->createBuffer(image)); 1308 surface->damage(image.rect()); 1309 surface->commit(KWayland::Client::Surface::CommitFlag::None); 1310 QSignalSpy committedSpy(serverSurface, &KWin::SurfaceInterface::committed); 1311 QVERIFY(committedSpy.wait()); 1312 1313 std::unique_ptr<KWayland::Client::Pointer> p(m_seat->createPointer()); 1314 QVERIFY(p->isValid()); 1315 wl_display_flush(m_connection->display()); 1316 QCoreApplication::processEvents(); 1317 1318 QSignalSpy enteredSpy(p.get(), &KWayland::Client::Pointer::entered); 1319 1320 uint32_t serial = m_seatInterface->display()->serial(); 1321 m_seatInterface->notifyPointerEnter(serverSurface, QPointF(20, 18), QPointF(10, 15)); 1322 QVERIFY(enteredSpy.wait()); 1323 QCOMPARE_GT(enteredSpy.first().first().value<quint32>(), serial); 1324 QVERIFY(m_seatInterface->focusedPointerSurface()); 1325 1326 QSignalSpy cursorChangedSpy(m_seatInterface->pointer(), &KWin::PointerInterface::cursorChanged); 1327 // just remove the pointer 1328 p->setCursor(nullptr); 1329 QVERIFY(cursorChangedSpy.wait()); 1330 QCOMPARE(cursorChangedSpy.count(), 1); 1331 auto cursor = std::get<KWin::PointerSurfaceCursor *>(cursorChangedSpy.last().first().value<KWin::PointerCursor>()); 1332 QVERIFY(cursor); 1333 QVERIFY(!cursor->surface()); 1334 QCOMPARE(cursor->hotspot(), QPoint()); 1335 1336 // test changing hotspot 1337 p->setCursor(nullptr, QPoint(1, 2)); 1338 QVERIFY(cursorChangedSpy.wait()); 1339 QCOMPARE(cursorChangedSpy.count(), 2); 1340 QCOMPARE(cursor->surface(), nullptr); 1341 QCOMPARE(cursor->hotspot(), QPoint(1, 2)); 1342 1343 // set surface 1344 QImage img(QSize(10, 20), QImage::Format_RGB32); 1345 img.fill(Qt::red); 1346 auto cursorSurface = m_compositor->createSurface(m_compositor); 1347 cursorSurface->attachBuffer(m_shm->createBuffer(img)); 1348 cursorSurface->damage(QRect(0, 0, 10, 20)); 1349 cursorSurface->commit(KWayland::Client::Surface::CommitFlag::None); 1350 p->setCursor(cursorSurface, QPoint(1, 2)); 1351 QVERIFY(cursorChangedSpy.wait()); 1352 QCOMPARE(cursorChangedSpy.count(), 3); 1353 QCOMPARE(cursor->hotspot(), QPoint(1, 2)); 1354 QVERIFY(cursor->surface()); 1355 1356 p->hideCursor(); 1357 QVERIFY(cursorChangedSpy.wait()); 1358 QCOMPARE(cursorChangedSpy.count(), 4); 1359 QVERIFY(!cursor->surface()); 1360 } 1361 1362 void TestWaylandSeat::testKeyboard() 1363 { 1364 using namespace KWin; 1365 1366 QSignalSpy keyboardSpy(m_seat, &KWayland::Client::Seat::hasKeyboardChanged); 1367 m_seatInterface->setHasKeyboard(true); 1368 QVERIFY(keyboardSpy.wait()); 1369 1370 // update modifiers before any surface focused 1371 m_seatInterface->notifyKeyboardModifiers(4, 3, 2, 1); 1372 1373 // create the surface 1374 QSignalSpy surfaceCreatedSpy(m_compositorInterface, &KWin::CompositorInterface::surfaceCreated); 1375 KWayland::Client::Surface *s = m_compositor->createSurface(m_compositor); 1376 QVERIFY(surfaceCreatedSpy.wait()); 1377 SurfaceInterface *serverSurface = surfaceCreatedSpy.first().first().value<KWin::SurfaceInterface *>(); 1378 QVERIFY(serverSurface); 1379 1380 KWayland::Client::Keyboard *keyboard = m_seat->createKeyboard(m_seat); 1381 QSignalSpy repeatInfoSpy(keyboard, &KWayland::Client::Keyboard::keyRepeatChanged); 1382 const KWayland::Client::Keyboard &ckeyboard = *keyboard; 1383 QVERIFY(keyboard->isValid()); 1384 QCOMPARE(keyboard->isKeyRepeatEnabled(), false); 1385 QCOMPARE(keyboard->keyRepeatDelay(), 0); 1386 QCOMPARE(keyboard->keyRepeatRate(), 0); 1387 QVERIFY(repeatInfoSpy.wait()); 1388 1389 auto serverKeyboard = m_seatInterface->keyboard(); 1390 QVERIFY(serverKeyboard); 1391 1392 // we should get the repeat info announced 1393 QCOMPARE(repeatInfoSpy.count(), 1); 1394 QCOMPARE(keyboard->isKeyRepeatEnabled(), false); 1395 QCOMPARE(keyboard->keyRepeatDelay(), 0); 1396 QCOMPARE(keyboard->keyRepeatRate(), 0); 1397 1398 // let's change repeat in server 1399 m_seatInterface->keyboard()->setRepeatInfo(25, 660); 1400 QVERIFY(repeatInfoSpy.wait()); 1401 QCOMPARE(repeatInfoSpy.count(), 2); 1402 QCOMPARE(keyboard->isKeyRepeatEnabled(), true); 1403 QCOMPARE(keyboard->keyRepeatRate(), 25); 1404 QCOMPARE(keyboard->keyRepeatDelay(), 660); 1405 1406 std::chrono::milliseconds time(1); 1407 1408 m_seatInterface->setTimestamp(time++); 1409 m_seatInterface->notifyKeyboardKey(KEY_K, KeyboardKeyState::Pressed); 1410 m_seatInterface->setTimestamp(time++); 1411 m_seatInterface->notifyKeyboardKey(KEY_D, KeyboardKeyState::Pressed); 1412 m_seatInterface->setTimestamp(time++); 1413 m_seatInterface->notifyKeyboardKey(KEY_E, KeyboardKeyState::Pressed); 1414 1415 QSignalSpy modifierSpy(keyboard, &KWayland::Client::Keyboard::modifiersChanged); 1416 1417 QSignalSpy enteredSpy(keyboard, &KWayland::Client::Keyboard::entered); 1418 m_seatInterface->setFocusedKeyboardSurface(serverSurface); 1419 QCOMPARE(m_seatInterface->focusedKeyboardSurface(), serverSurface); 1420 QCOMPARE(m_seatInterface->keyboard()->focusedSurface(), serverSurface); 1421 1422 // we get the modifiers sent after the enter 1423 QVERIFY(modifierSpy.wait()); 1424 QCOMPARE(modifierSpy.count(), 1); 1425 QCOMPARE(modifierSpy.first().at(0).value<quint32>(), quint32(4)); 1426 QCOMPARE(modifierSpy.first().at(1).value<quint32>(), quint32(3)); 1427 QCOMPARE(modifierSpy.first().at(2).value<quint32>(), quint32(2)); 1428 QCOMPARE(modifierSpy.first().at(3).value<quint32>(), quint32(1)); 1429 QCOMPARE(enteredSpy.count(), 1); 1430 // TODO: get through API 1431 QCOMPARE(enteredSpy.first().first().value<quint32>(), m_display->serial() - 1); 1432 1433 QSignalSpy keyChangedSpy(keyboard, &KWayland::Client::Keyboard::keyChanged); 1434 1435 m_seatInterface->setTimestamp(time++); 1436 m_seatInterface->notifyKeyboardKey(KEY_E, KeyboardKeyState::Released); 1437 QVERIFY(keyChangedSpy.wait()); 1438 m_seatInterface->setTimestamp(time++); 1439 m_seatInterface->notifyKeyboardKey(KEY_D, KeyboardKeyState::Released); 1440 QVERIFY(keyChangedSpy.wait()); 1441 m_seatInterface->setTimestamp(time++); 1442 m_seatInterface->notifyKeyboardKey(KEY_K, KeyboardKeyState::Released); 1443 QVERIFY(keyChangedSpy.wait()); 1444 m_seatInterface->setTimestamp(time++); 1445 m_seatInterface->notifyKeyboardKey(KEY_F1, KeyboardKeyState::Pressed); 1446 QVERIFY(keyChangedSpy.wait()); 1447 m_seatInterface->setTimestamp(time++); 1448 m_seatInterface->notifyKeyboardKey(KEY_F1, KeyboardKeyState::Released); 1449 QVERIFY(keyChangedSpy.wait()); 1450 1451 QCOMPARE(keyChangedSpy.count(), 5); 1452 QCOMPARE(keyChangedSpy.at(0).at(0).value<quint32>(), quint32(KEY_E)); 1453 QCOMPARE(keyChangedSpy.at(0).at(1).value<KWayland::Client::Keyboard::KeyState>(), KWayland::Client::Keyboard::KeyState::Released); 1454 QCOMPARE(keyChangedSpy.at(0).at(2).value<quint32>(), quint32(4)); 1455 QCOMPARE(keyChangedSpy.at(1).at(0).value<quint32>(), quint32(KEY_D)); 1456 QCOMPARE(keyChangedSpy.at(1).at(1).value<KWayland::Client::Keyboard::KeyState>(), KWayland::Client::Keyboard::KeyState::Released); 1457 QCOMPARE(keyChangedSpy.at(1).at(2).value<quint32>(), quint32(5)); 1458 QCOMPARE(keyChangedSpy.at(2).at(0).value<quint32>(), quint32(KEY_K)); 1459 QCOMPARE(keyChangedSpy.at(2).at(1).value<KWayland::Client::Keyboard::KeyState>(), KWayland::Client::Keyboard::KeyState::Released); 1460 QCOMPARE(keyChangedSpy.at(2).at(2).value<quint32>(), quint32(6)); 1461 QCOMPARE(keyChangedSpy.at(3).at(0).value<quint32>(), quint32(KEY_F1)); 1462 QCOMPARE(keyChangedSpy.at(3).at(1).value<KWayland::Client::Keyboard::KeyState>(), KWayland::Client::Keyboard::KeyState::Pressed); 1463 QCOMPARE(keyChangedSpy.at(3).at(2).value<quint32>(), quint32(7)); 1464 QCOMPARE(keyChangedSpy.at(4).at(0).value<quint32>(), quint32(KEY_F1)); 1465 QCOMPARE(keyChangedSpy.at(4).at(1).value<KWayland::Client::Keyboard::KeyState>(), KWayland::Client::Keyboard::KeyState::Released); 1466 QCOMPARE(keyChangedSpy.at(4).at(2).value<quint32>(), quint32(8)); 1467 1468 // releasing a key which is already released should not set a key changed 1469 m_seatInterface->notifyKeyboardKey(KEY_F1, KeyboardKeyState::Released); 1470 QVERIFY(sync()); 1471 QCOMPARE(keyChangedSpy.count(), 5); 1472 // let's press it again 1473 m_seatInterface->notifyKeyboardKey(KEY_F1, KeyboardKeyState::Pressed); 1474 QVERIFY(keyChangedSpy.wait()); 1475 QCOMPARE(keyChangedSpy.count(), 6); 1476 // press again should be ignored 1477 m_seatInterface->notifyKeyboardKey(KEY_F1, KeyboardKeyState::Pressed); 1478 QVERIFY(sync()); 1479 QCOMPARE(keyChangedSpy.count(), 6); 1480 // and release 1481 m_seatInterface->notifyKeyboardKey(KEY_F1, KeyboardKeyState::Released); 1482 QVERIFY(keyChangedSpy.wait()); 1483 QCOMPARE(keyChangedSpy.count(), 7); 1484 1485 m_seatInterface->notifyKeyboardModifiers(1, 2, 3, 4); 1486 QVERIFY(modifierSpy.wait()); 1487 QCOMPARE(modifierSpy.count(), 2); 1488 QCOMPARE(modifierSpy.last().at(0).value<quint32>(), quint32(1)); 1489 QCOMPARE(modifierSpy.last().at(1).value<quint32>(), quint32(2)); 1490 QCOMPARE(modifierSpy.last().at(2).value<quint32>(), quint32(3)); 1491 QCOMPARE(modifierSpy.last().at(3).value<quint32>(), quint32(4)); 1492 1493 QSignalSpy leftSpy(keyboard, &KWayland::Client::Keyboard::left); 1494 m_seatInterface->setFocusedKeyboardSurface(nullptr); 1495 QVERIFY(!m_seatInterface->focusedKeyboardSurface()); 1496 QVERIFY(leftSpy.wait()); 1497 QCOMPARE(leftSpy.count(), 1); 1498 // TODO: get through API 1499 QCOMPARE(leftSpy.first().first().value<quint32>(), m_display->serial() - 1); 1500 1501 QVERIFY(!keyboard->enteredSurface()); 1502 QVERIFY(!ckeyboard.enteredSurface()); 1503 1504 // enter it again 1505 m_seatInterface->setFocusedKeyboardSurface(serverSurface); 1506 QVERIFY(modifierSpy.wait()); 1507 QCOMPARE(m_seatInterface->focusedKeyboardSurface(), serverSurface); 1508 QCOMPARE(m_seatInterface->keyboard()->focusedSurface(), serverSurface); 1509 QCOMPARE(enteredSpy.count(), 2); 1510 1511 QCOMPARE(keyboard->enteredSurface(), s); 1512 QCOMPARE(ckeyboard.enteredSurface(), s); 1513 1514 QSignalSpy serverSurfaceDestroyedSpy(serverSurface, &QObject::destroyed); 1515 QCOMPARE(keyboard->enteredSurface(), s); 1516 delete s; 1517 QVERIFY(!keyboard->enteredSurface()); 1518 QVERIFY(leftSpy.wait()); 1519 QCOMPARE(serverSurfaceDestroyedSpy.count(), 1); 1520 QVERIFY(!m_seatInterface->focusedKeyboardSurface()); 1521 QVERIFY(!serverKeyboard->focusedSurface()); 1522 1523 // let's create a Surface again 1524 std::unique_ptr<KWayland::Client::Surface> s2(m_compositor->createSurface()); 1525 QVERIFY(surfaceCreatedSpy.wait()); 1526 QCOMPARE(surfaceCreatedSpy.count(), 2); 1527 serverSurface = surfaceCreatedSpy.last().first().value<SurfaceInterface *>(); 1528 QVERIFY(serverSurface); 1529 m_seatInterface->setFocusedKeyboardSurface(serverSurface); 1530 QCOMPARE(m_seatInterface->focusedKeyboardSurface(), serverSurface); 1531 QCOMPARE(m_seatInterface->keyboard(), serverKeyboard); 1532 } 1533 1534 void TestWaylandSeat::testSelection() 1535 { 1536 using namespace KWin; 1537 std::unique_ptr<DataDeviceManagerInterface> ddmi(new DataDeviceManagerInterface(m_display)); 1538 KWayland::Client::Registry registry; 1539 QSignalSpy dataDeviceManagerSpy(®istry, &KWayland::Client::Registry::dataDeviceManagerAnnounced); 1540 m_seatInterface->setHasKeyboard(true); 1541 registry.setEventQueue(m_queue); 1542 registry.create(m_connection->display()); 1543 QVERIFY(registry.isValid()); 1544 registry.setup(); 1545 1546 QVERIFY(dataDeviceManagerSpy.wait()); 1547 std::unique_ptr<KWayland::Client::DataDeviceManager> ddm( 1548 registry.createDataDeviceManager(dataDeviceManagerSpy.first().first().value<quint32>(), dataDeviceManagerSpy.first().last().value<quint32>())); 1549 QVERIFY(ddm->isValid()); 1550 1551 std::unique_ptr<KWayland::Client::DataDevice> dd1(ddm->getDataDevice(m_seat)); 1552 QVERIFY(dd1->isValid()); 1553 QSignalSpy selectionSpy(dd1.get(), &KWayland::Client::DataDevice::selectionOffered); 1554 QSignalSpy selectionClearedSpy(dd1.get(), &KWayland::Client::DataDevice::selectionCleared); 1555 1556 QSignalSpy surfaceCreatedSpy(m_compositorInterface, &KWin::CompositorInterface::surfaceCreated); 1557 std::unique_ptr<KWayland::Client::Surface> surface(m_compositor->createSurface()); 1558 QVERIFY(surface->isValid()); 1559 QVERIFY(surfaceCreatedSpy.wait()); 1560 auto serverSurface = surfaceCreatedSpy.first().first().value<SurfaceInterface *>(); 1561 QVERIFY(!m_seatInterface->selection()); 1562 m_seatInterface->setFocusedKeyboardSurface(serverSurface); 1563 QCOMPARE(m_seatInterface->focusedKeyboardSurface(), serverSurface); 1564 QVERIFY(selectionClearedSpy.wait()); 1565 QVERIFY(selectionSpy.isEmpty()); 1566 QVERIFY(!selectionClearedSpy.isEmpty()); 1567 selectionClearedSpy.clear(); 1568 QVERIFY(!m_seatInterface->selection()); 1569 1570 // now let's try to set a selection - we have keyboard focus, so it should be sent to us 1571 std::unique_ptr<KWayland::Client::DataSource> ds(ddm->createDataSource()); 1572 QVERIFY(ds->isValid()); 1573 ds->offer(QStringLiteral("text/plain")); 1574 dd1->setSelection(0, ds.get()); 1575 QVERIFY(selectionSpy.wait()); 1576 QCOMPARE(selectionSpy.count(), 1); 1577 auto ddi = m_seatInterface->selection(); 1578 QVERIFY(ddi); 1579 auto df = selectionSpy.first().first().value<KWayland::Client::DataOffer *>(); 1580 QCOMPARE(df->offeredMimeTypes().count(), 1); 1581 QCOMPARE(df->offeredMimeTypes().first().name(), QStringLiteral("text/plain")); 1582 1583 // try to clear 1584 dd1->setSelection(0); 1585 QVERIFY(selectionClearedSpy.wait()); 1586 QCOMPARE(selectionClearedSpy.count(), 1); 1587 QCOMPARE(selectionSpy.count(), 1); 1588 1589 // unset the keyboard focus 1590 m_seatInterface->setFocusedKeyboardSurface(nullptr); 1591 QVERIFY(!m_seatInterface->focusedKeyboardSurface()); 1592 serverSurface->client()->flush(); 1593 QCoreApplication::processEvents(); 1594 QCoreApplication::processEvents(); 1595 1596 // try to set Selection 1597 dd1->setSelection(0, ds.get()); 1598 wl_display_flush(m_connection->display()); 1599 QCoreApplication::processEvents(); 1600 QCoreApplication::processEvents(); 1601 QCOMPARE(selectionSpy.count(), 1); 1602 1603 // let's unset the selection on the seat 1604 m_seatInterface->setSelection(nullptr); 1605 // and pass focus back on our surface 1606 m_seatInterface->setFocusedKeyboardSurface(serverSurface); 1607 // we don't have a selection, so it should not send a selection 1608 QVERIFY(sync()); 1609 QCOMPARE(selectionSpy.count(), 1); 1610 // now let's set it manually 1611 m_seatInterface->setSelection(ddi); 1612 QCOMPARE(m_seatInterface->selection(), ddi); 1613 QVERIFY(selectionSpy.wait()); 1614 QCOMPARE(selectionSpy.count(), 2); 1615 // setting the same again should not change 1616 m_seatInterface->setSelection(ddi); 1617 QVERIFY(sync()); 1618 QCOMPARE(selectionSpy.count(), 2); 1619 // now clear it manually 1620 m_seatInterface->setSelection(nullptr); 1621 QVERIFY(selectionClearedSpy.wait()); 1622 QCOMPARE(selectionSpy.count(), 2); 1623 1624 // create a second ddi and a data source 1625 std::unique_ptr<KWayland::Client::DataDevice> dd2(ddm->getDataDevice(m_seat)); 1626 QVERIFY(dd2->isValid()); 1627 std::unique_ptr<KWayland::Client::DataSource> ds2(ddm->createDataSource()); 1628 QVERIFY(ds2->isValid()); 1629 ds2->offer(QStringLiteral("text/plain")); 1630 dd2->setSelection(0, ds2.get()); 1631 QVERIFY(selectionSpy.wait()); 1632 QSignalSpy cancelledSpy(ds2.get(), &KWayland::Client::DataSource::cancelled); 1633 m_seatInterface->setSelection(ddi); 1634 QVERIFY(cancelledSpy.wait()); 1635 } 1636 1637 void TestWaylandSeat::testDataDeviceForKeyboardSurface() 1638 { 1639 // this test verifies that the server does not crash when creating a datadevice for the focused keyboard surface 1640 // and the currentSelection does not have a DataSource. 1641 // to properly test the functionality this test requires a second client 1642 using namespace KWin; 1643 // create the DataDeviceManager 1644 std::unique_ptr<DataDeviceManagerInterface> ddmi(new DataDeviceManagerInterface(m_display)); 1645 QSignalSpy ddiCreatedSpy(ddmi.get(), &DataDeviceManagerInterface::dataDeviceCreated); 1646 m_seatInterface->setHasKeyboard(true); 1647 1648 // create a second Wayland client connection to use it for setSelection 1649 auto c = new KWayland::Client::ConnectionThread; 1650 QSignalSpy connectedSpy(c, &KWayland::Client::ConnectionThread::connected); 1651 c->setSocketName(s_socketName); 1652 1653 auto thread = new QThread(this); 1654 c->moveToThread(thread); 1655 thread->start(); 1656 1657 c->initConnection(); 1658 QVERIFY(connectedSpy.wait()); 1659 1660 std::unique_ptr<KWayland::Client::EventQueue> queue(new KWayland::Client::EventQueue); 1661 queue->setup(c); 1662 1663 std::unique_ptr<KWayland::Client::Registry> registry(new KWayland::Client::Registry); 1664 QSignalSpy interfacesAnnouncedSpy(registry.get(), &KWayland::Client::Registry::interfacesAnnounced); 1665 registry->setEventQueue(queue.get()); 1666 registry->create(c); 1667 QVERIFY(registry->isValid()); 1668 registry->setup(); 1669 1670 QVERIFY(interfacesAnnouncedSpy.wait()); 1671 std::unique_ptr<KWayland::Client::Seat> seat( 1672 registry->createSeat(registry->interface(KWayland::Client::Registry::Interface::Seat).name, registry->interface(KWayland::Client::Registry::Interface::Seat).version)); 1673 QVERIFY(seat->isValid()); 1674 std::unique_ptr<KWayland::Client::DataDeviceManager> ddm1(registry->createDataDeviceManager(registry->interface(KWayland::Client::Registry::Interface::DataDeviceManager).name, 1675 registry->interface(KWayland::Client::Registry::Interface::DataDeviceManager).version)); 1676 QVERIFY(ddm1->isValid()); 1677 1678 // now create our first datadevice 1679 std::unique_ptr<KWayland::Client::DataDevice> dd1(ddm1->getDataDevice(seat.get())); 1680 QVERIFY(ddiCreatedSpy.wait()); 1681 auto ddi = ddiCreatedSpy.first().first().value<DataDeviceInterface *>(); 1682 QVERIFY(ddi); 1683 m_seatInterface->setSelection(ddi->selection()); 1684 1685 // switch to other client 1686 // create a surface and pass it keyboard focus 1687 QSignalSpy surfaceCreatedSpy(m_compositorInterface, &CompositorInterface::surfaceCreated); 1688 std::unique_ptr<KWayland::Client::Surface> surface(m_compositor->createSurface()); 1689 QVERIFY(surface->isValid()); 1690 QVERIFY(surfaceCreatedSpy.wait()); 1691 auto serverSurface = surfaceCreatedSpy.first().first().value<SurfaceInterface *>(); 1692 m_seatInterface->setFocusedKeyboardSurface(serverSurface); 1693 QCOMPARE(m_seatInterface->focusedKeyboardSurface(), serverSurface); 1694 1695 // now create a DataDevice 1696 KWayland::Client::Registry registry2; 1697 QSignalSpy dataDeviceManagerSpy(®istry2, &KWayland::Client::Registry::dataDeviceManagerAnnounced); 1698 registry2.setEventQueue(m_queue); 1699 registry2.create(m_connection->display()); 1700 QVERIFY(registry2.isValid()); 1701 registry2.setup(); 1702 1703 QVERIFY(dataDeviceManagerSpy.wait()); 1704 std::unique_ptr<KWayland::Client::DataDeviceManager> ddm( 1705 registry2.createDataDeviceManager(dataDeviceManagerSpy.first().first().value<quint32>(), dataDeviceManagerSpy.first().last().value<quint32>())); 1706 QVERIFY(ddm->isValid()); 1707 1708 std::unique_ptr<KWayland::Client::DataDevice> dd(ddm->getDataDevice(m_seat)); 1709 QVERIFY(dd->isValid()); 1710 QVERIFY(ddiCreatedSpy.wait()); 1711 1712 // unset surface and set again 1713 m_seatInterface->setFocusedKeyboardSurface(nullptr); 1714 m_seatInterface->setFocusedKeyboardSurface(serverSurface); 1715 1716 // and delete the connection thread again 1717 dd1.reset(); 1718 ddm1.reset(); 1719 seat.reset(); 1720 registry.reset(); 1721 queue.reset(); 1722 c->deleteLater(); 1723 thread->quit(); 1724 thread->wait(); 1725 delete thread; 1726 } 1727 1728 void TestWaylandSeat::testTouch() 1729 { 1730 using namespace KWin; 1731 1732 QSignalSpy touchSpy(m_seat, &KWayland::Client::Seat::hasTouchChanged); 1733 m_seatInterface->setHasTouch(true); 1734 QVERIFY(touchSpy.wait()); 1735 1736 // create the surface 1737 QSignalSpy surfaceCreatedSpy(m_compositorInterface, &KWin::CompositorInterface::surfaceCreated); 1738 KWayland::Client::Surface *s = m_compositor->createSurface(m_compositor); 1739 QVERIFY(surfaceCreatedSpy.wait()); 1740 SurfaceInterface *serverSurface = surfaceCreatedSpy.first().first().value<KWin::SurfaceInterface *>(); 1741 QVERIFY(serverSurface); 1742 1743 m_seatInterface->setFocusedTouchSurface(serverSurface); 1744 // no keyboard yet 1745 QCOMPARE(m_seatInterface->focusedTouchSurface(), serverSurface); 1746 1747 KWayland::Client::Touch *touch = m_seat->createTouch(m_seat); 1748 QVERIFY(touch->isValid()); 1749 1750 // Process wl_touch bind request. 1751 wl_display_flush(m_connection->display()); 1752 QCoreApplication::processEvents(); 1753 1754 QSignalSpy sequenceStartedSpy(touch, &KWayland::Client::Touch::sequenceStarted); 1755 QSignalSpy sequenceEndedSpy(touch, &KWayland::Client::Touch::sequenceEnded); 1756 QSignalSpy sequenceCanceledSpy(touch, &KWayland::Client::Touch::sequenceCanceled); 1757 QSignalSpy frameEndedSpy(touch, &KWayland::Client::Touch::frameEnded); 1758 QSignalSpy pointAddedSpy(touch, &KWayland::Client::Touch::pointAdded); 1759 QSignalSpy pointMovedSpy(touch, &KWayland::Client::Touch::pointMoved); 1760 QSignalSpy pointRemovedSpy(touch, &KWayland::Client::Touch::pointRemoved); 1761 1762 std::chrono::milliseconds timestamp(1); 1763 1764 // try a few things 1765 m_seatInterface->setFocusedTouchSurfacePosition(QPointF(10, 20)); 1766 QCOMPARE(m_seatInterface->focusedTouchSurfacePosition(), QPointF(10, 20)); 1767 m_seatInterface->setTimestamp(timestamp++); 1768 m_seatInterface->notifyTouchDown(0, QPointF(15, 26)); 1769 QVERIFY(sequenceStartedSpy.wait()); 1770 QCOMPARE(sequenceStartedSpy.count(), 1); 1771 QCOMPARE(sequenceEndedSpy.count(), 0); 1772 QCOMPARE(sequenceCanceledSpy.count(), 0); 1773 QCOMPARE(frameEndedSpy.count(), 0); 1774 QCOMPARE(pointAddedSpy.count(), 0); 1775 QCOMPARE(pointMovedSpy.count(), 0); 1776 QCOMPARE(pointRemovedSpy.count(), 0); 1777 KWayland::Client::TouchPoint *tp = sequenceStartedSpy.first().first().value<KWayland::Client::TouchPoint *>(); 1778 QVERIFY(tp); 1779 QCOMPARE(tp->downSerial(), m_seatInterface->display()->serial()); 1780 QCOMPARE(tp->id(), 0); 1781 QVERIFY(tp->isDown()); 1782 QCOMPARE(tp->position(), QPointF(5, 6)); 1783 QCOMPARE(tp->positions().size(), 1); 1784 QCOMPARE(tp->time(), 1u); 1785 QCOMPARE(tp->timestamps().count(), 1); 1786 QCOMPARE(tp->upSerial(), 0u); 1787 QCOMPARE(tp->surface().data(), s); 1788 QCOMPARE(touch->sequence().count(), 1); 1789 QCOMPARE(touch->sequence().first(), tp); 1790 1791 // let's end the frame 1792 m_seatInterface->notifyTouchFrame(); 1793 QVERIFY(frameEndedSpy.wait()); 1794 QCOMPARE(frameEndedSpy.count(), 1); 1795 1796 // move the one point 1797 m_seatInterface->setTimestamp(timestamp++); 1798 m_seatInterface->notifyTouchMotion(0, QPointF(10, 20)); 1799 m_seatInterface->notifyTouchFrame(); 1800 QVERIFY(frameEndedSpy.wait()); 1801 QCOMPARE(sequenceStartedSpy.count(), 1); 1802 QCOMPARE(sequenceEndedSpy.count(), 0); 1803 QCOMPARE(sequenceCanceledSpy.count(), 0); 1804 QCOMPARE(frameEndedSpy.count(), 2); 1805 QCOMPARE(pointAddedSpy.count(), 0); 1806 QCOMPARE(pointMovedSpy.count(), 1); 1807 QCOMPARE(pointRemovedSpy.count(), 0); 1808 QCOMPARE(pointMovedSpy.first().first().value<KWayland::Client::TouchPoint *>(), tp); 1809 1810 QCOMPARE(tp->id(), 0); 1811 QVERIFY(tp->isDown()); 1812 QCOMPARE(tp->position(), QPointF(0, 0)); 1813 QCOMPARE(tp->positions().size(), 2); 1814 QCOMPARE(tp->time(), 2u); 1815 QCOMPARE(tp->timestamps().count(), 2); 1816 QCOMPARE(tp->upSerial(), 0u); 1817 QCOMPARE(tp->surface().data(), s); 1818 1819 // add onther point 1820 m_seatInterface->setTimestamp(timestamp++); 1821 m_seatInterface->notifyTouchDown(1, QPointF(15, 26)); 1822 m_seatInterface->notifyTouchFrame(); 1823 QVERIFY(frameEndedSpy.wait()); 1824 QCOMPARE(sequenceStartedSpy.count(), 1); 1825 QCOMPARE(sequenceEndedSpy.count(), 0); 1826 QCOMPARE(sequenceCanceledSpy.count(), 0); 1827 QCOMPARE(frameEndedSpy.count(), 3); 1828 QCOMPARE(pointAddedSpy.count(), 1); 1829 QCOMPARE(pointMovedSpy.count(), 1); 1830 QCOMPARE(pointRemovedSpy.count(), 0); 1831 QCOMPARE(touch->sequence().count(), 2); 1832 QCOMPARE(touch->sequence().first(), tp); 1833 KWayland::Client::TouchPoint *tp2 = pointAddedSpy.first().first().value<KWayland::Client::TouchPoint *>(); 1834 QVERIFY(tp2); 1835 QCOMPARE(touch->sequence().last(), tp2); 1836 QCOMPARE(tp2->id(), 1); 1837 QVERIFY(tp2->isDown()); 1838 QCOMPARE(tp2->position(), QPointF(5, 6)); 1839 QCOMPARE(tp2->positions().size(), 1); 1840 QCOMPARE(tp2->time(), 3u); 1841 QCOMPARE(tp2->timestamps().count(), 1); 1842 QCOMPARE(tp2->upSerial(), 0u); 1843 QCOMPARE(tp2->surface().data(), s); 1844 1845 // send it an up 1846 m_seatInterface->setTimestamp(timestamp++); 1847 m_seatInterface->notifyTouchUp(1); 1848 m_seatInterface->notifyTouchFrame(); 1849 QVERIFY(frameEndedSpy.wait()); 1850 QCOMPARE(sequenceStartedSpy.count(), 1); 1851 QCOMPARE(sequenceEndedSpy.count(), 0); 1852 QCOMPARE(sequenceCanceledSpy.count(), 0); 1853 QCOMPARE(frameEndedSpy.count(), 4); 1854 QCOMPARE(pointAddedSpy.count(), 1); 1855 QCOMPARE(pointMovedSpy.count(), 1); 1856 QCOMPARE(pointRemovedSpy.count(), 1); 1857 QCOMPARE(pointRemovedSpy.first().first().value<KWayland::Client::TouchPoint *>(), tp2); 1858 QCOMPARE(tp2->id(), 1); 1859 QVERIFY(!tp2->isDown()); 1860 QCOMPARE(tp2->position(), QPointF(5, 6)); 1861 QCOMPARE(tp2->positions().size(), 1); 1862 QCOMPARE(tp2->time(), 4u); 1863 QCOMPARE(tp2->timestamps().count(), 2); 1864 QCOMPARE(tp2->upSerial(), m_seatInterface->display()->serial()); 1865 QCOMPARE(tp2->surface().data(), s); 1866 1867 // send another down and up 1868 m_seatInterface->setTimestamp(timestamp++); 1869 m_seatInterface->notifyTouchDown(1, QPointF(15, 26)); 1870 m_seatInterface->notifyTouchFrame(); 1871 m_seatInterface->setTimestamp(timestamp++); 1872 m_seatInterface->notifyTouchUp(1); 1873 // and send an up for the first point 1874 m_seatInterface->notifyTouchUp(0); 1875 m_seatInterface->notifyTouchFrame(); 1876 QVERIFY(frameEndedSpy.wait()); 1877 QCOMPARE(sequenceStartedSpy.count(), 1); 1878 QCOMPARE(sequenceEndedSpy.count(), 1); 1879 QCOMPARE(sequenceCanceledSpy.count(), 0); 1880 QCOMPARE(frameEndedSpy.count(), 6); 1881 QCOMPARE(pointAddedSpy.count(), 2); 1882 QCOMPARE(pointMovedSpy.count(), 1); 1883 QCOMPARE(pointRemovedSpy.count(), 3); 1884 QCOMPARE(touch->sequence().count(), 3); 1885 QVERIFY(!touch->sequence().at(0)->isDown()); 1886 QVERIFY(!touch->sequence().at(1)->isDown()); 1887 QVERIFY(!touch->sequence().at(2)->isDown()); 1888 QVERIFY(!m_seatInterface->isTouchSequence()); 1889 1890 // try cancel 1891 m_seatInterface->setFocusedTouchSurface(serverSurface, QPointF(15, 26)); 1892 m_seatInterface->setTimestamp(timestamp++); 1893 m_seatInterface->notifyTouchDown(0, QPointF(15, 26)); 1894 m_seatInterface->notifyTouchFrame(); 1895 m_seatInterface->notifyTouchCancel(); 1896 QVERIFY(sequenceCanceledSpy.wait()); 1897 QCOMPARE(sequenceStartedSpy.count(), 2); 1898 QCOMPARE(sequenceEndedSpy.count(), 1); 1899 QCOMPARE(sequenceCanceledSpy.count(), 1); 1900 QCOMPARE(frameEndedSpy.count(), 7); 1901 QCOMPARE(pointAddedSpy.count(), 2); 1902 QCOMPARE(pointMovedSpy.count(), 1); 1903 QCOMPARE(pointRemovedSpy.count(), 3); 1904 QCOMPARE(touch->sequence().first()->position(), QPointF(0, 0)); 1905 } 1906 1907 void TestWaylandSeat::testKeymap() 1908 { 1909 using namespace KWin; 1910 1911 m_seatInterface->setHasKeyboard(true); 1912 QSignalSpy keyboardChangedSpy(m_seat, &KWayland::Client::Seat::hasKeyboardChanged); 1913 QVERIFY(keyboardChangedSpy.wait()); 1914 1915 std::unique_ptr<KWayland::Client::Keyboard> keyboard(m_seat->createKeyboard()); 1916 1917 // create surface 1918 QSignalSpy surfaceCreatedSpy(m_compositorInterface, &KWin::CompositorInterface::surfaceCreated); 1919 std::unique_ptr<KWayland::Client::Surface> surface(m_compositor->createSurface()); 1920 QVERIFY(surface->isValid()); 1921 QVERIFY(surfaceCreatedSpy.wait()); 1922 auto serverSurface = surfaceCreatedSpy.first().first().value<SurfaceInterface *>(); 1923 QVERIFY(!m_seatInterface->selection()); 1924 m_seatInterface->setFocusedKeyboardSurface(serverSurface); 1925 1926 QSignalSpy keymapChangedSpy(keyboard.get(), &KWayland::Client::Keyboard::keymapChanged); 1927 1928 m_seatInterface->keyboard()->setKeymap(QByteArrayLiteral("foo")); 1929 QVERIFY(keymapChangedSpy.wait()); 1930 int fd = keymapChangedSpy.first().first().toInt(); 1931 QVERIFY(fd != -1); 1932 // Account for null terminator. 1933 QCOMPARE(keymapChangedSpy.first().last().value<quint32>(), 4u); 1934 QFile file; 1935 QVERIFY(file.open(fd, QIODevice::ReadOnly)); 1936 const char *address = reinterpret_cast<char *>(file.map(0, keymapChangedSpy.first().last().value<quint32>())); 1937 QVERIFY(address); 1938 QCOMPARE(qstrcmp(address, "foo"), 0); 1939 file.close(); 1940 1941 // change the keymap 1942 keymapChangedSpy.clear(); 1943 m_seatInterface->keyboard()->setKeymap(QByteArrayLiteral("bar")); 1944 QVERIFY(keymapChangedSpy.wait()); 1945 fd = keymapChangedSpy.first().first().toInt(); 1946 QVERIFY(fd != -1); 1947 // Account for null terminator. 1948 QCOMPARE(keymapChangedSpy.first().last().value<quint32>(), 4u); 1949 QVERIFY(file.open(fd, QIODevice::ReadWrite)); 1950 address = reinterpret_cast<char *>(file.map(0, keymapChangedSpy.first().last().value<quint32>())); 1951 QVERIFY(address); 1952 QCOMPARE(qstrcmp(address, "bar"), 0); 1953 } 1954 1955 QTEST_GUILESS_MAIN(TestWaylandSeat) 1956 #include "test_wayland_seat.moc"