Plug memory leak when gestures are grabbed but never triggered

When a gesture is grabbed by QAbstractScrollArea but never triggered
then the deletion of the QAbstractScrollArea would mean that the gesture
created for it would not be deleted.  This ensures that it always
deletes the gestures waiting to be deleted even if no gesture event is
triggered

Task-number: QTBUG-25011

Change-Id: I36118b82baaa60ac4e014896159060e1af76b2d2
Reviewed-by: Denis Dzyubenko <denis.dzyubenko@nokia.com>
This commit is contained in:
Andy Shaw 2012-03-28 21:54:52 +02:00 committed by Qt by Nokia
parent 94f7d70a4b
commit 3ec88b355b

View File

@ -285,106 +285,104 @@ bool QGestureManager::filterEventThroughContexts(const QMultiMap<QObject *,
}
}
}
if (triggeredGestures.isEmpty() && finishedGestures.isEmpty()
&& newMaybeGestures.isEmpty() && notGestures.isEmpty())
return consumeEventHint;
if (!triggeredGestures.isEmpty() || !finishedGestures.isEmpty()
|| !newMaybeGestures.isEmpty() || !notGestures.isEmpty()) {
QSet<QGesture *> startedGestures = triggeredGestures - m_activeGestures;
triggeredGestures &= m_activeGestures;
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 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 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;
// 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;
// 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;
// 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());
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;
}
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)
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(notStarted, &undeliveredGestures);
finishedGestures -= undeliveredGestures;
}
deliverEvents(startedGestures+triggeredGestures+finishedGestures+canceledGestures,
&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;
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);
}
}
// 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;
m_activeGestures -= undeliveredGestures;
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);
// reset gestures that ended
QSet<QGesture *> endedGestures =
finishedGestures + canceledGestures + undeliveredGestures + maybeToCanceledGestures;
foreach (QGesture *gesture, endedGestures) {
recycle(gesture);
m_gestureTargets.remove(gesture);
}
}
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();