diff options
-rw-r--r-- | src/quick/items/qquickitem.cpp | 27 | ||||
-rw-r--r-- | src/quick/items/qquickitem.h | 2 | ||||
-rw-r--r-- | src/quick/items/qquickitem_p.h | 1 | ||||
-rw-r--r-- | src/quick/items/qquickmultipointtoucharea.cpp | 1 | ||||
-rw-r--r-- | src/quick/items/qquickpincharea.cpp | 1 | ||||
-rw-r--r-- | src/quick/items/qquickwindow.cpp | 32 | ||||
-rw-r--r-- | src/quick/items/qquickwindow_p.h | 2 | ||||
-rw-r--r-- | tests/auto/quick/qquickflickable/tst_qquickflickable.cpp | 4 | ||||
-rw-r--r-- | tests/auto/quick/qquickitem/tst_qquickitem.cpp | 10 | ||||
-rw-r--r-- | tests/auto/quick/touchmouse/tst_touchmouse.cpp | 1 |
10 files changed, 64 insertions, 17 deletions
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index bfc4a59851..ef22af965a 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -3172,6 +3172,7 @@ QQuickItemPrivate::QQuickItemPrivate() , antialiasingValid(false) , isTabFence(false) , replayingPressEvent(false) + , touchEnabled(false) , dirtyAttributes(0) , nextDirtyItem(0) , prevDirtyItem(0) @@ -7190,6 +7191,32 @@ void QQuickItem::setAcceptHoverEvents(bool enabled) d->setHasHoverInChild(enabled); } +/*! + Returns whether touch events are accepted by this item. + + The default value is false. + + If this is false, then the item will not receive any touch events through + the touchEvent() function. +*/ +bool QQuickItem::acceptTouchEvents() const +{ + Q_D(const QQuickItem); + return d->touchEnabled; +} + +/*! + If \a enabled is true, this sets the item to accept touch events; + otherwise, touch events are not accepted by this item. + + \sa acceptTouchEvents() +*/ +void QQuickItem::setAcceptTouchEvents(bool accept) +{ + Q_D(QQuickItem); + d->touchEnabled = accept; +} + void QQuickItemPrivate::setHasCursorInChild(bool hasCursor) { #if QT_CONFIG(cursor) diff --git a/src/quick/items/qquickitem.h b/src/quick/items/qquickitem.h index 1d174ca979..b7a25581a7 100644 --- a/src/quick/items/qquickitem.h +++ b/src/quick/items/qquickitem.h @@ -292,6 +292,8 @@ public: void setAcceptedMouseButtons(Qt::MouseButtons buttons); bool acceptHoverEvents() const; void setAcceptHoverEvents(bool enabled); + bool acceptTouchEvents() const; + void setAcceptTouchEvents(bool accept); #if QT_CONFIG(cursor) QCursor cursor() const; diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h index 263cb19d20..6b010fc24d 100644 --- a/src/quick/items/qquickitem_p.h +++ b/src/quick/items/qquickitem_p.h @@ -442,6 +442,7 @@ public: // focus chain and prevents tabbing outside. bool isTabFence:1; bool replayingPressEvent:1; + bool touchEnabled:1; enum DirtyType { TransformOrigin = 0x00000001, diff --git a/src/quick/items/qquickmultipointtoucharea.cpp b/src/quick/items/qquickmultipointtoucharea.cpp index 62119effb2..9b2b4daa58 100644 --- a/src/quick/items/qquickmultipointtoucharea.cpp +++ b/src/quick/items/qquickmultipointtoucharea.cpp @@ -420,6 +420,7 @@ QQuickMultiPointTouchArea::QQuickMultiPointTouchArea(QQuickItem *parent) if (qmlVisualTouchDebugging()) { setFlag(QQuickItem::ItemHasContents); } + setAcceptTouchEvents(true); #ifdef Q_OS_OSX setAcceptHoverEvents(true); // needed to enable touch events on mouse hover. #endif diff --git a/src/quick/items/qquickpincharea.cpp b/src/quick/items/qquickpincharea.cpp index 6295aa1932..171b98cd31 100644 --- a/src/quick/items/qquickpincharea.cpp +++ b/src/quick/items/qquickpincharea.cpp @@ -288,6 +288,7 @@ QQuickPinchArea::QQuickPinchArea(QQuickItem *parent) { Q_D(QQuickPinchArea); d->init(); + setAcceptTouchEvents(true); #ifdef Q_OS_OSX setAcceptHoverEvents(true); // needed to enable touch events on mouse hover. #endif diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 888b0cde85..e6f77ea69a 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -1720,7 +1720,7 @@ void QQuickWindowPrivate::deliverMouseEvent(QQuickPointerMouseEvent *pointerEven } // If some points weren't grabbed, deliver to non-grabber PointerHandlers in reverse paint order if (!pointerEvent->allPointsGrabbed() && pointerEvent->buttons()) { - QVector<QQuickItem *> targetItems = pointerTargets(contentItem, point->scenePos(), false); + QVector<QQuickItem *> targetItems = pointerTargets(contentItem, point->scenePos(), false, false); for (QQuickItem *item : targetItems) { QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item); pointerEvent->localize(item); @@ -2206,7 +2206,10 @@ void QQuickWindowPrivate::deliverPointerEvent(QQuickPointerEvent *event) // check if item or any of its child items contain the point // FIXME: should this be iterative instead of recursive? -QVector<QQuickItem *> QQuickWindowPrivate::pointerTargets(QQuickItem *item, const QPointF &scenePos, bool checkMouseButtons) const +// If checkMouseButtons is true, it means we are finding targets for a mouse event, so no item for which acceptedMouseButtons() is NoButton will be added. +// If checkAcceptsTouch is true, it means we are finding targets for a touch event, so either acceptTouchEvents() must return true OR +// it must accept a synth. mouse event, thus if acceptTouchEvents() returns false but acceptedMouseButtons() is true, gets added; if not, it doesn't. +QVector<QQuickItem *> QQuickWindowPrivate::pointerTargets(QQuickItem *item, const QPointF &scenePos, bool checkMouseButtons, bool checkAcceptsTouch) const { QVector<QQuickItem *> targets; auto itemPrivate = QQuickItemPrivate::get(item); @@ -2224,13 +2227,16 @@ QVector<QQuickItem *> QQuickWindowPrivate::pointerTargets(QQuickItem *item, cons auto childPrivate = QQuickItemPrivate::get(child); if (!child->isVisible() || !child->isEnabled() || childPrivate->culled) continue; - targets << pointerTargets(child, scenePos, false); + targets << pointerTargets(child, scenePos, checkMouseButtons, checkAcceptsTouch); } - if (item->contains(itemPos) && (!checkMouseButtons || itemPrivate->acceptedMouseButtons())) { - // add this item last - children take precedence - targets << item; - } + bool relevant = item->contains(itemPos); + if (relevant && checkMouseButtons && item->acceptedMouseButtons() == Qt::NoButton) + relevant = false; + if (relevant && checkAcceptsTouch && !(item->acceptTouchEvents() || item->acceptedMouseButtons())) + relevant = false; + if (relevant) + targets << item; // add this item last: children take precedence return targets; } @@ -2337,7 +2343,7 @@ void QQuickWindowPrivate::deliverUpdatedTouchPoints(QQuickPointerTouchEvent *eve QQuickEventPoint *point = event->point(i); if (point->state() == QQuickEventPoint::Pressed) continue; // presses were delivered earlier; not the responsibility of deliverUpdatedTouchPoints - QVector<QQuickItem *> targetItemsForPoint = pointerTargets(contentItem, point->scenePos(), false); + QVector<QQuickItem *> targetItemsForPoint = pointerTargets(contentItem, point->scenePos(), false, false); if (targetItems.count()) { targetItems = mergePointerTargets(targetItems, targetItemsForPoint); } else { @@ -2363,8 +2369,9 @@ bool QQuickWindowPrivate::deliverPressEvent(QQuickPointerEvent *event) { const QVector<QPointF> points = event->unacceptedPressedPointScenePositions(); QVector<QQuickItem *> targetItems; + bool isTouchEvent = (event->asPointerTouchEvent() != nullptr); for (QPointF point: points) { - QVector<QQuickItem *> targetItemsForPoint = pointerTargets(contentItem, point, false); + QVector<QQuickItem *> targetItemsForPoint = pointerTargets(contentItem, point, !isTouchEvent, isTouchEvent); if (targetItems.count()) { targetItems = mergePointerTargets(targetItems, targetItemsForPoint); } else { @@ -2661,8 +2668,9 @@ void QQuickWindowPrivate::updateFilteringParentItems(const QVector<QQuickItem *> for (QQuickItem *item : targetItems) { QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(item); // If the item neither handles events nor has handlers which do, then it will never be a receiver, so filtering is irrelevant - if (!item->acceptedMouseButtons() && !(itemPriv->extra.isAllocated() && !itemPriv->extra->pointerHandlers.isEmpty())) - continue; // TODO there's no acceptTouchEvents, so it's hard to avoid skipping any items which handle only touch + if (!item->acceptedMouseButtons() && !item->acceptTouchEvents() && + !(itemPriv->extra.isAllocated() && !itemPriv->extra->pointerHandlers.isEmpty())) + continue; QQuickItem *parent = item->parentItem(); while (parent) { if (parent->filtersChildMouseEvents()) { @@ -2700,6 +2708,8 @@ bool QQuickWindowPrivate::sendFilteredPointerEvent(QQuickPointerEvent *event, QQ QVarLengthArray<QPair<QQuickPointerHandler *, QQuickEventPoint *>, 32> passiveGrabsToCancel; for (QPair<QQuickItem *,QQuickItem *> itemAndParent : filteringParentItems) { QQuickItem *item = receiver ? receiver : itemAndParent.first; + if (!item->acceptTouchEvents() && !item->acceptedMouseButtons()) + continue; // if this item won't accept, parents don't need to filter the touch for it QQuickItem *filteringParent = itemAndParent.second; if (item == filteringParent) continue; // a filtering item never needs to filter for itself diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h index b8131a056f..f66809cc8a 100644 --- a/src/quick/items/qquickwindow_p.h +++ b/src/quick/items/qquickwindow_p.h @@ -172,7 +172,7 @@ public: void deliverUpdatedTouchPoints(QQuickPointerTouchEvent *event); void deliverMatchingPointsToItem(QQuickItem *item, QQuickPointerEvent *pointerEvent); - QVector<QQuickItem *> pointerTargets(QQuickItem *, const QPointF &, bool checkMouseButtons) const; + QVector<QQuickItem *> pointerTargets(QQuickItem *, const QPointF &, bool checkMouseButtons, bool checkAcceptsTouch) const; QVector<QQuickItem *> mergePointerTargets(const QVector<QQuickItem *> &list1, const QVector<QQuickItem *> &list2) const; void updateFilteringParentItems(const QVector<QQuickItem *> &targetItems); diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp index ef6e444580..b37bb03305 100644 --- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp +++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp @@ -63,7 +63,9 @@ public: , touchReleases(0) , ungrabs(0) , m_active(false) - { } + { + setAcceptTouchEvents(true); + } QPointF pos() const { return m_pos; } diff --git a/tests/auto/quick/qquickitem/tst_qquickitem.cpp b/tests/auto/quick/qquickitem/tst_qquickitem.cpp index 10a3a0bfa8..dbfe97d640 100644 --- a/tests/auto/quick/qquickitem/tst_qquickitem.cpp +++ b/tests/auto/quick/qquickitem/tst_qquickitem.cpp @@ -46,10 +46,12 @@ class TestItem : public QQuickItem Q_OBJECT public: TestItem(QQuickItem *parent = 0) - : QQuickItem(parent), focused(false), pressCount(0), releaseCount(0) - , wheelCount(0), acceptIncomingTouchEvents(true) - , touchEventReached(false), timestamp(0) - , lastWheelEventPos(0, 0), lastWheelEventGlobalPos(0, 0) {} + : QQuickItem(parent), focused(false), pressCount(0), releaseCount(0) + , wheelCount(0), acceptIncomingTouchEvents(true) + , touchEventReached(false), timestamp(0) + , lastWheelEventPos(0, 0), lastWheelEventGlobalPos(0, 0) { + setAcceptTouchEvents(true); + } bool focused; int pressCount; diff --git a/tests/auto/quick/touchmouse/tst_touchmouse.cpp b/tests/auto/quick/touchmouse/tst_touchmouse.cpp index 6e7fce6189..6f5c9a37d5 100644 --- a/tests/auto/quick/touchmouse/tst_touchmouse.cpp +++ b/tests/auto/quick/touchmouse/tst_touchmouse.cpp @@ -74,6 +74,7 @@ public: : QQuickItem(parent), touchUngrabCount(0), acceptMouse(false), acceptTouch(false), filterTouch(false), point0(-1) { setAcceptedMouseButtons(Qt::LeftButton); + setAcceptTouchEvents(true); } void touchEvent(QTouchEvent *event) |