diff options
Diffstat (limited to 'src/plugins/platforms/cocoa/qcocoamenubar.mm')
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoamenubar.mm | 79 |
1 files changed, 58 insertions, 21 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoamenubar.mm b/src/plugins/platforms/cocoa/qcocoamenubar.mm index b112e40549..73331db40d 100644 --- a/src/plugins/platforms/cocoa/qcocoamenubar.mm +++ b/src/plugins/platforms/cocoa/qcocoamenubar.mm @@ -83,9 +83,24 @@ QCocoaMenuBar::~QCocoaMenuBar() } } -void QCocoaMenuBar::insertMenu(QPlatformMenu *platformMenu, QPlatformMenu *before) +void QCocoaMenuBar::insertNativeMenu(QCocoaMenu *menu, QCocoaMenu *beforeMenu) { QCocoaAutoReleasePool pool; + + if (beforeMenu) { + NSUInteger nativeIndex = [m_nativeMenu indexOfItem:beforeMenu->nsMenuItem()]; + [m_nativeMenu insertItem: menu->nsMenuItem() atIndex: nativeIndex]; + } else { + [m_nativeMenu addItem: menu->nsMenuItem()]; + } + + menu->setMenuBar(this); + syncMenu(static_cast<QPlatformMenu *>(menu)); + [m_nativeMenu setSubmenu: menu->nsMenu() forItem: menu->nsMenuItem()]; +} + +void QCocoaMenuBar::insertMenu(QPlatformMenu *platformMenu, QPlatformMenu *before) +{ QCocoaMenu *menu = static_cast<QCocoaMenu *>(platformMenu); QCocoaMenu *beforeMenu = static_cast<QCocoaMenu *>(before); #ifdef QT_COCOA_ENABLE_MENU_DEBUG @@ -96,39 +111,36 @@ void QCocoaMenuBar::insertMenu(QPlatformMenu *platformMenu, QPlatformMenu *befor qWarning() << Q_FUNC_INFO << "This menu already belongs to the menubar, remove it first"; return; } - if (beforeMenu) { - if (!m_menus.contains(beforeMenu)) { - qWarning() << Q_FUNC_INFO << "The before menu does not belong to the menubar"; - return; - } - m_menus.insert(m_menus.indexOf(beforeMenu), menu); - NSUInteger nativeIndex = [m_nativeMenu indexOfItem:beforeMenu->nsMenuItem()]; - [m_nativeMenu insertItem: menu->nsMenuItem() atIndex: nativeIndex]; - } else { - m_menus.append(menu); - [m_nativeMenu addItem: menu->nsMenuItem()]; + + if (beforeMenu && !m_menus.contains(beforeMenu)) { + qWarning() << Q_FUNC_INFO << "The before menu does not belong to the menubar"; + return; } - platformMenu->setParent(this); - syncMenu(platformMenu); - [m_nativeMenu setSubmenu: menu->nsMenu() forItem: menu->nsMenuItem()]; + m_menus.insert(beforeMenu ? m_menus.indexOf(beforeMenu) : m_menus.size(), menu); + if (!menu->menuBar()) + insertNativeMenu(menu, beforeMenu); } -void QCocoaMenuBar::removeMenu(QPlatformMenu *platformMenu) +void QCocoaMenuBar::removeNativeMenu(QCocoaMenu *menu) { QCocoaAutoReleasePool pool; + if (menu->menuBar() == this) + menu->setMenuBar(0); + NSUInteger realIndex = [m_nativeMenu indexOfItem:menu->nsMenuItem()]; + [m_nativeMenu removeItemAtIndex: realIndex]; +} + +void QCocoaMenuBar::removeMenu(QPlatformMenu *platformMenu) +{ QCocoaMenu *menu = static_cast<QCocoaMenu *>(platformMenu); if (!m_menus.contains(menu)) { qWarning() << Q_FUNC_INFO << "Trying to remove a menu that does not belong to the menubar"; return; } m_menus.removeOne(menu); - - if (platformMenu->parent() == this) - platformMenu->setParent(0); - NSUInteger realIndex = [m_nativeMenu indexOfItem:menu->nsMenuItem()]; - [m_nativeMenu removeItemAtIndex: realIndex]; + removeNativeMenu(menu); } void QCocoaMenuBar::syncMenu(QPlatformMenu *menu) @@ -136,6 +148,17 @@ void QCocoaMenuBar::syncMenu(QPlatformMenu *menu) QCocoaMenu *cocoaMenu = static_cast<QCocoaMenu *>(menu); Q_FOREACH (QCocoaMenuItem *item, cocoaMenu->items()) cocoaMenu->syncMenuItem(item); + + // If the NSMenu has no visble items, or only separators, we should hide it + // on the menubar. This can happen after syncing the menu items since they + // can be moved to other menus. + BOOL shouldHide = YES; + for (NSMenuItem *item in [cocoaMenu->nsMenu() itemArray]) + if (![item isSeparatorItem] && ![item isHidden]) { + shouldHide = NO; + break; + } + [cocoaMenu->nsMenuItem() setHidden:shouldHide]; } void QCocoaMenuBar::handleReparent(QWindow *newParentWindow) @@ -196,6 +219,20 @@ void QCocoaMenuBar::updateMenuBarImmediately() m->syncModalState(disableForModal); } + // reparent shared menu items if necessary. + // We browse the list in reverse order to be sure that the next items are redrawn before the current ones, + // in this way we are sure that "beforeMenu" (see below) is part of the native menu before "m" is redraw + for (int i = mb->m_menus.size() - 1; i >= 0; i--) { + QCocoaMenu *m = mb->m_menus.at(i); + QCocoaMenuBar *menuBar = m->menuBar(); + if (menuBar != mb) { + QCocoaMenu *beforeMenu = i < (mb->m_menus.size() - 1) ? mb->m_menus.at(i + 1) : 0; + if (menuBar) + menuBar->removeNativeMenu(m); + mb->insertNativeMenu(m, beforeMenu); + } + } + QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *loader = getMenuLoader(); [loader ensureAppMenuInMenu:mb->nsMenu()]; |