diff options
Diffstat (limited to 'src/quick')
-rw-r--r-- | src/quick/items/qquickitem.cpp | 4 | ||||
-rw-r--r-- | src/quick/items/qquickwindow.cpp | 71 | ||||
-rw-r--r-- | src/quick/items/qquickwindow_p.h | 3 |
3 files changed, 44 insertions, 34 deletions
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index de43f2fb7d..d482dcdfca 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -6058,7 +6058,7 @@ bool QQuickItemPrivate::setEffectiveVisibleRecur(bool newEffectiveVisible) if (window) { QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window); - windowPriv->removeGrabber(q); + windowPriv->removeGrabber(q, true, true, true); } bool childVisibilityChanged = false; @@ -6105,7 +6105,7 @@ void QQuickItemPrivate::setEffectiveEnableRecur(QQuickItem *scope, bool newEffec if (window) { QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window); - windowPriv->removeGrabber(q); + windowPriv->removeGrabber(q, true, true, true); if (scope && !effectiveEnable && activeFocus) { windowPriv->clearFocusInScope( scope, q, Qt::OtherFocusReason, QQuickWindowPrivate::DontChangeFocusProperty | QQuickWindowPrivate::DontChangeSubFocusItem); diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index b32b40e8fd..a2cf478f68 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -1049,14 +1049,14 @@ bool QQuickWindowPrivate::deliverTouchAsMouse(QQuickItem *item, QTouchEvent *poi but if not all points are released, it cannot be sure whether to call touchUngrabEvent() or not; so we have to do it here. */ -void QQuickWindowPrivate::removeGrabber(QQuickItem *grabber, bool mouse, bool touch) +void QQuickWindowPrivate::removeGrabber(QQuickItem *grabber, bool mouse, bool touch, bool cancel) { Q_Q(QQuickWindow); if (eventsInDelivery.isEmpty()) { // do it the expensive way for (auto dev : knownPointingDevices) { auto devPriv = QPointingDevicePrivate::get(const_cast<QPointingDevice *>(dev)); - devPriv->removeGrabber(grabber); + devPriv->removeGrabber(grabber, cancel); } return; } @@ -1084,19 +1084,6 @@ void QQuickWindowPrivate::removeGrabber(QQuickItem *grabber, bool mouse, bool to } } -void QQuickWindowPrivate::sendUngrabEvent(QQuickItem *grabber, bool touch) -{ - if (!grabber) - return; - QEvent e(QEvent::UngrabMouse); - hasFiltered.clear(); - if (!sendFilteredMouseEvent(&e, grabber, grabber->parentItem())) { - grabber->mouseUngrabEvent(); - if (touch) - grabber->touchUngrabEvent(); - } -} - /*! \internal Translates QEventPoint::scenePosition() in \a touchEvent to this window. @@ -2265,11 +2252,6 @@ bool QQuickWindowPrivate::deliverTouchCancelEvent(QTouchEvent *event) { qCDebug(DBG_TOUCH) << event; - if (isDeliveringTouchAsMouse()) { - if (QQuickItem *grabber = qmlobject_cast<QQuickItem *>(event->exclusiveGrabber(touchMouseId))) - sendUngrabEvent(grabber, true); - } - // An incoming TouchCancel event will typically not contain any points, // but sendTouchCancelEvent() adds the points that have grabbers to the event. // Deliver it to all items and handlers that have active touches. @@ -2579,14 +2561,41 @@ void QQuickWindowPrivate::onGrabChanged(QObject *grabber, QPointingDevice::GrabT const QPointerEvent *event, const QEventPoint &point) { qCDebug(lcPtrGrab) << grabber << transition << event << point; - // event can be null, if the signal was emitted from QPointingDevicePrivate::removeGrabber(grabber) - switch (transition) { - case QPointingDevice::UngrabExclusive: - if (point.device()->type() == QInputDevice::DeviceType::Mouse || isDeliveringTouchAsMouse()) - sendUngrabEvent(qobject_cast<QQuickItem *>(grabber), isDeliveringTouchAsMouse()); - break; - default: - break; + // note: event can be null, if the signal was emitted from QPointingDevicePrivate::removeGrabber(grabber) + if (auto *handler = qmlobject_cast<QQuickPointerHandler *>(grabber)) { + handler->onGrabChanged(handler, transition, const_cast<QPointerEvent *>(event), + const_cast<QEventPoint &>(point)); + } else { + switch (transition) { + case QPointingDevice::CancelGrabExclusive: + case QPointingDevice::UngrabExclusive: + if (auto *item = qmlobject_cast<QQuickItem *>(grabber)) { + bool filtered = false; + if (isDeliveringTouchAsMouse() || + point.device()->type() == QInputDevice::DeviceType::Mouse || + point.device()->type() == QInputDevice::DeviceType::TouchPad) { + QEvent e(QEvent::UngrabMouse); + hasFiltered.clear(); + filtered = sendFilteredMouseEvent(&e, item, item->parentItem()); + if (!filtered) + item->mouseUngrabEvent(); + } + if (point.device()->type() == QInputDevice::DeviceType::TouchScreen && event) { + bool allReleased = true; + for (const auto &pt : event->points()) { + if (pt.state() != QEventPoint::State::Released) { + allReleased = false; + break; + } + } + if (allReleased) + item->touchUngrabEvent(); + } + } + break; + default: + break; + } } } @@ -2627,8 +2636,10 @@ void QQuickWindowPrivate::deliverPointerEvent(QPointerEvent *event) if (isTouchEvent(event)) { for (int i = 0; i < event->pointCount(); ++i) { auto &point = event->point(i); - event->setExclusiveGrabber(point, nullptr); - event->clearPassiveGrabbers(point); + if (point.state() == QEventPoint::State::Released) { + event->setExclusiveGrabber(point, nullptr); + event->clearPassiveGrabbers(point); + } } // never allow touch->mouse synthesis to persist either cancelTouchMouseSynthesis(); diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h index 632cf1b6da..81c0ebef45 100644 --- a/src/quick/items/qquickwindow_p.h +++ b/src/quick/items/qquickwindow_p.h @@ -170,8 +170,7 @@ public: QPointF lastMousePosition; bool deliverTouchAsMouse(QQuickItem *item, QTouchEvent *pointerEvent); void translateTouchEvent(QTouchEvent *touchEvent); - void removeGrabber(QQuickItem *grabber, bool mouse = true, bool touch = true); - void sendUngrabEvent(QQuickItem *grabber, bool touch); + void removeGrabber(QQuickItem *grabber, bool mouse = true, bool touch = true, bool cancel = false); void onGrabChanged(QObject *grabber, QPointingDevice::GrabTransition transition, const QPointerEvent *event, const QEventPoint &point); static QMouseEvent *cloneMouseEvent(QMouseEvent *event, QPointF *transformedLocalPos = nullptr); void deliverToPassiveGrabbers(const QVector<QPointer<QObject> > &passiveGrabbers, QPointerEvent *pointerEvent); |