aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew den Exter <andrew.den.exter@jollamobile.com>2014-03-07 17:54:20 +1000
committerAndrew den Exter <andrew.den.exter@qinetic.com.au>2014-07-22 05:22:04 +0200
commit71a1288e3d9601d24545ab9650cd079c40766a63 (patch)
treed5ed4ed025513a9ba9cb6666f957a62fb64ac2f1
parenta8a66e51ef5d9506a5458425c7e749935afa649d (diff)
Don't allow a filtering item to block other filtering items.
With delayed press it's possible for a filtering item to not accept a press on the first go around but to later steal mouse grab and accept future events. This means outer items which also filter will have received the mouse press, but don't receive release events leading to phantom long presses or inadvertent drags. Task-number: QTBUG-37316 Change-Id: I2ff18df2a019f8d3a5e81a0adc2c5b5994799862 Reviewed-by: Michael Brasser <michael.brasser@live.com> Reviewed-by: Martin Jones <martin.jones@jollamobile.com>
-rw-r--r--src/quick/items/qquickwindow.cpp18
-rw-r--r--tests/auto/quick/qquickflickable/data/nestedClickThenFlick.qml39
-rw-r--r--tests/auto/quick/qquickflickable/tst_qquickflickable.cpp46
3 files changed, 94 insertions, 9 deletions
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index e7c13d15e4..a7659e4871 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -2251,6 +2251,8 @@ bool QQuickWindowPrivate::sendFilteredTouchEvent(QQuickItem *target, QQuickItem
if (!target)
return false;
+ bool filtered = false;
+
QQuickItemPrivate *targetPrivate = QQuickItemPrivate::get(target);
if (targetPrivate->filtersChildMouseEvents) {
QScopedPointer<QTouchEvent> targetEvent(touchEventForItemBounds(target, *event));
@@ -2264,7 +2266,7 @@ bool QQuickWindowPrivate::sendFilteredTouchEvent(QQuickItem *target, QQuickItem
mouseGrabberItem->ungrabMouse();
touchMouseId = -1;
}
- return true;
+ filtered = true;
}
// Only offer a mouse event to the filter if we have one point
@@ -2290,13 +2292,12 @@ bool QQuickWindowPrivate::sendFilteredTouchEvent(QQuickItem *target, QQuickItem
itemForTouchPointId[tp.id()] = target;
touchMouseId = tp.id();
target->grabMouse();
- return true;
+ filtered = true;
}
}
}
}
-
- return sendFilteredTouchEvent(target->parentItem(), item, event);
+ return sendFilteredTouchEvent(target->parentItem(), item, event) || filtered;
}
bool QQuickWindowPrivate::sendFilteredMouseEvent(QQuickItem *target, QQuickItem *item, QEvent *event)
@@ -2304,15 +2305,14 @@ bool QQuickWindowPrivate::sendFilteredMouseEvent(QQuickItem *target, QQuickItem
if (!target)
return false;
+ bool filtered = false;
+
QQuickItemPrivate *targetPrivate = QQuickItemPrivate::get(target);
if (targetPrivate->filtersChildMouseEvents)
if (target->childMouseEventFilter(item, event))
- return true;
-
- if (sendFilteredMouseEvent(target->parentItem(), item, event))
- return true;
+ filtered = true;
- return false;
+ return sendFilteredMouseEvent(target->parentItem(), item, event) || filtered;
}
bool QQuickWindowPrivate::dragOverThreshold(qreal d, Qt::Axis axis, QMouseEvent *event, int startDragThreshold)
diff --git a/tests/auto/quick/qquickflickable/data/nestedClickThenFlick.qml b/tests/auto/quick/qquickflickable/data/nestedClickThenFlick.qml
new file mode 100644
index 0000000000..619ab6d1dc
--- /dev/null
+++ b/tests/auto/quick/qquickflickable/data/nestedClickThenFlick.qml
@@ -0,0 +1,39 @@
+import QtQuick 2.0
+
+Flickable {
+ property bool pressed: ma.pressed
+ width: 240
+ height: 320
+ contentWidth: 480
+ contentHeight: 320
+ flickableDirection: Flickable.HorizontalFlick
+ pressDelay: 50
+ Rectangle {
+ anchors.fill: parent
+ anchors.margins: 50
+ color: "yellow"
+
+ }
+
+ onMovingChanged: console.log("outer moving", moving)
+
+ Flickable {
+ objectName: "innerFlickable"
+ anchors.fill: parent
+ flickableDirection: Flickable.VerticalFlick
+ contentWidth: 480
+ contentHeight: 1480
+ pressDelay: 50
+ Rectangle {
+ anchors.fill: parent
+ anchors.margins: 100
+ color: ma.pressed ? 'blue' : 'green'
+ }
+ MouseArea {
+ id: ma
+ objectName: "mouseArea"
+ anchors.fill: parent
+ }
+ }
+}
+
diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
index 7cc3350b05..80aaf5895f 100644
--- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
+++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
@@ -75,6 +75,7 @@ private slots:
void flickDeceleration();
void pressDelay();
void nestedPressDelay();
+ void nestedClickThenFlick();
void flickableDirection();
void resizeContent();
void returnToBounds();
@@ -513,6 +514,51 @@ void tst_qquickflickable::nestedPressDelay()
QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(90, 150));
}
+// QTBUG-37316
+void tst_qquickflickable::nestedClickThenFlick()
+{
+ QScopedPointer<QQuickView> window(new QQuickView);
+ window->setSource(testFileUrl("nestedClickThenFlick.qml"));
+ QTRY_COMPARE(window->status(), QQuickView::Ready);
+ QQuickViewTestUtil::centerOnScreen(window.data());
+ QQuickViewTestUtil::moveMouseAway(window.data());
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+ QVERIFY(window->rootObject() != 0);
+
+ QQuickFlickable *outer = qobject_cast<QQuickFlickable*>(window->rootObject());
+ QVERIFY(outer != 0);
+
+ QQuickFlickable *inner = window->rootObject()->findChild<QQuickFlickable*>("innerFlickable");
+ QVERIFY(inner != 0);
+
+ QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(150, 150));
+
+ // the MouseArea is not pressed immediately
+ QVERIFY(outer->property("pressed").toBool() == false);
+ QTRY_VERIFY(outer->property("pressed").toBool() == true);
+
+ QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(150, 150));
+
+ QVERIFY(outer->property("pressed").toBool() == false);
+
+ // Dragging inner Flickable should work
+ QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(80, 150));
+ // the MouseArea is not pressed immediately
+
+ QVERIFY(outer->property("pressed").toBool() == false);
+
+ QTest::mouseMove(window.data(), QPoint(80, 148));
+ QTest::mouseMove(window.data(), QPoint(80, 140));
+ QTest::mouseMove(window.data(), QPoint(80, 120));
+ QTest::mouseMove(window.data(), QPoint(80, 100));
+
+ QVERIFY(outer->property("moving").toBool() == false);
+ QVERIFY(inner->property("moving").toBool() == true);
+
+ QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(80, 100));
+}
+
void tst_qquickflickable::flickableDirection()
{
QQmlComponent component(&engine);