diff options
author | Shawn Rutledge <shawn.rutledge@qt.io> | 2017-08-29 10:34:23 +0200 |
---|---|---|
committer | Jan Arve Sæther <jan-arve.saether@qt.io> | 2017-08-29 09:53:52 +0000 |
commit | 213a7054b563fc7374d328bc458739f8b8afa863 (patch) | |
tree | fba265d82e1f4de1b67b8c1c5764d1e96081c166 | |
parent | 18052d17999c2e95cb666508e6e571594163562a (diff) |
failsafe: never allow touch or mouse grab to persist after release
If a PointerHandler acquires a passive grab and we fail to remove it,
then next time the mouse moves, a filtering parent Flickable will have
a chance to see the mouse hover movement in the course of delivery
to that handler, and will grab. Thus you are stuck in flicking state
even though no mouse button is held. Passive grabs must therefore
always be cleared on release.
Change-Id: Ibaf46de32d7855e7b5f377c2d4fdae1312601c4f
Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io>
-rw-r--r-- | src/quick/items/qquickwindow.cpp | 14 |
1 files changed, 8 insertions, 6 deletions
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 3d355bb5b3..cf64a94631 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -1669,9 +1669,9 @@ void QQuickWindowPrivate::deliverMouseEvent(QQuickPointerMouseEvent *pointerEven { auto point = pointerEvent->point(0); lastMousePosition = point->scenePos(); + const bool mouseIsReleased = (point->state() == QQuickEventPoint::Released && pointerEvent->buttons() == Qt::NoButton); if (point->exclusiveGrabber()) { - bool mouseIsReleased = (point->state() == QQuickEventPoint::Released && pointerEvent->buttons() == Qt::NoButton); if (auto grabber = point->grabberItem()) { if (sendFilteredPointerEvent(pointerEvent, grabber)) return; @@ -1700,10 +1700,8 @@ void QQuickWindowPrivate::deliverMouseEvent(QQuickPointerMouseEvent *pointerEven pointerEvent->localize(handler->parentItem()); if (!sendFilteredPointerEvent(pointerEvent, handler->parentItem())) handler->handlePointerEvent(pointerEvent); - if (mouseIsReleased) { + if (mouseIsReleased) point->setGrabberPointerHandler(nullptr, true); - point->clearPassiveGrabbers(); - } } } else { bool delivered = false; @@ -1742,6 +1740,9 @@ void QQuickWindowPrivate::deliverMouseEvent(QQuickPointerMouseEvent *pointerEven // make sure not to accept unhandled events pointerEvent->setAccepted(false); } + // failsafe: never allow any kind of grab to persist after release + if (mouseIsReleased) + pointerEvent->clearGrabbers(); } bool QQuickWindowPrivate::sendHoverEvent(QEvent::Type type, QQuickItem *item, @@ -2332,8 +2333,9 @@ void QQuickWindowPrivate::deliverTouchEvent(QQuickPointerTouchEvent *event) } } - if (allReleased && !event->exclusiveGrabbers().isEmpty()) { - qWarning() << "No release received for some grabbers" << event->exclusiveGrabbers(); + if (allReleased) { + if (Q_UNLIKELY(!event->exclusiveGrabbers().isEmpty())) + qWarning() << "No release received for some grabbers" << event->exclusiveGrabbers(); event->clearGrabbers(); } } |