Bug 1637 - Master clock improvements
[profile/ivi/clutter.git] / clutter / clutter-main.c
1 /*
2  * Clutter.
3  *
4  * An OpenGL based 'interactive canvas' library.
5  *
6  * Authored By Matthew Allum  <mallum@openedhand.com>
7  *
8  * Copyright (C) 2006 OpenedHand
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the
22  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23  * Boston, MA 02111-1307, USA.
24  */
25 /**
26  * SECTION:clutter-main
27  * @short_description: Various 'global' clutter functions.
28  *
29  * Functions to retrieve various global Clutter resources and other utility
30  * functions for mainloops, events and threads
31  */
32
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
36
37 #include <stdlib.h>
38 #include <glib/gi18n-lib.h>
39 #include <locale.h>
40
41 #include "clutter-event.h"
42 #include "clutter-backend.h"
43 #include "clutter-main.h"
44 #include "clutter-master-clock.h"
45 #include "clutter-feature.h"
46 #include "clutter-actor.h"
47 #include "clutter-stage.h"
48 #include "clutter-private.h"
49 #include "clutter-debug.h"
50 #include "clutter-version.h"    /* For flavour define */
51 #include "clutter-frame-source.h"
52
53 #include "cogl/cogl.h"
54 #include "pango/cogl-pango.h"
55
56 /* main context */
57 static ClutterMainContext *ClutterCntx       = NULL;
58
59 /* main lock and locking/unlocking functions */
60 static GMutex *clutter_threads_mutex         = NULL;
61 static GCallback clutter_threads_lock        = NULL;
62 static GCallback clutter_threads_unlock      = NULL;
63
64 /* command line options */
65 static gboolean clutter_is_initialized       = FALSE;
66 static gboolean clutter_show_fps             = FALSE;
67 static gboolean clutter_fatal_warnings       = FALSE;
68 static gboolean clutter_disable_mipmap_text  = FALSE;
69 static gboolean clutter_use_fuzzy_picking    = FALSE;
70
71 static guint clutter_default_fps             = 60;
72
73 static PangoDirection clutter_text_direction = PANGO_DIRECTION_LTR;
74
75 static guint clutter_main_loop_level         = 0;
76 static GSList *main_loops                    = NULL;
77
78 guint clutter_debug_flags = 0;  /* global clutter debug flag */
79
80 #ifdef CLUTTER_ENABLE_DEBUG
81 static const GDebugKey clutter_debug_keys[] = {
82   { "misc", CLUTTER_DEBUG_MISC },
83   { "actor", CLUTTER_DEBUG_ACTOR },
84   { "texture", CLUTTER_DEBUG_TEXTURE },
85   { "event", CLUTTER_DEBUG_EVENT },
86   { "paint", CLUTTER_DEBUG_PAINT },
87   { "gl", CLUTTER_DEBUG_GL },
88   { "alpha", CLUTTER_DEBUG_ALPHA },
89   { "behaviour", CLUTTER_DEBUG_BEHAVIOUR },
90   { "pango", CLUTTER_DEBUG_PANGO },
91   { "backend", CLUTTER_DEBUG_BACKEND },
92   { "scheduler", CLUTTER_DEBUG_SCHEDULER },
93   { "script", CLUTTER_DEBUG_SCRIPT },
94   { "shader", CLUTTER_DEBUG_SHADER },
95   { "multistage", CLUTTER_DEBUG_MULTISTAGE },
96   { "animation", CLUTTER_DEBUG_ANIMATION },
97   { "layout", CLUTTER_DEBUG_LAYOUT }
98 };
99 #endif /* CLUTTER_ENABLE_DEBUG */
100
101 /**
102  * clutter_get_show_fps:
103  *
104  * Returns whether Clutter should print out the frames per second on the
105  * console. You can enable this setting either using the
106  * <literal>CLUTTER_SHOW_FPS</literal> environment variable or passing
107  * the <literal>--clutter-show-fps</literal> command line argument. *
108  *
109  * Return value: %TRUE if Clutter should show the FPS.
110  *
111  * Since: 0.4
112  */
113 gboolean
114 clutter_get_show_fps (void)
115 {
116   return clutter_show_fps;
117 }
118
119 void
120 _clutter_stage_maybe_relayout (ClutterActor *stage)
121 {
122   gfloat natural_width, natural_height;
123   ClutterActorBox box = { 0, };
124
125   /* avoid reentrancy */
126   if (!(CLUTTER_PRIVATE_FLAGS (stage) & CLUTTER_ACTOR_IN_RELAYOUT))
127     {
128       CLUTTER_NOTE (ACTOR, "Recomputing layout");
129
130       CLUTTER_SET_PRIVATE_FLAGS (stage, CLUTTER_ACTOR_IN_RELAYOUT);
131
132       natural_width = natural_height = 0;
133       clutter_actor_get_preferred_size (stage,
134                                         NULL, NULL,
135                                         &natural_width, &natural_height);
136
137       box.x1 = 0;
138       box.y1 = 0;
139       box.x2 = natural_width;
140       box.y2 = natural_height;
141
142       CLUTTER_NOTE (ACTOR, "Allocating (0, 0 - %d, %d) for the stage",
143                     (int) natural_width,
144                     (int) natural_height);
145
146       clutter_actor_allocate (stage, &box, CLUTTER_ALLOCATION_NONE);
147
148       CLUTTER_UNSET_PRIVATE_FLAGS (stage, CLUTTER_ACTOR_IN_RELAYOUT);
149     }
150 }
151
152 void
153 _clutter_stage_maybe_setup_viewport (ClutterStage *stage)
154 {
155   if (CLUTTER_PRIVATE_FLAGS (stage) & CLUTTER_ACTOR_SYNC_MATRICES)
156     {
157       ClutterPerspective perspective;
158       gfloat width, height;
159
160       clutter_actor_get_size (CLUTTER_ACTOR (stage), &width, &height);
161       clutter_stage_get_perspective (stage, &perspective);
162
163       CLUTTER_NOTE (PAINT,
164                     "Setting up the viewport { w:%.2f, h:%.2f }",
165                     width, height);
166
167       _cogl_setup_viewport (width, height,
168                             perspective.fovy,
169                             perspective.aspect,
170                             perspective.z_near,
171                             perspective.z_far);
172
173       CLUTTER_UNSET_PRIVATE_FLAGS (stage, CLUTTER_ACTOR_SYNC_MATRICES);
174     }
175 }
176
177 void
178 _clutter_do_redraw (ClutterStage *stage)
179 {
180   ClutterMainContext *ctx;
181   ClutterMasterClock *master_clock;
182   static GTimer *timer = NULL;
183   static guint timer_n_frames = 0;
184
185   ctx  = clutter_context_get_default ();
186   master_clock = _clutter_master_clock_get_default ();
187
188   /* Before we can paint, we have to be sure we have the latest layout */
189   _clutter_stage_maybe_relayout (CLUTTER_ACTOR (stage));
190
191   _clutter_backend_ensure_context (ctx->backend, stage);
192
193   /* Setup FPS count - not currently across *all* stages rather than per */
194   if (G_UNLIKELY (clutter_get_show_fps ()))
195     {
196       if (!timer)
197         timer = g_timer_new ();
198     }
199
200   /* The code below can't go in stage paint as base actor_paint
201    * will get called before it (and break picking, etc)
202    */
203   _clutter_stage_maybe_setup_viewport (stage);
204
205   /* Call through to the actual backend to do the painting down from
206    * the stage. It will likely need to swap buffers, vblank sync etc
207    * which will be windowing system dependent
208   */
209   _clutter_backend_redraw (ctx->backend, stage);
210
211   /* Complete FPS info */
212   if (G_UNLIKELY (clutter_get_show_fps ()))
213     {
214       timer_n_frames++;
215
216       if (g_timer_elapsed (timer, NULL) >= 1.0)
217         {
218           g_print ("*** FPS: %i ***\n", timer_n_frames);
219           timer_n_frames = 0;
220           g_timer_start (timer);
221         }
222     }
223
224   CLUTTER_TIMESTAMP (SCHEDULER, "Redraw finish for stage:%p", stage);
225 }
226
227 /**
228  * clutter_redraw:
229  *
230  * Forces a redraw of the entire stage. Applications should never use this
231  * function, but queue a redraw using clutter_actor_queue_redraw().
232  *
233  * This function should only be used by libraries integrating Clutter from
234  * within another toolkit.
235  */
236 void
237 clutter_redraw (ClutterStage *stage)
238 {
239   g_return_if_fail (CLUTTER_IS_STAGE (stage));
240
241   clutter_stage_ensure_redraw (stage);
242 }
243
244 /**
245  * clutter_set_motion_events_enabled:
246  * @enable: %TRUE to enable per-actor motion events
247  *
248  * Sets whether per-actor motion events should be enabled or not (the
249  * default is to enable them).
250  *
251  * If @enable is %FALSE the following events will not work:
252  * <itemizedlist>
253  *   <listitem><para>ClutterActor::motion-event, unless on the
254  *     #ClutterStage</para></listitem>
255  *   <listitem><para>ClutterActor::enter-event</para></listitem>
256  *   <listitem><para>ClutterActor::leave-event</para></listitem>
257  * </itemizedlist>
258  *
259  * Since: 0.6
260  */
261 void
262 clutter_set_motion_events_enabled (gboolean enable)
263 {
264   ClutterMainContext *context = clutter_context_get_default ();
265
266   context->motion_events_per_actor = enable;
267 }
268
269 /**
270  * clutter_get_motion_events_enabled:
271  *
272  * Gets whether the per-actor motion events are enabled.
273  *
274  * Return value: %TRUE if the motion events are enabled
275  *
276  * Since: 0.6
277  */
278 gboolean
279 clutter_get_motion_events_enabled (void)
280 {
281   ClutterMainContext *context = clutter_context_get_default ();
282
283   return context->motion_events_per_actor;
284 }
285
286 guint _clutter_pix_to_id (guchar pixel[4]);
287
288 static inline void init_bits (void)
289 {
290   ClutterMainContext *ctx;
291
292   static gboolean done = FALSE;
293   if (G_LIKELY (done))
294     return;
295
296   ctx = clutter_context_get_default ();
297
298   done = TRUE;
299 }
300
301 void
302 _clutter_id_to_color (guint id, ClutterColor *col)
303 {
304   ClutterMainContext *ctx;
305   gint                red, green, blue;
306   ctx = clutter_context_get_default ();
307
308   /* compute the numbers we'll store in the components */
309   red   = (id >> (ctx->fb_g_mask_used+ctx->fb_b_mask_used))
310                 & (0xff >> (8-ctx->fb_r_mask_used));
311   green = (id >> ctx->fb_b_mask_used) & (0xff >> (8-ctx->fb_g_mask_used));
312   blue  = (id)  & (0xff >> (8-ctx->fb_b_mask_used));
313
314   /* shift left bits a bit and add one, this circumvents
315    * at least some potential rounding errors in GL/GLES
316    * driver / hw implementation.
317    */
318   if (ctx->fb_r_mask_used != ctx->fb_r_mask)
319     red = red * 2;
320   if (ctx->fb_g_mask_used != ctx->fb_g_mask)
321     green = green * 2;
322   if (ctx->fb_b_mask_used != ctx->fb_b_mask)
323     blue  = blue  * 2;
324
325   /* shift up to be full 8bit values */
326   red   = (red   << (8 - ctx->fb_r_mask)) | (0x7f >> (ctx->fb_r_mask_used));
327   green = (green << (8 - ctx->fb_g_mask)) | (0x7f >> (ctx->fb_g_mask_used));
328   blue  = (blue  << (8 - ctx->fb_b_mask)) | (0x7f >> (ctx->fb_b_mask_used));
329
330   col->red   = red;
331   col->green = green;
332   col->blue  = blue;
333   col->alpha = 0xff;
334 }
335
336 guint
337 _clutter_pixel_to_id (guchar pixel[4])
338 {
339   ClutterMainContext *ctx;
340   gint  red, green, blue;
341   guint id;
342
343   ctx = clutter_context_get_default ();
344
345   /* reduce the pixel components to the number of bits actually used of the
346    * 8bits.
347    */
348   red   = pixel[0] >> (8 - ctx->fb_r_mask);
349   green = pixel[1] >> (8 - ctx->fb_g_mask);
350   blue  = pixel[2] >> (8 - ctx->fb_b_mask);
351
352   /* divide potentially by two if 'fuzzy' */
353   red   = red   >> (ctx->fb_r_mask - ctx->fb_r_mask_used);
354   green = green >> (ctx->fb_g_mask - ctx->fb_g_mask_used);
355   blue  = blue  >> (ctx->fb_b_mask - ctx->fb_b_mask_used);
356
357   /* combine the correct per component values into the final id */
358   id =  blue + (green <<  ctx->fb_b_mask_used)
359           + (red << (ctx->fb_b_mask_used + ctx->fb_g_mask_used));
360
361   return id;
362 }
363
364 ClutterActor *
365 _clutter_do_pick (ClutterStage   *stage,
366                   gint            x,
367                   gint            y,
368                   ClutterPickMode mode)
369 {
370   ClutterMainContext *context;
371   guchar              pixel[4];
372   GLint               viewport[4];
373   CoglColor           white;
374   guint32             id;
375   GLboolean           dither_was_on;
376
377   context = clutter_context_get_default ();
378
379   _clutter_backend_ensure_context (context->backend, stage);
380
381   /* needed for when a context switch happens */
382   _clutter_stage_maybe_setup_viewport (stage);
383
384   cogl_clip_push_window_rect (x, y, 1, 1);
385   cogl_color_set_from_4ub (&white, 255, 255, 255, 255);
386   cogl_disable_fog ();
387   cogl_clear (&white,
388               COGL_BUFFER_BIT_COLOR |
389               COGL_BUFFER_BIT_DEPTH);
390
391   /* Disable dithering (if any) when doing the painting in pick mode */
392   dither_was_on = glIsEnabled (GL_DITHER);
393   if (dither_was_on)
394     glDisable (GL_DITHER);
395
396   /* Render the entire scence in pick mode - just single colored silhouette's
397    * are drawn offscreen (as we never swap buffers)
398   */
399   context->pick_mode = mode;
400   clutter_actor_paint (CLUTTER_ACTOR (stage));
401   context->pick_mode = CLUTTER_PICK_NONE;
402   cogl_clip_pop ();
403
404   /* Calls should work under both GL and GLES, note GLES needs RGBA */
405   glGetIntegerv(GL_VIEWPORT, viewport);
406
407   /* Read the color of the screen co-ords pixel */
408   glReadPixels (x, viewport[3] - y -1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
409
410   /* Restore whether GL_DITHER was enabled */
411   if (dither_was_on)
412     glEnable (GL_DITHER);
413
414   if (pixel[0] == 0xff && pixel[1] == 0xff && pixel[2] == 0xff)
415     return CLUTTER_ACTOR (stage);
416
417   id = _clutter_pixel_to_id (pixel);
418
419   return clutter_get_actor_by_gid (id);
420 }
421
422 static PangoDirection
423 clutter_get_text_direction (void)
424 {
425   PangoDirection dir = PANGO_DIRECTION_LTR;
426   const gchar *direction;
427
428   direction = g_getenv ("CLUTTER_TEXT_DIRECTION");
429   if (direction && *direction != '\0')
430     {
431       if (strcmp (direction, "rtl") == 0)
432         dir = PANGO_DIRECTION_RTL;
433       else if (strcmp (direction, "ltr") == 0)
434         dir = PANGO_DIRECTION_LTR;
435     }
436   else
437     {
438       /* Translate to default:RTL if you want your widgets
439        * to be RTL, otherwise translate to default:LTR.
440        *
441        * Do *not* translate it to "predefinito:LTR": if it
442        * it isn't default:LTR or default:RTL it will not work
443        */
444       char *e = _("default:LTR");
445
446       if (strcmp (e, "default:RTL") == 0)
447         dir = PANGO_DIRECTION_RTL;
448       else if (strcmp (e, "default:LTR") == 0)
449         dir = PANGO_DIRECTION_LTR;
450       else
451         g_warning ("Whoever translated default:LTR did so wrongly.");
452     }
453
454   return dir;
455 }
456
457 static void
458 update_pango_context (ClutterBackend *backend,
459                       PangoContext   *context)
460 {
461   PangoFontDescription *font_desc;
462   const cairo_font_options_t *font_options;
463   const gchar *font_name;
464   gdouble resolution;
465
466   /* update the text direction */
467   pango_context_set_base_dir (context, clutter_text_direction);
468
469   /* get the configuration for the PangoContext from the backend */
470   font_name = clutter_backend_get_font_name (backend);
471   font_options = clutter_backend_get_font_options (backend);
472   resolution = clutter_backend_get_resolution (backend);
473
474   font_desc = pango_font_description_from_string (font_name);
475
476   if (resolution < 0)
477     resolution = 96.0; /* fall back */
478
479   pango_context_set_font_description (context, font_desc);
480   pango_cairo_context_set_font_options (context, font_options);
481   pango_cairo_context_set_resolution (context, resolution);
482
483   pango_font_description_free (font_desc);
484 }
485
486 PangoContext *
487 _clutter_context_get_pango_context (ClutterMainContext *self)
488 {
489   if (G_UNLIKELY (self->pango_context == NULL))
490     {
491       PangoContext *context;
492
493       context = cogl_pango_font_map_create_context (self->font_map);
494       self->pango_context = context;
495
496       g_signal_connect (self->backend, "resolution-changed",
497                         G_CALLBACK (update_pango_context),
498                         self->pango_context);
499       g_signal_connect (self->backend, "font-changed",
500                         G_CALLBACK (update_pango_context),
501                         self->pango_context);
502     }
503
504   update_pango_context (self->backend, self->pango_context);
505
506   return self->pango_context;
507 }
508
509 PangoContext *
510 _clutter_context_create_pango_context (ClutterMainContext *self)
511 {
512   PangoContext *context;
513
514   context = cogl_pango_font_map_create_context (self->font_map);
515   update_pango_context (self->backend, context);
516
517   return context;
518 }
519
520 /**
521  * clutter_main_quit:
522  *
523  * Terminates the Clutter mainloop.
524  */
525 void
526 clutter_main_quit (void)
527 {
528   g_return_if_fail (main_loops != NULL);
529
530   g_main_loop_quit (main_loops->data);
531 }
532
533 /**
534  * clutter_main_level:
535  *
536  * Retrieves the depth of the Clutter mainloop.
537  *
538  * Return value: The level of the mainloop.
539  */
540 gint
541 clutter_main_level (void)
542 {
543   return clutter_main_loop_level;
544 }
545
546 /**
547  * clutter_main:
548  *
549  * Starts the Clutter mainloop.
550  */
551 void
552 clutter_main (void)
553 {
554   GMainLoop *loop;
555
556   /* Make sure there is a context */
557   CLUTTER_CONTEXT ();
558
559   if (!clutter_is_initialized)
560     {
561       g_warning ("Called clutter_main() but Clutter wasn't initialised.  "
562                  "You must call clutter_init() first.");
563       return;
564     }
565
566   CLUTTER_MARK ();
567
568   clutter_main_loop_level++;
569
570   loop = g_main_loop_new (NULL, TRUE);
571   main_loops = g_slist_prepend (main_loops, loop);
572
573 #ifdef HAVE_CLUTTER_FRUITY
574   /* clutter fruity creates an application that forwards events and manually
575    * spins the mainloop
576    */
577   clutter_fruity_main ();
578 #else
579   if (g_main_loop_is_running (main_loops->data))
580     {
581       clutter_threads_leave ();
582       g_main_loop_run (loop);
583       clutter_threads_enter ();
584     }
585 #endif
586
587   main_loops = g_slist_remove (main_loops, loop);
588
589   g_main_loop_unref (loop);
590
591   clutter_main_loop_level--;
592
593   CLUTTER_MARK ();
594 }
595
596 static void
597 clutter_threads_impl_lock (void)
598 {
599   if (clutter_threads_mutex)
600     g_mutex_lock (clutter_threads_mutex);
601 }
602
603 static void
604 clutter_threads_impl_unlock (void)
605 {
606   if (clutter_threads_mutex)
607     g_mutex_unlock (clutter_threads_mutex);
608 }
609
610 /**
611  * clutter_threads_init:
612  *
613  * Initialises the Clutter threading mechanism, so that Clutter API can be
614  * called by multiple threads, using clutter_threads_enter() and
615  * clutter_threads_leave() to mark the critical sections.
616  *
617  * You must call g_thread_init() before this function.
618  *
619  * This function must be called before clutter_init().
620  *
621  * Since: 0.4
622  */
623 void
624 clutter_threads_init (void)
625 {
626   if (!g_thread_supported ())
627     g_error ("g_thread_init() must be called before clutter_threads_init()");
628
629   clutter_threads_mutex = g_mutex_new ();
630
631   if (!clutter_threads_lock)
632     clutter_threads_lock = clutter_threads_impl_lock;
633
634   if (!clutter_threads_unlock)
635     clutter_threads_unlock = clutter_threads_impl_unlock;
636 }
637
638 /**
639  * clutter_threads_set_lock_functions:
640  * @enter_fn: function called when aquiring the Clutter main lock
641  * @leave_fn: function called when releasing the Clutter main lock
642  *
643  * Allows the application to replace the standard method that
644  * Clutter uses to protect its data structures. Normally, Clutter
645  * creates a single #GMutex that is locked by clutter_threads_enter(),
646  * and released by clutter_threads_leave(); using this function an
647  * application provides, instead, a function @enter_fn that is
648  * called by clutter_threads_enter() and a function @leave_fn that is
649  * called by clutter_threads_leave().
650  *
651  * The functions must provide at least same locking functionality
652  * as the default implementation, but can also do extra application
653  * specific processing.
654  *
655  * As an example, consider an application that has its own recursive
656  * lock that when held, holds the Clutter lock as well. When Clutter
657  * unlocks the Clutter lock when entering a recursive main loop, the
658  * application must temporarily release its lock as well.
659  *
660  * Most threaded Clutter apps won't need to use this method.
661  *
662  * This method must be called before clutter_threads_init(), and cannot
663  * be called multiple times.
664  *
665  * Since: 0.4
666  */
667 void
668 clutter_threads_set_lock_functions (GCallback enter_fn,
669                                     GCallback leave_fn)
670 {
671   g_return_if_fail (clutter_threads_lock == NULL &&
672                     clutter_threads_unlock == NULL);
673
674   clutter_threads_lock = enter_fn;
675   clutter_threads_unlock = leave_fn;
676 }
677
678 typedef struct
679 {
680   GSourceFunc func;
681   gpointer data;
682   GDestroyNotify notify;
683 } ClutterThreadsDispatch;
684
685 static gboolean
686 clutter_threads_dispatch (gpointer data)
687 {
688   ClutterThreadsDispatch *dispatch = data;
689   gboolean ret = FALSE;
690
691   clutter_threads_enter ();
692
693   if (!g_source_is_destroyed (g_main_current_source ()))
694     ret = dispatch->func (dispatch->data);
695
696   clutter_threads_leave ();
697
698   return ret;
699 }
700
701 static void
702 clutter_threads_dispatch_free (gpointer data)
703 {
704   ClutterThreadsDispatch *dispatch = data;
705
706   /* XXX - we cannot hold the thread lock here because the main loop
707    * might destroy a source while still in the dispatcher function; so
708    * knowing whether the lock is being held or not is not known a priori.
709    *
710    * see bug: http://bugzilla.gnome.org/show_bug.cgi?id=459555
711    */
712   if (dispatch->notify)
713     dispatch->notify (dispatch->data);
714
715   g_slice_free (ClutterThreadsDispatch, dispatch);
716 }
717
718 /**
719  * clutter_threads_add_idle_full:
720  * @priority: the priority of the timeout source. Typically this will be in the
721  *    range between #G_PRIORITY_DEFAULT_IDLE and #G_PRIORITY_HIGH_IDLE
722  * @func: function to call
723  * @data: data to pass to the function
724  * @notify: functio to call when the idle source is removed
725  *
726  * Adds a function to be called whenever there are no higher priority
727  * events pending. If the function returns %FALSE it is automatically
728  * removed from the list of event sources and will not be called again.
729  *
730  * This function can be considered a thread-safe variant of g_idle_add_full():
731  * it will call @function while holding the Clutter lock. It is logically
732  * equivalent to the following implementation:
733  *
734  * |[
735  * static gboolean
736  * idle_safe_callback (gpointer data)
737  * {
738  *    SafeClosure *closure = data;
739  *    gboolean res = FALSE;
740  *
741  *    /&ast; mark the critical section &ast;/
742  *
743  *    clutter_threads_enter();
744  *
745  *    /&ast; the callback does not need to acquire the Clutter
746  *     &ast; lock itself, as it is held by the this proxy handler
747  *     &ast;/
748  *    res = closure->callback (closure->data);
749  *
750  *    clutter_threads_leave();
751  *
752  *    return res;
753  * }
754  * static gulong
755  * add_safe_idle (GSourceFunc callback,
756  *                gpointer    data)
757  * {
758  *   SafeClosure *closure = g_new0 (SafeClosure, 1);
759  *
760  *   closure-&gt;callback = callback;
761  *   closure-&gt;data = data;
762  *
763  *   return g_add_idle_full (G_PRIORITY_DEFAULT_IDLE,
764  *                           idle_safe_callback,
765  *                           closure,
766  *                           g_free)
767  * }
768  *]|
769  *
770  * This function should be used by threaded applications to make sure
771  * that @func is emitted under the Clutter threads lock and invoked
772  * from the same thread that started the Clutter main loop. For instance,
773  * it can be used to update the UI using the results from a worker
774  * thread:
775  *
776  * |[
777  * static gboolean
778  * update_ui (gpointer data)
779  * {
780  *   SomeClosure *closure = data;
781  *
782  *   /&ast; it is safe to call Clutter API from this function because
783  *    &ast; it is invoked from the same thread that started the main
784  *    &ast; loop and under the Clutter thread lock
785  *    &ast;/
786  *   clutter_label_set_text (CLUTTER_LABEL (closure-&gt;label),
787  *                           closure-&gt;text);
788  *
789  *   g_object_unref (closure-&gt;label);
790  *   g_free (closure);
791  *
792  *   return FALSE;
793  * }
794  *
795  *   /&ast; within another thread &ast;/
796  *   closure = g_new0 (SomeClosure, 1);
797  *   /&ast; always take a reference on GObject instances &ast;/
798  *   closure-&gt;label = g_object_ref (my_application-&gt;label);
799  *   closure-&gt;text = g_strdup (processed_text_to_update_the_label);
800  *
801  *   clutter_threads_add_idle_full (G_PRIORITY_HIGH_IDLE,
802  *                                  update_ui,
803  *                                  closure,
804  *                                  NULL);
805  * ]|
806  *
807  * Return value: the ID (greater than 0) of the event source.
808  *
809  * Since: 0.4
810  */
811 guint
812 clutter_threads_add_idle_full (gint           priority,
813                                GSourceFunc    func,
814                                gpointer       data,
815                                GDestroyNotify notify)
816 {
817   ClutterThreadsDispatch *dispatch;
818
819   g_return_val_if_fail (func != NULL, 0);
820
821   dispatch = g_slice_new (ClutterThreadsDispatch);
822   dispatch->func = func;
823   dispatch->data = data;
824   dispatch->notify = notify;
825
826   return g_idle_add_full (priority,
827                           clutter_threads_dispatch, dispatch,
828                           clutter_threads_dispatch_free);
829 }
830
831 /**
832  * clutter_threads_add_idle:
833  * @func: function to call
834  * @data: data to pass to the function
835  *
836  * Simple wrapper around clutter_threads_add_idle_full() using the
837  * default priority.
838  *
839  * Return value: the ID (greater than 0) of the event source.
840  *
841  * Since: 0.4
842  */
843 guint
844 clutter_threads_add_idle (GSourceFunc func,
845                           gpointer    data)
846 {
847   g_return_val_if_fail (func != NULL, 0);
848
849   return clutter_threads_add_idle_full (G_PRIORITY_DEFAULT_IDLE,
850                                         func, data,
851                                         NULL);
852 }
853
854 /**
855  * clutter_threads_add_timeout_full:
856  * @priority: the priority of the timeout source. Typically this will be in the
857  *            range between #G_PRIORITY_DEFAULT and #G_PRIORITY_HIGH.
858  * @interval: the time between calls to the function, in milliseconds
859  * @func: function to call
860  * @data: data to pass to the function
861  * @notify: function to call when the timeout source is removed
862  *
863  * Sets a function to be called at regular intervals holding the Clutter
864  * threads lock, with the given priority. The function is called repeatedly
865  * until it returns %FALSE, at which point the timeout is automatically
866  * removed and the function will not be called again. The @notify function
867  * is called when the timeout is removed.
868  *
869  * The first call to the function will be at the end of the first @interval.
870  *
871  * It is important to note that, due to how the Clutter main loop is
872  * implemented, the timing will not be accurate and it will not try to
873  * "keep up" with the interval. A more reliable source is available
874  * using clutter_threads_add_frame_source_full(), which is also internally
875  * used by #ClutterTimeline.
876  *
877  * See also clutter_threads_add_idle_full().
878  *
879  * Return value: the ID (greater than 0) of the event source.
880  *
881  * Since: 0.4
882  */
883 guint
884 clutter_threads_add_timeout_full (gint           priority,
885                                   guint          interval,
886                                   GSourceFunc    func,
887                                   gpointer       data,
888                                   GDestroyNotify notify)
889 {
890   ClutterThreadsDispatch *dispatch;
891
892   g_return_val_if_fail (func != NULL, 0);
893
894   dispatch = g_slice_new (ClutterThreadsDispatch);
895   dispatch->func = func;
896   dispatch->data = data;
897   dispatch->notify = notify;
898
899   return g_timeout_add_full (priority,
900                              interval,
901                              clutter_threads_dispatch, dispatch,
902                              clutter_threads_dispatch_free);
903 }
904
905 /**
906  * clutter_threads_add_timeout:
907  * @interval: the time between calls to the function, in milliseconds
908  * @func: function to call
909  * @data: data to pass to the function
910  *
911  * Simple wrapper around clutter_threads_add_timeout_full().
912  *
913  * Return value: the ID (greater than 0) of the event source.
914  *
915  * Since: 0.4
916  */
917 guint
918 clutter_threads_add_timeout (guint       interval,
919                              GSourceFunc func,
920                              gpointer    data)
921 {
922   g_return_val_if_fail (func != NULL, 0);
923
924   return clutter_threads_add_timeout_full (G_PRIORITY_DEFAULT,
925                                            interval,
926                                            func, data,
927                                            NULL);
928 }
929
930 /**
931  * clutter_threads_add_frame_source_full:
932  * @priority: the priority of the frame source. Typically this will be in the
933  *            range between #G_PRIORITY_DEFAULT and #G_PRIORITY_HIGH.
934  * @fps: the number of times per second to call the function
935  * @func: function to call
936  * @data: data to pass to the function
937  * @notify: function to call when the timeout source is removed
938  *
939  * Sets a function to be called at regular intervals holding the Clutter
940  * threads lock, with the given priority. The function is called repeatedly
941  * until it returns %FALSE, at which point the timeout is automatically
942  * removed and the function will not be called again. The @notify function
943  * is called when the timeout is removed.
944  *
945  * This function is similar to clutter_threads_add_timeout_full()
946  * except that it will try to compensate for delays. For example, if
947  * @func takes half the interval time to execute then the function
948  * will be called again half the interval time after it finished. In
949  * contrast clutter_threads_add_timeout_full() would not fire until a
950  * full interval after the function completes so the delay between
951  * calls would be @interval * 1.5. This function does not however try
952  * to invoke the function multiple times to catch up missing frames if
953  * @func takes more than @interval ms to execute.
954  *
955  * See also clutter_threads_add_idle_full().
956  *
957  * Return value: the ID (greater than 0) of the event source.
958  *
959  * Since: 0.8
960  */
961 guint
962 clutter_threads_add_frame_source_full (gint           priority,
963                                        guint          fps,
964                                        GSourceFunc    func,
965                                        gpointer       data,
966                                        GDestroyNotify notify)
967 {
968   ClutterThreadsDispatch *dispatch;
969
970   g_return_val_if_fail (func != NULL, 0);
971
972   dispatch = g_slice_new (ClutterThreadsDispatch);
973   dispatch->func = func;
974   dispatch->data = data;
975   dispatch->notify = notify;
976
977   return clutter_frame_source_add_full (priority,
978                                         fps,
979                                         clutter_threads_dispatch, dispatch,
980                                         clutter_threads_dispatch_free);
981 }
982
983 /**
984  * clutter_threads_add_frame_source:
985  * @fps: the number of times per second to call the function
986  * @func: function to call
987  * @data: data to pass to the function
988  *
989  * Simple wrapper around clutter_threads_add_frame_source_full().
990  *
991  * Return value: the ID (greater than 0) of the event source.
992  *
993  * Since: 0.8
994  */
995 guint
996 clutter_threads_add_frame_source (guint       fps,
997                                   GSourceFunc func,
998                                   gpointer    data)
999 {
1000   g_return_val_if_fail (func != NULL, 0);
1001
1002   return clutter_threads_add_frame_source_full (G_PRIORITY_DEFAULT,
1003                                                 fps,
1004                                                 func, data,
1005                                                 NULL);
1006 }
1007
1008 /**
1009  * clutter_threads_enter:
1010  *
1011  * Locks the Clutter thread lock.
1012  *
1013  * Since: 0.4
1014  */
1015 void
1016 clutter_threads_enter (void)
1017 {
1018   if (clutter_threads_lock)
1019     (* clutter_threads_lock) ();
1020 }
1021
1022 /**
1023  * clutter_threads_leave:
1024  *
1025  * Unlocks the Clutter thread lock.
1026  *
1027  * Since: 0.4
1028  */
1029 void
1030 clutter_threads_leave (void)
1031 {
1032   if (clutter_threads_unlock)
1033     (* clutter_threads_unlock) ();
1034 }
1035
1036
1037 /**
1038  * clutter_get_debug_enabled:
1039  *
1040  * Check if clutter has debugging turned on.
1041  *
1042  * Return value: TRUE if debugging is turned on, FALSE otherwise.
1043  */
1044 gboolean
1045 clutter_get_debug_enabled (void)
1046 {
1047 #ifdef CLUTTER_ENABLE_DEBUG
1048   return clutter_debug_flags != 0;
1049 #else
1050   return FALSE;
1051 #endif
1052 }
1053
1054 ClutterMainContext *
1055 clutter_context_get_default (void)
1056 {
1057   if (G_UNLIKELY(!ClutterCntx))
1058     {
1059       ClutterMainContext *ctx;
1060
1061       ClutterCntx = ctx = g_new0 (ClutterMainContext, 1);
1062       ctx->backend = g_object_new (_clutter_backend_impl_get_type (), NULL);
1063
1064       ctx->is_initialized = FALSE;
1065       ctx->motion_events_per_actor = TRUE;
1066
1067       ctx->master_clock = _clutter_master_clock_get_default ();
1068
1069 #ifdef CLUTTER_ENABLE_DEBUG
1070       ctx->timer          =  g_timer_new ();
1071       g_timer_start (ctx->timer);
1072 #endif
1073     }
1074
1075   return ClutterCntx;
1076 }
1077
1078 /**
1079  * clutter_get_timestamp:
1080  *
1081  * Returns the approximate number of microseconds passed since clutter was
1082  * intialised.
1083  *
1084  * Return value: Number of microseconds since clutter_init() was called.
1085  */
1086 gulong
1087 clutter_get_timestamp (void)
1088 {
1089 #ifdef CLUTTER_ENABLE_DEBUG
1090   ClutterMainContext *ctx;
1091   gdouble seconds;
1092
1093   ctx = clutter_context_get_default ();
1094
1095   /* FIXME: may need a custom timer for embedded setups */
1096   seconds = g_timer_elapsed (ctx->timer, NULL);
1097
1098   return (gulong)(seconds / 1.0e-6);
1099 #else
1100   return 0;
1101 #endif
1102 }
1103
1104 static gboolean
1105 clutter_arg_direction_cb (const char *key,
1106                           const char *value,
1107                           gpointer    user_data)
1108 {
1109   clutter_text_direction =
1110     (strcmp (value, "rtl") == 0) ? PANGO_DIRECTION_RTL
1111                                  : PANGO_DIRECTION_LTR;
1112
1113   return TRUE;
1114 }
1115
1116 #ifdef CLUTTER_ENABLE_DEBUG
1117 static gboolean
1118 clutter_arg_debug_cb (const char *key,
1119                       const char *value,
1120                       gpointer    user_data)
1121 {
1122   clutter_debug_flags |=
1123     g_parse_debug_string (value,
1124                           clutter_debug_keys,
1125                           G_N_ELEMENTS (clutter_debug_keys));
1126   return TRUE;
1127 }
1128
1129 static gboolean
1130 clutter_arg_no_debug_cb (const char *key,
1131                          const char *value,
1132                          gpointer    user_data)
1133 {
1134   clutter_debug_flags &=
1135     ~g_parse_debug_string (value,
1136                            clutter_debug_keys,
1137                            G_N_ELEMENTS (clutter_debug_keys));
1138   return TRUE;
1139 }
1140 #endif /* CLUTTER_ENABLE_DEBUG */
1141
1142 GQuark
1143 clutter_init_error_quark (void)
1144 {
1145   return g_quark_from_static_string ("clutter-init-error-quark");
1146 }
1147
1148 static ClutterInitError
1149 clutter_init_real (GError **error)
1150 {
1151   ClutterMainContext *ctx;
1152   ClutterActor *stage;
1153   gdouble resolution;
1154   ClutterBackend *backend;
1155
1156   /* Note, creates backend if not already existing, though parse args will
1157    * have likely created it
1158    */
1159   ctx = clutter_context_get_default ();
1160   backend = ctx->backend;
1161
1162   if (!ctx->options_parsed)
1163     {
1164       g_set_error (error, CLUTTER_INIT_ERROR,
1165                    CLUTTER_INIT_ERROR_INTERNAL,
1166                    "When using clutter_get_option_group_without_init() "
1167                    "you must parse options before calling clutter_init()");
1168
1169       return CLUTTER_INIT_ERROR_INTERNAL;
1170     }
1171
1172   /*
1173    * Call backend post parse hooks.
1174    */
1175   if (!_clutter_backend_post_parse (backend, error))
1176     return CLUTTER_INIT_ERROR_BACKEND;
1177
1178   /* Stage will give us a GL Context etc */
1179   stage = clutter_stage_get_default ();
1180   if (!stage)
1181     {
1182       if (error)
1183         g_set_error (error, CLUTTER_INIT_ERROR,
1184                      CLUTTER_INIT_ERROR_INTERNAL,
1185                      "Unable to create the default stage");
1186       else
1187         g_critical ("Unable to create the default stage");
1188
1189       return CLUTTER_INIT_ERROR_INTERNAL;
1190     }
1191
1192   clutter_stage_set_title (CLUTTER_STAGE (stage), g_get_prgname ());
1193
1194   clutter_actor_realize (stage);
1195
1196   if (!CLUTTER_ACTOR_IS_REALIZED (stage))
1197     {
1198       if (error)
1199         g_set_error (error, CLUTTER_INIT_ERROR,
1200                      CLUTTER_INIT_ERROR_INTERNAL,
1201                      "Unable to realize the default stage");
1202       else
1203         g_critical ("Unable to realize the default stage");
1204
1205       return CLUTTER_INIT_ERROR_INTERNAL;
1206     }
1207
1208   /* Now we can safely assume we have a valid GL context and can
1209    * start issueing cogl commands
1210   */
1211
1212   /*
1213    * Resolution requires display to be open, so can only be queried after
1214    * the post_parse hooks run.
1215    *
1216    * NB: cogl_pango requires a Cogl context.
1217    */
1218   ctx->font_map = COGL_PANGO_FONT_MAP (cogl_pango_font_map_new ());
1219
1220   resolution = clutter_backend_get_resolution (ctx->backend);
1221   cogl_pango_font_map_set_resolution (ctx->font_map, resolution);
1222
1223   if (G_LIKELY (!clutter_disable_mipmap_text))
1224     cogl_pango_font_map_set_use_mipmapping (ctx->font_map, TRUE);
1225
1226   clutter_text_direction = clutter_get_text_direction ();
1227
1228
1229   /* Figure out framebuffer masks used for pick */
1230   cogl_get_bitmasks (&ctx->fb_r_mask, &ctx->fb_g_mask, &ctx->fb_b_mask, NULL);
1231
1232   ctx->fb_r_mask_used = ctx->fb_r_mask;
1233   ctx->fb_g_mask_used = ctx->fb_g_mask;
1234   ctx->fb_b_mask_used = ctx->fb_b_mask;
1235
1236   /* XXX - describe what "fuzzy picking" is */
1237   if (clutter_use_fuzzy_picking)
1238     {
1239       ctx->fb_r_mask_used--;
1240       ctx->fb_g_mask_used--;
1241       ctx->fb_b_mask_used--;
1242     }
1243
1244   /* Initiate event collection */
1245   _clutter_backend_init_events (ctx->backend);
1246
1247   /* finally features - will call to backend and cogl */
1248   _clutter_feature_init ();
1249
1250   clutter_is_initialized = TRUE;
1251   ctx->is_initialized = TRUE;
1252
1253   return CLUTTER_INIT_SUCCESS;
1254 }
1255
1256 static GOptionEntry clutter_args[] = {
1257   { "clutter-show-fps", 0, 0, G_OPTION_ARG_NONE, &clutter_show_fps,
1258     N_("Show frames per second"), NULL },
1259   { "clutter-default-fps", 0, 0, G_OPTION_ARG_INT, &clutter_default_fps,
1260     N_("Default frame rate"), "FPS" },
1261   { "g-fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &clutter_fatal_warnings,
1262     N_("Make all warnings fatal"), NULL },
1263   { "clutter-text-direction", 0, 0, G_OPTION_ARG_CALLBACK,
1264     clutter_arg_direction_cb,
1265     N_("Direction for the text"), "DIRECTION" },
1266   { "clutter-disable-mipmapped-text", 0, 0, G_OPTION_ARG_NONE,
1267     &clutter_disable_mipmap_text,
1268     N_("Disable mipmapping on text"), NULL },
1269   { "clutter-use-fuzzy-picking", 0, 0, G_OPTION_ARG_NONE,
1270     &clutter_use_fuzzy_picking,
1271     N_("Use 'fuzzy' picking"), NULL },
1272 #ifdef CLUTTER_ENABLE_DEBUG
1273   { "clutter-debug", 0, 0, G_OPTION_ARG_CALLBACK, clutter_arg_debug_cb,
1274     N_("Clutter debugging flags to set"), "FLAGS" },
1275   { "clutter-no-debug", 0, 0, G_OPTION_ARG_CALLBACK, clutter_arg_no_debug_cb,
1276     N_("Clutter debugging flags to unset"), "FLAGS" },
1277 #endif /* CLUTTER_ENABLE_DEBUG */
1278   { NULL, },
1279 };
1280
1281 /* pre_parse_hook: initialise variables depending on environment
1282  * variables; these variables might be overridden by the command
1283  * line arguments that are going to be parsed after.
1284  */
1285 static gboolean
1286 pre_parse_hook (GOptionContext  *context,
1287                 GOptionGroup    *group,
1288                 gpointer         data,
1289                 GError         **error)
1290 {
1291   ClutterMainContext *clutter_context;
1292   ClutterBackend *backend;
1293   const char *env_string;
1294
1295   if (clutter_is_initialized)
1296     return TRUE;
1297
1298   if (setlocale (LC_ALL, "") == NULL)
1299     g_warning ("Locale not supported by C library.\n"
1300                "Using the fallback 'C' locale.");
1301
1302   clutter_context = clutter_context_get_default ();
1303
1304   clutter_context->id_pool = clutter_id_pool_new (256);
1305
1306   backend = clutter_context->backend;
1307   g_assert (CLUTTER_IS_BACKEND (backend));
1308
1309 #ifdef CLUTTER_ENABLE_DEBUG
1310   env_string = g_getenv ("CLUTTER_DEBUG");
1311   if (env_string != NULL)
1312     {
1313       clutter_debug_flags =
1314         g_parse_debug_string (env_string,
1315                               clutter_debug_keys,
1316                               G_N_ELEMENTS (clutter_debug_keys));
1317       env_string = NULL;
1318     }
1319 #endif /* CLUTTER_ENABLE_DEBUG */
1320
1321   env_string = g_getenv ("CLUTTER_SHOW_FPS");
1322   if (env_string)
1323     clutter_show_fps = TRUE;
1324
1325   env_string = g_getenv ("CLUTTER_DEFAULT_FPS");
1326   if (env_string)
1327     {
1328       gint default_fps = g_ascii_strtoll (env_string, NULL, 10);
1329
1330       clutter_default_fps = CLAMP (default_fps, 1, 1000);
1331     }
1332
1333   env_string = g_getenv ("CLUTTER_DISABLE_MIPMAPPED_TEXT");
1334   if (env_string)
1335     clutter_disable_mipmap_text = TRUE;
1336
1337 #ifdef HAVE_CLUTTER_FRUITY
1338   /* we always enable fuzzy picking in the "fruity" backend */
1339   clutter_use_fuzzy_picking = TRUE;
1340 #else
1341   env_string = g_getenv ("CLUTTER_FUZZY_PICK");
1342   if (env_string)
1343     clutter_use_fuzzy_picking = TRUE;
1344 #endif /* HAVE_CLUTTER_FRUITY */
1345
1346   return _clutter_backend_pre_parse (backend, error);
1347 }
1348
1349 /* post_parse_hook: initialise the context and data structures
1350  * and opens the X display
1351  */
1352 static gboolean
1353 post_parse_hook (GOptionContext  *context,
1354                  GOptionGroup    *group,
1355                  gpointer         data,
1356                  GError         **error)
1357 {
1358   ClutterMainContext *clutter_context;
1359   ClutterBackend *backend;
1360
1361   if (clutter_is_initialized)
1362     return TRUE;
1363
1364   clutter_context = clutter_context_get_default ();
1365   backend = clutter_context->backend;
1366   g_assert (CLUTTER_IS_BACKEND (backend));
1367
1368   if (clutter_fatal_warnings)
1369     {
1370       GLogLevelFlags fatal_mask;
1371
1372       fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
1373       fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
1374       g_log_set_always_fatal (fatal_mask);
1375     }
1376
1377   clutter_context->frame_rate = clutter_default_fps;
1378   clutter_context->options_parsed = TRUE;
1379
1380   /*
1381    * If not asked to defer display setup, call clutter_init_real(),
1382    * which in turn calls the backend post parse hooks.
1383    */
1384   if (!clutter_context->defer_display_setup)
1385     return clutter_init_real (error);
1386
1387   return TRUE;
1388 }
1389
1390 /**
1391  * clutter_get_option_group:
1392  *
1393  * Returns a #GOptionGroup for the command line arguments recognized
1394  * by Clutter. You should add this group to your #GOptionContext with
1395  * g_option_context_add_group(), if you are using g_option_context_parse()
1396  * to parse your commandline arguments.
1397  *
1398  * Calling g_option_context_parse() with Clutter's #GOptionGroup will result
1399  * in Clutter's initialization. That is, the following code:
1400  *
1401  * |[
1402  *   g_option_context_set_main_group (context, clutter_get_option_group ());
1403  *   res = g_option_context_parse (context, &amp;argc, &amp;argc, NULL);
1404  * ]|
1405  *
1406  * is functionally equivalent to:
1407  *
1408  * |[
1409  *   clutter_init (&amp;argc, &amp;argv);
1410  * ]|
1411  *
1412  * After g_option_context_parse() on a #GOptionContext containing the
1413  * Clutter #GOptionGroup has returned %TRUE, Clutter is guaranteed to be
1414  * initialized.
1415  *
1416  * Return value: (transfer full): a #GOptionGroup for the commandline arguments
1417  *   recognized by Clutter
1418  *
1419  * Since: 0.2
1420  */
1421 GOptionGroup *
1422 clutter_get_option_group (void)
1423 {
1424   ClutterMainContext *context;
1425   GOptionGroup *group;
1426
1427   clutter_base_init ();
1428
1429   context = clutter_context_get_default ();
1430
1431   group = g_option_group_new ("clutter",
1432                               _("Clutter Options"),
1433                               _("Show Clutter Options"),
1434                               NULL,
1435                               NULL);
1436
1437   g_option_group_set_parse_hooks (group, pre_parse_hook, post_parse_hook);
1438   g_option_group_add_entries (group, clutter_args);
1439   g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
1440
1441   /* add backend-specific options */
1442   _clutter_backend_add_options (context->backend, group);
1443
1444   return group;
1445 }
1446
1447 /**
1448  * clutter_get_option_group_without_init:
1449  *
1450  * Returns a #GOptionGroup for the command line arguments recognized
1451  * by Clutter. You should add this group to your #GOptionContext with
1452  * g_option_context_add_group(), if you are using g_option_context_parse()
1453  * to parse your commandline arguments. Unlike clutter_get_option_group(),
1454  * calling g_option_context_parse() with the #GOptionGroup returned by this
1455  * function requires a subsequent explicit call to clutter_init(); use this
1456  * function when needing to set foreign display connection with
1457  * clutter_x11_set_display(), or with gtk_clutter_init().
1458  *
1459  * Return value: (transfer full): a #GOptionGroup for the commandline arguments
1460  *   recognized by Clutter
1461  *
1462  * Since: 0.8.2
1463  */
1464 GOptionGroup *
1465 clutter_get_option_group_without_init (void)
1466 {
1467   ClutterMainContext *context;
1468   GOptionGroup *group;
1469
1470   clutter_base_init ();
1471
1472   context = clutter_context_get_default ();
1473   context->defer_display_setup = TRUE;
1474
1475   group = clutter_get_option_group ();
1476
1477   return group;
1478 }
1479
1480 /* Note that the gobject-introspection annotations for the argc/argv
1481  * parameters do not produce the right result; however, they do
1482  * allow the common case of argc=NULL, argv=NULL to work.
1483  */
1484
1485 /**
1486  * clutter_init_with_args:
1487  * @argc: (inout): a pointer to the number of command line arguments
1488  * @argv: (array length=argc) (inout): a pointer to the array of command line arguments
1489  * @parameter_string: a string which is displayed in the
1490  *   first line of <option>--help</option> output, after
1491  *   <literal><replaceable>programname</replaceable> [OPTION...]</literal>
1492  * @entries: a %NULL terminated array of #GOptionEntry<!-- -->s
1493  *   describing the options of your program
1494  * @translation_domain: a translation domain to use for translating
1495  *   the <option>--help</option> output for the options in @entries
1496  *   with gettext(), or %NULL
1497  * @error: a return location for a #GError
1498  *
1499  * This function does the same work as clutter_init(). Additionally,
1500  * it allows you to add your own command line options, and it
1501  * automatically generates nicely formatted <option>--help</option>
1502  * output. Note that your program will be terminated after writing
1503  * out the help output. Also note that, in case of error, the
1504  * error message will be placed inside @error instead of being
1505  * printed on the display.
1506  *
1507  * Return value: %CLUTTER_INIT_SUCCESS if Clutter has been successfully
1508  *   initialised, or other values or #ClutterInitError in case of
1509  *   error.
1510  *
1511  * Since: 0.2
1512  */
1513 ClutterInitError
1514 clutter_init_with_args (int            *argc,
1515                         char         ***argv,
1516                         const char     *parameter_string,
1517                         GOptionEntry   *entries,
1518                         const char     *translation_domain,
1519                         GError        **error)
1520 {
1521   GOptionContext *context;
1522   GOptionGroup *group;
1523   gboolean res;
1524   ClutterMainContext *ctx;
1525
1526   if (clutter_is_initialized)
1527     return CLUTTER_INIT_SUCCESS;
1528
1529   clutter_base_init ();
1530
1531   ctx = clutter_context_get_default ();
1532
1533   if (!ctx->defer_display_setup)
1534     {
1535       if (argc && *argc > 0 && *argv)
1536         g_set_prgname ((*argv)[0]);
1537
1538       context = g_option_context_new (parameter_string);
1539
1540       group = clutter_get_option_group ();
1541       g_option_context_add_group (context, group);
1542
1543       group = cogl_get_option_group ();
1544       g_option_context_add_group (context, group);
1545
1546       if (entries)
1547         g_option_context_add_main_entries (context, entries, translation_domain);
1548
1549       res = g_option_context_parse (context, argc, argv, error);
1550       g_option_context_free (context);
1551
1552       /* if res is FALSE, the error is filled for
1553        * us by g_option_context_parse()
1554        */
1555       if (!res)
1556         {
1557           /* if there has been an error in the initialization, the
1558            * error id will be preserved inside the GError code
1559            */
1560           if (error && *error)
1561             return (*error)->code;
1562           else
1563             return CLUTTER_INIT_ERROR_INTERNAL;
1564         }
1565
1566       return CLUTTER_INIT_SUCCESS;
1567     }
1568   else
1569     return clutter_init_real (error);
1570 }
1571
1572 static gboolean
1573 clutter_parse_args (int    *argc,
1574                     char ***argv)
1575 {
1576   GOptionContext *option_context;
1577   GOptionGroup   *clutter_group, *cogl_group;
1578   GError         *error = NULL;
1579   gboolean        ret = TRUE;
1580
1581   if (clutter_is_initialized)
1582     return TRUE;
1583
1584   option_context = g_option_context_new (NULL);
1585   g_option_context_set_ignore_unknown_options (option_context, TRUE);
1586   g_option_context_set_help_enabled (option_context, FALSE);
1587
1588   /* Initiate any command line options from the backend */
1589
1590   clutter_group = clutter_get_option_group ();
1591   g_option_context_set_main_group (option_context, clutter_group);
1592
1593   cogl_group = cogl_get_option_group ();
1594   g_option_context_add_group (option_context, cogl_group);
1595
1596   if (!g_option_context_parse (option_context, argc, argv, &error))
1597     {
1598       if (error)
1599         {
1600           g_warning ("%s", error->message);
1601           g_error_free (error);
1602         }
1603
1604       ret = FALSE;
1605     }
1606
1607   g_option_context_free (option_context);
1608
1609   return ret;
1610 }
1611
1612 /**
1613  * clutter_init:
1614  * @argc: (inout): The number of arguments in @argv
1615  * @argv: (array length=argc) (inout): A pointer to an array of arguments.
1616  *
1617  * It will initialise everything needed to operate with Clutter and
1618  * parses some standard command line options. @argc and @argv are
1619  * adjusted accordingly so your own code will never see those standard
1620  * arguments.
1621  *
1622  * Return value: 1 on success, < 0 on failure.
1623  */
1624 ClutterInitError
1625 clutter_init (int    *argc,
1626               char ***argv)
1627 {
1628   ClutterMainContext *ctx;
1629   GError *error = NULL;
1630
1631   if (clutter_is_initialized)
1632     return CLUTTER_INIT_SUCCESS;
1633
1634   clutter_base_init ();
1635
1636   ctx = clutter_context_get_default ();
1637
1638   if (!ctx->defer_display_setup)
1639     {
1640       if (argc && *argc > 0 && *argv)
1641         g_set_prgname ((*argv)[0]);
1642
1643       /* parse_args will trigger backend creation and things like
1644        * DISPLAY connection etc.
1645        */
1646       if (clutter_parse_args (argc, argv) == FALSE)
1647         {
1648           CLUTTER_NOTE (MISC, "failed to parse arguments.");
1649           return CLUTTER_INIT_ERROR_INTERNAL;
1650         }
1651
1652       return CLUTTER_INIT_SUCCESS;
1653     }
1654   else
1655     return clutter_init_real (&error);
1656 }
1657
1658 gboolean
1659 _clutter_boolean_handled_accumulator (GSignalInvocationHint *ihint,
1660                                       GValue                *return_accu,
1661                                       const GValue          *handler_return,
1662                                       gpointer               dummy)
1663 {
1664   gboolean continue_emission;
1665   gboolean signal_handled;
1666
1667   signal_handled = g_value_get_boolean (handler_return);
1668   g_value_set_boolean (return_accu, signal_handled);
1669   continue_emission = !signal_handled;
1670
1671   return continue_emission;
1672 }
1673
1674 static void
1675 event_click_count_generate (ClutterEvent *event)
1676 {
1677   /* multiple button click detection */
1678   static gint    click_count            = 0;
1679   static gint    previous_x             = -1;
1680   static gint    previous_y             = -1;
1681   static guint32 previous_time          = 0;
1682   static gint    previous_button_number = -1;
1683
1684   ClutterBackend *backend;
1685   guint           double_click_time;
1686   guint           double_click_distance;
1687
1688   backend = clutter_context_get_default ()->backend;
1689   double_click_distance = clutter_backend_get_double_click_distance (backend);
1690   double_click_time = clutter_backend_get_double_click_time (backend);
1691
1692   if (event->button.device != NULL)
1693     {
1694       click_count = event->button.device->click_count;
1695       previous_x = event->button.device->previous_x;
1696       previous_y = event->button.device->previous_y;
1697       previous_time = event->button.device->previous_time;
1698       previous_button_number = event->button.device->previous_button_number;
1699     }
1700
1701   switch (event->type)
1702     {
1703       case CLUTTER_BUTTON_PRESS:
1704       case CLUTTER_SCROLL:
1705         /* check if we are in time and within distance to increment an
1706          * existing click count
1707          */
1708         if (event->button.time < previous_time + double_click_time &&
1709             (ABS (event->button.x - previous_x) <= double_click_distance) &&
1710             (ABS (event->button.y - previous_y) <= double_click_distance)
1711             && event->button.button == previous_button_number)
1712           {
1713             click_count ++;
1714           }
1715         else /* start a new click count*/
1716           {
1717             click_count=1;
1718             previous_button_number = event->button.button;
1719           }
1720
1721         /* store time and position for this click for comparison with
1722          * next event
1723          */
1724         previous_time = event->button.time;
1725         previous_x    = event->button.x;
1726         previous_y    = event->button.y;
1727
1728         /* fallthrough */
1729       case CLUTTER_BUTTON_RELEASE:
1730         event->button.click_count=click_count;
1731         break;
1732       default:
1733         g_assert (NULL);
1734     }
1735
1736   if (event->button.device != NULL)
1737     {
1738       event->button.device->click_count = click_count;
1739       event->button.device->previous_x = previous_x;
1740       event->button.device->previous_y = previous_y;
1741       event->button.device->previous_time = previous_time;
1742       event->button.device->previous_button_number = previous_button_number;
1743     }
1744 }
1745
1746
1747 static inline void
1748 emit_event (ClutterEvent *event,
1749             gboolean      is_key_event)
1750 {
1751   static gboolean      lock = FALSE;
1752
1753   GPtrArray *event_tree = NULL;
1754   ClutterActor *actor;
1755   gint i = 0;
1756
1757   if (!event->any.source)
1758     {
1759       CLUTTER_NOTE (EVENT, "No source set, discarding event");
1760       return;
1761     }
1762
1763   /* reentrancy check */
1764   if (lock != FALSE)
1765     {
1766       g_warning ("Tried emitting event during event delivery, bailing out.n");
1767       return;
1768     }
1769
1770   lock = TRUE;
1771
1772   event_tree = g_ptr_array_sized_new (64);
1773
1774   actor = event->any.source;
1775
1776   /* Build 'tree' of emitters for the event */
1777   while (actor)
1778     {
1779       ClutterActor *parent;
1780
1781       parent = clutter_actor_get_parent (actor);
1782
1783       if (clutter_actor_get_reactive (actor) ||
1784           parent == NULL ||         /* stage gets all events */
1785           is_key_event)             /* keyboard events are always emitted */
1786         {
1787           g_ptr_array_add (event_tree, g_object_ref (actor));
1788         }
1789
1790       actor = parent;
1791     }
1792
1793   /* Capture */
1794   for (i = event_tree->len - 1; i >= 0; i--)
1795     if (clutter_actor_event (g_ptr_array_index (event_tree, i), event, TRUE))
1796       goto done;
1797
1798   /* Bubble */
1799   for (i = 0; i < event_tree->len; i++)
1800     if (clutter_actor_event (g_ptr_array_index (event_tree, i), event, FALSE))
1801       goto done;
1802
1803 done:
1804   for (i = 0; i < event_tree->len; i++)
1805     g_object_unref (g_ptr_array_index (event_tree, i));
1806
1807   g_ptr_array_free (event_tree, TRUE);
1808
1809   lock = FALSE;
1810 }
1811
1812 /*
1813  * Emits a pointer event after having prepared the event for delivery (setting
1814  * source, computing click_count, generating enter/leave etc.).
1815  */
1816
1817 static inline void
1818 emit_pointer_event (ClutterEvent       *event,
1819                     ClutterInputDevice *device)
1820 {
1821   /* Using the global variable directly, since it has to be initialized
1822    * at this point
1823    */
1824   ClutterMainContext *context = ClutterCntx;
1825
1826   if (G_UNLIKELY (context->pointer_grab_actor != NULL &&
1827                   device == NULL))
1828     {
1829       /* global grab */
1830       clutter_actor_event (context->pointer_grab_actor, event, FALSE);
1831     }
1832   else if (G_UNLIKELY (device != NULL &&
1833                        device->pointer_grab_actor != NULL))
1834     {
1835       /* per device grab */
1836       clutter_actor_event (device->pointer_grab_actor, event, FALSE);
1837     }
1838   else
1839     {
1840       /* no grab, time to capture and bubble */
1841       emit_event (event, FALSE);
1842     }
1843 }
1844
1845 static inline void
1846 emit_keyboard_event (ClutterEvent *event)
1847 {
1848   ClutterMainContext *context = ClutterCntx;
1849
1850   if (G_UNLIKELY (context->keyboard_grab_actor != NULL))
1851     clutter_actor_event (context->keyboard_grab_actor, event, FALSE);
1852   else
1853     emit_event (event, TRUE);
1854 }
1855
1856 static void
1857 unset_motion_last_actor (ClutterActor *actor, ClutterInputDevice *dev)
1858 {
1859   ClutterMainContext *context = ClutterCntx;
1860
1861   if (dev == NULL)
1862     context->motion_last_actor = NULL;
1863   else
1864     dev->motion_last_actor = NULL;
1865 }
1866
1867 static ClutterInputDevice * clutter_event_get_device (ClutterEvent *event);
1868
1869 /* This function should perhaps be public and in clutter-event.c ?
1870  */
1871 static ClutterInputDevice *
1872 clutter_event_get_device (ClutterEvent *event)
1873 {
1874   g_return_val_if_fail (event != NULL, NULL);
1875
1876   switch (event->type)
1877     {
1878     case CLUTTER_NOTHING:
1879     case CLUTTER_STAGE_STATE:
1880     case CLUTTER_DESTROY_NOTIFY:
1881     case CLUTTER_CLIENT_MESSAGE:
1882     case CLUTTER_DELETE:
1883     case CLUTTER_ENTER:
1884     case CLUTTER_LEAVE:
1885       return NULL;
1886       break;
1887     case CLUTTER_BUTTON_PRESS:
1888     case CLUTTER_BUTTON_RELEASE:
1889       return event->button.device;
1890     case CLUTTER_MOTION:
1891       return event->motion.device;
1892     case CLUTTER_SCROLL:
1893       return event->scroll.device;
1894       break;
1895     case CLUTTER_KEY_PRESS:
1896     case CLUTTER_KEY_RELEASE:
1897       break;
1898     }
1899   return NULL;
1900 }
1901
1902 static void
1903 set_motion_last_actor (ClutterActor       *motion_current_actor,
1904                        ClutterInputDevice *device)
1905 {
1906   ClutterMainContext *context              = ClutterCntx;
1907   ClutterActor       *last_actor           = context->motion_last_actor;
1908
1909   if (device != NULL)
1910     last_actor = device->motion_last_actor;
1911
1912   if (last_actor && last_actor != motion_current_actor)
1913     {
1914       g_signal_handlers_disconnect_by_func
1915                        (last_actor,
1916                         G_CALLBACK (unset_motion_last_actor),
1917                         device);
1918     }
1919
1920   if (motion_current_actor && last_actor != motion_current_actor)
1921     {
1922       g_signal_connect (motion_current_actor, "destroy",
1923                         G_CALLBACK (unset_motion_last_actor),
1924                         device);
1925     }
1926
1927   if (device != NULL)
1928     device->motion_last_actor = motion_current_actor;
1929   else
1930     context->motion_last_actor = motion_current_actor;
1931 }
1932
1933 static inline void
1934 generate_enter_leave_events (ClutterEvent *event)
1935 {
1936   ClutterMainContext *context              = ClutterCntx;
1937   ClutterActor       *motion_current_actor = event->motion.source;
1938   ClutterActor       *last_actor           = context->motion_last_actor;
1939   ClutterInputDevice *device               = clutter_event_get_device (event);
1940
1941   if (device != NULL)
1942     last_actor = device->motion_last_actor;
1943
1944   if (last_actor != motion_current_actor)
1945     {
1946       if (motion_current_actor)
1947         {
1948           ClutterEvent cev;
1949           gfloat x, y;
1950
1951           cev.crossing.device  = device;
1952           clutter_event_get_coords (event, &x, &y);
1953
1954           if (context->motion_last_actor)
1955             {
1956               cev.crossing.type    = CLUTTER_LEAVE;
1957               cev.crossing.time    = event->any.time;
1958               cev.crossing.flags   = 0;
1959               cev.crossing.x       = x;
1960               cev.crossing.y       = y;
1961               cev.crossing.source  = last_actor;
1962               cev.crossing.stage   = event->any.stage;
1963               cev.crossing.related = motion_current_actor;
1964
1965               emit_pointer_event (&cev, device);
1966             }
1967
1968           cev.crossing.type    = CLUTTER_ENTER;
1969           cev.crossing.time    = event->any.time;
1970           cev.crossing.flags   = 0;
1971           cev.crossing.x       = x;
1972           cev.crossing.y       = y;
1973           cev.crossing.source  = motion_current_actor;
1974           cev.crossing.stage   = event->any.stage;
1975
1976           if (context->motion_last_actor)
1977             cev.crossing.related = last_actor;
1978           else
1979             cev.crossing.related = NULL;
1980
1981           emit_pointer_event (&cev, device);
1982         }
1983     }
1984
1985   set_motion_last_actor (motion_current_actor, device);
1986 }
1987
1988 /**
1989  * clutter_do_event
1990  * @event: a #ClutterEvent.
1991  *
1992  * Processes an event. This function should never be called by applications.
1993  *
1994  * Since: 0.4
1995  */
1996 void
1997 clutter_do_event (ClutterEvent *event)
1998 {
1999   if (!event->any.stage)
2000     return;
2001
2002   /* Instead of processing events when received, we queue them up to
2003    * handle per-frame before animations, layout, and drawing.
2004    *
2005    * This gives us the chance to reliably compress motion events
2006    * because we've "looked ahead" and know all motion events that
2007    * will occur before drawing the frame.
2008    */
2009   _clutter_stage_queue_event (event->any.stage, event);
2010 }
2011
2012 /**
2013  * _clutter_process_event
2014  * @event: a #ClutterEvent.
2015  *
2016  * Does the actual work of processing an event that was queued earlier
2017  * out of clutter_do_event().
2018  */
2019 void
2020 _clutter_process_event (ClutterEvent *event)
2021 {
2022   /* FIXME: This should probably be clutter_cook_event() - it would
2023    * take a raw event from the backend and 'cook' it so its more tasty.
2024    *
2025   */
2026   ClutterMainContext  *context;
2027   ClutterBackend      *backend;
2028   ClutterActor        *stage;
2029   ClutterInputDevice  *device = NULL;
2030
2031   context = clutter_context_get_default ();
2032   backend = context->backend;
2033   stage   = CLUTTER_ACTOR(event->any.stage);
2034
2035   if (!stage)
2036     return;
2037
2038   CLUTTER_TIMESTAMP (EVENT, "Event received");
2039
2040   context->last_event_time = clutter_event_get_time (event);
2041
2042   switch (event->type)
2043     {
2044       case CLUTTER_NOTHING:
2045         event->any.source = stage;
2046         break;
2047
2048       case CLUTTER_LEAVE:
2049         /* The source is set for generated events, not for events
2050          * resulting from the cursor leaving the stage
2051          */
2052         if (event->any.source == NULL)
2053           {
2054             ClutterActor *last_actor = context->motion_last_actor;
2055
2056             if (event->crossing.device != NULL)
2057               last_actor = event->crossing.device->motion_last_actor;
2058
2059             event->any.source = last_actor;
2060
2061             set_motion_last_actor (NULL, event->crossing.device);
2062           }
2063         /* flow through */
2064       case CLUTTER_ENTER:
2065         emit_pointer_event (event, event->crossing.device);
2066         break;
2067
2068       case CLUTTER_DESTROY_NOTIFY:
2069       case CLUTTER_DELETE:
2070         event->any.source = stage;
2071         /* the stage did not handle the event, so we just quit */
2072         if (!clutter_stage_event (CLUTTER_STAGE (stage), event))
2073           {
2074             if (stage == clutter_stage_get_default())
2075               clutter_main_quit ();
2076             else
2077               clutter_actor_destroy (stage);
2078           }
2079
2080         break;
2081
2082       case CLUTTER_KEY_PRESS:
2083       case CLUTTER_KEY_RELEASE:
2084         {
2085           ClutterActor *actor = NULL;
2086
2087           /* check that we're not a synthetic event with source set */
2088           if (event->any.source == NULL)
2089             {
2090               actor = clutter_stage_get_key_focus (CLUTTER_STAGE (stage));
2091               event->any.source = actor;
2092               if (G_UNLIKELY (actor == NULL))
2093                 {
2094                   g_warning ("No key focus set, discarding");
2095                   return;
2096                 }
2097             }
2098
2099           emit_keyboard_event (event);
2100         }
2101         break;
2102
2103       case CLUTTER_MOTION:
2104         device = event->motion.device;
2105
2106         /* Only stage gets motion events if clutter_set_motion_events is TRUE,
2107          * and the event is not a synthetic event with source set.
2108          */
2109         if (!context->motion_events_per_actor &&
2110             event->any.source == NULL)
2111           {
2112             /* Only stage gets motion events */
2113             event->any.source = stage;
2114
2115             /* global grabs */
2116             if (context->pointer_grab_actor != NULL)
2117               {
2118                 clutter_actor_event (context->pointer_grab_actor,
2119                                      event, FALSE);
2120                 break;
2121               }
2122             else if (device != NULL && device->pointer_grab_actor != NULL)
2123               {
2124                 clutter_actor_event (device->pointer_grab_actor,
2125                                      event, FALSE);
2126                 break;
2127               }
2128
2129             /* Trigger handlers on stage in both capture .. */
2130             if (!clutter_actor_event (stage, event, TRUE))
2131               {
2132                 /* and bubbling phase */
2133                 clutter_actor_event (stage, event, FALSE);
2134               }
2135             break;
2136           }
2137
2138         /* fallthrough */
2139
2140       case CLUTTER_BUTTON_PRESS:
2141       case CLUTTER_BUTTON_RELEASE:
2142       case CLUTTER_SCROLL:
2143         {
2144           ClutterActor *actor;
2145           gfloat x, y;
2146
2147           clutter_event_get_coords (event, &x, &y);
2148
2149           /* Only do a pick to find the source if source is not already set
2150            * (as it could be in a synthetic event)
2151            */
2152           if (event->any.source == NULL)
2153             {
2154               /* Handle release off stage */
2155               if ((x >= clutter_actor_get_width (stage) ||
2156                    y >= clutter_actor_get_height (stage) ||
2157                    x < 0 || y < 0))
2158                 {
2159                   if (event->type == CLUTTER_BUTTON_RELEASE)
2160                     {
2161                       CLUTTER_NOTE (EVENT,
2162                                     "Release off stage received at %.2f, %.2f",
2163                                     x, y);
2164
2165                       event->button.source = stage;
2166                       emit_pointer_event (event, event->button.device);
2167                     }
2168                   break;
2169                 }
2170
2171               /* Map the event to a reactive actor */
2172               actor = _clutter_do_pick (CLUTTER_STAGE (stage),
2173                                         x, y,
2174                                         CLUTTER_PICK_REACTIVE);
2175
2176               event->any.source = actor;
2177               if (!actor)
2178                 break;
2179             }
2180           else
2181             {
2182               /* use the source already set in the synthetic event */
2183               actor = event->any.source;
2184             }
2185
2186
2187           /* FIXME: for an optimisation should check if there are
2188            * actually any reactive actors and avoid the pick all together
2189            * (signalling just the stage). Should be big help for gles.
2190            */
2191
2192           CLUTTER_NOTE (EVENT,
2193                         "Reactive event received at %.2f, %.2f - actor: %p",
2194                         x, y,
2195                         actor);
2196
2197           /* Create, enter/leave events if needed */
2198           generate_enter_leave_events (event);
2199
2200           if (event->type != CLUTTER_MOTION)
2201             {
2202               /* Generate click count */
2203               event_click_count_generate (event);
2204             }
2205
2206           if (device == NULL)
2207             {
2208               switch (event->type)
2209                 {
2210                   case CLUTTER_BUTTON_PRESS:
2211                   case CLUTTER_BUTTON_RELEASE:
2212                     device = event->button.device;
2213                     break;
2214                   case CLUTTER_SCROLL:
2215                     device = event->scroll.device;
2216                     break;
2217                   case CLUTTER_MOTION:
2218                     /* already handled in the MOTION case of the switch */
2219                   default:
2220                     break;
2221                 }
2222             }
2223
2224           emit_pointer_event (event, device);
2225           break;
2226         }
2227
2228       case CLUTTER_STAGE_STATE:
2229         /* fullscreen / focus - forward to stage */
2230         event->any.source = stage;
2231         clutter_stage_event (CLUTTER_STAGE (stage), event);
2232         break;
2233
2234       case CLUTTER_CLIENT_MESSAGE:
2235         break;
2236     }
2237 }
2238
2239 /**
2240  * clutter_get_actor_by_gid
2241  * @id: a #ClutterActor ID.
2242  *
2243  * Retrieves the #ClutterActor with @id.
2244  *
2245  * Return value: (transfer none): the actor with the passed id or %NULL.
2246  *   The returned actor does not have its reference count increased.
2247  *
2248  * Since: 0.6
2249  */
2250 ClutterActor*
2251 clutter_get_actor_by_gid (guint32 id)
2252 {
2253   ClutterMainContext *context;
2254
2255   context = clutter_context_get_default ();
2256
2257   g_return_val_if_fail (context != NULL, NULL);
2258
2259   return CLUTTER_ACTOR (clutter_id_pool_lookup (context->id_pool, id));
2260 }
2261
2262 void
2263 clutter_base_init (void)
2264 {
2265   static gboolean initialised = FALSE;
2266
2267   if (!initialised)
2268     {
2269       GType foo; /* Quiet gcc */
2270
2271       initialised = TRUE;
2272
2273       bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
2274       bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
2275
2276       /* initialise GLib type system */
2277       g_type_init ();
2278
2279       /* CLUTTER_TYPE_ACTOR */
2280       foo = clutter_actor_get_type ();
2281     }
2282 }
2283
2284 /**
2285  * clutter_get_default_frame_rate:
2286  *
2287  * Retrieves the default frame rate. See clutter_set_default_frame_rate().
2288  *
2289  * Return value: the default frame rate
2290  *
2291  * Since: 0.6
2292  */
2293 guint
2294 clutter_get_default_frame_rate (void)
2295 {
2296   ClutterMainContext *context;
2297
2298   context = clutter_context_get_default ();
2299
2300   return context->frame_rate;
2301 }
2302
2303 /**
2304  * clutter_set_default_frame_rate:
2305  * @frames_per_sec: the new default frame rate
2306  *
2307  * Sets the default frame rate. This frame rate will be used to limit
2308  * the number of frames drawn if Clutter is not able to synchronize
2309  * with the vertical refresh rate of the display. When synchronization
2310  * is possible, this value is ignored.
2311  *
2312  * Since: 0.6
2313  */
2314 void
2315 clutter_set_default_frame_rate (guint frames_per_sec)
2316 {
2317   ClutterMainContext *context;
2318
2319   context = clutter_context_get_default ();
2320
2321   if (context->frame_rate != frames_per_sec)
2322     context->frame_rate = frames_per_sec;
2323 }
2324
2325
2326 static void
2327 on_pointer_grab_weak_notify (gpointer data,
2328                              GObject *where_the_object_was)
2329 {
2330   ClutterInputDevice *dev = (ClutterInputDevice *)data;
2331   ClutterMainContext *context;
2332
2333   context = clutter_context_get_default ();
2334
2335   if (dev)
2336     {
2337       dev->pointer_grab_actor = NULL;
2338       clutter_ungrab_pointer_for_device (dev->id);
2339     }
2340   else
2341     {
2342       context->pointer_grab_actor = NULL;
2343       clutter_ungrab_pointer ();
2344     }
2345 }
2346
2347 /**
2348  * clutter_grab_pointer:
2349  * @actor: a #ClutterActor
2350  *
2351  * Grabs pointer events, after the grab is done all pointer related events
2352  * (press, motion, release, enter, leave and scroll) are delivered to this
2353  * actor directly without passing through both capture and bubble phases of
2354  * the event delivery chain. The source set in the event will be the actor
2355  * that would have received the event if the pointer grab was not in effect.
2356  *
2357  * <note><para>Grabs completely override the entire event delivery chain
2358  * done by Clutter. Pointer grabs should only be used as a last resource;
2359  * using the #ClutterActor::captured-event signal should always be the
2360  * preferred way to intercept event delivery to reactive actors.</para></note>
2361  *
2362  * If you wish to grab all the pointer events for a specific input device,
2363  * you should use clutter_grab_pointer_for_device().
2364  *
2365  * Since: 0.6
2366  */
2367 void
2368 clutter_grab_pointer (ClutterActor *actor)
2369 {
2370   ClutterMainContext *context;
2371
2372   g_return_if_fail (actor == NULL || CLUTTER_IS_ACTOR (actor));
2373
2374   context = clutter_context_get_default ();
2375
2376   if (context->pointer_grab_actor == actor)
2377     return;
2378
2379   if (context->pointer_grab_actor)
2380     {
2381       g_object_weak_unref (G_OBJECT (context->pointer_grab_actor),
2382                            on_pointer_grab_weak_notify,
2383                            NULL);
2384       context->pointer_grab_actor = NULL;
2385     }
2386
2387   if (actor)
2388     {
2389       context->pointer_grab_actor = actor;
2390
2391       g_object_weak_ref (G_OBJECT (actor),
2392                          on_pointer_grab_weak_notify,
2393                          NULL);
2394     }
2395 }
2396
2397 /**
2398  * clutter_grab_pointer_for_device:
2399  * @actor: a #ClutterActor
2400  * @id: a device id, or -1
2401  *
2402  * Grabs all the pointer events coming from the device @id for @actor.
2403  *
2404  * If @id is -1 then this function is equivalent to clutter_grab_pointer().
2405  *
2406  * Since: 0.8
2407  */
2408 void
2409 clutter_grab_pointer_for_device (ClutterActor *actor,
2410                                  gint          id)
2411 {
2412   ClutterInputDevice *dev;
2413
2414   g_return_if_fail (actor == NULL || CLUTTER_IS_ACTOR (actor));
2415
2416   /* essentially a global grab */
2417   if (id == -1)
2418     {
2419       clutter_grab_pointer (actor);
2420       return;
2421     }
2422
2423   dev = clutter_get_input_device_for_id (id);
2424
2425   if (!dev)
2426     return;
2427
2428   if (dev->pointer_grab_actor == actor)
2429     return;
2430
2431   if (dev->pointer_grab_actor)
2432     {
2433       g_object_weak_unref (G_OBJECT (dev->pointer_grab_actor),
2434                           on_pointer_grab_weak_notify,
2435                           dev);
2436       dev->pointer_grab_actor = NULL;
2437     }
2438
2439   if (actor)
2440     {
2441       dev->pointer_grab_actor = actor;
2442
2443       g_object_weak_ref (G_OBJECT (actor),
2444                         on_pointer_grab_weak_notify,
2445                         dev);
2446     }
2447 }
2448
2449
2450 /**
2451  * clutter_ungrab_pointer:
2452  *
2453  * Removes an existing grab of the pointer.
2454  *
2455  * Since: 0.6
2456  */
2457 void
2458 clutter_ungrab_pointer (void)
2459 {
2460   clutter_grab_pointer (NULL);
2461 }
2462
2463 /**
2464  * clutter_ungrab_pointer_for_device:
2465  * @id: a device id
2466  *
2467  * Removes an existing grab of the pointer events for device @id.
2468  *
2469  * Since: 0.8
2470  */
2471 void
2472 clutter_ungrab_pointer_for_device (gint id)
2473 {
2474   clutter_grab_pointer_for_device (NULL, id);
2475 }
2476
2477
2478 /**
2479  * clutter_get_pointer_grab:
2480  *
2481  * Queries the current pointer grab of clutter.
2482  *
2483  * Return value: (transfer none): the actor currently holding the pointer grab, or NULL if there is no grab.
2484  *
2485  * Since: 0.6
2486  */
2487 ClutterActor *
2488 clutter_get_pointer_grab (void)
2489 {
2490   ClutterMainContext *context;
2491   context = clutter_context_get_default ();
2492
2493   return context->pointer_grab_actor;
2494 }
2495
2496
2497 static void
2498 on_keyboard_grab_weak_notify (gpointer data,
2499                               GObject *where_the_object_was)
2500 {
2501   ClutterMainContext *context;
2502
2503   context = clutter_context_get_default ();
2504   context->keyboard_grab_actor = NULL;
2505
2506   clutter_ungrab_keyboard ();
2507 }
2508
2509 /**
2510  * clutter_grab_keyboard:
2511  * @actor: a #ClutterActor
2512  *
2513  * Grabs keyboard events, after the grab is done keyboard
2514  * events (#ClutterActor::key-press-event and #ClutterActor::key-release-event)
2515  * are delivered to this actor directly. The source set in the event will be
2516  * the actor that would have received the event if the keyboard grab was not
2517  * in effect.
2518  *
2519  * Like pointer grabs, keyboard grabs should only be used as a last
2520  * resource.
2521  *
2522  * See also clutter_stage_set_key_focus() and clutter_actor_grab_key_focus()
2523  * to perform a "soft" key grab and assign key focus to a specific actor.
2524  *
2525  * Since: 0.6
2526  */
2527 void
2528 clutter_grab_keyboard (ClutterActor *actor)
2529 {
2530   ClutterMainContext *context;
2531
2532   g_return_if_fail (actor == NULL || CLUTTER_IS_ACTOR (actor));
2533
2534   context = clutter_context_get_default ();
2535
2536   if (context->keyboard_grab_actor == actor)
2537     return;
2538
2539   if (context->keyboard_grab_actor)
2540     {
2541       g_object_weak_unref (G_OBJECT (context->keyboard_grab_actor),
2542                            on_keyboard_grab_weak_notify,
2543                            NULL);
2544       context->keyboard_grab_actor = NULL;
2545     }
2546
2547   if (actor)
2548     {
2549       context->keyboard_grab_actor = actor;
2550
2551       g_object_weak_ref (G_OBJECT (actor),
2552                          on_keyboard_grab_weak_notify,
2553                          NULL);
2554     }
2555 }
2556
2557 /**
2558  * clutter_ungrab_keyboard:
2559  *
2560  * Removes an existing grab of the keyboard.
2561  *
2562  * Since: 0.6
2563  */
2564 void
2565 clutter_ungrab_keyboard (void)
2566 {
2567   clutter_grab_keyboard (NULL);
2568 }
2569
2570 /**
2571  * clutter_get_keyboard_grab:
2572  *
2573  * Queries the current keyboard grab of clutter.
2574  *
2575  * Return value: (transfer none): the actor currently holding the keyboard grab, or NULL if there is no grab.
2576  *
2577  * Since: 0.6
2578  */
2579 ClutterActor *
2580 clutter_get_keyboard_grab (void)
2581 {
2582   ClutterMainContext *context;
2583   context = clutter_context_get_default ();
2584
2585   return context->keyboard_grab_actor;
2586 }
2587
2588 /**
2589  * clutter_clear_glyph_cache:
2590  *
2591  * Clears the internal cache of glyphs used by the Pango
2592  * renderer. This will free up some memory and GL texture
2593  * resources. The cache will be automatically refilled as more text is
2594  * drawn.
2595  *
2596  * Since: 0.8
2597  */
2598 void
2599 clutter_clear_glyph_cache (void)
2600 {
2601   if (CLUTTER_CONTEXT ()->font_map)
2602     cogl_pango_font_map_clear_glyph_cache (CLUTTER_CONTEXT ()->font_map);
2603 }
2604
2605 /**
2606  * clutter_set_font_flags:
2607  * @flags: The new flags
2608  *
2609  * Sets the font quality options for subsequent text rendering
2610  * operations.
2611  *
2612  * Using mipmapped textures will improve the quality for scaled down
2613  * text but will use more texture memory.
2614  *
2615  * Enabling hinting improves text quality for static text but may
2616  * introduce some artifacts if the text is animated.
2617  *
2618  * Since: 1.0
2619  */
2620 void
2621 clutter_set_font_flags (ClutterFontFlags flags)
2622 {
2623   ClutterFontFlags old_flags, changed_flags;
2624   const cairo_font_options_t *font_options;
2625   cairo_font_options_t *new_font_options;
2626   ClutterBackend *backend;
2627
2628   backend = clutter_get_default_backend ();
2629
2630   if (CLUTTER_CONTEXT ()->font_map)
2631     cogl_pango_font_map_set_use_mipmapping (CLUTTER_CONTEXT ()->font_map,
2632                                             (flags
2633                                              & CLUTTER_FONT_MIPMAPPING) != 0);
2634
2635   old_flags = clutter_get_font_flags ();
2636
2637   font_options = clutter_backend_get_font_options (backend);
2638   new_font_options = cairo_font_options_copy (font_options);
2639
2640   /* Only set the font options that have actually changed so we don't
2641      override a detailed setting from the backend */
2642   changed_flags = old_flags ^ flags;
2643
2644   if ((changed_flags & CLUTTER_FONT_HINTING))
2645     cairo_font_options_set_hint_style (new_font_options,
2646                                        (flags & CLUTTER_FONT_HINTING)
2647                                        ? CAIRO_HINT_STYLE_FULL
2648                                        : CAIRO_HINT_STYLE_NONE);
2649
2650   clutter_backend_set_font_options (backend, new_font_options);
2651
2652   cairo_font_options_destroy (new_font_options);
2653
2654   if (CLUTTER_CONTEXT ()->pango_context)
2655     update_pango_context (backend, CLUTTER_CONTEXT ()->pango_context);
2656 }
2657
2658 /**
2659  * clutter_get_font_flags:
2660  *
2661  * Gets the current font flags for rendering text. See
2662  * clutter_set_font_flags().
2663  *
2664  * Return value: The font flags
2665  *
2666  * Since: 1.0
2667  */
2668 ClutterFontFlags
2669 clutter_get_font_flags (void)
2670 {
2671   ClutterMainContext *ctxt = CLUTTER_CONTEXT ();
2672   CoglPangoFontMap *font_map = NULL;
2673   const cairo_font_options_t *font_options;
2674   ClutterFontFlags flags = 0;
2675
2676   font_map = CLUTTER_CONTEXT ()->font_map;
2677
2678   if (G_LIKELY (font_map)
2679       && cogl_pango_font_map_get_use_mipmapping (font_map))
2680     flags |= CLUTTER_FONT_MIPMAPPING;
2681
2682   font_options = clutter_backend_get_font_options (ctxt->backend);
2683
2684   if ((cairo_font_options_get_hint_style (font_options)
2685        != CAIRO_HINT_STYLE_DEFAULT)
2686       && (cairo_font_options_get_hint_style (font_options)
2687           != CAIRO_HINT_STYLE_NONE))
2688     flags |= CLUTTER_FONT_HINTING;
2689
2690   return flags;
2691 }
2692
2693 /**
2694  * clutter_get_input_device_for_id:
2695  * @id: a device id
2696  *
2697  * Retrieves the #ClutterInputDevice from its id.
2698  *
2699  * Return value: (transfer none): a #ClutterInputDevice, or %NULL
2700  *
2701  * Since: 0.8
2702  */
2703 ClutterInputDevice *
2704 clutter_get_input_device_for_id (gint id)
2705 {
2706   GSList *item;
2707   ClutterInputDevice *device = NULL;
2708   ClutterMainContext  *context;
2709
2710   context = clutter_context_get_default ();
2711
2712   for (item = context->input_devices;
2713        item != NULL;
2714        item = item->next)
2715   {
2716     device = item->data;
2717
2718     if (device->id == id)
2719       return device;
2720   }
2721
2722   return NULL;
2723 }
2724
2725 /**
2726  * clutter_get_font_map:
2727  *
2728  * Retrieves the #PangoFontMap instance used by Clutter.
2729  * You can use the global font map object with the COGL
2730  * Pango API.
2731  *
2732  * Return value: (transfer none): the #PangoFontMap instance. The returned
2733  *   value is owned by Clutter and it should never be unreferenced.
2734  *
2735  * Since: 1.0
2736  */
2737 PangoFontMap *
2738 clutter_get_font_map (void)
2739 {
2740   if (CLUTTER_CONTEXT ()->font_map)
2741     return PANGO_FONT_MAP (CLUTTER_CONTEXT ()->font_map);
2742
2743   return NULL;
2744 }
2745
2746 typedef struct _ClutterRepaintFunction
2747 {
2748   guint id;
2749   GSourceFunc func;
2750   gpointer data;
2751   GDestroyNotify notify;
2752 } ClutterRepaintFunction;
2753
2754 /**
2755  * clutter_threads_remove_repaint_func:
2756  * @handle_id: an unsigned integer greater than zero
2757  *
2758  * Removes the repaint function with @handle_id as its id
2759  *
2760  * Since: 1.0
2761  */
2762 void
2763 clutter_threads_remove_repaint_func (guint handle_id)
2764 {
2765   ClutterRepaintFunction *repaint_func;
2766   ClutterMainContext *context;
2767   GList *l;
2768
2769   g_return_if_fail (handle_id > 0);
2770
2771   context = CLUTTER_CONTEXT ();
2772   l = context->repaint_funcs;
2773   while (l != NULL)
2774     {
2775       repaint_func = l->data;
2776
2777       if (repaint_func->id == handle_id)
2778         {
2779           context->repaint_funcs =
2780             g_list_remove_link (context->repaint_funcs, l);
2781
2782           g_list_free (l);
2783
2784           if (repaint_func->notify)
2785             repaint_func->notify (repaint_func->data);
2786
2787           g_slice_free (ClutterRepaintFunction, repaint_func);
2788
2789           return;
2790         }
2791
2792       l = l->next;
2793     }
2794 }
2795
2796 /**
2797  * clutter_threads_add_repaint_func:
2798  * @func: the function to be called within the paint cycle
2799  * @data: data to be passed to the function, or %NULL
2800  * @notify: function to be called when removing the repaint
2801  *    function, or %NULL
2802  *
2803  * Adds a function to be called whenever Clutter is repainting a Stage.
2804  * If the function returns %FALSE it is automatically removed from the
2805  * list of repaint functions and will not be called again.
2806  *
2807  * This function is guaranteed to be called from within the same thread
2808  * that called clutter_main(), and while the Clutter lock is being held.
2809  *
2810  * A repaint function is useful to ensure that an update of the scenegraph
2811  * is performed before the scenegraph is repainted; for instance, uploading
2812  * a frame from a video into a #ClutterTexture.
2813  *
2814  * When the repaint function is removed (either because it returned %FALSE
2815  * or because clutter_threads_remove_repaint_func() has been called) the
2816  * @notify function will be called, if any is set.
2817  *
2818  * Return value: the ID (greater than 0) of the repaint function. You
2819  *   can use the returned integer to remove the repaint function by
2820  *   calling clutter_threads_remove_repaint_func().
2821  *
2822  * Since: 1.0
2823  */
2824 guint
2825 clutter_threads_add_repaint_func (GSourceFunc    func,
2826                                   gpointer       data,
2827                                   GDestroyNotify notify)
2828 {
2829   static guint repaint_id = 1;
2830   ClutterMainContext *context;
2831   ClutterRepaintFunction *repaint_func;
2832
2833   g_return_val_if_fail (func != NULL, 0);
2834
2835   context = CLUTTER_CONTEXT ();
2836
2837   /* XXX lock the context */
2838
2839   repaint_func = g_slice_new (ClutterRepaintFunction);
2840
2841   repaint_func->id = repaint_id++;
2842   repaint_func->func = func;
2843   repaint_func->data = data;
2844   repaint_func->notify = notify;
2845
2846   context->repaint_funcs = g_list_prepend (context->repaint_funcs,
2847                                            repaint_func);
2848
2849   /* XXX unlock the context */
2850
2851   return repaint_func->id;
2852 }
2853
2854 /*
2855  * _clutter_run_repaint_functions:
2856  *
2857  * Executes the repaint functions added using the
2858  * clutter_threads_add_repaint_func() function.
2859  *
2860  * Must be called before calling clutter_redraw() and
2861  * with the Clutter thread lock held.
2862  */
2863 void
2864 _clutter_run_repaint_functions (void)
2865 {
2866   ClutterMainContext *context = CLUTTER_CONTEXT ();
2867   ClutterRepaintFunction *repaint_func;
2868   GList *reinvoke_list, *l;
2869
2870   if (context->repaint_funcs == NULL)
2871     return;
2872
2873   reinvoke_list = NULL;
2874
2875   /* consume the whole list while we execute the functions */
2876   while (context->repaint_funcs)
2877     {
2878       gboolean res = FALSE;
2879
2880       repaint_func = context->repaint_funcs->data;
2881
2882       l = context->repaint_funcs;
2883       context->repaint_funcs =
2884         g_list_remove_link (context->repaint_funcs, context->repaint_funcs);
2885
2886       g_list_free (l);
2887
2888       res = repaint_func->func (repaint_func->data);
2889
2890       if (res)
2891         reinvoke_list = g_list_prepend (reinvoke_list, repaint_func);
2892       else
2893         {
2894           if (repaint_func->notify)
2895             repaint_func->notify (repaint_func->data);
2896
2897           g_slice_free (ClutterRepaintFunction, repaint_func);
2898         }
2899     }
2900
2901   if (reinvoke_list)
2902     context->repaint_funcs = reinvoke_list;
2903 }