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(&registry, &KWayland::Client::Registry::compositorAnnounced);
0191     QSignalSpy seatSpy(&registry, &KWayland::Client::Registry::seatAnnounced);
0192     QSignalSpy shmSpy(&registry, &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(&registry, &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(&registry, &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(&registry2, &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"