Flickable: drag-over-bounds is not velocity-sensitive
authorShawn Rutledge <shawn.rutledge@digia.com>
Fri, 26 Jun 2015 16:14:31 +0000 (18:14 +0200)
committerShawn Rutledge <shawn.rutledge@theqtcompany.com>
Thu, 9 Jul 2015 10:30:42 +0000 (10:30 +0000)
The inspiration for velocity sensitivity was to make it feel more like
native trackpad flicking on OS X.  But on touchscreens it doesn't
make as much sense, and it became too difficult to intentionally
overshoot in applications that depend on pull-to-refresh functionality.

Task-number: QTBUG-46108
Change-Id: I3fea5324aaac1f003ead200e14b0c76bd8c0ece6
Reviewed-by: J-P Nurmi <jpnurmi@theqtcompany.com>
src/quick/items/qquickflickable.cpp
src/quick/items/qquickflickable_p_p.h

index 52142346ab346d744894cafbd5d8a6678121ddb2..19fb66c19c6817313938b45ade5ae2a9e1ebbdd7 100644 (file)
@@ -1004,7 +1004,8 @@ void QQuickFlickablePrivate::maybeBeginDrag(qint64 currentTimestamp, const QPoin
 }
 
 void QQuickFlickablePrivate::drag(qint64 currentTimestamp, QEvent::Type eventType, const QPointF &localPos,
-                                  const QVector2D &deltas, bool overThreshold, bool momentum, const QVector2D &velocity)
+                                  const QVector2D &deltas, bool overThreshold, bool momentum,
+                                  bool velocitySensitiveOverBounds, const QVector2D &velocity)
 {
     Q_Q(QQuickFlickable);
     bool rejectY = false;
@@ -1061,9 +1062,13 @@ void QQuickFlickablePrivate::drag(qint64 currentTimestamp, QEvent::Type eventTyp
                         }
                         return;
                     }
-                    qreal overshoot = (newY - minY) * vData.velocity / QML_FLICK_DEFAULTMAXVELOCITY / QML_FLICK_OVERSHOOTFRICTION;
-                    overshoot = QML_FLICK_OVERSHOOT * devicePixelRatio() * EaseOvershoot(overshoot / QML_FLICK_OVERSHOOT / devicePixelRatio());
-                    newY = minY + overshoot;
+                    if (velocitySensitiveOverBounds) {
+                        qreal overshoot = (newY - minY) * vData.velocity / QML_FLICK_DEFAULTMAXVELOCITY / QML_FLICK_OVERSHOOTFRICTION;
+                        overshoot = QML_FLICK_OVERSHOOT * devicePixelRatio() * EaseOvershoot(overshoot / QML_FLICK_OVERSHOOT / devicePixelRatio());
+                        newY = minY + overshoot;
+                    } else {
+                        newY = minY + (newY - minY) / 2;
+                    }
                 } else if (newY < maxY && maxY - minY <= 0) {
                     // Overshoot beyond the bottom.  But don't wait for momentum phase to end before returning to bounds.
                     if (momentum && vData.atEnd) {
@@ -1073,9 +1078,13 @@ void QQuickFlickablePrivate::drag(qint64 currentTimestamp, QEvent::Type eventTyp
                         }
                         return;
                     }
-                    qreal overshoot = (newY - maxY) * vData.velocity / QML_FLICK_DEFAULTMAXVELOCITY / QML_FLICK_OVERSHOOTFRICTION;
-                    overshoot = QML_FLICK_OVERSHOOT * devicePixelRatio() * EaseOvershoot(overshoot / QML_FLICK_OVERSHOOT / devicePixelRatio());
-                    newY = maxY - overshoot;
+                    if (velocitySensitiveOverBounds) {
+                        qreal overshoot = (newY - maxY) * vData.velocity / QML_FLICK_DEFAULTMAXVELOCITY / QML_FLICK_OVERSHOOTFRICTION;
+                        overshoot = QML_FLICK_OVERSHOOT * devicePixelRatio() * EaseOvershoot(overshoot / QML_FLICK_OVERSHOOT / devicePixelRatio());
+                        newY = maxY - overshoot;
+                    } else {
+                        newY = maxY + (newY - maxY) / 2;
+                    }
                 }
             }
             if (!rejectY && stealMouse && dy != 0.0 && dy != vData.previousDragDelta) {
@@ -1126,9 +1135,13 @@ void QQuickFlickablePrivate::drag(qint64 currentTimestamp, QEvent::Type eventTyp
                         }
                         return;
                     }
