aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn Rutledge <shawn.rutledge@qt.io>2020-07-23 13:56:26 +0200
committerShawn Rutledge <shawn.rutledge@qt.io>2020-09-18 20:56:25 +0200
commita97759a336c597327cb82eebc9f45c793aec32c9 (patch)
tree632bbee8568d38af56974e02df5810afcf48aedc
parent39f4d687fc37f48cbc181f42797c42be91b4a345 (diff)
Remove QQuickPointerEvent etc.; deliver QPointerEvents directly
QEventPoint does not have an accessor to get the QPointerEvent that it came from, because that's inconsistent with the idea that QPointerEvent instances are temporary, stack-allocated and movable (the pointer would often be wrong or null, therefore could not be relied upon). So most functions that worked directly with QQuickEventPoint before (which fortunately are still private API) now need to receive the QPointerEvent too, which we choose to pass by pointer. QEventPoint is always passed by reference (const where possible) to be consistent with functions in QPointerEvent that take QEventPoint by reference. QEventPoint::velocity() should be always in scene coordinates now, which saves us the trouble of transforming it to each item's coordinate system during delivery, but means that it will need to be done in handlers or applications sometimes. If we were going to transform it, it would be important to also store the sceneVelocity separately in QEventPoint so that the transformation could be done repeatedly for different items. Task-number: QTBUG-72173 Change-Id: I7ee164d2e6893c4e407fb7d579c75aa32843933a Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
-rw-r--r--src/quick/handlers/qquickdraghandler.cpp29
-rw-r--r--src/quick/handlers/qquickdraghandler_p.h4
-rw-r--r--src/quick/handlers/qquickhandlerpoint.cpp54
-rw-r--r--src/quick/handlers/qquickhandlerpoint_p.h2
-rw-r--r--src/quick/handlers/qquickhoverhandler.cpp20
-rw-r--r--src/quick/handlers/qquickhoverhandler_p.h4
-rw-r--r--src/quick/handlers/qquickmultipointhandler.cpp66
-rw-r--r--src/quick/handlers/qquickmultipointhandler_p.h16
-rw-r--r--src/quick/handlers/qquickpinchhandler.cpp53
-rw-r--r--src/quick/handlers/qquickpinchhandler_p.h4
-rw-r--r--src/quick/handlers/qquickpointerdevicehandler.cpp11
-rw-r--r--src/quick/handlers/qquickpointerdevicehandler_p.h2
-rw-r--r--src/quick/handlers/qquickpointerhandler.cpp150
-rw-r--r--src/quick/handlers/qquickpointerhandler_p.h36
-rw-r--r--src/quick/handlers/qquickpointerhandler_p_p.h6
-rw-r--r--src/quick/handlers/qquickpointhandler.cpp29
-rw-r--r--src/quick/handlers/qquickpointhandler_p.h4
-rw-r--r--src/quick/handlers/qquicksinglepointhandler.cpp76
-rw-r--r--src/quick/handlers/qquicksinglepointhandler_p.h12
-rw-r--r--src/quick/handlers/qquicktaphandler.cpp76
-rw-r--r--src/quick/handlers/qquicktaphandler_p.h15
-rw-r--r--src/quick/handlers/qquickwheelhandler.cpp45
-rw-r--r--src/quick/handlers/qquickwheelhandler_p.h6
-rw-r--r--src/quick/items/qquickevents.cpp1636
-rw-r--r--src/quick/items/qquickevents_p_p.h448
-rw-r--r--src/quick/items/qquickflickable.cpp14
-rw-r--r--src/quick/items/qquickitem.cpp165
-rw-r--r--src/quick/items/qquickitem.h2
-rw-r--r--src/quick/items/qquickitem_p.h5
-rw-r--r--src/quick/items/qquickmultipointtoucharea.cpp33
-rw-r--r--src/quick/items/qquickmultipointtoucharea_p.h2
-rw-r--r--src/quick/items/qquickpincharea.cpp16
-rw-r--r--src/quick/items/qquickwindow.cpp1004
-rw-r--r--src/quick/items/qquickwindow_p.h55
-rw-r--r--tests/auto/quick/pointerhandlers/mousearea_interop/tst_mousearea_interop.cpp14
-rw-r--r--tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp53
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp18
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp97
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp6
-rw-r--r--tests/auto/quick/qquickflickable/data/nestedPressDelay.qml1
-rw-r--r--tests/auto/quick/qquickflickable/tst_qquickflickable.cpp11
-rw-r--r--tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp16
-rw-r--r--tests/auto/quick/qquickwindow/tst_qquickwindow.cpp112
-rw-r--r--tests/auto/quick/touchmouse/tst_touchmouse.cpp124
-rw-r--r--tests/manual/pointer/inputinspector.cpp42
-rw-r--r--tests/manual/pointer/inputinspector.h4
-rw-r--r--tests/manual/pointer/singlePointHandlerProperties.qml2
-rw-r--r--tests/manual/pointer/tapHandler.qml2
48 files changed, 1243 insertions, 3359 deletions
diff --git a/src/quick/handlers/qquickdraghandler.cpp b/src/quick/handlers/qquickdraghandler.cpp
index 492897b68b..0794b86b11 100644
--- a/src/quick/handlers/qquickdraghandler.cpp
+++ b/src/quick/handlers/qquickdraghandler.cpp
@@ -110,10 +110,10 @@ QPointF QQuickDragHandler::targetCentroidPosition()
return pos;
}
-void QQuickDragHandler::onGrabChanged(QQuickPointerHandler *grabber, QQuickEventPoint::GrabTransition transition, QQuickEventPoint *point)
+void QQuickDragHandler::onGrabChanged(QQuickPointerHandler *grabber, QPointingDevice::GrabTransition transition, QPointerEvent *event, QEventPoint &point)
{
- QQuickMultiPointHandler::onGrabChanged(grabber, transition, point);
- if (grabber == this && transition == QQuickEventPoint::GrabExclusive && target()) {
+ QQuickMultiPointHandler::onGrabChanged(grabber, transition, event, point);
+ if (grabber == this && transition == QPointingDevice::GrabExclusive && target()) {
// In case the grab got handed over from another grabber, we might not get the Press.
auto isDescendant = [](QQuickItem *parent, QQuickItem *target) {
@@ -162,7 +162,7 @@ void QQuickDragHandler::onActiveChanged()
QQuickMultiPointHandler::onActiveChanged();
if (active()) {
if (auto parent = parentItem()) {
- if (currentEvent()->asPointerTouchEvent())
+ if (QQuickWindowPrivate::isTouchEvent(currentEvent()))
parent->setKeepTouchGrab(true);
// tablet and mouse are treated the same by Item's legacy event handling, and
// touch becomes synth-mouse for Flickable, so we need to prevent stealing
@@ -179,7 +179,7 @@ void QQuickDragHandler::onActiveChanged()
}
}
-void QQuickDragHandler::handlePointerEventImpl(QQuickPointerEvent *event)
+void QQuickDragHandler::handlePointerEventImpl(QPointerEvent *event)
{
QQuickMultiPointHandler::handlePointerEventImpl(event);
event->setAccepted(true);
@@ -199,18 +199,19 @@ void QQuickDragHandler::handlePointerEventImpl(QQuickPointerEvent *event)
// and in approximately the same direction
qreal minAngle = 361;
qreal maxAngle = -361;
- bool allOverThreshold = !event->isReleaseEvent();
- QVector <QQuickEventPoint *> chosenPoints;
+ bool allOverThreshold = !event->isEndEvent();
+ QVector<QEventPoint> chosenPoints;
- if (event->isPressEvent())
+ if (event->isBeginEvent())
m_pressedInsideTarget = target() && currentPoints().count() > 0;
for (const QQuickHandlerPoint &p : currentPoints()) {
if (!allOverThreshold)
break;
- QQuickEventPoint *point = event->pointById(p.id());
- chosenPoints << point;
- setPassiveGrab(point);
+ auto point = event->pointById(p.id());
+ Q_ASSERT(point);
+ chosenPoints << *point;
+ setPassiveGrab(event, *point);
// Calculate drag delta, taking into account the axis enabled constraint
// i.e. if xAxis is not enabled, then ignore the horizontal component of the actual movement
QVector2D accumulatedDragDelta = QVector2D(point->scenePosition() - point->scenePressPosition());
@@ -237,7 +238,7 @@ void QQuickDragHandler::handlePointerEventImpl(QQuickPointerEvent *event)
if (allOverThreshold && !overThreshold)
allOverThreshold = false;
- if (event->isPressEvent()) {
+ if (event->isBeginEvent()) {
// m_pressedInsideTarget should stay true iff ALL points in which DragHandler is interested
// have been pressed inside the target() Item. (E.g. in a Slider the parent might be the
// whole control while the target is just the knob.)
@@ -250,7 +251,7 @@ void QQuickDragHandler::handlePointerEventImpl(QQuickPointerEvent *event)
// (That affects behavior for mouse but not for touch, because Flickable only handles mouse.)
// So we have to compensate by accepting the event here to avoid any parent Flickable from
// getting the event via direct delivery and grabbing too soon.
- point->setAccepted(event->asPointerMouseEvent()); // stop propagation iff it's a mouse event
+ point->setAccepted(QQuickWindowPrivate::isMouseEvent(event)); // stop propagation iff it's a mouse event
}
}
if (allOverThreshold) {
@@ -258,7 +259,7 @@ void QQuickDragHandler::handlePointerEventImpl(QQuickPointerEvent *event)
if (angleDiff > 180)
angleDiff = 360 - angleDiff;
qCDebug(lcDragHandler) << "angle min" << minAngle << "max" << maxAngle << "range" << angleDiff;
- if (angleDiff < DragAngleToleranceDegrees && grabPoints(chosenPoints))
+ if (angleDiff < DragAngleToleranceDegrees && grabPoints(event, chosenPoints))
setActive(true);
}
}
diff --git a/src/quick/handlers/qquickdraghandler_p.h b/src/quick/handlers/qquickdraghandler_p.h
index 1315f79114..c1ff108e13 100644
--- a/src/quick/handlers/qquickdraghandler_p.h
+++ b/src/quick/handlers/qquickdraghandler_p.h
@@ -77,7 +77,7 @@ public:
explicit QQuickDragHandler(QQuickItem *parent = nullptr);
- void handlePointerEventImpl(QQuickPointerEvent *event) override;
+ void handlePointerEventImpl(QPointerEvent *event) override;
QQuickDragAxis *xAxis() { return &m_xAxis; }
QQuickDragAxis *yAxis() { return &m_yAxis; }
@@ -95,7 +95,7 @@ Q_SIGNALS:
protected:
void onActiveChanged() override;
- void onGrabChanged(QQuickPointerHandler *grabber, QQuickEventPoint::GrabTransition transition, QQuickEventPoint *point) override;
+ void onGrabChanged(QQuickPointerHandler *grabber, QPointingDevice::GrabTransition transition, QPointerEvent *event, QEventPoint &point) override;
private:
void ungrab();
diff --git a/src/quick/handlers/qquickhandlerpoint.cpp b/src/quick/handlers/qquickhandlerpoint.cpp
index 2990215719..3cd1bccbfc 100644
--- a/src/quick/handlers/qquickhandlerpoint.cpp
+++ b/src/quick/handlers/qquickhandlerpoint.cpp
@@ -49,7 +49,7 @@ Q_DECLARE_LOGGING_CATEGORY(DBG_TOUCH_TARGET)
\inqmlmodule QtQuick
\brief An event point.
- A QML representation of a QQuickEventPoint.
+ A QML representation of a QEventPoint.
It's possible to make bindings to properties of a handler's current
\l {SinglePointHandler::point}{point} or
@@ -98,46 +98,44 @@ void QQuickHandlerPoint::reset()
m_pressedModifiers = Qt::NoModifier;
}
-void QQuickHandlerPoint::reset(const QQuickEventPoint *point)
+void QQuickHandlerPoint::reset(const QPointerEvent *event, const QEventPoint &point)
{
- m_id = point->pointId();
- m_device = point->pointerEvent()->device();
- const QQuickPointerEvent *event = point->pointerEvent();
- switch (point->state()) {
- case QQuickEventPoint::Pressed:
- m_pressPosition = point->position();
- m_scenePressPosition = point->scenePosition();
- m_pressedButtons = event->buttons();
+ m_id = point.id();
+ m_device = event->pointingDevice();
+ switch (point.state()) {
+ case QEventPoint::Pressed:
+ m_pressPosition = point.position();
+ m_scenePressPosition = point.scenePosition();
break;
default:
break;
}
- m_scenePressPosition = point->scenePressPosition();
- m_pressedButtons = event->buttons();
+ const bool isTouch = QQuickWindowPrivate::isTouchEvent(event);
+ if (!isTouch)
+ m_pressedButtons = static_cast<const QSinglePointEvent *>(event)->buttons();
m_pressedModifiers = event->modifiers();
- if (event->asPointerTouchEvent()) {
- const QQuickEventTouchPoint *tp = static_cast<const QQuickEventTouchPoint *>(point);
- m_uniqueId = tp->uniqueId();
- m_rotation = tp->rotation();
- m_pressure = tp->pressure();
- m_ellipseDiameters = tp->ellipseDiameters();
+ if (isTouch) {
+ m_uniqueId = point.uniqueId();
+ m_rotation = point.rotation();
+ m_pressure = point.pressure();
+ m_ellipseDiameters = point.ellipseDiameters();
#if QT_CONFIG(tabletevent)
- } else if (event->asPointerTabletEvent()) {
- m_uniqueId = event->device()->uniqueId();
- m_rotation = static_cast<const QQuickEventTabletPoint *>(point)->rotation();
- m_pressure = static_cast<const QQuickEventTabletPoint *>(point)->pressure();
+ } else if (QQuickWindowPrivate::isTabletEvent(event)) {
+ m_uniqueId = event->pointingDevice()->uniqueId();
+ m_rotation = point.rotation();
+ m_pressure = point.pressure();
m_ellipseDiameters = QSizeF();
#endif
} else {
- m_uniqueId = event->device()->uniqueId();
+ m_uniqueId = event->pointingDevice()->uniqueId();
m_rotation = 0;
- m_pressure = event->buttons() ? 1 : 0;
+ m_pressure = m_pressedButtons ? 1 : 0;
m_ellipseDiameters = QSizeF();
}
- m_position = point->position();
- m_scenePosition = point->scenePosition();
- if (point->state() == QQuickEventPoint::Updated)
- m_velocity = point->velocity();
+ m_position = point.position();
+ m_scenePosition = point.scenePosition();
+ if (point.state() == QEventPoint::Updated)
+ m_velocity = point.velocity();
}
void QQuickHandlerPoint::reset(const QVector<QQuickHandlerPoint> &points)
diff --git a/src/quick/handlers/qquickhandlerpoint_p.h b/src/quick/handlers/qquickhandlerpoint_p.h
index fd3b365e32..8e175281f2 100644
--- a/src/quick/handlers/qquickhandlerpoint_p.h
+++ b/src/quick/handlers/qquickhandlerpoint_p.h
@@ -96,7 +96,7 @@ public:
void localize(QQuickItem *item);
void reset();
- void reset(const QQuickEventPoint *point);
+ void reset(const QPointerEvent *event, const QEventPoint &point);
void reset(const QVector<QQuickHandlerPoint> &points);
private:
diff --git a/src/quick/handlers/qquickhoverhandler.cpp b/src/quick/handlers/qquickhoverhandler.cpp
index 76e5bc0605..cdb9b2578c 100644
--- a/src/quick/handlers/qquickhoverhandler.cpp
+++ b/src/quick/handlers/qquickhoverhandler.cpp
@@ -89,12 +89,12 @@ void QQuickHoverHandler::componentComplete()
QQuickItemPrivate::get(parentItem())->setHasHoverInChild(true);
}
-bool QQuickHoverHandler::wantsPointerEvent(QQuickPointerEvent *event)
+bool QQuickHoverHandler::wantsPointerEvent(QPointerEvent *event)
{
- QQuickEventPoint *point = event->point(0);
- if (QQuickPointerDeviceHandler::wantsPointerEvent(event) && wantsEventPoint(point) && parentContains(point)) {
+ auto &point = event->point(0);
+ if (QQuickPointerDeviceHandler::wantsPointerEvent(event) && wantsEventPoint(event, point) && parentContains(point)) {
// assume this is a mouse or tablet event, so there's only one point
- setPointId(point->pointId());
+ setPointId(point.id());
return true;
}
@@ -106,22 +106,22 @@ bool QQuickHoverHandler::wantsPointerEvent(QQuickPointerEvent *event)
// the hovered property to transition to false prematurely.
// If a QQuickPointerTabletEvent caused the hovered property to become true,
// then only another QQuickPointerTabletEvent can make it become false.
- if (!(m_hoveredTablet && event->asPointerMouseEvent()))
+ if (!(m_hoveredTablet && QQuickWindowPrivate::isMouseEvent(event)))
setHovered(false);
return false;
}
-void QQuickHoverHandler::handleEventPoint(QQuickEventPoint *point)
+void QQuickHoverHandler::handleEventPoint(QPointerEvent *ev, QEventPoint &point)
{
bool hovered = true;
- if (point->state() == QQuickEventPoint::Released &&
- point->pointerEvent()->device()->pointerType() == QPointingDevice::PointerType::Finger)
+ if (point.state() == QEventPoint::Released &&
+ ev->pointingDevice()->pointerType() == QPointingDevice::PointerType::Finger)
hovered = false;
- else if (point->pointerEvent()->asPointerTabletEvent())
+ else if (QQuickWindowPrivate::isTabletEvent(ev))
m_hoveredTablet = true;
setHovered(hovered);
- setPassiveGrab(point);
+ setPassiveGrab(ev, point);
}
/*!
diff --git a/src/quick/handlers/qquickhoverhandler_p.h b/src/quick/handlers/qquickhoverhandler_p.h
index 4b9d0a9f39..fe9a3bcde3 100644
--- a/src/quick/handlers/qquickhoverhandler_p.h
+++ b/src/quick/handlers/qquickhoverhandler_p.h
@@ -76,8 +76,8 @@ Q_SIGNALS:
protected:
void componentComplete() override;
- bool wantsPointerEvent(QQuickPointerEvent *event) override;
- void handleEventPoint(QQuickEventPoint *point) override;
+ bool wantsPointerEvent(QPointerEvent *event) override;
+ void handleEventPoint(QPointerEvent *ev, QEventPoint &point) override;
private:
void setHovered(bool hovered);
diff --git a/src/quick/handlers/qquickmultipointhandler.cpp b/src/quick/handlers/qquickmultipointhandler.cpp
index f404788de4..97cb958aa6 100644
--- a/src/quick/handlers/qquickmultipointhandler.cpp
+++ b/src/quick/handlers/qquickmultipointhandler.cpp
@@ -64,18 +64,18 @@ QQuickMultiPointHandler::QQuickMultiPointHandler(QQuickItem *parent, int minimum
{
}
-bool QQuickMultiPointHandler::wantsPointerEvent(QQuickPointerEvent *event)
+bool QQuickMultiPointHandler::wantsPointerEvent(QPointerEvent *event)
{
Q_D(QQuickMultiPointHandler);
if (!QQuickPointerDeviceHandler::wantsPointerEvent(event))
return false;
- if (event->asPointerScrollEvent())
+ if (event->type() == QEvent::Wheel)
return false;
bool ret = false;
#if QT_CONFIG(gestures)
- if (event->asPointerNativeGestureEvent() && event->point(0)->state() != QQuickEventPoint::Released)
+ if (event->type() == QEvent::NativeGesture && event->point(0).state() != QEventPoint::Released)
ret = true;
#endif
@@ -86,7 +86,7 @@ bool QQuickMultiPointHandler::wantsPointerEvent(QQuickPointerEvent *event)
// are all still there in the event, we're good to go (do not reset
// currentPoints, because we don't want to lose the pressPosition, and do
// not want to reshuffle the order either).
- const QVector<QQuickEventPoint *> candidatePoints = eligiblePoints(event);
+ const auto candidatePoints = eligiblePoints(event);
if (candidatePoints.count() != d->currentPoints.count()) {
d->currentPoints.clear();
if (active()) {
@@ -103,7 +103,7 @@ bool QQuickMultiPointHandler::wantsPointerEvent(QQuickPointerEvent *event)
const int c = candidatePoints.count();
d->currentPoints.resize(c);
for (int i = 0; i < c; ++i) {
- d->currentPoints[i].reset(candidatePoints[i]);
+ d->currentPoints[i].reset(event, candidatePoints[i]);
d->currentPoints[i].localize(parentItem());
}
} else {
@@ -112,7 +112,7 @@ bool QQuickMultiPointHandler::wantsPointerEvent(QQuickPointerEvent *event)
return ret;
}
-void QQuickMultiPointHandler::handlePointerEventImpl(QQuickPointerEvent *event)
+void QQuickMultiPointHandler::handlePointerEventImpl(QPointerEvent *event)
{
Q_D(QQuickMultiPointHandler);
QQuickPointerHandler::handlePointerEventImpl(event);
@@ -120,9 +120,8 @@ void QQuickMultiPointHandler::handlePointerEventImpl(QQuickPointerEvent *event)
// is _not_ a shallow copy of the QQuickPointerTouchEvent::m_touchPoints vector.
// So we have to update our currentPoints instances based on the given event.
for (QQuickHandlerPoint &p : d->currentPoints) {
- const QQuickEventPoint *ep = event->pointById(p.id());
- if (ep)
- p.reset(ep);
+ if (const QEventPoint *ep = event->pointById(p.id()))
+ p.reset(event, *ep);
}
QPointF sceneGrabPos = d->centroid.sceneGrabPosition();
d->centroid.reset(d->currentPoints);
@@ -146,36 +145,35 @@ void QQuickMultiPointHandler::onActiveChanged()
}
}
-void QQuickMultiPointHandler::onGrabChanged(QQuickPointerHandler *, QQuickEventPoint::GrabTransition transition, QQuickEventPoint *)
+void QQuickMultiPointHandler::onGrabChanged(QQuickPointerHandler *, QPointingDevice::GrabTransition transition, QPointerEvent *, QEventPoint &)
{
Q_D(QQuickMultiPointHandler);
// If another handler or item takes over this set of points, assume it has
// decided that it's the better fit for them. Don't immediately re-grab
// at the next opportunity. This should help to avoid grab cycles
// (e.g. between DragHandler and PinchHandler).
- if (transition == QQuickEventPoint::UngrabExclusive || transition == QQuickEventPoint::CancelGrabExclusive)
+ if (transition == QPointingDevice::UngrabExclusive || transition == QPointingDevice::CancelGrabExclusive)
d->currentPoints.clear();
}
-QVector<QQuickEventPoint *> QQuickMultiPointHandler::eligiblePoints(QQuickPointerEvent *event)
+QVector<QEventPoint> QQuickMultiPointHandler::eligiblePoints(QPointerEvent *event)
{
- QVector<QQuickEventPoint *> ret;
- int c = event->pointCount();
+ QVector<QEventPoint> ret;
// If one or more points are newly pressed or released, all non-released points are candidates for this handler.
// In other cases however, check whether it would be OK to steal the grab if the handler chooses to do that.
- bool stealingAllowed = event->isPressEvent() || event->isReleaseEvent();
- for (int i = 0; i < c; ++i) {
- QQuickEventPoint *p = event->point(i);
- if (QQuickPointerMouseEvent *me = event->asPointerMouseEvent()) {
- if (me->buttons() == Qt::NoButton)
+ bool stealingAllowed = event->isBeginEvent() || event->isEndEvent();
+ for (int i = 0; i < event->pointCount(); ++i) {
+ auto &p = QMutableEventPoint::from(event->point(i));
+ if (QQuickWindowPrivate::isMouseEvent(event)) {
+ if (static_cast<QMouseEvent *>(event)->buttons() == Qt::NoButton)
continue;
}
if (!stealingAllowed) {
- QObject *exclusiveGrabber = p->exclusiveGrabber();
- if (exclusiveGrabber && exclusiveGrabber != this && !canGrab(p))
+ QObject *exclusiveGrabber = event->exclusiveGrabber(p);
+ if (exclusiveGrabber && exclusiveGrabber != this && !canGrab(event, p))
continue;
}
- if (p->state() != QQuickEventPoint::Released && wantsEventPoint(p))
+ if (p.state() != QEventPoint::Released && wantsEventPoint(event, p))
ret << p;
}
return ret;
@@ -274,7 +272,7 @@ QVector<QQuickHandlerPoint> &QQuickMultiPointHandler::currentPoints()
return d->currentPoints;
}
-bool QQuickMultiPointHandler::hasCurrentPoints(QQuickPointerEvent *event)
+bool QQuickMultiPointHandler::hasCurrentPoints(QPointerEvent *event)
{
Q_D(const QQuickMultiPointHandler);
if (event->pointCount() < d->currentPoints.size() || d->currentPoints.size() == 0)
@@ -282,10 +280,10 @@ bool QQuickMultiPointHandler::hasCurrentPoints(QQuickPointerEvent *event)
// TODO optimize: either ensure the points are sorted,
// or use std::equal with a predicate
for (const QQuickHandlerPoint &p : qAsConst(d->currentPoints)) {
- const QQuickEventPoint *ep = event->pointById(p.id());
+ const QEventPoint *ep = event->pointById(p.id());
if (!ep)
return false;
- if (ep->state() == QQuickEventPoint::Released)
+ if (ep->state() == QEventPoint::Released)
return false;
}
return true;
@@ -358,26 +356,28 @@ qreal QQuickMultiPointHandler::averageAngleDelta(const QVector<PointData> &old,
return avgAngleDelta;
}
-void QQuickMultiPointHandler::acceptPoints(const QVector<QQuickEventPoint *> &points)
+void QQuickMultiPointHandler::acceptPoints(const QVector<QEventPoint> &points)
{
- for (QQuickEventPoint* point : points)
- point->setAccepted();
+ // "auto point" is a copy, but it's OK because
+ // setAccepted() changes QEventPointPrivate::accept via the shared d-pointer
+ for (auto point : points)
+ point.setAccepted();
}
-bool QQuickMultiPointHandler::grabPoints(const QVector<QQuickEventPoint *> &points)
+bool QQuickMultiPointHandler::grabPoints(QPointerEvent *event, const QVector<QEventPoint> &points)
{
if (points.isEmpty())
return false;
bool allowed = true;
- for (QQuickEventPoint* point : points) {
- if (point->exclusiveGrabber() != this && !canGrab(point)) {
+ for (auto &point : points) {
+ if (event->exclusiveGrabber(point) != this && !canGrab(event, point)) {
allowed = false;
break;
}
}
if (allowed) {
- for (QQuickEventPoint* point : points)
- setExclusiveGrab(point);
+ for (auto point : points)
+ setExclusiveGrab(event, point);
}
return allowed;
}
diff --git a/src/quick/handlers/qquickmultipointhandler_p.h b/src/quick/handlers/qquickmultipointhandler_p.h
index c0751aa5c5..01cd78f9db 100644
--- a/src/quick/handlers/qquickmultipointhandler_p.h
+++ b/src/quick/handlers/qquickmultipointhandler_p.h
@@ -91,22 +91,22 @@ protected:
qreal angle;
};
- bool wantsPointerEvent(QQuickPointerEvent *event) override;
- void handlePointerEventImpl(QQuickPointerEvent *event) override;
+ bool wantsPointerEvent(QPointerEvent *event) override;
+ void handlePointerEventImpl(QPointerEvent *event) override;
void onActiveChanged() override;
- void onGrabChanged(QQuickPointerHandler *grabber, QQuickEventPoint::GrabTransition transition, QQuickEventPoint *point) override;
- QVector<QQuickHandlerPoint> &currentPoints();
+ void onGrabChanged(QQuickPointerHandler *grabber, QPointingDevice::GrabTransition transition, QPointerEvent *event, QEventPoint &point) override;
+ QList<QQuickHandlerPoint> &currentPoints();
QQuickHandlerPoint &mutableCentroid();
- bool hasCurrentPoints(QQuickPointerEvent *event);
- QVector<QQuickEventPoint *> eligiblePoints(QQuickPointerEvent *event);
+ bool hasCurrentPoints(QPointerEvent *event);
+ QVector<QEventPoint> eligiblePoints(QPointerEvent *event);
qreal averageTouchPointDistance(const QPointF &ref);
qreal averageStartingDistance(const QPointF &ref);
qreal averageTouchPointAngle(const QPointF &ref);
qreal averageStartingAngle(const QPointF &ref);
QVector<PointData> angles(const QPointF &ref) const;
static qreal averageAngleDelta(const QVector<PointData> &old, const QVector<PointData> &newAngles);
- void acceptPoints(const QVector<QQuickEventPoint *> &points);
- bool grabPoints(const QVector<QQuickEventPoint *> &points);
+ void acceptPoints(const QVector<QEventPoint> &points);
+ bool grabPoints(QPointerEvent *event, const QVector<QEventPoint> &points);
void moveTarget(QPointF pos);
Q_DECLARE_PRIVATE(QQuickMultiPointHandler)
diff --git a/src/quick/handlers/qquickpinchhandler.cpp b/src/quick/handlers/qquickpinchhandler.cpp
index 8413b8b721..b1dca9a905 100644
--- a/src/quick/handlers/qquickpinchhandler.cpp
+++ b/src/quick/handlers/qquickpinchhandler.cpp
@@ -153,15 +153,16 @@ void QQuickPinchHandler::setMaximumRotation(qreal maximumRotation)
emit maximumRotationChanged();
}
-bool QQuickPinchHandler::wantsPointerEvent(QQuickPointerEvent *event)
+bool QQuickPinchHandler::wantsPointerEvent(QPointerEvent *event)
{
if (!QQuickMultiPointHandler::wantsPointerEvent(event))
return false;
#if QT_CONFIG(gestures)
- if (const auto gesture = event->asPointerNativeGestureEvent()) {
+ if (event->type() == QEvent::NativeGesture) {
+ const auto gesture = static_cast<const QNativeGestureEvent *>(event);
if (minimumPointCount() == 2) {
- switch (gesture->type()) {
+ switch (gesture->gestureType()) {
case Qt::BeginNativeGesture:
case Qt::EndNativeGesture:
case Qt::ZoomNativeGesture:
@@ -243,7 +244,7 @@ void QQuickPinchHandler::onActiveChanged()
}
}
-void QQuickPinchHandler::handlePointerEventImpl(QQuickPointerEvent *event)
+void QQuickPinchHandler::handlePointerEventImpl(QPointerEvent *event)
{
if (Q_UNLIKELY(lcPinchHandler().isDebugEnabled())) {
for (const QQuickHandlerPoint &p : currentPoints())
@@ -253,9 +254,10 @@ void QQuickPinchHandler::handlePointerEventImpl(QQuickPointerEvent *event)
qreal dist = 0;
#if QT_CONFIG(gestures)
- if (const auto gesture = event->asPointerNativeGestureEvent()) {
- mutableCentroid().reset(event->point(0));
- switch (gesture->type()) {
+ if (event->type() == QEvent::NativeGesture) {
+ const auto gesture = static_cast<const QNativeGestureEvent *>(event);
+ mutableCentroid().reset(event, event->point(0));
+ switch (gesture->gestureType()) {
case Qt::EndNativeGesture:
m_activeScale = 1;
m_activeRotation = 0;
@@ -283,11 +285,12 @@ void QQuickPinchHandler::handlePointerEventImpl(QQuickPointerEvent *event)
} else
#endif // QT_CONFIG(gestures)
{
- const bool containsReleasedPoints = event->isReleaseEvent();
- QVector<QQuickEventPoint *> chosenPoints;
+ const bool containsReleasedPoints = event->isEndEvent();
+ QVector<QEventPoint> chosenPoints;
for (const QQuickHandlerPoint &p : currentPoints()) {
- QQuickEventPoint *ep = event->pointById(p.id());
- chosenPoints << ep;
+ auto ep = event->pointById(p.id());
+ Q_ASSERT(ep);
+ chosenPoints << *ep;
}
if (!active()) {
// Verify that at least one of the points has moved beyond threshold needed to activate the handler
@@ -300,14 +303,14 @@ void QQuickPinchHandler::handlePointerEventImpl(QQuickPointerEvent *event)
const int dragThresholdSquared = dragThreshold * dragThreshold;
double accumulatedCentroidDistance = 0; // Used to detect scale
- if (event->isPressEvent())
+ if (event->isBeginEvent())
m_accumulatedStartCentroidDistance = 0; // Used to detect scale
float accumulatedMovementMagnitude = 0;
- for (QQuickEventPoint *point : qAsConst(chosenPoints)) {
+ for (auto &point : chosenPoints) {
if (!containsReleasedPoints) {
- accumulatedDrag += QVector2D(point->scenePressPosition() - point->scenePosition());
+ accumulatedDrag += QVector2D(point.scenePressPosition() - point.scenePosition());
/*
In order to detect a drag, we want to check if all points have moved more or
less in the same direction.
@@ -341,20 +344,20 @@ void QQuickPinchHandler::handlePointerEventImpl(QQuickPointerEvent *event)
was moved, but the relative position between each finger remained very much
the same). This is then used to rule out if there is a rotation or scale.
*/
- QVector2D pressCentroidRelativePosition = QVector2D(point->scenePosition()) - currentCentroid;
- QVector2D currentCentroidRelativePosition = QVector2D(point->scenePressPosition()) - pressCentroid;
+ QVector2D pressCentroidRelativePosition = QVector2D(point.scenePosition()) - currentCentroid;
+ QVector2D currentCentroidRelativePosition = QVector2D(point.scenePressPosition()) - pressCentroid;
QVector2D centroidRelativeMovement = currentCentroidRelativePosition - pressCentroidRelativePosition;
accumulatedMovementMagnitude += centroidRelativeMovement.length();
accumulatedCentroidDistance += qreal(pressCentroidRelativePosition.length());
- if (event->isPressEvent())
- m_accumulatedStartCentroidDistance += qreal((QVector2D(point->scenePressPosition()) - pressCentroid).length());
+ if (event->isBeginEvent())
+ m_accumulatedStartCentroidDistance += qreal((QVector2D(point.scenePressPosition()) - pressCentroid).length());
} else {
- setPassiveGrab(point);
+ setPassiveGrab(event, point);
}
- if (point->state() == QQuickEventPoint::Pressed) {
- point->setAccepted(false); // don't stop propagation
- setPassiveGrab(point);
+ if (point.state() == QEventPoint::Pressed) {
+ point.setAccepted(false); // don't stop propagation
+ setPassiveGrab(event, point);
}
Q_D(QQuickMultiPointHandler);
if (d->dragOverThreshold(point))
@@ -376,17 +379,17 @@ void QQuickPinchHandler::handlePointerEventImpl(QQuickPointerEvent *event)
if (numberOfPointsDraggedOverThreshold >= 1) {
if (requiredNumberOfPointsDraggedOverThreshold && avgDrag.lengthSquared() >= dragThresholdSquared && accumulatedMovementMagnitude < dragThreshold) {
// Drag
- if (grabPoints(chosenPoints))
+ if (grabPoints(event, chosenPoints))
setActive(true);
} else if (distanceToCentroidDelta > dragThreshold) { // all points should in accumulation have been moved beyond threshold (?)
// Scale
- if (grabPoints(chosenPoints))
+ if (grabPoints(event, chosenPoints))
setActive(true);
} else if (distanceToCentroidDelta < dragThreshold && (centroidMovementDelta < dragThreshold)) {
// Rotate
// Since it wasn't a scale and if we exceeded the dragthreshold, and the
// centroid didn't moved much, the points must have been moved around the centroid.
- if (grabPoints(chosenPoints))
+ if (grabPoints(event, chosenPoints))
setActive(true);
}
}
diff --git a/src/quick/handlers/qquickpinchhandler_p.h b/src/quick/handlers/qquickpinchhandler_p.h
index b4e9fa0336..8099982d46 100644
--- a/src/quick/handlers/qquickpinchhandler_p.h
+++ b/src/quick/handlers/qquickpinchhandler_p.h
@@ -106,9 +106,9 @@ signals:
void updated();
protected:
- bool wantsPointerEvent(QQuickPointerEvent *event) override;
+ bool wantsPointerEvent(QPointerEvent *event) override;
void onActiveChanged() override;
- void handlePointerEventImpl(QQuickPointerEvent *event) override;
+ void handlePointerEventImpl(QPointerEvent *event) override;
private:
// properties
diff --git a/src/quick/handlers/qquickpointerdevicehandler.cpp b/src/quick/handlers/qquickpointerdevicehandler.cpp
index 592abb6660..a27aec7d56 100644
--- a/src/quick/handlers/qquickpointerdevicehandler.cpp
+++ b/src/quick/handlers/qquickpointerdevicehandler.cpp
@@ -290,7 +290,7 @@ void QQuickPointerDeviceHandler::setAcceptedModifiers(Qt::KeyboardModifiers acce
emit acceptedModifiersChanged();
}
-bool QQuickPointerDeviceHandler::wantsPointerEvent(QQuickPointerEvent *event)
+bool QQuickPointerDeviceHandler::wantsPointerEvent(QPointerEvent *event)
{
Q_D(QQuickPointerDeviceHandler);
if (!QQuickPointerHandler::wantsPointerEvent(event))
@@ -301,14 +301,15 @@ bool QQuickPointerDeviceHandler::wantsPointerEvent(QQuickPointerEvent *event)
<< "modifiers" << d->acceptedModifiers;
if (!d->acceptedDevices.testFlag(event->device()->type()))
return false;
- if (!d->acceptedPointerTypes.testFlag(event->device()->pointerType()))
+ if (!d->acceptedPointerTypes.testFlag(event->pointingDevice()->pointerType()))
return false;
if (d->acceptedModifiers != Qt::KeyboardModifierMask && event->modifiers() != d->acceptedModifiers)
return false;
// HoverHandler sets acceptedButtons to Qt::NoButton to indicate that button state is irrelevant.
- if (event->device()->pointerType() != QPointingDevice::PointerType::Finger && acceptedButtons() != Qt::NoButton &&
- (event->buttons() & acceptedButtons()) == 0 && (event->button() & acceptedButtons()) == 0
- && !event->asPointerScrollEvent())
+ if (event->pointingDevice()->pointerType() != QPointingDevice::PointerType::Finger &&
+ acceptedButtons() != Qt::NoButton && event->type() != QEvent::Wheel &&
+ (static_cast<QSinglePointEvent *>(event)->buttons() & acceptedButtons()) == 0 &&
+ (static_cast<QSinglePointEvent *>(event)->button() & acceptedButtons()) == 0)
return false;
return true;
}
diff --git a/src/quick/handlers/qquickpointerdevicehandler_p.h b/src/quick/handlers/qquickpointerdevicehandler_p.h
index 28c88db2b7..6091646c14 100644
--- a/src/quick/handlers/qquickpointerdevicehandler_p.h
+++ b/src/quick/handlers/qquickpointerdevicehandler_p.h
@@ -87,7 +87,7 @@ Q_SIGNALS:
protected:
QQuickPointerDeviceHandler(QQuickPointerDeviceHandlerPrivate &dd, QQuickItem *parent = nullptr);
- bool wantsPointerEvent(QQuickPointerEvent *event) override;
+ bool wantsPointerEvent(QPointerEvent *event) override;
Q_DECLARE_PRIVATE(QQuickPointerDeviceHandler)
};
diff --git a/src/quick/handlers/qquickpointerhandler.cpp b/src/quick/handlers/qquickpointerhandler.cpp
index ce59a35b62..0dc2435b4e 100644
--- a/src/quick/handlers/qquickpointerhandler.cpp
+++ b/src/quick/handlers/qquickpointerhandler.cpp
@@ -247,31 +247,32 @@ bool QQuickPointerHandler::isCursorShapeExplicitlySet() const
call its parent class's implementation in addition to (usually after)
whatever custom behavior it implements.
*/
-void QQuickPointerHandler::onGrabChanged(QQuickPointerHandler *grabber, QQuickEventPoint::GrabTransition transition, QQuickEventPoint *point)
+void QQuickPointerHandler::onGrabChanged(QQuickPointerHandler *grabber, QPointingDevice::GrabTransition transition,
+ QPointerEvent *event, QEventPoint &point)
{
+ Q_UNUSED(event);
qCDebug(lcPointerHandlerGrab) << point << transition << grabber;
- Q_ASSERT(point);
if (grabber == this) {
bool wasCanceled = false;
switch (transition) {
- case QQuickEventPoint::GrabPassive:
- case QQuickEventPoint::GrabExclusive:
+ case QPointingDevice::GrabPassive:
+ case QPointingDevice::GrabExclusive:
break;
- case QQuickEventPoint::CancelGrabPassive:
- case QQuickEventPoint::CancelGrabExclusive:
+ case QPointingDevice::CancelGrabPassive:
+ case QPointingDevice::CancelGrabExclusive:
wasCanceled = true; // the grab was stolen by something else
Q_FALLTHROUGH();
- case QQuickEventPoint::UngrabPassive:
- case QQuickEventPoint::UngrabExclusive:
+ case QPointingDevice::UngrabPassive:
+ case QPointingDevice::UngrabExclusive:
setActive(false);
- point->setAccepted(false);
+ point.setAccepted(false);
if (auto par = parentItem()) {
Q_D(const QQuickPointerHandler);
par->setKeepMouseGrab(d->hadKeepMouseGrab);
par->setKeepTouchGrab(d->hadKeepTouchGrab);
}
break;
- case QQuickEventPoint::OverrideGrabPassive:
+ case QPointingDevice::OverrideGrabPassive:
// Passive grab is still there, but we won't receive point updates right now.
// No need to notify about this.
return;
@@ -297,13 +298,13 @@ void QQuickPointerHandler::onGrabChanged(QQuickPointerHandler *grabber, QQuickEv
grab, or it may acquire an exclusive grab if the gesture clearly must not
be interpreted in another way by another handler.
*/
-void QQuickPointerHandler::setPassiveGrab(QQuickEventPoint *point, bool grab)
+void QQuickPointerHandler::setPassiveGrab(QPointerEvent *event, const QEventPoint &point, bool grab)
{
qCDebug(lcPointerHandlerGrab) << point << grab;
if (grab) {
- point->setGrabberPointerHandler(this, false);
+ event->addPassiveGrabber(point, this);
} else {
- point->removePassiveGrabber(this);
+ event->removePassiveGrabber(point, this);
}
}
@@ -318,11 +319,11 @@ void QQuickPointerHandler::setPassiveGrab(QQuickEventPoint *point, bool grab)
also calls approveGrabTransition() on the handler which is about to lose
its grab. Either one can deny the takeover.
*/
-bool QQuickPointerHandler::canGrab(QQuickEventPoint *point)
+bool QQuickPointerHandler::canGrab(QPointerEvent *event, const QEventPoint &point)
{
- QQuickPointerHandler *existingPhGrabber = point->grabberPointerHandler();
- return approveGrabTransition(point, this) &&
- (existingPhGrabber ? existingPhGrabber->approveGrabTransition(point, this) : true);
+ QQuickPointerHandler *existingPhGrabber = qobject_cast<QQuickPointerHandler *>(event->exclusiveGrabber(point));
+ return approveGrabTransition(event, point, this) &&
+ (existingPhGrabber ? existingPhGrabber->approveGrabTransition(event, point, this) : true);
}
/*!
@@ -331,15 +332,15 @@ bool QQuickPointerHandler::canGrab(QQuickEventPoint *point)
will take the grab, and once on the instance which would thereby lose its grab,
in case of a takeover scenario.
*/
-bool QQuickPointerHandler::approveGrabTransition(QQuickEventPoint *point, QObject *proposedGrabber)
+bool QQuickPointerHandler::approveGrabTransition(QPointerEvent *event, const QEventPoint &point, QObject *proposedGrabber)
{
Q_D(const QQuickPointerHandler);
bool allowed = false;
if (proposedGrabber == this) {
- QObject* existingGrabber = point->exclusiveGrabber();
+ QObject* existingGrabber = event->exclusiveGrabber(point);
allowed = (existingGrabber == nullptr) || ((d->grabPermissions & CanTakeOverFromAnything) == CanTakeOverFromAnything);
if (existingGrabber) {
- if (QQuickPointerHandler *existingPhGrabber = point->grabberPointerHandler()) {
+ if (QQuickPointerHandler *existingPhGrabber = qobject_cast<QQuickPointerHandler *>(event->exclusiveGrabber(point))) {
if (!allowed && (d->grabPermissions & CanTakeOverFromHandlersOfDifferentType) &&
existingPhGrabber->metaObject()->className() != metaObject()->className())
allowed = true;
@@ -347,9 +348,9 @@ bool QQuickPointerHandler::approveGrabTransition(QQuickEventPoint *point, QObjec
existingPhGrabber->metaObject()->className() == metaObject()->className())
allowed = true;
} else if ((d->grabPermissions & CanTakeOverFromItems)) {
- QQuickItem * existingItemGrabber = point->grabberItem();
- if (existingItemGrabber && !((existingItemGrabber->keepMouseGrab() && point->pointerEvent()->asPointerMouseEvent()) ||
- (existingItemGrabber->keepTouchGrab() && point->pointerEvent()->asPointerTouchEvent()))) {
+ QQuickItem * existingItemGrabber = qobject_cast<QQuickItem *>(event->exclusiveGrabber(point));
+ if (existingItemGrabber && !((existingItemGrabber->keepMouseGrab() && QQuickWindowPrivate::isMouseEvent(event)) ||
+ (existingItemGrabber->keepTouchGrab() && QQuickWindowPrivate::isTouchEvent(event)))) {
allowed = true;
// If the handler wants to steal the exclusive grab from an Item, the Item can usually veto
// by having its keepMouseGrab flag set. But an exception is if that Item is a parent that
@@ -361,8 +362,8 @@ bool QQuickPointerHandler::approveGrabTransition(QQuickEventPoint *point, QObjec
if (existingItemGrabber->keepMouseGrab() &&
!(existingItemGrabber->filtersChildMouseEvents() && existingItemGrabber->isAncestorOf(parentItem()))) {
QQuickWindowPrivate *winPriv = QQuickWindowPrivate::get(parentItem()->window());
- if (winPriv->isDeliveringTouchAsMouse() && point->pointId() == winPriv->touchMouseId) {
- qCDebug(lcPointerHandlerGrab) << this << "wants to grab touchpoint" << point->pointId()
+ if (winPriv->isDeliveringTouchAsMouse() && point.id() == winPriv->touchMouseId) {
+ qCDebug(lcPointerHandlerGrab) << this << "wants to grab touchpoint" << point.id()
<< "but declines to steal grab from touch-mouse grabber with keepMouseGrab=true" << existingItemGrabber;
allowed = false;
}
@@ -388,7 +389,7 @@ bool QQuickPointerHandler::approveGrabTransition(QQuickEventPoint *point, QObjec
allowed = true;
}
}
- qCDebug(lcPointerHandlerGrab) << "point" << Qt::hex << point->pointId() << "permission" <<
+ qCDebug(lcPointerHandlerGrab) << "point" << Qt::hex << point.id() << "permission" <<
QMetaEnum::fromType<GrabPermissions>().valueToKeys(grabPermissions()) <<
':' << this << (allowed ? "approved to" : "denied to") << proposedGrabber;
return allowed;
@@ -449,7 +450,7 @@ void QQuickPointerHandler::componentComplete()
{
}
-QQuickPointerEvent *QQuickPointerHandler::currentEvent()
+QPointerEvent *QQuickPointerHandler::currentEvent()
{
Q_D(const QQuickPointerHandler);
return d->currentEvent;
@@ -463,52 +464,60 @@ QQuickPointerEvent *QQuickPointerHandler::currentEvent()
specified. Returns false if permission is denied either by this handler or
by the handler or item from which this handler would take over
*/
-bool QQuickPointerHandler::setExclusiveGrab(QQuickEventPoint *point, bool grab)
+bool QQuickPointerHandler::setExclusiveGrab(QPointerEvent *ev, const QEventPoint &point, bool grab)
{
- if ((grab && point->exclusiveGrabber() == this) || (!grab && point->exclusiveGrabber() != this))
+ if ((grab && ev->exclusiveGrabber(point) == this) || (!grab && ev->exclusiveGrabber(point) != this))
return true;
// TODO m_hadKeepMouseGrab m_hadKeepTouchGrab
bool allowed = true;
if (grab) {
- allowed = canGrab(point);
+ allowed = canGrab(ev, point);
} else {
- QQuickPointerHandler *existingPhGrabber = point->grabberPointerHandler();
+ QQuickPointerHandler *existingPhGrabber = qobject_cast<QQuickPointerHandler *>(ev->exclusiveGrabber(point));
// Ask before allowing one handler to cancel another's grab
- if (existingPhGrabber && existingPhGrabber != this && !existingPhGrabber->approveGrabTransition(point, nullptr))
+ if (existingPhGrabber && existingPhGrabber != this && !existingPhGrabber->approveGrabTransition(ev, point, nullptr))
allowed = false;
}
qCDebug(lcPointerHandlerGrab) << point << (grab ? "grab" : "ungrab") << (allowed ? "allowed" : "forbidden") <<
- point->exclusiveGrabber() << "->" << (grab ? this : nullptr);
+ ev->exclusiveGrabber(point) << "->" << (grab ? this : nullptr);
if (allowed)
- point->setGrabberPointerHandler(grab ? this : nullptr, true);
+ ev->setExclusiveGrabber(point, grab ? this : nullptr);
return allowed;
}
/*!
Cancel any existing grab of the given \a point.
*/
-void QQuickPointerHandler::cancelAllGrabs(QQuickEventPoint *point)
+void QQuickPointerHandler::cancelAllGrabs(QPointerEvent *event, QEventPoint &point)
{
qCDebug(lcPointerHandlerGrab) << point;
- point->cancelAllGrabs(this);
+ if (event->exclusiveGrabber(point) == this) {
+ event->setExclusiveGrabber(point, nullptr);
+ onGrabChanged(this, QPointingDevice::CancelGrabExclusive, event, point);
+ }
+ if (event->removePassiveGrabber(point, this))
+ onGrabChanged(this, QPointingDevice::CancelGrabPassive, event, point);
}
-QPointF QQuickPointerHandler::eventPos(const QQuickEventPoint *point) const
+QPointF QQuickPointerHandler::eventPos(const QEventPoint &point) const
{
- return (target() ? target()->mapFromScene(point->scenePosition()) : point->scenePosition());
+ return (target() ? target()->mapFromScene(point.scenePosition()) : point.scenePosition());
}
-bool QQuickPointerHandler::parentContains(const QQuickEventPoint *point) const
+bool QQuickPointerHandler::parentContains(const QEventPoint &point) const
+{
+ return parentContains(point.scenePosition());
+}
+
+bool QQuickPointerHandler::parentContains(const QPointF &scenePosition) const
{
- if (!point)
- return false;
if (QQuickItem *par = parentItem()) {
if (par->window()) {
- QPoint screenPosition = par->window()->mapToGlobal(point->scenePosition().toPoint());
+ QPoint screenPosition = par->window()->mapToGlobal(scenePosition.toPoint());
if (!par->window()->geometry().contains(screenPosition))
return false;
}
- QPointF p = par->mapFromScene(point->scenePosition());
+ QPointF p = par->mapFromScene(scenePosition);
qreal m = margin();
if (m > 0)
return p.x() >= -m && p.y() >= -m && p.x() <= par->width() + m && p.y() <= par->height() + m;
@@ -582,7 +591,29 @@ QQuickItem *QQuickPointerHandler::target() const
return d->target;
}
-void QQuickPointerHandler::handlePointerEvent(QQuickPointerEvent *event)
+/*! \internal
+ Pointer Handlers do most of their work in implementations of virtual functions
+ that are called directly from QQuickItem, not by direct event handling.
+ But it's convenient to deliver TouchCancel events via QCoreApplication::sendEvent().
+ Perhaps it will turn out that more events could be delivered this way.
+*/
+bool QQuickPointerHandler::event(QEvent *e)
+{
+ switch (e->type()) {
+ case QEvent::TouchCancel: {
+ auto te = static_cast<QTouchEvent *>(e);
+ for (int i = 0; i < te->pointCount(); ++i)
+ onGrabChanged(this, QPointingDevice::CancelGrabExclusive, te, te->point(i));
+ return true;
+ break;
+ }
+ default:
+ return QObject::event(e);
+ break;
+ }
+}
+
+void QQuickPointerHandler::handlePointerEvent(QPointerEvent *event)
{
bool wants = wantsPointerEvent(event);
qCDebug(lcPointerHandlerDispatch) << metaObject()->className() << objectName()
@@ -592,27 +623,30 @@ void QQuickPointerHandler::handlePointerEvent(QQuickPointerEvent *event)
handlePointerEventImpl(event);
} else {
setActive(false);
- int pCount = event->pointCount();
- for (int i = 0; i < pCount; ++i) {
- QQuickEventPoint *pt = event->point(i);
- if (pt->grabberPointerHandler() == this && pt->state() != QQuickEventPoint::Stationary)
- pt->cancelExclusiveGrab();
+ for (int i = 0; i < event->pointCount(); ++i) {
+ auto &pt = event->point(i);
+ if (event->exclusiveGrabber(pt) == this && pt.state() != QEventPoint::Stationary) {
+ event->setExclusiveGrabber(pt, nullptr);
+ onGrabChanged(this, QPointingDevice::CancelGrabExclusive, event, pt);
+ }
}
}
QQuickPointerHandlerPrivate::deviceDeliveryTargets(event->device()).append(this);
}
-bool QQuickPointerHandler::wantsPointerEvent(QQuickPointerEvent *event)
+bool QQuickPointerHandler::wantsPointerEvent(QPointerEvent *event)
{
Q_D(const QQuickPointerHandler);
Q_UNUSED(event);
return d->enabled;
}
-bool QQuickPointerHandler::wantsEventPoint(QQuickEventPoint *point)
+bool QQuickPointerHandler::wantsEventPoint(const QPointerEvent *event, const QEventPoint &point)
{
- bool ret = point->exclusiveGrabber() == this || point->passiveGrabbers().contains(this) || parentContains(point);
- qCDebug(lcPointerHandlerDispatch) << Qt::hex << point->pointId() << "@" << point->scenePosition()
+ Q_UNUSED(event);
+ bool ret = event->exclusiveGrabber(point) == this ||
+ event->passiveGrabbers(point).contains(this) || parentContains(point);
+ qCDebug(lcPointerHandlerDispatch) << Qt::hex << point.id() << "@" << point.scenePosition()
<< metaObject()->className() << objectName() << ret;
return ret;
}
@@ -638,7 +672,7 @@ void QQuickPointerHandler::setActive(bool active)
}
}
-void QQuickPointerHandler::handlePointerEventImpl(QQuickPointerEvent *event)
+void QQuickPointerHandler::handlePointerEventImpl(QPointerEvent *event)
{
Q_D(QQuickPointerHandler);
d->currentEvent = event;
@@ -689,14 +723,14 @@ QQuickPointerHandlerPrivate::QQuickPointerHandlerPrivate()
}
template <typename TEventPoint>
-bool QQuickPointerHandlerPrivate::dragOverThreshold(qreal d, Qt::Axis axis, const TEventPoint *p) const
+bool QQuickPointerHandlerPrivate::dragOverThreshold(qreal d, Qt::Axis axis, const TEventPoint &p) const
{
Q_Q(const QQuickPointerHandler);
QStyleHints *styleHints = qApp->styleHints();
bool overThreshold = qAbs(d) > q->dragThreshold();
const bool dragVelocityLimitAvailable = (styleHints->startDragVelocity() > 0);
if (!overThreshold && dragVelocityLimitAvailable) {
- qreal velocity = qreal(axis == Qt::XAxis ? p->velocity().x() : p->velocity().y());
+ qreal velocity = qreal(axis == Qt::XAxis ? p.velocity().x() : p.velocity().y());
overThreshold |= qAbs(velocity) > styleHints->startDragVelocity();
}
return overThreshold;
@@ -709,9 +743,9 @@ bool QQuickPointerHandlerPrivate::dragOverThreshold(QVector2D delta) const
return qAbs(delta.x()) > threshold || qAbs(delta.y()) > threshold;
}
-bool QQuickPointerHandlerPrivate::dragOverThreshold(const QQuickEventPoint *point) const
+bool QQuickPointerHandlerPrivate::dragOverThreshold(const QEventPoint &point) const
{
- QPointF delta = point->scenePosition() - point->scenePressPosition();
+ QPointF delta = point.scenePosition() - point.scenePressPosition();
return (dragOverThreshold(delta.x(), Qt::XAxis, point) ||
dragOverThreshold(delta.y(), Qt::YAxis, point));
}
diff --git a/src/quick/handlers/qquickpointerhandler_p.h b/src/quick/handlers/qquickpointerhandler_p.h
index 3e7876b3d9..8d7fdcdcad 100644
--- a/src/quick/handlers/qquickpointerhandler_p.h
+++ b/src/quick/handlers/qquickpointerhandler_p.h
@@ -110,7 +110,7 @@ public:
QQuickItem * parentItem() const;
- void handlePointerEvent(QQuickPointerEvent *event);
+ void handlePointerEvent(QPointerEvent *event);
GrabPermissions grabPermissions() const;
void setGrabPermissions(GrabPermissions grabPermissions);
@@ -135,9 +135,9 @@ Q_SIGNALS:
void targetChanged();
void marginChanged();
Q_REVISION(2, 15) void dragThresholdChanged();
- void grabChanged(QQuickEventPoint::GrabTransition transition, QQuickEventPoint *point);
+ void grabChanged(QPointingDevice::GrabTransition transition, QEventPoint point);
void grabPermissionChanged();
- void canceled(QQuickEventPoint *point);
+ void canceled(QEventPoint point);
#if QT_CONFIG(cursor)
Q_REVISION(2, 15) void cursorShapeChanged();
#endif
@@ -147,24 +147,26 @@ protected:
void classBegin() override;
void componentComplete() override;
+ bool event(QEvent *) override;
- QQuickPointerEvent *currentEvent();
- virtual bool wantsPointerEvent(QQuickPointerEvent *event);
- virtual bool wantsEventPoint(QQuickEventPoint *point);
- virtual void handlePointerEventImpl(QQuickPointerEvent *event);
+ QPointerEvent *currentEvent();
+ virtual bool wantsPointerEvent(QPointerEvent *event);
+ virtual bool wantsEventPoint(const QPointerEvent *event, const QEventPoint &point);
+ virtual void handlePointerEventImpl(QPointerEvent *event);
void setActive(bool active);
virtual void onTargetChanged(QQuickItem *oldTarget) { Q_UNUSED(oldTarget); }
virtual void onActiveChanged() { }
- virtual void onGrabChanged(QQuickPointerHandler *grabber, QQuickEventPoint::GrabTransition transition, QQuickEventPoint *point);
- virtual bool canGrab(QQuickEventPoint *point);
- virtual bool approveGrabTransition(QQuickEventPoint *point, QObject *proposedGrabber);
- void setPassiveGrab(QQuickEventPoint *point, bool grab = true);
- bool setExclusiveGrab(QQuickEventPoint *point, bool grab = true);
- void cancelAllGrabs(QQuickEventPoint *point);
- QPointF eventPos(const QQuickEventPoint *point) const;
- bool parentContains(const QQuickEventPoint *point) const;
-
- friend class QQuickEventPoint;
+ virtual void onGrabChanged(QQuickPointerHandler *grabber, QPointingDevice::GrabTransition transition,
+ QPointerEvent *event, QEventPoint &point);
+ virtual bool canGrab(QPointerEvent *event, const QEventPoint &point);
+ virtual bool approveGrabTransition(QPointerEvent *event, const QEventPoint &point, QObject *proposedGrabber);
+ void setPassiveGrab(QPointerEvent *event, const QEventPoint &point, bool grab = true);
+ bool setExclusiveGrab(QPointerEvent *ev, const QEventPoint &point, bool grab = true);
+ void cancelAllGrabs(QPointerEvent *event, QEventPoint &point);
+ QPointF eventPos(const QEventPoint &point) const;
+ bool parentContains(const QEventPoint &point) const;
+ bool parentContains(const QPointF &scenePosition) const;
+
friend class QQuickItemPrivate;
friend class QQuickWindowPrivate;
diff --git a/src/quick/handlers/qquickpointerhandler_p_p.h b/src/quick/handlers/qquickpointerhandler_p_p.h
index 03b36c6dae..99120523d8 100644
--- a/src/quick/handlers/qquickpointerhandler_p_p.h
+++ b/src/quick/handlers/qquickpointerhandler_p_p.h
@@ -69,14 +69,14 @@ public:
QQuickPointerHandlerPrivate();
template<typename TEventPoint>
- bool dragOverThreshold(qreal d, Qt::Axis axis, const TEventPoint *p) const;
+ bool dragOverThreshold(qreal d, Qt::Axis axis, const TEventPoint &p) const;
bool dragOverThreshold(QVector2D delta) const;
- bool dragOverThreshold(const QQuickEventPoint *point) const;
+ bool dragOverThreshold(const QEventPoint &point) const;
static QVector<QObject *> &deviceDeliveryTargets(const QInputDevice *device);
- QQuickPointerEvent *currentEvent = nullptr;
+ QPointerEvent *currentEvent = nullptr;
QQuickItem *target = nullptr;
qreal m_margin = 0;
qint16 dragThreshold = -1; // -1 means use the platform default
diff --git a/src/quick/handlers/qquickpointhandler.cpp b/src/quick/handlers/qquickpointhandler.cpp
index 30f62332ba..c3dd997e4a 100644
--- a/src/quick/handlers/qquickpointhandler.cpp
+++ b/src/quick/handlers/qquickpointhandler.cpp
@@ -120,11 +120,11 @@ QQuickPointHandler::QQuickPointHandler(QQuickItem *parent)
setIgnoreAdditionalPoints();
}
-bool QQuickPointHandler::wantsEventPoint(QQuickEventPoint *pt)
+bool QQuickPointHandler::wantsEventPoint(const QPointerEvent *event, const QEventPoint &point)
{
// On press, we want it unless a sibling of the same type also does.
- if (pt->state() == QQuickEventPoint::Pressed && QQuickSinglePointHandler::wantsEventPoint(pt)) {
- for (const QQuickPointerHandler *grabber : pt->passiveGrabbers()) {
+ if (point.state() == QEventPoint::Pressed && QQuickSinglePointHandler::wantsEventPoint(event, point)) {
+ for (const QObject *grabber : event->passiveGrabbers(point)) {
if (grabber && grabber->parent() == parent() &&
grabber->metaObject()->className() == metaObject()->className())
return false;
@@ -132,28 +132,29 @@ bool QQuickPointHandler::wantsEventPoint(QQuickEventPoint *pt)
return true;
}
// If we've already been interested in a point, stay interested, even if it has strayed outside bounds.
- return (pt->state() != QQuickEventPoint::Pressed && point().id() == pt->pointId());
+ return (point.state() != QEventPoint::Pressed &&
+ QQuickSinglePointHandler::point().id() == point.id());
}
-void QQuickPointHandler::handleEventPoint(QQuickEventPoint *point)
+void QQuickPointHandler::handleEventPoint(QPointerEvent *event, QEventPoint &point)
{
- switch (point->state()) {
- case QQuickEventPoint::Pressed:
- if (point->pointerEvent()->asPointerTouchEvent() ||
- (point->pointerEvent()->buttons() & acceptedButtons()) != Qt::NoButton) {
- setPassiveGrab(point);
+ switch (point.state()) {
+ case QEventPoint::Pressed:
+ if (QQuickWindowPrivate::isTouchEvent(event) ||
+ (static_cast<const QSinglePointEvent *>(event)->buttons() & acceptedButtons()) != Qt::NoButton) {
+ setPassiveGrab(event, point);
setActive(true);
}
break;
- case QQuickEventPoint::Released:
- if (point->pointerEvent()->asPointerTouchEvent() ||
- (point->pointerEvent()->buttons() & acceptedButtons()) == Qt::NoButton)
+ case QEventPoint::Released:
+ if (QQuickWindowPrivate::isTouchEvent(event) ||
+ (static_cast<const QSinglePointEvent *>(event)->buttons() & acceptedButtons()) == Qt::NoButton)
setActive(false);
break;
default:
break;
}
- point->setAccepted(false); // Just lurking... don't interfere with propagation
+ point.setAccepted(false); // Just lurking... don't interfere with propagation
emit translationChanged();
}
diff --git a/src/quick/handlers/qquickpointhandler_p.h b/src/quick/handlers/qquickpointhandler_p.h
index cedbc1c539..cec48b193d 100644
--- a/src/quick/handlers/qquickpointhandler_p.h
+++ b/src/quick/handlers/qquickpointhandler_p.h
@@ -71,8 +71,8 @@ Q_SIGNALS:
void translationChanged();
protected:
- bool wantsEventPoint(QQuickEventPoint *pt) override;
- void handleEventPoint(QQuickEventPoint *point) override;
+ bool wantsEventPoint(const QPointerEvent *event, const QEventPoint &point) override;
+ void handleEventPoint(QPointerEvent *event, QEventPoint &point) override;
};
QT_END_NAMESPACE
diff --git a/src/quick/handlers/qquicksinglepointhandler.cpp b/src/quick/handlers/qquicksinglepointhandler.cpp
index 89081b4e84..18636991e6 100644
--- a/src/quick/handlers/qquicksinglepointhandler.cpp
+++ b/src/quick/handlers/qquicksinglepointhandler.cpp
@@ -69,7 +69,7 @@ QQuickSinglePointHandler::QQuickSinglePointHandler(QQuickSinglePointHandlerPriva
{
}
-bool QQuickSinglePointHandler::wantsPointerEvent(QQuickPointerEvent *event)
+bool QQuickSinglePointHandler::wantsPointerEvent(QPointerEvent *event)
{
Q_D(QQuickSinglePointHandler);
if (!QQuickPointerDeviceHandler::wantsPointerEvent(event))
@@ -81,17 +81,16 @@ bool QQuickSinglePointHandler::wantsPointerEvent(QQuickPointerEvent *event)
// If we no longer want it, cancel the grab.
int candidatePointCount = 0;
bool missing = true;
- QQuickEventPoint *point = nullptr;
- int c = event->pointCount();
- for (int i = 0; i < c; ++i) {
- QQuickEventPoint *p = event->point(i);
- const bool found = (p->pointId() == d->pointInfo.id());
+ QEventPoint *point = nullptr;
+ for (int i = 0; i < event->pointCount(); ++i) {
+ auto &p = event->point(i);
+ const bool found = (p.id() == d->pointInfo.id());
if (found)
missing = false;
- if (wantsEventPoint(p)) {
+ if (wantsEventPoint(event, p)) {
++candidatePointCount;
if (found)
- point = p;
+ point = &p;
}
}
if (missing)
@@ -102,7 +101,7 @@ bool QQuickSinglePointHandler::wantsPointerEvent(QQuickPointerEvent *event)
point->setAccepted();
return true;
} else {
- point->cancelAllGrabs(this);
+ cancelAllGrabs(event, *point);
}
} else {
return false;
@@ -110,62 +109,63 @@ bool QQuickSinglePointHandler::wantsPointerEvent(QQuickPointerEvent *event)
} else {
// We have not yet chosen a point; choose the first one for which wantsEventPoint() returns true.
int candidatePointCount = 0;
- int c = event->pointCount();
- QQuickEventPoint *chosen = nullptr;
- for (int i = 0; i < c && !chosen; ++i) {
- QQuickEventPoint *p = event->point(i);
- if (!p->exclusiveGrabber() && wantsEventPoint(p)) {
- if (!chosen)
- chosen = p;
+ QEventPoint *chosen = nullptr;
+ for (int i = 0; i < event->pointCount(); ++i) {
+ auto &p = event->point(i);
+ if (!event->exclusiveGrabber(p) && wantsEventPoint(event, p)) {
++candidatePointCount;
+ if (!chosen) {
+ chosen = &p;
+ break;
+ }
}
}
if (chosen && candidatePointCount == 1) {
- setPointId(chosen->pointId());
+ setPointId(chosen->id());
chosen->setAccepted();
}
}
return d->pointInfo.id() != -1;
}
-void QQuickSinglePointHandler::handlePointerEventImpl(QQuickPointerEvent *event)
+void QQuickSinglePointHandler::handlePointerEventImpl(QPointerEvent *event)
{
Q_D(QQuickSinglePointHandler);
QQuickPointerDeviceHandler::handlePointerEventImpl(event);
- QQuickEventPoint *currentPoint = event->pointById(d->pointInfo.id());
+ QEventPoint *currentPoint = const_cast<QEventPoint *>(event->pointById(d->pointInfo.id()));
Q_ASSERT(currentPoint);
- d->pointInfo.reset(currentPoint);
- handleEventPoint(currentPoint);
- if (currentPoint->state() == QQuickEventPoint::Released && (event->buttons() & acceptedButtons()) == Qt::NoButton) {
- setExclusiveGrab(currentPoint, false);
+ d->pointInfo.reset(event, *currentPoint);
+ handleEventPoint(event, *currentPoint);
+ if (currentPoint->state() == QEventPoint::Released && (static_cast<QSinglePointEvent *>(event)->buttons() & acceptedButtons()) == Qt::NoButton) {
+ setExclusiveGrab(event, *currentPoint, false);
d->reset();
}
emit pointChanged();
}
-void QQuickSinglePointHandler::onGrabChanged(QQuickPointerHandler *grabber, QQuickEventPoint::GrabTransition transition, QQuickEventPoint *point)
+void QQuickSinglePointHandler::onGrabChanged(QQuickPointerHandler *grabber, QPointingDevice::GrabTransition transition, QPointerEvent *event, QEventPoint &point)
{
Q_D(QQuickSinglePointHandler);
if (grabber != this)
return;
switch (transition) {
- case QQuickEventPoint::GrabExclusive:
- d->pointInfo.m_sceneGrabPosition = point->sceneGrabPosition();
+ case QPointingDevice::GrabExclusive:
+ d->pointInfo.m_sceneGrabPosition = point.sceneGrabPosition();
setActive(true);
- QQuickPointerHandler::onGrabChanged(grabber, transition, point);
+ QQuickPointerHandler::onGrabChanged(grabber, transition, event, point);
break;
- case QQuickEventPoint::GrabPassive:
- d->pointInfo.m_sceneGrabPosition = point->sceneGrabPosition();
- QQuickPointerHandler::onGrabChanged(grabber, transition, point);
+ case QPointingDevice::GrabPassive:
+ d->pointInfo.m_sceneGrabPosition = point.sceneGrabPosition();
+ QQuickPointerHandler::onGrabChanged(grabber, transition, event, point);
break;
- case QQuickEventPoint::OverrideGrabPassive:
+ case QPointingDevice::OverrideGrabPassive:
return; // don't emit
- case QQuickEventPoint::UngrabPassive:
- case QQuickEventPoint::UngrabExclusive:
- case QQuickEventPoint::CancelGrabPassive:
- case QQuickEventPoint::CancelGrabExclusive:
+ case QPointingDevice::UngrabPassive:
+ case QPointingDevice::UngrabExclusive:
+ case QPointingDevice::CancelGrabPassive:
+ case QPointingDevice::CancelGrabExclusive:
// the grab is lost or relinquished, so the point is no longer relevant
- QQuickPointerHandler::onGrabChanged(grabber, transition, point);
+ QQuickPointerHandler::onGrabChanged(grabber, transition, event, point);
d->reset();
break;
}
@@ -177,11 +177,11 @@ void QQuickSinglePointHandler::setIgnoreAdditionalPoints(bool v)
d->ignoreAdditionalPoints = v;
}
-void QQuickSinglePointHandler::moveTarget(QPointF pos, QQuickEventPoint *point)
+void QQuickSinglePointHandler::moveTarget(QPointF pos, QEventPoint &point)
{
Q_D(QQuickSinglePointHandler);
target()->setPosition(pos);
- d->pointInfo.m_scenePosition = point->scenePosition();
+ d->pointInfo.m_scenePosition = point.scenePosition();
d->pointInfo.m_position = target()->mapFromScene(d->pointInfo.m_scenePosition);
}
diff --git a/src/quick/handlers/qquicksinglepointhandler_p.h b/src/quick/handlers/qquicksinglepointhandler_p.h
index edc55aaaf6..85ab4f24d4 100644
--- a/src/quick/handlers/qquicksinglepointhandler_p.h
+++ b/src/quick/handlers/qquicksinglepointhandler_p.h
@@ -74,16 +74,16 @@ Q_SIGNALS:
protected:
QQuickSinglePointHandler(QQuickSinglePointHandlerPrivate &dd, QQuickItem *parent);
- bool wantsPointerEvent(QQuickPointerEvent *event) override;
- void handlePointerEventImpl(QQuickPointerEvent *event) override;
- virtual void handleEventPoint(QQuickEventPoint *point) = 0;
+ bool wantsPointerEvent(QPointerEvent *event) override;
+ void handlePointerEventImpl(QPointerEvent *event) override;
+ virtual void handleEventPoint(QPointerEvent *event, QEventPoint &point) = 0;
- QQuickEventPoint *currentPoint(QQuickPointerEvent *ev);
- void onGrabChanged(QQuickPointerHandler *grabber, QQuickEventPoint::GrabTransition transition, QQuickEventPoint *point) override;
+ QEventPoint &currentPoint(QPointerEvent *ev);
+ void onGrabChanged(QQuickPointerHandler *grabber, QPointingDevice::GrabTransition transition, QPointerEvent *event, QEventPoint &point) override;
void setIgnoreAdditionalPoints(bool v = true);
- void moveTarget(QPointF pos, QQuickEventPoint *point);
+ void moveTarget(QPointF pos, QEventPoint &point);
void setPointId(int id);
diff --git a/src/quick/handlers/qquicktaphandler.cpp b/src/quick/handlers/qquicktaphandler.cpp
index 2fabd39709..c8525cfcb0 100644
--- a/src/quick/handlers/qquicktaphandler.cpp
+++ b/src/quick/handlers/qquicktaphandler.cpp
@@ -97,11 +97,10 @@ QQuickTapHandler::QQuickTapHandler(QQuickItem *parent)
}
}
-bool QQuickTapHandler::wantsEventPoint(QQuickEventPoint *point)
+bool QQuickTapHandler::wantsEventPoint(const QPointerEvent *event, const QEventPoint &point)
{
- if (!point->pointerEvent()->asPointerMouseEvent() &&
- !point->pointerEvent()->asPointerTouchEvent() &&
- !point->pointerEvent()->asPointerTabletEvent() )
+ if (!QQuickWindowPrivate::isMouseEvent(event) && !QQuickWindowPrivate::isTouchEvent(event) &&
+ !QQuickWindowPrivate::isTabletEvent(event))
return false;
// If the user has not violated any constraint, it could be a tap.
// Otherwise we want to give up the grab so that a competing handler
@@ -113,12 +112,12 @@ bool QQuickTapHandler::wantsEventPoint(QQuickEventPoint *point)
m_longPressTimer.stop();
m_holdTimer.invalidate();
}
- switch (point->state()) {
- case QQuickEventPoint::Pressed:
- case QQuickEventPoint::Released:
+ switch (point.state()) {
+ case QEventPoint::Pressed:
+ case QEventPoint::Released:
ret = parentContains(point);
break;
- case QQuickEventPoint::Updated:
+ case QEventPoint::Updated:
switch (m_gesturePolicy) {
case DragThreshold:
ret = !overThreshold && parentContains(point);
@@ -127,35 +126,39 @@ bool QQuickTapHandler::wantsEventPoint(QQuickEventPoint *point)
ret = parentContains(point);
break;
case ReleaseWithinBounds:
- ret = point->pointId() == this->point().id();
+ ret = point.id() == this->point().id();
break;
}
break;
- case QQuickEventPoint::Stationary:
+ case QEventPoint::Stationary:
// If the point hasn't moved since last time, the return value should be the same as last time.
// If we return false here, QQuickPointerHandler::handlePointerEvent() will call setActive(false).
- ret = point->pointId() == this->point().id();
+ ret = point.id() == this->point().id();
+ break;
+ case QEventPoint::Unknown:
break;
}
// If this is the grabber, returning false from this function will cancel the grab,
// so onGrabChanged(this, CancelGrabExclusive, point) and setPressed(false) will be called.
// But when m_gesturePolicy is DragThreshold, we don't get an exclusive grab, but
// we still don't want to be pressed anymore.
- if (!ret && point->pointId() == this->point().id())
- setPressed(false, true, point);
+ if (!ret && point.id() == this->point().id())
+ setPressed(false, true, const_cast<QPointerEvent *>(event), const_cast<QEventPoint &>(point));
return ret;
}
-void QQuickTapHandler::handleEventPoint(QQuickEventPoint *point)
+void QQuickTapHandler::handleEventPoint(QPointerEvent *event, QEventPoint &point)
{
- switch (point->state()) {
- case QQuickEventPoint::Pressed:
- setPressed(true, false, point);
+ switch (point.state()) {
+ case QEventPoint::Pressed:
+ setPressed(true, false, event, point);
break;
- case QQuickEventPoint::Released:
- if ((point->pointerEvent()->buttons() & acceptedButtons()) == Qt::NoButton)
- setPressed(false, false, point);
+ case QEventPoint::Released: {
+ if (QQuickWindowPrivate::isTouchEvent(event) ||
+ (static_cast<const QSinglePointEvent *>(event)->buttons() & acceptedButtons()) == Qt::NoButton)
+ setPressed(false, false, event, point);
break;
+ }
default:
break;
}
@@ -253,7 +256,7 @@ void QQuickTapHandler::setGesturePolicy(QQuickTapHandler::GesturePolicy gestureP
\l gesturePolicy. When the event point is released or the policy is
violated, \e pressed will change to false.
*/
-void QQuickTapHandler::setPressed(bool press, bool cancel, QQuickEventPoint *point)
+void QQuickTapHandler::setPressed(bool press, bool cancel, QPointerEvent *event, QEventPoint &point)
{
if (m_pressed != press) {
qCDebug(lcTapHandler) << objectName() << "pressed" << m_pressed << "->" << press << (cancel ? "CANCEL" : "") << point;
@@ -270,17 +273,17 @@ void QQuickTapHandler::setPressed(bool press, bool cancel, QQuickEventPoint *poi
if (press) {
// on press, grab before emitting changed signals
if (m_gesturePolicy == DragThreshold)
- setPassiveGrab(point, press);
+ setPassiveGrab(event, point, press);
else
- setExclusiveGrab(point, press);
+ setExclusiveGrab(event, point, press);
}
if (!cancel && !press && parentContains(point)) {
- if (point->timeHeld() < longPressThreshold()) {
+ if (point.timeHeld() < longPressThreshold()) {
// Assuming here that pointerEvent()->timestamp() is in ms.
- qreal ts = point->pointerEvent()->timestamp() / 1000.0;
+ qreal ts = event->timestamp() / 1000.0;
if (ts - m_lastTapTimestamp < m_multiTapInterval &&
- QVector2D(point->scenePosition() - m_lastTapPos).lengthSquared() <
- (point->pointerEvent()->device()->type() == QInputDevice::DeviceType::Mouse ?
+ QVector2D(point.scenePosition() - m_lastTapPos).lengthSquared() <
+ (event->device()->type() == QInputDevice::DeviceType::Mouse ?
m_mouseMultiClickDistanceSquared : m_touchMultiTapDistanceSquared))
++m_tapCount;
else
@@ -293,19 +296,19 @@ void QQuickTapHandler::setPressed(bool press, bool cancel, QQuickEventPoint *poi
else if (m_tapCount == 2)
emit doubleTapped(point);
m_lastTapTimestamp = ts;
- m_lastTapPos = point->scenePosition();
+ m_lastTapPos = point.scenePosition();
} else {
- qCDebug(lcTapHandler) << objectName() << "tap threshold" << longPressThreshold() << "exceeded:" << point->timeHeld();
+ qCDebug(lcTapHandler) << objectName() << "tap threshold" << longPressThreshold() << "exceeded:" << point.timeHeld();
}
}
emit pressedChanged();
if (!press && m_gesturePolicy != DragThreshold) {
// on release, ungrab after emitting changed signals
- setExclusiveGrab(point, press);
+ setExclusiveGrab(event, point, press);
}
if (cancel) {
emit canceled(point);
- setExclusiveGrab(point, false);
+ setExclusiveGrab(event, point, false);
// In case there is a filtering parent (Flickable), we should not give up the passive grab,
// so that it can continue to filter future events.
d_func()->reset();
@@ -314,12 +317,13 @@ void QQuickTapHandler::setPressed(bool press, bool cancel, QQuickEventPoint *poi
}
}
-void QQuickTapHandler::onGrabChanged(QQuickPointerHandler *grabber, QQuickEventPoint::GrabTransition transition, QQuickEventPoint *point)
+void QQuickTapHandler::onGrabChanged(QQuickPointerHandler *grabber, QPointingDevice::GrabTransition transition,
+ QPointerEvent *ev, QEventPoint &point)
{
- QQuickSinglePointHandler::onGrabChanged(grabber, transition, point);
- bool isCanceled = transition == QQuickEventPoint::CancelGrabExclusive || transition == QQuickEventPoint::CancelGrabPassive;
- if (grabber == this && (isCanceled || point->state() == QQuickEventPoint::Released))
- setPressed(false, isCanceled, point);
+ QQuickSinglePointHandler::onGrabChanged(grabber, transition, ev, point);
+ bool isCanceled = transition == QPointingDevice::CancelGrabExclusive || transition == QPointingDevice::CancelGrabPassive;
+ if (grabber == this && (isCanceled || point.state() == QEventPoint::Released))
+ setPressed(false, isCanceled, ev, point);
}
void QQuickTapHandler::connectPreRenderSignal(bool conn)
diff --git a/src/quick/handlers/qquicktaphandler_p.h b/src/quick/handlers/qquicktaphandler_p.h
index d5c16b071f..d75547eee2 100644
--- a/src/quick/handlers/qquicktaphandler_p.h
+++ b/src/quick/handlers/qquicktaphandler_p.h
@@ -97,19 +97,20 @@ Q_SIGNALS:
void timeHeldChanged();
void longPressThresholdChanged();
void gesturePolicyChanged();
- void tapped(QQuickEventPoint *eventPoint);
- void singleTapped(QQuickEventPoint *eventPoint);
- void doubleTapped(QQuickEventPoint *eventPoint);
+ void tapped(QEventPoint eventPoint);
+ void singleTapped(QEventPoint eventPoint);
+ void doubleTapped(QEventPoint eventPoint);
void longPressed();
protected:
- void onGrabChanged(QQuickPointerHandler *grabber, QQuickEventPoint::GrabTransition transition, QQuickEventPoint *point) override;
+ void onGrabChanged(QQuickPointerHandler *grabber, QPointingDevice::GrabTransition transition,
+ QPointerEvent *ev, QEventPoint &point) override;
void timerEvent(QTimerEvent *event) override;
- bool wantsEventPoint(QQuickEventPoint *point) override;
- void handleEventPoint(QQuickEventPoint *point) override;
+ bool wantsEventPoint(const QPointerEvent *event, const QEventPoint &point) override;
+ void handleEventPoint(QPointerEvent *event, QEventPoint &point) override;
private:
- void setPressed(bool press, bool cancel, QQuickEventPoint *point);
+ void setPressed(bool press, bool cancel, QPointerEvent *event, QEventPoint &point);
int longPressThresholdMilliseconds() const;
void connectPreRenderSignal(bool conn = true);
void updateTimeHeld();
diff --git a/src/quick/handlers/qquickwheelhandler.cpp b/src/quick/handlers/qquickwheelhandler.cpp
index b55d9aa27b..b9c112a0d2 100644
--- a/src/quick/handlers/qquickwheelhandler.cpp
+++ b/src/quick/handlers/qquickwheelhandler.cpp
@@ -360,60 +360,62 @@ void QQuickWheelHandler::setTargetTransformAroundCursor(bool ttac)
emit targetTransformAroundCursorChanged();
}
-bool QQuickWheelHandler::wantsPointerEvent(QQuickPointerEvent *event)
+bool QQuickWheelHandler::wantsPointerEvent(QPointerEvent *event)
{
if (!event)
return false;
- QQuickPointerScrollEvent *scroll = event->asPointerScrollEvent();
- if (!scroll)
+ if (event->type() != QEvent::Wheel)
return false;
+ QWheelEvent *we = static_cast<QWheelEvent *>(event);
if (!acceptedDevices().testFlag(QPointingDevice::DeviceType::TouchPad)
- && scroll->synthSource() != Qt::MouseEventNotSynthesized)
+ && we->source() != Qt::MouseEventNotSynthesized)
return false;
if (!active()) {
switch (orientation()) {
case Qt::Horizontal:
- if (qFuzzyIsNull(scroll->angleDelta().x()) && qFuzzyIsNull(scroll->pixelDelta().x()))
+ if (!(we->angleDelta().x()) && !(we->pixelDelta().x()))
return false;
break;
case Qt::Vertical:
- if (qFuzzyIsNull(scroll->angleDelta().y()) && qFuzzyIsNull(scroll->pixelDelta().y()))
+ if (!(we->angleDelta().y()) && !(we->pixelDelta().y()))
return false;
break;
}
}
- QQuickEventPoint *point = event->point(0);
- if (QQuickPointerDeviceHandler::wantsPointerEvent(event) && wantsEventPoint(point) && parentContains(point)) {
- setPointId(point->pointId());
+ auto &point = event->point(0);
+ if (QQuickPointerDeviceHandler::wantsPointerEvent(event) && wantsEventPoint(event, point) && parentContains(point)) {
+ setPointId(point.id());
return true;
}
return false;
}
-void QQuickWheelHandler::handleEventPoint(QQuickEventPoint *point)
+void QQuickWheelHandler::handleEventPoint(QPointerEvent *ev, QEventPoint &point)
{
Q_D(QQuickWheelHandler);
- QQuickPointerScrollEvent *event = point->pointerEvent()->asPointerScrollEvent();
+ if (ev->type() != QEvent::Wheel)
+ return;
+ const QWheelEvent *event = static_cast<const QWheelEvent *>(ev);
setActive(true); // ScrollEnd will not happen unless it was already active (see setActive(false) below)
- point->setAccepted();
+ point.setAccepted();
qreal inversion = !d->invertible && event->isInverted() ? -1 : 1;
qreal angleDelta = inversion * qreal(orientation() == Qt::Horizontal ? event->angleDelta().x() :
event->angleDelta().y()) / 8;
d->rotation += angleDelta;
emit rotationChanged();
- emit wheel(event);
+ emit wheel(*event);
if (!d->propertyName.isEmpty() && target()) {
QQuickItem *t = target();
// writing target()'s property is done via QMetaProperty::write() so that any registered interceptors can react.
if (d->propertyName == QLatin1String("scale")) {
qreal multiplier = qPow(d->targetScaleMultiplier, angleDelta * d->rotationScale / 15); // wheel "clicks"
- const QPointF centroidParentPos = t->parentItem()->mapFromScene(point->scenePosition());
+ const QPointF centroidParentPos = t->parentItem()->mapFromScene(point.scenePosition());
const QPointF positionWas = t->position();
const qreal scaleWas = t->scale();
const qreal activePropertyValue = scaleWas * multiplier;
qCDebug(lcWheelHandler) << objectName() << "angle delta" << event->angleDelta() << "pixel delta" << event->pixelDelta()
- << "@" << point->position() << "in parent" << centroidParentPos
- << "in scene" << point->scenePosition()
+ << "@" << point.position() << "in parent" << centroidParentPos
+ << "in scene" << point.scenePosition()
<< "multiplier" << multiplier << "scale" << scaleWas
<< "->" << activePropertyValue;
d->targetMetaProperty().write(t, activePropertyValue);
@@ -429,10 +431,10 @@ void QQuickWheelHandler::handleEventPoint(QQuickEventPoint *point)
const QPointF positionWas = t->position();
const qreal rotationWas = t->rotation();
const qreal activePropertyValue = rotationWas + angleDelta * d->rotationScale;
- const QPointF centroidParentPos = t->parentItem()->mapFromScene(point->scenePosition());
+ const QPointF centroidParentPos = t->parentItem()->mapFromScene(point.scenePosition());
qCDebug(lcWheelHandler) << objectName() << "angle delta" << event->angleDelta() << "pixel delta" << event->pixelDelta()
- << "@" << point->position() << "in parent" << centroidParentPos
- << "in scene" << point->scenePosition() << "rotation" << t->rotation()
+ << "@" << point.position() << "in parent" << centroidParentPos
+ << "in scene" << point.scenePosition() << "rotation" << t->rotation()
<< "->" << activePropertyValue;
d->targetMetaProperty().write(t, activePropertyValue);
if (d->targetTransformAroundCursor) {
@@ -444,8 +446,9 @@ void QQuickWheelHandler::handleEventPoint(QQuickEventPoint *point)
t->setPosition(adjPos);
}
} else {
- qCDebug(lcWheelHandler) << objectName() << "angle delta" << event->angleDelta() << "scaled" << angleDelta << "total" << d->rotation << "pixel delta" << event->pixelDelta()
- << "@" << point->position() << "in scene" << point->scenePosition() << "rotation" << t->rotation();
+ qCDebug(lcWheelHandler) << objectName() << "angle delta" << event->angleDelta() << "scaled" << angleDelta
+ << "total" << d->rotation << "pixel delta" << event->pixelDelta()
+ << "@" << point.position() << "in scene" << point.scenePosition() << "rotation" << t->rotation();
qreal delta = 0;
if (event->hasPixelDelta()) {
delta = inversion * d->rotationScale * qreal(orientation() == Qt::Horizontal ? event->pixelDelta().x() : event->pixelDelta().y());
diff --git a/src/quick/handlers/qquickwheelhandler_p.h b/src/quick/handlers/qquickwheelhandler_p.h
index 021cd23679..b1688a3c2a 100644
--- a/src/quick/handlers/qquickwheelhandler_p.h
+++ b/src/quick/handlers/qquickwheelhandler_p.h
@@ -103,7 +103,7 @@ public:
void setTargetTransformAroundCursor(bool ttac);
Q_SIGNALS:
- void wheel(QQuickPointerScrollEvent *event);
+ void wheel(QWheelEvent event);
void orientationChanged();
void invertibleChanged();
@@ -115,8 +115,8 @@ Q_SIGNALS:
void targetTransformAroundCursorChanged();
protected:
- bool wantsPointerEvent(QQuickPointerEvent *event) override;
- void handleEventPoint(QQuickEventPoint *point) override;
+ bool wantsPointerEvent(QPointerEvent *event) override;
+ void handleEventPoint(QPointerEvent *event, QEventPoint &point) override;
void onTargetChanged(QQuickItem *oldTarget) override;
void onActiveChanged() override;
void timerEvent(QTimerEvent *event) override;
diff --git a/src/quick/items/qquickevents.cpp b/src/quick/items/qquickevents.cpp
index 66e850f59c..ab7b407af5 100644
--- a/src/quick/items/qquickevents.cpp
+++ b/src/quick/items/qquickevents.cpp
@@ -51,7 +51,6 @@
QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcPointerEvents, "qt.quick.pointer.events")
-Q_LOGGING_CATEGORY(lcPtrGrab, "qt.quick.pointer.grab")
/*!
\qmltype KeyEvent
@@ -470,1639 +469,4 @@ Item {
\l inverted always returns false.
*/
-/*!
- \qmltype PointerDevice
- \instantiates QPointingDevice
- \inqmlmodule QtQuick
- \ingroup qtquick-input-events
-
- \brief Provides information about a pointing device.
-
- A pointing device can be a mouse, a touchscreen, or a stylus on a graphics
- tablet.
-
- \sa PointerEvent, PointerHandler
-*/
-
-/*!
- \readonly
- \qmlproperty enumeration QtQuick::PointerDevice::type
-
- This property holds the type of the pointing device.
-
- Valid values are:
-
- \value DeviceType.Unknown
- the device cannot be identified
- \value DeviceType.Mouse
- a mouse
- \value DeviceType.TouchScreen
- a touchscreen providing absolute coordinates
- \value DeviceType.TouchPad
- a trackpad or touchpad providing relative coordinates
- \value DeviceType.Stylus
- a pen-like device
- \value DeviceType.Airbrush
- a stylus with a thumbwheel to adjust
- \l {QTabletEvent::tangentialPressure}{tangentialPressure}
- \value DeviceType.Puck
- a device that is similar to a flat mouse with a
- transparent circle with cross-hairs
- (same as \l {QTabletEvent::Puck} {Puck})
- \value DeviceType.AllDevices
- any of the above; used as a default value for construction
-
- \sa QPointingDevice::DeviceType
-*/
-
-/*!
- \readonly
- \qmlproperty enumeration QtQuick::PointerDevice::pointerType
-
- This property holds a value indicating what is interacting with
- the device. Think of the device as having a planar 2D surface, and
- the value of this property as identifying what interacts with the
- device.
-
- There is some redundancy between this property and \l {PointerDevice::type}.
- If a tocuchscreen is used, then the device is TouchScreen and
- pointerType is Finger (always).
-
- Valid values are:
-
- \value PointerDevice.Generic
- a mouse or something acting like a mouse (the core pointer on X11)
- \value PointerDevice.Finger
- the user's finger
- \value PointerDevice.Pen
- the drawing end of a stylus
- \value PointerDevice.Eraser
- the other end of the stylus (if it has a virtual eraser on the other end)
- \value PointerDevice.Cursor
- a cursor in the pre-computer sense of the word
- \value PointerDevice.AllPointerTypes
- any of the above (used as a default value in constructors)
-*/
-
-/*!
- \readonly
- \qmlproperty enumeration QtQuick::PointerDevice::capabilities
-
- This property holds a bitwise combination of the capabilities of the
- pointing device. It tells you under which conditions events are sent,
- and which properties of PointerEvent are expected to be valid.
-
- Valid values are:
-
- \value Capability.Position
- the \l {QtQuick::EventPoint::position}{position} and
- \l {QtQuick::EventPoint::scenePosition}{scenePosition} properties
- \value Capability.Area
- the \l {QtQuick::EventTouchPoint::ellipseDiameters}{ellipseDiameters} property
- \value Capability.Pressure
- the \l {QtQuick::EventTouchPoint::pressure}{pressure} property
- \value Capability.Velocity
- the \l {QtQuick::EventPoint::velocity}{velocity} property
- \value Capability.Scroll
- a \l {QtQuick::PointerDevice::type}{Mouse} has a wheel, or the
- operating system recognizes scroll gestures on a
- \l {QtQuick::PointerDevice::type}{TouchPad}
- \value Capability.Hover
- events are sent even when no button is pressed, or the finger or stylus
- is not in contact with the surface
- \value Capability.Rotation
- the \l {QtQuick::EventTouchPoint::rotation}{rotation} property
- \value Capability.XTilt
- horizontal angle between a stylus and the axis perpendicular to the surface
- \value Capability.YTilt
- vertical angle between a stylus and the axis perpendicular to the surface
-
- \sa QPointingDevice::capabilities
-*/
-
-
-// debugging helpers
-static const char *pointStateString(const QQuickEventPoint *point)
-{
- static const QMetaEnum stateMetaEnum = point->metaObject()->enumerator(point->metaObject()->indexOfEnumerator("State"));
- return stateMetaEnum.valueToKey(point->state());
-}
-
-static const QString pointDeviceName(const QQuickEventPoint *point)
-{
- auto device = static_cast<const QQuickPointerEvent *>(point->parent())->device();
- QString deviceName = (device ? device->name() : QLatin1String("null device"));
- deviceName.resize(16, u' '); // shorten, and align in case of sequential output
- return deviceName;
-}
-
-/*!
- \qmltype EventPoint
- \qmlabstract
- \instantiates QQuickEventPoint
- \inqmlmodule QtQuick
- \ingroup qtquick-input-events
- \brief Provides information about an individual point within a PointerEvent.
-
- A PointerEvent contains an EventPoint for each point of contact: one corresponding
- to the mouse cursor, or one for each finger touching a touchscreen.
-
- \sa PointerEvent, PointerHandler
-*/
-
-/*!
- \readonly
- \qmlproperty point QtQuick::EventPoint::position
-
- This property holds the coordinates of the position supplied by the event,
- relative to the upper-left corner of the Item which has the PointerHandler.
- If a contact patch is available from the pointing device, this point
- represents its centroid.
-*/
-
-/*!
- \readonly
- \qmlproperty point QtQuick::EventPoint::scenePosition
-
- This property holds the coordinates of the position supplied by the event,
- relative to the scene. If a contact patch is available from the
- \l {QtQuick::PointerEvent::device} {device}, this point represents its centroid.
-*/
-
-/*!
- \readonly
- \qmlproperty point QtQuick::EventPoint::scenePressPosition
-
- This property holds the scene-relative position at which the press event
- (on a touch device) or most recent change in QQuickPointerEvent::buttons()
- (on a mouse or tablet stylus) occurred.
-*/
-
-/*!
- \readonly
- \qmlproperty point QtQuick::EventPoint::sceneGrabPosition
-
- This property holds the scene-relative position at which the EventPoint was
- located when setGrabber() was called most recently.
-*/
-
-/*!
- \readonly
- \qmlproperty vector2d QtQuick::EventPoint::velocity
-
- This property holds average recent velocity: how fast and in which
- direction the event point has been moving recently.
-*/
-
-/*!
- \readonly
- \qmlproperty int QtQuick::EventPoint::state
-
- This property tells what the user is currently doing at this point.
-
- It can be one of:
- \value Pressed
- The user's finger is now pressing a touchscreen, button or stylus
- which was not pressed already
- \value Updated
- The touchpoint or position is being moved, with no change in pressed state
- \value Stationary
- The touchpoint or position is not being moved, and there is also
- no change in pressed state
- \value Released
- The user's finger has now released a touch point, button or stylus
- which was pressed
-*/
-
-/*!
- \readonly
- \qmlproperty int QtQuick::EventPoint::pointId
-
- This property holds the ID of the event, if any.
-
- Touchpoints have automatically-incrementing IDs: each time the user
- presses a finger against the touchscreen, it will be a larger number.
- In other cases, it will be -1.
-
- \sa {QtQuick::EventTouchPoint::uniqueId}{uniqueId}
-*/
-
-/*!
- \readonly
- \qmlproperty bool QtQuick::EventPoint::accepted
-
- Setting \a accepted to true prevents the event from being propagated to
- Items below the PointerHandler's Item.
-
- Generally, if the handler acts on the mouse event, then it should be
- accepted so that items lower in the stacking order do not also respond to
- the same event.
-*/
-
-/*!
- \readonly
- \qmlproperty real QtQuick::EventPoint::timeHeld
-
- This property holds the amount of time in seconds that the button or touchpoint has
- been held. It can be used to detect a "long press", and can drive an
- animation to show progress toward activation of the "long press" action.
-*/
-
-void QQuickEventPoint::reset(QEventPoint::State state, const QPointF &scenePos, int pointId, ulong timestamp, const QVector2D &velocity)
-{
- m_scenePos = scenePos;
- m_pointId = pointId;
- m_accept = false;
- m_state = static_cast<QQuickEventPoint::State>(state);
- m_timestamp = timestamp;
- if (state == QEventPoint::State::Pressed) {
- m_pressTimestamp = timestamp;
- m_scenePressPos = scenePos;
- }
- m_velocity = (Q_LIKELY(velocity.isNull()) ? estimatedVelocity() : velocity);
-}
-
-void QQuickEventPoint::localizePosition(QQuickItem *target)
-{
- if (target)
- m_pos = target->mapFromScene(scenePosition());
- else
- m_pos = QPointF();
-}
-
-/*!
- If this point has an exclusive grabber, returns a pointer to it; else
- returns null, if there is no grabber. The grabber could be either
- an Item or a PointerHandler.
-*/
-QObject *QQuickEventPoint::exclusiveGrabber() const
-{
- return m_exclusiveGrabber.data();
-}
-
-/*!
- Set the given Item or PointerHandler as the exclusive grabber of this point.
- If there was already an exclusive grab, it will be canceled. If there
- were passive grabbers, they will continue to lurk, but the exclusive grab
- is a behavioral override of the passive grab as long as it remains.
- If you already know whether the grabber is to be an Item or a PointerHandler,
- you should instead call setGrabberItem() or setGrabberPointerHandler(),
- because it is slightly more efficient.
-*/
-void QQuickEventPoint::setExclusiveGrabber(QObject *grabber)
-{
- if (QQuickPointerHandler *phGrabber = qmlobject_cast<QQuickPointerHandler *>(grabber))
- setGrabberPointerHandler(phGrabber, true);
- else
- setGrabberItem(static_cast<QQuickItem *>(grabber));
-}
-
-/*!
- If the exclusive grabber of this point is an Item, returns a
- pointer to that Item; else returns null, if there is no grabber or if
- the grabber is a PointerHandler.
-*/
-QQuickItem *QQuickEventPoint::grabberItem() const
-{
- return (m_grabberIsHandler ? nullptr : static_cast<QQuickItem *>(m_exclusiveGrabber.data()));
-}
-
-/*!
- Set the given Item \a grabber as the exclusive grabber of this point.
- If there was already an exclusive grab, it will be canceled. If there
- were passive grabbers, they will continue to lurk, but the exclusive grab
- is a behavioral override of the passive grab as long as it remains.
-*/
-void QQuickEventPoint::setGrabberItem(QQuickItem *grabber)
-{
- if (grabber != m_exclusiveGrabber.data()) {
- QQuickPointerHandler *oldGrabberHandler = grabberPointerHandler();
- if (oldGrabberHandler && !oldGrabberHandler->approveGrabTransition(this, grabber))
- return;
- if (Q_UNLIKELY(lcPtrGrab().isDebugEnabled())) {
- qCDebug(lcPtrGrab) << pointDeviceName(this) << "point" << Qt::hex << m_pointId << pointStateString(this) << "@" << m_scenePos
- << ": grab" << m_exclusiveGrabber << "->" << grabber;
- }
- QQuickItem *oldGrabberItem = grabberItem();
- m_exclusiveGrabber = QPointer<QObject>(grabber);
- m_grabberIsHandler = false;
- m_sceneGrabPos = m_scenePos;
- if (oldGrabberHandler) {
- oldGrabberHandler->onGrabChanged(oldGrabberHandler, (grabber ? CancelGrabExclusive : UngrabExclusive), this);
- } else if (oldGrabberItem && oldGrabberItem != grabber && grabber && grabber->window()) {
- QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(grabber->window());
- windowPriv->sendUngrabEvent(oldGrabberItem, windowPriv->isDeliveringTouchAsMouse());
- }
- if (grabber) {
- for (QPointer<QQuickPointerHandler> passiveGrabber : m_passiveGrabbers)
- if (passiveGrabber)
- passiveGrabber->onGrabChanged(passiveGrabber, OverrideGrabPassive, this);
- }
- }
-}
-
-/*!
- If the exclusive grabber of this point is a PointerHandler, returns a
- pointer to that handler; else returns null, if there is no grabber or if
- the grabber is an Item.
-*/
-QQuickPointerHandler *QQuickEventPoint::grabberPointerHandler() const
-{
- return (m_grabberIsHandler ? static_cast<QQuickPointerHandler *>(m_exclusiveGrabber.data()) : nullptr);
-}
-
-/*!
- Set the given PointerHandler \a grabber as grabber of this point. If \a
- exclusive is true, it will override any other grabs; if false, \a grabber
- will be added to the list of passive grabbers of this point.
-*/
-void QQuickEventPoint::setGrabberPointerHandler(QQuickPointerHandler *grabber, bool exclusive)
-{
- if (Q_UNLIKELY(lcPtrGrab().isDebugEnabled())) {
- if (exclusive) {
- if (m_exclusiveGrabber != grabber)
- qCDebug(lcPtrGrab) << pointDeviceName(this) << "point" << Qt::hex << m_pointId << pointStateString(this)
- << ": grab (exclusive)" << m_exclusiveGrabber << "->" << grabber;
- } else {
- qCDebug(lcPtrGrab) << pointDeviceName(this) << "point" << Qt::hex << m_pointId << pointStateString(this)
- << ": grab (passive)" << grabber;
- }
- }
- if (exclusive) {
- if (grabber != m_exclusiveGrabber.data()) {
- QQuickPointerHandler *oldGrabberHandler = grabberPointerHandler();
- QQuickItem *oldGrabberItem = grabberItem();
- m_exclusiveGrabber = QPointer<QObject>(grabber);
- m_grabberIsHandler = true;
- m_sceneGrabPos = m_scenePos;
- if (grabber) {
- grabber->onGrabChanged(grabber, GrabExclusive, this);
- for (QPointer<QQuickPointerHandler> passiveGrabber : m_passiveGrabbers) {
- if (!passiveGrabber.isNull() && passiveGrabber != grabber)
- passiveGrabber->onGrabChanged(grabber, OverrideGrabPassive, this);
- }
- }
- if (oldGrabberHandler) {
- oldGrabberHandler->onGrabChanged(oldGrabberHandler, (grabber ? CancelGrabExclusive : UngrabExclusive), this);
- } else if (oldGrabberItem) {
- if (pointerEvent()->asPointerTouchEvent())
- oldGrabberItem->touchUngrabEvent();
- else if (pointerEvent()->asPointerMouseEvent())
- oldGrabberItem->mouseUngrabEvent();
- }
- // touchUngrabEvent() can result in the grabber being set to null (MPTA does that, for example).
- // So set it again to ensure that final state is what we want.
- m_exclusiveGrabber = QPointer<QObject>(grabber);
- m_grabberIsHandler = true;
- m_sceneGrabPos = m_scenePos;
- }
- } else {
- if (!grabber) {
- qDebug() << "can't set passive grabber to null";
- return;
- }
- auto ptr = QPointer<QQuickPointerHandler>(grabber);
- if (!m_passiveGrabbers.contains(ptr)) {
- m_passiveGrabbers.append(ptr);
- grabber->onGrabChanged(grabber, GrabPassive, this);
- }
- }
-}
-
-/*!
- If this point has an existing exclusive grabber (Item or PointerHandler),
- inform the grabber that its grab is canceled, and remove it as grabber.
- This normally happens when the grab is stolen by another Item.
-*/
-void QQuickEventPoint::cancelExclusiveGrab()
-{
- if (m_exclusiveGrabber.isNull())
- qWarning("cancelGrab: no grabber");
- else
- cancelExclusiveGrabImpl();
-}
-
-void QQuickEventPoint::cancelExclusiveGrabImpl(QTouchEvent *cancelEvent)
-{
- if (m_exclusiveGrabber.isNull())
- return;
- if (Q_UNLIKELY(lcPtrGrab().isDebugEnabled())) {
- qCDebug(lcPtrGrab) << pointDeviceName(this) << "point" << Qt::hex << m_pointId << pointStateString(this)
- << ": grab (exclusive)" << m_exclusiveGrabber << "-> nullptr";
- }
- if (auto handler = grabberPointerHandler()) {
- handler->onGrabChanged(handler, CancelGrabExclusive, this);
- } else if (auto item = grabberItem()) {
- if (cancelEvent)
- QCoreApplication::sendEvent(item, cancelEvent);
- else
- item->touchUngrabEvent();
- }
- m_exclusiveGrabber.clear();
-}
-
-/*!
- If this point has the given \a handler as a passive grabber,
- inform the grabber that its grab is canceled, and remove it as grabber.
- This normally happens when another Item or PointerHandler does an exclusive grab.
-*/
-void QQuickEventPoint::cancelPassiveGrab(QQuickPointerHandler *handler)
-{
- if (removePassiveGrabber(handler)) {
- if (Q_UNLIKELY(lcPtrGrab().isDebugEnabled())) {
- qCDebug(lcPtrGrab) << pointDeviceName(this) << "point" << Qt::hex << m_pointId << pointStateString(this)
- << ": grab (passive)" << handler << "removed";
- }
- handler->onGrabChanged(handler, CancelGrabPassive, this);
- }
-}
-
-/*!
- If this point has the given \a handler as a passive grabber, remove it as grabber.
- Returns true if it was removed, false if it wasn't a grabber.
-*/
-bool QQuickEventPoint::removePassiveGrabber(QQuickPointerHandler *handler)
-{
- return m_passiveGrabbers.removeOne(handler);
-}
-
-/*!
- If the given \a handler is grabbing this point passively, exclusively
- or both, cancel the grab and remove it as grabber.
- This normally happens when the handler decides that the behavior of this
- point can no longer satisfy the handler's behavioral constraints within
- the remainder of the gesture which the user is performing: for example
- the handler tries to detect a tap but a drag is occurring instead, or
- it tries to detect a drag in one direction but the drag is going in
- another direction. In such cases the handler no longer needs or wants
- to be informed of any further movements of this point.
-*/
-void QQuickEventPoint::cancelAllGrabs(QQuickPointerHandler *handler)
-{
- if (m_exclusiveGrabber == handler) {
- handler->onGrabChanged(handler, CancelGrabExclusive, this);
- m_exclusiveGrabber.clear();
- }
- cancelPassiveGrab(handler);
-}
-
-/*!
- Sets this point as \a accepted (true) or rejected (false).
-
- During delivery of the current event to the Items in the scene, each Item
- or Pointer Handler should accept the points for which it is taking
- responsibility. As soon as all points within the event are accepted, event
- propagation stops. However accepting the point does not imply any kind of
- grab, passive or exclusive.
-
- \sa setExclusiveGrabber, QQuickPointerHandler::setPassiveGrab, QQuickPointerHandler::setExclusiveGrab
-*/
-void QQuickEventPoint::setAccepted(bool accepted)
-{
- if (m_accept != accepted) {
- qCDebug(lcPointerEvents) << this << m_accept << "->" << accepted;
- m_accept = accepted;
- }
-}
-
-
-/*!
- \qmltype EventTouchPoint
- \qmlabstract
- \instantiates QQuickEventTouchPoint
- \inqmlmodule QtQuick
- \ingroup qtquick-input-events
- \brief Provides information about an individual touch point within a PointerEvent.
-
- \sa PointerEvent, PointerHandler
-*/
-
-/*!
- \readonly
- \qmlproperty QPointerUniqueId QtQuick::EventTouchPoint::uniqueId
-
- This property holds the unique ID of the fiducial or stylus in use, if any.
-
- On touchscreens that can track physical objects (such as knobs or game
- pieces) in addition to fingers, each object usually has a unique ID.
- Likewise, each stylus that can be used with a graphics tablet usually has a
- unique serial number. Qt so far only supports numeric IDs. You can get the
- actual number as uniqueId.numeric, but that is a device-specific detail.
- In the future, there may be support for non-numeric IDs, so you should
- not assume that the number is meaningful.
-
- If you need to identify specific objects, your application should provide
- UI for registering objects and mapping them to functionality: allow the
- user to select a meaning, virtual tool, or action, prompt the user to bring
- the object into proximity, and store a mapping from uniqueId to its
- purpose, for example in \l Settings.
-*/
-
-/*!
- \readonly
- \qmlproperty qreal QtQuick::EventTouchPoint::rotation
-
- This property holds the rotation angle of the stylus on a graphics tablet
- or the contact patch of a touchpoint on a touchscreen.
-
- It is valid only with certain tablet stylus devices and touchscreens that
- can measure the rotation angle. Otherwise, it will be zero.
-*/
-
-/*!
- \readonly
- \qmlproperty qreal QtQuick::EventTouchPoint::pressure
-
- This property tells how hard the user is pressing the stylus on a graphics
- tablet or the finger against a touchscreen, in the range from \c 0 (no
- measurable pressure) to \c 1.0 (maximum pressure which the device can
- measure).
-
- It is valid only with certain tablets and touchscreens that can measure
- pressure. Otherwise, it will be \c 1.0 when pressed.
-*/
-
-/*!
- \readonly
- \qmlproperty size QtQuick::EventTouchPoint::ellipseDiameters
-
- This property holds the diameters of the contact patch, if the event
- comes from a touchpoint and the \l {QtQuick::PointerEvent::device} {device}
- provides this information.
-
- A touchpoint is modeled as an elliptical area where the finger is
- pressed against the touchscreen. (In fact, it could also be
- modeled as a bitmap; but in that case we expect an elliptical
- bounding estimate to be fitted to the contact patch before the
- event is sent.) The harder the user presses, the larger the
- contact patch; so, these diameters provide an alternate way of
- detecting pressure, in case the device does not include a separate
- pressure sensor. The ellipse is centered on
- \l {QtQuick::EventPoint::scenePosition} {scenePosition}
- (\l {QtQuick::EventPoint::position} {position} in the PointerHandler's
- Item's local coordinates). The \l rotation property provides the
- rotation of the ellipse, if known. It is expected that if the
- \l rotation is zero, the verticalDiameter of the ellipse is the
- larger one (the major axis), because of the usual hand position,
- reaching upward or outward across the surface.
-
- If the contact patch is unknown, or the \l {QtQuick::PointerEvent::device} {device}
- is not a touchscreen, these values will be zero.
-*/
-
-QQuickEventTouchPoint::QQuickEventTouchPoint(QQuickPointerTouchEvent *parent)
- : QQuickEventPoint(parent), m_rotation(0), m_pressure(0)
-{}
-
-void QQuickEventTouchPoint::reset(const QEventPoint &tp, ulong timestamp)
-{
- QQuickEventPoint::reset(tp.state(), tp.scenePosition(), tp.id(), timestamp, tp.velocity());
- m_exclusiveGrabber.clear();
- m_passiveGrabbers.clear();
- m_rotation = tp.rotation();
- m_pressure = tp.pressure();
- m_ellipseDiameters = tp.ellipseDiameters();
- m_uniqueId = tp.uniqueId();
-}
-
-struct PointVelocityData {
- QVector2D velocity;
- QPointF pos;
- ulong timestamp = 0;
-};
-
-typedef QMap<quint64, PointVelocityData> PointDataForPointIdMap;
-Q_GLOBAL_STATIC(PointDataForPointIdMap, g_previousPointData)
-static const int PointVelocityAgeLimit = 500; // milliseconds
-
-/*!
- \internal
- Estimates the velocity based on a weighted average of all previous velocities.
- The older the velocity is, the less significant it becomes for the estimate.
-*/
-QVector2D QQuickEventPoint::estimatedVelocity() const
-{
- auto prevPointIt = g_previousPointData->find(m_pointId);
- auto end = g_previousPointData->end();
- if (prevPointIt == end) {
- // cleanup events older than PointVelocityAgeLimit
- for (auto it = g_previousPointData->begin(); it != end; ) {
- if (m_timestamp - it->timestamp > PointVelocityAgeLimit)
- it = g_previousPointData->erase(it);
- else
- ++it;
- }
- prevPointIt = g_previousPointData->insert(m_pointId, PointVelocityData());
- }
-
- auto &prevPoint = prevPointIt.value();
- const ulong timeElapsed = m_timestamp - prevPoint.timestamp;
- if (timeElapsed == 0) // in case we call estimatedVelocity() twice on the same QQuickEventPoint
- return m_velocity;
-
- QVector2D newVelocity;
- if (prevPoint.timestamp != 0)
- newVelocity = QVector2D(m_scenePos - prevPoint.pos) / timeElapsed;
-
- // VERY simple kalman filter: does a weighted average
- // where the older velocities get less and less significant
- static const float KalmanGain = 0.7f;
- QVector2D filteredVelocity = newVelocity * KalmanGain + m_velocity * (1.0f - KalmanGain);
-
- prevPoint.velocity = filteredVelocity;
- prevPoint.pos = m_scenePos;
- prevPoint.timestamp = m_timestamp;
- return filteredVelocity;
-}
-
-/*!
- \qmltype PointerEvent
- \instantiates QQuickPointerEvent
- \inqmlmodule QtQuick
- \ingroup qtquick-input-events
-
- \brief Provides information about an event from a pointing device.
-
- A PointerEvent is an event describing contact or movement across a surface,
- provided by a mouse, a touchpoint (single finger on a touchscreen), or a
- stylus on a graphics tablet. The \l {QtQuick::PointerEvent::device} {device}
- property provides more information about where the event came from.
-
- \sa PointerHandler
-
- \image touchpoint-metrics.png
-*/
-
-/*!
- \internal
- \class QQuickPointerEvent
-
- QQuickPointerEvent is used as a long-lived object to store data related to
- an event from a pointing device, such as a mouse, touch or tablet event,
- during event delivery. It also provides properties which may be used later
- to expose the event to QML, the same as is done with QQuickMouseEvent,
- QQuickTouchPoint, QQuickKeyEvent, etc. Since only one event can be
- delivered at a time, this class is effectively a singleton. We don't worry
- about the QObject overhead because the instances are long-lived: we don't
- dynamically create and destroy objects of this type for each event.
-*/
-
-/*!
- \readonly
- \qmlproperty enumeration QtQuick::PointerEvent::button
-
- This property holds the \l {Qt::MouseButton}{button} that caused the event,
- if any. If the \l {QtQuick::PointerEvent::device} {device} does not have
- buttons, or the event is a hover event, it will be \c Qt.NoButton.
-*/
-
-/*!
- \readonly
- \qmlproperty int QtQuick::PointerEvent::buttons
-
- This property holds the combination of mouse or stylus
- \l {Qt::MouseButton}{buttons} pressed when the event was generated. For move
- events, this is all buttons that are pressed down. For press events, this
- includes the button that caused the event, as well as any others that were
- already held. For release events, this excludes the button that caused the
- event.
-*/
-
-/*!
- \readonly
- \qmlproperty int QtQuick::PointerEvent::modifiers
-
- This property holds the \l {Qt::KeyboardModifier}{keyboard modifier} flags
- that existed immediately before the event occurred.
-
- It contains a bitwise combination of the following flags:
- \value Qt.NoModifier
- No modifier key is pressed.
- \value Qt.ShiftModifier
- A Shift key on the keyboard is pressed.
- \value Qt.ControlModifier
- A Ctrl key on the keyboard is pressed.
- \value Qt.AltModifier
- An Alt key on the keyboard is pressed.
- \value Qt.MetaModifier
- A Meta key on the keyboard is pressed.
- \value Qt.KeypadModifier
- A keypad button is pressed.
-
- For example, to react to a Shift key + Left mouse button click:
- \qml
- Item {
- TapHandler {
- onTapped: {
- if ((event.button == Qt.LeftButton) && (event.modifiers & Qt.ShiftModifier))
- doSomething();
- }
- }
- }
- \endqml
-*/
-
-/*!
- \readonly
- \qmlproperty PointerDevice QtQuick::PointerEvent::device
-
- This property holds the device that generated the event.
-*/
-
-QQuickPointerEvent::~QQuickPointerEvent()
-{}
-
-QQuickPointerMouseEvent::QQuickPointerMouseEvent(QObject *parent, const QPointingDevice *device)
- : QQuickSinglePointEvent(parent, device)
-{
- m_point = new QQuickEventPoint(this);
-}
-
-QQuickPointerEvent *QQuickPointerMouseEvent::reset(QEvent *event)
-{
- auto ev = static_cast<QMouseEvent*>(event);
- m_event = ev;
- if (!event)
- return this;
-
- QQuickPointerHandlerPrivate::deviceDeliveryTargets(ev->device()).clear();
- m_button = ev->button();
- m_pressedButtons = ev->buttons();
- QEventPoint::State state = QEventPoint::State::Stationary;
- switch (ev->type()) {
- case QEvent::MouseButtonPress:
- m_point->clearPassiveGrabbers();
- Q_FALLTHROUGH();
- case QEvent::MouseButtonDblClick:
- state = QEventPoint::State::Pressed;
- break;
- case QEvent::MouseButtonRelease:
- state = QEventPoint::State::Released;
- break;
- case QEvent::MouseMove:
- state = QEventPoint::State::Updated;
- break;
- default:
- break;
- }
- m_point->reset(state, ev->scenePosition(), ev->point(0).id(), ev->timestamp());
- return this;
-}
-
-void QQuickSinglePointEvent::localize(QQuickItem *target)
-{
- m_point->localizePosition(target);
-}
-
-QQuickPointerEvent *QQuickPointerTouchEvent::reset(QEvent *event)
-{
- auto ev = static_cast<QTouchEvent*>(event);
- m_event = ev;
- if (!event)
- return this;
-
- QQuickPointerHandlerPrivate::deviceDeliveryTargets(ev->device()).clear();
- m_button = Qt::NoButton;
- m_pressedButtons = Qt::NoButton;
-
- const QList<QEventPoint> &tps = ev->touchPoints();
- int newPointCount = tps.count();
- m_touchPoints.reserve(newPointCount);
-
- for (int i = m_touchPoints.size(); i < newPointCount; ++i)
- m_touchPoints.insert(i, new QQuickEventTouchPoint(this));
-
- // Make sure the grabbers and on-pressed values are right from one event to the next
- struct ToPreserve {
- int pointId; // just for double-checking
- ulong pressTimestamp;
- QPointF scenePressPos;
- QPointF sceneGrabPos;
- QObject * grabber;
- QVector <QPointer <QQuickPointerHandler> > passiveGrabbers;
-
- ToPreserve() : pointId(0), pressTimestamp(0), grabber(nullptr) {}
- };
- QVector<ToPreserve> preserves(newPointCount); // jar of pickled touchpoints, in order of points in the _new_ event
-
- // Copy stuff we need to preserve, because the order of points might have changed in the event.
- // The ID is all that we can rely on (release might remove the first point etc).
- for (int i = 0; i < newPointCount; ++i) {
- int pid = tps.at(i).id();
- if (auto point = pointById(pid)) {
- preserves[i].pointId = pid;
- preserves[i].pressTimestamp = point->m_pressTimestamp;
- preserves[i].scenePressPos = point->scenePressPosition();
- preserves[i].sceneGrabPos = point->sceneGrabPosition();
- preserves[i].grabber = point->exclusiveGrabber();
- preserves[i].passiveGrabbers = point->passiveGrabbers();
- }
- }
-
- for (int i = 0; i < newPointCount; ++i) {
- auto point = m_touchPoints.at(i);
- point->reset(tps.at(i), ev->timestamp());
- const auto &preserved = preserves.at(i);
- if (point->state() == QQuickEventPoint::Pressed) {
- if (preserved.grabber)
- qWarning() << "TouchPointPressed without previous release event" << point;
- point->setGrabberItem(nullptr);
- point->clearPassiveGrabbers();
- } else {
- // Restore the grabbers without notifying (don't call onGrabChanged)
- Q_ASSERT(preserved.pointId == 0 || preserved.pointId == point->pointId());
- point->m_pressTimestamp = preserved.pressTimestamp;
- point->m_scenePressPos = preserved.scenePressPos;
- point->m_sceneGrabPos = preserved.sceneGrabPos;
- point->m_exclusiveGrabber = preserved.grabber;
- point->m_grabberIsHandler = (qmlobject_cast<QQuickPointerHandler *>(point->m_exclusiveGrabber) != nullptr);
- point->m_passiveGrabbers = preserved.passiveGrabbers;
- }
- }
- m_pointCount = newPointCount;
- return this;
-}
-
-void QQuickPointerTouchEvent::localize(QQuickItem *target)
-{
- for (auto point : qAsConst(m_touchPoints))
- point->localizePosition(target);
-}
-
-#if QT_CONFIG(gestures)
-QQuickPointerNativeGestureEvent::QQuickPointerNativeGestureEvent(QObject *parent, const QPointingDevice *device)
- : QQuickSinglePointEvent(parent, device)
-{
- m_point = new QQuickEventPoint(this);
-}
-
-QQuickPointerEvent *QQuickPointerNativeGestureEvent::reset(QEvent *event)
-{
- auto ev = static_cast<QNativeGestureEvent*>(event);
- m_event = ev;
- if (!event)
- return this;
-
- QQuickPointerHandlerPrivate::deviceDeliveryTargets(ev->device()).clear();
- QEventPoint::State state = QEventPoint::State::Updated;
- switch (type()) {
- case Qt::BeginNativeGesture:
- state = QEventPoint::State::Pressed;
- break;
- case Qt::EndNativeGesture:
- state = QEventPoint::State::Released;
- break;
- default:
- break;
- }
- m_point->reset(state, ev->scenePosition(), ev->point(0).id(), ev->timestamp());
- return this;
-}
-#endif // QT_CONFIG(gestures)
-
-QQuickEventPoint *QQuickSinglePointEvent::point(int i) const
-{
- if (i == 0)
- return m_point;
- return nullptr;
-}
-
-
-/*!
- \qmltype PointerScrollEvent
- \instantiates QQuickPointerScrollEvent
- \inqmlmodule QtQuick
- \ingroup qtquick-input-events
- \brief Provides information about a scrolling event, such as from a mouse wheel.
-
- \sa WheelHandler
-*/
-
-/*!
- \internal
- \class QQuickPointerScrollEvent
-*/
-
-/*!
- \readonly
- \qmlproperty PointerDevice QtQuick::PointerScrollEvent::device
-
- This property holds the device that generated the event.
-*/
-
-/*!
- \qmlproperty int QtQuick::PointerScrollEvent::buttons
-
- This property holds the mouse buttons pressed when the wheel event was generated.
-
- It contains a bitwise combination of:
- \list
- \li \l {Qt::LeftButton} {Qt.LeftButton}
- \li \l {Qt::RightButton} {Qt.RightButton}
- \li \l {Qt::MiddleButton} {Qt.MiddleButton}
- \endlist
-*/
-
-/*!
- \readonly
- \qmlproperty int QtQuick::PointerScrollEvent::modifiers
-
- This property holds the \l {Qt::KeyboardModifier}{keyboard modifier} keys
- that were pressed immediately before the event occurred.
-
- It contains a bitwise combination of the following flags:
- \value Qt.NoModifier
- No modifier key is pressed.
- \value Qt.ShiftModifier
- A Shift key on the keyboard is pressed.
- \value Qt.ControlModifier
- A Ctrl key on the keyboard is pressed.
- \value Qt.AltModifier
- An Alt key on the keyboard is pressed.
- \value Qt.MetaModifier
- A Meta key on the keyboard is pressed.
- \value Qt.KeypadModifier
- A keypad button is pressed.
-
- For example, to react to a Shift key + Left mouse button click:
- \qml
- Item {
- TapHandler {
- onTapped: {
- if ((event.button == Qt.LeftButton) && (event.modifiers & Qt.ShiftModifier))
- doSomething();
- }
- }
- }
- \endqml
-*/
-
-/*!
- \qmlproperty point QtQuick::PointerScrollEvent::angleDelta
-
- This property holds the distance that the wheel is rotated in wheel degrees.
- The x and y cordinate of this property holds the delta in horizontal and
- vertical orientation.
-
- A positive value indicates that the wheel was rotated up/right;
- a negative value indicates that the wheel was rotated down/left.
-
- Most mouse types work in steps of 15 degrees, in which case the delta value is a
- multiple of 120; i.e., 120 units * 1/8 = 15 degrees.
-*/
-
-/*!
- \qmlproperty point QtQuick::PointerScrollEvent::pixelDelta
-
- This property holds the delta in screen pixels and is available in platforms that
- have high-resolution trackpads, such as \macos.
- The x and y coordinates of this property hold the delta in horizontal and
- vertical orientation. The value should be used directly to scroll content on screen.
-
- For platforms without high-resolution touchpad support, pixelDelta will
- always be (0,0), and angleDelta should be used instead.
-*/
-
-/*!
- \qmlproperty bool QtQuick::PointerScrollEvent::hasAngleDelta
-
- Returns whether the \l angleDelta property has a non-null value.
-*/
-
-/*!
- \qmlproperty bool QtQuick::PointerScrollEvent::hasPixelDelta
-
- Returns whether the \l pixelDelta property has a non-null value.
-*/
-
-/*!
- \qmlproperty bool QtQuick::PointerScrollEvent::inverted
-
- Returns whether the delta values delivered with the event are inverted.
-
- Normally, a vertical wheel will produce a PointerScrollEvent with positive delta
- values if the top of the wheel is rotating away from the hand operating it.
- Similarly, a horizontal wheel movement will produce a PointerScrollEvent with
- positive delta values if the top of the wheel is moved to the left.
-
- However, on some platforms this is configurable, so that the same
- operations described above will produce negative delta values (but with the
- same magnitude). In a QML component (such as a tumbler or a slider) where
- it is appropriate to synchronize the movement or rotation of an item with
- the direction of the wheel, regardless of the system settings, the wheel
- event handler can use the inverted property to decide whether to negate the
- \l angleDelta or \l pixelDelta values.
-
- \note Many platforms provide no such information. On such platforms,
- \c inverted always returns false.
-*/
-QQuickPointerScrollEvent::QQuickPointerScrollEvent(QObject *parent, const QPointingDevice *device)
- : QQuickSinglePointEvent(parent, device)
-{
- m_point = new QQuickEventPoint(this);
-}
-
-QQuickPointerEvent *QQuickPointerScrollEvent::reset(QEvent *event)
-{
- m_event = static_cast<QPointerEvent*>(event);
- if (!event)
- return this;
-#if QT_CONFIG(wheelevent)
- if (event->type() == QEvent::Wheel) {
- auto ev = static_cast<QWheelEvent*>(event);
- QQuickPointerHandlerPrivate::deviceDeliveryTargets(ev->device()).clear();
- // m_button = Qt::NoButton;
- m_pressedButtons = ev->buttons();
- m_angleDelta = QVector2D(ev->angleDelta());
- m_pixelDelta = QVector2D(ev->pixelDelta());
- m_phase = ev->phase();
- m_synthSource = ev->source();
- m_inverted = ev->inverted();
- m_point->reset(QEventPoint::State::Updated, ev->position(), ev->point(0).id(), ev->timestamp());
- }
-#endif
- // TODO else if (event->type() == QEvent::Scroll) ...
- return this;
-}
-
-void QQuickPointerScrollEvent::localize(QQuickItem *target)
-{
- m_point->localizePosition(target);
-}
-
-QQuickEventPoint *QQuickPointerTouchEvent::point(int i) const
-{
- if (i >= 0 && i < m_pointCount)
- return m_touchPoints.at(i);
- return nullptr;
-}
-
-QQuickEventPoint::QQuickEventPoint(QQuickPointerEvent *parent)
- : QObject(parent), m_pointId(0), m_exclusiveGrabber(nullptr), m_timestamp(0), m_pressTimestamp(0),
- m_state(QQuickEventPoint::Released), m_accept(false), m_grabberIsHandler(false)
-{
- Q_UNUSED(m_reserved);
-}
-
-QQuickPointerEvent *QQuickEventPoint::pointerEvent() const
-{
- return static_cast<QQuickPointerEvent *>(parent());
-}
-
-bool QQuickSinglePointEvent::allPointsAccepted() const
-{
- return m_point->isAccepted();
-}
-
-bool QQuickSinglePointEvent::allUpdatedPointsAccepted() const
-{
- return m_point->state() == QQuickEventPoint::Pressed || m_point->isAccepted();
-}
-
-bool QQuickSinglePointEvent::allPointsGrabbed() const
-{
- return m_point->exclusiveGrabber() != nullptr;
-}
-
-QMouseEvent *QQuickPointerMouseEvent::asMouseEvent(const QPointF &localPos) const
-{
- if (!m_event)
- return nullptr;
- static_cast<QMutableSinglePointEvent *>(m_event)->mutablePoint().setPosition(localPos);
- return static_cast<QMouseEvent *>(m_event);
-}
-
-/*!
- Returns the exclusive grabber of this event, if any, in a vector.
-*/
-QVector<QObject *> QQuickSinglePointEvent::exclusiveGrabbers() const
-{
- QVector<QObject *> result;
- if (QObject *grabber = m_point->exclusiveGrabber())
- result << grabber;
- return result;
-}
-
-/*!
- Remove all passive and exclusive grabbers of this event, without notifying.
-*/
-void QQuickSinglePointEvent::clearGrabbers() const
-{
- m_point->setGrabberItem(nullptr);
- m_point->clearPassiveGrabbers();
-}
-
-/*!
- Returns whether the given \a handler is the exclusive grabber of this event.
-*/
-bool QQuickSinglePointEvent::hasExclusiveGrabber(const QQuickPointerHandler *handler) const
-{
- return handler && (m_point->exclusiveGrabber() == handler);
-}
-
-bool QQuickPointerMouseEvent::isPressEvent() const
-{
- if (!m_event)
- return false;
- auto me = static_cast<QMouseEvent*>(m_event);
- return ((me->type() == QEvent::MouseButtonPress || me->type() == QEvent::MouseButtonDblClick) &&
- (me->buttons() & me->button()) == me->buttons());
-}
-
-bool QQuickPointerMouseEvent::isDoubleClickEvent() const
-{
- if (!m_event)
- return false;
- auto me = static_cast<QMouseEvent*>(m_event);
- return (me->type() == QEvent::MouseButtonDblClick);
-}
-
-bool QQuickPointerMouseEvent::isUpdateEvent() const
-{
- if (!m_event)
- return false;
- auto me = static_cast<QMouseEvent*>(m_event);
- return me->type() == QEvent::MouseMove;
-}
-
-bool QQuickPointerMouseEvent::isReleaseEvent() const
-{
- if (!m_event)
- return false;
- auto me = static_cast<QMouseEvent*>(m_event);
- return me && me->type() == QEvent::MouseButtonRelease;
-}
-
-bool QQuickPointerTouchEvent::allPointsAccepted() const
-{
- for (int i = 0; i < m_pointCount; ++i) {
- if (!m_touchPoints.at(i)->isAccepted())
- return false;
- }
- return true;
-}
-
-bool QQuickPointerTouchEvent::allUpdatedPointsAccepted() const
-{
- for (int i = 0; i < m_pointCount; ++i) {
- auto point = m_touchPoints.at(i);
- if (point->state() != QQuickEventPoint::Pressed && !point->isAccepted())
- return false;
- }
- return true;
-}
-
-bool QQuickPointerTouchEvent::allPointsGrabbed() const
-{
- for (int i = 0; i < m_pointCount; ++i) {
- if (!m_touchPoints.at(i)->exclusiveGrabber())
- return false;
- }
- return true;
-}
-
-/*!
- Returns the exclusive grabbers of all points in this event, if any, in a vector.
-*/
-QVector<QObject *> QQuickPointerTouchEvent::exclusiveGrabbers() const
-{
- QVector<QObject *> result;
- for (int i = 0; i < m_pointCount; ++i) {
- if (QObject *grabber = m_touchPoints.at(i)->exclusiveGrabber()) {
- if (!result.contains(grabber))
- result << grabber;
- }
- }
- return result;
-}
-
-/*!
- Remove all passive and exclusive grabbers of all touchpoints in this event,
- without notifying.
-*/
-void QQuickPointerTouchEvent::clearGrabbers() const
-{
- for (auto point: m_touchPoints) {
- point->setGrabberItem(nullptr);
- point->clearPassiveGrabbers();
- }
-}
-
-QEventPoint::States QQuickPointerTouchEvent::touchPointStates() const
-{
- return m_event
- ? static_cast<QTouchEvent*>(m_event)->touchPointStates()
- : QEventPoint::States();
-}
-
-/*!
- Returns whether the given \a handler is the exclusive grabber of any
- touchpoint within this event.
-*/
-bool QQuickPointerTouchEvent::hasExclusiveGrabber(const QQuickPointerHandler *handler) const
-{
- for (auto point: m_touchPoints)
- if (point->exclusiveGrabber() == handler)
- return true;
- return false;
-}
-
-bool QQuickPointerTouchEvent::isPressEvent() const
-{
- return touchPointStates() & QEventPoint::State::Pressed;
-}
-
-bool QQuickPointerTouchEvent::isUpdateEvent() const
-{
- return touchPointStates() & (QEventPoint::State::Updated | QEventPoint::State::Stationary);
-}
-
-bool QQuickPointerTouchEvent::isReleaseEvent() const
-{
- return touchPointStates() & QEventPoint::State::Released;
-}
-
-QVector<QPointF> QQuickPointerEvent::unacceptedPressedPointScenePositions() const
-{
- QVector<QPointF> points;
- for (int i = 0; i < pointCount(); ++i) {
- if (!point(i)->isAccepted() && point(i)->state() == QQuickEventPoint::Pressed)
- points << point(i)->scenePosition();
- }
- return points;
-}
-
-/*!
- \internal
- Populate the reusable synth-mouse event from one touchpoint.
- It's required that isTouchEvent() be true when this is called.
- If the touchpoint cannot be found, this returns nullptr.
- Ownership of the event is NOT transferred to the caller.
-*/
-QMouseEvent *QQuickPointerTouchEvent::syntheticMouseEvent(int pointID, QQuickItem *relativeTo) const
-{
- const QEventPoint *p = touchPointById(pointID);
- if (!p)
- return nullptr;
- QEvent::Type type;
- Qt::MouseButton buttons = Qt::LeftButton;
- switch (p->state()) {
- case QEventPoint::State::Pressed:
- type = QEvent::MouseButtonPress;
- break;
- case QEventPoint::State::Updated:
- case QEventPoint::State::Stationary:
- type = QEvent::MouseMove;
- break;
- case QEventPoint::State::Released:
- type = QEvent::MouseButtonRelease;
- buttons = Qt::NoButton;
- break;
- default:
- Q_ASSERT(false);
- return nullptr;
- }
- m_synthMouseEvent = QMouseEvent(type, relativeTo->mapFromScene(p->scenePosition()),
- p->scenePosition(), p->globalPosition(), Qt::LeftButton, buttons, m_event->modifiers(),
- Qt::MouseEventSynthesizedByQt, device());
- m_synthMouseEvent.setAccepted(true);
- m_synthMouseEvent.setTimestamp(m_event->timestamp());
- // ### Qt 6: try to always have valid velocity in every QEventPoint (either from the platform, or synthesized in QtGui).
- // QQuickFlickablePrivate::handleMouseMoveEvent() checks for QInputDevice::Capability::Velocity
- // and if it is set, then it does not need to do its own velocity calculations.
- // But because m_synthMouseEvent gets the same device() where the (usually) touch event came from,
- // the capability won't be set, in practice, until we have the velocity in place.
- QMutableSinglePointEvent::from(m_synthMouseEvent).mutablePoint().setVelocity(p->velocity());
- return &m_synthMouseEvent;
-}
-
-#if QT_CONFIG(tabletevent)
-QQuickPointerTabletEvent::QQuickPointerTabletEvent(QObject *parent, const QPointingDevice *device)
- : QQuickSinglePointEvent(parent, device)
-{
- m_point = new QQuickEventTabletPoint(this);
-}
-
-QQuickPointerEvent *QQuickPointerTabletEvent::reset(QEvent *event)
-{
- auto ev = static_cast<QTabletEvent*>(event);
- m_event = ev;
- if (!event)
- return this;
-
- QQuickPointerHandlerPrivate::deviceDeliveryTargets(ev->device()).clear();
- m_button = ev->button();
- m_pressedButtons = ev->buttons();
- static_cast<QQuickEventTabletPoint *>(m_point)->reset(ev);
- return this;
-}
-
-QQuickEventTabletPoint::QQuickEventTabletPoint(QQuickPointerTabletEvent *parent)
- : QQuickEventPoint(parent)
-{
-}
-
-void QQuickEventTabletPoint::reset(const QTabletEvent *ev)
-{
- QEventPoint::State state = QEventPoint::State::Stationary;
- switch (ev->type()) {
- case QEvent::TabletPress:
- state = QEventPoint::State::Pressed;
- clearPassiveGrabbers();
- break;
- case QEvent::TabletRelease:
- state = QEventPoint::State::Released;
- break;
- case QEvent::TabletMove:
- state = QEventPoint::State::Updated;
- break;
- default:
- break;
- }
- QQuickEventPoint::reset(state, ev->position(), 1, ev->timestamp());
- m_rotation = ev->rotation();
- m_pressure = ev->pressure();
- m_tangentialPressure = ev->tangentialPressure();
- m_tilt = QVector2D(ev->xTilt(), ev->yTilt());
-}
-
-bool QQuickPointerTabletEvent::isPressEvent() const
-{
- auto me = static_cast<QTabletEvent *>(m_event);
- return me->type() == QEvent::TabletPress;
-}
-
-bool QQuickPointerTabletEvent::isUpdateEvent() const
-{
- auto me = static_cast<QTabletEvent *>(m_event);
- return me->type() == QEvent::TabletMove;
-}
-
-bool QQuickPointerTabletEvent::isReleaseEvent() const
-{
- auto me = static_cast<QTabletEvent *>(m_event);
- return me->type() == QEvent::TabletRelease;
-}
-
-QTabletEvent *QQuickPointerTabletEvent::asTabletEvent() const
-{
- return static_cast<QTabletEvent *>(m_event);
-}
-#endif // QT_CONFIG(tabletevent)
-
-#if QT_CONFIG(gestures)
-bool QQuickPointerNativeGestureEvent::isPressEvent() const
-{
- return type() == Qt::BeginNativeGesture;
-}
-
-bool QQuickPointerNativeGestureEvent::isUpdateEvent() const
-{
- switch (type()) {
- case Qt::BeginNativeGesture:
- case Qt::EndNativeGesture:
- return false;
- default:
- return true;
- }
-}
-
-bool QQuickPointerNativeGestureEvent::isReleaseEvent() const
-{
- return type() == Qt::EndNativeGesture;
-}
-
-Qt::NativeGestureType QQuickPointerNativeGestureEvent::type() const
-{
- return static_cast<QNativeGestureEvent *>(m_event)->gestureType();
-}
-
-qreal QQuickPointerNativeGestureEvent::value() const
-{
- return static_cast<QNativeGestureEvent *>(m_event)->value();
-}
-#endif // QT_CONFIG(gestures)
-
-/*!
- Returns whether the scroll event has Qt::ScrollBegin phase. On touchpads
- which provide phase information, this is true when the fingers are placed
- on the touchpad and scrolling begins. On other devices where this
- information is not available, it remains false.
-*/
-bool QQuickPointerScrollEvent::isPressEvent() const
-{
- return phase() == Qt::ScrollBegin;
-}
-
-/*!
- Returns true when the scroll event has Qt::ScrollUpdate phase, or when the
- phase is unknown. Some multi-touch-capable touchpads and trackpads provide
- phase information; whereas ordinary mouse wheels and other types of
- trackpads do not, and in such cases this is always true.
-*/
-bool QQuickPointerScrollEvent::isUpdateEvent() const
-{
- return phase() == Qt::ScrollUpdate || phase() == Qt::NoScrollPhase;
-}
-
-/*!
- Returns whether the scroll event has Qt::ScrollBegin phase. On touchpads
- which provide phase information, this is true when the fingers are lifted
- from the touchpad. On other devices where this information is not
- available, it remains false.
-*/
-bool QQuickPointerScrollEvent::isReleaseEvent() const
-{
- return phase() == Qt::ScrollEnd;
-}
-
-/*!
- \internal
- Returns a pointer to the QQuickEventPoint which has the \a pointId as
- \l {QQuickEventPoint::pointId}{pointId}.
- Returns nullptr if there is no point with that ID.
-
- \fn QQuickPointerEvent::pointById(int pointId) const
-*/
-QQuickEventPoint *QQuickSinglePointEvent::pointById(int pointId) const
-{
- if (m_point && pointId == m_point->pointId())
- return m_point;
- return nullptr;
-}
-
-QQuickEventPoint *QQuickPointerTouchEvent::pointById(int pointId) const
-{
- auto it = std::find_if(m_touchPoints.constBegin(), m_touchPoints.constEnd(),
- [pointId](const QQuickEventTouchPoint *tp) { return tp->pointId() == pointId; } );
- if (it != m_touchPoints.constEnd())
- return *it;
- return nullptr;
-}
-
-/*!
- \internal
- Returns a pointer to the original TouchPoint which has the same
- \l {QEventPoint::id}{id} as \a pointId, if the original event is a
- QTouchEvent, and if that point is found. Otherwise, returns nullptr.
-*/
-const QEventPoint *QQuickPointerTouchEvent::touchPointById(int pointId) const
-{
- const QTouchEvent *ev = asTouchEvent();
- if (!ev)
- return nullptr;
- const QList<QEventPoint> &tps = ev->touchPoints();
- auto it = std::find_if(tps.constBegin(), tps.constEnd(),
- [pointId](QEventPoint const& tp) { return tp.id() == pointId; } );
- // return the pointer to the actual TP in QTouchEvent::_touchPoints
- return (it == tps.constEnd() ? nullptr : &*it);
-}
-
-/*!
- \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,
- 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
-{
- QList<QEventPoint> touchPoints;
- QEventPoint::States eventStates; // TODO maybe avoid accumulating this, since the touchevent ctor doesn't need it
- // TODO maybe add QQuickItem::mapVector2DFromScene(QVector2D) to avoid needing QQuickItemPrivate here
- // 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 anyPressOrReleaseInside = false;
- bool anyStationaryWithModifiedPropertyInside = false;
- bool anyGrabber = false;
- QMatrix4x4 transformMatrix(QQuickItemPrivate::get(item)->windowToItemTransform());
- for (int i = 0; i < m_pointCount; ++i) {
- auto p = m_touchPoints.at(i);
- if (p->isAccepted())
- continue;
- // include points where item is the grabber
- bool isGrabber = p->exclusiveGrabber() == item;
- if (isGrabber)
- anyGrabber = true;
- // include points inside the bounds if no other item is the grabber or if the item is filtering
- bool isInside = item->contains(item->mapFromScene(p->scenePosition()));
- bool hasAnotherGrabber = p->exclusiveGrabber() && p->exclusiveGrabber() != item;
-
- // filtering: (childMouseEventFilter) include points that are grabbed by children of the target item
- bool grabberIsChild = false;
- auto parent = p->grabberItem();
- while (isFiltering && parent) {
- if (parent == item) {
- grabberIsChild = true;
- break;
- }
- parent = parent->parentItem();
- }
-
- bool filterRelevant = isFiltering && grabberIsChild;
- if (!(isGrabber || (isInside && (!hasAnotherGrabber || isFiltering)) || filterRelevant))
- continue;
- if ((p->state() == QQuickEventPoint::Pressed || p->state() == QQuickEventPoint::Released) && isInside)
- anyPressOrReleaseInside = true;
- // we don't use QMutableEventPoint::from() because it's fine to have const here
- const QMutableEventPoint *tp = static_cast<const QMutableEventPoint *>(touchPointById(p->pointId()));
- if (tp) {
- if (isInside && tp->stationaryWithModifiedProperty())
- anyStationaryWithModifiedPropertyInside = true;
- eventStates |= tp->state();
- QMutableEventPoint tpCopy(*tp);
- tpCopy.setPosition(item->mapFromScene(tp->scenePosition()));
- tpCopy.setVelocity(transformMatrix.mapVector(tpCopy.velocity()).toVector2D());
- touchPoints << tpCopy;
- }
- }
-
- // 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 == QEventPoint::State::Stationary && !anyStationaryWithModifiedPropertyInside) ||
- touchPoints.isEmpty() || (!anyPressOrReleaseInside && !anyGrabber && !isFiltering))
- return nullptr;
-
- // if all points have the same state, set the event type accordingly
- const QTouchEvent &event = *asTouchEvent();
- QEvent::Type eventType = event.type();
- switch (eventStates) {
- case QEventPoint::State::Pressed:
- eventType = QEvent::TouchBegin;
- break;
- case QEventPoint::State::Released:
- eventType = QEvent::TouchEnd;
- break;
- default:
- eventType = QEvent::TouchUpdate;
- break;
- }
-
- QMutableTouchEvent *touchEvent = new QMutableTouchEvent(eventType, event.pointingDevice(),
- event.modifiers(), touchPoints);
- touchEvent->setTarget(item);
- touchEvent->setTimestamp(event.timestamp());
- touchEvent->accept();
- return touchEvent;
-}
-
-QTouchEvent *QQuickPointerTouchEvent::asTouchEvent() const
-{
- return static_cast<QTouchEvent *>(m_event);
-}
-
-#ifndef QT_NO_DEBUG_STREAM
-
-Q_QUICK_PRIVATE_EXPORT QDebug operator<<(QDebug dbg, const QQuickPointerEvent *event)
-{
- QDebugStateSaver saver(dbg);
- dbg.nospace();
- if (!event) {
- dbg << "QQuickPointerEvent(0)";
- return dbg;
- }
- dbg << "QQuickPointerEvent(";
- dbg << event->timestamp();
- if (event->device()) {
- dbg << " dev:";
- QtDebugUtils::formatQEnum(dbg, event->device()->type());
- dbg << " " << event->device()->name();
- } else {
- dbg << " dev: null";
- }
- if (event->buttons() != Qt::NoButton) {
- dbg << " buttons:";
- QtDebugUtils::formatQEnum(dbg, event->buttons());
- }
- dbg << " [";
- int c = event->pointCount();
- for (int i = 0; i < c; ++i)
- dbg << event->point(i) << ' ';
- dbg << "])";
- return dbg;
-}
-
-Q_QUICK_PRIVATE_EXPORT QDebug operator<<(QDebug dbg, const QQuickEventPoint *event)
-{
- QDebugStateSaver saver(dbg);
- dbg.nospace();
- if (!event) {
- dbg << "QQuickEventPoint(0)";
- return dbg;
- }
- dbg << "QQuickEventPoint(accepted:" << event->isAccepted()
- << " state:";
- QtDebugUtils::formatQEnum(dbg, event->state());
- dbg << " scenePos:" << event->scenePosition() << " id:" << Qt::hex << event->pointId() << Qt::dec
- << " timeHeld:" << event->timeHeld() << ')';
- return dbg;
-}
-
-#endif
-
QT_END_NAMESPACE
diff --git a/src/quick/items/qquickevents_p_p.h b/src/quick/items/qquickevents_p_p.h
index b491445323..9b89d8300e 100644
--- a/src/quick/items/qquickevents_p_p.h
+++ b/src/quick/items/qquickevents_p_p.h
@@ -68,14 +68,8 @@
QT_BEGIN_NAMESPACE
class QPointingDevice;
-class QQuickPointerEvent;
-class QQuickPointerMouseEvent;
-#if QT_CONFIG(gestures)
-class QQuickPointerNativeGestureEvent;
-#endif
-class QQuickPointerScrollEvent;
-class QQuickPointerTabletEvent;
-class QQuickPointerTouchEvent;
+class QPointerEvent;
+class QMouseEvent;
class QQuickPointerHandler;
class QQuickKeyEvent : public QObject
@@ -267,441 +261,6 @@ private:
bool _accepted = true;
};
-class Q_QUICK_PRIVATE_EXPORT QQuickEventPoint : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(QQuickPointerEvent *event READ pointerEvent CONSTANT)
- Q_PROPERTY(QPointF position READ position CONSTANT)
- Q_PROPERTY(QPointF scenePosition READ scenePosition CONSTANT)
- Q_PROPERTY(QPointF scenePressPosition READ scenePressPosition CONSTANT)
- Q_PROPERTY(QPointF sceneGrabPosition READ sceneGrabPosition CONSTANT)
- Q_PROPERTY(State state READ state CONSTANT)
- Q_PROPERTY(int pointId READ pointId CONSTANT)
- Q_PROPERTY(qreal timeHeld READ timeHeld CONSTANT)
- Q_PROPERTY(QVector2D velocity READ velocity CONSTANT)
- Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)
- Q_PROPERTY(QObject *exclusiveGrabber READ exclusiveGrabber WRITE setExclusiveGrabber)
-
- QML_NAMED_ELEMENT(EventPoint)
- QML_UNCREATABLE("EventPoint is only available as a member of PointerEvent.")
- QML_ADDED_IN_VERSION(2, 12)
-
-public:
- enum State {
- Pressed = QEventPoint::State::Pressed,
- Updated = QEventPoint::State::Updated,
- Stationary = QEventPoint::State::Stationary,
- Released = QEventPoint::State::Released
- };
- Q_DECLARE_FLAGS(States, State)
- Q_FLAG(States)
-
- enum GrabTransition {
- GrabPassive = 0x01,
- UngrabPassive = 0x02,
- CancelGrabPassive = 0x03,
- OverrideGrabPassive = 0x04,
- GrabExclusive = 0x10,
- UngrabExclusive = 0x20,
- CancelGrabExclusive = 0x30,
- };
- Q_ENUM(GrabTransition)
-
- QQuickEventPoint(QQuickPointerEvent *parent);
-
- void reset(QEventPoint::State state, const QPointF &scenePosition, int pointId, ulong timestamp, const QVector2D &velocity = QVector2D());
- void localizePosition(QQuickItem *target);
-
- QQuickPointerEvent *pointerEvent() const;
- QPointF position() const { return m_pos; }
- QPointF scenePosition() const { return m_scenePos; }
- QPointF scenePressPosition() const { return m_scenePressPos; }
- QPointF sceneGrabPosition() const { return m_sceneGrabPos; }
- QVector2D velocity() const { return m_velocity; }
- State state() const { return m_state; }
- int pointId() const { return m_pointId; }
- qreal timeHeld() const { return (m_timestamp - m_pressTimestamp) / 1000.0; }
- bool isAccepted() const { return m_accept; }
- void setAccepted(bool accepted = true);
- QObject *exclusiveGrabber() const;
- void setExclusiveGrabber(QObject *exclusiveGrabber);
-
- QQuickItem *grabberItem() const;
- void setGrabberItem(QQuickItem *exclusiveGrabber);
-
- QQuickPointerHandler *grabberPointerHandler() const;
- void setGrabberPointerHandler(QQuickPointerHandler *exclusiveGrabber, bool exclusive = false);
-
- void cancelExclusiveGrab();
- void cancelPassiveGrab(QQuickPointerHandler *handler);
- bool removePassiveGrabber(QQuickPointerHandler *handler);
- void cancelAllGrabs(QQuickPointerHandler *handler);
-
- QVector<QPointer <QQuickPointerHandler> > passiveGrabbers() const { return m_passiveGrabbers; }
- void setPassiveGrabbers(const QVector<QPointer <QQuickPointerHandler> > &grabbers) { m_passiveGrabbers = grabbers; }
- void clearPassiveGrabbers() { m_passiveGrabbers.clear(); }
-
-protected:
- void cancelExclusiveGrabImpl(QTouchEvent *cancelEvent = nullptr);
-
-private:
- QVector2D estimatedVelocity() const;
-
-protected:
- QPointF m_pos;
- QPointF m_scenePos;
- QPointF m_scenePressPos;
- QPointF m_sceneGrabPos;
- QVector2D m_velocity;
- int m_pointId;
- QPointer<QObject> m_exclusiveGrabber;
- QVector<QPointer <QQuickPointerHandler> > m_passiveGrabbers;
- ulong m_timestamp;
- ulong m_pressTimestamp;
- State m_state;
- bool m_accept : 1;
- bool m_grabberIsHandler : 1;
- int m_reserved : 29;
-
- friend class QQuickPointerTouchEvent;
- friend class QQuickWindowPrivate;
-
- Q_DISABLE_COPY(QQuickEventPoint)
-};
-
-class Q_QUICK_PRIVATE_EXPORT QQuickEventTouchPoint : public QQuickEventPoint
-{
- Q_OBJECT
- Q_PROPERTY(qreal rotation READ rotation)
- Q_PROPERTY(qreal pressure READ pressure)
- Q_PROPERTY(QSizeF ellipseDiameters READ ellipseDiameters)
- Q_PROPERTY(QPointingDeviceUniqueId uniqueId READ uniqueId)
-
- QML_NAMED_ELEMENT(EventTouchPoint)
- QML_UNCREATABLE("EventTouchPoint is only available as a member of PointerEvent.")
- QML_ADDED_IN_VERSION(2, 12)
-
-public:
- QQuickEventTouchPoint(QQuickPointerTouchEvent *parent);
-
- void reset(const QEventPoint &tp, ulong timestamp);
-
- qreal rotation() const { return m_rotation; }
- qreal pressure() const { return m_pressure; }
- QSizeF ellipseDiameters() const { return m_ellipseDiameters; }
- QPointingDeviceUniqueId uniqueId() const { return m_uniqueId; }
-
-private:
- qreal m_rotation;
- qreal m_pressure;
- QSizeF m_ellipseDiameters;
- QPointingDeviceUniqueId m_uniqueId;
-
- friend class QQuickPointerTouchEvent;
-
- Q_DISABLE_COPY(QQuickEventTouchPoint)
-};
-
-class Q_QUICK_PRIVATE_EXPORT QQuickPointerEvent : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(QPointingDevice *device READ device CONSTANT)
- Q_PROPERTY(Qt::KeyboardModifiers modifiers READ modifiers CONSTANT)
- Q_PROPERTY(Qt::MouseButtons button READ button CONSTANT)
- Q_PROPERTY(Qt::MouseButtons buttons READ buttons CONSTANT)
-
- QML_NAMED_ELEMENT(PointerEvent)
- QML_UNCREATABLE("PointerEvent is only available as a parameter of several signals in PointerHandler")
- QML_ADDED_IN_VERSION(2, 12)
-
-public:
- QQuickPointerEvent(QObject *parent = nullptr, const QPointingDevice *device = nullptr)
- : QObject(parent)
- , m_device(device)
- , m_pressedButtons(Qt::NoButton)
- {}
-
- ~QQuickPointerEvent() override;
-
-public: // property accessors
- // non-const only because of QML engine limitations (similar to QTBUG-61749)
- QPointingDevice *device() const { return const_cast<QPointingDevice *>(m_device); }
- Qt::KeyboardModifiers modifiers() const { return m_event ? m_event->modifiers() : Qt::NoModifier; }
- Qt::MouseButton button() const { return m_button; }
- Qt::MouseButtons buttons() const { return m_pressedButtons; }
-
-public: // helpers for C++ only (during event delivery)
- virtual QQuickPointerEvent *reset(QEvent *ev) = 0;
- virtual void localize(QQuickItem *target) = 0;
-
- virtual bool isPressEvent() const = 0;
- virtual bool isDoubleClickEvent() const { return false; }
- virtual bool isUpdateEvent() const = 0;
- virtual bool isReleaseEvent() const = 0;
- virtual QQuickPointerMouseEvent *asPointerMouseEvent() { return nullptr; }
- virtual QQuickPointerTouchEvent *asPointerTouchEvent() { return nullptr; }
- virtual QQuickPointerTabletEvent *asPointerTabletEvent() { return nullptr; }
-#if QT_CONFIG(gestures)
- virtual QQuickPointerNativeGestureEvent *asPointerNativeGestureEvent() { return nullptr; }
-#endif
- virtual QQuickPointerScrollEvent *asPointerScrollEvent() { return nullptr; }
- virtual const QQuickPointerMouseEvent *asPointerMouseEvent() const { return nullptr; }
- virtual const QQuickPointerTouchEvent *asPointerTouchEvent() const { return nullptr; }
- virtual const QQuickPointerTabletEvent *asPointerTabletEvent() const { return nullptr; }
-#if QT_CONFIG(gestures)
- virtual const QQuickPointerNativeGestureEvent *asPointerNativeGestureEvent() const { return nullptr; }
-#endif
- virtual const QQuickPointerScrollEvent *asPointerScrollEvent() const { return nullptr; }
- virtual bool allPointsAccepted() const = 0;
- virtual bool allUpdatedPointsAccepted() const = 0;
- virtual bool allPointsGrabbed() const = 0;
- bool isAccepted() { return m_event ? m_event->isAccepted() : false; }
- void setAccepted(bool accepted) { if (m_event) m_event->setAccepted(accepted); }
- QVector<QPointF> unacceptedPressedPointScenePositions() const;
-
- virtual int pointCount() const = 0;
- virtual QQuickEventPoint *point(int i) const = 0;
- virtual QQuickEventPoint *pointById(int pointId) const = 0;
- virtual QVector<QObject *> exclusiveGrabbers() const = 0;
- virtual void clearGrabbers() const = 0;
- virtual bool hasExclusiveGrabber(const QQuickPointerHandler *handler) const = 0;
-
- ulong timestamp() const { return m_event ? m_event->timestamp() : 0; }
-
-protected:
- const QPointingDevice *m_device = nullptr;
- QPointerEvent *m_event = nullptr; // original event as received by QQuickWindow
- Qt::MouseButton m_button = Qt::NoButton;
- Qt::MouseButtons m_pressedButtons;
-
- friend class QQuickWindowPrivate;
-
- Q_DISABLE_COPY(QQuickPointerEvent)
-};
-
-class Q_QUICK_PRIVATE_EXPORT QQuickSinglePointEvent : public QQuickPointerEvent
-{
- Q_OBJECT
-public:
- QQuickSinglePointEvent(QObject *parent, const QPointingDevice *device)
- : QQuickPointerEvent(parent, device) { }
-
- void localize(QQuickItem *target) override;
- int pointCount() const override { return 1; }
- QQuickEventPoint *point(int i) const override;
- QQuickEventPoint *pointById(int pointId) const override;
- bool allPointsAccepted() const override;
- bool allUpdatedPointsAccepted() const override;
- bool allPointsGrabbed() const override;
- QVector<QObject *> exclusiveGrabbers() const override;
- void clearGrabbers() const override;
- bool hasExclusiveGrabber(const QQuickPointerHandler *handler) const override;
-
-protected:
- QQuickEventPoint *m_point = nullptr;
-
- Q_DISABLE_COPY(QQuickSinglePointEvent)
-};
-
-class Q_QUICK_PRIVATE_EXPORT QQuickPointerMouseEvent : public QQuickSinglePointEvent
-{
- Q_OBJECT
-
- QML_NAMED_ELEMENT(PointerMouseEvent)
- QML_UNCREATABLE("PointerMouseEvent is only available as a parameter of several signals in PointerHandler")
- QML_ADDED_IN_VERSION(2, 12)
-
-public:
- QQuickPointerMouseEvent(QObject *parent, const QPointingDevice *device);
-
- QQuickPointerEvent *reset(QEvent *) override;
- bool isPressEvent() const override;
- bool isDoubleClickEvent() const override;
- bool isUpdateEvent() const override;
- bool isReleaseEvent() const override;
- QQuickPointerMouseEvent *asPointerMouseEvent() override { return this; }
- const QQuickPointerMouseEvent *asPointerMouseEvent() const override { return this; }
-
- QMouseEvent *asMouseEvent(const QPointF& localPos) const;
-
- Q_DISABLE_COPY(QQuickPointerMouseEvent)
-};
-
-class Q_QUICK_PRIVATE_EXPORT QQuickPointerTouchEvent : public QQuickPointerEvent
-{
- Q_OBJECT
-
- QML_NAMED_ELEMENT(PointerTouchEvent)
- QML_UNCREATABLE("PointerTouchEvent is only available as a parameter of several signals in PointerHandler")
- QML_ADDED_IN_VERSION(2, 12)
-
-public:
- QQuickPointerTouchEvent(QObject *parent = nullptr, const QPointingDevice *device = nullptr)
- : QQuickPointerEvent(parent, device)
- , m_synthMouseEvent(QEvent::MouseMove, QPointF(), Qt::NoButton, Qt::NoButton, Qt::NoModifier)
- {}
-
- QQuickPointerEvent *reset(QEvent *) override;
- void localize(QQuickItem *target) override;
- bool isPressEvent() const override;
- bool isUpdateEvent() const override;
- bool isReleaseEvent() const override;
- QQuickPointerTouchEvent *asPointerTouchEvent() override { return this; }
- const QQuickPointerTouchEvent *asPointerTouchEvent() const override { return this; }
- int pointCount() const override { return m_pointCount; }
- QQuickEventPoint *point(int i) const override;
- QQuickEventPoint *pointById(int pointId) const override;
- const QEventPoint *touchPointById(int pointId) const;
- bool allPointsAccepted() const override;
- bool allUpdatedPointsAccepted() const override;
- bool allPointsGrabbed() const override;
- QVector<QObject *> exclusiveGrabbers() const override;
- void clearGrabbers() const override;
- bool hasExclusiveGrabber(const QQuickPointerHandler *handler) const override;
-
- QMouseEvent *syntheticMouseEvent(int pointID, QQuickItem *relativeTo) const;
- QTouchEvent *touchEventForItem(QQuickItem *item, bool isFiltering = false) const;
-
- QTouchEvent *asTouchEvent() const;
-
-private:
- QEventPoint::States touchPointStates() const;
-
- int m_pointCount = 0;
- QVector<QQuickEventTouchPoint *> m_touchPoints;
- mutable QMouseEvent m_synthMouseEvent;
-
- Q_DISABLE_COPY(QQuickPointerTouchEvent)
-};
-
-#if QT_CONFIG(tabletevent)
-class Q_QUICK_PRIVATE_EXPORT QQuickEventTabletPoint : public QQuickEventPoint
-{
- Q_OBJECT
- Q_PROPERTY(qreal rotation READ rotation)
- Q_PROPERTY(qreal pressure READ pressure)
- Q_PROPERTY(qreal tangentialPressure READ tangentialPressure)
- Q_PROPERTY(QVector2D tilt READ tilt)
-
- QML_NAMED_ELEMENT(EventTabletPoint)
- QML_UNCREATABLE("EventTouchPoint is only available as a member of PointerEvent.")
- QML_ADDED_IN_VERSION(2, 15)
-
-public:
- QQuickEventTabletPoint(QQuickPointerTabletEvent *parent);
-
- void reset(const QTabletEvent *e);
-
- qreal rotation() const { return m_rotation; }
- qreal pressure() const { return m_pressure; }
- qreal tangentialPressure() const { return m_tangentialPressure; }
- QVector2D tilt() const { return m_tilt; }
-
-private:
- qreal m_rotation;
- qreal m_pressure;
- qreal m_tangentialPressure;
- QVector2D m_tilt;
-
- friend class QQuickPointerTouchEvent;
-
- Q_DISABLE_COPY(QQuickEventTabletPoint)
-};
-
-class Q_QUICK_PRIVATE_EXPORT QQuickPointerTabletEvent : public QQuickSinglePointEvent
-{
- Q_OBJECT
-public:
- QQuickPointerTabletEvent(QObject *parent, const QPointingDevice *device);
-
- QQuickPointerEvent *reset(QEvent *) override;
- bool isPressEvent() const override;
- bool isUpdateEvent() const override;
- bool isReleaseEvent() const override;
- QQuickPointerTabletEvent *asPointerTabletEvent() override { return this; }
- const QQuickPointerTabletEvent *asPointerTabletEvent() const override { return this; }
- const QQuickEventTabletPoint *tabletPoint() const { return static_cast<QQuickEventTabletPoint *>(m_point); }
-
- QTabletEvent *asTabletEvent() const;
-
- Q_DISABLE_COPY(QQuickPointerTabletEvent)
-};
-#endif // QT_CONFIG(tabletevent)
-
-#if QT_CONFIG(gestures)
-class Q_QUICK_PRIVATE_EXPORT QQuickPointerNativeGestureEvent : public QQuickSinglePointEvent
-{
- Q_OBJECT
- Q_PROPERTY(Qt::NativeGestureType type READ type CONSTANT)
- Q_PROPERTY(qreal value READ value CONSTANT)
-
-public:
- QQuickPointerNativeGestureEvent(QObject *parent, const QPointingDevice *device);
-
- QQuickPointerEvent *reset(QEvent *) override;
- bool isPressEvent() const override;
- bool isUpdateEvent() const override;
- bool isReleaseEvent() const override;
- QQuickPointerNativeGestureEvent *asPointerNativeGestureEvent() override { return this; }
- const QQuickPointerNativeGestureEvent *asPointerNativeGestureEvent() const override { return this; }
- Qt::NativeGestureType type() const;
- qreal value() const;
-
- Q_DISABLE_COPY(QQuickPointerNativeGestureEvent)
-};
-#endif // QT_CONFIG(gestures)
-
-class Q_QUICK_PRIVATE_EXPORT QQuickPointerScrollEvent : public QQuickSinglePointEvent
-{
- Q_OBJECT
- Q_PROPERTY(QVector2D angleDelta READ angleDelta CONSTANT)
- Q_PROPERTY(QVector2D pixelDelta READ pixelDelta CONSTANT)
- Q_PROPERTY(bool hasAngleDelta READ hasAngleDelta CONSTANT)
- Q_PROPERTY(bool hasPixelDelta READ hasPixelDelta CONSTANT)
- Q_PROPERTY(bool inverted READ isInverted CONSTANT)
-
- QML_NAMED_ELEMENT(PointerScrollEvent)
- QML_UNCREATABLE("PointerScrollEvent is only available via the WheelHandler::wheel signal.")
- QML_ADDED_IN_VERSION(2, 14)
-
-public:
- QQuickPointerScrollEvent(QObject *parent, const QPointingDevice *device);
-
- QQuickPointerEvent *reset(QEvent *) override;
- void localize(QQuickItem *target) override;
- bool isPressEvent() const override;
- bool isUpdateEvent() const override;
- bool isReleaseEvent() const override;
- QQuickPointerScrollEvent *asPointerScrollEvent() override { return this; }
- const QQuickPointerScrollEvent *asPointerScrollEvent() const override { return this; }
- QVector2D angleDelta() const { return m_angleDelta; }
- QVector2D pixelDelta() const { return m_pixelDelta; }
- bool hasAngleDelta() const { return !angleDelta().isNull(); }
- bool hasPixelDelta() const { return !pixelDelta().isNull(); }
- bool isInverted() const { return m_inverted; }
- Qt::ScrollPhase phase() const { return m_phase; }
-
-private:
- // TODO remove this if it's obsolete
- Qt::MouseEventSource synthSource() const { return m_synthSource; }
-
-private:
- QVector2D m_angleDelta;
- QVector2D m_pixelDelta;
- Qt::ScrollPhase m_phase = Qt::NoScrollPhase;
- Qt::MouseEventSource m_synthSource = Qt::MouseEventNotSynthesized;
- bool m_inverted = false;
-
- friend class QQuickWindowPrivate;
- friend class QQuickWheelHandler;
-
- Q_DISABLE_COPY(QQuickPointerScrollEvent)
-};
-
-Q_QUICK_PRIVATE_EXPORT QDebug operator<<(QDebug, const QQuickPointerEvent *);
-Q_QUICK_PRIVATE_EXPORT QDebug operator<<(QDebug, const QQuickEventPoint *);
-//Q_QUICK_PRIVATE_EXPORT QDebug operator<<(QDebug, const QQuickEventTouchPoint *); TODO maybe
-
QT_END_NAMESPACE
QML_DECLARE_TYPE(QQuickKeyEvent)
@@ -710,7 +269,6 @@ QML_DECLARE_TYPE(QQuickWheelEvent)
QML_DECLARE_TYPE(QQuickCloseEvent)
QML_DECLARE_TYPE(QPointingDevice)
QML_DECLARE_TYPE(QPointingDeviceUniqueId)
-QML_DECLARE_TYPE(QQuickPointerEvent)
-Q_DECLARE_METATYPE(QQuickEventPoint::GrabTransition)
+QML_DECLARE_TYPE(QPointerEvent)
#endif // QQUICKEVENTS_P_P_H
diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp
index 0a3c1a71c9..d20f23466b 100644
--- a/src/quick/items/qquickflickable.cpp
+++ b/src/quick/items/qquickflickable.cpp
@@ -1606,19 +1606,7 @@ void QQuickFlickablePrivate::captureDelayedPress(QQuickItem *item, QMouseEvent *
if (!isInnermostPressDelay(item))
return;
- // delayedPressEvent = QQuickWindowPrivate::cloneMouseEvent(event); // TODO make it OK to tell the truth about the device
-
- // temporary hack to keep the Qt 5 solution for QTBUG-78818 working the same for now:
- // when QQuickWindowPrivate::pointerEventInstance() is called, it has to look like a mouse event from a mouse,
- // not a mouse event that actually comes from a touchscreen (which is what it actually is).
- // Otherwise a nested MultiPointTouchArea will receive a delayed touch
- // (which is what we actually want, later on; but the code isn't ready for that yet).
- delayedPressEvent = new QMouseEvent(QEvent::MouseButtonPress, event->position(),
- event->scenePosition(), event->globalPosition(), event->button(), event->buttons(),
- event->modifiers(), Qt::MouseEventSynthesizedByQt);
- QMutableSinglePointEvent::from(delayedPressEvent)->setTimestamp(event->timestamp());
- // end of hack
-
+ delayedPressEvent = QQuickWindowPrivate::cloneMouseEvent(event);
delayedPressEvent->setAccepted(false);
delayedPressTimer.start(pressDelay, q);
}
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index 8bf5e4f4bf..8e6bb0f224 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -3015,7 +3015,6 @@ void QQuickItemPrivate::derefWindow()
QQuickWindowPrivate *c = QQuickWindowPrivate::get(window);
if (polishScheduled)
c->itemsToPolish.removeOne(q);
- c->removeGrabber(q);
#if QT_CONFIG(cursor)
if (c->cursorItem == q) {
c->cursorItem = nullptr;
@@ -5249,12 +5248,12 @@ void QQuickItemPrivate::deliverShortcutOverrideEvent(QKeyEvent *event)
}
}
-bool QQuickItemPrivate::anyPointerHandlerWants(QQuickEventPoint *point) const
+bool QQuickItemPrivate::anyPointerHandlerWants(const QPointerEvent *event, const QEventPoint &point) const
{
if (!hasPointerHandlers())
return false;
for (QQuickPointerHandler *handler : extra->pointerHandlers) {
- if (handler->wantsEventPoint(point))
+ if (handler->wantsEventPoint(event, point))
return true;
}
return false;
@@ -5267,13 +5266,22 @@ bool QQuickItemPrivate::anyPointerHandlerWants(QQuickEventPoint *point) const
delivery to any handler which is the exclusive grabber of any point within this event
(because delivery to exclusive grabbers is handled separately).
*/
-bool QQuickItemPrivate::handlePointerEvent(QQuickPointerEvent *event, bool avoidExclusiveGrabber)
+bool QQuickItemPrivate::handlePointerEvent(QPointerEvent *event, bool avoidExclusiveGrabber)
{
bool delivered = false;
- QVector<QObject *> &eventDeliveryTargets = QQuickPointerHandlerPrivate::deviceDeliveryTargets(event->device());
if (extra.isAllocated()) {
for (QQuickPointerHandler *handler : extra->pointerHandlers) {
- if ((!avoidExclusiveGrabber || !event->hasExclusiveGrabber(handler)) && !eventDeliveryTargets.contains(handler)) {
+ bool avoidThisHandler = false;
+ if (avoidExclusiveGrabber) {
+ for (auto &p : event->points()) {
+ if (event->exclusiveGrabber(p) == handler) {
+ avoidThisHandler = true;
+ break;
+ }
+ }
+ }
+ if (!avoidThisHandler &&
+ !QQuickPointerHandlerPrivate::deviceDeliveryTargets(event->device()).contains(handler)) {
handler->handlePointerEvent(event);
delivered = true;
}
@@ -7623,6 +7631,8 @@ QQuickPointerHandler *QQuickItemPrivate::effectiveCursorHandler() const
#endif
/*!
+ \obsolete Use QPointerEvent::setExclusiveGrabber()
+
Grabs the mouse input.
This item will receive all mouse events until ungrabMouse() is called.
@@ -7637,18 +7647,21 @@ QQuickPointerHandler *QQuickItemPrivate::effectiveCursorHandler() const
void QQuickItem::grabMouse()
{
Q_D(QQuickItem);
- if (!d->window || d->window->mouseGrabberItem() == this)
+ if (!d->window)
return;
QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(d->window);
- bool fromTouch = windowPriv->isDeliveringTouchAsMouse();
- auto point = fromTouch ?
- windowPriv->pointerEventInstance(windowPriv->touchMouseDevice)->pointById(windowPriv->touchMouseId) :
- windowPriv->pointerEventInstance(QPointingDevice::primaryPointingDevice())->point(0);
- if (point)
- point->setGrabberItem(this);
+ auto eventInDelivery = windowPriv->eventInDelivery();
+ if (!eventInDelivery) {
+ qWarning() << "cannot grab mouse: no event is currently being delivered";
+ return;
+ }
+ auto epd = windowPriv->mousePointData();
+ eventInDelivery->setExclusiveGrabber(epd->eventPoint, this);
}
/*!
+ \obsolete Use QPointerEvent::setExclusiveGrabber()
+
Releases the mouse grab following a call to grabMouse().
Note that this function should only be called when the item wants
@@ -7663,10 +7676,18 @@ void QQuickItem::ungrabMouse()
if (!d->window)
return;
QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(d->window);
- windowPriv->removeGrabber(this, true, windowPriv->isDeliveringTouchAsMouse());
+ auto eventInDelivery = windowPriv->eventInDelivery();
+ if (!eventInDelivery) {
+ // do it the expensive way
+ windowPriv->removeGrabber(this);
+ return;
+ }
+ const auto &eventPoint = windowPriv->mousePointData()->eventPoint;
+ if (eventInDelivery->exclusiveGrabber(eventPoint) != this)
+ return;
+ eventInDelivery->setExclusiveGrabber(eventPoint, this);
}
-
/*!
Returns whether mouse input should exclusively remain with this item.
@@ -7701,32 +7722,31 @@ void QQuickItem::setKeepMouseGrab(bool keep)
}
/*!
+ \obsolete Use QPointerEvent::setExclusiveGrabber().
Grabs the touch points specified by \a ids.
These touch points will be owned by the item until
they are released. Alternatively, the grab can be stolen
by a filtering item like Flickable. Use setKeepTouchGrab()
to prevent the grab from being stolen.
-
- \sa ungrabTouchPoints(), setKeepTouchGrab()
*/
void QQuickItem::grabTouchPoints(const QList<int> &ids)
{
- Q_D(QQuickItem);
- if (!d->window)
+ QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window());
+ auto event = windowPriv->eventInDelivery();
+ if (Q_UNLIKELY(!event)) {
+ qWarning() << "cannot grab: no event is currently being delivered";
return;
- QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(d->window);
- windowPriv->grabTouchPoints(this, ids);
+ }
+ for (auto pt : event->points()) {
+ if (ids.contains(pt.id()))
+ event->setExclusiveGrabber(pt, this);
+ }
}
/*!
+ \obsolete Use QEventPoint::setExclusiveGrabber() instead.
Ungrabs the touch points owned by this item.
-
- \note there is hardly any reason to call this function. It should only be
- called when an item does not want to receive any further events, so no
- move or release events will be delivered after calling this function.
-
- \sa grabTouchPoints()
*/
void QQuickItem::ungrabTouchPoints()
{
@@ -8338,6 +8358,97 @@ QQuickItemLayer *QQuickItemPrivate::layer() const
#endif
}
+/*!
+ \internal
+ Create a modified copy of the given \a event intended for delivery to this
+ item, containing pointers to only the QEventPoint instances that are
+ relevant to this item, and transforming their positions to this item's
+ coordinate system.
+
+ Returns an invalid event with type \l QEvent::None 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
+ \a isFiltering is false.
+
+ When \a 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 QQuickItemPrivate::localizedTouchEvent(const QTouchEvent *event, bool isFiltering)
+{
+ Q_Q(QQuickItem);
+ QList<QEventPoint> touchPoints;
+ QEventPoint::States eventStates;
+
+ bool anyPressOrReleaseInside = false;
+ bool anyStationaryWithModifiedPropertyInside = false;
+ bool anyGrabber = false;
+ for (auto &p : event->points()) {
+ if (p.isAccepted())
+ continue;
+ // include points where item is the grabber
+ auto pointGrabber = event->exclusiveGrabber(p);
+ bool isGrabber = (pointGrabber == q);
+ if (isGrabber)
+ anyGrabber = true;
+ // include points inside the bounds if no other item is the grabber or if the item is filtering
+ const auto localPos = q->mapFromScene(p.scenePosition());
+ bool isInside = q->contains(localPos);
+ bool hasAnotherGrabber = pointGrabber && pointGrabber != q;
+
+ // filtering: (childMouseEventFilter) include points that are grabbed by children of the target item
+ bool grabberIsChild = false;
+ auto parent = qobject_cast<QQuickItem*>(pointGrabber);
+ while (isFiltering && parent) {
+ if (parent == q) {
+ grabberIsChild = true;
+ break;
+ }
+ parent = parent->parentItem();
+ }
+
+ bool filterRelevant = isFiltering && grabberIsChild;
+ if (!(isGrabber || (isInside && (!hasAnotherGrabber || isFiltering)) || filterRelevant))
+ continue;
+ if ((p.state() == QEventPoint::State::Pressed || p.state() == QEventPoint::State::Released) && isInside)
+ anyPressOrReleaseInside = true;
+ QEventPoint pCopy(p);
+ QMutableEventPoint mut = QMutableEventPoint::from(pCopy);
+ if (isInside && mut.stationaryWithModifiedProperty())
+ anyStationaryWithModifiedPropertyInside = true;
+ eventStates |= p.state();
+ mut.setPosition(localPos);
+ touchPoints << mut;
+ }
+
+ // 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 == QEventPoint::State::Stationary && !anyStationaryWithModifiedPropertyInside) ||
+ touchPoints.isEmpty() || (!anyPressOrReleaseInside && !anyGrabber && !isFiltering))
+ return QTouchEvent(QEvent::None);
+
+ // if all points have the same state, set the event type accordingly
+ QEvent::Type eventType = event->type();
+ switch (eventStates) {
+ case QEventPoint::State::Pressed:
+ eventType = QEvent::TouchBegin;
+ break;
+ case QEventPoint::State::Released:
+ eventType = QEvent::TouchEnd;
+ break;
+ default:
+ eventType = QEvent::TouchUpdate;
+ break;
+ }
+
+ QMutableTouchEvent ret(eventType, event->pointingDevice(), event->modifiers(), touchPoints);
+ ret.setTarget(q);
+ ret.setTimestamp(event->timestamp());
+ ret.accept();
+ return ret;
+}
+
bool QQuickItemPrivate::hasPointerHandlers() const
{
return extra.isAllocated() && !extra->pointerHandlers.isEmpty();
diff --git a/src/quick/items/qquickitem.h b/src/quick/items/qquickitem.h
index 3f75eca5e1..775bc6edbe 100644
--- a/src/quick/items/qquickitem.h
+++ b/src/quick/items/qquickitem.h
@@ -462,7 +462,7 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_resourceObjectDeleted(QObject *))
Q_PRIVATE_SLOT(d_func(), quint64 _q_createJSWrapper(QV4::ExecutionEngine *))
- friend class QQuickEventPoint;
+ friend class QEventPoint;
friend class QQuickWindow;
friend class QQuickWindowPrivate;
friend class QSGRenderer;
diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h
index 2461ea29f7..68c5d59dfe 100644
--- a/src/quick/items/qquickitem_p.h
+++ b/src/quick/items/qquickitem_p.h
@@ -281,6 +281,7 @@ public:
QQuickItemLayer *layer() const;
+ QTouchEvent localizedTouchEvent(const QTouchEvent *event, bool isFiltering);
bool hasPointerHandlers() const;
bool hasHoverHandlers() const;
virtual void addPointerHandler(QQuickPointerHandler *h);
@@ -613,8 +614,8 @@ public:
#endif
void deliverShortcutOverrideEvent(QKeyEvent *);
- bool anyPointerHandlerWants(QQuickEventPoint *point) const;
- virtual bool handlePointerEvent(QQuickPointerEvent *, bool avoidExclusiveGrabber = false);
+ bool anyPointerHandlerWants(const QPointerEvent *event, const QEventPoint &point) const;
+ virtual bool handlePointerEvent(QPointerEvent *, bool avoidExclusiveGrabber = false);
virtual void setVisible(bool visible);
diff --git a/src/quick/items/qquickmultipointtoucharea.cpp b/src/quick/items/qquickmultipointtoucharea.cpp
index cebfe74df0..8b666628e3 100644
--- a/src/quick/items/qquickmultipointtoucharea.cpp
+++ b/src/quick/items/qquickmultipointtoucharea.cpp
@@ -45,6 +45,7 @@
#include <private/qquickwindow_p.h>
#include <private/qguiapplication_p.h>
#include <QtGui/private/qevent_p.h>
+#include <QtGui/private/qpointingdevice_p.h>
#include <QEvent>
#include <QMouseEvent>
#include <QDebug>
@@ -553,20 +554,19 @@ void QQuickMultiPointTouchArea::touchEvent(QTouchEvent *event)
}
}
-void QQuickMultiPointTouchArea::grabGesture()
+void QQuickMultiPointTouchArea::grabGesture(QPointingDevice *dev)
{
_stealMouse = true;
grabMouse();
setKeepMouseGrab(true);
- QList<int> ids;
- ids.reserve(_touchPoints.size());
+ QPointingDevicePrivate *devPriv = QPointingDevicePrivate::get(dev);
for (auto it = _touchPoints.keyBegin(), end = _touchPoints.keyEnd(); it != end; ++it) {
if (*it != -1) // -1 might be the mouse-point, but we already grabbed the mouse above.
- ids.append(*it);
+ if (auto pt = devPriv->queryPointById(*it))
+ pt->exclusiveGrabber = this;
}
- grabTouchPoints(ids);
setKeepTouchGrab(true);
}
@@ -579,13 +579,17 @@ void QQuickMultiPointTouchArea::updateTouchData(QEvent *event)
clearTouchLists();
QList<QEventPoint> touchPoints;
QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window());
+ QPointingDevice *dev = nullptr;
switch (event->type()) {
case QEvent::TouchBegin:
case QEvent::TouchUpdate:
- case QEvent::TouchEnd:
- touchPoints = static_cast<QTouchEvent*>(event)->touchPoints();
+ case QEvent::TouchEnd: {
+ QTouchEvent* te = static_cast<QTouchEvent*>(event);
+ touchPoints = te->points();
+ dev = const_cast<QPointingDevice *>(te->pointingDevice());
break;
+ }
case QEvent::MouseButtonPress:
_mouseQpaTouchPoint = QEventPoint(windowPriv->touchMouseId);
_touchMouseDevice = windowPriv->touchMouseDevice;
@@ -593,7 +597,8 @@ void QQuickMultiPointTouchArea::updateTouchData(QEvent *event)
case QEvent::MouseMove:
case QEvent::MouseButtonRelease: {
QMouseEvent *me = static_cast<QMouseEvent*>(event);
- _mouseQpaTouchPoint = me->point(0);
+ _mouseQpaTouchPoint = me->points().first();
+ dev = const_cast<QPointingDevice *>(me->pointingDevice());
if (event->type() == QEvent::MouseButtonPress) {
addTouchPoint(me);
started = true;
@@ -623,7 +628,7 @@ void QQuickMultiPointTouchArea::updateTouchData(QEvent *event)
}
}
if (numTouchPoints >= _minimumTouchPoints && numTouchPoints <= _maximumTouchPoints) {
- for (const QEventPoint &p : qAsConst(touchPoints)) {
+ for (QEventPoint &p : touchPoints) {
QEventPoint::State touchPointState = p.state();
int id = p.id();
if (touchPointState & QEventPoint::State::Released) {
@@ -633,7 +638,7 @@ void QQuickMultiPointTouchArea::updateTouchData(QEvent *event)
addTouchPoint(&p);
started = true;
} else if ((touchPointState & QEventPoint::State::Updated) ||
- QMutableEventPoint::from(const_cast<QEventPoint &>(p)).stationaryWithModifiedProperty()) {
+ QMutableEventPoint::from(p).stationaryWithModifiedProperty()) {
// React to a stationary point with a property change (velocity, pressure) as if the point moved. (QTBUG-77142)
QQuickTouchPoint* dtp = static_cast<QQuickTouchPoint*>(_touchPoints.value(id));
Q_ASSERT(dtp);
@@ -668,8 +673,8 @@ void QQuickMultiPointTouchArea::updateTouchData(QEvent *event)
QQuickGrabGestureEvent event;
event._touchPoints = _touchPoints.values();
emit gestureStarted(&event);
- if (event.wantsGrab())
- grabGesture();
+ if (event.wantsGrab() && dev)
+ grabGesture(dev);
}
}
@@ -957,7 +962,7 @@ bool QQuickMultiPointTouchArea::childMouseEventFilter(QQuickItem *receiver, QEve
_lastFilterableTouchPointIds.clear();
Q_FALLTHROUGH();
case QEvent::TouchUpdate:
- for (auto tp : static_cast<QTouchEvent*>(event)->touchPoints()) {
+ for (const auto &tp : static_cast<QTouchEvent*>(event)->points()) {
if (tp.state() == QEventPoint::State::Pressed)
_lastFilterableTouchPointIds << tp.id();
}
@@ -998,7 +1003,7 @@ bool QQuickMultiPointTouchArea::shouldFilter(QEvent *event)
case QEvent::TouchUpdate:
case QEvent::TouchEnd: {
QTouchEvent *te = static_cast<QTouchEvent*>(event);
- for (const QEventPoint &point : te->touchPoints()) {
+ for (const QEventPoint &point : te->points()) {
if (contains(mapFromScene(point.scenePosition()))) {
containsPoint = true;
break;
diff --git a/src/quick/items/qquickmultipointtoucharea_p.h b/src/quick/items/qquickmultipointtoucharea_p.h
index 693ceea50c..16e490adab 100644
--- a/src/quick/items/qquickmultipointtoucharea_p.h
+++ b/src/quick/items/qquickmultipointtoucharea_p.h
@@ -281,7 +281,7 @@ protected:
bool sendMouseEvent(QMouseEvent *event);
bool shouldFilter(QEvent *event);
- void grabGesture();
+ void grabGesture(QPointingDevice *dev);
QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *) override;
#ifdef Q_OS_OSX
void hoverEnterEvent(QHoverEvent *event) override;
diff --git a/src/quick/items/qquickpincharea.cpp b/src/quick/items/qquickpincharea.cpp
index c021e5181c..6a5dda483d 100644
--- a/src/quick/items/qquickpincharea.cpp
+++ b/src/quick/items/qquickpincharea.cpp
@@ -335,10 +335,9 @@ void QQuickPinchArea::touchEvent(QTouchEvent *event)
case QEvent::TouchBegin:
case QEvent::TouchUpdate:
d->touchPoints.clear();
- for (int i = 0; i < event->touchPoints().count(); ++i) {
- if (!(event->touchPoints().at(i).state() & QEventPoint::State::Released)) {
- d->touchPoints << event->touchPoints().at(i);
- }
+ for (auto &tp : event->points()) {
+ if (!(tp.state() & QEventPoint::State::Released))
+ d->touchPoints << tp;
}
updatePinch();
break;
@@ -639,11 +638,12 @@ bool QQuickPinchArea::childMouseEventFilter(QQuickItem *i, QEvent *e)
clearPinch();
Q_FALLTHROUGH();
case QEvent::TouchUpdate: {
- QTouchEvent *touch = static_cast<QTouchEvent*>(e);
+ const auto &points = static_cast<QTouchEvent*>(e)->points();
d->touchPoints.clear();
- for (int i = 0; i < touch->touchPoints().count(); ++i)
- if (!(touch->touchPoints().at(i).state() & QEventPoint::State::Released))
- d->touchPoints << touch->touchPoints().at(i);
+ for (auto &tp : points) {
+ if (!(tp.state() & QEventPoint::State::Released))
+ d->touchPoints << tp;
+ }
updatePinch();
}
e->setAccepted(d->inPinch);
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 96527d955b..06c2df41a9 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -97,9 +97,12 @@
QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(DBG_TOUCH, "qt.quick.touch")
+Q_LOGGING_CATEGORY(lcTouchCmprs, "qt.quick.touch.compression")
Q_LOGGING_CATEGORY(DBG_TOUCH_TARGET, "qt.quick.touch.target")
Q_LOGGING_CATEGORY(DBG_MOUSE, "qt.quick.mouse")
Q_LOGGING_CATEGORY(DBG_MOUSE_TARGET, "qt.quick.mouse.target")
+Q_LOGGING_CATEGORY(lcPtr, "qt.quick.pointer")
+Q_LOGGING_CATEGORY(lcPtrGrab, "qt.quick.pointer.grab")
Q_LOGGING_CATEGORY(lcTablet, "qt.quick.tablet")
Q_LOGGING_CATEGORY(lcWheelTarget, "qt.quick.wheel.target")
Q_LOGGING_CATEGORY(lcGestureTarget, "qt.quick.gesture.target")
@@ -855,23 +858,18 @@ QQmlListProperty<QObject> QQuickWindowPrivate::data()
QQuickWindowPrivate::data_removeLast);
}
-QMouseEvent *QQuickWindowPrivate::touchToMouseEvent(QEvent::Type type, const QEventPoint &p, QTouchEvent *event, QQuickItem *item, bool transformNeeded)
+QMouseEvent QQuickWindowPrivate::touchToMouseEvent(QEvent::Type type, const QEventPoint &p, QTouchEvent *event, QQuickItem *item)
{
+ Q_UNUSED(item)
Q_ASSERT(QCoreApplication::testAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents));
- // The touch point local position and velocity are not yet transformed.
- QMouseEvent *me = new QMouseEvent(type, transformNeeded ? item->mapFromScene(p.scenePosition()) : p.position(), p.scenePosition(), p.globalPosition(),
- Qt::LeftButton, (type == QEvent::MouseButtonRelease ? Qt::NoButton : Qt::LeftButton), event->modifiers(),
- Qt::MouseEventSynthesizedByQt, event->pointingDevice());
- me->setAccepted(true);
- me->setTimestamp(event->timestamp());
- QVector2D transformedVelocity = p.velocity();
- if (transformNeeded) {
- QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
- QMatrix4x4 transformMatrix(itemPrivate->windowToItemTransform());
- transformedVelocity = transformMatrix.mapVector(p.velocity()).toVector2D();
- }
- QMutableSinglePointEvent::from(me)->mutablePoint().setVelocity(transformedVelocity);
- return me;
+ QMutableSinglePointEvent ret(type, event->pointingDevice(), p,
+ (type == QEvent::MouseMove ? Qt::NoButton : Qt::LeftButton),
+ (type == QEvent::MouseButtonRelease ? Qt::NoButton : Qt::LeftButton),
+ event->modifiers(), Qt::MouseEventSynthesizedByQt);
+ ret.setAccepted(true);
+ ret.setTimestamp(event->timestamp());
+ static_assert(sizeof(QMutableSinglePointEvent) == sizeof(QMouseEvent));
+ return *reinterpret_cast<QMouseEvent*>(&ret);
}
bool QQuickWindowPrivate::checkIfDoubleTapped(ulong newPressEventTimestamp, QPoint newPressPos)
@@ -900,18 +898,37 @@ bool QQuickWindowPrivate::checkIfDoubleTapped(ulong newPressEventTimestamp, QPoi
return doubleClicked;
}
+QPointerEvent *QQuickWindowPrivate::eventInDelivery() const
+{
+ if (eventsInDelivery.isEmpty())
+ return nullptr;
+ return eventsInDelivery.top();
+}
+
+/*! \internal
+ A helper function for the benefit of obsolete APIs like QQuickItem::grabMouse()
+ that don't have the currently-being-delivered event in context.
+ Returns the device the currently-being-delivered event comse from.
+*/
+QPointingDevicePrivate::EventPointData *QQuickWindowPrivate::mousePointData()
+{
+ if (eventsInDelivery.isEmpty())
+ return nullptr;
+ auto devPriv = QPointingDevicePrivate::get(const_cast<QPointingDevice*>(eventsInDelivery.top()->pointingDevice()));
+ return devPriv->pointById(isDeliveringTouchAsMouse() ? touchMouseId : 0);
+}
+
void QQuickWindowPrivate::cancelTouchMouseSynthesis()
{
- qCDebug(DBG_TOUCH_TARGET);
+ qCDebug(DBG_TOUCH_TARGET) << "id" << touchMouseId << "on" << touchMouseDevice;
touchMouseId = -1;
touchMouseDevice = nullptr;
}
-bool QQuickWindowPrivate::deliverTouchAsMouse(QQuickItem *item, QQuickPointerEvent *pointerEvent)
+bool QQuickWindowPrivate::deliverTouchAsMouse(QQuickItem *item, QTouchEvent *pointerEvent)
{
Q_ASSERT(QCoreApplication::testAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents));
- Q_Q(QQuickWindow);
- auto device = pointerEvent->device();
+ auto device = pointerEvent->pointingDevice();
// A touch event from a trackpad is likely to be followed by a mouse or gesture event, so mouse event synth is redundant
if (device->type() == QInputDevice::DeviceType::TouchPad && device->capabilities().testFlag(QInputDevice::Capability::MouseEmulation)) {
@@ -920,15 +937,14 @@ bool QQuickWindowPrivate::deliverTouchAsMouse(QQuickItem *item, QQuickPointerEve
}
// FIXME: make this work for mouse events too and get rid of the asTouchEvent in here.
- Q_ASSERT(pointerEvent->asPointerTouchEvent());
- QScopedPointer<QTouchEvent> event(pointerEvent->asPointerTouchEvent()->touchEventForItem(item));
- if (event.isNull())
+ QTouchEvent event = QQuickItemPrivate::get(item)->localizedTouchEvent(pointerEvent, false);
+ if (!event.points().count())
return false;
// For each point, check if it is accepted, if not, try the next point.
// Any of the fingers can become the mouse one.
// This can happen because a mouse area might not accept an event at some point but another.
- for (auto &p : event->points()) {
+ for (auto &p : event.points()) {
// A new touch point
if (touchMouseId == -1 && p.state() & QEventPoint::State::Pressed) {
QPointF pos = item->mapFromScene(p.scenePosition());
@@ -938,26 +954,25 @@ bool QQuickWindowPrivate::deliverTouchAsMouse(QQuickItem *item, QQuickPointerEve
break;
qCDebug(DBG_TOUCH_TARGET) << "TP (mouse)" << Qt::hex << p.id() << "->" << item;
- QScopedPointer<QMouseEvent> mousePress(touchToMouseEvent(QEvent::MouseButtonPress, p, event.data(), item, false));
+ QMouseEvent mousePress = touchToMouseEvent(QEvent::MouseButtonPress, p, &event, item);
// Send a single press and see if that's accepted
- QCoreApplication::sendEvent(item, mousePress.data());
- event->setAccepted(mousePress->isAccepted());
- if (mousePress->isAccepted()) {
+ QCoreApplication::sendEvent(item, &mousePress);
+ event.setAccepted(mousePress.isAccepted());
+ if (mousePress.isAccepted()) {
touchMouseDevice = device;
touchMouseId = p.id();
- if (!q->mouseGrabberItem())
- item->grabMouse();
- if (auto pointerEventPoint = pointerEvent->pointById(p.id()))
- pointerEventPoint->setGrabberItem(item);
+ const auto &pt = mousePress.point(0);
+ if (!mousePress.exclusiveGrabber(pt))
+ mousePress.setExclusiveGrabber(pt, item);
- if (checkIfDoubleTapped(event->timestamp(), p.globalPosition().toPoint())) {
+ if (checkIfDoubleTapped(event.timestamp(), p.globalPosition().toPoint())) {
// since we synth the mouse event from from touch, we respect the
// QPlatformTheme::TouchDoubleTapDistance instead of QPlatformTheme::MouseDoubleClickDistance
- QScopedPointer<QMouseEvent> mouseDoubleClick(touchToMouseEvent(QEvent::MouseButtonDblClick, p, event.data(), item, false));
- QCoreApplication::sendEvent(item, mouseDoubleClick.data());
- event->setAccepted(mouseDoubleClick->isAccepted());
- if (!mouseDoubleClick->isAccepted())
+ QMouseEvent mouseDoubleClick = touchToMouseEvent(QEvent::MouseButtonDblClick, p, &event, item);
+ QCoreApplication::sendEvent(item, &mouseDoubleClick);
+ event.setAccepted(mouseDoubleClick.isAccepted());
+ if (!mouseDoubleClick.isAccepted())
cancelTouchMouseSynthesis();
}
@@ -974,52 +989,49 @@ bool QQuickWindowPrivate::deliverTouchAsMouse(QQuickItem *item, QQuickPointerEve
if (moveDelta.x() >= doubleTapDistance || moveDelta.y() >= doubleTapDistance)
touchMousePressTimestamp = 0; // Got dragged too far, dismiss the double tap
}
- if (QQuickItem *mouseGrabberItem = q->mouseGrabberItem()) {
- QScopedPointer<QMouseEvent> me(touchToMouseEvent(QEvent::MouseMove, p, event.data(), mouseGrabberItem, false));
- QCoreApplication::sendEvent(item, me.data());
- event->setAccepted(me->isAccepted());
- if (me->isAccepted()) {
+ if (QQuickItem *mouseGrabberItem = qmlobject_cast<QQuickItem *>(pointerEvent->exclusiveGrabber(p))) {
+ QMouseEvent me = touchToMouseEvent(QEvent::MouseMove, p, &event, mouseGrabberItem);
+ QCoreApplication::sendEvent(item, &me);
+ event.setAccepted(me.isAccepted());
+ if (me.isAccepted())
qCDebug(DBG_TOUCH_TARGET) << "TP (mouse)" << Qt::hex << p.id() << "->" << mouseGrabberItem;
- }
- return event->isAccepted();
+ return event.isAccepted();
} else {
// no grabber, check if we care about mouse hover
// FIXME: this should only happen once, not recursively... I'll ignore it just ignore hover now.
// hover for touch???
- QScopedPointer<QMouseEvent> me(touchToMouseEvent(QEvent::MouseMove, p, event.data(), item, false));
+ QMouseEvent me = touchToMouseEvent(QEvent::MouseMove, p, &event, item);
if (lastMousePosition.isNull())
- lastMousePosition = me->scenePosition();
+ lastMousePosition = me.scenePosition();
QPointF last = lastMousePosition;
- lastMousePosition = me->scenePosition();
+ lastMousePosition = me.scenePosition();
- bool accepted = me->isAccepted();
- bool delivered = deliverHoverEvent(contentItem, me->scenePosition(), last, me->modifiers(), me->timestamp(), accepted);
- if (!delivered) {
- //take care of any exits
- accepted = clearHover(me->timestamp());
- }
- me->setAccepted(accepted);
+ bool accepted = me.isAccepted();
+ bool delivered = deliverHoverEvent(contentItem, me.scenePosition(), last, me.modifiers(), me.timestamp(), accepted);
+ // take care of any exits
+ if (!delivered)
+ clearHover(me.timestamp());
break;
}
} else if (p.state() & QEventPoint::State::Released) {
// currently handled point was released
- if (QQuickItem *mouseGrabberItem = q->mouseGrabberItem()) {
- QScopedPointer<QMouseEvent> me(touchToMouseEvent(QEvent::MouseButtonRelease, p, event.data(), mouseGrabberItem, false));
- QCoreApplication::sendEvent(item, me.data());
+ if (QQuickItem *mouseGrabberItem = qmlobject_cast<QQuickItem *>(pointerEvent->exclusiveGrabber(p))) {
+ QMouseEvent me = touchToMouseEvent(QEvent::MouseButtonRelease, p, &event, mouseGrabberItem);
+ QCoreApplication::sendEvent(item, &me);
if (item->acceptHoverEvents() && p.globalPosition() != QGuiApplicationPrivate::lastCursorPosition) {
QPointF localMousePos(qInf(), qInf());
if (QWindow *w = item->window())
localMousePos = item->mapFromScene(w->mapFromGlobal(QGuiApplicationPrivate::lastCursorPosition.toPoint()));
QMouseEvent mm(QEvent::MouseMove, localMousePos, QGuiApplicationPrivate::lastCursorPosition,
- Qt::NoButton, Qt::NoButton, event->modifiers());
+ Qt::NoButton, Qt::NoButton, event.modifiers());
QCoreApplication::sendEvent(item, &mm);
}
- if (q->mouseGrabberItem()) // might have ungrabbed due to event
- q->mouseGrabberItem()->ungrabMouse();
+ if (pointerEvent->exclusiveGrabber(p) == mouseGrabberItem) // might have ungrabbed due to event
+ pointerEvent->setExclusiveGrabber(p, nullptr);
cancelTouchMouseSynthesis();
- return me->isAccepted();
+ return me.isAccepted();
}
}
break;
@@ -1028,74 +1040,34 @@ bool QQuickWindowPrivate::deliverTouchAsMouse(QQuickItem *item, QQuickPointerEve
return false;
}
-void QQuickWindowPrivate::grabTouchPoints(QObject *grabber, const QVector<int> &ids)
-{
- QQuickPointerEvent *ev = nullptr;
- for (int i = 0; i < ids.count(); ++i) {
- int id = ids.at(i);
- if (Q_UNLIKELY(id < 0)) {
- qWarning("ignoring grab of touchpoint %d", id);
- continue;
- }
- if (id == touchMouseId) {
- auto point = pointerEventInstance(touchMouseDevice)->pointById(id);
- auto touchMouseGrabber = point->grabberItem();
- if (touchMouseGrabber) {
- point->setExclusiveGrabber(nullptr);
- touchMouseGrabber->mouseUngrabEvent();
- touchMouseGrabber->touchUngrabEvent();
- cancelTouchMouseSynthesis();
- }
- qCDebug(DBG_MOUSE_TARGET) << "grabTouchPoints: mouse grabber changed due to grabTouchPoints:" << touchMouseGrabber << "-> null";
- }
-
- // optimization to avoid the loop over devices below:
- // all ids are probably from the same event, so we don't have to search
- if (ev) {
- auto point = ev->pointById(id);
- if (point && point->exclusiveGrabber() != grabber) {
- point->setExclusiveGrabber(grabber);
- continue; // next id in the ids loop
- }
- }
- // search all devices for a QQuickPointerEvent instance that is delivering the point with id
- const auto devs = QPointingDevice::devices();
- for (auto device : devs) {
- if (device->type() != QInputDevice::DeviceType::TouchScreen)
- continue;
- QQuickPointerEvent *pev = pointerEventInstance(static_cast<const QPointingDevice *>(device));
- auto point = pev->pointById(id);
- if (point) {
- ev = pev;
- if (point->exclusiveGrabber() != grabber)
- point->setExclusiveGrabber(grabber);
- break; // out of touchDevices loop
- }
- }
- }
-}
-
/*!
Ungrabs all touchpoint grabs and/or the mouse grab from the given item \a grabber.
This should not be called when processing a release event - that's redundant.
It is called in other cases, when the points may not be released, but the item
nevertheless must lose its grab due to becoming disabled, invisible, etc.
- QQuickEventPoint::setGrabberItem() calls touchUngrabEvent() when all points are released,
+ QPointerEvent::setExclusiveGrabber() calls touchUngrabEvent() when all points are released,
but if not all points are released, it cannot be sure whether to call touchUngrabEvent()
or not; so we have to do it here.
*/
void QQuickWindowPrivate::removeGrabber(QQuickItem *grabber, bool mouse, bool touch)
{
Q_Q(QQuickWindow);
- if (Q_LIKELY(mouse) && q->mouseGrabberItem() == grabber) {
- bool fromTouch = isDeliveringTouchAsMouse();
- auto point = fromTouch ?
- pointerEventInstance(touchMouseDevice)->pointById(touchMouseId) :
- pointerEventInstance(QPointingDevice::primaryPointingDevice())->point(0);
- QQuickItem *oldGrabber = point->grabberItem();
+ if (eventsInDelivery.isEmpty()) {
+ // do it the expensive way
+ for (auto dev : knownPointingDevices) {
+ auto devPriv = QPointingDevicePrivate::get(const_cast<QPointingDevice *>(dev));
+ devPriv->removeGrabber(grabber);
+ }
+ return;
+ }
+ auto eventInDelivery = eventsInDelivery.top();
+ if (Q_LIKELY(mouse) && q->mouseGrabberItem() == grabber && eventInDelivery) {
+ const bool fromTouch = isDeliveringTouchAsMouse();
+ auto point = eventInDelivery->pointById(fromTouch ? touchMouseId : 0);
+ Q_ASSERT(point);
+ QQuickItem *oldGrabber = qobject_cast<QQuickItem *>(eventInDelivery->exclusiveGrabber(*point));
qCDebug(DBG_MOUSE_TARGET) << "removeGrabber" << oldGrabber << "-> null";
- point->setGrabberItem(nullptr);
- sendUngrabEvent(oldGrabber, fromTouch);
+ eventInDelivery->setExclusiveGrabber(*point, nullptr);
}
if (Q_LIKELY(touch)) {
bool ungrab = false;
@@ -1103,14 +1075,9 @@ void QQuickWindowPrivate::removeGrabber(QQuickItem *grabber, bool mouse, bool to
for (auto device : touchDevices) {
if (device->type() != QInputDevice::DeviceType::TouchScreen)
continue;
- if (auto pointerEvent = queryPointerEventInstance(static_cast<const QPointingDevice *>(device))) {
- for (int i = 0; i < pointerEvent->pointCount(); ++i) {
- if (pointerEvent->point(i)->exclusiveGrabber() == grabber) {
- pointerEvent->point(i)->setGrabberItem(nullptr);
- ungrab = true;
- }
- }
- }
+ if (QPointingDevicePrivate::get(const_cast<QPointingDevice *>(static_cast<const QPointingDevice *>(device)))->
+ removeExclusiveGrabber(eventInDelivery, grabber))
+ ungrab = true;
}
if (ungrab)
grabber->touchUngrabEvent();
@@ -1691,8 +1658,6 @@ QQuickWindow::~QQuickWindow()
QQuickRootItem *root = d->contentItem;
d->contentItem = nullptr;
delete root;
- qDeleteAll(d->pointerEventInstances);
- d->pointerEventInstances.clear();
d->renderJobMutex.lock();
qDeleteAll(d->beforeSynchronizingJobs);
@@ -1897,38 +1862,21 @@ QObject *QQuickWindow::focusObject() const
/*!
- Returns the item which currently has the mouse grab.
+ \obsolete Use QPointerEvent::exclusiveGrabber()
+ Returns the item which currently has the mouse grab.
*/
-// TODO deprecate this, or take seat name as an argument
QQuickItem *QQuickWindow::mouseGrabberItem() const
{
Q_D(const QQuickWindow);
-
- if (d->isDeliveringTouchAsMouse()) {
- if (QQuickPointerEvent *event = d->queryPointerEventInstance(d->touchMouseDevice)) {
- auto point = event->pointById(d->touchMouseId);
- return point ? point->grabberItem() : nullptr;
- }
- } else {
- const QPointingDevice *mouse = QPointingDevice::primaryPointingDevice();
- if (mouse->type() != QInputDevice::DeviceType::Mouse) {
- // TODO don't assume the first mouse is the core pointer (but so far there is normally only one)
- for (const auto *dev : QInputDevice::devices()) {
- if (dev->type() == QInputDevice::DeviceType::Mouse) {
- mouse = static_cast<const QPointingDevice *>(dev);
- break;
- }
- }
- }
- if (QQuickPointerEvent *event = d->queryPointerEventInstance(mouse)) {
- Q_ASSERT(event->pointCount());
- return event->point(0)->grabberItem();
- }
+ auto epd = const_cast<QQuickWindowPrivate *>(d)->mousePointData();
+ if (!epd && d->eventsInDelivery.isEmpty()) {
+ qCDebug(DBG_MOUSE, "mouse grabber ambiguous: no event is currently being delivered");
+ return qmlobject_cast<QQuickItem *>(QPointingDevicePrivate::get(QPointingDevice::primaryPointingDevice())->
+ firstPointExclusiveGrabber());
}
- return nullptr;
+ return qobject_cast<QQuickItem *>(epd->exclusiveGrabber);
}
-
bool QQuickWindowPrivate::clearHover(ulong timestamp)
{
Q_Q(QQuickWindow);
@@ -1940,20 +1888,6 @@ bool QQuickWindowPrivate::clearHover(ulong timestamp)
bool accepted = false;
for (QQuickItem* item : qAsConst(hoverItems)) {
accepted = sendHoverEvent(QEvent::HoverLeave, item, pos, pos, QGuiApplication::keyboardModifiers(), timestamp, true) || accepted;
-#if QT_CONFIG(cursor)
- QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
- if (itemPrivate->hasPointerHandlers()) {
- pos = q->mapFromGlobal(QCursor::pos());
- const auto dev = QPointingDevice::primaryPointingDevice();
- QQuickPointerEvent *pointerEvent = pointerEventInstance(dev, QEvent::MouseMove);
- pointerEvent->point(0)->reset(QEventPoint::State::Updated, pos, int(dev->systemId()), timestamp, QVector2D());
- pointerEvent->point(0)->setAccepted(true);
- pointerEvent->localize(item);
- for (QQuickPointerHandler *h : itemPrivate->extra->pointerHandlers)
- if (QQuickHoverHandler *hh = qmlobject_cast<QQuickHoverHandler *>(h))
- hh->handlePointerEvent(pointerEvent);
- }
-#endif
}
hoverItems.clear();
return accepted;
@@ -2037,7 +1971,7 @@ bool QQuickWindow::event(QEvent *e)
}
#if QT_CONFIG(gestures)
case QEvent::NativeGesture:
- d->deliverSinglePointEventUntilAccepted(d->pointerEventInstance(e));
+ d->deliverSinglePointEventUntilAccepted(static_cast<QPointerEvent *>(e));
break;
#endif
case QEvent::ShortcutOverride:
@@ -2123,20 +2057,21 @@ void QQuickWindowPrivate::deliverKeyEvent(QKeyEvent *e)
QMouseEvent *QQuickWindowPrivate::cloneMouseEvent(QMouseEvent *event, QPointF *transformedLocalPos)
{
QMouseEvent *me = new QMouseEvent(*event);
- QMutableEventPoint &point = QMutableSinglePointEvent::from(me)->mutablePoint();
+ QMutableEventPoint &point = QMutableEventPoint::from(event->point(0));
point.setTimestamp(event->timestamp());
point.setPosition(transformedLocalPos ? *transformedLocalPos : event->position());
return me;
}
-void QQuickWindowPrivate::deliverToPassiveGrabbers(const QVector<QPointer <QQuickPointerHandler> > &passiveGrabbers,
- QQuickPointerEvent *pointerEvent)
+void QQuickWindowPrivate::deliverToPassiveGrabbers(const QVector<QPointer <QObject> > &passiveGrabbers,
+ QPointerEvent *pointerEvent)
{
const QVector<QObject *> &eventDeliveryTargets =
QQuickPointerHandlerPrivate::deviceDeliveryTargets(pointerEvent->device());
QVarLengthArray<QPair<QQuickItem *, bool>, 4> sendFilteredPointerEventResult;
hasFiltered.clear();
- for (auto handler : passiveGrabbers) {
+ for (auto o : passiveGrabbers) {
+ QQuickPointerHandler *handler = qobject_cast<QQuickPointerHandler *>(o);
// a null pointer in passiveGrabbers is unlikely, unless the grabbing handler was deleted dynamically
if (Q_LIKELY(handler) && !eventDeliveryTargets.contains(handler)) {
bool alreadyFiltered = false;
@@ -2154,97 +2089,13 @@ void QQuickWindowPrivate::deliverToPassiveGrabbers(const QVector<QPointer <QQuic
sendFilteredPointerEventResult << qMakePair(par, alreadyFiltered);
}
if (!alreadyFiltered) {
- pointerEvent->localize(handler->parentItem());
+ localizePointerEvent(pointerEvent, handler->parentItem());
handler->handlePointerEvent(pointerEvent);
}
}
}
}
-
-
-void QQuickWindowPrivate::deliverMouseEvent(QQuickPointerMouseEvent *pointerEvent)
-{
- Q_Q(QQuickWindow);
- auto point = pointerEvent->point(0);
- lastMousePosition = point->scenePosition();
- const bool mouseIsReleased = (point->state() == QQuickEventPoint::Released && pointerEvent->buttons() == Qt::NoButton);
- QQuickItem *grabberItem = point->grabberItem();
- if (!grabberItem && isDeliveringTouchAsMouse())
- grabberItem = q->mouseGrabberItem();
-
- if (grabberItem) {
- bool handled = false;
- hasFiltered.clear();
- if (sendFilteredPointerEvent(pointerEvent, grabberItem))
- handled = true;
- // if the grabber is an Item:
- // if the update consists of changing button state, don't accept it unless
- // the button is one in which the grabber is interested
- Qt::MouseButtons acceptedButtons = grabberItem->acceptedMouseButtons();
- if (!handled && pointerEvent->button() != Qt::NoButton && acceptedButtons
- && !(acceptedButtons & pointerEvent->button())) {
- pointerEvent->setAccepted(false);
- handled = true;
- }
-
- // send update
- if (!handled) {
- QPointF localPos = grabberItem->mapFromScene(lastMousePosition);
- auto me = pointerEvent->asMouseEvent(localPos);
- me->accept();
- QCoreApplication::sendEvent(grabberItem, me);
- point->setAccepted(me->isAccepted());
- }
-
- // release event: ungrab if no buttons are pressed anymore
- if (mouseIsReleased)
- removeGrabber(grabberItem, true, isDeliveringTouchAsMouse());
- deliverToPassiveGrabbers(point->passiveGrabbers(), pointerEvent);
- } else if (auto handler = point->grabberPointerHandler()) {
- pointerEvent->localize(handler->parentItem());
- hasFiltered.clear();
- if (!sendFilteredPointerEvent(pointerEvent, handler->parentItem()))
- handler->handlePointerEvent(pointerEvent);
- if (mouseIsReleased)
- point->setGrabberPointerHandler(nullptr, true);
- deliverToPassiveGrabbers(point->passiveGrabbers(), pointerEvent);
- } else {
- bool delivered = false;
- if (pointerEvent->isPressEvent()) {
- // send initial press
- delivered = deliverPressOrReleaseEvent(pointerEvent);
- } else if (pointerEvent->device()->type() == QInputDevice::DeviceType::Mouse) {
- // if this is an update or release from an actual mouse,
- // and the point wasn't grabbed, deliver only to PointerHandlers:
- // passive grabbers first, then the rest
- deliverToPassiveGrabbers(point->passiveGrabbers(), pointerEvent);
-
- // 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, false, false);
- for (QQuickItem *item : targetItems) {
- QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
- if (!itemPrivate->extra.isAllocated() || itemPrivate->extra->pointerHandlers.isEmpty())
- continue;
- pointerEvent->localize(item);
- hasFiltered.clear();
- if (!sendFilteredPointerEvent(pointerEvent, item)) {
- if (itemPrivate->handlePointerEvent(pointerEvent, true)) // avoid re-delivering to grabbers
- delivered = true;
- }
- if (point->exclusiveGrabber())
- break;
- }
- }
- }
-
- if (!delivered)
- // make sure not to accept unhandled events
- pointerEvent->setAccepted(false);
- }
-}
-
bool QQuickWindowPrivate::sendHoverEvent(QEvent::Type type, QQuickItem *item,
const QPointF &scenePos, const QPointF &lastScenePos,
Qt::KeyboardModifiers modifiers, ulong timestamp,
@@ -2291,14 +2142,13 @@ bool QQuickWindowPrivate::deliverHoverEvent(QQuickItem *item, const QPointF &sce
}
if (itemPrivate->hasPointerHandlers()) {
- const auto dev = QPointingDevice::primaryPointingDevice();
- QQuickPointerEvent *pointerEvent = pointerEventInstance(dev, QEvent::MouseMove);
- pointerEvent->point(0)->reset(QEventPoint::State::Updated, scenePos, dev->systemId(), timestamp, QVector2D());
- pointerEvent->point(0)->setAccepted(true);
- pointerEvent->localize(item);
+ const QPointF localPos = item->mapFromScene(scenePos);
+ QMouseEvent hoverEvent(QEvent::MouseMove, localPos, scenePos, q->mapToGlobal(scenePos), Qt::NoButton, Qt::NoButton, modifiers);
+ hoverEvent.setTimestamp(timestamp);
+ hoverEvent.setAccepted(true);
for (QQuickPointerHandler *h : itemPrivate->extra->pointerHandlers)
if (QQuickHoverHandler *hh = qmlobject_cast<QQuickHoverHandler *>(h))
- hh->handlePointerEvent(pointerEvent);
+ hh->handlePointerEvent(&hoverEvent);
}
if (itemPrivate->hoverEnabled) {
@@ -2355,49 +2205,26 @@ bool QQuickWindowPrivate::deliverHoverEvent(QQuickItem *item, const QPointF &sce
// Simple delivery of non-mouse, non-touch Pointer Events: visit the items and handlers
// in the usual reverse-paint-order until propagation is stopped
-bool QQuickWindowPrivate::deliverSinglePointEventUntilAccepted(QQuickPointerEvent *event)
+bool QQuickWindowPrivate::deliverSinglePointEventUntilAccepted(QPointerEvent *event)
{
- Q_ASSERT(event->pointCount() == 1);
- QQuickEventPoint *point = event->point(0);
- QVector<QQuickItem *> targetItems = pointerTargets(contentItem, point, false, false);
+ Q_ASSERT(event->points().count() == 1);
+ QEventPoint &point = event->point(0);
+ QVector<QQuickItem *> targetItems = pointerTargets(contentItem, event, point, false, false);
+ point.setAccepted(false);
for (QQuickItem *item : targetItems) {
QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
- event->localize(item);
+ localizePointerEvent(event, item);
// Let Pointer Handlers have the first shot
itemPrivate->handlePointerEvent(event);
- if (point->isAccepted())
+ if (point.isAccepted())
+ return true;
+ event->accept();
+ QCoreApplication::sendEvent(item, event);
+ if (event->isAccepted()) {
+ qCDebug(lcWheelTarget) << event << "->" << item;
return true;
- QPointF g = item->window()->mapToGlobal(point->scenePosition().toPoint());
-#if QT_CONFIG(wheelevent)
- // Let the Item have a chance to handle it
- if (QQuickPointerScrollEvent *pse = event->asPointerScrollEvent()) {
- QWheelEvent wheel(point->position(), g, pse->pixelDelta().toPoint(), pse->angleDelta().toPoint(),
- pse->buttons(), pse->modifiers(), pse->phase(),
- pse->isInverted(), pse->synthSource());
- wheel.setTimestamp(pse->timestamp());
- wheel.accept();
- QCoreApplication::sendEvent(item, &wheel);
- if (wheel.isAccepted()) {
- qCDebug(lcWheelTarget) << &wheel << "->" << item;
- event->setAccepted(true);
- return true;
- }
- }
-#endif
-#if QT_CONFIG(gestures)
- if (QQuickPointerNativeGestureEvent *pnge = event->asPointerNativeGestureEvent()) {
- QNativeGestureEvent nge(pnge->type(), pnge->device(), point->position(), point->scenePosition(), g,
- pnge->value(), 0L, 0L); // TODO can't copy things I can't access
- nge.accept();
- QCoreApplication::sendEvent(item, &nge);
- if (nge.isAccepted()) {
- qCDebug(lcGestureTarget) << &nge << "->" << item;
- event->setAccepted(true);
- return true;
- }
}
-#endif // gestures
}
return false; // it wasn't handled
@@ -2411,14 +2238,14 @@ void QQuickWindow::wheelEvent(QWheelEvent *event)
Q_QUICK_INPUT_PROFILE(QQuickProfiler::Mouse, QQuickProfiler::InputMouseWheel,
event->angleDelta().x(), event->angleDelta().y());
- qCDebug(DBG_MOUSE) << "QQuickWindow::wheelEvent()" << event->pixelDelta() << event->angleDelta() << event->phase();
+ qCDebug(DBG_MOUSE) << event;
//if the actual wheel event was accepted, accept the compatibility wheel event and return early
if (d->lastWheelEventAccepted && event->angleDelta().isNull() && event->phase() == Qt::ScrollUpdate)
return;
event->ignore();
- d->deliverPointerEvent(d->pointerEventInstance(event));
+ d->deliverSinglePointEventUntilAccepted(event);
d->lastWheelEventAccepted = event->isAccepted();
}
#endif // wheelevent
@@ -2430,37 +2257,123 @@ void QQuickWindow::tabletEvent(QTabletEvent *event)
Q_D(QQuickWindow);
qCDebug(lcTablet) << event;
// TODO Qt 6: make sure TabletEnterProximity and TabletLeaveProximity are delivered here
- d->deliverPointerEvent(d->pointerEventInstance(event));
+ d->deliverPointerEvent(event);
}
#endif // tabletevent
bool QQuickWindowPrivate::deliverTouchCancelEvent(QTouchEvent *event)
{
qCDebug(DBG_TOUCH) << event;
- Q_Q(QQuickWindow);
- if (QQuickItem *grabber = q->mouseGrabberItem())
- sendUngrabEvent(grabber, true);
- cancelTouchMouseSynthesis();
+ if (isDeliveringTouchAsMouse()) {
+ if (QQuickItem *grabber = qmlobject_cast<QQuickItem *>(event->exclusiveGrabber(touchMouseId)))
+ sendUngrabEvent(grabber, true);
+ }
- // A TouchCancel event will typically not contain any points.
+ // An incoming TouchCancel event will typically not contain any points,
+ // but sendTouchCancelEvent() adds the points that have grabbers to the event.
// Deliver it to all items and handlers that have active touches.
- QQuickPointerEvent *pointerEvent = pointerEventInstance(event->pointingDevice());
- for (int i = 0; i < pointerEvent->pointCount(); ++i)
- pointerEvent->point(i)->cancelExclusiveGrabImpl(event);
+ const_cast<QPointingDevicePrivate *>(QPointingDevicePrivate::get(event->pointingDevice()))->
+ sendTouchCancelEvent(event);
- // The next touch event can only be a TouchBegin, so clean up.
- pointerEvent->clearGrabbers();
return true;
}
void QQuickWindowPrivate::deliverDelayedTouchEvent()
{
// Deliver and delete delayedTouch.
- // Set delayedTouch to 0 before delivery to avoid redelivery in case of
+ // Set delayedTouch to nullptr before delivery to avoid redelivery in case of
// event loop recursions (e.g if it the touch starts a dnd session).
QScopedPointer<QTouchEvent> e(delayedTouch.take());
- deliverPointerEvent(pointerEventInstance(e.data()));
+ qCDebug(lcTouchCmprs) << "delivering" << e.data();
+ deliverPointerEvent(e.data());
+}
+
+bool QQuickWindowPrivate::allUpdatedPointsAccepted(const QPointerEvent *ev)
+{
+ for (auto &point : ev->points()) {
+ if (point.state() != QEventPoint::State::Pressed && !point.isAccepted())
+ return false;
+ }
+ return true;
+}
+
+/*! \internal
+ Localize \a ev for delivery to \a dest.
+
+ Unlike QMutableTouchEvent::localized(), this modifies the QEventPoint
+ instances in \a ev, which is more efficient than making a copy.
+*/
+void QQuickWindowPrivate::localizePointerEvent(QPointerEvent *ev, const QQuickItem *dest)
+{
+ for (int i = 0; i < ev->pointCount(); ++i) {
+ auto &point = QMutableEventPoint::from(ev->point(i));
+ QMutableEventPoint::from(point).setPosition(dest->mapFromScene(point.scenePosition()));
+ }
+}
+
+QList<QObject *> QQuickWindowPrivate::exclusiveGrabbers(QPointerEvent *ev)
+{
+ QList<QObject *> result;
+ for (const QEventPoint &point : ev->points()) {
+ if (QObject *grabber = ev->exclusiveGrabber(point)) {
+ if (!result.contains(grabber))
+ result << grabber;
+ }
+ }
+ return result;
+}
+
+bool QQuickWindowPrivate::isMouseEvent(const QPointerEvent *ev)
+{
+ switch (ev->type()) {
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseButtonDblClick:
+ case QEvent::MouseMove:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool QQuickWindowPrivate::isTouchEvent(const QPointerEvent *ev)
+{
+ switch (ev->type()) {
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate:
+ case QEvent::TouchEnd:
+ case QEvent::TouchCancel:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool QQuickWindowPrivate::isTabletEvent(const QPointerEvent *ev)
+{
+ switch (ev->type()) {
+ case QEvent::TabletPress:
+ case QEvent::TabletMove:
+ case QEvent::TabletRelease:
+ case QEvent::TabletEnterProximity:
+ case QEvent::TabletLeaveProximity:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/*! \internal
+ Add the given \a point.
+*/
+void QMutableTouchEvent::addPoint(const QEventPoint &point)
+{
+ m_points.append(point);
+ auto &added = m_points.last();
+ if (!added.device())
+ QMutableEventPoint::from(added).setDevice(pointingDevice());
+ m_touchPointStates |= point.state();
}
bool QQuickWindowPrivate::compressTouchEvent(QTouchEvent *event)
@@ -2468,13 +2381,14 @@ bool QQuickWindowPrivate::compressTouchEvent(QTouchEvent *event)
Q_Q(QQuickWindow);
QEventPoint::States states = event->touchPointStates();
if (states.testFlag(QEventPoint::State::Pressed) || states.testFlag(QEventPoint::State::Released)) {
- // we can only compress something that isn't a press or release
+ // we can only compress an event that doesn't include any pressed or released points
return false;
}
if (!delayedTouch) {
delayedTouch.reset(new QMutableTouchEvent(event->type(), event->pointingDevice(), event->modifiers(), event->points()));
delayedTouch->setTimestamp(event->timestamp());
+ qCDebug(lcTouchCmprs) << "delayed" << delayedTouch.data();
if (renderControl)
QQuickRenderControlPrivate::get(renderControl)->maybeUpdate();
else if (windowManager)
@@ -2510,6 +2424,7 @@ bool QQuickWindowPrivate::compressTouchEvent(QTouchEvent *event)
// TODO optimize, or move event compression elsewhere
delayedTouch.reset(new QMutableTouchEvent(event->type(), event->pointingDevice(), event->modifiers(), tpts));
delayedTouch->setTimestamp(event->timestamp());
+ qCDebug(lcTouchCmprs) << "coalesced" << delayedTouch.data();
return true;
}
}
@@ -2529,6 +2444,7 @@ bool QQuickWindowPrivate::compressTouchEvent(QTouchEvent *event)
void QQuickWindowPrivate::handleTouchEvent(QTouchEvent *event)
{
translateTouchEvent(event);
+ // TODO remove: touch and mouse should be independent until we come to touch->mouse synth
if (event->pointCount()) {
auto &point = event->point(0);
if (point.state() == QEventPoint::State::Released) {
@@ -2543,14 +2459,16 @@ void QQuickWindowPrivate::handleTouchEvent(QTouchEvent *event)
static bool qquickwindow_no_touch_compression = qEnvironmentVariableIsSet("QML_NO_TOUCH_COMPRESSION");
if (qquickwindow_no_touch_compression || pointerEventRecursionGuard) {
- deliverPointerEvent(pointerEventInstance(event));
+ deliverPointerEvent(event);
return;
}
if (!compressTouchEvent(event)) {
- if (delayedTouch)
+ if (delayedTouch) {
deliverDelayedTouchEvent();
- deliverPointerEvent(pointerEventInstance(event));
+ qCDebug(lcTouchCmprs) << "resuming delivery" << event;
+ }
+ deliverPointerEvent(event);
}
}
@@ -2591,12 +2509,12 @@ void QQuickWindowPrivate::handleMouseEvent(QMouseEvent *event)
case QEvent::MouseButtonPress:
Q_QUICK_INPUT_PROFILE(QQuickProfiler::Mouse, QQuickProfiler::InputMousePress, event->button(),
event->buttons());
- deliverPointerEvent(pointerEventInstance(event));
+ deliverPointerEvent(event);
break;
case QEvent::MouseButtonRelease:
Q_QUICK_INPUT_PROFILE(QQuickProfiler::Mouse, QQuickProfiler::InputMouseRelease, event->button(),
event->buttons());
- deliverPointerEvent(pointerEventInstance(event));
+ deliverPointerEvent(event);
#if QT_CONFIG(cursor)
updateCursor(event->scenePosition());
#endif
@@ -2605,7 +2523,7 @@ void QQuickWindowPrivate::handleMouseEvent(QMouseEvent *event)
Q_QUICK_INPUT_PROFILE(QQuickProfiler::Mouse, QQuickProfiler::InputMouseDoubleClick,
event->button(), event->buttons());
if (allowDoubleClick)
- deliverPointerEvent(pointerEventInstance(event));
+ deliverPointerEvent(event);
break;
case QEvent::MouseMove: {
Q_QUICK_INPUT_PROFILE(QQuickProfiler::Mouse, QQuickProfiler::InputMouseMove,
@@ -2616,8 +2534,7 @@ void QQuickWindowPrivate::handleMouseEvent(QMouseEvent *event)
#if QT_CONFIG(cursor)
updateCursor(event->scenePosition());
#endif
- auto pointerEvent = pointerEventInstance(event->pointingDevice());
- if (!pointerEvent->pointCount() || !pointerEvent->point(0)->exclusiveGrabber()) {
+ if (!event->points().count() || !event->exclusiveGrabber(event->point(0))) {
QPointF last = lastMousePosition.isNull() ? event->scenePosition() : lastMousePosition;
lastMousePosition = event->scenePosition();
@@ -2629,7 +2546,7 @@ void QQuickWindowPrivate::handleMouseEvent(QMouseEvent *event)
}
event->setAccepted(accepted);
}
- deliverPointerEvent(pointerEventInstance(event));
+ deliverPointerEvent(event);
break;
}
default:
@@ -2660,6 +2577,7 @@ void QQuickWindowPrivate::flushFrameSynchronousEvents()
// For instance, during animation (including the case of a ListView
// whose delegates contain MouseAreas), a MouseArea needs to know
// whether it has moved into a position where it is now under the cursor.
+ // TODO do this for each known mouse device or come up with a different strategy
if (!q->mouseGrabberItem() && !lastMousePosition.isNull() && dirtyItemList) {
bool accepted = false;
bool delivered = deliverHoverEvent(contentItem, lastMousePosition, lastMousePosition, QGuiApplication::keyboardModifiers(), 0, accepted);
@@ -2669,136 +2587,71 @@ void QQuickWindowPrivate::flushFrameSynchronousEvents()
#endif
}
-QQuickPointerEvent *QQuickWindowPrivate::queryPointerEventInstance(const QPointingDevice *device, QEvent::Type eventType) const
+void QQuickWindowPrivate::onGrabChanged(QObject *grabber, QPointingDevice::GrabTransition transition,
+ const QPointerEvent *event, const QEventPoint &point)
{
- // Search for a matching reusable event object.
- for (QQuickPointerEvent *e : pointerEventInstances) {
- // If device can generate native gestures (e.g. a trackpad), there might be multiple QQuickPointerEvents:
- // QQuickPointerNativeGestureEvent, QQuickPointerScrollEvent, and QQuickPointerTouchEvent.
- // Use eventType to disambiguate.
-#if QT_CONFIG(gestures)
- if ((eventType == QEvent::NativeGesture) != bool(e->asPointerNativeGestureEvent()))
- continue;
-#endif
- if ((eventType == QEvent::Wheel) != bool(e->asPointerScrollEvent()))
- continue;
- // Otherwise we assume there's only one event type per device.
- // More disambiguation tests might need to be added above if that changes later.
- if (e->device() == device)
- return e;
- }
- return nullptr;
-}
-
-QQuickPointerEvent *QQuickWindowPrivate::pointerEventInstance(const QPointingDevice *device, QEvent::Type eventType) const
-{
- QQuickPointerEvent *ev = queryPointerEventInstance(device, eventType);
- if (ev)
- return ev;
- QQuickWindow *q = const_cast<QQuickWindow*>(q_func());
- switch (device->type()) {
- case QInputDevice::DeviceType::Mouse:
- // QWindowSystemInterface::handleMouseEvent() does not take a device parameter:
- // we assume all mouse events come from one mouse (the "core pointer").
- // So when the event is a mouse event, device == QPointingDevice::primaryPointingDevice()
- if (eventType == QEvent::Wheel)
- ev = new QQuickPointerScrollEvent(q, device);
- else
- ev = new QQuickPointerMouseEvent(q, device);
+ qCDebug(lcPtrGrab) << grabber << transition << event << point;
+ // event can be null, if the signal was emitted from QPointingDevicePrivate::removeGrabber(grabber)
+ switch (transition) {
+ case QPointingDevice::UngrabExclusive:
+ if (point.device()->type() == QInputDevice::DeviceType::Mouse || isDeliveringTouchAsMouse())
+ sendUngrabEvent(qobject_cast<QQuickItem *>(grabber), isDeliveringTouchAsMouse());
break;
- case QInputDevice::DeviceType::TouchPad:
- case QInputDevice::DeviceType::TouchScreen:
-#if QT_CONFIG(gestures)
- if (eventType == QEvent::NativeGesture)
- ev = new QQuickPointerNativeGestureEvent(q, device);
- else // assume QEvent::Type is one of TouchBegin/Update/End
-#endif
- ev = new QQuickPointerTouchEvent(q, device);
- break;
-#if QT_CONFIG(tabletevent)
- case QInputDevice::DeviceType::Stylus:
- case QPointingDevice::DeviceType::Airbrush:
- case QPointingDevice::DeviceType::Puck:
- ev = new QQuickPointerTabletEvent(q, device);
- break;
-#endif
default:
break;
}
- pointerEventInstances << ev;
- return ev;
}
-/*!
- \internal
- Returns a QQuickPointerEvent instance suitable for wrapping and delivering \a event.
-
- There is a unique instance per QPointingDevice, which is determined
- from \a event's device.
-*/
-QQuickPointerEvent *QQuickWindowPrivate::pointerEventInstance(QEvent *event) const
+void QQuickWindowPrivate::ensureDeviceConnected(const QPointingDevice *dev)
{
- const QPointingDevice *dev = nullptr;
- switch (event->type()) {
- case QEvent::MouseButtonPress:
- case QEvent::MouseButtonRelease:
- case QEvent::MouseButtonDblClick:
- case QEvent::MouseMove:
- case QEvent::Wheel:
- case QEvent::TouchBegin:
- case QEvent::TouchUpdate:
- case QEvent::TouchEnd:
- case QEvent::TouchCancel:
-#if QT_CONFIG(tabletevent)
- case QEvent::TabletPress:
- case QEvent::TabletMove:
- case QEvent::TabletRelease:
- case QEvent::TabletEnterProximity:
- case QEvent::TabletLeaveProximity:
-#endif
-#if QT_CONFIG(gestures)
- case QEvent::NativeGesture:
-#endif
- dev = static_cast<QPointerEvent *>(event)->pointingDevice();
- break;
- default:
- break;
- }
-
- Q_ASSERT(dev);
- return pointerEventInstance(dev, event->type())->reset(event);
+ if (knownPointingDevices.contains(dev))
+ return;
+ knownPointingDevices.append(dev);
+ connect(dev, &QPointingDevice::grabChanged, this, &QQuickWindowPrivate::onGrabChanged);
}
-void QQuickWindowPrivate::deliverPointerEvent(QQuickPointerEvent *event)
+void QQuickWindowPrivate::deliverPointerEvent(QPointerEvent *event)
{
- Q_Q(QQuickWindow);
// If users spin the eventloop as a result of event delivery, we disable
// event compression and send events directly. This is because we consider
// the usecase a bit evil, but we at least don't want to lose events.
++pointerEventRecursionGuard;
+ eventsInDelivery.push(event);
skipDelivery.clear();
- if (event->asPointerMouseEvent()) {
- deliverMouseEvent(event->asPointerMouseEvent());
- // failsafe: never allow any kind of grab to persist after release
- if (event->isReleaseEvent() && event->buttons() == Qt::NoButton) {
- QQuickItem *oldGrabber = q->mouseGrabberItem();
- event->clearGrabbers();
- sendUngrabEvent(oldGrabber, false);
+ QQuickPointerHandlerPrivate::deviceDeliveryTargets(event->pointingDevice()).clear();
+ qCDebug(lcPtr) << "delivering" << event;
+ for (int i = 0; i < event->pointCount(); ++i)
+ event->point(i).setAccepted(false);
+
+ if (event->isBeginEvent()) {
+ ensureDeviceConnected(event->pointingDevice());
+ if (!deliverPressOrReleaseEvent(event))
+ event->setAccepted(false);
+ }
+ if (!allUpdatedPointsAccepted(event))
+ deliverUpdatedPoints(event);
+ if (event->isEndEvent())
+ deliverPressOrReleaseEvent(event, true);
+
+ // failsafe: never allow any kind of grab to persist after release
+ if (event->isEndEvent()) {
+ if (isTouchEvent(event)) {
+ for (int i = 0; i < event->pointCount(); ++i) {
+ auto &point = event->point(i);
+ event->setExclusiveGrabber(point, nullptr);
+ event->clearPassiveGrabbers(point);
+ }
+ // never allow touch->mouse synthesis to persist either
+ cancelTouchMouseSynthesis();
+ } else if (static_cast<QSinglePointEvent *>(event)->buttons() == Qt::NoButton) {
+ auto &firstPt = event->point(0);
+ event->setExclusiveGrabber(firstPt, nullptr);
+ event->clearPassiveGrabbers(firstPt);
}
- } else if (event->asPointerTouchEvent()) {
- deliverTouchEvent(event->asPointerTouchEvent());
- } else {
- deliverSinglePointEventUntilAccepted(event);
- // If any handler got interested in the tablet event, we don't want to receive a synth-mouse event from QtGui
- // TODO Qt 6: QTabletEvent will be accepted by default, like other events
- if (event->asPointerTabletEvent() &&
- (!event->point(0)->passiveGrabbers().isEmpty() || event->point(0)->exclusiveGrabber()))
- event->setAccepted(true);
}
- event->reset(nullptr);
-
+ eventsInDelivery.pop();
--pointerEventRecursionGuard;
}
@@ -2807,11 +2660,12 @@ void QQuickWindowPrivate::deliverPointerEvent(QQuickPointerEvent *event)
// 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, QQuickEventPoint *point, bool checkMouseButtons, bool checkAcceptsTouch) const
+QVector<QQuickItem *> QQuickWindowPrivate::pointerTargets(QQuickItem *item, const QPointerEvent *event, const QEventPoint &point,
+ bool checkMouseButtons, bool checkAcceptsTouch) const
{
QVector<QQuickItem *> targets;
auto itemPrivate = QQuickItemPrivate::get(item);
- QPointF itemPos = item->mapFromScene(point->scenePosition());
+ QPointF itemPos = item->mapFromScene(point.scenePosition());
bool relevant = item->contains(itemPos);
// if the item clips, we can potentially return early
if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) {
@@ -2821,7 +2675,7 @@ QVector<QQuickItem *> QQuickWindowPrivate::pointerTargets(QQuickItem *item, QQui
if (itemPrivate->hasPointerHandlers()) {
if (!relevant)
- if (itemPrivate->anyPointerHandlerWants(point))
+ if (itemPrivate->anyPointerHandlerWants(event, point))
relevant = true;
} else {
if (relevant && checkMouseButtons && item->acceptedMouseButtons() == Qt::NoButton)
@@ -2844,7 +2698,7 @@ QVector<QQuickItem *> QQuickWindowPrivate::pointerTargets(QQuickItem *item, QQui
continue;
if (child != item)
- targets << pointerTargets(child, point, checkMouseButtons, checkAcceptsTouch);
+ targets << pointerTargets(child, event, point, checkMouseButtons, checkAcceptsTouch);
else
targets << child;
}
@@ -2874,45 +2728,14 @@ QVector<QQuickItem *> QQuickWindowPrivate::mergePointerTargets(const QVector<QQu
return targets;
}
-void QQuickWindowPrivate::deliverTouchEvent(QQuickPointerTouchEvent *event)
-{
- qCDebug(DBG_TOUCH) << " - delivering" << event->asTouchEvent();
-
- if (event->isPressEvent())
- deliverPressOrReleaseEvent(event);
- if (!event->allUpdatedPointsAccepted())
- deliverUpdatedTouchPoints(event);
- if (event->isReleaseEvent())
- deliverPressOrReleaseEvent(event, true);
-
- // Remove released points from itemForTouchPointId
- bool allReleased = true;
- int pointCount = event->pointCount();
- for (int i = 0; i < pointCount; ++i) {
- QQuickEventPoint *point = event->point(i);
- if (point->state() == QQuickEventPoint::Released) {
- int id = point->pointId();
- qCDebug(DBG_TOUCH_TARGET) << "TP" << Qt::hex << id << "released";
- point->setGrabberItem(nullptr);
- if (id == touchMouseId)
- cancelTouchMouseSynthesis();
- } else {
- allReleased = false;
- }
- }
-
- if (allReleased) {
- if (Q_UNLIKELY(!event->exclusiveGrabbers().isEmpty()))
- qWarning() << "No release received for some grabbers" << event->exclusiveGrabbers();
- event->clearGrabbers();
- }
-}
-
-// Deliver touch points to existing grabbers
-void QQuickWindowPrivate::deliverUpdatedTouchPoints(QQuickPointerTouchEvent *event)
+/*! \internal
+ Deliver updated points to existing grabbers.
+*/
+void QQuickWindowPrivate::deliverUpdatedPoints(QPointerEvent *event)
{
bool done = false;
- const auto grabbers = event->exclusiveGrabbers();
+ const auto grabbers = exclusiveGrabbers(event);
+ hasFiltered.clear();
for (auto grabber : grabbers) {
// The grabber is guaranteed to be either an item or a handler.
QQuickItem *receiver = qmlobject_cast<QQuickItem *>(grabber);
@@ -2923,22 +2746,19 @@ void QQuickWindowPrivate::deliverUpdatedTouchPoints(QQuickPointerTouchEvent *eve
hasFiltered.clear();
if (sendFilteredPointerEvent(event, receiver))
done = true;
- event->localize(receiver);
+ localizePointerEvent(event, receiver);
handler->handlePointerEvent(event);
}
if (done)
break;
// If the grabber is an item or the grabbing handler didn't handle it,
// then deliver the event to the item (which may have multiple handlers).
- deliverMatchingPointsToItem(receiver, event);
+ deliverMatchingPointsToItem(receiver, true, event);
}
// Deliver to each eventpoint's passive grabbers (but don't visit any handler more than once)
- int pointCount = event->pointCount();
- for (int i = 0; i < pointCount; ++i) {
- QQuickEventPoint *point = event->point(i);
- deliverToPassiveGrabbers(point->passiveGrabbers(), event);
- }
+ for (auto &point : event->points())
+ deliverToPassiveGrabbers(event->passiveGrabbers(point), event);
if (done)
return;
@@ -2946,11 +2766,10 @@ void QQuickWindowPrivate::deliverUpdatedTouchPoints(QQuickPointerTouchEvent *eve
// If some points weren't grabbed, deliver only to non-grabber PointerHandlers in reverse paint order
if (!event->allPointsGrabbed()) {
QVector<QQuickItem *> targetItems;
- for (int i = 0; i < pointCount; ++i) {
- QQuickEventPoint *point = event->point(i);
- if (point->state() == QQuickEventPoint::Pressed)
+ for (auto &point : event->points()) {
+ if (point.state() == QEventPoint::Pressed)
continue; // presses were delivered earlier; not the responsibility of deliverUpdatedTouchPoints
- QVector<QQuickItem *> targetItemsForPoint = pointerTargets(contentItem, point, false, false);
+ QVector<QQuickItem *> targetItemsForPoint = pointerTargets(contentItem, event, point, false, false);
if (targetItems.count()) {
targetItems = mergePointerTargets(targetItems, targetItemsForPoint);
} else {
@@ -2961,7 +2780,7 @@ void QQuickWindowPrivate::deliverUpdatedTouchPoints(QQuickPointerTouchEvent *eve
if (grabbers.contains(item))
continue;
QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
- event->localize(item);
+ localizePointerEvent(event, item);
itemPrivate->handlePointerEvent(event, true); // avoid re-delivering to grabbers
if (event->allPointsGrabbed())
break;
@@ -2970,13 +2789,12 @@ void QQuickWindowPrivate::deliverUpdatedTouchPoints(QQuickPointerTouchEvent *eve
}
// Deliver an event containing newly pressed or released touch points
-bool QQuickWindowPrivate::deliverPressOrReleaseEvent(QQuickPointerEvent *event, bool handlersOnly)
+bool QQuickWindowPrivate::deliverPressOrReleaseEvent(QPointerEvent *event, bool handlersOnly)
{
- int pointCount = event->pointCount();
QVector<QQuickItem *> targetItems;
- bool isTouchEvent = (event->asPointerTouchEvent() != nullptr);
- if (isTouchEvent && event->isPressEvent() && isDeliveringTouchAsMouse()) {
- if (const QQuickEventPoint *point = pointerEventInstance(touchMouseDevice)->pointById(touchMouseId)) {
+ const bool isTouch = isTouchEvent(event);
+ if (isTouch && event->isBeginEvent() && isDeliveringTouchAsMouse()) {
+ if (auto point = const_cast<QPointingDevicePrivate *>(QPointingDevicePrivate::get(touchMouseDevice))->queryPointById(touchMouseId)) {
// When a second point is pressed, if the first point's existing
// grabber was a pointer handler while a filtering parent is filtering
// the same first point _as mouse_: we're starting over with delivery,
@@ -2986,20 +2804,17 @@ bool QQuickWindowPrivate::deliverPressOrReleaseEvent(QQuickPointerEvent *event,
// synth-mouse and perhaps grab it. Ideally we would always do this
// when a new touchpoint is pressed, but this compromise fixes
// QTBUG-70998 and avoids breaking tst_FlickableInterop::touchDragSliderAndFlickable
- if (point->grabberPointerHandler())
+ if (qobject_cast<QQuickPointerHandler *>(event->exclusiveGrabber(point->eventPoint)))
cancelTouchMouseSynthesis();
} else {
qCWarning(DBG_TOUCH_TARGET) << "during delivery of touch press, synth-mouse ID" << Qt::hex << touchMouseId << "is missing from" << event;
}
}
- for (int i = 0; i < pointCount; ++i) {
- auto point = event->point(i);
- if (point->state() == QQuickEventPoint::Pressed && !event->isDoubleClickEvent())
- point->clearPassiveGrabbers();
- point->setAccepted(false); // because otherwise touchEventForItem will ignore it
- if (point->grabberPointerHandler() && point->state() == QQuickEventPoint::Released)
- point->setGrabberPointerHandler(nullptr, true);
- QVector<QQuickItem *> targetItemsForPoint = pointerTargets(contentItem, point, !isTouchEvent, isTouchEvent);
+ for (int i = 0; i < event->pointCount(); ++i) {
+ auto &point = event->point(i);
+ if (point.state() == QEventPoint::Pressed && event->type() != QEvent::MouseButtonDblClick)
+ event->clearPassiveGrabbers(point);
+ QVector<QQuickItem *> targetItemsForPoint = pointerTargets(contentItem, event, point, !isTouch, isTouch);
if (targetItems.count()) {
targetItems = mergePointerTargets(targetItems, targetItemsForPoint);
} else {
@@ -3008,15 +2823,11 @@ bool QQuickWindowPrivate::deliverPressOrReleaseEvent(QQuickPointerEvent *event,
}
for (QQuickItem *item : targetItems) {
- if (!event->m_event) {
- qWarning("event went missing during delivery! (nested sendEvent() is not allowed)");
- break;
- }
hasFiltered.clear();
if (!handlersOnly && sendFilteredPointerEvent(event, item)) {
if (event->isAccepted()) {
for (int i = 0; i < event->pointCount(); ++i)
- event->point(i)->setAccepted();
+ event->point(i).setAccepted();
return true;
}
skipDelivery.append(item);
@@ -3026,11 +2837,7 @@ bool QQuickWindowPrivate::deliverPressOrReleaseEvent(QQuickPointerEvent *event,
// nor to any item which already had a chance to filter.
if (skipDelivery.contains(item))
continue;
- if (!event->m_event) {
- qWarning("event went missing during delivery! (nested sendEvent() is not allowed)");
- break;
- }
- deliverMatchingPointsToItem(item, event, handlersOnly);
+ deliverMatchingPointsToItem(item, false, event, handlersOnly);
if (event->allPointsAccepted())
handlersOnly = true;
}
@@ -3038,77 +2845,78 @@ bool QQuickWindowPrivate::deliverPressOrReleaseEvent(QQuickPointerEvent *event,
return event->allPointsAccepted();
}
-void QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, QQuickPointerEvent *pointerEvent, bool handlersOnly)
+void QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, bool isGrabber, QPointerEvent *pointerEvent, bool handlersOnly)
{
- Q_Q(QQuickWindow);
QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
- pointerEvent->localize(item);
+ localizePointerEvent(pointerEvent, item);
+ bool isMouse = isMouseEvent(pointerEvent);
// Let the Item's handlers (if any) have the event first.
// However, double click should never be delivered to handlers.
- if (!pointerEvent->isDoubleClickEvent()) {
+ if (pointerEvent->type() != QEvent::MouseButtonDblClick) {
bool wasAccepted = pointerEvent->allPointsAccepted();
itemPrivate->handlePointerEvent(pointerEvent);
- allowDoubleClick = wasAccepted || !(pointerEvent->asPointerMouseEvent() && pointerEvent->isPressEvent() && pointerEvent->allPointsAccepted());
+ allowDoubleClick = wasAccepted || !(isMouse && pointerEvent->isBeginEvent() && pointerEvent->allPointsAccepted());
}
if (handlersOnly)
return;
// If all points are released and the item is not the grabber, it doesn't get the event.
// But if at least one point is still pressed, we might be in a potential gesture-takeover scenario.
- if (pointerEvent->isReleaseEvent() && !pointerEvent->isUpdateEvent()
- && !pointerEvent->exclusiveGrabbers().contains(item))
+ if (pointerEvent->isEndEvent() && !pointerEvent->isUpdateEvent()
+ && !exclusiveGrabbers(pointerEvent).contains(item))
return;
// TODO: unite this mouse point delivery with the synthetic mouse event below
- auto event = pointerEvent->asPointerMouseEvent();
- if (event && item->acceptedMouseButtons() & event->button()) {
- auto point = event->point(0);
- // The only reason to already have a mouse grabber here is
- // synthetic events - flickable sends one when setPressDelay is used.
- auto oldMouseGrabber = q->mouseGrabberItem();
- QPointF localPos = item->mapFromScene(point->scenePosition());
- QMouseEvent *me = event->asMouseEvent(localPos);
- me->accept();
- QCoreApplication::sendEvent(item, me);
- if (me->isAccepted()) {
- auto mouseGrabber = q->mouseGrabberItem();
- if (mouseGrabber && mouseGrabber != item && mouseGrabber != oldMouseGrabber) {
- item->mouseUngrabEvent();
- } else if (item->isEnabled() && item->isVisible()) {
- item->grabMouse();
- }
- point->setAccepted(true);
+ if (isMouse && (isGrabber || (item->acceptedMouseButtons() & static_cast<QSinglePointEvent *>(pointerEvent)->button()))) {
+ // The only reason to already have a mouse grabber here is
+ // synthetic events - flickable sends one when setPressDelay is used.
+ auto oldMouseGrabber = pointerEvent->exclusiveGrabber(pointerEvent->point(0));
+ pointerEvent->accept();
+ if (isGrabber && sendFilteredPointerEvent(pointerEvent, item))
+ return;
+ localizePointerEvent(pointerEvent, item);
+ QCoreApplication::sendEvent(item, pointerEvent);
+ if (pointerEvent->isAccepted()) {
+ auto &point = pointerEvent->point(0);
+ auto mouseGrabber = pointerEvent->exclusiveGrabber(point);
+ if (mouseGrabber && mouseGrabber != item && mouseGrabber != oldMouseGrabber) {
+ // we don't need item->mouseUngrabEvent() because QQuickWindowPrivate::onGrabChanged does it
+ } else if (item->isEnabled() && item->isVisible()) {
+ pointerEvent->setExclusiveGrabber(point, item);
}
+ point.setAccepted(true);
+ }
return;
}
- QQuickPointerTouchEvent *ptEvent = pointerEvent->asPointerTouchEvent();
- if (!ptEvent)
+ if (!isTouchEvent(pointerEvent))
return;
- QScopedPointer<QTouchEvent> touchEvent(ptEvent->touchEventForItem(item));
- if (!touchEvent)
- return;
-
- qCDebug(DBG_TOUCH) << "considering delivering " << touchEvent.data() << " to " << item;
bool eventAccepted = false;
+ QTouchEvent touchEvent = QQuickItemPrivate::get(item)->localizedTouchEvent(static_cast<QTouchEvent *>(pointerEvent), false);
+ if (touchEvent.type() == QEvent::None)
+ return; // no points inside this item
- // If any parent filters the event, we're done.
- hasFiltered.clear();
- if (sendFilteredPointerEvent(pointerEvent, item))
- return;
+ if (item->acceptTouchEvents()) {
+ qCDebug(DBG_TOUCH) << "considering delivering" << &touchEvent << " to " << item;
- // Deliver the touch event to the given item
- qCDebug(DBG_TOUCH) << " - actually delivering " << touchEvent.data() << " to " << item;
- QCoreApplication::sendEvent(item, touchEvent.data());
- eventAccepted = touchEvent->isAccepted();
+ // If any parent filters the event, we're done.
+ hasFiltered.clear();
+ if (sendFilteredPointerEvent(pointerEvent, item))
+ return;
+
+ // Deliver the touch event to the given item
+ qCDebug(DBG_TOUCH) << "actually delivering" << &touchEvent << " to " << item;
+ QCoreApplication::sendEvent(item, &touchEvent);
+ eventAccepted = touchEvent.isAccepted();
+ }
// If the touch event wasn't accepted, synthesize a mouse event and see if the item wants it.
if (Q_LIKELY(QCoreApplication::testAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents))) {
if (!eventAccepted && (itemPrivate->acceptedMouseButtons() & Qt::LeftButton)) {
// send mouse event
- if (deliverTouchAsMouse(item, ptEvent))
+ if (deliverTouchAsMouse(item, &touchEvent))
eventAccepted = true;
}
}
@@ -3116,24 +2924,21 @@ 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 isPressOrRelease = pointerEvent->isPressEvent() || pointerEvent->isReleaseEvent();
- for (const auto &point: touchEvent->points()) {
- if (auto pointerEventPoint = ptEvent->pointById(point.id())) {
- pointerEventPoint->setAccepted();
- if (isPressOrRelease)
- pointerEventPoint->setGrabberItem(item);
- }
+ bool isPressOrRelease = pointerEvent->isBeginEvent() || pointerEvent->isEndEvent();
+ for (int i = 0; i < touchEvent.pointCount(); ++i) {
+ auto &point = QMutableEventPoint::from(touchEvent.point(i));
+ point.setAccepted();
+ if (isPressOrRelease)
+ pointerEvent->setExclusiveGrabber(point, item);
}
} else {
// But if the event was not accepted then we know this item
// will not be interested in further updates for those touchpoint IDs either.
- for (const auto &point: touchEvent->points()) {
+ for (const auto &point: touchEvent.points()) {
if (point.state() == QEventPoint::State::Pressed) {
- if (auto *tp = ptEvent->pointById(point.id())) {
- if (tp->exclusiveGrabber() == item) {
- qCDebug(DBG_TOUCH_TARGET) << "TP" << Qt::hex << point.id() << "disassociated";
- tp->setGrabberItem(nullptr);
- }
+ if (pointerEvent->exclusiveGrabber(point) == item) {
+ qCDebug(DBG_TOUCH_TARGET) << "TP" << Qt::hex << point.id() << "disassociated";
+ pointerEvent->setExclusiveGrabber(point, nullptr);
}
}
}
@@ -3342,11 +3147,7 @@ QPair<QQuickItem*, QQuickPointerHandler*> QQuickWindowPrivate::findCursorItemAnd
}
if (itemPrivate->hasCursorHandler) {
if (auto handler = itemPrivate->effectiveCursorHandler()) {
- QQuickPointerEvent *pointerEvent = pointerEventInstance(QPointingDevice::primaryPointingDevice(), QEvent::MouseMove);
- pointerEvent->point(0)->reset(QEventPoint::State::Updated, scenePos, 0, 0);
- pointerEvent->point(0)->setAccepted(true);
- pointerEvent->localize(item);
- if (handler->parentContains(pointerEvent->point(0)))
+ if (handler->parentContains(scenePos))
return {item, handler};
}
}
@@ -3361,12 +3162,12 @@ QPair<QQuickItem*, QQuickPointerHandler*> QQuickWindowPrivate::findCursorItemAnd
}
#endif
-bool QQuickWindowPrivate::sendFilteredPointerEvent(QQuickPointerEvent *event, QQuickItem *receiver, QQuickItem *filteringParent)
+bool QQuickWindowPrivate::sendFilteredPointerEvent(QPointerEvent *event, QQuickItem *receiver, QQuickItem *filteringParent)
{
return sendFilteredPointerEventImpl(event, receiver, filteringParent ? filteringParent : receiver->parentItem());
}
-bool QQuickWindowPrivate::sendFilteredPointerEventImpl(QQuickPointerEvent *event, QQuickItem *receiver, QQuickItem *filteringParent)
+bool QQuickWindowPrivate::sendFilteredPointerEventImpl(QPointerEvent *event, QQuickItem *receiver, QQuickItem *filteringParent)
{
if (!allowChildEventFiltering)
return false;
@@ -3375,58 +3176,58 @@ bool QQuickWindowPrivate::sendFilteredPointerEventImpl(QQuickPointerEvent *event
bool filtered = false;
if (filteringParent->filtersChildMouseEvents() && !hasFiltered.contains(filteringParent)) {
hasFiltered.append(filteringParent);
- if (QQuickPointerMouseEvent *pme = event->asPointerMouseEvent()) {
+ if (isMouseEvent(event)) {
+ auto me = static_cast<QMouseEvent *>(event);
if (receiver->acceptedMouseButtons()) {
- QPointF localPos = receiver->mapFromScene(pme->point(0)->scenePosition());
- QMouseEvent *me = pme->asMouseEvent(localPos);
const bool wasAccepted = me->isAccepted();
- me->setAccepted(true);
- auto oldMouseGrabber = pme->point(0)->grabberItem();
- if (filteringParent->childMouseEventFilter(receiver, me)) {
+ Q_ASSERT(event->pointCount());
+ localizePointerEvent(event, receiver);
+ event->setAccepted(true);
+ auto oldMouseGrabber = event->exclusiveGrabber(event->point(0));
+ if (filteringParent->childMouseEventFilter(receiver, const_cast<QMouseEvent *>(me))) {
qCDebug(DBG_MOUSE) << "mouse event intercepted by childMouseEventFilter of " << filteringParent;
skipDelivery.append(filteringParent);
filtered = true;
- if (me->isAccepted() && pme->isPressEvent()) {
- auto mouseGrabber = pme->point(0)->grabberItem();
+ if (me->isAccepted() && me->isBeginEvent()) {
+ auto &point = event->point(0);
+ auto mouseGrabber = event->exclusiveGrabber(point);
if (mouseGrabber && mouseGrabber != receiver && mouseGrabber != oldMouseGrabber) {
receiver->mouseUngrabEvent();
} else {
- pme->point(0)->setGrabberItem(receiver);
+ event->setExclusiveGrabber(point, receiver);
}
}
} else {
// Restore accepted state if the event was not filtered.
- me->setAccepted(wasAccepted);
+ const_cast<QMouseEvent *>(me)->setAccepted(wasAccepted);
}
}
- } else if (QQuickPointerTouchEvent *pte = event->asPointerTouchEvent()) {
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ } else if (isTouchEvent(event)) {
+ auto te = static_cast<QTouchEvent *>(event);
bool acceptsTouchEvents = receiver->acceptTouchEvents();
-#else
- // In versions prior to Qt 6, we can't trust item->acceptTouchEvents() here, because it defaults to true.
- bool acceptsTouchEvents = false;
-#endif
- auto device = pte->device();
+ auto device = te->device();
if (device->type() == QInputDevice::DeviceType::TouchPad &&
device->capabilities().testFlag(QInputDevice::Capability::MouseEmulation)) {
qCDebug(DBG_TOUCH_TARGET) << "skipping filtering of synth-mouse event from" << device;
} else if (acceptsTouchEvents || receiver->acceptedMouseButtons()) {
// get a touch event customized for delivery to filteringParent
- QScopedPointer<QTouchEvent> filteringParentTouchEvent(pte->touchEventForItem(receiver, true));
- if (filteringParentTouchEvent) {
- if (filteringParent->childMouseEventFilter(receiver, filteringParentTouchEvent.data())) {
+ // TODO should not be necessary? because QQuickWindowPrivate::deliverMatchingPointsToItem() does it
+ QTouchEvent filteringParentTouchEvent =
+ QQuickItemPrivate::get(receiver)->localizedTouchEvent(te, true);
+ if (filteringParentTouchEvent.type() != QEvent::None) {
+ if (filteringParent->childMouseEventFilter(receiver, &filteringParentTouchEvent)) {
qCDebug(DBG_TOUCH) << "touch event intercepted by childMouseEventFilter of " << filteringParent;
skipDelivery.append(filteringParent);
- for (const auto &point: filteringParentTouchEvent->points()) {
- QQuickEventPoint *pt = event->pointById(point.id());
- pt->setAccepted();
- pt->setGrabberItem(filteringParent);
+ for (qsizetype i = 0; i < filteringParentTouchEvent.pointCount(); ++i) {
+ auto &point = QMutableEventPoint::from(filteringParentTouchEvent.point(i));
+ point.setAccepted();
+ te->setExclusiveGrabber(point, filteringParent);
}
return true;
- } else if (Q_LIKELY(QCoreApplication::testAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents))) {
+ }
+ else if (Q_LIKELY(QCoreApplication::testAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents))) {
// filteringParent didn't filter the touch event. Give it a chance to filter a synthetic mouse event.
- for (auto &tp : filteringParentTouchEvent->points()) {
-
+ for (auto &tp : filteringParentTouchEvent.points()) {
QEvent::Type t;
switch (tp.state()) {
case QEventPoint::State::Pressed:
@@ -3447,21 +3248,20 @@ bool QQuickWindowPrivate::sendFilteredPointerEventImpl(QQuickPointerEvent *event
if (touchMouseUnset || touchMouseId == tp.id()) {
// convert filteringParentTouchEvent (which is already transformed wrt local position, velocity, etc.)
// into a synthetic mouse event, and let childMouseEventFilter() have another chance with that
- QScopedPointer<QMouseEvent> mouseEvent(touchToMouseEvent(t, tp, filteringParentTouchEvent.data(), receiver, false));
+ QMouseEvent mouseEvent = touchToMouseEvent(t, tp, &filteringParentTouchEvent, receiver);
// If a filtering item calls QQuickWindow::mouseGrabberItem(), it should
// report the touchpoint's grabber. Whenever we send a synthetic mouse event,
// touchMouseId and touchMouseDevice must be set, even if it's only temporarily and isn't grabbed.
touchMouseId = tp.id();
- touchMouseDevice = event->device();
- const QPointingDevice *dev = touchMouseDevice;
- if (filteringParent->childMouseEventFilter(receiver, mouseEvent.data())) {
+ touchMouseDevice = event->pointingDevice();
+ if (filteringParent->childMouseEventFilter(receiver, &mouseEvent)) {
qCDebug(DBG_TOUCH) << "touch event intercepted as synth mouse event by childMouseEventFilter of " << filteringParent;
skipDelivery.append(filteringParent);
if (t != QEvent::MouseButtonRelease) {
qCDebug(DBG_TOUCH_TARGET) << "TP (mouse)" << Qt::hex << tp.id() << "->" << filteringParent;
- pointerEventInstance(dev)->pointById(tp.id())->setGrabberItem(filteringParent);
+ filteringParentTouchEvent.setExclusiveGrabber(tp, filteringParent);
touchMouseUnset = false; // We want to leave touchMouseId and touchMouseDevice set
- if (mouseEvent->isAccepted())
+ if (mouseEvent.isAccepted())
filteringParent->grabMouse();
}
filtered = true;
diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h
index 2046fb0462..632cf1b6da 100644
--- a/src/quick/items/qquickwindow_p.h
+++ b/src/quick/items/qquickwindow_p.h
@@ -64,8 +64,10 @@
#include <QtCore/qmutex.h>
#include <QtCore/qwaitcondition.h>
#include <QtCore/qrunnable.h>
+#include <QtCore/qstack.h>
#include <QtGui/private/qevent_p.h>
+#include <QtGui/private/qpointingdevice_p.h>
#include <QtGui/private/qwindow_p.h>
#include <QtGui/qevent.h>
#include <QtGui/qstylehints.h>
@@ -150,28 +152,33 @@ public:
#if QT_CONFIG(quick_draganddrop)
QQuickDragGrabber *dragGrabber;
#endif
- int touchMouseId;
+ QStack<QPointerEvent *> eventsInDelivery;
+
+ int touchMouseId; // only for obsolete stuff like QQuickItem::grabMouse()
+ // TODO get rid of these
const QPointingDevice *touchMouseDevice;
- bool checkIfDoubleTapped(ulong newPressEventTimestamp, QPoint newPressPos);
ulong touchMousePressTimestamp;
QPoint touchMousePressPos; // in screen coordiantes
+ bool isDeliveringTouchAsMouse() const { return touchMouseId != -1 && touchMouseDevice; }
void cancelTouchMouseSynthesis();
+ bool checkIfDoubleTapped(ulong newPressEventTimestamp, QPoint newPressPos);
+ QPointingDevicePrivate::EventPointData *mousePointData();
+ QPointerEvent *eventInDelivery() const;
+
// Mouse positions are saved in widget coordinates
QPointF lastMousePosition;
- bool deliverTouchAsMouse(QQuickItem *item, QQuickPointerEvent *pointerEvent);
- bool isDeliveringTouchAsMouse() const { return touchMouseId != -1 && touchMouseDevice; }
+ bool deliverTouchAsMouse(QQuickItem *item, QTouchEvent *pointerEvent);
void translateTouchEvent(QTouchEvent *touchEvent);
- void grabTouchPoints(QObject *grabber, const QVector<int> &ids);
void removeGrabber(QQuickItem *grabber, bool mouse = true, bool touch = true);
void sendUngrabEvent(QQuickItem *grabber, bool touch);
+ void onGrabChanged(QObject *grabber, QPointingDevice::GrabTransition transition, const QPointerEvent *event, const QEventPoint &point);
static QMouseEvent *cloneMouseEvent(QMouseEvent *event, QPointF *transformedLocalPos = nullptr);
- void deliverToPassiveGrabbers(const QVector<QPointer <QQuickPointerHandler> > &passiveGrabbers, QQuickPointerEvent *pointerEvent);
- void deliverMouseEvent(QQuickPointerMouseEvent *pointerEvent);
+ void deliverToPassiveGrabbers(const QVector<QPointer<QObject> > &passiveGrabbers, QPointerEvent *pointerEvent);
bool sendFilteredMouseEvent(QEvent *event, QQuickItem *receiver, QQuickItem *filteringParent);
- bool sendFilteredPointerEvent(QQuickPointerEvent *event, QQuickItem *receiver, QQuickItem *filteringParent = nullptr);
- bool sendFilteredPointerEventImpl(QQuickPointerEvent *event, QQuickItem *receiver, QQuickItem *filteringParent);
- bool deliverSinglePointEventUntilAccepted(QQuickPointerEvent *);
+ bool sendFilteredPointerEvent(QPointerEvent *event, QQuickItem *receiver, QQuickItem *filteringParent = nullptr);
+ bool sendFilteredPointerEventImpl(QPointerEvent *event, QQuickItem *receiver, QQuickItem *filteringParent);
+ bool deliverSinglePointEventUntilAccepted(QPointerEvent *);
// entry point of events to the window
void handleTouchEvent(QTouchEvent *);
@@ -180,22 +187,25 @@ public:
void flushFrameSynchronousEvents();
void deliverDelayedTouchEvent();
- // the device-specific event instances which are reused during event delivery
- mutable QVector<QQuickPointerEvent *> pointerEventInstances;
- QQuickPointerEvent *queryPointerEventInstance(const QPointingDevice *device, QEvent::Type eventType = QEvent::None) const;
- QQuickPointerEvent *pointerEventInstance(const QPointingDevice *device, QEvent::Type eventType = QEvent::None) const;
+ // utility functions that used to be in QQuickPointerEvent et al.
+ bool allUpdatedPointsAccepted(const QPointerEvent *ev);
+ void localizePointerEvent(QPointerEvent *ev, const QQuickItem *dest);
+ QList<QObject *> exclusiveGrabbers(QPointerEvent *ev);
+ static bool isMouseEvent(const QPointerEvent *ev);
+ static bool isTouchEvent(const QPointerEvent *ev);
+ static bool isTabletEvent(const QPointerEvent *ev);
// delivery of pointer events:
- QMouseEvent *touchToMouseEvent(QEvent::Type type, const QEventPoint &p, QTouchEvent *event, QQuickItem *item, bool transformNeeded = true);
- QQuickPointerEvent *pointerEventInstance(QEvent *ev) const;
- void deliverPointerEvent(QQuickPointerEvent *);
- void deliverTouchEvent(QQuickPointerTouchEvent *);
+ QMouseEvent touchToMouseEvent(QEvent::Type type, const QEventPoint &p, QTouchEvent *event, QQuickItem *item);
+ void ensureDeviceConnected(const QPointingDevice *dev);
+ void deliverPointerEvent(QPointerEvent *);
bool deliverTouchCancelEvent(QTouchEvent *);
- bool deliverPressOrReleaseEvent(QQuickPointerEvent *, bool handlersOnly = false);
- void deliverUpdatedTouchPoints(QQuickPointerTouchEvent *event);
- void deliverMatchingPointsToItem(QQuickItem *item, QQuickPointerEvent *pointerEvent, bool handlersOnly = false);
+ bool deliverPressOrReleaseEvent(QPointerEvent *, bool handlersOnly = false);
+ void deliverUpdatedPoints(QPointerEvent *event);
+ void deliverMatchingPointsToItem(QQuickItem *item, bool isGrabber, QPointerEvent *pointerEvent, bool handlersOnly = false);
- QVector<QQuickItem *> pointerTargets(QQuickItem *, QQuickEventPoint *point, bool checkMouseButtons, bool checkAcceptsTouch) const;
+ QVector<QQuickItem *> pointerTargets(QQuickItem *, const QPointerEvent *event, const QEventPoint &point,
+ bool checkMouseButtons, bool checkAcceptsTouch) const;
QVector<QQuickItem *> mergePointerTargets(const QVector<QQuickItem *> &list1, const QVector<QQuickItem *> &list2) const;
// hover delivery
@@ -277,6 +287,7 @@ public:
QQuickRenderControl *renderControl;
QScopedPointer<QQuickAnimatorController> animationController;
QScopedPointer<QMutableTouchEvent> delayedTouch;
+ QList<const QPointingDevice *> knownPointingDevices;
int pointerEventRecursionGuard;
diff --git a/tests/auto/quick/pointerhandlers/mousearea_interop/tst_mousearea_interop.cpp b/tests/auto/quick/pointerhandlers/mousearea_interop/tst_mousearea_interop.cpp
index 26b6e0540b..44d0e9a27a 100644
--- a/tests/auto/quick/pointerhandlers/mousearea_interop/tst_mousearea_interop.cpp
+++ b/tests/auto/quick/pointerhandlers/mousearea_interop/tst_mousearea_interop.cpp
@@ -34,6 +34,7 @@
#include <QtQuick/private/qquickmousearea_p.h>
#include <QtQuick/qquickitem.h>
#include <QtQuick/qquickview.h>
+#include <QtGui/private/qpointingdevice_p.h>
#include "../../../shared/util.h"
#include "../../shared/viewtestutil.h"
@@ -76,7 +77,6 @@ void tst_MouseAreaInterop::dragHandlerInSiblingStealingGrabFromMouseAreaViaMouse
QScopedPointer<QQuickView> windowPtr;
createView(windowPtr, "dragTakeOverFromSibling.qml");
QQuickView * window = windowPtr.data();
- auto pointerEvent = QQuickWindowPrivate::get(window)->pointerEventInstance(QPointingDevice::primaryPointingDevice());
QPointer<QQuickPointerHandler> handler = window->rootObject()->findChild<QQuickPointerHandler*>();
QVERIFY(handler);
@@ -92,10 +92,12 @@ void tst_MouseAreaInterop::dragHandlerInSiblingStealingGrabFromMouseAreaViaMouse
// DragHandler keeps monitoring, due to its passive grab,
// and eventually steals the exclusive grab from MA
int dragStoleGrab = 0;
+ auto devPriv = QPointingDevicePrivate::get(QPointingDevice::primaryPointingDevice());
for (int i = 0; i < 4; ++i) {
p1 += QPoint(dragThreshold / 2, 0);
QTest::mouseMove(window, p1);
- if (!dragStoleGrab && pointerEvent->point(0)->exclusiveGrabber() == handler)
+
+ if (!dragStoleGrab && devPriv->pointById(0)->exclusiveGrabber == handler)
dragStoleGrab = i;
}
if (dragStoleGrab)
@@ -124,7 +126,7 @@ void tst_MouseAreaInterop::dragHandlerInSiblingStealingGrabFromMouseAreaViaTouch
QScopedPointer<QQuickView> windowPtr;
createView(windowPtr, "dragTakeOverFromSibling.qml");
QQuickView * window = windowPtr.data();
- auto pointerEvent = QQuickWindowPrivate::get(window)->pointerEventInstance(touchDevice);
+ auto devPriv = QPointingDevicePrivate::get(QPointingDevice::primaryPointingDevice());
QPointer<QQuickPointerHandler> handler = window->rootObject()->findChild<QQuickPointerHandler*>();
QVERIFY(handler);
@@ -137,8 +139,8 @@ void tst_MouseAreaInterop::dragHandlerInSiblingStealingGrabFromMouseAreaViaTouch
touch.press(1, p1).commit();
QQuickTouchUtils::flush(window);
- QTRY_VERIFY(pointerEvent->point(0)->passiveGrabbers().contains(handler));
- QCOMPARE(pointerEvent->point(0)->grabberItem(), ma);
+ QTRY_VERIFY(devPriv->pointById(0)->passiveGrabbers.contains(handler.data()));
+ QCOMPARE(devPriv->pointById(0)->exclusiveGrabber, ma);
QCOMPARE(window->mouseGrabberItem(), ma);
QCOMPARE(ma->pressed(), true);
@@ -150,7 +152,7 @@ void tst_MouseAreaInterop::dragHandlerInSiblingStealingGrabFromMouseAreaViaTouch
p1 += QPoint(dragThreshold / 2, 0);
touch.move(1, p1).commit();
QQuickTouchUtils::flush(window);
- if (!dragStoleGrab && pointerEvent->point(0)->exclusiveGrabber() == handler)
+ if (!dragStoleGrab && devPriv->pointById(0)->exclusiveGrabber == handler)
dragStoleGrab = i;
}
if (dragStoleGrab)
diff --git a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp
index 82e9b4e71f..9a278cd570 100644
--- a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp
+++ b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp
@@ -35,6 +35,7 @@
#include <QtQuick/private/qquickpinchhandler_p.h>
#include <QtQuick/qquickitem.h>
#include <QtQuick/qquickview.h>
+#include <QtGui/private/qpointingdevice_p.h>
#include "../../../shared/util.h"
#include "../../shared/viewtestutil.h"
@@ -108,9 +109,9 @@ void tst_MptaInterop::touchDrag()
QPoint p1 = mpta->mapToScene(QPointF(20, 20)).toPoint();
touch.press(1, p1).commit();
QQuickTouchUtils::flush(window);
- auto pointerEvent = QQuickWindowPrivate::get(window)->pointerEventInstance(touchDevice);
+ auto devPriv = QPointingDevicePrivate::get(touchDevice);
QCOMPARE(tp.at(0)->property("pressed").toBool(), true);
- QTRY_VERIFY(pointerEvent->point(0)->passiveGrabbers().contains(drag));
+ QTRY_VERIFY(devPriv->pointById(0)->passiveGrabbers.contains(drag));
// Start moving
// DragHandler keeps monitoring, due to its passive grab,
@@ -120,7 +121,7 @@ void tst_MptaInterop::touchDrag()
p1 += QPoint(dragThreshold / 2, 0);
touch.move(1, p1).commit();
QQuickTouchUtils::flush(window);
- if (!dragStoleGrab && pointerEvent->point(0)->exclusiveGrabber() == drag)
+ if (!dragStoleGrab && devPriv->pointById(0)->exclusiveGrabber == drag)
dragStoleGrab = i;
}
if (dragStoleGrab)
@@ -150,7 +151,7 @@ void tst_MptaInterop::touchesThenPinch()
QSignalSpy mptaReleasedSpy(mpta, SIGNAL(released(QList<QObject*>)));
QSignalSpy mptaCanceledSpy(mpta, SIGNAL(canceled(QList<QObject*>)));
QTest::QTouchEventSequence touch = QTest::touchEvent(window, touchDevice);
- auto pointerEvent = QQuickWindowPrivate::get(window)->pointerEventInstance(touchDevice);
+ auto devPriv = QPointingDevicePrivate::get(touchDevice);
// Press one touchpoint:
// DragHandler gets a passive grab
@@ -159,8 +160,8 @@ void tst_MptaInterop::touchesThenPinch()
QPoint p1 = mpta->mapToScene(QPointF(20, 20)).toPoint();
touch.press(1, p1).commit();
QQuickTouchUtils::flush(window);
- QTRY_COMPARE(pointerEvent->point(0)->exclusiveGrabber(), mpta);
- QTRY_COMPARE(pointerEvent->point(0)->passiveGrabbers().first(), drag);
+ QTRY_COMPARE(devPriv->pointById(0)->exclusiveGrabber, mpta);
+ QTRY_COMPARE(devPriv->pointById(0)->passiveGrabbers.first(), drag);
// Press a second touchpoint: MPTA grabs it
QPoint p2 = mpta->mapToScene(QPointF(200, 30)).toPoint();
@@ -179,9 +180,9 @@ void tst_MptaInterop::touchesThenPinch()
QCOMPARE(tp.at(2)->property("pressed").toBool(), true);
QCOMPARE(mptaPressedSpy.count(), 3);
QCOMPARE(mptaCanceledSpy.count(), 0);
- QCOMPARE(pointerEvent->point(0)->exclusiveGrabber(), mpta);
- QCOMPARE(pointerEvent->point(1)->exclusiveGrabber(), mpta);
- QCOMPARE(pointerEvent->point(2)->exclusiveGrabber(), mpta);
+ QCOMPARE(devPriv->pointById(0)->exclusiveGrabber, mpta);
+ QCOMPARE(devPriv->pointById(1)->exclusiveGrabber, mpta);
+ QCOMPARE(devPriv->pointById(2)->exclusiveGrabber, mpta);
QVERIFY(!pinch->active());
// Start moving: PinchHandler steals the exclusive grab from MPTA as soon as dragThreshold is exceeded
@@ -197,7 +198,7 @@ void tst_MptaInterop::touchesThenPinch()
p3 = xform.map(p3);
touch.move(1, p1).move(2, p2).move(3, p3).commit();
QQuickTouchUtils::flush(window);
- if (!pinchStoleGrab && pointerEvent->point(0)->exclusiveGrabber() == pinch) {
+ if (!pinchStoleGrab && devPriv->pointById(0)->exclusiveGrabber == pinch) {
pinchStoleGrab = i;
QCOMPARE(tp.at(0)->property("pressed").toBool(), false);
QCOMPARE(tp.at(1)->property("pressed").toBool(), false);
@@ -212,10 +213,10 @@ void tst_MptaInterop::touchesThenPinch()
QPoint p4 = mpta->mapToScene(QPointF(300, 200)).toPoint();
touch.move(1, p1).move(2, p2).move(3, p3).press(4, p4).commit();
// PinchHandler deactivates, which lets MPTA grab all the points
- QTRY_COMPARE(pointerEvent->point(0)->exclusiveGrabber(), mpta);
- QCOMPARE(pointerEvent->point(1)->exclusiveGrabber(), mpta);
- QCOMPARE(pointerEvent->point(2)->exclusiveGrabber(), mpta);
- QCOMPARE(pointerEvent->point(3)->exclusiveGrabber(), mpta);
+ QTRY_COMPARE(devPriv->pointById(0)->exclusiveGrabber, mpta);
+ QCOMPARE(devPriv->pointById(1)->exclusiveGrabber, mpta);
+ QCOMPARE(devPriv->pointById(2)->exclusiveGrabber, mpta);
+ QCOMPARE(devPriv->pointById(3)->exclusiveGrabber, mpta);
// Move some more... MPTA keeps reacting
for (int i = 0; i < 8; ++i) {
p1 += QPoint(4, 4);
@@ -223,10 +224,10 @@ void tst_MptaInterop::touchesThenPinch()
p3 += QPoint(-4, 4);
p4 += QPoint(-4, -4);
touch.move(1, p1).move(2, p2).move(3, p3).move(4, p4).commit();
- QCOMPARE(pointerEvent->point(0)->exclusiveGrabber(), mpta);
- QCOMPARE(pointerEvent->point(1)->exclusiveGrabber(), mpta);
- QCOMPARE(pointerEvent->point(2)->exclusiveGrabber(), mpta);
- QCOMPARE(pointerEvent->point(3)->exclusiveGrabber(), mpta);
+ QCOMPARE(devPriv->pointById(0)->exclusiveGrabber, mpta);
+ QCOMPARE(devPriv->pointById(1)->exclusiveGrabber, mpta);
+ QCOMPARE(devPriv->pointById(2)->exclusiveGrabber, mpta);
+ QCOMPARE(devPriv->pointById(3)->exclusiveGrabber, mpta);
QCOMPARE(tp.at(0)->property("pressed").toBool(), true);
QCOMPARE(tp.at(1)->property("pressed").toBool(), true);
QCOMPARE(tp.at(2)->property("pressed").toBool(), true);
@@ -241,9 +242,9 @@ void tst_MptaInterop::touchesThenPinch()
p2 += QPoint(4, 4);
p3 -= QPoint(-4, 4);
touch.move(1, p1).move(2, p2).move(3, p3).commit();
- QTRY_COMPARE(pointerEvent->point(0)->exclusiveGrabber(), pinch);
- QCOMPARE(pointerEvent->point(1)->exclusiveGrabber(), pinch);
- QCOMPARE(pointerEvent->point(2)->exclusiveGrabber(), pinch);
+ QTRY_COMPARE(devPriv->pointById(0)->exclusiveGrabber, pinch);
+ QCOMPARE(devPriv->pointById(1)->exclusiveGrabber, pinch);
+ QCOMPARE(devPriv->pointById(2)->exclusiveGrabber, pinch);
}
// Release the first finger
@@ -267,12 +268,12 @@ void tst_MptaInterop::touchesThenPinch()
p2 += QPoint(8, -8);
touch.move(2, p2).commit();
QQuickTouchUtils::flush(window);
- QVERIFY(pointerEvent->point(0)->passiveGrabbers().contains(drag));
- if (!dragTookGrab && pointerEvent->point(0)->exclusiveGrabber() == drag)
+ QVERIFY(devPriv->pointById(0)->passiveGrabbers.contains(drag));
+ if (!dragTookGrab && devPriv->pointById(0)->exclusiveGrabber == drag)
dragTookGrab = i;
}
qCDebug(lcPointerTests) << "drag started after" << dragTookGrab << "moves; ended with translation" << drag->translation();
- QCOMPARE(pointerEvent->point(0)->exclusiveGrabber(), drag);
+ QCOMPARE(devPriv->pointById(0)->exclusiveGrabber, drag);
QTRY_VERIFY(drag->translation().x() > 0);
touch.release(2, p2).commit();
@@ -304,7 +305,7 @@ void tst_MptaInterop::dragHandlerInParentStealingGrabFromItem() // QTBUG-75025
QScopedPointer<QQuickView> windowPtr;
createView(windowPtr, "dragParentOfMPTA.qml");
QQuickView * window = windowPtr.data();
- auto pointerEvent = QQuickWindowPrivate::get(window)->pointerEventInstance(QPointingDevice::primaryPointingDevice());
+ auto devPriv = QPointingDevicePrivate::get(touchDevice);
QPointer<QQuickPointerHandler> handler = window->rootObject()->findChild<QQuickPointerHandler*>();
QVERIFY(handler);
@@ -326,7 +327,7 @@ void tst_MptaInterop::dragHandlerInParentStealingGrabFromItem() // QTBUG-75025
for (int i = 0; i < 4; ++i) {
point += QPoint(dragThreshold / 2, 0);
QTest::mouseMove(window, point);
- if (!dragStoleGrab && pointerEvent->point(0)->exclusiveGrabber() == handler)
+ if (!dragStoleGrab && devPriv->pointById(0)->exclusiveGrabber == handler)
dragStoleGrab = i;
}
if (dragStoleGrab)
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp b/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp
index a5884659b3..9c9ca2fe00 100644
--- a/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp
@@ -35,6 +35,7 @@
#include <QtQuick/private/qquicktaphandler_p.h>
#include <QtQuick/qquickitem.h>
#include <QtQuick/qquickview.h>
+#include <QtGui/private/qpointingdevice_p.h>
#include "../../../shared/util.h"
#include "../../shared/viewtestutil.h"
@@ -90,15 +91,14 @@ void tst_DragHandler::createView(QScopedPointer<QQuickView> &window, const char
QSet<QQuickPointerHandler*> tst_DragHandler::passiveGrabbers(QQuickWindow *window, int pointId /*= 0*/)
{
+ Q_UNUSED(window);
QSet<QQuickPointerHandler*> result;
- QQuickWindowPrivate *winp = QQuickWindowPrivate::get(window);
- QQuickPointerEvent *pointerEvent = winp->pointerEventInstance(touchDevice);
- for (int i = 0; i < pointerEvent->pointCount(); ++i) {
- QQuickEventPoint *eventPoint = pointerEvent->point(i);
- QVector<QPointer <QQuickPointerHandler> > passives = eventPoint->passiveGrabbers();
- if (!pointId || eventPoint->pointId() == pointId) {
+ auto devPriv = QPointingDevicePrivate::get(touchDevice);
+ for (auto &epd : devPriv->activePoints.values()) {
+ auto passives = epd.passiveGrabbers;
+ if (!pointId || epd.eventPoint.id() == pointId) {
for (auto it = passives.constBegin(); it != passives.constEnd(); ++it)
- result << it->data();
+ result << qobject_cast<QQuickPointerHandler *>(it->data());
}
}
return result;
@@ -263,7 +263,7 @@ void tst_DragHandler::mouseDrag()
p1 += QPoint(dragThreshold, 0);
QTest::mouseMove(window, p1);
if (shouldDrag) {
- QTRY_VERIFY(dragHandler->centroid().velocity().x() > 0);
+// QTRY_VERIFY(dragHandler->centroid().velocity().x() > 0); // TODO QTBUG-33891
QCOMPARE(centroidChangedSpy.count(), 2);
QVERIFY(!dragHandler->active());
#if QT_CONFIG(cursor)
@@ -294,7 +294,7 @@ void tst_DragHandler::mouseDrag()
QCOMPARE(dragHandler->centroid().sceneGrabPosition(), sceneGrabPos);
QCOMPARE(dragHandler->translation().x(), dragThreshold + 20.0);
QCOMPARE(dragHandler->translation().y(), 0.0);
- QVERIFY(dragHandler->centroid().velocity().x() > 0);
+// QVERIFY(dragHandler->centroid().velocity().x() > 0); // TODO QTBUG-33891
QCOMPARE(centroidChangedSpy.count(), 4);
#if QT_CONFIG(cursor)
QCOMPARE(window->cursor().shape(), Qt::ClosedHandCursor);
diff --git a/tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp b/tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp
index 6f81e6b566..a4ff2477bb 100644
--- a/tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp
+++ b/tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp
@@ -30,6 +30,7 @@
#include <private/qdebug_p.h>
#include <QtGui/qstylehints.h>
+#include <QtGui/private/qpointingdevice_p.h>
#include <QtQuick/private/qquickpointerhandler_p.h>
#include <QtQuick/qquickitem.h>
#include <QtQuick/qquickview.h>
@@ -58,7 +59,7 @@ public:
Destination destination;
QEvent::Type type; // if this represents a QEvent that was received
QEventPoint::State state; // if this represents an event (pointer, touch or mouse)
- int grabTransition; // if this represents an onGrabChanged() notification (QQuickEventPoint::GrabTransition)
+ int grabTransition; // if this represents an onGrabChanged() notification (QPointingDevice::GrabTransition)
QPointF posWrtItem;
QPointF posWrtScene;
};
@@ -75,7 +76,7 @@ QDebug operator<<(QDebug dbg, const class Event &event) {
QtDebugUtils::formatQEnum(dbg, event.state);
if (event.grabTransition) {
dbg << ' ';
- QtDebugUtils::formatQEnum(dbg, QQuickEventPoint::GrabTransition(event.grabTransition));
+ QtDebugUtils::formatQEnum(dbg, QPointingDevice::GrabTransition(event.grabTransition));
}
dbg << " @ ";
QtDebugUtils::formatQPoint(dbg, event.posWrtItem);
@@ -99,13 +100,13 @@ public:
{}
inline int grabTransition(bool accept, QEventPoint::State state) {
- return (accept && (state != QEventPoint::State::Released)) ? (int)QQuickEventPoint::GrabExclusive : (int)NoGrab;
+ return (accept && (state != QEventPoint::State::Released)) ? (int)QPointingDevice::GrabExclusive : (int)NoGrab;
}
void touchEvent(QTouchEvent *event)
{
qCDebug(lcPointerTests) << event << "will accept?" << acceptTouch;
- for (const QEventPoint &tp : event->touchPoints())
+ for (auto &tp : event->points())
eventList.append(Event(Event::TouchDestination, event->type(), tp.state(), grabTransition(acceptTouch, tp.state()), tp.position(), tp.scenePosition()));
event->setAccepted(acceptTouch);
}
@@ -137,7 +138,7 @@ public:
void mouseUngrabEvent()
{
qCDebug(lcPointerTests);
- eventList.append(Event(Event::MouseDestination, QEvent::UngrabMouse, QEventPoint::State::Released, QQuickEventPoint::UngrabExclusive, QPoint(0,0), QPoint(0,0)));
+ eventList.append(Event(Event::MouseDestination, QEvent::UngrabMouse, QEventPoint::State::Released, QPointingDevice::UngrabExclusive, QPoint(0,0), QPoint(0,0)));
}
bool event(QEvent *event)
@@ -161,8 +162,9 @@ public:
event->type() == QEvent::TouchCancel ||
event->type() == QEvent::TouchEnd) {
QTouchEvent *touch = static_cast<QTouchEvent*>(event);
- for (const QEventPoint &tp : touch->touchPoints())
- eventList.append(Event(Event::FilterDestination, event->type(), tp.state(), QQuickEventPoint::GrabExclusive, tp.position(), tp.scenePosition()));
+ for (auto &tp : touch->points())
+ eventList.append(Event(Event::FilterDestination, event->type(), tp.state(),
+ QPointingDevice::GrabExclusive, tp.position(), tp.scenePosition()));
if (filterTouch)
event->accept();
return true;
@@ -183,42 +185,43 @@ public:
class EventHandler : public QQuickPointerHandler
{
public:
- void handlePointerEventImpl(QQuickPointerEvent *event) override
+ void handlePointerEventImpl(QPointerEvent *event) override
{
QQuickPointerHandler::handlePointerEventImpl(event);
if (!enabled())
return;
- if (event->isPressEvent())
+ if (event->isBeginEvent())
++pressEventCount;
- if (event->isReleaseEvent())
+ if (event->isEndEvent())
++releaseEventCount;
EventItem *item = qmlobject_cast<EventItem *>(target());
if (!item) {
- event->point(0)->setGrabberPointerHandler(this);
+ event->setExclusiveGrabber(event->point(0), this);
return;
}
qCDebug(lcPointerTests) << item->objectName() << event;
- int c = event->pointCount();
- for (int i = 0; i < c; ++i) {
- QQuickEventPoint *point = event->point(i);
+ for (auto point : event->points()) {
if (item->acceptPointer)
- point->setAccepted(item->acceptPointer); // does NOT imply a grab
+ point.setAccepted(item->acceptPointer); // does NOT imply a grab
if (item->grabPointer)
- setExclusiveGrab(point, true);
- qCDebug(lcPointerTests) << " " << i << ":" << point << "accepted?" << item->acceptPointer << "grabbed?" << (point->exclusiveGrabber() == this);
+ setExclusiveGrab(event, point, true);
+ qCDebug(lcPointerTests) << " " << point << "accepted?" << item->acceptPointer
+ << "grabbed?" << (event->exclusiveGrabber(point) == this);
item->eventList.append(Event(Event::HandlerDestination, QEvent::Pointer,
- static_cast<QEventPoint::State>(point->state()),
- item->grabPointer ? (int)QQuickEventPoint::GrabExclusive : (int)NoGrab,
- eventPos(point), point->scenePosition()));
+ static_cast<QEventPoint::State>(point.state()),
+ item->grabPointer ? (int)QPointingDevice::GrabExclusive : (int)NoGrab,
+ eventPos(point), point.scenePosition()));
}
}
- void onGrabChanged(QQuickPointerHandler *, QQuickEventPoint::GrabTransition stateChange, QQuickEventPoint *point) override
+ void onGrabChanged(QQuickPointerHandler *, QPointingDevice::GrabTransition stateChange,
+ QPointerEvent *ev, QEventPoint &point) override
{
+ Q_UNUSED(ev);
EventItem *item = qmlobject_cast<EventItem *>(target());
if (item)
item->eventList.append(Event(Event::HandlerDestination, QEvent::None,
- static_cast<QEventPoint::State>(point->state()), stateChange, eventPos(point), point->scenePosition()));
+ static_cast<QEventPoint::State>(point.state()), stateChange, eventPos(point), point.scenePosition()));
}
int pressEventCount = 0;
@@ -342,15 +345,15 @@ void tst_PointerHandlers::touchEventDelivery()
QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 2);
QCOMPARE_EVENT(0, Event::HandlerDestination, QEvent::Pointer, QEventPoint::State::Pressed, NoGrab);
- QCOMPARE_EVENT(1, Event::TouchDestination, QEvent::TouchBegin, QEventPoint::State::Pressed, QQuickEventPoint::GrabExclusive);
- auto pointerEvent = QQuickWindowPrivate::get(window)->pointerEventInstance(touchDevice);
- QCOMPARE(pointerEvent->point(0)->exclusiveGrabber(), eventItem1);
+ QCOMPARE_EVENT(1, Event::TouchDestination, QEvent::TouchBegin, QEventPoint::State::Pressed, QPointingDevice::GrabExclusive);
+ auto devPriv = QPointingDevicePrivate::get(touchDevice);
+ QCOMPARE(devPriv->pointById(0)->exclusiveGrabber, eventItem1);
p1 += QPoint(10, 0);
QTest::touchEvent(window, touchDevice).move(0, p1, window);
QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 4);
QCOMPARE_EVENT(2, Event::HandlerDestination, QEvent::Pointer, QEventPoint::State::Updated, NoGrab);
- QCOMPARE_EVENT(3, Event::TouchDestination, QEvent::TouchUpdate, QEventPoint::State::Updated, QQuickEventPoint::GrabExclusive);
+ QCOMPARE_EVENT(3, Event::TouchDestination, QEvent::TouchUpdate, QEventPoint::State::Updated, QPointingDevice::GrabExclusive);
QTest::touchEvent(window, touchDevice).release(0, p1, window);
QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 6);
@@ -372,7 +375,7 @@ void tst_PointerHandlers::touchEventDelivery()
QCOMPARE_EVENT(0, Event::HandlerDestination, QEvent::Pointer, QEventPoint::State::Pressed, NoGrab);
QCOMPARE_EVENT(1, Event::TouchDestination, QEvent::TouchBegin, QEventPoint::State::Pressed, NoGrab);
if (synthMouse)
- QCOMPARE_EVENT(2, Event::MouseDestination, QEvent::MouseButtonPress, QEventPoint::State::Pressed, QQuickEventPoint::GrabExclusive);
+ QCOMPARE_EVENT(2, Event::MouseDestination, QEvent::MouseButtonPress, QEventPoint::State::Pressed, QPointingDevice::GrabExclusive);
QCOMPARE(window->mouseGrabberItem(), synthMouse ? eventItem1 : nullptr);
QPointF localPos = eventItem1->mapFromScene(p1);
@@ -391,7 +394,7 @@ void tst_PointerHandlers::touchEventDelivery()
if (synthMouse) {
QCOMPARE_EVENT(3, Event::HandlerDestination, QEvent::Pointer, QEventPoint::State::Updated, NoGrab);
QCOMPARE_EVENT(4, Event::TouchDestination, QEvent::TouchUpdate, QEventPoint::State::Updated, NoGrab);
- QCOMPARE_EVENT(5, Event::MouseDestination, QEvent::MouseMove, QEventPoint::State::Updated, QQuickEventPoint::GrabExclusive);
+ QCOMPARE_EVENT(5, Event::MouseDestination, QEvent::MouseMove, QEventPoint::State::Updated, QPointingDevice::GrabExclusive);
}
QTest::touchEvent(window, touchDevice).release(0, p1, window);
QQuickTouchUtils::flush(window);
@@ -400,7 +403,7 @@ void tst_PointerHandlers::touchEventDelivery()
QCOMPARE_EVENT(6, Event::HandlerDestination, QEvent::Pointer, QEventPoint::State::Released, NoGrab);
QCOMPARE_EVENT(7, Event::TouchDestination, QEvent::TouchEnd, QEventPoint::State::Released, NoGrab);
QCOMPARE_EVENT(8, Event::MouseDestination, QEvent::MouseButtonRelease, QEventPoint::State::Released, NoGrab);
- QCOMPARE_EVENT(9, Event::MouseDestination, QEvent::UngrabMouse, QEventPoint::State::Released, QQuickEventPoint::UngrabExclusive);
+ QCOMPARE_EVENT(9, Event::MouseDestination, QEvent::UngrabMouse, QEventPoint::State::Released, QPointingDevice::UngrabExclusive);
} else {
QCOMPARE_EVENT(3, Event::HandlerDestination, QEvent::Pointer, QEventPoint::State::Released, NoGrab);
}
@@ -421,7 +424,7 @@ void tst_PointerHandlers::touchEventDelivery()
QCOMPARE_EVENT(1, Event::TouchDestination, QEvent::TouchBegin, QEventPoint::State::Pressed, NoGrab);
if (synthMouse)
QCOMPARE_EVENT(2, Event::MouseDestination, QEvent::MouseButtonPress, QEventPoint::State::Pressed, NoGrab);
- QCOMPARE(pointerEvent->point(0)->exclusiveGrabber(), nullptr);
+ QCOMPARE(devPriv->pointById(0)->exclusiveGrabber, nullptr);
p1 += QPoint(10, 0);
QTest::touchEvent(window, touchDevice).move(0, p1, window);
QQuickTouchUtils::flush(window);
@@ -442,13 +445,13 @@ void tst_PointerHandlers::touchEventDelivery()
QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 2);
QCOMPARE_EVENT(0, Event::HandlerDestination, QEvent::Pointer, QEventPoint::State::Pressed, NoGrab);
- QCOMPARE_EVENT(1, Event::TouchDestination, QEvent::TouchBegin, QEventPoint::State::Pressed, QQuickEventPoint::GrabExclusive);
+ QCOMPARE_EVENT(1, Event::TouchDestination, QEvent::TouchBegin, QEventPoint::State::Pressed, QPointingDevice::GrabExclusive);
p1 += QPoint(10, 0);
QTest::touchEvent(window, touchDevice).move(0, p1, window);
QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 4);
QCOMPARE_EVENT(2, Event::HandlerDestination, QEvent::Pointer, QEventPoint::State::Updated, NoGrab);
- QCOMPARE_EVENT(3, Event::TouchDestination, QEvent::TouchUpdate, QEventPoint::State::Updated, QQuickEventPoint::GrabExclusive);
+ QCOMPARE_EVENT(3, Event::TouchDestination, QEvent::TouchUpdate, QEventPoint::State::Updated, QPointingDevice::GrabExclusive);
QTest::touchEvent(window, touchDevice).release(0, p1, window);
QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 6);
@@ -463,19 +466,19 @@ void tst_PointerHandlers::touchEventDelivery()
QTest::touchEvent(window, touchDevice).press(0, p1, window);
QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 2);
- QCOMPARE_EVENT(0, Event::HandlerDestination, QEvent::None, QEventPoint::State::Pressed, QQuickEventPoint::GrabExclusive);
- QCOMPARE_EVENT(1, Event::HandlerDestination, QEvent::Pointer, QEventPoint::State::Pressed, QQuickEventPoint::GrabExclusive);
+ QCOMPARE_EVENT(0, Event::HandlerDestination, QEvent::None, QEventPoint::State::Pressed, QPointingDevice::GrabExclusive);
+ QCOMPARE_EVENT(1, Event::HandlerDestination, QEvent::Pointer, QEventPoint::State::Pressed, QPointingDevice::GrabExclusive);
p1 += QPoint(10, 0);
QTest::touchEvent(window, touchDevice).move(0, p1, window);
QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 3);
- QCOMPARE_EVENT(2, Event::HandlerDestination, QEvent::Pointer, QEventPoint::State::Updated, QQuickEventPoint::GrabExclusive);
+ QCOMPARE_EVENT(2, Event::HandlerDestination, QEvent::Pointer, QEventPoint::State::Updated, QPointingDevice::GrabExclusive);
QTest::touchEvent(window, touchDevice).release(0, p1, window);
QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 5);
qCDebug(lcPointerTests) << eventItem1->eventList;
- QCOMPARE_EVENT(3, Event::HandlerDestination, QEvent::Pointer, QEventPoint::State::Released, QQuickEventPoint::GrabExclusive);
- QCOMPARE_EVENT(4, Event::HandlerDestination, QEvent::None, QEventPoint::State::Released, QQuickEventPoint::UngrabExclusive);
+ QCOMPARE_EVENT(3, Event::HandlerDestination, QEvent::Pointer, QEventPoint::State::Released, QPointingDevice::GrabExclusive);
+ QCOMPARE_EVENT(4, Event::HandlerDestination, QEvent::None, QEventPoint::State::Released, QPointingDevice::UngrabExclusive);
eventItem1->eventList.clear();
}
@@ -510,7 +513,7 @@ void tst_PointerHandlers::mouseEventDelivery()
QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
QCOMPARE(eventItem1->eventList.size(), 2);
QCOMPARE_EVENT(0, Event::HandlerDestination, QEvent::Pointer, QEventPoint::State::Pressed, NoGrab);
- QCOMPARE_EVENT(1, Event::MouseDestination, QEvent::MouseButtonPress, QEventPoint::State::Pressed, QQuickEventPoint::GrabExclusive);
+ QCOMPARE_EVENT(1, Event::MouseDestination, QEvent::MouseButtonPress, QEventPoint::State::Pressed, QPointingDevice::GrabExclusive);
QCOMPARE(window->mouseGrabberItem(), eventItem1);
QPointF localPos = eventItem1->mapFromScene(p1);
@@ -523,11 +526,11 @@ void tst_PointerHandlers::mouseEventDelivery()
p1 += QPoint(10, 0);
QTest::mouseMove(window, p1);
QCOMPARE(eventItem1->eventList.size(), 3);
- QCOMPARE_EVENT(2, Event::MouseDestination, QEvent::MouseMove, QEventPoint::State::Updated, QQuickEventPoint::GrabExclusive);
+ QCOMPARE_EVENT(2, Event::MouseDestination, QEvent::MouseMove, QEventPoint::State::Updated, QPointingDevice::GrabExclusive);
QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
QCOMPARE(eventItem1->eventList.size(), 5);
QCOMPARE_EVENT(3, Event::MouseDestination, QEvent::MouseButtonRelease, QEventPoint::State::Released, NoGrab);
- QCOMPARE_EVENT(4, Event::MouseDestination, QEvent::UngrabMouse, QEventPoint::State::Released, QQuickEventPoint::UngrabExclusive);
+ QCOMPARE_EVENT(4, Event::MouseDestination, QEvent::UngrabMouse, QEventPoint::State::Released, QPointingDevice::UngrabExclusive);
eventItem1->eventList.clear();
// wait to avoid getting a double click event
@@ -540,17 +543,17 @@ void tst_PointerHandlers::mouseEventDelivery()
p1 = QPoint(20, 20);
QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
QTRY_COMPARE(eventItem1->eventList.size(), 3);
- QCOMPARE_EVENT(0, Event::HandlerDestination, QEvent::None, QEventPoint::State::Pressed, QQuickEventPoint::GrabExclusive);
- QCOMPARE_EVENT(1, Event::HandlerDestination, QEvent::Pointer, QEventPoint::State::Pressed, QQuickEventPoint::GrabExclusive);
+ QCOMPARE_EVENT(0, Event::HandlerDestination, QEvent::None, QEventPoint::State::Pressed, QPointingDevice::GrabExclusive);
+ QCOMPARE_EVENT(1, Event::HandlerDestination, QEvent::Pointer, QEventPoint::State::Pressed, QPointingDevice::GrabExclusive);
QCOMPARE_EVENT(2, Event::MouseDestination, QEvent::MouseButtonPress, QEventPoint::State::Pressed, 0);
p1 += QPoint(10, 0);
QTest::mouseMove(window, p1);
QCOMPARE(eventItem1->eventList.size(), 4);
- QCOMPARE_EVENT(3, Event::HandlerDestination, QEvent::Pointer, QEventPoint::State::Updated, QQuickEventPoint::GrabExclusive);
+ QCOMPARE_EVENT(3, Event::HandlerDestination, QEvent::Pointer, QEventPoint::State::Updated, QPointingDevice::GrabExclusive);
QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
QCOMPARE(eventItem1->eventList.size(), 6);
- QCOMPARE_EVENT(4, Event::HandlerDestination, QEvent::Pointer, QEventPoint::State::Released, QQuickEventPoint::GrabExclusive);
- QCOMPARE_EVENT(5, Event::HandlerDestination, QEvent::None, QEventPoint::State::Released, QQuickEventPoint::UngrabExclusive);
+ QCOMPARE_EVENT(4, Event::HandlerDestination, QEvent::Pointer, QEventPoint::State::Released, QPointingDevice::GrabExclusive);
+ QCOMPARE_EVENT(5, Event::HandlerDestination, QEvent::None, QEventPoint::State::Released, QPointingDevice::UngrabExclusive);
eventItem1->eventList.clear();
}
@@ -568,11 +571,11 @@ void tst_PointerHandlers::touchReleaseOutside_data()
QTest::newRow("reject and ignore") << false << false << 6 << 5 << (int)Event::TouchDestination
<< (int)QEvent::TouchEnd << (int)QEventPoint::State::Released << (int)NoGrab;
QTest::newRow("reject and grab") << false << true << 5 << 4 << (int)Event::HandlerDestination
- << (int)QEvent::None << (int)QEventPoint::State::Released << (int)QQuickEventPoint::UngrabExclusive;
+ << (int)QEvent::None << (int)QEventPoint::State::Released << (int)QPointingDevice::UngrabExclusive;
QTest::newRow("accept and ignore") << true << false << 1 << 0 << (int)Event::HandlerDestination
<< (int)QEvent::Pointer << (int)QEventPoint::State::Pressed << (int)NoGrab;
QTest::newRow("accept and grab") << true << true << 5 << 4 << (int)Event::HandlerDestination
- << (int)QEvent::None << (int)QEventPoint::State::Released << (int)QQuickEventPoint::UngrabExclusive;
+ << (int)QEvent::None << (int)QEventPoint::State::Released << (int)QPointingDevice::UngrabExclusive;
}
void tst_PointerHandlers::touchReleaseOutside()
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp b/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp
index 89de571abd..43b1affc09 100644
--- a/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp
@@ -685,8 +685,8 @@ void tst_TapHandler::componentUserBehavioralOverride()
QQuickTapHandler *userTapHandler = button->findChild<QQuickTapHandler*>("override");
QVERIFY(userTapHandler);
QSignalSpy tappedSpy(button, SIGNAL(tapped()));
- QSignalSpy innerGrabChangedSpy(innerTapHandler, SIGNAL(grabChanged(QQuickEventPoint::GrabTransition, QQuickEventPoint *)));
- QSignalSpy userGrabChangedSpy(userTapHandler, SIGNAL(grabChanged(QQuickEventPoint::GrabTransition, QQuickEventPoint *)));
+ QSignalSpy innerGrabChangedSpy(innerTapHandler, SIGNAL(grabChanged(QPointingDevice::GrabTransition, QEventPoint *)));
+ QSignalSpy userGrabChangedSpy(userTapHandler, SIGNAL(grabChanged(QPointingDevice::GrabTransition, QEventPoint *)));
QSignalSpy innerPressedChangedSpy(innerTapHandler, SIGNAL(pressedChanged()));
QSignalSpy userPressedChangedSpy(userTapHandler, SIGNAL(pressedChanged()));
@@ -715,7 +715,7 @@ void tst_TapHandler::rightLongPressIgnoreWheel()
QQuickTapHandler *tap = window->rootObject()->findChild<QQuickTapHandler*>();
QVERIFY(tap);
- QSignalSpy tappedSpy(tap, SIGNAL(tapped(QQuickEventPoint *)));
+ QSignalSpy tappedSpy(tap, SIGNAL(tapped(QEventPoint *)));
QSignalSpy longPressedSpy(tap, SIGNAL(longPressed()));
QPoint p1(100, 100);
diff --git a/tests/auto/quick/qquickflickable/data/nestedPressDelay.qml b/tests/auto/quick/qquickflickable/data/nestedPressDelay.qml
index bdb866ce65..3cc0987141 100644
--- a/tests/auto/quick/qquickflickable/data/nestedPressDelay.qml
+++ b/tests/auto/quick/qquickflickable/data/nestedPressDelay.qml
@@ -1,6 +1,7 @@
import QtQuick 2.0
Flickable {
+ objectName: "outerFlickable"
property bool pressed: ma.pressed
width: 240
height: 320
diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
index f6a6ab17b4..0a75690904 100644
--- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
+++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
@@ -65,11 +65,7 @@ public:
, ungrabs(0)
, m_active(false)
{
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
setAcceptTouchEvents(true);
-#else
- setAcceptedMouseButtons(Qt::LeftButton); // not really, but we want touch events
-#endif
}
QPointF pos() const { return m_pos; }
@@ -97,8 +93,8 @@ public:
protected:
void touchEvent(QTouchEvent *ev) override
{
- QCOMPARE(ev->touchPoints().count(), 1);
- auto touchpoint = ev->touchPoints().first();
+ QCOMPARE(ev->points().count(), 1);
+ auto touchpoint = ev->points().first();
switch (touchpoint.state()) {
case QEventPoint::State::Pressed:
QVERIFY(!m_active);
@@ -115,6 +111,7 @@ protected:
++touchReleases;
emit activeChanged();
case QEventPoint::State::Stationary:
+ case QEventPoint::State::Unknown:
break;
}
touchPointStates << touchpoint.state();
@@ -1566,6 +1563,8 @@ void tst_qquickflickable::cancelOnHide()
void tst_qquickflickable::cancelOnMouseGrab()
{
+ QSKIP("need a realistic test scenario: can no longer grab mouse between events");
+
QScopedPointer<QQuickView> window(new QQuickView);
window->setSource(testFileUrl("cancel.qml"));
QTRY_COMPARE(window->status(), QQuickView::Ready);
diff --git a/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp b/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
index 47f7943d12..1cb5591519 100644
--- a/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
+++ b/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
@@ -36,6 +36,7 @@
#include <QtQuick/qquickview.h>
#include <QtGui/QScreen>
#include <QtGui/private/qevent_p.h>
+#include <QtGui/private/qpointingdevice_p.h>
#include "../../shared/util.h"
#include "../shared/viewtestutil.h"
@@ -814,7 +815,6 @@ void tst_QQuickMultiPointTouchArea::inFlickableWithPressDelay() // QTBUG-78818
const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
QScopedPointer<QQuickView> window(createAndShowView("inFlickable.qml"));
QVERIFY(window->rootObject() != nullptr);
- QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window.data());
QQuickFlickable *flickable = qobject_cast<QQuickFlickable *>(window->rootObject());
QVERIFY(flickable != nullptr);
@@ -831,8 +831,8 @@ void tst_QQuickMultiPointTouchArea::inFlickableWithPressDelay() // QTBUG-78818
QTest::touchEvent(window.data(), device).press(0, p1);
QQuickTouchUtils::flush(window.data());
QTRY_COMPARE(point11->pressed(), true);
- auto pointerEvent = windowPriv->pointerEventInstance(device);
- QCOMPARE(pointerEvent->point(0)->exclusiveGrabber(), mpta);
+ auto devPriv = QPointingDevicePrivate::get(device);
+ QCOMPARE(devPriv->pointById(0)->exclusiveGrabber, mpta);
// release: MPTA receives TouchEnd (which is asymmetric with mouse press); does NOT emit canceled.
QTest::touchEvent(window.data(), device).release(0, p1);
@@ -843,18 +843,18 @@ void tst_QQuickMultiPointTouchArea::inFlickableWithPressDelay() // QTBUG-78818
QTest::touchEvent(window.data(), device).press(0, p1);
QQuickTouchUtils::flush(window.data());
QTRY_COMPARE(point11->pressed(), true); // wait until pressDelay exceeded
- QCOMPARE(pointerEvent->point(0)->exclusiveGrabber(), mpta);
+ QCOMPARE(devPriv->pointById(0)->exclusiveGrabber, mpta);
// drag past the threshold: Flickable takes over the grab, MPTA gets touchUngrab and is no longer pressed
int i = 0;
- for (; i < 10 && window->mouseGrabberItem() != flickable; ++i) {
+ for (; i < 10 && devPriv->firstPointExclusiveGrabber() != flickable; ++i) {
p1 += QPoint(0,dragThreshold);
QTest::touchEvent(window.data(), device).move(0, p1);
QQuickTouchUtils::flush(window.data());
}
- QCOMPARE(window->mouseGrabberItem(), flickable);
+ QCOMPARE(devPriv->firstPointExclusiveGrabber(), flickable);
qCDebug(lcTests, "Flickable stole grab from MPTA after %d moves", i);
- QCOMPARE(pointerEvent->point(0)->exclusiveGrabber(), flickable);
+ QCOMPARE(devPriv->pointById(0)->exclusiveGrabber, flickable);
QCOMPARE(point11->pressed(), false);
QVERIFY(flickable->property("cancelCount").toInt() > 0); // actually 2 because 2 touchPoints are declared... but only one was really cancelled
diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
index cfccfe88ba..dd95ab1808 100644
--- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
+++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
@@ -85,12 +85,23 @@ static TouchEventData makeTouchData(QEvent::Type type, QWindow *w, QEventPoint::
const QList<QEventPoint>& touchPoints = QList<QEventPoint>())
{
TouchEventData d = { type, nullptr, w, states, touchPoints };
+ for (auto &pt : d.touchPoints)
+ QMutableEventPoint::from(pt).detach();
+ return d;
+}
+static TouchEventData makeTouchData(QEvent::Type type, QWindow *w, QEventPoint::States states,
+ const QList<QEventPoint*>& touchPoints)
+{
+ QList <QEventPoint> pts;
+ for (auto pt : touchPoints)
+ pts << *pt;
+ TouchEventData d = { type, nullptr, w, states, pts };
return d;
}
static TouchEventData makeTouchData(QEvent::Type type, QWindow *w, QEventPoint::States states, const QEventPoint &touchPoint)
{
- QList<QEventPoint> points;
- points << touchPoint;
+ QList<QEventPoint*> points;
+ points << const_cast<QEventPoint *>(&touchPoint);
return makeTouchData(type, w, states, points);
}
@@ -157,6 +168,7 @@ public:
{
border()->setWidth(1);
setAcceptedMouseButtons(Qt::LeftButton);
+ setAcceptTouchEvents(true);
setFiltersChildMouseEvents(true);
}
@@ -165,7 +177,7 @@ public:
setEnabled(true);
setVisible(true);
- lastEvent = makeTouchData(QEvent::None, window(), {}, QList<QEventPoint>());//CHECK_VALID
+ lastEvent = makeTouchData(QEvent::None, window());//CHECK_VALID
lastVelocity = lastVelocityFromMouseMove = QVector2D();
lastMousePos = QPointF();
@@ -204,10 +216,11 @@ public:
event->ignore();
return;
}
+ qCDebug(lcTests) << objectName() << event;
++touchEventCount;
- lastEvent = makeTouchData(event->type(), nullptr, event->touchPointStates(), event->touchPoints());
- if (event->device()->capabilities().testFlag(QPointingDevice::Capability::Velocity) && !event->touchPoints().isEmpty()) {
- lastVelocity = event->touchPoints().first().velocity();
+ lastEvent = makeTouchData(event->type(), nullptr, event->touchPointStates(), event->points());
+ if (event->device()->capabilities().testFlag(QPointingDevice::Capability::Velocity) && !event->points().isEmpty()) {
+ lastVelocity = event->points().first().velocity();
} else {
lastVelocity = QVector2D();
}
@@ -232,7 +245,7 @@ public:
return;
}
mouseMoveCount = ++mouseMoveNum;
- lastVelocityFromMouseMove = e->point(0).velocity();
+ lastVelocityFromMouseMove = e->points().first().velocity();
lastMouseCapabilityFlags = e->device()->capabilities();
lastMousePos = e->position().toPoint();
}
@@ -248,6 +261,7 @@ public:
}
void mouseUngrabEvent() {
+ qCDebug(lcTests) << objectName();
++mouseUngrabEventCount;
}
@@ -340,6 +354,7 @@ public:
{
setSize(QSizeF(300, 300));
setAcceptedMouseButtons(Qt::LeftButton);
+ setAcceptTouchEvents(true);
}
protected:
@@ -477,8 +492,6 @@ private slots:
void testHoverTimestamp();
void test_circleMapItem();
- void pointerEventTypeAndPointCount();
-
void grabContentItemToImage();
void testDragEventPropertyPropagation();
@@ -727,8 +740,11 @@ void tst_qquickwindow::touchEvent_basic()
QCOMPARE(topItem->lastEvent.touchPoints.count(), 1);
QVERIFY(middleItem->lastEvent.touchPoints.isEmpty());
QCOMPARE(bottomItem->lastEvent.touchPoints.count(), 1);
+ // Since qtbase 2692237bb1b0c0f50b7cc5d920eb8ab065063d47, if the point didn't have a different position on release,
+ // then lastPosition is not changed. So in this case, it still holds the press position. I.e. on release,
+ // it's the last position that was actually different.
COMPARE_TOUCH_DATA(topItem->lastEvent, makeTouchData(QEvent::TouchEnd, window, QEventPoint::State::Released,
- makeTouchPoint(topItem, topItem->mapFromItem(bottomItem, pos))));
+ makeTouchPoint(topItem, topItem->mapFromItem(bottomItem, pos), pos)));
COMPARE_TOUCH_DATA(bottomItem->lastEvent, makeTouchData(QEvent::TouchBegin, window, QEventPoint::State::Pressed, makeTouchPoint(bottomItem, pos)));
topItem->reset();
bottomItem->reset();
@@ -910,7 +926,7 @@ void tst_qquickwindow::touchEvent_cancel()
QWindowSystemInterface::handleTouchCancelEvent(nullptr, touchDevice);
QCoreApplication::processEvents();
- d = makeTouchData(QEvent::TouchCancel, window);
+ d = makeTouchData(QEvent::TouchCancel, window, QEventPoint::State::Pressed, makeTouchPoint(item, pos));
COMPARE_TOUCH_DATA(item->lastEvent, d);
delete item;
@@ -1031,18 +1047,18 @@ void tst_qquickwindow::touchEvent_velocity()
QCOMPARE(item->lastEvent.touchPoints.count(), 1);
QCOMPARE(item->lastVelocity, velocity);
- // Now have a transformation on the item and check if velocity and position are transformed accordingly.
+ // Now have a transformation on the item and check if position is transformed accordingly.
+ // (In Qt 6, transforming the velocity is an exercise left to the user. This saves work
+ // during delivery. If we want it to be transformed, we should add QEventPoint::sceneVelocity
+ // so that we can keep transforming it repeatedly during Item-localization.)
item->setRotation(90); // clockwise
- QMatrix4x4 transformMatrix;
- transformMatrix.rotate(-90, 0, 0, 1); // counterclockwise
- QVector2D transformedVelocity = transformMatrix.mapVector(velocity).toVector2D();
points[0].setPosition(points[0].position() + QPointF(5, 5));
points[0].setGlobalPosition(points[0].globalPosition() + QPointF(5, 5));
QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity,
QWindowSystemInterfacePrivate::toNativeTouchPoints(points, window));
QGuiApplication::processEvents();
QQuickTouchUtils::flush(window);
- QCOMPARE(item->lastVelocity, transformedVelocity);
+ QCOMPARE(item->lastVelocity, velocity);
QPoint itemLocalPos = item->mapFromScene(points[0].position()).toPoint();
QPoint itemLocalPosFromEvent = item->lastEvent.touchPoints[0].position().toPoint();
QCOMPARE(itemLocalPos, itemLocalPosFromEvent);
@@ -1183,9 +1199,6 @@ void tst_qquickwindow::mouseFromTouch_basic()
// Now the same with a transformation.
item->setRotation(90); // clockwise
- QMatrix4x4 transformMatrix;
- transformMatrix.rotate(-90, 0, 0, 1); // counterclockwise
- QVector2D transformedVelocity = transformMatrix.mapVector(velocity).toVector2D();
points[0].setState(QEventPoint::State::Pressed);
points[0].setVelocity(velocity);
tp.setPosition(localPos);
@@ -1202,8 +1215,7 @@ void tst_qquickwindow::mouseFromTouch_basic()
QGuiApplication::processEvents();
QQuickTouchUtils::flush(window);
QCOMPARE(item->lastMousePos.toPoint(), item->mapFromScene(points[0].position()).toPoint());
- QEXPECT_FAIL(0, "fails after pointer event refactoring in qtbase", Abort);
- QCOMPARE(item->lastVelocityFromMouseMove, transformedVelocity);
+ QCOMPARE(item->lastVelocityFromMouseMove, velocity); // Velocity is always in scene coords
points[0].setState(QEventPoint::State::Released);
QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity,
@@ -1242,8 +1254,11 @@ void tst_qquickwindow::synthMouseFromTouch()
QPoint p1 = QPoint(20, 20);
QPoint p2 = QPoint(30, 30);
QTest::touchEvent(window.data(), touchDevice).press(0, p1, window.data());
+ QQuickTouchUtils::flush(window.data());
QTest::touchEvent(window.data(), touchDevice).move(0, p2, window.data());
+ QQuickTouchUtils::flush(window.data());
QTest::touchEvent(window.data(), touchDevice).release(0, p2, window.data());
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(item->m_touchEvents.count(), !synthMouse && !acceptTouch ? 1 : 3);
QCOMPARE(item->m_mouseEvents.count(), (acceptTouch || !synthMouse) ? 0 : 3);
@@ -1295,7 +1310,8 @@ void tst_qquickwindow::synthMouseDoubleClickFromTouch()
const int eventCount = item->m_mouseEvents.count();
QVERIFY(eventCount >= 2);
- const int nDoubleClicks = std::count_if(item->m_mouseEvents.constBegin(), item->m_mouseEvents.constEnd(), [](const QMouseEvent &ev) { return (ev.type() == QEvent::MouseButtonDblClick); } );
+ const int nDoubleClicks = std::count_if(item->m_mouseEvents.constBegin(), item->m_mouseEvents.constEnd(),
+ [](const QMouseEvent &ev) { return (ev.type() == QEvent::MouseButtonDblClick); } );
const bool foundDoubleClick = (nDoubleClicks == 1);
QCOMPARE(foundDoubleClick, expectedSynthesizedDoubleClickEvent);
@@ -2834,58 +2850,6 @@ void tst_qquickwindow::test_circleMapItem()
QCOMPARE(topSpy.count(), 1);
}
-void tst_qquickwindow::pointerEventTypeAndPointCount()
-{
- QPointF localPosition(33, 66);
- QPointF scenePosition(133, 166);
- QPointF screenPosition(333, 366);
- QMouseEvent me(QEvent::MouseButtonPress, localPosition, scenePosition, screenPosition,
- Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
- QMutableTouchEvent te(QEvent::TouchBegin, touchDevice, Qt::NoModifier,
- QList<QEventPoint>() << QEventPoint(1));
-
-
- QQuickPointerMouseEvent pme(nullptr, QPointingDevice::primaryPointingDevice());
- pme.reset(&me);
- QCOMPARE(pme.asMouseEvent(localPosition), &me);
- QVERIFY(pme.asPointerMouseEvent());
- QVERIFY(!pme.asPointerTouchEvent());
- QVERIFY(!pme.asPointerTabletEvent());
-// QVERIFY(!pe->asTabletEvent()); // TODO
- QCOMPARE(pme.pointCount(), 1);
- QCOMPARE(pme.point(0)->scenePosition(), scenePosition);
- QCOMPARE(pme.asMouseEvent(localPosition)->position(), localPosition);
- QCOMPARE(pme.asMouseEvent(localPosition)->globalPosition(), screenPosition);
-
- QQuickPointerTouchEvent pte(nullptr, touchDevice);
- pte.reset(&te);
- QCOMPARE(pte.asTouchEvent(), &te);
- QVERIFY(!pte.asPointerMouseEvent());
- QVERIFY(pte.asPointerTouchEvent());
- QVERIFY(!pte.asPointerTabletEvent());
- QVERIFY(pte.asTouchEvent());
-// QVERIFY(!pte.asTabletEvent()); // TODO
- QCOMPARE(pte.pointCount(), 1);
- QCOMPARE(pte.touchPointById(1)->id(), 1);
- QVERIFY(!pte.touchPointById(0));
-
- te = QMutableTouchEvent(QEvent::TouchBegin, touchDevice, Qt::NoModifier,
- QList<QEventPoint>() << QEventPoint(1) << QEventPoint(2));
- pte.reset(&te);
- QCOMPARE(pte.pointCount(), 2);
- QCOMPARE(pte.touchPointById(1)->id(), 1);
- QCOMPARE(pte.touchPointById(2)->id(), 2);
- QVERIFY(!pte.touchPointById(0));
-
- te = QMutableTouchEvent(QEvent::TouchBegin, touchDevice, Qt::NoModifier,
- QList<QEventPoint>() << QEventPoint(2));
- pte.reset(&te);
- QCOMPARE(pte.pointCount(), 1);
- QCOMPARE(pte.touchPointById(2)->id(), 2);
- QVERIFY(!pte.touchPointById(1));
- QVERIFY(!pte.touchPointById(0));
-}
-
void tst_qquickwindow::grabContentItemToImage()
{
QQmlEngine engine;
diff --git a/tests/auto/quick/touchmouse/tst_touchmouse.cpp b/tests/auto/quick/touchmouse/tst_touchmouse.cpp
index 1c53a3abe2..2deaf31079 100644
--- a/tests/auto/quick/touchmouse/tst_touchmouse.cpp
+++ b/tests/auto/quick/touchmouse/tst_touchmouse.cpp
@@ -32,6 +32,7 @@
#include <QtGui/qstylehints.h>
#include <private/qdebug_p.h>
+#include <QtGui/private/qpointingdevice_p.h>
#include <QtQuick/qquickview.h>
#include <QtQuick/qquickitem.h>
@@ -56,9 +57,12 @@ struct Event
:type(t), mousePos(mouse), mousePosGlobal(global)
{}
- Event(QEvent::Type t, QList<QEventPoint> touch)
- :type(t), points(touch)
- {}
+ Event(QEvent::Type t, const QList<QEventPoint> &touch)
+ :type(t)
+ {
+ for (auto &tp : touch)
+ points << tp;
+ }
QEvent::Type type;
QPoint mousePos;
@@ -93,48 +97,57 @@ public:
: QQuickItem(parent)
{
setAcceptedMouseButtons(Qt::LeftButton);
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
setAcceptTouchEvents(true);
-#endif
}
void touchEvent(QTouchEvent *event)
{
- eventList.append(Event(event->type(), event->touchPoints()));
- QList<QEventPoint> tps = event->touchPoints();
- Q_ASSERT(!tps.isEmpty());
- point0 = tps.first().id();
+ qCDebug(lcTests) << event << "accepting?" << acceptTouch;
+ eventList.append(Event(event->type(), event->points()));
+ Q_ASSERT(event->pointCount() > 0);
+ point0 = event->point(0).id();
event->setAccepted(acceptTouch);
emit onTouchEvent(this);
}
void mousePressEvent(QMouseEvent *event)
{
+ qCDebug(lcTests) << event << "accepting?" << acceptMouse;
eventList.append(Event(event->type(), event->position().toPoint(), event->globalPosition().toPoint()));
+ mouseGrabber = event->exclusiveGrabber(event->points().first());
event->setAccepted(acceptMouse);
}
void mouseMoveEvent(QMouseEvent *event)
{
+ qCDebug(lcTests) << event << "accepting?" << acceptMouse;
eventList.append(Event(event->type(), event->position().toPoint(), event->globalPosition().toPoint()));
+ mouseGrabber = event->exclusiveGrabber(event->points().first());
event->setAccepted(acceptMouse);
}
void mouseReleaseEvent(QMouseEvent *event)
{
+ qCDebug(lcTests) << event << "accepting?" << acceptMouse;
eventList.append(Event(event->type(), event->position().toPoint(), event->globalPosition().toPoint()));
+ mouseGrabber = event->exclusiveGrabber(event->points().first());
event->setAccepted(acceptMouse);
}
void mouseDoubleClickEvent(QMouseEvent *event)
{
+ qCDebug(lcTests) << event << "accepting?" << acceptMouse;
eventList.append(Event(event->type(), event->position().toPoint(), event->globalPosition().toPoint()));
+ mouseGrabber = event->exclusiveGrabber(event->points().first());
event->setAccepted(acceptMouse);
}
void mouseUngrabEvent()
{
+ qCDebug(lcTests);
eventList.append(Event(QEvent::UngrabMouse, QPoint(0,0), QPoint(0,0)));
+ mouseGrabber = nullptr;
}
void touchUngrabEvent()
{
+ qCDebug(lcTests);
++touchUngrabCount;
}
@@ -143,6 +156,7 @@ public:
}
QList<Event> eventList;
+ QObject *mouseGrabber = nullptr;
int touchUngrabCount = 0;
bool acceptMouse = false;
bool acceptTouch = false;
@@ -154,11 +168,11 @@ public:
event->type() == QEvent::TouchUpdate ||
event->type() == QEvent::TouchCancel ||
event->type() == QEvent::TouchEnd) {
+ qCDebug(lcTests) << event;
QTouchEvent *touch = static_cast<QTouchEvent*>(event);
- eventList.append(Event(event->type(), touch->touchPoints()));
- QList<QEventPoint> tps = touch->touchPoints();
- Q_ASSERT(!tps.isEmpty());
- point0 = tps.first().id();
+ eventList.append(Event(event->type(), touch->points()));
+ Q_ASSERT(touch->pointCount() > 0);
+ point0 = touch->point(0).id();
if (filterTouch)
event->accept();
return true;
@@ -168,6 +182,37 @@ public:
int point0 = -1;
};
+class GrabMonitor : public QObject
+{
+public:
+ QObject *exclusiveGrabber = nullptr;
+ bool fromMouseEvent = false;
+ bool canceled = false;
+
+ void onGrabChanged(QObject *grabber, QPointingDevice::GrabTransition transition, const QPointerEvent *event, const QEventPoint &point)
+ {
+ qCDebug(lcTests) << grabber << transition << event << point << point.device();
+ switch (transition) {
+ case QPointingDevice::GrabTransition::GrabExclusive:
+ exclusiveGrabber = grabber;
+ fromMouseEvent = event && QQuickWindowPrivate::isMouseEvent(event);
+ canceled = false;
+ break;
+ case QPointingDevice::GrabTransition::UngrabExclusive:
+ exclusiveGrabber = nullptr;
+ canceled = false;
+ break;
+ case QPointingDevice::GrabTransition::CancelGrabExclusive:
+ exclusiveGrabber = nullptr;
+ canceled = true;
+ break;
+ default:
+ // ignore the passive grabs since this test doesn't involve pointer handlers
+ break;
+ }
+ }
+};
+
class tst_TouchMouse : public QQmlDataTest
{
Q_OBJECT
@@ -219,6 +264,7 @@ private:
QQuickView *createView();
QPointingDevice *device = QTest::createTouchDevice();
QList<Event> filteredEventList;
+ GrabMonitor grabMonitor;
};
QQuickView *tst_TouchMouse::createView()
@@ -231,6 +277,7 @@ void tst_TouchMouse::initTestCase()
{
QQmlDataTest::initTestCase();
qmlRegisterType<EventItem>("Qt.test", 1, 0, "EventItem");
+ connect(device, &QPointingDevice::grabChanged, &grabMonitor, &GrabMonitor::onGrabChanged);
}
void tst_TouchMouse::simpleTouchEvent_data()
@@ -254,6 +301,7 @@ void tst_TouchMouse::simpleTouchEvent()
EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
QVERIFY(eventItem1);
+ auto devPriv = QPointingDevicePrivate::get(device);
// Do not accept touch or mouse
QPoint p1;
@@ -302,7 +350,7 @@ void tst_TouchMouse::simpleTouchEvent()
QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
if (synthMouse)
QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress);
- QCOMPARE(window->mouseGrabberItem(), synthMouse ? eventItem1 : nullptr);
+ QCOMPARE(devPriv->firstPointExclusiveGrabber(), synthMouse ? eventItem1 : nullptr);
QPoint localPos = eventItem1->mapFromScene(p1).toPoint();
QPoint globalPos = window->mapToGlobal(p1);
@@ -612,9 +660,9 @@ void tst_TouchMouse::buttonOnFlickable()
QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window.data());
QVERIFY(windowPriv->touchMouseId != -1);
- auto pointerEvent = windowPriv->pointerEventInstance(device);
- QCOMPARE(pointerEvent->point(0)->exclusiveGrabber(), eventItem1);
- QCOMPARE(window->mouseGrabberItem(), eventItem1);
+ auto devPriv = QPointingDevicePrivate::get(device);
+ QCOMPARE(devPriv->pointById(0)->exclusiveGrabber, eventItem1);
+ QCOMPARE(grabMonitor.exclusiveGrabber, eventItem1);
int dragDelta = -qApp->styleHints()->startDragDistance();
p1 += QPoint(0, dragDelta);
@@ -628,15 +676,14 @@ void tst_TouchMouse::buttonOnFlickable()
QTest::touchEvent(window.data(), device).move(0, p3, window.data());
QQuickTouchUtils::flush(window.data());
- // we cannot really know when the events get grabbed away
QVERIFY(eventItem1->eventList.size() >= 4);
QCOMPARE(eventItem1->eventList.at(2).type, QEvent::TouchUpdate);
QCOMPARE(eventItem1->eventList.at(3).type, QEvent::MouseMove);
- QCOMPARE(window->mouseGrabberItem(), flickable);
+ QCOMPARE(grabMonitor.exclusiveGrabber, flickable);
QVERIFY(windowPriv->touchMouseId != -1);
- QCOMPARE(pointerEvent->point(0)->exclusiveGrabber(), flickable);
- QVERIFY(flickable->isMovingVertically());
+ QCOMPARE(devPriv->pointById(0)->exclusiveGrabber, flickable);
+// QVERIFY(flickable->isMovingVertically()); // it will move after a couple more mouse moves
QTest::touchEvent(window.data(), device).release(0, p3, window.data());
QQuickTouchUtils::flush(window.data());
@@ -673,9 +720,9 @@ void tst_TouchMouse::touchButtonOnFlickable()
QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window.data());
QVERIFY(windowPriv->touchMouseId == -1);
- auto pointerEvent = windowPriv->pointerEventInstance(device);
- QCOMPARE(pointerEvent->point(0)->grabberItem(), eventItem2);
- QCOMPARE(window->mouseGrabberItem(), nullptr);
+ auto devPriv = QPointingDevicePrivate::get(device);
+ QCOMPARE(devPriv->pointById(0)->exclusiveGrabber, eventItem2);
+ QCOMPARE(grabMonitor.exclusiveGrabber, eventItem2);
int dragDelta = qApp->styleHints()->startDragDistance() * -0.7;
p1 += QPoint(0, dragDelta);
@@ -693,9 +740,9 @@ void tst_TouchMouse::touchButtonOnFlickable()
QTRY_COMPARE(eventItem2->touchUngrabCount, 1);
QVERIFY(eventItem2->eventList.size() > 2);
QCOMPARE(eventItem2->eventList.at(1).type, QEvent::TouchUpdate);
- QCOMPARE(window->mouseGrabberItem(), flickable);
+ QCOMPARE(grabMonitor.exclusiveGrabber, flickable);
QVERIFY(windowPriv->touchMouseId != -1);
- QCOMPARE(pointerEvent->point(0)->grabberItem(), flickable);
+ QCOMPARE(devPriv->pointById(0)->exclusiveGrabber, flickable);
QVERIFY(flickable->isMovingVertically());
QTest::touchEvent(window.data(), device).release(0, p3, window.data());
@@ -809,10 +856,10 @@ void tst_TouchMouse::buttonOnDelayedPressFlickable()
// flickable should have the mouse grab, and have moved the itemForTouchPointId
// for the touchMouseId to the new grabber.
- QCOMPARE(window->mouseGrabberItem(), flickable);
+ QCOMPARE(grabMonitor.exclusiveGrabber, flickable);
QVERIFY(windowPriv->touchMouseId != -1);
- auto pointerEvent = windowPriv->pointerEventInstance(device);
- QCOMPARE(pointerEvent->point(0)->grabberItem(), flickable);
+ auto devPriv = QPointingDevicePrivate::get(device);
+ QCOMPARE(devPriv->pointById(0)->exclusiveGrabber, flickable);
}
QTest::touchEvent(window.data(), device).release(0, pEnd, window.data());
@@ -1243,8 +1290,6 @@ void tst_TouchMouse::mouseOnFlickableOnPinch()
pinchSequence.move(0, p, window.data()).commit();
QQuickTouchUtils::flush(window.data());
- QCOMPARE(window->mouseGrabberItem(), flickable);
-
// Add a second finger, this should lead to stealing
p1 = QPoint(40, 100);
p2 = QPoint(60, 100);
@@ -1348,21 +1393,20 @@ void tst_TouchMouse::touchGrabCausesMouseUngrab()
QCOMPARE(leftItem->eventList.size(), 2);
QCOMPARE(leftItem->eventList.at(0).type, QEvent::TouchBegin);
QCOMPARE(leftItem->eventList.at(1).type, QEvent::MouseButtonPress);
- QCOMPARE(window->mouseGrabberItem(), leftItem);
+ QCOMPARE(grabMonitor.exclusiveGrabber, leftItem);
leftItem->eventList.clear();
rightItem->acceptTouch = true;
- {
- QList<int> ids;
- ids.append(leftItem->point0);
- rightItem->grabTouchPoints(ids);
- }
+ auto devPriv = QPointingDevicePrivate::get(device);
+ auto epd = devPriv->queryPointById(0);
+ QVERIFY(epd);
+ devPriv->setExclusiveGrabber(nullptr, epd->eventPoint, rightItem);
// leftItem should have lost the mouse as the touch point that was being used to emulate it
// has been grabbed by another item.
QCOMPARE(leftItem->eventList.size(), 1);
QCOMPARE(leftItem->eventList.at(0).type, QEvent::UngrabMouse);
- QCOMPARE(window->mouseGrabberItem(), (QQuickItem*)nullptr);
+ QCOMPARE(grabMonitor.exclusiveGrabber, rightItem);
}
void tst_TouchMouse::touchPointDeliveryOrder()
@@ -1556,6 +1600,7 @@ void tst_TouchMouse::implicitUngrab()
QQuickViewTestUtil::centerOnScreen(window.data());
QQuickViewTestUtil::moveMouseAway(window.data());
QVERIFY(QTest::qWaitForWindowActive(window.data()));
+ QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window.data());
QQuickItem *root = window->rootObject();
QVERIFY(root != nullptr);
@@ -1564,12 +1609,13 @@ void tst_TouchMouse::implicitUngrab()
QPoint p1(20, 20);
QTest::touchEvent(window.data(), device).press(0, p1);
- QCOMPARE(window->mouseGrabberItem(), eventItem);
+ QCOMPARE(grabMonitor.exclusiveGrabber, eventItem);
eventItem->eventList.clear();
eventItem->setEnabled(false);
QVERIFY(!eventItem->eventList.isEmpty());
QCOMPARE(eventItem->eventList.at(0).type, QEvent::UngrabMouse);
QTest::touchEvent(window.data(), device).release(0, p1); // clean up potential state
+ QCOMPARE(windowPriv->touchMouseId, -1);
eventItem->setEnabled(true);
QTest::touchEvent(window.data(), device).press(0, p1);
diff --git a/tests/manual/pointer/inputinspector.cpp b/tests/manual/pointer/inputinspector.cpp
index ff921fab0f..b919c489f4 100644
--- a/tests/manual/pointer/inputinspector.cpp
+++ b/tests/manual/pointer/inputinspector.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the manual tests of the Qt Toolkit.
@@ -27,9 +27,9 @@
****************************************************************************/
#include "inputinspector.h"
-#include <QtQuick/QQuickWindow>
#include <QtQuick/QQuickItem>
#include <QtQuick/private/qquickpointerhandler_p.h>
+#include <QtGui/private/qpointingdevice_p.h>
#include <QtCore/QSet>
static const int timerInterval = 100;
@@ -139,23 +139,13 @@ const QPointingDevice *InputInspector::pointerDevice() const
QVector<QObject*> InputInspector::passiveGrabbers_helper(int pointId /*= 0*/) const
{
QVector<QObject*> result;
- QSet<QObject*> visited;
const QPointingDevice *device = pointerDevice();
if (device && source()) {
- QQuickWindowPrivate *winPriv = QQuickWindowPrivate::get(source());
- QQuickPointerEvent *pointerEvent = winPriv->pointerEventInstance(device);
- if (pointerEvent) {
- for (int i = 0; i < pointerEvent->pointCount(); ++i) {
- QQuickEventPoint *eventPoint = pointerEvent->point(i);
- QVector<QPointer <QQuickPointerHandler> > passives = eventPoint->passiveGrabbers();
- if (!pointId || eventPoint->pointId() == pointId) {
- for (auto it = passives.constBegin(); it != passives.constEnd(); ++it) {
- QObject *handler = it->data();
- if (!visited.contains(handler)) {
- result << it->data();
- visited << handler;
- }
- }
+ for (auto eventPoint : QPointingDevicePrivate::get(device)->activePoints) {
+ if (!pointId || eventPoint.id() == pointId) {
+ for (auto pg : eventPoint.passiveGrabbers()) {
+ if (!result.contains(pg))
+ result << pg;
}
}
}
@@ -166,21 +156,13 @@ QVector<QObject*> InputInspector::passiveGrabbers_helper(int pointId /*= 0*/) co
QVector<QObject*> InputInspector::exclusiveGrabbers_helper(int pointId /*= 0*/) const
{
QVector<QObject*> result;
- QSet<QObject*> visited;
const QPointingDevice *device = pointerDevice();
if (device && source()) {
- QQuickWindowPrivate *winPriv = QQuickWindowPrivate::get(source());
- QQuickPointerEvent *pointerEvent = winPriv->pointerEventInstance(device);
- if (pointerEvent) {
- for (int i = 0; i < pointerEvent->pointCount(); ++i) {
- QQuickEventPoint *eventPoint = pointerEvent->point(i);
- if (!pointId || eventPoint->pointId() == pointId) {
- if (QObject *exclusiveGrabber = eventPoint->exclusiveGrabber()) {
- if (!visited.contains(exclusiveGrabber)) {
- result << exclusiveGrabber;
- visited << exclusiveGrabber;
- }
- }
+ for (auto eventPoint : QPointingDevicePrivate::get(device)->activePoints) {
+ if (!pointId || eventPoint.id() == pointId) {
+ if (auto g = eventPoint.exclusiveGrabber()) {
+ if (!result.contains(g))
+ result << g;
}
}
}
diff --git a/tests/manual/pointer/inputinspector.h b/tests/manual/pointer/inputinspector.h
index 0ef0a96987..31d99cf25d 100644
--- a/tests/manual/pointer/inputinspector.h
+++ b/tests/manual/pointer/inputinspector.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the manual tests of the Qt Toolkit.
@@ -30,7 +30,7 @@
#define INPUTINSPECTOR_H
#include <QObject>
-class QQuickWindow;
+#include <QtQuick/QQuickWindow>
class QQuickPointerHandler;
class QPointingDevice;
diff --git a/tests/manual/pointer/singlePointHandlerProperties.qml b/tests/manual/pointer/singlePointHandlerProperties.qml
index c2500770f0..9bebf23810 100644
--- a/tests/manual/pointer/singlePointHandlerProperties.qml
+++ b/tests/manual/pointer/singlePointHandlerProperties.qml
@@ -140,7 +140,7 @@ Rectangle {
id: pointHandler
target: null
acceptedButtons: Qt.AllButtons
- onGrabChanged: if (active) { // 'point' is an implicit parameter referencing to a QQuickEventPoint instance
+ onGrabChanged: if (active) { // 'point' is an implicit parameter referencing to a QEventPoint instance
console.log("grabbed " + point.pointId + " @ " + point.sceneGrabPos)
grabbingLocationIndicator.createObject(root, {"x": point.sceneGrabPosition.x, "y": point.sceneGrabPosition.y - 16})
}
diff --git a/tests/manual/pointer/tapHandler.qml b/tests/manual/pointer/tapHandler.qml
index 8c1fac9a2f..6e51fc6fda 100644
--- a/tests/manual/pointer/tapHandler.qml
+++ b/tests/manual/pointer/tapHandler.qml
@@ -53,7 +53,7 @@ Item {
borderBlink.blinkColor = "red"
borderBlink.start()
}
- onTapped: { // 'eventPoint' is a signal parameter of type QQuickEventPoint*
+ onTapped: { // 'eventPoint' is a signal parameter of type QEventPoint*
console.log("tapped button " + eventPoint.event.button + " @ " + eventPoint.scenePosition +
" on device '" + eventPoint.event.device.name + "' " + (tapCount > 1 ? (tapCount + " times") : "for the first time"))
if (tapCount > 1) {