diff options
-rw-r--r-- | src/widgets/kernel/qwidgetwindow.cpp | 6 | ||||
-rw-r--r-- | tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp | 194 |
2 files changed, 190 insertions, 10 deletions
diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index b49441beba..94e851ac4c 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -244,7 +244,11 @@ void QWidgetWindow::handleEnterLeaveEvent(QEvent *event) // both native and non-native widgets work similarly. // When mousegrabbing, leaves are only generated if leaving the parent window. if (!enter || !QWidget::mouseGrabber()) { - QWidget *leave = qt_last_mouse_receiver ? qt_last_mouse_receiver.data() : m_widget; + // Preferred leave target is the last mouse receiver, unless it has native window, + // in which case it is assumed to receive it's own leave event when relevant. + QWidget *leave = m_widget; + if (qt_last_mouse_receiver && !qt_last_mouse_receiver->internalWinId()) + leave = qt_last_mouse_receiver.data(); QApplicationPrivate::dispatchEnterLeave(enter, leave); qt_last_mouse_receiver = enter; } diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index 1052a9100d..0340677dac 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -4724,7 +4724,7 @@ class ColorWidget : public QWidget { public: ColorWidget(QWidget *parent = 0, const QColor &c = QColor(Qt::red)) - : QWidget(parent, Qt::FramelessWindowHint), color(c) + : QWidget(parent, Qt::FramelessWindowHint), color(c), enters(0), leaves(0) { QPalette opaquePalette = palette(); opaquePalette.setColor(backgroundRole(), color); @@ -4740,8 +4740,19 @@ public: r = QRegion(); } + void enterEvent(QEvent *) { ++enters; } + void leaveEvent(QEvent *) { ++leaves; } + + void resetCounts() + { + enters = 0; + leaves = 0; + } + QColor color; QRegion r; + int enters; + int leaves; }; #define VERIFY_COLOR(region, color) { \ @@ -9605,16 +9616,18 @@ 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); + ColorWidget topLevelWidget(0, Qt::blue); + ColorWidget childWidget1(&topLevelWidget, Qt::yellow); + ColorWidget childWidget2(&topLevelWidget, Qt::black); + ColorWidget popupWidget(0, Qt::green); topLevelWidget.setObjectName("topLevelWidget"); childWidget1.setObjectName("childWidget1"); childWidget2.setObjectName("childWidget2"); popupWidget.setObjectName("popupWidget"); + popupWidget.setWindowFlags(Qt::Popup); + topLevelWidget.setGeometry(100, 100, 300, 300); childWidget1.setGeometry(20, 20, 100, 100); childWidget2.setGeometry(20, 120, 100, 100); @@ -9627,7 +9640,8 @@ void tst_QWidget::underMouse() QPoint outsideWindowPoint(30, -10); QPoint inWindowPoint(30, 10); QPoint child1Point(30, 50); - QPoint child2Point(30, 150); + QPoint child2PointA(30, 150); + QPoint child2PointB(31, 151); // Outside window QTest::mouseMove(window, outsideWindowPoint); @@ -9650,11 +9664,16 @@ void tst_QWidget::underMouse() QVERIFY(!childWidget2.underMouse()); // In childWidget2 - QTest::mouseMove(window, child2Point); + QTest::mouseMove(window, child2PointA); QVERIFY(topLevelWidget.underMouse()); QVERIFY(!childWidget1.underMouse()); QVERIFY(childWidget2.underMouse()); + topLevelWidget.resetCounts(); + childWidget1.resetCounts(); + childWidget2.resetCounts(); + popupWidget.resetCounts(); + // Throw up a popup window popupWidget.show(); QVERIFY(QTest::qWaitForWindowExposed(&popupWidget)); @@ -9662,21 +9681,178 @@ void tst_QWidget::underMouse() QVERIFY(popupWindow); QVERIFY(QApplication::activePopupWidget() == &popupWidget); - // If there is an active popup, undermouse should not be reported (QTBUG-27478) + // If there is an active popup, undermouse should not be reported (QTBUG-27478), + // but opening a popup causes leave for widgets under mouse. QVERIFY(!topLevelWidget.underMouse()); QVERIFY(!childWidget1.underMouse()); QVERIFY(!childWidget2.underMouse()); + QVERIFY(!popupWidget.underMouse()); + QCOMPARE(popupWidget.enters, 0); + QCOMPARE(popupWidget.leaves, 0); + QCOMPARE(topLevelWidget.enters, 0); + QCOMPARE(topLevelWidget.leaves, 1); + QCOMPARE(childWidget1.enters, 0); + QCOMPARE(childWidget1.leaves, 0); + QCOMPARE(childWidget2.enters, 0); + QCOMPARE(childWidget2.leaves, 1); + topLevelWidget.resetCounts(); + childWidget2.resetCounts(); + + // Note about commented out compares below: + // Widgets are not receiving enter/leave events properly when there is a popup up, + // so all enter and leave counts are not correct yet. + // Fix this test when QTBUG-27800 is fixed (i.e. uncomment commented out compares). + + // Moving around while popup active should not change undermouse either, + // but should send enter and leave events for widgets + QTest::mouseMove(popupWindow, popupWindow->mapFromGlobal(window->mapToGlobal(child2PointB))); + QVERIFY(!topLevelWidget.underMouse()); + QVERIFY(!childWidget1.underMouse()); + QVERIFY(!childWidget2.underMouse()); + QVERIFY(!popupWidget.underMouse()); + QCOMPARE(popupWidget.enters, 0); + QCOMPARE(popupWidget.leaves, 0); + //QCOMPARE(topLevelWidget.enters, 1); // QTBUG-27800 + QCOMPARE(topLevelWidget.leaves, 0); + QCOMPARE(childWidget1.enters, 0); + QCOMPARE(childWidget1.leaves, 0); + //QCOMPARE(childWidget2.enters, 1); // QTBUG-27800 + QCOMPARE(childWidget2.leaves, 0); + topLevelWidget.resetCounts(); + childWidget2.resetCounts(); - // 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()); + QVERIFY(!popupWidget.underMouse()); + QCOMPARE(popupWidget.enters, 0); + QCOMPARE(popupWidget.leaves, 0); + QCOMPARE(topLevelWidget.enters, 0); + QCOMPARE(topLevelWidget.leaves, 0); + QCOMPARE(childWidget1.enters, 0); + QCOMPARE(childWidget1.leaves, 0); + QCOMPARE(childWidget2.enters, 0); + //QCOMPARE(childWidget2.leaves, 1); // QTBUG-27800 + childWidget2.resetCounts(); QTest::mouseMove(popupWindow, popupWindow->mapFromGlobal(window->mapToGlobal(child1Point))); QVERIFY(!topLevelWidget.underMouse()); QVERIFY(!childWidget1.underMouse()); QVERIFY(!childWidget2.underMouse()); + QVERIFY(!popupWidget.underMouse()); + QCOMPARE(popupWidget.enters, 0); + QCOMPARE(popupWidget.leaves, 0); + QCOMPARE(topLevelWidget.enters, 0); + QCOMPARE(topLevelWidget.leaves, 0); + //QCOMPARE(childWidget1.enters, 1); // QTBUG-27800 + QCOMPARE(childWidget1.leaves, 0); + QCOMPARE(childWidget2.enters, 0); + QCOMPARE(childWidget2.leaves, 0); + childWidget1.resetCounts(); + + // Mouse moves off-application, should cause leaves for currently entered widgets + QWindowSystemInterface::handleLeaveEvent(window); + QApplication::processEvents(); + QVERIFY(!topLevelWidget.underMouse()); + QVERIFY(!childWidget1.underMouse()); + QVERIFY(!childWidget2.underMouse()); + QVERIFY(!popupWidget.underMouse()); + QCOMPARE(popupWidget.enters, 0); + QCOMPARE(popupWidget.leaves, 0); + QCOMPARE(topLevelWidget.enters, 0); + QCOMPARE(topLevelWidget.leaves, 1); + QCOMPARE(childWidget1.enters, 0); + //QCOMPARE(childWidget1.leaves, 1); // QTBUG-27800 + QCOMPARE(childWidget2.enters, 0); + QCOMPARE(childWidget2.leaves, 0); + topLevelWidget.resetCounts(); + childWidget1.resetCounts(); + + // Mouse enters back in, should cause enter to topLevelWidget + QWindowSystemInterface::handleEnterEvent(window); + QApplication::processEvents(); + QVERIFY(!topLevelWidget.underMouse()); + QVERIFY(!childWidget1.underMouse()); + QVERIFY(!childWidget2.underMouse()); + QVERIFY(!popupWidget.underMouse()); + QCOMPARE(popupWidget.enters, 0); + QCOMPARE(popupWidget.leaves, 0); + QCOMPARE(topLevelWidget.enters, 1); + QCOMPARE(topLevelWidget.leaves, 0); + QCOMPARE(childWidget1.enters, 0); + QCOMPARE(childWidget1.leaves, 0); + QCOMPARE(childWidget2.enters, 0); + QCOMPARE(childWidget2.leaves, 0); + topLevelWidget.resetCounts(); + + // Mouse moves to child widget, should cause enter to child + QTest::mouseMove(popupWindow, popupWindow->mapFromGlobal(window->mapToGlobal(child2PointB))); + QVERIFY(!topLevelWidget.underMouse()); + QVERIFY(!childWidget1.underMouse()); + QVERIFY(!childWidget2.underMouse()); + QVERIFY(!popupWidget.underMouse()); + QCOMPARE(popupWidget.enters, 0); + QCOMPARE(popupWidget.leaves, 0); + QCOMPARE(topLevelWidget.enters, 0); + QCOMPARE(topLevelWidget.leaves, 0); + QCOMPARE(childWidget1.enters, 0); + QCOMPARE(childWidget1.leaves, 0); + //QCOMPARE(childWidget2.enters, 1); // QTBUG-27800 + QCOMPARE(childWidget2.leaves, 0); + childWidget2.resetCounts(); + + // Mouse enters popup, should cause enter to popup and leave to current widgets under mouse + QWindowSystemInterface::handleLeaveEvent(window); + QWindowSystemInterface::handleEnterEvent(popupWindow); + QApplication::processEvents(); + QVERIFY(!topLevelWidget.underMouse()); + QVERIFY(!childWidget1.underMouse()); + QVERIFY(!childWidget2.underMouse()); + QVERIFY(popupWidget.underMouse()); + QCOMPARE(popupWidget.enters, 1); + QCOMPARE(popupWidget.leaves, 0); + QCOMPARE(topLevelWidget.enters, 0); + QCOMPARE(topLevelWidget.leaves, 1); + QCOMPARE(childWidget1.enters, 0); + QCOMPARE(childWidget1.leaves, 0); + QCOMPARE(childWidget2.enters, 0); + //QCOMPARE(childWidget2.leaves, 1); // QTBUG-27800 + popupWidget.resetCounts(); + topLevelWidget.resetCounts(); + childWidget2.resetCounts(); + + // Mouse moves around inside popup, no changes + QTest::mouseMove(popupWindow, QPoint(5, 5)); + QVERIFY(!topLevelWidget.underMouse()); + QVERIFY(!childWidget1.underMouse()); + QVERIFY(!childWidget2.underMouse()); + QVERIFY(popupWidget.underMouse()); + QCOMPARE(popupWidget.enters, 0); + QCOMPARE(popupWidget.leaves, 0); + QCOMPARE(topLevelWidget.enters, 0); + QCOMPARE(topLevelWidget.leaves, 0); + QCOMPARE(childWidget1.enters, 0); + QCOMPARE(childWidget1.leaves, 0); + QCOMPARE(childWidget2.enters, 0); + QCOMPARE(childWidget2.leaves, 0); + + // Mouse leaves popup and enters topLevelWidget, should cause enter to topLevelWidget and leave for popup + QWindowSystemInterface::handleLeaveEvent(popupWindow); + QWindowSystemInterface::handleEnterEvent(window); + QApplication::processEvents(); + QVERIFY(!topLevelWidget.underMouse()); + QVERIFY(!childWidget1.underMouse()); + QVERIFY(!childWidget2.underMouse()); + QVERIFY(!popupWidget.underMouse()); + QCOMPARE(popupWidget.enters, 0); + QCOMPARE(popupWidget.leaves, 1); + QCOMPARE(topLevelWidget.enters, 1); + QCOMPARE(topLevelWidget.leaves, 0); + QCOMPARE(childWidget1.enters, 0); + QCOMPARE(childWidget1.leaves, 0); + QCOMPARE(childWidget2.enters, 0); + QCOMPARE(childWidget2.leaves, 0); } #endif // QTEST_NO_CURSOR |