* nsmenu.m (ns_update_menubar): Call fillWithWidgetValue:setDelegate.
authorJan Djärv <jan.h.d@swipnet.se>
Sun, 11 Aug 2013 14:57:12 +0000 (16:57 +0200)
committerJan Djärv <jan.h.d@swipnet.se>
Sun, 11 Aug 2013 14:57:12 +0000 (16:57 +0200)
(x_activate_menubar): Update the whole menu.
(trackingNotification:): Call ns_check_menu_open if tracking ends.
(menuWillOpen:): Increment trackingMenu.  For OSX <= 10.6, exit if
current event is not NSSystemDefined.
Call ns_check_menu_open only if trackingMenu is 2.
(menuDidClose:): New method, decrease trackingMenu.
(fillWithWidgetValue:setDelegate:): New method.
(fillWithWidgetValue:): Call the above.

* nsterm.h (EmacsMenu): Add fillWithWidgetValue:setDelegate:

* nsterm.m (menu_pending_title, ns_get_pending_menu_title): Remove.
(ns_check_menu_open): Handle menu == nil.  Remove assignment to
menu_pending_title.

Fixes: debbugs:15001

src/ChangeLog
src/nsmenu.m
src/nsterm.h
src/nsterm.m

index e114db5..58806f4 100644 (file)
@@ -1,3 +1,21 @@
+2013-08-11  Jan Djärv  <jan.h.d@swipnet.se>
+
+       * nsterm.m (menu_pending_title, ns_get_pending_menu_title): Remove.
+       (ns_check_menu_open): Handle menu == nil.  Remove assignment to
+       menu_pending_title.
+
+       * nsmenu.m (ns_update_menubar): Call fillWithWidgetValue:setDelegate.
+       (x_activate_menubar): Update the whole menu.
+       (trackingNotification:): Call ns_check_menu_open if tracking ends.
+       (menuWillOpen:): Increment trackingMenu.  For OSX <= 10.6, exit if
+       current event is not NSSystemDefined (Bug#15001).
+       Call ns_check_menu_open only if trackingMenu is 2.
+       (menuDidClose:): New method, decrease trackingMenu.
+       (fillWithWidgetValue:setDelegate:): New method.
+       (fillWithWidgetValue:): Call the above.
+
+       * nsterm.h (EmacsMenu): Add fillWithWidgetValue:setDelegate:
+
 2013-08-11  Paul Eggert  <eggert@cs.ucla.edu>
 
        Omit some unnecessary casts.
index 5b3c214..1ae2a34 100644 (file)
@@ -366,7 +366,7 @@ ns_update_menubar (struct frame *f, bool deep_p, EmacsMenu *submenu)
         }
       else
         {
-          [menu fillWithWidgetValue: first_wv->contents];
+          [menu fillWithWidgetValue: first_wv->contents setDelegate:YES];
         }
 
     }
@@ -504,21 +504,7 @@ void
 x_activate_menubar (struct frame *f)
 {
 #ifdef NS_IMPL_COCOA
-  NSArray *a = [[NSApp mainMenu] itemArray];
-  /* Update each submenu separately so ns_update_menubar doesn't reset
-     the delegate.  */
-  int i = 0;
-  while (i < [a count])
-    {
-      EmacsMenu *menu = (EmacsMenu *)[[a objectAtIndex:i] submenu];
-      const char *title = [[menu title] UTF8String];
-      if (strcmp (title, ns_get_pending_menu_title ()) == 0)
-        {
-          ns_update_menubar (f, true, menu);
-          break;
-        }
-      ++i;
-    }
+  ns_update_menubar (f, true, nil);
   ns_check_pending_open_menu ();
 #endif
 }
@@ -576,17 +562,34 @@ extern NSString *NSMenuDidBeginTrackingNotification;
   /* Update menu in menuNeedsUpdate only while tracking menus.  */
   trackingMenu = ([notification name] == NSMenuDidBeginTrackingNotification
                   ? 1 : 0);
+  if (! trackingMenu) ns_check_menu_open (nil);
 }
 
 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
 - (void)menuWillOpen:(NSMenu *)menu
 {
-  ns_check_menu_open (menu);
-}
-#endif
+  ++trackingMenu;
 
