diff options
-rw-r--r-- | src/quick/items/qquickevents.cpp | 4 | ||||
-rw-r--r-- | src/quick/items/qquickevents_p_p.h | 3 | ||||
-rw-r--r-- | src/quick/items/qquickwindow.cpp | 45 | ||||
-rw-r--r-- | src/quick/items/qquickwindow_p.h | 8 |
4 files changed, 48 insertions, 12 deletions
diff --git a/src/quick/items/qquickevents.cpp b/src/quick/items/qquickevents.cpp index 4f677e841c..911cc9a52c 100644 --- a/src/quick/items/qquickevents.cpp +++ b/src/quick/items/qquickevents.cpp @@ -450,8 +450,8 @@ Item { to expose the event to QML, the same as is done with QQuickMouseEvent, QQuickTouchPoint, QQuickKeyEvent, etc. Since only one event can be delivered at a time, this class is effectively a singleton. We don't worry - about the QObject overhead because we never dynamically create and destroy - objects of this type. + about the QObject overhead because the instances are long-lived: we don't + dynamically create and destroy objects of this type for each event. */ /*! diff --git a/src/quick/items/qquickevents_p_p.h b/src/quick/items/qquickevents_p_p.h index b798165861..624c131683 100644 --- a/src/quick/items/qquickevents_p_p.h +++ b/src/quick/items/qquickevents_p_p.h @@ -435,6 +435,7 @@ public: int buttonCount() const { return m_buttonCount; } QString name() const { return m_name; } qint64 uniqueId() const { return m_uniqueId; } + QQuickPointerEvent *pointerEvent() const { return &m_event; } private: DeviceType m_deviceType; @@ -444,6 +445,8 @@ private: int m_buttonCount; QString m_name; qint64 m_uniqueId; + // the device-specific event instance which is reused during event delivery + mutable QQuickPointerEvent m_event; Q_DISABLE_COPY(QQuickPointerDevice) }; diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index af72ff3af2..22086c577c 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -1892,7 +1892,7 @@ void QQuickWindowPrivate::deliverDelayedTouchEvent() // Set delayedTouch to 0 before delivery to avoid redelivery in case of // event loop recursions (e.g if it the touch starts a dnd session). QScopedPointer<QTouchEvent> e(delayedTouch.take()); - deliverPointerEvent(currentPointerEvent.reset(e.data())); + deliverPointerEvent(pointerEventInstance(e.data())); } static bool qquickwindow_no_touch_compression = qEnvironmentVariableIsSet("QML_NO_TOUCH_COMPRESSION"); @@ -1971,14 +1971,14 @@ void QQuickWindowPrivate::handleTouchEvent(QTouchEvent *event) qCDebug(DBG_TOUCH) << event; if (qquickwindow_no_touch_compression || pointerEventRecursionGuard) { - deliverPointerEvent(currentPointerEvent.reset(event)); + deliverPointerEvent(pointerEventInstance(event)); return; } if (!compressTouchEvent(event)) { if (delayedTouch) deliverDelayedTouchEvent(); - deliverPointerEvent(currentPointerEvent.reset(event)); + deliverPointerEvent(pointerEventInstance(event)); } } @@ -2019,7 +2019,7 @@ void QQuickWindowPrivate::handleMouseEvent(QMouseEvent *event) case QEvent::MouseButtonPress: Q_QUICK_INPUT_PROFILE(QQuickProfiler::Mouse, QQuickProfiler::InputMousePress, event->button(), event->buttons()); - deliverPointerEvent(currentPointerEvent.reset(event)); + deliverPointerEvent(pointerEventInstance(event)); break; case QEvent::MouseButtonRelease: Q_QUICK_INPUT_PROFILE(QQuickProfiler::Mouse, QQuickProfiler::InputMouseRelease, event->button(), @@ -2029,14 +2029,14 @@ void QQuickWindowPrivate::handleMouseEvent(QMouseEvent *event) return; } - deliverPointerEvent(currentPointerEvent.reset(event)); + deliverPointerEvent(pointerEventInstance(event)); if (mouseGrabberItem && !event->buttons()) mouseGrabberItem->ungrabMouse(); break; case QEvent::MouseButtonDblClick: Q_QUICK_INPUT_PROFILE(QQuickProfiler::Mouse, QQuickProfiler::InputMouseDoubleClick, event->button(), event->buttons()); - deliverPointerEvent(currentPointerEvent.reset(event)); + deliverPointerEvent(pointerEventInstance(event)); break; case QEvent::MouseMove: Q_QUICK_INPUT_PROFILE(QQuickProfiler::Mouse, QQuickProfiler::InputMouseMove, @@ -2063,7 +2063,7 @@ void QQuickWindowPrivate::handleMouseEvent(QMouseEvent *event) event->setAccepted(accepted); return; } - deliverPointerEvent(currentPointerEvent.reset(event)); + deliverPointerEvent(pointerEventInstance(event)); break; default: Q_ASSERT(false); @@ -2095,6 +2095,37 @@ void QQuickWindowPrivate::flushFrameSynchronousEvents() } } +/*! + \internal + Returns a QQuickPointerEvent instance suitable for wrapping and delivering \a event. + + There is a unique instance per QQuickPointerDevice, which is determined + from \a event's device. +*/ +QQuickPointerEvent *QQuickWindowPrivate::pointerEventInstance(QEvent *event) +{ + QQuickPointerDevice *dev = nullptr; + switch (event->type()) { + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseButtonDblClick: + case QEvent::MouseMove: + dev = genericMouseDevice; + break; + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + case QEvent::TouchEnd: + case QEvent::TouchCancel: + dev = touchDevice(static_cast<QTouchEvent *>(event)->device()); + break; + // TODO tablet event types + default: + break; + } + Q_ASSERT(dev); + return dev->pointerEvent()->reset(event); +} + void QQuickWindowPrivate::deliverPointerEvent(QQuickPointerEvent *event) { // If users spin the eventloop as a result of event delivery, we disable diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h index 7183d17514..ab704b9adf 100644 --- a/src/quick/items/qquickwindow_p.h +++ b/src/quick/items/qquickwindow_p.h @@ -163,6 +163,7 @@ public: void deliverDelayedTouchEvent(); // delivery of pointer events: + QQuickPointerEvent *pointerEventInstance(QEvent *ev); void deliverPointerEvent(QQuickPointerEvent *); void deliverTouchEvent(QQuickPointerEvent *); bool deliverTouchCancelEvent(QTouchEvent *); @@ -245,9 +246,10 @@ public: QQuickAnimatorController *animationController; QScopedPointer<QTouchEvent> delayedTouch; - // The current touch or mouse event that is delivered. - // This event gets re-used (reset) for every incoming mouse/touch event. - QQuickPointerEvent currentPointerEvent; + // An event instance for each device that we've seen so far. + // One of these gets re-used (reset) for every incoming mouse/touch/tablet event. + // One reason to keep them separate is so that m_touchPoints will be only those from a single device. + QVector<QQuickPointerEvent> pointerEventsByDevice; int pointerEventRecursionGuard; QQuickCustomRenderStage *customRenderStage; |