]> Pileus Git - ~andy/gtk/blob - gdk/quartz/gdkeventloop-quartz.c
Fix a few more doc issues
[~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 gint getting_events = 0;
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   /* Don't check for CFRunLoopIsWaiting() here because it causes a
212    * race condition (the loop could go into waiting state right after
213    * we checked).
214    */
215   CFRunLoopWakeUp (main_thread_run_loop);
216 }
217
218 static void *
219 select_thread_func (void *arg)
220 {
221   char c;
222   
223   SELECT_THREAD_LOCK ();
224
225   while (TRUE)
226     {
227       switch (select_thread_state)
228         {
229         case BEFORE_START:
230           /* The select thread has not been started yet
231            */
232           g_assert_not_reached ();
233           
234         case WAITING:
235           /* Waiting for a set of file descriptors to be submitted by the main thread
236            *
237            *  => POLLING_QUEUED: main thread thread submits a set of file descriptors
238            */ 
239           SELECT_THREAD_WAIT ();
240           break;
241           
242         case POLLING_QUEUED:
243           /* Waiting for a set of file descriptors to be submitted by the main thread
244            *
245            *  => POLLING_DESCRIPTORS: select thread picks up the file descriptors to begin polling
246            */ 
247           if (current_pollfds)
248             g_free (current_pollfds);
249           
250           current_pollfds = next_pollfds;
251           current_n_pollfds = next_n_pollfds;
252
253           next_pollfds = NULL;
254           next_n_pollfds = 0;
255
256           select_thread_set_state (POLLING_DESCRIPTORS);
257           break;
258           
259         case POLLING_RESTART:
260           /* Select thread is currently polling a set of file descriptors, main thread has
261            * began a new iteration with the same set of file descriptors. We don't want to
262            * wake the select thread up and wait for it to restart immediately, but to avoid
263            * a race (described below in select_thread_start_polling()) we need to recheck after
264            * polling completes.
265            *
266            * => POLLING_DESCRIPTORS: select completes, main thread rechecks by polling again
267            * => POLLING_QUEUED: main thread submits a new set of file descriptors to be polled
268            */
269           select_thread_set_state (POLLING_DESCRIPTORS);
270           break;
271
272         case POLLING_DESCRIPTORS:
273           /* In the process of polling the file descriptors
274            *
275            *  => WAITING: polling completes when a file descriptor becomes active
276            *  => POLLING_QUEUED: main thread submits a new set of file descriptors to be polled
277            *  => POLLING_RESTART: main thread begins a new iteration with the same set file descriptors
278            */ 
279           SELECT_THREAD_UNLOCK ();
280           old_poll_func (current_pollfds, current_n_pollfds, -1);
281           SELECT_THREAD_LOCK ();
282
283           read (select_thread_wakeup_pipe[0], &c, 1);
284
285           if (select_thread_state == POLLING_DESCRIPTORS)
286             {
287               signal_main_thread ();
288               select_thread_set_state (WAITING);
289             }
290           break;
291         }
292     }
293 }
294
295 static void 
296 got_fd_activity (void *info)
297 {
298   NSEvent *event;
299
300   /* Post a message so we'll break out of the message loop */
301   event = [NSEvent otherEventWithType: NSApplicationDefined
302                              location: NSZeroPoint
303                         modifierFlags: 0
304                             timestamp: 0
305                          windowNumber: 0
306                               context: nil
307                               subtype: GDK_QUARTZ_EVENT_SUBTYPE_EVENTLOOP
308                                 data1: 0 
309                                 data2: 0];
310
311   [NSApp postEvent:event atStart:YES];
312 }
313
314 static void
315 select_thread_start (void)
316 {
317   g_return_if_fail (select_thread_state == BEFORE_START);
318   
319   pipe (select_thread_wakeup_pipe);
320   fcntl (select_thread_wakeup_pipe[0], F_SETFL, O_NONBLOCK);
321
322   CFRunLoopSourceContext source_context = {0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, got_fd_activity };
323   select_main_thread_source = CFRunLoopSourceCreate (NULL, 0, &source_context);
324   
325   CFRunLoopAddSource (main_thread_run_loop, select_main_thread_source, kCFRunLoopCommonModes);
326
327   select_thread_state = WAITING;
328   
329   while (TRUE)
330     {
331       if (pthread_create (&select_thread, NULL, select_thread_func, NULL) == 0)
332           break;
333
334       g_warning ("Failed to create select thread, sleeping and trying again");
335       sleep (1);
336     }
337 }
338
339 #ifdef G_ENABLE_DEBUG
340 static void
341 dump_poll_result (GPollFD *ufds,
342                   guint    nfds)
343 {
344   gint i;
345
346   for (i = 0; i < nfds; i++)
347     {
348       if (ufds[i].fd >= 0 && ufds[i].revents)
349         {
350           g_print (" %d:", ufds[i].fd);
351           if (ufds[i].revents & G_IO_IN)
352             g_print (" in");
353           if (ufds[i].revents & G_IO_OUT)
354             g_print (" out");
355           if (ufds[i].revents & G_IO_PRI)
356             g_print (" pri");
357           g_print ("\n");
358         }
359     }
360 }
361 #endif
362
363 gboolean
364 pollfds_equal (GPollFD *old_pollfds,
365                guint    old_n_pollfds,
366                GPollFD *new_pollfds,
367                guint    new_n_pollfds)
368 {
369   gint i;
370   
371   if (old_n_pollfds != new_n_pollfds)
372     return FALSE;
373
374   for (i = 0; i < old_n_pollfds; i++)
375     {
376       if (old_pollfds[i].fd != new_pollfds[i].fd ||
377           old_pollfds[i].events != new_pollfds[i].events)
378         return FALSE;
379     }
380
381   return TRUE;
382 }
383
384 /* Begins a polling operation with the specified GPollFD array; the 
385  * timeout is used only to tell if the polling operation is blocking
386  * or non-blocking.
387  *
388  * Return value:
389  *  -1: No file descriptors ready, began asynchronous poll
390  *   0: No file descriptors ready, asynchronous poll not needed
391  * > 0: Number of file descriptors ready
392  */
393 static gint
394 select_thread_start_poll (GPollFD *ufds,
395                           guint    nfds,                          gint     timeout)
396 {
397   gint n_ready;
398   gboolean have_new_pollfds = FALSE;
399   gint poll_fd_index = -1;
400   gint i;
401
402   for (i = 0; i < nfds; i++)
403     if (ufds[i].fd == -1)
404       {
405         poll_fd_index = i;
406         break;
407       }
408   
409   if (nfds == 0 ||
410       (nfds == 1 && poll_fd_index >= 0))
411     {
412       GDK_NOTE (EVENTLOOP, g_print ("EventLoop: Nothing to poll\n"));
413       return 0;
414     }
415
416   /* If we went immediately to an async poll, then we might decide to
417    * dispatch idle functions when higher priority file descriptor sources
418    * are ready to be dispatched. So we always need to first check
419    * check synchronously with a timeout of zero, and only when no
420    * sources are immediately ready, go to the asynchronous poll.
421    *
422    * Of course, if the timeout passed in is 0, then the synchronous
423    * check is sufficient and we never need to do the asynchronous poll.
424    */
425   n_ready = old_poll_func (ufds, nfds, 0);
426   if (n_ready > 0 || timeout == 0)
427     {
428 #ifdef G_ENABLE_DEBUG
429       if ((_gdk_debug_flags & GDK_DEBUG_EVENTLOOP) && n_ready > 0)
430         {
431           g_print ("EventLoop: Found ready file descriptors before waiting\n");
432           dump_poll_result (ufds, nfds);
433         }
434 #endif
435   
436       return n_ready;
437     }
438   
439   SELECT_THREAD_LOCK ();
440
441   if (select_thread_state == BEFORE_START)
442     {
443       select_thread_start ();
444     }
445   
446   if (select_thread_state == POLLING_QUEUED)
447     {
448       /* If the select thread hasn't picked up the set of file descriptors yet
449        * then we can simply replace an old stale set with a new set.
450        */
451       if (!pollfds_equal (ufds, nfds, next_pollfds, next_n_pollfds - 1))
452         {
453           g_free (next_pollfds);
454           next_pollfds = NULL;
455           next_n_pollfds = 0;
456           
457           have_new_pollfds = TRUE;
458         }
459     }
460   else if (select_thread_state == POLLING_RESTART || select_thread_state == POLLING_DESCRIPTORS)
461     {
462       /* If we are already in the process of polling the right set of file descriptors,
463        * there's no need for us to immediately force the select thread to stop polling
464        * and then restart again. And avoiding doing so increases the efficiency considerably
465        * in the common case where we have a set of basically inactive file descriptors that
466        * stay unchanged present as we process many events.
467        *
468        * However, we have to be careful that we don't hit the following race condition
469        *  Select Thread              Main Thread
470        *  -----------------          ---------------
471        *  Polling Completes
472        *                             Reads data or otherwise changes file descriptor state
473        *                             Checks if polling is current
474        *                             Does nothing (*)
475        *                             Releases lock
476        *  Acquires lock
477        *  Marks polling as complete
478        *  Wakes main thread
479        *                             Receives old stale file descriptor state
480        * 
481        * To avoid this, when the new set of poll descriptors is the same as the current
482        * one, we transition to the POLLING_RESTART stage at the point marked (*). When
483        * the select thread wakes up from the poll because a file descriptor is active, if
484        * the state is POLLING_RESTART it immediately begins polling same the file descriptor
485        * set again. This normally will just return the same set of active file descriptors
486        * as the first time, but in sequence described above will properly update the
487        * file descriptor state.
488        *
489        * Special case: this RESTART logic is not needed if the only FD is the internal GLib
490        * "wakeup pipe" that is presented when threads are initialized.
491        *
492        * P.S.: The harm in the above sequence is mostly that sources can be signalled
493        *   as ready when they are no longer ready. This may prompt a blocking read
494        *   from a file descriptor that hangs.
495        */
496       if (!pollfds_equal (ufds, nfds, current_pollfds, current_n_pollfds - 1))
497         have_new_pollfds = TRUE;
498       else
499         {
500           if (!((nfds == 1 && poll_fd_index < 0 && g_thread_supported ()) ||
501                 (nfds == 2 && poll_fd_index >= 0 && g_thread_supported ())))
502             select_thread_set_state (POLLING_RESTART);
503         }
504     }
505   else
506     have_new_pollfds = TRUE;
507
508   if (have_new_pollfds)
509     {
510       GDK_NOTE (EVENTLOOP, g_print ("EventLoop: Submitting a new set of file descriptor to the select thread\n"));
511       
512       g_assert (next_pollfds == NULL);
513       
514       next_n_pollfds = nfds + 1;
515       next_pollfds = g_new (GPollFD, nfds + 1);
516       memcpy (next_pollfds, ufds, nfds * sizeof (GPollFD));
517   
518       next_pollfds[nfds].fd = select_thread_wakeup_pipe[0];
519       next_pollfds[nfds].events = G_IO_IN;
520   
521       if (select_thread_state != POLLING_QUEUED && select_thread_state != WAITING)
522         {
523           if (select_thread_wakeup_pipe[1])
524             {
525               char c = 'A';
526               write (select_thread_wakeup_pipe[1], &c, 1);
527             }
528         }
529       
530       select_thread_set_state (POLLING_QUEUED);
531     }
532   
533   SELECT_THREAD_UNLOCK ();
534
535   return -1;
536 }
537
538 /* End an asynchronous polling operation started with
539  * select_thread_collect_poll(). This must be called if and only if
540  * select_thread_start_poll() return -1. The GPollFD array passed
541  * in must be identical to the one passed to select_thread_start_poll().
542  *
543  * The results of the poll are written into the GPollFD array passed in.
544  *
545  * Return Value: number of file descriptors ready
546  */
547 static int
548 select_thread_collect_poll (GPollFD *ufds, guint nfds)
549 {
550   gint i;
551   gint n_ready = 0;
552   
553   SELECT_THREAD_LOCK ();
554
555   if (select_thread_state == WAITING) /* The poll completed */
556     {
557       for (i = 0; i < nfds; i++)
558         {
559           if (ufds[i].fd == -1)
560             continue;
561           
562           g_assert (ufds[i].fd == current_pollfds[i].fd);
563           g_assert (ufds[i].events == current_pollfds[i].events);
564
565           if (current_pollfds[i].revents)
566             {
567               ufds[i].revents = current_pollfds[i].revents;
568               n_ready++;
569             }
570         }
571       
572 #ifdef G_ENABLE_DEBUG
573       if (_gdk_debug_flags & GDK_DEBUG_EVENTLOOP)
574         {
575           g_print ("EventLoop: Found ready file descriptors after waiting\n");
576           dump_poll_result (ufds, nfds);
577         }
578 #endif
579     }
580
581   SELECT_THREAD_UNLOCK ();
582
583   return n_ready;
584 }
585
586 /************************************************************
587  *********             Main Loop Source             *********
588  ************************************************************/
589
590 gboolean
591 _gdk_quartz_event_loop_check_pending (void)
592 {
593   return current_events && current_events->head;
594 }
595
596 NSEvent*
597 _gdk_quartz_event_loop_get_pending (void)
598 {
599   NSEvent *event = NULL;
600
601   if (current_events)
602     event = g_queue_pop_tail (current_events);
603
604   return event;
605 }
606
607 void
608 _gdk_quartz_event_loop_release_event (NSEvent *event)
609 {
610   [event release];
611 }
612
613 static gboolean
614 gdk_event_prepare (GSource *source,
615                    gint    *timeout)
616 {
617   gboolean retval;
618
619   gdk_threads_enter ();
620   
621   *timeout = -1;
622
623   if (display->event_pause_count > 0)
624     retval = FALSE;
625   else
626     retval = (_gdk_event_queue_find_first (_gdk_display) != NULL ||
627               _gdk_quartz_event_loop_check_pending ());
628
629   gdk_threads_leave ();
630
631   return retval;
632 }
633
634 static gboolean
635 gdk_event_check (GSource *source)
636 {
637   gboolean retval;
638
639   gdk_threads_enter ();
640
641   if (display->event_pause_count > 0)
642     retval = FALSE;
643   else
644     retval = (_gdk_event_queue_find_first (_gdk_display) != NULL ||
645               _gdk_quartz_event_loop_check_pending ());
646
647   gdk_threads_leave ();
648
649   return retval;
650 }
651
652 static gboolean
653 gdk_event_dispatch (GSource     *source,
654                     GSourceFunc  callback,
655                     gpointer     user_data)
656 {
657   GdkEvent *event;
658
659   gdk_threads_enter ();
660
661   /* Refresh the autorelease pool if we're at the base CFRunLoop level
662    * (indicated by current_loop_level) and the base g_main_loop level
663    * (indicated by g_main_depth()). Messing with the autorelease pool at
664    * any level of nesting can cause access to deallocated memory because
665    * autorelease_pool is static and releasing a pool will cause all pools
666    * allocated inside of it to be released as well.
667    */
668   if (current_loop_level == 0 && g_main_depth() == 0)
669     {
670       if (autorelease_pool)
671         [autorelease_pool drain];
672
673       autorelease_pool = [[NSAutoreleasePool alloc] init];
674     }
675
676   _gdk_quartz_display_queue_events (_gdk_display);
677
678   event = _gdk_event_unqueue (_gdk_display);
679
680   if (event)
681     {
682       _gdk_event_emit (event);
683
684       gdk_event_free (event);
685     }
686
687   gdk_threads_leave ();
688
689   return TRUE;
690 }
691
692 static GSourceFuncs event_funcs = {
693   gdk_event_prepare,
694   gdk_event_check,
695   gdk_event_dispatch,
696   NULL
697 };
698
699 /************************************************************
700  *********             Our Poll Function            *********
701  ************************************************************/
702
703 static gint
704 poll_func (GPollFD *ufds,
705            guint    nfds,
706            gint     timeout_)
707 {
708   NSEvent *event;
709   NSDate *limit_date;
710   gint n_ready;
711
712   static GPollFD *last_ufds;
713
714   last_ufds = ufds;
715
716   n_ready = select_thread_start_poll (ufds, nfds, timeout_);
717   if (n_ready > 0)
718     timeout_ = 0;
719
720   if (timeout_ == -1)
721     limit_date = [NSDate distantFuture];
722   else if (timeout_ == 0)
723     limit_date = [NSDate distantPast];
724   else
725     limit_date = [NSDate dateWithTimeIntervalSinceNow:timeout_/1000.0];
726
727   getting_events++;
728   event = [NSApp nextEventMatchingMask: NSAnyEventMask
729                              untilDate: limit_date
730                                 inMode: NSDefaultRunLoopMode
731                                dequeue: YES];
732   getting_events--;
733
734   /* We check if last_ufds did not change since the time this function was
735    * called. It is possible that a recursive main loop (and thus recursive
736    * invocation of this poll function) is triggered while in
737    * nextEventMatchingMask:. If during that time new fds are added,
738    * the cached fds array might be replaced in g_main_context_iterate().
739    * So, we should avoid accessing the old fd array (still pointed at by
740    * ufds) here in that case, since it might have been freed. We avoid this
741    * by not calling the collect stage.
742    */
743   if (last_ufds == ufds && n_ready < 0)
744     n_ready = select_thread_collect_poll (ufds, nfds);
745       
746   if (event &&
747       [event type] == NSApplicationDefined &&
748       [event subtype] == GDK_QUARTZ_EVENT_SUBTYPE_EVENTLOOP)
749     {
750       /* Just used to wake us up; if an event and a FD arrived at the same
751        * time; could have come from a previous iteration in some cases,
752        * but the spurious wake up is harmless if a little inefficient.
753        */
754       event = NULL;
755     }
756
757   if (event) 
758     {
759       if (!current_events)
760         current_events = g_queue_new ();
761       g_queue_push_head (current_events, [event retain]);
762     }
763
764   return n_ready;
765 }
766
767 /************************************************************
768  *********  Running the main loop out of CFRunLoop  *********
769  ************************************************************/
770
771 /* Wrapper around g_main_context_query() that handles reallocating
772  * run_loop_pollfds up to the proper size
773  */
774 static gint
775 query_main_context (GMainContext *context,
776                     int           max_priority,
777                     int          *timeout)
778 {
779   gint nfds;
780   
781   if (!run_loop_pollfds)
782     {
783       run_loop_pollfds_size = RUN_LOOP_POLLFDS_INITIAL_SIZE;
784       run_loop_pollfds = g_new (GPollFD, run_loop_pollfds_size);
785     }
786
787   while ((nfds = g_main_context_query (context, max_priority, timeout,
788                                        run_loop_pollfds, 
789                                        run_loop_pollfds_size)) > run_loop_pollfds_size)
790     {
791       g_free (run_loop_pollfds);
792       run_loop_pollfds_size = nfds;
793       run_loop_pollfds = g_new (GPollFD, nfds);
794     }
795
796   return nfds;
797 }
798
799 static void
800 run_loop_entry (void)
801 {
802   if (acquired_loop_level == -1)
803     {
804       if (g_main_context_acquire (NULL))
805         {
806           GDK_NOTE (EVENTLOOP, g_print ("EventLoop: Beginning tracking run loop activity\n"));
807           acquired_loop_level = current_loop_level;
808         }
809       else
810         {
811           /* If we fail to acquire the main context, that means someone is iterating
812            * the main context in a different thread; we simply wait until this loop
813            * exits and then try again at next entry. In general, iterating the loop
814            * from a different thread is rare: it is only possible when GDK threading
815            * is initialized and is not frequently used even then. So, we hope that
816            * having GLib main loop iteration blocked in the combination of that and
817            * a native modal operation is a minimal problem. We could imagine using a
818            * thread that does g_main_context_wait() and then wakes us back up, but
819            * the gain doesn't seem worth the complexity.
820            */
821           GDK_NOTE (EVENTLOOP, g_print ("EventLoop: Can't acquire main loop; skipping tracking run loop activity\n"));
822         }
823     }
824 }
825
826 static void
827 run_loop_before_timers (void)
828 {
829 }
830
831 static void
832 run_loop_before_sources (void)
833 {
834   GMainContext *context = g_main_context_default ();
835   gint max_priority;
836   gint nfds;
837
838   /* Before we let the CFRunLoop process sources, we want to check if there
839    * are any pending GLib main loop sources more urgent than
840    * G_PRIORITY_DEFAULT that need to be dispatched. (We consider all activity
841    * from the CFRunLoop to have a priority of G_PRIORITY_DEFAULT.) If no
842    * sources are processed by the CFRunLoop, then processing will continue
843    * on to the BeforeWaiting stage where we check for lower priority sources.
844    */
845   
846   g_main_context_prepare (context, &max_priority); 
847   max_priority = MIN (max_priority, G_PRIORITY_DEFAULT);
848
849   /* We ignore the timeout that query_main_context () returns since we'll
850    * always query again before waiting.
851    */
852   nfds = query_main_context (context, max_priority, NULL);
853
854   if (nfds)
855     old_poll_func (run_loop_pollfds, nfds, 0);
856   
857   if (g_main_context_check (context, max_priority, run_loop_pollfds, nfds))
858     {
859       GDK_NOTE (EVENTLOOP, g_print ("EventLoop: Dispatching high priority sources\n"));
860       g_main_context_dispatch (context);
861     }
862 }
863
864 static void
865 dummy_timer_callback (CFRunLoopTimerRef  timer,
866                       void              *info)
867 {
868   /* Nothing; won't normally even be called */
869 }
870
871 static void
872 run_loop_before_waiting (void)
873 {
874   GMainContext *context = g_main_context_default ();
875   gint timeout;
876   gint n_ready;
877
878   /* At this point, the CFRunLoop is ready to wait. We start a GMain loop
879    * iteration by calling the check() and query() stages. We start a
880    * poll, and if it doesn't complete immediately we let the run loop
881    * go ahead and sleep. Before doing that, if there was a timeout from
882    * GLib, we set up a CFRunLoopTimer to wake us up.
883    */
884   
885   g_main_context_prepare (context, &run_loop_max_priority); 
886   
887   run_loop_n_pollfds = query_main_context (context, run_loop_max_priority, &timeout);
888
889   n_ready = select_thread_start_poll (run_loop_pollfds, run_loop_n_pollfds, timeout);
890
891   if (n_ready > 0 || timeout == 0)
892     {
893       /* We have stuff to do, no sleeping allowed! */
894       CFRunLoopWakeUp (main_thread_run_loop);
895     }
896   else if (timeout > 0)
897     {
898       /* We need to get the run loop to break out of its wait when our timeout
899        * expires. We do this by adding a dummy timer that we'll remove immediately
900        * after the wait wakes up.
901        */
902       GDK_NOTE (EVENTLOOP, g_print ("EventLoop: Adding timer to wake us up in %d milliseconds\n", timeout));
903       
904       run_loop_timer = CFRunLoopTimerCreate (NULL, /* allocator */
905                                              CFAbsoluteTimeGetCurrent () + timeout / 1000.,
906                                              0, /* interval (0=does not repeat) */
907                                              0, /* flags */
908                                              0, /* order (priority) */
909                                              dummy_timer_callback,
910                                              NULL);
911
912       CFRunLoopAddTimer (main_thread_run_loop, run_loop_timer, kCFRunLoopCommonModes);
913     }
914   
915   run_loop_polling_async = n_ready < 0;
916 }
917
918 static void
919 run_loop_after_waiting (void)
920 {
921   GMainContext *context = g_main_context_default ();
922
923   /* After sleeping, we finish of the GMain loop iteratin started in before_waiting()
924    * by doing the check() and dispatch() stages.
925    */
926
927   if (run_loop_timer)
928     {
929       CFRunLoopRemoveTimer (main_thread_run_loop, run_loop_timer, kCFRunLoopCommonModes);
930       CFRelease (run_loop_timer);
931       run_loop_timer = NULL;
932     }
933   
934   if (run_loop_polling_async)
935     {
936       select_thread_collect_poll (run_loop_pollfds, run_loop_n_pollfds);
937       run_loop_polling_async = FALSE;
938     }
939   
940   if (g_main_context_check (context, run_loop_max_priority, run_loop_pollfds, run_loop_n_pollfds))
941     {
942       GDK_NOTE (EVENTLOOP, g_print ("EventLoop: Dispatching after waiting\n"));
943       g_main_context_dispatch (context);
944     }
945 }
946
947 static void
948 run_loop_exit (void)
949 {
950   /* + 1 because we decrement current_loop_level separately in observer_callback() */
951   if ((current_loop_level + 1) == acquired_loop_level)
952     {
953       g_main_context_release (NULL);
954       acquired_loop_level = -1;
955       GDK_NOTE (EVENTLOOP, g_print ("EventLoop: Ended tracking run loop activity\n"));
956     }
957 }
958
959 static void
960 run_loop_observer_callback (CFRunLoopObserverRef observer,
961                             CFRunLoopActivity    activity,
962                             void                *info)
963 {
964   switch (activity)
965     {
966     case kCFRunLoopEntry:
967       current_loop_level++;
968       break;
969     case kCFRunLoopExit:
970       g_return_if_fail (current_loop_level > 0);
971       current_loop_level--;
972       break;
973     default:
974       break;
975     }
976
977   if (getting_events > 0) /* Activity we triggered */
978     return;
979
980   switch (activity)
981     {
982     case kCFRunLoopEntry:
983       run_loop_entry ();
984       break;
985     case kCFRunLoopBeforeTimers:
986       run_loop_before_timers ();
987       break;
988     case kCFRunLoopBeforeSources:
989       run_loop_before_sources ();
990       break;
991     case kCFRunLoopBeforeWaiting:
992       run_loop_before_waiting ();
993       break;
994     case kCFRunLoopAfterWaiting:
995       run_loop_after_waiting ();
996       break;
997     case kCFRunLoopExit:
998       run_loop_exit ();
999       break;
1000     default:
1001       break;
1002     }
1003 }
1004
1005 /************************************************************/
1006
1007 void
1008 _gdk_quartz_event_loop_init (void)
1009 {
1010   GSource *source;
1011   CFRunLoopObserverRef observer;
1012
1013   /* Hook into the GLib main loop */
1014
1015   event_poll_fd.events = G_IO_IN;
1016   event_poll_fd.fd = -1;
1017
1018   source = g_source_new (&event_funcs, sizeof (GSource));
1019   g_source_set_name (source, "GDK Quartz event source"); 
1020   g_source_add_poll (source, &event_poll_fd);
1021   g_source_set_priority (source, GDK_PRIORITY_EVENTS);
1022   g_source_set_can_recurse (source, TRUE);
1023   g_source_attach (source, NULL);
1024
1025   old_poll_func = g_main_context_get_poll_func (NULL);
1026   g_main_context_set_poll_func (NULL, poll_func);
1027   
1028   /* Hook into the the CFRunLoop for the main thread */
1029
1030   main_thread_run_loop = CFRunLoopGetCurrent ();
1031
1032   observer = CFRunLoopObserverCreate (NULL, /* default allocator */
1033                                       kCFRunLoopAllActivities,
1034                                       true, /* repeats: not one-shot */
1035                                       0, /* order (priority) */
1036                                       run_loop_observer_callback,
1037                                       NULL);
1038                                      
1039   CFRunLoopAddObserver (main_thread_run_loop, observer, kCFRunLoopCommonModes);
1040   
1041   /* Initialize our autorelease pool */
1042
1043   autorelease_pool = [[NSAutoreleasePool alloc] init];
1044 }