diff options
author | Shawn Rutledge <shawn.rutledge@qt.io> | 2022-05-06 16:31:37 +0200 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2022-06-04 13:26:47 +0000 |
commit | e9f1881c0dced63b3559f469d73613bcaba06f8d (patch) | |
tree | 29e49fd2ae10dcf12e03cf07c2aa61d877f42ced /src/quick | |
parent | 4602dbc7e10eac711b11bce87e1c717fa1ec49be (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
Change-Id: I60af1dd932835d358baa1422523cc24b2ab046a0
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
(cherry picked from commit 8068bde891eefe99a43deb83e58166b476f65225)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Diffstat (limited to 'src/quick')
-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 551c0cf6cf..09f2a87183 100644 --- a/src/quick/items/qquickflickable.cpp +++ b/src/quick/items/qquickflickable.cpp @@ -1054,6 +1054,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()) @@ -1361,9 +1372,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); @@ -1395,12 +1406,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; @@ -1415,7 +1428,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 35f221b3cc..fad63c1ef1 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; |