diff options
author | Błażej Szczygieł <spaz16@wp.pl> | 2016-01-21 13:19:37 +0100 |
---|---|---|
committer | Shawn Rutledge <shawn.rutledge@theqtcompany.com> | 2016-02-24 04:33:36 +0000 |
commit | 57ecd5aeeb1f609206933be66b92fcdf703703d7 (patch) | |
tree | 158a491f8fab6563c8990e35af2bdd35d74c6976 /tests/auto | |
parent | eadd7e9cfb4e0802aa9da63badc41c39fec219bb (diff) |
QtWidgets: Proper delivery of enter/leave event to context menus
First-level context menu grabs the mouse, so all mouse events are
delivered to it. This menu passes the mouse events to submenus. Any
platform delivers mouse enter/leave event differently when window is
grabbed. This patch unifies event delivery to context menus - it can
block some unwanted events and it emulates fake events if necessary.
This patch can reduce duplicated events and can provide proper enter
or leave event to additional widgets in the context menu. It can also
prevent submenu from unwanted close on Windows and X11.
Added autotest.
Task-number: QTBUG-45565
Task-number: QTBUG-45893
Task-number: QTBUG-47515
Change-Id: I7dd476d0be23afa34e947e54aef235012d173dcf
Reviewed-by: Shawn Rutledge <shawn.rutledge@theqtcompany.com>
Diffstat (limited to 'tests/auto')
-rw-r--r-- | tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp index b3f9c54f24..20f17f6e9e 100644 --- a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp +++ b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp @@ -110,6 +110,9 @@ private slots: void QTBUG7411_submenus_activate(); void QTBUG30595_rtl_submenu(); void QTBUG20403_nested_popup_on_shortcut_trigger(); +#ifndef QT_NO_CURSOR + void QTBUG47515_widgetActionEnterLeave(); +#endif void QTBUG_10735_crashWithDialog(); #ifdef Q_OS_MAC void QTBUG_37933_ampersands_data(); @@ -1070,6 +1073,112 @@ void tst_QMenu::QTBUG20403_nested_popup_on_shortcut_trigger() QVERIFY(!subsub1.isVisible()); } +class MyWidget : public QWidget +{ +public: + MyWidget(QWidget *parent) : + QWidget(parent), + move(0), enter(0), leave(0) + { + setMinimumSize(100, 100); + setMouseTracking(true); + } + + bool event(QEvent *e) Q_DECL_OVERRIDE + { + switch (e->type()) { + case QEvent::MouseMove: + ++move; + break; + case QEvent::Enter: + ++enter; + break; + case QEvent::Leave: + ++leave; + break; + default: + break; + } + return QWidget::event(e); + } + + int move, enter, leave; +}; + +#ifndef QT_NO_CURSOR +void tst_QMenu::QTBUG47515_widgetActionEnterLeave() +{ + if (QGuiApplication::platformName() == QLatin1String("cocoa")) + QSKIP("This test fails on OS X on CI"); + + const QPoint center = QGuiApplication::primaryScreen()->availableGeometry().center(); + const QPoint cursorPos = center - QPoint(100, 100); + + QScopedPointer<QMenu> menu1(new QMenu("Menu1")); + QScopedPointer<QMenu> menu2(new QMenu("Menu2")); + + QWidgetAction *wA1 = new QWidgetAction(menu1.data()); + MyWidget *w1 = new MyWidget(menu1.data()); + wA1->setDefaultWidget(w1); + + QWidgetAction *wA2 = new QWidgetAction(menu2.data()); + MyWidget *w2 = new MyWidget(menu2.data()); + wA2->setDefaultWidget(w2); + + QAction *nextMenuAct = menu1->addMenu(menu2.data()); + + menu1->addAction(wA1); + menu2->addAction(wA2); + + // Root menu + { + QCursor::setPos(cursorPos); + QCoreApplication::processEvents(); + + menu1->popup(center); + QVERIFY(QTest::qWaitForWindowExposed(menu1.data())); + + QCursor::setPos(w1->mapToGlobal(w1->rect().center())); + QVERIFY(w1->isVisible()); + QTRY_COMPARE(w1->leave, 0); + QTRY_COMPARE(w1->enter, 1); + + // Check whether leave event is not delivered on mouse move + w1->move = 0; + QCursor::setPos(w1->mapToGlobal(w1->rect().center()) + QPoint(1, 1)); + QTRY_COMPARE(w1->move, 1); + QTRY_COMPARE(w1->leave, 0); + QTRY_COMPARE(w1->enter, 1); + + QCursor::setPos(cursorPos); + QTRY_COMPARE(w1->leave, 1); + QTRY_COMPARE(w1->enter, 1); + } + + // Submenu + { + menu1->setActiveAction(nextMenuAct); + QVERIFY(QTest::qWaitForWindowExposed(menu2.data())); + + QCursor::setPos(w2->mapToGlobal(w2->rect().center())); + QVERIFY(w2->isVisible()); + QTRY_COMPARE(w2->leave, 0); + QTRY_COMPARE(w2->enter, 1); + + // Check whether leave event is not delivered on mouse move + w2->move = 0; + QCursor::setPos(w2->mapToGlobal(w2->rect().center()) + QPoint(1, 1)); + QTRY_COMPARE(w2->move, 1); + QTRY_COMPARE(w2->leave, 0); + QTRY_COMPARE(w2->enter, 1); + + QCursor::setPos(cursorPos); + QTRY_COMPARE(w2->leave, 1); + QTRY_COMPARE(w2->enter, 1); + } +} +#endif // !QT_NO_CURSOR + class MyMenu : public QMenu { Q_OBJECT |