aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick/items')
-rw-r--r--src/quick/items/qquickevents.cpp118
-rw-r--r--src/quick/items/qquickevents_p_p.h41
-rw-r--r--src/quick/items/qquickwindow.cpp45
-rw-r--r--src/quick/items/qquickwindow_p.h2
4 files changed, 191 insertions, 15 deletions
diff --git a/src/quick/items/qquickevents.cpp b/src/quick/items/qquickevents.cpp
index 3011d75aa0..0f64890825 100644
--- a/src/quick/items/qquickevents.cpp
+++ b/src/quick/items/qquickevents.cpp
@@ -40,6 +40,7 @@
#include "qquickevents_p_p.h"
#include <QtCore/qmap.h>
#include <QtGui/private/qguiapplication_p.h>
+#include <QtGui/private/qtouchdevice_p.h>
#include <QtQuick/private/qquickitem_p.h>
#include <QtQuick/private/qquickpointerhandler_p.h>
#include <QtQuick/private/qquickwindow_p.h>
@@ -525,7 +526,7 @@ Item {
\sa QTouchDevice::capabilities
*/
-typedef QHash<QTouchDevice *, QQuickPointerDevice *> PointerDeviceForTouchDeviceHash;
+typedef QHash<const QTouchDevice *, QQuickPointerDevice *> PointerDeviceForTouchDeviceHash;
Q_GLOBAL_STATIC(PointerDeviceForTouchDeviceHash, g_touchDevices)
struct ConstructableQQuickPointerDevice : public QQuickPointerDevice
@@ -561,7 +562,7 @@ static const QString pointDeviceName(const QQuickEventPoint *point)
}
-QQuickPointerDevice *QQuickPointerDevice::touchDevice(QTouchDevice *d)
+QQuickPointerDevice *QQuickPointerDevice::touchDevice(const QTouchDevice *d)
{
if (g_touchDevices->contains(d))
return g_touchDevices->value(d);
@@ -1330,6 +1331,36 @@ void QQuickPointerTouchEvent::localize(QQuickItem *target)
point->localizePosition(target);
}
+QQuickPointerEvent *QQuickPointerNativeGestureEvent::reset(QEvent *event)
+{
+ auto ev = static_cast<QNativeGestureEvent*>(event);
+ m_event = ev;
+ if (!event)
+ return this;
+
+ m_device = QQuickPointerDevice::touchDevice(ev->device());
+ m_device->eventDeliveryTargets().clear();
+ Qt::TouchPointState state = Qt::TouchPointMoved;
+ switch (type()) {
+ case Qt::BeginNativeGesture:
+ state = Qt::TouchPointPressed;
+ break;
+ case Qt::EndNativeGesture:
+ state = Qt::TouchPointReleased;
+ break;
+ default:
+ break;
+ }
+ quint64 deviceId = QTouchDevicePrivate::get(const_cast<QTouchDevice *>(ev->device()))->id; // a bit roundabout since QTouchDevice::mTouchDeviceId is protected
+ m_gesturePoint->reset(state, ev->windowPos(), deviceId << 24, ev->timestamp());
+ return this;
+}
+
+void QQuickPointerNativeGestureEvent::localize(QQuickItem *target)
+{
+ m_gesturePoint->localizePosition(target);
+}
+
QQuickEventPoint *QQuickPointerMouseEvent::point(int i) const {
if (i == 0)
return m_mousePoint;
@@ -1342,6 +1373,12 @@ QQuickEventPoint *QQuickPointerTouchEvent::point(int i) const {
return nullptr;
}
+QQuickEventPoint *QQuickPointerNativeGestureEvent::point(int i) const {
+ if (i == 0)
+ return m_gesturePoint;
+ return nullptr;
+}
+
QQuickEventPoint::QQuickEventPoint(QQuickPointerEvent *parent)
: QObject(parent), m_pointId(0), m_exclusiveGrabber(nullptr), m_timestamp(0), m_pressTimestamp(0),
m_state(QQuickEventPoint::Released), m_accept(false), m_grabberIsHandler(false)
@@ -1562,6 +1599,64 @@ QMouseEvent *QQuickPointerTouchEvent::syntheticMouseEvent(int pointID, QQuickIte
}
/*!
+ Returns the exclusive grabber of this event, if any, in a vector.
+*/
+QVector<QObject *> QQuickPointerNativeGestureEvent::exclusiveGrabbers() const
+{
+ QVector<QObject *> result;
+ if (QObject *grabber = m_gesturePoint->exclusiveGrabber())
+ result << grabber;
+ return result;
+}
+
+/*!
+ Remove all passive and exclusive grabbers of this event, without notifying.
+*/
+void QQuickPointerNativeGestureEvent::clearGrabbers() const {
+ m_gesturePoint->setGrabberItem(nullptr);
+ m_gesturePoint->clearPassiveGrabbers();
+}
+
+/*!
+ Returns whether the given \a handler is the exclusive grabber of this event.
+*/
+bool QQuickPointerNativeGestureEvent::hasExclusiveGrabber(const QQuickPointerHandler *handler) const
+{
+ return m_gesturePoint->exclusiveGrabber() == handler;
+}
+
+bool QQuickPointerNativeGestureEvent::isPressEvent() const
+{
+ return type() == Qt::BeginNativeGesture;
+}
+
+bool QQuickPointerNativeGestureEvent::isUpdateEvent() const
+{
+ switch (type()) {
+ case Qt::BeginNativeGesture:
+ case Qt::EndNativeGesture:
+ return false;
+ default:
+ return true;
+ }
+}
+
+bool QQuickPointerNativeGestureEvent::isReleaseEvent() const
+{
+ return type() == Qt::EndNativeGesture;
+}
+
+Qt::NativeGestureType QQuickPointerNativeGestureEvent::type() const
+{
+ return static_cast<QNativeGestureEvent *>(m_event)->gestureType();
+}
+
+qreal QQuickPointerNativeGestureEvent::value() const
+{
+ return static_cast<QNativeGestureEvent *>(m_event)->value();
+}
+
+/*!
\internal
Returns a pointer to the QQuickEventPoint which has the \a pointId as
\l {QQuickEventPoint::pointId}{pointId}.
@@ -1583,6 +1678,12 @@ QQuickEventPoint *QQuickPointerTouchEvent::pointById(int pointId) const {
return nullptr;
}
+QQuickEventPoint *QQuickPointerNativeGestureEvent::pointById(int pointId) const {
+ if (m_gesturePoint && pointId == m_gesturePoint->pointId())
+ return m_gesturePoint;
+ return nullptr;
+}
+
/*!
\internal
@@ -1701,6 +1802,19 @@ QTouchEvent *QQuickPointerTouchEvent::asTouchEvent() const
return static_cast<QTouchEvent *>(m_event);
}
+bool QQuickPointerNativeGestureEvent::allPointsAccepted() const {
+ return m_gesturePoint->isAccepted();
+}
+
+bool QQuickPointerNativeGestureEvent::allUpdatedPointsAccepted() const {
+ return m_gesturePoint->state() == QQuickEventPoint::Pressed || m_gesturePoint->isAccepted();
+}
+
+bool QQuickPointerNativeGestureEvent::allPointsGrabbed() const
+{
+ return m_gesturePoint->exclusiveGrabber() != nullptr;
+}
+
#ifndef QT_NO_DEBUG_STREAM
Q_QUICK_PRIVATE_EXPORT QDebug operator<<(QDebug dbg, const QQuickPointerDevice *dev) {
diff --git a/src/quick/items/qquickevents_p_p.h b/src/quick/items/qquickevents_p_p.h
index 50c9a86b9f..09a63febdc 100644
--- a/src/quick/items/qquickevents_p_p.h
+++ b/src/quick/items/qquickevents_p_p.h
@@ -66,6 +66,7 @@ QT_BEGIN_NAMESPACE
class QQuickPointerDevice;
class QQuickPointerEvent;
class QQuickPointerMouseEvent;
+class QQuickPointerNativeGestureEvent;
class QQuickPointerTabletEvent;
class QQuickPointerTouchEvent;
class QQuickPointerHandler;
@@ -413,9 +414,11 @@ public: // helpers for C++ only (during event delivery)
virtual QQuickPointerMouseEvent *asPointerMouseEvent() { return nullptr; }
virtual QQuickPointerTouchEvent *asPointerTouchEvent() { return nullptr; }
virtual QQuickPointerTabletEvent *asPointerTabletEvent() { return nullptr; }
+ virtual QQuickPointerNativeGestureEvent *asPointerNativeGestureEvent() { return nullptr; }
virtual const QQuickPointerMouseEvent *asPointerMouseEvent() const { return nullptr; }
virtual const QQuickPointerTouchEvent *asPointerTouchEvent() const { return nullptr; }
virtual const QQuickPointerTabletEvent *asPointerTabletEvent() const { return nullptr; }
+ virtual const QQuickPointerNativeGestureEvent *asPointerNativeGestureEvent() const { return nullptr; }
virtual bool allPointsAccepted() const = 0;
virtual bool allUpdatedPointsAccepted() const = 0;
virtual bool allPointsGrabbed() const = 0;
@@ -515,6 +518,42 @@ private:
Q_DISABLE_COPY(QQuickPointerTouchEvent)
};
+class Q_QUICK_PRIVATE_EXPORT QQuickPointerNativeGestureEvent : public QQuickPointerEvent
+{
+ Q_OBJECT
+ Q_PROPERTY(Qt::NativeGestureType type READ type CONSTANT)
+ Q_PROPERTY(qreal value READ value CONSTANT)
+
+public:
+ QQuickPointerNativeGestureEvent(QObject *parent = nullptr, QQuickPointerDevice *device = nullptr)
+ : QQuickPointerEvent(parent, device), m_gesturePoint(new QQuickEventPoint(this)) { }
+
+ QQuickPointerEvent *reset(QEvent *) override;
+ void localize(QQuickItem *target) override;
+ bool isPressEvent() const override;
+ bool isUpdateEvent() const override;
+ bool isReleaseEvent() const override;
+ QQuickPointerNativeGestureEvent *asPointerNativeGestureEvent() override { return this; }
+ const QQuickPointerNativeGestureEvent *asPointerNativeGestureEvent() const override { return this; }
+ int pointCount() const override { return 1; }
+ QQuickEventPoint *point(int i) const override;
+ QQuickEventPoint *pointById(int pointId) const override;
+ bool allPointsAccepted() const override;
+ bool allUpdatedPointsAccepted() const override;
+ bool allPointsGrabbed() const override;
+ QVector<QObject *> exclusiveGrabbers() const override;
+ void clearGrabbers() const override;
+ bool hasExclusiveGrabber(const QQuickPointerHandler *handler) const override;
+ Qt::NativeGestureType type() const;
+ qreal value() const;
+
+private:
+ QQuickEventPoint *m_gesturePoint;
+
+ Q_DISABLE_COPY(QQuickPointerNativeGestureEvent)
+};
+
+
// ### Qt 6: move this to qtbase, replace QTouchDevice and the enums in QTabletEvent
class Q_QUICK_PRIVATE_EXPORT QQuickPointerDevice : public QObject
{
@@ -579,7 +618,7 @@ public:
QString name() const { return m_name; }
QPointingDeviceUniqueId uniqueId() const { return m_uniqueId; }
- static QQuickPointerDevice *touchDevice(QTouchDevice *d);
+ static QQuickPointerDevice *touchDevice(const QTouchDevice *d);
static QList<QQuickPointerDevice *> touchDevices();
static QQuickPointerDevice *genericMouseDevice();
static QQuickPointerDevice *tabletDevice(qint64);
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index bd1a5076fd..8c7cbe5117 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -1915,10 +1915,20 @@ bool QQuickWindowPrivate::deliverNativeGestureEvent(QQuickItem *item, QNativeGes
return true;
}
- QPointF p = item->mapFromScene(event->localPos());
+ // Try the Item's pointer handlers first
+ QQuickPointerEvent *pointerEvent = pointerEventInstance(event);
+ pointerEvent->localize(item);
+ if (itemPrivate->handlePointerEvent(pointerEvent, false)) {
+ if (pointerEvent->allPointsAccepted()) {
+ event->accept();
+ return true;
+ }
+ }
+ // If still not accepted, try direct delivery to the item
+ QPointF p = item->mapFromScene(event->localPos());
if (item->contains(p)) {
- QNativeGestureEvent copy(event->gestureType(), p, event->windowPos(), event->screenPos(),
+ QNativeGestureEvent copy(event->gestureType(), event->device(), p, event->windowPos(), event->screenPos(),
event->value(), 0L, 0L); // TODO can't copy things I can't access
event->accept();
item->event(&copy);
@@ -2164,23 +2174,36 @@ void QQuickWindowPrivate::flushFrameSynchronousEvents()
}
}
-QQuickPointerEvent *QQuickWindowPrivate::pointerEventInstance(QQuickPointerDevice *device) const
+QQuickPointerEvent *QQuickWindowPrivate::pointerEventInstance(QQuickPointerDevice *device, QEvent::Type eventType) const
{
- // the list of devices should be very small so a linear search should be ok
- for (QQuickPointerEvent *e: pointerEventInstances) {
+ // Search for a matching reusable event object.
+ for (QQuickPointerEvent *e : pointerEventInstances) {
+ // If device can generate native gestures (e.g. a trackpad), there might be two QQuickPointerEvents:
+ // QQuickPointerNativeGestureEvent and QQuickPointerTouchEvent. Use eventType to disambiguate.
+ if (eventType == QEvent::NativeGesture && !qobject_cast<QQuickPointerNativeGestureEvent*>(e))
+ continue;
+ // Otherwise we assume there's only one event type per device.
+ // More disambiguation tests might need to be added above if that changes later.
if (e->device() == device)
return e;
}
+ // Not found: we have to create a suitable event instance.
QQuickPointerEvent *ev = nullptr;
QQuickWindow *q = const_cast<QQuickWindow*>(q_func());
switch (device->type()) {
case QQuickPointerDevice::Mouse:
+ // QWindowSystemInterface::handleMouseEvent() does not take a device parameter:
+ // we assume all mouse events come from one mouse (the "core pointer").
+ // So when the event is a mouse event, device == QQuickPointerDevice::genericMouseDevice()
ev = new QQuickPointerMouseEvent(q, device);
break;
case QQuickPointerDevice::TouchPad:
case QQuickPointerDevice::TouchScreen:
- ev = new QQuickPointerTouchEvent(q, device);
+ if (eventType == QEvent::NativeGesture)
+ ev = new QQuickPointerNativeGestureEvent(q, device);
+ else // assume QEvent::Type is one of TouchBegin/Update/End
+ ev = new QQuickPointerTouchEvent(q, device);
break;
default:
// TODO tablet event types
@@ -2200,29 +2223,29 @@ QQuickPointerEvent *QQuickWindowPrivate::pointerEventInstance(QQuickPointerDevic
QQuickPointerEvent *QQuickWindowPrivate::pointerEventInstance(QEvent *event) const
{
QQuickPointerDevice *dev = nullptr;
- QQuickPointerEvent *ev = nullptr;
switch (event->type()) {
case QEvent::MouseButtonPress:
case QEvent::MouseButtonRelease:
case QEvent::MouseButtonDblClick:
case QEvent::MouseMove:
dev = QQuickPointerDevice::genericMouseDevice();
- ev = pointerEventInstance(dev);
break;
case QEvent::TouchBegin:
case QEvent::TouchUpdate:
case QEvent::TouchEnd:
case QEvent::TouchCancel:
dev = QQuickPointerDevice::touchDevice(static_cast<QTouchEvent *>(event)->device());
- ev = pointerEventInstance(dev);
break;
// TODO tablet event types
+ case QEvent::NativeGesture:
+ dev = QQuickPointerDevice::touchDevice(static_cast<QNativeGestureEvent *>(event)->device());
+ break;
default:
break;
}
- Q_ASSERT(ev);
- return ev->reset(event);
+ Q_ASSERT(dev);
+ return pointerEventInstance(dev, event->type())->reset(event);
}
void QQuickWindowPrivate::deliverPointerEvent(QQuickPointerEvent *event)
diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h
index 0399b26f62..ae49d5e304 100644
--- a/src/quick/items/qquickwindow_p.h
+++ b/src/quick/items/qquickwindow_p.h
@@ -166,7 +166,7 @@ public:
// the device-specific event instances which are reused during event delivery
mutable QVector<QQuickPointerEvent *> pointerEventInstances;
- QQuickPointerEvent *pointerEventInstance(QQuickPointerDevice *device) const;
+ QQuickPointerEvent *pointerEventInstance(QQuickPointerDevice *device, QEvent::Type eventType = QEvent::None) const;
// delivery of pointer events:
QQuickPointerEvent *pointerEventInstance(QEvent *ev) const;