-                    qreal overshoot = (newX - minX) * hData.velocity / QML_FLICK_DEFAULTMAXVELOCITY / QML_FLICK_OVERSHOOTFRICTION;
-                    overshoot = QML_FLICK_OVERSHOOT * devicePixelRatio() * EaseOvershoot(overshoot / QML_FLICK_OVERSHOOT / devicePixelRatio());
-                    newX = minX + overshoot;
+                    if (velocitySensitiveOverBounds) {
+                        qreal overshoot = (newX - minX) * hData.velocity / QML_FLICK_DEFAULTMAXVELOCITY / QML_FLICK_OVERSHOOTFRICTION;
+                        overshoot = QML_FLICK_OVERSHOOT * devicePixelRatio() * EaseOvershoot(overshoot / QML_FLICK_OVERSHOOT / devicePixelRatio());
+                        newX = minX + overshoot;
+                    } else {
+                        newX = minX + (newX - minX) / 2;
+                    }
                 } else if (newX < maxX && maxX - minX <= 0) {
                     // Overshoot beyond the right.  But don't wait for momentum phase to end before returning to bounds.
                     if (momentum && hData.atEnd) {
@@ -1138,9 +1151,13 @@ void QQuickFlickablePrivate::drag(qint64 currentTimestamp, QEvent::Type eventTyp
                         }
                         return;
                     }
-                    qreal overshoot = (newX - maxX) * hData.velocity / QML_FLICK_DEFAULTMAXVELOCITY / QML_FLICK_OVERSHOOTFRICTION;
-                    overshoot = QML_FLICK_OVERSHOOT * devicePixelRatio() * EaseOvershoot(overshoot / QML_FLICK_OVERSHOOT / devicePixelRatio());
-                    newX = maxX - overshoot;
+                    if (velocitySensitiveOverBounds) {
+                        qreal overshoot = (newX - maxX) * hData.velocity / QML_FLICK_DEFAULTMAXVELOCITY / QML_FLICK_OVERSHOOTFRICTION;
+                        overshoot = QML_FLICK_OVERSHOOT * devicePixelRatio() * EaseOvershoot(overshoot / QML_FLICK_OVERSHOOT / devicePixelRatio());
+                        newX = maxX - overshoot;
+                    } else {
+                        newX = maxX + (newX - maxX) / 2;
+                    }
                 }
             }
 
@@ -1210,7 +1227,7 @@ void QQuickFlickablePrivate::handleMouseMoveEvent(QMouseEvent *event)
     if (q->xflick())
         overThreshold |= QQuickWindowPrivate::dragOverThreshold(deltas.x(), Qt::XAxis, event);
 
-    drag(currentTimestamp, event->type(), event->localPos(), deltas, overThreshold, false, velocity);
+    drag(currentTimestamp, event->type(), event->localPos(), deltas, overThreshold, false, false, velocity);
 }
 
 void QQuickFlickablePrivate::handleMouseReleaseEvent(QMouseEvent *event)
@@ -1433,7 +1450,7 @@ void QQuickFlickable::wheelEvent(QWheelEvent *event)
         QVector2D velocity(xDelta / elapsed, yDelta / elapsed);
         d->lastPosTime = currentTimestamp;
         d->accumulatedWheelPixelDelta += QVector2D(event->pixelDelta());
-        d->drag(currentTimestamp, event->type(), event->posF(), d->accumulatedWheelPixelDelta, true, !d->scrollingPhase, velocity);
+        d->drag(currentTimestamp, event->type(), event->posF(), d->accumulatedWheelPixelDelta, true, !d->scrollingPhase, true, velocity);
     }
 
     if (!event->isAccepted())
index d7148ca57abb0b7f4a7c27dc848b17957819f130..65bb3e802d40d4dc3a294e30fa7239084acba76c 100644 (file)
@@ -250,7 +250,8 @@ public:
 
     void maybeBeginDrag(qint64 currentTimestamp, const QPointF &pressPosn);
     void drag(qint64 currentTimestamp, QEvent::Type eventType, const QPointF &localPos,
-              const QVector2D &deltas, bool overThreshold, bool momentum, const QVector2D &velocity);
+              const QVector2D &deltas, bool overThreshold, bool momentum,
+              bool velocitySensitiveOverBounds, const QVector2D &velocity);
 
     qint64 computeCurrentTime(QInputEvent *event);
     qreal devicePixelRatio();