Subject: Re: bug#32864: 26.1; menus don't work correctly in Mac OS Mojave

From: Mattias Engdegård <[email-masked]>
Date: Mon, 3 Jun 2019 19:25:27 +0200

Bug explained:

When the user clicks on the menu bar, Emacs receives a menuWillOpen: message, and immediately cancels the menu by sending cancelTracking. It then returns from the event loop to rebuild the menu, but first synthesises a mouse click on the menu bar in the hope that this will make the menu actually open.

In MacOS Mojave, synthetic mouse events are blocked for security reasons, so this no longer works; the synthetic click is discarded and the menu doesn't open. When the user clicks on the menu bar a second time, Emacs believes it's the synthetic click that was acted upon and happily allows the menu to open.

So why does Emacs do this to begin with? Because the menu contents are generated dynamically from elisp code each time. The standard way to do this in Cocoa is to implement menuNeedsUpdate:, but this requires running arbitrary elisp code inside the event loop, which is undesirable for some reason.

The workarounds mentioned involved adding Emacs to some sort of whitelist for legacy applications, but this cannot be a solution. The synthetic mouse click hack must go away.

Could someone explain why, exactly, elisp code cannot be run inside the event loop? An alternative would be to run elisp code in a different thread, and let menuNeedsUpdate: block until the menu has been updated. I'm not sure what the difference would be.