diff --git a/src/plugins/platforms/cocoa/qcocoamenu.h b/src/plugins/platforms/cocoa/qcocoamenu.h index b77071536b..06688dbf3d 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.h +++ b/src/plugins/platforms/cocoa/qcocoamenu.h @@ -96,14 +96,18 @@ public: bool isOpen() const; void setIsOpen(bool isOpen); + void timerEvent(QTimerEvent *e) Q_DECL_OVERRIDE; + private: QCocoaMenuItem *itemOrNull(int index) const; void insertNative(QCocoaMenuItem *item, QCocoaMenuItem *beforeItem); + void scheduleUpdate(); QList m_menuItems; NSMenu *m_nativeMenu; NSMenuItem *m_attachedItem; quintptr m_tag; + int m_updateTimer; bool m_enabled:1; bool m_parentEnabled:1; bool m_visible:1; diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm index 8e47974d12..e5681c0894 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.mm +++ b/src/plugins/platforms/cocoa/qcocoamenu.mm @@ -260,6 +260,7 @@ QT_BEGIN_NAMESPACE QCocoaMenu::QCocoaMenu() : m_attachedItem(0), m_tag(0), + m_updateTimer(0), m_enabled(true), m_parentEnabled(true), m_visible(true), @@ -410,6 +411,20 @@ QCocoaMenuItem *QCocoaMenu::itemOrNull(int index) const return m_menuItems.at(index); } +void QCocoaMenu::scheduleUpdate() +{ + if (!m_updateTimer) + m_updateTimer = startTimer(0); +} + +void QCocoaMenu::timerEvent(QTimerEvent *e) +{ + if (e->timerId() == m_updateTimer) { + m_updateTimer = 0; + [m_nativeMenu update]; + } +} + void QCocoaMenu::syncMenuItem(QPlatformMenuItem *menuItem) { QMacAutoReleasePool pool; @@ -436,9 +451,9 @@ void QCocoaMenu::syncMenuItem(QPlatformMenuItem *menuItem) QCocoaMenuItem* beforeItem = itemOrNull(m_menuItems.indexOf(cocoaItem) + 1); insertNative(cocoaItem, beforeItem); } else { - // Force NSMenuValidation to kick in. This is needed e.g. + // Schedule NSMenuValidation to kick in. This is needed e.g. // when an item's enabled state changes after menuWillOpen: - [m_nativeMenu update]; + scheduleUpdate(); } } diff --git a/tests/manual/cocoa/menurama/mainwindow.cpp b/tests/manual/cocoa/menurama/mainwindow.cpp index 5cccc16974..06867bd7c9 100644 --- a/tests/manual/cocoa/menurama/mainwindow.cpp +++ b/tests/manual/cocoa/menurama/mainwindow.cpp @@ -56,6 +56,19 @@ MainWindow::MainWindow(QWidget *parent) : connect(ui->pushButton, &QPushButton::clicked, [=] { menuApp->populateMenu(ui->menuOn_Click, true /*clear*/); }); + + connect(ui->addManyButton, &QPushButton::clicked, [=] { + QMenu *menu = new QMenu(QLatin1String("Many More ") + + QString::number(ui->menuBar->actions().count())); + ui->menuBar->insertMenu(ui->menuDynamic_Stuff->menuAction(), menu); + for (int i = 0; i < 2000; i++) { + auto *action = menu->addAction(QLatin1String("Item ") + QString::number(i)); + if (i & 0x1) + action->setEnabled(false); + if (i & 0x2) + action->setVisible(false); + } + }); } MainWindow::~MainWindow() diff --git a/tests/manual/cocoa/menurama/mainwindow.ui b/tests/manual/cocoa/menurama/mainwindow.ui index d3caa6c608..18cded70d2 100644 --- a/tests/manual/cocoa/menurama/mainwindow.ui +++ b/tests/manual/cocoa/menurama/mainwindow.ui @@ -6,50 +6,60 @@ 0 0 - 429 - 251 + 486 + 288 MainWindow - + - - - 24 - - - - - The "Help" menu should NOT be visible. + + + The "Help" menu should NOT be visible. Click on "Dynamic Stuff" then move left and right to other menus. Disabled items should remain that way. - - - false - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - true - - - + + + false + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + true + + + + + + + Enable "Stuff" Menu + + + true + + + + + + + + 0 + 0 + + + + Populate Dynamic Submenu + + + + + - - - Enable "Stuff" Menu - - - true - - - - - + 0 @@ -57,7 +67,17 @@ Click on "Dynamic Stuff" then move left and right to other menus. Disa - Populate Dynamic Submenu + Add Many Items + + + + + + + Adding hundreds of items should not block the UI for noticeable periods of time. Odd numbered items should be disabled, those with 2nd LSB on should be hidden. + + + true @@ -70,7 +90,7 @@ Click on "Dynamic Stuff" then move left and right to other menus. Disa 0 0 - 429 + 486 22