Commit 75acb783 authored by Martin Flöser's avatar Martin Flöser

Implementation of PointerGestures protocol

Summary:
Pointer gestures are created for a pointer and there are two types of
gestures: swipe and pinch.

At a given time there can only be one active gesture. The implementation
in SeatInterface ensures that there can only be one active gesture.

Each gesture consists of a start event, 0 to multiple update events and
an end event. The end can also be a cancel. To better support this the
implementation doesn't follow the protocol and splits end and cancel
into dedicated methods in the server side and into dedicated signals in
the client side.

Reviewers: #plasma_on_wayland

Subscribers: plasma-devel

Tags: #plasma_on_wayland

Differential Revision: https://phabricator.kde.org/D3169
parent 70ba7718
......@@ -26,6 +26,7 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
#include "../../src/client/event_queue.h"
#include "../../src/client/registry.h"
#include "../../src/client/output.h"
#include "../../src/client/pointergestures.h"
#include "../../src/client/seat.h"
#include "../../src/client/relativepointer.h"
#include "../../src/client/server_decoration.h"
......@@ -46,6 +47,7 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
#include "../../src/server/subcompositor_interface.h"
#include "../../src/server/outputmanagement_interface.h"
#include "../../src/server/outputdevice_interface.h"
#include "../../src/server/pointergestures_interface.h"
#include "../../src/server/textinput_interface.h"
#include "../../src/server/xdgshell_interface.h"
#include "../../src/server/relativepointer_interface.h"
......@@ -57,6 +59,7 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
#include <wayland-text-input-v2-client-protocol.h>
#include <wayland-xdg-shell-v5-client-protocol.h>
#include <wayland-relativepointer-unstable-v1-client-protocol.h>
#include <wayland-pointer-gestures-unstable-v1-client-protocol.h>
class TestWaylandRegistry : public QObject
{
......@@ -84,6 +87,7 @@ private Q_SLOTS:
void testBindTextInputManagerUnstableV2();
void testBindXdgShellUnstableV5();
void testBindRelativePointerManagerUnstableV1();
void testBindPointerGesturesUnstableV1();
void testGlobalSync();
void testGlobalSyncThreaded();
void testRemoval();
......@@ -106,6 +110,7 @@ private:
KWayland::Server::TextInputManagerInterface *m_textInputManagerV2;
KWayland::Server::XdgShellInterface *m_xdgShellUnstableV5;
KWayland::Server::RelativePointerManagerInterface *m_relativePointerV1;
KWayland::Server::PointerGesturesInterface *m_pointerGesturesV1;
};
static const QString s_socketName = QStringLiteral("kwin-test-wayland-registry-0");
......@@ -126,6 +131,7 @@ TestWaylandRegistry::TestWaylandRegistry(QObject *parent)
, m_textInputManagerV2(nullptr)
, m_xdgShellUnstableV5(nullptr)
, m_relativePointerV1(nullptr)
, m_pointerGesturesV1(nullptr)
{
}
......@@ -170,6 +176,9 @@ void TestWaylandRegistry::init()
m_relativePointerV1 = m_display->createRelativePointerManager(KWayland::Server::RelativePointerInterfaceVersion::UnstableV1);
m_relativePointerV1->create();
QCOMPARE(m_relativePointerV1->interfaceVersion(), KWayland::Server::RelativePointerInterfaceVersion::UnstableV1);
m_pointerGesturesV1 = m_display->createPointerGestures(KWayland::Server::PointerGesturesInterfaceVersion::UnstableV1);
m_pointerGesturesV1->create();
QCOMPARE(m_pointerGesturesV1->interfaceVersion(), KWayland::Server::PointerGesturesInterfaceVersion::UnstableV1);
}
void TestWaylandRegistry::cleanup()
......@@ -317,6 +326,11 @@ void TestWaylandRegistry::testBindRelativePointerManagerUnstableV1()
TEST_BIND(KWayland::Client::Registry::Interface::RelativePointerManagerUnstableV1, SIGNAL(relativePointerManagerUnstableV1Announced(quint32,quint32)), bindRelativePointerManagerUnstableV1, zwp_relative_pointer_manager_v1_destroy)
}
void TestWaylandRegistry::testBindPointerGesturesUnstableV1()
{
TEST_BIND(KWayland::Client::Registry::Interface::PointerGesturesUnstableV1, SIGNAL(pointerGesturesUnstableV1Announced(quint32,quint32)), bindPointerGesturesUnstableV1, zwp_pointer_gestures_v1_destroy)
}
#undef TEST_BIND
void TestWaylandRegistry::testRemoval()
......
......@@ -28,6 +28,7 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
#include "../../src/client/event_queue.h"
#include "../../src/client/keyboard.h"
#include "../../src/client/pointer.h"
#include "../../src/client/pointergestures.h"
#include "../../src/client/surface.h"
#include "../../src/client/registry.h"
#include "../../src/client/relativepointer.h"
......@@ -42,6 +43,7 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
#include "../../src/server/display.h"
#include "../../src/server/keyboard_interface.h"
#include "../../src/server/pointer_interface.h"
#include "../../src/server/pointergestures_interface.h"
#include "../../src/server/relativepointer_interface.h"
#include "../../src/server/seat_interface.h"
#include "../../src/server/subcompositor_interface.h"
......@@ -72,6 +74,10 @@ private Q_SLOTS:
void testPointerButton_data();
void testPointerButton();
void testPointerSubSurfaceTree();
void testPointerSwipeGesture_data();
void testPointerSwipeGesture();
void testPointerPinchGesture_data();
void testPointerPinchGesture();
void testKeyboardSubSurfaceTreeFromPointer();
void testCursor();
void testCursorDamage();
......@@ -92,12 +98,14 @@ private:
KWayland::Server::SeatInterface *m_seatInterface;
KWayland::Server::SubCompositorInterface *m_subCompositorInterface;
KWayland::Server::RelativePointerManagerInterface *m_relativePointerManagerInterface;
KWayland::Server::PointerGesturesInterface *m_pointerGesturesInterface;
KWayland::Client::ConnectionThread *m_connection;
KWayland::Client::Compositor *m_compositor;
KWayland::Client::Seat *m_seat;
KWayland::Client::ShmPool *m_shm;
KWayland::Client::SubCompositor * m_subCompositor;
KWayland::Client::RelativePointerManager *m_relativePointerManager;
KWayland::Client::PointerGestures *m_pointerGestures;
KWayland::Client::EventQueue *m_queue;
QThread *m_thread;
};
......@@ -111,12 +119,14 @@ TestWaylandSeat::TestWaylandSeat(QObject *parent)
, m_seatInterface(nullptr)
, m_subCompositorInterface(nullptr)
, m_relativePointerManagerInterface(nullptr)
, m_pointerGesturesInterface(nullptr)
, m_connection(nullptr)
, m_compositor(nullptr)
, m_seat(nullptr)
, m_shm(nullptr)
, m_subCompositor(nullptr)
, m_relativePointerManager(nullptr)
, m_pointerGestures(nullptr)
, m_queue(nullptr)
, m_thread(nullptr)
{
......@@ -147,6 +157,11 @@ void TestWaylandSeat::init()
m_relativePointerManagerInterface->create();
QVERIFY(m_relativePointerManagerInterface->isValid());
m_pointerGesturesInterface = m_display->createPointerGestures(PointerGesturesInterfaceVersion::UnstableV1, m_display);
QVERIFY(m_pointerGesturesInterface);
m_pointerGesturesInterface->create();
QVERIFY(m_pointerGesturesInterface->isValid());
// setup connection
m_connection = new KWayland::Client::ConnectionThread;
QSignalSpy connectedSpy(m_connection, SIGNAL(connected()));
......@@ -200,10 +215,19 @@ void TestWaylandSeat::init()
registry.interface(KWayland::Client::Registry::Interface::RelativePointerManagerUnstableV1).version,
this);
QVERIFY(m_relativePointerManager->isValid());
m_pointerGestures = registry.createPointerGestures(registry.interface(KWayland::Client::Registry::Interface::PointerGesturesUnstableV1).name,
registry.interface(KWayland::Client::Registry::Interface::PointerGesturesUnstableV1).version,
this);
QVERIFY(m_pointerGestures->isValid());
}
void TestWaylandSeat::cleanup()
{
if (m_pointerGestures) {
delete m_pointerGestures;
m_pointerGestures = nullptr;
}
if (m_relativePointerManager) {
delete m_relativePointerManager;
m_relativePointerManager = nullptr;
......@@ -251,6 +275,9 @@ void TestWaylandSeat::cleanup()
delete m_relativePointerManagerInterface;
m_relativePointerManagerInterface = nullptr;
delete m_pointerGesturesInterface;
m_pointerGesturesInterface = nullptr;
delete m_display;
m_display = nullptr;
}
......@@ -871,6 +898,242 @@ void TestWaylandSeat::testPointerSubSurfaceTree()
QCOMPARE(pointer->enteredSurface(), parentSurface.data());
}
void TestWaylandSeat::testPointerSwipeGesture_data()
{
QTest::addColumn<bool>("cancel");
QTest::addColumn<int>("expectedEndCount");
QTest::addColumn<int>("expectedCancelCount");
QTest::newRow("end") << false << 1 << 0;
QTest::newRow("cancel") << true << 0 << 1;
}
void TestWaylandSeat::testPointerSwipeGesture()
{
using namespace KWayland::Client;
using namespace KWayland::Server;
// first create the pointer and pointer swipe gesture
QSignalSpy hasPointerChangedSpy(m_seat, &Seat::hasPointerChanged);
QVERIFY(hasPointerChangedSpy.isValid());
m_seatInterface->setHasPointer(true);
QVERIFY(hasPointerChangedSpy.wait());
QScopedPointer<Pointer> pointer(m_seat->createPointer());
QScopedPointer<PointerSwipeGesture> gesture(m_pointerGestures->createSwipeGesture(pointer.data()));
QVERIFY(gesture);
QVERIFY(gesture->isValid());
QVERIFY(gesture->surface().isNull());
QCOMPARE(gesture->fingerCount(), 0u);
QSignalSpy startSpy(gesture.data(), &PointerSwipeGesture::started);
QVERIFY(startSpy.isValid());
QSignalSpy updateSpy(gesture.data(), &PointerSwipeGesture::updated);
QVERIFY(updateSpy.isValid());
QSignalSpy endSpy(gesture.data(), &PointerSwipeGesture::ended);
QVERIFY(endSpy.isValid());
QSignalSpy cancelledSpy(gesture.data(), &PointerSwipeGesture::cancelled);
QVERIFY(cancelledSpy.isValid());
// now create a surface
QSignalSpy surfaceCreatedSpy(m_compositorInterface, &CompositorInterface::surfaceCreated);
QVERIFY(surfaceCreatedSpy.isValid());
QScopedPointer<Surface> surface(m_compositor->createSurface());
QVERIFY(surfaceCreatedSpy.wait());
auto serverSurface = surfaceCreatedSpy.first().first().value<SurfaceInterface*>();
QVERIFY(serverSurface);
m_seatInterface->setFocusedPointerSurface(serverSurface);
QCOMPARE(m_seatInterface->focusedPointerSurface(), serverSurface);
QVERIFY(m_seatInterface->focusedPointer());
// send in the start
quint32 timestamp = 1;
m_seatInterface->setTimestamp(timestamp++);
m_seatInterface->startPointerSwipeGesture(2);
QVERIFY(startSpy.wait());
QCOMPARE(startSpy.count(), 1);
QCOMPARE(startSpy.first().at(0).value<quint32>(), m_display->serial());
QCOMPARE(startSpy.first().at(1).value<quint32>(), 1u);
QCOMPARE(gesture->fingerCount(), 2u);
QCOMPARE(gesture->surface().data(), surface.data());
// another start should not be possible
m_seatInterface->startPointerSwipeGesture(2);
QVERIFY(!startSpy.wait());
// send in some updates
m_seatInterface->setTimestamp(timestamp++);
m_seatInterface->updatePointerSwipeGesture(QSizeF(2, 3));
QVERIFY(updateSpy.wait());
m_seatInterface->setTimestamp(timestamp++);
m_seatInterface->updatePointerSwipeGesture(QSizeF(4, 5));
QVERIFY(updateSpy.wait());
QCOMPARE(updateSpy.count(), 2);
QCOMPARE(updateSpy.at(0).at(0).toSizeF(), QSizeF(2, 3));
QCOMPARE(updateSpy.at(0).at(1).value<quint32>(), 2u);
QCOMPARE(updateSpy.at(1).at(0).toSizeF(), QSizeF(4, 5));
QCOMPARE(updateSpy.at(1).at(1).value<quint32>(), 3u);
// now end or cancel
QFETCH(bool, cancel);
QSignalSpy *spy;
m_seatInterface->setTimestamp(timestamp++);
if (cancel) {
m_seatInterface->cancelPointerSwipeGesture();
spy = &cancelledSpy;
} else {
m_seatInterface->endPointerSwipeGesture();
spy = &endSpy;
}
QVERIFY(spy->wait());
QTEST(endSpy.count(), "expectedEndCount");
QTEST(cancelledSpy.count(), "expectedCancelCount");
QCOMPARE(spy->count(), 1);
QCOMPARE(spy->first().at(0).value<quint32>(), m_display->serial());
QCOMPARE(spy->first().at(1).value<quint32>(), 4u);
QCOMPARE(gesture->fingerCount(), 0u);
QVERIFY(gesture->surface().isNull());
// now a start should be possible again
m_seatInterface->setTimestamp(timestamp++);
m_seatInterface->startPointerSwipeGesture(2);
QVERIFY(startSpy.wait());
// unsetting the focused pointer surface should not change anything
m_seatInterface->setFocusedPointerSurface(nullptr);
m_seatInterface->setTimestamp(timestamp++);
m_seatInterface->updatePointerSwipeGesture(QSizeF(6, 7));
QVERIFY(updateSpy.wait());
// and end
m_seatInterface->setTimestamp(timestamp++);
if (cancel) {
m_seatInterface->cancelPointerSwipeGesture();
} else {
m_seatInterface->endPointerSwipeGesture();
}
QVERIFY(spy->wait());
}
void TestWaylandSeat::testPointerPinchGesture_data()
{
QTest::addColumn<bool>("cancel");
QTest::addColumn<int>("expectedEndCount");
QTest::addColumn<int>("expectedCancelCount");
QTest::newRow("end") << false << 1 << 0;
QTest::newRow("cancel") << true << 0 << 1;
}
void TestWaylandSeat::testPointerPinchGesture()
{
using namespace KWayland::Client;
using namespace KWayland::Server;
// first create the pointer and pointer swipe gesture
QSignalSpy hasPointerChangedSpy(m_seat, &Seat::hasPointerChanged);
QVERIFY(hasPointerChangedSpy.isValid());
m_seatInterface->setHasPointer(true);
QVERIFY(hasPointerChangedSpy.wait());
QScopedPointer<Pointer> pointer(m_seat->createPointer());
QScopedPointer<PointerPinchGesture> gesture(m_pointerGestures->createPinchGesture(pointer.data()));
QVERIFY(gesture);
QVERIFY(gesture->isValid());
QVERIFY(gesture->surface().isNull());
QCOMPARE(gesture->fingerCount(), 0u);
QSignalSpy startSpy(gesture.data(), &PointerPinchGesture::started);
QVERIFY(startSpy.isValid());
QSignalSpy updateSpy(gesture.data(), &PointerPinchGesture::updated);
QVERIFY(updateSpy.isValid());
QSignalSpy endSpy(gesture.data(), &PointerPinchGesture::ended);
QVERIFY(endSpy.isValid());
QSignalSpy cancelledSpy(gesture.data(), &PointerPinchGesture::cancelled);
QVERIFY(cancelledSpy.isValid());
// now create a surface
QSignalSpy surfaceCreatedSpy(m_compositorInterface, &CompositorInterface::surfaceCreated);
QVERIFY(surfaceCreatedSpy.isValid());
QScopedPointer<Surface> surface(m_compositor->createSurface());
QVERIFY(surfaceCreatedSpy.wait());
auto serverSurface = surfaceCreatedSpy.first().first().value<SurfaceInterface*>();
QVERIFY(serverSurface);
m_seatInterface->setFocusedPointerSurface(serverSurface);
QCOMPARE(m_seatInterface->focusedPointerSurface(), serverSurface);
QVERIFY(m_seatInterface->focusedPointer());
// send in the start
quint32 timestamp = 1;
m_seatInterface->setTimestamp(timestamp++);
m_seatInterface->startPointerPinchGesture(3);
QVERIFY(startSpy.wait());
QCOMPARE(startSpy.count(), 1);
QCOMPARE(startSpy.first().at(0).value<quint32>(), m_display->serial());
QCOMPARE(startSpy.first().at(1).value<quint32>(), 1u);
QCOMPARE(gesture->fingerCount(), 3u);
QCOMPARE(gesture->surface().data(), surface.data());
// another start should not be possible
m_seatInterface->startPointerPinchGesture(3);
QVERIFY(!startSpy.wait());
// send in some updates
m_seatInterface->setTimestamp(timestamp++);
m_seatInterface->updatePointerPinchGesture(QSizeF(2, 3), 2, 45);
QVERIFY(updateSpy.wait());
m_seatInterface->setTimestamp(timestamp++);
m_seatInterface->updatePointerPinchGesture(QSizeF(4, 5), 1, 90);
QVERIFY(updateSpy.wait());
QCOMPARE(updateSpy.count(), 2);
QCOMPARE(updateSpy.at(0).at(0).toSizeF(), QSizeF(2, 3));
QCOMPARE(updateSpy.at(0).at(1).value<quint32>(), 2u);
QCOMPARE(updateSpy.at(0).at(2).value<quint32>(), 45u);
QCOMPARE(updateSpy.at(0).at(3).value<quint32>(), 2u);
QCOMPARE(updateSpy.at(1).at(0).toSizeF(), QSizeF(4, 5));
QCOMPARE(updateSpy.at(1).at(1).value<quint32>(), 1u);
QCOMPARE(updateSpy.at(1).at(2).value<quint32>(), 90u);
QCOMPARE(updateSpy.at(1).at(3).value<quint32>(), 3u);
// now end or cancel
QFETCH(bool, cancel);
QSignalSpy *spy;
m_seatInterface->setTimestamp(timestamp++);
if (cancel) {
m_seatInterface->cancelPointerPinchGesture();
spy = &cancelledSpy;
} else {
m_seatInterface->endPointerPinchGesture();
spy = &endSpy;
}
QVERIFY(spy->wait());
QTEST(endSpy.count(), "expectedEndCount");
QTEST(cancelledSpy.count(), "expectedCancelCount");
QCOMPARE(spy->count(), 1);
QCOMPARE(spy->first().at(0).value<quint32>(), m_display->serial());
QCOMPARE(spy->first().at(1).value<quint32>(), 4u);
QCOMPARE(gesture->fingerCount(), 0u);
QVERIFY(gesture->surface().isNull());
// now a start should be possible again
m_seatInterface->setTimestamp(timestamp++);
m_seatInterface->startPointerPinchGesture(3);
QVERIFY(startSpy.wait());
// unsetting the focused pointer surface should not change anything
m_seatInterface->setFocusedPointerSurface(nullptr);
m_seatInterface->setTimestamp(timestamp++);
m_seatInterface->updatePointerPinchGesture(QSizeF(6, 7), 2, -45);
QVERIFY(updateSpy.wait());
// and end
m_seatInterface->setTimestamp(timestamp++);
if (cancel) {
m_seatInterface->cancelPointerPinchGesture();
} else {
m_seatInterface->endPointerPinchGesture();
}
QVERIFY(spy->wait());
}
void TestWaylandSeat::testKeyboardSubSurfaceTreeFromPointer()
{
// this test verifies that when clicking on a sub-surface the keyboard focus passes to it
......@@ -1419,6 +1682,7 @@ void TestWaylandSeat::testDestroy()
connect(m_connection, &ConnectionThread::connectionDied, m_shm, &ShmPool::destroy);
connect(m_connection, &ConnectionThread::connectionDied, m_subCompositor, &SubCompositor::destroy);
connect(m_connection, &ConnectionThread::connectionDied, m_relativePointerManager, &RelativePointerManager::destroy);
connect(m_connection, &ConnectionThread::connectionDied, m_pointerGestures, &PointerGestures::destroy);
connect(m_connection, &ConnectionThread::connectionDied, m_queue, &EventQueue::destroy);
QVERIFY(m_seat->isValid());
......@@ -1430,6 +1694,7 @@ void TestWaylandSeat::testDestroy()
m_seatInterface = nullptr;
m_subCompositorInterface = nullptr;
m_relativePointerManagerInterface = nullptr;
m_pointerGesturesInterface = nullptr;
QVERIFY(connectionDiedSpy.wait());
// now the seat should be destroyed;
......@@ -1977,6 +2242,7 @@ void TestWaylandSeat::testDisconnect()
pointer->destroy();
touch->destroy();
m_relativePointerManager->destroy();
m_pointerGestures->destroy();
m_compositor->destroy();
m_seat->destroy();
m_shm->destroy();
......
......@@ -28,6 +28,7 @@ set(CLIENT_LIB_SRCS
logging.cpp
output.cpp
pointer.cpp
pointergestures.cpp
plasmashell.cpp
plasmawindowmanagement.cpp
plasmawindowmodel.cpp
......@@ -128,6 +129,10 @@ ecm_add_wayland_client_protocol(CLIENT_LIB_SRCS
PROTOCOL ${KWayland_SOURCE_DIR}/src/client/protocols/relative-pointer-unstable-v1.xml
BASENAME relativepointer-unstable-v1
)
ecm_add_wayland_client_protocol(CLIENT_LIB_SRCS
PROTOCOL ${KWAYLAND_SOURCE_DIR}/src/client/protocols/pointer-gestures-unstable-v1.xml
BASENAME pointer-gestures-unstable-v1
)
add_library(KF5WaylandClient ${CLIENT_LIB_SRCS})
generate_export_header(KF5WaylandClient
......@@ -178,6 +183,7 @@ install(FILES
plasmashell.h
plasmawindowmanagement.h
plasmawindowmodel.h
pointergestures.h
region.h
registry.h
relativepointer.h
......
/****************************************************************************
Copyright 2016 Martin Gräßlin <mgraesslin@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) version 3, or any
later version accepted by the membership of KDE e.V. (or its
successor approved by the membership of KDE e.V.), which shall
act as a proxy defined in Section 6 of version 3 of the license.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#include "pointergestures.h"
#include "pointer.h"
#include "event_queue.h"
#include "surface.h"
#include "wayland_pointer_p.h"
#include <wayland-pointer-gestures-unstable-v1-client-protocol.h>
#include <QSizeF>
namespace KWayland
{
namespace Client
{
class PointerGestures::Private
{
public:
Private() = default;
WaylandPointer<zwp_pointer_gestures_v1, zwp_pointer_gestures_v1_destroy> pointergestures;
EventQueue *queue = nullptr;
};
PointerGestures::PointerGestures(QObject *parent)
: QObject(parent)
, d(new Private)
{
}
PointerGestures::~PointerGestures()
{
release();
}
void PointerGestures::setup(zwp_pointer_gestures_v1 *pointergestures)
{
Q_ASSERT(pointergestures);
Q_ASSERT(!d->pointergestures);
d->pointergestures.setup(pointergestures);
}
void PointerGestures::release()
{
d->pointergestures.release();
}
void PointerGestures::destroy()
{
d->pointergestures.destroy();
}
PointerGestures::operator zwp_pointer_gestures_v1*() {
return d->pointergestures;
}
PointerGestures::operator zwp_pointer_gestures_v1*() const {
return d->pointergestures;
}
bool PointerGestures::isValid() const
{
return d->pointergestures.isValid();
}
void PointerGestures::setEventQueue(EventQueue *queue)
{
d->queue = queue;
}
EventQueue *PointerGestures::eventQueue()
{
return d->queue;
}
PointerSwipeGesture *PointerGestures::createSwipeGesture(Pointer *pointer, QObject *parent)
{
Q_ASSERT(isValid());
PointerSwipeGesture *p = new PointerSwipeGesture(parent);
auto w = zwp_pointer_gestures_v1_get_swipe_gesture(d->pointergestures, *pointer);
if (d->queue) {
d->queue->addProxy(w);
}
p->setup(w);
return p;
}
PointerPinchGesture *PointerGestures::createPinchGesture(Pointer *pointer, QObject *parent)
{
Q_ASSERT(isValid());
PointerPinchGesture *p = new PointerPinchGesture(parent);
auto w = zwp_pointer_gestures_v1_get_pinch_gesture(d->pointergestures, *pointer);
if (d->queue) {
d->queue->addProxy(w);
}
p->setup(w);
return p;
}
class PointerSwipeGesture::Private
{
public:
Private(PointerSwipeGesture *q);
void setup(zwp_pointer_gesture_swipe_v1 *pg);
WaylandPointer<zwp_pointer_gesture_swipe_v1, zwp_pointer_gesture_swipe_v1_destroy> pointerswipegesture;
quint32 fingerCount = 0;
QPointer<Surface> surface;
private:
static void beginCallback(void *data, zwp_pointer_gesture_swipe_v1 *zwp_pointer_gesture_swipe_v1, uint32_t serial, uint32_t time, wl_surface *surface, uint32_t fingers);
static void updateCallback(void *data, zwp_pointer_gesture_swipe_v1 *zwp_pointer_gesture_swipe_v1, uint32_t time, wl_fixed_t dx, wl_fixed_t dy);
static void endCallback(void *data, zwp_pointer_gesture_swipe_v1 *zwp_pointer_gesture_swipe_v1, uint32_t serial, uint32_t time, int32_t cancelled);
PointerSwipeGesture *q;
static const zwp_pointer_gesture_swipe_v1_listener s_listener;
};
const zwp_pointer_gesture_swipe_v1_listener PointerSwipeGesture::Private::s_listener = {
beginCallback,
updateCallback,
endCallback
};