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 <Friedemann.Kleint@digia.com>
Reviewed-by: Marc Mutz <marc.mutz@kdab.com>
This commit is contained in:
Miikka Heikkinen 2012-10-12 15:28:55 +03:00 committed by The Qt Project
parent 21b5c1d4a9
commit 698d5a2b9f
2 changed files with 89 additions and 0 deletions

View File

@ -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<QWidget> 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()

View File

@ -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"