diff options
| author | Shawn Rutledge <shawn.rutledge@qt.io> | 2022-05-06 16:31:37 +0200 |
|---|---|---|
| committer | Shawn Rutledge <shawn.rutledge@qt.io> | 2022-05-11 12:56:22 +0200 |
| commit | 8068bde891eefe99a43deb83e58166b476f65225 (patch) | |
| tree | 477456cdccce7346cd6c13f2d551a5593f5b7a4f /src | |
| parent | 5b0bb8d78e1854f3a23d7dd0bb286f524b272c37 (diff) | |
QQuickFlickable: fix flicking when item is rotated
QEventPoint::velocity() is in screen coordinates, as documented; it needs
to be transformed to local coordinates in case the Flickable is rotated
and/or scaled. windowToItemTransform() gives us a composite transform
matrix; we remove the translation components to get only the rotation
and scaling.
Also fix the press position calculation in handleReleaseEvent().
With the manual test one can pinch to scale and rotate a Flickable, then
verify that with a single finger, the Flickable gets scrolled by an
appropriate distance in spite of that.
Done-with: Ivan Solovev
Fixes: QTBUG-99639
Pick-to: 6.3 6.2
Change-Id: I60af1dd932835d358baa1422523cc24b2ab046a0
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
Diffstat (limited to 'src')
| -rw-r--r-- | src/quick/items/qquickflickable.cpp | 23 | ||||
| -rw-r--r-- | src/quick/items/qquickflickable_p_p.h | 1 |
2 files changed, 19 insertions, 5 deletions
diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp index 7c42e9b1d4..8dc9a9afe6 100644 --- a/src/quick/items/qquickflickable.cpp +++ b/src/quick/items/qquickflickable.cpp @@ -1055,6 +1055,17 @@ void QQuickFlickable::setSynchronousDrag(bool v) } } +/*! \internal + Take the velocity of the first point from the given \a event and transform + it to the local coordinate system (taking scale and rotation into account). +*/ +QVector2D QQuickFlickablePrivate::firstPointLocalVelocity(QPointerEvent *event) +{ + QTransform transform = windowToItemTransform(); + // rotate and scale the velocity vector from scene to local + return QVector2D(transform.map(event->point(0).velocity().toPointF()) - transform.map(QPointF())); +} + qint64 QQuickFlickablePrivate::computeCurrentTime(QInputEvent *event) const { if (0 != event->timestamp()) @@ -1362,9 +1373,9 @@ void QQuickFlickablePrivate::handleMoveEvent(QPointerEvent *event) qint64 currentTimestamp = computeCurrentTime(event); const auto &firstPoint = event->points().first(); const auto &pos = firstPoint.position(); - QVector2D deltas = QVector2D(pos - q->mapFromGlobal(firstPoint.globalPressPosition())); + const QVector2D deltas = QVector2D(pos - q->mapFromGlobal(firstPoint.globalPressPosition())); + const QVector2D velocity = firstPointLocalVelocity(event); bool overThreshold = false; - QVector2D velocity = event->point(0).velocity(); if (q->yflick()) overThreshold |= QQuickDeliveryAgentPrivate::dragOverThreshold(deltas.y(), Qt::YAxis, firstPoint); @@ -1396,12 +1407,14 @@ void QQuickFlickablePrivate::handleReleaseEvent(QPointerEvent *event) bool canBoost = false; const auto pos = event->points().first().position(); - const auto pressPos = event->points().first().pressPosition(); + const auto pressPos = q->mapFromGlobal(event->points().first().globalPressPosition()); + const QVector2D eventVelocity = firstPointLocalVelocity(event); + qCDebug(lcVel) << event->deviceType() << event->type() << "velocity" << event->points().first().velocity() << "transformed to local" << eventVelocity; qreal vVelocity = 0; if (elapsed < 100 && vData.velocity != 0.) { vVelocity = (event->device()->capabilities().testFlag(QInputDevice::Capability::Velocity) - ? event->point(0).velocity().y() : vData.velocity); + ? eventVelocity.y() : vData.velocity); } if ((vData.atBeginning && vVelocity > 0.) || (vData.atEnd && vVelocity < 0.)) { vVelocity /= 2; @@ -1416,7 +1429,7 @@ void QQuickFlickablePrivate::handleReleaseEvent(QPointerEvent *event) qreal hVelocity = 0; if (elapsed < 100 && hData.velocity != 0.) { hVelocity = (event->device()->capabilities().testFlag(QInputDevice::Capability::Velocity) - ? event->point(0).velocity().x() : hData.velocity); + ? eventVelocity.x() : hData.velocity); } if ((hData.atBeginning && hVelocity > 0.) || (hData.atEnd && hVelocity < 0.)) { hVelocity /= 2; diff --git a/src/quick/items/qquickflickable_p_p.h b/src/quick/items/qquickflickable_p_p.h index 388c70472f..9bc33d436f 100644 --- a/src/quick/items/qquickflickable_p_p.h +++ b/src/quick/items/qquickflickable_p_p.h @@ -268,6 +268,7 @@ public: const QVector2D &deltas, bool overThreshold, bool momentum, bool velocitySensitiveOverBounds, const QVector2D &velocity); + QVector2D firstPointLocalVelocity(QPointerEvent *event); qint64 computeCurrentTime(QInputEvent *event) const; qreal devicePixelRatio() const; |
