From 536b3fb03ace6d49697d0cda19368133672de778 Mon Sep 17 00:00:00 2001 From: Ralf Engels Date: Wed, 26 May 2010 16:39:59 +0200 Subject: Using scrollevents --- scroller/qflickgesture.cpp | 21 ++++-- scroller/qkineticscroller.cpp | 161 +++++++++++++----------------------------- scroller/qkineticscroller.h | 12 +--- scroller/qkineticscroller_p.h | 16 ++++- testapp/main.cpp | 15 ++-- testapp/settingswidget.cpp | 6 ++ testapp/testapp.pro | 4 +- 7 files changed, 99 insertions(+), 136 deletions(-) diff --git a/scroller/qflickgesture.cpp b/scroller/qflickgesture.cpp index 1feb050..a1eef75 100644 --- a/scroller/qflickgesture.cpp +++ b/scroller/qflickgesture.cpp @@ -48,7 +48,6 @@ QT_BEGIN_NAMESPACE - class QFlickGesturePrivate { public: @@ -58,11 +57,21 @@ public: QKineticScroller *scroller() { - if (!target || !target->parent()) + // qDebug() << "QKineticScroller::scroller"<parent(); + QKineticScroller *res = 0; + + if (!target) + return 0; + + res = target->property("kineticScroller").value(); + if (res) + return res; + + if (!target->parent()) return 0; - QKineticScroller *s = target->parent()->property("kineticScroller").value(); - return s; + res = target->parent()->property("kineticScroller").value(); + return res; } QPointer target; @@ -83,6 +92,7 @@ QFlickGestureRecognizer::QFlickGestureRecognizer() QGesture *QFlickGestureRecognizer::create(QObject *target) { + qDebug() << "Recognizer::create for"<isWidgetType():false); if (target && target->isWidgetType()) { QWidget *widget = static_cast(target); #if defined(Q_OS_WIN) && !defined(QT_NO_NATIVE_GESTURES) @@ -105,6 +115,7 @@ QGestureRecognizer::Result QFlickGestureRecognizer::recognize(QGesture *state, QFlickGesturePrivate *d = q->d; QKineticScroller *scroller = d->scroller(); + // qDebug() << "QFlickGestureRecognizer::recognize for"<(state); - /* flick->d->target = 0; flick->d->timer.start(); - */ QGestureRecognizer::reset(state); } diff --git a/scroller/qkineticscroller.cpp b/scroller/qkineticscroller.cpp index b835efc..75556a4 100644 --- a/scroller/qkineticscroller.cpp +++ b/scroller/qkineticscroller.cpp @@ -44,11 +44,14 @@ #include #include #include +#include #include QT_BEGIN_NAMESPACE +bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event); + #define KINETIC_SCROLLER_DEBUG #ifdef KINETIC_SCROLLER_DEBUG @@ -141,22 +144,24 @@ inline int qSign(qreal r) /*! Constructs a new kinetic scroller. */ -QKineticScroller::QKineticScroller() +QKineticScroller::QKineticScroller(QObject *receiver) : d_ptr(new QKineticScrollerPrivate()) { Q_D(QKineticScroller); d->q_ptr = this; d->init(); + d->receiver = receiver; } /*! \internal */ -QKineticScroller::QKineticScroller(QKineticScrollerPrivate &dd) +QKineticScroller::QKineticScroller(QObject *receiver, QKineticScrollerPrivate &dd) : d_ptr(&dd) { Q_D(QKineticScroller); d->q_ptr = this; d->init(); + d->receiver = receiver; } /*! @@ -190,7 +195,7 @@ QKineticScrollerPrivate::QKineticScrollerPrivate() , scrollToY(false) , overshootX(false) , overshootY(false) - , cancelPress(false) + , firstScroll(false) , debugHook(0) , debugHookUser(0) { } @@ -205,6 +210,11 @@ void QKineticScrollerPrivate::init() q->resetScrollMetrics(); } +void QKineticScrollerPrivate::sendEvent(QObject *o, QEvent *e) +{ + qt_sendSpontaneousEvent(o, e); +} + void QKineticScroller::registerDebugHook(void (*callback)(void *user, const QPointF &releaseVelocity, const QPointF &position, const QPointF &overshootPosition), void *user) { Q_D(QKineticScroller); @@ -589,8 +599,6 @@ QPointF QKineticScrollerPrivate::calculateVelocity(qreal time) void QKineticScrollerPrivate::handleDrag(const QPointF &position, qint64 timestamp) { - Q_Q(QKineticScroller); - QPointF deltaPixel = position - lastPosition; qint64 deltaTime = timestamp - lastTimestamp; @@ -614,7 +622,7 @@ void QKineticScrollerPrivate::handleDrag(const QPointF &position, qint64 timesta updateVelocity(deltaPixel, deltaTime); // restrict velocity, if content is not scrollable - QPointF maxPos = q->maximumContentPosition(); + QPointF maxPos = maximumContentPosition; bool canScrollX = maxPos.x() || (hOvershootPolicy == QKineticScroller::OvershootAlwaysOn); bool canScrollY = maxPos.y() || (vOvershootPolicy == QKineticScroller::OvershootAlwaysOn); @@ -646,15 +654,24 @@ void QKineticScrollerPrivate::handleDrag(const QPointF &position, qint64 timesta bool QKineticScrollerPrivate::pressWhileInactive(QKineticScroller::Input, const QPointF &position, qint64 timestamp) { - Q_Q(QKineticScroller); + QScrollPrepareEvent spe(position); + qDebug() << "Sending prepare event to "< qreal(0)) || + (hOvershootPolicy == QKineticScroller::OvershootAlwaysOn) || + (vOvershootPolicy == QKineticScroller::OvershootAlwaysOn)) { - if ((q->maximumContentPosition() > qreal(0)) || - (hOvershootPolicy == QKineticScroller::OvershootAlwaysOn) || - (vOvershootPolicy == QKineticScroller::OvershootAlwaysOn)) { - if (q->canStartScrollingAt(position)) { lastPosition = pressPosition = position; lastTimestamp = pressTimestamp = timestamp; - cancelPress = true; + firstScroll = true; setState(QKineticScroller::StatePressed); } } @@ -682,7 +699,7 @@ bool QKineticScrollerPrivate::moveWhilePressed(QKineticScroller::Input, const QP qreal deltaXtoY = qAbs(pressPosition.x() - position.x()) - qAbs(pressPosition.y() - position.y()); deltaXtoY /= pixelPerMeter; - QPointF maxPos = q->maximumContentPosition(); + QPointF maxPos = maximumContentPosition; bool canScrollX = (maxPos.x() > 0); bool canScrollY = (maxPos.y() > 0); @@ -701,8 +718,6 @@ bool QKineticScrollerPrivate::moveWhilePressed(QKineticScroller::Input, const QP } if (moveStarted) { - if (cancelPress) - q->cancelPress(pressPosition); setState(QKineticScroller::StateDragging); // subtract the dragStartDistance @@ -735,12 +750,10 @@ void QKineticScrollerPrivate::timerEventWhileDragging() bool QKineticScrollerPrivate::releaseWhileDragging(QKineticScroller::Input, const QPointF &, qint64 timestamp) { - Q_Q(QKineticScroller); - // calculate the fastSwipe velocity - QPointF maxPos = q->maximumContentPosition(); + QPointF maxPos = maximumContentPosition; QPointF fastSwipeVelocity = QPoint(0, 0); - QSizeF size = q->viewportSize(); + QSizeF size = viewportSize; if (size.width()) fastSwipeVelocity.setX(qMin(maximumVelocity, maxPos.x() / size.width() * fastSwipeBaseVelocity)); if (size.height()) @@ -811,7 +824,6 @@ bool QKineticScrollerPrivate::pressWhileScrolling(QKineticScroller::Input, const { lastPosition = pressPosition = position; lastTimestamp = pressTimestamp = timestamp; - cancelPress = false; setState(QKineticScroller::StatePressed); return true; } @@ -893,7 +905,7 @@ void QKineticScrollerPrivate::setState(QKineticScroller::State newstate) be reached after a platform-defined time span (1 second for Maemo 5). The final speed at the end position is not guaranteed to be zero. - \sa ensureVisible(), maximumContentPosition() + \sa ensureVisible() */ void QKineticScroller::scrollTo(const QPointF &pos, int scrollTime) { @@ -906,7 +918,7 @@ void QKineticScroller::scrollTo(const QPointF &pos, int scrollTime) qreal time = qreal(scrollTime) / 1000; - if ((pos == contentPosition()) || + if ((pos == d->contentPosition) || (d->state == QKineticScroller::StatePressed) || (d->state == QKineticScroller::StateDragging)) { return; @@ -933,10 +945,10 @@ void QKineticScroller::scrollTo(const QPointF &pos, int scrollTime) // vstart = ((lDF / 2) * time ^ 2 + (pos - contentPos())) / (eDB ^ time / ln(eDB) + C) // (for C = -1/ln(eDB) ) - QPointF scrollDir(qSign(pos.x() - contentPosition().x()), - qSign(pos.y() - contentPosition().y())); + QPointF scrollDir(qSign(pos.x() - d->contentPosition.x()), + qSign(pos.y() - d->contentPosition.y())); - QPointF v = (scrollDir * (d->linearDecelerationFactor / qreal(2)) * qreal(time) * qreal(time) + (pos - contentPosition()) / d->pixelPerMeter); + QPointF v = (scrollDir * (d->linearDecelerationFactor / qreal(2)) * qreal(time) * qreal(time) + (pos - d->contentPosition) / d->pixelPerMeter); if (d->exponentialDecelerationBase != qreal(1)) v /= (qPow(d->exponentialDecelerationBase, time) - 1) / qLn(d->exponentialDecelerationBase); else @@ -959,16 +971,16 @@ void QKineticScroller::scrollTo(const QPointF &pos, int scrollTime) nearest valid position. The default value for both margins is 50 pixels. This function performs the actual scrolling by calling scrollTo(). - - \sa maximumContentPosition() */ void QKineticScroller::ensureVisible(const QPointF &pos, int xmargin, int ymargin, int scrollTime) { - QSizeF visible = viewportSize(); - QPointF currentPos = contentPosition(); + Q_D(QKineticScroller); + + QSizeF visible = d->viewportSize; + QPointF currentPos = d->contentPosition; qKSDebug() << "QKS::ensureVisible(" << pos << " [pix], " << xmargin << " [pix], " << ymargin << " [pix], " << scrollTime << "[ms])"; - qKSDebug() << " --> content position:" << contentPosition(); + qKSDebug() << " --> content position:" << d->contentPosition; QRectF posRect(pos.x() - xmargin, pos.y() - ymargin, 2 * xmargin, 2 * ymargin); QRectF visibleRect(currentPos, visible); @@ -1004,14 +1016,12 @@ void QKineticScroller::ensureVisible(const QPointF &pos, int xmargin, int ymargi */ void QKineticScrollerPrivate::setContentPositionHelper(const QPointF &deltaPos) { - Q_Q(QKineticScroller); - if (state == QKineticScroller::StateDragging && overshootDragResistanceFactor) overshootPosition /= overshootDragResistanceFactor; - QPointF oldPos = q->contentPosition() + overshootPosition; + QPointF oldPos = contentPosition + overshootPosition; QPointF newPos = oldPos + deltaPos; - QPointF maxPos = q->maximumContentPosition(); + QPointF maxPos = maximumContentPosition; QPointF oldScrollToDist = scrollToPosition - oldPos; QPointF newScrollToDist = scrollToPosition - newPos; @@ -1130,7 +1140,12 @@ void QKineticScrollerPrivate::setContentPositionHelper(const QPointF &deltaPos) overshootPosition.setX(newOvershootX); overshootPosition.setY(newOvershootY); - q->setContentPosition(newClampedPos, overshootPosition); + if( target ) { + QScrollEvent se(newClampedPos, overshootPosition, firstScroll); + sendEvent(target, &se); + firstScroll = false; + } + contentPosition = newClampedPos; if (debugHook) debugHook(debugHookUser, calculateVelocity(qreal(scrollAbsoluteTimer.elapsed()) / 1000), newClampedPos, overshootPosition); @@ -1152,38 +1167,6 @@ void QKineticScrollerPrivate::setContentPositionHelper(const QPointF &deltaPos) \value OvershootAlwaysOn Overshooting is always enabled (even when the content is not scrollable). */ - -/*! - If kinetic scrolling can be started at the given content's \a position, - this function needs to return true; otherwise it needs to return false. - - The default value is true, regardless of \a position. -*/ -bool QKineticScroller::canStartScrollingAt(const QPointF &position) const -{ - Q_UNUSED(position); - return true; -} - -/*! - Since a mouse press is always delivered normally when the scroller is in - the StateInactive state, we may need to cancel it as soon as the user - has moved the mouse far enough to actually start a kinetic scroll - operation. - - The \a pressPosition parameter can be used to find out which widget (or - graphics item) received the mouse press in the first place. - - Subclasses may choose to simulate a fake mouse release event for that - widget (or graphics item), preferably \bold not within its boundaries. - The default implementation does nothing. -*/ -void QKineticScroller::cancelPress(const QPointF &pressPosition) -{ - Q_UNUSED(pressPosition); -} - - /*! This function get called whenever the state of the kinetic scroller changes. The old state is supplied as \a oldState, while the new state is returned by @@ -1198,48 +1181,4 @@ void QKineticScroller::stateChanged(State oldState) Q_UNUSED(oldState); } -/*! - \fn QPointF QKineticScroller::maximumContentPosition() const - - Returns the maximum valid content position. The minimum is always \c - (0,0). - - \sa scrollTo() -*/ - -/*! - \fn QSizeF QKineticScroller::viewportSize() const - - Returns the size of the currently visible content positions. In the - case where an QAbstractScrollArea is used, this is equivalent to the - viewport() size. - - \sa scrollTo() -*/ - -/*! - \fn QPointF QKineticScroller::contentPosition() const - - \brief Returns the current position of the content. - - Note that overshooting is not considered to be "real" scrolling so the - position might be (0,0) even if the user is currently dragging the - widget outside the "normal" maximumContentPosition(). - - \sa maximumContentPosition() -*/ - - -/*! - \fn void QKineticScroller::setContentPosition(const QPointF &position, const QPointF &overshoot) - - Set the content's \a position. This parameter will always be in the - valid range QPointF(0, 0) and maximumContentPosition(). - - In the case where overshooting is required, the \a overshoot parameter - will give the direction and the absolute distance to overshoot. - - \sa maximumContentPosition() -*/ - QT_END_NAMESPACE diff --git a/scroller/qkineticscroller.h b/scroller/qkineticscroller.h index 56bf733..610eb2f 100644 --- a/scroller/qkineticscroller.h +++ b/scroller/qkineticscroller.h @@ -59,6 +59,7 @@ class QKineticScrollerPrivate; class QKineticScroller { public: + explicit QKineticScroller(QObject *receiver); virtual ~QKineticScroller(); bool isEnabled() const; @@ -130,16 +131,7 @@ public: void registerDebugHook(void (*callback)(void *user, const QPointF &releaseVelocity, const QPointF &position, const QPointF &overshootPosition), void *user); protected: - explicit QKineticScroller(); - - virtual QSizeF viewportSize() const = 0; - virtual QPointF maximumContentPosition() const = 0; - virtual QPointF contentPosition() const = 0; - virtual void setContentPosition(const QPointF &pos, const QPointF &overshootDelta) = 0; - virtual void stateChanged(State oldState); - virtual bool canStartScrollingAt(const QPointF &pos) const; - virtual void cancelPress(const QPointF &pressPos); enum Input { InputPress, @@ -149,7 +141,7 @@ protected: bool handleInput(Input input, const QPointF &position, qint64 timestamp); - QKineticScroller(QKineticScrollerPrivate &dd); + QKineticScroller(QObject *receiver, QKineticScrollerPrivate &dd); QScopedPointer d_ptr; private: diff --git a/scroller/qkineticscroller_p.h b/scroller/qkineticscroller_p.h index 6036beb..0f5e030 100644 --- a/scroller/qkineticscroller_p.h +++ b/scroller/qkineticscroller_p.h @@ -54,7 +54,6 @@ #include #include #include -#include #if QT_VERSION < 0x040700 # include #else @@ -63,6 +62,9 @@ QT_BEGIN_NAMESPACE +class QEvent; +class QTimerEvent; + class QKineticScrollerPrivate : public QObject { Q_OBJECT @@ -73,6 +75,8 @@ public: virtual ~QKineticScrollerPrivate(); void init(); + void sendEvent(QObject *o, QEvent *e); + void setState(QKineticScroller::State s); bool pressWhileInactive(QKineticScroller::Input input, const QPointF &position, qint64 timestamp); @@ -119,6 +123,14 @@ public: qreal fastSwipeMaximumTime; int framesPerSecond; + // widget info + QPointer receiver; // the object this scroller was registered for + + QPointer target; + QSizeF viewportSize; + QPointF maximumContentPosition; + QPointF contentPosition; + // state bool enabled; @@ -157,7 +169,7 @@ public: qreal overshootStartTimeY; int timerId; - bool cancelPress; + bool firstScroll; void (*debugHook)(void *user, const QPointF &releaseVelocity, const QPointF &position, const QPointF &overshootPosition); void *debugHookUser; diff --git a/testapp/main.cpp b/testapp/main.cpp index c08c745..3dd4e1e 100644 --- a/testapp/main.cpp +++ b/testapp/main.cpp @@ -16,6 +16,7 @@ #endif #include "qscrollareakineticscroller.h" +#include #include "qwebviewkineticscroller.h" #include "settingswidget.h" @@ -120,6 +121,12 @@ private: QKineticScroller *installKineticScroller(QWidget *w) { + static Qt::GestureType gestureType = (Qt::GestureType)0; + // need to register the gesture type + if( !gestureType ) { + gestureType = QGestureRecognizer::registerRecognizer( new QFlickGestureRecognizer() ); + } + #if defined(Q_WS_MAEMO_5) // remove the old kinetic scroller if any QAbstractKineticScroller *oldScroller = w->property("kineticScroller").value(); @@ -127,13 +134,13 @@ private: #endif // set a new kinetic scroller if (QAbstractScrollArea *area = qobject_cast(w)) { - QScrollAreaKineticScroller *newScroller = new QScrollAreaKineticScroller(); - newScroller->setWidget(area); + area->viewport()->grabGesture(gestureType); + QKineticScroller *newScroller = new QKineticScroller(area); w->setProperty("kineticScroller", QVariant::fromValue(static_cast(newScroller)) ); return newScroller; } else if (QWebView *web = qobject_cast(w)) { - QWebViewKineticScroller *newScroller = new QWebViewKineticScroller(); - newScroller->setWidget(web); + web->grabGesture(gestureType); + QKineticScroller *newScroller = new QKineticScroller(web); w->setProperty("kineticScroller", QVariant::fromValue(static_cast(newScroller)) ); return newScroller; } else { diff --git a/testapp/settingswidget.cpp b/testapp/settingswidget.cpp index e0f5b95..30f1d90 100644 --- a/testapp/settingswidget.cpp +++ b/testapp/settingswidget.cpp @@ -265,8 +265,10 @@ void SettingsWidget::addToGrid(QGridLayout *grid, QWidget *label, int widgetCoun class HackScroller : public QKineticScroller { public: + /* using QKineticScroller::viewportSize; using QKineticScroller::maximumContentPosition; + */ }; class HackSpinBox : public QSpinBox { @@ -384,8 +386,12 @@ void SettingsWidget::setKineticScroller(QKineticScroller *scroller) m_vospolicy->setCurrentIndex(m_vospolicy->findData(m_scroller->verticalOvershootPolicy())); + /* QSizeF vp = static_cast(m_scroller)->viewportSize(); QPointF maxc = static_cast(m_scroller)->maximumContentPosition(); + */ + QSizeF vp(200, 200); + QPointF maxc(100, 1000); m_scrollx->setRange(int(-vp.width()), int(maxc.x() + vp.width())); m_scrolly->setRange(int(-vp.height()), int(maxc.y() + vp.height())); diff --git a/testapp/testapp.pro b/testapp/testapp.pro index 8f9d20a..585fd4c 100644 --- a/testapp/testapp.pro +++ b/testapp/testapp.pro @@ -15,10 +15,8 @@ win32:PRE_TARGETDEPS += ../scroller/scroller.lib QT += webkit network # Input -HEADERS += plotwidget.h qscrollareakineticscroller.h qwebviewkineticscroller.h settingswidget.h +HEADERS += plotwidget.h settingswidget.h SOURCES += main.cpp \ plotwidget.cpp \ - qscrollareakineticscroller.cpp \ - qwebviewkineticscroller.cpp \ settingswidget.cpp macx:LIBS += -frameworks Cocoa -- cgit v1.2.3