GNOME Bugzilla – Bug 766840
gdk event loop needs redesign for Quartz
Last modified: 2018-04-15 00:12:42 UTC
This is a placeholder bug report to track any work done to redesign and reimplement the GDK backend for Quartz. The current design implements a "poll function" that calls this code to get the next event: event = [NSApp nextEventMatchingMask: NSAnyEventMask untilDate: limit_date inMode: NSDefaultRunLoopMode dequeue: YES]; which is extremely different, semantically, from what the X11 and Windows backends do in their poll functions. This code actually causes the processes main CFRunLoop to make a pass through its update/redraw cycle, and it will keep doing that until it goes idle. If anything stops the main CFRunLoop from going idle, this call will never return, and gtk+/gdk/glib's own event loop will not run. What can stop it? Very slow drawing by code using CoreGraphics directly, for example. The current design is baroque, necessitated by being from a time when CFRunLoops could not support CFRunLoopSources that described file descriptors. This hasn't been the case since OS X 10.5 (i.e. a long time ago). The use of a separate "select thread" hasn't been necessary since the introduction of file descriptor support, and it needs to go away. The GDK/glib integration with CFRunLoop needs to be reimplemented to cast everything into CFRunLoop-related objects, and then just use a CFRunLoop directly. This is not a small task. There may be glib source types that are not easily convertible into CFRunLoopSources. If you, Dear Reader, have design ideas or notes on this, please leave them here so that when/if work begins, it can do so as fully informed as possible.
You probably also want to consider the comments on Quartz main loop issues that can be found in bug 704374.
Also related to bug #741450
(In reply to Sebastian Dröge (slomo) from comment #2) > Also related to bug #741450 I don't think the approach outlined there is the correct one (though it could work). I think that the right design is to make GMainContext have a CFRunLoop (the default GMainContext would use the default CFRunLoop). Each new GSource would also be a CFRunLoopSource. Adding a GSource to the GMainContext would actually just be a proxy for adding the corresponding CFRunLoopSource to the corresponding CFRunLoop. Running the GMainContext would just be running the CFRunLoop. There would be no back and forth between two different event loops, and no special technique to "hand control" back and forth. Running a GMainContext would be precisely equivalent to running a CFRunLoop. The hard part is that the glib API breaks out the internals of a GMainContext into many more parts than CFRunLoop does. We have the following API that may or may not map well onto CFRunLoop: GMainContext * g_main_context_default () gboolean g_main_context_iteration () #define g_main_iteration() gboolean g_main_context_pending () #define g_main_pending GSource * g_main_context_find_source_by_id () GSource * g_main_context_find_source_by_user_data () GSource * g_main_context_find_source_by_funcs_user_data () void g_main_context_wakeup () gboolean g_main_context_acquire () void g_main_context_release () gboolean g_main_context_is_owner () gboolean g_main_context_wait () gboolean g_main_context_prepare () gint g_main_context_query () gint g_main_context_check () void g_main_context_dispatch () void g_main_context_set_poll_func () GPollFunc g_main_context_get_poll_func () gint (*GPollFunc) () void g_main_context_add_poll () void g_main_context_remove_poll () gint g_main_depth () GSource * g_main_current_source () #define g_main_set_poll_func() void g_main_context_invoke () void g_main_context_invoke_full () GMainContext * g_main_context_get_thread_default () GMainContext * g_main_context_ref_thread_default () void g_main_context_push_thread_default () void g_main_context_pop_thread_default () For any changes to be accepted as part of glib, every single one of these API entry points needs to have behaviour sufficiently identical to the current system. Notably, things like the wait/prepare/check/dispatch methods are going to be quite hard to "translate" into the Cocoa model.
We're moving to gitlab! As part of this move, we are moving bugs to NEEDINFO if they haven't seen activity in more than a year. If this issue is still important to you and still relevant with GTK+ 3.22 or master, please reopen it and we will migrate it to gitlab.
As announced a while ago, we are migrating to gitlab, and bugs that haven't seen activity in the last year or so will be not be migrated, but closed out in bugzilla. If this bug is still relevant to you, you can open a new issue describing the symptoms and how to reproduce it with gtk 3.22.x or master in gitlab: https://gitlab.gnome.org/GNOME/gtk/issues/new