* nsmenu.m (ns_update_menubar): Call fillWithWidgetValue:setDelegate.
[bpt/emacs.git] / src / nsmenu.m
index baa6839..1ae2a34 100644 (file)
@@ -45,8 +45,6 @@ Carbon version by Yamamoto Mitsuharu. */
 #include <sys/types.h>
 #endif
 
-#define MenuStagger 10.0
-
 #if 0
 int menu_trace_num = 0;
 #define NSTRACE(x)        fprintf (stderr, "%s:%d: [%d] " #x "\n",        \
@@ -112,7 +110,7 @@ popup_activated (void)
     2) deep_p, submenu = nil: Recompute all submenus.
     3) deep_p, submenu = non-nil: Update contents of a single submenu.
    -------------------------------------------------------------------------- */
-void
+static void
 ns_update_menubar (struct frame *f, bool deep_p, EmacsMenu *submenu)
 {
   NSAutoreleasePool *pool;
@@ -368,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];
         }
 
     }
@@ -505,22 +503,10 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p)
 void
 x_activate_menubar (struct frame *f)
 {
-  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;
-    }
+#ifdef NS_IMPL_COCOA
+  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
@@ -612,8 +615,8 @@ extern NSString *NSMenuDidBeginTrackingNotification;
   if (trackingMenu == 0)
     return;
 /*fprintf (stderr, "Updating menu '%s'\n", [[self title] UTF8String]); NSLog (@"%@\n", event); */
-#if ! defined(NS_IMPL_COCOA) || \
-  MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
+#if (! defined (NS_IMPL_COCOA) \
+     || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5)
   /* Don't know how to do this for anything other than OSX >= 10.5
      This is wrong, as it might run Lisp code in the event loop.  */
   ns_update_menubar (frame, true, self);
@@ -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,10 +745,13 @@ 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];
-          [item setAction: nil];
+          [item setAction: (SEL)nil];
         }
     }
 
