aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items/qquickevents.cpp
diff options
context:
space:
mode:
authorShawn Rutledge <shawn.rutledge@qt.io>2017-04-03 11:37:03 +0200
committerShawn Rutledge <shawn.rutledge@qt.io>2017-05-22 19:12:12 +0000
commit48011c2dfeb83b4fe717034d4b3c353714fead48 (patch)
tree836196ff3c97c7085b5c9e7a4be052ad02759b33 /src/quick/items/qquickevents.cpp
parenta09b2f6fcd087e849f4e766a03c1ab47ae49d0d7 (diff)
Start over with event delivery when touchpoint releases occur
The new rule is that when the number of touchpoints changes, we start over with event delivery as if the touch had just begun, to give more opportunities to hand off processing from one item or handler to another. And MultiPointTouchArea can now handle the handoff: for example in tests/manual/pointer/pinchDragFlingMPTA.qml when the user is pressing three fingers, the PinchHandler is active; when the user then lifts one finger, the MPTA can resume handling the two remaining touchpoints as if they were just pressed. The change in QQuickMultiPointerHandler::wantsPointerEvent is both a behavior change and an optimization: released points aren't eligible; but if some points are released, then pressed, updated and stationary points are all eligible. And, figure this out without looping over the points twice. Change-Id: I26b7593de8e72b471adfec4a4482dd87a8288442 Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io>
Diffstat (limited to 'src/quick/items/qquickevents.cpp')
-rw-r--r--src/quick/items/qquickevents.cpp36
1 files changed, 29 insertions, 7 deletions
diff --git a/src/quick/items/qquickevents.cpp b/src/quick/items/qquickevents.cpp
index 0f613d300b..bde271882c 100644
--- a/src/quick/items/qquickevents.cpp
+++ b/src/quick/items/qquickevents.cpp
@@ -1055,6 +1055,18 @@ bool QQuickPointerMouseEvent::isPressEvent() const
(me->buttons() & me->button()) == me->buttons());
}
+bool QQuickPointerMouseEvent::isUpdateEvent() const
+{
+ auto me = static_cast<QMouseEvent*>(m_event);
+ return me->type() == QEvent::MouseMove;
+}
+
+bool QQuickPointerMouseEvent::isReleaseEvent() const
+{
+ auto me = static_cast<QMouseEvent*>(m_event);
+ return me->type() == QEvent::MouseButtonRelease;
+}
+
bool QQuickPointerTouchEvent::allPointsAccepted() const {
for (int i = 0; i < m_pointCount; ++i) {
if (!m_touchPoints.at(i)->isAccepted())
@@ -1124,6 +1136,16 @@ bool QQuickPointerTouchEvent::isPressEvent() const
return static_cast<QTouchEvent*>(m_event)->touchPointStates() & Qt::TouchPointPressed;
}
+bool QQuickPointerTouchEvent::isUpdateEvent() const
+{
+ return static_cast<QTouchEvent*>(m_event)->touchPointStates() & (Qt::TouchPointMoved | Qt::TouchPointStationary);
+}
+
+bool QQuickPointerTouchEvent::isReleaseEvent() const
+{
+ return static_cast<QTouchEvent*>(m_event)->touchPointStates() & Qt::TouchPointReleased;
+}
+
QVector<QPointF> QQuickPointerEvent::unacceptedPressedPointScenePositions() const
{
QVector<QPointF> points;
@@ -1239,7 +1261,7 @@ 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 anyPressOrReleaseInside = false;
bool anyGrabber = false;
QMatrix4x4 transformMatrix(QQuickItemPrivate::get(item)->windowToItemTransform());
for (int i = 0; i < m_pointCount; ++i) {
@@ -1250,8 +1272,9 @@ QTouchEvent *QQuickPointerTouchEvent::touchEventForItem(QQuickItem *item, bool i
bool isGrabber = p->exclusiveGrabber() == item;
if (isGrabber)
anyGrabber = true;
- // include points inside the bounds
+ // include points inside the bounds if no other item is the grabber or if the item is filtering
bool isInside = item->contains(item->mapFromScene(p->scenePos()));
+ bool hasAnotherGrabber = p->exclusiveGrabber() && p->exclusiveGrabber() != item;
// filtering: (childMouseEventFilter) include points that are grabbed by children of the target item
bool grabberIsChild = false;
@@ -1265,11 +1288,10 @@ QTouchEvent *QQuickPointerTouchEvent::touchEventForItem(QQuickItem *item, bool i
}
bool filterRelevant = isFiltering && grabberIsChild;
- if (!(isGrabber || isInside || filterRelevant))
+ if (!(isGrabber || (isInside && (!hasAnotherGrabber || isFiltering)) || filterRelevant))
continue;
- bool isPress = p->state() == QQuickEventPoint::Pressed;
- if (isPress && isInside)
- anyPressInside = true;
+ if ((p->state() == QQuickEventPoint::Pressed || p->state() == QQuickEventPoint::Released) && isInside)
+ anyPressOrReleaseInside = true;
const QTouchEvent::TouchPoint *tp = touchPointById(p->pointId());
if (tp) {
eventStates |= tp->state();
@@ -1285,7 +1307,7 @@ QTouchEvent *QQuickPointerTouchEvent::touchEventForItem(QQuickItem *item, bool i
// 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))
+ if (eventStates == Qt::TouchPointStationary || touchPoints.isEmpty() || (!anyPressOrReleaseInside && !anyGrabber && !isFiltering))
return nullptr;
// if all points have the same state, set the event type accordingly