diff options
author | Alan Third <alan@idiocy.org> | 2020-12-28 15:02:39 +0000 |
---|---|---|
committer | Alan Third <alan@idiocy.org> | 2020-12-28 18:03:48 +0000 |
commit | 16458631d49a19bd496a45517264059383e18c18 (patch) | |
tree | 38e5daf188ebd437742c583df21aca6511ebf2be | |
parent | 5e1416fd0a41c4b7d13d3cd6ecedab48ae7b55b5 (diff) | |
download | emacs-16458631d49a19bd496a45517264059383e18c18.tar.gz |
Fix crash in NS menu code
* src/nsmenu.m (ns_update_menubar): Don't assume that the top level
menus are correct when populating the submenus.
(free_frame_menubar): Clear the menu.
([EmacsMenu removeAllItems]): Actually remove all menu items.
-rw-r--r-- | src/nsmenu.m | 101 |
1 files changed, 46 insertions, 55 deletions
diff --git a/src/nsmenu.m b/src/nsmenu.m index 3f0cd0c6ed4..23699627b15 100644 --- a/src/nsmenu.m +++ b/src/nsmenu.m @@ -65,11 +65,22 @@ static int popup_activated_flag; /* Supposed to discard menubar and free storage. Since we share the menubar among frames and update its context for the focused window, - there is nothing to do here. */ + we do not discard the menu. We do, however, want to remove any + existing menu items. */ void free_frame_menubar (struct frame *f) { - return; + id menu = [NSApp mainMenu]; + for (int i = [menu numberOfItems] - 1 ; i >= 0; i--) + { + NSMenuItem *item = [menu itemAtIndex:i]; + NSString *title = [item title]; + + if ([ns_app_name isEqualToString:title]) + continue; + + [menu removeItemAtIndex:i]; + } } @@ -108,7 +119,7 @@ ns_update_menubar (struct frame *f, bool deep_p) NSTRACE ("ns_update_menubar"); - if (f != SELECTED_FRAME ()) + if (f != SELECTED_FRAME () || FRAME_EXTERNAL_MENU_BAR (f) == 0) return; XSETFRAME (Vmenu_updating_frame, f); /*fprintf (stderr, "ns_update_menubar: frame: %p\tdeep: %d\tsub: %p\n", f, deep_p, submenu); */ @@ -317,57 +328,44 @@ ns_update_menubar (struct frame *f, bool deep_p) } /* Now, update the NS menu. */ - if (deep_p) - { - /* This path is typically used when a menu has been clicked. I - think Apple expect us to only update that one menu, however - to update one we need to do the hard work of parsing the - whole tree, so we may as well update them all. */ -#ifdef NS_IMPL_COCOA - int i = 1; -#else - int i = 0; -#endif - for (wv = first_wv->contents; wv; wv = wv->next) - { - /* The contents of wv should match the top level menu. */ - EmacsMenu *submenu = (EmacsMenu*)[[menu itemAtIndex:i++] submenu]; + i = 0; - [submenu fillWithWidgetValue: wv->contents]; - } + /* Make sure we skip the "application" menu, which is always the + first entry in our top-level menu. */ + if (i < [menu numberOfItems]) + { + NSString *title = [[menu itemAtIndex:i] title]; + if ([ns_app_name isEqualToString:title]) + i += 1; } - else + + for (wv = first_wv->contents; wv; wv = wv->next) { - /* Make sure we skip the "application" menu, which is always the - first entry in our top-level menu. */ -#ifdef NS_IMPL_COCOA - int i = 1; -#else - int i = 0; -#endif - for (wv = first_wv->contents; wv; wv = wv->next) - { - if (i < [menu numberOfItems]) - { - NSString *titleStr = [NSString stringWithUTF8String: wv->name]; - NSMenuItem *item = [menu itemAtIndex:i]; - EmacsMenu *submenu = (EmacsMenu*)[item submenu]; + EmacsMenu *submenu; - [item setTitle:titleStr]; - [submenu setTitle:titleStr]; - [submenu removeAllItems]; - } - else - [menu addSubmenuWithTitle: wv->name]; + if (i < [menu numberOfItems]) + { + NSString *titleStr = [NSString stringWithUTF8String: wv->name]; + NSMenuItem *item = [menu itemAtIndex:i]; + submenu = (EmacsMenu*)[item submenu]; - i += 1; + [item setTitle:titleStr]; + [submenu setTitle:titleStr]; + [submenu removeAllItems]; } + else + submenu = [menu addSubmenuWithTitle: wv->name]; - while (i < [menu numberOfItems]) - { - /* Remove any extra items. */ - [menu removeItemAtIndex:i]; - } + if (deep_p) + [submenu fillWithWidgetValue: wv->contents]; + + i += 1; + } + + while (i < [menu numberOfItems]) + { + /* Remove any extra items. */ + [menu removeItemAtIndex:i]; } @@ -541,14 +539,7 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p) int n; for (n = [self numberOfItems]-1; n >= 0; n--) - { - NSMenuItem *item = [self itemAtIndex: n]; - NSString *title = [item title]; - if ([ns_app_name isEqualToString: title] - && ![item isSeparatorItem]) - continue; - [self removeItemAtIndex: n]; - } + [self removeItemAtIndex: n]; #endif needsUpdate = YES; |