aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/handlers
diff options
context:
space:
mode:
authorShawn Rutledge <shawn.rutledge@qt.io>2019-12-04 16:15:16 +0100
committerShawn Rutledge <shawn.rutledge@qt.io>2019-12-06 16:57:40 +0100
commit090f404cf80da35734f712b02cc1543acecd5b62 (patch)
tree57ff34091b51c7aa1576ac97d2dc6ff6cde26389 /src/quick/handlers
parent7cdc3727a2b01c59d0a9e19a3cfc4e226ac1ab77 (diff)
Don't let PointerHandler steal touch grab from preventStealing MouseArea
The scenario: - mouse press: MouseArea grabs; DragHandler gets a passive grab - drag a little: DragHandler's drag threshold is exceeded - drag some more: DragHandler tries to take the exclusive grab This grab takeover succeeded before, because although MA has keepMouseGrab(), the event being delivered is a touch event, and MA does not have keepTouchGrab(). If this happens while QQuickWindowPrivate::touchMouseId is the same touchpoint that the DragHandler is trying to grab, it should not succeed, because we honor the keepMouseGrab() flag. I.e. keepMouseGrab() implies keepTouchGrab() whenever the touchpoint under consideration is currently the touch-mouse. On the other hand, if a DragHandler is used on some item inside a Flickable: on press, the Flickable grabs right away (it has a bad case of FOMO), but the DragHandler just gets a passive grab. When the drag threshold is exceeded, DragHandler must be able to steal the grab from Flickable, because Flickable was just being too aggressive. So now we have the rule that if the Item it wants to steal the grab from is a parent of the type that filters all events, it's OK to ignore the keepMouseGrab() flag and steal anyway (as it did before this patch). Fixes: QTBUG-79163 Change-Id: I2b3f175bea867cb737357857657653b0a7b83995 Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io>
Diffstat (limited to 'src/quick/handlers')
-rw-r--r--src/quick/handlers/qquickpointerhandler.cpp19
1 files changed, 18 insertions, 1 deletions
diff --git a/src/quick/handlers/qquickpointerhandler.cpp b/src/quick/handlers/qquickpointerhandler.cpp
index 12c06aa179..0f5cf59c67 100644
--- a/src/quick/handlers/qquickpointerhandler.cpp
+++ b/src/quick/handlers/qquickpointerhandler.cpp
@@ -227,8 +227,25 @@ bool QQuickPointerHandler::approveGrabTransition(QQuickEventPoint *point, QObjec
} else if ((d->grabPermissions & CanTakeOverFromItems)) {
QQuickItem * existingItemGrabber = point->grabberItem();
if (existingItemGrabber && !((existingItemGrabber->keepMouseGrab() && point->pointerEvent()->asPointerMouseEvent()) ||
- (existingItemGrabber->keepTouchGrab() && point->pointerEvent()->asPointerTouchEvent())))
+ (existingItemGrabber->keepTouchGrab() && point->pointerEvent()->asPointerTouchEvent()))) {
allowed = true;
+ // 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
+ // DragHandler to operate on an Item inside a Flickable. Flickable is aggressive about
+ // grabbing on press (for fear of missing updates), but DragHandler uses a passive grab
+ // 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()))) {
+ QQuickWindowPrivate *winPriv = QQuickWindowPrivate::get(parentItem()->window());
+ if (winPriv->isDeliveringTouchAsMouse() && point->pointId() == winPriv->touchMouseId) {
+ qCDebug(lcPointerHandlerGrab) << this << "wants to grab touchpoint" << point->pointId()
+ << "but declines to steal grab from touch-mouse grabber with keepMouseGrab=true" << existingItemGrabber;
+ allowed = false;
+ }
+ }
+ }
}
}
} else {