diff options
Diffstat (limited to 'src/plugins/platforms/cocoa/qcocoamenu.mm')
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoamenu.mm | 40 |
1 files changed, 28 insertions, 12 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm index 8a3d259b3e..7a6999c2cc 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.mm +++ b/src/plugins/platforms/cocoa/qcocoamenu.mm @@ -18,6 +18,9 @@ #include "qcocoascreen.h" #include "qcocoaapplicationdelegate.h" +#include <QtCore/private/qcore_mac_p.h> +#include <QtCore/qpointer.h> + QT_BEGIN_NAMESPACE QCocoaMenu::QCocoaMenu() : @@ -35,11 +38,13 @@ QCocoaMenu::QCocoaMenu() : QCocoaMenu::~QCocoaMenu() { - for (auto *item : qAsConst(m_menuItems)) { + for (auto *item : std::as_const(m_menuItems)) { if (item->menuParent() == this) item->setMenuParent(nullptr); } + if (isOpen()) + dismiss(); [m_nativeMenu release]; } @@ -58,7 +63,7 @@ void QCocoaMenu::setMinimumWidth(int width) void QCocoaMenu::setFont(const QFont &font) { if (font.resolveMask()) { - NSFont *customMenuFont = [NSFont fontWithName:font.families().first().toNSString() + NSFont *customMenuFont = [NSFont fontWithName:font.families().constFirst().toNSString() size:font.pointSize()]; m_nativeMenu.font = customMenuFont; } @@ -86,7 +91,7 @@ void QCocoaMenu::insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem * int index = m_menuItems.indexOf(beforeItem); // if a before item is supplied, it should be in the menu if (index < 0) { - qWarning("Before menu item not found"); + qCWarning(lcQpaMenus) << beforeItem << "not in" << m_menuItems; return; } m_menuItems.insert(index, cocoaItem); @@ -124,13 +129,13 @@ void QCocoaMenu::insertNative(QCocoaMenuItem *item, QCocoaMenuItem *beforeItem) } if (nativeItem.menu) { - qWarning() << "Menu item" << item->text() << "already in menu" << QString::fromNSString(nativeItem.menu.title); + qCWarning(lcQpaMenus) << "Menu item" << item->text() << "already in menu" << QString::fromNSString(nativeItem.menu.title); return; } if (beforeItem) { if (beforeItem->isMerged()) { - qWarning("No non-merged before menu item found"); + qCWarning(lcQpaMenus, "No non-merged before menu item found"); return; } const NSInteger nativeIndex = [m_nativeMenu indexOfItem:beforeItem->nsItem()]; @@ -166,7 +171,7 @@ void QCocoaMenu::removeMenuItem(QPlatformMenuItem *menuItem) QMacAutoReleasePool pool; QCocoaMenuItem *cocoaItem = static_cast<QCocoaMenuItem *>(menuItem); if (!m_menuItems.contains(cocoaItem)) { - qWarning("Menu does not contain the item to be removed"); + qCWarning(lcQpaMenus) << m_menuItems << "does not contain" << cocoaItem; return; } @@ -179,7 +184,7 @@ void QCocoaMenu::removeMenuItem(QPlatformMenuItem *menuItem) m_menuItems.removeOne(cocoaItem); if (!cocoaItem->isMerged()) { if (m_nativeMenu != cocoaItem->nsItem().menu) { - qWarning("Item to remove does not belong to this menu"); + qCWarning(lcQpaMenus) << cocoaItem << "does not belong to" << m_nativeMenu; return; } [m_nativeMenu removeItem:cocoaItem->nsItem()]; @@ -219,7 +224,7 @@ void QCocoaMenu::syncMenuItem_helper(QPlatformMenuItem *menuItem, bool menubarUp QMacAutoReleasePool pool; QCocoaMenuItem *cocoaItem = static_cast<QCocoaMenuItem *>(menuItem); if (!m_menuItems.contains(cocoaItem)) { - qWarning("Item does not belong to this menu"); + qCWarning(lcQpaMenus) << cocoaItem << "does not belong to" << this; return; } @@ -284,7 +289,7 @@ void QCocoaMenu::syncSeparatorsCollapsible(bool enable) if (lastVisibleItem && lastVisibleItem.separatorItem) lastVisibleItem.hidden = YES; } else { - for (auto *item : qAsConst(m_menuItems)) { + for (auto *item : std::as_const(m_menuItems)) { if (!item->isSeparator()) continue; @@ -318,6 +323,8 @@ void QCocoaMenu::showPopup(const QWindow *parentWindow, const QRect &targetRect, { QMacAutoReleasePool pool; + QPointer<QCocoaMenu> guard = this; + QPoint pos = QPoint(targetRect.left(), targetRect.top() + targetRect.height()); QCocoaWindow *cocoaWindow = parentWindow ? static_cast<QCocoaWindow *>(parentWindow->handle()) : nullptr; NSView *view = cocoaWindow ? cocoaWindow->view() : nil; @@ -402,6 +409,11 @@ void QCocoaMenu::showPopup(const QWindow *parentWindow, const QRect &targetRect, } } + if (!guard) { + menuParentGuard.dismiss(); + return; + } + // The calls above block, and also swallow any mouse release event, // so we need to clear any mouse button that triggered the menu popup. if (cocoaWindow && !cocoaWindow->isForeignWindow()) @@ -423,7 +435,7 @@ QPlatformMenuItem *QCocoaMenu::menuItemAt(int position) const QPlatformMenuItem *QCocoaMenu::menuItemForTag(quintptr tag) const { - for (auto *item : qAsConst(m_menuItems)) { + for (auto *item : std::as_const(m_menuItems)) { if (item->tag() == tag) return item; } @@ -439,7 +451,7 @@ QList<QCocoaMenuItem *> QCocoaMenu::items() const QList<QCocoaMenuItem *> QCocoaMenu::merged() const { QList<QCocoaMenuItem *> result; - for (auto *item : qAsConst(m_menuItems)) { + for (auto *item : std::as_const(m_menuItems)) { if (item->menu()) { // recurse into submenus result.append(item->menu()->merged()); continue; @@ -460,7 +472,7 @@ void QCocoaMenu::propagateEnabledState(bool enabled) if (!m_enabled && enabled) // Some ancestor was enabled, but this menu is not return; - for (auto *item : qAsConst(m_menuItems)) { + for (auto *item : std::as_const(m_menuItems)) { if (QCocoaMenu *menu = item->menu()) menu->propagateEnabledState(enabled); else @@ -481,6 +493,10 @@ void QCocoaMenu::setAttachedItem(NSMenuItem *item) if (m_attachedItem) m_attachedItem.submenu = m_nativeMenu; + // NSMenuItems with a submenu and submenuAction: as the item's action + // will not take part in NSMenuValidation, so explicitly enable/disable + // the item here. See also QCocoaMenuItem::resolveTargetAction() + m_attachedItem.enabled = m_attachedItem.hasSubmenu; } NSMenuItem *QCocoaMenu::attachedItem() const |