summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/widgets/kernel/qwidgetwindow.cpp6
-rw-r--r--tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp194
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