aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorYuya Nishihara <yuya.nishihara@qt.io>2020-08-28 18:32:20 +0900
committerYuya Nishihara <yuya.nishihara@qt.io>2020-09-02 10:44:40 +0900
commitde007e507ca2693203d15506aede3294e6236a83 (patch)
tree8055b3e144555ae2be90e28009e65c0d21cfebaa /tests
parent704c009d839f69ad02a4112f1c0450a6d0d44096 (diff)
Menu: Close menu by Alt key on platforms supporting mnemonic shortcuts
This is close to what the widget QMenu (and Windows native menu) do. Before, the active menu was left open and Alt+<key> shortcut would be delivered to one of the matching items, which might be an item shadowed by the active menu popup. With this patch, the active menu is closed on Alt key pressed so the subsequent shortcut event will (likely) be delivered to the matching MenuBar item. Since I'm going to fix the issue of &mnemonic key conflict resolution, I need to first change the way of delivering a shortcut event to the parent MenuBar. The test cases use the undocumented function to simulate low-level behavior of Alt itself and Alt+<key> events. Apparently, there's no public QTest function to send multiple key events without releasing Alt modifier. Task-number: QTBUG-86276 Pick-to: 5.15 Change-Id: I0ed6ea94f0fee7983a5cb6352d388036d3a1f8df Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/qquickmenu/tst_qquickmenu.cpp14
-rw-r--r--tests/auto/qquickmenubar/tst_qquickmenubar.cpp42
-rw-r--r--tests/auto/shared/visualtestutil.cpp27
-rw-r--r--tests/auto/shared/visualtestutil.h17
4 files changed, 80 insertions, 20 deletions
diff --git a/tests/auto/qquickmenu/tst_qquickmenu.cpp b/tests/auto/qquickmenu/tst_qquickmenu.cpp
index a06b715f..d1b50357 100644
--- a/tests/auto/qquickmenu/tst_qquickmenu.cpp
+++ b/tests/auto/qquickmenu/tst_qquickmenu.cpp
@@ -533,6 +533,8 @@ void tst_QQuickMenu::mnemonics()
window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
+ MnemonicKeySimulator keySim(window);
+
QQuickMenu *menu = window->property("menu").value<QQuickMenu *>();
QQuickAction *action = window->property("action").value<QQuickAction *>();
QQuickMenuItem *menuItem = window->property("menuItem").value<QQuickMenuItem *>();
@@ -540,12 +542,13 @@ void tst_QQuickMenu::mnemonics()
QQuickMenuItem *subMenuItem = window->property("subMenuItem").value<QQuickMenuItem *>();
QVERIFY(menu && action && menuItem && subMenu && subMenuItem);
+ keySim.press(Qt::Key_Alt);
menu->open();
QTRY_VERIFY(menu->isOpened());
QSignalSpy actionSpy(action, &QQuickAction::triggered);
QVERIFY(actionSpy.isValid());
- QTest::keyClick(window, Qt::Key_A, Qt::AltModifier); // "&Action"
+ keySim.click(Qt::Key_A); // "&Action"
QCOMPARE(actionSpy.count(), 1);
menu->open();
@@ -553,18 +556,21 @@ void tst_QQuickMenu::mnemonics()
QSignalSpy menuItemSpy(menuItem, &QQuickMenuItem::triggered);
QVERIFY(menuItemSpy.isValid());
- QTest::keyClick(window, Qt::Key_I, Qt::AltModifier); // "Menu &Item"
+ keySim.click(Qt::Key_I); // "Menu &Item"
+ keySim.release(Qt::Key_Alt);
QCOMPARE(menuItemSpy.count(), 1);
+ keySim.press(Qt::Key_Alt);
menu->open();
QTRY_VERIFY(menu->isOpened());
- QTest::keyClick(window, Qt::Key_M, Qt::AltModifier); // "Sub &Menu"
+ keySim.click(Qt::Key_M); // "Sub &Menu"
QTRY_VERIFY(subMenu->isOpened());
QSignalSpy subMenuItemSpy(subMenuItem, &QQuickMenuItem::triggered);
QVERIFY(subMenuItemSpy.isValid());
- QTest::keyClick(window, Qt::Key_S, Qt::AltModifier); // "&Sub Menu Item"
+ keySim.click(Qt::Key_S); // "&Sub Menu Item"
+ keySim.release(Qt::Key_Alt);
QCOMPARE(subMenuItemSpy.count(), 1);
}
diff --git a/tests/auto/qquickmenubar/tst_qquickmenubar.cpp b/tests/auto/qquickmenubar/tst_qquickmenubar.cpp
index 2fb1a02b..62cb7363 100644
--- a/tests/auto/qquickmenubar/tst_qquickmenubar.cpp
+++ b/tests/auto/qquickmenubar/tst_qquickmenubar.cpp
@@ -418,6 +418,8 @@ void tst_qquickmenubar::mnemonics()
moveMouseAway(window.data());
QVERIFY(QTest::qWaitForWindowActive(window.data()));
+ MnemonicKeySimulator keySim(window.data());
+
QQuickMenuBar *menuBar = window->property("header").value<QQuickMenuBar *>();
QVERIFY(menuBar);
@@ -434,30 +436,35 @@ void tst_qquickmenubar::mnemonics()
QVERIFY(fileMenuBarItem && editMenuBarItem && viewMenuBarItem && helpMenuBarItem);
// trigger a menubar item to open a menu
- QTest::keyClick(window.data(), Qt::Key_E, Qt::AltModifier); // "&Edit"
+ keySim.press(Qt::Key_Alt);
+ keySim.click(Qt::Key_E); // "&Edit"
+ keySim.release(Qt::Key_Alt);
QVERIFY(editMenuBarItem->isHighlighted());
QVERIFY(!editMenuBarItem->hasActiveFocus());
QVERIFY(editMenuBarMenu->isVisible());
QTRY_VERIFY(editMenuBarMenu->isOpened());
QVERIFY(editMenuBarMenu->hasActiveFocus());
- // re-trigger a menubar item to hide the menu
- QTest::keyClick(window.data(), Qt::Key_E, Qt::AltModifier); // "&Edit"
- QVERIFY(editMenuBarItem->isHighlighted());
- QVERIFY(editMenuBarItem->hasActiveFocus());
+ // press Alt to hide the menu
+ keySim.click(Qt::Key_Alt);
+ QVERIFY(!editMenuBarItem->isHighlighted());
+ QVERIFY(!editMenuBarItem->hasActiveFocus());
QVERIFY(!editMenuBarMenu->hasActiveFocus());
QTRY_VERIFY(!editMenuBarMenu->isVisible());
// re-trigger a menubar item to show the menu again
- QTest::keyClick(window.data(), Qt::Key_E, Qt::AltModifier); // "&Edit"
+ keySim.press(Qt::Key_Alt);
+ keySim.click(Qt::Key_E); // "&Edit"
+ keySim.release(Qt::Key_Alt);
QVERIFY(editMenuBarItem->isHighlighted());
QVERIFY(editMenuBarMenu->isVisible());
QTRY_VERIFY(editMenuBarMenu->isOpened());
QVERIFY(editMenuBarMenu->hasActiveFocus());
QVERIFY(!editMenuBarItem->hasActiveFocus());
- // trigger another menubar item to open another menu
- QTest::keyClick(window.data(), Qt::Key_H, Qt::AltModifier); // "&Help"
+ // trigger another menubar item to open another menu, leave Alt pressed
+ keySim.press(Qt::Key_Alt);
+ keySim.click(Qt::Key_H); // "&Help"
QVERIFY(!editMenuBarItem->isHighlighted());
QVERIFY(helpMenuBarItem->isHighlighted());
QVERIFY(!viewMenuBarMenu->isVisible());
@@ -465,40 +472,43 @@ void tst_qquickmenubar::mnemonics()
QTRY_VERIFY(helpMenuBarMenu->isOpened());
// trigger a menu item to close the menu
- QTest::keyClick(window.data(), Qt::Key_A, Qt::AltModifier); // "&About"
+ keySim.click(Qt::Key_A); // "&About"
+ keySim.release(Qt::Key_Alt);
QVERIFY(!helpMenuBarItem->isHighlighted());
QTRY_VERIFY(!helpMenuBarMenu->isVisible());
- // trigger a menubar item to open a menu
- QTest::keyClick(window.data(), Qt::Key_V, Qt::AltModifier); // "&View"
+ // trigger a menubar item to open a menu, leave Alt pressed
+ keySim.press(Qt::Key_Alt);
+ keySim.click(Qt::Key_V); // "&View"
QVERIFY(!editMenuBarItem->isHighlighted());
QVERIFY(viewMenuBarItem->isHighlighted());
QVERIFY(viewMenuBarMenu->isVisible());
QTRY_VERIFY(viewMenuBarMenu->isOpened());
- // trigger a menu item to open a sub-menu
+ // trigger a menu item to open a sub-menu, leave Alt pressed
QQuickMenuItem *alignmentSubMenuItem = qobject_cast<QQuickMenuItem *>(viewMenuBarMenu->itemAt(0));
QVERIFY(alignmentSubMenuItem);
QQuickMenu *alignmentSubMenu = alignmentSubMenuItem->subMenu();
QVERIFY(alignmentSubMenu);
- QTest::keyClick(window.data(), Qt::Key_A, Qt::AltModifier); // "&Alignment"
+ keySim.click(Qt::Key_A); // "&Alignment"
QVERIFY(viewMenuBarMenu->isVisible());
QVERIFY(alignmentSubMenu->isVisible());
QTRY_VERIFY(alignmentSubMenu->isOpened());
- // trigger a menu item to open a sub-sub-menu
+ // trigger a menu item to open a sub-sub-menu, leave Alt pressed
QQuickMenuItem *verticalSubMenuItem = qobject_cast<QQuickMenuItem *>(alignmentSubMenu->itemAt(1));
QVERIFY(verticalSubMenuItem);
QQuickMenu *verticalSubMenu = verticalSubMenuItem->subMenu();
QVERIFY(verticalSubMenu);
- QTest::keyClick(window.data(), Qt::Key_V, Qt::AltModifier); // "&Vertical"
+ keySim.click(Qt::Key_V); // "&Vertical"
QVERIFY(viewMenuBarMenu->isVisible());
QVERIFY(alignmentSubMenu->isVisible());
QVERIFY(verticalSubMenu->isVisible());
QTRY_VERIFY(verticalSubMenu->isOpened());
// trigger a menu item to close the whole chain of menus
- QTest::keyClick(window.data(), Qt::Key_C, Qt::AltModifier); // "&Center"
+ keySim.click(Qt::Key_C); // "&Center"
+ keySim.release(Qt::Key_Alt);
QVERIFY(!viewMenuBarItem->isHighlighted());
QTRY_VERIFY(!viewMenuBarMenu->isVisible());
QTRY_VERIFY(!alignmentSubMenu->isVisible());
diff --git a/tests/auto/shared/visualtestutil.cpp b/tests/auto/shared/visualtestutil.cpp
index bfbf0a17..4e33c6f1 100644
--- a/tests/auto/shared/visualtestutil.cpp
+++ b/tests/auto/shared/visualtestutil.cpp
@@ -140,3 +140,30 @@ void QQuickVisualTestUtil::addTestRowForEachControl(QQmlEngine *engine, const QS
QTest::newRow(qPrintable(relativePath)) << absoluteUrl;
});
}
+
+QQuickVisualTestUtil::MnemonicKeySimulator::MnemonicKeySimulator(QWindow *window)
+ : m_window(window), m_modifiers(Qt::NoModifier)
+{
+}
+
+void QQuickVisualTestUtil::MnemonicKeySimulator::press(Qt::Key key)
+{
+ // QTest::keyPress() but not generating the press event for the modifier key.
+ if (key == Qt::Key_Alt)
+ m_modifiers |= Qt::AltModifier;
+ QTest::simulateEvent(m_window, true, key, m_modifiers, QString(), false);
+}
+
+void QQuickVisualTestUtil::MnemonicKeySimulator::release(Qt::Key key)
+{
+ // QTest::keyRelease() but not generating the release event for the modifier key.
+ if (key == Qt::Key_Alt)
+ m_modifiers &= ~Qt::AltModifier;
+ QTest::simulateEvent(m_window, false, key, m_modifiers, QString(), false);
+}
+
+void QQuickVisualTestUtil::MnemonicKeySimulator::click(Qt::Key key)
+{
+ press(key);
+ release(key);
+}
diff --git a/tests/auto/shared/visualtestutil.h b/tests/auto/shared/visualtestutil.h
index 726daa27..cbc0bade 100644
--- a/tests/auto/shared/visualtestutil.h
+++ b/tests/auto/shared/visualtestutil.h
@@ -39,6 +39,7 @@
#include <functional>
+#include <QtCore/QPointer>
#include <QtQuick/QQuickItem>
#include <QtQml/QQmlExpression>
#include <QtQuick/private/qquickitem_p.h>
@@ -190,6 +191,22 @@ namespace QQuickVisualTestUtil
void forEachControl(QQmlEngine *engine, const QString &sourcePath, const QString &targetPath, const QStringList &skipList, ForEachCallback callback);
void addTestRowForEachControl(QQmlEngine *engine, const QString &sourcePath, const QString &targetPath, const QStringList &skipList = QStringList());
+
+ // Helper to simulate Alt itself and Alt+<key> events.
+ class MnemonicKeySimulator
+ {
+ Q_DISABLE_COPY(MnemonicKeySimulator)
+ public:
+ explicit MnemonicKeySimulator(QWindow *window);
+
+ void press(Qt::Key key);
+ void release(Qt::Key key);
+ void click(Qt::Key key);
+
+ private:
+ QPointer<QWindow> m_window;
+ Qt::KeyboardModifiers m_modifiers;
+ };
}
#define QQUICK_VERIFY_POLISH(item) \