diff options
author | Shawn Rutledge <shawn.rutledge@qt.io> | 2017-03-31 13:11:09 +0200 |
---|---|---|
committer | Shawn Rutledge <shawn.rutledge@qt.io> | 2017-04-27 12:34:01 +0000 |
commit | 822e39df38b20763d2933d7a6d2d6ddf7b9b2639 (patch) | |
tree | 414593f26da336abfff57ac4c0a0213bdfc0dd0c | |
parent | 926d69a61c50bf970c0f6cc5dddf735e996f502e (diff) |
Start over with event delivery when touchpoint presses occur
It was part of the intended design for pointer handlers; omitting this
feature has until now prevented some opportunities for handoff
from one handler to another.
Now if PinchHandler has grabbed, pressing one more point will let
something else have a chance again, for example.
But this is incomplete in that if we release a point, we should do
the same thing, actually.
Change-Id: I10f567e7e4388bf0caab54c261178f19db20b14a
Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io>
-rw-r--r-- | src/quick/items/qquickevents.cpp | 25 | ||||
-rw-r--r-- | src/quick/items/qquickwindow.cpp | 14 |
2 files changed, 29 insertions, 10 deletions
diff --git a/src/quick/items/qquickevents.cpp b/src/quick/items/qquickevents.cpp index ba93a4195e..a2d8ea3ad6 100644 --- a/src/quick/items/qquickevents.cpp +++ b/src/quick/items/qquickevents.cpp @@ -1224,7 +1224,12 @@ const QTouchEvent::TouchPoint *QQuickPointerTouchEvent::touchPointById(int point \internal Make a new QTouchEvent, giving it a subset of the original touch points. - Returns a nullptr if all points are stationary or there are no points inside the item. + Returns a nullptr if all points are stationary, or there are no points inside the item, + or none of the points were pressed inside and the item was not grabbing any of them + and isFiltering is false. When isFiltering is true, it is assumed that the item + cares about all points which are inside its bounds, because most filtering items + need to monitor eventpoint movements until a drag threshold is exceeded or the + requirements for a gesture to be recognized are met in some other way. */ QTouchEvent *QQuickPointerTouchEvent::touchEventForItem(QQuickItem *item, bool isFiltering) const { @@ -1234,6 +1239,8 @@ QTouchEvent *QQuickPointerTouchEvent::touchEventForItem(QQuickItem *item, bool i // Or else just document that velocity is always scene-relative and is not scaled and rotated with the item // but that would require changing tst_qquickwindow::touchEvent_velocity(): it expects transformed velocity + bool anyPressInside = false; + bool anyGrabber = false; QMatrix4x4 transformMatrix(QQuickItemPrivate::get(item)->windowToItemTransform()); for (int i = 0; i < m_pointCount; ++i) { auto p = m_touchPoints.at(i); @@ -1241,8 +1248,10 @@ QTouchEvent *QQuickPointerTouchEvent::touchEventForItem(QQuickItem *item, bool i continue; // include points where item is the grabber bool isGrabber = p->exclusiveGrabber() == item; - // include newly pressed points inside the bounds - bool isPressInside = p->state() == QQuickEventPoint::Pressed && item->contains(item->mapFromScene(p->scenePos())); + if (isGrabber) + anyGrabber = true; + // include points inside the bounds + bool isInside = item->contains(item->mapFromScene(p->scenePos())); // filtering: (childMouseEventFilter) include points that are grabbed by children of the target item bool grabberIsChild = false; @@ -1256,9 +1265,11 @@ QTouchEvent *QQuickPointerTouchEvent::touchEventForItem(QQuickItem *item, bool i } bool filterRelevant = isFiltering && grabberIsChild; - if (!(isGrabber || isPressInside || filterRelevant)) + if (!(isGrabber || isInside || filterRelevant)) continue; - + bool isPress = p->state() == QQuickEventPoint::Pressed; + if (isPress && isInside) + anyPressInside = true; const QTouchEvent::TouchPoint *tp = touchPointById(p->pointId()); if (tp) { eventStates |= tp->state(); @@ -1272,7 +1283,9 @@ QTouchEvent *QQuickPointerTouchEvent::touchEventForItem(QQuickItem *item, bool i } } - if (eventStates == Qt::TouchPointStationary || touchPoints.isEmpty()) + // Now touchPoints will have only points which are inside the item. + // But if none of them were just pressed inside, and the item has no other reason to care, ignore them anyway. + if (eventStates == Qt::TouchPointStationary || touchPoints.isEmpty() || (!anyPressInside && !anyGrabber && !isFiltering)) return nullptr; // if all points have the same state, set the event type accordingly diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 359763bfb4..9c9764005d 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -754,6 +754,9 @@ void QQuickWindowPrivate::setMouseGrabber(QQuickItem *grabber) qCDebug(DBG_TOUCH_TARGET) << "TP (mouse)" << hex << touchMouseId << "->" << q->mouseGrabberItem(); auto point = touchMouseDevice->pointerEvent()->pointById(touchMouseId); if (point) { + auto originalEvent = point->pointerEvent()->device()->pointerEvent(); + for (int i = 0; i < originalEvent->pointCount(); ++i) + originalEvent->point(i)->cancelExclusiveGrab(); point->setGrabberItem(grabber); for (auto handler : point->passiveGrabbers()) point->cancelPassiveGrab(handler); @@ -2362,11 +2365,13 @@ void QQuickWindowPrivate::deliverUpdatedTouchPoints(QQuickPointerTouchEvent *eve // Deliver newly pressed touch points bool QQuickWindowPrivate::deliverPressEvent(QQuickPointerEvent *event) { - const QVector<QPointF> points = event->unacceptedPressedPointScenePositions(); + int pointCount = event->pointCount(); QVector<QQuickItem *> targetItems; bool isTouchEvent = (event->asPointerTouchEvent() != nullptr); - for (QPointF point: points) { - QVector<QQuickItem *> targetItemsForPoint = pointerTargets(contentItem, point, !isTouchEvent, isTouchEvent); + for (int i = 0; i < pointCount; ++i) { + auto point = event->point(i); + point->setAccepted(false); // because otherwise touchEventForItem will ignore it + QVector<QQuickItem *> targetItemsForPoint = pointerTargets(contentItem, point->scenePos(), !isTouchEvent, isTouchEvent); if (targetItems.count()) { targetItems = mergePointerTargets(targetItems, targetItemsForPoint); } else { @@ -2458,10 +2463,11 @@ void QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, QQuickPo if (eventAccepted) { // If the touch was accepted (regardless by whom or in what form), // update accepted new points. + bool isPress = pointerEvent->isPressEvent(); for (auto point: qAsConst(touchEvent->touchPoints())) { auto pointerEventPoint = ptEvent->pointById(point.id()); pointerEventPoint->setAccepted(); - if (point.state() == Qt::TouchPointPressed) + if (isPress) pointerEventPoint->setGrabberItem(item); } } else { |