From ce851964f45266cafd51f2c1ac4e9a7d89ce0ef0 Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Tue, 12 May 2009 11:39:16 +0200 Subject: Replaced evil foreach with a for loop. --- src/gui/kernel/qgesturemanager.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp index c7341f2..1dda34c 100644 --- a/src/gui/kernel/qgesturemanager.cpp +++ b/src/gui/kernel/qgesturemanager.cpp @@ -248,11 +248,15 @@ bool QGestureManager::filterEvent(QWidget *receiver, QEvent *event) activeGestures -= newMaybeGestures; activeGestures -= cancelledGestures; activeGestures += startedGestures; - foreach(QGestureRecognizer *r, startedGestures+finishedGestures+notGestures) { - QMap::iterator it = maybeGestures.find(r); - if (it != maybeGestures.end()) { + for(QMap::iterator it = maybeGestures.begin(); + it != maybeGestures.end();) { + QGestureRecognizer *r = it.key(); + if (startedGestures.contains(r) || finishedGestures.contains(r) || + notGestures.contains(r)) { killTimer(it.value()); - maybeGestures.erase(it); + it = maybeGestures.erase(it); + } else { + ++it; } } foreach(QGestureRecognizer *r, newMaybeGestures) { -- cgit v0.12 From 20b05e38c4f364e4d21dab79a4f66103e6fb2dc3 Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Tue, 12 May 2009 14:09:59 +0200 Subject: Mentioned in the doc that the QGesture pointer that is returned by the QGestureRecognizer *must* be the same object for a gesture sequence (i.e. GestureStarted, GestureUpdated and GestureFinished should use the same object) --- src/gui/kernel/qgesturerecognizer.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/gui/kernel/qgesturerecognizer.cpp b/src/gui/kernel/qgesturerecognizer.cpp index 41160cd..879f557 100644 --- a/src/gui/kernel/qgesturerecognizer.cpp +++ b/src/gui/kernel/qgesturerecognizer.cpp @@ -108,6 +108,9 @@ QString qt_getStandardGestureTypeName(Qt::GestureType gestureType); to QGestureRecognizer::GestureStarted or QGestureRecognizer::GestureFinished. + The returned QGesture object must point to the same object in a + single gesture sequence. + The gesture object is owned by the recognizer itself. */ -- cgit v0.12 From e599814feb5bc62c4a419d332bcca39bbea15190 Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Tue, 12 May 2009 16:38:08 +0200 Subject: Small improvement in gesturemanager and a fix for potential crash --- src/gui/kernel/qgesturemanager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp index 1dda34c..2750df4 100644 --- a/src/gui/kernel/qgesturemanager.cpp +++ b/src/gui/kernel/qgesturemanager.cpp @@ -519,7 +519,7 @@ bool QGestureManager::sendGestureEvent(QWidget *receiver, const QSet it != e; ++it) { QGesture *g = *it; QGesturePrivate *gd = g->d_func(); - if (!gd->widget && (g->state() == Qt::GestureStarted || g->state() == Qt::GestureFinished)) { + if (!gd->widget && (g->state() == Qt::GestureStarted || gd->singleshot)) { startedGestures.insert(g); // find the target widget QWidget *w = receiver; @@ -575,7 +575,7 @@ bool QGestureManager::sendGestureEvent(QWidget *receiver, const QSet QWidget *w = gd->widget; gd->widget = 0; - if (!w->isWindow()) { + if (w && !w->isWindow()) { g->translate(w->pos()); w = w->parentWidget(); QPoint offset; -- cgit v0.12 From 51bf6930372f3ff88c0b9a84a1bb55c458172385 Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Wed, 13 May 2009 10:49:59 +0200 Subject: Fixed mouse event propagation to widgets inside graphicsview - make sure spontaneous flag is preserved. --- src/gui/kernel/qapplication.cpp | 9 +++++++-- src/gui/kernel/qapplication_p.h | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index e46ccf1..f469c80 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -2876,7 +2876,8 @@ QWidget *QApplicationPrivate::pickMouseReceiver(QWidget *candidate, const QPoint */ bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event, QWidget *alienWidget, QWidget *nativeWidget, - QWidget **buttonDown, QPointer &lastMouseReceiver) + QWidget **buttonDown, QPointer &lastMouseReceiver, + bool spontaneous) { Q_ASSERT(receiver); Q_ASSERT(event); @@ -2929,7 +2930,11 @@ bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event, // We need this quard in case someone opens a modal dialog / popup. If that's the case // leaveAfterRelease is set to null, but we shall not update lastMouseReceiver. const bool wasLeaveAfterRelease = leaveAfterRelease != 0; - bool result = QApplication::sendSpontaneousEvent(receiver, event); + bool result; + if (spontaneous) + result = QApplication::sendSpontaneousEvent(receiver, event); + else + result = QApplication::sendEvent(receiver, event); if (!graphicsWidget && leaveAfterRelease && event->type() == QEvent::MouseButtonRelease && !event->buttons() && QWidget::mouseGrabber() != leaveAfterRelease) { diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h index 096c349..08020fb 100644 --- a/src/gui/kernel/qapplication_p.h +++ b/src/gui/kernel/qapplication_p.h @@ -424,7 +424,8 @@ public: QEvent::Type type, Qt::MouseButtons buttons, QWidget *buttonDown, QWidget *alienWidget); static bool sendMouseEvent(QWidget *receiver, QMouseEvent *event, QWidget *alienWidget, - QWidget *native, QWidget **buttonDown, QPointer &lastMouseReceiver); + QWidget *native, QWidget **buttonDown, QPointer &lastMouseReceiver, + bool spontaneous = true); #if defined(Q_WS_WIN) || defined(Q_WS_X11) void sendSyntheticEnterLeave(QWidget *widget); #endif -- cgit v0.12 From 8f1724f5b3b09f57e260518f644ebc002b065443 Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Thu, 14 May 2009 11:06:27 +0200 Subject: Don't export private class QGestureManager --- src/gui/kernel/qgesturemanager_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/kernel/qgesturemanager_p.h b/src/gui/kernel/qgesturemanager_p.h index 963edf9..18183e2 100644 --- a/src/gui/kernel/qgesturemanager_p.h +++ b/src/gui/kernel/qgesturemanager_p.h @@ -64,7 +64,7 @@ QT_BEGIN_NAMESPACE class QWidget; -class Q_GUI_EXPORT QGestureManager : public QObject +class Q_AUTOTEST_EXPORT QGestureManager : public QObject { Q_OBJECT public: -- cgit v0.12 From ac8e33994455200c369d8aa9d1853b618c225058 Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Thu, 14 May 2009 10:55:04 +0200 Subject: implemented gestures support in graphicsview for QGraphicsItems and QGraphicsProxyWidgets. This is still work-in-progress. --- src/gui/graphicsview/qgraphicsitem.cpp | 44 ++++++++-- src/gui/graphicsview/qgraphicsitem_p.h | 4 + src/gui/graphicsview/qgraphicsproxywidget.cpp | 16 +++- src/gui/graphicsview/qgraphicsscene.cpp | 120 +++++++++++++++++++++----- src/gui/graphicsview/qgraphicsscene_p.h | 5 +- src/gui/graphicsview/qgraphicssceneevent.cpp | 9 ++ src/gui/graphicsview/qgraphicssceneevent.h | 1 + src/gui/graphicsview/qgraphicsview.cpp | 1 + src/gui/kernel/qgesture.h | 2 + src/gui/kernel/qgesture_p.h | 4 +- src/gui/kernel/qgesturemanager.cpp | 38 ++++---- src/gui/kernel/qgesturemanager_p.h | 7 +- src/gui/kernel/qwidget.cpp | 22 ++++- src/gui/kernel/qwidget_p.h | 1 + 14 files changed, 216 insertions(+), 58 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index e2b8115..d9f450a 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -5802,6 +5802,7 @@ QVariant QGraphicsItem::inputMethodQuery(Qt::InputMethodQuery query) const */ int QGraphicsItem::grabGesture(Qt::GestureType gesture) { + /// TODO: if we are QGraphicsProxyWidget we should subscribe the widget to gesture as well. return grabGesture(qt_getStandardGestureTypeName(gesture)); } @@ -5817,12 +5818,30 @@ int QGraphicsItem::grabGesture(Qt::GestureType gesture) int QGraphicsItem::grabGesture(const QString &gesture) { int id = QGestureManager::instance()->makeGestureId(gesture); - d_ptr->gestures << id; - if (d_ptr->scene) - d_ptr->scene->d_func()->grabGesture(this, id); + d_ptr->grabGesture(id); return id; } +void QGraphicsItemPrivate::grabGesture(int id) +{ + Q_Q(QGraphicsItem); + gestures << id; + if (scene) + scene->d_func()->grabGesture(q, id); +} + +bool QGraphicsItemPrivate::releaseGesture(int id) +{ + Q_Q(QGraphicsItem); + if (gestures.contains(id)) { + if (scene) + scene->d_func()->releaseGesture(q, id); + gestures.remove(id); + return true; + } + return false; +} + /*! \since 4.6 @@ -5833,10 +5852,9 @@ int QGraphicsItem::grabGesture(const QString &gesture) */ void QGraphicsItem::releaseGesture(int gestureId) { - if (d_ptr->scene) - d_ptr->scene->d_func()->releaseGesture(this, gestureId); - QGestureManager::instance()->releaseGestureId(gestureId); - d_ptr->gestures.remove(gestureId); + /// TODO: if we are QGraphicsProxyWidget we should unsubscribe the widget from gesture as well. + if (d_ptr->releaseGesture(gestureId)) + QGestureManager::instance()->releaseGestureId(gestureId); } /*! @@ -5854,6 +5872,18 @@ void QGraphicsItem::setGestureEnabled(int gestureId, bool enable) //### } +bool QGraphicsItemPrivate::hasGesture(const QString &name) const +{ + QGestureManager *gm = QGestureManager::instance(); + QSet::const_iterator it = gestures.begin(), + e = gestures.end(); + for (; it != e; ++it) { + if (gm->gestureNameFromId(*it) == name) + return true; + } + return false; +} + /*! This virtual function is called by QGraphicsItem to notify custom items that some part of the item's state changes. By reimplementing this diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 1d3a316..e9e36fa 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -300,6 +300,10 @@ public: int depth; QSet gestures; + bool hasGesture(const QString &gesture) const; + void grabGesture(int id); + bool releaseGesture(int id); + // Packed 32 bytes quint32 acceptedMouseButtons : 5; quint32 visible : 1; diff --git a/src/gui/graphicsview/qgraphicsproxywidget.cpp b/src/gui/graphicsview/qgraphicsproxywidget.cpp index 01b7593..2d7490c 100644 --- a/src/gui/graphicsview/qgraphicsproxywidget.cpp +++ b/src/gui/graphicsview/qgraphicsproxywidget.cpp @@ -48,6 +48,7 @@ #include "private/qgraphicsproxywidget_p.h" #include "private/qwidget_p.h" #include "private/qapplication_p.h" +#include "private/qgesturemanager_p.h" #include #include @@ -275,7 +276,7 @@ void QGraphicsProxyWidgetPrivate::sendWidgetMouseEvent(QGraphicsSceneMouseEvent QWidget *embeddedMouseGrabberPtr = (QWidget *)embeddedMouseGrabber; QApplicationPrivate::sendMouseEvent(receiver, mouseEvent, alienWidget, widget, - &embeddedMouseGrabberPtr, lastWidgetUnderMouse); + &embeddedMouseGrabberPtr, lastWidgetUnderMouse, event->spontaneous()); embeddedMouseGrabber = embeddedMouseGrabberPtr; // Handle enter/leave events when last button is released from mouse @@ -648,6 +649,9 @@ void QGraphicsProxyWidgetPrivate::setWidget_helper(QWidget *newWidget, bool auto q->setAttribute(Qt::WA_OpaquePaintEvent); widget = newWidget; + foreach(int gestureId, widget->d_func()->gestures) { + grabGesture(gestureId); + } // Changes only go from the widget to the proxy. enabledChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode; @@ -871,6 +875,16 @@ bool QGraphicsProxyWidget::event(QEvent *event) } break; } + case QEvent::GraphicsSceneGesture: { + qDebug() << "QGraphicsProxyWidget: graphicsscenegesture"; + if (d->widget && d->widget->isVisible()) { + QGraphicsSceneGestureEvent *ge = static_cast(event); + //### TODO: widget->childAt(): decompose gesture event and find widget under hotspots. + QGestureManager::instance()->sendGestureEvent(d->widget, ge->gestures().toSet(), ge->cancelledGestures()); + return true; + } + break; + } default: break; } diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 3d4bb5c..9fdb46f 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -248,6 +248,7 @@ static const int QGRAPHICSSCENE_INDEXTIMER_TIMEOUT = 2000; #include #endif #include +#include QT_BEGIN_NAMESPACE @@ -3953,40 +3954,44 @@ bool QGraphicsScene::event(QEvent *event) update(); break; case QEvent::GraphicsSceneGesture: { + qDebug() << "GraphicsSceneGesture"; QGraphicsSceneGestureEvent *ev = static_cast(event); - QList gestureTypes = ev->gestureTypes(); QGraphicsView *view = qobject_cast(ev->widget()); if (!view) { qWarning("QGraphicsScene::event: gesture event was received without a view"); break; } - // find graphics items that intersects with gestures hot spots. - QPolygonF poly; - QMap sceneHotSpots; - foreach(const QString &type, gestureTypes) { - QPointF pt = ev->mapToScene(ev->gesture(type)->hotSpot()); - sceneHotSpots.insert(type, pt); - poly << pt; + // get a list of gestures that just started. + QSet startedGestures; + QList gestures = ev->gestures(); + for(QList::const_iterator it = gestures.begin(), e = gestures.end(); + it != e; ++it) { + QGesture *g = *it; + QGesturePrivate *gd = g->d_func(); + if (g->state() == Qt::GestureStarted || gd->singleshot) { + startedGestures.insert(g); + } } - QList itemsInGestureArea = items(poly, Qt::IntersectsItemBoundingRect); - - foreach(QGraphicsItem *item, itemsInGestureArea) { - QMap::const_iterator it = sceneHotSpots.begin(), - e = sceneHotSpots.end(); - for(; it != e; ++it) { - if (item->contains(item->mapFromScene(it.value()))) { - const QString gestureName = it.key(); - foreach(int gestureId, item->d_ptr->gestures) { - if (QGestureManager::instance()->gestureNameFromId(gestureId) == gestureName) { - d->sendEvent(item, ev); - if (ev->isAccepted()) - break; - } + if (!startedGestures.isEmpty()) { + // find a target for each started gesture. + for(QSet::const_iterator it = startedGestures.begin(), e = startedGestures.end(); + it != e; ++it) { + QGesture *g = *it; + QGesturePrivate *gd = g->d_func(); + QList itemsInGestureArea = items(g->hotSpot()); + const QString gestureName = g->type(); + foreach(QGraphicsItem *item, itemsInGestureArea) { + if (item->d_func()->hasGesture(gestureName)) { + Q_ASSERT(gd->graphicsItem == 0); + gd->graphicsItem = item; + d->itemsWithGestures[item].insert(g); + break; } } } } + d->sendGestureEvent(ev->gestures().toSet(), ev->cancelledGestures()); } break; case QEvent::GraphicsSceneTouchBegin: @@ -4010,6 +4015,74 @@ bool QGraphicsScene::event(QEvent *event) return true; } +void QGraphicsScenePrivate::sendGestureEvent(const QSet &gestures, const QSet &cancelled) +{ + qDebug() << "QGraphicsScenePrivate::sendGestureEvent:" << gestures; + Q_Q(QGraphicsScene); + typedef QMap > ItemGesturesMap; + ItemGesturesMap itemGestures; + QSet startedGestures; + for(QSet::const_iterator it = gestures.begin(), e = gestures.end(); + it != e; ++it) { + QGesture *g = *it; + Q_ASSERT(g != 0); + QGesturePrivate *gd = g->d_func(); + if (gd->graphicsItem != 0) { + itemGestures[gd->graphicsItem].insert(g); + if (g->state() == Qt::GestureStarted || gd->singleshot) + startedGestures.insert(g); + } + } + + qDebug() << "QGraphicsScenePrivate::sendGestureEvent: started: " << startedGestures; + QSet ignoredGestures; + for(ItemGesturesMap::const_iterator it = itemGestures.begin(), e = itemGestures.end(); + it != e; ++it) { + QGraphicsItem *receiver = it.key(); + Q_ASSERT(receiver != 0); + QGraphicsSceneGestureEvent event; + event.setGestures(it.value()); + event.setCancelledGestures(cancelled); + qDebug() << "QGraphicsScenePrivate::sendGestureEvent: sending to " << receiver << it.value(); + bool processed = sendEvent(receiver, &event); + QSet started = startedGestures.intersect(it.value()); + if (event.isAccepted()) + foreach(QGesture *g, started) + g->accept(); + if (!started.isEmpty() && !(processed && event.isAccepted())) { + // there are started gestures event that weren't + // accepted, so propagating each gesture independently. + QSet::const_iterator it = started.begin(), + e = started.end(); + for(; it != e; ++it) { + QGesture *g = *it; + qDebug() << "result: " << g << ":" << processed << g->isAccepted(); + if (processed && g->isAccepted()) { + continue; + } + QGesturePrivate *gd = g->d_func(); + QGraphicsItem *item = gd->graphicsItem; + gd->graphicsItem = 0; + + //### THIS IS BS, DONT FORGET TO REWRITE THIS CODE + // need to make sure we try to deliver event just once to each widget + const QString gestureType = g->type(); + QList itemsUnderGesture = q->items(g->hotSpot()); + for (int i = 0; i < itemsUnderGesture.size(); ++i) { + QGraphicsItem *item = itemsUnderGesture.at(i); + if (item != receiver && item->d_func()->hasGesture(gestureType)) { + ignoredGestures.insert(g); + gd->graphicsItem = item; + break; + } + } + } + } + } + if (!ignoredGestures.isEmpty()) + sendGestureEvent(ignoredGestures, cancelled); +} + /*! \reimp @@ -5641,12 +5714,13 @@ void QGraphicsScenePrivate::grabGesture(QGraphicsItem *item, int gestureId) foreach(QGraphicsView *view, views) view->d_func()->grabGesture(gestureId); } - itemsWithGestures << item; + (void)itemsWithGestures[item]; grabbedGestures << gestureId; } void QGraphicsScenePrivate::releaseGesture(QGraphicsItem *item, int gestureId) { + itemsWithGestures.remove(item); //### } diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 7928a45..160ba49 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -74,6 +74,7 @@ QT_BEGIN_NAMESPACE class QGraphicsView; class QGraphicsWidget; +class QGesture; class QGraphicsScenePrivate : public QObjectPrivate { @@ -267,10 +268,12 @@ public: void resolvePalette(); void updatePalette(const QPalette &palette); - QSet itemsWithGestures; + // items with gestures -> list of started gestures. + QMap > itemsWithGestures; QSet grabbedGestures; void grabGesture(QGraphicsItem *item, int gestureId); void releaseGesture(QGraphicsItem *item, int gestureId); + void sendGestureEvent(const QSet &gestures, const QSet &cancelled); mutable QVector sceneTransformCache; mutable QBitArray validTransforms; diff --git a/src/gui/graphicsview/qgraphicssceneevent.cpp b/src/gui/graphicsview/qgraphicssceneevent.cpp index d5d0fb9..2c5c946 100644 --- a/src/gui/graphicsview/qgraphicssceneevent.cpp +++ b/src/gui/graphicsview/qgraphicssceneevent.cpp @@ -1895,6 +1895,15 @@ void QGraphicsSceneGestureEvent::setGestures(const QList &gestures) } /*! + Set a list of gesture objects containing extended information about \a gestures. +*/ +void QGraphicsSceneGestureEvent::setGestures(const QSet &gestures) +{ + foreach(QGesture *g, gestures) + m_gestures.insert(g->type(), g); +} + +/*! Sets the accept flag of the all gestures inside the event object, the equivalent of calling \l{QEvent::accept()}{accept()} or \l{QEvent::setAccepted()}{setAccepted(true)}. diff --git a/src/gui/graphicsview/qgraphicssceneevent.h b/src/gui/graphicsview/qgraphicssceneevent.h index 01cdab9..8b24d33 100644 --- a/src/gui/graphicsview/qgraphicssceneevent.h +++ b/src/gui/graphicsview/qgraphicssceneevent.h @@ -325,6 +325,7 @@ public: const QGesture* gesture(const QString &type) const; QList gestures() const; void setGestures(const QList &gestures); + void setGestures(const QSet &gestures); QSet cancelledGestures() const; void setCancelledGestures(const QSet &cancelledGestures); diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 2d2113c..6a20139 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -2977,6 +2977,7 @@ bool QGraphicsView::viewportEvent(QEvent *event) gestureEvent.setGestures(ev->gestures()); gestureEvent.setCancelledGestures(ev->cancelledGestures()); QApplication::sendEvent(d->scene, &gestureEvent); + event->setAccepted(gestureEvent.isAccepted()); if (gestureEvent.isAccepted()) return true; } diff --git a/src/gui/kernel/qgesture.h b/src/gui/kernel/qgesture.h index d220232..bf501f2 100644 --- a/src/gui/kernel/qgesture.h +++ b/src/gui/kernel/qgesture.h @@ -110,6 +110,8 @@ private: friend class QGestureManager; friend class QApplication; + friend class QGraphicsScene; + friend class QGraphicsScenePrivate; friend class QGestureRecognizerPan; friend class QDoubleTapGestureRecognizer; friend class QTapAndHoldGestureRecognizer; diff --git a/src/gui/kernel/qgesture_p.h b/src/gui/kernel/qgesture_p.h index d2d77cc..0f2e791 100644 --- a/src/gui/kernel/qgesture_p.h +++ b/src/gui/kernel/qgesture_p.h @@ -60,13 +60,14 @@ QT_BEGIN_NAMESPACE +class QGraphicsItem; class QGesturePrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QGesture) public: QGesturePrivate() - : state(Qt::NoGesture), singleshot(0), duration(0) { } + : state(Qt::NoGesture), graphicsItem(0), singleshot(0), duration(0) { } void init(const QPoint &startPos, const QPoint &lastPos, const QPoint &pos, const QRect &rect, @@ -86,6 +87,7 @@ public: Qt::GestureState state; QPointer widget; + QGraphicsItem *graphicsItem; uint singleshot:1; QRect rect; diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp index 2750df4..23127cb 100644 --- a/src/gui/kernel/qgesturemanager.cpp +++ b/src/gui/kernel/qgesturemanager.cpp @@ -53,7 +53,7 @@ #include "qdebug.h" -// #define GESTURE_DEBUG +#define GESTURE_DEBUG #ifndef GESTURE_DEBUG # define DEBUG if (0) qDebug #else @@ -170,6 +170,7 @@ bool QGestureManager::filterEvent(QWidget *receiver, QEvent *event) foreach(QGestureRecognizer *r, finishedGestures) { if (QGesture *gesture = r->getGesture()) { gestures << gesture; + qDebug() << "SINGLESHOT" << gesture; gesture->d_func()->singleshot = true; } } @@ -277,7 +278,9 @@ bool QGestureManager::filterEvent(QWidget *receiver, QEvent *event) foreach(QGestureRecognizer *r, finishedGestures) { if (QGesture *gesture = r->getGesture()) { gestures << gesture; - gesture->d_func()->singleshot = activeGestures.contains(r); + gesture->d_func()->singleshot = !activeGestures.contains(r); + if (gesture->d_func()->singleshot) + qDebug() << "SINGLESHOT:" << gesture; } } activeGestures -= finishedGestures; @@ -492,18 +495,6 @@ void QGestureManager::recognizerStateChanged(QGestureRecognizer::Result result) } } -bool QGestureManager::widgetHasGesture(QWidget *widget, QGesture *gesture) const -{ - const QString gestureName = gesture->type(); - QSet::iterator it = widget->d_func()->gestures.begin(), - e = widget->d_func()->gestures.end(); - for (; it != e; ++it) { - if (gestureNameFromId(*it) == gestureName) - return true; - } - return false; -} - bool QGestureManager::sendGestureEvent(QWidget *receiver, const QSet &gestures, const QSet &cancelled) { @@ -519,13 +510,16 @@ bool QGestureManager::sendGestureEvent(QWidget *receiver, const QSet it != e; ++it) { QGesture *g = *it; QGesturePrivate *gd = g->d_func(); - if (!gd->widget && (g->state() == Qt::GestureStarted || gd->singleshot)) { + qDebug() << "sendGestureEvent:" << g << g->state() << "singleshot = " << gd->singleshot; + if (receiver && (g->state() == Qt::GestureStarted || gd->singleshot)) { startedGestures.insert(g); // find the target widget QWidget *w = receiver; QPoint offset; + const QString gestureType = g->type(); while (w) { - if (widgetHasGesture(w, g)) + qDebug() << w << w->d_func()->gestures; + if (w->d_func()->hasGesture(gestureType)) break; if (w->isWindow()) { w = 0; @@ -536,6 +530,7 @@ bool QGestureManager::sendGestureEvent(QWidget *receiver, const QSet } if (!w) // no widget in the tree that accepts this gesture. continue; + qDebug() << "QGestureManager::sendGestureEvent:" << g << "setting widget to " << w; gd->widget = w; g->translate(offset); } @@ -556,10 +551,14 @@ bool QGestureManager::sendGestureEvent(QWidget *receiver, const QSet Q_ASSERT(receiver != 0 /*should be taken care above*/); // TODO: send cancelled gesture event to the widget that received the original gesture! QGestureEvent event(it.value(), cancelled); + qDebug() << "QGestureManager::sendGestureEvent: sending now: " << receiver << it.value(); bool processed = qt_sendSpontaneousEvent(receiver, &event); QSet started = startedGestures.intersect(it.value()); + if (event.isAccepted()) + foreach(QGesture *g, started) + g->accept(); if (!started.isEmpty() && !(processed && event.isAccepted())) { - // there are started gestures event that weren't + // there are started gestures events that weren't // accepted, so propagating each gesture independently. QSet::const_iterator it = started.begin(), e = started.end(); @@ -579,9 +578,10 @@ bool QGestureManager::sendGestureEvent(QWidget *receiver, const QSet g->translate(w->pos()); w = w->parentWidget(); QPoint offset; + const QString gestureType = g->type(); while (w) { - if (widgetHasGesture(w, g)) { - DEBUG() << "QGestureManager: sendGestureEvent:" << w << "didn't accept gesture" << g; + if (w->d_func()->hasGesture(gestureType)) { + DEBUG() << "QGestureManager::sendGestureEvent:" << w << "didn't accept gesture" << g; ignoredGestures.insert(g); break; } diff --git a/src/gui/kernel/qgesturemanager_p.h b/src/gui/kernel/qgesturemanager_p.h index 18183e2..138def5 100644 --- a/src/gui/kernel/qgesturemanager_p.h +++ b/src/gui/kernel/qgesturemanager_p.h @@ -86,6 +86,9 @@ public: // declared in qapplication.cpp static QGestureManager* instance(); + bool sendGestureEvent(QWidget *receiver, const QSet &gestures, + const QSet &cancelled = QSet()); + protected: void timerEvent(QTimerEvent *event); @@ -93,10 +96,6 @@ private slots: void recognizerStateChanged(QGestureRecognizer::Result); private: - bool widgetHasGesture(QWidget *widget, QGesture *gesture) const; - bool sendGestureEvent(QWidget *receiver, const QSet &gestures, - const QSet &cancelled = QSet()); - QSet activeGestures; QMap maybeGestures; QSet recognizers; diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 3a146e5..7920139 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -10970,7 +10970,10 @@ QWindowSurface *QWidget::windowSurface() const int QWidget::grabGesture(const QString &gesture) { Q_D(QWidget); - return d->grabGesture(QGestureManager::instance()->makeGestureId(gesture)); + int id = d->grabGesture(QGestureManager::instance()->makeGestureId(gesture)); + if (d->extra && d->extra->proxyWidget) + d->extra->proxyWidget->QGraphicsItem::d_ptr->grabGesture(id); + return id; } int QWidgetPrivate::grabGesture(int gestureId) @@ -10993,6 +10996,18 @@ bool QWidgetPrivate::releaseGesture(int gestureId) return false; } +bool QWidgetPrivate::hasGesture(const QString &name) const +{ + QGestureManager *gm = QGestureManager::instance(); + QSet::const_iterator it = gestures.begin(), + e = gestures.end(); + for (; it != e; ++it) { + if (gm->gestureNameFromId(*it) == name) + return true; + } + return false; +} + /*! \since 4.6 @@ -11018,8 +11033,11 @@ int QWidget::grabGesture(Qt::GestureType gesture) void QWidget::releaseGesture(int gestureId) { Q_D(QWidget); - if (d->releaseGesture(gestureId)) + if (d->releaseGesture(gestureId)) { + if (d->extra && d->extra->proxyWidget) + d->extra->proxyWidget->QGraphicsItem::d_ptr->releaseGesture(gestureId); QGestureManager::instance()->releaseGestureId(gestureId); + } } /*! diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index a603b44..b2ae75e 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -521,6 +521,7 @@ public: QSet gestures; int grabGesture(int gestureId); bool releaseGesture(int gestureId); + bool hasGesture(const QString &type) const; // Bit fields. uint high_attributes[3]; // the low ones are in QWidget::widget_attributes -- cgit v0.12 From d62320c58a36e3a87b3018e9bc7be49b887fa2cb Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Mon, 18 May 2009 12:24:14 +0200 Subject: More improvement to gesture propagation (still no graphicsview). --- src/gui/graphicsview/qgraphicsproxywidget.cpp | 2 +- src/gui/kernel/qgesturemanager.cpp | 109 ++++++++++++++------------ src/gui/kernel/qgesturemanager_p.h | 4 +- 3 files changed, 62 insertions(+), 53 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsproxywidget.cpp b/src/gui/graphicsview/qgraphicsproxywidget.cpp index 2d7490c..5641068 100644 --- a/src/gui/graphicsview/qgraphicsproxywidget.cpp +++ b/src/gui/graphicsview/qgraphicsproxywidget.cpp @@ -880,7 +880,7 @@ bool QGraphicsProxyWidget::event(QEvent *event) if (d->widget && d->widget->isVisible()) { QGraphicsSceneGestureEvent *ge = static_cast(event); //### TODO: widget->childAt(): decompose gesture event and find widget under hotspots. - QGestureManager::instance()->sendGestureEvent(d->widget, ge->gestures().toSet(), ge->cancelledGestures()); + //QGestureManager::instance()->sendGestureEvent(d->widget, ge->gestures().toSet(), ge->cancelledGestures()); return true; } break; diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp index 23127cb..88704ef 100644 --- a/src/gui/kernel/qgesturemanager.cpp +++ b/src/gui/kernel/qgesturemanager.cpp @@ -53,7 +53,7 @@ #include "qdebug.h" -#define GESTURE_DEBUG +// #define GESTURE_DEBUG #ifndef GESTURE_DEBUG # define DEBUG if (0) qDebug #else @@ -139,7 +139,7 @@ bool QGestureManager::filterEvent(QWidget *receiver, QEvent *event) notGestures << r; } } - activeGestures -= newMaybeGestures; + Q_ASSERT(activeGestures.isEmpty()); activeGestures += startedGestures; for(QMap::iterator it = maybeGestures.begin(); it != maybeGestures.end();) { @@ -160,28 +160,24 @@ bool QGestureManager::filterEvent(QWidget *receiver, QEvent *event) maybeGestures.insert(r, timerId); } } - if (!finishedGestures.isEmpty() || !activeGestures.isEmpty()) { + if (!finishedGestures.isEmpty() || !startedGestures.isEmpty()) { // gesture found! ret = true; - DEBUG() << "QGestureManager: sending gesture event for: " - << activeGestures << " and " << finishedGestures; - - QSet gestures; + QSet started; foreach(QGestureRecognizer *r, finishedGestures) { if (QGesture *gesture = r->getGesture()) { - gestures << gesture; - qDebug() << "SINGLESHOT" << gesture; + started << gesture; gesture->d_func()->singleshot = true; } } - foreach(QGestureRecognizer *r, activeGestures) { + foreach(QGestureRecognizer *r, startedGestures) { if (QGesture *gesture = r->getGesture()) { - gestures << gesture; + started << gesture; gesture->d_func()->singleshot = false; } } - Q_ASSERT(!gestures.isEmpty()); - ret = sendGestureEvent(receiver, gestures); + Q_ASSERT(!started.isEmpty()); + ret = sendGestureEvent(receiver, started, QSet()); if (!activeGestures.isEmpty()) { DEBUG() << "QGestureManager: new state = Gesture"; @@ -244,11 +240,7 @@ bool QGestureManager::filterEvent(QWidget *receiver, QEvent *event) } } } - // TODO: make sure that if gesture recognizer ignored the event we dont swallow it. - activeGestures -= newMaybeGestures; - activeGestures -= cancelledGestures; - activeGestures += startedGestures; for(QMap::iterator it = maybeGestures.begin(); it != maybeGestures.end();) { QGestureRecognizer *r = it.key(); @@ -268,35 +260,37 @@ bool QGestureManager::filterEvent(QWidget *receiver, QEvent *event) maybeGestures.insert(r, timerId); } } - QSet gestures; - if (!finishedGestures.isEmpty() || !activeGestures.isEmpty()) { + QSet started, updated; + if (!finishedGestures.isEmpty() || !startedGestures.isEmpty()) { // another gesture found! ret = true; - DEBUG() << "QGestureManager: sending gesture event for: " - << activeGestures << " and " << finishedGestures; - foreach(QGestureRecognizer *r, finishedGestures) { if (QGesture *gesture = r->getGesture()) { - gestures << gesture; gesture->d_func()->singleshot = !activeGestures.contains(r); if (gesture->d_func()->singleshot) - qDebug() << "SINGLESHOT:" << gesture; + started << gesture; + else + updated << gesture; } } - activeGestures -= finishedGestures; - foreach(QGestureRecognizer *r, activeGestures) { + foreach(QGestureRecognizer *r, startedGestures) { if (QGesture *gesture = r->getGesture()) { - gestures << gesture; - gesture->d_func()->singleshot = false; + gesture->d_func()->singleshot = !activeGestures.contains(r); + if (gesture->d_func()->singleshot) + started << gesture; + else + updated << gesture; } } } + activeGestures -= newMaybeGestures; + activeGestures -= cancelledGestures; + activeGestures += startedGestures; + activeGestures -= finishedGestures; QSet cancelledGestureNames; foreach(QGestureRecognizer *r, cancelledGestures) cancelledGestureNames << r->gestureType(); - if(!gestures.isEmpty()) { - ret = sendGestureEvent(receiver, gestures, cancelledGestureNames); - } + ret = sendGestureEvent(receiver, started, updated, cancelledGestureNames); foreach(QGestureRecognizer *r, finishedGestures) r->reset(); @@ -495,30 +489,28 @@ void QGestureManager::recognizerStateChanged(QGestureRecognizer::Result result) } } -bool QGestureManager::sendGestureEvent(QWidget *receiver, const QSet &gestures, +bool QGestureManager::sendGestureEvent(QWidget *receiver, + const QSet &startedGestures, + const QSet &updatedGestures, const QSet &cancelled) { - if (gestures.isEmpty()) - return false; DEBUG() << "QGestureManager::sendGestureEvent: sending to" << receiver - << "gestures:" << gestures << "; cancelled:" << cancelled; - QSet startedGestures; + << "gestures:" << startedGestures << "," << updatedGestures + << "cancelled:" << cancelled; // grouping gesture objects by receiver widgets. typedef QMap > WidgetGesturesMap; WidgetGesturesMap widgetGestures; - for(QSet::const_iterator it = gestures.begin(), e = gestures.end(); + for(QSet::const_iterator it = startedGestures.begin(), e = startedGestures.end(); it != e; ++it) { QGesture *g = *it; QGesturePrivate *gd = g->d_func(); - qDebug() << "sendGestureEvent:" << g << g->state() << "singleshot = " << gd->singleshot; - if (receiver && (g->state() == Qt::GestureStarted || gd->singleshot)) { - startedGestures.insert(g); + if (receiver) { // find the target widget + gd->widget = 0; QWidget *w = receiver; QPoint offset; const QString gestureType = g->type(); while (w) { - qDebug() << w << w->d_func()->gestures; if (w->d_func()->hasGesture(gestureType)) break; if (w->isWindow()) { @@ -528,11 +520,11 @@ bool QGestureManager::sendGestureEvent(QWidget *receiver, const QSet offset += w->pos(); w = w->parentWidget(); } - if (!w) // no widget in the tree that accepts this gesture. - continue; - qDebug() << "QGestureManager::sendGestureEvent:" << g << "setting widget to " << w; + if (w && w != gd->widget) { + DEBUG() << "QGestureManager::sendGestureEvent:" << g << "propagating to widget" << w << "offset" << offset; + g->translate(offset); + } gd->widget = w; - g->translate(offset); } if (!gd->widget) { DEBUG() << "QGestureManager: didn't find a widget to send gesture event (" @@ -549,14 +541,21 @@ bool QGestureManager::sendGestureEvent(QWidget *receiver, const QSet it != e; ++it) { QWidget *receiver = it.key(); Q_ASSERT(receiver != 0 /*should be taken care above*/); + QSet gestures = it.value(); + // mark all gestures as ignored by default + for(QSet::iterator it = gestures.begin(), e = gestures.end(); it != e; ++it) + (*it)->ignore(); // TODO: send cancelled gesture event to the widget that received the original gesture! QGestureEvent event(it.value(), cancelled); - qDebug() << "QGestureManager::sendGestureEvent: sending now: " << receiver << it.value(); + DEBUG() << "QGestureManager::sendGestureEvent: sending now to" << receiver + << "gestures" << it.value(); bool processed = qt_sendSpontaneousEvent(receiver, &event); - QSet started = startedGestures.intersect(it.value()); - if (event.isAccepted()) + QSet started = startedGestures & it.value(); + if (event.isAccepted()) { + DEBUG() << "QGestureManager::sendGestureEvent: all gestures were accepted"; foreach(QGesture *g, started) g->accept(); + } if (!started.isEmpty() && !(processed && event.isAccepted())) { // there are started gestures events that weren't // accepted, so propagating each gesture independently. @@ -581,8 +580,10 @@ bool QGestureManager::sendGestureEvent(QWidget *receiver, const QSet const QString gestureType = g->type(); while (w) { if (w->d_func()->hasGesture(gestureType)) { - DEBUG() << "QGestureManager::sendGestureEvent:" << w << "didn't accept gesture" << g; + DEBUG() << "QGestureManager::sendGestureEvent:" << receiver + << "didn't accept gesture" << g << "propagating to" << w; ignoredGestures.insert(g); + gd->widget = w; break; } if (w->isWindow()) { @@ -592,14 +593,20 @@ bool QGestureManager::sendGestureEvent(QWidget *receiver, const QSet offset += w->pos(); w = w->parentWidget(); } - if (w) + if (w) { g->translate(offset); + } else { + DEBUG() << "QGestureManager::sendGestureEvent:" << receiver + << "didn't accept gesture" << g << "and nobody wants it"; + } } } } } + if (ignoredGestures.isEmpty()) + return ret; // try to send all gestures that were ignored to the next parent - return sendGestureEvent(0, ignoredGestures, cancelled) || ret; + return sendGestureEvent(0, ignoredGestures, QSet(), cancelled) || ret; } int QGestureManager::eventDeliveryDelay() const diff --git a/src/gui/kernel/qgesturemanager_p.h b/src/gui/kernel/qgesturemanager_p.h index 138def5..745feb3 100644 --- a/src/gui/kernel/qgesturemanager_p.h +++ b/src/gui/kernel/qgesturemanager_p.h @@ -86,7 +86,9 @@ public: // declared in qapplication.cpp static QGestureManager* instance(); - bool sendGestureEvent(QWidget *receiver, const QSet &gestures, + bool sendGestureEvent(QWidget *receiver, + const QSet &startedGestures, + const QSet &updatedGestures, const QSet &cancelled = QSet()); protected: -- cgit v0.12 From 7196f70851ba9ad223efd8fd71b135ed13f22f1c Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Mon, 18 May 2009 15:03:01 +0200 Subject: Added autotest for gestures. --- tests/auto/gestures/customgesturerecognizer.cpp | 105 +++++ tests/auto/gestures/customgesturerecognizer.h | 147 +++++++ tests/auto/gestures/gestures.pro | 3 + tests/auto/gestures/tst_gestures.cpp | 487 ++++++++++++++++++++++++ 4 files changed, 742 insertions(+) create mode 100644 tests/auto/gestures/customgesturerecognizer.cpp create mode 100644 tests/auto/gestures/customgesturerecognizer.h create mode 100644 tests/auto/gestures/gestures.pro create mode 100644 tests/auto/gestures/tst_gestures.cpp diff --git a/tests/auto/gestures/customgesturerecognizer.cpp b/tests/auto/gestures/customgesturerecognizer.cpp new file mode 100644 index 0000000..906fd32 --- /dev/null +++ b/tests/auto/gestures/customgesturerecognizer.cpp @@ -0,0 +1,105 @@ +#include "customgesturerecognizer.h" +#include "qgesture.h" + +const char* SingleshotGestureRecognizer::Name = "SingleshotGesture"; +const char* PinchGestureRecognizer::Name = "PinchGesture"; +const char* SecondFingerGestureRecognizer::Name = "SecondFingerGesture"; + +SingleshotGestureRecognizer::SingleshotGestureRecognizer(QObject *parent) + : QGestureRecognizer(QString(SingleshotGestureRecognizer::Name), parent) +{ + gesture = new SingleshotGesture(this, SingleshotGestureRecognizer::Name); +} + +QGestureRecognizer::Result SingleshotGestureRecognizer::filterEvent(const QEvent *event) +{ + if (event->type() == SingleshotEvent::Type) { + return QGestureRecognizer::GestureFinished; + } + return QGestureRecognizer::NotGesture; +} + +void SingleshotGestureRecognizer::reset() +{ + gesture->offset = QPoint(); +} + +PinchGestureRecognizer::PinchGestureRecognizer(QObject *parent) + : QGestureRecognizer(PinchGestureRecognizer::Name, parent) +{ + gesture = new PinchGesture(this, PinchGestureRecognizer::Name); +} + +QGestureRecognizer::Result PinchGestureRecognizer::filterEvent(const QEvent *event) +{ + if (event->type() != TouchEvent::Type) + return QGestureRecognizer::Ignore; + + const TouchEvent *e = static_cast(event); + if (e->points[0].state == TouchPoint::Begin) + gesture->startPoints[0] = e->points[0]; + if (e->points[1].state == TouchPoint::Begin) + gesture->startPoints[1] = e->points[1]; + gesture->lastPoints[0] = gesture->points[0]; + gesture->lastPoints[1] = gesture->points[1]; + gesture->points[0] = e->points[0]; + gesture->points[1] = e->points[1]; + if (((e->points[0].state == TouchPoint::Begin || e->points[0].state == TouchPoint::Update))) { + if (e->points[1].state == TouchPoint::End || e->points[1].state == TouchPoint::None) + return MaybeGesture; + return GestureStarted; + } else if (((e->points[1].state == TouchPoint::Begin || e->points[1].state == TouchPoint::Update))) { + if (e->points[0].state == TouchPoint::End || e->points[0].state == TouchPoint::None) + return MaybeGesture; + return GestureStarted; + } else if ((e->points[0].state == TouchPoint::End && e->points[1].state == TouchPoint::End) || + (e->points[0].state == TouchPoint::End && e->points[1].state == TouchPoint::None) || + (e->points[0].state == TouchPoint::None && e->points[1].state == TouchPoint::End)) { + return QGestureRecognizer::NotGesture; + } + return QGestureRecognizer::NotGesture; +} + +void PinchGestureRecognizer::reset() +{ + gesture->startPoints[0] = TouchPoint(); + gesture->startPoints[1] = TouchPoint(); + gesture->lastPoints[0] = TouchPoint(); + gesture->lastPoints[1] = TouchPoint(); + gesture->points[0] = TouchPoint(); + gesture->points[1] = TouchPoint(); + gesture->offset = QPoint(); +} + +SecondFingerGestureRecognizer::SecondFingerGestureRecognizer(QObject *parent) + : QGestureRecognizer(SecondFingerGestureRecognizer::Name, parent) +{ + gesture = new SecondFingerGesture(this, SecondFingerGestureRecognizer::Name); +} + +QGestureRecognizer::Result SecondFingerGestureRecognizer::filterEvent(const QEvent *event) +{ + if (event->type() != TouchEvent::Type) + return QGestureRecognizer::Ignore; + + const TouchEvent *e = static_cast(event); + if (e->points[1].state != TouchPoint::None) { + if (e->points[1].state == TouchPoint::Begin) + gesture->startPoint = e->points[1]; + gesture->lastPoint = gesture->point; + gesture->point = e->points[1]; + if (e->points[1].state == TouchPoint::End) + return QGestureRecognizer::GestureFinished; + else if (e->points[1].state != TouchPoint::None) + return QGestureRecognizer::GestureStarted; + } + return QGestureRecognizer::NotGesture; +} + +void SecondFingerGestureRecognizer::reset() +{ + gesture->startPoint = TouchPoint(); + gesture->lastPoint = TouchPoint(); + gesture->point = TouchPoint(); + gesture->offset = QPoint(); +} diff --git a/tests/auto/gestures/customgesturerecognizer.h b/tests/auto/gestures/customgesturerecognizer.h new file mode 100644 index 0000000..b9ab421 --- /dev/null +++ b/tests/auto/gestures/customgesturerecognizer.h @@ -0,0 +1,147 @@ +#ifndef CUSTOMGESTURERECOGNIZER_H +#define CUSTOMGESTURERECOGNIZER_H + +#include "qgesturerecognizer.h" +#include "qgesture.h" +#include "qevent.h" + +class SingleshotEvent : public QEvent +{ +public: + static const int Type = QEvent::User + 1; + SingleshotEvent() : QEvent(QEvent::Type(Type)) { } +}; + +class SingleshotGesture : public QGesture +{ + Q_OBJECT +public: + SingleshotGesture(QObject *parent, const QString &type) + : QGesture(parent, type) { } + + QPoint offset; + +protected: + void translate(const QPoint &pt) + { + offset += pt; + } +}; + +class SingleshotGestureRecognizer : public QGestureRecognizer +{ + Q_OBJECT +public: + static const char *Name; + + SingleshotGestureRecognizer(QObject *parent = 0); + + QGestureRecognizer::Result filterEvent(const QEvent *event); + QGesture* getGesture() { return gesture; } + void reset(); + +private: + SingleshotGesture *gesture; +}; + +struct TouchPoint { + enum State + { + None, + Begin, + Update, + End + }; + int id; + QPoint pt; + State state; + TouchPoint() : id(0), state(None) { } + TouchPoint(int id_, int x_, int y_, State state_) : id(id_), pt(x_, y_), state(state_) { } +}; + +class TouchEvent : public QEvent +{ +public: + static const int Type = QEvent::User + 2; + + TouchEvent() + : QEvent(QEvent::Type(Type)) + { + } + + TouchPoint points[2]; +}; + +class PinchGesture : public QGesture +{ + Q_OBJECT +public: + PinchGesture(QObject *parent, const QString &type) + : QGesture(parent, type) { } + + TouchPoint startPoints[2]; + TouchPoint lastPoints[2]; + TouchPoint points[2]; + + QPoint offset; + +protected: + void translate(const QPoint &pt) + { + offset += pt; + } +}; + +class PinchGestureRecognizer : public QGestureRecognizer +{ + Q_OBJECT +public: + static const char *Name; + + PinchGestureRecognizer(QObject *parent = 0); + + QGestureRecognizer::Result filterEvent(const QEvent *event); + QGesture* getGesture() { return gesture; } + void reset(); + +private: + PinchGesture *gesture; +}; + +class SecondFingerGesture : public QGesture +{ + Q_OBJECT +public: + SecondFingerGesture(QObject *parent, const QString &type) + : QGesture(parent, type) { } + + TouchPoint startPoint; + TouchPoint lastPoint; + TouchPoint point; + + QPoint offset; + +protected: + void translate(const QPoint &pt) + { + offset += pt; + } +}; + +class SecondFingerGestureRecognizer : public QGestureRecognizer +{ + Q_OBJECT +public: + static const char *Name; + + SecondFingerGestureRecognizer(QObject *parent = 0); + + QGestureRecognizer::Result filterEvent(const QEvent *event); + QGesture* getGesture() { return gesture; } + void reset(); + +private: + SecondFingerGesture *gesture; +}; + +#endif diff --git a/tests/auto/gestures/gestures.pro b/tests/auto/gestures/gestures.pro new file mode 100644 index 0000000..ac99b19 --- /dev/null +++ b/tests/auto/gestures/gestures.pro @@ -0,0 +1,3 @@ +load(qttest_p4) +SOURCES += tst_gestures.cpp customgesturerecognizer.cpp +HEADERS += customgesturerecognizer.h diff --git a/tests/auto/gestures/tst_gestures.cpp b/tests/auto/gestures/tst_gestures.cpp new file mode 100644 index 0000000..eb692e9 --- /dev/null +++ b/tests/auto/gestures/tst_gestures.cpp @@ -0,0 +1,487 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the test suite 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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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 +#include + +#include + +#include "customgesturerecognizer.h" + +//TESTED_CLASS= +//TESTED_FILES= + +// color generator for syntax highlighting from QQ-26 by Helder Correia +QVector highlight(const QColor &bg, const + QColor &fg, int noColors) +{ + QVector colors; + const int HUE_BASE = (bg.hue() == -1) ? 90 : bg.hue(); + int h, s, v; + for (int i = 0; i < noColors; i++) { + h = int(HUE_BASE + (360.0 / noColors * i)) % 360; + s = 240; + v = int(qMax(bg.value(), fg.value()) * 0.85); + + const int M = 35; + if ((h < bg.hue() + M && h > bg.hue() - M) + || (h < fg.hue() + M && h > fg.hue() - M)) + { + h = ((bg.hue() + fg.hue()) / (i+1)) % 360; + s = ((bg.saturation() + fg.saturation() + 2*i) + / 2) % 256; + v = ((bg.value() + fg.value() + 2*i) / 2) + % 256; + } + colors.append(QColor::fromHsv(h, s, v)); + } + return colors; +} + + +// a hack to mark an event as spontaneous. +class QETWidget +{ +public: + static void setSpont(QEvent *event, bool spont) { event->spont = spont; } +}; + +class GestureWidget : public QWidget +{ + Q_OBJECT + static QVector colors; + static int numberOfWidgets; + +public: + enum Type { DoNotGrabGestures, GrabAllGestures, GrabSingleshot, GrabPinch, GrabSecondFinger }; + + static const int LeftMargin = 10; + static const int TopMargin = 20; + + GestureWidget(Type type = GrabAllGestures) + { + if (colors.isEmpty()) { + colors = highlight(palette().color(QPalette::Window), palette().color(QPalette::Text), 5); + } + QPalette p = palette(); + p.setColor(QPalette::Window, colors[numberOfWidgets % colors.size()]); + setPalette(p); + setAutoFillBackground(true); + ++numberOfWidgets; + + QVBoxLayout *l = new QVBoxLayout(this); + l->setSpacing(0); + l->setContentsMargins(LeftMargin, TopMargin, LeftMargin, TopMargin); + + singleshotGestureId = -1; + pinchGestureId = -1; + secondFingerGestureId = -1; + if (type == GrabAllGestures || type == GrabSingleshot) { + singleshotGestureId = grabGesture(SingleshotGestureRecognizer::Name); + } + if (type == GrabAllGestures || type == GrabPinch) { + pinchGestureId = grabGesture(PinchGestureRecognizer::Name); + } + if (type == GrabAllGestures || type == GrabSecondFinger) { + secondFingerGestureId = grabGesture(SecondFingerGestureRecognizer::Name); + } + + reset(); + } + ~GestureWidget() + { + --numberOfWidgets; + ungrabGestures(); + } + + void grabSingleshotGesture() + { + singleshotGestureId = grabGesture(SingleshotGestureRecognizer::Name); + } + void grabPinchGesture() + { + pinchGestureId = grabGesture(PinchGestureRecognizer::Name); + } + void grabSecondFingerGesture() + { + secondFingerGestureId = grabGesture(SecondFingerGestureRecognizer::Name); + } + void ungrabGestures() + { + releaseGesture(singleshotGestureId); + singleshotGestureId = -1; + releaseGesture(pinchGestureId); + pinchGestureId = -1; + releaseGesture(secondFingerGestureId); + secondFingerGestureId = -1; + } + + int singleshotGestureId; + int pinchGestureId; + int secondFingerGestureId; + + bool shouldAcceptSingleshotGesture; + bool shouldAcceptPinchGesture; + bool shouldAcceptSecondFingerGesture; + + int seenGestureEvent; + struct LastGestureEvent + { + struct SingleshotGesture + { + bool delivered; + QPoint offset; + } singleshot; + struct PinchGesture + { + bool delivered; + TouchPoint startPoints[2]; + TouchPoint lastPoints[2]; + TouchPoint points[2]; + QPoint offset; + } pinch; + struct SecondFingerGesture + { + bool delivered; + TouchPoint startPoint; + TouchPoint lastPoint; + TouchPoint point; + QPoint offset; + } secondfinger; + QSet cancelled; + } last; + void reset() + { + seenGestureEvent = 0; + last.singleshot.delivered = false; + last.singleshot.offset = QPoint(); + last.pinch.delivered = false; + last.pinch.startPoints[0] = TouchPoint(); + last.pinch.startPoints[1] = TouchPoint(); + last.pinch.lastPoints[0] = TouchPoint(); + last.pinch.lastPoints[1] = TouchPoint(); + last.pinch.points[0] = TouchPoint(); + last.pinch.points[1] = TouchPoint(); + last.pinch.offset = QPoint(); + last.secondfinger.delivered = false; + last.secondfinger.startPoint = TouchPoint(); + last.secondfinger.lastPoint = TouchPoint(); + last.secondfinger.point = TouchPoint(); + last.secondfinger.offset = QPoint(); + last.cancelled.clear(); + + shouldAcceptSingleshotGesture = true; + shouldAcceptPinchGesture = true; + shouldAcceptSecondFingerGesture = true; + } + +protected: + bool event(QEvent *event) + { + if (event->type() == QEvent::Gesture) { + QGestureEvent *e = static_cast(event); + ++seenGestureEvent; + if (SingleshotGesture *g = (SingleshotGesture*)e->gesture(SingleshotGestureRecognizer::Name)) { + last.singleshot.delivered = true; + last.singleshot.offset = g->offset; + if (shouldAcceptSingleshotGesture) + g->accept(); + } + if (PinchGesture *g = (PinchGesture*)e->gesture(PinchGestureRecognizer::Name)) { + last.pinch.delivered = true; + last.pinch.startPoints[0] = g->startPoints[0]; + last.pinch.startPoints[1] = g->startPoints[1]; + last.pinch.lastPoints[0] = g->lastPoints[0]; + last.pinch.lastPoints[1] = g->lastPoints[1]; + last.pinch.points[0] = g->points[0]; + last.pinch.points[1] = g->points[1]; + last.pinch.offset = g->offset; + if (shouldAcceptPinchGesture) + g->accept(); + } + if (SecondFingerGesture *g = (SecondFingerGesture*)e->gesture(SecondFingerGestureRecognizer::Name)) { + last.secondfinger.delivered = true; + last.secondfinger.startPoint = g->startPoint; + last.secondfinger.lastPoint = g->lastPoint; + last.secondfinger.point = g->point; + last.secondfinger.offset = g->offset; + if (shouldAcceptSecondFingerGesture) + g->accept(); + } + last.cancelled = e->cancelledGestures(); + return true; + } + return QWidget::event(event); + } +}; +QVector GestureWidget::colors; +int GestureWidget::numberOfWidgets = 0; + +class tst_Gestures : public QObject +{ + Q_OBJECT + +public: + tst_Gestures(); + virtual ~tst_Gestures(); + +public slots: + void initTestCase(); + void cleanupTestCase(); + void init(); + void cleanup(); + +private slots: + void singleshotGesture(); + void pinchGesture(); + + void simplePropagation(); + void simplePropagation2(); + void acceptedGesturePropagation(); + +private: + SingleshotGestureRecognizer *singleshotRecognizer; + PinchGestureRecognizer *pinchRecognizer; + SecondFingerGestureRecognizer *secondFingerRecognizer; + GestureWidget *mainWidget; + + bool sendSpontaneousEvent(QWidget *receiver, QEvent *event); + void sendPinchEvents(QWidget *receiver, const QPoint &fromFinger1, const QPoint &fromFinger2); +}; + +tst_Gestures::tst_Gestures() +{ + singleshotRecognizer = new SingleshotGestureRecognizer; + pinchRecognizer = new PinchGestureRecognizer; + secondFingerRecognizer = new SecondFingerGestureRecognizer; + qApp->addGestureRecognizer(singleshotRecognizer); + qApp->addGestureRecognizer(pinchRecognizer); + qApp->addGestureRecognizer(secondFingerRecognizer); +} + +tst_Gestures::~tst_Gestures() +{ +} + + +void tst_Gestures::initTestCase() +{ + mainWidget = new GestureWidget(GestureWidget::DoNotGrabGestures); + mainWidget->setObjectName("MainGestureWidget"); + mainWidget->resize(500, 600); + mainWidget->show(); +} + +void tst_Gestures::cleanupTestCase() +{ + delete mainWidget; mainWidget = 0; +} + +void tst_Gestures::init() +{ + // TODO: Add initialization code here. + // This will be executed immediately before each test is run. + mainWidget->reset(); +} + +void tst_Gestures::cleanup() +{ +} + +bool tst_Gestures::sendSpontaneousEvent(QWidget *receiver, QEvent *event) +{ + QETWidget::setSpont(event, true); + return qApp->notify(receiver, event); +} + +void tst_Gestures::singleshotGesture() +{ + mainWidget->grabSingleshotGesture(); + SingleshotEvent event; + sendSpontaneousEvent(mainWidget, &event); + QVERIFY(mainWidget->seenGestureEvent); + QVERIFY(mainWidget->last.singleshot.delivered); + QVERIFY(mainWidget->last.cancelled.isEmpty()); +} + +void tst_Gestures::sendPinchEvents(QWidget *receiver, const QPoint &fromFinger1, const QPoint &fromFinger2) +{ + int x1 = fromFinger1.x(); + int y1 = fromFinger1.x(); + int x2 = fromFinger2.x(); + int y2 = fromFinger2.x(); + + TouchEvent event; + event.points[0] = TouchPoint(0,x1,y1, TouchPoint::Begin); + event.points[1] = TouchPoint(); + sendSpontaneousEvent(receiver, &event); + event.points[0] = TouchPoint(0, x1+=2,y1+=2, TouchPoint::Update); + event.points[1] = TouchPoint(); + sendSpontaneousEvent(receiver, &event); + event.points[0] = TouchPoint(0, x1,y1, TouchPoint::Update); + event.points[1] = TouchPoint(1, x2,y2, TouchPoint::Begin); + sendSpontaneousEvent(receiver, &event); + event.points[0] = TouchPoint(0, x1+=5,y1+=10, TouchPoint::End); + event.points[1] = TouchPoint(1, x2+=3,y2+=6, TouchPoint::Update); + sendSpontaneousEvent(receiver, &event); + event.points[0] = TouchPoint(); + event.points[1] = TouchPoint(1, x2+=10,y2+=15, TouchPoint::Update); + sendSpontaneousEvent(receiver, &event); + event.points[0] = TouchPoint(); + event.points[1] = TouchPoint(1, x2,y2, TouchPoint::End); + sendSpontaneousEvent(receiver, &event); +} + +void tst_Gestures::pinchGesture() +{ + mainWidget->grabPinchGesture(); + sendPinchEvents(mainWidget, QPoint(10,10), QPoint(20,20)); + + QVERIFY(mainWidget->seenGestureEvent); + QVERIFY(!mainWidget->last.singleshot.delivered); + QVERIFY(mainWidget->last.cancelled.isEmpty()); + QVERIFY(mainWidget->last.pinch.delivered); + QCOMPARE(mainWidget->last.pinch.startPoints[0].pt, QPoint(10,10)); + QCOMPARE(mainWidget->last.pinch.startPoints[1].pt, QPoint(20,20)); + QCOMPARE(mainWidget->last.pinch.offset, QPoint(0,0)); +} + +void tst_Gestures::simplePropagation() +{ + mainWidget->grabSingleshotGesture(); + GestureWidget offsetWidget(GestureWidget::DoNotGrabGestures); + offsetWidget.setFixedSize(30, 30); + mainWidget->layout()->addWidget(&offsetWidget); + GestureWidget nonGestureWidget(GestureWidget::DoNotGrabGestures); + mainWidget->layout()->addWidget(&nonGestureWidget); + QApplication::processEvents(); + + SingleshotEvent event; + sendSpontaneousEvent(&nonGestureWidget, &event); + QVERIFY(!offsetWidget.seenGestureEvent); + QVERIFY(!nonGestureWidget.seenGestureEvent); + QVERIFY(mainWidget->seenGestureEvent); + QVERIFY(mainWidget->last.cancelled.isEmpty()); + QVERIFY(mainWidget->last.singleshot.delivered); + QCOMPARE(mainWidget->last.singleshot.offset, QPoint(GestureWidget::LeftMargin, 30 + GestureWidget::TopMargin)); +} + +void tst_Gestures::simplePropagation2() +{ + mainWidget->grabSingleshotGesture(); + mainWidget->grabPinchGesture(); + GestureWidget nonGestureMiddleWidget(GestureWidget::DoNotGrabGestures); + GestureWidget secondGestureWidget(GestureWidget::GrabPinch); + nonGestureMiddleWidget.layout()->addWidget(&secondGestureWidget); + mainWidget->layout()->addWidget(&nonGestureMiddleWidget); + QApplication::processEvents(); + + SingleshotEvent event; + sendSpontaneousEvent(&secondGestureWidget, &event); + QVERIFY(!secondGestureWidget.seenGestureEvent); + QVERIFY(!nonGestureMiddleWidget.seenGestureEvent); + QVERIFY(mainWidget->seenGestureEvent); + QVERIFY(mainWidget->last.singleshot.delivered); + QVERIFY(mainWidget->last.cancelled.isEmpty()); + QCOMPARE(mainWidget->last.singleshot.offset, QPoint(GestureWidget::LeftMargin*2,GestureWidget::TopMargin*2)); + + mainWidget->reset(); + nonGestureMiddleWidget.reset(); + secondGestureWidget.reset(); + + sendPinchEvents(&secondGestureWidget, QPoint(10,10), QPoint(20,20)); + QVERIFY(secondGestureWidget.seenGestureEvent); + QVERIFY(!secondGestureWidget.last.singleshot.delivered); + QVERIFY(secondGestureWidget.last.pinch.delivered); + QCOMPARE(secondGestureWidget.last.pinch.startPoints[0].pt, QPoint(10,10)); + QCOMPARE(secondGestureWidget.last.pinch.startPoints[1].pt, QPoint(20,20)); + QCOMPARE(secondGestureWidget.last.pinch.offset, QPoint(0,0)); + QVERIFY(!nonGestureMiddleWidget.seenGestureEvent); + QVERIFY(!mainWidget->seenGestureEvent); +} + +void tst_Gestures::acceptedGesturePropagation() +{ + mainWidget->grabSingleshotGesture(); + mainWidget->grabPinchGesture(); + mainWidget->grabSecondFingerGesture(); + GestureWidget nonGestureMiddleWidget(GestureWidget::DoNotGrabGestures); + nonGestureMiddleWidget.setObjectName("nonGestureMiddleWidget"); + GestureWidget secondGestureWidget(GestureWidget::GrabSecondFinger); + secondGestureWidget.setObjectName("secondGestureWidget"); + nonGestureMiddleWidget.layout()->addWidget(&secondGestureWidget); + mainWidget->layout()->addWidget(&nonGestureMiddleWidget); + QApplication::processEvents(); + + sendPinchEvents(&secondGestureWidget, QPoint(10, 10), QPoint(40, 40)); + QVERIFY(secondGestureWidget.seenGestureEvent); + QVERIFY(!secondGestureWidget.last.singleshot.delivered); + QVERIFY(!secondGestureWidget.last.pinch.delivered); + QVERIFY(secondGestureWidget.last.secondfinger.delivered); + QCOMPARE(secondGestureWidget.last.secondfinger.startPoint.pt, QPoint(40,40)); + QVERIFY(!nonGestureMiddleWidget.seenGestureEvent); + QVERIFY(mainWidget->seenGestureEvent); + QVERIFY(!mainWidget->last.singleshot.delivered); + QVERIFY(!mainWidget->last.secondfinger.delivered); + QVERIFY(mainWidget->last.pinch.delivered); + QCOMPARE(mainWidget->last.pinch.startPoints[0].pt, QPoint(10,10)); + QCOMPARE(mainWidget->last.pinch.startPoints[1].pt, QPoint(40,40)); + + mainWidget->reset(); + nonGestureMiddleWidget.reset(); + secondGestureWidget.reset(); + + // don't accept it and make sure it propagates to parent + secondGestureWidget.shouldAcceptSecondFingerGesture = false; + sendPinchEvents(&secondGestureWidget, QPoint(10, 10), QPoint(40, 40)); + QVERIFY(secondGestureWidget.seenGestureEvent); + QVERIFY(secondGestureWidget.last.secondfinger.delivered); + QVERIFY(!nonGestureMiddleWidget.seenGestureEvent); + QVERIFY(mainWidget->seenGestureEvent); + QVERIFY(!mainWidget->last.singleshot.delivered); + QVERIFY(mainWidget->last.secondfinger.delivered); + QVERIFY(mainWidget->last.pinch.delivered); +} + + +QTEST_MAIN(tst_Gestures) +#include "tst_gestures.moc" -- cgit v0.12 From f1e61b11ae9561a2886365f58a82dd5d33298582 Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Mon, 18 May 2009 12:25:23 +0200 Subject: Added a TODO entry (bad name in the enum). --- src/gui/kernel/qgesturerecognizer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/kernel/qgesturerecognizer.h b/src/gui/kernel/qgesturerecognizer.h index 8bc8b97..67d7949 100644 --- a/src/gui/kernel/qgesturerecognizer.h +++ b/src/gui/kernel/qgesturerecognizer.h @@ -60,7 +60,7 @@ public: { Ignore, NotGesture, - GestureStarted, + GestureStarted, //TODO: rename to just Gesture? GestureFinished, MaybeGesture }; -- cgit v0.12 From 2964d27fdad2b9722b639e9b5c7c4d7a98fe5a3b Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Mon, 18 May 2009 13:59:48 +0200 Subject: No need to mark QGesture ctor explicit --- src/gui/kernel/qgesture.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/kernel/qgesture.h b/src/gui/kernel/qgesture.h index bf501f2..64a1424 100644 --- a/src/gui/kernel/qgesture.h +++ b/src/gui/kernel/qgesture.h @@ -73,8 +73,8 @@ class Q_GUI_EXPORT QGesture : public QObject Q_PROPERTY(QPoint pos READ pos) public: - explicit QGesture(QObject *parent, const QString &type, - Qt::GestureState state = Qt::GestureStarted); + 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, -- cgit v0.12 From 537243d70de1474cf234880b215c75e83e80abcd Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Mon, 18 May 2009 14:08:07 +0200 Subject: Fixed warning. --- src/gui/kernel/qgesturemanager.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp index 88704ef..9e8a5bb 100644 --- a/src/gui/kernel/qgesturemanager.cpp +++ b/src/gui/kernel/qgesturemanager.cpp @@ -546,19 +546,20 @@ bool QGestureManager::sendGestureEvent(QWidget *receiver, for(QSet::iterator it = gestures.begin(), e = gestures.end(); it != e; ++it) (*it)->ignore(); // TODO: send cancelled gesture event to the widget that received the original gesture! - QGestureEvent event(it.value(), cancelled); + QGestureEvent event(gestures, cancelled); DEBUG() << "QGestureManager::sendGestureEvent: sending now to" << receiver - << "gestures" << it.value(); + << "gestures" << gestures; bool processed = qt_sendSpontaneousEvent(receiver, &event); - QSet started = startedGestures & it.value(); - if (event.isAccepted()) { - DEBUG() << "QGestureManager::sendGestureEvent: all gestures were accepted"; - foreach(QGesture *g, started) - g->accept(); - } + QSet started = startedGestures & gestures; + DEBUG() << "QGestureManager::sendGestureEvent:" << + (event.isAccepted() ? "" : "not") << "all gestures were accepted"; if (!started.isEmpty() && !(processed && event.isAccepted())) { // there are started gestures events that weren't // accepted, so propagating each gesture independently. + if (event.isAccepted()) { + foreach(QGesture *g, started) + g->accept(); + } QSet::const_iterator it = started.begin(), e = started.end(); for(; it != e; ++it) { -- cgit v0.12