aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/quick/items/qquickevents.cpp25
-rw-r--r--src/quick/items/qquickwindow.cpp14
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 {