Commit a3a73569 authored by Martin Flöser's avatar Martin Flöser
Browse files

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 4513dad6
......@@ -21,6 +21,8 @@ set(SERVER_LIB_SRCS
pointer_interface.cpp
plasmashell_interface.cpp
plasmawindowmanagement_interface.cpp
pointergestures_interface.cpp
pointergestures_interface_v1.cpp
qtsurfaceextension_interface.cpp
region_interface.cpp
relativepointer_interface.cpp
......@@ -127,6 +129,11 @@ ecm_add_wayland_server_protocol(SERVER_LIB_SRCS
BASENAME xdg-shell-v5
)
ecm_add_wayland_server_protocol(SERVER_LIB_SRCS
PROTOCOL ${KWAYLAND_SOURCE_DIR}/src/client/protocols/pointer-gestures-unstable-v1.xml
BASENAME pointer-gestures-unstable-v1
)
add_library(KF5WaylandServer ${SERVER_LIB_SRCS})
generate_export_header(KF5WaylandServer
BASE_NAME
......@@ -178,6 +185,7 @@ install(FILES
outputmanagement_interface.h
output_interface.h
pointer_interface.h
pointergestures_interface.h
plasmashell_interface.h
plasmawindowmanagement_interface.h
qtsurfaceextension_interface.h
......
......@@ -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();
......
......@@ -30,6 +30,7 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
#include "output_interface.h"
#include "plasmashell_interface.h"
#include "plasmawindowmanagement_interface.h"
#include "pointergestures_interface_p.h"
#include "qtsurfaceextension_interface.h"
#include "seat_interface.h"
#include "shadow_interface.h"
......@@ -382,6 +383,18 @@ RelativePointerManagerInterface *Display::createRelativePointerManager(const Rel
return r;
}
PointerGesturesInterface *Display::createPointerGestures(const PointerGesturesInterfaceVersion &version, QObject *parent)
{
PointerGesturesInterface *p = nullptr;
switch (version) {
case PointerGesturesInterfaceVersion::UnstableV1:
p = new PointerGesturesUnstableV1Interface(this, parent);
break;
}
connect(this, &Display::aboutToTerminate, p, [p] { delete p; });
return p;
}
void Display::createShm()
{
Q_ASSERT(d->display);
......
......@@ -76,6 +76,8 @@ enum class XdgShellInterfaceVersion;
class XdgShellInterface;
enum class RelativePointerInterfaceVersion;
class RelativePointerManagerInterface;
enum class PointerGesturesInterfaceVersion;
class PointerGesturesInterface;
/**
* @brief Class holding the Wayland server display loop.
......@@ -199,6 +201,14 @@ public:
**/
RelativePointerManagerInterface *createRelativePointerManager(const RelativePointerInterfaceVersion &version, QObject *parent = nullptr);
/**
* Creates the PointerGesturesInterface in interface @p version
*
* @returns The created manager object
* @since 5.29
**/
PointerGesturesInterface *createPointerGestures(const PointerGesturesInterfaceVersion &version, QObject *parent = nullptr);
/**
* Gets the ClientConnection for the given @p client.
* If there is no ClientConnection yet for the given @p client, it will be created.
......
......@@ -19,6 +19,7 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#include "pointer_interface.h"
#include "pointer_interface_p.h"
#include "pointergestures_interface_p.h"
#include "resource_p.h"
#include "relativepointer_interface_p.h"
#include "seat_interface.h"
......@@ -88,6 +89,27 @@ void PointerInterface::Private::registerRelativePointer(RelativePointerInterface
);
}
void PointerInterface::Private::registerSwipeGesture(PointerSwipeGestureInterface *gesture)
{
swipeGestures << gesture;
QObject::connect(gesture, &QObject::destroyed, q,
[this, gesture] {
swipeGestures.removeOne(gesture);
}
);
}
void PointerInterface::Private::registerPinchGesture(PointerPinchGestureInterface *gesture)
{
pinchGestures << gesture;
QObject::connect(gesture, &QObject::destroyed, q,
[this, gesture] {
pinchGestures.removeOne(gesture);
}
);
}
namespace {
static QPointF surfacePosition(SurfaceInterface *surface) {
if (surface && surface->subSurface()) {
......@@ -108,6 +130,86 @@ void PointerInterface::Private::sendEnter(SurfaceInterface *surface, const QPoin
wl_fixed_from_double(adjustedPos.x()), wl_fixed_from_double(adjustedPos.y()));
}
void PointerInterface::Private::startSwipeGesture(quint32 serial, quint32 fingerCount)
{
if (swipeGestures.isEmpty()) {
return;
}
for (auto it = swipeGestures.constBegin(), end = swipeGestures.constEnd(); it != end; it++) {
(*it)->start(serial, fingerCount);
}
}
void PointerInterface::Private::updateSwipeGesture(const QSizeF &delta)
{
if (swipeGestures.isEmpty()) {
return;
}
for (auto it = swipeGestures.constBegin(), end = swipeGestures.constEnd(); it != end; it++) {
(*it)->update(delta);
}
}
void PointerInterface::Private::endSwipeGesture(quint32 serial)
{
if (swipeGestures.isEmpty()) {
return;
}
for (auto it = swipeGestures.constBegin(), end = swipeGestures.constEnd(); it != end; it++) {
(*it)->end(serial);
}
}
void PointerInterface::Private::cancelSwipeGesture(quint32 serial)
{
if (swipeGestures.isEmpty()) {
return;
}
for (auto it = swipeGestures.constBegin(), end = swipeGestures.constEnd(); it != end; it++) {
(*it)->cancel(serial);
}
}
void PointerInterface::Private::startPinchGesture(quint32 serial, quint32 fingerCount)
{
if (pinchGestures.isEmpty()) {
return;
}
for (auto it = pinchGestures.constBegin(), end = pinchGestures.constEnd(); it != end; it++) {