aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/quick/items/qquickflickable.cpp223
-rw-r--r--src/quick/items/qquickflickable_p.h3
-rw-r--r--src/quick/items/qquickflickable_p_p.h10
-rw-r--r--src/quick/items/qquickitem.cpp42
-rw-r--r--src/quick/items/qquickwindow.cpp66
-rw-r--r--src/quick/items/qquickwindow_p.h10
-rw-r--r--tests/auto/qmltest/events/tst_touch.qml10
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnList.qml2
-rw-r--r--tests/auto/quick/qquickflickable/data/nestedStopAtBounds.qml5
-rw-r--r--tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp7
-rw-r--r--tests/auto/quick/touchmouse/tst_touchmouse.cpp84
11 files changed, 297 insertions, 165 deletions
diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp
index 960b02ea9c..a6171ade78 100644
--- a/src/quick/items/qquickflickable.cpp
+++ b/src/quick/items/qquickflickable.cpp
@@ -62,6 +62,8 @@
QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(lcHandlerParent)
+Q_LOGGING_CATEGORY(lcFilter, "qt.quick.flickable.filter")
+Q_LOGGING_CATEGORY(lcReplay, "qt.quick.flickable.replay")
// FlickThreshold determines how far the "mouse" must have moved
// before we perform a flick.
@@ -281,7 +283,7 @@ void QQuickFlickablePrivate::init()
qmlobject_connect(&velocityTimeline, QQuickTimeLine, SIGNAL(completed()),
q, QQuickFlickable, SLOT(velocityTimelineCompleted()));
q->setAcceptedMouseButtons(Qt::LeftButton);
- q->setAcceptTouchEvents(false); // rely on mouse events synthesized from touch
+ q->setAcceptTouchEvents(true);
q->setFiltersChildMouseEvents(true);
QQuickItemPrivate *viewportPrivate = QQuickItemPrivate::get(contentItem);
viewportPrivate->addItemChangeListener(this, QQuickItemPrivate::Geometry);
@@ -1032,7 +1034,7 @@ qreal QQuickFlickablePrivate::devicePixelRatio() const
return (window ? window->effectiveDevicePixelRatio() : qApp->devicePixelRatio());
}
-void QQuickFlickablePrivate::handleMousePressEvent(QMouseEvent *event)
+void QQuickFlickablePrivate::handlePressEvent(QPointerEvent *event)
{
Q_Q(QQuickFlickable);
timer.start();
@@ -1060,7 +1062,7 @@ void QQuickFlickablePrivate::handleMousePressEvent(QMouseEvent *event)
}
q->setKeepMouseGrab(stealMouse);
- maybeBeginDrag(computeCurrentTime(event), event->position());
+ maybeBeginDrag(computeCurrentTime(event), event->points().first().position());
}
void QQuickFlickablePrivate::maybeBeginDrag(qint64 currentTimestamp, const QPointF &pressPosn)
@@ -1311,34 +1313,29 @@ void QQuickFlickablePrivate::drag(qint64 currentTimestamp, QEvent::Type eventTyp
lastPos = localPos;
}
-void QQuickFlickablePrivate::handleMouseMoveEvent(QMouseEvent *event)
+void QQuickFlickablePrivate::handleMoveEvent(QPointerEvent *event)
{
Q_Q(QQuickFlickable);
- if (!interactive || lastPosTime == -1 || event->buttons() == Qt::NoButton)
+ if (!interactive || lastPosTime == -1 ||
+ (event->isSinglePointEvent() && static_cast<QSinglePointEvent *>(event)->buttons() == Qt::NoButton))
return;
qint64 currentTimestamp = computeCurrentTime(event);
- QVector2D deltas = QVector2D(event->position() - pressPos);
+ const auto &firstPoint = event->points().first();
+ const auto &pos = firstPoint.position();
+ QVector2D deltas = QVector2D(pos - q->mapFromGlobal(firstPoint.globalPressPosition()));
bool overThreshold = false;
QVector2D velocity = event->point(0).velocity();
- // TODO guarantee that events always have velocity so that it never needs to be computed here
- if (!event->device()->capabilities().testFlag(QInputDevice::Capability::Velocity)) {
- qint64 lastTimestamp = (lastPos.isNull() ? lastPressTime : lastPosTime);
- if (currentTimestamp == lastTimestamp)
- return; // events are too close together: velocity would be infinite
- qreal elapsed = qreal(currentTimestamp - lastTimestamp) / 1000.;
- velocity = QVector2D(event->position() - (lastPos.isNull() ? pressPos : lastPos)) / elapsed;
- }
if (q->yflick())
- overThreshold |= QQuickWindowPrivate::dragOverThreshold(deltas.y(), Qt::YAxis, event);
+ overThreshold |= QQuickWindowPrivate::dragOverThreshold(deltas.y(), Qt::YAxis, firstPoint);
if (q->xflick())
- overThreshold |= QQuickWindowPrivate::dragOverThreshold(deltas.x(), Qt::XAxis, event);
+ overThreshold |= QQuickWindowPrivate::dragOverThreshold(deltas.x(), Qt::XAxis, firstPoint);
- drag(currentTimestamp, event->type(), event->position(), deltas, overThreshold, false, false, velocity);
+ drag(currentTimestamp, event->type(), pos, deltas, overThreshold, false, false, velocity);
}
-void QQuickFlickablePrivate::handleMouseReleaseEvent(QMouseEvent *event)
+void QQuickFlickablePrivate::handleReleaseEvent(QPointerEvent *event)
{
Q_Q(QQuickFlickable);
stealMouse = false;
@@ -1359,6 +1356,8 @@ void QQuickFlickablePrivate::handleMouseReleaseEvent(QMouseEvent *event)
hData.vTime = vData.vTime = timeline.time();
bool canBoost = false;
+ const auto pos = event->points().first().position();
+ const auto pressPos = event->points().first().pressPosition();
qreal vVelocity = 0;
if (elapsed < 100 && vData.velocity != 0.) {
@@ -1394,7 +1393,7 @@ void QQuickFlickablePrivate::handleMouseReleaseEvent(QMouseEvent *event)
bool flickedVertically = false;
vVelocity *= flickBoost;
- bool isVerticalFlickAllowed = q->yflick() && qAbs(vVelocity) > MinimumFlickVelocity && qAbs(event->position().y() - pressPos.y()) > FlickThreshold;
+ bool isVerticalFlickAllowed = q->yflick() && qAbs(vVelocity) > MinimumFlickVelocity && qAbs(pos.y() - pressPos.y()) > FlickThreshold;
if (isVerticalFlickAllowed) {
velocityTimeline.reset(vData.smoothVelocity);
vData.smoothVelocity.setValue(-vVelocity);
@@ -1403,7 +1402,7 @@ void QQuickFlickablePrivate::handleMouseReleaseEvent(QMouseEvent *event)
bool flickedHorizontally = false;
hVelocity *= flickBoost;
- bool isHorizontalFlickAllowed = q->xflick() && qAbs(hVelocity) > MinimumFlickVelocity && qAbs(event->position().x() - pressPos.x()) > FlickThreshold;
+ bool isHorizontalFlickAllowed = q->xflick() && qAbs(hVelocity) > MinimumFlickVelocity && qAbs(pos.x() - pressPos.x()) > FlickThreshold;
if (isHorizontalFlickAllowed) {
velocityTimeline.reset(hData.smoothVelocity);
hData.smoothVelocity.setValue(-hVelocity);
@@ -1424,9 +1423,9 @@ void QQuickFlickablePrivate::handleMouseReleaseEvent(QMouseEvent *event)
void QQuickFlickable::mousePressEvent(QMouseEvent *event)
{
Q_D(QQuickFlickable);
- if (d->interactive && d->wantsPointerEvent(event)) {
+ if (d->interactive && !d->replayingPressEvent && d->wantsPointerEvent(event)) {
if (!d->pressed)
- d->handleMousePressEvent(event);
+ d->handlePressEvent(event);
event->accept();
} else {
QQuickItem::mousePressEvent(event);
@@ -1437,7 +1436,7 @@ void QQuickFlickable::mouseMoveEvent(QMouseEvent *event)
{
Q_D(QQuickFlickable);
if (d->interactive && d->wantsPointerEvent(event)) {
- d->handleMouseMoveEvent(event);
+ d->handleMoveEvent(event);
event->accept();
} else {
QQuickItem::mouseMoveEvent(event);
@@ -1452,10 +1451,11 @@ void QQuickFlickable::mouseReleaseEvent(QMouseEvent *event)
d->replayDelayedPress();
// Now send the release
- if (window() && window()->mouseGrabberItem()) {
- QPointF localPos = window()->mouseGrabberItem()->mapFromScene(event->scenePosition());
- QScopedPointer<QMouseEvent> mouseEvent(QQuickWindowPrivate::cloneMouseEvent(event, &localPos));
- QCoreApplication::sendEvent(window(), mouseEvent.data());
+ auto &firstPoint = event->point(0);
+ if (auto grabber = qmlobject_cast<QQuickItem *>(event->exclusiveGrabber(firstPoint))) {
+ QMouseEvent localized(*event);
+ QMutableEventPoint::from(firstPoint).setPosition(grabber->mapFromScene(event->scenePosition()));
+ QCoreApplication::sendEvent(window(), &localized);
}
// And the event has been consumed
@@ -1464,13 +1464,69 @@ void QQuickFlickable::mouseReleaseEvent(QMouseEvent *event)
return;
}
- d->handleMouseReleaseEvent(event);
+ d->handleReleaseEvent(event);
event->accept();
} else {
QQuickItem::mouseReleaseEvent(event);
}
}
+void QQuickFlickable::touchEvent(QTouchEvent *event)
+{
+ Q_D(QQuickFlickable);
+ bool unhandled = false;
+ const auto &firstPoint = event->points().first();
+ switch (firstPoint.state()) {
+ case QEventPoint::State::Pressed:
+ if (d->interactive && !d->replayingPressEvent && d->wantsPointerEvent(event)) {
+ if (!d->pressed)
+ d->handlePressEvent(event);
+ event->accept();
+ } else {
+ unhandled = true;
+ }
+ break;
+ case QEventPoint::State::Updated:
+ if (d->interactive && d->wantsPointerEvent(event)) {
+ d->handleMoveEvent(event);
+ event->accept();
+ } else {
+ unhandled = true;
+ }
+ break;
+ case QEventPoint::State::Released:
+ if (d->interactive && d->wantsPointerEvent(event)) {
+ if (d->delayedPressEvent) {
+ d->replayDelayedPress();
+
+ // Now send the release
+ auto &firstPoint = event->point(0);
+ if (auto grabber = qmlobject_cast<QQuickItem *>(event->exclusiveGrabber(firstPoint))) {
+ const auto localPos = grabber->mapFromScene(firstPoint.scenePosition());
+ QScopedPointer<QPointerEvent> localizedEvent(QQuickWindowPrivate::clonePointerEvent(event, localPos));
+ QCoreApplication::sendEvent(window(), localizedEvent.data());
+ }
+
+ // And the event has been consumed
+ d->stealMouse = false;
+ d->pressed = false;
+ return;
+ }
+
+ d->handleReleaseEvent(event);
+ event->accept();
+ } else {
+ unhandled = true;
+ }
+ break;
+ case QEventPoint::State::Stationary:
+ case QEventPoint::State::Unknown:
+ break;
+ }
+ if (unhandled)
+ QQuickItem::touchEvent(event);
+}
+
#if QT_CONFIG(wheelevent)
void QQuickFlickable::wheelEvent(QWheelEvent *event)
{
@@ -1595,7 +1651,7 @@ bool QQuickFlickablePrivate::isInnermostPressDelay(QQuickItem *i) const
return false;
}
-void QQuickFlickablePrivate::captureDelayedPress(QQuickItem *item, QMouseEvent *event)
+void QQuickFlickablePrivate::captureDelayedPress(QQuickItem *item, QPointerEvent *event)
{
Q_Q(QQuickFlickable);
if (!q->window() || pressDelay <= 0)
@@ -1606,15 +1662,17 @@ void QQuickFlickablePrivate::captureDelayedPress(QQuickItem *item, QMouseEvent *
if (!isInnermostPressDelay(item))
return;
- delayedPressEvent = QQuickWindowPrivate::cloneMouseEvent(event);
+ delayedPressEvent = QQuickWindowPrivate::clonePointerEvent(event);
delayedPressEvent->setAccepted(false);
delayedPressTimer.start(pressDelay, q);
+ qCDebug(lcReplay) << "begin press delay" << pressDelay << "ms with" << delayedPressEvent;
}
void QQuickFlickablePrivate::clearDelayedPress()
{
if (delayedPressEvent) {
delayedPressTimer.stop();
+ qCDebug(lcReplay) << "clear delayed press" << delayedPressEvent;
delete delayedPressEvent;
delayedPressEvent = nullptr;
}
@@ -1625,20 +1683,35 @@ void QQuickFlickablePrivate::replayDelayedPress()
Q_Q(QQuickFlickable);
if (delayedPressEvent) {
// Losing the grab will clear the delayed press event; take control of it here
- QScopedPointer<QMouseEvent> mouseEvent(delayedPressEvent);
+ QScopedPointer<QPointerEvent> event(delayedPressEvent);
delayedPressEvent = nullptr;
delayedPressTimer.stop();
// If we have the grab, release before delivering the event
- if (QQuickWindow *w = q->window()) {
- QQuickWindowPrivate *wpriv = QQuickWindowPrivate::get(w);
+ if (QQuickWindow *window = q->window()) {
+ QQuickWindowPrivate *wpriv = QQuickWindowPrivate::get(window);
wpriv->allowChildEventFiltering = false; // don't allow re-filtering during replay
replayingPressEvent = true;
- if (w->mouseGrabberItem() == q)
- q->ungrabMouse();
-
- // Use the event handler that will take care of finding the proper item to propagate the event
- QCoreApplication::sendEvent(w, mouseEvent.data());
+ auto &firstPoint = event->point(0);
+ // At first glance, it's weird for delayedPressEvent to already have a grabber;
+ // but on press, filterMouseEvent() took the exclusive grab, and that's stored
+ // in the device-specific EventPointData instance in QPointingDevicePrivate::activePoints,
+ // not in the event itself. If this Flickable is still the grabber of that point on that device,
+ // that's the reason; but now it doesn't need that grab anymore.
+ if (event->exclusiveGrabber(firstPoint) == q)
+ event->setExclusiveGrabber(firstPoint, nullptr);
+
+ qCDebug(lcReplay) << "replaying" << event.data();
+ // Put scenePosition into position, for the sake of QQuickWindowPrivate::translateTouchEvent()
+ // TODO remove this if we remove QQuickWindowPrivate::translateTouchEvent()
+ QMutableEventPoint::from(firstPoint).setPosition(firstPoint.scenePosition());
+ // Send it through like a fresh press event, and let QQuickWindow
+ // (more specifically, QQuickWindowPrivate::deliverPressOrReleaseEvent)
+ // find the item or handler that should receive it, as usual.
+ QCoreApplication::sendEvent(window, event.data());
+ qCDebug(lcReplay) << "replay done";
+
+ // We're done with replay, go back to normal delivery behavior
replayingPressEvent = false;
wpriv->allowChildEventFiltering = true;
}
@@ -2372,47 +2445,53 @@ void QQuickFlickablePrivate::addPointerHandler(QQuickPointerHandler *h)
QQuickItemPrivate::get(contentItem)->addPointerHandler(h);
}
-/*!
- QQuickFlickable::filterMouseEvent checks filtered mouse events and potentially steals them.
+/*! \internal
+ QQuickFlickable::filterPointerEvent filters pointer events intercepted on the way
+ to the child \a receiver, and potentially steals the exclusive grab.
- This is how flickable takes over events from other items (\a receiver) that are on top of it.
- It filters their events and may take over (grab) the \a event.
- Return true if the mouse event will be stolen.
- \internal
+ This is how flickable takes over the handling of events from child items.
+
+ Returns true if the event will be stolen and should <em>not</em> be delivered to the \a receiver.
*/
-bool QQuickFlickable::filterMouseEvent(QQuickItem *receiver, QMouseEvent *event)
+bool QQuickFlickable::filterPointerEvent(QQuickItem *receiver, QPointerEvent *event)
{
+ if (!(QQuickWindowPrivate::isMouseEvent(event) ||
+ QQuickWindowPrivate::isTouchEvent(event) ||
+ QQuickWindowPrivate::isTabletEvent(event)))
+ return false; // don't filter hover events or wheel events, for example
Q_ASSERT_X(receiver != this, "", "Flickable received a filter event for itself");
+ qCDebug(lcFilter) << objectName() << "filtering" << event << "for" << receiver;
Q_D(QQuickFlickable);
- QPointF localPos = mapFromScene(event->scenePosition());
+ const auto &firstPoint = event->points().first();
+ QPointF localPos = mapFromScene(firstPoint.scenePosition());
bool receiverDisabled = receiver && !receiver->isEnabled();
bool stealThisEvent = d->stealMouse;
bool receiverKeepsGrab = receiver && (receiver->keepMouseGrab() || receiver->keepTouchGrab());
if ((stealThisEvent || contains(localPos)) && (!receiver || !receiverKeepsGrab || receiverDisabled)) {
- QScopedPointer<QMouseEvent> mouseEvent(QQuickWindowPrivate::cloneMouseEvent(event, &localPos));
- mouseEvent->setAccepted(false);
-
- switch (mouseEvent->type()) {
- case QEvent::MouseMove:
- d->handleMouseMoveEvent(mouseEvent.data());
+ QScopedPointer<QPointerEvent> localizedEvent(QQuickWindowPrivate::clonePointerEvent(event, localPos));
+ localizedEvent->setAccepted(false);
+ switch (firstPoint.state()) {
+ case QEventPoint::State::Updated:
+ d->handleMoveEvent(localizedEvent.data());
break;
- case QEvent::MouseButtonPress:
- d->handleMousePressEvent(mouseEvent.data());
+ case QEventPoint::State::Pressed:
+ d->handlePressEvent(localizedEvent.data());
d->captureDelayedPress(receiver, event);
stealThisEvent = d->stealMouse; // Update stealThisEvent in case changed by function call above
break;
- case QEvent::MouseButtonRelease:
- d->handleMouseReleaseEvent(mouseEvent.data());
+ case QEventPoint::State::Released:
+ d->handleReleaseEvent(localizedEvent.data());
stealThisEvent = d->stealMouse;
break;
- default:
+ case QEventPoint::State::Stationary:
+ case QEventPoint::State::Unknown:
break;
}
if ((receiver && stealThisEvent && !receiverKeepsGrab && receiver != this) || receiverDisabled) {
d->clearDelayedPress();
- grabMouse();
+ event->setExclusiveGrabber(firstPoint, this);
} else if (d->delayedPressEvent) {
- grabMouse();
+ event->setExclusiveGrabber(firstPoint, this);
}
const bool filtered = stealThisEvent || d->delayedPressEvent || receiverDisabled;
@@ -2424,7 +2503,7 @@ bool QQuickFlickable::filterMouseEvent(QQuickItem *receiver, QMouseEvent *event)
d->lastPosTime = -1;
returnToBounds();
}
- if (event->type() == QEvent::MouseButtonRelease || (receiverKeepsGrab && !receiverDisabled)) {
+ if (firstPoint.state() == QEventPoint::State::Released || (receiverKeepsGrab && !receiverDisabled)) {
// mouse released, or another item has claimed the grab
d->lastPosTime = -1;
d->clearDelayedPress();
@@ -2434,7 +2513,10 @@ bool QQuickFlickable::filterMouseEvent(QQuickItem *receiver, QMouseEvent *event)
return false;
}
-
+/*! \internal
+ Despite the name, this function filters all pointer events on their way to any child within.
+ Returns true if the event will be stolen and should <em>not</em> be delivered to the \a receiver.
+*/
bool QQuickFlickable::childMouseEventFilter(QQuickItem *i, QEvent *e)
{
Q_D(QQuickFlickable);
@@ -2444,19 +2526,12 @@ bool QQuickFlickable::childMouseEventFilter(QQuickItem *i, QEvent *e)
return QQuickItem::childMouseEventFilter(i, e);
}
- switch (e->type()) {
- case QEvent::MouseButtonPress:
- case QEvent::MouseMove:
- case QEvent::MouseButtonRelease:
- return filterMouseEvent(i, static_cast<QMouseEvent *>(e));
- case QEvent::UngrabMouse:
- if (d->window && d->window->mouseGrabberItem() && d->window->mouseGrabberItem() != this) {
- // The grab has been taken away from a child and given to some other item.
- mouseUngrabEvent();
- }
- break;
- default:
- break;
+ if (e->isPointerEvent()) {
+ return filterPointerEvent(i, static_cast<QPointerEvent *>(e));
+ } else if (e->type() == QEvent::UngrabMouse && d->window &&
+ d->window->mouseGrabberItem() && d->window->mouseGrabberItem() != this) {
+ // The grab has been taken away from a child and given to some other item.
+ mouseUngrabEvent();
}
return QQuickItem::childMouseEventFilter(i, e);
diff --git a/src/quick/items/qquickflickable_p.h b/src/quick/items/qquickflickable_p.h
index d0fea9d5c5..7a12f5287b 100644
--- a/src/quick/items/qquickflickable_p.h
+++ b/src/quick/items/qquickflickable_p.h
@@ -280,6 +280,7 @@ protected:
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
+ void touchEvent(QTouchEvent *event) override;
#if QT_CONFIG(wheelevent)
void wheelEvent(QWheelEvent *event) override;
#endif
@@ -305,7 +306,7 @@ protected:
virtual void viewportMoved(Qt::Orientations orient);
void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override;
void mouseUngrabEvent() override;
- bool filterMouseEvent(QQuickItem *receiver, QMouseEvent *event);
+ bool filterPointerEvent(QQuickItem *receiver, QPointerEvent *event);
bool xflick() const;
bool yflick() const;
diff --git a/src/quick/items/qquickflickable_p_p.h b/src/quick/items/qquickflickable_p_p.h
index 4d47943702..f9f5ce7628 100644
--- a/src/quick/items/qquickflickable_p_p.h
+++ b/src/quick/items/qquickflickable_p_p.h
@@ -188,7 +188,7 @@ public:
void updateBeginningEnd();
bool isInnermostPressDelay(QQuickItem *item) const;
- void captureDelayedPress(QQuickItem *item, QMouseEvent *event);
+ void captureDelayedPress(QQuickItem *item, QPointerEvent *event);
void clearDelayedPress();
void replayDelayedPress();
@@ -235,7 +235,7 @@ public:
qreal deceleration;
qreal maxVelocity;
qreal reportedVelocitySmoothing;
- QMouseEvent *delayedPressEvent;
+ QPointerEvent *delayedPressEvent;
QBasicTimer delayedPressTimer;
int pressDelay;
int fixupDuration;
@@ -259,9 +259,9 @@ public:
void viewportAxisMoved(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
QQuickTimeLineCallback::Callback fixupCallback);
- void handleMousePressEvent(QMouseEvent *);
- void handleMouseMoveEvent(QMouseEvent *);
- void handleMouseReleaseEvent(QMouseEvent *);
+ void handlePressEvent(QPointerEvent *);
+ void handleMoveEvent(QPointerEvent *);
+ void handleReleaseEvent(QPointerEvent *);
void maybeBeginDrag(qint64 currentTimestamp, const QPointF &pressPosn);
void drag(qint64 currentTimestamp, QEvent::Type eventType, const QPointF &localPos,
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index 547c825502..e71ae85c54 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -4198,13 +4198,28 @@ void QQuickItem::dropEvent(QDropEvent *event)
#endif // quick_draganddrop
/*!
- Reimplement this method to filter the mouse events that are received by
+ Reimplement this method to filter the pointer events that are received by
this item's children.
- This method will only be called if filtersChildMouseEvents() is true.
+ This method will only be called if filtersChildMouseEvents() is \c true.
- Return true if the specified \a event should not be passed onto the
- specified child \a item, and false otherwise.
+ Return \c true if the specified \a event should not be passed on to the
+ specified child \a item, and \c false otherwise.
+
+ \note Despite the name, this function filters all QPointerEvent instances
+ during delivery to all children (typically mouse, touch, and tablet
+ events). When overriding this function in a subclass, we suggest writing
+ generic event-handling code using only the accessors found in
+ QPointerEvent. Alternatively you can switch on \c event->type() and/or
+ \c event->device()->type() to handle different event types in different ways.
+
+ \note Filtering is just one way to share responsibility in case of gestural
+ ambiguity (for example on press, you don't know whether the user will tap
+ or drag). Another way is to call QPointerEvent::addPassiveGrabber() on
+ press, so as to non-exclusively monitor the progress of the QEventPoint.
+ In either case, the item or pointer handler that is monitoring can steal
+ the exclusive grab later on, when it becomes clear that the gesture fits
+ the pattern that it is expecting.
\sa setFiltersChildMouseEvents()
*/
@@ -7331,8 +7346,13 @@ void QQuickItem::setAcceptedMouseButtons(Qt::MouseButtons buttons)
}
/*!
- Returns whether mouse and touch events of this item's children should be filtered
- through this item.
+ Returns whether pointer events intended for this item's children should be
+ filtered through this item.
+
+ If both this item and a child item have acceptTouchEvents() \c true, then
+ when a touch interaction occurs, this item will filter the touch event.
+ But if either this item or the child cannot handle touch events,
+ childMouseEventFilter() will be called with a synthesized mouse event.
\sa setFiltersChildMouseEvents(), childMouseEventFilter()
*/
@@ -7343,11 +7363,11 @@ bool QQuickItem::filtersChildMouseEvents() const
}
/*!
- Sets whether mouse and touch events of this item's children should be filtered
- through this item.
+ Sets whether pointer events intended for this item's children should be
+ filtered through this item.
If \a filter is true, childMouseEventFilter() will be called when
- a mouse event is triggered for a child item.
+ a pointer event is triggered for a child item.
\sa filtersChildMouseEvents()
*/
@@ -7400,9 +7420,9 @@ void QQuickItem::setAcceptHoverEvents(bool enabled)
/*!
Returns whether touch events are accepted by this item.
- The default value is false.
+ The default value is \c false.
- If this is false, then the item will not receive any touch events through
+ If this is \c false, then the item will not receive any touch events through
the touchEvent() function.
\since 5.10
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 419ad5bb87..b283f56ab9 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -2038,17 +2038,30 @@ void QQuickWindowPrivate::deliverKeyEvent(QKeyEvent *e)
}
}
-// TODO can we return by value to avoid heap allocation?
-// QQuickFlickablePrivate::delayedPressEvent is a ptr so that it can be null;
-// but QMouseEvent::isValid() would be an alternative if we can write it
-QMouseEvent *QQuickWindowPrivate::cloneMouseEvent(QMouseEvent *event, QPointF *transformedLocalPos)
+/*! \internal
+ Make a copy of any type of QPointerEvent, and optionally localize it
+ by setting its first point's local position() if \a transformedLocalPos is given.
+
+ \note some subclasses of QSinglePointEvent, such as QWheelEvent, add extra storage.
+ This function doesn't yet support cloning all of those; it can be extended if needed.
+*/
+QPointerEvent *QQuickWindowPrivate::clonePointerEvent(QPointerEvent *event, std::optional<QPointF> transformedLocalPos)
{
- QMouseEvent *me = new QMouseEvent(*event);
- QMutableEventPoint &point = QMutableEventPoint::from(me->point(0));
+ QPointerEvent *ret = nullptr;
+ if (isMouseEvent(event)) {
+ ret = new QMouseEvent(*(static_cast<QMouseEvent *>(event)));
+ } else if (isTouchEvent(event)) {
+ ret = new QTouchEvent(*(static_cast<QTouchEvent *>(event)));
+ } else if (isTabletEvent(event)) {
+ ret = new QTabletEvent(*(static_cast<QTabletEvent *>(event)));
+ }
+ QMutableEventPoint &point = QMutableEventPoint::from(ret->point(0));
point.detach();
point.setTimestamp(event->timestamp());
- point.setPosition(transformedLocalPos ? *transformedLocalPos : event->position());
- return me;
+ if (transformedLocalPos)
+ point.setPosition(*transformedLocalPos);
+
+ return ret;
}
void QQuickWindowPrivate::deliverToPassiveGrabbers(const QVector<QPointer <QObject> > &passiveGrabbers,
@@ -2581,15 +2594,17 @@ void QQuickWindowPrivate::onGrabChanged(QObject *grabber, QPointingDevice::GrabT
if (!filtered)
item->mouseUngrabEvent();
}
- if (point.device()->type() == QInputDevice::DeviceType::TouchScreen && event) {
- bool allReleased = true;
- for (const auto &pt : event->points()) {
- if (pt.state() != QEventPoint::State::Released) {
- allReleased = false;
- break;
+ if (point.device()->type() == QInputDevice::DeviceType::TouchScreen) {
+ bool allReleasedOrCancelled = true;
+ if (transition == QPointingDevice::UngrabExclusive && event) {
+ for (const auto &pt : event->points()) {
+ if (pt.state() != QEventPoint::State::Released) {
+ allReleasedOrCancelled = false;
+ break;
+ }
}
}
- if (allReleased)
+ if (allReleasedOrCancelled)
item->touchUngrabEvent();
}
}
@@ -2834,6 +2849,12 @@ bool QQuickWindowPrivate::deliverPressOrReleaseEvent(QPointerEvent *event, bool
// nor to any item which already had a chance to filter.
if (skipDelivery.contains(item))
continue;
+
+ // sendFilteredPointerEvent() changed the QEventPoint::accepted() state,
+ // but per-point acceptance is opt-in during normal delivery to items.
+ for (int i = 0; i < event->pointCount(); ++i)
+ event->point(i).setAccepted(false);
+
deliverMatchingPointsToItem(item, false, event, handlersOnly);
if (event->allPointsAccepted())
handlersOnly = true;
@@ -2935,6 +2956,8 @@ void QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, bool isG
bool isPressOrRelease = pointerEvent->isBeginEvent() || pointerEvent->isEndEvent();
for (int i = 0; i < touchEvent.pointCount(); ++i) {
auto &point = QMutableEventPoint::from(touchEvent.point(i));
+ // legacy-style delivery: if the item doesn't reject the event, that means it handled ALL the points
+ point.setAccepted();
if (isPressOrRelease)
pointerEvent->setExclusiveGrabber(point, item);
}
@@ -3220,14 +3243,19 @@ bool QQuickWindowPrivate::sendFilteredPointerEventImpl(QPointerEvent *event, QQu
QTouchEvent filteringParentTouchEvent =
QQuickItemPrivate::get(receiver)->localizedTouchEvent(static_cast<QTouchEvent *>(event), true);
if (filteringParentTouchEvent.type() != QEvent::None) {
+ qCDebug(DBG_TOUCH) << "letting parent" << filteringParent << "filter for" << receiver << &filteringParentTouchEvent;
if (filteringParent->childMouseEventFilter(receiver, &filteringParentTouchEvent)) {
qCDebug(DBG_TOUCH) << "touch event intercepted by childMouseEventFilter of " << filteringParent;
skipDelivery.append(filteringParent);
for (auto point : filteringParentTouchEvent.points())
event->setExclusiveGrabber(point, filteringParent);
return true;
- }
- else if (Q_LIKELY(QCoreApplication::testAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents))) {
+ } else if (Q_LIKELY(QCoreApplication::testAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents) &&
+ (!acceptsTouchEvents || !filteringParent->acceptTouchEvents()))) {
+ qCDebug(DBG_TOUCH) << "touch event NOT intercepted by childMouseEventFilter of " << filteringParent
+ << "; accepts touch?" << filteringParent->acceptTouchEvents()
+ << "receiver accepts touch?" << acceptsTouchEvents
+ << "so, letting parent filter a synth-mouse event";
// filteringParent didn't filter the touch event. Give it a chance to filter a synthetic mouse event.
for (auto &tp : filteringParentTouchEvent.points()) {
QEvent::Type t;
@@ -3323,13 +3351,13 @@ bool QQuickWindowPrivate::dragOverThreshold(qreal d, Qt::Axis axis, QMouseEvent
return overThreshold;
}
-bool QQuickWindowPrivate::dragOverThreshold(qreal d, Qt::Axis axis, const QEventPoint *tp, int startDragThreshold)
+bool QQuickWindowPrivate::dragOverThreshold(qreal d, Qt::Axis axis, const QEventPoint &tp, int startDragThreshold)
{
QStyleHints *styleHints = qApp->styleHints();
bool overThreshold = qAbs(d) > (startDragThreshold >= 0 ? startDragThreshold : styleHints->startDragDistance());
const bool dragVelocityLimitAvailable = (styleHints->startDragVelocity() > 0);
if (!overThreshold && dragVelocityLimitAvailable) {
- qreal velocity = axis == Qt::XAxis ? tp->velocity().x() : tp->velocity().y();
+ qreal velocity = axis == Qt::XAxis ? tp.velocity().x() : tp.velocity().y();
overThreshold |= qAbs(velocity) > styleHints->startDragVelocity();
}
return overThreshold;
diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h
index 62b16513c9..2928c99023 100644
--- a/src/quick/items/qquickwindow_p.h
+++ b/src/quick/items/qquickwindow_p.h
@@ -172,7 +172,7 @@ public:
void translateTouchEvent(QTouchEvent *touchEvent);
void removeGrabber(QQuickItem *grabber, bool mouse = true, bool touch = true, bool cancel = false);
void onGrabChanged(QObject *grabber, QPointingDevice::GrabTransition transition, const QPointerEvent *event, const QEventPoint &point);
- static QMouseEvent *cloneMouseEvent(QMouseEvent *event, QPointF *transformedLocalPos = nullptr);
+ static QPointerEvent *clonePointerEvent(QPointerEvent *event, std::optional<QPointF> transformedLocalPos = std::nullopt);
void deliverToPassiveGrabbers(const QVector<QPointer<QObject> > &passiveGrabbers, QPointerEvent *pointerEvent);
bool sendFilteredMouseEvent(QEvent *event, QQuickItem *receiver, QQuickItem *filteringParent);
bool sendFilteredPointerEvent(QPointerEvent *event, QQuickItem *receiver, QQuickItem *filteringParent = nullptr);
@@ -188,7 +188,7 @@ public:
// utility functions that used to be in QQuickPointerEvent et al.
bool allUpdatedPointsAccepted(const QPointerEvent *ev);
- void localizePointerEvent(QPointerEvent *ev, const QQuickItem *dest);
+ static void localizePointerEvent(QPointerEvent *ev, const QQuickItem *dest);
QList<QObject *> exclusiveGrabbers(QPointerEvent *ev);
static bool isMouseEvent(const QPointerEvent *ev);
static bool isTouchEvent(const QPointerEvent *ev);
@@ -324,7 +324,11 @@ public:
static bool dragOverThreshold(qreal d, Qt::Axis axis, QMouseEvent *event, int startDragThreshold = -1);
- static bool dragOverThreshold(qreal d, Qt::Axis axis, const QEventPoint *tp, int startDragThreshold = -1);
+ static bool dragOverThreshold(qreal d, Qt::Axis axis, const QEventPoint &tp, int startDragThreshold = -1);
+
+ // currently in use in Controls 2; TODO remove
+ static bool dragOverThreshold(qreal d, Qt::Axis axis, const QEventPoint *tp, int startDragThreshold = -1)
+ { return dragOverThreshold(d, axis, *tp, startDragThreshold); }
static bool dragOverThreshold(QVector2D delta);
diff --git a/tests/auto/qmltest/events/tst_touch.qml b/tests/auto/qmltest/events/tst_touch.qml
index ab54eb9e09..e6b8ac755e 100644
--- a/tests/auto/qmltest/events/tst_touch.qml
+++ b/tests/auto/qmltest/events/tst_touch.qml
@@ -160,7 +160,7 @@ MultiPointTouchArea {
sequence.stationary(first, null, 0, 0);
sequence.press(second, null, 1, 0);
sequence.commit();
- compare(touchUpdatedSpy.count, 3);
+ compare(touchUpdatedSpy.count, 2);
touchPoints = touchUpdatedSpy.signalArguments[1][0];
compare(touchPoints.length, 2);
verify(comparePoint(touchPoints[0], first, 0, 0));
@@ -169,15 +169,15 @@ MultiPointTouchArea {
sequence.release(first, null, 0, 0);
sequence.move(second, null, 1, 1);
sequence.commit();
- compare(touchUpdatedSpy.count, 4);
- touchPoints = touchUpdatedSpy.signalArguments[3][0];
+ compare(touchUpdatedSpy.count, 3);
+ touchPoints = touchUpdatedSpy.signalArguments[2][0];
compare(touchPoints.length, 1);
verify(comparePoint(touchPoints[0], second, 1, 1));
sequence.release(second, null, 0, 1);
sequence.commit();
- compare(touchUpdatedSpy.count, 5);
- touchPoints = touchUpdatedSpy.signalArguments[4][0];
+ compare(touchUpdatedSpy.count, 4);
+ touchPoints = touchUpdatedSpy.signalArguments[3][0];
compare(touchPoints.length, 0);
}
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnList.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnList.qml
index bb39c2267c..b7f4662476 100644
--- a/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnList.qml
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnList.qml
@@ -62,7 +62,7 @@ ListView {
}
DragHandler {
id: delegateDrag
- objectName: "delegateDrag"
+ objectName: "delegateDrag " + index
}
}
diff --git a/tests/auto/quick/qquickflickable/data/nestedStopAtBounds.qml b/tests/auto/quick/qquickflickable/data/nestedStopAtBounds.qml
index f2d25b292f..bedfe35470 100644
--- a/tests/auto/quick/qquickflickable/data/nestedStopAtBounds.qml
+++ b/tests/auto/quick/qquickflickable/data/nestedStopAtBounds.qml
@@ -10,6 +10,7 @@ Flickable {
contentWidth: 500
contentHeight: 500
flickableDirection: inner.flickableDirection
+ Text { x: 100; y: 80; text: "dragging: outer " + outer.dragging + " inner " + inner.dragging }
// faster rebound to speed up test runs
rebound: Transition {
@@ -28,6 +29,10 @@ Flickable {
color: "yellow"
objectName: "yellowRect"
+ Text {
+ text: "...."
+ y: 250
+ }
Flickable {
id: inner
diff --git a/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp b/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
index 70f5460c44..bfe09acca9 100644
--- a/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
+++ b/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
@@ -121,7 +121,7 @@ void tst_QQuickMultiPointTouchArea::signalTest()
QQuickTouchUtils::flush(window.data());
QCOMPARE(area->property("touchPointPressCount").toInt(), 1);
- QCOMPARE(area->property("touchPointUpdateCount").toInt(), 0);
+ QCOMPARE(area->property("touchPointUpdateCount").toInt(), 2);
QCOMPARE(area->property("touchPointReleaseCount").toInt(), 0);
QCOMPARE(area->property("touchCount").toInt(), 3);
QMetaObject::invokeMethod(area, "clearCounts");
@@ -132,7 +132,7 @@ void tst_QQuickMultiPointTouchArea::signalTest()
QQuickTouchUtils::flush(window.data());
QCOMPARE(area->property("touchPointPressCount").toInt(), 0);
- QCOMPARE(area->property("touchPointUpdateCount").toInt(), 2);
+ QCOMPARE(area->property("touchPointUpdateCount").toInt(), 3);
QCOMPARE(area->property("touchPointReleaseCount").toInt(), 0);
QCOMPARE(area->property("touchCount").toInt(), 3);
QMetaObject::invokeMethod(area, "clearCounts");
@@ -677,8 +677,10 @@ void tst_QQuickMultiPointTouchArea::inFlickable()
i, p1.x(), p1.y(), p2.x(), p2.y(), flickable->contentY());
}
+ QEXPECT_FAIL("", "currently flickable does grab the actual mouse", Continue);
QCOMPARE(flickable->contentY(), qreal(0));
QCOMPARE(point11->pressed(), true);
+ QEXPECT_FAIL("", "currently flickable does grab the actual mouse", Continue);
QCOMPARE(point12->pressed(), true);
QTest::touchEvent(window.data(), device).release(0, p1).release(1, p2);
@@ -783,6 +785,7 @@ void tst_QQuickMultiPointTouchArea::inFlickableWithPressDelay() // QTBUG-78818
QQuickMultiPointTouchArea *mpta = window->rootObject()->findChild<QQuickMultiPointTouchArea*>();
QVERIFY(mpta != nullptr);
+ mpta->setMouseEnabled(false); // don't depend on synth-mouse
mpta->setMinimumTouchPoints(1);
QQuickTouchPoint *point11 = window->rootObject()->findChild<QQuickTouchPoint*>("point1");
QPoint p1(20,100);
diff --git a/tests/auto/quick/touchmouse/tst_touchmouse.cpp b/tests/auto/quick/touchmouse/tst_touchmouse.cpp
index ac6b579d03..d06f1337c4 100644
--- a/tests/auto/quick/touchmouse/tst_touchmouse.cpp
+++ b/tests/auto/quick/touchmouse/tst_touchmouse.cpp
@@ -251,11 +251,12 @@ private slots:
protected:
bool eventFilter(QObject *, QEvent *event)
{
- if (event->type() == QEvent::MouseButtonPress ||
- event->type() == QEvent::MouseMove ||
- event->type() == QEvent::MouseButtonRelease) {
- QMouseEvent *me = static_cast<QMouseEvent*>(event);
- filteredEventList.append(Event(me->type(), me->position().toPoint(), me->globalPosition().toPoint()));
+ if (event->isPointerEvent()) {
+ qCDebug(lcTests) << "window filtering" << event;
+ QPointerEvent *pe = static_cast<QPointerEvent*>(event);
+ filteredEventList.append(Event(pe->type(),
+ pe->points().first().position().toPoint(),
+ pe->points().first().globalPosition().toPoint()));
}
return false;
}
@@ -773,10 +774,7 @@ void tst_TouchMouse::buttonOnDelayedPressFlickable()
// - eventItem2 y: 300, height 100
QFETCH(bool, scrollBeforeDelayIsOver);
QFETCH(bool, releaseBeforeDelayIsOver);
-
-#ifdef Q_OS_MACOS
- QSKIP("Deadlocks or crashes due to events changes in qtbase");
-#endif
+ const int threshold = qApp->styleHints()->startDragDistance();
qApp->setAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents, true);
filteredEventList.clear();
@@ -799,6 +797,7 @@ void tst_TouchMouse::buttonOnDelayedPressFlickable()
// should a mouse area button be clickable on top of flickable? yes :)
EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
QVERIFY(eventItem1);
+ eventItem1->setAcceptTouchEvents(true); // because it was that way by default in Qt 5
eventItem1->setAcceptedMouseButtons(Qt::LeftButton);
eventItem1->acceptMouse = true;
@@ -815,7 +814,6 @@ void tst_TouchMouse::buttonOnDelayedPressFlickable()
// touch press
QPoint p1 = QPoint(10, 110);
- QPoint pEnd = p1;
QTest::touchEvent(window.data(), device).press(0, p1, window.data());
QQuickTouchUtils::flush(window.data());
@@ -824,68 +822,66 @@ void tst_TouchMouse::buttonOnDelayedPressFlickable()
QCOMPARE(eventItem1->eventList.size(), 0);
} else {
// wait until the button sees the press
- QTRY_COMPARE(eventItem1->eventList.size(), 1);
- QCOMPARE(eventItem1->eventList.at(0).type, QEvent::MouseButtonPress);
- QCOMPARE(filteredEventList.count(), 1);
+ qCDebug(lcTests) << "expected delivered events: press(touch), press(mouse)" << eventItem1->eventList;
+ QTRY_COMPARE(eventItem1->eventList.size(), 2);
+ QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
+ QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress);
+ QCOMPARE(filteredEventList.count(), 2); // actual touch begin and replayed touch begin
}
if (!releaseBeforeDelayIsOver) {
// move the touchpoint: try to flick
- p1 += QPoint(0, -10);
- QPoint p2 = p1 + QPoint(0, -10);
- pEnd = p2 + QPoint(0, -10);
- QQuickTouchUtils::flush(window.data());
- QTest::touchEvent(window.data(), device).move(0, p1, window.data());
- QQuickTouchUtils::flush(window.data());
- QTest::touchEvent(window.data(), device).move(0, p2, window.data());
- QQuickTouchUtils::flush(window.data());
- QTest::touchEvent(window.data(), device).move(0, pEnd, window.data());
- QQuickTouchUtils::flush(window.data());
+ for (int i = 0; i < 3; ++i) {
+ p1 += QPoint(0, -threshold);
+ QTest::touchEvent(window.data(), device).move(0, p1, window.data());
+ QQuickTouchUtils::flush(window.data());
+ }
QTRY_VERIFY(flickable->isMovingVertically());
if (scrollBeforeDelayIsOver) {
QCOMPARE(eventItem1->eventList.size(), 0);
- QCOMPARE(filteredEventList.count(), 0);
+ qCDebug(lcTests) << "expected filtered events: 1 TouchBegin and 3 TouchUpdate" << filteredEventList;
+ QCOMPARE(filteredEventList.count(), 4);
} else {
// see at least press, move and ungrab
QTRY_VERIFY(eventItem1->eventList.size() > 2);
- QCOMPARE(eventItem1->eventList.at(0).type, QEvent::MouseButtonPress);
+ QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
QCOMPARE(eventItem1->eventList.last().type, QEvent::UngrabMouse);
- QCOMPARE(filteredEventList.count(), 1);
+ qCDebug(lcTests) << "expected filtered events: 2 TouchBegin and 3 TouchUpdate" << filteredEventList;
+ QCOMPARE(filteredEventList.count(), 5);
}
- // flickable should have the mouse grab, and have moved the itemForTouchPointId
- // for the touchMouseId to the new grabber.
+ // flickable should have the touchpoint grab: it no longer relies on synth-mouse
QCOMPARE(grabMonitor.exclusiveGrabber, flickable);
- QVERIFY(windowPriv->touchMouseId != -1);
auto devPriv = QPointingDevicePrivate::get(device);
QCOMPARE(devPriv->pointById(0)->exclusiveGrabber, flickable);
}
- QTest::touchEvent(window.data(), device).release(0, pEnd, window.data());
+ QTest::touchEvent(window.data(), device).release(0, p1, window.data());
QQuickTouchUtils::flush(window.data());
if (releaseBeforeDelayIsOver) {
// when the touchpoint was released, the child saw the delayed press and the release in sequence
- qCDebug(lcTests) << "expected delivered events: press, release, ungrab" << eventItem1->eventList;
- qCDebug(lcTests) << "expected filtered events: delayed press, release" << filteredEventList;
- QSKIP("QTBUG-85607");
- QTRY_COMPARE(eventItem1->eventList.size(), 3);
- QCOMPARE(eventItem1->eventList.at(0).type, QEvent::MouseButtonPress);
- QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonRelease);
+ qCDebug(lcTests) << "expected delivered events: press(touch), press(mouse), release(touch), release(mouse), ungrab" << eventItem1->eventList;
+ qCDebug(lcTests) << "expected filtered events: delayed press, release (touch)" << filteredEventList;
+ QTRY_COMPARE(eventItem1->eventList.size(), 5);
+ QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress);
+ QCOMPARE(eventItem1->eventList.at(3).type, QEvent::MouseButtonRelease);
QCOMPARE(eventItem1->eventList.last().type, QEvent::UngrabMouse);
// QQuickWindow filters the delayed press and release
- QCOMPARE(filteredEventList.count(), 2);
- QCOMPARE(filteredEventList.at(0).type, QEvent::MouseButtonPress);
- QCOMPARE(filteredEventList.at(1).type, QEvent::MouseButtonRelease);
+ QCOMPARE(filteredEventList.count(), 4);
+ QCOMPARE(filteredEventList.at(filteredEventList.count() - 2).type, QEvent::TouchBegin);
+ QCOMPARE(filteredEventList.last().type, QEvent::TouchEnd);
} else {
- // QQuickWindow filters the delayed press if there was one; otherwise nothing
+ // QQuickWindow filters the delayed press if there was one
if (scrollBeforeDelayIsOver) {
- QCOMPARE(filteredEventList.count(), 0);
+ qCDebug(lcTests) << "expected filtered events: 1 TouchBegin, 3 TouchUpdate, 1 TouchEnd" << filteredEventList;
+ QCOMPARE(filteredEventList.count(), 5);
} else {
- qCDebug(lcTests) << "expected filtered event: delayed press" << filteredEventList;
- QCOMPARE(filteredEventList.count(), 1);
- QCOMPARE(filteredEventList.at(0).type, QEvent::MouseButtonPress);
+ qCDebug(lcTests) << "expected filtered events: 2 TouchBegin, 3 TouchUpdate, 1 TouchEnd" << filteredEventList;
+ QCOMPARE(filteredEventList.count(), 6);
+ QCOMPARE(filteredEventList.at(0).type, QEvent::TouchBegin);
+ QCOMPARE(filteredEventList.last().type, QEvent::TouchEnd);
}
}
}