aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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) {