diff options
author | Ralf Engels <ralf.engels@nokia.com> | 2010-05-20 18:00:37 +0200 |
---|---|---|
committer | Ralf Engels <ralf.engels@nokia.com> | 2010-05-20 18:00:37 +0200 |
commit | 4d7cc49a79343aec00a9fc6241ae120177bf9d53 (patch) | |
tree | 95842d1e2f839d2dd757dcbba17efbc3fa783335 | |
parent | d00d11f9dcc0dbc966c4d2dca9ab0aab29c3671b (diff) |
Add gestures
-rw-r--r-- | scroller/qflickgesture.cpp | 208 | ||||
-rw-r--r-- | scroller/qflickgesture.h | 90 | ||||
-rw-r--r-- | scroller/qkineticscroller.h | 3 | ||||
-rw-r--r-- | scroller/scroller.pro | 4 | ||||
-rw-r--r-- | testapp/main.cpp | 2 | ||||
-rw-r--r-- | testapp/qscrollareakineticscroller.cpp | 45 | ||||
-rw-r--r-- | testapp/testapp.pro | 2 |
7 files changed, 335 insertions, 19 deletions
diff --git a/scroller/qflickgesture.cpp b/scroller/qflickgesture.cpp new file mode 100644 index 0000000..03434a2 --- /dev/null +++ b/scroller/qflickgesture.cpp @@ -0,0 +1,208 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qflickgesture.h" +#include "qgesture.h" +#include "qevent.h" +#include "qwidget.h" +#include "qabstractscrollarea.h" +#include "qdebug.h" + +QT_BEGIN_NAMESPACE + + +class QFlickGesturePrivate +{ +public: + QFlickGesturePrivate() + { + } + + QKineticScroller *scroller() + { + if (!target || !target->parent()) + return 0; + + QKineticScroller *s = target->parent()->property("kineticScroller").value<QKineticScroller *>(); + return s; + } + + QPointer<QWidget> target; + +#if QT_VERSION < 0x040700 + QTime timer; +#else + QElapsedTimer timer; +#endif + + friend class QFlickGesture; +}; + + +QFlickGestureRecognizer::QFlickGestureRecognizer() +{ +} + +QGesture *QFlickGestureRecognizer::create(QObject *target) +{ + if (target && target->isWidgetType()) { + QWidget *widget = static_cast<QWidget *>(target); +#if defined(Q_OS_WIN) && !defined(QT_NO_NATIVE_GESTURES) + // for scroll areas on Windows we want to use native gestures instead + if (!qobject_cast<QAbstractScrollArea *>(target->parent())) + widget->setAttribute(Qt::WA_AcceptTouchEvents); +#else + widget->setAttribute(Qt::WA_AcceptTouchEvents); +#endif + return new QFlickGesture(widget); + } + return new QFlickGesture(0); +} + +QGestureRecognizer::Result QFlickGestureRecognizer::recognize(QGesture *state, + QObject *, + QEvent *event) +{ + QFlickGesture *q = static_cast<QFlickGesture *>(state); + QFlickGesturePrivate *d = q->d; + + QKineticScroller *scroller = d->scroller(); + if (!scroller) + return QGestureRecognizer::Ignore; + + // eat mouse events if the scroller is active + if ((scroller->state() == QKineticScroller::StateDragging || + scroller->state() == QKineticScroller::StateScrolling) && + (event->type() != QEvent::MouseButtonPress && + event->type() != QEvent::MouseMove && + event->type() != QEvent::MouseButtonDblClick && + event->type() != QEvent::MouseButtonRelease) ) + return QGestureRecognizer::Ignore | QGestureRecognizer::ConsumeEventHint; + + // ignore all other events except touch + if (event->type() != QEvent::TouchBegin && + event->type() != QEvent::TouchEnd && + event->type() != QEvent::TouchUpdate) + return QGestureRecognizer::Ignore; + + qDebug()<<"recognize event: "<<event<<"target:"<<d->target<<"scroller:"<<d->scroller(); + + const QTouchEvent *ev = static_cast<const QTouchEvent *>(event); + QTouchEvent::TouchPoint tp = ev->touchPoints().first(); + + qint64 timestamp = d->timer.elapsed(); + + QKineticScroller::State oldState = scroller->state(); + + QGestureRecognizer::Result result = QGestureRecognizer::Ignore; + switch (event->type()) { + case QEvent::TouchBegin: + scroller->handleInput(QKineticScroller::InputPress, tp.pos(), timestamp); + break; + case QEvent::TouchEnd: + scroller->handleInput(QKineticScroller::InputRelease, tp.pos(), timestamp); + break; + case QEvent::TouchUpdate: + scroller->handleInput(QKineticScroller::InputMove, tp.pos(), timestamp); + break; + default: + break; + } + + QKineticScroller::State newState = scroller->state(); + + bool oldTriggered = (oldState == QKineticScroller::StateInactive) || + (oldState == QKineticScroller::StatePressed); + + bool newTriggered = (newState == QKineticScroller::StateInactive) || + (newState == QKineticScroller::StatePressed); + + if (event->type() == QEvent::TouchBegin && !newTriggered) + return QGestureRecognizer::MayBeGesture; + + if (event->type() == QEvent::TouchEnd && !oldTriggered) + return QGestureRecognizer::CancelGesture; + + if (!oldTriggered && !newTriggered) + return QGestureRecognizer::Ignore; + + if (oldTriggered && newTriggered) + return QGestureRecognizer::Ignore | QGestureRecognizer::ConsumeEventHint; + + if (!oldTriggered) + return QGestureRecognizer::TriggerGesture | QGestureRecognizer::ConsumeEventHint; + + return QGestureRecognizer::FinishGesture | QGestureRecognizer::ConsumeEventHint; +} + +void QFlickGestureRecognizer::reset(QGesture *state) +{ + QFlickGesture *flick = static_cast<QFlickGesture*>(state); + flick->d->target = 0; + flick->d->timer.start(); + + QGestureRecognizer::reset(state); +} + + + +/*! + \class QFlickGesture + \since 4.7 + \brief The QFlickGesture class describes a flicking gesture made by the user. + \ingroup gestures + + \sa {Gestures Programming}, QPinchGesture, QSwipeGesture +*/ + +/*! + \internal +*/ +QFlickGesture::QFlickGesture(QWidget *target, QObject *parent) + : QGesture(parent) +{ + d = new QFlickGesturePrivate(); + d->target = target; + d->timer.start(); + qDebug() << "QFlickGesture::FlickGesture for: " << target; +} + +QT_END_NAMESPACE diff --git a/scroller/qflickgesture.h b/scroller/qflickgesture.h new file mode 100644 index 0000000..b6571d0 --- /dev/null +++ b/scroller/qflickgesture.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QFLICKGESTURE_P_H +#define QFLICKGESTURE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qgesturerecognizer.h" +#include "private/qgesture_p.h" + +#include "qkineticscroller.h" + +QT_BEGIN_NAMESPACE + +class QFlickGestureRecognizer : public QGestureRecognizer +{ +public: + QFlickGestureRecognizer(); + + QGesture *create(QObject *target); + QGestureRecognizer::Result recognize(QGesture *state, QObject *watched, QEvent *event); + void reset(QGesture *state); +}; + +class QFlickGesturePrivate; + +class Q_GUI_EXPORT QFlickGesture : public QGesture +{ + Q_OBJECT + +public: + QFlickGesture(QWidget *widget, QObject *parent = 0); + + friend class QFlickGestureRecognizer; + +private: + QFlickGesturePrivate *d; +}; + +QT_END_NAMESPACE + +#endif // QFLICKGESTURES_P_H diff --git a/scroller/qkineticscroller.h b/scroller/qkineticscroller.h index f7eef8f..56bf733 100644 --- a/scroller/qkineticscroller.h +++ b/scroller/qkineticscroller.h @@ -53,6 +53,7 @@ QT_BEGIN_NAMESPACE QT_MODULE(Gui) +class QFlickGestureRecognizer; class QKineticScrollerPrivate; class QKineticScroller @@ -154,6 +155,8 @@ protected: private: Q_DISABLE_COPY(QKineticScroller) Q_DECLARE_PRIVATE(QKineticScroller) + + friend class QFlickGestureRecognizer; }; QT_END_NAMESPACE diff --git a/scroller/scroller.pro b/scroller/scroller.pro index 97a3ca7..28b794b 100644 --- a/scroller/scroller.pro +++ b/scroller/scroller.pro @@ -9,8 +9,8 @@ DEPENDPATH += . INCLUDEPATH += . # Input -HEADERS += qkineticscroller.h qkineticscroller_p.h -SOURCES += qkineticscroller.cpp +HEADERS += qkineticscroller.h qkineticscroller_p.h qflickgesture.h +SOURCES += qkineticscroller.cpp qflickgesture.cpp macx:SOURCES += qkineticscroller_mac.mm maemo5:SOURCES += qkineticscroller_maemo5.cpp diff --git a/testapp/main.cpp b/testapp/main.cpp index 4240979..c08c745 100644 --- a/testapp/main.cpp +++ b/testapp/main.cpp @@ -129,10 +129,12 @@ private: if (QAbstractScrollArea *area = qobject_cast<QAbstractScrollArea *>(w)) { QScrollAreaKineticScroller *newScroller = new QScrollAreaKineticScroller(); newScroller->setWidget(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); + w->setProperty("kineticScroller", QVariant::fromValue(static_cast<QKineticScroller*>(newScroller)) ); return newScroller; } else { return 0; diff --git a/testapp/qscrollareakineticscroller.cpp b/testapp/qscrollareakineticscroller.cpp index dbe20dc..43fb8dd 100644 --- a/testapp/qscrollareakineticscroller.cpp +++ b/testapp/qscrollareakineticscroller.cpp @@ -40,6 +40,8 @@ ****************************************************************************/ #include <qscrollareakineticscroller.h> +#include <qflickgesture.h> + #include <QApplication> #include <QGraphicsView> #include <QAbstractScrollArea> @@ -139,9 +141,13 @@ void QScrollAreaKineticScroller::setWidget(QAbstractScrollArea *widget) { Q_D(QScrollAreaKineticScroller); + static Qt::GestureType gestureType = (Qt::GestureType)0; + if (d->area) { d->area->viewport()->removeEventFilter(this); d->area->viewport()->move(d->area->viewport()->pos() + d->lastOvershoot); + + d->area->ungrabGesture(gestureType); d->area->viewport()->setAttribute(Qt::WA_AcceptTouchEvents, false); } @@ -152,7 +158,17 @@ void QScrollAreaKineticScroller::setWidget(QAbstractScrollArea *widget) setParent(d->area); if (d->area) { + + // need to register the gesture type + if( !gestureType ) { + gestureType = QGestureRecognizer::registerRecognizer( new QFlickGestureRecognizer() ); + } + + d->area->viewport()->grabGesture(gestureType); + + /* d->area->viewport()->setAttribute(Qt::WA_AcceptTouchEvents, true); + */ d->area->viewport()->installEventFilter(this); if (QAbstractItemView *view = qobject_cast<QAbstractItemView *>(d->area)) { view->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); @@ -174,30 +190,21 @@ bool QScrollAreaKineticScroller::eventFilter(QObject *o, QEvent *e) if (d->area && (o == d->area->viewport()) && !d->ignoreEvents && d->area->isEnabled() && isEnabled()) { switch (e->type()) { + case QEvent::Gesture: + qDebug("Got gesture event"); + res = true; + break; case QEvent::TouchBegin: case QEvent::TouchUpdate: case QEvent::TouchEnd: { - Input type = (e->type() == QEvent::TouchBegin) ? InputPress : - ((e->type() == QEvent::TouchEnd) ? InputRelease : InputMove); - QTouchEvent *te = static_cast<QTouchEvent *>(e); - int idx = (te->deviceType() == QTouchEvent::TouchScreen) ? 0 : 1; - - if (te->touchPoints().count() == (idx + 1)) { - res = handleInput(type, te->touchPoints().at(idx).pos() - d->lastOvershoot, timestamp); - if (type == InputPress) { - d->touchActive = true; - e->accept(); - } else if (type == InputRelease) { - d->touchActive = false; - } - } - break; + res = true; } case QEvent::Wheel: // the two-finger gesture on the Mac is mapped to wheel events by default res = d->touchActive; break; +#if 0 case QEvent::MouseButtonPress: // re-install the event filter so that we get the mouse release before all other filters. // this is an evil hack, but hard to work around without prioritized event filters. @@ -212,13 +219,19 @@ bool QScrollAreaKineticScroller::eventFilter(QObject *o, QEvent *e) case QEvent::MouseMove: case QEvent::MouseButtonRelease: if (!d->touchActive) { + res = !((state() == QKineticScroller::StateInactive) || + (state() == QKineticScroller::StatePressed)); + /* Input type = (e->type() == QEvent::MouseButtonRelease) ? InputRelease : ((e->type() == QEvent::MouseMove) ? InputMove : InputPress); QMouseEvent *me = static_cast<QMouseEvent *>(e); isMouseEvent = true; - res = handleInput(type, me->posF() - d->lastOvershoot, timestamp); + // res = handleInput(type, me->posF() - d->lastOvershoot, timestamp); + res = true; + */ } break; +#endif case QEvent::ChildAdded: case QEvent::ChildRemoved: { diff --git a/testapp/testapp.pro b/testapp/testapp.pro index 35f72a9..8f9d20a 100644 --- a/testapp/testapp.pro +++ b/testapp/testapp.pro @@ -12,7 +12,7 @@ LIBS += -L../scroller -lscroller unix:PRE_TARGETDEPS += ../scroller/libscroller.a win32:PRE_TARGETDEPS += ../scroller/scroller.lib -QT += webkit +QT += webkit network # Input HEADERS += plotwidget.h qscrollareakineticscroller.h qwebviewkineticscroller.h settingswidget.h |