diff options
Diffstat (limited to 'tests/auto/quickcontrols2/qquickmenu/tst_qquickmenu.cpp')
-rw-r--r-- | tests/auto/quickcontrols2/qquickmenu/tst_qquickmenu.cpp | 169 |
1 files changed, 136 insertions, 33 deletions
diff --git a/tests/auto/quickcontrols2/qquickmenu/tst_qquickmenu.cpp b/tests/auto/quickcontrols2/qquickmenu/tst_qquickmenu.cpp index 9806eff7c3..12707998d7 100644 --- a/tests/auto/quickcontrols2/qquickmenu/tst_qquickmenu.cpp +++ b/tests/auto/quickcontrols2/qquickmenu/tst_qquickmenu.cpp @@ -33,6 +33,8 @@ #include <QtGui/qkeysequence.h> #endif #include <QtGui/qstylehints.h> +#include <QtGui/qpa/qplatformintegration.h> +#include <QtGui/private/qguiapplication_p.h> #include <QtQml/qqmlengine.h> #include <QtQml/qqmlcomponent.h> #include <QtQml/qqmlcontext.h> @@ -74,7 +76,9 @@ private slots: void menuSeparator(); void repeater(); void order(); +#if QT_CONFIG(cursor) void popup(); +#endif void actions(); #if QT_CONFIG(shortcut) void actionShortcuts(); @@ -103,6 +107,11 @@ private slots: void menuItemWidthAfterImplicitWidthChanged(); void menuItemWidthAfterRetranslate(); void giveMenuItemFocusOnButtonPress(); + void customMenuCullItems(); + void customMenuUseRepeaterAsTheContentItem(); + +private: + static bool hasWindowActivation(); }; tst_QQuickMenu::tst_QQuickMenu() @@ -110,6 +119,11 @@ tst_QQuickMenu::tst_QQuickMenu() { } +bool tst_QQuickMenu::hasWindowActivation() +{ + return (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)); +} + void tst_QQuickMenu::defaults() { QQuickControlsApplicationHelper helper(this, QLatin1String("applicationwindow.qml")); @@ -153,6 +167,9 @@ void tst_QQuickMenu::count() void tst_QQuickMenu::mouse() { + if (!hasWindowActivation()) + QSKIP("Window activation is not supported"); + if ((QGuiApplication::platformName() == QLatin1String("offscreen")) || (QGuiApplication::platformName() == QLatin1String("minimal"))) QSKIP("Mouse hovering not functional on offscreen/minimal platforms"); @@ -183,14 +200,14 @@ void tst_QQuickMenu::mouse() // Ensure that presses cause the current index to change, // so that the highlight acts as a way of illustrating press state. QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, - QPoint(menu->leftPadding() + firstItem->width() / 2, menu->topPadding() + firstItem->height() / 2)); + QPoint(menu->x() + menu->leftPadding() + firstItem->width() / 2, menu->y() + menu->topPadding() + firstItem->height() / 2)); QVERIFY(firstItem->hasActiveFocus()); QCOMPARE(menu->currentIndex(), 0); QCOMPARE(menu->contentItem()->property("currentIndex"), QVariant(0)); QVERIFY(menu->isVisible()); QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, - QPoint(menu->leftPadding() + firstItem->width() / 2, menu->topPadding() + firstItem->height() / 2)); + QPoint(menu->x() + menu->leftPadding() + firstItem->width() / 2, menu->y() + menu->topPadding() + firstItem->height() / 2)); QCOMPARE(clickedSpy.count(), 1); QCOMPARE(triggeredSpy.count(), 1); QTRY_COMPARE(visibleSpy.count(), 1); @@ -232,8 +249,8 @@ void tst_QQuickMenu::mouse() if (!hoverItem || !hoverItem->isVisible() || hoverItem == prevHoverItem) continue; QTest::mouseMove(window, QPoint( - menu->leftPadding() + hoverItem->x() + hoverItem->width() / 2, - menu->topPadding() + hoverItem->y() + hoverItem->height() / 2)); + menu->x() + menu->leftPadding() + hoverItem->x() + hoverItem->width() / 2, + menu->y() + menu->topPadding() + hoverItem->y() + hoverItem->height() / 2)); QTRY_VERIFY(hoverItem->property("highlighted").toBool()); if (prevHoverItem) QVERIFY(!prevHoverItem->property("highlighted").toBool()); @@ -265,7 +282,7 @@ void tst_QQuickMenu::pressAndHold() QQuickWindow *window = helper.window; window->show(); - QVERIFY(QTest::qWaitForWindowActive(window)); + QVERIFY(QTest::qWaitForWindowExposed(window)); QQuickMenu *menu = window->property("menu").value<QQuickMenu *>(); QVERIFY(menu); @@ -282,6 +299,9 @@ void tst_QQuickMenu::pressAndHold() void tst_QQuickMenu::contextMenuKeyboard() { + if (!hasWindowActivation()) + QSKIP("Window activation is not supported"); + if (QGuiApplication::styleHints()->tabFocusBehavior() != Qt::TabFocusAllControls) QSKIP("This platform only allows tab focus for text controls"); @@ -468,6 +488,9 @@ void tst_QQuickMenu::contextMenuKeyboard() // QTBUG-70181 void tst_QQuickMenu::disabledMenuItemKeyNavigation() { + if (!hasWindowActivation()) + QSKIP("Window activation is not supported"); + if (QGuiApplication::styleHints()->tabFocusBehavior() != Qt::TabFocusAllControls) QSKIP("This platform only allows tab focus for text controls"); @@ -532,6 +555,9 @@ void tst_QQuickMenu::disabledMenuItemKeyNavigation() void tst_QQuickMenu::mnemonics() { + if (!hasWindowActivation()) + QSKIP("Window activation is not supported"); + #ifdef Q_OS_MACOS QSKIP("Mnemonics are not used on macOS"); #endif @@ -587,6 +613,9 @@ void tst_QQuickMenu::mnemonics() void tst_QQuickMenu::menuButton() { + if (!hasWindowActivation()) + QSKIP("Window activation is not supported"); + if (QGuiApplication::styleHints()->tabFocusBehavior() != Qt::TabFocusAllControls) QSKIP("This platform only allows tab focus for text controls"); @@ -621,7 +650,7 @@ void tst_QQuickMenu::addItem() QVERIFY2(helper.ready, helper.failureMessage()); QQuickApplicationWindow *window = helper.appWindow; window->show(); - QVERIFY(QTest::qWaitForWindowActive(window)); + QVERIFY(QTest::qWaitForWindowExposed(window)); QQuickMenu *menu = window->property("menu").value<QQuickMenu*>(); QVERIFY(menu); @@ -639,6 +668,9 @@ void tst_QQuickMenu::addItem() void tst_QQuickMenu::menuSeparator() { + if (!hasWindowActivation()) + QSKIP("Window activation is not supported"); + QQuickControlsApplicationHelper helper(this, QLatin1String("menuSeparator.qml")); QVERIFY2(helper.ready, helper.failureMessage()); QQuickWindow *window = helper.window; @@ -663,6 +695,7 @@ void tst_QQuickMenu::menuSeparator() QVERIFY(saveMenuItem); QCOMPARE(saveMenuItem->text(), QStringLiteral("Save")); QTRY_VERIFY(!QQuickItemPrivate::get(saveMenuItem)->culled); // QTBUG-53262 + QTRY_VERIFY(menu->isOpened()); // Clicking on items should still close the menu. QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, @@ -670,7 +703,7 @@ void tst_QQuickMenu::menuSeparator() QTRY_VERIFY(!menu->isVisible()); menu->open(); - QVERIFY(menu->isVisible()); + QTRY_VERIFY(menu->isOpened()); // Clicking on a separator shouldn't close the menu. QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, @@ -721,7 +754,7 @@ void tst_QQuickMenu::repeater() QVERIFY2(helper.ready, helper.failureMessage()); QQuickWindow *window = helper.window; window->show(); - QVERIFY(QTest::qWaitForWindowActive(window)); + QVERIFY(QTest::qWaitForWindowExposed(window)); QQuickMenu *menu = window->property("menu").value<QQuickMenu*>(); QVERIFY(menu); @@ -766,7 +799,7 @@ void tst_QQuickMenu::order() QVERIFY2(helper.ready, helper.failureMessage()); QQuickWindow *window = helper.window; window->show(); - QVERIFY(QTest::qWaitForWindowActive(window)); + QVERIFY(QTest::qWaitForWindowExposed(window)); QQuickMenu *menu = window->property("menu").value<QQuickMenu*>(); QVERIFY(menu); @@ -782,15 +815,29 @@ void tst_QQuickMenu::order() } } +#if QT_CONFIG(cursor) void tst_QQuickMenu::popup() { +#if defined(Q_OS_ANDROID) + QSKIP("Setting cursor position is not supported on Android"); +#endif + if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"))) + QSKIP("Setting cursor position is not supported on Wayland"); + + // Try moving the cursor from the current position + // Skip if it fails since the test relies on moving the cursor + const QPoint point = QCursor::pos() + QPoint(1, 1); + QCursor::setPos(point); + if (!QTest::qWaitFor([point]{ return QCursor::pos() == point; })) + QSKIP("Setting cursor position is not supported on this platform"); + QQuickControlsApplicationHelper helper(this, QLatin1String("popup.qml")); QVERIFY2(helper.ready, helper.failureMessage()); QQuickApplicationWindow *window = helper.appWindow; centerOnScreen(window); moveMouseAway(window); window->show(); - QVERIFY(QTest::qWaitForWindowActive(window)); + QVERIFY(QTest::qWaitForWindowExposed(window)); QQuickMenu *menu = window->property("menu").value<QQuickMenu *>(); QVERIFY(menu); @@ -807,8 +854,6 @@ void tst_QQuickMenu::popup() QQuickItem *button = window->property("button").value<QQuickItem *>(); QVERIFY(button); - // Android does not support settings cursor position -#if QT_CONFIG(cursor) && !defined(Q_OS_ANDROID) QPoint oldCursorPos = QCursor::pos(); QPoint cursorPos = window->mapToGlobal(QPoint(11, 22)); QCursor::setPos(cursorPos); @@ -832,16 +877,16 @@ void tst_QQuickMenu::popup() QCOMPARE(menu->parentItem(), window->contentItem()); QCOMPARE(menu->currentIndex(), -1); QCOMPARE(menu->contentItem()->property("currentIndex").toInt(), -1); - QTRY_VERIFY(qFuzzyCompare(menu->x(), 33)); - QTRY_VERIFY(qFuzzyCompare(menu->y(), 44)); + QTRY_VERIFY(qFuzzyCompare(menu->x(), qMax(qreal(33), menu->leftMargin()))); + QTRY_VERIFY(qFuzzyCompare(menu->y(), qMax(qreal(44), menu->topMargin()))); menu->close(); QVERIFY(QMetaObject::invokeMethod(window, "popupAtCoord", Q_ARG(QVariant, 55), Q_ARG(QVariant, 66))); QCOMPARE(menu->parentItem(), window->contentItem()); QCOMPARE(menu->currentIndex(), -1); QCOMPARE(menu->contentItem()->property("currentIndex").toInt(), -1); - QTRY_VERIFY(qFuzzyCompare(menu->x(), 55)); - QTRY_VERIFY(qFuzzyCompare(menu->y(), 66)); + QTRY_VERIFY(qFuzzyCompare(menu->x(), qMax(qreal(55), menu->leftMargin()))); + QTRY_VERIFY(qFuzzyCompare(menu->y(), qMax(qreal(66), menu->topMargin()))); menu->close(); menu->setParentItem(nullptr); @@ -937,8 +982,8 @@ void tst_QQuickMenu::popup() QCursor::setPos(oldCursorPos); QTRY_COMPARE(QCursor::pos(), oldCursorPos); -#endif } +#endif // QT_CONFIG(cursor) void tst_QQuickMenu::actions() { @@ -946,7 +991,7 @@ void tst_QQuickMenu::actions() QVERIFY2(helper.ready, helper.failureMessage()); QQuickWindow *window = helper.window; window->show(); - QVERIFY(QTest::qWaitForWindowActive(window)); + QVERIFY(QTest::qWaitForWindowExposed(window)); QQuickMenu *menu = window->property("menu").value<QQuickMenu *>(); QVERIFY(menu); @@ -1012,6 +1057,9 @@ void tst_QQuickMenu::actions() #if QT_CONFIG(shortcut) void tst_QQuickMenu::actionShortcuts() { + if (!hasWindowActivation()) + QSKIP("Window activation is not supported"); + QQuickControlsApplicationHelper helper(this, QLatin1String("actionShortcuts.qml")); QVERIFY2(helper.ready, helper.failureMessage()); QQuickWindow *window = helper.window; @@ -1065,7 +1113,7 @@ void tst_QQuickMenu::removeTakeItem() QVERIFY2(helper.ready, helper.failureMessage()); QQuickWindow *window = helper.window; window->show(); - QVERIFY(QTest::qWaitForWindowActive(window)); + QVERIFY(QTest::qWaitForWindowExposed(window)); QQuickMenu *menu = window->property("menu").value<QQuickMenu *>(); QVERIFY(menu); @@ -1125,7 +1173,7 @@ void tst_QQuickMenu::subMenuMouse() centerOnScreen(window); moveMouseAway(window); window->show(); - QVERIFY(QTest::qWaitForWindowActive(window)); + QVERIFY(QTest::qWaitForWindowExposed(window)); QQuickMenu *mainMenu = window->property("mainMenu").value<QQuickMenu *>(); QVERIFY(mainMenu); @@ -1244,7 +1292,7 @@ void tst_QQuickMenu::subMenuDisabledMouse() centerOnScreen(window); moveMouseAway(window); window->show(); - QVERIFY(QTest::qWaitForWindowActive(window)); + QVERIFY(QTest::qWaitForWindowExposed(window)); QQuickMenu *mainMenu = window->property("mainMenu").value<QQuickMenu *>(); QVERIFY(mainMenu); @@ -1258,16 +1306,22 @@ void tst_QQuickMenu::subMenuDisabledMouse() QVERIFY(subMenu); mainMenu->open(); - QVERIFY(mainMenu->isVisible()); + QTRY_VERIFY(mainMenu->isOpened()); QVERIFY(!menuItem1->isHighlighted()); QVERIFY(!subMenu->isVisible()); + // Hover-highlighting does not work on Android +#ifndef Q_OS_ANDROID + // Generate a hover event to set the current index + QTest::mouseMove(window, menuItem1->mapToScene(QPoint(2, 2)).toPoint()); + QTRY_VERIFY(menuItem1->isHighlighted()); +#endif // Open the sub-menu with a mouse click. QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, menuItem1->mapToScene(QPoint(1, 1)).toPoint()); - // Need to use the TRY variant here when cascade is false, - // as e.g. Material style menus have transitions and don't close immediately. + // Need to use the TRY variant here, + // as e.g. Material, iOS style menus have transitions and don't open/close immediately. QTRY_COMPARE(mainMenu->isVisible(), cascade); - QVERIFY(subMenu->isVisible()); + QTRY_VERIFY(subMenu->isOpened()); QTRY_VERIFY(menuItem1->isHighlighted()); // Now the sub-menu is open. The current behavior is that the first menu item // in the new menu is highlighted; make sure that we choose the next item if @@ -1298,6 +1352,9 @@ void tst_QQuickMenu::subMenuKeyboard_data() void tst_QQuickMenu::subMenuKeyboard() { + if (!hasWindowActivation()) + QSKIP("Window activation is not supported"); + QFETCH(bool, cascade); QFETCH(bool, mirrored); @@ -1424,6 +1481,9 @@ void tst_QQuickMenu::subMenuDisabledKeyboard_data() // QTBUG-69540 void tst_QQuickMenu::subMenuDisabledKeyboard() { + if (!hasWindowActivation()) + QSKIP("Window activation is not supported"); + QFETCH(bool, cascade); QFETCH(bool, mirrored); @@ -1539,7 +1599,7 @@ void tst_QQuickMenu::subMenuPosition() // unpredictable results window->showNormal(); #endif - QVERIFY(QTest::qWaitForWindowActive(window)); + QVERIFY(QTest::qWaitForWindowExposed(window)); if (mirrored) { QQmlExpression mirroringExpression(qmlContext(window), window, @@ -1653,7 +1713,7 @@ void tst_QQuickMenu::addRemoveSubMenus() QVERIFY2(helper.ready, helper.failureMessage()); QQuickWindow *window = helper.window; window->show(); - QVERIFY(QTest::qWaitForWindowActive(window)); + QVERIFY(QTest::qWaitForWindowExposed(window)); QQuickMenu *mainMenu = window->property("mainMenu").value<QQuickMenu *>(); QVERIFY(mainMenu); @@ -1729,7 +1789,7 @@ void tst_QQuickMenu::scrollable() #else window->showNormal(); #endif - QVERIFY(QTest::qWaitForWindowActive(window)); + QVERIFY(QTest::qWaitForWindowExposed(window)); QQuickMenu *menu = window->property("menu").value<QQuickMenu*>(); menu->open(); @@ -1769,7 +1829,7 @@ void tst_QQuickMenu::disableWhenTriggered() QVERIFY2(helper.ready, helper.failureMessage()); QQuickWindow *window = helper.window; window->show(); - QVERIFY(QTest::qWaitForWindowActive(window)); + QVERIFY(QTest::qWaitForWindowExposed(window)); QQuickMenu *menu = window->findChild<QQuickMenu*>("Menu"); QVERIFY(menu); @@ -1834,7 +1894,7 @@ void tst_QQuickMenu::menuItemWidth() QVERIFY2(helper.ready, helper.failureMessage()); QQuickApplicationWindow *window = helper.appWindow; window->show(); - QVERIFY(QTest::qWaitForWindowActive(window)); + QVERIFY(QTest::qWaitForWindowExposed(window)); if (mirrored) { QQmlExpression mirroringExpression(qmlContext(window), window, @@ -1866,7 +1926,7 @@ void tst_QQuickMenu::menuItemWidthAfterMenuWidthChanged() QVERIFY2(helper.ready, helper.failureMessage()); QQuickApplicationWindow *window = helper.appWindow; window->show(); - QVERIFY(QTest::qWaitForWindowActive(window)); + QVERIFY(QTest::qWaitForWindowExposed(window)); if (mirrored) { QQmlExpression mirroringExpression(qmlContext(window), window, @@ -1914,7 +1974,7 @@ void tst_QQuickMenu::menuItemWidthAfterImplicitWidthChanged() QVERIFY2(helper.ready, helper.failureMessage()); QQuickApplicationWindow *window = helper.appWindow; window->show(); - QVERIFY(QTest::qWaitForWindowActive(window)); + QVERIFY(QTest::qWaitForWindowExposed(window)); if (mirrored) { QQmlExpression mirroringExpression(qmlContext(window), window, @@ -1948,7 +2008,7 @@ void tst_QQuickMenu::menuItemWidthAfterRetranslate() QVERIFY2(helper.ready, helper.failureMessage()); QQuickApplicationWindow *window = helper.appWindow; window->show(); - QVERIFY(QTest::qWaitForWindowActive(window)); + QVERIFY(QTest::qWaitForWindowExposed(window)); QQuickMenu *menu = window->property("menu").value<QQuickMenu *>(); QVERIFY(menu); @@ -1976,6 +2036,9 @@ void tst_QQuickMenu::menuItemWidthAfterRetranslate() void tst_QQuickMenu::giveMenuItemFocusOnButtonPress() { + if (!hasWindowActivation()) + QSKIP("Window activation is not supported"); + QQuickControlsApplicationHelper helper(this, QLatin1String("giveMenuItemFocusOnButtonPress.qml")); QVERIFY2(helper.ready, helper.failureMessage()); QQuickApplicationWindow *window = helper.appWindow; @@ -2000,6 +2063,46 @@ void tst_QQuickMenu::giveMenuItemFocusOnButtonPress() QTRY_VERIFY(menu->isOpened()); } +void tst_QQuickMenu::customMenuCullItems() +{ + QQuickControlsApplicationHelper helper(this, QLatin1String("customMenuCullItems.qml")); + QVERIFY2(helper.ready, helper.failureMessage()); + QQuickApplicationWindow *window = helper.appWindow; + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + + QQuickMenu *menu = window->property("menu").value<QQuickMenu*>(); + QVERIFY(menu); + menu->open(); + QTRY_VERIFY(menu->isOpened()); + + QQuickItem *menuItemFirst = menu->itemAt(0); + QQuickItem *menuItemLast = menu->itemAt(menu->count() - 1); + QVERIFY(menuItemFirst); + QVERIFY(menuItemLast); + QTRY_VERIFY(!QQuickItemPrivate::get(menuItemFirst)->culled); + QTRY_VERIFY(QQuickItemPrivate::get(menuItemLast)->culled); +} + +void tst_QQuickMenu::customMenuUseRepeaterAsTheContentItem() +{ + QQuickControlsApplicationHelper helper(this, QLatin1String("customMenuUseRepeaterAsTheContentItem.qml")); + QVERIFY2(helper.ready, helper.failureMessage()); + QQuickApplicationWindow *window = helper.appWindow; + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + + QQuickMenu *menu = window->property("menu").value<QQuickMenu*>(); + QVERIFY(menu); + menu->open(); + QTRY_VERIFY(menu->isVisible()); + + QQuickItem *menuItemFirst = menu->itemAt(0); + QQuickItem *menuItemLast = menu->itemAt(menu->count() - 1); + QTRY_VERIFY(!QQuickItemPrivate::get(menuItemFirst)->culled); + QTRY_VERIFY(!QQuickItemPrivate::get(menuItemLast)->culled); +} + QTEST_QUICKCONTROLS_MAIN(tst_QQuickMenu) #include "tst_qquickmenu.moc" |