aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/quick/items/qquickitem.cpp27
-rw-r--r--src/quick/items/qquickitem.h2
-rw-r--r--src/quick/items/qquickitem_p.h1
-rw-r--r--src/quick/items/qquickmultipointtoucharea.cpp1
-rw-r--r--src/quick/items/qquickpincharea.cpp1
-rw-r--r--src/quick/items/qquickwindow.cpp32
-rw-r--r--src/quick/items/qquickwindow_p.h2
-rw-r--r--tests/auto/quick/qquickflickable/tst_qquickflickable.cpp4
-rw-r--r--tests/auto/quick/qquickitem/tst_qquickitem.cpp10
-rw-r--r--tests/auto/quick/touchmouse/tst_touchmouse.cpp1
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)