diff options
author | Mitch Curtis <[email protected]> | 2024-03-14 11:36:06 +0800 |
---|---|---|
committer | Mitch Curtis <[email protected]> | 2024-04-17 15:05:01 +0800 |
commit | 822db20f84e188de0adb49741c751548d3c000ea (patch) | |
tree | fcb0d61de31ea91b9608642ca0c3ab81219364ac | |
parent | 55806207069a7014bde8785d7352e84f9e9f9406 (diff) |
Menu, MenuBar: remove requestNative and rely solely on app attributes
It was decided that we'll have two attributes:
- AA_DontUseNativeMenuBar
- AA_DontUseNativeMenuWindows
Setting AA_DontUseNativeMenuWindows only affects windows we create
(context menus, combobox menus, menus of non-native menu bars).
So, setting AA_DontUseNativeMenuWindows restores Qt to today's behavior.
But we can't control the windows of native menu bars, so if you don't
want those to be native, you have to set AA_DontUseNativeMenuBar just
like today.
By removing requestNative, we also effectively default to native menus
and menu bars, as the attributes are not set by default.
[ChangeLog][Controls][Important Behavior Changes] Menu and MenuBar
now use native menus by default on platforms where they're supported.
Task-number: QTBUG-69558
Change-Id: Ia917c2f820634def0cf815aa8ca8895ca79db75d
Reviewed-by: Richard Moe Gustavsen <[email protected]>
38 files changed, 304 insertions, 287 deletions
diff --git a/src/quicktemplates/qquickmenu.cpp b/src/quicktemplates/qquickmenu.cpp index c8677f43d6..70212bba7d 100644 --- a/src/quicktemplates/qquickmenu.cpp +++ b/src/quicktemplates/qquickmenu.cpp @@ -284,9 +284,6 @@ void QQuickMenuPrivate::init() { Q_Q(QQuickMenu); contentModel = new QQmlObjectModel(q); - - // TODO: use an env var until we get Qt::AA_DontUseNativeMenu - requestNative = qEnvironmentVariableIsSet("QT_QUICK_CONTROLS_USE_NATIVE_MENUS"); } QQuickMenu *QQuickMenuPrivate::rootMenu() const @@ -313,7 +310,7 @@ bool QQuickMenuPrivate::useNativeMenu() const if (QQuickMenuBarPrivate::get(menuBar)->useNativeMenuBar()) return true; } - return root->requestNative(); + return !QCoreApplication::testAttribute(Qt::AA_DontUseNativeMenuWindows); } QPlatformMenu *QQuickMenuPrivate::nativeHandle() @@ -440,10 +437,10 @@ void QQuickMenuPrivate::syncWithNativeMenu() qCDebug(lcNativeMenus) << "... finished syncing" << q; } -void QQuickMenuPrivate::syncWithRequestNative() +void QQuickMenuPrivate::syncWithUseNativeMenu() { Q_Q(QQuickMenu); - // Users can change requestNative on sub-menus and menus that are visible, + // Users can change AA_DontUseNativeMenuWindows while a menu is visible, // but the changes won't take affect until the menu is re-opened. if (q->isVisible() || parentMenu) return; @@ -1531,11 +1528,11 @@ void QQuickMenu::setVisible(bool visible) if (visible && ((d->useNativeMenu() && !d->maybeNativeHandle()) || (!d->useNativeMenu() && d->maybeNativeHandle()))) { // We've been made visible, and our actual native state doesn't match our requested state, - // which means requestNative was set while we were visible or had a parent. Try to sync our - // state again now that we're about to be re-opened. + // which means AA_DontUseNativeMenuWindows was set while we were visible or had a parent. + // Try to sync our state again now that we're about to be re-opened. qCDebug(lcNativeMenus) << "setVisible called - useNativeMenu:" << d->useNativeMenu() << "maybeNativeHandle:" << d->maybeNativeHandle(); - d->syncWithRequestNative(); + d->syncWithUseNativeMenu(); } if (d->maybeNativeHandle()) { d->setNativeMenuVisible(visible); @@ -1702,29 +1699,6 @@ void QQuickMenu::resetCascade() setCascade(shouldCascade()); } -bool QQuickMenu::requestNative() const -{ - Q_D(const QQuickMenu); - return d->requestNative; -} - -void QQuickMenu::setRequestNative(bool native) -{ - Q_D(QQuickMenu); - if (d->requestNative == native) - return; - - d->requestNative = native; - if (d->complete) - d->syncWithRequestNative(); - emit requestNativeChanged(); -} - -void QQuickMenu::resetRequestNative() -{ - setRequestNative(true); -} - /*! \since QtQuick.Controls 2.3 (Qt 5.10) \qmlproperty real QtQuick.Controls::Menu::overlap @@ -1991,7 +1965,7 @@ void QQuickMenu::componentComplete() Q_D(QQuickMenu); QQuickPopup::componentComplete(); d->resizeItems(); - d->syncWithRequestNative(); + d->syncWithUseNativeMenu(); } void QQuickMenu::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) diff --git a/src/quicktemplates/qquickmenu_p.h b/src/quicktemplates/qquickmenu_p.h index c4c79d450d..e45239f696 100644 --- a/src/quicktemplates/qquickmenu_p.h +++ b/src/quicktemplates/qquickmenu_p.h @@ -45,9 +45,6 @@ class Q_QUICKTEMPLATES2_EXPORT QQuickMenu : public QQuickPopup Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged FINAL REVISION(2, 3)) // 6.5 (Qt 6.5) Q_PROPERTY(QQuickIcon icon READ icon WRITE setIcon NOTIFY iconChanged FINAL REVISION(6, 5)) - // 6.8 - Q_PROPERTY(bool requestNative READ requestNative WRITE setRequestNative RESET resetRequestNative - NOTIFY requestNativeChanged REVISION(6, 8)) Q_CLASSINFO("DefaultProperty", "contentData") QML_NAMED_ELEMENT(Menu) QML_ADDED_IN_VERSION(2, 0) @@ -75,10 +72,6 @@ public: void setCascade(bool cascade); void resetCascade(); - bool requestNative() const; - void setRequestNative(bool native); - void resetRequestNative(); - qreal overlap() const; void setOverlap(qreal overlap); @@ -129,8 +122,6 @@ Q_SIGNALS: Q_REVISION(2, 3) void currentIndexChanged(); // 6.5 (Qt 6.5) Q_REVISION(6, 5) void iconChanged(const QQuickIcon &icon); - // 6.7 - Q_REVISION(6, 7) void requestNativeChanged(); protected: void timerEvent(QTimerEvent *event) override; diff --git a/src/quicktemplates/qquickmenu_p_p.h b/src/quicktemplates/qquickmenu_p_p.h index 1b4ba04c5c..8a8bbf834a 100644 --- a/src/quicktemplates/qquickmenu_p_p.h +++ b/src/quicktemplates/qquickmenu_p_p.h @@ -52,7 +52,7 @@ public: bool useNativeMenu() const; bool createNativeMenu(); void syncWithNativeMenu(); - void syncWithRequestNative(); + void syncWithUseNativeMenu(); static void recursivelyDestroyNativeSubMenus(QQuickMenu *menu); void setNativeMenuVisible(bool visible); @@ -120,7 +120,6 @@ public: QPalette defaultPalette() const override; bool cascade = false; - bool requestNative = false; bool triedToCreateNativeMenu = false; int hoverTimer = 0; int currentIndex = -1; diff --git a/src/quicktemplates/qquickmenubar.cpp b/src/quicktemplates/qquickmenubar.cpp index 4ca6faf5ee..7e3e282d45 100644 --- a/src/quicktemplates/qquickmenubar.cpp +++ b/src/quicktemplates/qquickmenubar.cpp @@ -448,7 +448,7 @@ QQuickMenu *QQuickMenuBarPrivate::takeMenu(int index) bool QQuickMenuBarPrivate::useNativeMenuBar() const { - return requestNative && !QCoreApplication::testAttribute(Qt::AA_DontUseNativeMenuBar); + return !QCoreApplication::testAttribute(Qt::AA_DontUseNativeMenuBar); } void QQuickMenuBarPrivate::syncNativeMenuBarVisible() @@ -458,6 +458,8 @@ void QQuickMenuBarPrivate::syncNativeMenuBarVisible() return; const bool shouldBeVisible = q->isVisible() && useNativeMenuBar(); + qCDebug(lcMenuBar) << "syncNativeMenuBarVisible called - q->isVisible()" << q->isVisible() + << "useNativeMenuBar()" << useNativeMenuBar() << "handle" << handle.get(); if (shouldBeVisible && !handle) createNativeMenuBar(); else if (!shouldBeVisible && handle) @@ -846,6 +848,7 @@ void QQuickMenuBar::itemChange(QQuickItem::ItemChange change, const QQuickItem:: } break; case ItemVisibleHasChanged: + qCDebug(lcMenuBar) << "visibility of" << this << "changed to" << isVisible(); d->syncNativeMenuBarVisible(); break; default: @@ -908,28 +911,6 @@ QAccessible::Role QQuickMenuBar::accessibleRole() const } #endif -bool QQuickMenuBar::requestNative() const -{ - return d_func()->requestNative; -} - -void QQuickMenuBar::setRequestNative(bool requestNative) -{ - Q_D(QQuickMenuBar); - if (d->requestNative == requestNative) - return; - - d->requestNative = requestNative; - d->syncNativeMenuBarVisible(); - - emit requestNativeChanged(); -} - -void QQuickMenuBar::resetRequestNative() -{ - setRequestNative(false); -} - QT_END_NAMESPACE #include "moc_qquickmenubar_p.cpp" diff --git a/src/quicktemplates/qquickmenubar_p.h b/src/quicktemplates/qquickmenubar_p.h index 9aba8f2e66..f053ff6b49 100644 --- a/src/quicktemplates/qquickmenubar_p.h +++ b/src/quicktemplates/qquickmenubar_p.h @@ -30,8 +30,6 @@ class Q_QUICKTEMPLATES2_EXPORT QQuickMenuBar : public QQuickContainer Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged FINAL) Q_PRIVATE_PROPERTY(QQuickMenuBar::d_func(), QQmlListProperty<QQuickMenu> menus READ menus NOTIFY menusChanged FINAL) Q_PRIVATE_PROPERTY(QQuickMenuBar::d_func(), QQmlListProperty<QObject> contentData READ contentData FINAL) - Q_PROPERTY(bool requestNative READ requestNative WRITE setRequestNative RESET resetRequestNative - NOTIFY requestNativeChanged REVISION(6, 8)) QML_NAMED_ELEMENT(MenuBar) QML_ADDED_IN_VERSION(2, 3) @@ -48,14 +46,9 @@ public: Q_INVOKABLE void removeMenu(QQuickMenu *menu); Q_INVOKABLE QQuickMenu *takeMenu(int index); - bool requestNative() const; - void setRequestNative(bool requestNative); - void resetRequestNative(); - Q_SIGNALS: void delegateChanged(); void menusChanged(); - void requestNativeChanged(); protected: bool eventFilter(QObject *object, QEvent *event) override; diff --git a/src/quicktemplates/qquickmenubar_p_p.h b/src/quicktemplates/qquickmenubar_p_p.h index 6b13719428..d31bc8f74e 100644 --- a/src/quicktemplates/qquickmenubar_p_p.h +++ b/src/quicktemplates/qquickmenubar_p_p.h @@ -88,7 +88,6 @@ public: bool triggering = false; bool altPressed = false; - bool requestNative = false; QQmlComponent *delegate = nullptr; QPointer<QQuickMenuBarItem> currentItem; QPointer<QQuickItem> windowContentItem; diff --git a/tests/auto/quickcontrols/controls/basic/tst_basic.cpp b/tests/auto/quickcontrols/controls/basic/tst_basic.cpp index 33417cca55..7e73bd2231 100644 --- a/tests/auto/quickcontrols/controls/basic/tst_basic.cpp +++ b/tests/auto/quickcontrols/controls/basic/tst_basic.cpp @@ -8,6 +8,9 @@ int main(int argc, char *argv[]) { QTEST_SET_MAIN_SOURCE_PATH qputenv("QML_NO_TOUCH_COMPRESSION", "1"); + // The tests were originally written before native menus existed, + // and some of them try to open menus, which we can't test natively. + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows); QQuickStyle::setStyle("Basic"); return quick_test_main(argc, argv, "tst_controls::Basic", TST_CONTROLS_DATA); } diff --git a/tests/auto/quickcontrols/controls/fusion/tst_fusion.cpp b/tests/auto/quickcontrols/controls/fusion/tst_fusion.cpp index 4485ca0c70..3c1f255d6e 100644 --- a/tests/auto/quickcontrols/controls/fusion/tst_fusion.cpp +++ b/tests/auto/quickcontrols/controls/fusion/tst_fusion.cpp @@ -8,6 +8,9 @@ int main(int argc, char *argv[]) { QTEST_SET_MAIN_SOURCE_PATH qputenv("QML_NO_TOUCH_COMPRESSION", "1"); + // The tests were originally written before native menus existed, + // and some of them try to open menus, which we can't test natively. + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows); QQuickStyle::setStyle("Fusion"); return quick_test_main(argc, argv, "tst_controls::Fusion", TST_CONTROLS_DATA); } diff --git a/tests/auto/quickcontrols/controls/imagine/tst_imagine.cpp b/tests/auto/quickcontrols/controls/imagine/tst_imagine.cpp index 54c363797b..ca9ff3fddd 100644 --- a/tests/auto/quickcontrols/controls/imagine/tst_imagine.cpp +++ b/tests/auto/quickcontrols/controls/imagine/tst_imagine.cpp @@ -8,6 +8,9 @@ int main(int argc, char *argv[]) { QTEST_SET_MAIN_SOURCE_PATH qputenv("QML_NO_TOUCH_COMPRESSION", "1"); + // The tests were originally written before native menus existed, + // and some of them try to open menus, which we can't test natively. + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows); QQuickStyle::setStyle("Imagine"); return quick_test_main(argc, argv, "tst_controls::Imagine", TST_CONTROLS_DATA); } diff --git a/tests/auto/quickcontrols/controls/ios/tst_ios.cpp b/tests/auto/quickcontrols/controls/ios/tst_ios.cpp index 11c6f35b0b..b34a580e3c 100644 --- a/tests/auto/quickcontrols/controls/ios/tst_ios.cpp +++ b/tests/auto/quickcontrols/controls/ios/tst_ios.cpp @@ -8,6 +8,9 @@ int main(int argc, char *argv[]) { QTEST_SET_MAIN_SOURCE_PATH qputenv("QML_NO_TOUCH_COMPRESSION", "1"); + // The tests were originally written before native menus existed, + // and some of them try to open menus, which we can't test natively. + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows); QQuickStyle::setStyle("iOS"); return quick_test_main(argc, argv, "tst_controls::iOS", TST_CONTROLS_DATA); } diff --git a/tests/auto/quickcontrols/controls/macos/tst_macos.cpp b/tests/auto/quickcontrols/controls/macos/tst_macos.cpp index 1ba0ebf587..91ce22cc0b 100644 --- a/tests/auto/quickcontrols/controls/macos/tst_macos.cpp +++ b/tests/auto/quickcontrols/controls/macos/tst_macos.cpp @@ -10,6 +10,9 @@ int main(int argc, char *argv[]) qputenv("QML_NO_TOUCH_COMPRESSION", "1"); // See comment in tst_windows.cpp. qputenv("QT_QUICK_CONTROLS_IGNORE_CUSTOMIZATION_WARNINGS", "1"); + // The tests were originally written before native menus existed, + // and some of them try to open menus, which we can't test natively. + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows); QQuickStyle::setStyle("macOS"); return quick_test_main(argc, argv, "tst_controls::macOS", TST_CONTROLS_DATA); } diff --git a/tests/auto/quickcontrols/controls/material/tst_material.cpp b/tests/auto/quickcontrols/controls/material/tst_material.cpp index 782397a592..9a76046d23 100644 --- a/tests/auto/quickcontrols/controls/material/tst_material.cpp +++ b/tests/auto/quickcontrols/controls/material/tst_material.cpp @@ -8,6 +8,9 @@ int main(int argc, char *argv[]) { QTEST_SET_MAIN_SOURCE_PATH qputenv("QML_NO_TOUCH_COMPRESSION", "1"); + // The tests were originally written before native menus existed, + // and some of them try to open menus, which we can't test natively. + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows); QQuickStyle::setStyle("Material"); return quick_test_main(argc, argv, "tst_controls::Material", TST_CONTROLS_DATA); } diff --git a/tests/auto/quickcontrols/controls/universal/tst_universal.cpp b/tests/auto/quickcontrols/controls/universal/tst_universal.cpp index 2d9e687bea..3cd41be836 100644 --- a/tests/auto/quickcontrols/controls/universal/tst_universal.cpp +++ b/tests/auto/quickcontrols/controls/universal/tst_universal.cpp @@ -8,6 +8,9 @@ int main(int argc, char *argv[]) { QTEST_SET_MAIN_SOURCE_PATH qputenv("QML_NO_TOUCH_COMPRESSION", "1"); + // The tests were originally written before native menus existed, + // and some of them try to open menus, which we can't test natively. + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows); QQuickStyle::setStyle("Universal"); return quick_test_main(argc, argv, "tst_controls::Universal", TST_CONTROLS_DATA); } diff --git a/tests/auto/quickcontrols/controls/windows/tst_windows.cpp b/tests/auto/quickcontrols/controls/windows/tst_windows.cpp index 221ff116dd..bcd8fa35d8 100644 --- a/tests/auto/quickcontrols/controls/windows/tst_windows.cpp +++ b/tests/auto/quickcontrols/controls/windows/tst_windows.cpp @@ -17,6 +17,9 @@ int main(int argc, char *argv[]) // issued when default-constructing controls. For that we have // tst_customization::noCustomizationWarningsForDefaultControls. qputenv("QT_QUICK_CONTROLS_IGNORE_CUSTOMIZATION_WARNINGS", "1"); + // The tests were originally written before native menus existed, + // and some of them try to open menus, which we can't test natively. + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows); QQuickStyle::setStyle("Windows"); return quick_test_main(argc, argv, "tst_controls::Windows", TST_CONTROLS_DATA); } diff --git a/tests/auto/quickcontrols/focus/tst_focus.cpp b/tests/auto/quickcontrols/focus/tst_focus.cpp index c6a82ebaba..5b9326b7af 100644 --- a/tests/auto/quickcontrols/focus/tst_focus.cpp +++ b/tests/auto/quickcontrols/focus/tst_focus.cpp @@ -52,6 +52,7 @@ tst_focus::tst_focus() void tst_focus::initTestCase() { + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows); QQuickStyle::setStyle("Basic"); QQmlDataTest::initTestCase(); } diff --git a/tests/auto/quickcontrols/qquickapplicationwindow/tst_qquickapplicationwindow.cpp b/tests/auto/quickcontrols/qquickapplicationwindow/tst_qquickapplicationwindow.cpp index ff0b4418d2..5f1c877ab7 100644 --- a/tests/auto/quickcontrols/qquickapplicationwindow/tst_qquickapplicationwindow.cpp +++ b/tests/auto/quickcontrols/qquickapplicationwindow/tst_qquickapplicationwindow.cpp @@ -58,6 +58,8 @@ private slots: tst_QQuickApplicationWindow::tst_QQuickApplicationWindow() : QQmlDataTest(QT_QMLTEST_DATADIR) { + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows); + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar); QQuickStyle::setStyle("Basic"); } diff --git a/tests/auto/quickcontrols/qquickmaterialstyle/tst_qquickmaterialstyle.cpp b/tests/auto/quickcontrols/qquickmaterialstyle/tst_qquickmaterialstyle.cpp index 783c5499c8..48a3e2138a 100644 --- a/tests/auto/quickcontrols/qquickmaterialstyle/tst_qquickmaterialstyle.cpp +++ b/tests/auto/quickcontrols/qquickmaterialstyle/tst_qquickmaterialstyle.cpp @@ -2,4 +2,18 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QtQuickTest/quicktest.h> -QUICK_TEST_MAIN(tst_qquickmaterialstyle) + +class Setup : public QObject +{ + Q_OBJECT + +public slots: + void applicationAvailable() + { + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows); + } +}; + +QUICK_TEST_MAIN_WITH_SETUP(tst_qquickmaterialstyle, Setup) + +#include "tst_qquickmaterialstyle.moc" diff --git a/tests/auto/quickcontrols/qquickmenu/data/nativeDynamicSubmenus.qml b/tests/auto/quickcontrols/qquickmenu/data/nativeDynamicSubmenus.qml index b82091b740..c0326fb511 100644 --- a/tests/auto/quickcontrols/qquickmenu/data/nativeDynamicSubmenus.qml +++ b/tests/auto/quickcontrols/qquickmenu/data/nativeDynamicSubmenus.qml @@ -47,6 +47,5 @@ ApplicationWindow { Menu { id: contextMenu objectName: "menu" - requestNative: true } } diff --git a/tests/auto/quickcontrols/qquickmenu/data/nativeEmptyMenu.qml b/tests/auto/quickcontrols/qquickmenu/data/nativeEmptyMenu.qml index f5573a1e32..f1d4f33625 100644 --- a/tests/auto/quickcontrols/qquickmenu/data/nativeEmptyMenu.qml +++ b/tests/auto/quickcontrols/qquickmenu/data/nativeEmptyMenu.qml @@ -46,6 +46,5 @@ ApplicationWindow { Menu { id: contextMenu objectName: "menu" - requestNative: true } } diff --git a/tests/auto/quickcontrols/qquickmenu/data/nativeMenuSeparator.qml b/tests/auto/quickcontrols/qquickmenu/data/nativeMenuSeparator.qml index 1d2a0d5b73..a32d94bb6b 100644 --- a/tests/auto/quickcontrols/qquickmenu/data/nativeMenuSeparator.qml +++ b/tests/auto/quickcontrols/qquickmenu/data/nativeMenuSeparator.qml @@ -13,7 +13,6 @@ ApplicationWindow { Menu { id: contextMenu objectName: "menu" - requestNative: true Action { objectName: text diff --git a/tests/auto/quickcontrols/qquickmenu/data/nativeMixedItems.qml b/tests/auto/quickcontrols/qquickmenu/data/nativeMixedItems.qml index 80dd8fca27..3e6e851bb3 100644 --- a/tests/auto/quickcontrols/qquickmenu/data/nativeMixedItems.qml +++ b/tests/auto/quickcontrols/qquickmenu/data/nativeMixedItems.qml @@ -36,7 +36,6 @@ ApplicationWindow { Menu { id: contextMenu objectName: "menu" - requestNative: true Action { objectName: text diff --git a/tests/auto/quickcontrols/qquickmenu/data/nativeStatic.qml b/tests/auto/quickcontrols/qquickmenu/data/nativeStatic.qml index 0d5b85441f..f9ff438811 100644 --- a/tests/auto/quickcontrols/qquickmenu/data/nativeStatic.qml +++ b/tests/auto/quickcontrols/qquickmenu/data/nativeStatic.qml @@ -14,7 +14,6 @@ ApplicationWindow { Menu { id: contextMenu objectName: "menu" - requestNative: true Action { objectName: text @@ -36,7 +35,6 @@ ApplicationWindow { title: "subMenu" objectName: title // TODO: remove me when the defaults are true - requestNative: true Action { objectName: text diff --git a/tests/auto/quickcontrols/qquickmenu/tst_qquickmenu.cpp b/tests/auto/quickcontrols/qquickmenu/tst_qquickmenu.cpp index 3a1a3a47a1..f35baffa21 100644 --- a/tests/auto/quickcontrols/qquickmenu/tst_qquickmenu.cpp +++ b/tests/auto/quickcontrols/qquickmenu/tst_qquickmenu.cpp @@ -46,6 +46,8 @@ public: tst_QQuickMenu(); private slots: + void init(); + void defaults(); void count(); void mouse(); @@ -98,7 +100,7 @@ private slots: void nativeDynamicActions(); void nativeDynamicSubmenus(); void nativeMenuSeparator(); - void requestNativeChanges(); + void dontUseNativeMenuWindowsChanges(); void nativeMixedItems(); private: @@ -123,6 +125,16 @@ tst_QQuickMenu::tst_QQuickMenu() nativeMenuSupported = platformMenu != nullptr; } +void tst_QQuickMenu::init() +{ + QQmlDataTest::init(); + + // By default we don't want to use native menus, as the majority of the tests + // were written before they were a thing. We instead explicitly set it where necessary. + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows); + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar); +} + bool tst_QQuickMenu::hasWindowActivation() { return (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)); @@ -2189,6 +2201,7 @@ void tst_QQuickMenu::invalidUrlInImgTag() void tst_QQuickMenu::nativeStatic() { + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows, false); QQuickControlsApplicationHelper helper(this, QLatin1String("nativeStatic.qml")); QVERIFY2(helper.ready, helper.failureMessage()); QQuickApplicationWindow *window = helper.appWindow; @@ -2197,8 +2210,8 @@ void tst_QQuickMenu::nativeStatic() QQuickMenu *contextMenu = window->property("contextMenu").value<QQuickMenu*>(); QVERIFY(contextMenu); - QVERIFY(contextMenu->requestNative()); auto *contextMenuPrivate = QQuickMenuPrivate::get(contextMenu); + QVERIFY(contextMenuPrivate->useNativeMenu()); // Check that the actions of the parent menu can be accessed // and are in the appropriate places in contentModel and contentData. @@ -2232,6 +2245,7 @@ void tst_QQuickMenu::nativeStatic() void tst_QQuickMenu::nativeDynamicActions() { + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows, false); QQuickControlsApplicationHelper helper(this, QLatin1String("nativeEmptyMenu.qml")); QVERIFY2(helper.ready, helper.failureMessage()); QQuickApplicationWindow *window = helper.appWindow; @@ -2291,6 +2305,7 @@ void tst_QQuickMenu::nativeDynamicActions() void tst_QQuickMenu::nativeDynamicSubmenus() { + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows, false); QQuickControlsApplicationHelper helper(this, QLatin1String("nativeDynamicSubmenus.qml")); QVERIFY2(helper.ready, helper.failureMessage()); QQuickApplicationWindow *window = helper.appWindow; @@ -2398,6 +2413,7 @@ void tst_QQuickMenu::nativeDynamicSubmenus() void tst_QQuickMenu::nativeMenuSeparator() { + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows, false); QQuickControlsApplicationHelper helper(this, QLatin1String("nativeMenuSeparator.qml")); QVERIFY2(helper.ready, helper.failureMessage()); QQuickApplicationWindow *window = helper.appWindow; @@ -2435,8 +2451,12 @@ void tst_QQuickMenu::nativeMenuSeparator() } } -void tst_QQuickMenu::requestNativeChanges() +void tst_QQuickMenu::dontUseNativeMenuWindowsChanges() { + if (QSysInfo::productType() == QLatin1String("b2qt")) + QSKIP("b2qt doesn't support native menus"); + + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows, false); QQuickControlsApplicationHelper helper(this, QLatin1String("nativeStatic.qml")); QVERIFY2(helper.ready, helper.failureMessage()); QQuickApplicationWindow *window = helper.appWindow; @@ -2445,9 +2465,8 @@ void tst_QQuickMenu::requestNativeChanges() QQuickMenu *contextMenu = window->property("contextMenu").value<QQuickMenu*>(); QVERIFY(contextMenu); - QVERIFY(contextMenu->requestNative()); QCOMPARE(contextMenu->count(), 3); - // Sub-menus should respect the value of requestNative of their parents. + // Sub-menus should respect the native-ness of their parents. auto *subMenu = contextMenu->menuAt(2); auto *subMenuPrivate = QQuickMenuPrivate::get(subMenu); QVERIFY(subMenuPrivate->useNativeMenu()); @@ -2472,12 +2491,12 @@ void tst_QQuickMenu::requestNativeChanges() QVERIFY(contextMenuPrivate->handle); else QVERIFY(!contextMenuPrivate->handle); - contextMenu->setRequestNative(false); - QVERIFY(!contextMenu->requestNative()); + + // We need to wait until the menu is opened before it picks up the changes, + // which is why we don't check the native handle here yet. + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows); QVERIFY(!contextMenuPrivate->useNativeMenu()); - QVERIFY(!contextMenuPrivate->handle); QVERIFY(!subMenuPrivate->useNativeMenu()); - QVERIFY(!subMenuPrivate->handle); // Check that we can open the menu by right-clicking (or just open it manually // if the platform doesn't support (moving) QCursor). @@ -2505,6 +2524,9 @@ void tst_QQuickMenu::requestNativeChanges() QVERIFY(contextMenu->isVisible()); QTRY_VERIFY(contextMenu->isOpened()); QCOMPARE(aboutToShowSpy.size(), 1); + // Now that it's open and has picked up the changes to Qt::AA_DontUseNativeMenuWindows, we can check it. + QVERIFY(!contextMenuPrivate->handle); + QVERIFY(!subMenuPrivate->handle); // Check that it opened at the mouse cursor and actually has menu items. QCOMPARE(contextMenu->x(), cursorPos.x()); QCOMPARE(contextMenu->y(), cursorPos.y()); @@ -2512,10 +2534,10 @@ void tst_QQuickMenu::requestNativeChanges() QVERIFY(action1MenuItem); QCOMPARE(action1MenuItem->text(), "action1"); - // Test setting requestNative while visible has no effect (until it's re-opened, which we can't - // test because we can't test opening native menus). - contextMenu->setRequestNative(true); - QVERIFY(contextMenu->requestNative()); + // Test setting Qt::AA_DontUseNativeMenuWindows while visible has no effect + // (until it's re-opened, which we can't test because we can't test opening native menus). + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows, false); + QVERIFY(contextMenuPrivate->useNativeMenu()); QVERIFY(!contextMenuPrivate->handle); QVERIFY(!subMenuPrivate->handle); @@ -2535,23 +2557,16 @@ void tst_QQuickMenu::requestNativeChanges() // Although we can't open the native menu, we can at least check that // attempting (the changes won't come into effect until it's re-opened) // to make the menu native again doesn't e.g. crash. - contextMenu->setRequestNative(true); QVERIFY(contextMenuPrivate->useNativeMenu()); QVERIFY(subMenuPrivate->useNativeMenu()); QVERIFY(!contextMenuPrivate->handle); QVERIFY(!subMenuPrivate->handle); - - // Check that setting requestNative has no (immediate) effect on a sub-menu. - subMenu->setRequestNative(false); - // Its parent still is still requesting to be native, otherwise this would be false. - QVERIFY(subMenuPrivate->useNativeMenu()); - QVERIFY(!subMenuPrivate->requestNative); - QVERIFY(!subMenuPrivate->handle); } // Check that non-menu items (e.g. Rectangles) can be inserted between menu items without issues. void tst_QQuickMenu::nativeMixedItems() { + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows, false); QQuickControlsApplicationHelper helper(this, QLatin1String("nativeMixedItems.qml")); QVERIFY2(helper.ready, helper.failureMessage()); QQuickApplicationWindow *window = helper.appWindow; @@ -2560,7 +2575,6 @@ void tst_QQuickMenu::nativeMixedItems() QQuickMenu *contextMenu = window->property("contextMenu").value<QQuickMenu*>(); QVERIFY(contextMenu); - QVERIFY(contextMenu->requestNative()); // Insert a Rectangle between the Action and MenuItem in the top-level menu. QVERIFY(QMetaObject::invokeMethod(window, "insertRectangle", diff --git a/tests/auto/quickcontrols/qquickmenubar/data/menubarAsHeader.qml b/tests/auto/quickcontrols/qquickmenubar/data/menubarAsHeader.qml index dc25499e98..3261ca4b59 100644 --- a/tests/auto/quickcontrols/qquickmenubar/data/menubarAsHeader.qml +++ b/tests/auto/quickcontrols/qquickmenubar/data/menubarAsHeader.qml @@ -6,7 +6,6 @@ import QtQuick.Controls ApplicationWindow { id: root - property bool requestNative: false property bool menuBarVisible: true property alias fileMenu: fileMenu property alias contents: contents @@ -16,7 +15,6 @@ ApplicationWindow { visible: true header: MenuBar { - requestNative: root.requestNative visible: root.menuBarVisible Menu { id: fileMenu diff --git a/tests/auto/quickcontrols/qquickmenubar/data/menubaritems.qml b/tests/auto/quickcontrols/qquickmenubar/data/menubaritems.qml index a7d20571ee..d7b628afea 100644 --- a/tests/auto/quickcontrols/qquickmenubar/data/menubaritems.qml +++ b/tests/auto/quickcontrols/qquickmenubar/data/menubaritems.qml @@ -7,7 +7,6 @@ import QtQuick.Controls ApplicationWindow { id: root readonly property Button oopsButton: oopsButton - property bool requestNative: false property alias fileMenu: fileMenu width: 400 @@ -15,7 +14,6 @@ ApplicationWindow { visible: true menuBar: MenuBar { - requestNative: root.requestNative MenuBarItem { menu: Menu { id: fileMenu diff --git a/tests/auto/quickcontrols/qquickmenubar/data/menus.qml b/tests/auto/quickcontrols/qquickmenubar/data/menus.qml index 15ddfe7a8a..947beb50fb 100644 --- a/tests/auto/quickcontrols/qquickmenubar/data/menus.qml +++ b/tests/auto/quickcontrols/qquickmenubar/data/menus.qml @@ -6,7 +6,6 @@ import QtQuick.Controls ApplicationWindow { id: root - property bool requestNative: false property bool menuBarVisible: true property alias fileMenu: fileMenu property alias contents: contents @@ -16,7 +15,6 @@ ApplicationWindow { visible: true menuBar: MenuBar { - requestNative: root.requestNative visible: root.menuBarVisible Menu { id: fileMenu diff --git a/tests/auto/quickcontrols/qquickmenubar/data/mixed.qml b/tests/auto/quickcontrols/qquickmenubar/data/mixed.qml index ced13e7402..25dbf01e15 100644 --- a/tests/auto/quickcontrols/qquickmenubar/data/mixed.qml +++ b/tests/auto/quickcontrols/qquickmenubar/data/mixed.qml @@ -6,7 +6,6 @@ import QtQuick.Controls ApplicationWindow { id: root - property bool requestNative: false property bool menuBarVisible: true property alias fileMenu: fileMenu property alias contents: contents @@ -16,7 +15,6 @@ ApplicationWindow { visible: true menuBar: MenuBar { - requestNative: root.requestNative visible: root.menuBarVisible Menu { id: fileMenu diff --git a/tests/auto/quickcontrols/qquickmenubar/tst_qquickmenubar.cpp b/tests/auto/quickcontrols/qquickmenubar/tst_qquickmenubar.cpp index 8313d07550..d8694e0421 100644 --- a/tests/auto/quickcontrols/qquickmenubar/tst_qquickmenubar.cpp +++ b/tests/auto/quickcontrols/qquickmenubar/tst_qquickmenubar.cpp @@ -50,8 +50,6 @@ private slots: void addRemoveExistingMenus(); void checkHighlightWhenMenuDismissed(); void hoverAfterClosingWithEscape(); - void requestNative_data(); - void requestNative(); void AA_DontUseNativeMenuBar(); void containerItems_data(); void containerItems(); @@ -89,7 +87,7 @@ bool tst_qquickmenubar::hasWindowActivation() void tst_qquickmenubar::init() { // Enable non-native menubars by default. - // Note that the AA_DontUseNativeMenuBar test will set this property to 'true', which + // Note that some tests will set this property to 'true', which // is why we need to set it back to 'false' here. QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, false); } @@ -109,6 +107,9 @@ void tst_qquickmenubar::delegate() void tst_qquickmenubar::mouse() { + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar); + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows); + if (!hasWindowActivation()) QSKIP("Window activation is not supported"); @@ -294,6 +295,8 @@ void tst_qquickmenubar::mouse() // - It's what happens with e.g. overflow menus on Android. void tst_qquickmenubar::touch() { + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar); + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows); QQuickControlsApplicationHelper helper(this, QLatin1String("touch.qml")); QVERIFY2(helper.ready, helper.failureMessage()); centerOnScreen(helper.window); @@ -321,6 +324,8 @@ void tst_qquickmenubar::touch() void tst_qquickmenubar::keys() { + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar); + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows); if (!hasWindowActivation()) QSKIP("Window activation is not supported"); @@ -513,6 +518,8 @@ void tst_qquickmenubar::keys() void tst_qquickmenubar::mnemonics() { + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar); + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows); if (!hasWindowActivation()) QSKIP("Window activation is not supported"); @@ -666,6 +673,8 @@ void tst_qquickmenubar::mnemonics() void tst_qquickmenubar::altNavigation() { + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar); + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows); if (!QGuiApplicationPrivate::platformTheme()->themeHint(QPlatformTheme::MenuBarFocusOnAltPressRelease).toBool()) QSKIP("Menu doesn't get focus via Alt press&release on this platform"); @@ -706,7 +715,7 @@ void tst_qquickmenubar::altNavigation() void tst_qquickmenubar::addRemove_data() { QTest::addColumn<QString>("testUrl"); - QTest::addColumn<bool>("requestNative"); + QTest::addColumn<bool>("native"); QTest::newRow("menuitems, not native") << QStringLiteral("empty.qml") << false; QTest::newRow("menuitems, native") << QStringLiteral("empty.qml") << true; } @@ -714,17 +723,17 @@ void tst_qquickmenubar::addRemove_data() void tst_qquickmenubar::addRemove() { QFETCH(QString, testUrl); - QFETCH(bool, requestNative); + QFETCH(bool, native); + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, !native); QQmlApplicationEngine engine; - engine.setInitialProperties({{ "requestNative", requestNative }}); engine.load(testFileUrl(testUrl)); QQuickMenuBar *menuBar = qobject_cast<QQuickMenuBar *>(engine.rootObjects().value(0)); QVERIFY(menuBar); QQuickMenuBarPrivate *menuBarPrivate = QQuickMenuBarPrivate::get(menuBar); - QCOMPARE(menuBar->requestNative(), requestNative); - if (requestNative && nativeMenuBarSupported) + QCOMPARE(menuBarPrivate->useNativeMenuBar(), native); + if (native && nativeMenuBarSupported) QVERIFY(menuBarPrivate->nativeHandle()); QQmlComponent component(&engine); @@ -795,7 +804,7 @@ void tst_qquickmenubar::addRemove() void tst_qquickmenubar::addRemoveInlineMenus_data() { - QTest::addColumn<bool>("requestNative"); + QTest::addColumn<bool>("native"); QTest::newRow("not native") << false; QTest::newRow("native") << true; } @@ -806,10 +815,10 @@ void tst_qquickmenubar::addRemoveInlineMenus() // is an inline child from QML (fileMenu). Since it's owned by // JavaScript, it should be deleted by the gc when appropriate, and // not upon a call to removeMenu. - QFETCH(bool, requestNative); + QFETCH(bool, native); + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, !native); QQmlApplicationEngine engine; - engine.setInitialProperties({{ "requestNative", requestNative }}); engine.load(testFileUrl("menus.qml")); auto window = qobject_cast<QQuickApplicationWindow *>(engine.rootObjects().value(0)); @@ -840,7 +849,7 @@ void tst_qquickmenubar::addRemoveInlineMenus() void tst_qquickmenubar::addRemoveMenuFromQml_data() { - QTest::addColumn<bool>("requestNative"); + QTest::addColumn<bool>("native"); QTest::newRow("not native") << false; QTest::newRow("native") << true; } @@ -850,10 +859,10 @@ void tst_qquickmenubar::addRemoveMenuFromQml() // Create a menu dynamically from QML, and add it to // the menubar. Remove it again. Check that the // garbage collector will then destruct it. - QFETCH(bool, requestNative); + QFETCH(bool, native); + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, !native); QQmlApplicationEngine engine; - engine.setInitialProperties({{ "requestNative", requestNative }}); engine.load(testFileUrl("menus.qml")); auto window = qobject_cast<QQuickApplicationWindow *>(engine.rootObjects().value(0)); @@ -890,17 +899,17 @@ void tst_qquickmenubar::addRemoveMenuFromQml() void tst_qquickmenubar::insert_data() { - QTest::addColumn<bool>("requestNative"); + QTest::addColumn<bool>("native"); QTest::newRow("not native") << false; QTest::newRow("native") << true; } void tst_qquickmenubar::insert() { - QFETCH(bool, requestNative); + QFETCH(bool, native); + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, !native); QQmlApplicationEngine engine; - engine.setInitialProperties({{ "requestNative", requestNative }}); engine.load(testFileUrl("menus.qml")); QScopedPointer<QQuickApplicationWindow> window(qobject_cast<QQuickApplicationWindow *>(engine.rootObjects().value(0))); @@ -932,8 +941,9 @@ void tst_qquickmenubar::removeMenuThatIsOpen() // Check that if we remove a menu that is open, it ends // up being hidden / closed. This is mostly important for // non-native menubars. + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar); + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows); QQmlApplicationEngine engine; - engine.setInitialProperties({{ "requestNative", false }}); engine.load(testFileUrl("menus.qml")); QScopedPointer<QQuickApplicationWindow> window(qobject_cast<QQuickApplicationWindow *>(engine.rootObjects().value(0))); @@ -952,7 +962,7 @@ void tst_qquickmenubar::removeMenuThatIsOpen() void tst_qquickmenubar::addRemoveExistingMenus_data() { - QTest::addColumn<bool>("requestNative"); + QTest::addColumn<bool>("native"); QTest::newRow("not native") << false; QTest::newRow("native") << true; } @@ -961,10 +971,10 @@ void tst_qquickmenubar::addRemoveExistingMenus() { // Check that you get warnings if trying to add menus that // are already in the menubar, or remove menus that are not. - QFETCH(bool, requestNative); + QFETCH(bool, native); + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, !native); QQmlApplicationEngine engine; - engine.setInitialProperties({{ "requestNative", requestNative }}); engine.load(testFileUrl("menus.qml")); auto window = qobject_cast<QQuickApplicationWindow *>(engine.rootObjects().value(0)); @@ -987,6 +997,8 @@ void tst_qquickmenubar::addRemoveExistingMenus() void tst_qquickmenubar::checkHighlightWhenMenuDismissed() { + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar); + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows); if ((QGuiApplication::platformName() == QLatin1String("offscreen")) || (QGuiApplication::platformName() == QLatin1String("minimal"))) QSKIP("Mouse highlight not functional on offscreen/minimal platforms"); @@ -1045,6 +1057,8 @@ void tst_qquickmenubar::checkHighlightWhenMenuDismissed() void tst_qquickmenubar::hoverAfterClosingWithEscape() { + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar); + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows); if ((QGuiApplication::platformName() == QLatin1String("offscreen")) || (QGuiApplication::platformName() == QLatin1String("minimal"))) QSKIP("Mouse highlight not functional on offscreen/minimal platforms"); @@ -1077,47 +1091,12 @@ void tst_qquickmenubar::hoverAfterClosingWithEscape() QVERIFY(!secondMenu->isVisible()); } -void tst_qquickmenubar::requestNative_data() -{ - QTest::addColumn<QString>("testUrl"); - QTest::addColumn<bool>("requestNative"); - QTest::newRow("menuitems, not native") << QStringLiteral("menubaritems.qml") << false; - QTest::newRow("menuitems, native") << QStringLiteral("menubaritems.qml") << true; - QTest::newRow("menus, not native") << QStringLiteral("menus.qml") << false; - QTest::newRow("menus, native") << QStringLiteral("menus.qml") << true; -} - -void tst_qquickmenubar::requestNative() -{ - QFETCH(QString, testUrl); - QFETCH(bool, requestNative); - - QQmlApplicationEngine engine; - engine.setInitialProperties({{ "requestNative", requestNative }}); - engine.load(testFileUrl(testUrl)); - - QScopedPointer<QQuickApplicationWindow> window(qobject_cast<QQuickApplicationWindow *>(engine.rootObjects().value(0))); - QVERIFY(window); - QQuickMenuBar *menuBar = window->property("menuBar").value<QQuickMenuBar *>(); - QVERIFY(menuBar); - - QCOMPARE(menuBar->requestNative(), requestNative); - - QQuickMenu *fileMenu = window->property("fileMenu").value<QQuickMenu *>(); - QVERIFY(fileMenu); - QVERIFY(!fileMenu->requestNative()); - - QQuickMenuPrivate *fileMenuPriv = QQuickMenuPrivate::get(fileMenu); - QCOMPARE(fileMenuPriv->useNativeMenu(), requestNative); -} - void tst_qquickmenubar::AA_DontUseNativeMenuBar() { - // Check that we end up with a non-native menu bar when - // AA_DontUseNativeMenuBar is set, even if requestNative is true. + // Check that we end up with a non-native menu bar when AA_DontUseNativeMenuBar is set. QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar); + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows); QQmlApplicationEngine engine; - engine.setInitialProperties({{ "requestNative", true }}); engine.load(testFileUrl("menus.qml")); QScopedPointer<QQuickApplicationWindow> window(qobject_cast<QQuickApplicationWindow *>(engine.rootObjects().value(0))); @@ -1138,7 +1117,7 @@ void tst_qquickmenubar::AA_DontUseNativeMenuBar() void tst_qquickmenubar::containerItems_data() { QTest::addColumn<QString>("testUrl"); - QTest::addColumn<bool>("requestNative"); + QTest::addColumn<bool>("native"); QTest::newRow("menuitems, not native") << QStringLiteral("menubaritems.qml") << false; QTest::newRow("menuitems, native") << QStringLiteral("menubaritems.qml") << true; QTest::newRow("menus, not native") << QStringLiteral("menus.qml") << false; @@ -1153,17 +1132,18 @@ void tst_qquickmenubar::containerItems() // of accessing those MenuBarItems and menus in the MenuBar // API, so check that all end up in sync. QFETCH(QString, testUrl); - QFETCH(bool, requestNative); + QFETCH(bool, native); + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, !native); QQmlApplicationEngine engine; - engine.setInitialProperties({{ "requestNative", requestNative }}); engine.load(testFileUrl(testUrl)); QScopedPointer<QQuickApplicationWindow> window(qobject_cast<QQuickApplicationWindow *>(engine.rootObjects().value(0))); QVERIFY(window); QQuickMenuBar *menuBar = window->property("menuBar").value<QQuickMenuBar *>(); QVERIFY(menuBar); - QCOMPARE(menuBar->requestNative(), requestNative); + auto *menuBarPrivate = QQuickMenuBarPrivate::get(menuBar); + QCOMPARE(menuBarPrivate->useNativeMenuBar(), native); QCOMPARE(menuBar->count(), 4); for (int i = 0; i < menuBar->count(); ++i) { @@ -1178,7 +1158,7 @@ void tst_qquickmenubar::containerItems() QCOMPARE(menuBarItem->menu(), menu); // Test the "contentData" list property API - auto cd = QQuickMenuBarPrivate::get(menuBar)->contentData(); + auto cd = menuBarPrivate->contentData(); QCOMPARE(cd.count(&cd), menuBar->count()); auto cdItem = static_cast<QQuickItem *>(cd.at(&cd, i)); QVERIFY(cdItem); @@ -1197,7 +1177,7 @@ void tst_qquickmenubar::containerItems() void tst_qquickmenubar::mixedContainerItems_data() { - QTest::addColumn<bool>("requestNative"); + QTest::addColumn<bool>("native"); QTest::newRow("not native") << false; QTest::newRow("native") << true; } @@ -1207,10 +1187,10 @@ void tst_qquickmenubar::mixedContainerItems() // The application is allowed to add items other // than MenuBarItems and Menus as children. But those // should just be ignored by the MenuBar (and the Container). - QFETCH(bool, requestNative); + QFETCH(bool, native); + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, !native); QQmlApplicationEngine engine; - engine.setInitialProperties({{ "requestNative", requestNative }}); engine.load(testFileUrl("mixed.qml")); QScopedPointer<QQuickApplicationWindow> window(qobject_cast<QQuickApplicationWindow *>(engine.rootObjects().value(0))); @@ -1262,8 +1242,8 @@ void tst_qquickmenubar::mixedContainerItems() void tst_qquickmenubar::applicationWindow_data() { - QTest::addColumn<bool>("initialRequestNative"); - QTest::addColumn<bool>("initialVisible"); + QTest::addColumn<bool>("initiallyNative"); + QTest::addColumn<bool>("initiallyVisible"); QTest::newRow("initially not native, visible") << false << true; QTest::newRow("initially not native, hidden") << false << false; QTest::newRow("initially native, visible") << true << true; @@ -1273,13 +1253,14 @@ void tst_qquickmenubar::applicationWindow_data() void tst_qquickmenubar::applicationWindow() { // Check that ApplicationWindow adds or removes the non-native - // menubar in response to toggling MenuBar.requestNative and + // menubar in response to toggling Qt::AA_DontUseNativeMenuBar and // MenuBar.visible. - QFETCH(bool, initialRequestNative); - QFETCH(bool, initialVisible); + QFETCH(bool, initiallyNative); + QFETCH(bool, initiallyVisible); + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, !initiallyNative); QQmlApplicationEngine engine; - engine.setInitialProperties({{ "requestNative", initialRequestNative }, { "visible", initialVisible }}); + engine.setInitialProperties({{ "visible", initiallyVisible }}); engine.load(testFileUrl("menus.qml")); QPointer<QQuickApplicationWindow> window(qobject_cast<QQuickApplicationWindow *>(engine.rootObjects().value(0))); @@ -1290,13 +1271,11 @@ void tst_qquickmenubar::applicationWindow() QQuickItem *contents = window->property("contents").value<QQuickItem *>(); QVERIFY(contents); - for (const bool visible : {initialVisible, !initialVisible, initialVisible}) - for (const bool requestNative : {initialRequestNative, !initialRequestNative, initialRequestNative}) { - menuBar->setRequestNative(requestNative); + for (const bool visible : {initiallyVisible, !initiallyVisible, initiallyVisible}) { menuBar->setVisible(visible); const bool nativeMenuBarVisible = bool(menuBarPrivate->nativeHandle()); - QCOMPARE(nativeMenuBarVisible, nativeMenuBarSupported && requestNative && visible); + QCOMPARE(nativeMenuBarVisible, nativeMenuBarSupported && initiallyNative && visible); if (!visible) { QVERIFY(!menuBar->isVisible()); @@ -1315,7 +1294,7 @@ void tst_qquickmenubar::applicationWindow() void tst_qquickmenubar::menubarAsHeader_data() { - QTest::addColumn<bool>("requestNative"); + QTest::addColumn<bool>("native"); QTest::newRow("not native") << false; QTest::newRow("native") << true; } @@ -1325,10 +1304,10 @@ void tst_qquickmenubar::menubarAsHeader() // ApplicationWindow.menuBar was added in Qt 5.10. Before that // the menuBar was supposed to be assigned to ApplicationWindow.header. // For backwards compatibility, check that you can still do that. - QFETCH(bool, requestNative); + QFETCH(bool, native); + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, !native); QQmlApplicationEngine engine; - engine.setInitialProperties({{ "requestNative", requestNative }}); engine.load(testFileUrl("menubarAsHeader.qml")); QScopedPointer<QQuickApplicationWindow> window(qobject_cast<QQuickApplicationWindow *>(engine.rootObjects().value(0))); @@ -1339,7 +1318,7 @@ void tst_qquickmenubar::menubarAsHeader() QQuickItem *contents = window->property("contents").value<QQuickItem *>(); QVERIFY(contents); QVERIFY(menuBar->count() > 0); - QCOMPARE(menuBarPrivate->nativeHandle() != nullptr, nativeMenuBarSupported && requestNative); + QCOMPARE(menuBarPrivate->nativeHandle() != nullptr, nativeMenuBarSupported && native); if (menuBarPrivate->nativeHandle()) { // Using native menubar diff --git a/tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp b/tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp index aec7391f63..a1284ea660 100644 --- a/tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp +++ b/tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp @@ -121,6 +121,7 @@ tst_QQuickPopup::tst_QQuickPopup() void tst_QQuickPopup::initTestCase() { QQmlDataTest::initTestCase(); + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows); qputenv("QML_NO_TOUCH_COMPRESSION", "1"); } diff --git a/tests/auto/quickcontrols/qquickuniversalstyle/tst_qquickuniversalstyle.cpp b/tests/auto/quickcontrols/qquickuniversalstyle/tst_qquickuniversalstyle.cpp index f703c549f8..538bac0203 100644 --- a/tests/auto/quickcontrols/qquickuniversalstyle/tst_qquickuniversalstyle.cpp +++ b/tests/auto/quickcontrols/qquickuniversalstyle/tst_qquickuniversalstyle.cpp @@ -2,4 +2,18 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QtQuickTest/quicktest.h> -QUICK_TEST_MAIN(tst_qquickuniversalstyle) + +class Setup : public QObject +{ + Q_OBJECT + +public slots: + void applicationAvailable() + { + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows); + } +}; + +QUICK_TEST_MAIN_WITH_SETUP(tst_qquickuniversalstyle, Setup) + +#include "tst_qquickuniversalstyle.moc" diff --git a/tests/auto/quickcontrols/snippets/tst_snippets.cpp b/tests/auto/quickcontrols/snippets/tst_snippets.cpp index f0d1da48d7..68e6ef5dfa 100644 --- a/tests/auto/quickcontrols/snippets/tst_snippets.cpp +++ b/tests/auto/quickcontrols/snippets/tst_snippets.cpp @@ -39,6 +39,9 @@ static QMap<QString, QStringPair> findSnippets(const QDir &inputDir, const QDir void tst_Snippets::initTestCase() { + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows); + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar); + qInfo() << "Snippets are taken from" << QQC2_SNIPPETS_PATH; QDir snippetsDir(QQC2_SNIPPETS_PATH); diff --git a/tests/manual/quickcontrols/menus/CMakeLists.txt b/tests/manual/quickcontrols/menus/CMakeLists.txt index 23ee805aa9..b10ba019da 100644 --- a/tests/manual/quickcontrols/menus/CMakeLists.txt +++ b/tests/manual/quickcontrols/menus/CMakeLists.txt @@ -1,32 +1,44 @@ -# Copyright (C) 2023 The Qt Company Ltd. +# Copyright (C) 2024 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) - cmake_minimum_required(VERSION 3.16) - project(menus LANGUAGES C CXX ASM) - find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) -endif() +cmake_minimum_required(VERSION 3.16) +project(menus VERSION 0.1 LANGUAGES CXX) -qt_internal_add_manual_test(menus - GUI +set(CMAKE_AUTOMOC ON) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +find_package(Qt6 REQUIRED COMPONENTS Quick QuickControls2) + +qt_standard_project_setup(REQUIRES 6.8) + +qt_add_executable(appmenus + main.cpp +) + +qt_add_qml_module(appmenus + URI Menus + VERSION 1.0 + QML_FILES + Main.qml SOURCES + cppsettings.cpp + cppsettings.h main.cpp - LIBRARIES - Qt::CorePrivate - Qt::Gui - Qt::Qml - Qt::Quick - Qt::QuickControls2 ) -# Resources: -set(qml_resource_files - "main.qml" +# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1. +# If you are developing for iOS or macOS you should consider setting an +# explicit, fixed bundle identifier manually though. +set_target_properties(appmenus PROPERTIES +# MACOSX_BUNDLE_GUI_IDENTIFIER com.example.appmenus + MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} + MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} + MACOSX_BUNDLE TRUE + WIN32_EXECUTABLE TRUE ) -qt_internal_add_resource(menus "qml" - PREFIX - "/" - FILES - ${qml_resource_files} +target_link_libraries(appmenus + PRIVATE + Qt6::Quick + Qt6::QuickControls2 ) diff --git a/tests/manual/quickcontrols/menus/main.qml b/tests/manual/quickcontrols/menus/Main.qml index b82d3ec585..cce1edbb0f 100644 --- a/tests/manual/quickcontrols/menus/main.qml +++ b/tests/manual/quickcontrols/menus/Main.qml @@ -1,4 +1,4 @@ -// Copyright (C) 2023 The Qt Company Ltd. +// Copyright (C) 2024 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause import QtCore @@ -28,13 +28,11 @@ ApplicationWindow { } menuBar: MenuBar { - requestNative: requestNativeMenuBarSwitch.checked visible: menuBarVisibleSwitch.checked Menu { id: fileMenu objectName: "file" - requestNative: true title: qsTr("&File") ContextAction { text: qsTr("&New...") } ContextMenuItem { text: "menuItem" } @@ -135,9 +133,10 @@ ApplicationWindow { anchors.fill: parent Switch { - id: requestNativeAction - text: qsTr("Request native") - checked: true + text: qsTr("Don't use native menu windows") + checked: CppSettings.dontUseNativeMenuWindows + + onClicked: CppSettings.dontUseNativeMenuWindows = checked } Row { @@ -186,9 +185,10 @@ ApplicationWindow { Row { Switch { - id: requestNativeMenuBarSwitch - text: qsTr("Request native") - checked: true + text: qsTr("Don't use native menu bar") + checked: CppSettings.dontUseNativeMenuBar + + onClicked: CppSettings.dontUseNativeMenuBar = checked } Switch { id: menuBarVisibleSwitch @@ -245,7 +245,6 @@ ApplicationWindow { Menu { id: backgroundContextMenu objectName: "backgroundContextMenu" - requestNative: requestNativeAction.checked function appendAction() { let action = actionComponent.createObject(null, { text: qsTr("Extra context menu item") }) @@ -331,7 +330,6 @@ ApplicationWindow { Menu { id: editContextMenu objectName: "editContextMenu" - requestNative: requestNativeAction.checked ContextAction { text: qsTr("Cut") diff --git a/tests/manual/quickcontrols/menus/Menu.qml b/tests/manual/quickcontrols/menus/Menu.qml index 15786af830..0d18fca2ab 100644 --- a/tests/manual/quickcontrols/menus/Menu.qml +++ b/tests/manual/quickcontrols/menus/Menu.qml @@ -1,4 +1,4 @@ -// Copyright (C) 2020 The Qt Company Ltd. +// Copyright (C) 2024 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause import QtQuick.Controls diff --git a/tests/manual/quickcontrols/menus/cppsettings.cpp b/tests/manual/quickcontrols/menus/cppsettings.cpp new file mode 100644 index 0000000000..e06c59247f --- /dev/null +++ b/tests/manual/quickcontrols/menus/cppsettings.cpp @@ -0,0 +1,46 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "cppsettings.h" + +#include <QCoreApplication> + +CppSettings::CppSettings(QObject *parent) : + QObject(parent), + mSettings("QtProject", "menus") +{ + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows, dontUseNativeMenuWindows()); + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, dontUseNativeMenuBar()); +} + +bool CppSettings::dontUseNativeMenuWindows() const +{ + return mSettings.value("dontUseNativeMenuWindows").toBool(); +} + +void CppSettings::setDontUseNativeMenuWindows(bool dontUseNativeMenuWindows) +{ + const bool oldValue = this->dontUseNativeMenuWindows(); + if (dontUseNativeMenuWindows == oldValue) + return; + + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows, dontUseNativeMenuWindows); + mSettings.setValue("dontUseNativeMenuWindows", dontUseNativeMenuWindows); + emit dontUseNativeMenuWindowsChanged(); +} + +bool CppSettings::dontUseNativeMenuBar() const +{ + return mSettings.value("dontUseNativeMenuBar").toBool(); +} + +void CppSettings::setDontUseNativeMenuBar(bool dontUseNativeMenuBar) +{ + const bool oldValue = this->dontUseNativeMenuBar(); + if (dontUseNativeMenuBar == oldValue) + return; + + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, dontUseNativeMenuBar); + mSettings.setValue("dontUseNativeMenuBar", dontUseNativeMenuBar); + emit dontUseNativeMenuBarChanged(); +} diff --git a/tests/manual/quickcontrols/menus/cppsettings.h b/tests/manual/quickcontrols/menus/cppsettings.h new file mode 100644 index 0000000000..158ed1b20d --- /dev/null +++ b/tests/manual/quickcontrols/menus/cppsettings.h @@ -0,0 +1,38 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#ifndef CPPSETTINGS_H +#define CPPSETTINGS_H + +#include <QObject> +#include <QQmlEngine> +#include <QSettings> + +class CppSettings : public QObject +{ + Q_OBJECT + Q_PROPERTY(bool dontUseNativeMenuWindows READ dontUseNativeMenuWindows WRITE setDontUseNativeMenuWindows + NOTIFY dontUseNativeMenuWindowsChanged FINAL) + Q_PROPERTY(bool dontUseNativeMenuBar READ dontUseNativeMenuBar WRITE setDontUseNativeMenuBar + NOTIFY dontUseNativeMenuBarChanged FINAL) + QML_ELEMENT + QML_SINGLETON + +public: + explicit CppSettings(QObject *parent = nullptr); + + bool dontUseNativeMenuWindows() const; + void setDontUseNativeMenuWindows(bool dontUseNativeMenuWindows); + + bool dontUseNativeMenuBar() const; + void setDontUseNativeMenuBar(bool dontUseNativeMenuBar); + +signals: + void dontUseNativeMenuWindowsChanged(); + void dontUseNativeMenuBarChanged(); + +private: + QSettings mSettings; +}; + +#endif // CPPSETTINGS_H diff --git a/tests/manual/quickcontrols/menus/main.cpp b/tests/manual/quickcontrols/menus/main.cpp index d08850551e..e9b4e6d5eb 100644 --- a/tests/manual/quickcontrols/menus/main.cpp +++ b/tests/manual/quickcontrols/menus/main.cpp @@ -7,17 +7,20 @@ int main(int argc, char *argv[]) { - QGuiApplication::setApplicationName("menus"); QGuiApplication::setOrganizationName("QtProject"); + QGuiApplication::setApplicationName("menus"); QGuiApplication app(argc, argv); -// app.setAttribute(Qt::AA_DontUseNativeMenuBar, true); - qputenv("QT_QUICK_CONTROLS_USE_NATIVE_MENUS", "1"); - QQmlApplicationEngine engine; engine.setInitialProperties({{ "currentStyle", QQuickStyle::name() }}); - engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); + QObject::connect( + &engine, + &QQmlApplicationEngine::objectCreationFailed, + &app, + []() { QCoreApplication::exit(-1); }, + Qt::QueuedConnection); + engine.loadFromModule("Menus", "Main"); return app.exec(); } diff --git a/tests/manual/quickcontrols/menus/qml.qrc b/tests/manual/quickcontrols/menus/qml.qrc deleted file mode 100644 index 82e69be6f3..0000000000 --- a/tests/manual/quickcontrols/menus/qml.qrc +++ /dev/null @@ -1,55 +0,0 @@ -<RCC> - <qresource prefix="/"> - <file>ControlContainer.qml</file> - <file>controls/Button.qml</file> - <file>controls/CheckBox.qml</file> - <file>controls/RadioButton.qml</file> - <file>controls/CheckDelegate.qml</file> - <file>controls/ComboBox.qml</file> - <file>controls/DelayButton.qml</file> - <file>controls/Dial.qml</file> - <file>controls/Frame.qml</file> - <file>controls/GroupBox.qml</file> - <file>controls/ItemDelegate.qml</file> - <file>controls/Page.qml</file> - <file>controls/PageIndicator.qml</file> - <file>controls/Pane.qml</file> - <file>controls/ProgressBar.qml</file> - <file>controls/RadioDelegate.qml</file> - <file>controls/RangeSlider.qml</file> - <file>controls/RoundButton.qml</file> - <file>controls/ScrollBar.qml</file> - <file>controls/ScrollIndicator.qml</file> - <file>controls/Slider.qml</file> - <file>controls/SpinBox.qml</file> - <file>controls/SwipeDelegate.qml</file> - <file>controls/Switch.qml</file> - <file>controls/SwitchDelegate.qml</file> - <file>controls/TabBar.qml</file> - <file>controls/TextArea.qml</file> - <file>controls/TextField.qml</file> - <file>SettingsDialog.qml</file> - <file>ColorEditor.qml</file> - <file>controls/ToolBar.qml</file> - <file>controls/Dialog.qml</file> - <file>controls/Menu.qml</file> - <file>ExampleContainer.qml</file> - <file>controls/Label.qml</file> - <file>controls/ToolTip.qml</file> - <file>controls/Tumbler.qml</file> - <file>controls/BusyIndicator.qml</file> - <file>testbench.qml</file> - <file>controls/MenuBar.qml</file> - <file>controls/SplitView.qml</file> - <file>+Imagine/ApplicationWindow.qml</file> - <file>ApplicationWindow.qml</file> - <file>+Imagine/ToolBar.qml</file> - <file>ToolBar.qml</file> - <file>+Imagine/Menu.qml</file> - <file>Menu.qml</file> - <file>+Imagine/Dialog.qml</file> - <file>Dialog.qml</file> - <file>ContentPane.qml</file> - <file>+Imagine/ContentPane.qml</file> - </qresource> -</RCC> |