From d63ad7efb56452e3ad019c38ddf887ddcc8d338a Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Mon, 16 Nov 2020 15:00:08 +0100 Subject: Use QMutable*Event classes to copy and synthesize events QMutableTouch/SinglePointEvent can be publicly copy constructed from their non-mutable counterparts, make use of that. Change-Id: I7f56a9f9649bb7726cca1eaddccfdc3f21d47554 Reviewed-by: Qt CI Bot Reviewed-by: Lars Knoll Reviewed-by: Shawn Rutledge --- src/quick/items/qquickflickable.cpp | 7 ++-- src/quick/items/qquickitem.cpp | 10 +++--- src/quick/items/qquickitem_p.h | 2 +- src/quick/items/qquickmultipointtoucharea.cpp | 14 ++++---- src/quick/items/qquickpathview.cpp | 8 ++--- src/quick/items/qquickwindow.cpp | 48 +++++++++++++-------------- src/quick/items/qquickwindow_p.h | 2 +- 7 files changed, 45 insertions(+), 46 deletions(-) (limited to 'src') diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp index 9e7b2a4f17..b451c275c2 100644 --- a/src/quick/items/qquickflickable.cpp +++ b/src/quick/items/qquickflickable.cpp @@ -1451,10 +1451,9 @@ void QQuickFlickable::mouseReleaseEvent(QMouseEvent *event) d->replayDelayedPress(); // Now send the release - auto &firstPoint = event->point(0); - if (auto grabber = qmlobject_cast(event->exclusiveGrabber(firstPoint))) { - QMouseEvent localized(*event); - QMutableEventPoint::from(firstPoint).setPosition(grabber->mapFromScene(event->scenePosition())); + if (auto grabber = qmlobject_cast(event->exclusiveGrabber(event->point(0)))) { + QMutableSinglePointEvent localized(*event); + localized.mutablePoint().setPosition(grabber->mapFromScene(localized.scenePosition())); QCoreApplication::sendEvent(window(), &localized); } diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 116d1a370b..5dcc191053 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -8389,7 +8389,7 @@ QQuickItemLayer *QQuickItemPrivate::layer() const monitor eventpoint movements until a drag threshold is exceeded or the requirements for a gesture to be recognized are met in some other way. */ -QTouchEvent QQuickItemPrivate::localizedTouchEvent(const QTouchEvent *event, bool isFiltering) +void QQuickItemPrivate::localizedTouchEvent(const QTouchEvent *event, bool isFiltering, QMutableTouchEvent *localized) { Q_Q(QQuickItem); QList touchPoints; @@ -8449,8 +8449,10 @@ QTouchEvent QQuickItemPrivate::localizedTouchEvent(const QTouchEvent *event, boo // Now touchPoints will have only points which are inside the item. // But if none of them were just pressed inside, and the item has no other reason to care, ignore them anyway. - if (touchPoints.isEmpty() || (!anyPressOrReleaseInside && !anyGrabber && !isFiltering)) - return QTouchEvent(QEvent::None); + if (touchPoints.isEmpty() || (!anyPressOrReleaseInside && !anyGrabber && !isFiltering)) { + *localized = QMutableTouchEvent(QEvent::None); + return; + } // if all points have the same state, set the event type accordingly QEvent::Type eventType = event->type(); @@ -8470,7 +8472,7 @@ QTouchEvent QQuickItemPrivate::localizedTouchEvent(const QTouchEvent *event, boo ret.setTarget(q); ret.setTimestamp(event->timestamp()); ret.accept(); - return ret; + *localized = ret; } bool QQuickItemPrivate::hasPointerHandlers() const diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h index 1e33eadeac..b97b9cefd5 100644 --- a/src/quick/items/qquickitem_p.h +++ b/src/quick/items/qquickitem_p.h @@ -281,7 +281,7 @@ public: QQuickItemLayer *layer() const; - QTouchEvent localizedTouchEvent(const QTouchEvent *event, bool isFiltering); + void localizedTouchEvent(const QTouchEvent *event, bool isFiltering, QMutableTouchEvent *localized); bool hasPointerHandlers() const; bool hasHoverHandlers() const; virtual void addPointerHandler(QQuickPointerHandler *h); diff --git a/src/quick/items/qquickmultipointtoucharea.cpp b/src/quick/items/qquickmultipointtoucharea.cpp index 23cf6c0351..e23e7365df 100644 --- a/src/quick/items/qquickmultipointtoucharea.cpp +++ b/src/quick/items/qquickmultipointtoucharea.cpp @@ -908,21 +908,21 @@ bool QQuickMultiPointTouchArea::sendMouseEvent(QMouseEvent *event) QQuickItem *grabber = c ? c->mouseGrabberItem() : nullptr; bool stealThisEvent = _stealMouse; if ((stealThisEvent || contains(localPos)) && (!grabber || !grabber->keepMouseGrab())) { - QMouseEvent mouseEvent = *event; - auto mut = QMutableSinglePointEvent::from(&mouseEvent); - mut->mutablePoint().setPosition(localPos); - mut->setSource(Qt::MouseEventSynthesizedByQt); + QMutableSinglePointEvent mouseEvent(*event); + mouseEvent.mutablePoint().setPosition(localPos); + mouseEvent.setSource(Qt::MouseEventSynthesizedByQt); mouseEvent.setAccepted(false); + QMouseEvent *pmouseEvent = static_cast(static_cast(&mouseEvent)); switch (mouseEvent.type()) { case QEvent::MouseMove: - mouseMoveEvent(&mouseEvent); + mouseMoveEvent(pmouseEvent); break; case QEvent::MouseButtonPress: - mousePressEvent(&mouseEvent); + mousePressEvent(pmouseEvent); break; case QEvent::MouseButtonRelease: - mouseReleaseEvent(&mouseEvent); + mouseReleaseEvent(pmouseEvent); break; default: break; diff --git a/src/quick/items/qquickpathview.cpp b/src/quick/items/qquickpathview.cpp index d7f85c288d..d90ae7eb77 100644 --- a/src/quick/items/qquickpathview.cpp +++ b/src/quick/items/qquickpathview.cpp @@ -1859,20 +1859,20 @@ bool QQuickPathView::childMouseEventFilter(QQuickItem *i, QEvent *e) bool stealThisEvent = d->stealMouse; if ((stealThisEvent || contains(localPos)) && (!grabber || !grabber->keepMouseGrab() || grabberDisabled)) { // Make a localized copy of the QMouseEvent. - QMouseEvent localizedEvent(*static_cast(pe)); + QMutableSinglePointEvent localizedEvent(*static_cast(pe)); QMutableEventPoint::from(localizedEvent.point(0)).setPosition(localPos); localizedEvent.setAccepted(false); switch (localizedEvent.type()) { case QEvent::MouseMove: - d->handleMouseMoveEvent(&localizedEvent); + d->handleMouseMoveEvent(static_cast(static_cast(&localizedEvent))); break; case QEvent::MouseButtonPress: - d->handleMousePressEvent(&localizedEvent); + d->handleMousePressEvent(static_cast(static_cast(&localizedEvent))); stealThisEvent = d->stealMouse; // Update stealThisEvent in case changed by function call above break; case QEvent::MouseButtonRelease: - d->handleMouseReleaseEvent(&localizedEvent); + d->handleMouseReleaseEvent(static_cast(static_cast(&localizedEvent))); break; default: break; diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 8183988835..e09723e973 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -868,18 +868,15 @@ QQmlListProperty QQuickWindowPrivate::data() QQuickWindowPrivate::data_removeLast); } -QMouseEvent QQuickWindowPrivate::touchToMouseEvent(QEvent::Type type, const QEventPoint &p, QTouchEvent *event, QQuickItem *item) +void QQuickWindowPrivate::touchToMouseEvent(QEvent::Type type, const QEventPoint &p, const QTouchEvent *touchEvent, QMutableSinglePointEvent *mouseEvent) { - Q_UNUSED(item) Q_ASSERT(QCoreApplication::testAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents)); - QMutableSinglePointEvent ret(type, event->pointingDevice(), p, + QMutableSinglePointEvent ret(type, touchEvent->pointingDevice(), p, (type == QEvent::MouseMove ? Qt::NoButton : Qt::LeftButton), (type == QEvent::MouseButtonRelease ? Qt::NoButton : Qt::LeftButton), - event->modifiers(), Qt::MouseEventSynthesizedByQt); + touchEvent->modifiers(), Qt::MouseEventSynthesizedByQt); ret.setAccepted(true); // this now causes the persistent touchpoint to be accepted too - ret.setTimestamp(event->timestamp()); - static_assert(sizeof(QMutableSinglePointEvent) == sizeof(QMouseEvent)); - return *static_cast(static_cast(&ret)); + *mouseEvent = ret; } bool QQuickWindowPrivate::checkIfDoubleTapped(ulong newPressEventTimestamp, QPoint newPressPos) @@ -947,7 +944,8 @@ bool QQuickWindowPrivate::deliverTouchAsMouse(QQuickItem *item, QTouchEvent *poi } // FIXME: make this work for mouse events too and get rid of the asTouchEvent in here. - QTouchEvent event = QQuickItemPrivate::get(item)->localizedTouchEvent(pointerEvent, false); + QMutableTouchEvent event; + QQuickItemPrivate::get(item)->localizedTouchEvent(pointerEvent, false, &event); if (!event.points().count()) return false; @@ -964,7 +962,8 @@ bool QQuickWindowPrivate::deliverTouchAsMouse(QQuickItem *item, QTouchEvent *poi break; qCDebug(DBG_TOUCH_TARGET) << device << "TP (mouse)" << Qt::hex << p.id() << "->" << item; - QMouseEvent mousePress = touchToMouseEvent(QEvent::MouseButtonPress, p, &event, item); + QMutableSinglePointEvent mousePress(QEvent::None, nullptr, QEventPoint()); + touchToMouseEvent(QEvent::MouseButtonPress, p, &event, &mousePress); // Send a single press and see if that's accepted QCoreApplication::sendEvent(item, &mousePress); @@ -979,7 +978,8 @@ bool QQuickWindowPrivate::deliverTouchAsMouse(QQuickItem *item, QTouchEvent *poi if (checkIfDoubleTapped(event.timestamp(), p.globalPosition().toPoint())) { // since we synth the mouse event from from touch, we respect the // QPlatformTheme::TouchDoubleTapDistance instead of QPlatformTheme::MouseDoubleClickDistance - QMouseEvent mouseDoubleClick = touchToMouseEvent(QEvent::MouseButtonDblClick, p, &event, item); + QMutableSinglePointEvent mouseDoubleClick(QEvent::None, nullptr, QEventPoint()); + touchToMouseEvent(QEvent::MouseButtonDblClick, p, &event, &mouseDoubleClick); QCoreApplication::sendEvent(item, &mouseDoubleClick); event.setAccepted(mouseDoubleClick.isAccepted()); if (!mouseDoubleClick.isAccepted()) @@ -1000,7 +1000,8 @@ bool QQuickWindowPrivate::deliverTouchAsMouse(QQuickItem *item, QTouchEvent *poi touchMousePressTimestamp = 0; // Got dragged too far, dismiss the double tap } if (QQuickItem *mouseGrabberItem = qmlobject_cast(pointerEvent->exclusiveGrabber(p))) { - QMouseEvent me = touchToMouseEvent(QEvent::MouseMove, p, &event, mouseGrabberItem); + QMutableSinglePointEvent me(QEvent::None, nullptr, QEventPoint()); + touchToMouseEvent(QEvent::MouseMove, p, &event, &me); QCoreApplication::sendEvent(item, &me); event.setAccepted(me.isAccepted()); if (me.isAccepted()) @@ -1010,7 +1011,8 @@ bool QQuickWindowPrivate::deliverTouchAsMouse(QQuickItem *item, QTouchEvent *poi // no grabber, check if we care about mouse hover // FIXME: this should only happen once, not recursively... I'll ignore it just ignore hover now. // hover for touch??? - QMouseEvent me = touchToMouseEvent(QEvent::MouseMove, p, &event, item); + QMutableSinglePointEvent me(QEvent::None, nullptr, QEventPoint()); + touchToMouseEvent(QEvent::MouseMove, p, &event, &me); if (lastMousePosition.isNull()) lastMousePosition = me.scenePosition(); QPointF last = lastMousePosition; @@ -1026,7 +1028,8 @@ bool QQuickWindowPrivate::deliverTouchAsMouse(QQuickItem *item, QTouchEvent *poi } else if (p.state() & QEventPoint::State::Released) { // currently handled point was released if (QQuickItem *mouseGrabberItem = qmlobject_cast(pointerEvent->exclusiveGrabber(p))) { - QMouseEvent me = touchToMouseEvent(QEvent::MouseButtonRelease, p, &event, mouseGrabberItem); + QMutableSinglePointEvent me(QEvent::None, nullptr, QEventPoint()); + touchToMouseEvent(QEvent::MouseButtonRelease, p, &event, &me); QCoreApplication::sendEvent(item, &me); if (item->acceptHoverEvents() && p.globalPosition() != QGuiApplicationPrivate::lastCursorPosition) { @@ -2057,14 +2060,7 @@ void QQuickWindowPrivate::deliverKeyEvent(QKeyEvent *e) */ QPointerEvent *QQuickWindowPrivate::clonePointerEvent(QPointerEvent *event, std::optional transformedLocalPos) { - QPointerEvent *ret = nullptr; - if (isMouseEvent(event)) { - ret = new QMouseEvent(*(static_cast(event))); - } else if (isTouchEvent(event)) { - ret = new QTouchEvent(*(static_cast(event))); - } else if (isTabletEvent(event)) { - ret = new QTabletEvent(*(static_cast(event))); - } + QPointerEvent *ret = static_cast(event->clone()); QMutableEventPoint &point = QMutableEventPoint::from(ret->point(0)); point.detach(); point.setTimestamp(event->timestamp()); @@ -2945,7 +2941,8 @@ void QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, bool isG return; bool eventAccepted = false; - QTouchEvent touchEvent = QQuickItemPrivate::get(item)->localizedTouchEvent(static_cast(pointerEvent), false); + QMutableTouchEvent touchEvent; + QQuickItemPrivate::get(item)->localizedTouchEvent(static_cast(pointerEvent), false, &touchEvent); if (touchEvent.type() == QEvent::None) return; // no points inside this item @@ -3261,8 +3258,8 @@ bool QQuickWindowPrivate::sendFilteredPointerEventImpl(QPointerEvent *event, QQu } else if (acceptsTouchEvents || receiver->acceptedMouseButtons()) { // get a touch event customized for delivery to filteringParent // TODO should not be necessary? because QQuickWindowPrivate::deliverMatchingPointsToItem() does it - QTouchEvent filteringParentTouchEvent = - QQuickItemPrivate::get(receiver)->localizedTouchEvent(static_cast(event), true); + QMutableTouchEvent filteringParentTouchEvent; + QQuickItemPrivate::get(receiver)->localizedTouchEvent(static_cast(event), true, &filteringParentTouchEvent); if (filteringParentTouchEvent.type() != QEvent::None) { qCDebug(DBG_TOUCH) << "letting parent" << filteringParent << "filter for" << receiver << &filteringParentTouchEvent; if (filteringParent->childMouseEventFilter(receiver, &filteringParentTouchEvent)) { @@ -3299,7 +3296,8 @@ bool QQuickWindowPrivate::sendFilteredPointerEventImpl(QPointerEvent *event, QQu if (touchMouseUnset || touchMouseId == tp.id()) { // convert filteringParentTouchEvent (which is already transformed wrt local position, velocity, etc.) // into a synthetic mouse event, and let childMouseEventFilter() have another chance with that - QMouseEvent mouseEvent = touchToMouseEvent(t, tp, &filteringParentTouchEvent, receiver); + QMutableSinglePointEvent mouseEvent(QEvent::None, nullptr, QEventPoint()); + touchToMouseEvent(t, tp, &filteringParentTouchEvent, &mouseEvent); // If a filtering item calls QQuickWindow::mouseGrabberItem(), it should // report the touchpoint's grabber. Whenever we send a synthetic mouse event, // touchMouseId and touchMouseDevice must be set, even if it's only temporarily and isn't grabbed. diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h index 3be6f5cd8c..18a43487c1 100644 --- a/src/quick/items/qquickwindow_p.h +++ b/src/quick/items/qquickwindow_p.h @@ -197,7 +197,7 @@ public: static bool isTabletEvent(const QPointerEvent *ev); // delivery of pointer events: - QMouseEvent touchToMouseEvent(QEvent::Type type, const QEventPoint &p, QTouchEvent *event, QQuickItem *item); + void touchToMouseEvent(QEvent::Type type, const QEventPoint &p, const QTouchEvent *touchEvent, QMutableSinglePointEvent *mouseEvent); void ensureDeviceConnected(const QPointingDevice *dev); void deliverPointerEvent(QPointerEvent *); bool deliverTouchCancelEvent(QTouchEvent *); -- cgit v1.2.3