From f67b8df3ebdba2d398b9cce686b7c644adffff08 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Sat, 7 May 2011 00:02:01 +0200 Subject: library split --- src/widgets/kernel/qgesturemanager.cpp | 721 +++++++++++++++++++++++++++++++++ 1 file changed, 721 insertions(+) create mode 100644 src/widgets/kernel/qgesturemanager.cpp (limited to 'src/widgets/kernel/qgesturemanager.cpp') diff --git a/src/widgets/kernel/qgesturemanager.cpp b/src/widgets/kernel/qgesturemanager.cpp new file mode 100644 index 0000000000..5359fb37e8 --- /dev/null +++ b/src/widgets/kernel/qgesturemanager.cpp @@ -0,0 +1,721 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "private/qgesturemanager_p.h" +#include "private/qstandardgestures_p.h" +#include "private/qwidget_p.h" +#include "private/qgesture_p.h" +#include "private/qgraphicsitem_p.h" +#include "private/qevent_p.h" +#include "private/qapplication_p.h" +#include "qgesture.h" +#include "qevent.h" +#include "qgraphicsitem.h" + +#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" + +// #define GESTURE_DEBUG +#ifndef GESTURE_DEBUG +# define DEBUG if (0) qDebug +#else +# define DEBUG qDebug +#endif + +#ifndef QT_NO_GESTURES + +QT_BEGIN_NAMESPACE + +QGestureManager::QGestureManager(QObject *parent) + : QObject(parent), state(NotGesture), m_lastCustomGestureId(Qt::CustomGesture) +{ + qRegisterMetaType(); + +#if defined(Q_WS_MAC) + registerGestureRecognizer(new QMacSwipeGestureRecognizer); + registerGestureRecognizer(new QMacPinchGestureRecognizer); + #if defined(QT_MAC_USE_COCOA) + registerGestureRecognizer(new QMacPanGestureRecognizer); + #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) + if (QApplicationPrivate::HasTouchSupport) + 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->create(0); + if (!dummy) { + qWarning("QGestureManager::registerGestureRecognizer: " + "the recognizer fails to create a gesture object, skipping registration."); + return Qt::GestureType(0); + } + Qt::GestureType type = dummy->gestureType(); + if (type == Qt::CustomGesture) { + // generate a new custom gesture id + ++m_lastCustomGestureId; + type = Qt::GestureType(m_lastCustomGestureId); + } + m_recognizers.insertMulti(type, recognizer); + delete dummy; + return type; +} + +void QGestureManager::unregisterGestureRecognizer(Qt::GestureType type) +{ + QList list = m_recognizers.values(type); + while (QGestureRecognizer *recognizer = m_recognizers.take(type)) { + if (!m_obsoleteGestures.contains(recognizer)) { + // inserting even an empty QSet will cause the recognizer to be deleted on destruction of the manager + m_obsoleteGestures.insert(recognizer, QSet()); + } + } + foreach (QGesture *g, m_gestureToRecognizer.keys()) { + QGestureRecognizer *recognizer = m_gestureToRecognizer.value(g); + if (list.contains(recognizer)) { + m_deletedRecognizers.insert(g, recognizer); + } + } + + QMap >::const_iterator iter = m_objectGestures.begin(); + while (iter != m_objectGestures.end()) { + ObjectGesture objectGesture = iter.key(); + if (objectGesture.gesture == type) { + foreach (QGesture *g, iter.value()) { + if (QGestureRecognizer *recognizer = m_gestureToRecognizer.value(g)) { + m_gestureToRecognizer.remove(g); + m_obsoleteGestures[recognizer].insert(g); + } + } + } + ++iter; + } +} + +void QGestureManager::cleanupCachedGestures(QObject *target, Qt::GestureType type) +{ + QMap >::Iterator iter = m_objectGestures.begin(); + while (iter != m_objectGestures.end()) { + ObjectGesture objectGesture = iter.key(); + if (objectGesture.gesture == type && target == objectGesture.object) { + QSet gestures = iter.value().toSet(); + for (QHash >::iterator + it = m_obsoleteGestures.begin(), e = m_obsoleteGestures.end(); it != e; ++it) { + it.value() -= gestures; + } + foreach (QGesture *g, gestures) { + m_deletedRecognizers.remove(g); + m_gestureToRecognizer.remove(g); + m_maybeGestures.remove(g); + m_activeGestures.remove(g); + m_gestureOwners.remove(g); + m_gestureTargets.remove(g); + m_gesturesToDelete.insert(g); + } + + 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 careful not to + // create a new state, as it will create QWeakPointer which doesn't work + // from the destructor. + if (object->isWidgetType()) { + if (static_cast(object)->d_func()->data.in_destructor) + return 0; + } else if (QGesture *g = qobject_cast(object)) { + return g; +#ifndef QT_NO_GRAPHICSVIEW + } else { + Q_ASSERT(qobject_cast(object)); + QGraphicsObject *graphicsObject = static_cast(object); + if (graphicsObject->QGraphicsItem::d_func()->inDestructor) + return 0; +#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; + } + + 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)); +#endif + } + m_objectGestures[QGestureManager::ObjectGesture(object, type)].append(state); + m_gestureToRecognizer[state] = recognizer; + m_gestureOwners[state] = object; + + return state; +} + +bool QGestureManager::filterEventThroughContexts(const QMultiMap &contexts, + QEvent *event) +{ + QSet triggeredGestures; + QSet finishedGestures; + QSet newMaybeGestures; + QSet notGestures; + + // TODO: sort contexts by the gesture type and check if one of the contexts + // is already active. + + bool consumeEventHint = false; + + // filter the event through recognizers + typedef QMultiMap::const_iterator ContextIterator; + ContextIterator contextEnd = contexts.end(); + for (ContextIterator context = contexts.begin(); context != contextEnd; ++context) { + Qt::GestureType gestureType = context.value(); + QMap::const_iterator + typeToRecognizerIterator = m_recognizers.lowerBound(gestureType), + typeToRecognizerEnd = m_recognizers.upperBound(gestureType); + for (; typeToRecognizerIterator != typeToRecognizerEnd; ++typeToRecognizerIterator) { + QGestureRecognizer *recognizer = typeToRecognizerIterator.value(); + QObject *target = context.key(); + QGesture *state = getState(target, recognizer, gestureType); + if (!state) + continue; + QGestureRecognizer::Result recognizerResult = recognizer->recognize(state, target, event); + QGestureRecognizer::Result recognizerState = recognizerResult & QGestureRecognizer::ResultState_Mask; + QGestureRecognizer::Result resultHint = recognizerResult & QGestureRecognizer::ResultHint_Mask; + if (recognizerState == QGestureRecognizer::TriggerGesture) { + DEBUG() << "QGestureManager:Recognizer: gesture triggered: " << state; + triggeredGestures << state; + } else if (recognizerState == QGestureRecognizer::FinishGesture) { + DEBUG() << "QGestureManager:Recognizer: gesture finished: " << state; + finishedGestures << state; + } else if (recognizerState == QGestureRecognizer::MayBeGesture) { + DEBUG() << "QGestureManager:Recognizer: maybe gesture: " << state; + newMaybeGestures << state; + } else if (recognizerState == QGestureRecognizer::CancelGesture) { + DEBUG() << "QGestureManager:Recognizer: not gesture: " << state; + notGestures << state; + } else if (recognizerState == QGestureRecognizer::Ignore) { + DEBUG() << "QGestureManager:Recognizer: ignored the event: " << state; + } else { + DEBUG() << "QGestureManager:Recognizer: hm, lets assume the recognizer" + << "ignored the event: " << state; + } + if (resultHint & QGestureRecognizer::ConsumeEventHint) { + DEBUG() << "QGestureManager: we were asked to consume the event: " + << state; + consumeEventHint = true; + } + } + } + if (triggeredGestures.isEmpty() && finishedGestures.isEmpty() + && newMaybeGestures.isEmpty() && notGestures.isEmpty()) + return consumeEventHint; + + QSet startedGestures = triggeredGestures - m_activeGestures; + triggeredGestures &= m_activeGestures; + + // check if a running gesture switched back to maybe state + QSet activeToMaybeGestures = m_activeGestures & newMaybeGestures; + + // check if a maybe gesture switched to canceled - reset it but don't send an event + QSet maybeToCanceledGestures = m_maybeGestures & notGestures; + + // check if a running gesture switched back to not gesture state, + // i.e. were canceled + QSet canceledGestures = m_activeGestures & notGestures; + + // new gestures in maybe state + m_maybeGestures += newMaybeGestures; + + // gestures that were in maybe state + QSet notMaybeGestures = (startedGestures | triggeredGestures + | finishedGestures | canceledGestures + | notGestures); + m_maybeGestures -= notMaybeGestures; + + Q_ASSERT((startedGestures & finishedGestures).isEmpty()); + Q_ASSERT((startedGestures & newMaybeGestures).isEmpty()); + Q_ASSERT((startedGestures & canceledGestures).isEmpty()); + Q_ASSERT((finishedGestures & newMaybeGestures).isEmpty()); + Q_ASSERT((finishedGestures & canceledGestures).isEmpty()); + Q_ASSERT((canceledGestures & newMaybeGestures).isEmpty()); + + QSet 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. + foreach (QGesture *gesture, notStarted) + gesture->d_func()->state = Qt::GestureStarted; + QSet undeliveredGestures; + deliverEvents(notStarted, &undeliveredGestures); + finishedGestures -= undeliveredGestures; + } + + m_activeGestures += startedGestures; + // sanity check: all triggered gestures should already be in active gestures list + 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) + gesture->d_func()->state = Qt::GestureStarted; + foreach (QGesture *gesture, triggeredGestures) + gesture->d_func()->state = Qt::GestureUpdated; + foreach (QGesture *gesture, finishedGestures) + gesture->d_func()->state = Qt::GestureFinished; + foreach (QGesture *gesture, canceledGestures) + gesture->d_func()->state = Qt::GestureCanceled; + foreach (QGesture *gesture, activeToMaybeGestures) + gesture->d_func()->state = Qt::GestureFinished; + + if (!m_activeGestures.isEmpty() || !m_maybeGestures.isEmpty() || + !startedGestures.isEmpty() || !triggeredGestures.isEmpty() || + !finishedGestures.isEmpty() || !canceledGestures.isEmpty()) { + DEBUG() << "QGestureManager::filterEventThroughContexts:" + << "\n\tactiveGestures:" << m_activeGestures + << "\n\tmaybeGestures:" << m_maybeGestures + << "\n\tstarted:" << startedGestures + << "\n\ttriggered:" << triggeredGestures + << "\n\tfinished:" << finishedGestures + << "\n\tcanceled:" << canceledGestures + << "\n\tmaybe-canceled:" << maybeToCanceledGestures; + } + + QSet undeliveredGestures; + deliverEvents(startedGestures+triggeredGestures+finishedGestures+canceledGestures, + &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 endedGestures = + finishedGestures + canceledGestures + undeliveredGestures + maybeToCanceledGestures; + foreach (QGesture *gesture, endedGestures) { + recycle(gesture); + m_gestureTargets.remove(gesture); + } + + //Clean up the Gestures + qDeleteAll(m_gesturesToDelete); + m_gesturesToDelete.clear(); + + return consumeEventHint; +} + +// 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 cancelledGestures; + QSet::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 almostCanceledGestures = cancelledGestures; + while (!almostCanceledGestures.isEmpty()) { + QWidget *target = 0; + QSet 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 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); + if(!recognizer) //The Gesture is removed while in the even loop, so the recognizers for this gestures was removed + return; + 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) +{ + QMap types; + QMultiMap contexts; + QWidget *w = receiver; + typedef QMap::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(), 0); + contexts.insertMulti(w, it.key()); + } + } + // find all gesture contexts for the widget tree + w = w->isWindow() ? 0 : w->parentWidget(); + while (w) + { + for (ContextIterator it = w->d_func()->gestureContext.begin(), + e = w->d_func()->gestureContext.end(); it != e; ++it) { + if (!(it.value() & Qt::DontStartGestureOnChildren)) { + if (!types.contains(it.key())) { + types.insert(it.key(), 0); + contexts.insertMulti(w, it.key()); + } + } + } + if (w->isWindow()) + break; + w = w->parentWidget(); + } + return contexts.isEmpty() ? false : filterEventThroughContexts(contexts, event); +} + +#ifndef QT_NO_GRAPHICSVIEW +bool QGestureManager::filterEvent(QGraphicsObject *receiver, QEvent *event) +{ + QMap types; + QMultiMap contexts; + QGraphicsObject *item = receiver; + if (!item->QGraphicsItem::d_func()->gestureContext.isEmpty()) { + typedef QMap::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(), 0); + contexts.insertMulti(item, it.key()); + } + } + // find all gesture contexts for the graphics object tree + item = item->parentObject(); + while (item) + { + typedef QMap::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::DontStartGestureOnChildren)) { + if (!types.contains(it.key())) { + types.insert(it.key(), 0); + contexts.insertMulti(item, it.key()); + } + } + } + item = item->parentObject(); + } + return contexts.isEmpty() ? false : filterEventThroughContexts(contexts, event); +} +#endif + +bool QGestureManager::filterEvent(QObject *receiver, QEvent *event) +{ + if (!m_gestureToRecognizer.contains(static_cast(receiver))) + return false; + QGesture *state = static_cast(receiver); + QMultiMap contexts; + contexts.insert(state, state->gestureType()); + return filterEventThroughContexts(contexts, event); +} + +void QGestureManager::getGestureTargets(const QSet &gestures, + QMap > *conflicts, + QMap > *normal) +{ + typedef QHash > GestureByTypes; + GestureByTypes gestureByTypes; + + // sort gestures by types + foreach (QGesture *gesture, gestures) { + QWidget *receiver = m_gestureTargets.value(gesture, 0); + Q_ASSERT(receiver); + gestureByTypes[gesture->gestureType()].insert(receiver, gesture); + } + + // for each gesture type + foreach (Qt::GestureType type, gestureByTypes.keys()) { + QHash gestures = gestureByTypes.value(type); + foreach (QWidget *widget, gestures.keys()) { + QWidget *w = widget->parentWidget(); + while (w) { + QMap::const_iterator it + = w->d_func()->gestureContext.find(type); + if (it != w->d_func()->gestureContext.end()) { + // i.e. 'w' listens to gesture 'type' + Qt::GestureFlags flags = it.value(); + if (!(it.value() & Qt::DontStartGestureOnChildren) && w != widget) { + // conflicting gesture! + (*conflicts)[widget].append(gestures[widget]); + break; + } + } + if (w->isWindow()) { + w = 0; + break; + } + w = w->parentWidget(); + } + if (!w) + (*normal)[widget].append(gestures[widget]); + } + } +} + +void QGestureManager::deliverEvents(const QSet &gestures, + QSet *undeliveredGestures) +{ + if (gestures.isEmpty()) + return; + + typedef QMap > GesturesPerWidget; + GesturesPerWidget conflictedGestures; + GesturesPerWidget normalStartedGestures; + + QSet startedGestures; + // first figure out the initial receivers of gestures + for (QSet::const_iterator it = gestures.begin(), + e = gestures.end(); it != e; ++it) { + QGesture *gesture = *it; + 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); + if (gesture->hasHotSpot()) { + // guess the target widget using the hotspot of the gesture + QPoint pt = gesture->hotSpot().toPoint(); + if (QWidget *topLevel = qApp->topLevelAt(pt)) { + QWidget *child = topLevel->childAt(topLevel->mapFromGlobal(pt)); + target = child ? child : topLevel; + } + } else { + // or use the context of the gesture + QObject *context = m_gestureOwners.value(gesture, 0); + if (context->isWidgetType()) + target = static_cast(context); + } + if (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) { + startedGestures.insert(gesture); + } else { + normalStartedGestures[target].append(gesture); + } + } else { + DEBUG() << "QGestureManager::deliverEvent: could not find the target for gesture" + << gesture->gestureType(); + qWarning("QGestureManager::deliverEvent: could not find the target for gesture"); + undeliveredGestures->insert(gesture); + } + } + + getGestureTargets(startedGestures, &conflictedGestures, &normalStartedGestures); + DEBUG() << "QGestureManager::deliverEvents:" + << "\nstarted: " << startedGestures + << "\nconflicted: " << conflictedGestures + << "\nnormal: " << normalStartedGestures + << "\n"; + + // if there are conflicting gestures, send the GestureOverride event + for (GesturesPerWidget::const_iterator it = conflictedGestures.begin(), + e = conflictedGestures.end(); it != e; ++it) { + QWidget *receiver = it.key(); + QList gestures = it.value(); + DEBUG() << "QGestureManager::deliverEvents: sending GestureOverride to" + << receiver + << "gestures:" << gestures; + QGestureEvent event(gestures); + event.t = QEvent::GestureOverride; + // mark event and individual gestures as ignored + event.ignore(); + foreach(QGesture *g, gestures) + event.setAccepted(g, false); + + QApplication::sendEvent(receiver, &event); + bool eventAccepted = event.isAccepted(); + foreach(QGesture *gesture, event.gestures()) { + if (eventAccepted || event.isAccepted(gesture)) { + QWidget *w = event.d_func()->targetWidgets.value(gesture->gestureType(), 0); + Q_ASSERT(w); + DEBUG() << "override event: gesture was accepted:" << gesture << w; + QList &gestures = normalStartedGestures[w]; + gestures.append(gesture); + // override the target + m_gestureTargets[gesture] = w; + } else { + DEBUG() << "override event: gesture wasn't accepted. putting back:" << gesture; + QList &gestures = normalStartedGestures[receiver]; + gestures.append(gesture); + } + } + } + + // delivering gestures that are not in conflicted state + for (GesturesPerWidget::const_iterator it = normalStartedGestures.begin(), + e = normalStartedGestures.end(); it != e; ++it) { + if (!it.value().isEmpty()) { + DEBUG() << "QGestureManager::deliverEvents: sending to" << it.key() + << "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::recycle(QGesture *gesture) +{ + QGestureRecognizer *recognizer = m_gestureToRecognizer.value(gesture, 0); + if (recognizer) { + gesture->setGestureCancelPolicy(QGesture::CancelNone); + recognizer->reset(gesture); + m_activeGestures.remove(gesture); + } else { + cleanupGesturesForRemovedRecognizer(gesture); + } +} + +QT_END_NAMESPACE + +#endif // QT_NO_GESTURES + +#include "moc_qgesturemanager_p.cpp" -- cgit v1.2.3