diff options
authorShawn Rutledge <>2017-12-11 14:32:04 +0100
committerShawn Rutledge <>2017-12-13 06:53:01 +0000
commitae01e0dbf50cb6da1967e10eb95d63313dc5aa7a (patch)
parent61118298431a2719bb9028691810268ddb3058b7 (diff)
Flickable: don't jump after premature movementEnding due to timer
Followup to ef8c6f6a0bf5e4c9ee41306f2df59048ab96038f: we emit movementEnding for the benefit of the user, scrollbars, decorators etc. in case the ScrollEnd phase means that movement really ended (it means the user lifted his fingers from the trackpad, but momentum events can cause the movement to continue after that). But in case movement didn't end, we don't want to have a jump when it resumes. But scrollingPhase will be true after an event with ScrollBegin phase, and false after an event with ScrollEnd, also false if the mouse is an ordinary wheel mouse without phases. So when the timer fires, if the user has not yet lifted his fingers, scrollingPhase is true, and that means scrolling isn't really ending, so we should not set vMoved to false. Setting vMoved to false will cause the drag() function to reset vData.dragStartOffset to the current dy value, which ultimately causes the jump in contentY. It should be done only when scrolling really ends. If the timer fires and scrollingPhase is false, we can be sure it really ended. But if you flick, then rest your fingers, then lift them, there is no momentum, so the final event has scroll phase ScrollEnd, and we need to run the timer one more time to detect that there are no more updates and finish the transition back to the default state (set vMoved back to false, emit signals such as movementEnded, etc.) The ultimate solution is to add another Qt::ScrollPhase enum, such as ScrollMomentum, but we should not do that in the 5.9 series. Task-number: QTBUG-63026 Change-Id: I854c52a680028cb1d43b133be65653d87a05a0b1 Reviewed-by: Jan Arve Sæther <>
1 files changed, 11 insertions, 3 deletions
diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp
index 3662827973..44612edc49 100644
--- a/src/quick/items/qquickflickable.cpp
+++ b/src/quick/items/qquickflickable.cpp
@@ -1444,17 +1444,23 @@ void QQuickFlickable::wheelEvent(QWheelEvent *event)
case Qt::ScrollUpdate:
if (d->scrollingPhase)
d->pressed = true;
-#ifdef Q_OS_OSX
+#ifdef Q_OS_MACOS
+ // TODO eliminate this timer when ScrollMomentum has been added
d->movementEndingTimer.start(MovementEndingTimerInterval, this);
case Qt::ScrollEnd:
+ // TODO most of this should be done at transition to ScrollMomentum phase,
+ // then do what the movementEndingTimer triggers at transition to ScrollEnd phase
d->pressed = false;
d->scrollingPhase = false;
d->lastPosTime = -1;
+#ifdef Q_OS_MACOS
+ d->movementEndingTimer.start(MovementEndingTimerInterval, this);
@@ -2671,13 +2677,15 @@ void QQuickFlickable::movementEnding(bool hMovementEnding, bool vMovementEnding)
if (hMovementEnding && d->hData.moving
&& (!d->pressed && !d->stealMouse)) {
d->hData.moving = false;
- d->hMoved = false;
+ if (!d->scrollingPhase)
+ d->hMoved = false;
emit movingHorizontallyChanged();
if (vMovementEnding && d->vData.moving
&& (!d->pressed && !d->stealMouse)) {
d->vData.moving = false;
- d->vMoved = false;
+ if (!d->scrollingPhase)
+ d->vMoved = false;
emit movingVerticallyChanged();
if (wasMoving && !isMoving()) {