@@ -757,7 +768,7 @@ extern NSString *NSMenuDidBeginTrackingNotification;
 {
   NSString *titleStr = [NSString stringWithUTF8String: title];
   NSMenuItem *item = [self addItemWithTitle: titleStr
-                                     action: nil /*@selector (menuDown:) */
+                                     action: (SEL)nil /*@selector (menuDown:) */
                               keyEquivalent: @""];
   EmacsMenu *submenu = [[EmacsMenu alloc] initWithTitle: titleStr frame: f];
   [self setSubmenu: submenu forItem: item];
@@ -806,7 +817,7 @@ extern NSString *NSMenuDidBeginTrackingNotification;
    ========================================================================== */
 
 Lisp_Object
-ns_menu_show (FRAME_PTR f, int x, int y, bool for_click, bool keymaps,
+ns_menu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
              Lisp_Object title, const char **error)
 {
   EmacsMenu *pmenu;
@@ -1028,7 +1039,7 @@ ns_menu_show (FRAME_PTR f, int x, int y, bool for_click, bool keymaps,
    ========================================================================== */
 
 void
-free_frame_tool_bar (FRAME_PTR f)
+free_frame_tool_bar (struct frame *f)
 /* --------------------------------------------------------------------------
     Under NS we just hide the toolbar until it might be needed again.
    -------------------------------------------------------------------------- */
@@ -1040,18 +1051,23 @@ free_frame_tool_bar (FRAME_PTR f)
 }
 
 void
-update_frame_tool_bar (FRAME_PTR f)
+update_frame_tool_bar (struct frame *f)
 /* --------------------------------------------------------------------------
     Update toolbar contents
    -------------------------------------------------------------------------- */
 {
-  int i;
+  int i, k = 0;
   EmacsView *view = FRAME_NS_VIEW (f);
   NSWindow *window = [view window];
   EmacsToolbar *toolbar = [view toolbar];
 
   block_input ();
+
+#ifdef NS_IMPL_COCOA
   [toolbar clearActive];
+#else
+  [toolbar clearAll];
+#endif
 
   /* update EmacsToolbar as in GtkUtils, build items list */
   for (i = 0; i < f->n_tool_bar_items; ++i)
@@ -1067,6 +1083,15 @@ update_frame_tool_bar (FRAME_PTR f)
       Lisp_Object helpObj;
       const char *helpText;
 
+      /* Check if this is a separator.  */
+      if (EQ (TOOLPROP (TOOL_BAR_ITEM_TYPE), Qt))
+        {
+          /* Skip separators.  Newer OSX don't show them, and on GNUStep they
+             are wide as a button, thus overflowing the toolbar most of
+             the time.  */
+          continue;
+        }
+
       /* If image is a vector, choose the image according to the
         button state.  */
       image = TOOLPROP (TOOL_BAR_ITEM_IMAGES);
@@ -1103,7 +1128,10 @@ update_frame_tool_bar (FRAME_PTR f)
           continue;
         }
 
-      [toolbar addDisplayItemWithImage: img->pixmap idx: i helpText: helpText
+      [toolbar addDisplayItemWithImage: img->pixmap
+                                   idx: k++
+                                   tag: i
+                              helpText: helpText
                                enabled: enabled_p];
 #undef TOOLPROP
     }
@@ -1111,6 +1139,7 @@ update_frame_tool_bar (FRAME_PTR f)
   if (![toolbar isVisible])
       [toolbar setVisible: YES];
 
+#ifdef NS_IMPL_COCOA
   if ([toolbar changed])
     {
       /* inform app that toolbar has changed */
@@ -1132,6 +1161,7 @@ update_frame_tool_bar (FRAME_PTR f)
       [toolbar setConfigurationFromDictionary: newDict];
       [newDict release];
     }
+#endif
 
   FRAME_TOOLBAR_HEIGHT (f) =
     NSHeight ([window frameRectForContentRect: NSMakeRect (0, 0, 0, 0)])
@@ -1159,6 +1189,7 @@ update_frame_tool_bar (FRAME_PTR f)
   [self setDelegate: self];
   identifierToItem = [[NSMutableDictionary alloc] initWithCapacity: 10];
   activeIdentifiers = [[NSMutableArray alloc] initWithCapacity: 8];
+  prevIdentifiers = nil;
   prevEnablement = enablement = 0L;
   return self;
 }
@@ -1180,18 +1211,29 @@ update_frame_tool_bar (FRAME_PTR f)
   enablement = 0L;
 }
 
+- (void) clearAll
+{
+  [self clearActive];
+  while ([[self items] count] > 0)
+    [self removeItemAtIndex: 0];
+}
+
 - (BOOL) changed
 {
   return [activeIdentifiers isEqualToArray: prevIdentifiers] &&
     enablement == prevEnablement ? NO : YES;
 }
 
-- (void) addDisplayItemWithImage: (EmacsImage *)img idx: (int)idx
-                        helpText: (const char *)help enabled: (BOOL)enabled
+- (void) addDisplayItemWithImage: (EmacsImage *)img
+                             idx: (int)idx
+                             tag: (int)tag
+                        helpText: (const char *)help
+                         enabled: (BOOL)enabled
 {
   /* 1) come up w/identifier */
   NSString *identifier
       = [NSString stringWithFormat: @"%u", [img hash]];
+  [activeIdentifiers addObject: identifier];
 
   /* 2) create / reuse item */
   NSToolbarItem *item = [identifierToItem objectForKey: identifier];
@@ -1203,20 +1245,25 @@ update_frame_tool_bar (FRAME_PTR f)
       [item setToolTip: [NSString stringWithUTF8String: help]];
       [item setTarget: emacsView];
       [item setAction: @selector (toolbarClicked:)];
+      [identifierToItem setObject: item forKey: identifier];
     }
 
-  [item setTag: idx];
+#ifdef NS_IMPL_GNUSTEP
+  [self insertItemWithItemIdentifier: identifier atIndex: idx];
+#endif
+
+  [item setTag: tag];
   [item setEnabled: enabled];
 
   /* 3) update state */
