From: Jan Djärv Date: Sun, 18 Dec 2011 14:50:19 +0000 (+0100) Subject: Adapt code from AquaEmacs to handle occasional blank menus. X-Git-Tag: emacs-pretest-24.0.93~150 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=5fecd5fce0bac31f1d39d84caa9d2c444c8e7e01;p=emacs.git Adapt code from AquaEmacs to handle occasional blank menus. * nsmenu.m (trackingMenu): New variable. (NSMenuDidBeginTrackingNotification): Declare if OSX < 10.5 and NS_IMPL_COCOA. (trackingNotification): New method (from AquaEmacs). (menuNeedsUpdate): Expand comment and return if trackingMenu is 0, from AquaEmacs. (syms_of_nsmenu): Set trackingMenu to 1 if not NS_IMPL_COCOA. * nsterm.m (ns_term_init): Subscribe for notifications NSMenuDidBeginTrackingNotification and NSMenuDidEndTrackingNotification to method trackingNotification in EmacsMenu. Fixes: debbugs:7030 --- diff --git a/src/ChangeLog b/src/ChangeLog index 610079fe321..14eb35bdc1c 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,5 +1,17 @@ 2011-12-18 Jan Djärv + * nsterm.m (ns_term_init): Subscribe for notifications + NSMenuDidBeginTrackingNotification and NSMenuDidEndTrackingNotification + to method trackingNotification in EmacsMenu. + + * nsmenu.m (trackingMenu): New variable. + (NSMenuDidBeginTrackingNotification): Declare if OSX < 10.5 and + NS_IMPL_COCOA. + (trackingNotification): New method (from AquaEmacs). + (menuNeedsUpdate): Expand comment and return if trackingMenu is 0, + from AquaEmacs (Bug#7030). + (syms_of_nsmenu): Set trackingMenu to 1 if not NS_IMPL_COCOA. + * nsselect.m (CUT_BUFFER_SUPPORT): Remove define. (symbol_to_nsstring): Fix indentation. (ns_symbol_to_pb): New function. diff --git a/src/nsmenu.m b/src/nsmenu.m index 951282910ac..d599cdb6ce5 100644 --- a/src/nsmenu.m +++ b/src/nsmenu.m @@ -74,6 +74,10 @@ EmacsMenu *mainMenu, *svcsMenu, *dockMenu; static int popup_activated_flag; static NSModalSession popupSession; +/* Nonzero means we are tracking and updating menus. */ +static int trackingMenu; + + /* NOTE: toolbar implementation is at end, following complete menu implementation. */ @@ -543,21 +547,44 @@ set_frame_menubar (struct frame *f, int first_time, int deep_p) frame = f; } +#ifdef NS_IMPL_COCOA +#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5 +extern NSString *NSMenuDidBeginTrackingNotification; +#endif +#endif + +#ifdef NS_IMPL_COCOA +-(void)trackingNotification:(NSNotification *)notification +{ + /* Update menu in menuNeedsUpdate only while tracking menus. */ + trackingMenu = ([notification name] == NSMenuDidBeginTrackingNotification + ? 1 : 0); +} +#endif /* delegate method called when a submenu is being opened: run a 'deep' call to set_frame_menubar */ - (void)menuNeedsUpdate: (NSMenu *)menu { - NSEvent *event; if (!FRAME_LIVE_P (frame)) return; - event = [[FRAME_NS_VIEW (frame) window] currentEvent]; - /* HACK: Cocoa/Carbon will request update on every keystroke + + /* Cocoa/Carbon will request update on every keystroke via IsMenuKeyEvent -> CheckMenusForKeyEvent. These are not needed since key equivalents are handled through emacs. - On Leopard, even keystroke events generate SystemDefined events, but - their subtype is 8. */ - if ([event type] != NSSystemDefined || [event subtype] == 8 + On Leopard, even keystroke events generate SystemDefined event. + Third-party applications that enhance mouse / trackpad + interaction, or also VNC/Remote Desktop will send events + of type AppDefined rather than SysDefined. + Menus will fail to show up if they haven't been initialized. + AppDefined events may lack timing data. + + Thus, we rely on the didBeginTrackingNotification notification + as above to indicate the need for updates. + From 10.6 on, we could also use -[NSMenu propertiesToUpdate]: In the + key press case, NSMenuPropertyItemImage (e.g.) won't be set. + */ + if (trackingMenu == 0 /* Also, don't try this if from an event picked up asynchronously, as lots of lisp evaluation happens in ns_update_menubar. */ || handling_signal != 0) @@ -1795,6 +1822,11 @@ DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p, Smenu_or_popup_active_ void syms_of_nsmenu (void) { +#ifndef NS_IMPL_COCOA + /* Don't know how to keep track of this in Next/Open/Gnustep. Always + update menus there. */ + trackingMenu = 1; +#endif defsubr (&Sx_popup_dialog); defsubr (&Sns_reset_menu); defsubr (&Smenu_or_popup_active_p); diff --git a/src/nsterm.m b/src/nsterm.m index 1d645943065..055959bf2ac 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -4203,6 +4203,15 @@ ns_term_init (Lisp_Object display_name) [NSApp setServicesMenu: svcsMenu]; /* Needed at least on Cocoa, to get dock menu to show windows */ [NSApp setWindowsMenu: [[NSMenu alloc] init]]; + + [[NSNotificationCenter defaultCenter] + addObserver: mainMenu + selector: @selector (trackingNotification:) + name: NSMenuDidBeginTrackingNotification object: mainMenu]; + [[NSNotificationCenter defaultCenter] + addObserver: mainMenu + selector: @selector (trackingNotification:) + name: NSMenuDidEndTrackingNotification object: mainMenu]; } #endif /* MAC OS X menu setup */