summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/declarative/graphicsitems/qdeclarativeflickable.cpp48
-rw-r--r--src/declarative/graphicsitems/qdeclarativeflickable_p.h1
-rw-r--r--src/declarative/graphicsitems/qdeclarativeflickable_p_p.h1
-rw-r--r--tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp29
-rw-r--r--tests/auto/declarative/qdeclarativemousearea/tst_qdeclarativemousearea.cpp20
5 files changed, 80 insertions, 19 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();
diff --git a/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp b/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp
index f4bec8f..736f8f4 100644
--- a/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp
+++ b/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp
@@ -69,6 +69,7 @@ private slots:
void maximumFlickVelocity();
void flickDeceleration();
void pressDelay();
+ void nestedPressDelay();
void flickableDirection();
void qgraphicswidget();
void resizeContent();
@@ -246,6 +247,34 @@ void tst_qdeclarativeflickable::pressDelay()
QCOMPARE(spy.count(),1);
}
+// QTBUG-17361
+void tst_qdeclarativeflickable::nestedPressDelay()
+{
+ QDeclarativeView *canvas = new QDeclarativeView;
+ canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/nestedPressDelay.qml"));
+ canvas->show();
+ canvas->setFocus();
+ QVERIFY(canvas->rootObject() != 0);
+
+ QDeclarativeFlickable *outer = qobject_cast<QDeclarativeFlickable*>(canvas->rootObject());
+ QVERIFY(outer != 0);
+
+ QDeclarativeFlickable *inner = canvas->rootObject()->findChild<QDeclarativeFlickable*>("innerFlickable");
+ QVERIFY(inner != 0);
+
+ QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(150, 150)));
+ // the MouseArea is not pressed immediately
+ QVERIFY(outer->property("pressed").toBool() == false);
+
+ // The outer pressDelay will prevail (50ms, vs. 10sec)
+ QTest::qWait(300);
+ QVERIFY(outer->property("pressed").toBool() == true);
+
+ QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(150, 150)));
+
+ delete canvas;
+}
+
void tst_qdeclarativeflickable::flickableDirection()
{
QDeclarativeComponent component(&engine);
diff --git a/tests/auto/declarative/qdeclarativemousearea/tst_qdeclarativemousearea.cpp b/tests/auto/declarative/qdeclarativemousearea/tst_qdeclarativemousearea.cpp
index 60d51c6..e1c34fc 100644
--- a/tests/auto/declarative/qdeclarativemousearea/tst_qdeclarativemousearea.cpp
+++ b/tests/auto/declarative/qdeclarativemousearea/tst_qdeclarativemousearea.cpp
@@ -541,15 +541,11 @@ void tst_QDeclarativeMouseArea::preventStealing()
QSignalSpy mousePositionSpy(mouseArea, SIGNAL(positionChanged(QDeclarativeMouseEvent*)));
- QGraphicsScene *scene = canvas->scene();
- QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress);
- pressEvent.setScenePos(QPointF(80, 80));
- pressEvent.setButton(Qt::LeftButton);
- pressEvent.setButtons(Qt::LeftButton);
- QApplication::sendEvent(scene, &pressEvent);
+ QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(80, 80)));
// Without preventStealing, mouse movement over MouseArea would
// cause the Flickable to steal mouse and trigger content movement.
+ QGraphicsScene *scene = canvas->scene();
QGraphicsSceneMouseEvent moveEvent(QEvent::GraphicsSceneMouseMove);
moveEvent.setScenePos(QPointF(70, 70));
moveEvent.setButton(Qt::LeftButton);
@@ -574,17 +570,12 @@ void tst_QDeclarativeMouseArea::preventStealing()
QCOMPARE(flickable->contentX(), 0.);
QCOMPARE(flickable->contentY(), 0.);
- QGraphicsSceneMouseEvent releaseEvent(QEvent::GraphicsSceneMouseRelease);
- releaseEvent.setScenePos(QPointF(50, 50));
- releaseEvent.setButton(Qt::LeftButton);
- releaseEvent.setButtons(Qt::LeftButton);
- QApplication::sendEvent(scene, &releaseEvent);
+ QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(50, 50)));
// Now allow stealing and confirm Flickable does its thing.
canvas->rootObject()->setProperty("stealing", false);
- pressEvent.setScenePos(QPointF(80, 80));
- QApplication::sendEvent(scene, &pressEvent);
+ QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(80, 80)));
// Without preventStealing, mouse movement over MouseArea would
// cause the Flickable to steal mouse and trigger content movement.
@@ -606,8 +597,7 @@ void tst_QDeclarativeMouseArea::preventStealing()
QCOMPARE(flickable->contentX(), 10.);
QCOMPARE(flickable->contentY(), 10.);
- releaseEvent.setScenePos(QPointF(50, 50));
- QApplication::sendEvent(scene, &releaseEvent);
+ QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(50, 50)));
delete canvas;
}