From 1f3713a2b40a467e8a8c552d0980dbdd9f7a1ab4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Arve=20S=C3=A6ther?= Date: Fri, 11 May 2018 13:36:52 +0200 Subject: Fix bug where Ungrab event was not sent clearGrabbers() will also clear QQuickWindow::mouseGrabberItem(), so we have to retrieve a copy of the mouse grabber item in advance of calling clearGrabbers(). This could happen when a filtering parent actually called grabMouse() on mouse release(!) event. Change-Id: I287214dbdff802707be625d73c38dd9c5d723aef Task-number: QTBUG-68030 Reviewed-by: Shawn Rutledge --- src/quick/items/qquickwindow.cpp | 3 +- tests/auto/quick/qquickwindow/tst_qquickwindow.cpp | 41 ++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 48eba6a7a0..0f617733c4 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -2311,8 +2311,9 @@ void QQuickWindowPrivate::deliverPointerEvent(QQuickPointerEvent *event) deliverMouseEvent(event->asPointerMouseEvent()); // failsafe: never allow any kind of grab to persist after release if (event->isReleaseEvent() && event->buttons() == Qt::NoButton) { + QQuickItem *oldGrabber = q->mouseGrabberItem(); event->clearGrabbers(); - sendUngrabEvent(q->mouseGrabberItem(), false); + sendUngrabEvent(oldGrabber, false); } } else if (event->asPointerTouchEvent()) { deliverTouchEvent(event->asPointerTouchEvent()); diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp index cd3486f95f..042908bf0c 100644 --- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp +++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp @@ -179,6 +179,7 @@ public: bool acceptTouchEvents; bool acceptMouseEvents; + bool grabOnRelease = false; TouchEventData lastEvent; int mousePressCount; int mouseMoveCount; @@ -248,6 +249,10 @@ public: case QEvent::MouseButtonPress: mousePressCount = ++mousePressNum; break; + case QEvent::MouseButtonRelease: + if (grabOnRelease) + grabMouse(); + break; case QEvent::MouseMove: mouseMoveCount = ++mouseMoveNum; break; @@ -468,6 +473,7 @@ private slots: void testChildMouseEventFilter(); void testChildMouseEventFilter_data(); + void cleanupGrabsOnRelease(); private: QTouchDevice *touchDevice; @@ -3514,6 +3520,41 @@ void tst_qquickwindow::testChildMouseEventFilter() QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, mousePos); } +void tst_qquickwindow::cleanupGrabsOnRelease() +{ + TestTouchItem::clearMouseEventCounters(); + + QQuickWindow *window = new QQuickWindow; + QScopedPointer cleanup(window); + window->resize(250, 250); + window->setPosition(100, 100); + window->setTitle(QTest::currentTestFunction()); + window->show(); + QVERIFY(QTest::qWaitForWindowActive(window)); + + TestTouchItem *parent = new TestTouchItem(window->contentItem()); + parent->setObjectName("parent"); + parent->setSize(QSizeF(150, 150)); + parent->acceptMouseEvents = true; + parent->grabOnRelease = true; + + TestTouchItem *child = new TestTouchItem(parent); + child->setObjectName("child"); + child->setSize(QSizeF(100, 100)); + child->acceptMouseEvents = true; + + QPoint pos(80, 80); + + QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, pos); + QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, pos); + // There is an explicit parent->grabMouse on release(!). This means grab changes from child + // to parent: + // This will emit two ungrab events: + // 1. One for the child (due to the explicit call to parent->grabMouse()) + // 2. One for the parent (since the mouse button was finally released) + QCOMPARE(child->mouseUngrabEventCount, 1); + QCOMPARE(parent->mouseUngrabEventCount, 1); +} QTEST_MAIN(tst_qquickwindow) -- cgit v1.2.3