From b2f78b796b5b73d4f0732975ffd66f8aa392c001 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Mon, 5 Dec 2016 14:21:40 -0800 Subject: QCocoaMenu: Avoid exception when inserting item already in this menu This should not happen, but it's clearly not the user's fault. So we should try to carry on as gracefully as possible instead of letting Cocoa abort the application. The patch also factors the repeated calls to QCocoaMenuItem:: nsItem() in QCocoaMenu::insertNative() and improves a warning from QCocoaMenuIten::sync(). Change-Id: Id00135c219aaf40fb565b19a65cab68f6d9863b2 Task-number: QTBUG-57404 Reviewed-by: Richard Moe Gustavsen --- src/plugins/platforms/cocoa/qcocoamenu.mm | 20 +++++++++++++------- src/plugins/platforms/cocoa/qcocoamenuitem.mm | 2 +- 2 files changed, 14 insertions(+), 8 deletions(-) (limited to 'src/plugins/platforms/cocoa') diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm index 88ffd48538..915463a52a 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.mm +++ b/src/plugins/platforms/cocoa/qcocoamenu.mm @@ -331,11 +331,12 @@ void QCocoaMenu::insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem * void QCocoaMenu::insertNative(QCocoaMenuItem *item, QCocoaMenuItem *beforeItem) { - item->nsItem().target = m_nativeMenu.delegate; - item->nsItem().action = @selector(itemFired:); + NSMenuItem *nativeItem = item->nsItem(); + nativeItem.target = m_nativeMenu.delegate; + nativeItem.action = @selector(itemFired:); // Someone's adding new items after aboutToShow() was emitted - if (isOpen() && item->menu() && item->nsItem()) - item->menu()->setAttachedItem(item->nsItem()); + if (isOpen() && nativeItem) + item->menu()->setAttachedItem(nativeItem); item->setParentEnabled(isEnabled()); @@ -348,15 +349,20 @@ void QCocoaMenu::insertNative(QCocoaMenuItem *item, QCocoaMenuItem *beforeItem) beforeItem = itemOrNull(m_menuItems.indexOf(beforeItem) + 1); } + if (nativeItem.menu) { + qWarning() << "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"); return; } - NSUInteger nativeIndex = [m_nativeMenu indexOfItem:beforeItem->nsItem()]; - [m_nativeMenu insertItem: item->nsItem() atIndex: nativeIndex]; + const NSInteger nativeIndex = [m_nativeMenu indexOfItem:beforeItem->nsItem()]; + [m_nativeMenu insertItem:nativeItem atIndex:nativeIndex]; } else { - [m_nativeMenu addItem: item->nsItem()]; + [m_nativeMenu addItem:nativeItem]; } item->setMenuParent(this); } diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.mm b/src/plugins/platforms/cocoa/qcocoamenuitem.mm index e32ff26ff5..21f2b4de85 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuitem.mm +++ b/src/plugins/platforms/cocoa/qcocoamenuitem.mm @@ -288,7 +288,7 @@ NSMenuItem *QCocoaMenuItem::sync() } default: - qWarning() << "menu item" << m_text << "has unsupported role" << (int)m_role; + qWarning() << "Menu item" << m_text << "has unsupported role" << m_role; } if (mergeItem) { -- cgit v1.2.3 From 093e1111ef68a8a83e42d5d82fc9d5c93d47071b Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Mon, 5 Dec 2016 14:38:12 -0800 Subject: QCocoaMenu: Don't rely on tags when we can get the actual NSMenuItem -[NSMenu itemWithTag:] clearly states that it'll return the first item with that tag. Furthermore, when and item has been synced more than once, it could be that more than one such item exists in the same menu (e.g. lately changing the role of Edit->Copy). Change-Id: I95a4f0a151659ae273ba03a3cab4a720b781fc3a Task-number: QTBUG-57404 Reviewed-by: Jake Petroules --- src/plugins/platforms/cocoa/qcocoamenu.mm | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/plugins/platforms/cocoa') diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm index 915463a52a..81db919627 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.mm +++ b/src/plugins/platforms/cocoa/qcocoamenu.mm @@ -419,9 +419,8 @@ void QCocoaMenu::syncMenuItem(QPlatformMenuItem *menuItem) return; } - bool wasMerged = cocoaItem->isMerged(); - NSMenu *oldMenu = wasMerged ? [[QCocoaMenuLoader sharedMenuLoader] applicationMenu] : m_nativeMenu; - NSMenuItem *oldItem = [oldMenu itemWithTag:(NSInteger) cocoaItem]; + const bool wasMerged = cocoaItem->isMerged(); + NSMenuItem *oldItem = cocoaItem->nsItem(); if (cocoaItem->sync() != oldItem) { // native item was changed for some reason -- cgit v1.2.3 From 2a44f81fe7bb76cf7ced5bae5a2654b96f0e93c6 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Thu, 15 Dec 2016 14:24:48 -0800 Subject: QCocoMenu: Fix patch b2f78b796b5b73d4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A null pointer check was accidentally removed while refactoring the code. Change-Id: I547936671bd134bb7df710a4b123a0d731076bf2 Task-number: QTCREATORBUG-17438 Task-number: QTBUG-57404 Task-number: QTBUG-57657 Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/cocoa/qcocoamenu.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/plugins/platforms/cocoa') diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm index 81db919627..e177a24e73 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.mm +++ b/src/plugins/platforms/cocoa/qcocoamenu.mm @@ -335,7 +335,7 @@ void QCocoaMenu::insertNative(QCocoaMenuItem *item, QCocoaMenuItem *beforeItem) nativeItem.target = m_nativeMenu.delegate; nativeItem.action = @selector(itemFired:); // Someone's adding new items after aboutToShow() was emitted - if (isOpen() && nativeItem) + if (isOpen() && nativeItem && item->menu()) item->menu()->setAttachedItem(nativeItem); item->setParentEnabled(isEnabled()); -- cgit v1.2.3