Open turbo opened 3 months ago
Hi @turbo!
I am very surprised by this issue. Both for the proposal itself, and for the level of detail when proposing the solution. Thank you for the time you have dedicated and your involvement in the project.
It is a necessary feature, which will open the use of NAppGUI to existing applications, with their own runLoop. A few years ago, in an early version of NAppGUI I implemented this support (Windows only) to create an experimental interface for a Rhinoceros 3D plugin. The const bool_t with_run_loop
parameter of osapp_init_imp
is a legacy from those times.
I'll get into this as soon as possible.
Please email me with your Discord username. We have created a server with a small community of active users, where we have several open development lines.
Thanks again, and welcome to NAppGUI
My Discord user is summarity
(or send an invite to mail@summarity.com
) 🙂.
This is a feature request to extend the OSApp API to allow external message pumping.
The goal is to allow NApp to be integrated into programs that already have their own event loop (async runtimes, game engines, etc.). This proposal would make
osapp_run
non-blocking and expose an API function callable by the program's main thread to manually process events.The default would remain exactly as it works now, manual pumping would be an option. This is already partially in place for Windows, but not for other platforms.
Current Implementation
This is my understanding of the current implementation, which might be wrong (please correct me).
osapp_run
function.app->with_run_loop
, however it is ignored for macOS (src) and GTK (src), and for Windows it is always true and callsosgui_message_loop
while
loop inosapp_run
that manually pumps events by callingosgui_message_loop
osapp_run
calls[(NSApplication*)app run];
, which is a blocking call (Cocoa handles pumping internally)osapp_run
callsg_application_run
, which is a blocking call (GTK handles pumping internally)Proposed changes
First, implement
osgui_message_loop
on all platforms:[NsApp run]
, instead call it and then call[NSApp stop:nil];
from within theapplicationDidFinishLaunching
hook. This enables manual pumping. Then create aosgui_message_loop_imp
function that dequeues events from[NSApp nextEventMatchingMask ...]
and pumps them to[NSApp sendEvent:event];
g_application_run
, do the same setup, but create aosgui_message_loop_imp
function that keeps callingg_main_context_iteration
to cause GTK to pump events internally. This call must be made withg_main_context_iteration
in non-blocking mode, otherwise the internal pump blocks until the next event.Then, add an
app->blocking
flag that is TRUE by default. This flag must be respected in theosgui_message_loop_imp
implementations. If it is TRUE, then the message loops need to be blocking, as is the case for Windows today (src). However, when it is FALSE, the message loop must return after processing events in the queue.Finally, the
osgui_message_loop
function should be available via the public API so that in non-blocking mode, the parent program can call it.Result
Now applications can launch NApp in two different ways:
osmain
, and NApp/OSApp handles the event loop - nothing changes and no code changes are required for current appsapp->blocking
to false): Callosmain
, which immediately returns. The calling app then callsosgui_message_loop
from its own event loop or scheduler to keep the OSApp instance alive. When it's done, it calls the terminate API to clean up.This is how libraries like GLFW work today, and indeed I'm currently integrating NApp into an engine that has a competing event loop in the main thread. Here are details on the changes required:
[NsApp run]
into non-blocking calls (based directly on what GLFW does)g_application_run
into non-blocking callsAll in all, these changes should not require much additional code, OSApp is almost there and the concept of a message loop function is already in place.