emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 1645863: Fix crash in NS menu code


From: Alan Third
Subject: master 1645863: Fix crash in NS menu code
Date: Mon, 28 Dec 2020 13:05:52 -0500 (EST)

branch: master
commit 16458631d49a19bd496a45517264059383e18c18
Author: Alan Third <alan@idiocy.org>
Commit: Alan Third <alan@idiocy.org>

    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.
---
 src/nsmenu.m | 101 +++++++++++++++++++++++++++--------------------------------
 1 file changed, 46 insertions(+), 55 deletions(-)

diff --git a/src/nsmenu.m b/src/nsmenu.m
index 3f0cd0c..2369962 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;



reply via email to

[Prev in Thread] Current Thread [Next in Thread]