diff options
25 files changed, 501 insertions, 619 deletions
diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index 5747c3c..56ee768 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -1551,13 +1551,17 @@ public: TouchPointReleased }; - typedef QString GestureType; - static const char UnknownGesture[] = "???"; - static const char Tap[] = "Tap"; - static const char DoubleTap[] = "DoubleTap"; - static const char LongTap[] = "LongTap"; - static const char Pan[] = "Pan"; - static const char Pinch[] = "Pinch"; + enum GestureType + { + UnknownGesture, + TapGesture, + DoubleTapGesture, + TrippleTapGesture, + TapAndHoldGesture, + PanGesture, + PinchGesture + }; + enum GestureState { diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index a9ad1e1..cbd4834 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -561,6 +561,8 @@ public: }; Q_GLOBAL_STATIC(QGraphicsItemCustomDataStore, qt_dataStore) +QString qt_getStandardGestureTypeName(Qt::GestureType type); + /*! \internal @@ -5788,23 +5790,27 @@ QVariant QGraphicsItem::inputMethodQuery(Qt::InputMethodQuery query) const return QVariant(); } -void QGraphicsItem::grabGesture(const Qt::GestureType &type) +int QGraphicsItem::grabGesture(Qt::GestureType type) { - d_ptr->gestures.insert(type); - if (d_ptr->scene) - d_ptr->scene->d_func()->grabGesture(this, type); + return grabGesture(qt_getStandardGestureTypeName(type)); } -void QGraphicsItem::releaseGesture(const Qt::GestureType &type) +int QGraphicsItem::grabGesture(const QString &type) { - d_ptr->gestures.remove(type); + int id = qHash(type); + QSet<int>::iterator it = d_ptr->gestures.find(id); + if (it != d_ptr->gestures.end()) + return *it; + d_ptr->gestures << id; if (d_ptr->scene) - d_ptr->scene->d_func()->releaseGesture(this, type); + d_ptr->scene->d_func()->grabGesture(this, id); } -QSet<Qt::GestureType> QGraphicsItem::gestures() const +void QGraphicsItem::releaseGesture(int id) { - return d_ptr->gestures; + d_ptr->gestures.remove(id); + if (d_ptr->scene) + d_ptr->scene->d_func()->releaseGesture(this, id); } /*! @@ -5835,14 +5841,14 @@ QVariant QGraphicsItem::itemChange(GraphicsItemChange change, const QVariant &va if (!qVariantValue<QGraphicsScene*>(value)) { // the item has been removed from a scene, unsubscribe gestures. Q_ASSERT(d_ptr->scene); - foreach(const Qt::GestureType &gesture, d_ptr->gestures) - d_ptr->scene->d_func()->releaseGesture(this, gesture); + foreach(int id, d_ptr->gestures) + d_ptr->scene->d_func()->releaseGesture(this, id); } } else if (change == QGraphicsItem::ItemSceneHasChanged) { if (QGraphicsScene *scene = qVariantValue<QGraphicsScene*>(value)) { // item has been added to the scene - foreach(const Qt::GestureType &gesture, d_ptr->gestures) - scene->d_func()->grabGesture(this, gesture); + foreach(int id, d_ptr->gestures) + scene->d_func()->grabGesture(this, id); } } return value; diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index 2b4cdf5..4e6e96d 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -338,9 +338,9 @@ public: QVariant data(int key) const; void setData(int key, const QVariant &value); - void grabGesture(const Qt::GestureType &type); - void releaseGesture(const Qt::GestureType &type); - QSet<Qt::GestureType> gestures() const; + int grabGesture(Qt::GestureType type); + int grabGesture(const QString &type); + void releaseGesture(int gestureId); enum { Type = 1, diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index a67a49a..f6daa49 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -298,7 +298,7 @@ public: int siblingIndex; int index; int depth; - QSet<Qt::GestureType> gestures; + QSet<int> gestures; // Packed 32 bytes quint32 acceptedMouseButtons : 5; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 7e23620..0f70cfe 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5593,21 +5593,21 @@ void QGraphicsScene::setActiveWindow(QGraphicsWidget *widget) void QGraphicsScenePrivate::addView(QGraphicsView *view) { views << view; - foreach(const Qt::GestureType &gesture, grabbedGestures) - view->grabGesture(gesture); + foreach(int gestureId, grabbedGestures) + view->d_func()->grabGesture(gestureId); } void QGraphicsScenePrivate::removeView(QGraphicsView *view) { views.removeAll(view); - foreach(const Qt::GestureType &gesture, grabbedGestures) - view->releaseGesture(gesture); + foreach(int gestureId, grabbedGestures) + view->releaseGesture(gestureId); } void QGraphicsScene::gestureEvent(QGraphicsSceneGestureEvent *event) { Q_D(QGraphicsScene); - QList<Qt::GestureType> gestureTypes = event->gestureTypes(); + QList<QString> gestureTypes = event->gestureTypes(); QGraphicsView *view = qobject_cast<QGraphicsView*>(event->widget()); if (!view) { qWarning("QGraphicsScene::gestureEvent: gesture event was received without a view"); @@ -5616,19 +5616,20 @@ void QGraphicsScene::gestureEvent(QGraphicsSceneGestureEvent *event) // find graphics items that intersects with gestures hot spots. QPolygonF poly; - QMap<Qt::GestureType, QPointF> sceneHotSpots; - foreach(const Qt::GestureType &type, gestureTypes) { + QMap<int, QPointF> sceneHotSpots; + foreach(const QString &type, gestureTypes) { QPointF pt = event->mapToScene(event->gesture(type)->hotSpot()); - sceneHotSpots.insert(type, pt); + sceneHotSpots.insert(qHash(type), pt); poly << pt; } QList<QGraphicsItem*> itemsInGestureArea = items(poly, Qt::IntersectsItemBoundingRect); foreach(QGraphicsItem *item, itemsInGestureArea) { - QMap<Qt::GestureType, QPointF>::const_iterator it = sceneHotSpots.begin(), - e = sceneHotSpots.end(); + QMap<int, QPointF>::const_iterator it = sceneHotSpots.begin(), + e = sceneHotSpots.end(); for(; it != e; ++it) { - if (item->contains(item->mapFromScene(it.value())) && item->gestures().contains(it.key())) { + if (item->contains(item->mapFromScene(it.value())) && + item->d_ptr->gestures.contains(it.key())) { d->sendEvent(item, event); if (event->isAccepted()) break; @@ -5637,17 +5638,17 @@ void QGraphicsScene::gestureEvent(QGraphicsSceneGestureEvent *event) } } -void QGraphicsScenePrivate::grabGesture(QGraphicsItem *item, const Qt::GestureType &type) +void QGraphicsScenePrivate::grabGesture(QGraphicsItem *item, int gestureId) { - if (!grabbedGestures.contains(type)) { + if (!grabbedGestures.contains(gestureId)) { foreach(QGraphicsView *view, views) - view->grabGesture(type); + view->d_func()->grabGesture(gestureId); } itemsWithGestures << item; - grabbedGestures << type; + grabbedGestures << gestureId; } -void QGraphicsScenePrivate::releaseGesture(QGraphicsItem *item, const Qt::GestureType &type) +void QGraphicsScenePrivate::releaseGesture(QGraphicsItem *item, int gestureId) { //### } diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 1cd1788..074e95c 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -268,9 +268,9 @@ public: void updatePalette(const QPalette &palette); QSet<QGraphicsItem*> itemsWithGestures; - QSet<Qt::GestureType> grabbedGestures; - void grabGesture(QGraphicsItem *item, const Qt::GestureType &type); - void releaseGesture(QGraphicsItem *item, const Qt::GestureType &type); + QSet<int> grabbedGestures; + void grabGesture(QGraphicsItem *item, int gestureId); + void releaseGesture(QGraphicsItem *item, int gestureId); mutable QVector<QTransform> sceneTransformCache; mutable QBitArray validTransforms; diff --git a/src/gui/graphicsview/qgraphicssceneevent.h b/src/gui/graphicsview/qgraphicssceneevent.h index d3899cd..4d88cda 100644 --- a/src/gui/graphicsview/qgraphicssceneevent.h +++ b/src/gui/graphicsview/qgraphicssceneevent.h @@ -317,19 +317,19 @@ public: QGraphicsSceneGestureEvent(); ~QGraphicsSceneGestureEvent(); - inline bool contains(const Qt::GestureType &type) const + inline bool contains(const QString &type) const { return gesture(type) != 0; } - inline QList<Qt::GestureType> gestureTypes() const + inline QList<QString> gestureTypes() const { return m_gestures.keys(); } - inline const QGesture* gesture(const Qt::GestureType &type) const + inline const QGesture* gesture(const QString &type) const { return m_gestures.value(type, QSharedPointer<QGesture>()).data(); } inline QList<QSharedPointer<QGesture> > gestures() const { return m_gestures.values(); } void setGestures(const QList<QSharedPointer<QGesture> > &gestures); - inline QSet<Qt::GestureType> cancelledGestures() const + inline QSet<QString> cancelledGestures() const { return m_cancelledGestures; } - void setCancelledGestures(const QSet<Qt::GestureType> &cancelledGestures) + void setCancelledGestures(const QSet<QString> &cancelledGestures) { m_cancelledGestures = cancelledGestures; } QPointF mapToScene(const QPoint &point) const; @@ -338,8 +338,8 @@ public: QPolygonF mapToItem(const QRect &rect, QGraphicsItem *item) const; protected: - QHash<Qt::GestureType, QSharedPointer<QGesture> > m_gestures; - QSet<Qt::GestureType> m_cancelledGestures; + QHash<QString, QSharedPointer<QGesture> > m_gestures; + QSet<QString> m_cancelledGestures; }; class QGraphicsSceneTouchEventPrivate; diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri index b6ef6b2..adc2b10 100644 --- a/src/gui/kernel/kernel.pri +++ b/src/gui/kernel/kernel.pri @@ -44,6 +44,7 @@ HEADERS += \ kernel/qkeymapper_p.h \ kernel/qgesture.h \ kernel/qgesturemanager_p.h \ + kernel/qgesturerecognizer_p.h \ kernel/qgesturerecognizer.h \ kernel/qgesturestandardrecognizers_p.h \ kernel/qdirectionrecognizer_p.h \ @@ -79,6 +80,7 @@ SOURCES += \ kernel/qkeymapper.cpp \ kernel/qgesture.cpp \ kernel/qgesturemanager.cpp \ + kernel/qgesturerecognizer.cpp \ kernel/qgesturestandardrecognizers.cpp \ kernel/qdirectionrecognizer.cpp diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index 5774ae0..efe1b13 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -3720,7 +3720,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e) if (w && (mouse->type() != QEvent::MouseMove || mouse->buttons() != 0)) { // find the gesture target widget QWidget *target = w; - while (target && target->gestures().isEmpty()) + while (target && target->d_func()->gestures.isEmpty()) target = target->parentWidget(); if (target) { gm->setGestureTargetWidget(target); diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h index 40e928d..40cd4ae 100644 --- a/src/gui/kernel/qapplication_p.h +++ b/src/gui/kernel/qapplication_p.h @@ -428,7 +428,9 @@ public: void sendSyntheticEnterLeave(QWidget *widget); #endif - QMap<Qt::GestureType, int> grabbedGestures; + // map<gesture id -> number of grabbed widgets (something like refcount) + QMap<int, int> grabbedGestures; + static void updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent); #if defined(Q_WS_WIN) diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 6cdf781..225d8b1 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -3554,7 +3554,7 @@ QMenubarUpdatedEvent::QMenubarUpdatedEvent(QMenuBar * const menuBar) QGestureEvent::QGestureEvent(const QList<QGesture*> &gestures, - const QSet<Qt::GestureType> &cancelledGestures) + const QSet<QString> &cancelledGestures) : QEvent(QEvent::Gesture), m_cancelledGestures(cancelledGestures) { foreach(QGesture *r, gestures) diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index 603f358..db3d03f 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -718,26 +718,27 @@ class Q_GUI_EXPORT QGestureEvent : public QEvent { public: QGestureEvent(const QList<QGesture*> &gestures, - const QSet<Qt::GestureType> &cancelledGestures = QSet<Qt::GestureType>()); + const QSet<QString> &cancelledGestures = QSet<QString>()); // internal ctor QGestureEvent(const QGestureEvent &gestures, const QPoint &offset); ~QGestureEvent(); - inline bool contains(const Qt::GestureType &type) const + inline bool contains(const QString &type) const { return gesture(type) != 0; } - inline QList<Qt::GestureType> gestureTypes() const + inline QList<QString> gestureTypes() const { return m_gestures.keys(); } - inline const QGesture* gesture(const Qt::GestureType &type) const + + inline const QGesture* gesture(const QString &type) const { return m_gestures.value(type, QSharedPointer<QGesture>()).data(); } inline QList<QSharedPointer<QGesture> > gestures() const { return m_gestures.values(); } - inline QSet<Qt::GestureType> cancelledGestures() const + inline QSet<QString> cancelledGestures() const { return m_cancelledGestures; } protected: - QHash<Qt::GestureType, QSharedPointer<QGesture> > m_gestures; - QSet<Qt::GestureType> m_cancelledGestures; + QHash<QString, QSharedPointer<QGesture> > m_gestures; + QSet<QString> m_cancelledGestures; friend class QApplication; }; diff --git a/src/gui/kernel/qgesture.cpp b/src/gui/kernel/qgesture.cpp index fbabb8f..b2d357c 100644 --- a/src/gui/kernel/qgesture.cpp +++ b/src/gui/kernel/qgesture.cpp @@ -42,80 +42,80 @@ #include "qgesture.h" #include <private/qgesture_p.h> -QGesture::QGesture(const Qt::GestureType &type, Qt::GestureState state) - : d(new QGesturePrivate), gestureType_(type), gestureState_(state) +QT_BEGIN_NAMESPACE + +QString qt_getStandardGestureTypeName(Qt::GestureType type); + +QGesture::QGesture(QObject *parent, const QString &type, Qt::GestureState state) + : QObject(*new QGesturePrivate, parent), gestureType_(type), gestureState_(state) { } -QGesture::QGesture(const Qt::GestureType &type, const QPoint &startPos, +QGesture::QGesture(QObject *parent, const QString &type, const QPoint &startPos, const QPoint &lastPos, const QPoint &pos, const QRect &rect, const QPoint &hotSpot, const QDateTime &startTime, uint duration, Qt::GestureState state) - : d(new QGesturePrivate), gestureType_(type), gestureState_(state) + : QObject(*new QGesturePrivate, parent), gestureType_(type), gestureState_(state) { - d->init(startPos, lastPos, pos, rect, hotSpot, startTime, duration); + d_func()->init(startPos, lastPos, pos, rect, hotSpot, startTime, duration); } -QGesture::QGesture(QGesturePrivate &dd, const Qt::GestureType &type, +QGesture::QGesture(QGesturePrivate &dd, QObject *parent, const QString &type, Qt::GestureState state) - : d(&dd), gestureType_(type), gestureState_(state) + : QObject(dd, parent), gestureType_(type), gestureState_(state) { } QGesture::~QGesture() { - delete d; d = 0; } QRect QGesture::rect() const { - return d->rect; + return d_func()->rect; } QPoint QGesture::hotSpot() const { - return d->hotSpot; + return d_func()->hotSpot; } QDateTime QGesture::startTime() const { - return d->startTime; + return d_func()->startTime; } uint QGesture::duration() const { - return d->duration; + return d_func()->duration; } QPoint QGesture::startPos() const { - return d->startPos; + return d_func()->startPos; } QPoint QGesture::lastPos() const { - return d->lastPos; + return d_func()->lastPos; } QPoint QGesture::pos() const { - return d->pos; + return d_func()->pos; } -QPannableGesture::QPannableGesture(const Qt::GestureType &type, Qt::GestureState state) - : QGesture(*new QPannableGesturePrivate, type, state) -{ -} - -QPannableGesture::QPannableGesture(const Qt::GestureType &type, const QPoint &startPos, +QPannableGesture::QPannableGesture(QObject *parent, const QPoint &startPos, const QPoint &lastPos, const QPoint &pos, const QRect &rect, const QPoint &hotSpot, const QDateTime &startTime, uint duration, Qt::GestureState state) - : QGesture(*new QPannableGesturePrivate, type, state) + : QGesture(*new QPannableGesturePrivate, parent, + qt_getStandardGestureTypeName(Qt::PanGesture), state) { + Q_D(QPannableGesture); d->init(startPos, lastPos, pos, rect, hotSpot, startTime, duration); - ((QPannableGesturePrivate*)d)->lastDirection = QPannableGesture::None; - ((QPannableGesturePrivate*)d)->direction = QPannableGesture::None; + d->lastDirection = QPannableGesture::None; + d->direction = QPannableGesture::None; } QPannableGesture::~QPannableGesture() @@ -124,10 +124,14 @@ QPannableGesture::~QPannableGesture() QPannableGesture::DirectionType QPannableGesture::lastDirection() const { - return ((QPannableGesturePrivate*)d)->lastDirection; + Q_D(const QPannableGesture); + return d->lastDirection; } QPannableGesture::DirectionType QPannableGesture::direction() const { - return ((QPannableGesturePrivate*)d)->direction; + Q_D(const QPannableGesture); + return d->direction; } + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qgesture.h b/src/gui/kernel/qgesture.h index 16a5704..f20a63c 100644 --- a/src/gui/kernel/qgesture.h +++ b/src/gui/kernel/qgesture.h @@ -56,17 +56,21 @@ QT_BEGIN_NAMESPACE QT_MODULE(Gui) class QGesturePrivate; -class Q_GUI_EXPORT QGesture +class Q_GUI_EXPORT QGesture : public QObject { + Q_OBJECT + Q_DECLARE_PRIVATE(QGesture) public: - explicit QGesture(const Qt::GestureType &type, Qt::GestureState state = Qt::GestureStarted); - QGesture(const Qt::GestureType &type, const QPoint &startPos, + explicit QGesture(QObject *parent, const QString &type, + Qt::GestureState state = Qt::GestureStarted); + QGesture(QObject *parent, + const QString &type, const QPoint &startPos, const QPoint &lastPos, const QPoint &pos, const QRect &rect, const QPoint &hotSpot, const QDateTime &startTime, uint duration, Qt::GestureState state); virtual ~QGesture(); - inline Qt::GestureType gestureType() const { return gestureType_; } + inline QString gestureType() const { return gestureType_; } inline Qt::GestureState state() const { return gestureState_; } QRect rect() const; @@ -79,16 +83,20 @@ public: QPoint pos() const; protected: - QGesture(QGesturePrivate &dd, const Qt::GestureType &type, Qt::GestureState state = Qt::GestureStarted); - QGesturePrivate *d; + QGesture(QGesturePrivate &dd, QObject *parent, const QString &type, Qt::GestureState state); + //### virtual void translateCoordinates(const QPoint &offset); private: - Qt::GestureType gestureType_; + QString gestureType_; Qt::GestureState gestureState_; }; +class QPannableGesturePrivate; class Q_GUI_EXPORT QPannableGesture : public QGesture { + Q_OBJECT + Q_DECLARE_PRIVATE(QPannableGesture) + public: enum DirectionType { @@ -108,8 +116,7 @@ public: }; public: - explicit QPannableGesture(const Qt::GestureType &type, Qt::GestureState state = Qt::GestureStarted); - QPannableGesture(const Qt::GestureType &type, const QPoint &startPos, + QPannableGesture(QObject *parent, const QPoint &startPos, const QPoint &lastPos, const QPoint &pos, const QRect &rect, const QPoint &hotSpot, const QDateTime &startTime, uint duration, Qt::GestureState state); diff --git a/src/gui/kernel/qgesture_p.h b/src/gui/kernel/qgesture_p.h index 745590b..8a76186 100644 --- a/src/gui/kernel/qgesture_p.h +++ b/src/gui/kernel/qgesture_p.h @@ -56,11 +56,14 @@ #include "qrect.h" #include "qpoint.h" #include "qdatetime.h" +#include "private/qobject_p.h" QT_BEGIN_NAMESPACE -class QGesturePrivate +class QGesturePrivate : public QObjectPrivate { + Q_DECLARE_PUBLIC(QGesture) + public: QGesturePrivate() : duration(0) { } @@ -90,6 +93,8 @@ public: class QPannableGesturePrivate : public QGesturePrivate { + Q_DECLARE_PUBLIC(QPannableGesture) + public: QPannableGesture::DirectionType lastDirection; QPannableGesture::DirectionType direction; diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp index 9a287a0..0e2cea8 100644 --- a/src/gui/kernel/qgesturemanager.cpp +++ b/src/gui/kernel/qgesturemanager.cpp @@ -44,9 +44,10 @@ #include "qevent.h" #include "qapplication.h" -#include "private/qapplication_p.h" +#include "qapplication_p.h" +#include "qwidget_p.h" -#include "private/qgesturestandardrecognizers_p.h" +#include "qgesturestandardrecognizers_p.h" #include "qdebug.h" @@ -60,13 +61,6 @@ QT_BEGIN_NAMESPACE bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event); -static bool qt_sendGestureEvent(QWidget *receiver, QGestureEvent *event) -{ - QSet<Qt::GestureType> eventGestures = event->gestureTypes().toSet(); - while (receiver && (receiver->gestures() & eventGestures).isEmpty()) - receiver = receiver->parentWidget(); - return receiver ? qt_sendSpontaneousEvent(receiver, event) : false; -} static const unsigned int maximumGestureRecognitionTimeout = 2000; @@ -74,13 +68,12 @@ QGestureManager::QGestureManager() : targetWidget(0), state(NotGesture) { recognizers << new QDoubleTapGestureRecognizer(); - recognizers << new QLongTapGestureRecognizer(); + recognizers << new QTapAndHoldGestureRecognizer(); recognizers << new QGestureRecognizerPan(); - // recognizers << new QMultiTouchGestureRecognizer(); foreach(QGestureRecognizer *r, recognizers) - connect(r, SIGNAL(triggered(QGestureRecognizer::Result)), - this, SLOT(recognizerTriggered(QGestureRecognizer::Result))); + connect(r, SIGNAL(stateChanged(QGestureRecognizer::Result)), + this, SLOT(recognizerStateChanged(QGestureRecognizer::Result))); } void QGestureManager::addRecognizer(QGestureRecognizer *recognizer) @@ -98,9 +91,6 @@ bool QGestureManager::filterEvent(QEvent *event) if (!QApplication::testAttribute(Qt::AA_EnableGestures)) return false; - QList<QEvent*> events; - events << event; - QPoint currentPos; switch (event->type()) { case QEvent::MouseButtonPress: @@ -111,7 +101,7 @@ bool QGestureManager::filterEvent(QEvent *event) default: break; } - const QMap<Qt::GestureType, int> &grabbedGestures = qApp->d_func()->grabbedGestures; + const QMap<int, int> &grabbedGestures = qApp->d_func()->grabbedGestures; bool ret = false; QSet<QGestureRecognizer*> startedGestures; @@ -127,9 +117,9 @@ bool QGestureManager::filterEvent(QEvent *event) QSet<QGestureRecognizer*> stillMaybeGestures; // try other recognizers. foreach(QGestureRecognizer *r, recognizers) { - if (grabbedGestures.value(r->gestureType(), 0) <= 0) + if (grabbedGestures.value(qHash(r->gestureType()), 0) <= 0) continue; - QGestureRecognizer::Result result = r->recognize(events); + QGestureRecognizer::Result result = r->filterEvent(event); if (result == QGestureRecognizer::GestureStarted) { DEBUG() << "QGestureManager: gesture started: " << r; startedGestures << r; @@ -170,16 +160,16 @@ bool QGestureManager::filterEvent(QEvent *event) QList<QGesture*> gestures; foreach(QGestureRecognizer *r, finishedGestures) { - if (QGesture *gesture = r->makeEvent()) + if (QGesture *gesture = r->getGesture()) gestures << gesture; } foreach(QGestureRecognizer *r, activeGestures) { - if (QGesture *gesture = r->makeEvent()) + if (QGesture *gesture = r->getGesture()) gestures << gesture; } Q_ASSERT(!gestures.isEmpty()); QGestureEvent event(gestures); - ret = qt_sendGestureEvent(targetWidget, &event); + ret = sendGestureEvent(targetWidget, &event); ret = ret && event.isAccepted(); if (!activeGestures.isEmpty()) { @@ -220,9 +210,9 @@ bool QGestureManager::filterEvent(QEvent *event) Q_ASSERT(!activeGestures.isEmpty()); foreach(QGestureRecognizer *r, recognizers) { - if (grabbedGestures.value(r->gestureType(), 0) <= 0) + if (grabbedGestures.value(qHash(r->gestureType()), 0) <= 0) continue; - QGestureRecognizer::Result result = r->recognize(events); + QGestureRecognizer::Result result = r->filterEvent(event); if (result == QGestureRecognizer::GestureStarted) { DEBUG() << "QGestureManager: gesture started: " << r; startedGestures << r; @@ -271,20 +261,20 @@ bool QGestureManager::filterEvent(QEvent *event) << activeGestures << " and " << finishedGestures; foreach(QGestureRecognizer *r, finishedGestures) { - if (QGesture *gesture = r->makeEvent()) + if (QGesture *gesture = r->getGesture()) gestures << gesture; } foreach(QGestureRecognizer *r, activeGestures) { - if (QGesture *gesture = r->makeEvent()) + if (QGesture *gesture = r->getGesture()) gestures << gesture; } } - QSet<Qt::GestureType> cancelledGestureNames; + QSet<QString> cancelledGestureNames; foreach(QGestureRecognizer *r, cancelledGestures) cancelledGestureNames << r->gestureType(); if(!gestures.isEmpty()) { QGestureEvent event(gestures, cancelledGestureNames); - ret = qt_sendGestureEvent(targetWidget, &event); + ret = sendGestureEvent(targetWidget, &event); ret = ret && event.isAccepted(); } @@ -343,7 +333,7 @@ void QGestureManager::setGestureTargetWidget(QWidget *widget) targetWidget = widget; } -void QGestureManager::recognizerTriggered(QGestureRecognizer::Result result) +void QGestureManager::recognizerStateChanged(QGestureRecognizer::Result result) { if (!QApplication::testAttribute(Qt::AA_EnableGestures)) return; @@ -351,7 +341,7 @@ void QGestureManager::recognizerTriggered(QGestureRecognizer::Result result) QGestureRecognizer *recognizer = qobject_cast<QGestureRecognizer*>(sender()); if (!recognizer) return; - if (qApp->d_func()->grabbedGestures.value(recognizer->gestureType(), 0) <= 0) { + if (qApp->d_func()->grabbedGestures.value(qHash(recognizer->gestureType()), 0) <= 0) { recognizer->reset(); return; } @@ -372,11 +362,11 @@ void QGestureManager::recognizerTriggered(QGestureRecognizer::Result result) maybeGestures.remove(recognizer); } QList<QGesture*> gestures; - if (QGesture *gesture = recognizer->makeEvent()) + if (QGesture *gesture = recognizer->getGesture()) gestures << gesture; if(!gestures.isEmpty()) { QGestureEvent event(gestures); - qt_sendGestureEvent(targetWidget, &event); + sendGestureEvent(targetWidget, &event); } if (result == QGestureRecognizer::GestureFinished) recognizer->reset(); @@ -386,8 +376,8 @@ void QGestureManager::recognizerTriggered(QGestureRecognizer::Result result) DEBUG() << "QGestureManager: maybe gesture: " << recognizer; if (activeGestures.contains(recognizer)) { QGestureEvent event(QList<QGesture*>(), - QSet<Qt::GestureType>() << recognizer->gestureType()); - qt_sendGestureEvent(targetWidget, &event); + QSet<QString>() << recognizer->gestureType()); + sendGestureEvent(targetWidget, &event); } if (!maybeGestures.contains(recognizer)) { int timerId = startTimer(maximumGestureRecognitionTimeout); @@ -410,6 +400,17 @@ void QGestureManager::recognizerTriggered(QGestureRecognizer::Result result) } } +bool QGestureManager::sendGestureEvent(QWidget *receiver, QGestureEvent *event) +{ + QSet<int> eventGestures; + foreach(const QString &gesture, event->gestureTypes()) + eventGestures << qHash(gesture); + + while (receiver && (receiver->d_func()->gestures & eventGestures).isEmpty()) + receiver = receiver->parentWidget(); + return receiver ? qt_sendSpontaneousEvent(receiver, event) : false; +} + QT_END_NAMESPACE #include "moc_qgesturemanager_p.cpp" diff --git a/src/gui/kernel/qgesturemanager_p.h b/src/gui/kernel/qgesturemanager_p.h index 762b70d..18eed71 100644 --- a/src/gui/kernel/qgesturemanager_p.h +++ b/src/gui/kernel/qgesturemanager_p.h @@ -82,9 +82,11 @@ protected: void timerEvent(QTimerEvent *event); private slots: - void recognizerTriggered(QGestureRecognizer::Result); + void recognizerStateChanged(QGestureRecognizer::Result); private: + bool sendGestureEvent(QWidget *receiver, QGestureEvent *event); + QSet<QGestureRecognizer*> activeGestures; QMap<QGestureRecognizer*, int> maybeGestures; QSet<QGestureRecognizer*> recognizers; diff --git a/src/gui/kernel/qgesturerecognizer.cpp b/src/gui/kernel/qgesturerecognizer.cpp new file mode 100644 index 0000000..9a00138 --- /dev/null +++ b/src/gui/kernel/qgesturerecognizer.cpp @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgesturerecognizer.h" +#include "qgesture.h" + +#include <private/qobject_p.h> +#include <private/qgesturerecognizer_p.h> + +QT_BEGIN_NAMESPACE + +QString qt_getStandardGestureTypeName(Qt::GestureType gestureType); + +QGestureRecognizerPrivate::QGestureRecognizerPrivate() + : gestureType(Qt::UnknownGesture) +{ +} + +QGestureRecognizer::QGestureRecognizer(const QString &type) + : QObject(*new QGestureRecognizerPrivate, 0) +{ + d_func()->customGestureType = type; +} + +QString QGestureRecognizer::gestureType() const +{ + Q_D(const QGestureRecognizer); + if (d->gestureType == Qt::UnknownGesture) + return d->customGestureType; + return qt_getStandardGestureTypeName(d->gestureType); +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qgesturerecognizer.h b/src/gui/kernel/qgesturerecognizer.h index ca8972b..c0d4f5e 100644 --- a/src/gui/kernel/qgesturerecognizer.h +++ b/src/gui/kernel/qgesturerecognizer.h @@ -42,7 +42,6 @@ #ifndef QGESTURERECOGNIZER_H #define QGESTURERECOGNIZER_H -#include "qgesture.h" #include "qevent.h" #include "qlist.h" #include "qset.h" @@ -59,18 +58,18 @@ QT_BEGIN_NAMESPACE Usually gesture recognizer implements state machine, storing its state internally in the recognizer object. The recognizer receives - input events through the QGestureRecognizer::recognize() virtual + input events through the QGestureRecognizer::filterEvent() virtual function and decides whether the parsed event should change the state of the recognizer - i.e. if the event starts or ends a gesture or if it isn't related to gesture at all. */ -/*! \fn Qt::GestureType gestureType() const +/*! \fn QString gestureType() const Returns the name of the gesture that is handled by the recognizer. */ -/*! \fn Result recognize(const QList<QEvent*> &events) +/*! \fn Result filterEvent(const QEvent *event) This is a pure virtual function that need to be implemented in subclasses. @@ -79,7 +78,7 @@ QT_BEGIN_NAMESPACE sequence is a gesture or not. */ -/*! \fn QGesture* makeEvent() const +/*! \fn QGesture* getGesture() Creates a new gesture object that will be send to the widget. This function is called when the gesture recognizer returned a @@ -94,16 +93,20 @@ QT_BEGIN_NAMESPACE Resets the internal state of the gesture recognizer. */ -/*! \fn void triggered(QGestureRecognizer::Result result) +/*! \fn void stateChanged(QGestureRecognizer::Result result) The gesture recognizer might emit the signal when the gesture state changes asynchronously, i.e. without any event being received. */ +class QGesture; +class QGestureRecognizerPrivate; class Q_GUI_EXPORT QGestureRecognizer : public QObject { Q_OBJECT + Q_DECLARE_PRIVATE(QGestureRecognizer) + public: enum Result { @@ -113,21 +116,21 @@ public: MaybeGesture }; - inline QGestureRecognizer() { } - //### remove this ctor - inline QGestureRecognizer(const char *type) : type_(QLatin1String(type)) { } - inline QGestureRecognizer(const Qt::GestureType &type) : type_(type) { } - inline Qt::GestureType gestureType() const { return type_; } + explicit QGestureRecognizer(const QString &type); + + QString gestureType() const; - virtual Result recognize(const QList<QEvent*> &events) = 0; - virtual QGesture* makeEvent() const = 0; + virtual Result filterEvent(const QEvent* event) = 0; + virtual QGesture* getGesture() = 0; virtual void reset() = 0; signals: - void triggered(QGestureRecognizer::Result result); + void stateChanged(QGestureRecognizer::Result result); -protected: - Qt::GestureType type_; +private: + friend class QDoubleTapGestureRecognizer; + friend class QTapAndHoldGestureRecognizer; + friend class QGestureRecognizerPan; }; QT_END_NAMESPACE diff --git a/src/gui/kernel/qgesturerecognizer_p.h b/src/gui/kernel/qgesturerecognizer_p.h new file mode 100644 index 0000000..4d80b99 --- /dev/null +++ b/src/gui/kernel/qgesturerecognizer_p.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGESTURERECOGNIZER_P_H +#define QGESTURERECOGNIZER_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 <private/qobject_p.h> + +QT_BEGIN_NAMESPACE + +class QGestureRecognizerPrivate : public QObjectPrivate +{ +public: + QGestureRecognizerPrivate(); + +public: + Qt::GestureType gestureType; + QString customGestureType; +}; + +QT_END_NAMESPACE + +#endif // QGESTURERECOGNIZER_P_H diff --git a/src/gui/kernel/qgesturestandardrecognizers.cpp b/src/gui/kernel/qgesturestandardrecognizers.cpp index 504786a..718bdfd 100644 --- a/src/gui/kernel/qgesturestandardrecognizers.cpp +++ b/src/gui/kernel/qgesturestandardrecognizers.cpp @@ -41,6 +41,7 @@ #include "qgesturestandardrecognizers_p.h" #include "qgesture_p.h" +#include "qgesturerecognizer_p.h" // #define GESTURE_RECOGNIZER_DEBUG #ifndef GESTURE_RECOGNIZER_DEBUG @@ -50,205 +51,92 @@ #endif QT_BEGIN_NAMESPACE -/* -QGestureRecognizerMouseTwoButtons::QGestureRecognizerMouseTwoButtons() - : QGestureRecognizer(Qt::MouseTwoButtonClick) -{ - clear(); -} -QGestureRecognizer::Result QGestureRecognizerMouseTwoButtons::recognize(const QList<QEvent*> &inputEvents) +QString qt_getStandardGestureTypeName(Qt::GestureType gestureType) { - // get all mouse events - QList<QMouseEvent*> events; - for(int i = 0; i < inputEvents.count(); ++i) { - QEvent *event = inputEvents.at(i); - switch (event->type()) { - case QEvent::MouseButtonPress: - case QEvent::MouseButtonRelease: - events.push_back(static_cast<QMouseEvent*>(event)); - default: - break; - } - } - - QGestureRecognizer::Result result = QGestureRecognizer::NotGesture; - for(int i = 0; i < events.count(); ++i) { - QMouseEvent *event = events.at(i); - if (event->type() == QEvent::MouseButtonPress) { - if (userEvents[3]) { - // something wrong, we already has a gesture. - clear(); - } else if (userEvents[2]) { - // 1d, 2d, 1u, and user press another button. not gesture. - DEBUG() << "1"; - result = QGestureRecognizer::NotGesture; - clear(); - break; - } else if (userEvents[1]) { - // 1d, 2d, and user pressed third button. not gesture. - DEBUG() << "2"; - result = QGestureRecognizer::NotGesture; - clear(); - break; - } else if (userEvents[0]) { - // second button press. - DEBUG() << "3"; - userEvents[1] = event; - result = QGestureRecognizer::MaybeGesture; - } else { - // first button press. - DEBUG() << "4"; - userEvents[0] = event; - result = QGestureRecognizer::MaybeGesture; - } - } else if (event->type() == QEvent::MouseButtonRelease) { - if (userEvents[3]) { - // something wrong, we already has a gesture. - clear(); - } else if (userEvents[2]) { - // 1d, 2d, 1u, and button release - DEBUG() << "5"; - if (userEvents[1]->button() != event->button()) { - // got weird buttonreleased event. doesn't look like gesture. - result = QGestureRecognizer::NotGesture; - clear(); - break; - } - // gesture! - userEvents[3] = event; - result = QGestureRecognizer::GestureFinished; - break; - } else if (userEvents[1]) { - // 1d, 2d, and button release - DEBUG() << "6"; - if (userEvents[0]->button() != event->button()) { - // user released the wrong button. not gesture. - result = QGestureRecognizer::NotGesture; - clear(); - break; - } - // user released the right button! looks like gesture - userEvents[2] = event; - result = QGestureRecognizer::MaybeGesture; - } else if (userEvents[0]) { - // 1d, and some button was released. not a gesture. - DEBUG() << "7"; - result = QGestureRecognizer::NotGesture; - clear(); - break; - } - } + switch (gestureType) { + case Qt::TapGesture: + return QLatin1String("__QTapGesture"); + case Qt::DoubleTapGesture: + return QLatin1String("__QDoubleTapGesture"); + case Qt::TrippleTapGesture: + return QLatin1String("__QTrippleTapGesture"); + case Qt::TapAndHoldGesture: + return QLatin1String("__QTapAndHoldGesture"); + case Qt::PanGesture: + return QLatin1String("__QPanGesture"); + case Qt::PinchGesture: + return QLatin1String("__QPinchGesture"); + case Qt::UnknownGesture: + break; } - return result; -} - -QGesture* QGestureRecognizerMouseTwoButtons::makeEvent() const -{ - if (!userEvents[0] || !userEvents[1] || !userEvents[2] || !userEvents[3]) - return 0; - QGesture::Direction direction = - (userEvents[0]->button() < userEvents[1]->button() ? - QGesture::Left : QGesture::Right); - QList<QPoint> points; - points.push_back(userEvents[0]->globalPos()); - points.push_back(userEvents[1]->globalPos()); - QGesture *gesture = - new QGesture(Qt::MouseTwoButtonClick, points.at(0), points.at(1), points.at(1), - direction, - QRect(points.at(0), points.at(1)), - points.at(0)); - return gesture; + qFatal("QGestureRecognizer::gestureType: got an unhandled gesture type."); + return QLatin1String("__unknown_gesture"); } -void QGestureRecognizerMouseTwoButtons::reset() -{ - clear(); -} - -void QGestureRecognizerMouseTwoButtons::clear() -{ - userEvents[0] = userEvents[1] = userEvents[2] = userEvents[3] = 0; -} -*/ - // // QGestureRecognizerPan // QGestureRecognizerPan::QGestureRecognizerPan() - : QGestureRecognizer(Qt::Pan), mousePressed(false), gestureFinished(false), + : QGestureRecognizer(QString()), mousePressed(false), gestureFinished(false), lastDirection(Direction::None), currentDirection(Direction::None) { + Q_D(QGestureRecognizer); + d->gestureType = Qt::PanGesture; } -QGestureRecognizer::Result QGestureRecognizerPan::recognize(const QList<QEvent*> &inputEvents) +QGestureRecognizer::Result QGestureRecognizerPan::filterEvent(const QEvent *event) { - // get all mouse events - QList<QMouseEvent*> events; - for(int i = 0; i < inputEvents.count(); ++i) { - QEvent *event = inputEvents.at(i); - switch (event->type()) { - case QEvent::MouseButtonPress: - case QEvent::MouseButtonRelease: - case QEvent::MouseMove: - events.push_back(static_cast<QMouseEvent*>(event)); - default: - break; - } - } - - QGestureRecognizer::Result result = QGestureRecognizer::NotGesture; - for(int i = 0; i < events.count(); ++i) { - QMouseEvent *event = events.at(i); - if (event->type() == QEvent::MouseButtonPress) { - if (currentDirection != Direction::None) { - DEBUG() << "Pan: MouseButtonPress: fail. another press during pan"; - result = QGestureRecognizer::NotGesture; - reset(); - break; - } - DEBUG() << "Pan: MouseButtonPress: maybe gesture started"; - result = QGestureRecognizer::MaybeGesture; - mousePressed = true; - pressedPos = lastPos = currentPos = event->pos(); - } else if (event->type() == QEvent::MouseButtonRelease) { - if (mousePressed && currentDirection != Direction::None) { - DEBUG() << "Pan: MouseButtonRelease: pan detected"; - result = QGestureRecognizer::GestureFinished; - gestureFinished = true; - currentPos = event->pos(); - internalReset(); - break; - } - DEBUG() << "Pan: MouseButtonRelease: some weird release detected, ignoring"; - result = QGestureRecognizer::NotGesture; + if (event->type() == QEvent::MouseButtonPress) { + const QMouseEvent *ev = static_cast<const QMouseEvent*>(event); + if (currentDirection != Direction::None) { + DEBUG() << "Pan: MouseButtonPress: fail. another press during pan"; reset(); - break; - } else if (event->type() == QEvent::MouseMove) { - if (!mousePressed) - continue; - lastPos = currentPos; - currentPos = event->pos(); - Direction::DirectionType direction = - simpleRecognizer.addPosition(event->pos()).direction; - DEBUG() << "Pan: MouseMove: simplerecognizer result = " << direction; - if (currentDirection == Direction::None) { - if (direction == Direction::None) - result = QGestureRecognizer::MaybeGesture; - else - result = QGestureRecognizer::GestureStarted; - } else { + return QGestureRecognizer::NotGesture; + } + DEBUG() << "Pan: MouseButtonPress: maybe gesture started"; + mousePressed = true; + pressedPos = lastPos = currentPos = ev->pos(); + return QGestureRecognizer::MaybeGesture; + } else if (event->type() == QEvent::MouseButtonRelease) { + if (mousePressed && currentDirection != Direction::None) { + DEBUG() << "Pan: MouseButtonRelease: pan detected"; + gestureFinished = true; + const QMouseEvent *ev = static_cast<const QMouseEvent*>(event); + currentPos = ev->pos(); + internalReset(); + return QGestureRecognizer::GestureFinished; + } + DEBUG() << "Pan: MouseButtonRelease: some weird release detected, ignoring"; + reset(); + return QGestureRecognizer::NotGesture; + } else if (event->type() == QEvent::MouseMove) { + if (!mousePressed) + return QGestureRecognizer::NotGesture; + const QMouseEvent *ev = static_cast<const QMouseEvent*>(event); + lastPos = currentPos; + currentPos = ev->pos(); + Direction::DirectionType direction = + simpleRecognizer.addPosition(ev->pos()).direction; + DEBUG() << "Pan: MouseMove: simplerecognizer result = " << direction; + QGestureRecognizer::Result result = QGestureRecognizer::NotGesture; + if (currentDirection == Direction::None) { + if (direction == Direction::None) + result = QGestureRecognizer::MaybeGesture; + else result = QGestureRecognizer::GestureStarted; - } - if (direction != Direction::None) { - if (currentDirection != direction) - lastDirection = currentDirection; - currentDirection = direction; - } + } else { + result = QGestureRecognizer::GestureStarted; } + if (direction != Direction::None) { + if (currentDirection != direction) + lastDirection = currentDirection; + currentDirection = direction; + } + return result; } - return result; + return QGestureRecognizer::NotGesture; } static inline QPannableGesture::DirectionType convertPanningDirection(const Direction::DirectionType direction) @@ -268,17 +156,18 @@ static inline QPannableGesture::DirectionType convertPanningDirection(const Dire return QPannableGesture::None; } -QGesture* QGestureRecognizerPan::makeEvent() const +QGesture* QGestureRecognizerPan::getGesture() { QPannableGesture::DirectionType dir = convertPanningDirection(currentDirection); QPannableGesture::DirectionType lastDir = convertPanningDirection(lastDirection); if (dir == QPannableGesture::None) return 0; QPannableGesture *g = - new QPannableGesture(Qt::Pan, pressedPos, lastPos, currentPos, + new QPannableGesture(this, + pressedPos, lastPos, currentPos, QRect(), pressedPos, QDateTime(), 0, gestureFinished ? Qt::GestureFinished : Qt::GestureStarted); - QPannableGesturePrivate *d = (QPannableGesturePrivate*)g->d; + QPannableGesturePrivate *d = g->d_func(); d->lastDirection = lastDir; d->direction = dir; @@ -307,52 +196,37 @@ void QGestureRecognizerPan::internalReset() // QDoubleTapGestureRecognizer // QDoubleTapGestureRecognizer::QDoubleTapGestureRecognizer() - : QGestureRecognizer(Qt::DoubleTap) + : QGestureRecognizer(QString()) { + Q_D(QGestureRecognizer); + d->gestureType = Qt::DoubleTapGesture; } -QGestureRecognizer::Result QDoubleTapGestureRecognizer::recognize(const QList<QEvent*> &inputEvents) +QGestureRecognizer::Result QDoubleTapGestureRecognizer::filterEvent(const QEvent *event) { - // get all mouse events - QList<QMouseEvent*> events; - for(int i = 0; i < inputEvents.count(); ++i) { - QEvent *event = inputEvents.at(i); - switch (event->type()) { - case QEvent::MouseButtonPress: - case QEvent::MouseButtonRelease: - case QEvent::MouseButtonDblClick: - case QEvent::MouseMove: - events.push_back(static_cast<QMouseEvent*>(event)); - default: - break; - } - } - - QGestureRecognizer::Result result = QGestureRecognizer::NotGesture; - for(int i = 0; i < events.count(); ++i) { - QMouseEvent *event = events.at(i); - if (event->type() == QEvent::MouseButtonPress) { - if (pressedPosition.isNull()) { - result = QGestureRecognizer::MaybeGesture; - pressedPosition = event->pos(); - } else if ((pressedPosition - event->pos()).manhattanLength() < 10) { - result = QGestureRecognizer::GestureFinished; - } - } else if (event->type() == QEvent::MouseButtonRelease) { - if (!pressedPosition.isNull() && (pressedPosition - event->pos()).manhattanLength() < 10) - result = QGestureRecognizer::MaybeGesture; - } else if (event->type() == QEvent::MouseButtonDblClick) { - result = QGestureRecognizer::GestureFinished; - pressedPosition = event->pos(); - break; + if (event->type() == QEvent::MouseButtonPress) { + const QMouseEvent *ev = static_cast<const QMouseEvent*>(event); + if (pressedPosition.isNull()) { + pressedPosition = ev->pos(); + return QGestureRecognizer::MaybeGesture; + } else if ((pressedPosition - ev->pos()).manhattanLength() < 10) { + return QGestureRecognizer::GestureFinished; } + } else if (event->type() == QEvent::MouseButtonRelease) { + const QMouseEvent *ev = static_cast<const QMouseEvent*>(event); + if (!pressedPosition.isNull() && (pressedPosition - ev->pos()).manhattanLength() < 10) + return QGestureRecognizer::MaybeGesture; + } else if (event->type() == QEvent::MouseButtonDblClick) { + const QMouseEvent *ev = static_cast<const QMouseEvent*>(event); + pressedPosition = ev->pos(); + return QGestureRecognizer::GestureFinished; } - return result; + return QGestureRecognizer::NotGesture; } -QGesture* QDoubleTapGestureRecognizer::makeEvent() const +QGesture* QDoubleTapGestureRecognizer::getGesture() { - return new QGesture(Qt::DoubleTap, + return new QGesture(this, qt_getStandardGestureTypeName(Qt::DoubleTapGesture), pressedPosition, pressedPosition, pressedPosition, QRect(), pressedPosition, QDateTime(), 0, Qt::GestureFinished); } @@ -363,195 +237,66 @@ void QDoubleTapGestureRecognizer::reset() } // -// QLongTapGestureRecognizer +// QTapAndHoldGestureRecognizer // -const int QLongTapGestureRecognizer::iterationCount = 40; -const int QLongTapGestureRecognizer::iterationTimeout = 50; +const int QTapAndHoldGestureRecognizer::iterationCount = 40; +const int QTapAndHoldGestureRecognizer::iterationTimeout = 50; -QLongTapGestureRecognizer::QLongTapGestureRecognizer() - : QGestureRecognizer(Qt::LongTap), iteration(0) +QTapAndHoldGestureRecognizer::QTapAndHoldGestureRecognizer() + : QGestureRecognizer(QString()), iteration(0) { + Q_D(QGestureRecognizer); + d->gestureType = Qt::TapAndHoldGesture; } -QGestureRecognizer::Result QLongTapGestureRecognizer::recognize(const QList<QEvent*> &inputEvents) +QGestureRecognizer::Result QTapAndHoldGestureRecognizer::filterEvent(const QEvent *event) { - // get all mouse events - QList<QMouseEvent*> events; - for(int i = 0; i < inputEvents.count(); ++i) { - QEvent *event = inputEvents.at(i); - switch (event->type()) { - case QEvent::MouseButtonPress: - case QEvent::MouseButtonRelease: - case QEvent::MouseMove: - events.push_back(static_cast<QMouseEvent*>(event)); - default: - break; - } - } - - QGestureRecognizer::Result result = QGestureRecognizer::NotGesture; - for(int i = 0; i < events.count(); ++i) { - QMouseEvent *event = events.at(i); - if (event->type() == QEvent::MouseButtonPress) { - if (timer.isActive()) - timer.stop(); - timer.start(QLongTapGestureRecognizer::iterationTimeout, this); - pressedPosition = event->pos(); - result = QGestureRecognizer::MaybeGesture; - } else if (event->type() == QEvent::MouseMove) { - if ((pressedPosition - event->pos()).manhattanLength() < 15) - result = QGestureRecognizer::GestureStarted; - else - result = QGestureRecognizer::NotGesture; - } else if (event->type() == QEvent::MouseButtonRelease) { - result = QGestureRecognizer::NotGesture; + if (event->type() == QEvent::MouseButtonPress) { + const QMouseEvent *ev = static_cast<const QMouseEvent*>(event); + if (timer.isActive()) timer.stop(); - break; - } + timer.start(QTapAndHoldGestureRecognizer::iterationTimeout, this); + pressedPosition = ev->pos(); + return QGestureRecognizer::MaybeGesture; + } else if (event->type() == QEvent::MouseMove) { + const QMouseEvent *ev = static_cast<const QMouseEvent*>(event); + if ((pressedPosition - ev->pos()).manhattanLength() < 15) + return QGestureRecognizer::GestureStarted; + else + return QGestureRecognizer::NotGesture; + } else if (event->type() == QEvent::MouseButtonRelease) { + timer.stop(); + return QGestureRecognizer::NotGesture; } - return result; + return QGestureRecognizer::NotGesture; } -void QLongTapGestureRecognizer::timerEvent(QTimerEvent *event) +void QTapAndHoldGestureRecognizer::timerEvent(QTimerEvent *event) { if (event->timerId() != timer.timerId()) return; - if (++iteration == QLongTapGestureRecognizer::iterationCount) { - emit triggered(QGestureRecognizer::GestureFinished); + if (++iteration == QTapAndHoldGestureRecognizer::iterationCount) { + emit stateChanged(QGestureRecognizer::GestureFinished); timer.stop(); } else { - emit triggered(QGestureRecognizer::GestureStarted); + emit stateChanged(QGestureRecognizer::GestureStarted); } } -QGesture* QLongTapGestureRecognizer::makeEvent() const +QGesture* QTapAndHoldGestureRecognizer::getGesture() { - return new QGesture(Qt::LongTap, + return new QGesture(this, qt_getStandardGestureTypeName(Qt::TapAndHoldGesture), pressedPosition, pressedPosition, pressedPosition, QRect(), pressedPosition, QDateTime(), 0, - iteration >= QLongTapGestureRecognizer::iterationCount ? + iteration >= QTapAndHoldGestureRecognizer::iterationCount ? Qt::GestureFinished : Qt::GestureStarted); } -void QLongTapGestureRecognizer::reset() +void QTapAndHoldGestureRecognizer::reset() { pressedPosition = QPoint(); timer.stop(); iteration = 0; } -// -// QMultiTouchGestureRecognizer -// - -/* -QMultiTouchGestureRecognizer::QMultiTouchGestureRecognizer() - : QGestureRecognizer(Qt::Pinch) -{ -} - -QGestureRecognizer::Result QMultiTouchGestureRecognizer::recognize(const QList<QEvent*> &inputEvents) -{ - QGestureRecognizer::Result result = QGestureRecognizer::NotGesture; - for(int i = 0; i < inputEvents.count(); ++i) { - QEvent *inputEvent = inputEvents.at(i); - if (inputEvent->type() != QEvent::Pointer) { - if (touches.size() == 2) - result = QGestureRecognizer::GestureStarted; - else if (touches.size() == 1) - result = QGestureRecognizer::MaybeGesture; - continue; - } - QPointerEvent *event = static_cast<QPointerEvent*>(inputEvent); - Q_ASSERT(event->pointerCount() > 0); - for (int idx = 0; idx < event->pointerCount(); ++idx) { - switch (event->state(idx)) { - case QPointerEvent::Begin: - qDebug() << "Begin" << idx; - if (touches.size() == 2) { - // too many touches - qDebug() << "too many touches"; - result = QGestureRecognizer::MaybeGesture; - continue; - } - touches[event->pointerId(idx)].startPosition = event->pos(idx); - if (touches.size() == 1) { - result = QGestureRecognizer::MaybeGesture; - } else if (touches.size() == 2) { - result = QGestureRecognizer::GestureStarted; - } else { - result = QGestureRecognizer::NotGesture; - } - break; - - case QPointerEvent::Move: - qDebug() << "Move" << idx; - touches[event->pointerId(idx)].lastPosition = touches[event->pointerId(idx)].currentPosition; - touches[event->pointerId(idx)].currentPosition = event->pos(idx); - if (touches.size() == 1) - result = QGestureRecognizer::MaybeGesture; - else if (touches.size() == 2) - result = QGestureRecognizer::GestureStarted; - else - result = QGestureRecognizer::NotGesture; - break; - - case QPointerEvent::End: - qDebug() << "End" << idx; - touches.remove(event->pointerId(idx)); - if (touches.size() == 1) { - result = QGestureRecognizer::MaybeGesture; - } else if (touches.size() == 0) { - result = QGestureRecognizer::NotGesture; - } else { - qDebug() << "unexpected touch end event"; - return QGestureRecognizer::NotGesture; - } - break; - - case QPointerEvent::Stationary: - qDebug() << "Stationary" << idx; - if (touches.size() == 2) - result = QGestureRecognizer::GestureStarted; - else if (touches.size() == 1) - result = QGestureRecognizer::MaybeGesture; - break; - - default: - break; - } - } - } - return result; -} - -QGesture* QMultiTouchGestureRecognizer::makeEvent() const -{ - if (touches.size() != 2) - return 0; - - QGesture *g = new QGesture(Qt::Pinch); - QGesture::Data data; - - TapMap::const_iterator it = touches.begin(); - data.startPos = it->startPosition.toPoint(); - data.lastPos = it->lastPosition.toPoint(); - data.currentPos = it->currentPosition.toPoint(); - g->datas.push_back(data); - - ++it; - data.startPos = it->startPosition.toPoint(); - data.lastPos = it->lastPosition.toPoint(); - data.currentPos = it->currentPosition.toPoint(); - g->datas.push_back(data); - - return g; -} - -void QMultiTouchGestureRecognizer::reset() -{ - touches.clear(); -} -*/ - QT_END_NAMESPACE diff --git a/src/gui/kernel/qgesturestandardrecognizers_p.h b/src/gui/kernel/qgesturestandardrecognizers_p.h index 567cf65..75a206a 100644 --- a/src/gui/kernel/qgesturestandardrecognizers_p.h +++ b/src/gui/kernel/qgesturestandardrecognizers_p.h @@ -62,34 +62,14 @@ QT_BEGIN_NAMESPACE -/* -class QGestureRecognizerMouseTwoButtons : public QGestureRecognizer -{ - Q_OBJECT -public: - QGestureRecognizerMouseTwoButtons(); - QGestureRecognizer::Result recognize(const QList<QEvent*> &inputEvents); - - QGesture* makeEvent() const; - void reset(); - -private: - void clear(); - - // find the last two button click events - QMouseEvent* userEvents[4]; -}; -*/ - class QGestureRecognizerPan : public QGestureRecognizer { Q_OBJECT public: QGestureRecognizerPan(); - QGestureRecognizer::Result recognize(const QList<QEvent*> &inputEvents); - QGesture* makeEvent() const; - + QGestureRecognizer::Result filterEvent(const QEvent *event); + QGesture* getGesture(); void reset(); private: @@ -112,22 +92,22 @@ class QDoubleTapGestureRecognizer : public QGestureRecognizer public: QDoubleTapGestureRecognizer(); - QGestureRecognizer::Result recognize(const QList<QEvent*> &inputEvents); - QGesture* makeEvent() const; + QGestureRecognizer::Result filterEvent(const QEvent *event); + QGesture* getGesture(); void reset(); private: QPoint pressedPosition; }; -class QLongTapGestureRecognizer : public QGestureRecognizer +class QTapAndHoldGestureRecognizer : public QGestureRecognizer { Q_OBJECT public: - QLongTapGestureRecognizer(); + QTapAndHoldGestureRecognizer(); - QGestureRecognizer::Result recognize(const QList<QEvent*> &inputEvents); - QGesture* makeEvent() const; + QGestureRecognizer::Result filterEvent(const QEvent *event); + QGesture* getGesture(); void reset(); protected: @@ -141,30 +121,6 @@ private: static const int iterationTimeout; }; -/* -class QMultiTouchGestureRecognizer : public QGestureRecognizer -{ - Q_OBJECT -public: - QMultiTouchGestureRecognizer(); - - QMap<Qt::GestureType, int> maybeGestureCompletion(); - QGestureRecognizer::Result recognize(const QList<QEvent*> &inputEvents); - QGesture* makeEvent() const; - void reset(); - -private: - struct Tap { - //### should I use QPointF everywhere internally ?? - QPointF startPosition; - QPointF lastPosition; - QPointF currentPosition; - }; - typedef QMap<int, Tap> TapMap; - TapMap touches; -}; -*/ - QT_END_NAMESPACE #endif // QGESTURESTANDARDRECOGNIZERS_P_H diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index aea0003..2f794f4 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -127,6 +127,8 @@ Q_GUI_EXPORT void qt_x11_set_global_double_buffer(bool enable) } #endif +QString qt_getStandardGestureTypeName(Qt::GestureType); + static inline bool qRectIntersects(const QRect &r1, const QRect &r2) { return (qMax(r1.left(), r2.left()) <= qMin(r1.right(), r2.right()) && @@ -11026,60 +11028,56 @@ QWindowSurface *QWidget::windowSurface() const } /*! - \fn void QWidget::grabGesture(const Qt::GestureType &gesture) - Subscribes the widget to the specified \a gesture type. + + Returns the id of the gesture. */ -void QWidget::grabGesture(const Qt::GestureType &gesture) +int QWidget::grabGesture(const QString &gesture) { Q_D(QWidget); - if (d->gestures.contains(gesture)) - return; - d->gestures << gesture; - ++qApp->d_func()->grabbedGestures[gesture]; + return d->grabGesture(qHash(gesture)); +} + +int QWidgetPrivate::grabGesture(int id) +{ + QSet<int>::iterator it = gestures.find(id); + if (it != gestures.end()) + return *it; + gestures << id; + ++qApp->d_func()->grabbedGestures[id]; + return id; } /*! - \fn void QWidget::grabGestures(const QSet<Qt::GestureType> &gestures) + Subscribes the widget to the specified \a gesture type. - Subscribes the widget to the specified list of \a gestures. + Returns the id of the gesture. */ -void QWidget::grabGestures(const QSet<Qt::GestureType> &gestures) + +int QWidget::grabGesture(Qt::GestureType gesture) { - Q_D(QWidget); - foreach(const Qt::GestureType &gesture, gestures) { - if (!d->gestures.contains(gesture)) - ++qApp->d_func()->grabbedGestures[gesture]; - } - d->gestures.unite(gestures); + return grabGesture(qt_getStandardGestureTypeName(gesture)); } /*! - \fn void QWidget::releaseGesture(const Qt::GestureType &gesture) - - Unsubscribes the widget from the specified \a gesture type. + Unsubscribes the widget from a gesture, which is specified by its + \a id. */ -void QWidget::releaseGesture(const Qt::GestureType &gesture) +void QWidget::releaseGesture(int gestureId) { Q_D(QWidget); - QMap<Qt::GestureType, int>::iterator it = - qApp->d_func()->grabbedGestures.find(gesture); - if (it != qApp->d_func()->grabbedGestures.end() && - d->gestures.contains(gesture)) - ++it.value(); - d->gestures.remove(gesture); + QSet<int>::iterator it = d->gestures.find(gestureId); + if (it != d->gestures.end()) { + Q_ASSERT(qApp->d_func()->grabbedGestures[gestureId] > 0); + --qApp->d_func()->grabbedGestures[gestureId]; + d->gestures.erase(it); + } } -/*! - \fn QSet<Qt::GestureType> QWidget::gestures() const - - Returns a list of gestures that the widget is subscribed to. -*/ -QSet<Qt::GestureType> QWidget::gestures() const +void setGestureEnabled(int gestureId, bool enable) { - Q_D(const QWidget); - return d->gestures; + //### } void QWidgetPrivate::getLayoutItemMargins(int *left, int *top, int *right, int *bottom) const diff --git a/src/gui/kernel/qwidget.h b/src/gui/kernel/qwidget.h index e36b966..a76c50a 100644 --- a/src/gui/kernel/qwidget.h +++ b/src/gui/kernel/qwidget.h @@ -613,10 +613,10 @@ public: void setWindowSurface(QWindowSurface *surface); QWindowSurface *windowSurface() const; - void grabGesture(const Qt::GestureType &gesture); - void grabGestures(const QSet<Qt::GestureType> &gestures); - void releaseGesture(const Qt::GestureType &gesture); - QSet<Qt::GestureType> gestures() const; + int grabGesture(const QString &gesture); + int grabGesture(Qt::GestureType gesture); + void releaseGesture(int gestureId); + void setGestureEnabled(int gestureId, bool enable); Q_SIGNALS: void customContextMenuRequested(const QPoint &pos); @@ -755,6 +755,7 @@ private: friend bool isWidgetOpaque(const QWidget *); friend class QGLWidgetPrivate; #endif + friend class QGestureManager; #ifdef Q_WS_X11 friend void qt_net_update_user_time(QWidget *tlw, unsigned long timestamp); friend void qt_net_remove_user_time(QWidget *tlw); diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 178f7ba..abd7b8a 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -593,7 +593,8 @@ public: uint isGLWidget : 1; #endif - QSet<Qt::GestureType> gestures; + QSet<int> gestures; + int grabGesture(int gestureId); #if defined(Q_WS_X11) || defined (Q_WS_WIN) || defined(Q_WS_MAC) #ifdef Q_WS_MAC |