source: trunk/src/gui/kernel/qgesturemanager.cpp@ 1006

Last change on this file since 1006 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

  • Property svn:eol-style set to native
File size: 28.6 KB
Line 
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** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
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** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
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
71QT_BEGIN_NAMESPACE
72
73QGestureManager::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
100QGestureManager::~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
110Qt::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
129void 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
160void 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
189QGesture *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
234bool 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 ret = false;
247
248 // filter the event through recognizers
249 typedef QMultiMap<QObject *, Qt::GestureType>::const_iterator ContextIterator;
250 for (ContextIterator cit = contexts.begin(), ce = contexts.end(); cit != ce; ++cit) {
251 Qt::GestureType gestureType = cit.value();
252 QMap<Qt::GestureType, QGestureRecognizer *>::const_iterator
253 rit = m_recognizers.lowerBound(gestureType),
254 re = m_recognizers.upperBound(gestureType);
255 for (; rit != re; ++rit) {
256 QGestureRecognizer *recognizer = rit.value();
257 QObject *target = cit.key();
258 QGesture *state = getState(target, recognizer, gestureType);
259 if (!state)
260 continue;
261 QGestureRecognizer::Result result = recognizer->recognize(state, target, event);
262 QGestureRecognizer::Result type = result & QGestureRecognizer::ResultState_Mask;
263 result &= QGestureRecognizer::ResultHint_Mask;
264 if (type == QGestureRecognizer::TriggerGesture) {
265 DEBUG() << "QGestureManager:Recognizer: gesture triggered: " << state;
266 triggeredGestures << state;
267 } else if (type == QGestureRecognizer::FinishGesture) {
268 DEBUG() << "QGestureManager:Recognizer: gesture finished: " << state;
269 finishedGestures << state;
270 } else if (type == QGestureRecognizer::MayBeGesture) {
271 DEBUG() << "QGestureManager:Recognizer: maybe gesture: " << state;
272 newMaybeGestures << state;
273 } else if (type == QGestureRecognizer::CancelGesture) {
274 DEBUG() << "QGestureManager:Recognizer: not gesture: " << state;
275 notGestures << state;
276 } else if (type == QGestureRecognizer::Ignore) {
277 DEBUG() << "QGestureManager:Recognizer: ignored the event: " << state;
278 } else {
279 DEBUG() << "QGestureManager:Recognizer: hm, lets assume the recognizer"
280 << "ignored the event: " << state;
281 }
282 if (result & QGestureRecognizer::ConsumeEventHint) {
283 DEBUG() << "QGestureManager: we were asked to consume the event: "
284 << state;
285 ret = true;
286 }
287 }
288 }
289 if (triggeredGestures.isEmpty() && finishedGestures.isEmpty()
290 && newMaybeGestures.isEmpty() && notGestures.isEmpty())
291 return ret;
292
293 QSet<QGesture *> startedGestures = triggeredGestures - m_activeGestures;
294 triggeredGestures &= m_activeGestures;
295
296 // check if a running gesture switched back to maybe state
297 QSet<QGesture *> activeToMaybeGestures = m_activeGestures & newMaybeGestures;
298
299 // check if a maybe gesture switched to canceled - reset it but don't send an event
300 QSet<QGesture *> maybeToCanceledGestures = m_maybeGestures & notGestures;
301
302 // check if a running gesture switched back to not gesture state,
303 // i.e. were canceled
304 QSet<QGesture *> canceledGestures = m_activeGestures & notGestures;
305
306 // new gestures in maybe state
307 m_maybeGestures += newMaybeGestures;
308
309 // gestures that were in maybe state
310 QSet<QGesture *> notMaybeGestures = (startedGestures | triggeredGestures
311 | finishedGestures | canceledGestures
312 | notGestures);
313 m_maybeGestures -= notMaybeGestures;
314
315 Q_ASSERT((startedGestures & finishedGestures).isEmpty());
316 Q_ASSERT((startedGestures & newMaybeGestures).isEmpty());
317 Q_ASSERT((startedGestures & canceledGestures).isEmpty());
318 Q_ASSERT((finishedGestures & newMaybeGestures).isEmpty());
319 Q_ASSERT((finishedGestures & canceledGestures).isEmpty());
320 Q_ASSERT((canceledGestures & newMaybeGestures).isEmpty());
321
322 QSet<QGesture *> notStarted = finishedGestures - m_activeGestures;
323 if (!notStarted.isEmpty()) {
324 // there are some gestures that claim to be finished, but never started.
325 // probably those are "singleshot" gestures so we'll fake the started state.
326 foreach (QGesture *gesture, notStarted)
327 gesture->d_func()->state = Qt::GestureStarted;
328 QSet<QGesture *> undeliveredGestures;
329 deliverEvents(notStarted, &undeliveredGestures);
330 finishedGestures -= undeliveredGestures;
331 }
332
333 m_activeGestures += startedGestures;
334 // sanity check: all triggered gestures should already be in active gestures list
335 Q_ASSERT((m_activeGestures & triggeredGestures).size() == triggeredGestures.size());
336 m_activeGestures -= finishedGestures;
337 m_activeGestures -= activeToMaybeGestures;
338 m_activeGestures -= canceledGestures;
339
340 // set the proper gesture state on each gesture
341 foreach (QGesture *gesture, startedGestures)
342 gesture->d_func()->state = Qt::GestureStarted;
343 foreach (QGesture *gesture, triggeredGestures)
344 gesture->d_func()->state = Qt::GestureUpdated;
345 foreach (QGesture *gesture, finishedGestures)
346 gesture->d_func()->state = Qt::GestureFinished;
347 foreach (QGesture *gesture, canceledGestures)
348 gesture->d_func()->state = Qt::GestureCanceled;
349 foreach (QGesture *gesture, activeToMaybeGestures)
350 gesture->d_func()->state = Qt::GestureFinished;
351
352 if (!m_activeGestures.isEmpty() || !m_maybeGestures.isEmpty() ||
353 !startedGestures.isEmpty() || !triggeredGestures.isEmpty() ||
354 !finishedGestures.isEmpty() || !canceledGestures.isEmpty()) {
355 DEBUG() << "QGestureManager::filterEventThroughContexts:"
356 << "\n\tactiveGestures:" << m_activeGestures
357 << "\n\tmaybeGestures:" << m_maybeGestures
358 << "\n\tstarted:" << startedGestures
359 << "\n\ttriggered:" << triggeredGestures
360 << "\n\tfinished:" << finishedGestures
361 << "\n\tcanceled:" << canceledGestures
362 << "\n\tmaybe-canceled:" << maybeToCanceledGestures;
363 }
364
365 QSet<QGesture *> undeliveredGestures;
366 deliverEvents(startedGestures+triggeredGestures+finishedGestures+canceledGestures,
367 &undeliveredGestures);
368
369 foreach (QGesture *g, startedGestures) {
370 if (undeliveredGestures.contains(g))
371 continue;
372 if (g->gestureCancelPolicy() == QGesture::CancelAllInContext) {
373 DEBUG() << "lets try to cancel some";
374 // find gestures in context in Qt::GestureStarted or Qt::GestureUpdated state and cancel them
375 cancelGesturesForChildren(g);
376 }
377 }
378
379 m_activeGestures -= undeliveredGestures;
380
381 // reset gestures that ended
382 QSet<QGesture *> endedGestures =
383 finishedGestures + canceledGestures + undeliveredGestures + maybeToCanceledGestures;
384 foreach (QGesture *gesture, endedGestures) {
385 recycle(gesture);
386 m_gestureTargets.remove(gesture);
387 }
388
389 //Clean up the Gestures
390 qDeleteAll(m_gesturesToDelete);
391 m_gesturesToDelete.clear();
392
393 return ret;
394}
395
396// Cancel all gestures of children of the widget that original is associated with
397void QGestureManager::cancelGesturesForChildren(QGesture *original)
398{
399 Q_ASSERT(original);
400 QWidget *originatingWidget = m_gestureTargets.value(original);
401 Q_ASSERT(originatingWidget);
402
403 // iterate over all active gestures and all maybe gestures
404 // for each find the owner
405 // if the owner is part of our sub-hierarchy, cancel it.
406
407 QSet<QGesture*> cancelledGestures;
408 QSet<QGesture*>::Iterator iter = m_activeGestures.begin();
409 while (iter != m_activeGestures.end()) {
410 QWidget *widget = m_gestureTargets.value(*iter);
411 // note that we don't touch the gestures for our originatingWidget
412 if (widget != originatingWidget && originatingWidget->isAncestorOf(widget)) {
413 DEBUG() << " found a gesture to cancel" << (*iter);
414 (*iter)->d_func()->state = Qt::GestureCanceled;
415 cancelledGestures << *iter;
416 iter = m_activeGestures.erase(iter);
417 } else {
418 ++iter;
419 }
420 }
421
422 // TODO handle 'maybe' gestures too
423
424 // sort them per target widget by cherry picking from almostCanceledGestures and delivering
425 QSet<QGesture *> almostCanceledGestures = cancelledGestures;
426 while (!almostCanceledGestures.isEmpty()) {
427 QWidget *target = 0;
428 QSet<QGesture*> gestures;
429 iter = almostCanceledGestures.begin();
430 // sort per target widget
431 while (iter != almostCanceledGestures.end()) {
432 QWidget *widget = m_gestureTargets.value(*iter);
433 if (target == 0)
434 target = widget;
435 if (target == widget) {
436 gestures << *iter;
437 iter = almostCanceledGestures.erase(iter);
438 } else {
439 ++iter;
440 }
441 }
442 Q_ASSERT(target);
443
444 QSet<QGesture*> undeliveredGestures;
445 deliverEvents(gestures, &undeliveredGestures);
446 }
447
448 for (iter = cancelledGestures.begin(); iter != cancelledGestures.end(); ++iter)
449 recycle(*iter);
450}
451
452void QGestureManager::cleanupGesturesForRemovedRecognizer(QGesture *gesture)
453{
454 QGestureRecognizer *recognizer = m_deletedRecognizers.value(gesture);
455 if(!recognizer) //The Gesture is removed while in the even loop, so the recognizers for this gestures was removed
456 return;
457 m_deletedRecognizers.remove(gesture);
458 if (m_deletedRecognizers.keys(recognizer).isEmpty()) {
459 // no more active gestures, cleanup!
460 qDeleteAll(m_obsoleteGestures.value(recognizer));
461 m_obsoleteGestures.remove(recognizer);
462 delete recognizer;
463 }
464}
465
466// return true if accepted (consumed)
467bool QGestureManager::filterEvent(QWidget *receiver, QEvent *event)
468{
469 QMap<Qt::GestureType, int> types;
470 QMultiMap<QObject *, Qt::GestureType> contexts;
471 QWidget *w = receiver;
472 typedef QMap<Qt::GestureType, Qt::GestureFlags>::const_iterator ContextIterator;
473 if (!w->d_func()->gestureContext.isEmpty()) {
474 for(ContextIterator it = w->d_func()->gestureContext.begin(),
475 e = w->d_func()->gestureContext.end(); it != e; ++it) {
476 types.insert(it.key(), 0);
477 contexts.insertMulti(w, it.key());
478 }
479 }
480 // find all gesture contexts for the widget tree
481 w = w->isWindow() ? 0 : w->parentWidget();
482 while (w)
483 {
484 for (ContextIterator it = w->d_func()->gestureContext.begin(),
485 e = w->d_func()->gestureContext.end(); it != e; ++it) {
486 if (!(it.value() & Qt::DontStartGestureOnChildren)) {
487 if (!types.contains(it.key())) {
488 types.insert(it.key(), 0);
489 contexts.insertMulti(w, it.key());
490 }
491 }
492 }
493 if (w->isWindow())
494 break;
495 w = w->parentWidget();
496 }
497 return contexts.isEmpty() ? false : filterEventThroughContexts(contexts, event);
498}
499
500#ifndef QT_NO_GRAPHICSVIEW
501bool QGestureManager::filterEvent(QGraphicsObject *receiver, QEvent *event)
502{
503 QMap<Qt::GestureType, int> types;
504 QMultiMap<QObject *, Qt::GestureType> contexts;
505 QGraphicsObject *item = receiver;
506 if (!item->QGraphicsItem::d_func()->gestureContext.isEmpty()) {
507 typedef QMap<Qt::GestureType, Qt::GestureFlags>::const_iterator ContextIterator;
508 for(ContextIterator it = item->QGraphicsItem::d_func()->gestureContext.begin(),
509 e = item->QGraphicsItem::d_func()->gestureContext.end(); it != e; ++it) {
510 types.insert(it.key(), 0);
511 contexts.insertMulti(item, it.key());
512 }
513 }
514 // find all gesture contexts for the graphics object tree
515 item = item->parentObject();
516 while (item)
517 {
518 typedef QMap<Qt::GestureType, Qt::GestureFlags>::const_iterator ContextIterator;
519 for (ContextIterator it = item->QGraphicsItem::d_func()->gestureContext.begin(),
520 e = item->QGraphicsItem::d_func()->gestureContext.end(); it != e; ++it) {
521 if (!(it.value() & Qt::DontStartGestureOnChildren)) {
522 if (!types.contains(it.key())) {
523 types.insert(it.key(), 0);
524 contexts.insertMulti(item, it.key());
525 }
526 }
527 }
528 item = item->parentObject();
529 }
530 return contexts.isEmpty() ? false : filterEventThroughContexts(contexts, event);
531}
532#endif
533
534bool QGestureManager::filterEvent(QObject *receiver, QEvent *event)
535{
536 if (!m_gestureToRecognizer.contains(static_cast<QGesture *>(receiver)))
537 return false;
538 QGesture *state = static_cast<QGesture *>(receiver);
539 QMultiMap<QObject *, Qt::GestureType> contexts;
540 contexts.insert(state, state->gestureType());
541 return filterEventThroughContexts(contexts, event);
542}
543
544void QGestureManager::getGestureTargets(const QSet<QGesture*> &gestures,
545 QMap<QWidget *, QList<QGesture *> > *conflicts,
546 QMap<QWidget *, QList<QGesture *> > *normal)
547{
548 typedef QHash<Qt::GestureType, QHash<QWidget *, QGesture *> > GestureByTypes;
549 GestureByTypes gestureByTypes;
550
551 // sort gestures by types
552 foreach (QGesture *gesture, gestures) {
553 QWidget *receiver = m_gestureTargets.value(gesture, 0);
554 Q_ASSERT(receiver);
555 gestureByTypes[gesture->gestureType()].insert(receiver, gesture);
556 }
557
558 // for each gesture type
559 foreach (Qt::GestureType type, gestureByTypes.keys()) {
560 QHash<QWidget *, QGesture *> gestures = gestureByTypes.value(type);
561 foreach (QWidget *widget, gestures.keys()) {
562 QWidget *w = widget->parentWidget();
563 while (w) {
564 QMap<Qt::GestureType, Qt::GestureFlags>::const_iterator it
565 = w->d_func()->gestureContext.find(type);
566 if (it != w->d_func()->gestureContext.end()) {
567 // i.e. 'w' listens to gesture 'type'
568 Qt::GestureFlags flags = it.value();
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
587void 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
704void 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
716QT_END_NAMESPACE
717
718#endif // QT_NO_GESTURES
719
720#include "moc_qgesturemanager_p.cpp"
Note: See TracBrowser for help on using the repository browser.