]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix crash in NS menu code
authorAlan Third <alan@idiocy.org>
Mon, 28 Dec 2020 15:02:39 +0000 (15:02 +0000)
committerAlan Third <alan@idiocy.org>
Mon, 28 Dec 2020 18:03:48 +0000 (18:03 +0000)
* 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.

src/nsmenu.m

index 3f0cd0c6ed4b7c18992e56d83c2fc4b459e4bdd1..23699627b15f1d3994b5a7be2ebc5fa86546cae7 100644 (file)
@@ -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;