diff options
author | Shawn Rutledge <shawn.rutledge@qt.io> | 2017-11-30 14:12:17 +0100 |
---|---|---|
committer | Shawn Rutledge <shawn.rutledge@qt.io> | 2017-12-05 12:48:58 +0000 |
commit | 9b1b87b6eb5fdf2f98e9e380d25d71bce93e7e27 (patch) | |
tree | b82dd1f479ad61068cfb637379e2db5b14a57e71 /tests/auto/quick | |
parent | c34e75e6c9549daa3407eaae0ef4a0ac91802b02 (diff) |
grabMouse() and QQWPriv::removeGrabber(): be clear whether mouse or touch
The bug was that a MouseArea could be stuck in pressed state if a touch tap
occurred simultaneously on a second MouseArea while the first was held
pressed by the actual mouse.
QQuickWindowPrivate::setMouseGrabber(QQuickItem *) had too little
information to make the right choice in case the given item argument is
null. It should not mean ungrab everything: in this use case, the mouse and
the touchpoint can be pressing two different MouseAreas, and releasing
either one should ungrab only the MouseArea that is being released.
However the only place it was called with nullptr was in removeGrabber(),
and in that context we are given all the information: which item to ungrab
and whether we want to ungrab mouse, touch or both. It's better to have
a little code duplication between QQuickItem::grabMouse() and
QQuickWindowPrivate::removeGrabber() than to lose this information
about which device(s) and Item to ungrab.
Task-number: QTBUG-64249
Change-Id: I0710534a05f3ceeb66105a03ab0f32a61df8a522
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io>
Diffstat (limited to 'tests/auto/quick')
-rw-r--r-- | tests/auto/quick/qquickmousearea/data/twoMouseAreas.qml | 33 | ||||
-rw-r--r-- | tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp | 69 |
2 files changed, 102 insertions, 0 deletions
diff --git a/tests/auto/quick/qquickmousearea/data/twoMouseAreas.qml b/tests/auto/quick/qquickmousearea/data/twoMouseAreas.qml new file mode 100644 index 0000000000..28f48c742a --- /dev/null +++ b/tests/auto/quick/qquickmousearea/data/twoMouseAreas.qml @@ -0,0 +1,33 @@ +import QtQuick 2.0 +import QtQuick.Window 2.0 + +Rectangle { + width: 400 + height: 300 + + property bool topPressed: top.pressed + property bool bottomPressed: bottom.pressed + + MouseArea { + id: top + objectName: "top" + width: parent.width + height: parent.height / 2 - 2 + Rectangle { + anchors.fill: parent + color: parent.pressed ? "MediumSeaGreen" : "beige" + } + } + + MouseArea { + id: bottom + objectName: "bottom" + y: parent.height / 2 + width: parent.width + height: parent.height / 2 + Rectangle { + anchors.fill: parent + color: parent.pressed ? "MediumSeaGreen" : "beige" + } + } +} diff --git a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp index 01bce46ccb..12c6233ded 100644 --- a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp +++ b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp @@ -130,6 +130,8 @@ private slots: void notPressedAfterStolenGrab(); void pressAndHold_data(); void pressAndHold(); + void pressOneAndTapAnother_data(); + void pressOneAndTapAnother(); private: int startDragDistance() const { @@ -2173,6 +2175,73 @@ void tst_QQuickMouseArea::pressAndHold() QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, QPoint(50, 50)); } +void tst_QQuickMouseArea::pressOneAndTapAnother_data() +{ + QTest::addColumn<bool>("pressMouseFirst"); + QTest::addColumn<bool>("releaseMouseFirst"); + + QTest::newRow("press mouse, tap touch, release mouse") << true << false; // QTBUG-64249 as written + QTest::newRow("press touch, press mouse, release touch, release mouse") << false << false; + QTest::newRow("press mouse, press touch, release mouse, release touch") << true << true; + QTest::newRow("press touch, click mouse, release touch") << false << true; +} + +void tst_QQuickMouseArea::pressOneAndTapAnother() +{ + QFETCH(bool, pressMouseFirst); + QFETCH(bool, releaseMouseFirst); + + QQuickView window; + QByteArray errorMessage; + QVERIFY2(initView(window, testFileUrl("twoMouseAreas.qml"), true, &errorMessage), errorMessage.constData()); + window.show(); + window.requestActivate(); + QVERIFY(QTest::qWaitForWindowExposed(&window)); + QQuickItem *root = window.rootObject(); + QVERIFY(root); + QQuickMouseArea *bottomMA = window.rootObject()->findChild<QQuickMouseArea*>("bottom"); + QVERIFY(bottomMA); + QQuickMouseArea *topMA = window.rootObject()->findChild<QQuickMouseArea*>("top"); + QVERIFY(topMA); + + QPoint upper(32, 32); + QPoint lower(32, window.height() - 32); + + // press them both + if (pressMouseFirst) { + QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, lower); + QTRY_COMPARE(bottomMA->pressed(), true); + + QTest::touchEvent(&window, device).press(0, lower, &window); + QQuickTouchUtils::flush(&window); + QTRY_COMPARE(bottomMA->pressed(), true); + } else { + QTest::touchEvent(&window, device).press(0, lower, &window); + QQuickTouchUtils::flush(&window); + QTRY_COMPARE(bottomMA->pressed(), true); + + QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, lower); + QTRY_COMPARE(bottomMA->pressed(), true); + } + + // release them both and make sure neither one gets stuck + if (releaseMouseFirst) { + QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, lower); + QTRY_COMPARE(bottomMA->pressed(), false); + + QTest::touchEvent(&window, device).release(0, upper, &window); + QQuickTouchUtils::flush(&window); + QTRY_COMPARE(topMA->pressed(), false); + } else { + QTest::touchEvent(&window, device).release(0, upper, &window); + QQuickTouchUtils::flush(&window); + + QTRY_COMPARE(topMA->pressed(), false); + QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, lower); + QTRY_COMPARE(bottomMA->pressed(), false); + } +} + QTEST_MAIN(tst_QQuickMouseArea) #include "tst_qquickmousearea.moc" |