/****************************************************************************
**
** 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$
** GNU Lesser General Public License Usage
** 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.
**
** 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $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<Qt::GestureState>();

#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<QGestureRecognizer *> 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<QGesture *>());
        }
    }
    foreach (QGesture *g, m_gestureToRecognizer.keys()) {
        QGestureRecognizer *recognizer = m_gestureToRecognizer.value(g);
        if (list.contains(recognizer)) {
            m_deletedRecognizers.insert(g, recognizer);
        }
    }

    QMap<ObjectGesture, QList<QGesture *> >::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<ObjectGesture, QList<QGesture *> >::Iterator iter = m_objectGestures.begin();
    while (iter != m_objectGestures.end()) {
        ObjectGesture objectGesture = iter.key();
        if (objectGesture.gesture == type && target == objectGesture.object) {
            QSet<QGesture *> gestures = iter.value().toSet();
            for (QHash<QGestureRecognizer *, QSet<QGesture *> >::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<QWidget *>(object)->d_func()->data.in_destructor)
            return 0;
    } else if (QGesture *g = qobject_cast<QGesture *>(object)) {
        return g;
#ifndef QT_NO_GRAPHICSVIEW
    } else {
        Q_ASSERT(qobject_cast<QGraphicsObject *>(object));
        QGraphicsObject *graphicsObject = static_cast<QGraphicsObject *>(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<QObject *,
                                                 Qt::GestureType> &contexts,
                                                 QEvent *event)
{
    QSet<QGesture *> triggeredGestures;
    QSet<QGesture *> finishedGestures;
    QSet<QGesture *> newMaybeGestures;
    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 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 = 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, recognizer, gestureType);
            if (!state)
                continue;
            QGestureRecognizer::Result result = recognizer->recognize(state, target, event);
            QGestureRecognizer::Result type = result & QGestureRecognizer::ResultState_Mask;
            result &= QGestureRecognizer::ResultHint_Mask;
            if (type == QGestureRecognizer::TriggerGesture) {
                DEBUG() << "QGestureManager:Recognizer: gesture triggered: " << state;
                triggeredGestures << state;
            } else if (type == QGestureRecognizer::FinishGesture) {
                DEBUG() << "QGestureManager:Recognizer: gesture finished: " << state;
                finishedGestures << state;
            } else if (type == QGestureRecognizer::MayBeGesture) {
                DEBUG() << "QGestureManager:Recognizer: maybe gesture: " << state;
                newMaybeGestures << state;
            } else if (type == QGestureRecognizer::CancelGesture) {
                DEBUG() << "QGestureManager:Recognizer: not gesture: " << state;
                notGestures << state;
            } else if (type == QGestureRecognizer::Ignore) {
                DEBUG() << "QGestureManager:Recognizer: ignored the event: " << state;
            } else {
                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;
                ret = true;
            }
        }
    }
    if (triggeredGestures.isEmpty() && finishedGestures.isEmpty()
        && newMaybeGestures.isEmpty() && notGestures.isEmpty())
        return ret;

    QSet<QGesture *> startedGestures = triggeredGestures - m_activeGestures;
    triggeredGestures &= m_activeGestures;

    // check if a running gesture switched back to maybe state
    QSet<QGesture *> activeToMaybeGestures = m_activeGestures & newMaybeGestures;

    // check if a maybe gesture switched to canceled - reset it but don't send an event
    QSet<QGesture *> maybeToCanceledGestures = m_maybeGestures & notGestures;

    // check if a running gesture switched back to not gesture state,
    // i.e. were canceled
    QSet<QGesture *> canceledGestures = m_activeGestures & notGestures;

    // new gestures in maybe state
    m_maybeGestures += newMaybeGestures;

    // gestures that were in maybe state
    QSet<QGesture *> 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<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.
        foreach (QGesture *gesture, notStarted)
            gesture->d_func()->state = Qt::GestureStarted;
        QSet<QGesture *> 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<QGesture *> 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<QGesture *> 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 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);
    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<Qt::GestureType, int> types;
    QMultiMap<QObject *, Qt::GestureType> contexts;
    QWidget *w = receiver;
    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(), 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<Qt::GestureType, int> types;
    QMultiMap<QObject *, Qt::GestureType> contexts;
    QGraphicsObject *item = receiver;
    if (!item->QGraphicsItem::d_func()->gestureContext.isEmpty()) {
        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(), 0);
            contexts.insertMulti(item, it.key());
        }
    }
    // find all gesture contexts for the graphics object tree
    item = item->parentObject();
    while (item)
    {
        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::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<QGesture *>(receiver)))
        return false;
    QGesture *state = static_cast<QGesture *>(receiver);
    QMultiMap<QObject *, Qt::GestureType> contexts;
    contexts.insert(state, state->gestureType());
    return filterEventThroughContexts(contexts, event);
}

void QGestureManager::getGestureTargets(const QSet<QGesture*> &gestures,
    QMap<QWidget *, QList<QGesture *> > *conflicts,
    QMap<QWidget *, QList<QGesture *> > *normal)
{
    typedef QHash<Qt::GestureType, QHash<QWidget *, QGesture *> > 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<QWidget *, QGesture *> gestures = gestureByTypes.value(type);
        foreach (QWidget *widget, gestures.keys()) {
            QWidget *w = widget->parentWidget();
            while (w) {
                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::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<QGesture *> &gestures,
                                    QSet<QGesture *> *undeliveredGestures)
{
    if (gestures.isEmpty())
        return;

    typedef QMap<QWidget *, QList<QGesture *> > GesturesPerWidget;
    GesturesPerWidget conflictedGestures;
    GesturesPerWidget normalStartedGestures;

    QSet<QGesture *> startedGestures;
    // first figure out the initial receivers of gestures
    for (QSet<QGesture *>::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<QWidget *>(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<QGesture *> 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<QGesture *> &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<QGesture *> &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"
