Velocities reported by Flickable in onFlickStarted can be 0
authorMartin Jones <martin.jones@nokia.com>
Tue, 13 Sep 2011 02:50:48 +0000 (12:50 +1000)
committerQt by Nokia <qt-info@nokia.com>
Fri, 16 Sep 2011 00:15:03 +0000 (02:15 +0200)
Change 55cfbdb7c64068ae68f7baaceb8acfb96cb0c07e manually applied
from Qt 4.7

Ensure the smoothed velocity is set at the start of the flick.  Ensure
that the smoothed velocity animation isn't restarted unless there is
new valid data.

Change-Id: Ia77249be9980aba268a1bfa0ea3f69c49fa09e5e
Reviewed-by: Bea Lam
Reviewed-on: http://codereview.qt-project.org/4712
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Martin Jones <martin.jones@nokia.com>
src/declarative/items/qsgflickable.cpp
src/qtquick1/graphicsitems/qdeclarativeflickable.cpp
tests/auto/declarative/qsgflickable/data/flickable03.qml
tests/auto/declarative/qsgflickable/tst_qsgflickable.cpp
tests/auto/qtquick1/qdeclarativeflickable/data/flickable03.qml
tests/auto/qtquick1/qdeclarativeflickable/tst_qdeclarativeflickable.cpp

index ce8afa1..36d7db2 100644 (file)
@@ -962,18 +962,24 @@ void QSGFlickablePrivate::handleMouseReleaseEvent(QMouseEvent *event)
     qreal velocity = vData.velocity;
     if (vData.atBeginning || vData.atEnd)
         velocity /= 2;
-    if (qAbs(velocity) > MinimumFlickVelocity && qAbs(event->localPos().y() - pressPos.y()) > FlickThreshold)
+    if (q->yflick() && qAbs(velocity) > MinimumFlickVelocity && qAbs(event->localPos().y() - pressPos.y()) > FlickThreshold) {
+        velocityTimeline.reset(vData.smoothVelocity);
+        vData.smoothVelocity.setValue(-velocity);
         flickY(velocity);
-    else
+    } else {
         fixupY();
+    }
 
     velocity = hData.velocity;
     if (hData.atBeginning || hData.atEnd)
         velocity /= 2;
-    if (qAbs(velocity) > MinimumFlickVelocity && qAbs(event->localPos().x() - pressPos.x()) > FlickThreshold)
+    if (q->xflick() && qAbs(velocity) > MinimumFlickVelocity && qAbs(event->localPos().x() - pressPos.x()) > FlickThreshold) {
+        velocityTimeline.reset(hData.smoothVelocity);
+        hData.smoothVelocity.setValue(-velocity);
         flickX(velocity);
-    else
+    } else {
         fixupX();
+    }
 
     if (!timeline.isActive())
         q->movementEnding();
@@ -1156,19 +1162,25 @@ void QSGFlickable::viewportMoved()
 
     qreal prevX = d->lastFlickablePosition.x();
     qreal prevY = d->lastFlickablePosition.y();
