src/gui/kernel/qgesturemanager.cpp
changeset 3 41300fa6a67c
parent 0 1918ee327afb
child 4 3b1da2848fc7
child 7 f7bc934e204c
--- a/src/gui/kernel/qgesturemanager.cpp	Tue Jan 26 12:42:25 2010 +0200
+++ b/src/gui/kernel/qgesturemanager.cpp	Tue Feb 02 00:43:10 2010 +0200
@@ -52,6 +52,9 @@
 #ifdef Q_WS_MAC
 #include "qmacgesturerecognizer_mac_p.h"
 #endif
+#if defined(Q_OS_WIN) && !defined(QT_NO_NATIVE_GESTURES)
+#include "qwinnativepangesturerecognizer_win_p.h"
+#endif
 
 #include "qdebug.h"
 
@@ -64,8 +67,17 @@
 
 QT_BEGIN_NAMESPACE
 
+QGestureManager *qt_gestureManager = 0;
+
+QGestureManager* QGestureManager::instance()
+{
+    if (!qt_gestureManager)
+        qt_gestureManager = new QGestureManager(qApp);
+    return qt_gestureManager;
+}
+
 QGestureManager::QGestureManager(QObject *parent)
-    : QObject(parent), state(NotGesture), lastCustomGestureId(0)
+    : QObject(parent), state(NotGesture), m_lastCustomGestureId(0)
 {
     qRegisterMetaType<Qt::GestureState>();
 
@@ -77,17 +89,32 @@
   #endif
 #else
     registerGestureRecognizer(new QPanGestureRecognizer);
+    registerGestureRecognizer(new QPinchGestureRecognizer);
+    registerGestureRecognizer(new QSwipeGestureRecognizer);
+    registerGestureRecognizer(new QTapGestureRecognizer);
+#endif
+#if defined(Q_OS_WIN)
+  #if !defined(QT_NO_NATIVE_GESTURES)
+    registerGestureRecognizer(new QWinNativePanGestureRecognizer);
+  #endif
+#else
+    registerGestureRecognizer(new QTapAndHoldGestureRecognizer);
 #endif
 }
 
 QGestureManager::~QGestureManager()
 {
-
+    qDeleteAll(m_recognizers.values());
+    foreach (QGestureRecognizer *recognizer, m_obsoleteGestures.keys()) {
+        qDeleteAll(m_obsoleteGestures.value(recognizer));
+        delete recognizer;
+    }
+    m_obsoleteGestures.clear();
 }
 
 Qt::GestureType QGestureManager::registerGestureRecognizer(QGestureRecognizer *recognizer)
 {
-    QGesture *dummy = recognizer->createGesture(0);
+    QGesture *dummy = recognizer->create(0);
     if (!dummy) {
         qWarning("QGestureManager::registerGestureRecognizer: "
                  "the recognizer fails to create a gesture object, skipping registration.");
@@ -96,20 +123,55 @@
     Qt::GestureType type = dummy->gestureType();
     if (type == Qt::CustomGesture) {
         // generate a new custom gesture id
-        ++lastCustomGestureId;
-        type = Qt::GestureType(Qt::CustomGesture + lastCustomGestureId);
+        ++m_lastCustomGestureId;
+        type = Qt::GestureType(Qt::CustomGesture + m_lastCustomGestureId);
     }
-    recognizers.insertMulti(type, recognizer);
+    m_recognizers.insertMulti(type, recognizer);
     delete dummy;
     return type;
 }
 
-void QGestureManager::unregisterGestureRecognizer(Qt::GestureType)
+void QGestureManager::unregisterGestureRecognizer(Qt::GestureType type)
 {
+    QList<QGestureRecognizer *> list = m_recognizers.values(type);
+    m_recognizers.remove(type);
+    foreach (QGesture *g, m_gestureToRecognizer.keys()) {
+        QGestureRecognizer *recognizer = m_gestureToRecognizer.value(g);
+        if (list.contains(recognizer)) {
+            m_deletedRecognizers.insert(g, recognizer);
+            m_gestureToRecognizer.remove(g);
+        }
+    }
 
+    foreach (QGestureRecognizer *recognizer, list) {
+        QList<QGesture *> obsoleteGestures;
+        QMap<ObjectGesture, QList<QGesture *> >::Iterator iter = m_objectGestures.begin();
+        while (iter != m_objectGestures.end()) {
+            ObjectGesture objectGesture = iter.key();
+            if (objectGesture.gesture == type)
+                obsoleteGestures << iter.value();
+            ++iter;
+        }
+        m_obsoleteGestures.insert(recognizer, obsoleteGestures);
+    }
 }
 
-QGesture *QGestureManager::getState(QObject *object, Qt::GestureType type)
+void QGestureManager::cleanupCachedGestures(QObject *target, Qt::GestureType type)
+{
+    QMap<ObjectGesture, QList<QGesture *> >::Iterator iter = m_objectGestures.begin();
+    while (iter != m_objectGestures.end()) {
+        ObjectGesture objectGesture = iter.key();
+        if (objectGesture.gesture == type && target == objectGesture.object.data()) {
+            qDeleteAll(iter.value());
+            iter = m_objectGestures.erase(iter);
+        } else {
+            ++iter;
+        }
+    }
+}
+
+// get or create a QGesture object that will represent the state for a given object, used by the recognizer
+QGesture *QGestureManager::getState(QObject *object, QGestureRecognizer *recognizer, Qt::GestureType type)
 {
     // if the widget is being deleted we should be carefull and not to
     // create a new state, as it will create QWeakPointer which doesnt work
@@ -119,102 +181,110 @@
             return 0;
     } else if (QGesture *g = qobject_cast<QGesture *>(object)) {
         return g;
+#ifndef QT_NO_GRAPHICSVIEW
     } else {
         Q_ASSERT(qobject_cast<QGraphicsObject *>(object));
+#endif
+    }
+
+    // check if the QGesture for this recognizer has already been created
+    foreach (QGesture *state, m_objectGestures.value(QGestureManager::ObjectGesture(object, type))) {
+        if (m_gestureToRecognizer.value(state) == recognizer)
+            return state;
     }
 
-    QGesture *state =
-            objectGestures.value(QGestureManager::ObjectGesture(object, type));
-    if (!state) {
-        QGestureRecognizer *recognizer = recognizers.value(type);
-        if (recognizer) {
-            state = recognizer->createGesture(object);
-            if (!state)
-                return 0;
-            if (state->gestureType() == Qt::CustomGesture) {
-                // if the recognizer didn't fill in the gesture type, then this
-                // is a custom gesture with autogenerated it and we fill it.
-                state->d_func()->gestureType = type;
+    Q_ASSERT(recognizer);
+    QGesture *state = recognizer->create(object);
+    if (!state)
+        return 0;
+    state->setParent(this);
+    if (state->gestureType() == Qt::CustomGesture) {
+        // if the recognizer didn't fill in the gesture type, then this
+        // is a custom gesture with autogenerated id and we fill it.
+        state->d_func()->gestureType = type;
 #if defined(GESTURE_DEBUG)
-                state->setObjectName(QString::number((int)type));
+        state->setObjectName(QString::number((int)type));
 #endif
-            }
-            objectGestures.insert(QGestureManager::ObjectGesture(object, type), state);
-            gestureToRecognizer[state] = recognizer;
-            gestureOwners[state] = object;
-        }
     }
+    m_objectGestures[QGestureManager::ObjectGesture(object, type)].append(state);
+    m_gestureToRecognizer[state] = recognizer;
+    m_gestureOwners[state] = object;
+
     return state;
 }
 
-bool QGestureManager::filterEventThroughContexts(const QMap<QObject *,
+bool QGestureManager::filterEventThroughContexts(const QMultiMap<QObject *,
                                                  Qt::GestureType> &contexts,
                                                  QEvent *event)
 {
     QSet<QGesture *> triggeredGestures;
     QSet<QGesture *> finishedGestures;
     QSet<QGesture *> newMaybeGestures;
-    QSet<QGesture *> canceledGestures;
     QSet<QGesture *> notGestures;
 
     // TODO: sort contexts by the gesture type and check if one of the contexts
     //       is already active.
 
+    bool ret = false;
+
     // filter the event through recognizers
-    typedef QMap<QObject *, Qt::GestureType>::const_iterator ContextIterator;
+    typedef QMultiMap<QObject *, Qt::GestureType>::const_iterator ContextIterator;
     for (ContextIterator cit = contexts.begin(), ce = contexts.end(); cit != ce; ++cit) {
         Qt::GestureType gestureType = cit.value();
         QMap<Qt::GestureType, QGestureRecognizer *>::const_iterator
-                rit = recognizers.lowerBound(gestureType),
-                re = recognizers.upperBound(gestureType);
+                rit = m_recognizers.lowerBound(gestureType),
+                re = m_recognizers.upperBound(gestureType);
         for (; rit != re; ++rit) {
             QGestureRecognizer *recognizer = rit.value();
             QObject *target = cit.key();
-            QGesture *state = getState(target, gestureType);
+            QGesture *state = getState(target, recognizer, gestureType);
             if (!state)
                 continue;
-            QGestureRecognizer::Result result = recognizer->filterEvent(state, target, event);
+            QGestureRecognizer::Result result = recognizer->recognize(state, target, event);
             QGestureRecognizer::Result type = result & QGestureRecognizer::ResultState_Mask;
-            if (type == QGestureRecognizer::GestureTriggered) {
-                DEBUG() << "QGestureManager: gesture triggered: " << state;
+            result &= QGestureRecognizer::ResultHint_Mask;
+            if (type == QGestureRecognizer::TriggerGesture) {
+                DEBUG() << "QGestureManager:Recognizer: gesture triggered: " << state;
                 triggeredGestures << state;
-            } else if (type == QGestureRecognizer::GestureFinished) {
-                DEBUG() << "QGestureManager: gesture finished: " << state;
+            } else if (type == QGestureRecognizer::FinishGesture) {
+                DEBUG() << "QGestureManager:Recognizer: gesture finished: " << state;
                 finishedGestures << state;
-            } else if (type == QGestureRecognizer::MaybeGesture) {
-                DEBUG() << "QGestureManager: maybe gesture: " << state;
+            } else if (type == QGestureRecognizer::MayBeGesture) {
+                DEBUG() << "QGestureManager:Recognizer: maybe gesture: " << state;
                 newMaybeGestures << state;
-            } else if (type == QGestureRecognizer::NotGesture) {
-                DEBUG() << "QGestureManager: not gesture: " << state;
+            } else if (type == QGestureRecognizer::CancelGesture) {
+                DEBUG() << "QGestureManager:Recognizer: not gesture: " << state;
                 notGestures << state;
             } else if (type == QGestureRecognizer::Ignore) {
-                DEBUG() << "QGestureManager: gesture ignored the event: " << state;
+                DEBUG() << "QGestureManager:Recognizer: ignored the event: " << state;
             } else {
-                DEBUG() << "QGestureManager: hm, lets assume the recognizer"
+                DEBUG() << "QGestureManager:Recognizer: hm, lets assume the recognizer"
                         << "ignored the event: " << state;
             }
             if (result & QGestureRecognizer::ConsumeEventHint) {
                 DEBUG() << "QGestureManager: we were asked to consume the event: "
                         << state;
-                //TODO: consume events if asked
+                ret = true;
             }
         }
     }
+    if (triggeredGestures.isEmpty() && finishedGestures.isEmpty()
+        && newMaybeGestures.isEmpty() && notGestures.isEmpty())
+        return ret;
 
-    QSet<QGesture *> startedGestures = triggeredGestures - activeGestures;
-    triggeredGestures &= activeGestures;
+    QSet<QGesture *> startedGestures = triggeredGestures - m_activeGestures;
+    triggeredGestures &= m_activeGestures;
 
     // check if a running gesture switched back to maybe state
-    QSet<QGesture *> activeToMaybeGestures = activeGestures & newMaybeGestures;
+    QSet<QGesture *> activeToMaybeGestures = m_activeGestures & newMaybeGestures;
 
     // check if a running gesture switched back to not gesture state,
     // i.e. were canceled
-    QSet<QGesture *> activeToCancelGestures = activeGestures & notGestures;
-    canceledGestures += activeToCancelGestures;
+    QSet<QGesture *> canceledGestures = m_activeGestures & notGestures;
 
     // start timers for new gestures in maybe state
     foreach (QGesture *state, newMaybeGestures) {
-        QBasicTimer &timer = maybeGestures[state];
+        QBasicTimer &timer = m_maybeGestures[state];
         if (!timer.isActive())
             timer.start(3000, this);
     }
@@ -223,11 +293,11 @@
                                          | finishedGestures | canceledGestures
                                          | notGestures);
     foreach(QGesture *gesture, notMaybeGestures) {
-        QMap<QGesture *, QBasicTimer>::iterator it =
-                maybeGestures.find(gesture);
-        if (it != maybeGestures.end()) {
+        QHash<QGesture *, QBasicTimer>::iterator it =
+                m_maybeGestures.find(gesture);
+        if (it != m_maybeGestures.end()) {
             it.value().stop();
-            maybeGestures.erase(it);
+            m_maybeGestures.erase(it);
         }
     }
 
@@ -238,7 +308,7 @@
     Q_ASSERT((finishedGestures & canceledGestures).isEmpty());
     Q_ASSERT((canceledGestures & newMaybeGestures).isEmpty());
 
-    QSet<QGesture *> notStarted = finishedGestures - activeGestures;
+    QSet<QGesture *> notStarted = finishedGestures - m_activeGestures;
     if (!notStarted.isEmpty()) {
         // there are some gestures that claim to be finished, but never started.
         // probably those are "singleshot" gestures so we'll fake the started state.
@@ -249,12 +319,12 @@
         finishedGestures -= undeliveredGestures;
     }
 
-    activeGestures += startedGestures;
+    m_activeGestures += startedGestures;
     // sanity check: all triggered gestures should already be in active gestures list
-    Q_ASSERT((activeGestures & triggeredGestures).size() == triggeredGestures.size());
-    activeGestures -= finishedGestures;
-    activeGestures -= activeToMaybeGestures;
-    activeGestures -= canceledGestures;
+    Q_ASSERT((m_activeGestures & triggeredGestures).size() == triggeredGestures.size());
+    m_activeGestures -= finishedGestures;
+    m_activeGestures -= activeToMaybeGestures;
+    m_activeGestures -= canceledGestures;
 
     // set the proper gesture state on each gesture
     foreach (QGesture *gesture, startedGestures)
@@ -268,12 +338,12 @@
     foreach (QGesture *gesture, activeToMaybeGestures)
         gesture->d_func()->state = Qt::GestureFinished;
 
-    if (!activeGestures.isEmpty() || !maybeGestures.isEmpty() ||
+    if (!m_activeGestures.isEmpty() || !m_maybeGestures.isEmpty() ||
         !startedGestures.isEmpty() || !triggeredGestures.isEmpty() ||
         !finishedGestures.isEmpty() || !canceledGestures.isEmpty()) {
-        DEBUG() << "QGestureManager::filterEvent:"
-                << "\n\tactiveGestures:" << activeGestures
-                << "\n\tmaybeGestures:" << maybeGestures.keys()
+        DEBUG() << "QGestureManager::filterEventThroughContexts:"
+                << "\n\tactiveGestures:" << m_activeGestures
+                << "\n\tmaybeGestures:" << m_maybeGestures.keys()
                 << "\n\tstarted:" << startedGestures
                 << "\n\ttriggered:" << triggeredGestures
                 << "\n\tfinished:" << finishedGestures
@@ -284,30 +354,108 @@
     deliverEvents(startedGestures+triggeredGestures+finishedGestures+canceledGestures,
                   &undeliveredGestures);
 
-    activeGestures -= undeliveredGestures;
+    foreach (QGesture *g, startedGestures) {
+        if (undeliveredGestures.contains(g))
+            continue;
+        if (g->gestureCancelPolicy() == QGesture::CancelAllInContext) {
+            DEBUG() << "lets try to cancel some";
+            // find gestures in context in Qt::GestureStarted or Qt::GestureUpdated state and cancel them
+            cancelGesturesForChildren(g);
+        }
+    }
+
+    m_activeGestures -= undeliveredGestures;
 
     // reset gestures that ended
     QSet<QGesture *> endedGestures =
             finishedGestures + canceledGestures + undeliveredGestures;
     foreach (QGesture *gesture, endedGestures) {
-        if (QGestureRecognizer *recognizer = gestureToRecognizer.value(gesture, 0)) {
-            recognizer->reset(gesture);
-        }
-        gestureTargets.remove(gesture);
+        recycle(gesture);
+        m_gestureTargets.remove(gesture);
     }
-    return false;
+    return ret;
 }
 
+// Cancel all gestures of children of the widget that original is associated with
+void QGestureManager::cancelGesturesForChildren(QGesture *original)
+{
+    Q_ASSERT(original);
+    QWidget *originatingWidget = m_gestureTargets.value(original);
+    Q_ASSERT(originatingWidget);
+
+    // iterate over all active gestures and all maybe gestures
+    // for each find the owner
+    // if the owner is part of our sub-hierarchy, cancel it.
+
+    QSet<QGesture*> cancelledGestures;
+    QSet<QGesture*>::Iterator iter = m_activeGestures.begin();
+    while (iter != m_activeGestures.end()) {
+        QWidget *widget = m_gestureTargets.value(*iter);
+        // note that we don't touch the gestures for our originatingWidget
+        if (widget != originatingWidget && originatingWidget->isAncestorOf(widget)) {
+            DEBUG() << "  found a gesture to cancel" << (*iter);
+            (*iter)->d_func()->state = Qt::GestureCanceled;
+            cancelledGestures << *iter;
+            iter = m_activeGestures.erase(iter);
+        } else {
+            ++iter;
+        }
+    }
+
+    // TODO handle 'maybe' gestures too
+
+    // sort them per target widget by cherry picking from almostCanceledGestures and delivering
+    QSet<QGesture *> almostCanceledGestures = cancelledGestures;
+    while (!almostCanceledGestures.isEmpty()) {
+        QWidget *target = 0;
+        QSet<QGesture*> gestures;
+        iter = almostCanceledGestures.begin();
+        // sort per target widget
+        while (iter != almostCanceledGestures.end()) {
+            QWidget *widget = m_gestureTargets.value(*iter);
+            if (target == 0)
+                target = widget;
+            if (target == widget) {
+                gestures << *iter;
+                iter = almostCanceledGestures.erase(iter);
+            } else {
+                ++iter;
+            }
+        }
+        Q_ASSERT(target);
+
+        QSet<QGesture*> undeliveredGestures;
+        deliverEvents(gestures, &undeliveredGestures);
+    }
+
+    for (iter = cancelledGestures.begin(); iter != cancelledGestures.end(); ++iter)
+        recycle(*iter);
+}
+
+void QGestureManager::cleanupGesturesForRemovedRecognizer(QGesture *gesture)
+{
+    QGestureRecognizer *recognizer = m_deletedRecognizers.value(gesture);
+    Q_ASSERT(recognizer);
+    m_deletedRecognizers.remove(gesture);
+    if (m_deletedRecognizers.keys(recognizer).isEmpty()) {
+        // no more active gestures, cleanup!
+        qDeleteAll(m_obsoleteGestures.value(recognizer));
+        m_obsoleteGestures.remove(recognizer);
+        delete recognizer;
+    }
+}
+
+// return true if accepted (consumed)
 bool QGestureManager::filterEvent(QWidget *receiver, QEvent *event)
 {
-    QSet<Qt::GestureType> types;
-    QMap<QObject *, Qt::GestureType> contexts;
+    QMap<Qt::GestureType, int> types;
+    QMultiMap<QObject *, Qt::GestureType> contexts;
     QWidget *w = receiver;
-    typedef QMap<Qt::GestureType, Qt::GestureContext>::const_iterator ContextIterator;
+    typedef QMap<Qt::GestureType, Qt::GestureFlags>::const_iterator ContextIterator;
     if (!w->d_func()->gestureContext.isEmpty()) {
         for(ContextIterator it = w->d_func()->gestureContext.begin(),
             e = w->d_func()->gestureContext.end(); it != e; ++it) {
-            types.insert(it.key());
+            types.insert(it.key(), 0);
             contexts.insertMulti(w, it.key());
         }
     }
@@ -317,9 +465,9 @@
     {
         for (ContextIterator it = w->d_func()->gestureContext.begin(),
              e = w->d_func()->gestureContext.end(); it != e; ++it) {
-            if (it.value() == Qt::WidgetWithChildrenGesture) {
+            if (!(it.value() & Qt::DontStartGestureOnChildren)) {
                 if (!types.contains(it.key())) {
-                    types.insert(it.key());
+                    types.insert(it.key(), 0);
                     contexts.insertMulti(w, it.key());
                 }
             }
@@ -328,19 +476,20 @@
             break;
         w = w->parentWidget();
     }
-    return filterEventThroughContexts(contexts, event);
+    return contexts.isEmpty() ? false : filterEventThroughContexts(contexts, event);
 }
 
+#ifndef QT_NO_GRAPHICSVIEW
 bool QGestureManager::filterEvent(QGraphicsObject *receiver, QEvent *event)
 {
-    QSet<Qt::GestureType> types;
-    QMap<QObject *, Qt::GestureType> contexts;
+    QMap<Qt::GestureType, int> types;
+    QMultiMap<QObject *, Qt::GestureType> contexts;
     QGraphicsObject *item = receiver;
     if (!item->QGraphicsItem::d_func()->gestureContext.isEmpty()) {
-        typedef QMap<Qt::GestureType, Qt::GestureContext>::const_iterator ContextIterator;
+        typedef QMap<Qt::GestureType, Qt::GestureFlags>::const_iterator ContextIterator;
         for(ContextIterator it = item->QGraphicsItem::d_func()->gestureContext.begin(),
             e = item->QGraphicsItem::d_func()->gestureContext.end(); it != e; ++it) {
-            types.insert(it.key());
+            types.insert(it.key(), 0);
             contexts.insertMulti(item, it.key());
         }
     }
@@ -348,22 +497,28 @@
     item = item->parentObject();
     while (item)
     {
-        typedef QMap<Qt::GestureType, Qt::GestureContext>::const_iterator ContextIterator;
+        typedef QMap<Qt::GestureType, Qt::GestureFlags>::const_iterator ContextIterator;
         for (ContextIterator it = item->QGraphicsItem::d_func()->gestureContext.begin(),
              e = item->QGraphicsItem::d_func()->gestureContext.end(); it != e; ++it) {
-            if (it.value() == Qt::ItemWithChildrenGesture) {
-                if (!types.contains(it.key()))
+            if (!(it.value() & Qt::DontStartGestureOnChildren)) {
+                if (!types.contains(it.key())) {
+                    types.insert(it.key(), 0);
                     contexts.insertMulti(item, it.key());
+                }
             }
         }
         item = item->parentObject();
     }
-    return filterEventThroughContexts(contexts, event);
+    return contexts.isEmpty() ? false : filterEventThroughContexts(contexts, event);
 }
+#endif
 
-bool QGestureManager::filterEvent(QGesture *state, QEvent *event)
+bool QGestureManager::filterEvent(QObject *receiver, QEvent *event)
 {
-    QMap<QObject *, Qt::GestureType> contexts;
+    if (!m_gestureToRecognizer.contains(static_cast<QGesture *>(receiver)))
+        return false;
+    QGesture *state = static_cast<QGesture *>(receiver);
+    QMultiMap<QObject *, Qt::GestureType> contexts;
     contexts.insert(state, state->gestureType());
     return filterEventThroughContexts(contexts, event);
 }
@@ -377,7 +532,7 @@
 
     // sort gestures by types
     foreach (QGesture *gesture, gestures) {
-        QWidget *receiver = gestureTargets.value(gesture, 0);
+        QWidget *receiver = m_gestureTargets.value(gesture, 0);
         Q_ASSERT(receiver);
         gestureByTypes[gesture->gestureType()].insert(receiver, gesture);
     }
@@ -388,12 +543,12 @@
         foreach (QWidget *widget, gestures.keys()) {
             QWidget *w = widget->parentWidget();
             while (w) {
-                QMap<Qt::GestureType, Qt::GestureContext>::const_iterator it
+                QMap<Qt::GestureType, Qt::GestureFlags>::const_iterator it
                         = w->d_func()->gestureContext.find(type);
                 if (it != w->d_func()->gestureContext.end()) {
                     // i.e. 'w' listens to gesture 'type'
-                    Qt::GestureContext context = it.value();
-                    if (context == Qt::WidgetWithChildrenGesture && w != widget) {
+                    Qt::GestureFlags flags = it.value();
+                    if (!(it.value() & Qt::DontStartGestureOnChildren) && w != widget) {
                         // conflicting gesture!
                         (*conflicts)[widget].append(gestures[widget]);
                         break;
@@ -426,7 +581,7 @@
     for (QSet<QGesture *>::const_iterator it = gestures.begin(),
          e = gestures.end(); it != e; ++it) {
         QGesture *gesture = *it;
-        QWidget *target = gestureTargets.value(gesture, 0);
+        QWidget *target = m_gestureTargets.value(gesture, 0);
         if (!target) {
             // the gesture has just started and doesn't have a target yet.
             Q_ASSERT(gesture->state() == Qt::GestureStarted);
@@ -438,16 +593,17 @@
                 }
             } else {
                 // or use the context of the gesture
-                QObject *context = gestureOwners.value(gesture, 0);
+                QObject *context = m_gestureOwners.value(gesture, 0);
                 if (context->isWidgetType())
                     target = static_cast<QWidget *>(context);
             }
             if (target)
-                gestureTargets.insert(gesture, target);
+                m_gestureTargets.insert(gesture, target);
         }
 
         Qt::GestureType gestureType = gesture->gestureType();
         Q_ASSERT(gestureType != Qt::CustomGesture);
+        Q_UNUSED(gestureType);
 
         if (target) {
             if (gesture->state() == Qt::GestureStarted) {
@@ -487,7 +643,7 @@
 
         QApplication::sendEvent(receiver, &event);
         bool eventAccepted = event.isAccepted();
-        foreach(QGesture *gesture, event.allGestures()) {
+        foreach(QGesture *gesture, event.gestures()) {
             if (eventAccepted || event.isAccepted(gesture)) {
                 QWidget *w = event.d_func()->targetWidgets.value(gesture->gestureType(), 0);
                 Q_ASSERT(w);
@@ -495,7 +651,7 @@
                 QList<QGesture *> &gestures = normalStartedGestures[w];
                 gestures.append(gesture);
                 // override the target
-                gestureTargets[gesture] = w;
+                m_gestureTargets[gesture] = w;
             } else {
                 DEBUG() << "override event: gesture wasn't accepted. putting back:" << gesture;
                 QList<QGesture *> &gestures = normalStartedGestures[receiver];
@@ -512,32 +668,51 @@
                     << "gestures:" << it.value();
             QGestureEvent event(it.value());
             QApplication::sendEvent(it.key(), &event);
+            bool eventAccepted = event.isAccepted();
+            foreach (QGesture *gesture, event.gestures()) {
+                if (gesture->state() == Qt::GestureStarted &&
+                    (eventAccepted || event.isAccepted(gesture))) {
+                    QWidget *w = event.d_func()->targetWidgets.value(gesture->gestureType(), 0);
+                    Q_ASSERT(w);
+                    DEBUG() << "started gesture was delivered and accepted by" << w;
+                    m_gestureTargets[gesture] = w;
+                }
+            }
         }
     }
 }
 
 void QGestureManager::timerEvent(QTimerEvent *event)
 {
-    QMap<QGesture*, QBasicTimer>::iterator it = maybeGestures.begin(),
-                                            e = maybeGestures.end();
+    QHash<QGesture *, QBasicTimer>::iterator it = m_maybeGestures.begin(),
+                                             e = m_maybeGestures.end();
     for (; it != e; ) {
         QBasicTimer &timer = it.value();
         Q_ASSERT(timer.isActive());
         if (timer.timerId() == event->timerId()) {
             timer.stop();
             QGesture *gesture = it.key();
-            it = maybeGestures.erase(it);
+            it = m_maybeGestures.erase(it);
             DEBUG() << "QGestureManager::timerEvent: gesture stopped due to timeout:"
                     << gesture;
-            QGestureRecognizer *recognizer = gestureToRecognizer.value(gesture, 0);
-            if (recognizer)
-                recognizer->reset(gesture);
+            recycle(gesture);
         } else {
             ++it;
         }
     }
 }
 
+void QGestureManager::recycle(QGesture *gesture)
+{
+    QGestureRecognizer *recognizer = m_gestureToRecognizer.value(gesture, 0);
+    if (recognizer) {
+        gesture->setGestureCancelPolicy(QGesture::CancelNone);
+        recognizer->reset(gesture);
+    } else {
+        cleanupGesturesForRemovedRecognizer(gesture);
+    }
+}
+
 QT_END_NAMESPACE
 
 #include "moc_qgesturemanager_p.cpp"