summaryrefslogtreecommitdiffstats
path: root/src/gui/kernel/qgesturemanager.cpp
diff options
context:
space:
mode:
authorJørgen Lind <jorgen.lind@nokia.com>2009-11-02 10:01:08 (GMT)
committerJørgen Lind <jorgen.lind@nokia.com>2009-11-02 10:01:08 (GMT)
commit5e0bdffd92cbff2a9eb551f77850a24bf2a2116a (patch)
treefcf764b8326d8282e7f194a4fe1b2a88a7082319 /src/gui/kernel/qgesturemanager.cpp
parentb68cd1df21935fc032a93c7d7bc33fcb77c7b8cd (diff)
parent5d7e254583551659df42e59fab4756994d4211ed (diff)
downloadQt-5e0bdffd92cbff2a9eb551f77850a24bf2a2116a.zip
Qt-5e0bdffd92cbff2a9eb551f77850a24bf2a2116a.tar.gz
Qt-5e0bdffd92cbff2a9eb551f77850a24bf2a2116a.tar.bz2
Merge commit 'origin/4.6' into feature
Diffstat (limited to 'src/gui/kernel/qgesturemanager.cpp')
-rw-r--r--src/gui/kernel/qgesturemanager.cpp290
1 files changed, 216 insertions, 74 deletions
diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp
index 5ad607b..0a88a24 100644
--- a/src/gui/kernel/qgesturemanager.cpp
+++ b/src/gui/kernel/qgesturemanager.cpp
@@ -65,7 +65,7 @@
QT_BEGIN_NAMESPACE
QGestureManager::QGestureManager(QObject *parent)
- : QObject(parent), state(NotGesture), lastCustomGestureId(0)
+ : QObject(parent), state(NotGesture), m_lastCustomGestureId(0)
{
qRegisterMetaType<Qt::GestureState>();
@@ -82,7 +82,12 @@ QGestureManager::QGestureManager(QObject *parent)
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)
@@ -96,20 +101,55 @@ Qt::GestureType QGestureManager::registerGestureRecognizer(QGestureRecognizer *r
Qt::GestureType type = dummy->gestureType();
if (type == Qt::CustomGesture) {
// generate a new custom gesture id
- ++lastCustomGestureId;
- type = Qt::GestureType(Qt::CustomGesture + lastCustomGestureId);
+ ++m_lastCustomGestureId;
+ type = Qt::GestureType(Qt::CustomGesture + m_lastCustomGestureId);
}
- recognizers.insertMulti(type, recognizer);
+ m_recognizers.insertMulti(type, recognizer);
delete dummy;
return type;
}
-void QGestureManager::unregisterGestureRecognizer(Qt::GestureType)
+void QGestureManager::unregisterGestureRecognizer(Qt::GestureType type)
{
+ QList<QGestureRecognizer *> list = m_recognizers.values(type);
+ m_recognizers.remove(type);
+ foreach (QGesture *g, m_gestureToRecognizer.keys()) {
+ QGestureRecognizer *recognizer = m_gestureToRecognizer.value(g);
+ if (list.contains(recognizer)) {
+ m_deletedRecognizers.insert(g, recognizer);
+ m_gestureToRecognizer.remove(g);
+ }
+ }
+ foreach (QGestureRecognizer *recognizer, list) {
+ QList<QGesture *> obsoleteGestures;
+ QMap<ObjectGesture, QList<QGesture *> >::Iterator iter = m_objectGestures.begin();
+ while (iter != m_objectGestures.end()) {
+ ObjectGesture objectGesture = iter.key();
+ if (objectGesture.gesture == type)
+ obsoleteGestures << iter.value();
+ ++iter;
+ }
+ m_obsoleteGestures.insert(recognizer, obsoleteGestures);
+ }
}
-QGesture *QGestureManager::getState(QObject *object, Qt::GestureType type)
+void QGestureManager::cleanupCachedGestures(QObject *target, Qt::GestureType type)
+{
+ QMap<ObjectGesture, QList<QGesture *> >::Iterator iter = m_objectGestures.begin();
+ while (iter != m_objectGestures.end()) {
+ ObjectGesture objectGesture = iter.key();
+ if (objectGesture.gesture == type && target == objectGesture.object.data()) {
+ qDeleteAll(iter.value());
+ iter = m_objectGestures.erase(iter);
+ } else {
+ ++iter;
+ }
+ }
+}
+
+// get or create a QGesture object that will represent the state for a given object, used by the recognizer
+QGesture *QGestureManager::getState(QObject *object, QGestureRecognizer *recognizer, Qt::GestureType type)
{
// if the widget is being deleted we should be carefull and not to
// create a new state, as it will create QWeakPointer which doesnt work
@@ -123,31 +163,35 @@ QGesture *QGestureManager::getState(QObject *object, Qt::GestureType type)
Q_ASSERT(qobject_cast<QGraphicsObject *>(object));
}
- QGesture *state =
- objectGestures.value(QGestureManager::ObjectGesture(object, type));
- if (!state) {
- QGestureRecognizer *recognizer = recognizers.value(type);
- if (recognizer) {
- state = recognizer->createGesture(object);
- if (!state)
- return 0;
- if (state->gestureType() == Qt::CustomGesture) {
- // if the recognizer didn't fill in the gesture type, then this
- // is a custom gesture with autogenerated it and we fill it.
- state->d_func()->gestureType = type;
+ QList<QGesture *> states =
+ m_objectGestures.value(QGestureManager::ObjectGesture(object, type));
+ // check if the QGesture for this recognizer has already been created
+ foreach (QGesture *state, states) {
+ if (m_gestureToRecognizer.value(state) == recognizer)
+ return state;
+ }
+
+ Q_ASSERT(recognizer);
+ QGesture *state = recognizer->createGesture(object);
+ if (!state)
+ return 0;
+ state->setParent(this);
+ if (state->gestureType() == Qt::CustomGesture) {
+ // if the recognizer didn't fill in the gesture type, then this
+ // is a custom gesture with autogenerated id and we fill it.
+ state->d_func()->gestureType = type;
#if defined(GESTURE_DEBUG)
- state->setObjectName(QString::number((int)type));
+ state->setObjectName(QString::number((int)type));
#endif
- }
- objectGestures.insert(QGestureManager::ObjectGesture(object, type), state);
- gestureToRecognizer[state] = recognizer;
- gestureOwners[state] = object;
- }
}
+ m_objectGestures[QGestureManager::ObjectGesture(object, type)].append(state);
+ m_gestureToRecognizer[state] = recognizer;
+ m_gestureOwners[state] = object;
+
return state;
}
-bool QGestureManager::filterEventThroughContexts(const QMap<QObject *,
+bool QGestureManager::filterEventThroughContexts(const QMultiHash<QObject *,
Qt::GestureType> &contexts,
QEvent *event)
{
@@ -160,61 +204,63 @@ bool QGestureManager::filterEventThroughContexts(const QMap<QObject *,
// TODO: sort contexts by the gesture type and check if one of the contexts
// is already active.
+ bool ret = false;
+
// filter the event through recognizers
- typedef QMap<QObject *, Qt::GestureType>::const_iterator ContextIterator;
+ typedef QHash<QObject *, Qt::GestureType>::const_iterator ContextIterator;
for (ContextIterator cit = contexts.begin(), ce = contexts.end(); cit != ce; ++cit) {
Qt::GestureType gestureType = cit.value();
QMap<Qt::GestureType, QGestureRecognizer *>::const_iterator
- rit = recognizers.lowerBound(gestureType),
- re = recognizers.upperBound(gestureType);
+ rit = m_recognizers.lowerBound(gestureType),
+ re = m_recognizers.upperBound(gestureType);
for (; rit != re; ++rit) {
QGestureRecognizer *recognizer = rit.value();
QObject *target = cit.key();
- QGesture *state = getState(target, gestureType);
+ QGesture *state = getState(target, recognizer, gestureType);
if (!state)
continue;
QGestureRecognizer::Result result = recognizer->filterEvent(state, target, event);
QGestureRecognizer::Result type = result & QGestureRecognizer::ResultState_Mask;
if (type == QGestureRecognizer::GestureTriggered) {
- DEBUG() << "QGestureManager: gesture triggered: " << state;
+ DEBUG() << "QGestureManager:Recognizer: gesture triggered: " << state;
triggeredGestures << state;
} else if (type == QGestureRecognizer::GestureFinished) {
- DEBUG() << "QGestureManager: gesture finished: " << state;
+ DEBUG() << "QGestureManager:Recognizer: gesture finished: " << state;
finishedGestures << state;
} else if (type == QGestureRecognizer::MaybeGesture) {
- DEBUG() << "QGestureManager: maybe gesture: " << state;
+ DEBUG() << "QGestureManager:Recognizer: maybe gesture: " << state;
newMaybeGestures << state;
} else if (type == QGestureRecognizer::NotGesture) {
- DEBUG() << "QGestureManager: not gesture: " << state;
+ DEBUG() << "QGestureManager:Recognizer: not gesture: " << state;
notGestures << state;
} else if (type == QGestureRecognizer::Ignore) {
- DEBUG() << "QGestureManager: gesture ignored the event: " << state;
+ DEBUG() << "QGestureManager:Recognizer: ignored the event: " << state;
} else {
- DEBUG() << "QGestureManager: hm, lets assume the recognizer"
+ DEBUG() << "QGestureManager:Recognizer: hm, lets assume the recognizer"
<< "ignored the event: " << state;
}
if (result & QGestureRecognizer::ConsumeEventHint) {
DEBUG() << "QGestureManager: we were asked to consume the event: "
<< state;
- //TODO: consume events if asked
+ ret = true;
}
}
}
- QSet<QGesture *> startedGestures = triggeredGestures - activeGestures;
- triggeredGestures &= activeGestures;
+ QSet<QGesture *> startedGestures = triggeredGestures - m_activeGestures;
+ triggeredGestures &= m_activeGestures;
// check if a running gesture switched back to maybe state
- QSet<QGesture *> activeToMaybeGestures = activeGestures & newMaybeGestures;
+ QSet<QGesture *> activeToMaybeGestures = m_activeGestures & newMaybeGestures;
// check if a running gesture switched back to not gesture state,
// i.e. were canceled
- QSet<QGesture *> activeToCancelGestures = activeGestures & notGestures;
+ QSet<QGesture *> activeToCancelGestures = m_activeGestures & notGestures;
canceledGestures += activeToCancelGestures;
// start timers for new gestures in maybe state
foreach (QGesture *state, newMaybeGestures) {
- QBasicTimer &timer = maybeGestures[state];
+ QBasicTimer &timer = m_maybeGestures[state];
if (!timer.isActive())
timer.start(3000, this);
}
@@ -223,11 +269,11 @@ bool QGestureManager::filterEventThroughContexts(const QMap<QObject *,
| finishedGestures | canceledGestures
| notGestures);
foreach(QGesture *gesture, notMaybeGestures) {
- QMap<QGesture *, QBasicTimer>::iterator it =
- maybeGestures.find(gesture);
- if (it != maybeGestures.end()) {
+ QHash<QGesture *, QBasicTimer>::iterator it =
+ m_maybeGestures.find(gesture);
+ if (it != m_maybeGestures.end()) {
it.value().stop();
- maybeGestures.erase(it);
+ m_maybeGestures.erase(it);
}
}
@@ -238,7 +284,7 @@ bool QGestureManager::filterEventThroughContexts(const QMap<QObject *,
Q_ASSERT((finishedGestures & canceledGestures).isEmpty());
Q_ASSERT((canceledGestures & newMaybeGestures).isEmpty());
- QSet<QGesture *> notStarted = finishedGestures - activeGestures;
+ QSet<QGesture *> notStarted = finishedGestures - m_activeGestures;
if (!notStarted.isEmpty()) {
// there are some gestures that claim to be finished, but never started.
// probably those are "singleshot" gestures so we'll fake the started state.
@@ -249,12 +295,12 @@ bool QGestureManager::filterEventThroughContexts(const QMap<QObject *,
finishedGestures -= undeliveredGestures;
}
- activeGestures += startedGestures;
+ m_activeGestures += startedGestures;
// sanity check: all triggered gestures should already be in active gestures list
- Q_ASSERT((activeGestures & triggeredGestures).size() == triggeredGestures.size());
- activeGestures -= finishedGestures;
- activeGestures -= activeToMaybeGestures;
- activeGestures -= canceledGestures;
+ Q_ASSERT((m_activeGestures & triggeredGestures).size() == triggeredGestures.size());
+ m_activeGestures -= finishedGestures;
+ m_activeGestures -= activeToMaybeGestures;
+ m_activeGestures -= canceledGestures;
// set the proper gesture state on each gesture
foreach (QGesture *gesture, startedGestures)
@@ -268,12 +314,12 @@ bool QGestureManager::filterEventThroughContexts(const QMap<QObject *,
foreach (QGesture *gesture, activeToMaybeGestures)
gesture->d_func()->state = Qt::GestureFinished;
- if (!activeGestures.isEmpty() || !maybeGestures.isEmpty() ||
+ if (!m_activeGestures.isEmpty() || !m_maybeGestures.isEmpty() ||
!startedGestures.isEmpty() || !triggeredGestures.isEmpty() ||
!finishedGestures.isEmpty() || !canceledGestures.isEmpty()) {
- DEBUG() << "QGestureManager::filterEvent:"
- << "\n\tactiveGestures:" << activeGestures
- << "\n\tmaybeGestures:" << maybeGestures.keys()
+ DEBUG() << "QGestureManager::filterEventThroughContexts:"
+ << "\n\tactiveGestures:" << m_activeGestures
+ << "\n\tmaybeGestures:" << m_maybeGestures.keys()
<< "\n\tstarted:" << startedGestures
<< "\n\ttriggered:" << triggeredGestures
<< "\n\tfinished:" << finishedGestures
@@ -284,24 +330,114 @@ bool QGestureManager::filterEventThroughContexts(const QMap<QObject *,
deliverEvents(startedGestures+triggeredGestures+finishedGestures+canceledGestures,
&undeliveredGestures);
- activeGestures -= undeliveredGestures;
+ foreach (QGesture *g, startedGestures) {
+ if (undeliveredGestures.contains(g))
+ continue;
+ if (g->gestureCancelPolicy() == QGesture::CancelAllInContext) {
+ DEBUG() << "lets try to cancel some";
+ // find gestures in context in Qt::GestureStarted or Qt::GestureUpdated state and cancel them
+ cancelGesturesForChildren(g);
+ }
+ }
+
+ m_activeGestures -= undeliveredGestures;
// reset gestures that ended
QSet<QGesture *> endedGestures =
finishedGestures + canceledGestures + undeliveredGestures;
foreach (QGesture *gesture, endedGestures) {
- if (QGestureRecognizer *recognizer = gestureToRecognizer.value(gesture, 0)) {
+ if (QGestureRecognizer *recognizer = m_gestureToRecognizer.value(gesture, 0)) {
+ gesture->setGestureCancelPolicy(QGesture::CancelNone);
recognizer->reset(gesture);
+ } else {
+ cleanupGesturesForRemovedRecognizer(gesture);
+ }
+ m_gestureTargets.remove(gesture);
+ }
+ 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;
}
- gestureTargets.remove(gesture);
}
- return false;
+
+ // 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) {
+ QGestureRecognizer *recognizer = m_gestureToRecognizer.value(*iter, 0);
+ if (recognizer) {
+ (*iter)->setGestureCancelPolicy(QGesture::CancelNone);
+ recognizer->reset(*iter);
+ } else {
+ cleanupGesturesForRemovedRecognizer(*iter);
+ }
+ }
+}
+
+void QGestureManager::cleanupGesturesForRemovedRecognizer(QGesture *gesture)
+{
+ QGestureRecognizer *recognizer = m_deletedRecognizers.value(gesture);
+ Q_ASSERT(recognizer);
+ m_deletedRecognizers.remove(gesture);
+ if (m_deletedRecognizers.keys(recognizer).isEmpty()) {
+ // no more active gestures, cleanup!
+ qDeleteAll(m_obsoleteGestures.value(recognizer));
+ m_obsoleteGestures.remove(recognizer);
+ delete recognizer;
+ }
}
+// return true if accepted (consumed)
bool QGestureManager::filterEvent(QWidget *receiver, QEvent *event)
{
QSet<Qt::GestureType> types;
- QMap<QObject *, Qt::GestureType> contexts;
+ QMultiHash<QObject *, Qt::GestureType> contexts;
QWidget *w = receiver;
typedef QMap<Qt::GestureType, Qt::GestureContext>::const_iterator ContextIterator;
if (!w->d_func()->gestureContext.isEmpty()) {
@@ -335,7 +471,7 @@ bool QGestureManager::filterEvent(QWidget *receiver, QEvent *event)
bool QGestureManager::filterEvent(QGraphicsObject *receiver, QEvent *event)
{
QSet<Qt::GestureType> types;
- QMap<QObject *, Qt::GestureType> contexts;
+ QMultiHash<QObject *, Qt::GestureType> contexts;
QGraphicsObject *item = receiver;
if (!item->QGraphicsItem::d_func()->gestureContext.isEmpty()) {
typedef QMap<Qt::GestureType, Qt::GestureContext>::const_iterator ContextIterator;
@@ -353,8 +489,10 @@ bool QGestureManager::filterEvent(QGraphicsObject *receiver, QEvent *event)
for (ContextIterator it = item->QGraphicsItem::d_func()->gestureContext.begin(),
e = item->QGraphicsItem::d_func()->gestureContext.end(); it != e; ++it) {
if (it.value() == Qt::ItemWithChildrenGesture) {
- if (!types.contains(it.key()))
+ if (!types.contains(it.key())) {
+ types.insert(it.key());
contexts.insertMulti(item, it.key());
+ }
}
}
item = item->parentObject();
@@ -365,7 +503,7 @@ bool QGestureManager::filterEvent(QGraphicsObject *receiver, QEvent *event)
bool QGestureManager::filterEvent(QGesture *state, QEvent *event)
{
- QMap<QObject *, Qt::GestureType> contexts;
+ QMultiHash<QObject *, Qt::GestureType> contexts;
contexts.insert(state, state->gestureType());
return filterEventThroughContexts(contexts, event);
}
@@ -379,7 +517,7 @@ void QGestureManager::getGestureTargets(const QSet<QGesture*> &gestures,
// sort gestures by types
foreach (QGesture *gesture, gestures) {
- QWidget *receiver = gestureTargets.value(gesture, 0);
+ QWidget *receiver = m_gestureTargets.value(gesture, 0);
Q_ASSERT(receiver);
gestureByTypes[gesture->gestureType()].insert(receiver, gesture);
}
@@ -428,7 +566,7 @@ void QGestureManager::deliverEvents(const QSet<QGesture *> &gestures,
for (QSet<QGesture *>::const_iterator it = gestures.begin(),
e = gestures.end(); it != e; ++it) {
QGesture *gesture = *it;
- QWidget *target = gestureTargets.value(gesture, 0);
+ QWidget *target = m_gestureTargets.value(gesture, 0);
if (!target) {
// the gesture has just started and doesn't have a target yet.
Q_ASSERT(gesture->state() == Qt::GestureStarted);
@@ -440,12 +578,12 @@ void QGestureManager::deliverEvents(const QSet<QGesture *> &gestures,
}
} else {
// or use the context of the gesture
- QObject *context = gestureOwners.value(gesture, 0);
+ QObject *context = m_gestureOwners.value(gesture, 0);
if (context->isWidgetType())
target = static_cast<QWidget *>(context);
}
if (target)
- gestureTargets.insert(gesture, target);
+ m_gestureTargets.insert(gesture, target);
}
Qt::GestureType gestureType = gesture->gestureType();
@@ -497,7 +635,7 @@ void QGestureManager::deliverEvents(const QSet<QGesture *> &gestures,
QList<QGesture *> &gestures = normalStartedGestures[w];
gestures.append(gesture);
// override the target
- gestureTargets[gesture] = w;
+ m_gestureTargets[gesture] = w;
} else {
DEBUG() << "override event: gesture wasn't accepted. putting back:" << gesture;
QList<QGesture *> &gestures = normalStartedGestures[receiver];
@@ -520,20 +658,24 @@ void QGestureManager::deliverEvents(const QSet<QGesture *> &gestures,
void QGestureManager::timerEvent(QTimerEvent *event)
{
- QMap<QGesture*, QBasicTimer>::iterator it = maybeGestures.begin(),
- e = maybeGestures.end();
+ QHash<QGesture *, QBasicTimer>::iterator it = m_maybeGestures.begin(),
+ e = m_maybeGestures.end();
for (; it != e; ) {
QBasicTimer &timer = it.value();
Q_ASSERT(timer.isActive());
if (timer.timerId() == event->timerId()) {
timer.stop();
QGesture *gesture = it.key();
- it = maybeGestures.erase(it);
+ it = m_maybeGestures.erase(it);
DEBUG() << "QGestureManager::timerEvent: gesture stopped due to timeout:"
<< gesture;
- QGestureRecognizer *recognizer = gestureToRecognizer.value(gesture, 0);
- if (recognizer)
+ QGestureRecognizer *recognizer = m_gestureToRecognizer.value(gesture, 0);
+ if (recognizer) {
+ gesture->setGestureCancelPolicy(QGesture::CancelNone);
recognizer->reset(gesture);
+ } else {
+ cleanupGesturesForRemovedRecognizer(gesture);
+ }
} else {
++it;
}