-  [identifierToItem setObject: item forKey: identifier];
-  [activeIdentifiers addObject: identifier];
   enablement = (enablement << 1) | (enabled == YES);
 }
 
 /* This overrides super's implementation, which automatically sets
    all items to enabled state (for some reason). */
-- (void)validateVisibleItems { }
+- (void)validateVisibleItems
+{
+}
 
 
 /* delegate methods */
@@ -1239,7 +1286,8 @@ update_frame_tool_bar (FRAME_PTR f)
 - (NSArray *)toolbarAllowedItemIdentifiers: (NSToolbar *)toolbar
 {
   /* return entire set... */
-  return [identifierToItem allKeys];
+  return activeIdentifiers;
+  //return [identifierToItem allKeys];
 }
 
 /* optional and unneeded */
@@ -1373,10 +1421,10 @@ struct Popdown_data
   EmacsDialogPanel *dialog;
 };
 
-static Lisp_Object
-pop_down_menu (Lisp_Object arg)
+static void
+pop_down_menu (void *arg)
 {
-  struct Popdown_data *unwind_data = XSAVE_POINTER (arg, 0);
+  struct Popdown_data *unwind_data = arg;
 
   block_input ();
   if (popup_activated_flag)
@@ -1390,8 +1438,6 @@ pop_down_menu (Lisp_Object arg)
 
   xfree (unwind_data);
   unblock_input ();
-
-  return Qnil;
 }
 
 
@@ -1455,7 +1501,7 @@ ns_popup_dialog (Lisp_Object position, Lisp_Object contents, Lisp_Object header)
   if (NILP (Fcar (Fcdr (contents))))
     /* No buttons specified, add an "Ok" button so users can pop down
        the dialog.  */
-    contents = Fcons (title, Fcons (Fcons (build_string ("Ok"), Qt), Qnil));
+    contents = list2 (title, Fcons (build_string ("Ok"), Qt));
 
   block_input ();
   pool = [[NSAutoreleasePool alloc] init];
@@ -1469,7 +1515,7 @@ ns_popup_dialog (Lisp_Object position, Lisp_Object contents, Lisp_Object header)
     unwind_data->pool = pool;
     unwind_data->dialog = dialog;
 
-    record_unwind_protect (pop_down_menu, make_save_pointer (unwind_data));
+    record_unwind_protect_ptr (pop_down_menu, unwind_data);
     popup_activated_flag = 1;
     tem = [dialog runDialogAt: p];
     unbind_to (specpdl_count, Qnil);  /* calls pop_down_menu */
@@ -1531,7 +1577,7 @@ ns_popup_dialog (Lisp_Object position, Lisp_Object contents, Lisp_Object header)
   [img autorelease];
   [imgView autorelease];
 
-  aStyle = NSTitledWindowMask;
+  aStyle = NSTitledWindowMask|NSClosableWindowMask|NSUtilityWindowMask;
   flag = YES;
   rows = 0;
   cols = 1;
@@ -1599,9 +1645,6 @@ ns_popup_dialog (Lisp_Object position, Lisp_Object contents, Lisp_Object header)
   [self setOneShot: YES];
   [self setReleasedWhenClosed: YES];
   [self setHidesOnDeactivate: YES];
-  [self setStyleMask:
-          NSTitledWindowMask|NSClosableWindowMask|NSUtilityWindowMask];
-
   return self;
 }
 
@@ -1633,7 +1676,7 @@ ns_popup_dialog (Lisp_Object position, Lisp_Object contents, Lisp_Object header)
     }
 
   if (buttons > 0)
-    button_values = (Lisp_Object *) xmalloc (buttons * sizeof (*button_values));
+    button_values = xmalloc (buttons * sizeof *button_values);
 
   for (; XTYPE (list) == Lisp_Cons; list = XCDR (list))
     {