From 698d5a2b9f3df52fb6c4e178d50d2743db000b3d Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Fri, 12 Oct 2012 15:28:55 +0300 Subject: [PATCH] Improve Qt::WA_UnderMouse accuracy Qt::WA_UnderMouse is set/cleared when widgets get enter/leave events. When there is a popup active, Qt::WA_UnderMouse should always report false, but this was not happening, because existing state was not cleared when popup was opened. Dispatch a leave event for last mouse receiver when a popup is opened to update the Qt::WA_UnderMouse state. This is roughly equivalent to what happens on Qt4. Task-number: QTBUG-27478 Change-Id: I7739e75727213e748ab2f42f1027d32325d89fb0 Reviewed-by: Friedemann Kleint Reviewed-by: Marc Mutz --- src/widgets/kernel/qapplication_qpa.cpp | 7 ++ tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp | 82 +++++++++++++++++++++++ 2 files changed, 89 insertions(+) diff --git a/src/widgets/kernel/qapplication_qpa.cpp b/src/widgets/kernel/qapplication_qpa.cpp index 6b04c18..5dc68e4 100644 --- a/src/widgets/kernel/qapplication_qpa.cpp +++ b/src/widgets/kernel/qapplication_qpa.cpp @@ -77,6 +77,7 @@ extern QWidget *qt_button_down; extern QWidget *qt_popup_down; extern bool qt_replay_popup_mouse_event; int openPopupCount = 0; +extern QPointer qt_last_mouse_receiver; void QApplicationPrivate::createEventDispatcher() { @@ -249,6 +250,12 @@ void QApplicationPrivate::openPopup(QWidget *popup) QApplication::sendEvent(fw, &e); } } + + // Dispatch leave for last mouse receiver to update undermouse states + if (qt_last_mouse_receiver && !QWidget::mouseGrabber()) { + QApplicationPrivate::dispatchEnterLeave(0, qt_last_mouse_receiver.data()); + qt_last_mouse_receiver = 0; + } } void QApplicationPrivate::initializeMultitouch_sys() diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index 07ed38f..b4f31ac 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -353,6 +353,7 @@ private slots: #ifndef QTEST_NO_CURSOR void syntheticEnterLeave(); void taskQTBUG_4055_sendSyntheticEnterLeave(); + void underMouse(); #endif void windowFlags(); void initialPosForDontShowOnScreenWidgets(); @@ -9598,5 +9599,86 @@ void tst_QWidget::styleSheetPropagation() } } +#ifndef QTEST_NO_CURSOR +void tst_QWidget::underMouse() +{ + // Move the mouse cursor to a safe location + QCursor::setPos(0,0); + + QWidget topLevelWidget; + QLineEdit childWidget1(&topLevelWidget); + QLineEdit childWidget2(&topLevelWidget); + QWidget popupWidget(0, Qt::Popup); + + topLevelWidget.setObjectName("topLevelWidget"); + childWidget1.setObjectName("childWidget1"); + childWidget2.setObjectName("childWidget2"); + popupWidget.setObjectName("popupWidget"); + + topLevelWidget.setGeometry(100, 100, 300, 300); + childWidget1.setGeometry(20, 20, 100, 100); + childWidget2.setGeometry(20, 120, 100, 100); + popupWidget.setGeometry(50, 100, 50, 50); + + topLevelWidget.show(); + QVERIFY(QTest::qWaitForWindowExposed(&topLevelWidget)); + QWindow *window = topLevelWidget.windowHandle(); + + QPoint outsideWindowPoint(30, -10); + QPoint inWindowPoint(30, 10); + QPoint child1Point(30, 50); + QPoint child2Point(30, 150); + + // Outside window + QTest::mouseMove(window, outsideWindowPoint); + QVERIFY(!topLevelWidget.underMouse()); + QVERIFY(!childWidget1.underMouse()); + QVERIFY(!childWidget2.underMouse()); + + // Enter window, outside children + // Note: QTest::mouseMove will not generate enter events for windows, so send one explicitly + QWindowSystemInterface::handleEnterEvent(window); + QTest::mouseMove(window, inWindowPoint); + QVERIFY(topLevelWidget.underMouse()); + QVERIFY(!childWidget1.underMouse()); + QVERIFY(!childWidget2.underMouse()); + + // In childWidget1 + QTest::mouseMove(window, child1Point); + QVERIFY(topLevelWidget.underMouse()); + QVERIFY(childWidget1.underMouse()); + QVERIFY(!childWidget2.underMouse()); + + // In childWidget2 + QTest::mouseMove(window, child2Point); + QVERIFY(topLevelWidget.underMouse()); + QVERIFY(!childWidget1.underMouse()); + QVERIFY(childWidget2.underMouse()); + + // Throw up a popup window + popupWidget.show(); + QVERIFY(QTest::qWaitForWindowExposed(&popupWidget)); + QWindow *popupWindow = popupWidget.windowHandle(); + QVERIFY(popupWindow); + QVERIFY(QApplication::activePopupWidget() == &popupWidget); + + // If there is an active popup, undermouse should not be reported (QTBUG-27478) + QVERIFY(!topLevelWidget.underMouse()); + QVERIFY(!childWidget1.underMouse()); + QVERIFY(!childWidget2.underMouse()); + + // Moving around while popup active should not change undermouse either + QTest::mouseMove(popupWindow, popupWindow->mapFromGlobal(window->mapToGlobal(inWindowPoint))); + QVERIFY(!topLevelWidget.underMouse()); + QVERIFY(!childWidget1.underMouse()); + QVERIFY(!childWidget2.underMouse()); + + QTest::mouseMove(popupWindow, popupWindow->mapFromGlobal(window->mapToGlobal(child1Point))); + QVERIFY(!topLevelWidget.underMouse()); + QVERIFY(!childWidget1.underMouse()); + QVERIFY(!childWidget2.underMouse()); +} +#endif // QTEST_NO_CURSOR + QTEST_MAIN(tst_QWidget) #include "tst_qwidget.moc" -- 2.7.4