Fixes warnings about unused variables
[profile/ivi/qtbase.git] / src / gui / kernel / qgesturemanager.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the QtGui module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file.  Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "private/qgesturemanager_p.h"
43 #include "private/qstandardgestures_p.h"
44 #include "private/qwidget_p.h"
45 #include "private/qgesture_p.h"
46 #include "private/qgraphicsitem_p.h"
47 #include "private/qevent_p.h"
48 #include "private/qapplication_p.h"
49 #include "qgesture.h"
50 #include "qevent.h"
51 #include "qgraphicsitem.h"
52
53 #ifdef Q_WS_MAC
54 #include "qmacgesturerecognizer_mac_p.h"
55 #endif
56 #if defined(Q_OS_WIN) && !defined(QT_NO_NATIVE_GESTURES)
57 #include "qwinnativepangesturerecognizer_win_p.h"
58 #endif
59
60 #include "qdebug.h"
61
62 // #define GESTURE_DEBUG
63 #ifndef GESTURE_DEBUG
64 # define DEBUG if (0) qDebug
65 #else
66 # define DEBUG qDebug
67 #endif
68
69 #ifndef QT_NO_GESTURES
70
71 QT_BEGIN_NAMESPACE
72
73 QGestureManager::QGestureManager(QObject *parent)
74     : QObject(parent), state(NotGesture), m_lastCustomGestureId(Qt::CustomGesture)
75 {
76     qRegisterMetaType<Qt::GestureState>();
77
78 #if defined(Q_WS_MAC)
79     registerGestureRecognizer(new QMacSwipeGestureRecognizer);
80     registerGestureRecognizer(new QMacPinchGestureRecognizer);
81   #if defined(QT_MAC_USE_COCOA)
82     registerGestureRecognizer(new QMacPanGestureRecognizer);
83   #endif
84 #else
85     registerGestureRecognizer(new QPanGestureRecognizer);
86     registerGestureRecognizer(new QPinchGestureRecognizer);
87     registerGestureRecognizer(new QSwipeGestureRecognizer);
88     registerGestureRecognizer(new QTapGestureRecognizer);
89 #endif
90 #if defined(Q_OS_WIN)
91   #if !defined(QT_NO_NATIVE_GESTURES)
92     if (QApplicationPrivate::HasTouchSupport)
93         registerGestureRecognizer(new QWinNativePanGestureRecognizer);
94   #endif
95 #else
96     registerGestureRecognizer(new QTapAndHoldGestureRecognizer);
97 #endif
98 }
99
100 QGestureManager::~QGestureManager()
101 {
102     qDeleteAll(m_recognizers.values());
103     foreach (QGestureRecognizer *recognizer, m_obsoleteGestures.keys()) {
104         qDeleteAll(m_obsoleteGestures.value(recognizer));
105         delete recognizer;
106     }
107     m_obsoleteGestures.clear();
108 }
109
110 Qt::GestureType QGestureManager::registerGestureRecognizer(QGestureRecognizer *recognizer)
111 {
112     QGesture *dummy = recognizer->create(0);
113     if (!dummy) {
114         qWarning("QGestureManager::registerGestureRecognizer: "
115                  "the recognizer fails to create a gesture object, skipping registration.");
116         return Qt::GestureType(0);
117     }
118     Qt::GestureType type = dummy->gestureType();
119     if (type == Qt::CustomGesture) {
120         // generate a new custom gesture id
121         ++m_lastCustomGestureId;
122         type = Qt::GestureType(m_lastCustomGestureId);
123     }
124     m_recognizers.insertMulti(type, recognizer);
125     delete dummy;
126     return type;
127 }
128
129 void QGestureManager::unregisterGestureRecognizer(Qt::GestureType type)
130 {
131     QList<QGestureRecognizer *> list = m_recognizers.values(type);
132     while (QGestureRecognizer *recognizer = m_recognizers.take(type)) {
133         if (!m_obsoleteGestures.contains(recognizer)) {
134             // inserting even an empty QSet will cause the recognizer to be deleted on destruction of the manager
135             m_obsoleteGestures.insert(recognizer, QSet<QGesture *>());
136         }
137     }
138     foreach (QGesture *g, m_gestureToRecognizer.keys()) {
139         QGestureRecognizer *recognizer = m_gestureToRecognizer.value(g);
140         if (list.contains(recognizer)) {
141             m_deletedRecognizers.insert(g, recognizer);
142         }
143     }
144
145     QMap<ObjectGesture, QList<QGesture *> >::const_iterator iter = m_objectGestures.begin();
146     while (iter != m_objectGestures.end()) {
147         ObjectGesture objectGesture = iter.key();
148         if (objectGesture.gesture == type) {
149             foreach (QGesture *g, iter.value()) {
150                 if (QGestureRecognizer *recognizer = m_gestureToRecognizer.value(g)) {
151                     m_gestureToRecognizer.remove(g);
152                     m_obsoleteGestures[recognizer].insert(g);
153                 }
154             }
155         }
156         ++iter;
157     }
158 }
159
160 void QGestureManager::cleanupCachedGestures(QObject *target, Qt::GestureType type)
161 {
162     QMap<ObjectGesture, QList<QGesture *> >::Iterator iter = m_objectGestures.begin();
163     while (iter != m_objectGestures.end()) {
164         ObjectGesture objectGesture = iter.key();
165         if (objectGesture.gesture == type && target == objectGesture.object) {
166             QSet<QGesture *> gestures = iter.value().toSet();
167             for (QHash<QGestureRecognizer *, QSet<QGesture *> >::iterator
168                  it = m_obsoleteGestures.begin(), e = m_obsoleteGestures.end(); it != e; ++it) {
169                 it.value() -= gestures;
170             }
171             foreach (QGesture *g, gestures) {
172                 m_deletedRecognizers.remove(g);
173                 m_gestureToRecognizer.remove(g);
174                 m_maybeGestures.remove(g);
175                 m_activeGestures.remove(g);
176                 m_gestureOwners.remove(g);
177                 m_gestureTargets.remove(g);
178                 m_gesturesToDelete.insert(g);
179             }
180
181             iter = m_objectGestures.erase(iter);
182         } else {
183             ++iter;
184         }
185     }
186 }
187
188 // get or create a QGesture object that will represent the state for a given object, used by the recognizer
189 QGesture *QGestureManager::getState(QObject *object, QGestureRecognizer *recognizer, Qt::GestureType type)
190 {
191     // if the widget is being deleted we should be careful not to
192     // create a new state, as it will create QWeakPointer which doesn't work
193     // from the destructor.
194     if (object->isWidgetType()) {
195         if (static_cast<QWidget *>(object)->d_func()->data.in_destructor)
196             return 0;
197     } else if (QGesture *g = qobject_cast<QGesture *>(object)) {
198         return g;
199 #ifndef QT_NO_GRAPHICSVIEW
200     } else {
201         Q_ASSERT(qobject_cast<QGraphicsObject *>(object));
202         QGraphicsObject *graphicsObject = static_cast<QGraphicsObject *>(object);
203         if (graphicsObject->QGraphicsItem::d_func()->inDestructor)
204             return 0;
205 #endif
206     }
207
208     // check if the QGesture for this recognizer has already been created
209     foreach (QGesture *state, m_objectGestures.value(QGestureManager::ObjectGesture(object, type))) {
210         if (m_gestureToRecognizer.value(state) == recognizer)
211             return state;
212     }
213
214     Q_ASSERT(recognizer);
215     QGesture *state = recognizer->create(object);
216     if (!state)
217         return 0;
218     state->setParent(this);
219     if (state->gestureType() == Qt::CustomGesture) {
220         // if the recognizer didn't fill in the gesture type, then this
221         // is a custom gesture with autogenerated id and we fill it.
222         state->d_func()->gestureType = type;
223 #if defined(GESTURE_DEBUG)
224         state->setObjectName(QString::number((int)type));
225 #endif
226     }
227     m_objectGestures[QGestureManager::ObjectGesture(object, type)].append(state);
228     m_gestureToRecognizer[state] = recognizer;
229     m_gestureOwners[state] = object;
230
231     return state;
232 }
233
234 bool QGestureManager::filterEventThroughContexts(const QMultiMap<QObject *,
235                                                  Qt::GestureType> &contexts,
236                                                  QEvent *event)
237 {
238     QSet<QGesture *> triggeredGestures;
239     QSet<QGesture *> finishedGestures;
240     QSet<QGesture *> newMaybeGestures;
241     QSet<QGesture *> notGestures;
242
243     // TODO: sort contexts by the gesture type and check if one of the contexts
244     //       is already active.
245
246     bool consumeEventHint = false;
247
248     // filter the event through recognizers
249     typedef QMultiMap<QObject *, Qt::GestureType>::const_iterator ContextIterator;
250     ContextIterator contextEnd = contexts.end();
251     for (ContextIterator context = contexts.begin(); context != contextEnd; ++context) {
252         Qt::GestureType gestureType = context.value();
253         QMap<Qt::GestureType, QGestureRecognizer *>::const_iterator
254                 typeToRecognizerIterator = m_recognizers.lowerBound(gestureType),
255                 typeToRecognizerEnd = m_recognizers.upperBound(gestureType);
256         for (; typeToRecognizerIterator != typeToRecognizerEnd; ++typeToRecognizerIterator) {
257             QGestureRecognizer *recognizer = typeToRecognizerIterator.value();
258             QObject *target = context.key();
259             QGesture *state = getState(target, recognizer, gestureType);
260             if (!state)
261                 continue;
262             QGestureRecognizer::Result recognizerResult = recognizer->recognize(state, target, event);
263             QGestureRecognizer::Result recognizerState = recognizerResult & QGestureRecognizer::ResultState_Mask;
264             QGestureRecognizer::Result resultHint = recognizerResult & QGestureRecognizer::ResultHint_Mask;
265             if (recognizerState == QGestureRecognizer::TriggerGesture) {
266                 DEBUG() << "QGestureManager:Recognizer: gesture triggered: " << state;
267                 triggeredGestures << state;
268             } else if (recognizerState == QGestureRecognizer::FinishGesture) {
269                 DEBUG() << "QGestureManager:Recognizer: gesture finished: " << state;
270                 finishedGestures << state;
271             } else if (recognizerState == QGestureRecognizer::MayBeGesture) {
272                 DEBUG() << "QGestureManager:Recognizer: maybe gesture: " << state;
273                 newMaybeGestures << state;
274             } else if (recognizerState == QGestureRecognizer::CancelGesture) {
275                 DEBUG() << "QGestureManager:Recognizer: not gesture: " << state;
276                 notGestures << state;
277             } else if (recognizerState == QGestureRecognizer::Ignore) {
278                 DEBUG() << "QGestureManager:Recognizer: ignored the event: " << state;
279             } else {
280                 DEBUG() << "QGestureManager:Recognizer: hm, lets assume the recognizer"
281                         << "ignored the event: " << state;
282             }
283             if (resultHint & QGestureRecognizer::ConsumeEventHint) {
284                 DEBUG() << "QGestureManager: we were asked to consume the event: "
285                         << state;
286                 consumeEventHint = true;
287             }
288         }
289     }
290     if (triggeredGestures.isEmpty() && finishedGestures.isEmpty()
291         && newMaybeGestures.isEmpty() && notGestures.isEmpty())
292         return consumeEventHint;
293
294     QSet<QGesture *> startedGestures = triggeredGestures - m_activeGestures;
295     triggeredGestures &= m_activeGestures;
296
297     // check if a running gesture switched back to maybe state
298     QSet<QGesture *> activeToMaybeGestures = m_activeGestures & newMaybeGestures;
299
300     // check if a maybe gesture switched to canceled - reset it but don't send an event
301     QSet<QGesture *> maybeToCanceledGestures = m_maybeGestures & notGestures;
302
303     // check if a running gesture switched back to not gesture state,
304     // i.e. were canceled
305     QSet<QGesture *> canceledGestures = m_activeGestures & notGestures;
306
307     // new gestures in maybe state
308     m_maybeGestures += newMaybeGestures;
309
310     // gestures that were in maybe state
311     QSet<QGesture *> notMaybeGestures = (startedGestures | triggeredGestures
312                                          | finishedGestures | canceledGestures
313                                          | notGestures);
314     m_maybeGestures -= notMaybeGestures;
315
316     Q_ASSERT((startedGestures & finishedGestures).isEmpty());
317     Q_ASSERT((startedGestures & newMaybeGestures).isEmpty());
318     Q_ASSERT((startedGestures & canceledGestures).isEmpty());
319     Q_ASSERT((finishedGestures & newMaybeGestures).isEmpty());
320     Q_ASSERT((finishedGestures & canceledGestures).isEmpty());
321     Q_ASSERT((canceledGestures & newMaybeGestures).isEmpty());
322
323     QSet<QGesture *> notStarted = finishedGestures - m_activeGestures;
324     if (!notStarted.isEmpty()) {
325         // there are some gestures that claim to be finished, but never started.
326         // probably those are "singleshot" gestures so we'll fake the started state.
327         foreach (QGesture *gesture, notStarted)
328             gesture->d_func()->state = Qt::GestureStarted;
329         QSet<QGesture *> undeliveredGestures;
330         deliverEvents(notStarted, &undeliveredGestures);
331         finishedGestures -= undeliveredGestures;
332     }
333
334     m_activeGestures += startedGestures;
335     // sanity check: all triggered gestures should already be in active gestures list
336     Q_ASSERT((m_activeGestures & triggeredGestures).size() == triggeredGestures.size());
337     m_activeGestures -= finishedGestures;
338     m_activeGestures -= activeToMaybeGestures;
339     m_activeGestures -= canceledGestures;
340
341     // set the proper gesture state on each gesture
342     foreach (QGesture *gesture, startedGestures)
343         gesture->d_func()->state = Qt::GestureStarted;
344     foreach (QGesture *gesture, triggeredGestures)
345         gesture->d_func()->state = Qt::GestureUpdated;
346     foreach (QGesture *gesture, finishedGestures)
347         gesture->d_func()->state = Qt::GestureFinished;
348     foreach (QGesture *gesture, canceledGestures)
349         gesture->d_func()->state = Qt::GestureCanceled;
350     foreach (QGesture *gesture, activeToMaybeGestures)
351         gesture->d_func()->state = Qt::GestureFinished;
352
353     if (!m_activeGestures.isEmpty() || !m_maybeGestures.isEmpty() ||
354         !startedGestures.isEmpty() || !triggeredGestures.isEmpty() ||
355         !finishedGestures.isEmpty() || !canceledGestures.isEmpty()) {
356         DEBUG() << "QGestureManager::filterEventThroughContexts:"
357                 << "\n\tactiveGestures:" << m_activeGestures
358                 << "\n\tmaybeGestures:" << m_maybeGestures
359                 << "\n\tstarted:" << startedGestures
360                 << "\n\ttriggered:" << triggeredGestures
361                 << "\n\tfinished:" << finishedGestures
362                 << "\n\tcanceled:" << canceledGestures
363                 << "\n\tmaybe-canceled:" << maybeToCanceledGestures;
364     }
365
366     QSet<QGesture *> undeliveredGestures;
367     deliverEvents(startedGestures+triggeredGestures+finishedGestures+canceledGestures,
368                   &undeliveredGestures);
369
370     foreach (QGesture *g, startedGestures) {
371         if (undeliveredGestures.contains(g))
372             continue;
373         if (g->gestureCancelPolicy() == QGesture::CancelAllInContext) {
374             DEBUG() << "lets try to cancel some";
375             // find gestures in context in Qt::GestureStarted or Qt::GestureUpdated state and cancel them
376             cancelGesturesForChildren(g);
377         }
378     }
379
380     m_activeGestures -= undeliveredGestures;
381
382     // reset gestures that ended
383     QSet<QGesture *> endedGestures =
384             finishedGestures + canceledGestures + undeliveredGestures + maybeToCanceledGestures;
385     foreach (QGesture *gesture, endedGestures) {
386         recycle(gesture);
387         m_gestureTargets.remove(gesture);
388     }
389
390     //Clean up the Gestures
391     qDeleteAll(m_gesturesToDelete);
392     m_gesturesToDelete.clear();
393
394     return consumeEventHint;
395 }
396
397 // Cancel all gestures of children of the widget that original is associated with
398 void QGestureManager::cancelGesturesForChildren(QGesture *original)
399 {
400     Q_ASSERT(original);
401     QWidget *originatingWidget = m_gestureTargets.value(original);
402     Q_ASSERT(originatingWidget);
403
404     // iterate over all active gestures and all maybe gestures
405     // for each find the owner
406     // if the owner is part of our sub-hierarchy, cancel it.
407
408     QSet<QGesture*> cancelledGestures;
409     QSet<QGesture*>::Iterator iter = m_activeGestures.begin();
410     while (iter != m_activeGestures.end()) {
411         QWidget *widget = m_gestureTargets.value(*iter);
412         // note that we don't touch the gestures for our originatingWidget
413         if (widget != originatingWidget && originatingWidget->isAncestorOf(widget)) {
414             DEBUG() << "  found a gesture to cancel" << (*iter);
415             (*iter)->d_func()->state = Qt::GestureCanceled;
416             cancelledGestures << *iter;
417             iter = m_activeGestures.erase(iter);
418         } else {
419             ++iter;
420         }
421     }
422
423     // TODO handle 'maybe' gestures too
424
425     // sort them per target widget by cherry picking from almostCanceledGestures and delivering
426     QSet<QGesture *> almostCanceledGestures = cancelledGestures;
427     while (!almostCanceledGestures.isEmpty()) {
428         QWidget *target = 0;
429         QSet<QGesture*> gestures;
430         iter = almostCanceledGestures.begin();
431         // sort per target widget
432         while (iter != almostCanceledGestures.end()) {
433             QWidget *widget = m_gestureTargets.value(*iter);
434             if (target == 0)
435                 target = widget;
436             if (target == widget) {
437                 gestures << *iter;
438                 iter = almostCanceledGestures.erase(iter);
439             } else {
440                 ++iter;
441             }
442         }
443         Q_ASSERT(target);
444
445         QSet<QGesture*> undeliveredGestures;
446         deliverEvents(gestures, &undeliveredGestures);
447     }
448
449     for (iter = cancelledGestures.begin(); iter != cancelledGestures.end(); ++iter)
450         recycle(*iter);
451 }
452
453 void QGestureManager::cleanupGesturesForRemovedRecognizer(QGesture *gesture)
454 {
455     QGestureRecognizer *recognizer = m_deletedRecognizers.value(gesture);
456     if(!recognizer) //The Gesture is removed while in the even loop, so the recognizers for this gestures was removed
457         return;
458     m_deletedRecognizers.remove(gesture);
459     if (m_deletedRecognizers.keys(recognizer).isEmpty()) {
460         // no more active gestures, cleanup!
461         qDeleteAll(m_obsoleteGestures.value(recognizer));
462         m_obsoleteGestures.remove(recognizer);
463         delete recognizer;
464     }
465 }
466
467 // return true if accepted (consumed)
468 bool QGestureManager::filterEvent(QWidget *receiver, QEvent *event)
469 {
470     QMap<Qt::GestureType, int> types;
471     QMultiMap<QObject *, Qt::GestureType> contexts;
472     QWidget *w = receiver;
473     typedef QMap<Qt::GestureType, Qt::GestureFlags>::const_iterator ContextIterator;
474     if (!w->d_func()->gestureContext.isEmpty()) {
475         for(ContextIterator it = w->d_func()->gestureContext.begin(),
476             e = w->d_func()->gestureContext.end(); it != e; ++it) {
477             types.insert(it.key(), 0);
478             contexts.insertMulti(w, it.key());
479         }
480     }
481     // find all gesture contexts for the widget tree
482     w = w->isWindow() ? 0 : w->parentWidget();
483     while (w)
484     {
485         for (ContextIterator it = w->d_func()->gestureContext.begin(),
486              e = w->d_func()->gestureContext.end(); it != e; ++it) {
487             if (!(it.value() & Qt::DontStartGestureOnChildren)) {
488                 if (!types.contains(it.key())) {
489                     types.insert(it.key(), 0);
490                     contexts.insertMulti(w, it.key());
491                 }
492             }
493         }
494         if (w->isWindow())
495             break;
496         w = w->parentWidget();
497     }
498     return contexts.isEmpty() ? false : filterEventThroughContexts(contexts, event);
499 }
500
501 #ifndef QT_NO_GRAPHICSVIEW
502 bool QGestureManager::filterEvent(QGraphicsObject *receiver, QEvent *event)
503 {
504     QMap<Qt::GestureType, int> types;
505     QMultiMap<QObject *, Qt::GestureType> contexts;
506     QGraphicsObject *item = receiver;
507     if (!item->QGraphicsItem::d_func()->gestureContext.isEmpty()) {
508         typedef QMap<Qt::GestureType, Qt::GestureFlags>::const_iterator ContextIterator;
509         for(ContextIterator it = item->QGraphicsItem::d_func()->gestureContext.begin(),
510             e = item->QGraphicsItem::d_func()->gestureContext.end(); it != e; ++it) {
511             types.insert(it.key(), 0);
512             contexts.insertMulti(item, it.key());
513         }
514     }
515     // find all gesture contexts for the graphics object tree
516     item = item->parentObject();
517     while (item)
518     {
519         typedef QMap<Qt::GestureType, Qt::GestureFlags>::const_iterator ContextIterator;
520         for (ContextIterator it = item->QGraphicsItem::d_func()->gestureContext.begin(),
521              e = item->QGraphicsItem::d_func()->gestureContext.end(); it != e; ++it) {
522             if (!(it.value() & Qt::DontStartGestureOnChildren)) {
523                 if (!types.contains(it.key())) {
524                     types.insert(it.key(), 0);
525                     contexts.insertMulti(item, it.key());
526                 }
527             }
528         }
529         item = item->parentObject();
530     }
531     return contexts.isEmpty() ? false : filterEventThroughContexts(contexts, event);
532 }
533 #endif
534
535 bool QGestureManager::filterEvent(QObject *receiver, QEvent *event)
536 {
537     if (!m_gestureToRecognizer.contains(static_cast<QGesture *>(receiver)))
538         return false;
539     QGesture *state = static_cast<QGesture *>(receiver);
540     QMultiMap<QObject *, Qt::GestureType> contexts;
541     contexts.insert(state, state->gestureType());
542     return filterEventThroughContexts(contexts, event);
543 }
544
545 void QGestureManager::getGestureTargets(const QSet<QGesture*> &gestures,
546     QMap<QWidget *, QList<QGesture *> > *conflicts,
547     QMap<QWidget *, QList<QGesture *> > *normal)
548 {
549     typedef QHash<Qt::GestureType, QHash<QWidget *, QGesture *> > GestureByTypes;
550     GestureByTypes gestureByTypes;
551
552     // sort gestures by types
553     foreach (QGesture *gesture, gestures) {
554         QWidget *receiver = m_gestureTargets.value(gesture, 0);
555         Q_ASSERT(receiver);
556         gestureByTypes[gesture->gestureType()].insert(receiver, gesture);
557     }
558
559     // for each gesture type
560     foreach (Qt::GestureType type, gestureByTypes.keys()) {
561         QHash<QWidget *, QGesture *> gestures = gestureByTypes.value(type);
562         foreach (QWidget *widget, gestures.keys()) {
563             QWidget *w = widget->parentWidget();
564             while (w) {
565                 QMap<Qt::GestureType, Qt::GestureFlags>::const_iterator it
566                         = w->d_func()->gestureContext.find(type);
567                 if (it != w->d_func()->gestureContext.end()) {
568                     // i.e. 'w' listens to gesture 'type'
569                     if (!(it.value() & Qt::DontStartGestureOnChildren) && w != widget) {
570                         // conflicting gesture!
571                         (*conflicts)[widget].append(gestures[widget]);
572                         break;
573                     }
574                 }
575                 if (w->isWindow()) {
576                     w = 0;
577                     break;
578                 }
579                 w = w->parentWidget();
580             }
581             if (!w)
582                 (*normal)[widget].append(gestures[widget]);
583         }
584     }
585 }
586
587 void QGestureManager::deliverEvents(const QSet<QGesture *> &gestures,
588                                     QSet<QGesture *> *undeliveredGestures)
589 {
590     if (gestures.isEmpty())
591         return;
592
593     typedef QMap<QWidget *, QList<QGesture *> > GesturesPerWidget;
594     GesturesPerWidget conflictedGestures;
595     GesturesPerWidget normalStartedGestures;
596
597     QSet<QGesture *> startedGestures;
598     // first figure out the initial receivers of gestures
599     for (QSet<QGesture *>::const_iterator it = gestures.begin(),
600          e = gestures.end(); it != e; ++it) {
601         QGesture *gesture = *it;
602         QWidget *target = m_gestureTargets.value(gesture, 0);
603         if (!target) {
604             // the gesture has just started and doesn't have a target yet.
605             Q_ASSERT(gesture->state() == Qt::GestureStarted);
606             if (gesture->hasHotSpot()) {
607                 // guess the target widget using the hotspot of the gesture
608                 QPoint pt = gesture->hotSpot().toPoint();
609                 if (QWidget *topLevel = qApp->topLevelAt(pt)) {
610                     QWidget *child = topLevel->childAt(topLevel->mapFromGlobal(pt));
611                     target = child ? child : topLevel;
612                 }
613             } else {
614                 // or use the context of the gesture
615                 QObject *context = m_gestureOwners.value(gesture, 0);
616                 if (context->isWidgetType())
617                     target = static_cast<QWidget *>(context);
618             }
619             if (target)
620                 m_gestureTargets.insert(gesture, target);
621         }
622
623         Qt::GestureType gestureType = gesture->gestureType();
624         Q_ASSERT(gestureType != Qt::CustomGesture);
625         Q_UNUSED(gestureType);
626
627         if (target) {
628             if (gesture->state() == Qt::GestureStarted) {
629                 startedGestures.insert(gesture);
630             } else {
631                 normalStartedGestures[target].append(gesture);
632             }
633         } else {
634             DEBUG() << "QGestureManager::deliverEvent: could not find the target for gesture"
635                     << gesture->gestureType();
636             qWarning("QGestureManager::deliverEvent: could not find the target for gesture");
637             undeliveredGestures->insert(gesture);
638         }
639     }
640
641     getGestureTargets(startedGestures, &conflictedGestures, &normalStartedGestures);
642     DEBUG() << "QGestureManager::deliverEvents:"
643             << "\nstarted: " << startedGestures
644             << "\nconflicted: " << conflictedGestures
645             << "\nnormal: " << normalStartedGestures
646             << "\n";
647
648     // if there are conflicting gestures, send the GestureOverride event
649     for (GesturesPerWidget::const_iterator it = conflictedGestures.begin(),
650         e = conflictedGestures.end(); it != e; ++it) {
651         QWidget *receiver = it.key();
652         QList<QGesture *> gestures = it.value();
653         DEBUG() << "QGestureManager::deliverEvents: sending GestureOverride to"
654                 << receiver
655                 << "gestures:" << gestures;
656         QGestureEvent event(gestures);
657         event.t = QEvent::GestureOverride;
658         // mark event and individual gestures as ignored
659         event.ignore();
660         foreach(QGesture *g, gestures)
661             event.setAccepted(g, false);
662
663         QApplication::sendEvent(receiver, &event);
664         bool eventAccepted = event.isAccepted();
665         foreach(QGesture *gesture, event.gestures()) {
666             if (eventAccepted || event.isAccepted(gesture)) {
667                 QWidget *w = event.d_func()->targetWidgets.value(gesture->gestureType(), 0);
668                 Q_ASSERT(w);
669                 DEBUG() << "override event: gesture was accepted:" << gesture << w;
670                 QList<QGesture *> &gestures = normalStartedGestures[w];
671                 gestures.append(gesture);
672                 // override the target
673                 m_gestureTargets[gesture] = w;
674             } else {
675                 DEBUG() << "override event: gesture wasn't accepted. putting back:" << gesture;
676                 QList<QGesture *> &gestures = normalStartedGestures[receiver];
677                 gestures.append(gesture);
678             }
679         }
680     }
681
682     // delivering gestures that are not in conflicted state
683     for (GesturesPerWidget::const_iterator it = normalStartedGestures.begin(),
684         e = normalStartedGestures.end(); it != e; ++it) {
685         if (!it.value().isEmpty()) {
686             DEBUG() << "QGestureManager::deliverEvents: sending to" << it.key()
687                     << "gestures:" << it.value();
688             QGestureEvent event(it.value());
689             QApplication::sendEvent(it.key(), &event);
690             bool eventAccepted = event.isAccepted();
691             foreach (QGesture *gesture, event.gestures()) {
692                 if (gesture->state() == Qt::GestureStarted &&
693                     (eventAccepted || event.isAccepted(gesture))) {
694                     QWidget *w = event.d_func()->targetWidgets.value(gesture->gestureType(), 0);
695                     Q_ASSERT(w);
696                     DEBUG() << "started gesture was delivered and accepted by" << w;
697                     m_gestureTargets[gesture] = w;
698                 }
699             }
700         }
701     }
702 }
703
704 void QGestureManager::recycle(QGesture *gesture)
705 {
706     QGestureRecognizer *recognizer = m_gestureToRecognizer.value(gesture, 0);
707     if (recognizer) {
708         gesture->setGestureCancelPolicy(QGesture::CancelNone);
709         recognizer->reset(gesture);
710         m_activeGestures.remove(gesture);
711     } else {
712         cleanupGesturesForRemovedRecognizer(gesture);
713     }
714 }
715
716 QT_END_NAMESPACE
717
718 #endif // QT_NO_GESTURES
719
720 #include "moc_qgesturemanager_p.cpp"