aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Djärv <[email protected]>2013-03-30 10:57:27 +0100
committerJan Djärv <[email protected]>2013-03-30 10:57:27 +0100
commit6d01f1feafdbcf90b4a602ed6ae4a3f543f5b8b9 (patch)
tree0ef1e43f227757901b27e5c113203c53af34a827
parent73572c72157ae732679c858bc5f3497473649b2f (diff)
* 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. (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.
-rw-r--r--src/ChangeLog17
-rw-r--r--src/nsmenu.m48
-rw-r--r--src/nsterm.h3
-rw-r--r--src/nsterm.m90
4 files changed, 148 insertions, 10 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 14e21e402d..9899f32fc4 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,20 @@
+2013-03-30 Jan Djärv <[email protected]>
+
+ * 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 <[email protected]>
* indent.c (current_column_bol_cache): Remove leftover which is not
diff --git a/src/nsmenu.m b/src/nsmenu.m
index b764d3f595..02c5f9e6e5 100644
--- a/src/nsmenu.m
+++ b/src/nsmenu.m
@@ -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
}
diff --git a/src/nsterm.h b/src/nsterm.h
index 6bd04b9668..a43a90428d 100644
--- a/src/nsterm.h
+++ b/src/nsterm.h
@@ -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 */
diff --git a/src/nsterm.m b/src/nsterm.m
index c75167d753..9baa95a506 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -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)
/* --------------------------------------------------------------------------