Details
-
Bug
-
Resolution: Unresolved
-
P2: Important
-
None
-
5.15.0
-
None
Description
We discovered that QScroller misinterprets "stop" gestures as "accelerating flick" gestures in this case:
- Flick in direction A.
- While the view is coasting, decide that you want to stop close to the current position.
- Grab the view (still coasting), and drag it slowly in direction A.
- When you reached the desired point, stop your movement, and release the view.
- QScroller interprets this release as "accelerating flick", and makes the view coast faster in direction A.
A video of this is available here: https://invent.kde.org/graphics/okular/uploads/513cb20a3ff47050522a00be09d2a050/vokoscreenNG-2020-11-06_16-57-50.mkv
QScroller misses to check the speed of the flick gesture; our current workaround is to limit the duration using QScrollerProperties::AcceleratingFlickMaximumTime.
This is what I found as possible problem:
bool QScrollerPrivate::releaseWhileDragging(const QPointF &position, qint64 timestamp) { Q_Q(QScroller); const QScrollerPropertiesPrivate *sp = properties.d.data(); // handleDrag updates lastPosition, lastTimestamp and velocity // [This calls updateVelocity(), which sets QPointF releaseVelocity to the current drag velocity.] handleDrag(position, timestamp); // check if we moved at all - this can happen if you stop a running // scroller with a press and release shortly afterwards QPointF deltaPixel = position - pressPosition; if (((deltaPixel / q->pixelPerMeter()).manhattanLength()) > sp->dragStartDistance) { // handle accelerating flicks // [This if's condition checks whether this flick gesture meets the requirements for _accelerating_ flick, but not whether it _is_ a flick.] if ((oldVelocity != QPointF(0, 0)) && sp->acceleratingFlickMaximumTime && ((timestamp - pressTimestamp) < qint64(sp->acceleratingFlickMaximumTime * 1000))) { // [...] // [Multiplies releaseVelocity] } } // [...] }
I suggest to insert this additional condition where I have written "but not whether it is a flick":
qMax(qAbs(releaseVelocity.x()), qAbs(releaseVelocity.y())) >= sp->minimumVelocity &&
.
This would check whether the current movement speed is above the QScrollerProperties::MinimumSpeed setting, using the biggest component, like createScrollingSegments(QPointF, ...) does.