* nsmenu.m (ns_update_menubar): Correct NSTRACE.
authorJan Djärv <jan.h.d@swipnet.se>
Sat, 30 Mar 2013 09:57:27 +0000 (10:57 +0100)
committerJan Djärv <jan.h.d@swipnet.se>
Sat, 30 Mar 2013 09:57:27 +0000 (10:57 +0100)
(x_activate_menubar): Update the menu with title that matches
ns_get_pending_menu_title, and call
ns_check_pending_openmenu.
(menuWillOpen:): New method.
(menuNeedsUpdate:): Add check for ! COCOA || OSX < 10.5 (Bug#12698).

* nsterm.h (ns_get_pending_menu_title, ns_check_menu_open)
(ns_check_pending_open_menu): Declare.

* nsterm.m (menu_will_open_state, menu_mouse_point)
(menu_pending_title): New varaibles.
(ns_get_pending_menu_title, ns_check_menu_open)
(ns_check_pending_open_menu): New functions.

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

index 14e21e4..9899f32 100644 (file)
@@ -1,3 +1,20 @@
+2013-03-30  Jan Djärv  <jan.h.d@swipnet.se>
+
+       * nsterm.h (ns_get_pending_menu_title, ns_check_menu_open)
+       (ns_check_pending_open_menu): Declare.
+
+       * nsmenu.m (ns_update_menubar): Correct NSTRACE.
+       (x_activate_menubar): Update the menu with title that matches
+       ns_get_pending_menu_title, and call
+       ns_check_pending_openmenu (Bug#12698).
+       (menuWillOpen:): New method.
+       (menuNeedsUpdate:): Add check for ! COCOA || OSX < 10.5 (Bug#12698).
+
+       * nsterm.m (menu_will_open_state, menu_mouse_point)
+       (menu_pending_title): New varaibles.
+       (ns_get_pending_menu_title, ns_check_menu_open)
+       (ns_check_pending_open_menu): New functions.
+
 2013-03-29  Dmitry Antipov  <dmantipov@yandex.ru>
 
        * indent.c (current_column_bol_cache): Remove leftover which is not
index b764d3f..02c5f9e 100644 (file)
@@ -88,14 +88,6 @@ static int trackingMenu;
    ========================================================================== */
 
 
-/* FIXME: not currently used, but should normalize with other terms. */
-void
-x_activate_menubar (struct frame *f)
-{
-    fprintf (stderr, "XXX: Received x_activate_menubar event.\n");
-}
-
-
 /* 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. */
@@ -138,7 +130,7 @@ ns_update_menubar (struct frame *f, bool deep_p, EmacsMenu *submenu)
   long t;
 #endif
 
-  NSTRACE (set_frame_menubar);
+  NSTRACE (ns_update_menubar);
 
   if (f != SELECTED_FRAME ())
       return;
@@ -512,6 +504,29 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p)
   ns_update_menubar (f, deep_p, nil);
 }
 
+void
+x_activate_menubar (struct frame *f)
+{
+  NSArray *a = [[NSApp mainMenu] itemArray];
+  /* Update each submenu separatly so ns_update_menubar don'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_check_pending_open_menu ();
+}
+
+
+
 
 /* ==========================================================================
 
@@ -564,6 +579,14 @@ extern NSString *NSMenuDidBeginTrackingNotification;
   trackingMenu = ([notification name] == NSMenuDidBeginTrackingNotification
                   ? 1 : 0);
 }
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+- (void)menuWillOpen:(NSMenu *)menu
+{
+  ns_check_menu_open (menu);
+}
+#endif
+
 #endif
 
 /* delegate method called when a submenu is being opened: run a 'deep' call
@@ -591,7 +614,12 @@ extern NSString *NSMenuDidBeginTrackingNotification;
   if (trackingMenu == 0)
     return;
 /*fprintf (stderr, "Updating menu '%s'\n", [[self title] UTF8String]); NSLog (@"%@\n", event); */
-  ns_update_menubar (frame, 1, self);
+#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);
+#endif
 }
 
 
index 6bd04b9..a43a904 100644 (file)
@@ -792,6 +792,9 @@ extern int ns_lisp_to_color (Lisp_Object color, NSColor **col);
 extern NSColor *ns_lookup_indexed_color (unsigned long idx, struct frame *f);
 extern unsigned long ns_index_color (NSColor *color, struct frame *f);
 extern void ns_free_indexed_color (unsigned long idx, struct frame *f);
+extern const char *ns_get_pending_menu_title ();
+extern void ns_check_menu_open (NSMenu *menu);
+extern void ns_check_pending_open_menu ();
 #endif
 
 /* C access to ObjC functionality */
index c75167d..9baa95a 100644 (file)
@@ -228,6 +228,25 @@ static struct {
   NULL, 0, 0
 };
 
+/*
+ * State for pending menu activation:
+ * MENU_NONE     Normal state
+ * MENU_PENDING  A menu has been clicked on, but has been canceled so we can
+ *               run lisp to update the menu.
+ * MENU_OPENING  Menu is up to date, and the click event is redone so the menu
+ *               will open.
+ */
+#define MENU_NONE 0
+#define MENU_PENDING 1
+#define MENU_OPENING 2
+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;
+
 /* Convert modifiers in a NeXTstep event to emacs style modifiers.  */
 #define NS_FUNCTION_KEY_MASK 0x800000
 #define NSLeftControlKeyMask    (0x000001 | NSControlKeyMask)
@@ -3388,6 +3407,77 @@ check_native_fs ()
 }
 #endif
 
+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)
+{
+  /* 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
+
+  /* Click in menu bar? */
+  NSArray *a = [[NSApp mainMenu] itemArray];
+  int i;
+  BOOL found = NO;
+  for (i = 0; ! found && i < [a count]; i++)
+    found = menu == [[a objectAtIndex:i] submenu];
+  if (found)
+    {
+      if (menu_will_open_state == MENU_NONE && emacs_event)
+        {
+          NSEvent *theEvent = [NSApp currentEvent];
+          struct frame *emacsframe = SELECTED_FRAME ();
+
+          [menu cancelTracking];
+          menu_will_open_state = MENU_PENDING;
+          emacs_event->kind = MENU_BAR_ACTIVATE_EVENT;
+          EV_TRAILER (theEvent);
+
+          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)
+        {
+          menu_will_open_state = MENU_NONE;
+        }
+    }
+#endif
+}
+
+/* Redo saved menu click if state is MENU_PENDING.  */
+void
+ns_check_pending_open_menu ()
+{
+#ifdef NS_IMPL_COCOA
+  if (menu_will_open_state == MENU_PENDING)
+    {
+      CGEventSourceRef source
+        = CGEventSourceCreate (kCGEventSourceStateHIDSystemState);
+
+      CGEventRef event = CGEventCreateMouseEvent (source,
+                                                  kCGEventLeftMouseDown,
+                                                  menu_mouse_point,
+                                                  kCGMouseButtonLeft);
+      CGEventSetType (event, kCGEventLeftMouseDown);
+      CGEventPost (kCGHIDEventTap, event);
+      CFRelease (event);
+      CFRelease (source);
+
+      menu_will_open_state = MENU_OPENING;
+    }
+#endif
+}
+
+
 static int
 ns_read_socket (struct terminal *terminal, struct input_event *hold_quit)
 /* --------------------------------------------------------------------------