]> Pileus Git - ~andy/gtk/blob - gdk/quartz/gdkeventloop-quartz.c
39f5c0aee34cb4174862e13de12a25ef37868753
[~andy/gtk] / gdk / quartz / gdkeventloop-quartz.c
1 #include "config.h"
2
3 #include <glib.h>
4 #include <pthread.h>
5 #include <sys/types.h>
6 #include <sys/uio.h>
7 #include <unistd.h>
8
9 #include "gdkprivate-quartz.h"
10
11 /* 
12  * This file implementations integration between the GLib main loop and
13  * the native system of the Core Foundation run loop and Cocoa event
14  * handling. There are basically two different cases that we need to
15  * handle: either the GLib main loop is in control (the application
16  * has called gtk_main(), or is otherwise iterating the main loop), or
17  * CFRunLoop is in control (we are in a modal operation such as window
18  * resizing or drag-and-drop.)
19  *
20  * When the GLib main loop is in control we integrate in native event
21  * handling in two ways: first we add a GSource that handles checking
22  * whether there are native events available, translating native events
23  * to GDK events, and dispatching GDK events. Second we replace the
24  * "poll function" of the GLib main loop with our own version that knows
25  * how to wait for both the file descriptors and timeouts that GLib is
26  * interested in and also for incoming native events.
27  *
28  * When CFRunLoop is in control, we integrate in GLib main loop handling
29  * by adding a "run loop observer" that gives us notification at various
30  * points in the run loop cycle. We map these points onto the corresponding
31  * stages of the GLib main loop (prepare, check, dispatch), and make the
32  * appropriate calls into GLib.
33  *
34  * Both cases share a single problem: the OS X API's don't allow us to
35  * wait simultaneously for file descriptors and for events. So when we
36  * need to do a blocking wait that includes file descriptor activity, we
37  * push the actual work of calling select() to a helper thread (the
38  * "select thread") and wait for native events in the main thread.
39  *
40  * The main known limitation of this code is that if a callback is triggered
41  * via the OS X run loop while we are "polling" (in either case described
42  * above), iteration of the GLib main loop is not possible from within
43  * that callback. If the programmer tries to do so explicitly, then they
44  * will get a warning from GLib "main loop already active in another thread".
45  */
46
47 /******* State for run loop iteration *******/
48
49 /* Count of number of times we've gotten an "Entry" notification for
50  * our run loop observer.
51  */
52 static int current_loop_level = 0;
53
54 /* Run loop level at which we acquired ownership of the GLib main
55  * loop. See note in run_loop_entry(). -1 means that we don't have
56  * ownership
57  */ 
58 static int acquired_loop_level = -1;
59
60 /* Between run_loop_before_waiting() and run_loop_after_waiting();
61  * whether we we need to call select_thread_collect_poll()
62  */
63 static gboolean run_loop_polling_async = FALSE;
64
65 /* Between run_loop_before_waiting() and run_loop_after_waiting();
66  * max_prioritiy to pass to g_main_loop_check()
67  */
68 static gint run_loop_max_priority;
69
70 /* Timer that we've added to wake up the run loop when a GLib timeout
71  */
72 static CFRunLoopTimerRef run_loop_timer = NULL;
73
74 /* These are the file descriptors that are we are polling out of
75  * the run loop. (We keep the array around and reuse it to avoid
76  * constant allocations.)
77  */
78 #define RUN_LOOP_POLLFDS_INITIAL_SIZE 16
79 static GPollFD *run_loop_pollfds;
80 static guint run_loop_pollfds_size; /* Allocated size of the array */
81 static guint run_loop_n_pollfds;    /* Number of file descriptors in the array */
82
83 /******* Other global variables *******/
84
85 /* Since we count on replacing the GLib main loop poll function as our
86  * method of integrating Cocoa event handling into the GLib main loop
87  * we need to make sure that the poll function is always called even
88  * when there are no file descriptors that need to be polled. To do
89  * this, we add a dummy GPollFD to our event source with a file
90  * descriptor of '-1'. Then any time that GLib is polling the event
91  * source, it will call our poll function.
92  */
93 static GPollFD event_poll_fd;
94
95 /* Current NSEvents that we've gotten from Cocoa but haven't yet converted
96  * to GdkEvents. We wait until our dispatch() function to do the conversion
97  * since the conversion can conceivably cause signals to be emmitted
98  * or other things that shouldn't happen inside a poll function.
99  */
100 static GQueue *current_events;
101
102 /* The default poll function for GLib; we replace this with our own
103  * Cocoa-aware version and then call the old version to do actual
104  * file descriptor polling. There's no actual need to chain to the
105  * old one; we could reimplement the same functionality from scratch,
106  * but since the default implementation does the right thing, why
107  * bother.
108  */
109 static GPollFunc old_poll_func;
110
111 /* Reference to the run loop of the main thread. (There is a unique
112  * CFRunLoop per thread.)
113  */
114 static CFRunLoopRef main_thread_run_loop;
115
116 /* Normally the Cocoa main loop maintains an NSAutoReleasePool and frees
117  * it on every iteration. Since we are replacing the main loop we have
118  * to provide this functionality ourself. We free and replace the
119  * auto-release pool in our sources prepare() function.
120  */
121 static NSAutoreleasePool *autorelease_pool;
122
123 /* Flag when we've called nextEventMatchingMask ourself; this triggers
124  * a run loop iteration, so we need to detect that and avoid triggering
125  * our "run the GLib main looop while the run loop is active machinery.
126  */
127 static gboolean getting_events;
128
129 /************************************************************
130  *********              Select Thread               *********
131  ************************************************************/
132
133 /* The states in our state machine, see comments in select_thread_func()
134  * for descriptiions of each state
135  */
136 typedef enum {
137   BEFORE_START,
138   WAITING,
139   POLLING_QUEUED,
140   POLLING_RESTART,
141   POLLING_DESCRIPTORS,
142 } SelectThreadState;
143
144 #ifdef G_ENABLE_DEBUG
145 static const char *const state_names[]  = {
146   "BEFORE_START",
147   "WAITING",
148   "POLLING_QUEUED",
149   "POLLING_RESTART",
150   "POLLING_DESCRIPTORS"
151 };
152 #endif
153
154 static SelectThreadState select_thread_state = BEFORE_START;
155
156 static pthread_t select_thread;
157 static pthread_mutex_t select_thread_mutex = PTHREAD_MUTEX_INITIALIZER;
158 static pthread_cond_t select_thread_cond = PTHREAD_COND_INITIALIZER;
159
160 #define SELECT_THREAD_LOCK() pthread_mutex_lock (&select_thread_mutex)
161 #define SELECT_THREAD_UNLOCK() pthread_mutex_unlock (&select_thread_mutex)
162 #define SELECT_THREAD_SIGNAL() pthread_cond_signal (&select_thread_cond)
163 #define SELECT_THREAD_WAIT() pthread_cond_wait (&select_thread_cond, &select_thread_mutex)
164
165 /* These are the file descriptors that the select thread is currently
166  * polling.
167  */
168 static GPollFD *current_pollfds;
169 static guint current_n_pollfds;
170
171 /* These are the file descriptors that the select thread should pick
172  * up and start polling when it has a chance.
173  */
174 static GPollFD *next_pollfds;
175 static guint next_n_pollfds;
176
177 /* Pipe used to wake up the select thread */
178 static gint select_thread_wakeup_pipe[2];
179
180 /* Run loop source used to wake up the main thread */
181 static CFRunLoopSourceRef select_main_thread_source;
182
183 static void
184 select_thread_set_state (SelectThreadState new_state)
185 {
186   gboolean old_state;
187
188   if (select_thread_state == new_state)
189     return;
190
191   GDK_NOTE (EVENTLOOP, g_print ("EventLoop: Select thread state: %s => %s\n", state_names[select_thread_state], state_names[new_state]));
192
193   old_state = select_thread_state;
194   select_thread_state = new_state;
195   if (old_state == WAITING && new_state != WAITING)
196     SELECT_THREAD_SIGNAL ();
197 }
198
199 static void
200 signal_main_thread (void)
201 {
202   GDK_NOTE (EVENTLOOP, g_print ("EventLoop: Waking up main thread\n"));
203
204   /* If we are in nextEventMatchingMask, then we need to make sure an
205    * event gets queued, otherwise it's enough to simply wake up the
206    * main thread run loop
207    */
208   if (!run_loop_polling_async)
209     CFRunLoopSourceSignal (select_main_thread_source);
210   
211   if (CFRunLoopIsWaiting (main_thread_run_loop))
212     CFRunLoopWakeUp (main_thread_run_loop);
213 }
214
215 static void *
216 select_thread_func (void *arg)
217 {
218   char c;
219   
220   SELECT_THREAD_LOCK ();
221
222   while (TRUE)
223     {
224       switch (select_thread_state)
225         {
226         case BEFORE_START:
227           /* The select thread has not been started yet
228            */
229           g_assert_not_reached ();
230           
231         case WAITING:
232           /* Waiting for a set of file descriptors to be submitted by the main thread
233            *
234            *  => POLLING_QUEUED: main thread thread submits a set of file descriptors
235            */ 
236           SELECT_THREAD_WAIT ();
237           break;
238           
239         case POLLING_QUEUED:
240           /* Waiting for a set of file descriptors to be submitted by the main thread
241            *
242            *  => POLLING_DESCRIPTORS: select thread picks up the file descriptors to begin polling
243            */ 
244           if (current_pollfds)
245             g_free (current_pollfds);
246           
247           current_pollfds = next_pollfds;
248           current_n_pollfds = next_n_pollfds;
249
250           next_pollfds = NULL;
251           next_n_pollfds = 0;
252
253           select_thread_set_state (POLLING_DESCRIPTORS);
254           break;
255           
256         case POLLING_RESTART:
257           /* Select thread is currently polling a set of file descriptors, main thread has
258            * began a new iteration with the same set of file descriptors. We don't want to
259            * wake the select thread up and wait for it to restart immediately, but to avoid
260            * a race (described below in select_thread_start_polling()) we need to recheck after
261            * polling completes.
262            *
263            * => POLLING_DESCRIPTORS: select completes, main thread rechecks by polling again
264            * => POLLING_QUEUED: main thread submits a new set of file descriptors to be polled
265            */
266           select_thread_set_state (POLLING_DESCRIPTORS);
267           break;
268
269         case POLLING_DESCRIPTORS:
270           /* In the process of polling the file descriptors
271            *
272            *  => WAITING: polling completes when a file descriptor becomes active
273            *  => POLLING_QUEUED: main thread submits a new set of file descriptors to be polled
274            *  => POLLING_RESTART: main thread begins a new iteration with the same set file descriptors
275            */ 
276           SELECT_THREAD_UNLOCK ();
277           old_poll_func (current_pollfds, current_n_pollfds, -1);
278           SELECT_THREAD_LOCK ();
279
280           read (select_thread_wakeup_pipe[0], &c, 1);
281
282           if (select_thread_state == POLLING_DESCRIPTORS)
283             {
284               signal_main_thread ();
285               select_thread_set_state (WAITING);
286             }
287           break;
288         }
289     }
290 }
291
292 static void 
293 got_fd_activity (void *info)
294 {
295   NSEvent *event;
296
297   /* Post a message so we'll break out of the message loop */
298   event = [NSEvent otherEventWithType: NSApplicationDefined
299                              location: NSZeroPoint
300                         modifierFlags: 0
301                             timestamp: 0
302                          windowNumber: 0
303                               context: nil
304                               subtype: GDK_QUARTZ_EVENT_SUBTYPE_EVENTLOOP
305                                 data1: 0 
306                                 data2: 0];
307
308   [NSApp postEvent:event atStart:YES];
309 }
310
311 static void
312 select_thread_start (void)
313 {
314   g_return_if_fail (select_thread_state == BEFORE_START);
315   
316   pipe (select_thread_wakeup_pipe);
317   fcntl (select_thread_wakeup_pipe[0], F_SETFL, O_NONBLOCK);
318
319   CFRunLoopSourceContext source_context = {0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, got_fd_activity };
320   select_main_thread_source = CFRunLoopSourceCreate (NULL, 0, &source_context);
321   
322   CFRunLoopAddSource (main_thread_run_loop, select_main_thread_source, kCFRunLoopCommonModes);
323
324   select_thread_state = WAITING;
325   
326   while (TRUE)
327     {
328       if (pthread_create (&select_thread, NULL, select_thread_func, NULL) == 0)
329           break;
330
331       g_warning ("Failed to create select thread, sleeping and trying again");
332       sleep (1);
333     }
334 }
335
336 #ifdef G_ENABLE_DEBUG
337 static void
338 dump_poll_result (GPollFD *ufds,
339                   guint    nfds)
340 {
341   gint i;
342
343   for (i = 0; i < nfds; i++)
344     {
345       if (ufds[i].fd >= 0 && ufds[i].revents)
346         {
347           g_print (" %d:", ufds[i].fd);
348           if (ufds[i].revents & G_IO_IN)
349             g_print (" in");
350           if (ufds[i].revents & G_IO_OUT)
351             g_print (" out");
352           if (ufds[i].revents & G_IO_PRI)
353             g_print (" pri");
354           g_print ("\n");
355         }
356     }
357 }
358 #endif
359
360 gboolean
361 pollfds_equal (GPollFD *old_pollfds,
362                guint    old_n_pollfds,
363                GPollFD *new_pollfds,
364                guint    new_n_pollfds)
365 {
366   gint i;
367   
368   if (old_n_pollfds != new_n_pollfds)
369     return FALSE;
370
371   for (i = 0; i < old_n_pollfds; i++)
372     {
373       if (old_pollfds[i].fd != new_pollfds[i].fd ||
374           old_pollfds[i].events != new_pollfds[i].events)
375         return FALSE;
376     }
377
378   return TRUE;
379 }
380
381 /* Begins a polling operation with the specified GPollFD array; the 
382  * timeout is used only to tell if the polling operation is blocking
383  * or non-blocking.
384  *
385  * Return value:
386  *  -1: No file descriptors ready, began asynchronous poll
387  *   0: No file descriptors ready, asynchronous poll not needed
388  * > 0: Number of file descriptors ready
389  */
390 static gint
391 select_thread_start_poll (GPollFD *ufds,
392                           guint    nfds,                          gint     timeout)
393 {
394   gint n_ready;
395   gboolean have_new_pollfds = FALSE;
396   gint poll_fd_index = -1;
397   gint i;
398
399   for (i = 0; i < nfds; i++)
400     if (ufds[i].fd == -1)
401       {
402         poll_fd_index = i;
403         break;
404       }
405   
406   if (nfds == 0 ||
407       (nfds == 1 && poll_fd_index >= 0))
408     {
409       GDK_NOTE (EVENTLOOP, g_print ("EventLoop: Nothing to poll\n"));
410       return 0;
411     }
412
413   /* If we went immediately to an async poll, then we might decide to
414    * dispatch idle functions when higher priority file descriptor sources
415    * are ready to be dispatched. So we always need to first check
416    * check synchronously with a timeout of zero, and only when no
417    * sources are immediately ready, go to the asynchronous poll.
418    *
419    * Of course, if the timeout passed in is 0, then the synchronous
420    * check is sufficient and we never need to do the asynchronous poll.
421    */
422   n_ready = old_poll_func (ufds, nfds, 0);
423   if (n_ready > 0 || timeout == 0)
424     {
425 #ifdef G_ENABLE_DEBUG
426       if ((_gdk_debug_flags & GDK_DEBUG_EVENTLOOP) && n_ready > 0)
427         {
428           g_print ("EventLoop: Found ready file descriptors before waiting\n");
429           dump_poll_result (ufds, nfds);
430         }
431 #endif
432   
433       return n_ready;
434     }
435   
436   SELECT_THREAD_LOCK ();
437
438   if (select_thread_state == BEFORE_START)
439     {
440       select_thread_start ();
441     }
442   
443   if (select_thread_state == POLLING_QUEUED)
444     {
445       /* If the select thread hasn't picked up the set of file descriptors yet
446        * then we can simply replace an old stale set with a new set.
447        */
448       if (!pollfds_equal (ufds, nfds, next_pollfds, next_n_pollfds - 1))
449         {
450           g_free (next_pollfds);
451           next_pollfds = NULL;
452           next_n_pollfds = 0;
453           
454           have_new_pollfds = TRUE;
455         }
456     }
457   else if (select_thread_state == POLLING_RESTART || select_thread_state == POLLING_DESCRIPTORS)
458     {
459       /* If we are already in the process of polling the right set of file descriptors,
460        * there's no need for us to immediately force the select thread to stop polling
461        * and then restart again. And avoiding doing so increases the efficiency considerably
462        * in the common case where we have a set of basically inactive file descriptors that
463        * stay unchanged present as we process many events.
464        *
465        * However, we have to be careful that we don't hit the following race condition
466        *  Select Thread              Main Thread
467        *  -----------------          ---------------
468        *  Polling Completes
469        *                             Reads data or otherwise changes file descriptor state
470        *                             Checks if polling is current
471        *                             Does nothing (*)
472        *                             Releases lock
473        *  Acquires lock
474        *  Marks polling as complete
475        *  Wakes main thread
476        *                             Receives old stale file descriptor state
477        * 
478        * To avoid this, when the new set of poll descriptors is the same as the current
479        * one, we transition to the POLLING_RESTART stage at the point marked (*). When
480        * the select thread wakes up from the poll because a file descriptor is active, if
481        * the state is POLLING_RESTART it immediately begins polling same the file descriptor
482        * set again. This normally will just return the same set of active file descriptors
483        * as the first time, but in sequence described above will properly update the
484        * file descriptor state.
485        *
486        * Special case: this RESTART logic is not needed if the only FD is the internal GLib
487        * "wakeup pipe" that is presented when threads are initialized.
488        *
489        * P.S.: The harm in the above sequence is mostly that sources can be signalled
490        *   as ready when they are no longer ready. This may prompt a blocking read
491        *   from a file descriptor that hangs.
492        */
493       if (!pollfds_equal (ufds, nfds, current_pollfds, current_n_pollfds - 1))
494         have_new_pollfds = TRUE;
495       else
496         {
497           if (!((nfds == 1 && poll_fd_index < 0 && g_thread_supported ()) ||
498                 (nfds == 2 && poll_fd_index >= 0 && g_thread_supported ())))
499             select_thread_set_state (POLLING_RESTART);
500         }
501     }
502   else
503     have_new_pollfds = TRUE;
504
505   if (have_new_pollfds)
506     {
507       GDK_NOTE (EVENTLOOP, g_print ("EventLoop: Submitting a new set of file descriptor to the select thread\n"));
508       
509       g_assert (next_pollfds == NULL);
510       
511       next_n_pollfds = nfds + 1;
512       next_pollfds = g_new (GPollFD, nfds + 1);
513       memcpy (next_pollfds, ufds, nfds * sizeof (GPollFD));
514   
515       next_pollfds[nfds].fd = select_thread_wakeup_pipe[0];
516       next_pollfds[nfds].events = G_IO_IN;
517   
518       if (select_thread_state != POLLING_QUEUED && select_thread_state != WAITING)
519         {
520           if (select_thread_wakeup_pipe[1])
521             {
522               char c = 'A';
523               write (select_thread_wakeup_pipe[1], &c, 1);
524             }
525         }
526       
527       select_thread_set_state (POLLING_QUEUED);
528     }
529   
530   SELECT_THREAD_UNLOCK ();
531
532   return -1;
533 }
534
535 /* End an asynchronous polling operation started with
536  * select_thread_collect_poll(). This must be called if and only if
537  * select_thread_start_poll() return -1. The GPollFD array passed
538  * in must be identical to the one passed to select_thread_start_poll().
539  *
540  * The results of the poll are written into the GPollFD array passed in.
541  *
542  * Return Value: number of file descriptors ready
543  */
544 static int
545 select_thread_collect_poll (GPollFD *ufds, guint nfds)
546 {
547   gint i;
548   gint n_ready = 0;
549   
550   SELECT_THREAD_LOCK ();
551
552   if (select_thread_state == WAITING) /* The poll completed */
553     {
554       for (i = 0; i < nfds; i++)
555         {
556           if (ufds[i].fd == -1)
557             continue;
558           
559           g_assert (ufds[i].fd == current_pollfds[i].fd);
560           g_assert (ufds[i].events == current_pollfds[i].events);
561
562           if (current_pollfds[i].revents)
563             {
564               ufds[i].revents = current_pollfds[i].revents;
565               n_ready++;
566             }
567         }
568       
569 #ifdef G_ENABLE_DEBUG
570       if (_gdk_debug_flags & GDK_DEBUG_EVENTLOOP)
571         {
572           g_print ("EventLoop: Found ready file descriptors after waiting\n");
573           dump_poll_result (ufds, nfds);
574         }
575 #endif
576     }
577
578   SELECT_THREAD_UNLOCK ();
579
580   return n_ready;
581 }
582
583 /************************************************************
584  *********             Main Loop Source             *********
585  ************************************************************/
586
587 gboolean
588 _gdk_quartz_event_loop_check_pending (void)
589 {
590   return current_events && current_events->head;
591 }
592
593 NSEvent*
594 _gdk_quartz_event_loop_get_pending (void)
595 {
596   NSEvent *event = NULL;
597
598   if (current_events)
599     event = g_queue_pop_tail (current_events);
600
601   return event;
602 }
603
604 void
605 _gdk_quartz_event_loop_release_event (NSEvent *event)
606 {
607   [event release];
608 }
609
610 static gboolean
611 gdk_event_prepare (GSource *source,
612                    gint    *timeout)
613 {
614   gboolean retval;
615
616   GDK_THREADS_ENTER ();
617   
618   *timeout = -1;
619
620   retval = (_gdk_event_queue_find_first (_gdk_display) != NULL ||
621             _gdk_quartz_event_loop_check_pending ());
622
623   GDK_THREADS_LEAVE ();
624
625   return retval;
626 }
627
628 static gboolean
629 gdk_event_check (GSource *source)
630 {
631   gboolean retval;
632
633   GDK_THREADS_ENTER ();
634
635 /* Refresh the autorelease pool if we're at the base CFRunLoop level
636  * (indicated by current_loop_level) and the base g_main_loop level
637  * (indicated by g_main_depth()). Messing with the autorelease pool at
638  * any level of nesting can cause access to deallocated memory because
639  * autorelease_pool is static and releasing a pool will cause all
640  * pools allocated inside of it to be released as well.
641  */
642   if (current_loop_level == 0 && g_main_depth() == 0)
643     {
644       if (autorelease_pool)
645         [autorelease_pool release];
646       autorelease_pool = [[NSAutoreleasePool alloc] init];
647     }
648
649   retval = (_gdk_event_queue_find_first (_gdk_display) != NULL ||
650             _gdk_quartz_event_loop_check_pending ());
651
652   GDK_THREADS_LEAVE ();
653
654   return retval;
655 }
656
657 static gboolean
658 gdk_event_dispatch (GSource     *source,
659                     GSourceFunc  callback,
660                     gpointer     user_data)
661 {
662   GdkEvent *event;
663
664   GDK_THREADS_ENTER ();
665
666   _gdk_quartz_display_queue_events (_gdk_display);
667
668   event = _gdk_event_unqueue (_gdk_display);
669
670   if (event)
671     {
672       _gdk_event_emit (event);
673
674       gdk_event_free (event);
675     }
676
677   GDK_THREADS_LEAVE ();
678
679   return TRUE;
680 }
681
682 static GSourceFuncs event_funcs = {
683   gdk_event_prepare,
684   gdk_event_check,
685   gdk_event_dispatch,
686   NULL
687 };
688
689 /************************************************************
690  *********             Our Poll Function            *********
691  ************************************************************/
692
693 static gint
694 poll_func (GPollFD *ufds,
695            guint    nfds,
696            gint     timeout_)
697 {
698   NSEvent *event;
699   NSDate *limit_date;
700   gint n_ready;
701
702   n_ready = select_thread_start_poll (ufds, nfds, timeout_);
703   if (n_ready > 0)
704     timeout_ = 0;
705
706   if (timeout_ == -1)
707     limit_date = [NSDate distantFuture];
708   else if (timeout_ == 0)
709     limit_date = [NSDate distantPast];
710   else
711     limit_date = [NSDate dateWithTimeIntervalSinceNow:timeout_/1000.0];
712
713   getting_events = TRUE;
714   event = [NSApp nextEventMatchingMask: NSAnyEventMask
715                              untilDate: limit_date
716                                 inMode: NSDefaultRunLoopMode
717                                dequeue: YES];
718   getting_events = FALSE;
719
720   if (n_ready < 0)
721     n_ready = select_thread_collect_poll (ufds, nfds);
722       
723   if (event &&
724       [event type] == NSApplicationDefined &&
725       [event subtype] == GDK_QUARTZ_EVENT_SUBTYPE_EVENTLOOP)
726     {
727       /* Just used to wake us up; if an event and a FD arrived at the same
728        * time; could have come from a previous iteration in some cases,
729        * but the spurious wake up is harmless if a little inefficient.
730        */
731       event = NULL;
732     }
733
734   if (event) 
735     {
736       if (!current_events)
737         current_events = g_queue_new ();
738       g_queue_push_head (current_events, [event retain]);
739     }
740
741   return n_ready;
742 }
743
744 /************************************************************
745  *********  Running the main loop out of CFRunLoop  *********
746  ************************************************************/
747
748 /* Wrapper around g_main_context_query() that handles reallocating
749  * run_loop_pollfds up to the proper size
750  */
751 static gint
752 query_main_context (GMainContext *context,
753                     int           max_priority,
754                     int          *timeout)
755 {
756   gint nfds;
757   
758   if (!run_loop_pollfds)
759     {
760       run_loop_pollfds_size = RUN_LOOP_POLLFDS_INITIAL_SIZE;
761       run_loop_pollfds = g_new (GPollFD, run_loop_pollfds_size);
762     }
763
764   while ((nfds = g_main_context_query (context, max_priority, timeout,
765                                        run_loop_pollfds, 
766                                        run_loop_pollfds_size)) > run_loop_pollfds_size)
767     {
768       g_free (run_loop_pollfds);
769       run_loop_pollfds_size = nfds;
770       run_loop_pollfds = g_new (GPollFD, nfds);
771     }
772
773   return nfds;
774 }
775
776 static void
777 run_loop_entry (void)
778 {
779   current_loop_level++;
780
781   if (acquired_loop_level == -1)
782     {
783       if (g_main_context_acquire (NULL))
784         {
785           GDK_NOTE (EVENTLOOP, g_print ("EventLoop: Beginning tracking run loop activity\n"));
786           acquired_loop_level = current_loop_level;
787         }
788       else
789         {
790           /* If we fail to acquire the main context, that means someone is iterating
791            * the main context in a different thread; we simply wait until this loop
792            * exits and then try again at next entry. In general, iterating the loop
793            * from a different thread is rare: it is only possible when GDK threading
794            * is initialized and is not frequently used even then. So, we hope that
795            * having GLib main loop iteration blocked in the combination of that and
796            * a native modal operation is a minimal problem. We could imagine using a
797            * thread that does g_main_context_wait() and then wakes us back up, but
798            * the gain doesn't seem worth the complexity.
799            */
800           GDK_NOTE (EVENTLOOP, g_print ("EventLoop: Can't acquire main loop; skipping tracking run loop activity\n"));
801         }
802     }
803 }
804
805 static void
806 run_loop_before_timers (void)
807 {
808 }
809
810 static void
811 run_loop_before_sources (void)
812 {
813   GMainContext *context = g_main_context_default ();
814   gint max_priority;
815   gint nfds;
816
817   /* Before we let the CFRunLoop process sources, we want to check if there
818    * are any pending GLib main loop sources more urgent than
819    * G_PRIORITY_DEFAULT that need to be dispatched. (We consider all activity
820    * from the CFRunLoop to have a priority of G_PRIORITY_DEFAULT.) If no
821    * sources are processed by the CFRunLoop, then processing will continue
822    * on to the BeforeWaiting stage where we check for lower priority sources.
823    */
824   
825   g_main_context_prepare (context, &max_priority); 
826   max_priority = MIN (max_priority, G_PRIORITY_DEFAULT);
827
828   /* We ignore the timeout that query_main_context () returns since we'll
829    * always query again before waiting.
830    */
831   nfds = query_main_context (context, max_priority, NULL);
832
833   if (nfds)
834     old_poll_func (run_loop_pollfds, nfds, 0);
835   
836   if (g_main_context_check (context, max_priority, run_loop_pollfds, nfds))
837     {
838       GDK_NOTE (EVENTLOOP, g_print ("EventLoop: Dispatching high priority sources\n"));
839       g_main_context_dispatch (context);
840     }
841 }
842
843 static void
844 dummy_timer_callback (CFRunLoopTimerRef  timer,
845                       void              *info)
846 {
847   /* Nothing; won't normally even be called */
848 }
849
850 static void
851 run_loop_before_waiting (void)
852 {
853   GMainContext *context = g_main_context_default ();
854   gint timeout;
855   gint n_ready;
856
857   /* At this point, the CFRunLoop is ready to wait. We start a GMain loop
858    * iteration by calling the check() and query() stages. We start a
859    * poll, and if it doesn't complete immediately we let the run loop
860    * go ahead and sleep. Before doing that, if there was a timeout from
861    * GLib, we set up a CFRunLoopTimer to wake us up.
862    */
863   
864   g_main_context_prepare (context, &run_loop_max_priority); 
865   
866   run_loop_n_pollfds = query_main_context (context, run_loop_max_priority, &timeout);
867
868   n_ready = select_thread_start_poll (run_loop_pollfds, run_loop_n_pollfds, timeout);
869
870   if (n_ready > 0 || timeout == 0)
871     {
872       /* We have stuff to do, no sleeping allowed! */
873       CFRunLoopWakeUp (main_thread_run_loop);
874     }
875   else if (timeout > 0)
876     {
877       /* We need to get the run loop to break out of it's wait when our timeout
878        * expires. We do this by adding a dummy timer that we'll remove immediately
879        * after the wait wakes up.
880        */
881       GDK_NOTE (EVENTLOOP, g_print ("EventLoop: Adding timer to wake us up in %d milliseconds\n", timeout));
882       
883       run_loop_timer = CFRunLoopTimerCreate (NULL, /* allocator */
884                                              CFAbsoluteTimeGetCurrent () + timeout / 1000.,
885                                              0, /* interval (0=does not repeat) */
886                                              0, /* flags */
887                                              0, /* order (priority) */
888                                              dummy_timer_callback,
889                                              NULL);
890
891       CFRunLoopAddTimer (main_thread_run_loop, run_loop_timer, kCFRunLoopCommonModes);
892     }
893   
894   run_loop_polling_async = n_ready < 0;
895 }
896
897 static void
898 run_loop_after_waiting (void)
899 {
900   GMainContext *context = g_main_context_default ();
901
902   /* After sleeping, we finish of the GMain loop iteratin started in before_waiting()
903    * by doing the check() and dispatch() stages.
904    */
905
906   if (run_loop_timer)
907     {
908       CFRunLoopRemoveTimer (main_thread_run_loop, run_loop_timer, kCFRunLoopCommonModes);
909       CFRelease (run_loop_timer);
910       run_loop_timer = NULL;
911     }
912   
913   if (run_loop_polling_async)
914     {
915       select_thread_collect_poll (run_loop_pollfds, run_loop_n_pollfds);
916       run_loop_polling_async = FALSE;
917     }
918   
919   if (g_main_context_check (context, run_loop_max_priority, run_loop_pollfds, run_loop_n_pollfds))
920     {
921       GDK_NOTE (EVENTLOOP, g_print ("EventLoop: Dispatching after waiting\n"));
922       g_main_context_dispatch (context);
923     }
924 }
925
926 static void
927 run_loop_exit (void)
928 {
929   g_return_if_fail (current_loop_level > 0);
930
931   if (current_loop_level == acquired_loop_level)
932     {
933       g_main_context_release (NULL);
934       acquired_loop_level = -1;
935       GDK_NOTE (EVENTLOOP, g_print ("EventLoop: Ended tracking run loop activity\n"));
936     }
937   
938   current_loop_level--;
939 }
940
941 static void
942 run_loop_observer_callback (CFRunLoopObserverRef observer,
943                             CFRunLoopActivity    activity,
944                             void                *info)
945 {
946   if (getting_events) /* Activity we triggered */
947     return;
948   
949   switch (activity)
950     {
951     case kCFRunLoopEntry:
952       run_loop_entry ();
953       break;
954     case kCFRunLoopBeforeTimers:
955       run_loop_before_timers ();
956       break;
957     case kCFRunLoopBeforeSources:
958       run_loop_before_sources ();
959       break;
960     case kCFRunLoopBeforeWaiting:
961       run_loop_before_waiting ();
962       break;
963     case kCFRunLoopAfterWaiting:
964       run_loop_after_waiting ();
965       break;
966     case kCFRunLoopExit:
967       run_loop_exit ();
968       break;
969     default:
970       break;
971     }
972 }
973
974 /************************************************************/
975
976 void
977 _gdk_quartz_event_loop_init (void)
978 {
979   GSource *source;
980   CFRunLoopObserverRef observer;
981
982   /* Hook into the GLib main loop */
983
984   event_poll_fd.events = G_IO_IN;
985   event_poll_fd.fd = -1;
986
987   source = g_source_new (&event_funcs, sizeof (GSource));
988   g_source_set_name (source, "GDK Quartz event source"); 
989   g_source_add_poll (source, &event_poll_fd);
990   g_source_set_priority (source, GDK_PRIORITY_EVENTS);
991   g_source_set_can_recurse (source, TRUE);
992   g_source_attach (source, NULL);
993
994   old_poll_func = g_main_context_get_poll_func (NULL);
995   g_main_context_set_poll_func (NULL, poll_func);
996   
997   /* Hook into the the CFRunLoop for the main thread */
998
999   main_thread_run_loop = CFRunLoopGetCurrent ();
1000
1001   observer = CFRunLoopObserverCreate (NULL, /* default allocator */
1002                                       kCFRunLoopAllActivities,
1003                                       true, /* repeats: not one-shot */
1004                                       0, /* order (priority) */
1005                                       run_loop_observer_callback,
1006                                       NULL);
1007                                      
1008   CFRunLoopAddObserver (main_thread_run_loop, observer, kCFRunLoopCommonModes);
1009   
1010   /* Initialize our autorelease pool */
1011
1012   autorelease_pool = [[NSAutoreleasePool alloc] init];
1013 }