diff options
author | Shawn Rutledge <shawn.rutledge@qt.io> | 2019-09-10 15:26:56 +0200 |
---|---|---|
committer | Shawn Rutledge <shawn.rutledge@qt.io> | 2019-09-12 18:54:12 +0200 |
commit | 3df387d63421f09533ab72e2a73fb5d259693120 (patch) | |
tree | 6de0851db68e73b442523a39054fae88ec399261 | |
parent | 90a706dffb944e7d18b8b199b1cea68633e2b172 (diff) |
PathView: reduce velocity by linear decay model if release is delayed
That is, from the time between the last mouse move event to the mouse
release, the velocity will be linearly discounted/depreciated until it
reaches 0 at QML_FLICK_VELOCITY_DECAY_TIME, which is currently 50 ms.
50 ms seems like a long time if the user meant to flick and release
immediately (in practice it might be more like 4 ms), and also a
short time if the user meant to "dwell" before releasing.
If we try to translate the fake physics to real physics, this would be
approximately equivalent to saying that if you slide a flat plate on an
air hockey table with one finger, and then stop suddenly, its momentum
_would_ cause it to keep moving under your finger for up to 50ms (except
that it doesn't, because our timeline doesn't "tick" until after the
release); and yet if you hold it for longer than 50ms, it will stop
right on the spot. That's not quite realistic, but feels OK for fake
physics (like the rest of the physics in Qt Quick).
Also add the qt.quick.pathview logging category, which will just log
the velocity calculations for now (but is intended for anything else
in PathView that seems worth logging later on).
Task-number: QTBUG-77173
Task-number: QTBUG-59052
Change-Id: Ie86f18d3b3305874b698c848290e0fd3beda94de
Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io>
-rw-r--r-- | src/quick/items/qquickflickablebehavior_p.h | 5 | ||||
-rw-r--r-- | src/quick/items/qquickpathview.cpp | 11 |
2 files changed, 15 insertions, 1 deletions
diff --git a/src/quick/items/qquickflickablebehavior_p.h b/src/quick/items/qquickflickablebehavior_p.h index ae7fe71359..fbce62f075 100644 --- a/src/quick/items/qquickflickablebehavior_p.h +++ b/src/quick/items/qquickflickablebehavior_p.h @@ -93,6 +93,11 @@ #define QML_FLICK_MULTIFLICK_THRESHOLD 1250 #endif +// If the time (ms) between the last move and the release exceeds this, then velocity will be zero. +#ifndef QML_FLICK_VELOCITY_DECAY_TIME +#define QML_FLICK_VELOCITY_DECAY_TIME 50 +#endif + // Multiflick acceleration minimum contentSize/viewSize ratio #ifndef QML_FLICK_MULTIFLICK_RATIO #define QML_FLICK_MULTIFLICK_RATIO 10 diff --git a/src/quick/items/qquickpathview.cpp b/src/quick/items/qquickpathview.cpp index 4e81573356..35b8a872ec 100644 --- a/src/quick/items/qquickpathview.cpp +++ b/src/quick/items/qquickpathview.cpp @@ -60,6 +60,7 @@ QT_BEGIN_NAMESPACE Q_DECLARE_LOGGING_CATEGORY(lcItemViewDelegateLifecycle) +Q_LOGGING_CATEGORY(lcPathView, "qt.quick.pathview") const qreal MinimumFlickVelocity = 75.0; @@ -1623,6 +1624,7 @@ void QQuickPathViewPrivate::addVelocitySample(qreal v) velocityBuffer.append(v); if (velocityBuffer.count() > QML_FLICK_SAMPLEBUFFER) velocityBuffer.remove(0); + qCDebug(lcPathView) << "instantaneous velocity" << v; } qreal QQuickPathViewPrivate::calcVelocity() const @@ -1635,6 +1637,7 @@ qreal QQuickPathViewPrivate::calcVelocity() const velocity += v; } velocity /= count; + qCDebug(lcPathView) << "average velocity" << velocity << "based on" << count << "samples"; } return velocity; } @@ -1765,7 +1768,7 @@ void QQuickPathView::mouseReleaseEvent(QMouseEvent *event) } } -void QQuickPathViewPrivate::handleMouseReleaseEvent(QMouseEvent *) +void QQuickPathViewPrivate::handleMouseReleaseEvent(QMouseEvent *event) { Q_Q(QQuickPathView); stealMouse = false; @@ -1779,6 +1782,12 @@ void QQuickPathViewPrivate::handleMouseReleaseEvent(QMouseEvent *) } qreal velocity = calcVelocity(); + qint64 elapsed = computeCurrentTime(event) - lastPosTime; + // Let the velocity linearly decay such that it becomes 0 if elapsed time > QML_FLICK_VELOCITY_DECAY_TIME + // The intention is that if you are flicking at some speed, then stop in one place for some time before releasing, + // the previous velocity is lost. (QTBUG-77173, QTBUG-59052) + velocity *= qreal(qMax(0LL, QML_FLICK_VELOCITY_DECAY_TIME - elapsed)) / QML_FLICK_VELOCITY_DECAY_TIME; + qCDebug(lcPathView) << "after elapsed time" << elapsed << "velocity decayed to" << velocity; qreal count = pathItems == -1 ? modelCount : qMin(pathItems, modelCount); const auto averageItemLength = path->path().length() / count; qreal pixelVelocity = averageItemLength * velocity; |