Merge from emacs-24; up to 2013-01-03T02:37:57Z!rgm@gnu.org
[bpt/emacs.git] / src / nsmenu.m
index 1d3d111..19f1617 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 frame: f];
         }
 
     }
@@ -504,23 +504,11 @@ 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;
-    }
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+  ns_update_menubar (f, true, nil);
   ns_check_pending_open_menu ();
 #endif
+#endif
 }
 
 
@@ -541,6 +529,7 @@ x_activate_menubar (struct frame *f)
 /* override designated initializer */
 - initWithTitle: (NSString *)title
 {
+  frame = 0;
   if ((self = [super initWithTitle: title]))
     [self setAutoenablesItems: NO];
   return self;
@@ -576,17 +565,36 @@ extern NSString *NSMenuDidBeginTrackingNotification;
   /* Update menu in menuNeedsUpdate only while tracking menus.  */
   trackingMenu = ([notification name] == NSMenuDidBeginTrackingNotification
                   ? 1 : 0);
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+  if (! trackingMenu) ns_check_menu_open (nil);
+#endif
 }
 
 #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_7
+  // 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 +620,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 +729,11 @@ extern NSString *NSMenuDidBeginTrackingNotification;
 
 
 - (void)fillWithWidgetValue: (void *)wvptr
+{
+  [self fillWithWidgetValue: wvptr frame: (struct frame *)nil];
+}
+
+- (void)fillWithWidgetValue: (void *)wvptr frame: (struct frame *)f
 {
   widget_value *wv = (widget_value *)wvptr;
 
@@ -735,7 +748,12 @@ extern NSString *NSMenuDidBeginTrackingNotification;
 
       if (wv->contents)
         {
-          EmacsMenu *submenu = [[EmacsMenu alloc] initWithTitle: [item title]];
+          EmacsMenu *submenu;
+
+          if (f)
+            submenu = [[EmacsMenu alloc] initWithTitle: [item title] frame:f];
+          else
+            submenu = [[EmacsMenu alloc] initWithTitle: [item title]];
 
           [self setSubmenu: submenu forItem: item];
           [submenu fillWithWidgetValue: wv->contents];
@@ -806,7 +824,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;
@@ -815,6 +833,8 @@ ns_menu_show (FRAME_PTR f, int x, int y, bool for_click, bool keymaps,
   ptrdiff_t specpdl_count = SPECPDL_INDEX ();
   widget_value *wv, *first_wv = 0;
 
+  block_input ();
+
   p.x = x; p.y = y;
 
   /* now parse stage 2 as in ns_update_menubar */
@@ -1017,6 +1037,7 @@ ns_menu_show (FRAME_PTR f, int x, int y, bool for_click, bool keymaps,
   popup_activated_flag = 0;
   [[FRAME_NS_VIEW (SELECTED_FRAME ()) window] makeKeyWindow];
 
+  unblock_input ();
   return tem;
 }
 
@@ -1028,7 +1049,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,7 +1061,7 @@ 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
    -------------------------------------------------------------------------- */
@@ -1221,7 +1242,7 @@ update_frame_tool_bar (FRAME_PTR f)
 {
   /* 1) come up w/identifier */
   NSString *identifier
-      = [NSString stringWithFormat: @"%u", [img hash]];
+    = [NSString stringWithFormat: @"%lu", (unsigned long)[img hash]];
   [activeIdentifiers addObject: identifier];
 
   /* 2) create / reuse item */
@@ -1240,7 +1261,7 @@ update_frame_tool_bar (FRAME_PTR f)
 #ifdef NS_IMPL_GNUSTEP
   [self insertItemWithItemIdentifier: identifier atIndex: idx];
 #endif
-  
+
   [item setTag: tag];
   [item setEnabled: enabled];
 
@@ -1410,10 +1431,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)
@@ -1427,13 +1448,11 @@ pop_down_menu (Lisp_Object arg)
 
   xfree (unwind_data);
   unblock_input ();
-
-  return Qnil;
 }
 
 
 Lisp_Object
-ns_popup_dialog (Lisp_Object position, Lisp_Object contents, Lisp_Object header)
+ns_popup_dialog (Lisp_Object position, Lisp_Object header, Lisp_Object contents)
 {
   id dialog;
   Lisp_Object window, tem, title;
@@ -1492,7 +1511,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];
@@ -1506,7 +1525,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 */
@@ -1667,7 +1686,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))
     {
@@ -1851,11 +1870,11 @@ ns_popup_dialog (Lisp_Object position, Lisp_Object contents, Lisp_Object header)
   while (popup_activated_flag)
     {
       NSTimer *tmo = nil;
-      EMACS_TIME next_time = timer_check ();
+      struct timespec next_time = timer_check ();
 
-      if (EMACS_TIME_VALID_P (next_time))
+      if (timespec_valid_p (next_time))
         {
-          double time = EMACS_TIME_TO_DOUBLE (next_time);
+          double time = timespectod (next_time);
           tmo = [NSTimer timerWithTimeInterval: time
                                         target: self
                                       selector: @selector (timeout_handler:)
@@ -1900,34 +1919,6 @@ DEFUN ("ns-reset-menu", Fns_reset_menu, Sns_reset_menu, 0, 0, 0,
 }
 
 
-DEFUN ("x-popup-dialog", Fx_popup_dialog, Sx_popup_dialog, 2, 3, 0,
-       doc: /* Pop up a dialog box and return user's selection.
-POSITION specifies which frame to use.
-This is normally a mouse button event or a window or frame.
-If POSITION is t, it means to use the frame the mouse is on.
-The dialog box appears in the middle of the specified frame.
-
-CONTENTS specifies the alternatives to display in the dialog box.
-It is a list of the form (DIALOG ITEM1 ITEM2...).
-Each ITEM is a cons cell (STRING . VALUE).
-The return value is VALUE from the chosen item.
-
-An ITEM may also be just a string--that makes a nonselectable item.
-An ITEM may also be nil--that means to put all preceding items
-on the left of the dialog box and all following items on the right.
-\(By default, approximately half appear on each side.)
-
-If HEADER is non-nil, the frame title for the box is "Information",
-otherwise it is "Question".
-
-If the user gets rid of the dialog box without making a valid choice,
-for instance using the window manager, then this produces a quit and
-`x-popup-dialog' does not return.  */)
-     (Lisp_Object position, Lisp_Object contents, Lisp_Object header)
-{
-  return ns_popup_dialog (position, contents, header);
-}
-
 DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p, Smenu_or_popup_active_p, 0, 0, 0,
        doc: /* Return t if a menu or popup dialog is active.  */)
      (void)
@@ -1949,7 +1940,6 @@ syms_of_nsmenu (void)
      update menus there.  */
   trackingMenu = 1;
 #endif
-  defsubr (&Sx_popup_dialog);
   defsubr (&Sns_reset_menu);
   defsubr (&Smenu_or_popup_active_p);