Subject: bug#31371: 26.1; Menu-bar stops working after search

From: Nick Helm <[email-masked]>
Date: Sun, 13 May 2018 22:09:06 +1200

I think I've worked out what's going on here. I've attached a patch -
could you give it a try and see if works for you? 

When the user types in the search field, NSMenu looks for matching
candidates by creating events to open each menu, trigger an update and
read the results. If the search field already contains text, this
happens as soon as the Help menu opens, either when the user clicks Help
or mouse drags onto the Help menu. 

The code in ns_check_menu_open and ns_check_pending_open_menu that
postpones mouse clicks (to fetch menus from Lisp) also tries to postpone
these drag and search events. When it releases a delayed click on Help
(even if the event wasn't a click to begin with), the menu reopens and
the process loops.

The attached patch gets around this by never postponing mouse drag or
non-user mouse down events.

--- a/src/nsterm.m	2018-05-13 16:45:39.000000000 +1200
+++ b/src/nsterm.m	2018-05-13 16:44:31.000000000 +1200
@@ -4299,14 +4299,22 @@
           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);
+          /*On macOS, the following can cause an event loop when the 
+            Spotlight for Help search field is populated.  Avoid this by
+            not postponing mouse drag and non-user-generated mouse down 
+            events.  (bug#31371).*/
+          if (([theEvent type] == NSEventTypeLeftMouseDown)
+              && [theEvent eventNumber])
+            {
+              [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);
+            }
         }
       else if (menu_will_open_state == MENU_OPENING)
         {

On Wed, 09 May 2018 at 09:40:24 +1200, Alan Third wrote:

> I notice all this code is cocoa only, though. Makes me wonder why
> GNUstep is different. (The menus on GNUstep Emacs are awful, though,
> they flicker constantly.)

I think Cocoa uses a delegate method to update single submenus which
(I've read) isn't supported on GNUStep. This means ns_update_menubar has
to recreate every menu on every call (deep_p is always 1). Maybe that
has something to do with it?