9 #include "gdkprivate-quartz.h"
10 #include <gdk/gdkdisplayprivate.h>
13 * This file implementations integration between the GLib main loop and
14 * the native system of the Core Foundation run loop and Cocoa event
15 * handling. There are basically two different cases that we need to
16 * handle: either the GLib main loop is in control (the application
17 * has called gtk_main(), or is otherwise iterating the main loop), or
18 * CFRunLoop is in control (we are in a modal operation such as window
19 * resizing or drag-and-drop.)
21 * When the GLib main loop is in control we integrate in native event
22 * handling in two ways: first we add a GSource that handles checking
23 * whether there are native events available, translating native events
24 * to GDK events, and dispatching GDK events. Second we replace the
25 * "poll function" of the GLib main loop with our own version that knows
26 * how to wait for both the file descriptors and timeouts that GLib is
27 * interested in and also for incoming native events.
29 * When CFRunLoop is in control, we integrate in GLib main loop handling
30 * by adding a "run loop observer" that gives us notification at various
31 * points in the run loop cycle. We map these points onto the corresponding
32 * stages of the GLib main loop (prepare, check, dispatch), and make the
33 * appropriate calls into GLib.
35 * Both cases share a single problem: the OS X API's don't allow us to
36 * wait simultaneously for file descriptors and for events. So when we
37 * need to do a blocking wait that includes file descriptor activity, we
38 * push the actual work of calling select() to a helper thread (the
39 * "select thread") and wait for native events in the main thread.
41 * The main known limitation of this code is that if a callback is triggered
42 * via the OS X run loop while we are "polling" (in either case described
43 * above), iteration of the GLib main loop is not possible from within
44 * that callback. If the programmer tries to do so explicitly, then they
45 * will get a warning from GLib "main loop already active in another thread".
48 /******* State for run loop iteration *******/
50 /* Count of number of times we've gotten an "Entry" notification for
51 * our run loop observer.
53 static int current_loop_level = 0;
55 /* Run loop level at which we acquired ownership of the GLib main
56 * loop. See note in run_loop_entry(). -1 means that we don't have
59 static int acquired_loop_level = -1;
61 /* Between run_loop_before_waiting() and run_loop_after_waiting();
62 * whether we we need to call select_thread_collect_poll()
64 static gboolean run_loop_polling_async = FALSE;
66 /* Between run_loop_before_waiting() and run_loop_after_waiting();
67 * max_prioritiy to pass to g_main_loop_check()
69 static gint run_loop_max_priority;
71 /* Timer that we've added to wake up the run loop when a GLib timeout
73 static CFRunLoopTimerRef run_loop_timer = NULL;
75 /* These are the file descriptors that are we are polling out of
76 * the run loop. (We keep the array around and reuse it to avoid
77 * constant allocations.)
79 #define RUN_LOOP_POLLFDS_INITIAL_SIZE 16
80 static GPollFD *run_loop_pollfds;
81 static guint run_loop_pollfds_size; /* Allocated size of the array */
82 static guint run_loop_n_pollfds; /* Number of file descriptors in the array */
84 /******* Other global variables *******/
86 /* Since we count on replacing the GLib main loop poll function as our
87 * method of integrating Cocoa event handling into the GLib main loop
88 * we need to make sure that the poll function is always called even
89 * when there are no file descriptors that need to be polled. To do
90 * this, we add a dummy GPollFD to our event source with a file
91 * descriptor of '-1'. Then any time that GLib is polling the event
92 * source, it will call our poll function.
94 static GPollFD event_poll_fd;
96 /* Current NSEvents that we've gotten from Cocoa but haven't yet converted
97 * to GdkEvents. We wait until our dispatch() function to do the conversion
98 * since the conversion can conceivably cause signals to be emmitted
99 * or other things that shouldn't happen inside a poll function.
101 static GQueue *current_events;
103 /* The default poll function for GLib; we replace this with our own
104 * Cocoa-aware version and then call the old version to do actual
105 * file descriptor polling. There's no actual need to chain to the
106 * old one; we could reimplement the same functionality from scratch,
107 * but since the default implementation does the right thing, why
110 static GPollFunc old_poll_func;
112 /* Reference to the run loop of the main thread. (There is a unique
113 * CFRunLoop per thread.)
115 static CFRunLoopRef main_thread_run_loop;
117 /* Normally the Cocoa main loop maintains an NSAutoReleasePool and frees
118 * it on every iteration. Since we are replacing the main loop we have
119 * to provide this functionality ourself. We free and replace the
120 * auto-release pool in our sources prepare() function.
122 static NSAutoreleasePool *autorelease_pool;
124 /* Flag when we've called nextEventMatchingMask ourself; this triggers
125 * a run loop iteration, so we need to detect that and avoid triggering
126 * our "run the GLib main looop while the run loop is active machinery.
128 static gint getting_events = 0;
130 /************************************************************
131 ********* Select Thread *********
132 ************************************************************/
134 /* The states in our state machine, see comments in select_thread_func()
135 * for descriptiions of each state
145 #ifdef G_ENABLE_DEBUG
146 static const char *const state_names[] = {
151 "POLLING_DESCRIPTORS"
155 static SelectThreadState select_thread_state = BEFORE_START;
157 static pthread_t select_thread;
158 static pthread_mutex_t select_thread_mutex = PTHREAD_MUTEX_INITIALIZER;
159 static pthread_cond_t select_thread_cond = PTHREAD_COND_INITIALIZER;
161 #define SELECT_THREAD_LOCK() pthread_mutex_lock (&select_thread_mutex)
162 #define SELECT_THREAD_UNLOCK() pthread_mutex_unlock (&select_thread_mutex)
163 #define SELECT_THREAD_SIGNAL() pthread_cond_signal (&select_thread_cond)
164 #define SELECT_THREAD_WAIT() pthread_cond_wait (&select_thread_cond, &select_thread_mutex)
166 /* These are the file descriptors that the select thread is currently
169 static GPollFD *current_pollfds;
170 static guint current_n_pollfds;
172 /* These are the file descriptors that the select thread should pick
173 * up and start polling when it has a chance.
175 static GPollFD *next_pollfds;
176 static guint next_n_pollfds;
178 /* Pipe used to wake up the select thread */
179 static gint select_thread_wakeup_pipe[2];
181 /* Run loop source used to wake up the main thread */
182 static CFRunLoopSourceRef select_main_thread_source;
185 select_thread_set_state (SelectThreadState new_state)
189 if (select_thread_state == new_state)
192 GDK_NOTE (EVENTLOOP, g_print ("EventLoop: Select thread state: %s => %s\n", state_names[select_thread_state], state_names[new_state]));
194 old_state = select_thread_state;
195 select_thread_state = new_state;
196 if (old_state == WAITING && new_state != WAITING)
197 SELECT_THREAD_SIGNAL ();
201 signal_main_thread (void)
203 GDK_NOTE (EVENTLOOP, g_print ("EventLoop: Waking up main thread\n"));
205 /* If we are in nextEventMatchingMask, then we need to make sure an
206 * event gets queued, otherwise it's enough to simply wake up the
207 * main thread run loop
209 if (!run_loop_polling_async)
210 CFRunLoopSourceSignal (select_main_thread_source);
212 /* Don't check for CFRunLoopIsWaiting() here because it causes a
213 * race condition (the loop could go into waiting state right after
216 CFRunLoopWakeUp (main_thread_run_loop);
220 select_thread_func (void *arg)
224 SELECT_THREAD_LOCK ();
228 switch (select_thread_state)
231 /* The select thread has not been started yet
233 g_assert_not_reached ();
236 /* Waiting for a set of file descriptors to be submitted by the main thread
238 * => POLLING_QUEUED: main thread thread submits a set of file descriptors
240 SELECT_THREAD_WAIT ();
244 /* Waiting for a set of file descriptors to be submitted by the main thread
246 * => POLLING_DESCRIPTORS: select thread picks up the file descriptors to begin polling
249 g_free (current_pollfds);
251 current_pollfds = next_pollfds;
252 current_n_pollfds = next_n_pollfds;
257 select_thread_set_state (POLLING_DESCRIPTORS);
260 case POLLING_RESTART:
261 /* Select thread is currently polling a set of file descriptors, main thread has
262 * began a new iteration with the same set of file descriptors. We don't want to
263 * wake the select thread up and wait for it to restart immediately, but to avoid
264 * a race (described below in select_thread_start_polling()) we need to recheck after
267 * => POLLING_DESCRIPTORS: select completes, main thread rechecks by polling again
268 * => POLLING_QUEUED: main thread submits a new set of file descriptors to be polled
270 select_thread_set_state (POLLING_DESCRIPTORS);
273 case POLLING_DESCRIPTORS:
274 /* In the process of polling the file descriptors
276 * => WAITING: polling completes when a file descriptor becomes active
277 * => POLLING_QUEUED: main thread submits a new set of file descriptors to be polled
278 * => POLLING_RESTART: main thread begins a new iteration with the same set file descriptors
280 SELECT_THREAD_UNLOCK ();
281 old_poll_func (current_pollfds, current_n_pollfds, -1);
282 SELECT_THREAD_LOCK ();
284 read (select_thread_wakeup_pipe[0], &c, 1);
286 if (select_thread_state == POLLING_DESCRIPTORS)
288 signal_main_thread ();
289 select_thread_set_state (WAITING);
297 got_fd_activity (void *info)
301 /* Post a message so we'll break out of the message loop */
302 event = [NSEvent otherEventWithType: NSApplicationDefined
303 location: NSZeroPoint
308 subtype: GDK_QUARTZ_EVENT_SUBTYPE_EVENTLOOP
312 [NSApp postEvent:event atStart:YES];
316 select_thread_start (void)
318 g_return_if_fail (select_thread_state == BEFORE_START);
320 pipe (select_thread_wakeup_pipe);
321 fcntl (select_thread_wakeup_pipe[0], F_SETFL, O_NONBLOCK);
323 CFRunLoopSourceContext source_context = {0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, got_fd_activity };
324 select_main_thread_source = CFRunLoopSourceCreate (NULL, 0, &source_context);
326 CFRunLoopAddSource (main_thread_run_loop, select_main_thread_source, kCFRunLoopCommonModes);
328 select_thread_state = WAITING;
332 if (pthread_create (&select_thread, NULL, select_thread_func, NULL) == 0)
335 g_warning ("Failed to create select thread, sleeping and trying again");
340 #ifdef G_ENABLE_DEBUG
342 dump_poll_result (GPollFD *ufds,
347 for (i = 0; i < nfds; i++)
349 if (ufds[i].fd >= 0 && ufds[i].revents)
351 g_print (" %d:", ufds[i].fd);
352 if (ufds[i].revents & G_IO_IN)
354 if (ufds[i].revents & G_IO_OUT)
356 if (ufds[i].revents & G_IO_PRI)
365 pollfds_equal (GPollFD *old_pollfds,
367 GPollFD *new_pollfds,
372 if (old_n_pollfds != new_n_pollfds)
375 for (i = 0; i < old_n_pollfds; i++)
377 if (old_pollfds[i].fd != new_pollfds[i].fd ||
378 old_pollfds[i].events != new_pollfds[i].events)
385 /* Begins a polling operation with the specified GPollFD array; the
386 * timeout is used only to tell if the polling operation is blocking
390 * -1: No file descriptors ready, began asynchronous poll
391 * 0: No file descriptors ready, asynchronous poll not needed
392 * > 0: Number of file descriptors ready
395 select_thread_start_poll (GPollFD *ufds,
396 guint nfds, gint timeout)
399 gboolean have_new_pollfds = FALSE;
400 gint poll_fd_index = -1;
403 for (i = 0; i < nfds; i++)
404 if (ufds[i].fd == -1)
411 (nfds == 1 && poll_fd_index >= 0))
413 GDK_NOTE (EVENTLOOP, g_print ("EventLoop: Nothing to poll\n"));
417 /* If we went immediately to an async poll, then we might decide to
418 * dispatch idle functions when higher priority file descriptor sources
419 * are ready to be dispatched. So we always need to first check
420 * check synchronously with a timeout of zero, and only when no
421 * sources are immediately ready, go to the asynchronous poll.
423 * Of course, if the timeout passed in is 0, then the synchronous
424 * check is sufficient and we never need to do the asynchronous poll.
426 n_ready = old_poll_func (ufds, nfds, 0);
427 if (n_ready > 0 || timeout == 0)
429 #ifdef G_ENABLE_DEBUG
430 if ((_gdk_debug_flags & GDK_DEBUG_EVENTLOOP) && n_ready > 0)
432 g_print ("EventLoop: Found ready file descriptors before waiting\n");
433 dump_poll_result (ufds, nfds);
440 SELECT_THREAD_LOCK ();
442 if (select_thread_state == BEFORE_START)
444 select_thread_start ();
447 if (select_thread_state == POLLING_QUEUED)
449 /* If the select thread hasn't picked up the set of file descriptors yet
450 * then we can simply replace an old stale set with a new set.
452 if (!pollfds_equal (ufds, nfds, next_pollfds, next_n_pollfds - 1))
454 g_free (next_pollfds);
458 have_new_pollfds = TRUE;
461 else if (select_thread_state == POLLING_RESTART || select_thread_state == POLLING_DESCRIPTORS)
463 /* If we are already in the process of polling the right set of file descriptors,
464 * there's no need for us to immediately force the select thread to stop polling
465 * and then restart again. And avoiding doing so increases the efficiency considerably
466 * in the common case where we have a set of basically inactive file descriptors that
467 * stay unchanged present as we process many events.
469 * However, we have to be careful that we don't hit the following race condition
470 * Select Thread Main Thread
471 * ----------------- ---------------
473 * Reads data or otherwise changes file descriptor state
474 * Checks if polling is current
478 * Marks polling as complete
480 * Receives old stale file descriptor state
482 * To avoid this, when the new set of poll descriptors is the same as the current
483 * one, we transition to the POLLING_RESTART stage at the point marked (*). When
484 * the select thread wakes up from the poll because a file descriptor is active, if
485 * the state is POLLING_RESTART it immediately begins polling same the file descriptor
486 * set again. This normally will just return the same set of active file descriptors
487 * as the first time, but in sequence described above will properly update the
488 * file descriptor state.
490 * Special case: this RESTART logic is not needed if the only FD is the internal GLib
491 * "wakeup pipe" that is presented when threads are initialized.
493 * P.S.: The harm in the above sequence is mostly that sources can be signalled
494 * as ready when they are no longer ready. This may prompt a blocking read
495 * from a file descriptor that hangs.
497 if (!pollfds_equal (ufds, nfds, current_pollfds, current_n_pollfds - 1))
498 have_new_pollfds = TRUE;
501 if (!((nfds == 1 && poll_fd_index < 0 && g_thread_supported ()) ||
502 (nfds == 2 && poll_fd_index >= 0 && g_thread_supported ())))
503 select_thread_set_state (POLLING_RESTART);
507 have_new_pollfds = TRUE;
509 if (have_new_pollfds)
511 GDK_NOTE (EVENTLOOP, g_print ("EventLoop: Submitting a new set of file descriptor to the select thread\n"));
513 g_assert (next_pollfds == NULL);
515 next_n_pollfds = nfds + 1;
516 next_pollfds = g_new (GPollFD, nfds + 1);
517 memcpy (next_pollfds, ufds, nfds * sizeof (GPollFD));
519 next_pollfds[nfds].fd = select_thread_wakeup_pipe[0];
520 next_pollfds[nfds].events = G_IO_IN;
522 if (select_thread_state != POLLING_QUEUED && select_thread_state != WAITING)
524 if (select_thread_wakeup_pipe[1])
527 write (select_thread_wakeup_pipe[1], &c, 1);
531 select_thread_set_state (POLLING_QUEUED);
534 SELECT_THREAD_UNLOCK ();
539 /* End an asynchronous polling operation started with
540 * select_thread_collect_poll(). This must be called if and only if
541 * select_thread_start_poll() return -1. The GPollFD array passed
542 * in must be identical to the one passed to select_thread_start_poll().
544 * The results of the poll are written into the GPollFD array passed in.
546 * Return Value: number of file descriptors ready
549 select_thread_collect_poll (GPollFD *ufds, guint nfds)
554 SELECT_THREAD_LOCK ();
556 if (select_thread_state == WAITING) /* The poll completed */
558 for (i = 0; i < nfds; i++)
560 if (ufds[i].fd == -1)
563 g_assert (ufds[i].fd == current_pollfds[i].fd);
564 g_assert (ufds[i].events == current_pollfds[i].events);
566 if (current_pollfds[i].revents)
568 ufds[i].revents = current_pollfds[i].revents;
573 #ifdef G_ENABLE_DEBUG
574 if (_gdk_debug_flags & GDK_DEBUG_EVENTLOOP)
576 g_print ("EventLoop: Found ready file descriptors after waiting\n");
577 dump_poll_result (ufds, nfds);
582 SELECT_THREAD_UNLOCK ();
587 /************************************************************
588 ********* Main Loop Source *********
589 ************************************************************/
592 _gdk_quartz_event_loop_check_pending (void)
594 return current_events && current_events->head;
598 _gdk_quartz_event_loop_get_pending (void)
600 NSEvent *event = NULL;
603 event = g_queue_pop_tail (current_events);
609 _gdk_quartz_event_loop_release_event (NSEvent *event)
615 gdk_event_prepare (GSource *source,
620 gdk_threads_enter ();
624 if (_gdk_display->event_pause_count > 0)
627 retval = (_gdk_event_queue_find_first (_gdk_display) != NULL ||
628 _gdk_quartz_event_loop_check_pending ());
630 gdk_threads_leave ();
636 gdk_event_check (GSource *source)
640 gdk_threads_enter ();
642 if (_gdk_display->event_pause_count > 0)
645 retval = (_gdk_event_queue_find_first (_gdk_display) != NULL ||
646 _gdk_quartz_event_loop_check_pending ());
648 gdk_threads_leave ();
654 gdk_event_dispatch (GSource *source,
655 GSourceFunc callback,
660 gdk_threads_enter ();
662 /* Refresh the autorelease pool if we're at the base CFRunLoop level
663 * (indicated by current_loop_level) and the base g_main_loop level
664 * (indicated by g_main_depth()). Messing with the autorelease pool at
665 * any level of nesting can cause access to deallocated memory because
666 * autorelease_pool is static and releasing a pool will cause all pools
667 * allocated inside of it to be released as well.
669 if (current_loop_level == 0 && g_main_depth() == 0)
671 if (autorelease_pool)
672 [autorelease_pool drain];
674 autorelease_pool = [[NSAutoreleasePool alloc] init];
677 _gdk_quartz_display_queue_events (_gdk_display);
679 event = _gdk_event_unqueue (_gdk_display);
683 _gdk_event_emit (event);
685 gdk_event_free (event);
688 gdk_threads_leave ();
693 static GSourceFuncs event_funcs = {
700 /************************************************************
701 ********* Our Poll Function *********
702 ************************************************************/
705 poll_func (GPollFD *ufds,
713 static GPollFD *last_ufds;
717 n_ready = select_thread_start_poll (ufds, nfds, timeout_);
722 limit_date = [NSDate distantFuture];
723 else if (timeout_ == 0)
724 limit_date = [NSDate distantPast];
726 limit_date = [NSDate dateWithTimeIntervalSinceNow:timeout_/1000.0];
729 event = [NSApp nextEventMatchingMask: NSAnyEventMask
730 untilDate: limit_date
731 inMode: NSDefaultRunLoopMode
735 /* We check if last_ufds did not change since the time this function was
736 * called. It is possible that a recursive main loop (and thus recursive
737 * invocation of this poll function) is triggered while in
738 * nextEventMatchingMask:. If during that time new fds are added,
739 * the cached fds array might be replaced in g_main_context_iterate().
740 * So, we should avoid accessing the old fd array (still pointed at by
741 * ufds) here in that case, since it might have been freed. We avoid this
742 * by not calling the collect stage.
744 if (last_ufds == ufds && n_ready < 0)
745 n_ready = select_thread_collect_poll (ufds, nfds);
748 [event type] == NSApplicationDefined &&
749 [event subtype] == GDK_QUARTZ_EVENT_SUBTYPE_EVENTLOOP)
751 /* Just used to wake us up; if an event and a FD arrived at the same
752 * time; could have come from a previous iteration in some cases,
753 * but the spurious wake up is harmless if a little inefficient.
761 current_events = g_queue_new ();
762 g_queue_push_head (current_events, [event retain]);
768 /************************************************************
769 ********* Running the main loop out of CFRunLoop *********
770 ************************************************************/
772 /* Wrapper around g_main_context_query() that handles reallocating
773 * run_loop_pollfds up to the proper size
776 query_main_context (GMainContext *context,
782 if (!run_loop_pollfds)
784 run_loop_pollfds_size = RUN_LOOP_POLLFDS_INITIAL_SIZE;
785 run_loop_pollfds = g_new (GPollFD, run_loop_pollfds_size);
788 while ((nfds = g_main_context_query (context, max_priority, timeout,
790 run_loop_pollfds_size)) > run_loop_pollfds_size)
792 g_free (run_loop_pollfds);
793 run_loop_pollfds_size = nfds;
794 run_loop_pollfds = g_new (GPollFD, nfds);
801 run_loop_entry (void)
803 if (acquired_loop_level == -1)
805 if (g_main_context_acquire (NULL))
807 GDK_NOTE (EVENTLOOP, g_print ("EventLoop: Beginning tracking run loop activity\n"));
808 acquired_loop_level = current_loop_level;
812 /* If we fail to acquire the main context, that means someone is iterating
813 * the main context in a different thread; we simply wait until this loop
814 * exits and then try again at next entry. In general, iterating the loop
815 * from a different thread is rare: it is only possible when GDK threading
816 * is initialized and is not frequently used even then. So, we hope that
817 * having GLib main loop iteration blocked in the combination of that and
818 * a native modal operation is a minimal problem. We could imagine using a
819 * thread that does g_main_context_wait() and then wakes us back up, but
820 * the gain doesn't seem worth the complexity.
822 GDK_NOTE (EVENTLOOP, g_print ("EventLoop: Can't acquire main loop; skipping tracking run loop activity\n"));
828 run_loop_before_timers (void)
833 run_loop_before_sources (void)
835 GMainContext *context = g_main_context_default ();
839 /* Before we let the CFRunLoop process sources, we want to check if there
840 * are any pending GLib main loop sources more urgent than
841 * G_PRIORITY_DEFAULT that need to be dispatched. (We consider all activity
842 * from the CFRunLoop to have a priority of G_PRIORITY_DEFAULT.) If no
843 * sources are processed by the CFRunLoop, then processing will continue
844 * on to the BeforeWaiting stage where we check for lower priority sources.
847 g_main_context_prepare (context, &max_priority);
848 max_priority = MIN (max_priority, G_PRIORITY_DEFAULT);
850 /* We ignore the timeout that query_main_context () returns since we'll
851 * always query again before waiting.
853 nfds = query_main_context (context, max_priority, NULL);
856 old_poll_func (run_loop_pollfds, nfds, 0);
858 if (g_main_context_check (context, max_priority, run_loop_pollfds, nfds))
860 GDK_NOTE (EVENTLOOP, g_print ("EventLoop: Dispatching high priority sources\n"));
861 g_main_context_dispatch (context);
866 dummy_timer_callback (CFRunLoopTimerRef timer,
869 /* Nothing; won't normally even be called */
873 run_loop_before_waiting (void)
875 GMainContext *context = g_main_context_default ();
879 /* At this point, the CFRunLoop is ready to wait. We start a GMain loop
880 * iteration by calling the check() and query() stages. We start a
881 * poll, and if it doesn't complete immediately we let the run loop
882 * go ahead and sleep. Before doing that, if there was a timeout from
883 * GLib, we set up a CFRunLoopTimer to wake us up.
886 g_main_context_prepare (context, &run_loop_max_priority);
888 run_loop_n_pollfds = query_main_context (context, run_loop_max_priority, &timeout);
890 n_ready = select_thread_start_poll (run_loop_pollfds, run_loop_n_pollfds, timeout);
892 if (n_ready > 0 || timeout == 0)
894 /* We have stuff to do, no sleeping allowed! */
895 CFRunLoopWakeUp (main_thread_run_loop);
897 else if (timeout > 0)
899 /* We need to get the run loop to break out of its wait when our timeout
900 * expires. We do this by adding a dummy timer that we'll remove immediately
901 * after the wait wakes up.
903 GDK_NOTE (EVENTLOOP, g_print ("EventLoop: Adding timer to wake us up in %d milliseconds\n", timeout));
905 run_loop_timer = CFRunLoopTimerCreate (NULL, /* allocator */
906 CFAbsoluteTimeGetCurrent () + timeout / 1000.,
907 0, /* interval (0=does not repeat) */
909 0, /* order (priority) */
910 dummy_timer_callback,
913 CFRunLoopAddTimer (main_thread_run_loop, run_loop_timer, kCFRunLoopCommonModes);
916 run_loop_polling_async = n_ready < 0;
920 run_loop_after_waiting (void)
922 GMainContext *context = g_main_context_default ();
924 /* After sleeping, we finish of the GMain loop iteratin started in before_waiting()
925 * by doing the check() and dispatch() stages.
930 CFRunLoopRemoveTimer (main_thread_run_loop, run_loop_timer, kCFRunLoopCommonModes);
931 CFRelease (run_loop_timer);
932 run_loop_timer = NULL;
935 if (run_loop_polling_async)
937 select_thread_collect_poll (run_loop_pollfds, run_loop_n_pollfds);
938 run_loop_polling_async = FALSE;
941 if (g_main_context_check (context, run_loop_max_priority, run_loop_pollfds, run_loop_n_pollfds))
943 GDK_NOTE (EVENTLOOP, g_print ("EventLoop: Dispatching after waiting\n"));
944 g_main_context_dispatch (context);
951 /* + 1 because we decrement current_loop_level separately in observer_callback() */
952 if ((current_loop_level + 1) == acquired_loop_level)
954 g_main_context_release (NULL);
955 acquired_loop_level = -1;
956 GDK_NOTE (EVENTLOOP, g_print ("EventLoop: Ended tracking run loop activity\n"));
961 run_loop_observer_callback (CFRunLoopObserverRef observer,
962 CFRunLoopActivity activity,
967 case kCFRunLoopEntry:
968 current_loop_level++;
971 g_return_if_fail (current_loop_level > 0);
972 current_loop_level--;
978 if (getting_events > 0) /* Activity we triggered */
983 case kCFRunLoopEntry:
986 case kCFRunLoopBeforeTimers:
987 run_loop_before_timers ();
989 case kCFRunLoopBeforeSources:
990 run_loop_before_sources ();
992 case kCFRunLoopBeforeWaiting:
993 run_loop_before_waiting ();
995 case kCFRunLoopAfterWaiting:
996 run_loop_after_waiting ();
1006 /************************************************************/
1009 _gdk_quartz_event_loop_init (void)
1012 CFRunLoopObserverRef observer;
1014 /* Hook into the GLib main loop */
1016 event_poll_fd.events = G_IO_IN;
1017 event_poll_fd.fd = -1;
1019 source = g_source_new (&event_funcs, sizeof (GSource));
1020 g_source_set_name (source, "GDK Quartz event source");
1021 g_source_add_poll (source, &event_poll_fd);
1022 g_source_set_priority (source, GDK_PRIORITY_EVENTS);
1023 g_source_set_can_recurse (source, TRUE);
1024 g_source_attach (source, NULL);
1026 old_poll_func = g_main_context_get_poll_func (NULL);
1027 g_main_context_set_poll_func (NULL, poll_func);
1029 /* Hook into the the CFRunLoop for the main thread */
1031 main_thread_run_loop = CFRunLoopGetCurrent ();
1033 observer = CFRunLoopObserverCreate (NULL, /* default allocator */
1034 kCFRunLoopAllActivities,
1035 true, /* repeats: not one-shot */
1036 0, /* order (priority) */
1037 run_loop_observer_callback,
1040 CFRunLoopAddObserver (main_thread_run_loop, observer, kCFRunLoopCommonModes);
1042 /* Initialize our autorelease pool */
1044 autorelease_pool = [[NSAutoreleasePool alloc] init];