Fix inconsistent leave/enter events for main window when popup is open
Changed the platform leave event handling logic in QWidgetWindow to match platform leave event handling logic in Qt4, where last mouse receiver is used as leave target only if last mouse receiver wasn't a native window itself. In that case it is assumed to get leave event of its own when relevant. Task-number: QTBUG-27639 Change-Id: Id6edcd29754a15c959f18ab38b20d66e5d446510 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com> Reviewed-by: Oliver Wolff <oliver.wolff@digia.com>
This commit is contained in:
parent
7d5b813de3
commit
715902051a
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user