+#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_6
+  // On 10.6 we get repeated calls, only the one for NSSystemDefined is "real".
+  if ([[NSApp currentEvent] type] != NSSystemDefined) return;
 #endif
 
+  /* When dragging from one menu to another, we get willOpen followed by didClose,
+     i.e. trackingMenu == 3 in willOpen and then 2 after didClose.
+     We have updated all menus, so avoid doing it when trackingMenu == 3.  */
+  if (trackingMenu == 2)
+    ns_check_menu_open (menu);
+}
+
+- (void)menuDidClose:(NSMenu *)menu
+{
+  --trackingMenu;
+}
+#endif /* OSX >= 10.5 */
+
+#endif /* NS_IMPL_COCOA */
+
 /* delegate method called when a submenu is being opened: run a 'deep' call
    to set_frame_menubar */
 - (void)menuNeedsUpdate: (NSMenu *)menu
@@ -721,6 +724,11 @@ extern NSString *NSMenuDidBeginTrackingNotification;
 
 
 - (void)fillWithWidgetValue: (void *)wvptr
+{
+  [self fillWithWidgetValue: wvptr setDelegate:NO];
+}
+
+- (void)fillWithWidgetValue: (void *)wvptr setDelegate: (BOOL)set
 {
   widget_value *wv = (widget_value *)wvptr;
 
@@ -737,6 +745,9 @@ extern NSString *NSMenuDidBeginTrackingNotification;
         {
           EmacsMenu *submenu = [[EmacsMenu alloc] initWithTitle: [item title]];
 
+#ifdef NS_IMPL_COCOA
+          if (set) [submenu setDelegate: submenu];
+#endif
           [self setSubmenu: submenu forItem: item];
           [submenu fillWithWidgetValue: wv->contents];
           [submenu release];
index 1303a47..cf8e26d 100644 (file)
@@ -196,6 +196,7 @@ typedef float EmacsCGFloat;
 - (NSString *)parseKeyEquiv: (const char *)key;
 - (NSMenuItem *)addItemWithWidgetValue: (void *)wvptr;
 - (void)fillWithWidgetValue: (void *)wvptr;
+- (void)fillWithWidgetValue: (void *)wvptr setDelegate: (BOOL)set;
 - (EmacsMenu *)addSubmenuWithTitle: (const char *)title forFrame: (struct frame *)f;
 - (void) clear;
 - (Lisp_Object)runMenuAt: (NSPoint)p forFrame: (struct frame *)f
index d391d39..e519244 100644 (file)
@@ -250,9 +250,6 @@ static int menu_will_open_state = MENU_NONE;
 
 /* Saved position for menu click.  */
 static CGPoint menu_mouse_point;
-
-/* Title for the menu to open.  */
-static char *menu_pending_title = 0;
 #endif
 
 /* Convert modifiers in a NeXTstep event to emacs style modifiers.  */
@@ -3397,12 +3394,6 @@ check_native_fs ()
 /* GNUStep and OSX <= 10.4 does not have cancelTracking.  */
 #if defined (NS_IMPL_COCOA) && \
   MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
-const char *
-ns_get_pending_menu_title ()
-{
-  return menu_pending_title;
-}
-
 /* Check if menu open should be cancelled or continued as normal.  */
 void
 ns_check_menu_open (NSMenu *menu)
@@ -3411,6 +3402,14 @@ ns_check_menu_open (NSMenu *menu)
   NSArray *a = [[NSApp mainMenu] itemArray];
   int i;
   BOOL found = NO;
+
+  if (menu == nil) // Menu tracking ended.
+    {
+      if (menu_will_open_state == MENU_OPENING)
+        menu_will_open_state = MENU_NONE;
+      return;
+    }
+
   for (i = 0; ! found && i < [a count]; i++)
     found = menu == [[a objectAtIndex:i] submenu];
   if (found)
@@ -3428,8 +3427,6 @@ ns_check_menu_open (NSMenu *menu)
           CGEventRef ourEvent = CGEventCreate (NULL);
           menu_mouse_point = CGEventGetLocation (ourEvent);
           CFRelease (ourEvent);
-          xfree (menu_pending_title);
-          menu_pending_title = xstrdup ([[menu title] UTF8String]);
         }
       else if (menu_will_open_state == MENU_OPENING)
         {