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
select_thread_set_state(SelectThreadState new_state)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
signal_main_thread(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 *
select_thread_func(void * arg)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
got_fd_activity(void * info)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
select_thread_start(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
dump_poll_result(GPollFD * ufds,guint nfds)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
pollfds_equal(GPollFD * old_pollfds,guint old_n_pollfds,GPollFD * new_pollfds,guint new_n_pollfds)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
select_thread_start_poll(GPollFD * ufds,guint nfds,gint timeout)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
select_thread_collect_poll(GPollFD * ufds,guint nfds)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
_gdk_quartz_event_loop_check_pending(void)591 _gdk_quartz_event_loop_check_pending (void)
592 {
593 return current_events && current_events->head;
594 }
595
596 NSEvent*
_gdk_quartz_event_loop_get_pending(void)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
_gdk_quartz_event_loop_release_event(NSEvent * event)608 _gdk_quartz_event_loop_release_event (NSEvent *event)
609 {
610 [event release];
611 }
612
613 static gboolean
gdk_event_prepare(GSource * source,gint * timeout)614 gdk_event_prepare (GSource *source,
615 gint *timeout)
616 {
617 gboolean retval;
618
619 GDK_THREADS_ENTER ();
620
621 /* The prepare stage is the stage before the main loop starts polling
622 * and dispatching events. The autorelease poll is drained here for
623 * the preceding main loop iteration or, in case of the first iteration,
624 * for the operations carried out between event loop initialization and
625 * this first iteration.
626 *
627 * The autorelease poll must only be drained when the following conditions
628 * apply:
629 * - We are at the base CFRunLoop level (indicated by current_loop_level),
630 * - We are at the base g_main_loop level (indicated by
631 * g_main_depth())
632 * - We are at the base poll_func level (indicated by getting events).
633 *
634 * Messing with the autorelease pool at any level of nesting can cause access
635 * to deallocated memory because autorelease_pool is static and releasing a
636 * pool will cause all pools allocated inside of it to be released as well.
637 */
638 if (current_loop_level == 0 && g_main_depth() == 0 && getting_events == 0)
639 {
640 if (autorelease_pool)
641 [autorelease_pool drain];
642
643 autorelease_pool = [[NSAutoreleasePool alloc] init];
644 }
645
646 *timeout = -1;
647
648 retval = (_gdk_event_queue_find_first (_gdk_display) != NULL ||
649 _gdk_quartz_event_loop_check_pending ());
650
651 GDK_THREADS_LEAVE ();
652
653 return retval;
654 }
655
656 static gboolean
gdk_event_check(GSource * source)657 gdk_event_check (GSource *source)
658 {
659 gboolean retval;
660
661 GDK_THREADS_ENTER ();
662
663 retval = (_gdk_event_queue_find_first (_gdk_display) != NULL ||
664 _gdk_quartz_event_loop_check_pending ());
665
666 GDK_THREADS_LEAVE ();
667
668 return retval;
669 }
670
671 static gboolean
gdk_event_dispatch(GSource * source,GSourceFunc callback,gpointer user_data)672 gdk_event_dispatch (GSource *source,
673 GSourceFunc callback,
674 gpointer user_data)
675 {
676 GdkEvent *event;
677
678 GDK_THREADS_ENTER ();
679
680 _gdk_events_queue (_gdk_display);
681
682 event = _gdk_event_unqueue (_gdk_display);
683
684 if (event)
685 {
686 if (_gdk_event_func)
687 (*_gdk_event_func) (event, _gdk_event_data);
688
689 gdk_event_free (event);
690 }
691
692 GDK_THREADS_LEAVE ();
693
694 return TRUE;
695 }
696
697 static GSourceFuncs event_funcs = {
698 gdk_event_prepare,
699 gdk_event_check,
700 gdk_event_dispatch,
701 NULL
702 };
703
704 /************************************************************
705 ********* Our Poll Function *********
706 ************************************************************/
707
708 static gint
poll_func(GPollFD * ufds,guint nfds,gint timeout_)709 poll_func (GPollFD *ufds,
710 guint nfds,
711 gint timeout_)
712 {
713 NSEvent *event;
714 NSDate *limit_date;
715 gint n_ready;
716
717 static GPollFD *last_ufds;
718
719 last_ufds = ufds;
720
721 n_ready = select_thread_start_poll (ufds, nfds, timeout_);
722 if (n_ready > 0)
723 timeout_ = 0;
724
725 if (timeout_ == -1)
726 limit_date = [NSDate distantFuture];
727 else if (timeout_ == 0)
728 limit_date = [NSDate distantPast];
729 else
730 limit_date = [NSDate dateWithTimeIntervalSinceNow:timeout_/1000.0];
731
732 getting_events++;
733 event = [NSApp nextEventMatchingMask: NSAnyEventMask
734 untilDate: limit_date
735 inMode: NSDefaultRunLoopMode
736 dequeue: YES];
737 getting_events--;
738
739 /* We check if last_ufds did not change since the time this function was
740 * called. It is possible that a recursive main loop (and thus recursive
741 * invocation of this poll function) is triggered while in
742 * nextEventMatchingMask:. If during that time new fds are added,
743 * the cached fds array might be replaced in g_main_context_iterate().
744 * So, we should avoid accessing the old fd array (still pointed at by
745 * ufds) here in that case, since it might have been freed. We avoid this
746 * by not calling the collect stage.
747 */
748 if (last_ufds == ufds && n_ready < 0)
749 n_ready = select_thread_collect_poll (ufds, nfds);
750
751 if (event &&
752 [event type] == NSApplicationDefined &&
753 [event subtype] == GDK_QUARTZ_EVENT_SUBTYPE_EVENTLOOP)
754 {
755 /* Just used to wake us up; if an event and a FD arrived at the same
756 * time; could have come from a previous iteration in some cases,
757 * but the spurious wake up is harmless if a little inefficient.
758 */
759 event = NULL;
760 }
761
762 if (event)
763 {
764 if (!current_events)
765 current_events = g_queue_new ();
766 g_queue_push_head (current_events, [event retain]);
767 }
768
769 return n_ready;
770 }
771
772 /************************************************************
773 ********* Running the main loop out of CFRunLoop *********
774 ************************************************************/
775
776 /* Wrapper around g_main_context_query() that handles reallocating
777 * run_loop_pollfds up to the proper size
778 */
779 static gint
query_main_context(GMainContext * context,int max_priority,int * timeout)780 query_main_context (GMainContext *context,
781 int max_priority,
782 int *timeout)
783 {
784 gint nfds;
785
786 if (!run_loop_pollfds)
787 {
788 run_loop_pollfds_size = RUN_LOOP_POLLFDS_INITIAL_SIZE;
789 run_loop_pollfds = g_new (GPollFD, run_loop_pollfds_size);
790 }
791
792 while ((nfds = g_main_context_query (context, max_priority, timeout,
793 run_loop_pollfds,
794 run_loop_pollfds_size)) > run_loop_pollfds_size)
795 {
796 g_free (run_loop_pollfds);
797 run_loop_pollfds_size = nfds;
798 run_loop_pollfds = g_new (GPollFD, nfds);
799 }
800
801 return nfds;
802 }
803
804 static void
run_loop_entry(void)805 run_loop_entry (void)
806 {
807 if (acquired_loop_level == -1)
808 {
809 if (g_main_context_acquire (NULL))
810 {
811 GDK_NOTE (EVENTLOOP, g_print ("EventLoop: Beginning tracking run loop activity\n"));
812 acquired_loop_level = current_loop_level;
813 }
814 else
815 {
816 /* If we fail to acquire the main context, that means someone is iterating
817 * the main context in a different thread; we simply wait until this loop
818 * exits and then try again at next entry. In general, iterating the loop
819 * from a different thread is rare: it is only possible when GDK threading
820 * is initialized and is not frequently used even then. So, we hope that
821 * having GLib main loop iteration blocked in the combination of that and
822 * a native modal operation is a minimal problem. We could imagine using a
823 * thread that does g_main_context_wait() and then wakes us back up, but
824 * the gain doesn't seem worth the complexity.
825 */
826 GDK_NOTE (EVENTLOOP, g_print ("EventLoop: Can't acquire main loop; skipping tracking run loop activity\n"));
827 }
828 }
829 }
830
831 static void
run_loop_before_timers(void)832 run_loop_before_timers (void)
833 {
834 }
835
836 static void
run_loop_before_sources(void)837 run_loop_before_sources (void)
838 {
839 GMainContext *context = g_main_context_default ();
840 gint max_priority;
841 gint nfds;
842
843 /* Before we let the CFRunLoop process sources, we want to check if there
844 * are any pending GLib main loop sources more urgent than
845 * G_PRIORITY_DEFAULT that need to be dispatched. (We consider all activity
846 * from the CFRunLoop to have a priority of G_PRIORITY_DEFAULT.) If no
847 * sources are processed by the CFRunLoop, then processing will continue
848 * on to the BeforeWaiting stage where we check for lower priority sources.
849 */
850
851 g_main_context_prepare (context, &max_priority);
852 max_priority = MIN (max_priority, G_PRIORITY_DEFAULT);
853
854 /* We ignore the timeout that query_main_context () returns since we'll
855 * always query again before waiting.
856 */
857 nfds = query_main_context (context, max_priority, NULL);
858
859 if (nfds)
860 old_poll_func (run_loop_pollfds, nfds, 0);
861
862 if (g_main_context_check (context, max_priority, run_loop_pollfds, nfds))
863 {
864 GDK_NOTE (EVENTLOOP, g_print ("EventLoop: Dispatching high priority sources\n"));
865 g_main_context_dispatch (context);
866 }
867 }
868
869 static void
dummy_timer_callback(CFRunLoopTimerRef timer,void * info)870 dummy_timer_callback (CFRunLoopTimerRef timer,
871 void *info)
872 {
873 /* Nothing; won't normally even be called */
874 }
875
876 static void
run_loop_before_waiting(void)877 run_loop_before_waiting (void)
878 {
879 GMainContext *context = g_main_context_default ();
880 gint timeout;
881 gint n_ready;
882
883 /* At this point, the CFRunLoop is ready to wait. We start a GMain loop
884 * iteration by calling the check() and query() stages. We start a
885 * poll, and if it doesn't complete immediately we let the run loop
886 * go ahead and sleep. Before doing that, if there was a timeout from
887 * GLib, we set up a CFRunLoopTimer to wake us up.
888 */
889
890 g_main_context_prepare (context, &run_loop_max_priority);
891
892 run_loop_n_pollfds = query_main_context (context, run_loop_max_priority, &timeout);
893
894 n_ready = select_thread_start_poll (run_loop_pollfds, run_loop_n_pollfds, timeout);
895
896 if (n_ready > 0 || timeout == 0)
897 {
898 /* We have stuff to do, no sleeping allowed! */
899 CFRunLoopWakeUp (main_thread_run_loop);
900 }
901 else if (timeout > 0)
902 {
903 /* We need to get the run loop to break out of it's wait when our timeout
904 * expires. We do this by adding a dummy timer that we'll remove immediately
905 * after the wait wakes up.
906 */
907 GDK_NOTE (EVENTLOOP, g_print ("EventLoop: Adding timer to wake us up in %d milliseconds\n", timeout));
908
909 run_loop_timer = CFRunLoopTimerCreate (NULL, /* allocator */
910 CFAbsoluteTimeGetCurrent () + timeout / 1000.,
911 0, /* interval (0=does not repeat) */
912 0, /* flags */
913 0, /* order (priority) */
914 dummy_timer_callback,
915 NULL);
916
917 CFRunLoopAddTimer (main_thread_run_loop, run_loop_timer, kCFRunLoopCommonModes);
918 }
919
920 run_loop_polling_async = n_ready < 0;
921 }
922
923 static void
run_loop_after_waiting(void)924 run_loop_after_waiting (void)
925 {
926 GMainContext *context = g_main_context_default ();
927
928 /* After sleeping, we finish of the GMain loop iteratin started in before_waiting()
929 * by doing the check() and dispatch() stages.
930 */
931
932 if (run_loop_timer)
933 {
934 CFRunLoopRemoveTimer (main_thread_run_loop, run_loop_timer, kCFRunLoopCommonModes);
935 CFRelease (run_loop_timer);
936 run_loop_timer = NULL;
937 }
938
939 if (run_loop_polling_async)
940 {
941 select_thread_collect_poll (run_loop_pollfds, run_loop_n_pollfds);
942 run_loop_polling_async = FALSE;
943 }
944
945 if (g_main_context_check (context, run_loop_max_priority, run_loop_pollfds, run_loop_n_pollfds))
946 {
947 GDK_NOTE (EVENTLOOP, g_print ("EventLoop: Dispatching after waiting\n"));
948 g_main_context_dispatch (context);
949 }
950 }
951
952 static void
run_loop_exit(void)953 run_loop_exit (void)
954 {
955 /* + 1 because we decrement current_loop_level separately in observer_callback() */
956 if ((current_loop_level + 1) == acquired_loop_level)
957 {
958 g_main_context_release (NULL);
959 acquired_loop_level = -1;
960 GDK_NOTE (EVENTLOOP, g_print ("EventLoop: Ended tracking run loop activity\n"));
961 }
962 }
963
964 static void
run_loop_observer_callback(CFRunLoopObserverRef observer,CFRunLoopActivity activity,void * info)965 run_loop_observer_callback (CFRunLoopObserverRef observer,
966 CFRunLoopActivity activity,
967 void *info)
968 {
969 switch (activity)
970 {
971 case kCFRunLoopEntry:
972 current_loop_level++;
973 break;
974 case kCFRunLoopExit:
975 g_return_if_fail (current_loop_level > 0);
976 current_loop_level--;
977 break;
978 default:
979 break;
980 }
981
982 if (getting_events > 0) /* Activity we triggered */
983 return;
984
985 switch (activity)
986 {
987 case kCFRunLoopEntry:
988 run_loop_entry ();
989 break;
990 case kCFRunLoopBeforeTimers:
991 run_loop_before_timers ();
992 break;
993 case kCFRunLoopBeforeSources:
994 run_loop_before_sources ();
995 break;
996 case kCFRunLoopBeforeWaiting:
997 run_loop_before_waiting ();
998 break;
999 case kCFRunLoopAfterWaiting:
1000 run_loop_after_waiting ();
1001 break;
1002 case kCFRunLoopExit:
1003 run_loop_exit ();
1004 break;
1005 default:
1006 break;
1007 }
1008 }
1009
1010 /************************************************************/
1011
1012 void
_gdk_quartz_event_loop_init(void)1013 _gdk_quartz_event_loop_init (void)
1014 {
1015 GSource *source;
1016 CFRunLoopObserverRef observer;
1017
1018 /* Hook into the GLib main loop */
1019
1020 event_poll_fd.events = G_IO_IN;
1021 event_poll_fd.fd = -1;
1022
1023 source = g_source_new (&event_funcs, sizeof (GSource));
1024 g_source_set_name (source, "GDK Quartz event source");
1025 g_source_add_poll (source, &event_poll_fd);
1026 g_source_set_priority (source, GDK_PRIORITY_EVENTS);
1027 g_source_set_can_recurse (source, TRUE);
1028 g_source_attach (source, NULL);
1029
1030 old_poll_func = g_main_context_get_poll_func (NULL);
1031 g_main_context_set_poll_func (NULL, poll_func);
1032
1033 /* Hook into the the CFRunLoop for the main thread */
1034
1035 main_thread_run_loop = CFRunLoopGetCurrent ();
1036
1037 observer = CFRunLoopObserverCreate (NULL, /* default allocator */
1038 kCFRunLoopAllActivities,
1039 true, /* repeats: not one-shot */
1040 0, /* order (priority) */
1041 run_loop_observer_callback,
1042 NULL);
1043
1044 CFRunLoopAddObserver (main_thread_run_loop, observer, kCFRunLoopCommonModes);
1045
1046 /* Initialize our autorelease pool */
1047
1048 autorelease_pool = [[NSAutoreleasePool alloc] init];
1049 }
1050