diff options
author | Shawn Rutledge <shawn.rutledge@qt.io> | 2018-08-01 21:02:31 +0200 |
---|---|---|
committer | Shawn Rutledge <shawn.rutledge@qt.io> | 2018-08-02 17:48:20 +0000 |
commit | 6008c5ded48b6d03d56bf4c4ab96177fbb185f93 (patch) | |
tree | 99dc028580b9fba6bd8cb37fc1f14b909aeb928d /src/quick | |
parent | ea195452e80e4b5a70e8c8cdf96a30581a8dd456 (diff) |
MultiPointHandler::wantsPointerEvent: reset if different cand count
We always intended to "start over" with event delivery when the number
of touchpoints changes. Change 48011c2dfeb83b4fe717034d4b3c353714fead48
began this process, but in addition to QQuickWindow delivering the
event to all items and their handlers in reverse paint order, ignoring
existing grabs, the handlers themselves have responsibility to act
as if it was an initial press whenever the number of relevant
touchpoints changes; and because QQuickWindow starts over, handlers do
not need to rely on passive grabs to retain interest in one point at
the time when a transition to a different number of points occurs.
For example, DragHandler by default handles just one point, so if you
press one point such that it takes a passive grab and adds that point
to m_currentPoints, then you press a second finger within the bounds
of the same parentItem, the DragHandler should not go on "wanting" the
first point anymore, because a two-finger gesture is different, and
not suitable for the DragHandler unless its maximumPointCount >= 2.
Even if the second point is released, QQuickWindow will "start over"
with delivery, so a multi-point handler does not need to rely on
retaining a passive grab to handle the transition from two points back
to one again.
This also helps enable smoother transitions between different
gestures: e.g. in the map.qml manual test, you can drag one finger and
transition from dragging to pinching and back while the second finger
is pressed, dragged and released.
Change-Id: Id9b8f30029ed1ff9fd2d64a5e413a47055622083
Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io>
Diffstat (limited to 'src/quick')
-rw-r--r-- | src/quick/handlers/qquickmultipointhandler.cpp | 20 | ||||
-rw-r--r-- | src/quick/handlers/qquickpointerhandler.cpp | 2 |
2 files changed, 16 insertions, 6 deletions
diff --git a/src/quick/handlers/qquickmultipointhandler.cpp b/src/quick/handlers/qquickmultipointhandler.cpp index 687bccdc4f..b50989b466 100644 --- a/src/quick/handlers/qquickmultipointhandler.cpp +++ b/src/quick/handlers/qquickmultipointhandler.cpp @@ -78,10 +78,21 @@ bool QQuickMultiPointHandler::wantsPointerEvent(QQuickPointerEvent *event) if (event->asPointerScrollEvent()) return false; - if (hasCurrentPoints(event)) + // If points were pressed or released within parentItem, reset stored state + // and check eligible points again. This class of handlers is intended to + // handle a specific number of points, so a differing number of points will + // usually result in different behavior. But otherwise if the currentPoints + // are all still there in the event, we're good to go (do not reset + // m_currentPoints, because we don't want to lose the pressPosition, and do + // not want to reshuffle the order either). + const QVector<QQuickEventPoint *> candidatePoints = eligiblePoints(event); + if (candidatePoints.count() != m_currentPoints.count()) { + m_currentPoints.clear(); + setActive(false); + } else if (hasCurrentPoints(event)) { return true; + } - const QVector<QQuickEventPoint *> candidatePoints = eligiblePoints(event); const bool ret = (candidatePoints.size() >= minimumPointCount() && candidatePoints.size() <= maximumPointCount()); if (ret) { const int c = candidatePoints.count(); @@ -143,14 +154,13 @@ QVector<QQuickEventPoint *> QQuickMultiPointHandler::eligiblePoints(QQuickPointe QVector<QQuickEventPoint *> ret; int c = event->pointCount(); // If one or more points are newly pressed or released, all non-released points are candidates for this handler. - // In other cases however, do not steal the grab: that is, if a point has a grabber, - // it's not a candidate for this handler. + // In other cases however, check whether it would be OK to steal the grab if the handler chooses to do that. bool stealingAllowed = event->isPressEvent() || event->isReleaseEvent(); for (int i = 0; i < c; ++i) { QQuickEventPoint *p = event->point(i); if (!stealingAllowed) { QObject *exclusiveGrabber = p->exclusiveGrabber(); - if (exclusiveGrabber && exclusiveGrabber != this) + if (exclusiveGrabber && exclusiveGrabber != this && !canGrab(p)) continue; } if (p->state() != QQuickEventPoint::Released && wantsEventPoint(p)) diff --git a/src/quick/handlers/qquickpointerhandler.cpp b/src/quick/handlers/qquickpointerhandler.cpp index 0be3c05e96..db58046e81 100644 --- a/src/quick/handlers/qquickpointerhandler.cpp +++ b/src/quick/handlers/qquickpointerhandler.cpp @@ -453,7 +453,7 @@ bool QQuickPointerHandler::wantsPointerEvent(QQuickPointerEvent *event) bool QQuickPointerHandler::wantsEventPoint(QQuickEventPoint *point) { - bool ret = parentContains(point); + bool ret = point->exclusiveGrabber() == this || point->passiveGrabbers().contains(this) || parentContains(point); qCDebug(lcPointerHandlerDispatch) << hex << point->pointId() << "@" << point->scenePosition() << metaObject()->className() << objectName() << ret; return ret; |