aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorShawn Rutledge <shawn.rutledge@qt.io>2017-04-05 11:21:29 +0200
committerShawn Rutledge <shawn.rutledge@qt.io>2017-04-14 08:47:53 +0000
commit1457df74f4c1d770e1e820de8cd082be1bd2489e (patch)
tree9a6a637ee9304607e0cab1163db9c4c9479f0352 /src
parent70513c7496dabf504132dd5c900cd85b367bd1b7 (diff)
Add QQuickItem acceptTouchEvents/setAcceptTouchEvents; require for touch
It has been suboptimal to speculatively deliver touch events to Items which are not interested; even worse is when we must deliver to a parent item which is filtering events, when the child Item will not accept the touch event anyway. So now it is required that any QQuickItem subclass which wishes to accept touch events must call setAcceptTouchEvents(true) (typically in its constructor). If it does not do this, it will not get any touch events (and this saves us the trouble of looking for parents which filter touch events, too). It is consistent with needing to call setAcceptHoverEvents() to get hover events, and setAcceptedMouseButtons() to get mouse events. [ChangeLog][QtQuick][QQuickItem] When subclassing QQuickItem, it is now required to call setAcceptTouchEvents(true) if you need the item to receive touch events. Change-Id: Idc76c04f4e7f1d4a613087e756e96dac368f4f23 Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
Diffstat (limited to 'src')
-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
7 files changed, 54 insertions, 12 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);