Alan Third schrieb am Sa., 19. Mai 2018 um 12:34 Uhr: > On Sat, May 19, 2018 at 04:42:54PM +1200, Nick Helm wrote: > > On Sat, 19 May 2018 at 07:36:32 +1200, Alan Third wrote: > > > > > There are two problems, though. > > > > > > * Application Menu > > > > > > When the last NS frame is deleted the menus aren’t updated, so I think > > > they’ll be the menus as defined for the last frame. They should > > > probably be cut right back to just the ‘Emacs’ menu, and perhaps > > > ‘help’. > > > > This is interesting. I think we could tweak the EmacsMenu side of things > > to do this, even with the current code. We'd want to make sure to > > include some kind of new frame command somewhere. > > > > These menus are derived dynamically from Lisp though, and it might be > > difficult to convince it to provide valid entries when no frame is > > selected. > > I’m not sure if the ‘Emacs’ menu is derived from lisp. If you turn off > menus completely it still exists. > > > One way around that might be to create a new menu containing > > static NSMenu versions of File and Help, much like we do for the appMenu > > now. When no frame is selected and there are no Lisp menu entries, we > > switch mainMenu to this new menu. When a frame is created, we switch > > back. > > Perhaps we could modify ns_update_menubar to handle the case where > there’s no frame? > > > > * Dock Menu > > > > > > This has a ‘new frame’ option but just plain doesn’t work. I think the > > > problem is the way it’s trying to create a new frame:... > > > > > > This seems to rely on there being an existing NS frame, but we’ve > > > deleted the last one. I assume if we were clever we’d be able to use > > > the, still open, terminal frame. > > > > With all of this discussion, I feel like I'm missing something really > > fundamental. Putting emacsclient aside for a moment, if we were dealing > > with a standard Cocoa app, the window server and NSApp loop would keep > > running in the background and we could close everything, then create a > > new frame (as a view on an NSWindow instance) as needed. > > FWIW, the NSApp loop does keep running, but it’s embedded in ns_select > and ns_read_socket. We can, in theory, create a new frame directly, > but it needs to run through Emacs first. > > > How is the architecture of Emacs on NS so different from standard Cocoa > > that these kinds of workarounds are necessary? > > The fundamental issue in the NS port is that we have two bosses: the > NSApp run loop, and Emacs lisp, and we need to mediate between them. > > A standard Cocoa app responds to events from the NSApp loop, and > that’s pretty much it. As I understand it you can make a complete app > without very much work this way. The NSApp loop is the boss. > > Emacs’ architecture expects everything to go through lisp and it makes > decisions on what we do with our GUI. Emacs lisp is the boss. > > We can’t react directly to NS events like a normal NS app. We get > input from the NSApp loop and send it to lisp. Lisp might tell us to > do something any time. We also need to know how Emacs expects to do > things (the GUI code was originally written for a completely different > platform after all) and then try and make Cocoa/GNUstep handle it > correctly. > > In an ideal world (and I believe the Mac port has gone this way) we > would put the NSApp run loop in one thread, and Emacs lisp in another > and let them communicate with each other asynchronously. This wouldn’t > solve everything, but it would make some of our problems easier. > > We can’t easily do that, though, as the inter‐thread communication > systems provided in Objective‐C are either a pain to implement with > complex types like Lisp_Object, or aren’t compatible with GCC and/or > GNUstep (Grand Central Dispatch). > > Additionally I think we sometimes have workarounds fixing workarounds > fixing hacks, all written by different people, and the simplest > solution is to strip it right back to the basics. I have a feeling the > menus fall somewhat into this category, and the drag‐n‐drop stuff > definitely does. > > > In an ideal world (and I believe the Mac port has gone this way) we > TL;DR: Emacs internal architecture doesn’t fit well into the standard > NS application architecture. > FWIW, this problem description and the solution seem the same on every OS/toolkit: the Lisp interpreter should always run in a background thread and communicate with the UI thread asynchronously through message passing.