From: Jan Djärv Date: Sat, 30 Mar 2013 09:57:27 +0000 (+0100) Subject: * nsmenu.m (ns_update_menubar): Correct NSTRACE. X-Git-Url: http://git.hcoop.net/bpt/emacs.git/commitdiff_plain/6d01f1feafdbcf90b4a602ed6ae4a3f543f5b8b9 * 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. --- 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 + + * 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 * 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) /* --------------------------------------------------------------------------