summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRalf Engels <ralf.engels@nokia.com>2010-05-26 16:39:59 +0200
committerRalf Engels <ralf.engels@nokia.com>2010-05-26 16:39:59 +0200
commit536b3fb03ace6d49697d0cda19368133672de778 (patch)
tree611f7fd181153bc63ec8d8ed74c38b35e60cff1f
parentd2d5f539dd0d36a83ddb35b5d404315f6569560c (diff)
Using scrollevents
-rw-r--r--scroller/qflickgesture.cpp21
-rw-r--r--scroller/qkineticscroller.cpp161
-rw-r--r--scroller/qkineticscroller.h12
-rw-r--r--scroller/qkineticscroller_p.h16
-rw-r--r--testapp/main.cpp15
-rw-r--r--testapp/settingswidget.cpp6
-rw-r--r--testapp/testapp.pro4
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"<<target<<"parent:"<<target->parent();
+ QKineticScroller *res = 0;
+
+ if (!target)
+ return 0;
+
+ res = target->property("kineticScroller").value<QKineticScroller *>();
+ if (res)
+ return res;
+
+ if (!target->parent())
return 0;
- QKineticScroller *s = target->parent()->property("kineticScroller").value<QKineticScroller *>();
- return s;
+ res = target->parent()->property("kineticScroller").value<QKineticScroller *>();
+ return res;
}
QPointer<QWidget> target;
@@ -83,6 +92,7 @@ QFlickGestureRecognizer::QFlickGestureRecognizer()
QGesture *QFlickGestureRecognizer::create(QObject *target)
{
+ qDebug() << "Recognizer::create for"<<target<<"widget?"<<(target?target->isWidgetType():false);
if (target && target->isWidgetType()) {
QWidget *widget = static_cast<QWidget *>(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"<<scroller;
if (!scroller)
return QGestureRecognizer::Ignore;
@@ -189,10 +200,8 @@ QGestureRecognizer::Result QFlickGestureRecognizer::recognize(QGesture *state,
void QFlickGestureRecognizer::reset(QGesture *state)
{
QFlickGesture *flick = static_cast<QFlickGesture*>(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 <QApplication>
#include <QDesktopWidget>
#include <QtCore/qmath.h>
+#include <QtGui/qevent.h>
#include <QtDebug>
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 "<<receiver;
+ sendEvent(receiver, &spe);
+
+ qDebug() << "Returned with "<<spe.isAccepted()<<"for"<<spe.target();
+ if (spe.isAccepted() && spe.target()) {
+ target = spe.target();
+ viewportSize = spe.viewportSize();
+ maximumContentPosition = spe.maxContentPos();
+ contentPosition = spe.contentPos();
+
+ if ((maximumContentPosition > 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<QKineticScrollerPrivate> 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 <QPointer>
#include <QObject>
#include <qkineticscroller.h>
-#include <QEvent>
#if QT_VERSION < 0x040700
# include <QTime>
#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<QObject> receiver; // the object this scroller was registered for
+
+ QPointer<QObject> 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 <qflickgesture.h>
#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<QAbstractKineticScroller *>();
@@ -127,13 +134,13 @@ private:
#endif
// set a new kinetic scroller
if (QAbstractScrollArea *area = qobject_cast<QAbstractScrollArea *>(w)) {
- QScrollAreaKineticScroller *newScroller = new QScrollAreaKineticScroller();
- newScroller->setWidget(area);
+ area->viewport()->grabGesture(gestureType);
+ QKineticScroller *newScroller = new QKineticScroller(area);
w->setProperty("kineticScroller", QVariant::fromValue(static_cast<QKineticScroller*>(newScroller)) );
return newScroller;
} else if (QWebView *web = qobject_cast<QWebView *>(w)) {
- QWebViewKineticScroller *newScroller = new QWebViewKineticScroller();
- newScroller->setWidget(web);
+ web->grabGesture(gestureType);
+ QKineticScroller *newScroller = new QKineticScroller(web);
w->setProperty("kineticScroller", QVariant::fromValue(static_cast<QKineticScroller*>(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<HackScroller *>(m_scroller)->viewportSize();
QPointF maxc = static_cast<HackScroller *>(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