diff options
author | Martin Jones <martin.jones@nokia.com> | 2011-02-21 04:57:08 (GMT) |
---|---|---|
committer | Martin Jones <martin.jones@nokia.com> | 2011-02-21 06:08:41 (GMT) |
commit | 1bcddaaf318fc37c71c5191913f3487c49444ec6 (patch) | |
tree | 82984444b9874bdaf21c1b5f7a62dc593a98ebef /src/declarative | |
parent | 8e9c28eaa4d7a3372b9a9a21a984701b62f96456 (diff) | |
download | Qt-1bcddaaf318fc37c71c5191913f3487c49444ec6.zip Qt-1bcddaaf318fc37c71c5191913f3487c49444ec6.tar.gz Qt-1bcddaaf318fc37c71c5191913f3487c49444ec6.tar.bz2 |
Prevent recursion due to nested Flickables with pressDelay
The outermost Flickable handles pressDelay for all descendents, rather
than having it cascade up and replayed multiple times.
Change-Id: Id294862469f3ce56b0940fbbb0e041d4c9f64f28
Task-number: QTBUG-17361
Reviewed-by: Michael Brasser
Diffstat (limited to 'src/declarative')
3 files changed, 46 insertions, 4 deletions
diff --git a/src/declarative/graphicsitems/qdeclarativeflickable.cpp b/src/declarative/graphicsitems/qdeclarativeflickable.cpp index 5d5fd0b..a3d9f41 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable.cpp +++ b/src/declarative/graphicsitems/qdeclarativeflickable.cpp @@ -845,7 +845,8 @@ void QDeclarativeFlickable::mousePressEvent(QGraphicsSceneMouseEvent *event) { Q_D(QDeclarativeFlickable); if (d->interactive) { - d->handleMousePressEvent(event); + if (!d->pressed) + d->handleMousePressEvent(event); event->accept(); } else { QDeclarativeItem::mousePressEvent(event); @@ -910,11 +911,27 @@ void QDeclarativeFlickable::wheelEvent(QGraphicsSceneWheelEvent *event) } } +bool QDeclarativeFlickablePrivate::isOutermostPressDelay() const +{ + Q_Q(const QDeclarativeFlickable); + QDeclarativeItem *item = q->parentItem(); + while (item) { + QDeclarativeFlickable *flick = qobject_cast<QDeclarativeFlickable*>(item); + if (flick && flick->pressDelay() > 0 && flick->isInteractive()) + return false; + item = item->parentItem(); + } + + return true; +} + void QDeclarativeFlickablePrivate::captureDelayedPress(QGraphicsSceneMouseEvent *event) { Q_Q(QDeclarativeFlickable); if (!q->scene() || pressDelay <= 0) return; + if (!isOutermostPressDelay()) + return; delayedPressTarget = q->scene()->mouseGrabberItem(); delayedPressEvent = new QGraphicsSceneMouseEvent(event->type()); delayedPressEvent->setAccepted(false); @@ -970,9 +987,10 @@ void QDeclarativeFlickable::timerEvent(QTimerEvent *event) if (scene()->mouseGrabberItem() == d->delayedPressTarget) d->delayedPressTarget->ungrabMouse(); //Use the event handler that will take care of finding the proper item to propagate the event - QApplication::sendEvent(scene(), d->delayedPressEvent); + QApplication::postEvent(scene(), d->delayedPressEvent); + } else { + delete d->delayedPressEvent; } - delete d->delayedPressEvent; d->delayedPressEvent = 0; } } @@ -1364,6 +1382,22 @@ bool QDeclarativeFlickable::yflick() const return d->flickableDirection & QDeclarativeFlickable::VerticalFlick; } +bool QDeclarativeFlickable::sceneEvent(QEvent *event) +{ + bool rv = QDeclarativeItem::sceneEvent(event); + if (event->type() == QEvent::UngrabMouse) { + Q_D(QDeclarativeFlickable); + if (d->pressed) { + // if our mouse grab has been removed (probably by another Flickable), + // fix our state + d->pressed = false; + d->stealMouse = false; + setKeepMouseGrab(false); + } + } + return rv; +} + bool QDeclarativeFlickable::sendMouseEvent(QGraphicsSceneMouseEvent *event) { Q_D(QDeclarativeFlickable); @@ -1391,7 +1425,7 @@ bool QDeclarativeFlickable::sendMouseEvent(QGraphicsSceneMouseEvent *event) d->handleMouseMoveEvent(&mouseEvent); break; case QEvent::GraphicsSceneMousePress: - if (d->delayedPressEvent) + if (d->pressed) // we are already pressed - this is a delayed replay return false; d->handleMousePressEvent(&mouseEvent); @@ -1410,6 +1444,8 @@ bool QDeclarativeFlickable::sendMouseEvent(QGraphicsSceneMouseEvent *event) // We send the release scene()->sendEvent(s->mouseGrabberItem(), event); // And the event has been consumed + d->stealMouse = false; + d->pressed = false; return true; } d->handleMouseReleaseEvent(&mouseEvent); @@ -1432,6 +1468,7 @@ bool QDeclarativeFlickable::sendMouseEvent(QGraphicsSceneMouseEvent *event) d->stealMouse = false; d->pressed = false; } + return false; } @@ -1530,6 +1567,9 @@ bool QDeclarativeFlickable::isFlickingVertically() const If the flickable is dragged/flicked before the delay times out the press event will not be delivered. If the button is released within the timeout, both the press and release will be delivered. + + Note that for nested Flickables with pressDelay set, the pressDelay of + inner Flickables is overridden by the outermost Flickable. */ int QDeclarativeFlickable::pressDelay() const { diff --git a/src/declarative/graphicsitems/qdeclarativeflickable_p.h b/src/declarative/graphicsitems/qdeclarativeflickable_p.h index 4fde1d5..a14cc1c 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable_p.h +++ b/src/declarative/graphicsitems/qdeclarativeflickable_p.h @@ -204,6 +204,7 @@ protected: virtual void viewportMoved(); virtual void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry); + bool sceneEvent(QEvent *event); bool sendMouseEvent(QGraphicsSceneMouseEvent *event); bool xflick() const; diff --git a/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h b/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h index 5ad6ff6..1b6081c 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h @@ -118,6 +118,7 @@ public: void updateBeginningEnd(); + bool isOutermostPressDelay() const; void captureDelayedPress(QGraphicsSceneMouseEvent *event); void clearDelayedPress(); |