From 76b2d6b7e50ce211641fc6aa9a902719a124e9ca Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Thu, 14 Jan 2021 19:29:45 +0100 Subject: Pass QWheelEvent data to QML engine via QQuickWheelEvent pointer Passing events as objects or references in signal parameters requires copying, and we removed the broken copy semantics from QEvent for Qt 6 as much as possible. QVariant::fromValue still allows creation of a QVariant from a type that doesn't have a (public) copy constructor, which is why this passing of a QWheelEvent through a QVariant to QML went unnoticed. While QWheelEvent is a gadget and thus supposed to be invokable from QML, it's still a QEvent. Most QEvents are not gadgets - like QKeyEvent, QMouseEvent, QTouchEvent. We have QQuick*Event QObject wrappers instead to provide access to the low level event data from QML. So, use a single QQuickWheelEvent object instead to pass the data to QML, that class is designed for exactly that prupose. We need to copy the data anyway, and since we don't need to create/destroy the wrapper object for each event, this has no practical overhead. Extend the QQuickWheelEvent to provide access to the phase information of QWheelEvent as well, and simplify the reset() method. Note: making the QQuickWheelEvent store the QWheelEvent directly would allow passing calls to setAccepted through to the QWheelEvent. That is left for a future cleanup, and another reason for not passing events around as copies. Fixes: QTBUG-89594 Change-Id: Id86a9b30c5a8c7c50091e464e368568a7f5ca2ea Reviewed-by: Shawn Rutledge (cherry picked from commit 2b15a1fbe2f26a090f79ab5aa238f375bc67fda3) Reviewed-by: Qt Cherry-pick Bot --- src/quick/handlers/qquickwheelhandler.cpp | 4 +++- src/quick/handlers/qquickwheelhandler_p.h | 2 +- src/quick/handlers/qquickwheelhandler_p_p.h | 1 + src/quick/items/qquickevents_p_p.h | 33 +++++++++++++++++------------ src/quick/items/qquickmousearea.cpp | 3 +-- 5 files changed, 25 insertions(+), 18 deletions(-) diff --git a/src/quick/handlers/qquickwheelhandler.cpp b/src/quick/handlers/qquickwheelhandler.cpp index 563bf16b49..414a41f2cd 100644 --- a/src/quick/handlers/qquickwheelhandler.cpp +++ b/src/quick/handlers/qquickwheelhandler.cpp @@ -405,7 +405,9 @@ void QQuickWheelHandler::handleEventPoint(QPointerEvent *ev, QEventPoint &point) event->angleDelta().y()) / 8; d->rotation += angleDelta; emit rotationChanged(); - emit wheel(*event); + + d->wheelEvent.reset(event); + emit wheel(&d->wheelEvent); if (!d->propertyName.isEmpty() && target()) { QQuickItem *t = target(); // writing target()'s property is done via QMetaProperty::write() so that any registered interceptors can react. diff --git a/src/quick/handlers/qquickwheelhandler_p.h b/src/quick/handlers/qquickwheelhandler_p.h index 25390dc4c4..cbc9c4328c 100644 --- a/src/quick/handlers/qquickwheelhandler_p.h +++ b/src/quick/handlers/qquickwheelhandler_p.h @@ -103,7 +103,7 @@ public: void setTargetTransformAroundCursor(bool ttac); Q_SIGNALS: - void wheel(const QWheelEvent &event); + void wheel(QQuickWheelEvent *event); void orientationChanged(); void invertibleChanged(); diff --git a/src/quick/handlers/qquickwheelhandler_p_p.h b/src/quick/handlers/qquickwheelhandler_p_p.h index d35e04c51b..b18f83cb16 100644 --- a/src/quick/handlers/qquickwheelhandler_p_p.h +++ b/src/quick/handlers/qquickwheelhandler_p_p.h @@ -80,6 +80,7 @@ public: mutable bool metaPropertyDirty = true; bool invertible = true; bool targetTransformAroundCursor = true; + QQuickWheelEvent wheelEvent; }; QT_END_NAMESPACE diff --git a/src/quick/items/qquickevents_p_p.h b/src/quick/items/qquickevents_p_p.h index a9aeae2217..91f6c5de23 100644 --- a/src/quick/items/qquickevents_p_p.h +++ b/src/quick/items/qquickevents_p_p.h @@ -211,10 +211,12 @@ private: class QQuickWheelEvent : public QObject { Q_OBJECT + Q_PROPERTY(const QPointingDevice *device READ pointingDevice CONSTANT) Q_PROPERTY(qreal x READ x CONSTANT) Q_PROPERTY(qreal y READ y CONSTANT) Q_PROPERTY(QPoint angleDelta READ angleDelta CONSTANT) Q_PROPERTY(QPoint pixelDelta READ pixelDelta CONSTANT) + Q_PROPERTY(Qt::ScrollPhase phase READ phase CONSTANT) Q_PROPERTY(int buttons READ buttons CONSTANT) Q_PROPERTY(int modifiers READ modifiers CONSTANT) Q_PROPERTY(bool inverted READ inverted CONSTANT) @@ -223,40 +225,43 @@ class QQuickWheelEvent : public QObject QML_ADDED_IN_VERSION(2, 0) public: - QQuickWheelEvent() - : _buttons(Qt::NoButton), _modifiers(Qt::NoModifier) - {} + QQuickWheelEvent() = default; - void reset(qreal x, qreal y, const QPoint &angleDelta, const QPoint &pixelDelta, - Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, bool inverted) + void reset(const QWheelEvent *event) { - _x = x; - _y = y; - _angleDelta = angleDelta; - _pixelDelta = pixelDelta; - _buttons = buttons; - _modifiers = modifiers; + _device = event->pointingDevice(); + _x = event->position().x(); + _y = event->position().y(); + _angleDelta = event->angleDelta(); + _pixelDelta = event->pixelDelta(); + _buttons = event->buttons(); + _modifiers = event->modifiers(); _accepted = true; - _inverted = inverted; + _inverted = event->inverted(); + _phase = event->phase(); } + const QPointingDevice *pointingDevice() const { return _device; } qreal x() const { return _x; } qreal y() const { return _y; } QPoint angleDelta() const { return _angleDelta; } QPoint pixelDelta() const { return _pixelDelta; } int buttons() const { return _buttons; } int modifiers() const { return _modifiers; } + Qt::ScrollPhase phase() const { return _phase; } bool inverted() const { return _inverted; } bool isAccepted() { return _accepted; } void setAccepted(bool accepted) { _accepted = accepted; } private: + const QPointingDevice *_device = nullptr; qreal _x = 0; qreal _y = 0; QPoint _angleDelta; QPoint _pixelDelta; - Qt::MouseButtons _buttons; - Qt::KeyboardModifiers _modifiers; + Qt::MouseButtons _buttons = Qt::NoButton; + Qt::KeyboardModifiers _modifiers = Qt::NoModifier; + Qt::ScrollPhase _phase = Qt::NoScrollPhase; bool _inverted = false; bool _accepted = false; }; diff --git a/src/quick/items/qquickmousearea.cpp b/src/quick/items/qquickmousearea.cpp index 6e7688a734..1a406dbbc2 100644 --- a/src/quick/items/qquickmousearea.cpp +++ b/src/quick/items/qquickmousearea.cpp @@ -885,8 +885,7 @@ void QQuickMouseArea::wheelEvent(QWheelEvent *event) } QQuickWheelEvent &we = d->quickWheelEvent; - we.reset(event->position().x(), event->position().y(), event->angleDelta(), event->pixelDelta(), - event->buttons(), event->modifiers(), event->inverted()); + we.reset(event); we.setAccepted(d->isWheelConnected()); emit wheel(&we); if (!we.isAccepted()) -- cgit v1.2.3