Fix Flickable movementEnded() signal emission
authorAndras Becsi <andras.becsi@nokia.com>
Thu, 13 Sep 2012 13:18:19 +0000 (15:18 +0200)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Tue, 18 Sep 2012 15:14:22 +0000 (17:14 +0200)
In case the content was flicked horizontally so that the vertical
position did not change handleMouseReleaseEvent performed a fixup
for the vertical position to be an integer _before_ starting the
horizontal flick. For some large content the rounding fixup had
finished before the flicking animation started which resulted
in a premature emission of the movementEnded() signal.
This race condition did not affect vertical flicking because the
vertical animation had always been started before the horizontal
fixup was scheduled.

The issue was revealed by QQuickWebView which above a certain
velocity threshold locks the movement in one direction, thus
produces the exact same vertical position throughout a horizontal
pan gesture.

This patch removes the race condition by starting the flick
animation in either direction first then performing the
position fixup if needed.

There does not seem to be a reliable way to auto-test this.

Change-Id: Idc8fb59b0a6ead71c6cfc7083a386d51048ec50c
Reviewed-by: Jocelyn Turcotte <jocelyn.turcotte@digia.com>
Reviewed-by: Shawn Rutledge <shawn.rutledge@digia.com>
Reviewed-by: Frederik Gladhorn <frederik.gladhorn@digia.com>

src/quick/items/qquickflickable.cpp

index 99a0c50..5ba5908 100644 (file)
@@ -1172,27 +1172,31 @@ void QQuickFlickablePrivate::handleMouseReleaseEvent(QMouseEvent *event)
 
     flickBoost = canBoost ? qBound(1.0, flickBoost+0.25, QML_FLICK_MULTIFLICK_MAXBOOST) : 1.0;
 
-    bool flickedV = false;
+    bool flickedVertically = false;
     vVelocity *= flickBoost;
-    if (q->yflick() && qAbs(vVelocity) > MinimumFlickVelocity && qAbs(event->localPos().y() - pressPos.y()) > FlickThreshold) {
+    bool isVerticalFlickAllowed = q->yflick() && qAbs(vVelocity) > MinimumFlickVelocity && qAbs(event->localPos().y() - pressPos.y()) > FlickThreshold;
+    if (isVerticalFlickAllowed) {
         velocityTimeline.reset(vData.smoothVelocity);
         vData.smoothVelocity.setValue(-vVelocity);
-        flickedV = flickY(vVelocity);
-    } else {
-        fixupY();
+        flickedVertically = flickY(vVelocity);
     }
 
-    bool flickedH = false;
+    bool flickedHorizontally = false;
     hVelocity *= flickBoost;
-    if (q->xflick() && qAbs(hVelocity) > MinimumFlickVelocity && qAbs(event->localPos().x() - pressPos.x()) > FlickThreshold) {
+    bool isHorizontalFlickAllowed = q->xflick() && qAbs(hVelocity) > MinimumFlickVelocity && qAbs(event->localPos().x() - pressPos.x()) > FlickThreshold;
+    if (isHorizontalFlickAllowed) {
         velocityTimeline.reset(hData.smoothVelocity);
         hData.smoothVelocity.setValue(-hVelocity);
-        flickedH = flickX(hVelocity);
-    } else {
-        fixupX();
+        flickedHorizontally = flickX(hVelocity);
     }
 
-    flickingStarted(flickedH, flickedV);
+    if (!isVerticalFlickAllowed)
+        fixupY();
+
+    if (!isHorizontalFlickAllowed)
+        fixupX();
+
+    flickingStarted(flickedHorizontally, flickedVertically);
     if (!isViewMoving())
         q->movementEnding();
 }