-    d->velocityTimeline.clear();
     if (d->pressed || d->calcVelocity) {
         int elapsed = QSGItemPrivate::restart(d->velocityTime);
         if (elapsed > 0) {
             qreal horizontalVelocity = (prevX - d->hData.move.value()) * 1000 / elapsed;
+            if (qAbs(horizontalVelocity) > 0) {
+                d->velocityTimeline.reset(d->hData.smoothVelocity);
+                d->velocityTimeline.move(d->hData.smoothVelocity, horizontalVelocity, d->reportedVelocitySmoothing);
+                d->velocityTimeline.move(d->hData.smoothVelocity, 0, d->reportedVelocitySmoothing);
+            }
             qreal verticalVelocity = (prevY - d->vData.move.value()) * 1000 / elapsed;
-            d->velocityTimeline.move(d->hData.smoothVelocity, horizontalVelocity, d->reportedVelocitySmoothing);
-            d->velocityTimeline.move(d->hData.smoothVelocity, 0, d->reportedVelocitySmoothing);
-            d->velocityTimeline.move(d->vData.smoothVelocity, verticalVelocity, d->reportedVelocitySmoothing);
-            d->velocityTimeline.move(d->vData.smoothVelocity, 0, d->reportedVelocitySmoothing);
+            if (qAbs(verticalVelocity) > 0) {
+                d->velocityTimeline.reset(d->vData.smoothVelocity);
+                d->velocityTimeline.move(d->vData.smoothVelocity, verticalVelocity, d->reportedVelocitySmoothing);
+                d->velocityTimeline.move(d->vData.smoothVelocity, 0, d->reportedVelocitySmoothing);
+            }
         }
     } else {
         if (d->timeline.time() > d->vTime) {
+            d->velocityTimeline.clear();
             qreal horizontalVelocity = (prevX - d->hData.move.value()) * 1000 / (d->timeline.time() - d->vTime);
             qreal verticalVelocity = (prevY - d->vData.move.value()) * 1000 / (d->timeline.time() - d->vTime);
             d->hData.smoothVelocity.setValue(horizontalVelocity);
index f145312..6fa92b3 100644 (file)
@@ -913,18 +913,24 @@ void QDeclarative1FlickablePrivate::handleMouseReleaseEvent(QGraphicsSceneMouseE
     qreal velocity = vData.velocity;
     if (vData.atBeginning || vData.atEnd)
         velocity /= 2;
-    if (qAbs(velocity) > MinimumFlickVelocity && qAbs(event->pos().y() - pressPos.y()) > FlickThreshold)
+    if (q->yflick() && qAbs(velocity) > MinimumFlickVelocity && qAbs(event->pos().y() - pressPos.y()) > FlickThreshold) {
+        velocityTimeline.reset(vData.smoothVelocity);
+        vData.smoothVelocity.setValue(-velocity);
         flickY(velocity);
-    else
+    } else {
         fixupY();
+    }
 
     velocity = hData.velocity;
     if (hData.atBeginning || hData.atEnd)
         velocity /= 2;
-    if (qAbs(velocity) > MinimumFlickVelocity && qAbs(event->pos().x() - pressPos.x()) > FlickThreshold)
+    if (q->xflick() && qAbs(velocity) > MinimumFlickVelocity && qAbs(event->pos().x() - pressPos.x()) > FlickThreshold) {
+        velocityTimeline.reset(hData.smoothVelocity);
+        hData.smoothVelocity.setValue(-velocity);
         flickX(velocity);
-    else
+    } else {
         fixupX();
+    }
 
     if (!timeline.isActive())
         q->movementEnding();
@@ -1124,19 +1130,25 @@ void QDeclarative1Flickable::viewportMoved()
 
     qreal prevX = d->lastFlickablePosition.x();
     qreal prevY = d->lastFlickablePosition.y();
-    d->velocityTimeline.clear();
     if (d->pressed || d->calcVelocity) {
         int elapsed = QDeclarativeItemPrivate::restart(d->velocityTime);
         if (elapsed > 0) {
             qreal horizontalVelocity = (prevX - d->hData.move.value()) * 1000 / elapsed;
+            if (qAbs(horizontalVelocity) > 0) {
+                d->velocityTimeline.reset(d->hData.smoothVelocity);
+                d->velocityTimeline.move(d->hData.smoothVelocity, horizontalVelocity, d->reportedVelocitySmoothing);
+                d->velocityTimeline.move(d->hData.smoothVelocity, 0, d->reportedVelocitySmoothing);
+            }
             qreal verticalVelocity = (prevY - d->vData.move.value()) * 1000 / elapsed;
-            d->velocityTimeline.move(d->hData.smoothVelocity, horizontalVelocity, d->reportedVelocitySmoothing);
-            d->velocityTimeline.move(d->hData.smoothVelocity, 0, d->reportedVelocitySmoothing);
-            d->velocityTimeline.move(d->vData.smoothVelocity, verticalVelocity, d->reportedVelocitySmoothing);
-            d->velocityTimeline.move(d->vData.smoothVelocity, 0, d->reportedVelocitySmoothing);
+            if (qAbs(verticalVelocity) > 0) {
+                d->velocityTimeline.reset(d->vData.smoothVelocity);
+                d->velocityTimeline.move(d->vData.smoothVelocity, verticalVelocity, d->reportedVelocitySmoothing);
+                d->velocityTimeline.move(d->vData.smoothVelocity, 0, d->reportedVelocitySmoothing);
+            }
         }
     } else {
         if (d->timeline.time() > d->vTime) {
+            d->velocityTimeline.clear();
             qreal horizontalVelocity = (prevX - d->hData.move.value()) * 1000 / (d->timeline.time() - d->vTime);
             qreal verticalVelocity = (prevY - d->vData.move.value()) * 1000 / (d->timeline.time() - d->vTime);
             d->hData.smoothVelocity.setValue(horizontalVelocity);
index e34b63b..ebc49ba 100644 (file)
@@ -1,7 +1,7 @@
 import QtQuick 2.0
 
 Flickable {
-    width: 100; height: 100
+    width: 100; height: 200
     contentWidth: column.width; contentHeight: column.height
 
     Column {
index 0b9fdf0..d12008f 100644 (file)
@@ -79,10 +79,12 @@ private slots:
     void wheel();
     void movingAndDragging();
     void disabled();
+    void flickVelocity();
 
 private:
     QDeclarativeEngine engine;
 
+    void flick(QSGView *canvas, const QPoint &from, const QPoint &to, int duration);
     template<typename T>
     T *findItem(QSGItem *parent, const QString &objectName);
 };
@@ -545,6 +547,52 @@ void tst_qsgflickable::disabled()
     QVERIFY(canvas->rootObject()->property("clicked").toBool() == true);
 }
 
+void tst_qsgflickable::flickVelocity()
+{
+#ifdef Q_WS_MAC
+    QSKIP("Producing flicks on Mac CI impossible due to timing problems", SkipAll);
+#endif
+
+    QSGView *canvas = new QSGView;
+    canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/flickable03.qml"));
+    canvas->show();
+    canvas->setFocus();
+    QVERIFY(canvas->rootObject() != 0);
+
+    QSGFlickable *flickable = qobject_cast<QSGFlickable*>(canvas->rootObject());
+    QVERIFY(flickable != 0);
+
+    // flick up
+    flick(canvas, QPoint(20,190), QPoint(20, 50), 200);
+    QVERIFY(flickable->verticalVelocity() > 0.0);
+    QTRY_VERIFY(flickable->verticalVelocity() == 0.0);
+
+    // flick down
+    flick(canvas, QPoint(20,10), QPoint(20, 140), 200);
+    QVERIFY(flickable->verticalVelocity() < 0.0);
+    QTRY_VERIFY(flickable->verticalVelocity() == 0.0);
+
+    delete canvas;
+}
+
+void tst_qsgflickable::flick(QSGView *canvas, const QPoint &from, const QPoint &to, int duration)
+{
+    const int pointCount = 5;
+    QPoint diff = to - from;
+
+    // send press, five equally spaced moves, and release.
+    QTest::mousePress(canvas, Qt::LeftButton, 0, from);
+
+    for (int i = 0; i < pointCount; ++i) {
+        QMouseEvent mv(QEvent::MouseMove, from + (i+1)*diff/pointCount, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
+        QApplication::sendEvent(canvas, &mv);
+        QTest::qWait(duration/pointCount);
+        QCoreApplication::processEvents();
+    }
+
+    QTest::mouseRelease(canvas, Qt::LeftButton, 0, to);
+}
+
 template<typename T>
 T *tst_qsgflickable::findItem(QSGItem *parent, const QString &objectName)
 {
index a3e92fe..8359ad1 100644 (file)
@@ -1,7 +1,7 @@
 import QtQuick 1.0
 
 Flickable {
-    width: 100; height: 100
+    width: 100; height: 200
     contentWidth: column.width; contentHeight: column.height
 
     Column {
index 80bf71a..2d8c75b 100644 (file)
@@ -79,10 +79,12 @@ private slots:
     void testQtQuick11Attributes_data();
     void wheel();
     void disabled();
+    void flickVelocity();
 
 private:
     QDeclarativeEngine engine;
 
+    void flick(QGraphicsView *canvas, const QPoint &from, const QPoint &to, int duration);
     template<typename T>
     T *findItem(QGraphicsObject *parent, const QString &objectName);
 };
@@ -514,6 +516,53 @@ void tst_qdeclarativeflickable::disabled()
     QVERIFY(canvas->rootObject()->property("clicked").toBool() == true);
 }
 
+void tst_qdeclarativeflickable::flickVelocity()
+{
+#ifdef Q_WS_MAC
+    QSKIP("Producing flicks on Mac CI impossible due to timing problems", SkipAll);
+#endif
+
+    QDeclarativeView *canvas = new QDeclarativeView;
+    canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/flickable03.qml"));
+    canvas->show();
+    canvas->setFocus();
+    QVERIFY(canvas->rootObject() != 0);
+
+    QDeclarative1Flickable *flickable = qobject_cast<QDeclarative1Flickable*>(canvas->rootObject());
+    QVERIFY(flickable != 0);
+
+    // flick up
+    flick(canvas, QPoint(20,190), QPoint(20, 50), 200);
+    QVERIFY(flickable->verticalVelocity() > 0.0);
+    QTRY_VERIFY(flickable->verticalVelocity() == 0.0);
+
+    // flick down
+    flick(canvas, QPoint(20,10), QPoint(20, 140), 200);
+    QVERIFY(flickable->verticalVelocity() < 0.0);
+    QTRY_VERIFY(flickable->verticalVelocity() == 0.0);
+
+    delete canvas;
+}
+
+void tst_qdeclarativeflickable::flick(QGraphicsView *canvas, const QPoint &from, const QPoint &to, int duration)
+{
+    const int pointCount = 5;
+    QPoint diff = to - from;
+
+    // send press, five equally spaced moves, and release.
+    QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(from));
+
+    for (int i = 0; i < pointCount; ++i) {
+        QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(from + (i+1)*diff/pointCount), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
+        QApplication::sendEvent(canvas->viewport(), &mv);
+        QTest::qWait(duration/pointCount);
+        QCoreApplication::processEvents();
+    }
+
+    QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(to));
+}
+
+
 template<typename T>
 T *tst_qdeclarativeflickable::findItem(QGraphicsObject *parent, const QString &objectName)
 {