diff options
Diffstat (limited to 'src/plugins/platforms/cocoa/qcocoamenubar.mm')
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoamenubar.mm | 130 |
1 files changed, 38 insertions, 92 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoamenubar.mm b/src/plugins/platforms/cocoa/qcocoamenubar.mm index 61ac5eb7f0..30bff78a36 100644 --- a/src/plugins/platforms/cocoa/qcocoamenubar.mm +++ b/src/plugins/platforms/cocoa/qcocoamenubar.mm @@ -1,5 +1,6 @@ /**************************************************************************** ** +** Copyright (C) 2018 The Qt Company Ltd. ** Copyright (C) 2012 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author James Turner <james.turner@kdab.com> ** Contact: https://www.qt.io/licensing/ ** @@ -67,7 +68,7 @@ QCocoaMenuBar::~QCocoaMenuBar() #ifdef QT_COCOA_ENABLE_MENU_DEBUG qDebug() << "~QCocoaMenuBar" << this; #endif - foreach (QCocoaMenu *menu, m_menus) { + for (auto menu : qAsConst(m_menus)) { if (!menu) continue; NSMenuItem *item = nativeItemForMenu(menu); @@ -79,14 +80,13 @@ QCocoaMenuBar::~QCocoaMenuBar() static_menubars.removeOne(this); if (!m_window.isNull() && m_window->menubar() == this) { - m_window->setMenubar(0); + m_window->setMenubar(nullptr); // Delete the children first so they do not cause // the native menu items to be hidden after // the menu bar was updated qDeleteAll(children()); updateMenuBarImmediately(); - resetKnownMenuItemsToQt(); } } @@ -199,8 +199,8 @@ void QCocoaMenuBar::syncMenu_helper(QPlatformMenu *menu, bool menubarUpdate) // 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. - for (NSMenuItem *item in [cocoaMenu->nsMenu() itemArray]) - if (![item isSeparatorItem] && ![item isHidden]) { + for (NSMenuItem *item in cocoaMenu->nsMenu().itemArray) + if (!item.separatorItem && !item.hidden) { shouldHide = NO; break; } @@ -230,7 +230,7 @@ void QCocoaMenuBar::handleReparent(QWindow *newParentWindow) if (!m_window.isNull()) m_window->setMenubar(nullptr); - if (newParentWindow == nullptr) { + if (!newParentWindow) { m_window.clear(); } else { newParentWindow->create(); @@ -241,82 +241,28 @@ void QCocoaMenuBar::handleReparent(QWindow *newParentWindow) updateMenuBarImmediately(); } +QWindow *QCocoaMenuBar::parentWindow() const +{ + return m_window ? m_window->window() : nullptr; +} + + QCocoaWindow *QCocoaMenuBar::findWindowForMenubar() { if (qApp->focusWindow()) return static_cast<QCocoaWindow*>(qApp->focusWindow()->handle()); - return NULL; + return nullptr; } QCocoaMenuBar *QCocoaMenuBar::findGlobalMenubar() { - foreach (QCocoaMenuBar *mb, static_menubars) { - if (mb->m_window.isNull()) - return mb; + for (auto *menubar : qAsConst(static_menubars)) { + if (menubar->m_window.isNull()) + return menubar; } - return NULL; -} - -void QCocoaMenuBar::redirectKnownMenuItemsToFirstResponder() -{ - // QTBUG-17291: http://forums.macrumors.com/showthread.php?t=1249452 - // When a dialog is opened, shortcuts for actions inside the dialog (cut, paste, ...) - // continue to go through the same menu items which claimed those shortcuts. - // They are not keystrokes which we can intercept in any other way; the OS intercepts them. - // The menu items had to be created by the application. That's why we need roles - // to identify those "special" menu items which can be useful even when non-Qt - // native widgets are in focus. When the native widget is focused it will be the - // first responder, so the menu item needs to have its target be the first responder; - // this is done by setting it to nil. - - // This function will find all menu items on all menus which have - // "special" roles, set the target and also set the standard actions which - // apply to those roles. But afterwards it is necessary to call - // resetKnownMenuItemsToQt() to put back the target and action so that - // those menu items will go back to invoking their associated QActions. - foreach (QCocoaMenuBar *mb, static_menubars) - foreach (QCocoaMenu *m, mb->m_menus) - foreach (QCocoaMenuItem *i, m->items()) { - bool known = true; - switch (i->effectiveRole()) { - case QPlatformMenuItem::CutRole: - [i->nsItem() setAction:@selector(cut:)]; - break; - case QPlatformMenuItem::CopyRole: - [i->nsItem() setAction:@selector(copy:)]; - break; - case QPlatformMenuItem::PasteRole: - [i->nsItem() setAction:@selector(paste:)]; - break; - case QPlatformMenuItem::SelectAllRole: - [i->nsItem() setAction:@selector(selectAll:)]; - break; - // We may discover later that there are other roles/actions which - // are meaningful to standard native widgets; they can be added. - default: - known = false; - break; - } - if (known) - [i->nsItem() setTarget:nil]; - } -} - -void QCocoaMenuBar::resetKnownMenuItemsToQt() -{ - // Undo the effect of redirectKnownMenuItemsToFirstResponder(): - // reset the menu items' target/action. - foreach (QCocoaMenuBar *mb, static_menubars) { - foreach (QCocoaMenu *m, mb->m_menus) { - foreach (QCocoaMenuItem *i, m->items()) { - if (i->effectiveRole() >= QPlatformMenuItem::ApplicationSpecificRole) { - m->setItemTargetAction(i); - } - } - } - } + return nullptr; } void QCocoaMenuBar::updateMenuBarImmediately() @@ -325,7 +271,7 @@ void QCocoaMenuBar::updateMenuBarImmediately() QCocoaMenuBar *mb = findGlobalMenubar(); QCocoaWindow *cw = findWindowForMenubar(); - QWindow *win = cw ? cw->window() : 0; + QWindow *win = cw ? cw->window() : nullptr; if (win && (win->flags() & Qt::Popup) == Qt::Popup) { // context menus, comboboxes, etc. don't need to update the menubar, // but if an application has only Qt::Tool window(s) on start, @@ -353,7 +299,7 @@ void QCocoaMenuBar::updateMenuBarImmediately() #endif bool disableForModal = mb->shouldDisable(cw); - foreach (QCocoaMenu *menu, mb->m_menus) { + for (auto menu : qAsConst(mb->m_menus)) { if (!menu) continue; NSMenuItem *item = mb->nativeItemForMenu(menu); @@ -368,16 +314,16 @@ void QCocoaMenuBar::updateMenuBarImmediately() [loader ensureAppMenuInMenu:mb->nsMenu()]; NSMutableSet *mergedItems = [[NSMutableSet setWithCapacity:mb->merged().count()] retain]; - foreach (QCocoaMenuItem *m, mb->merged()) { - [mergedItems addObject:m->nsItem()]; - m->syncMerged(); + for (auto mergedItem : mb->merged()) { + [mergedItems addObject:mergedItem->nsItem()]; + mergedItem->syncMerged(); } // hide+disable all mergeable items we're not currently using for (NSMenuItem *mergeable in [loader mergeable]) { if (![mergedItems containsObject:mergeable]) { - [mergeable setHidden:YES]; - [mergeable setEnabled:NO]; + mergeable.hidden = YES; + mergeable.enabled = NO; } } @@ -389,7 +335,7 @@ void QCocoaMenuBar::updateMenuBarImmediately() QList<QCocoaMenuItem*> QCocoaMenuBar::merged() const { QList<QCocoaMenuItem*> r; - foreach (QCocoaMenu* menu, m_menus) + for (auto menu : qAsConst(m_menus)) r.append(menu->merged()); return r; @@ -409,11 +355,11 @@ bool QCocoaMenuBar::shouldDisable(QCocoaWindow *active) const // When there is an application modal window on screen, the entries of // the menubar should be disabled. The exception in Qt is that if the // modal window is the only window on screen, then we enable the menu bar. - foreach (QWindow *w, topWindows) { - if (w->isVisible() && w->modality() == Qt::ApplicationModal) { + for (auto *window : qAsConst(topWindows)) { + if (window->isVisible() && window->modality() == Qt::ApplicationModal) { // check for other visible windows - foreach (QWindow *other, topWindows) { - if ((w != other) && (other->isVisible())) { + for (auto *other : qAsConst(topWindows)) { + if ((window != other) && (other->isVisible())) { // INVARIANT: we found another visible window // on screen other than our modalWidget. We therefore // disable the menu bar to follow normal modality logic: @@ -433,21 +379,21 @@ bool QCocoaMenuBar::shouldDisable(QCocoaWindow *active) const QPlatformMenu *QCocoaMenuBar::menuForTag(quintptr tag) const { - foreach (QCocoaMenu *menu, m_menus) { + for (auto menu : qAsConst(m_menus)) if (menu->tag() == tag) return menu; - } - return 0; + return nullptr; } -NSMenuItem *QCocoaMenuBar::itemForRole(QPlatformMenuItem::MenuRole r) +NSMenuItem *QCocoaMenuBar::itemForRole(QPlatformMenuItem::MenuRole role) { - foreach (QCocoaMenu *m, m_menus) - foreach (QCocoaMenuItem *i, m->items()) - if (i->effectiveRole() == r) - return i->nsItem(); - return nullptr; + for (auto menu : qAsConst(m_menus)) + for (auto *item : menu->items()) + if (item->effectiveRole() == role) + return item->nsItem(); + + return nil; } QCocoaWindow *QCocoaMenuBar::cocoaWindow() const |