summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRalf Engels <ralf.engels@nokia.com>2010-04-01 17:19:26 +0200
committerRalf Engels <ralf.engels@nokia.com>2010-04-01 17:19:26 +0200
commitf5cd7a76c3b73616afbd6d79bf5eff522ceb24c5 (patch)
tree1b52367497cf68b3acde85b1e8c6977e089c8f25
parent8eac27d4c572d1f23ad067ed8fa398488e24733b (diff)
Debugging
-rw-r--r--qkineticscroller.cpp81
-rw-r--r--qkineticscroller.h2
-rw-r--r--qscrollareakineticscroller.cpp27
3 files changed, 77 insertions, 33 deletions
diff --git a/qkineticscroller.cpp b/qkineticscroller.cpp
index ec46f08..005abb8 100644
--- a/qkineticscroller.cpp
+++ b/qkineticscroller.cpp
@@ -169,10 +169,10 @@ void QKineticScroller::resetScrollMetrics()
static QMap<ScrollMetric, QVariant> metrics;
#ifdef Q_WS_MAEMO_5
- metrics.insert(DragVelocitySmoothingFactor, qreal(0.85));
+ metrics.insert(DragVelocitySmoothingFactor, qreal(0.15));
metrics.insert(FrictionCoefficent, qreal(0.85));
metrics.insert(OvershootSpringConstant, qreal(0.1));
- metrics.insert(OvershootMaximumDistance, qreal(150));
+ metrics.insert(OvershootMaximumDistance, QPointF(qreal(150), qreal(150)));
metrics.insert(OvershootMaximumVelocity, qreal(2600));
metrics.insert(DragStartDistance, qreal(25));
metrics.insert(DragStartDirectionErrorMargin, qreal(10));
@@ -186,15 +186,16 @@ void QKineticScroller::resetScrollMetrics()
metrics.insert(FastSwipeMaximumTime, qreal(0.125));
metrics.insert(FramesPerSecond, qreal(20));
#else
- metrics.insert(DragVelocitySmoothingFactor, qreal(0.85));
- metrics.insert(FrictionCoefficent, qreal(0.95));
- metrics.insert(OvershootSpringConstant, qreal(0.1));
- metrics.insert(OvershootMaximumDistance, qreal(14.25 / 1000));
+ metrics.insert(DragVelocitySmoothingFactor, qreal(0.02));
+ metrics.insert(FrictionCoefficent, qreal(0.05));
+ metrics.insert(OvershootSpringConstant, qreal(2.0));
+ metrics.insert(OvershootMaximumDistance, QPointF(qreal(14.25 / 1000), qreal(14.25 / 1000)));
metrics.insert(OvershootMaximumVelocity, qreal(247.0 / 1000));
metrics.insert(DragStartDistance, qreal(2.5 / 1000));
metrics.insert(DragStartDirectionErrorMargin, qreal(1.0 / 1000));
metrics.insert(MaximumVelocity, qreal(6650.0 / 1000));
- metrics.insert(MinimumVelocity, qreal(19.0 / 1000));
+ metrics.insert(MaximumVelocity, qreal(6650.0 / 1000));
+ metrics.insert(MinimumVelocity, qreal(30.0 / 1000));
metrics.insert(MaximumNonAcceleratedVelocity, qreal(532.0 / 1000));
metrics.insert(MaximumClickThroughVelocity, qreal(66.5 / 1000));
metrics.insert(AxisLockThreshold, qreal(0));
@@ -281,6 +282,8 @@ bool QKineticScroller::handleInput(Input input, const QPointF &position, qint64
{
Q_D(QKineticScroller);
+
+qKSDebug() << __PRETTY_FUNCTION__ << input << "pos: " << position << "timestamp: " << timestamp;
struct statechange {
State state;
Input input;
@@ -441,13 +444,18 @@ void QKineticScrollerPrivate::updateVelocity(const QPointF &deltaPixelRaw, qint6
if (((deltaPixelRaw / qreal(deltaTime)).manhattanLength() / pixelPerMeter * 1000) > qreal(2.5))
deltaPixel = deltaPixelRaw * qreal(2.5) * pixelPerMeter / 1000 / (deltaPixelRaw / qreal(deltaTime)).manhattanLength();
- QPointF newv = -deltaPixel / qreal(deltaTime) * 1000 / pixelPerMeter;
- newv = newv * dragVelocitySmoothingFactor + velocity * (qreal(1) - dragVelocitySmoothingFactor);
+ qreal inversSmoothingFactor = ((qreal(1) - dragVelocitySmoothingFactor) * qreal(deltaTime) / qreal(1000));
+ QPointF newv = -deltaPixel / qreal(deltaTime) * qreal(1000) / pixelPerMeter;
+ newv = newv * (qreal(1) - inversSmoothingFactor) + velocity * inversSmoothingFactor;
+
+ // newv = newv * dragVelocitySmoothingFactor + velocity * (qreal(1) - dragVelocitySmoothingFactor);
if (deltaPixel.x())
velocity.setX(qBound(-maximumVelocity, newv.x(), maximumVelocity));
if (deltaPixel.y())
velocity.setY(qBound(-maximumVelocity, newv.y(), maximumVelocity));
+
+ qKSDebug() << "resulting new velocity:" << velocity;
}
@@ -549,7 +557,10 @@ bool QKineticScrollerPrivate::pressWhileInactive(QKineticScroller::Input, const
bool QKineticScrollerPrivate::releaseWhilePressed(QKineticScroller::Input, const QPointF &, qint64)
{
- setState(QKineticScroller::StateInactive);
+ if (!overshootDistance.isNull())
+ setState(QKineticScroller::StateScrolling);
+ else
+ setState(QKineticScroller::StateInactive);
return false;
}
@@ -608,7 +619,7 @@ void QKineticScrollerPrivate::timerEventWhileDragging(qint64)
Q_Q(QKineticScroller);
if (!dragDistance.isNull()) {
- setContentPositionHelper(q->contentPosition() - overshootDistance - dragDistance);
+ setContentPositionHelper(q->contentPosition() + overshootDistance - dragDistance);
dragDistance = QPointF(0, 0);
}
}
@@ -654,7 +665,11 @@ bool QKineticScrollerPrivate::releaseWhileDragging(QKineticScroller::Input, cons
}
- if (!overshootDistance.isNull() || velocity >= minimumVelocity)
+ qKSDebug() << "release While dragging, velocity: "<<velocity<<"minimum velocity"<<minimumVelocity;
+ if (!overshootDistance.isNull()) {
+ velocity = QPointF(0, 0);
+ setState(QKineticScroller::StateScrolling);
+ } else if (velocity >= minimumVelocity)
setState(QKineticScroller::StateScrolling);
else
setState(QKineticScroller::StateInactive);
@@ -671,6 +686,8 @@ void QKineticScrollerPrivate::timerEventWhileScrolling(qint64 time)
// calculate the new overshoot distance (convert from [m/s] to [pixel/frame]
QPointF newOvershootDistance = overshootDistance + velocity * qreal(time) / 1000 * pixelPerMeter;
+ qKSDebug() << "Overshooting, old: "<<overshootDistance<<"new:"<<newOvershootDistance;
+
// -- check if we going back. Then stop
if (overshootDistance.x() && ((overshootDistance.x() > 0) != (newOvershootDistance.x() > 0))) {
overshootDistance.setX(0);
@@ -685,9 +702,11 @@ void QKineticScrollerPrivate::timerEventWhileScrolling(qint64 time)
}
// -- move (convert from [m/s] to [pix/frame]
- setContentPositionHelper(q->contentPosition() - overshootDistance + velocity * qreal(time) / 1000 * pixelPerMeter);
+ setContentPositionHelper(q->contentPosition() + overshootDistance + velocity * qreal(time) / 1000 * pixelPerMeter);
+
// --- (de)accelerate overshooting axis using spring constant or friction
+ // actually we would need to calculate a root and not just divide
qreal forcePerFrame = overshootSpringConstant * qreal(time) / 1000;
qreal frictionPerFrame = (qreal(1) - ((qreal(1) - frictionCoefficent) * qreal(time) / 1000));
@@ -695,7 +714,7 @@ void QKineticScrollerPrivate::timerEventWhileScrolling(qint64 time)
// -- x coordinate
if (overshootDistance.x()) {
- velocity.rx() += forcePerFrame * overshootDistance.x() / pixelPerMeter;
+ velocity.rx() -= forcePerFrame * overshootDistance.x() / pixelPerMeter;
velocity.setX(qBound(-overshootMaximumVelocity, velocity.x(), overshootMaximumVelocity));
} else if (scrollToX) {
@@ -715,7 +734,7 @@ void QKineticScrollerPrivate::timerEventWhileScrolling(qint64 time)
// -- y coordinate
if (overshootDistance.y()) {
- velocity.ry() += forcePerFrame * overshootDistance.y() / pixelPerMeter;
+ velocity.ry() -= forcePerFrame * overshootDistance.y() / pixelPerMeter;
velocity.setY(qBound(-overshootMaximumVelocity, velocity.y(), overshootMaximumVelocity));
} else if (scrollToY) {
@@ -752,7 +771,7 @@ void QKineticScrollerPrivate::setState(QKineticScroller::State newstate)
if (state == newstate)
return;
- qWarning() << "Switiching to state " << stateName(newstate);
+ qWarning() << "Switching to state " << stateName(newstate);
switch (newstate) {
case QKineticScroller::StateInactive:
@@ -768,6 +787,10 @@ void QKineticScrollerPrivate::setState(QKineticScroller::State newstate)
break;
case QKineticScroller::StatePressed:
+ if (timerId) {
+ killTimer(timerId);
+ timerId = 0;
+ }
velocity = QPointF(0, 0);
break;
@@ -784,6 +807,11 @@ void QKineticScrollerPrivate::setState(QKineticScroller::State newstate)
break;
case QKineticScroller::StateScrolling:
+ if (state == QKineticScroller::StatePressed) {
+ if (!timerId) {
+ timerId = startTimer(1000 / framesPerSecond);
+ }
+ }
scrollTimer.start();
break;
}
@@ -886,18 +914,29 @@ void QKineticScrollerPrivate::setContentPositionHelper(const QPointF &pos)
clampedPos.setY(qBound(qreal(0), pos.y(), maxPos.y()));
bool alwaysOvershoot = (overshootPolicy == QKineticScroller::OvershootAlwaysOn);
- qreal overshootX = (maxPos.x() || alwaysOvershoot) ? clampedPos.x() - pos.x() : 0;
- qreal overshootY = (maxPos.y() || alwaysOvershoot) ? clampedPos.y() - pos.y() : 0;
+ qreal overshootX = (maxPos.x() || alwaysOvershoot) ? pos.x() - clampedPos.x() : 0;
+ qreal overshootY = (maxPos.y() || alwaysOvershoot) ? pos.y() - clampedPos.y() : 0;
+ // -- stop at the maximum overshoot distance (if set)
if (!overshootMaximumDistance.isNull()) {
- overshootDistance.setX(qBound(-overshootMaximumDistance.x(), overshootX, overshootMaximumDistance.x()));
- overshootDistance.setY(qBound(-overshootMaximumDistance.y(), overshootY, overshootMaximumDistance.y()));
+
+ qreal x = qBound(-overshootMaximumDistance.x() * pixelPerMeter, overshootX, overshootMaximumDistance.x() * pixelPerMeter);
+ if (x != overshootX)
+ velocity.setX(0);
+ overshootDistance.setX(x);
+
+ qKSDebug() << "Overshoot y: "<<(overshootMaximumDistance.y() * pixelPerMeter)<<"distance: "<<overshootY;
+ qreal y = qBound(-overshootMaximumDistance.y() * pixelPerMeter, overshootY, overshootMaximumDistance.y() * pixelPerMeter);
+ if (y != overshootY)
+ velocity.setY(0);
+ overshootDistance.setY(y);
+
} else {
overshootDistance = QPointF(overshootX, overshootY);
}
qKSDebug() << "setPosition raw: " << pos << ", clamped: " << clampedPos << ", overshoot: " << overshootDistance;
- q->setContentPosition(clampedPos, overshootPolicy == QKineticScroller::OvershootAlwaysOff ? QPoint() : overshootDistance);
+ q->setContentPosition(clampedPos, overshootPolicy == QKineticScroller::OvershootAlwaysOff ? QPointF() : overshootDistance);
}
diff --git a/qkineticscroller.h b/qkineticscroller.h
index 34fb175..8e9336c 100644
--- a/qkineticscroller.h
+++ b/qkineticscroller.h
@@ -86,7 +86,7 @@ public:
enum ScrollMetric
{
- DragVelocitySmoothingFactor, // qreal [0..1] v = v_new* DASF + v_old * (1-DASF)
+ DragVelocitySmoothingFactor, // qreal [0..1/s] (complex calculation involving time) v = v_new* DASF + v_old * (1-DASF)
FrictionCoefficent, // qreal [0..1]
OvershootSpringConstant, // qreal [0..1]
OvershootMaximumDistance, // QPointF([m], [m])
diff --git a/qscrollareakineticscroller.cpp b/qscrollareakineticscroller.cpp
index 3b9c980..7b28dee 100644
--- a/qscrollareakineticscroller.cpp
+++ b/qscrollareakineticscroller.cpp
@@ -76,7 +76,7 @@ public:
QAbstractScrollArea *area;
QItemSelection oldSelection; // the selection before the first mouse down
bool ignoreEvents;
- QPointF lastOvershoot;
+ QPoint lastOvershoot; // don't change the type to QPointF or we might never shoot completely back.
QPointer<QWidget> childWidget; // the widget where the mouse was pressed
QElapsedTimer timer;
@@ -136,11 +136,15 @@ void QScrollAreaKineticScroller::setWidget(QAbstractScrollArea *widget)
{
Q_D(QScrollAreaKineticScroller);
- if (d->area)
+ if (d->area) {
d->area->viewport()->removeEventFilter(this);
- // todo: move back overshoot
+ d->area->viewport()->move(d->area->viewport()->pos() + d->lastOvershoot );
+ }
+
reset();
d->area = widget;
+ d->lastOvershoot = QPoint();
+
setParent(d->area);
if (d->area) {
d->area->viewport()->installEventFilter(this);
@@ -149,7 +153,6 @@ void QScrollAreaKineticScroller::setWidget(QAbstractScrollArea *widget)
view->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
}
}
- d->lastOvershoot = QPointF();
}
bool QScrollAreaKineticScroller::eventFilter(QObject *o, QEvent *e)
@@ -172,7 +175,7 @@ bool QScrollAreaKineticScroller::eventFilter(QObject *o, QEvent *e)
// fall through
QMouseEvent *me = static_cast<QMouseEvent *>(e);
isMouseEvent = true;
- res = handleInput(InputPress, me->posF(), timestamp);
+ res = handleInput(InputPress, me->posF() - d->lastOvershoot, timestamp);
break;
}
case QEvent::MouseButtonDblClick: {
@@ -180,21 +183,22 @@ bool QScrollAreaKineticScroller::eventFilter(QObject *o, QEvent *e)
// fall through
QMouseEvent *me = static_cast<QMouseEvent *>(e);
isMouseEvent = true;
- res = handleInput(InputPress, me->pos(), timestamp);
+ res = handleInput(InputPress, me->posF() - d->lastOvershoot, timestamp);
break;
}
case QEvent::MouseMove: {
QMouseEvent *me = static_cast<QMouseEvent *>(e);
isMouseEvent = true;
- res = handleInput(InputMove, me->posF(), timestamp);
+ res = handleInput(InputMove, me->posF() - d->lastOvershoot, timestamp);
break;
}
case QEvent::MouseButtonRelease: {
QMouseEvent *me = static_cast<QMouseEvent *>(e);
isMouseEvent = true;
- res = handleInput(InputRelease, me->pos(), timestamp);
+ res = handleInput(InputRelease, me->posF() - d->lastOvershoot, timestamp);
break;
}
+
case QEvent::ChildAdded:
case QEvent::ChildRemoved: {
QChildEvent *ce = static_cast<QChildEvent *>(e);
@@ -256,6 +260,7 @@ bool QScrollAreaKineticScroller::canStartScrollingAt(const QPointF &pos) const
if (childItem && (childItem->flags() & QGraphicsItem::ItemIsMovable))
return false;
}
+
// don't start scrolling on a QSlider
if (qobject_cast<QSlider *>(d->mouseTransparentChildAtGlobalPos(d->area->viewport(), d->area->viewport()->mapToGlobal(pos.toPoint())))) {
return false;
@@ -336,10 +341,10 @@ void QScrollAreaKineticScroller::setContentPosition(const QPointF &p, const QPoi
if (QScrollBar *s = d->area->verticalScrollBar())
s->setValue(p.y());
- QPointF delta = overshootDelta - d->lastOvershoot;
+ QPoint delta = d->lastOvershoot - overshootDelta.toPoint();
if (!delta.isNull())
- d->area->viewport()->move(d->area->viewport()->pos() + delta.toPoint());
- d->lastOvershoot = overshootDelta;
+ d->area->viewport()->move(d->area->viewport()->pos() + delta);
+ d->lastOvershoot -= delta;
}
}