diff options
Diffstat (limited to 'src/quick/handlers')
-rw-r--r-- | src/quick/handlers/qquickdraghandler.cpp | 11 | ||||
-rw-r--r-- | src/quick/handlers/qquickmultipointhandler.cpp | 16 | ||||
-rw-r--r-- | src/quick/handlers/qquickpinchhandler.cpp | 24 | ||||
-rw-r--r-- | src/quick/handlers/qquickpointerhandler.cpp | 43 | ||||
-rw-r--r-- | src/quick/handlers/qquicktaphandler.cpp | 15 | ||||
-rw-r--r-- | src/quick/handlers/qquickwheelhandler.cpp | 2 |
6 files changed, 79 insertions, 32 deletions
diff --git a/src/quick/handlers/qquickdraghandler.cpp b/src/quick/handlers/qquickdraghandler.cpp index 980481303f..9471ef7660 100644 --- a/src/quick/handlers/qquickdraghandler.cpp +++ b/src/quick/handlers/qquickdraghandler.cpp @@ -182,7 +182,13 @@ void QQuickDragHandler::onActiveChanged() bool QQuickDragHandler::wantsPointerEvent(QPointerEvent *event) { if (!QQuickMultiPointHandler::wantsPointerEvent(event)) - return false; + /* Do handle other events than we would normally care about + while we are still doing a drag; otherwise we would suddenly + become inactive when a wheel event arrives during dragging. + This extra condition needs to be kept in sync with + handlePointerEventImpl */ + if (!active()) + return false; #if QT_CONFIG(gestures) if (event->type() == QEvent::NativeGesture) @@ -194,6 +200,9 @@ bool QQuickDragHandler::wantsPointerEvent(QPointerEvent *event) void QQuickDragHandler::handlePointerEventImpl(QPointerEvent *event) { + if (active() && !QQuickMultiPointHandler::wantsPointerEvent(event)) + return; // see QQuickDragHandler::wantsPointerEvent; we don't want to handle those events + QQuickMultiPointHandler::handlePointerEventImpl(event); event->setAccepted(true); diff --git a/src/quick/handlers/qquickmultipointhandler.cpp b/src/quick/handlers/qquickmultipointhandler.cpp index 97cb958aa6..6f66d0e426 100644 --- a/src/quick/handlers/qquickmultipointhandler.cpp +++ b/src/quick/handlers/qquickmultipointhandler.cpp @@ -145,7 +145,7 @@ void QQuickMultiPointHandler::onActiveChanged() } } -void QQuickMultiPointHandler::onGrabChanged(QQuickPointerHandler *, QPointingDevice::GrabTransition transition, QPointerEvent *, QEventPoint &) +void QQuickMultiPointHandler::onGrabChanged(QQuickPointerHandler *grabber, QPointingDevice::GrabTransition transition, QPointerEvent *event, QEventPoint &point) { Q_D(QQuickMultiPointHandler); // If another handler or item takes over this set of points, assume it has @@ -154,6 +154,20 @@ void QQuickMultiPointHandler::onGrabChanged(QQuickPointerHandler *, QPointingDev // (e.g. between DragHandler and PinchHandler). if (transition == QPointingDevice::UngrabExclusive || transition == QPointingDevice::CancelGrabExclusive) d->currentPoints.clear(); + if (grabber != this) + return; + switch (transition) { + case QPointingDevice::GrabExclusive: + case QPointingDevice::GrabPassive: + case QPointingDevice::UngrabPassive: + case QPointingDevice::UngrabExclusive: + case QPointingDevice::CancelGrabPassive: + case QPointingDevice::CancelGrabExclusive: + QQuickPointerHandler::onGrabChanged(grabber, transition, event, point); + break; + case QPointingDevice::OverrideGrabPassive: + return; // don't emit + } } QVector<QEventPoint> QQuickMultiPointHandler::eligiblePoints(QPointerEvent *event) diff --git a/src/quick/handlers/qquickpinchhandler.cpp b/src/quick/handlers/qquickpinchhandler.cpp index fffcc2f848..68b5f2faed 100644 --- a/src/quick/handlers/qquickpinchhandler.cpp +++ b/src/quick/handlers/qquickpinchhandler.cpp @@ -85,7 +85,14 @@ Q_LOGGING_CATEGORY(lcPinchHandler, "qt.quick.handler.pinch") \image touchpoints-pinchhandler.png - \sa PinchArea + \note The pinch begins when the number of fingers pressed is between + \l {MultiPointHandler::minimumPointCount}{minimumPointCount} and + \l {MultiPointHandler::maximumPointCount}{maximumPointCount}, inclusive. + Until then, PinchHandler tracks the positions of any pressed fingers, + but if it's a disallowed number, it does not scale or rotate + its \l target, and the \l active property remains \c false. + + \sa PinchArea, QPointerEvent::pointCount() */ QQuickPinchHandler::QQuickPinchHandler(QQuickItem *parent) @@ -209,19 +216,12 @@ bool QQuickPinchHandler::wantsPointerEvent(QPointerEvent *event) */ /*! - \qmlproperty int QtQuick::PinchHandler::minimumTouchPoints - - The pinch begins when this number of fingers are pressed. - Until then, PinchHandler tracks the positions of any pressed fingers, - but if it's an insufficient number, it does not scale or rotate - its \l target, and the \l active property will remain false. -*/ - -/*! \qmlproperty bool QtQuick::PinchHandler::active - This property is true when all the constraints (epecially \l minimumTouchPoints) - are satisfied and the \l target, if any, is being manipulated. + This property is \c true when all the constraints (epecially + \l {MultiPointHandler::minimumPointCount}{minimumPointCount} and + \l {MultiPointHandler::maximumPointCount}{maximumPointCount}) are satisfied + and the \l target, if any, is being manipulated. */ void QQuickPinchHandler::onActiveChanged() diff --git a/src/quick/handlers/qquickpointerhandler.cpp b/src/quick/handlers/qquickpointerhandler.cpp index 11c29ee812..12b064a79b 100644 --- a/src/quick/handlers/qquickpointerhandler.cpp +++ b/src/quick/handlers/qquickpointerhandler.cpp @@ -302,7 +302,8 @@ void QQuickPointerHandler::onGrabChanged(QQuickPointerHandler *grabber, QPointin */ void QQuickPointerHandler::setPassiveGrab(QPointerEvent *event, const QEventPoint &point, bool grab) { - qCDebug(lcPointerHandlerGrab) << point << grab; + qCDebug(lcPointerHandlerGrab) << this << point << grab << "via" + << QQuickDeliveryAgentPrivate::currentOrItemDeliveryAgent(parentItem()); if (grab) { event->addPassiveGrabber(point, this); } else { @@ -338,8 +339,8 @@ bool QQuickPointerHandler::approveGrabTransition(QPointerEvent *event, const QEv { Q_D(const QQuickPointerHandler); bool allowed = false; + QObject* existingGrabber = event->exclusiveGrabber(point); if (proposedGrabber == this) { - QObject* existingGrabber = event->exclusiveGrabber(point); allowed = (existingGrabber == nullptr) || ((d->grabPermissions & CanTakeOverFromAnything) == CanTakeOverFromAnything); if (existingGrabber) { if (QQuickPointerHandler *existingPhGrabber = qobject_cast<QQuickPointerHandler *>(event->exclusiveGrabber(point))) { @@ -350,10 +351,17 @@ bool QQuickPointerHandler::approveGrabTransition(QPointerEvent *event, const QEv existingPhGrabber->metaObject()->className() == metaObject()->className()) allowed = true; } else if ((d->grabPermissions & CanTakeOverFromItems)) { + allowed = true; QQuickItem * existingItemGrabber = qobject_cast<QQuickItem *>(event->exclusiveGrabber(point)); - if (existingItemGrabber && !((existingItemGrabber->keepMouseGrab() && QQuickWindowPrivate::isMouseEvent(event)) || - (existingItemGrabber->keepTouchGrab() && QQuickWindowPrivate::isTouchEvent(event)))) { - allowed = true; + auto da = parentItem() ? QQuickItemPrivate::get(parentItem())->deliveryAgentPrivate() + : QQuickDeliveryAgentPrivate::currentEventDeliveryAgent ? static_cast<QQuickDeliveryAgentPrivate *>( + QQuickDeliveryAgentPrivate::get(QQuickDeliveryAgentPrivate::currentEventDeliveryAgent)) : nullptr; + const bool isTouchMouse = (da && da->isDeliveringTouchAsMouse()); + if (existingItemGrabber && + ((existingItemGrabber->keepMouseGrab() && + (QQuickWindowPrivate::isMouseEvent(event) || isTouchMouse)) || + (existingItemGrabber->keepTouchGrab() && QQuickWindowPrivate::isTouchEvent(event)))) { + allowed = false; // If the handler wants to steal the exclusive grab from an Item, the Item can usually veto // by having its keepMouseGrab flag set. But an exception is if that Item is a parent that // normally filters events (such as a Flickable): it needs to be possible for e.g. a @@ -362,15 +370,20 @@ bool QQuickPointerHandler::approveGrabTransition(QPointerEvent *event, const QEv // at first and then expects to be able to steal the grab later on. It cannot respect // Flickable's wishes in that case, because then it would never have a chance. if (existingItemGrabber->keepMouseGrab() && - !(existingItemGrabber->filtersChildMouseEvents() && existingItemGrabber->isAncestorOf(parentItem()))) { - auto da = QQuickItemPrivate::get(parentItem())->deliveryAgentPrivate(); + existingItemGrabber->filtersChildMouseEvents() && existingItemGrabber->isAncestorOf(parentItem())) { Q_ASSERT(da); - if (da->isDeliveringTouchAsMouse() && point.id() == da->touchMouseId) { - qCDebug(lcPointerHandlerGrab) << this << "wants to grab touchpoint" << point.id() - << "but declines to steal grab from touch-mouse grabber with keepMouseGrab=true" << existingItemGrabber; - allowed = false; + if (isTouchMouse && point.id() == da->touchMouseId) { + qCDebug(lcPointerHandlerGrab) << this << "steals touchpoint" << point.id() + << "despite parent touch-mouse grabber with keepMouseGrab=true" << existingItemGrabber; + allowed = true; } } + if (!allowed) { + qCDebug(lcPointerHandlerGrab) << this << "wants to grab point" << point.id() + << "but declines to steal from grabber" << existingItemGrabber + << "with keepMouseGrab=" << existingItemGrabber->keepMouseGrab() + << "keepTouchGrab=" << existingItemGrabber->keepTouchGrab(); + } } } } @@ -394,7 +407,8 @@ bool QQuickPointerHandler::approveGrabTransition(QPointerEvent *event, const QEv } qCDebug(lcPointerHandlerGrab) << "point" << Qt::hex << point.id() << "permission" << QMetaEnum::fromType<GrabPermissions>().valueToKeys(grabPermissions()) << - ':' << this << (allowed ? "approved to" : "denied to") << proposedGrabber; + ':' << this << (allowed ? "approved from" : "denied from") << + existingGrabber << "to" << proposedGrabber; return allowed; } @@ -516,8 +530,11 @@ bool QQuickPointerHandler::parentContains(const QPointF &scenePosition) const { if (QQuickItem *par = parentItem()) { if (par->window()) { + QRect windowGeometry = par->window()->geometry(); + if (!par->window()->isTopLevel()) + windowGeometry = QRect(QWindowPrivate::get(par->window())->globalPosition(), par->window()->size()); QPoint screenPosition = par->window()->mapToGlobal(scenePosition.toPoint()); - if (!par->window()->geometry().contains(screenPosition)) + if (!windowGeometry.contains(screenPosition)) return false; } QPointF p = par->mapFromScene(scenePosition); diff --git a/src/quick/handlers/qquicktaphandler.cpp b/src/quick/handlers/qquicktaphandler.cpp index 0a7cc7e075..6c6d491f3c 100644 --- a/src/quick/handlers/qquicktaphandler.cpp +++ b/src/quick/handlers/qquicktaphandler.cpp @@ -77,6 +77,8 @@ int QQuickTapHandler::m_touchMultiTapDistanceSquared(-1); button in order to cancel the click. For this use case, set the \l gesturePolicy to \c TapHandler.ReleaseWithinBounds. + \snippet pointerHandlers/tapHandlerButton.qml 0 + For multi-tap gestures (double-tap, triple-tap etc.), the distance moved must not exceed QStyleHints::mouseDoubleClickDistance() with mouse and QStyleHints::touchDoubleTapDistance() with touch, and the time between @@ -214,6 +216,8 @@ void QQuickTapHandler::timerEvent(QTimerEvent *event) If the spatial constraint is violated, \l pressed transitions immediately from true to false, regardless of the time held. + The \c gesturePolicy also affects grab behavior as described below. + \value TapHandler.DragThreshold (the default value) The event point must not move significantly. If the mouse, finger or stylus moves past the system-wide drag @@ -222,11 +226,13 @@ void QQuickTapHandler::timerEvent(QTimerEvent *event) can be useful whenever TapHandler needs to cooperate with other input handlers (for example \l DragHandler) or event-handling Items (for example QtQuick Controls), because in this case TapHandler - will not take the exclusive grab, but merely a passive grab. + will not take the exclusive grab, but merely a + \l {QPointerEvent::addPassiveGrabber()}{passive grab}. \value TapHandler.WithinBounds If the event point leaves the bounds of the \c parent Item, the tap - gesture is canceled. The TapHandler will take the exclusive grab on + gesture is canceled. The TapHandler will take the + \l {QPointerEvent::setExclusiveGrabber}{exclusive grab} on press, but will release the grab as soon as the boundary constraint is no longer satisfied. @@ -237,8 +243,9 @@ void QQuickTapHandler::timerEvent(QTimerEvent *event) typical behavior for button widgets: you can cancel a click by dragging outside the button, and you can also change your mind by dragging back inside the button before release. Note that it's - necessary for TapHandler take the exclusive grab on press and retain - it until release in order to detect this gesture. + necessary for TapHandler to take the + \l {QPointerEvent::setExclusiveGrabber}{exclusive grab} on press + and retain it until release in order to detect this gesture. */ void QQuickTapHandler::setGesturePolicy(QQuickTapHandler::GesturePolicy gesturePolicy) { diff --git a/src/quick/handlers/qquickwheelhandler.cpp b/src/quick/handlers/qquickwheelhandler.cpp index 7045f10d8e..51cb72032b 100644 --- a/src/quick/handlers/qquickwheelhandler.cpp +++ b/src/quick/handlers/qquickwheelhandler.cpp @@ -502,7 +502,7 @@ void QQuickWheelHandler::timerEvent(QTimerEvent *event) } /*! - \qmlsignal QtQuick::WheelHandler::wheel(PointerScrollEvent event) + \qmlsignal QtQuick::WheelHandler::wheel(WheelEvent event) This signal is emitted every time this handler receives an \a event of type \l QWheelEvent: that is, every time the wheel is moved or the |