From 0ac019111137b13788468ddb3c020302f1a25038 Mon Sep 17 00:00:00 2001 From: Alberto Mardegan Date: Sun, 18 Dec 2011 19:19:29 +0200 Subject: Fix QScroller diagonal scrolling Compute the time needed for the scrolling operation before computing the movement on the X and Y components. This ensures (except when overshooting or snapping to snap points) that the scrolling on the X and Y components takes the same time. That is, scrolling occurs always along a straight line. Task-number: QTBUG-23227 Change-Id: Ic3b78b8611dbcbf19711c3dd96485a0d53accaed Reviewed-by: Robin Burchell --- src/widgets/util/qscroller.cpp | 63 ++++++++++++++++++++++++++---------------- src/widgets/util/qscroller_p.h | 5 +++- 2 files changed, 43 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/widgets/util/qscroller.cpp b/src/widgets/util/qscroller.cpp index 4482134c7b..e39ed9c0a5 100644 --- a/src/widgets/util/qscroller.cpp +++ b/src/widgets/util/qscroller.cpp @@ -58,6 +58,7 @@ #include #include #include +#include #include #include #include @@ -1160,11 +1161,10 @@ void QScrollerPrivate::recalcScrollingSegments(bool forceRecalc) releaseVelocity = q->velocity(); - if (forceRecalc || !scrollingSegmentsValid(Qt::Horizontal)) - createScrollingSegments(releaseVelocity.x(), contentPosition.x() + overshootPosition.x(), ppm.x(), Qt::Horizontal); - - if (forceRecalc || !scrollingSegmentsValid(Qt::Vertical)) - createScrollingSegments(releaseVelocity.y(), contentPosition.y() + overshootPosition.y(), ppm.y(), Qt::Vertical); + if (forceRecalc || + !scrollingSegmentsValid(Qt::Horizontal) || + !scrollingSegmentsValid(Qt::Vertical)) + createScrollingSegments(releaseVelocity, contentPosition + overshootPosition, ppm); } /*! \internal @@ -1256,7 +1256,9 @@ void QScrollerPrivate::createScrollToSegments(qreal v, qreal deltaTime, qreal en /*! \internal */ -void QScrollerPrivate::createScrollingSegments(qreal v, qreal startPos, qreal ppm, Qt::Orientation orientation) +void QScrollerPrivate::createScrollingSegments(qreal v, qreal startPos, + qreal deltaTime, qreal deltaPos, + Qt::Orientation orientation) { const QScrollerPropertiesPrivate *sp = properties.d.data(); @@ -1287,22 +1289,6 @@ void QScrollerPrivate::createScrollingSegments(qreal v, qreal startPos, qreal pp qScrollerDebug() << "v = " << v << ", decelerationFactor = " << sp->decelerationFactor << ", curveType = " << sp->scrollingCurve.type(); - // This is only correct for QEasingCurve::OutQuad (linear velocity, - // constant deceleration), but the results look and feel ok for OutExpo - // and OutSine as well - - // v(t) = deltaTime * a * 0.5 * differentialForProgress(t / deltaTime) - // v(0) = vrelease - // v(deltaTime) = 0 - // deltaTime = (2 * vrelease) / (a * differntial(0)) - - // pos(t) = integrate(v(t)dt) - // pos(t) = vrelease * t - 0.5 * a * t * t - // pos(t) = deltaTime * a * 0.5 * progress(t / deltaTime) * deltaTime - // deltaPos = pos(deltaTime) - - qreal deltaTime = (qreal(2) * qAbs(v)) / (sp->decelerationFactor * differentialForProgress(sp->scrollingCurve, 0)); - qreal deltaPos = qSign(v) * deltaTime * deltaTime * qreal(0.5) * sp->decelerationFactor * ppm; qreal endPos = startPos + deltaPos; qScrollerDebug() << " Real Delta:" << deltaPos; @@ -1414,6 +1400,36 @@ void QScrollerPrivate::createScrollingSegments(qreal v, qreal startPos, qreal pp } +void QScrollerPrivate::createScrollingSegments(const QPointF &v, + const QPointF &startPos, + const QPointF &ppm) +{ + const QScrollerPropertiesPrivate *sp = properties.d.data(); + + // This is only correct for QEasingCurve::OutQuad (linear velocity, + // constant deceleration), but the results look and feel ok for OutExpo + // and OutSine as well + + // v(t) = deltaTime * a * 0.5 * differentialForProgress(t / deltaTime) + // v(0) = vrelease + // v(deltaTime) = 0 + // deltaTime = (2 * vrelease) / (a * differntial(0)) + + // pos(t) = integrate(v(t)dt) + // pos(t) = vrelease * t - 0.5 * a * t * t + // pos(t) = deltaTime * a * 0.5 * progress(t / deltaTime) * deltaTime + // deltaPos = pos(deltaTime) + + QVector2D vel(v); + qreal deltaTime = (qreal(2) * vel.length()) / (sp->decelerationFactor * differentialForProgress(sp->scrollingCurve, 0)); + QPointF deltaPos = (vel.normalized() * QVector2D(ppm)).toPointF() * deltaTime * deltaTime * qreal(0.5) * sp->decelerationFactor; + + createScrollingSegments(v.x(), startPos.x(), deltaTime, deltaPos.x(), + Qt::Horizontal); + createScrollingSegments(v.y(), startPos.y(), deltaTime, deltaPos.y(), + Qt::Vertical); +} + /*! \internal Prepares scrolling by sending a QScrollPrepareEvent to the receiver widget. Returns true if the scrolling was accepted and a target was returned. @@ -1650,8 +1666,7 @@ bool QScrollerPrivate::releaseWhileDragging(const QPointF &position, qint64 time } QPointF ppm = q->pixelPerMeter(); - createScrollingSegments(releaseVelocity.x(), contentPosition.x() + overshootPosition.x(), ppm.x(), Qt::Horizontal); - createScrollingSegments(releaseVelocity.y(), contentPosition.y() + overshootPosition.y(), ppm.y(), Qt::Vertical); + createScrollingSegments(releaseVelocity, contentPosition + overshootPosition, ppm); qScrollerDebug() << "QScroller::releaseWhileDragging() -- velocity:" << releaseVelocity << "-- minimum velocity:" << sp->minimumVelocity << "overshoot" << overshootPosition; diff --git a/src/widgets/util/qscroller_p.h b/src/widgets/util/qscroller_p.h index 6463f03573..26bd64461f 100644 --- a/src/widgets/util/qscroller_p.h +++ b/src/widgets/util/qscroller_p.h @@ -131,7 +131,10 @@ public: qreal scrollingSegmentsEndPos(Qt::Orientation orientation) const; bool scrollingSegmentsValid(Qt::Orientation orientation); void createScrollToSegments(qreal v, qreal deltaTime, qreal endPos, Qt::Orientation orientation, ScrollType type); - void createScrollingSegments(qreal v, qreal startPos, qreal ppm, Qt::Orientation orientation); + void createScrollingSegments(qreal v, qreal startPos, + qreal deltaTime, qreal deltaPos, + Qt::Orientation orientation); + void createScrollingSegments(const QPointF &v, const QPointF &startPos, const QPointF &ppm); void setContentPositionHelperDragging(const QPointF &deltaPos); void setContentPositionHelperScrolling(); -- cgit v1.2.3