Release Clutter 1.11.4 (snapshot)
[profile/ivi/clutter.git] / clutter / clutter-stage.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, see <http://www.gnu.org/licenses/>.
22  *
23  *
24  */
25
26 /**
27  * SECTION:clutter-stage
28  * @short_description: Top level visual element to which actors are placed.
29  *
30  * #ClutterStage is a top level 'window' on which child actors are placed
31  * and manipulated.
32  *
33  * Backends might provide support for multiple stages. The support for this
34  * feature can be checked at run-time using the clutter_feature_available()
35  * function and the %CLUTTER_FEATURE_STAGE_MULTIPLE flag. If the backend used
36  * supports multiple stages, new #ClutterStage instances can be created
37  * using clutter_stage_new(). These stages must be managed by the developer
38  * using clutter_actor_destroy(), which will take care of destroying all the
39  * actors contained inside them.
40  *
41  * #ClutterStage is a proxy actor, wrapping the backend-specific
42  * implementation of the windowing system. It is possible to subclass
43  * #ClutterStage, as long as every overridden virtual function chains up to
44  * the parent class corresponding function.
45  */
46
47 #ifdef HAVE_CONFIG_H
48 #include "config.h"
49 #endif
50
51 #include <math.h>
52 #include <cairo.h>
53
54 #define CLUTTER_DISABLE_DEPRECATION_WARNINGS
55
56 #include "clutter-stage.h"
57 #include "deprecated/clutter-stage.h"
58 #include "deprecated/clutter-container.h"
59
60 #include "clutter-actor-private.h"
61 #include "clutter-backend-private.h"
62 #include "clutter-cairo.h"
63 #include "clutter-color.h"
64 #include "clutter-container.h"
65 #include "clutter-debug.h"
66 #include "clutter-device-manager-private.h"
67 #include "clutter-enum-types.h"
68 #include "clutter-event-private.h"
69 #include "clutter-id-pool.h"
70 #include "clutter-main.h"
71 #include "clutter-marshal.h"
72 #include "clutter-master-clock.h"
73 #include "clutter-paint-volume-private.h"
74 #include "clutter-private.h"
75 #include "clutter-profile.h"
76 #include "clutter-stage-manager-private.h"
77 #include "clutter-stage-private.h"
78 #include "clutter-util.h"
79 #include "clutter-version.h"    /* For flavour */
80 #include "clutter-private.h"
81
82 #include "cogl/cogl.h"
83
84 static void clutter_container_iface_init (ClutterContainerIface *iface);
85
86 G_DEFINE_TYPE_WITH_CODE (ClutterStage, clutter_stage, CLUTTER_TYPE_GROUP,
87                          G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTAINER,
88                                                 clutter_container_iface_init))
89
90 #define CLUTTER_STAGE_GET_PRIVATE(obj) \
91 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), CLUTTER_TYPE_STAGE, ClutterStagePrivate))
92
93 /* <private>
94  * ClutterStageHint:
95  * @CLUTTER_STAGE_NONE: No hint set
96  * @CLUTTER_STAGE_NO_CLEAR_ON_PAINT: When this hint is set, the stage
97  *   should not clear the viewport; this flag is useful when painting
98  *   fully opaque actors covering the whole visible area of the stage,
99  *   i.e. when no blending with the stage color happens over the whole
100  *   stage viewport
101  *
102  * A series of hints that enable or disable behaviours on the stage
103  */
104 typedef enum { /*< prefix=CLUTTER_STAGE >*/
105   CLUTTER_STAGE_HINT_NONE = 0,
106
107   CLUTTER_STAGE_NO_CLEAR_ON_PAINT = 1 << 0
108 } ClutterStageHint;
109
110 #define STAGE_NO_CLEAR_ON_PAINT(s)      ((((ClutterStage *) (s))->priv->stage_hints & CLUTTER_STAGE_NO_CLEAR_ON_PAINT) != 0)
111
112 struct _ClutterStageQueueRedrawEntry
113 {
114   ClutterActor *actor;
115   gboolean has_clip;
116   ClutterPaintVolume clip;
117 };
118
119 struct _ClutterStagePrivate
120 {
121   /* the stage implementation */
122   ClutterStageWindow *impl;
123
124   ClutterPerspective perspective;
125   CoglMatrix projection;
126   CoglMatrix inverse_projection;
127   CoglMatrix view;
128   float viewport[4];
129
130   ClutterFog fog;
131
132   gchar *title;
133   ClutterActor *key_focused_actor;
134
135   GQueue *event_queue;
136
137   ClutterStageHint stage_hints;
138
139   gint picks_per_frame;
140
141   GArray *paint_volume_stack;
142
143   ClutterPlane current_clip_planes[4];
144
145   GList *pending_queue_redraws;
146
147   ClutterPickMode pick_buffer_mode;
148
149   CoglFramebuffer *active_framebuffer;
150
151   GHashTable *devices;
152
153   GTimer *fps_timer;
154   gint32 timer_n_frames;
155
156   ClutterIDPool *pick_id_pool;
157
158 #ifdef CLUTTER_ENABLE_DEBUG
159   gulong redraw_count;
160 #endif /* CLUTTER_ENABLE_DEBUG */
161
162   ClutterStageState current_state;
163
164   guint relayout_pending       : 1;
165   guint redraw_pending         : 1;
166   guint is_fullscreen          : 1;
167   guint is_cursor_visible      : 1;
168   guint is_user_resizable      : 1;
169   guint use_fog                : 1;
170   guint throttle_motion_events : 1;
171   guint use_alpha              : 1;
172   guint min_size_changed       : 1;
173   guint dirty_viewport         : 1;
174   guint dirty_projection       : 1;
175   guint have_valid_pick_buffer : 1;
176   guint accept_focus           : 1;
177   guint motion_events_enabled  : 1;
178   guint has_custom_perspective : 1;
179 };
180
181 enum
182 {
183   PROP_0,
184
185   PROP_COLOR,
186   PROP_FULLSCREEN_SET,
187   PROP_OFFSCREEN,
188   PROP_CURSOR_VISIBLE,
189   PROP_PERSPECTIVE,
190   PROP_TITLE,
191   PROP_USER_RESIZABLE,
192   PROP_USE_FOG,
193   PROP_FOG,
194   PROP_USE_ALPHA,
195   PROP_KEY_FOCUS,
196   PROP_NO_CLEAR_HINT,
197   PROP_ACCEPT_FOCUS
198 };
199
200 enum
201 {
202   FULLSCREEN,
203   UNFULLSCREEN,
204   ACTIVATE,
205   DEACTIVATE,
206   DELETE_EVENT,
207
208   LAST_SIGNAL
209 };
210
211 static guint stage_signals[LAST_SIGNAL] = { 0, };
212
213 static const ClutterColor default_stage_color = { 255, 255, 255, 255 };
214
215 static void _clutter_stage_maybe_finish_queue_redraws (ClutterStage *stage);
216
217 static void
218 clutter_stage_real_add (ClutterContainer *container,
219                         ClutterActor     *child)
220 {
221   clutter_actor_add_child (CLUTTER_ACTOR (container), child);
222 }
223
224 static void
225 clutter_stage_real_remove (ClutterContainer *container,
226                            ClutterActor     *child)
227 {
228   clutter_actor_remove_child (CLUTTER_ACTOR (container), child);
229 }
230
231 static void
232 clutter_stage_real_foreach (ClutterContainer *container,
233                             ClutterCallback   callback,
234                             gpointer          user_data)
235 {
236   ClutterActorIter iter;
237   ClutterActor *child;
238
239   clutter_actor_iter_init (&iter, CLUTTER_ACTOR (container));
240
241   while (clutter_actor_iter_next (&iter, &child))
242     callback (child, user_data);
243 }
244
245 static void
246 clutter_stage_real_raise (ClutterContainer *container,
247                           ClutterActor     *child,
248                           ClutterActor     *sibling)
249 {
250   clutter_actor_set_child_above_sibling (CLUTTER_ACTOR (container),
251                                          child,
252                                          sibling);
253 }
254
255 static void
256 clutter_stage_real_lower (ClutterContainer *container,
257                           ClutterActor     *child,
258                           ClutterActor     *sibling)
259 {
260   clutter_actor_set_child_below_sibling (CLUTTER_ACTOR (container),
261                                          child,
262                                          sibling);
263 }
264
265 static void
266 clutter_stage_real_sort_depth_order (ClutterContainer *container)
267 {
268 }
269
270 static void
271 clutter_container_iface_init (ClutterContainerIface *iface)
272 {
273   iface->add = clutter_stage_real_add;
274   iface->remove = clutter_stage_real_remove;
275   iface->foreach = clutter_stage_real_foreach;
276   iface->raise = clutter_stage_real_raise;
277   iface->lower = clutter_stage_real_lower;
278   iface->sort_depth_order = clutter_stage_real_sort_depth_order;
279 }
280
281 static void
282 clutter_stage_get_preferred_width (ClutterActor *self,
283                                    gfloat        for_height,
284                                    gfloat       *min_width_p,
285                                    gfloat       *natural_width_p)
286 {
287   ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
288   cairo_rectangle_int_t geom;
289
290   if (priv->impl == NULL)
291     return;
292
293   _clutter_stage_window_get_geometry (priv->impl, &geom);
294
295   if (min_width_p)
296     *min_width_p = geom.width;
297
298   if (natural_width_p)
299     *natural_width_p = geom.width;
300 }
301
302 static void
303 clutter_stage_get_preferred_height (ClutterActor *self,
304                                     gfloat        for_width,
305                                     gfloat       *min_height_p,
306                                     gfloat       *natural_height_p)
307 {
308   ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
309   cairo_rectangle_int_t geom;
310
311   if (priv->impl == NULL)
312     return;
313
314   _clutter_stage_window_get_geometry (priv->impl, &geom);
315
316   if (min_height_p)
317     *min_height_p = geom.height;
318
319   if (natural_height_p)
320     *natural_height_p = geom.height;
321 }
322
323 static inline void
324 queue_full_redraw (ClutterStage *stage)
325 {
326   ClutterStageWindow *stage_window;
327
328   if (CLUTTER_ACTOR_IN_DESTRUCTION (stage))
329     return;
330
331   clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
332
333   /* Just calling clutter_actor_queue_redraw will typically only
334    * redraw the bounding box of the children parented on the stage but
335    * in this case we really need to ensure that the full stage is
336    * redrawn so we add a NULL redraw clip to the stage window. */
337   stage_window = _clutter_stage_get_window (stage);
338   if (stage_window == NULL)
339     return;
340
341   _clutter_stage_window_add_redraw_clip (stage_window, NULL);
342 }
343
344 static gboolean
345 stage_is_default (ClutterStage *stage)
346 {
347   ClutterStageManager *stage_manager;
348   ClutterStageWindow *impl;
349
350   stage_manager = clutter_stage_manager_get_default ();
351   if (stage != clutter_stage_manager_get_default_stage (stage_manager))
352     return FALSE;
353
354   impl = _clutter_stage_get_window (stage);
355   if (impl != _clutter_stage_get_default_window ())
356     return FALSE;
357
358   return TRUE;
359 }
360
361 static void
362 clutter_stage_allocate (ClutterActor           *self,
363                         const ClutterActorBox  *box,
364                         ClutterAllocationFlags  flags)
365 {
366   ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
367   ClutterGeometry prev_geom, geom;
368   cairo_rectangle_int_t window_size;
369   gboolean origin_changed;
370   gint width, height;
371
372   origin_changed = (flags & CLUTTER_ABSOLUTE_ORIGIN_CHANGED)
373                  ? TRUE
374                  : FALSE;
375
376   if (priv->impl == NULL)
377     return;
378
379   /* our old allocation */
380   clutter_actor_get_allocation_geometry (self, &prev_geom);
381
382   /* the current allocation */
383   width = clutter_actor_box_get_width (box);
384   height = clutter_actor_box_get_height (box);
385
386   /* the current Stage implementation size */
387   _clutter_stage_window_get_geometry (priv->impl, &window_size);
388
389   /* if the stage is fixed size (for instance, it's using a EGL framebuffer)
390    * then we simply ignore any allocation request and override the
391    * allocation chain - because we cannot forcibly change the size of the
392    * stage window.
393    */
394   if ((!clutter_feature_available (CLUTTER_FEATURE_STAGE_STATIC)))
395     {
396       CLUTTER_NOTE (LAYOUT,
397                     "Following allocation to %dx%d (origin %s)",
398                     width, height,
399                     origin_changed ? "changed" : "not changed");
400
401       clutter_actor_set_allocation (self, box,
402                                     flags | CLUTTER_DELEGATE_LAYOUT);
403
404       /* Ensure the window is sized correctly */
405       if (!priv->is_fullscreen)
406         {
407           if (priv->min_size_changed)
408             {
409               gfloat min_width, min_height;
410               gboolean min_width_set, min_height_set;
411
412               g_object_get (G_OBJECT (self),
413                             "min-width", &min_width,
414                             "min-width-set", &min_width_set,
415                             "min-height", &min_height,
416                             "min-height-set", &min_height_set,
417                             NULL);
418
419               if (!min_width_set)
420                 min_width = 1;
421               if (!min_height_set)
422                 min_height = 1;
423
424               if (width < min_width)
425                 width = min_width;
426               if (height < min_height)
427                 height = min_height;
428
429               priv->min_size_changed = FALSE;
430             }
431
432           if (window_size.width != width ||
433               window_size.height != height)
434             {
435               _clutter_stage_window_resize (priv->impl, width, height);
436             }
437         }
438     }
439   else
440     {
441       ClutterActorBox override = { 0, };
442
443       /* override the passed allocation */
444       override.x1 = 0;
445       override.y1 = 0;
446       override.x2 = window_size.width;
447       override.y2 = window_size.height;
448
449       CLUTTER_NOTE (LAYOUT,
450                     "Overrigin original allocation of %dx%d "
451                     "with %dx%d (origin %s)",
452                     width, height,
453                     (int) (override.x2),
454                     (int) (override.y2),
455                     origin_changed ? "changed" : "not changed");
456
457       /* and store the overridden allocation */
458       clutter_actor_set_allocation (self, &override,
459                                     flags | CLUTTER_DELEGATE_LAYOUT);
460     }
461
462   /* XXX: Until Cogl becomes fully responsible for backend windows
463    * Clutter need to manually keep it informed of the current window
464    * size. We do this after the allocation above so that the stage
465    * window has a chance to update the window size based on the
466    * allocation.
467    */
468   _clutter_stage_window_get_geometry (priv->impl, &window_size);
469   cogl_onscreen_clutter_backend_set_size (window_size.width,
470                                           window_size.height);
471
472   /* reset the viewport if the allocation effectively changed */
473   clutter_actor_get_allocation_geometry (self, &geom);
474   if (geom.width != prev_geom.width ||
475       geom.height != prev_geom.height)
476     {
477       _clutter_stage_set_viewport (CLUTTER_STAGE (self),
478                                    0, 0,
479                                    geom.width,
480                                    geom.height);
481
482       /* Note: we don't assume that set_viewport will queue a full redraw
483        * since it may bail-out early if something preemptively set the
484        * viewport before the stage was really allocated its new size.
485        */
486       queue_full_redraw (CLUTTER_STAGE (self));
487     }
488 }
489
490 typedef struct _Vector4
491 {
492   float x, y, z, w;
493 } Vector4;
494
495 static void
496 _cogl_util_get_eye_planes_for_screen_poly (float *polygon,
497                                            int n_vertices,
498                                            float *viewport,
499                                            const CoglMatrix *projection,
500                                            const CoglMatrix *inverse_project,
501                                            ClutterPlane *planes)
502 {
503   float Wc;
504   Vector4 *tmp_poly;
505   ClutterPlane *plane;
506   int i;
507   float b[3];
508   float c[3];
509   int count;
510
511   tmp_poly = g_alloca (sizeof (Vector4) * n_vertices * 2);
512
513 #define DEPTH -50
514
515   /* Determine W in clip-space (Wc) for a point (0, 0, DEPTH, 1)
516    *
517    * Note: the depth could be anything except 0.
518    *
519    * We will transform the polygon into clip coordinates using this
520    * depth and then into eye coordinates. Our clip planes will be
521    * defined by triangles that extend between points of the polygon at
522    * DEPTH and corresponding points of the same polygon at DEPTH * 2.
523    *
524    * NB: Wc defines the position of the clip planes in clip
525    * coordinates. Given a screen aligned cross section through the
526    * frustum; coordinates range from [-Wc,Wc] left to right on the
527    * x-axis and [Wc,-Wc] top to bottom on the y-axis.
528    */
529   Wc = DEPTH * projection->wz + projection->ww;
530
531 #define CLIP_X(X) ((((float)X - viewport[0]) * (2.0 / viewport[2])) - 1) * Wc
532 #define CLIP_Y(Y) ((((float)Y - viewport[1]) * (2.0 / viewport[3])) - 1) * -Wc
533
534   for (i = 0; i < n_vertices; i++)
535     {
536       tmp_poly[i].x = CLIP_X (polygon[i * 2]);
537       tmp_poly[i].y = CLIP_Y (polygon[i * 2 + 1]);
538       tmp_poly[i].z = DEPTH;
539       tmp_poly[i].w = Wc;
540     }
541
542   Wc = DEPTH * 2 * projection->wz + projection->ww;
543
544   /* FIXME: technically we don't need to project all of the points
545    * twice, it would be enough project every other point since
546    * we can share points in this set to define the plane vectors. */
547   for (i = 0; i < n_vertices; i++)
548     {
549       tmp_poly[n_vertices + i].x = CLIP_X (polygon[i * 2]);
550       tmp_poly[n_vertices + i].y = CLIP_Y (polygon[i * 2 + 1]);
551       tmp_poly[n_vertices + i].z = DEPTH * 2;
552       tmp_poly[n_vertices + i].w = Wc;
553     }
554
555 #undef CLIP_X
556 #undef CLIP_Y
557
558   cogl_matrix_project_points (inverse_project,
559                               4,
560                               sizeof (Vector4),
561                               tmp_poly,
562                               sizeof (Vector4),
563                               tmp_poly,
564                               n_vertices * 2);
565
566   /* XXX: It's quite ugly that we end up with these casts between
567    * Vector4 types and CoglVector3s, it might be better if the
568    * cogl_vector APIs just took pointers to floats.
569    */
570
571   count = n_vertices - 1;
572   for (i = 0; i < count; i++)
573     {
574       plane = &planes[i];
575       memcpy (plane->v0, tmp_poly + i, sizeof (float) * 3);
576       memcpy (b, tmp_poly + n_vertices + i, sizeof (float) * 3);
577       memcpy (c, tmp_poly + n_vertices + i + 1, sizeof (float) * 3);
578       cogl_vector3_subtract (b, b, plane->v0);
579       cogl_vector3_subtract (c, c, plane->v0);
580       cogl_vector3_cross_product (plane->n, b, c);
581       cogl_vector3_normalize (plane->n);
582     }
583
584   plane = &planes[n_vertices - 1];
585   memcpy (plane->v0, tmp_poly + 0, sizeof (float) * 3);
586   memcpy (b, tmp_poly + (2 * n_vertices - 1), sizeof (float) * 3);
587   memcpy (c, tmp_poly + n_vertices, sizeof (float) * 3);
588   cogl_vector3_subtract (b, b, plane->v0);
589   cogl_vector3_subtract (c, c, plane->v0);
590   cogl_vector3_cross_product (plane->n, b, c);
591   cogl_vector3_normalize (plane->n);
592 }
593
594 static void
595 _clutter_stage_update_active_framebuffer (ClutterStage *stage)
596 {
597   ClutterStagePrivate *priv = stage->priv;
598
599   /* We track the CoglFramebuffer that corresponds to the stage itself
600    * so, for example, we can disable culling when rendering to an
601    * offscreen framebuffer.
602    */
603
604   priv->active_framebuffer =
605     _clutter_stage_window_get_active_framebuffer (priv->impl);
606
607   if (!priv->active_framebuffer)
608     priv->active_framebuffer = cogl_get_draw_framebuffer ();
609 }
610
611 /* This provides a common point of entry for painting the scenegraph
612  * for picking or painting...
613  *
614  * XXX: Instead of having a toplevel 2D clip region, it might be
615  * better to have a clip volume within the view frustum. This could
616  * allow us to avoid projecting actors into window coordinates to
617  * be able to cull them.
618  */
619 void
620 _clutter_stage_do_paint (ClutterStage                *stage,
621                          const cairo_rectangle_int_t *clip)
622 {
623   ClutterStagePrivate *priv = stage->priv;
624   float clip_poly[8];
625   cairo_rectangle_int_t geom;
626
627   _clutter_stage_window_get_geometry (priv->impl, &geom);
628
629   if (clip)
630     {
631       clip_poly[0] = MAX (clip->x, 0);
632       clip_poly[1] = MAX (clip->y, 0);
633       clip_poly[2] = MIN (clip->x + clip->width, geom.width);
634       clip_poly[3] = clip_poly[1];
635       clip_poly[4] = clip_poly[2];
636       clip_poly[5] = MIN (clip->y + clip->height, geom.height);
637       clip_poly[6] = clip_poly[0];
638       clip_poly[7] = clip_poly[5];
639     }
640   else
641     {
642       clip_poly[0] = 0;
643       clip_poly[1] = 0;
644       clip_poly[2] = geom.width;
645       clip_poly[3] = 0;
646       clip_poly[4] = geom.width;
647       clip_poly[5] = geom.height;
648       clip_poly[6] = 0;
649       clip_poly[7] = geom.height;
650     }
651
652   CLUTTER_NOTE (CLIPPING, "Setting stage clip too: "
653                 "x=%f, y=%f, width=%f, height=%f",
654                 clip_poly[0], clip_poly[1],
655                 clip_poly[2] - clip_poly[0],
656                 clip_poly[5] - clip_poly[1]);
657
658   _cogl_util_get_eye_planes_for_screen_poly (clip_poly,
659                                              4,
660                                              priv->viewport,
661                                              &priv->projection,
662                                              &priv->inverse_projection,
663                                              priv->current_clip_planes);
664
665   _clutter_stage_paint_volume_stack_free_all (stage);
666   _clutter_stage_update_active_framebuffer (stage);
667   clutter_actor_paint (CLUTTER_ACTOR (stage));
668 }
669
670 static void
671 clutter_stage_paint (ClutterActor *self)
672 {
673   ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
674   CoglBufferBit clear_flags;
675   ClutterColor bg_color;
676   CoglColor stage_color;
677   ClutterActorIter iter;
678   ClutterActor *child;
679   guint8 real_alpha;
680
681   CLUTTER_STATIC_TIMER (stage_clear_timer,
682                         "Painting actors", /* parent */
683                         "Stage clear",
684                         "The time spent clearing the stage",
685                         0 /* no application private data */);
686
687   CLUTTER_NOTE (PAINT, "Initializing stage paint");
688
689   /* composite the opacity to the stage color */
690   clutter_actor_get_background_color (self, &bg_color);
691   real_alpha = clutter_actor_get_opacity (self)
692              * bg_color.alpha
693              / 255;
694
695   clear_flags = COGL_BUFFER_BIT_DEPTH;
696   if (!STAGE_NO_CLEAR_ON_PAINT (self))
697     clear_flags |= COGL_BUFFER_BIT_COLOR;
698
699   CLUTTER_TIMER_START (_clutter_uprof_context, stage_clear_timer);
700   /* we use the real alpha to clear the stage if :use-alpha is
701    * set; the effect depends entirely on the Clutter backend
702    */
703   cogl_color_init_from_4ub (&stage_color,
704                             bg_color.red,
705                             bg_color.green,
706                             bg_color.blue,
707                             priv->use_alpha ? real_alpha : 255);
708   cogl_color_premultiply (&stage_color);
709   cogl_clear (&stage_color, clear_flags);
710   CLUTTER_TIMER_STOP (_clutter_uprof_context, stage_clear_timer);
711
712   clutter_actor_iter_init (&iter, self);
713   while (clutter_actor_iter_next (&iter, &child))
714     clutter_actor_paint (child);
715 }
716
717 static void
718 clutter_stage_pick (ClutterActor       *self,
719                     const ClutterColor *color)
720 {
721   ClutterActorIter iter;
722   ClutterActor *child;
723
724   /* Note: we don't chain up to our parent as we don't want any geometry
725    * emitted for the stage itself. The stage's pick id is effectively handled
726    * by the call to cogl_clear done in clutter-main.c:_clutter_do_pick_async()
727    */
728   clutter_actor_iter_init (&iter, self);
729   while (clutter_actor_iter_next (&iter, &child))
730     clutter_actor_paint (child);
731 }
732
733 static gboolean
734 clutter_stage_get_paint_volume (ClutterActor *self,
735                                 ClutterPaintVolume *volume)
736 {
737   /* Returning False effectively means Clutter has to assume it covers
738    * everything... */
739   return FALSE;
740 }
741
742 static void
743 clutter_stage_realize (ClutterActor *self)
744 {
745   ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
746   gboolean is_realized;
747
748   /* Make sure the viewport and projection matrix are valid for the
749    * first paint (which will likely occur before the ConfigureNotify
750    * is received)
751    */
752   priv->dirty_viewport = TRUE;
753   priv->dirty_projection = TRUE;
754
755   g_assert (priv->impl != NULL);
756   is_realized = _clutter_stage_window_realize (priv->impl);
757
758   /* ensure that the stage is using the context if the
759    * realization sequence was successful
760    */
761   if (is_realized)
762     {
763       ClutterBackend *backend = clutter_get_default_backend ();
764
765       /* We want to select the context without calling
766          clutter_backend_ensure_context so that it doesn't call any
767          Cogl functions. Otherwise it would create the Cogl context
768          before we get a chance to check whether the GL version is
769          valid */
770       _clutter_backend_ensure_context_internal (backend, CLUTTER_STAGE (self));
771     }
772   else
773     CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_REALIZED);
774 }
775
776 static void
777 clutter_stage_unrealize (ClutterActor *self)
778 {
779   ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
780
781   /* and then unrealize the implementation */
782   g_assert (priv->impl != NULL);
783   _clutter_stage_window_unrealize (priv->impl);
784
785   CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_REALIZED);
786
787   clutter_stage_ensure_current (CLUTTER_STAGE (self));
788 }
789
790 static void
791 clutter_stage_show_all (ClutterActor *self)
792 {
793   ClutterActorIter iter;
794   ClutterActor *child;
795
796   /* we don't do a recursive show_all(), to maintain the old
797    * invariants from ClutterGroup
798    */
799   clutter_actor_iter_init (&iter, self);
800   while (clutter_actor_iter_next (&iter, &child))
801     clutter_actor_show (child);
802
803   clutter_actor_show (self);
804 }
805
806 static void
807 clutter_stage_show (ClutterActor *self)
808 {
809   ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
810
811   CLUTTER_ACTOR_CLASS (clutter_stage_parent_class)->show (self);
812
813   /* Possibly do an allocation run so that the stage will have the
814      right size before we map it */
815   _clutter_stage_maybe_relayout (self);
816
817   g_assert (priv->impl != NULL);
818   _clutter_stage_window_show (priv->impl, TRUE);
819 }
820
821 static void
822 clutter_stage_hide_all (ClutterActor *self)
823 {
824   ClutterActorIter iter;
825   ClutterActor *child;
826
827   clutter_actor_hide (self);
828
829   /* we don't do a recursive hide_all(), to maintain the old invariants
830    * from ClutterGroup
831    */
832   clutter_actor_iter_init (&iter, self);
833   while (clutter_actor_iter_next (&iter, &child))
834     clutter_actor_hide (child);
835 }
836
837 static void
838 clutter_stage_hide (ClutterActor *self)
839 {
840   ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
841
842   g_assert (priv->impl != NULL);
843   _clutter_stage_window_hide (priv->impl);
844
845   CLUTTER_ACTOR_CLASS (clutter_stage_parent_class)->hide (self);
846 }
847
848 static void
849 clutter_stage_emit_key_focus_event (ClutterStage *stage,
850                                     gboolean      focus_in)
851 {
852   ClutterStagePrivate *priv = stage->priv;
853
854   if (priv->key_focused_actor == NULL)
855     return;
856
857   if (focus_in)
858     g_signal_emit_by_name (priv->key_focused_actor, "key-focus-in");
859   else
860     g_signal_emit_by_name (priv->key_focused_actor, "key-focus-out");
861
862   g_object_notify (G_OBJECT (stage), "key-focus");
863 }
864
865 static void
866 clutter_stage_real_activate (ClutterStage *stage)
867 {
868   clutter_stage_emit_key_focus_event (stage, TRUE);
869 }
870
871 static void
872 clutter_stage_real_deactivate (ClutterStage *stage)
873 {
874   clutter_stage_emit_key_focus_event (stage, FALSE);
875 }
876
877 static void
878 clutter_stage_real_fullscreen (ClutterStage *stage)
879 {
880   ClutterStagePrivate *priv = stage->priv;
881   cairo_rectangle_int_t geom;
882   ClutterActorBox box;
883
884   /* we need to force an allocation here because the size
885    * of the stage might have been changed by the backend
886    *
887    * this is a really bad solution to the issues caused by
888    * the fact that fullscreening the stage on the X11 backends
889    * is really an asynchronous operation
890    */
891   _clutter_stage_window_get_geometry (priv->impl, &geom);
892
893   box.x1 = 0;
894   box.y1 = 0;
895   box.x2 = geom.width;
896   box.y2 = geom.height;
897
898   /* we need to blow the caching on the Stage size, given that
899    * we're about to force an allocation, because if anything
900    * ends up querying the size of the stage during the allocate()
901    * call, like constraints or signal handlers, we'll get into an
902    * inconsistent state: the stage will report the old cached size,
903    * but the allocation will be updated anyway.
904    */
905   clutter_actor_set_size (CLUTTER_ACTOR (stage), -1.0, -1.0);
906   clutter_actor_allocate (CLUTTER_ACTOR (stage),
907                           &box,
908                           CLUTTER_ALLOCATION_NONE);
909 }
910
911 void
912 _clutter_stage_queue_event (ClutterStage *stage,
913                             ClutterEvent *event)
914 {
915   ClutterStagePrivate *priv;
916   gboolean first_event;
917   ClutterInputDevice *device;
918
919   g_return_if_fail (CLUTTER_IS_STAGE (stage));
920
921   priv = stage->priv;
922
923   first_event = priv->event_queue->length == 0;
924
925   g_queue_push_tail (priv->event_queue, clutter_event_copy (event));
926
927   if (first_event)
928     {
929       ClutterMasterClock *master_clock = _clutter_master_clock_get_default ();
930       _clutter_master_clock_start_running (master_clock);
931     }
932
933   /* if needed, update the state of the input device of the event.
934    * we do it here to avoid calling the same code from every backend
935    * event processing function
936    */
937   device = clutter_event_get_device (event);
938   if (device != NULL)
939     {
940       ClutterModifierType event_state = clutter_event_get_state (event);
941       guint32 event_time = clutter_event_get_time (event);
942       gfloat event_x, event_y;
943
944       clutter_event_get_coords (event, &event_x, &event_y);
945
946       _clutter_input_device_set_coords (device, event_x, event_y);
947       _clutter_input_device_set_state (device, event_state);
948       _clutter_input_device_set_time (device, event_time);
949     }
950 }
951
952 gboolean
953 _clutter_stage_has_queued_events (ClutterStage *stage)
954 {
955   ClutterStagePrivate *priv;
956
957   g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE);
958
959   priv = stage->priv;
960
961   return priv->event_queue->length > 0;
962 }
963
964 void
965 _clutter_stage_process_queued_events (ClutterStage *stage)
966 {
967   ClutterStagePrivate *priv;
968   GList *events, *l;
969
970   g_return_if_fail (CLUTTER_IS_STAGE (stage));
971
972   priv = stage->priv;
973
974   if (priv->event_queue->length == 0)
975     return;
976
977   /* In case the stage gets destroyed during event processing */
978   g_object_ref (stage);
979
980   /* Steal events before starting processing to avoid reentrancy
981    * issues */
982   events = priv->event_queue->head;
983   priv->event_queue->head =  NULL;
984   priv->event_queue->tail = NULL;
985   priv->event_queue->length = 0;
986
987   for (l = events; l != NULL; l = l->next)
988     {
989       ClutterEvent *event;
990       ClutterEvent *next_event;
991       ClutterInputDevice *device;
992       ClutterInputDevice *next_device;
993       gboolean check_device = FALSE;
994
995       event = l->data;
996       next_event = l->next ? l->next->data : NULL;
997
998       device = clutter_event_get_device (event);
999
1000       if (next_event != NULL)
1001         next_device = clutter_event_get_device (next_event);
1002       else
1003         next_device = NULL;
1004
1005       if (device != NULL && next_device != NULL)
1006         check_device = TRUE;
1007
1008       /* Skip consecutive motion events coming from the same device */
1009       if (priv->throttle_motion_events &&
1010           next_event != NULL &&
1011           event->type == CLUTTER_MOTION &&
1012           (next_event->type == CLUTTER_MOTION ||
1013            next_event->type == CLUTTER_LEAVE) &&
1014           (!check_device || (device == next_device)))
1015         {
1016           CLUTTER_NOTE (EVENT,
1017                         "Omitting motion event at %d, %d",
1018                         (int) event->motion.x,
1019                         (int) event->motion.y);
1020           goto next_event;
1021         }
1022
1023       _clutter_process_event (event);
1024
1025     next_event:
1026       clutter_event_free (event);
1027     }
1028
1029   g_list_free (events);
1030
1031   g_object_unref (stage);
1032 }
1033
1034 /**
1035  * _clutter_stage_needs_update:
1036  * @stage: A #ClutterStage
1037  *
1038  * Determines if _clutter_stage_do_update() needs to be called.
1039  *
1040  * Return value: %TRUE if the stage need layout or painting
1041  */
1042 gboolean
1043 _clutter_stage_needs_update (ClutterStage *stage)
1044 {
1045   ClutterStagePrivate *priv;
1046
1047   g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE);
1048
1049   priv = stage->priv;
1050
1051   return priv->relayout_pending || priv->redraw_pending;
1052 }
1053
1054 void
1055 _clutter_stage_maybe_relayout (ClutterActor *actor)
1056 {
1057   ClutterStage *stage = CLUTTER_STAGE (actor);
1058   ClutterStagePrivate *priv = stage->priv;
1059   gfloat natural_width, natural_height;
1060   ClutterActorBox box = { 0, };
1061   CLUTTER_STATIC_TIMER (relayout_timer,
1062                         "Mainloop", /* no parent */
1063                         "Layouting",
1064                         "The time spent reallocating the stage",
1065                         0 /* no application private data */);
1066
1067   if (!priv->relayout_pending)
1068     return;
1069
1070   /* avoid reentrancy */
1071   if (!CLUTTER_ACTOR_IN_RELAYOUT (stage))
1072     {
1073       priv->relayout_pending = FALSE;
1074
1075       CLUTTER_TIMER_START (_clutter_uprof_context, relayout_timer);
1076       CLUTTER_NOTE (ACTOR, "Recomputing layout");
1077
1078       CLUTTER_SET_PRIVATE_FLAGS (stage, CLUTTER_IN_RELAYOUT);
1079
1080       natural_width = natural_height = 0;
1081       clutter_actor_get_preferred_size (CLUTTER_ACTOR (stage),
1082                                         NULL, NULL,
1083                                         &natural_width, &natural_height);
1084
1085       box.x1 = 0;
1086       box.y1 = 0;
1087       box.x2 = natural_width;
1088       box.y2 = natural_height;
1089
1090       CLUTTER_NOTE (ACTOR, "Allocating (0, 0 - %d, %d) for the stage",
1091                     (int) natural_width,
1092                     (int) natural_height);
1093
1094       clutter_actor_allocate (CLUTTER_ACTOR (stage),
1095                               &box, CLUTTER_ALLOCATION_NONE);
1096
1097       CLUTTER_UNSET_PRIVATE_FLAGS (stage, CLUTTER_IN_RELAYOUT);
1098       CLUTTER_TIMER_STOP (_clutter_uprof_context, relayout_timer);
1099     }
1100 }
1101
1102 static gboolean
1103 _clutter_stage_get_pick_buffer_valid (ClutterStage *stage, ClutterPickMode mode)
1104 {
1105   g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE);
1106
1107   if (stage->priv->pick_buffer_mode != mode)
1108     return FALSE;
1109
1110   return stage->priv->have_valid_pick_buffer;
1111 }
1112
1113 static void
1114 _clutter_stage_set_pick_buffer_valid (ClutterStage   *stage,
1115                                       gboolean        valid,
1116                                       ClutterPickMode mode)
1117 {
1118   g_return_if_fail (CLUTTER_IS_STAGE (stage));
1119
1120   stage->priv->have_valid_pick_buffer = !!valid;
1121   stage->priv->pick_buffer_mode = mode;
1122 }
1123
1124 static void
1125 clutter_stage_do_redraw (ClutterStage *stage)
1126 {
1127   ClutterBackend *backend = clutter_get_default_backend ();
1128   ClutterActor *actor = CLUTTER_ACTOR (stage);
1129   ClutterStagePrivate *priv = stage->priv;
1130
1131   CLUTTER_STATIC_COUNTER (redraw_counter,
1132                           "clutter_stage_do_redraw counter",
1133                           "Increments for each Stage redraw",
1134                           0 /* no application private data */);
1135   CLUTTER_STATIC_TIMER (redraw_timer,
1136                         "Master Clock", /* parent */
1137                         "Redrawing",
1138                         "The time spent redrawing everything",
1139                         0 /* no application private data */);
1140
1141   if (CLUTTER_ACTOR_IN_DESTRUCTION (stage))
1142     return;
1143
1144   if (priv->impl == NULL)
1145     return;
1146
1147   CLUTTER_NOTE (PAINT, "Redraw started for stage '%s'[%p]",
1148                 _clutter_actor_get_debug_name (actor),
1149                 stage);
1150
1151   _clutter_stage_set_pick_buffer_valid (stage, FALSE, -1);
1152   priv->picks_per_frame = 0;
1153
1154   _clutter_backend_ensure_context (backend, stage);
1155
1156   if (_clutter_context_get_show_fps ())
1157     {
1158       if (priv->fps_timer == NULL)
1159         priv->fps_timer = g_timer_new ();
1160     }
1161
1162   _clutter_stage_maybe_setup_viewport (stage);
1163
1164   CLUTTER_COUNTER_INC (_clutter_uprof_context, redraw_counter);
1165   CLUTTER_TIMER_START (_clutter_uprof_context, redraw_timer);
1166
1167   _clutter_stage_window_redraw (priv->impl);
1168
1169   CLUTTER_TIMER_STOP (_clutter_uprof_context, redraw_timer);
1170
1171   if (_clutter_context_get_show_fps ())
1172     {
1173       priv->timer_n_frames += 1;
1174
1175       if (g_timer_elapsed (priv->fps_timer, NULL) >= 1.0)
1176         {
1177           g_print ("*** FPS for %s: %i ***\n",
1178                    _clutter_actor_get_debug_name (actor),
1179                    priv->timer_n_frames);
1180
1181           priv->timer_n_frames = 0;
1182           g_timer_start (priv->fps_timer);
1183         }
1184     }
1185
1186   CLUTTER_NOTE (PAINT, "Redraw finished for stage '%s'[%p]",
1187                 _clutter_actor_get_debug_name (actor),
1188                 stage);
1189 }
1190
1191 /**
1192  * _clutter_stage_do_update:
1193  * @stage: A #ClutterStage
1194  *
1195  * Handles per-frame layout and repaint for the stage.
1196  *
1197  * Return value: %TRUE if the stage was updated
1198  */
1199 gboolean
1200 _clutter_stage_do_update (ClutterStage *stage)
1201 {
1202   ClutterStagePrivate *priv = stage->priv;
1203
1204   /* if the stage is being destroyed, or if the destruction already
1205    * happened and we don't have an StageWindow any more, then we
1206    * should bail out
1207    */
1208   if (CLUTTER_ACTOR_IN_DESTRUCTION (stage) || priv->impl == NULL)
1209     return FALSE;
1210
1211   if (!CLUTTER_ACTOR_IS_REALIZED (stage))
1212     return FALSE;
1213
1214   /* NB: We need to ensure we have an up to date layout *before* we
1215    * check or clear the pending redraws flag since a relayout may
1216    * queue a redraw.
1217    */
1218   _clutter_stage_maybe_relayout (CLUTTER_ACTOR (stage));
1219
1220   if (!priv->redraw_pending)
1221     return FALSE;
1222
1223   _clutter_stage_maybe_finish_queue_redraws (stage);
1224
1225   clutter_stage_do_redraw (stage);
1226
1227   /* reset the guard, so that new redraws are possible */
1228   priv->redraw_pending = FALSE;
1229
1230 #ifdef CLUTTER_ENABLE_DEBUG
1231   if (priv->redraw_count > 0)
1232     {
1233       CLUTTER_NOTE (SCHEDULER, "Queued %lu redraws during the last cycle",
1234                     priv->redraw_count);
1235
1236       priv->redraw_count = 0;
1237     }
1238 #endif /* CLUTTER_ENABLE_DEBUG */
1239
1240   return TRUE;
1241 }
1242
1243 static void
1244 clutter_stage_real_queue_relayout (ClutterActor *self)
1245 {
1246   ClutterStage *stage = CLUTTER_STAGE (self);
1247   ClutterStagePrivate *priv = stage->priv;
1248   ClutterActorClass *parent_class;
1249
1250   priv->relayout_pending = TRUE;
1251
1252   /* chain up */
1253   parent_class = CLUTTER_ACTOR_CLASS (clutter_stage_parent_class);
1254   parent_class->queue_relayout (self);
1255 }
1256
1257 static void
1258 clutter_stage_real_queue_redraw (ClutterActor *actor,
1259                                  ClutterActor *leaf)
1260 {
1261   ClutterStage *stage = CLUTTER_STAGE (actor);
1262   ClutterStageWindow *stage_window;
1263   ClutterPaintVolume *redraw_clip;
1264   ClutterActorBox bounding_box;
1265   ClutterActorBox intersection_box;
1266   cairo_rectangle_int_t geom, stage_clip;
1267
1268   if (CLUTTER_ACTOR_IN_DESTRUCTION (actor))
1269     return;
1270
1271   /* If the backend can't do anything with redraw clips (e.g. it already knows
1272    * it needs to redraw everything anyway) then don't spend time transforming
1273    * any clip volume into stage coordinates... */
1274   stage_window = _clutter_stage_get_window (stage);
1275   if (stage_window == NULL)
1276     return;
1277
1278   if (_clutter_stage_window_ignoring_redraw_clips (stage_window))
1279     {
1280       _clutter_stage_window_add_redraw_clip (stage_window, NULL);
1281       return;
1282     }
1283
1284   /* Convert the clip volume into stage coordinates and then into an
1285    * axis aligned stage coordinates bounding box...
1286    */
1287   redraw_clip = _clutter_actor_get_queue_redraw_clip (leaf);
1288   if (redraw_clip == NULL)
1289     {
1290       _clutter_stage_window_add_redraw_clip (stage_window, NULL);
1291       return;
1292     }
1293
1294   _clutter_paint_volume_get_stage_paint_box (redraw_clip,
1295                                              stage,
1296                                              &bounding_box);
1297
1298   _clutter_stage_window_get_geometry (stage_window, &geom);
1299
1300   intersection_box.x1 = MAX (bounding_box.x1, 0);
1301   intersection_box.y1 = MAX (bounding_box.y1, 0);
1302   intersection_box.x2 = MIN (bounding_box.x2, geom.width);
1303   intersection_box.y2 = MIN (bounding_box.y2, geom.height);
1304
1305   /* There is no need to track degenerate/empty redraw clips */
1306   if (intersection_box.x2 <= intersection_box.x1 ||
1307       intersection_box.y2 <= intersection_box.y1)
1308     return;
1309
1310   /* when converting to integer coordinates make sure we round the edges of the
1311    * clip rectangle outwards... */
1312   stage_clip.x = intersection_box.x1;
1313   stage_clip.y = intersection_box.y1;
1314   stage_clip.width = intersection_box.x2 - stage_clip.x;
1315   stage_clip.height = intersection_box.y2 - stage_clip.y;
1316
1317   _clutter_stage_window_add_redraw_clip (stage_window, &stage_clip);
1318 }
1319
1320 gboolean
1321 _clutter_stage_has_full_redraw_queued (ClutterStage *stage)
1322 {
1323   ClutterStageWindow *stage_window = _clutter_stage_get_window (stage);
1324
1325   if (CLUTTER_ACTOR_IN_DESTRUCTION (stage) || stage_window == NULL)
1326     return FALSE;
1327
1328   if (stage->priv->redraw_pending &&
1329       !_clutter_stage_window_has_redraw_clips (stage_window))
1330     return TRUE;
1331   else
1332     return FALSE;
1333 }
1334
1335 /**
1336  * clutter_stage_get_redraw_clip_bounds:
1337  * @stage: A #ClutterStage
1338  * @clip: (out caller-allocates): Return location for the clip bounds
1339  *
1340  * Gets the bounds of the current redraw for @stage in stage pixel
1341  * coordinates. E.g., if only a single actor has queued a redraw then
1342  * Clutter may redraw the stage with a clip so that it doesn't have to
1343  * paint every pixel in the stage. This function would then return the
1344  * bounds of that clip. An application can use this information to
1345  * avoid some extra work if it knows that some regions of the stage
1346  * aren't going to be painted. This should only be called while the
1347  * stage is being painted. If there is no current redraw clip then
1348  * this function will set @clip to the full extents of the stage.
1349  *
1350  * Since: 1.8
1351  */
1352 void
1353 clutter_stage_get_redraw_clip_bounds (ClutterStage          *stage,
1354                                       cairo_rectangle_int_t *clip)
1355 {
1356   ClutterStagePrivate *priv;
1357
1358   g_return_if_fail (CLUTTER_IS_STAGE (stage));
1359   g_return_if_fail (clip != NULL);
1360
1361   priv = stage->priv;
1362
1363   if (!_clutter_stage_window_get_redraw_clip_bounds (priv->impl, clip))
1364     {
1365       /* Set clip to the full extents of the stage */
1366       _clutter_stage_window_get_geometry (priv->impl, clip);
1367     }
1368 }
1369
1370 static void
1371 read_pixels_to_file (char *filename_stem,
1372                      int   x,
1373                      int   y,
1374                      int   width,
1375                      int   height)
1376 {
1377   guint8 *data;
1378   cairo_surface_t *surface;
1379   static int read_count = 0;
1380   char *filename = g_strdup_printf ("%s-%05d.png",
1381                                     filename_stem,
1382                                     read_count);
1383
1384   data = g_malloc (4 * width * height);
1385   cogl_read_pixels (x, y, width, height,
1386                     COGL_READ_PIXELS_COLOR_BUFFER,
1387                     CLUTTER_CAIRO_FORMAT_ARGB32,
1388                     data);
1389
1390   surface = cairo_image_surface_create_for_data (data, CAIRO_FORMAT_RGB24,
1391                                                  width, height,
1392                                                  width * 4);
1393
1394   cairo_surface_write_to_png (surface, filename);
1395   cairo_surface_destroy (surface);
1396
1397   g_free (data);
1398   g_free (filename);
1399
1400   read_count++;
1401 }
1402
1403 ClutterActor *
1404 _clutter_stage_do_pick (ClutterStage   *stage,
1405                         gint            x,
1406                         gint            y,
1407                         ClutterPickMode mode)
1408 {
1409   ClutterStagePrivate *priv;
1410   ClutterMainContext *context;
1411   guchar pixel[4] = { 0xff, 0xff, 0xff, 0xff };
1412   CoglColor stage_pick_id;
1413   gboolean dither_enabled_save;
1414   CoglFramebuffer *fb;
1415   ClutterActor *actor;
1416   gboolean is_clipped;
1417   CLUTTER_STATIC_COUNTER (do_pick_counter,
1418                           "_clutter_stage_do_pick counter",
1419                           "Increments for each full pick run",
1420                           0 /* no application private data */);
1421   CLUTTER_STATIC_TIMER (pick_timer,
1422                         "Mainloop", /* parent */
1423                         "Picking",
1424                         "The time spent picking",
1425                         0 /* no application private data */);
1426   CLUTTER_STATIC_TIMER (pick_clear,
1427                         "Picking", /* parent */
1428                         "Stage clear (pick)",
1429                         "The time spent clearing stage for picking",
1430                         0 /* no application private data */);
1431   CLUTTER_STATIC_TIMER (pick_paint,
1432                         "Picking", /* parent */
1433                         "Painting actors (pick mode)",
1434                         "The time spent painting actors in pick mode",
1435                         0 /* no application private data */);
1436   CLUTTER_STATIC_TIMER (pick_read,
1437                         "Picking", /* parent */
1438                         "Read Pixels",
1439                         "The time spent issuing a read pixels",
1440                         0 /* no application private data */);
1441
1442   g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL);
1443
1444   priv = stage->priv;
1445
1446   if (G_UNLIKELY (clutter_pick_debug_flags & CLUTTER_DEBUG_NOP_PICKING))
1447     return CLUTTER_ACTOR (stage);
1448
1449 #ifdef CLUTTER_ENABLE_PROFILE
1450   if (clutter_profile_flags & CLUTTER_PROFILE_PICKING_ONLY)
1451     _clutter_profile_resume ();
1452 #endif /* CLUTTER_ENABLE_PROFILE */
1453
1454   CLUTTER_COUNTER_INC (_clutter_uprof_context, do_pick_counter);
1455   CLUTTER_TIMER_START (_clutter_uprof_context, pick_timer);
1456
1457   context = _clutter_context_get_default ();
1458   clutter_stage_ensure_current (stage);
1459
1460   /* It's possible that we currently have a static scene and have renderered a
1461    * full, unclipped pick buffer. If so we can simply continue to read from
1462    * this cached buffer until the scene next changes. */
1463   if (_clutter_stage_get_pick_buffer_valid (stage, mode))
1464     {
1465       CLUTTER_TIMER_START (_clutter_uprof_context, pick_read);
1466       cogl_read_pixels (x, y, 1, 1,
1467                         COGL_READ_PIXELS_COLOR_BUFFER,
1468                         COGL_PIXEL_FORMAT_RGBA_8888_PRE,
1469                         pixel);
1470       CLUTTER_TIMER_STOP (_clutter_uprof_context, pick_read);
1471
1472       CLUTTER_NOTE (PICK, "Reusing pick buffer from previous render to fetch "
1473                     "actor at %i,%i", x, y);
1474
1475       goto check_pixel;
1476     }
1477
1478   priv->picks_per_frame++;
1479
1480   _clutter_backend_ensure_context (context->backend, stage);
1481
1482   /* needed for when a context switch happens */
1483   _clutter_stage_maybe_setup_viewport (stage);
1484
1485   /* If we are seeing multiple picks per frame that means the scene is static
1486    * so we promote to doing a non-scissored pick render so that all subsequent
1487    * picks for the same static scene won't require additional renders */
1488   if (priv->picks_per_frame < 2)
1489     {
1490       if (G_LIKELY (!(clutter_pick_debug_flags &
1491                       CLUTTER_DEBUG_DUMP_PICK_BUFFERS)))
1492         cogl_clip_push_window_rectangle (x, y, 1, 1);
1493       is_clipped = TRUE;
1494     }
1495   else
1496     is_clipped = FALSE;
1497
1498   CLUTTER_NOTE (PICK, "Performing %s pick at %i,%i",
1499                 is_clipped ? "clippped" : "full", x, y);
1500
1501   cogl_color_init_from_4ub (&stage_pick_id, 255, 255, 255, 255);
1502   CLUTTER_TIMER_START (_clutter_uprof_context, pick_clear);
1503   cogl_clear (&stage_pick_id,
1504               COGL_BUFFER_BIT_COLOR |
1505               COGL_BUFFER_BIT_DEPTH);
1506   CLUTTER_TIMER_STOP (_clutter_uprof_context, pick_clear);
1507
1508   /* Disable dithering (if any) when doing the painting in pick mode */
1509   fb = cogl_get_draw_framebuffer ();
1510   dither_enabled_save = cogl_framebuffer_get_dither_enabled (fb);
1511   cogl_framebuffer_set_dither_enabled (fb, FALSE);
1512
1513   /* Render the entire scence in pick mode - just single colored silhouette's
1514    * are drawn offscreen (as we never swap buffers)
1515   */
1516   CLUTTER_TIMER_START (_clutter_uprof_context, pick_paint);
1517   context->pick_mode = mode;
1518   _clutter_stage_do_paint (stage, NULL);
1519   context->pick_mode = CLUTTER_PICK_NONE;
1520   CLUTTER_TIMER_STOP (_clutter_uprof_context, pick_paint);
1521
1522   if (is_clipped)
1523     {
1524       if (G_LIKELY (!(clutter_pick_debug_flags &
1525                       CLUTTER_DEBUG_DUMP_PICK_BUFFERS)))
1526         cogl_clip_pop ();
1527
1528       _clutter_stage_set_pick_buffer_valid (stage, FALSE, -1);
1529     }
1530   else
1531     _clutter_stage_set_pick_buffer_valid (stage, TRUE, mode);
1532
1533   /* Read the color of the screen co-ords pixel. RGBA_8888_PRE is used
1534      even though we don't care about the alpha component because under
1535      GLES this is the only format that is guaranteed to work so Cogl
1536      will end up having to do a conversion if any other format is
1537      used. The format is requested as pre-multiplied because Cogl
1538      assumes that all pixels in the framebuffer are premultiplied so
1539      it avoids a conversion. */
1540   CLUTTER_TIMER_START (_clutter_uprof_context, pick_read);
1541   cogl_read_pixels (x, y, 1, 1,
1542                     COGL_READ_PIXELS_COLOR_BUFFER,
1543                     COGL_PIXEL_FORMAT_RGBA_8888_PRE,
1544                     pixel);
1545   CLUTTER_TIMER_STOP (_clutter_uprof_context, pick_read);
1546
1547   if (G_UNLIKELY (clutter_pick_debug_flags & CLUTTER_DEBUG_DUMP_PICK_BUFFERS))
1548     {
1549       char *file_name =
1550         g_strconcat ("pick-buffer-",
1551                      _clutter_actor_get_debug_name (CLUTTER_ACTOR (stage)),
1552                      NULL);
1553
1554       read_pixels_to_file (file_name, 0, 0,
1555                            clutter_actor_get_width (CLUTTER_ACTOR (stage)),
1556                            clutter_actor_get_height (CLUTTER_ACTOR (stage)));
1557
1558       g_free (file_name);
1559     }
1560
1561   /* Restore whether GL_DITHER was enabled */
1562   cogl_framebuffer_set_dither_enabled (fb, dither_enabled_save);
1563
1564 check_pixel:
1565   if (pixel[0] == 0xff && pixel[1] == 0xff && pixel[2] == 0xff)
1566     {
1567       actor = CLUTTER_ACTOR (stage);
1568     }
1569   else
1570     {
1571       guint32 id_ = _clutter_pixel_to_id (pixel);
1572
1573       actor = _clutter_get_actor_by_id (stage, id_);
1574     }
1575
1576   CLUTTER_TIMER_STOP (_clutter_uprof_context, pick_timer);
1577
1578 #ifdef CLUTTER_ENABLE_PROFILE
1579   if (clutter_profile_flags & CLUTTER_PROFILE_PICKING_ONLY)
1580     _clutter_profile_suspend ();
1581 #endif
1582
1583   return actor;
1584 }
1585
1586
1587
1588 static gboolean
1589 clutter_stage_real_delete_event (ClutterStage *stage,
1590                                  ClutterEvent *event)
1591 {
1592   if (stage_is_default (stage))
1593     clutter_main_quit ();
1594   else
1595     clutter_actor_destroy (CLUTTER_ACTOR (stage));
1596
1597   return TRUE;
1598 }
1599
1600 static void
1601 clutter_stage_real_apply_transform (ClutterActor *stage,
1602                                     CoglMatrix   *matrix)
1603 {
1604   ClutterStagePrivate *priv = CLUTTER_STAGE (stage)->priv;
1605
1606   /* FIXME: we probably shouldn't be explicitly reseting the matrix
1607    * here... */
1608   cogl_matrix_init_identity (matrix);
1609   cogl_matrix_multiply (matrix, matrix, &priv->view);
1610 }
1611
1612 static void
1613 clutter_stage_constructed (GObject *gobject)
1614 {
1615   ClutterStage *self = CLUTTER_STAGE (gobject);
1616   ClutterStageManager *stage_manager;
1617
1618   stage_manager = clutter_stage_manager_get_default ();
1619
1620   /* this will take care to sinking the floating reference */
1621   _clutter_stage_manager_add_stage (stage_manager, self);
1622
1623   /* if this stage has been created on a backend that does not
1624    * support multiple stages then it becomes the default stage
1625    * as well; any other attempt at creating a ClutterStage will
1626    * fail.
1627    */
1628   if (!clutter_feature_available (CLUTTER_FEATURE_STAGE_MULTIPLE))
1629     {
1630       if (G_UNLIKELY (clutter_stage_manager_get_default_stage (stage_manager) != NULL))
1631         {
1632           g_error ("Unable to create another stage: the backend of "
1633                    "type '%s' does not support multiple stages. Use "
1634                    "clutter_stage_manager_get_default_stage() instead "
1635                    "to access the stage singleton.",
1636                    G_OBJECT_TYPE_NAME (clutter_get_default_backend ()));
1637         }
1638
1639       _clutter_stage_manager_set_default_stage (stage_manager, self);
1640     }
1641
1642   G_OBJECT_CLASS (clutter_stage_parent_class)->constructed (gobject);
1643 }
1644
1645 static void
1646 clutter_stage_set_property (GObject      *object,
1647                             guint         prop_id,
1648                             const GValue *value,
1649                             GParamSpec   *pspec)
1650 {
1651   ClutterStage *stage = CLUTTER_STAGE (object);
1652
1653   switch (prop_id)
1654     {
1655     case PROP_COLOR:
1656       clutter_actor_set_background_color (CLUTTER_ACTOR (stage),
1657                                           clutter_value_get_color (value));
1658       break;
1659
1660     case PROP_OFFSCREEN:
1661       if (g_value_get_boolean (value))
1662         g_warning ("Offscreen stages are currently not supported\n");
1663       break;
1664
1665     case PROP_CURSOR_VISIBLE:
1666       if (g_value_get_boolean (value))
1667         clutter_stage_show_cursor (stage);
1668       else
1669         clutter_stage_hide_cursor (stage);
1670       break;
1671
1672     case PROP_PERSPECTIVE:
1673       clutter_stage_set_perspective (stage, g_value_get_boxed (value));
1674       break;
1675
1676     case PROP_TITLE:
1677       clutter_stage_set_title (stage, g_value_get_string (value));
1678       break;
1679
1680     case PROP_USER_RESIZABLE:
1681       clutter_stage_set_user_resizable (stage, g_value_get_boolean (value));
1682       break;
1683
1684     case PROP_USE_FOG:
1685       clutter_stage_set_use_fog (stage, g_value_get_boolean (value));
1686       break;
1687
1688     case PROP_FOG:
1689       clutter_stage_set_fog (stage, g_value_get_boxed (value));
1690       break;
1691
1692     case PROP_USE_ALPHA:
1693       clutter_stage_set_use_alpha (stage, g_value_get_boolean (value));
1694       break;
1695
1696     case PROP_KEY_FOCUS:
1697       clutter_stage_set_key_focus (stage, g_value_get_object (value));
1698       break;
1699
1700     case PROP_NO_CLEAR_HINT:
1701       clutter_stage_set_no_clear_hint (stage, g_value_get_boolean (value));
1702       break;
1703
1704     case PROP_ACCEPT_FOCUS:
1705       clutter_stage_set_accept_focus (stage, g_value_get_boolean (value));
1706       break;
1707
1708     default:
1709       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1710       break;
1711   }
1712 }
1713
1714 static void
1715 clutter_stage_get_property (GObject    *gobject,
1716                             guint       prop_id,
1717                             GValue     *value,
1718                             GParamSpec *pspec)
1719 {
1720   ClutterStagePrivate *priv = CLUTTER_STAGE (gobject)->priv;
1721
1722   switch (prop_id)
1723     {
1724     case PROP_COLOR:
1725       {
1726         ClutterColor bg_color;
1727
1728         clutter_actor_get_background_color (CLUTTER_ACTOR (gobject),
1729                                             &bg_color);
1730         clutter_value_set_color (value, &bg_color);
1731       }
1732       break;
1733
1734     case PROP_OFFSCREEN:
1735       g_value_set_boolean (value, FALSE);
1736       break;
1737
1738     case PROP_FULLSCREEN_SET:
1739       g_value_set_boolean (value, priv->is_fullscreen);
1740       break;
1741
1742     case PROP_CURSOR_VISIBLE:
1743       g_value_set_boolean (value, priv->is_cursor_visible);
1744       break;
1745
1746     case PROP_PERSPECTIVE:
1747       g_value_set_boxed (value, &priv->perspective);
1748       break;
1749
1750     case PROP_TITLE:
1751       g_value_set_string (value, priv->title);
1752       break;
1753
1754     case PROP_USER_RESIZABLE:
1755       g_value_set_boolean (value, priv->is_user_resizable);
1756       break;
1757
1758     case PROP_USE_FOG:
1759       g_value_set_boolean (value, priv->use_fog);
1760       break;
1761
1762     case PROP_FOG:
1763       g_value_set_boxed (value, &priv->fog);
1764       break;
1765
1766     case PROP_USE_ALPHA:
1767       g_value_set_boolean (value, priv->use_alpha);
1768       break;
1769
1770     case PROP_KEY_FOCUS:
1771       g_value_set_object (value, priv->key_focused_actor);
1772       break;
1773
1774     case PROP_NO_CLEAR_HINT:
1775       {
1776         gboolean hint =
1777           (priv->stage_hints & CLUTTER_STAGE_NO_CLEAR_ON_PAINT) != 0;
1778
1779         g_value_set_boolean (value, hint);
1780       }
1781       break;
1782
1783     case PROP_ACCEPT_FOCUS:
1784       g_value_set_boolean (value, priv->accept_focus);
1785       break;
1786
1787     default:
1788       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
1789       break;
1790     }
1791 }
1792
1793 static void
1794 clutter_stage_dispose (GObject *object)
1795 {
1796   ClutterStage        *stage = CLUTTER_STAGE (object);
1797   ClutterStagePrivate *priv = stage->priv;
1798   ClutterStageManager *stage_manager;
1799
1800   clutter_actor_hide (CLUTTER_ACTOR (object));
1801
1802   /* remove_stage() will unref() the stage instance, so we need to
1803    * add a reference here to keep it temporarily alive
1804    */
1805   g_object_ref (object);
1806   stage_manager = clutter_stage_manager_get_default ();
1807   _clutter_stage_manager_remove_stage (stage_manager, stage);
1808
1809   _clutter_clear_events_queue_for_stage (stage);
1810
1811   if (priv->impl != NULL)
1812     {
1813       CLUTTER_NOTE (BACKEND, "Disposing of the stage implementation");
1814
1815       if (CLUTTER_ACTOR_IS_REALIZED (object))
1816         _clutter_stage_window_unrealize (priv->impl);
1817
1818       g_object_unref (priv->impl);
1819       priv->impl = NULL;
1820     }
1821
1822   clutter_actor_remove_all_children (CLUTTER_ACTOR (object));
1823
1824   G_OBJECT_CLASS (clutter_stage_parent_class)->dispose (object);
1825 }
1826
1827 static void
1828 clutter_stage_finalize (GObject *object)
1829 {
1830   ClutterStage *stage = CLUTTER_STAGE (object);
1831   ClutterStagePrivate *priv = stage->priv;
1832
1833   g_queue_foreach (priv->event_queue, (GFunc) clutter_event_free, NULL);
1834   g_queue_free (priv->event_queue);
1835
1836   g_free (priv->title);
1837
1838   g_array_free (priv->paint_volume_stack, TRUE);
1839
1840   g_hash_table_destroy (priv->devices);
1841
1842   _clutter_id_pool_free (priv->pick_id_pool);
1843
1844   if (priv->fps_timer != NULL)
1845     g_timer_destroy (priv->fps_timer);
1846
1847   G_OBJECT_CLASS (clutter_stage_parent_class)->finalize (object);
1848 }
1849
1850 static void
1851 clutter_stage_class_init (ClutterStageClass *klass)
1852 {
1853   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
1854   ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
1855   GParamSpec *pspec;
1856
1857   gobject_class->constructed = clutter_stage_constructed;
1858   gobject_class->set_property = clutter_stage_set_property;
1859   gobject_class->get_property = clutter_stage_get_property;
1860   gobject_class->dispose = clutter_stage_dispose;
1861   gobject_class->finalize = clutter_stage_finalize;
1862
1863   actor_class->allocate = clutter_stage_allocate;
1864   actor_class->get_preferred_width = clutter_stage_get_preferred_width;
1865   actor_class->get_preferred_height = clutter_stage_get_preferred_height;
1866   actor_class->paint = clutter_stage_paint;
1867   actor_class->pick = clutter_stage_pick;
1868   actor_class->get_paint_volume = clutter_stage_get_paint_volume;
1869   actor_class->realize = clutter_stage_realize;
1870   actor_class->unrealize = clutter_stage_unrealize;
1871   actor_class->show = clutter_stage_show;
1872   actor_class->show_all = clutter_stage_show_all;
1873   actor_class->hide = clutter_stage_hide;
1874   actor_class->hide_all = clutter_stage_hide_all;
1875   actor_class->queue_relayout = clutter_stage_real_queue_relayout;
1876   actor_class->queue_redraw = clutter_stage_real_queue_redraw;
1877   actor_class->apply_transform = clutter_stage_real_apply_transform;
1878
1879   /**
1880    * ClutterStage:fullscreen:
1881    *
1882    * Whether the stage should be fullscreen or not.
1883    *
1884    * This property is set by calling clutter_stage_set_fullscreen()
1885    * but since the actual implementation is delegated to the backend
1886    * you should connect to the notify::fullscreen-set signal in order
1887    * to get notification if the fullscreen state has been successfully
1888    * achieved.
1889    *
1890    * Since: 1.0
1891    */
1892   pspec = g_param_spec_boolean ("fullscreen-set",
1893                                 P_("Fullscreen Set"),
1894                                 P_("Whether the main stage is fullscreen"),
1895                                 FALSE,
1896                                 CLUTTER_PARAM_READABLE);
1897   g_object_class_install_property (gobject_class,
1898                                    PROP_FULLSCREEN_SET,
1899                                    pspec);
1900   /**
1901    * ClutterStage:offscreen:
1902    *
1903    * Whether the stage should be rendered in an offscreen buffer.
1904    *
1905    * Deprecated: 1.10: This property does not do anything.
1906    */
1907   pspec = g_param_spec_boolean ("offscreen",
1908                                 P_("Offscreen"),
1909                                 P_("Whether the main stage should be rendered offscreen"),
1910                                 FALSE,
1911                                 CLUTTER_PARAM_READWRITE | G_PARAM_DEPRECATED);
1912   g_object_class_install_property (gobject_class,
1913                                    PROP_OFFSCREEN,
1914                                    pspec);
1915   /**
1916    * ClutterStage:cursor-visible:
1917    *
1918    * Whether the mouse pointer should be visible
1919    */
1920   pspec = g_param_spec_boolean ("cursor-visible",
1921                                 P_("Cursor Visible"),
1922                                 P_("Whether the mouse pointer is visible on the main stage"),
1923                                 TRUE,
1924                                 CLUTTER_PARAM_READWRITE);
1925   g_object_class_install_property (gobject_class,
1926                                    PROP_CURSOR_VISIBLE,
1927                                    pspec);
1928   /**
1929    * ClutterStage:user-resizable:
1930    *
1931    * Whether the stage is resizable via user interaction.
1932    *
1933    * Since: 0.4
1934    */
1935   pspec = g_param_spec_boolean ("user-resizable",
1936                                 P_("User Resizable"),
1937                                 P_("Whether the stage is able to be resized via user interaction"),
1938                                 FALSE,
1939                                 CLUTTER_PARAM_READWRITE);
1940   g_object_class_install_property (gobject_class,
1941                                    PROP_USER_RESIZABLE,
1942                                    pspec);
1943   /**
1944    * ClutterStage:color:
1945    *
1946    * The background color of the main stage.
1947    *
1948    * Deprecated: 1.10: Use the #ClutterActor:background-color property of
1949    *   #ClutterActor instead.
1950    */
1951   pspec = clutter_param_spec_color ("color",
1952                                     P_("Color"),
1953                                     P_("The color of the stage"),
1954                                     &default_stage_color,
1955                                     CLUTTER_PARAM_READWRITE |
1956                                     G_PARAM_DEPRECATED);
1957   g_object_class_install_property (gobject_class, PROP_COLOR, pspec);
1958
1959   /**
1960    * ClutterStage:perspective:
1961    *
1962    * The parameters used for the perspective projection from 3D
1963    * coordinates to 2D
1964    *
1965    * Since: 0.8.2
1966    */
1967   pspec = g_param_spec_boxed ("perspective",
1968                               P_("Perspective"),
1969                               P_("Perspective projection parameters"),
1970                               CLUTTER_TYPE_PERSPECTIVE,
1971                               CLUTTER_PARAM_READWRITE);
1972   g_object_class_install_property (gobject_class,
1973                                    PROP_PERSPECTIVE,
1974                                    pspec);
1975
1976   /**
1977    * ClutterStage:title:
1978    *
1979    * The stage's title - usually displayed in stage windows title decorations.
1980    *
1981    * Since: 0.4
1982    */
1983   pspec = g_param_spec_string ("title",
1984                                P_("Title"),
1985                                P_("Stage Title"),
1986                                NULL,
1987                                CLUTTER_PARAM_READWRITE);
1988   g_object_class_install_property (gobject_class, PROP_TITLE, pspec);
1989
1990   /**
1991    * ClutterStage:use-fog:
1992    *
1993    * Whether the stage should use a linear GL "fog" in creating the
1994    * depth-cueing effect, to enhance the perception of depth by fading
1995    * actors farther from the viewpoint.
1996    *
1997    * Since: 0.6
1998    *
1999    * Deprecated: 1.10: This property does not do anything.
2000    */
2001   pspec = g_param_spec_boolean ("use-fog",
2002                                 P_("Use Fog"),
2003                                 P_("Whether to enable depth cueing"),
2004                                 FALSE,
2005                                 CLUTTER_PARAM_READWRITE | G_PARAM_DEPRECATED);
2006   g_object_class_install_property (gobject_class, PROP_USE_FOG, pspec);
2007
2008   /**
2009    * ClutterStage:fog:
2010    *
2011    * The settings for the GL "fog", used only if #ClutterStage:use-fog
2012    * is set to %TRUE
2013    *
2014    * Since: 1.0
2015    *
2016    * Deprecated: 1.10: This property does not do anything.
2017    */
2018   pspec = g_param_spec_boxed ("fog",
2019                               P_("Fog"),
2020                               P_("Settings for the depth cueing"),
2021                               CLUTTER_TYPE_FOG,
2022                               CLUTTER_PARAM_READWRITE | G_PARAM_DEPRECATED);
2023   g_object_class_install_property (gobject_class, PROP_FOG, pspec);
2024
2025   /**
2026    * ClutterStage:use-alpha:
2027    *
2028    * Whether the #ClutterStage should honour the alpha component of the
2029    * #ClutterStage:color property when painting. If Clutter is run under
2030    * a compositing manager this will result in the stage being blended
2031    * with the underlying window(s)
2032    *
2033    * Since: 1.2
2034    */
2035   pspec = g_param_spec_boolean ("use-alpha",
2036                                 P_("Use Alpha"),
2037                                 P_("Whether to honour the alpha component of the stage color"),
2038                                 FALSE,
2039                                 CLUTTER_PARAM_READWRITE);
2040   g_object_class_install_property (gobject_class, PROP_USE_ALPHA, pspec);
2041
2042   /**
2043    * ClutterStage:key-focus:
2044    *
2045    * The #ClutterActor that will receive key events from the underlying
2046    * windowing system.
2047    *
2048    * If %NULL, the #ClutterStage will receive the events.
2049    *
2050    * Since: 1.2
2051    */
2052   pspec = g_param_spec_object ("key-focus",
2053                                P_("Key Focus"),
2054                                P_("The currently key focused actor"),
2055                                CLUTTER_TYPE_ACTOR,
2056                                CLUTTER_PARAM_READWRITE);
2057   g_object_class_install_property (gobject_class, PROP_KEY_FOCUS, pspec);
2058
2059   /**
2060    * ClutterStage:no-clear-hint:
2061    *
2062    * Whether or not the #ClutterStage should clear its contents
2063    * before each paint cycle.
2064    *
2065    * See clutter_stage_set_no_clear_hint() for further information.
2066    *
2067    * Since: 1.4
2068    */
2069   pspec = g_param_spec_boolean ("no-clear-hint",
2070                                 P_("No Clear Hint"),
2071                                 P_("Whether the stage should clear its contents"),
2072                                 FALSE,
2073                                 CLUTTER_PARAM_READWRITE);
2074   g_object_class_install_property (gobject_class, PROP_NO_CLEAR_HINT, pspec);
2075
2076   /**
2077    * ClutterStage:accept-focus:
2078    *
2079    * Whether the #ClutterStage should accept key focus when shown.
2080    *
2081    * Since: 1.6
2082    */
2083   pspec = g_param_spec_boolean ("accept-focus",
2084                                 P_("Accept Focus"),
2085                                 P_("Whether the stage should accept focus on show"),
2086                                 TRUE,
2087                                 CLUTTER_PARAM_READWRITE);
2088   g_object_class_install_property (gobject_class, PROP_ACCEPT_FOCUS, pspec);
2089
2090   /**
2091    * ClutterStage::fullscreen:
2092    * @stage: the stage which was fullscreened
2093    *
2094    * The ::fullscreen signal is emitted when the stage is made fullscreen.
2095    *
2096    * Since: 0.6
2097    */
2098   stage_signals[FULLSCREEN] =
2099     g_signal_new (I_("fullscreen"),
2100                   G_TYPE_FROM_CLASS (gobject_class),
2101                   G_SIGNAL_RUN_FIRST,
2102                   G_STRUCT_OFFSET (ClutterStageClass, fullscreen),
2103                   NULL, NULL,
2104                   _clutter_marshal_VOID__VOID,
2105                   G_TYPE_NONE, 0);
2106   /**
2107    * ClutterStage::unfullscreen:
2108    * @stage: the stage which has left a fullscreen state.
2109    *
2110    * The ::unfullscreen signal is emitted when the stage leaves a fullscreen
2111    * state.
2112    *
2113    * Since: 0.6
2114    */
2115   stage_signals[UNFULLSCREEN] =
2116     g_signal_new (I_("unfullscreen"),
2117                   G_TYPE_FROM_CLASS (gobject_class),
2118                   G_SIGNAL_RUN_LAST,
2119                   G_STRUCT_OFFSET (ClutterStageClass, unfullscreen),
2120                   NULL, NULL,
2121                   _clutter_marshal_VOID__VOID,
2122                   G_TYPE_NONE, 0);
2123   /**
2124    * ClutterStage::activate:
2125    * @stage: the stage which was activated
2126    *
2127    * The ::activate signal is emitted when the stage receives key focus
2128    * from the underlying window system.
2129    *
2130    * Since: 0.6
2131    */
2132   stage_signals[ACTIVATE] =
2133     g_signal_new (I_("activate"),
2134                   G_TYPE_FROM_CLASS (gobject_class),
2135                   G_SIGNAL_RUN_LAST,
2136                   G_STRUCT_OFFSET (ClutterStageClass, activate),
2137                   NULL, NULL,
2138                   _clutter_marshal_VOID__VOID,
2139                   G_TYPE_NONE, 0);
2140   /**
2141    * ClutterStage::deactivate:
2142    * @stage: the stage which was deactivated
2143    *
2144    * The ::activate signal is emitted when the stage loses key focus
2145    * from the underlying window system.
2146    *
2147    * Since: 0.6
2148    */
2149   stage_signals[DEACTIVATE] =
2150     g_signal_new (I_("deactivate"),
2151                   G_TYPE_FROM_CLASS (gobject_class),
2152                   G_SIGNAL_RUN_LAST,
2153                   G_STRUCT_OFFSET (ClutterStageClass, deactivate),
2154                   NULL, NULL,
2155                   _clutter_marshal_VOID__VOID,
2156                   G_TYPE_NONE, 0);
2157
2158   /**
2159    * ClutterStage::delete-event:
2160    * @stage: the stage that received the event
2161    * @event: a #ClutterEvent of type %CLUTTER_DELETE
2162    *
2163    * The ::delete-event signal is emitted when the user closes a
2164    * #ClutterStage window using the window controls.
2165    *
2166    * Clutter by default will call clutter_main_quit() if @stage is
2167    * the default stage, and clutter_actor_destroy() for any other
2168    * stage.
2169    *
2170    * It is possible to override the default behaviour by connecting
2171    * a new handler and returning %TRUE there.
2172    *
2173    * <note>This signal is emitted only on Clutter backends that
2174    * embed #ClutterStage in native windows. It is not emitted for
2175    * backends that use a static frame buffer.</note>
2176    *
2177    * Since: 1.2
2178    */
2179   stage_signals[DELETE_EVENT] =
2180     g_signal_new (I_("delete-event"),
2181                   G_TYPE_FROM_CLASS (gobject_class),
2182                   G_SIGNAL_RUN_LAST,
2183                   G_STRUCT_OFFSET (ClutterStageClass, delete_event),
2184                   _clutter_boolean_handled_accumulator, NULL,
2185                   _clutter_marshal_BOOLEAN__BOXED,
2186                   G_TYPE_BOOLEAN, 1,
2187                   CLUTTER_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
2188
2189   klass->fullscreen = clutter_stage_real_fullscreen;
2190   klass->activate = clutter_stage_real_activate;
2191   klass->deactivate = clutter_stage_real_deactivate;
2192   klass->delete_event = clutter_stage_real_delete_event;
2193
2194   g_type_class_add_private (gobject_class, sizeof (ClutterStagePrivate));
2195 }
2196
2197 static void
2198 clutter_stage_notify_min_size (ClutterStage *self)
2199 {
2200   self->priv->min_size_changed = TRUE;
2201 }
2202
2203 static void
2204 clutter_stage_init (ClutterStage *self)
2205 {
2206   cairo_rectangle_int_t geom = { 0, };
2207   ClutterStagePrivate *priv;
2208   ClutterStageWindow *impl;
2209   ClutterBackend *backend;
2210   GError *error;
2211
2212   /* a stage is a top-level object */
2213   CLUTTER_SET_PRIVATE_FLAGS (self, CLUTTER_IS_TOPLEVEL);
2214
2215   self->priv = priv = CLUTTER_STAGE_GET_PRIVATE (self);
2216
2217   CLUTTER_NOTE (BACKEND, "Creating stage from the default backend");
2218   backend = clutter_get_default_backend ();
2219
2220   error = NULL;
2221   impl = _clutter_backend_create_stage (backend, self, &error);
2222
2223   if (G_LIKELY (impl != NULL))
2224     {
2225       _clutter_stage_set_window (self, impl);
2226       _clutter_stage_window_get_geometry (priv->impl, &geom);
2227     }
2228   else
2229     {
2230       if (error != NULL)
2231         {
2232           g_critical ("Unable to create a new stage implementation: %s",
2233                       error->message);
2234           g_error_free (error);
2235         }
2236       else
2237         g_critical ("Unable to create a new stage implementation.");
2238     }
2239
2240   priv->event_queue = g_queue_new ();
2241
2242   priv->is_fullscreen = FALSE;
2243   priv->is_user_resizable = FALSE;
2244   priv->is_cursor_visible = TRUE;
2245   priv->use_fog = FALSE;
2246   priv->throttle_motion_events = TRUE;
2247   priv->min_size_changed = FALSE;
2248
2249   /* XXX - we need to keep the invariant that calling
2250    * clutter_set_motion_event_enabled() before the stage creation
2251    * will cause motion event delivery to be disabled on any newly
2252    * created stage. this can go away when we break API and remove
2253    * deprecated functions.
2254    */
2255   priv->motion_events_enabled = _clutter_context_get_motion_events_enabled ();
2256
2257   clutter_actor_set_background_color (CLUTTER_ACTOR (self),
2258                                       &default_stage_color);
2259
2260   priv->perspective.fovy   = 60.0; /* 60 Degrees */
2261   priv->perspective.aspect = (float) geom.width / (float) geom.height;
2262   priv->perspective.z_near = 0.1;
2263   priv->perspective.z_far  = 100.0;
2264
2265   cogl_matrix_init_identity (&priv->projection);
2266   cogl_matrix_perspective (&priv->projection,
2267                            priv->perspective.fovy,
2268                            priv->perspective.aspect,
2269                            priv->perspective.z_near,
2270                            priv->perspective.z_far);
2271   cogl_matrix_get_inverse (&priv->projection,
2272                            &priv->inverse_projection);
2273   cogl_matrix_init_identity (&priv->view);
2274   cogl_matrix_view_2d_in_perspective (&priv->view,
2275                                       priv->perspective.fovy,
2276                                       priv->perspective.aspect,
2277                                       priv->perspective.z_near,
2278                                       50, /* distance to 2d plane */
2279                                       geom.width,
2280                                       geom.height);
2281
2282
2283   /* FIXME - remove for 2.0 */
2284   priv->fog.z_near = 1.0;
2285   priv->fog.z_far  = 2.0;
2286
2287   priv->relayout_pending = TRUE;
2288
2289   clutter_actor_set_reactive (CLUTTER_ACTOR (self), TRUE);
2290   clutter_stage_set_title (self, g_get_prgname ());
2291   clutter_stage_set_key_focus (self, NULL);
2292
2293   g_signal_connect (self, "notify::min-width",
2294                     G_CALLBACK (clutter_stage_notify_min_size), NULL);
2295   g_signal_connect (self, "notify::min-height",
2296                     G_CALLBACK (clutter_stage_notify_min_size), NULL);
2297
2298   _clutter_stage_set_viewport (self, 0, 0, geom.width, geom.height);
2299
2300   _clutter_stage_set_pick_buffer_valid (self, FALSE, CLUTTER_PICK_ALL);
2301   priv->picks_per_frame = 0;
2302
2303   priv->paint_volume_stack =
2304     g_array_new (FALSE, FALSE, sizeof (ClutterPaintVolume));
2305
2306   priv->devices = g_hash_table_new (NULL, NULL);
2307
2308   priv->pick_id_pool = _clutter_id_pool_new (256);
2309 }
2310
2311 /**
2312  * clutter_stage_get_default:
2313  *
2314  * Retrieves a #ClutterStage singleton.
2315  *
2316  * This function is not as useful as it sounds, and will most likely
2317  * by deprecated in the future. Application code should only create
2318  * a #ClutterStage instance using clutter_stage_new(), and manage the
2319  * lifetime of the stage manually.
2320  *
2321  * The default stage singleton has a platform-specific behaviour: on
2322  * platforms without the %CLUTTER_FEATURE_STAGE_MULTIPLE feature flag
2323  * set, the first #ClutterStage instance will also be set to be the
2324  * default stage instance, and this function will always return a
2325  * pointer to it.
2326  *
2327  * On platforms with the %CLUTTER_FEATURE_STAGE_MULTIPLE feature flag
2328  * set, the default stage will be created by the first call to this
2329  * function, and every following call will return the same pointer to
2330  * it.
2331  *
2332  * Return value: (transfer none) (type Clutter.Stage): the main
2333  *   #ClutterStage. You should never destroy or unref the returned
2334  *   actor.
2335  *
2336  * Deprecated: 1.10: Use clutter_stage_new() instead.
2337  */
2338 ClutterActor *
2339 clutter_stage_get_default (void)
2340 {
2341   ClutterStageManager *stage_manager = clutter_stage_manager_get_default ();
2342   ClutterStage *stage;
2343
2344   stage = clutter_stage_manager_get_default_stage (stage_manager);
2345   if (G_UNLIKELY (stage == NULL))
2346     {
2347       /* This will take care of automatically adding the stage to the
2348        * stage manager and setting it as the default. Its floating
2349        * reference will be claimed by the stage manager.
2350        */
2351       stage = g_object_new (CLUTTER_TYPE_STAGE, NULL);
2352       _clutter_stage_manager_set_default_stage (stage_manager, stage);
2353
2354       /* the default stage is realized by default */
2355       clutter_actor_realize (CLUTTER_ACTOR (stage));
2356     }
2357
2358   return CLUTTER_ACTOR (stage);
2359 }
2360
2361 /**
2362  * clutter_stage_set_color:
2363  * @stage: A #ClutterStage
2364  * @color: A #ClutterColor
2365  *
2366  * Sets the stage color.
2367  *
2368  * Deprecated: 1.10: Use clutter_actor_set_background_color() instead.
2369  */
2370 void
2371 clutter_stage_set_color (ClutterStage       *stage,
2372                          const ClutterColor *color)
2373 {
2374   clutter_actor_set_background_color (CLUTTER_ACTOR (stage), color);
2375
2376   g_object_notify (G_OBJECT (stage), "color");
2377 }
2378
2379 /**
2380  * clutter_stage_get_color:
2381  * @stage: A #ClutterStage
2382  * @color: (out caller-allocates): return location for a #ClutterColor
2383  *
2384  * Retrieves the stage color.
2385  *
2386  * Deprecated: 1.10: Use clutter_actor_get_background_color() instead.
2387  */
2388 void
2389 clutter_stage_get_color (ClutterStage *stage,
2390                          ClutterColor *color)
2391 {
2392   clutter_actor_get_background_color (CLUTTER_ACTOR (stage), color);
2393 }
2394
2395 static void
2396 clutter_stage_set_perspective_internal (ClutterStage       *stage,
2397                                         ClutterPerspective *perspective)
2398 {
2399   ClutterStagePrivate *priv = stage->priv;
2400
2401   if (priv->perspective.fovy == perspective->fovy &&
2402       priv->perspective.aspect == perspective->aspect &&
2403       priv->perspective.z_near == perspective->z_near &&
2404       priv->perspective.z_far == perspective->z_far)
2405     return;
2406
2407   priv->perspective = *perspective;
2408
2409   cogl_matrix_init_identity (&priv->projection);
2410   cogl_matrix_perspective (&priv->projection,
2411                            priv->perspective.fovy,
2412                            priv->perspective.aspect,
2413                            priv->perspective.z_near,
2414                            priv->perspective.z_far);
2415   cogl_matrix_get_inverse (&priv->projection,
2416                            &priv->inverse_projection);
2417
2418   priv->dirty_projection = TRUE;
2419   clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
2420 }
2421
2422 /**
2423  * clutter_stage_set_perspective:
2424  * @stage: A #ClutterStage
2425  * @perspective: A #ClutterPerspective
2426  *
2427  * Sets the stage perspective. Using this function is not recommended
2428  * because it will disable Clutter's attempts to generate an
2429  * appropriate perspective based on the size of the stage.
2430  */
2431 void
2432 clutter_stage_set_perspective (ClutterStage       *stage,
2433                                ClutterPerspective *perspective)
2434 {
2435   ClutterStagePrivate *priv;
2436
2437   g_return_if_fail (CLUTTER_IS_STAGE (stage));
2438   g_return_if_fail (perspective != NULL);
2439   g_return_if_fail (perspective->z_far - perspective->z_near != 0);
2440
2441   priv = stage->priv;
2442
2443   /* If the application ever calls this function then we'll stop
2444      automatically updating the perspective when the stage changes
2445      size */
2446   priv->has_custom_perspective = TRUE;
2447
2448   clutter_stage_set_perspective_internal (stage, perspective);
2449 }
2450
2451 /**
2452  * clutter_stage_get_perspective:
2453  * @stage: A #ClutterStage
2454  * @perspective: (out caller-allocates) (allow-none): return location for a
2455  *   #ClutterPerspective
2456  *
2457  * Retrieves the stage perspective.
2458  */
2459 void
2460 clutter_stage_get_perspective (ClutterStage       *stage,
2461                                ClutterPerspective *perspective)
2462 {
2463   g_return_if_fail (CLUTTER_IS_STAGE (stage));
2464   g_return_if_fail (perspective != NULL);
2465
2466   *perspective = stage->priv->perspective;
2467 }
2468
2469 /*
2470  * clutter_stage_get_projection_matrix:
2471  * @stage: A #ClutterStage
2472  * @projection: return location for a #CoglMatrix representing the
2473  *              perspective projection applied to actors on the given
2474  *              @stage.
2475  *
2476  * Retrieves the @stage's projection matrix. This is derived from the
2477  * current perspective set using clutter_stage_set_perspective().
2478  *
2479  * Since: 1.6
2480  */
2481 void
2482 _clutter_stage_get_projection_matrix (ClutterStage *stage,
2483                                       CoglMatrix *projection)
2484 {
2485   g_return_if_fail (CLUTTER_IS_STAGE (stage));
2486   g_return_if_fail (projection != NULL);
2487
2488   *projection = stage->priv->projection;
2489 }
2490
2491 /* This simply provides a simple mechanism for us to ensure that
2492  * the projection matrix gets re-asserted before painting.
2493  *
2494  * This is used when switching between multiple stages */
2495 void
2496 _clutter_stage_dirty_projection (ClutterStage *stage)
2497 {
2498   stage->priv->dirty_projection = TRUE;
2499 }
2500
2501 /*
2502  * clutter_stage_set_viewport:
2503  * @stage: A #ClutterStage
2504  * @x: The X postition to render the stage at, in window coordinates
2505  * @y: The Y position to render the stage at, in window coordinates
2506  * @width: The width to render the stage at, in window coordinates
2507  * @height: The height to render the stage at, in window coordinates
2508  *
2509  * Sets the stage viewport. The viewport defines a final scale and
2510  * translation of your rendered stage and actors. This lets you render
2511  * your stage into a subregion of the stage window or you could use it to
2512  * pan a subregion of the stage if your stage window is smaller then
2513  * the stage. (XXX: currently this isn't possible)
2514  *
2515  * Unlike a scale and translation done using the modelview matrix this
2516  * is done after everything has had perspective projection applied, so
2517  * for example if you were to pan across a subregion of the stage using
2518  * the viewport then you would not see a change in perspective for the
2519  * actors on the stage.
2520  *
2521  * Normally the stage viewport will automatically track the size of the
2522  * stage window with no offset so the stage will fill your window. This
2523  * behaviour can be changed with the "viewport-mimics-window" property
2524  * which will automatically be set to FALSE if you use this API. If
2525  * you want to revert to the original behaviour then you should set
2526  * this property back to %TRUE using
2527  * clutter_stage_set_viewport_mimics_window().
2528  * (XXX: If we were to make this API public then we might want to do
2529  *  add that property.)
2530  *
2531  * Note: currently this interface only support integer precision
2532  * offsets and sizes for viewports but the interface takes floats because
2533  * OpenGL 4.0 has introduced floating point viewports which we might
2534  * want to expose via this API eventually.
2535  *
2536  * Since: 1.6
2537  */
2538 void
2539 _clutter_stage_set_viewport (ClutterStage *stage,
2540                              float         x,
2541                              float         y,
2542                              float         width,
2543                              float         height)
2544 {
2545   ClutterStagePrivate *priv;
2546
2547   g_return_if_fail (CLUTTER_IS_STAGE (stage));
2548
2549   priv = stage->priv;
2550
2551
2552   if (x == priv->viewport[0] &&
2553       y == priv->viewport[1] &&
2554       width == priv->viewport[2] &&
2555       height == priv->viewport[3])
2556     return;
2557
2558   priv->viewport[0] = x;
2559   priv->viewport[1] = y;
2560   priv->viewport[2] = width;
2561   priv->viewport[3] = height;
2562
2563   priv->dirty_viewport = TRUE;
2564
2565   queue_full_redraw (stage);
2566 }
2567
2568 /* This simply provides a simple mechanism for us to ensure that
2569  * the viewport gets re-asserted before next painting.
2570  *
2571  * This is used when switching between multiple stages */
2572 void
2573 _clutter_stage_dirty_viewport (ClutterStage *stage)
2574 {
2575   stage->priv->dirty_viewport = TRUE;
2576 }
2577
2578 /*
2579  * clutter_stage_get_viewport:
2580  * @stage: A #ClutterStage
2581  * @x: A location for the X position where the stage is rendered,
2582  *     in window coordinates.
2583  * @y: A location for the Y position where the stage is rendered,
2584  *     in window coordinates.
2585  * @width: A location for the width the stage is rendered at,
2586  *         in window coordinates.
2587  * @height: A location for the height the stage is rendered at,
2588  *          in window coordinates.
2589  *
2590  * Returns the viewport offset and size set using
2591  * clutter_stage_set_viewport() or if the "viewport-mimics-window" property
2592  * is TRUE then @x and @y will be set to 0 and @width and @height will equal
2593  * the width if the stage window.
2594  *
2595  * Since: 1.6
2596  */
2597 void
2598 _clutter_stage_get_viewport (ClutterStage *stage,
2599                              float        *x,
2600                              float        *y,
2601                              float        *width,
2602                              float        *height)
2603 {
2604   ClutterStagePrivate *priv;
2605
2606   g_return_if_fail (CLUTTER_IS_STAGE (stage));
2607
2608   priv = stage->priv;
2609
2610   *x = priv->viewport[0];
2611   *y = priv->viewport[1];
2612   *width = priv->viewport[2];
2613   *height = priv->viewport[3];
2614 }
2615
2616 /**
2617  * clutter_stage_set_fullscreen:
2618  * @stage: a #ClutterStage
2619  * @fullscreen: %TRUE to to set the stage fullscreen
2620  *
2621  * Asks to place the stage window in the fullscreen or unfullscreen
2622  * states.
2623  *
2624  ( Note that you shouldn't assume the window is definitely full screen
2625  * afterward, because other entities (e.g. the user or window manager)
2626  * could unfullscreen it again, and not all window managers honor
2627  * requests to fullscreen windows.
2628  *
2629  * If you want to receive notification of the fullscreen state you
2630  * should either use the #ClutterStage::fullscreen and
2631  * #ClutterStage::unfullscreen signals, or use the notify signal
2632  * for the #ClutterStage:fullscreen-set property
2633  *
2634  * Since: 1.0
2635  */
2636 void
2637 clutter_stage_set_fullscreen (ClutterStage *stage,
2638                               gboolean      fullscreen)
2639 {
2640   ClutterStagePrivate *priv;
2641
2642   g_return_if_fail (CLUTTER_IS_STAGE (stage));
2643
2644   priv = stage->priv;
2645
2646   if (priv->is_fullscreen != fullscreen)
2647     {
2648       ClutterStageWindow *impl = CLUTTER_STAGE_WINDOW (priv->impl);
2649       ClutterStageWindowIface *iface;
2650
2651       iface = CLUTTER_STAGE_WINDOW_GET_IFACE (impl);
2652
2653       /* Only set if backend implements.
2654        *
2655        * Also see clutter_stage_event() for setting priv->is_fullscreen
2656        * on state change event.
2657        */
2658       if (iface->set_fullscreen)
2659         iface->set_fullscreen (impl, fullscreen);
2660     }
2661
2662   /* If the backend did fullscreen the stage window then we need to resize
2663    * the stage and update its viewport so we queue a relayout.  Note: if the
2664    * fullscreen request is handled asynchronously we can't rely on this
2665    * queue_relayout to update the viewport, but for example the X backend
2666    * will recieve a ConfigureNotify after a successful resize which is how
2667    * we ensure the viewport is updated on X.
2668    */
2669   clutter_actor_queue_relayout (CLUTTER_ACTOR (stage));
2670 }
2671
2672 /**
2673  * clutter_stage_get_fullscreen:
2674  * @stage: a #ClutterStage
2675  *
2676  * Retrieves whether the stage is full screen or not
2677  *
2678  * Return value: %TRUE if the stage is full screen
2679  *
2680  * Since: 1.0
2681  */
2682 gboolean
2683 clutter_stage_get_fullscreen (ClutterStage *stage)
2684 {
2685   g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE);
2686
2687   return stage->priv->is_fullscreen;
2688 }
2689
2690 /**
2691  * clutter_stage_set_user_resizable:
2692  * @stage: a #ClutterStage
2693  * @resizable: whether the stage should be user resizable.
2694  *
2695  * Sets if the stage is resizable by user interaction (e.g. via
2696  * window manager controls)
2697  *
2698  * Since: 0.4
2699  */
2700 void
2701 clutter_stage_set_user_resizable (ClutterStage *stage,
2702                                   gboolean      resizable)
2703 {
2704   ClutterStagePrivate *priv;
2705
2706   g_return_if_fail (CLUTTER_IS_STAGE (stage));
2707
2708   priv = stage->priv;
2709
2710   if (clutter_feature_available (CLUTTER_FEATURE_STAGE_USER_RESIZE)
2711       && priv->is_user_resizable != resizable)
2712     {
2713       ClutterStageWindow *impl = CLUTTER_STAGE_WINDOW (priv->impl);
2714       ClutterStageWindowIface *iface;
2715
2716       iface = CLUTTER_STAGE_WINDOW_GET_IFACE (impl);
2717       if (iface->set_user_resizable)
2718         {
2719           priv->is_user_resizable = resizable;
2720
2721           iface->set_user_resizable (impl, resizable);
2722
2723           g_object_notify (G_OBJECT (stage), "user-resizable");
2724         }
2725     }
2726 }
2727
2728 /**
2729  * clutter_stage_get_user_resizable:
2730  * @stage: a #ClutterStage
2731  *
2732  * Retrieves the value set with clutter_stage_set_user_resizable().
2733  *
2734  * Return value: %TRUE if the stage is resizable by the user.
2735  *
2736  * Since: 0.4
2737  */
2738 gboolean
2739 clutter_stage_get_user_resizable (ClutterStage *stage)
2740 {
2741   g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE);
2742
2743   return stage->priv->is_user_resizable;
2744 }
2745
2746 /**
2747  * clutter_stage_show_cursor:
2748  * @stage: a #ClutterStage
2749  *
2750  * Shows the cursor on the stage window
2751  */
2752 void
2753 clutter_stage_show_cursor (ClutterStage *stage)
2754 {
2755   ClutterStagePrivate *priv;
2756
2757   g_return_if_fail (CLUTTER_IS_STAGE (stage));
2758
2759   priv = stage->priv;
2760   if (!priv->is_cursor_visible)
2761     {
2762       ClutterStageWindow *impl = CLUTTER_STAGE_WINDOW (priv->impl);
2763       ClutterStageWindowIface *iface;
2764
2765       iface = CLUTTER_STAGE_WINDOW_GET_IFACE (impl);
2766       if (iface->set_cursor_visible)
2767         {
2768           priv->is_cursor_visible = TRUE;
2769
2770           iface->set_cursor_visible (impl, TRUE);
2771
2772           g_object_notify (G_OBJECT (stage), "cursor-visible");
2773         }
2774     }
2775 }
2776
2777 /**
2778  * clutter_stage_hide_cursor:
2779  * @stage: a #ClutterStage
2780  *
2781  * Makes the cursor invisible on the stage window
2782  *
2783  * Since: 0.4
2784  */
2785 void
2786 clutter_stage_hide_cursor (ClutterStage *stage)
2787 {
2788   ClutterStagePrivate *priv;
2789
2790   g_return_if_fail (CLUTTER_IS_STAGE (stage));
2791
2792   priv = stage->priv;
2793   if (priv->is_cursor_visible)
2794     {
2795       ClutterStageWindow *impl = CLUTTER_STAGE_WINDOW (priv->impl);
2796       ClutterStageWindowIface *iface;
2797
2798       iface = CLUTTER_STAGE_WINDOW_GET_IFACE (impl);
2799       if (iface->set_cursor_visible)
2800         {
2801           priv->is_cursor_visible = FALSE;
2802
2803           iface->set_cursor_visible (impl, FALSE);
2804
2805           g_object_notify (G_OBJECT (stage), "cursor-visible");
2806         }
2807     }
2808 }
2809
2810 /**
2811  * clutter_stage_read_pixels:
2812  * @stage: A #ClutterStage
2813  * @x: x coordinate of the first pixel that is read from stage
2814  * @y: y coordinate of the first pixel that is read from stage
2815  * @width: Width dimention of pixels to be read, or -1 for the
2816  *   entire stage width
2817  * @height: Height dimention of pixels to be read, or -1 for the
2818  *   entire stage height
2819  *
2820  * Makes a screenshot of the stage in RGBA 8bit data, returns a
2821  * linear buffer with @width * 4 as rowstride.
2822  *
2823  * The alpha data contained in the returned buffer is driver-dependent,
2824  * and not guaranteed to hold any sensible value.
2825  *
2826  * Return value: (array): a pointer to newly allocated memory with the buffer
2827  *   or %NULL if the read failed. Use g_free() on the returned data
2828  *   to release the resources it has allocated.
2829  */
2830 guchar *
2831 clutter_stage_read_pixels (ClutterStage *stage,
2832                            gint          x,
2833                            gint          y,
2834                            gint          width,
2835                            gint          height)
2836 {
2837   ClutterGeometry geom;
2838   guchar *pixels;
2839
2840   g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL);
2841
2842   /* Force a redraw of the stage before reading back pixels */
2843   clutter_stage_ensure_current (stage);
2844   clutter_actor_paint (CLUTTER_ACTOR (stage));
2845
2846   clutter_actor_get_allocation_geometry (CLUTTER_ACTOR (stage), &geom);
2847
2848   if (width < 0)
2849     width = geom.width;
2850
2851   if (height < 0)
2852     height = geom.height;
2853
2854   pixels = g_malloc (height * width * 4);
2855
2856   cogl_read_pixels (x, y, width, height,
2857                     COGL_READ_PIXELS_COLOR_BUFFER,
2858                     COGL_PIXEL_FORMAT_RGBA_8888,
2859                     pixels);
2860
2861   return pixels;
2862 }
2863
2864 /**
2865  * clutter_stage_get_actor_at_pos:
2866  * @stage: a #ClutterStage
2867  * @pick_mode: how the scene graph should be painted
2868  * @x: X coordinate to check
2869  * @y: Y coordinate to check
2870  *
2871  * Checks the scene at the coordinates @x and @y and returns a pointer
2872  * to the #ClutterActor at those coordinates.
2873  *
2874  * By using @pick_mode it is possible to control which actors will be
2875  * painted and thus available.
2876  *
2877  * Return value: (transfer none): the actor at the specified coordinates,
2878  *   if any
2879  */
2880 ClutterActor *
2881 clutter_stage_get_actor_at_pos (ClutterStage    *stage,
2882                                 ClutterPickMode  pick_mode,
2883                                 gint             x,
2884                                 gint             y)
2885 {
2886   return _clutter_stage_do_pick (stage, x, y, pick_mode);
2887 }
2888
2889 /**
2890  * clutter_stage_event:
2891  * @stage: a #ClutterStage
2892  * @event: a #ClutterEvent
2893  *
2894  * This function is used to emit an event on the main stage.
2895  *
2896  * You should rarely need to use this function, except for
2897  * synthetised events.
2898  *
2899  * Return value: the return value from the signal emission
2900  *
2901  * Since: 0.4
2902  */
2903 gboolean
2904 clutter_stage_event (ClutterStage *stage,
2905                      ClutterEvent *event)
2906 {
2907   ClutterStagePrivate *priv;
2908
2909   g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE);
2910   g_return_val_if_fail (event != NULL, FALSE);
2911
2912   priv = stage->priv;
2913
2914   if (event->type == CLUTTER_DELETE)
2915     {
2916       gboolean retval = FALSE;
2917
2918       g_signal_emit_by_name (stage, "event", event, &retval);
2919
2920       if (!retval)
2921         g_signal_emit_by_name (stage, "delete-event", event, &retval);
2922
2923       return retval;
2924     }
2925
2926   if (event->type != CLUTTER_STAGE_STATE)
2927     return FALSE;
2928
2929   /* emit raw event */
2930   if (clutter_actor_event (CLUTTER_ACTOR (stage), event, FALSE))
2931     return TRUE;
2932
2933   if (event->stage_state.changed_mask & CLUTTER_STAGE_STATE_FULLSCREEN)
2934     {
2935       if (event->stage_state.new_state & CLUTTER_STAGE_STATE_FULLSCREEN)
2936         {
2937           priv->is_fullscreen = TRUE;
2938           g_signal_emit (stage, stage_signals[FULLSCREEN], 0);
2939
2940           g_object_notify (G_OBJECT (stage), "fullscreen-set");
2941         }
2942       else
2943         {
2944           priv->is_fullscreen = FALSE;
2945           g_signal_emit (stage, stage_signals[UNFULLSCREEN], 0);
2946
2947           g_object_notify (G_OBJECT (stage), "fullscreen-set");
2948         }
2949     }
2950
2951   if (event->stage_state.changed_mask & CLUTTER_STAGE_STATE_ACTIVATED)
2952     {
2953       if (event->stage_state.new_state & CLUTTER_STAGE_STATE_ACTIVATED)
2954         g_signal_emit (stage, stage_signals[ACTIVATE], 0);
2955       else
2956         g_signal_emit (stage, stage_signals[DEACTIVATE], 0);
2957     }
2958
2959   return TRUE;
2960 }
2961
2962 /**
2963  * clutter_stage_set_title:
2964  * @stage: A #ClutterStage
2965  * @title: A utf8 string for the stage windows title.
2966  *
2967  * Sets the stage title.
2968  *
2969  * Since: 0.4
2970  **/
2971 void
2972 clutter_stage_set_title (ClutterStage       *stage,
2973                          const gchar        *title)
2974 {
2975   ClutterStagePrivate *priv;
2976   ClutterStageWindow *impl;
2977
2978   g_return_if_fail (CLUTTER_IS_STAGE (stage));
2979
2980   priv = stage->priv;
2981
2982   g_free (priv->title);
2983   priv->title = g_strdup (title);
2984
2985   impl = CLUTTER_STAGE_WINDOW (priv->impl);
2986   if (CLUTTER_STAGE_WINDOW_GET_IFACE(impl)->set_title != NULL)
2987     CLUTTER_STAGE_WINDOW_GET_IFACE (impl)->set_title (impl, priv->title);
2988
2989   g_object_notify (G_OBJECT (stage), "title");
2990 }
2991
2992 /**
2993  * clutter_stage_get_title:
2994  * @stage: A #ClutterStage
2995  *
2996  * Gets the stage title.
2997  *
2998  * Return value: pointer to the title string for the stage. The
2999  * returned string is owned by the actor and should not
3000  * be modified or freed.
3001  *
3002  * Since: 0.4
3003  **/
3004 const gchar *
3005 clutter_stage_get_title (ClutterStage       *stage)
3006 {
3007   g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL);
3008
3009   return stage->priv->title;
3010 }
3011
3012 static void
3013 on_key_focus_destroy (ClutterActor *actor,
3014                       ClutterStage *stage)
3015 {
3016   /* unset the key focus */
3017   clutter_stage_set_key_focus (stage, NULL);
3018 }
3019
3020 /**
3021  * clutter_stage_set_key_focus:
3022  * @stage: the #ClutterStage
3023  * @actor: (allow-none): the actor to set key focus to, or %NULL
3024  *
3025  * Sets the key focus on @actor. An actor with key focus will receive
3026  * all the key events. If @actor is %NULL, the stage will receive
3027  * focus.
3028  *
3029  * Since: 0.6
3030  */
3031 void
3032 clutter_stage_set_key_focus (ClutterStage *stage,
3033                              ClutterActor *actor)
3034 {
3035   ClutterStagePrivate *priv;
3036
3037   g_return_if_fail (CLUTTER_IS_STAGE (stage));
3038   g_return_if_fail (actor == NULL || CLUTTER_IS_ACTOR (actor));
3039
3040   priv = stage->priv;
3041
3042   /* avoid emitting signals and notifications if we're setting the same
3043    * actor as the key focus
3044    */
3045   if (priv->key_focused_actor == actor)
3046     return;
3047
3048   if (priv->key_focused_actor != NULL)
3049     {
3050       ClutterActor *old_focused_actor;
3051
3052       old_focused_actor = priv->key_focused_actor;
3053
3054       /* set key_focused_actor to NULL before emitting the signal or someone
3055        * might hide the previously focused actor in the signal handler and we'd
3056        * get re-entrant call and get glib critical from g_object_weak_unref
3057        */
3058       g_signal_handlers_disconnect_by_func (priv->key_focused_actor,
3059                                             G_CALLBACK (on_key_focus_destroy),
3060                                             stage);
3061       priv->key_focused_actor = NULL;
3062
3063       g_signal_emit_by_name (old_focused_actor, "key-focus-out");
3064     }
3065   else
3066     g_signal_emit_by_name (stage, "key-focus-out");
3067
3068   /* Note, if someone changes key focus in focus-out signal handler we'd be
3069    * overriding the latter call below moving the focus where it was originally
3070    * intended. The order of events would be:
3071    *   1st focus-out, 2nd focus-out (on stage), 2nd focus-in, 1st focus-in
3072    */
3073   if (actor != NULL)
3074     {
3075       priv->key_focused_actor = actor;
3076
3077       g_signal_connect (actor,
3078                         "destroy", G_CALLBACK (on_key_focus_destroy),
3079                         stage);
3080       g_signal_emit_by_name (priv->key_focused_actor, "key-focus-in");
3081     }
3082   else
3083     g_signal_emit_by_name (stage, "key-focus-in");
3084
3085   g_object_notify (G_OBJECT (stage), "key-focus");
3086 }
3087
3088 /**
3089  * clutter_stage_get_key_focus:
3090  * @stage: the #ClutterStage
3091  *
3092  * Retrieves the actor that is currently under key focus.
3093  *
3094  * Return value: (transfer none): the actor with key focus, or the stage
3095  *
3096  * Since: 0.6
3097  */
3098 ClutterActor *
3099 clutter_stage_get_key_focus (ClutterStage *stage)
3100 {
3101   g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL);
3102
3103   if (stage->priv->key_focused_actor)
3104     return stage->priv->key_focused_actor;
3105
3106   return CLUTTER_ACTOR (stage);
3107 }
3108
3109 /**
3110  * clutter_stage_get_use_fog:
3111  * @stage: the #ClutterStage
3112  *
3113  * Gets whether the depth cueing effect is enabled on @stage.
3114  *
3115  * Return value: %TRUE if the depth cueing effect is enabled
3116  *
3117  * Since: 0.6
3118  *
3119  * Deprecated: 1.10: This function will always return %FALSE
3120  */
3121 gboolean
3122 clutter_stage_get_use_fog (ClutterStage *stage)
3123 {
3124   g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE);
3125
3126   return stage->priv->use_fog;
3127 }
3128
3129 /**
3130  * clutter_stage_set_use_fog:
3131  * @stage: the #ClutterStage
3132  * @fog: %TRUE for enabling the depth cueing effect
3133  *
3134  * Sets whether the depth cueing effect on the stage should be enabled
3135  * or not.
3136  *
3137  * Depth cueing is a 3D effect that makes actors farther away from the
3138  * viewing point less opaque, by fading them with the stage color.
3139
3140  * The parameters of the GL fog used can be changed using the
3141  * clutter_stage_set_fog() function.
3142  *
3143  * Since: 0.6
3144  *
3145  * Deprecated: 1.10: Calling this function produces no visible effect
3146  */
3147 void
3148 clutter_stage_set_use_fog (ClutterStage *stage,
3149                            gboolean      fog)
3150 {
3151 }
3152
3153 /**
3154  * clutter_stage_set_fog:
3155  * @stage: the #ClutterStage
3156  * @fog: a #ClutterFog structure
3157  *
3158  * Sets the fog (also known as "depth cueing") settings for the @stage.
3159  *
3160  * A #ClutterStage will only use a linear fog progression, which
3161  * depends solely on the distance from the viewer. The cogl_set_fog()
3162  * function in COGL exposes more of the underlying implementation,
3163  * and allows changing the for progression function. It can be directly
3164  * used by disabling the #ClutterStage:use-fog property and connecting
3165  * a signal handler to the #ClutterActor::paint signal on the @stage,
3166  * like:
3167  *
3168  * |[
3169  *   clutter_stage_set_use_fog (stage, FALSE);
3170  *   g_signal_connect (stage, "paint", G_CALLBACK (on_stage_paint), NULL);
3171  * ]|
3172  *
3173  * The paint signal handler will call cogl_set_fog() with the
3174  * desired settings:
3175  *
3176  * |[
3177  *   static void
3178  *   on_stage_paint (ClutterActor *actor)
3179  *   {
3180  *     ClutterColor stage_color = { 0, };
3181  *     CoglColor fog_color = { 0, };
3182  *
3183  *     /&ast; set the fog color to the stage background color &ast;/
3184  *     clutter_stage_get_color (CLUTTER_STAGE (actor), &amp;stage_color);
3185  *     cogl_color_init_from_4ub (&amp;fog_color,
3186  *                               stage_color.red,
3187  *                               stage_color.green,
3188  *                               stage_color.blue,
3189  *                               stage_color.alpha);
3190  *
3191  *     /&ast; enable fog &ast;/
3192  *     cogl_set_fog (&amp;fog_color,
3193  *                   COGL_FOG_MODE_EXPONENTIAL, /&ast; mode &ast;/
3194  *                   0.5,                       /&ast; density &ast;/
3195  *                   5.0, 30.0);                /&ast; z_near and z_far &ast;/
3196  *   }
3197  * ]|
3198  *
3199  * <note>The fogging functions only work correctly when the visible actors use
3200  * unmultiplied alpha colors. By default Cogl will premultiply textures and
3201  * cogl_set_source_color() will premultiply colors, so unless you explicitly
3202  * load your textures requesting an unmultiplied internal format and use
3203  * cogl_material_set_color() you can only use fogging with fully opaque actors.
3204  * Support for premultiplied colors will improve in the future when we can
3205  * depend on fragment shaders.</note>
3206  *
3207  * Since: 0.6
3208  *
3209  * Deprecated: 1.10: Fog settings are ignored.
3210  */
3211 void
3212 clutter_stage_set_fog (ClutterStage *stage,
3213                        ClutterFog   *fog)
3214 {
3215 }
3216
3217 /**
3218  * clutter_stage_get_fog:
3219  * @stage: the #ClutterStage
3220  * @fog: (out): return location for a #ClutterFog structure
3221  *
3222  * Retrieves the current depth cueing settings from the stage.
3223  *
3224  * Since: 0.6
3225  *
3226  * Deprecated: 1.10: This function will always return the default
3227  *   values of #ClutterFog
3228  */
3229 void
3230 clutter_stage_get_fog (ClutterStage *stage,
3231                         ClutterFog   *fog)
3232 {
3233   g_return_if_fail (CLUTTER_IS_STAGE (stage));
3234   g_return_if_fail (fog != NULL);
3235
3236   *fog = stage->priv->fog;
3237 }
3238
3239 /*** Perspective boxed type ******/
3240
3241 static gpointer
3242 clutter_perspective_copy (gpointer data)
3243 {
3244   if (G_LIKELY (data))
3245     return g_slice_dup (ClutterPerspective, data);
3246
3247   return NULL;
3248 }
3249
3250 static void
3251 clutter_perspective_free (gpointer data)
3252 {
3253   if (G_LIKELY (data))
3254     g_slice_free (ClutterPerspective, data);
3255 }
3256
3257 G_DEFINE_BOXED_TYPE (ClutterPerspective, clutter_perspective,
3258                      clutter_perspective_copy,
3259                      clutter_perspective_free);
3260
3261 static gpointer
3262 clutter_fog_copy (gpointer data)
3263 {
3264   if (G_LIKELY (data))
3265     return g_slice_dup (ClutterFog, data);
3266
3267   return NULL;
3268 }
3269
3270 static void
3271 clutter_fog_free (gpointer data)
3272 {
3273   if (G_LIKELY (data))
3274     g_slice_free (ClutterFog, data);
3275 }
3276
3277 G_DEFINE_BOXED_TYPE (ClutterFog, clutter_fog, clutter_fog_copy, clutter_fog_free);
3278
3279 /**
3280  * clutter_stage_new:
3281  *
3282  * Creates a new, non-default stage. A non-default stage is a new
3283  * top-level actor which can be used as another container. It works
3284  * exactly like the default stage, but while clutter_stage_get_default()
3285  * will always return the same instance, you will have to keep a pointer
3286  * to any #ClutterStage returned by clutter_stage_new().
3287  *
3288  * The ability to support multiple stages depends on the current
3289  * backend. Use clutter_feature_available() and
3290  * %CLUTTER_FEATURE_STAGE_MULTIPLE to check at runtime whether a
3291  * backend supports multiple stages.
3292  *
3293  * Return value: a new stage, or %NULL if the default backend does
3294  *   not support multiple stages. Use clutter_actor_destroy() to
3295  *   programmatically close the returned stage.
3296  *
3297  * Since: 0.8
3298  */
3299 ClutterActor *
3300 clutter_stage_new (void)
3301 {
3302   return g_object_new (CLUTTER_TYPE_STAGE, NULL);
3303 }
3304
3305 /**
3306  * clutter_stage_ensure_current:
3307  * @stage: the #ClutterStage
3308  *
3309  * This function essentially makes sure the right GL context is
3310  * current for the passed stage. It is not intended to
3311  * be used by applications.
3312  *
3313  * Since: 0.8
3314  */
3315 void
3316 clutter_stage_ensure_current (ClutterStage *stage)
3317 {
3318   ClutterBackend *backend;
3319
3320   g_return_if_fail (CLUTTER_IS_STAGE (stage));
3321
3322   backend = clutter_get_default_backend ();
3323   _clutter_backend_ensure_context (backend, stage);
3324 }
3325
3326 /**
3327  * clutter_stage_ensure_viewport:
3328  * @stage: a #ClutterStage
3329  *
3330  * Ensures that the GL viewport is updated with the current
3331  * stage window size.
3332  *
3333  * This function will queue a redraw of @stage.
3334  *
3335  * This function should not be called by applications; it is used
3336  * when embedding a #ClutterStage into a toolkit with another
3337  * windowing system, like GTK+.
3338  *
3339  * Since: 1.0
3340  */
3341 void
3342 clutter_stage_ensure_viewport (ClutterStage *stage)
3343 {
3344   g_return_if_fail (CLUTTER_IS_STAGE (stage));
3345
3346   _clutter_stage_dirty_viewport (stage);
3347
3348   clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
3349 }
3350
3351 /* This calculates a distance into the view frustum to position the
3352  * stage so there is a decent amount of space to position geometry
3353  * between the stage and the near clipping plane.
3354  *
3355  * Some awkward issues with this problem are:
3356  * - It's not possible to have a gap as large as the stage size with
3357  *   a fov > 53° which is basically always the case since the default
3358  *   fov is 60°.
3359  *    - This can be deduced if you consider that this requires a
3360  *      triangle as wide as it is deep to fit in the frustum in front
3361  *      of the z_near plane. That triangle will always have an angle
3362  *      of 53.13° at the point sitting on the z_near plane, but if the
3363  *      frustum has a wider fov angle the left/right clipping planes
3364  *      can never converge with the two corners of our triangle no
3365  *      matter what size the triangle has.
3366  * - With a fov > 53° there is a trade off between maximizing the gap
3367  *   size relative to the stage size but not loosing depth precision.
3368  * - Perhaps ideally we wouldn't just consider the fov on the y-axis
3369  *   that is usually used to define a perspective, we would consider
3370  *   the fov of the axis with the largest stage size so the gap would
3371  *   accommodate that size best.
3372  *
3373  * After going around in circles a few times with how to handle these
3374  * issues, we decided in the end to go for the simplest solution to
3375  * start with instead of an elaborate function that handles arbitrary
3376  * fov angles that we currently have no use-case for.
3377  *
3378  * The solution assumes a fovy of 60° and for that case gives a gap
3379  * that's 85% of the stage height. We can consider more elaborate
3380  * functions if necessary later.
3381  *
3382  * One guide we had to steer the gap size we support is the
3383  * interactive test, test-texture-quality which expects to animate an
3384  * actor to +400 on the z axis with a stage size of 640x480. A gap
3385  * that's 85% of the stage height gives a gap of 408 in that case.
3386  */
3387 static float
3388 calculate_z_translation (float z_near)
3389 {
3390   /* This solution uses fairly basic trigonometry, but is seems worth
3391    * clarifying the particular geometry we are looking at in-case
3392    * anyone wants to develop this further later. Not sure how well an
3393    * ascii diagram is going to work :-)
3394    *
3395    *    |--- stage_height ---|
3396    *    |     stage line     |
3397    *   ╲━━━━━━━━━━━━━━━━━━━━━╱------------
3398    *    ╲.  (2)   │        .╱       |   |
3399    *   C ╲ .      │      . ╱     gap|   |
3400    * =0.5°╲  . a  │    .  ╱         |   |
3401    *      b╲(1). D│  .   ╱          |   |
3402    *        ╲   B.│.    ╱near plane |   |
3403    *      A= ╲━━━━━━━━━╱-------------   |
3404    *     120° ╲ c │   ╱  |            z_2d
3405    *           ╲  │  ╱  z_near          |
3406    *       left ╲ │ ╱    |              |
3407    *       clip  60°fovy |              |
3408    *       plane  ╳----------------------
3409    *              |
3410    *              |
3411    *         origin line
3412    *
3413    * The area of interest is the triangle labeled (1) at the top left
3414    * marked with the ... line (a) from where the origin line crosses
3415    * the near plane to the top left where the stage line cross the
3416    * left clip plane.
3417    *
3418    * The sides of the triangle are a, b and c and the corresponding
3419    * angles opposite those sides are A, B and C.
3420    *
3421    * The angle of C is what trades off the gap size we have relative
3422    * to the stage size vs the depth precision we have.
3423    *
3424    * As mentioned above we arove at the angle for C is by working
3425    * backwards from how much space we want for test-texture-quality.
3426    * With a stage_height of 480 we want a gap > 400, ideally we also
3427    * wanted a somewhat round number as a percentage of the height for
3428    * documentation purposes. ~87% or a gap of ~416 is the limit
3429    * because that's where we approach a C angle of 0° and effectively
3430    * loose all depth precision.
3431    *
3432    * So for our test app with a stage_height of 480 if we aim for a
3433    * gap of 408 (85% of 480) we can get the angle D as
3434    * atan (stage_height/2/408) = 30.5°.
3435    *
3436    * That gives us the angle for B as 90° - 30.5° = 59.5°
3437    *
3438    * We can already determine that A has an angle of (fovy/2 + 90°) =
3439    * 120°
3440    *
3441    * Therefore C = 180 - A - B = 0.5°
3442    *
3443    * The length of c = z_near * tan (30°)
3444    *
3445    * Now we can use the rule a/SinA = c/SinC to calculate the
3446    * length of a. After some rearranging that gives us:
3447    *
3448    *      a              c
3449    *  ----------  =  ----------
3450    *  sin (120°)     sin (0.5°)
3451    *
3452    *      c * sin (120°)
3453    *  a = --------------
3454    *        sin (0.5°)
3455    *
3456    * And with that we can determine z_2d = cos (D) * a =
3457    * cos (30.5°) * a + z_near:
3458    *
3459    *         c * sin (120°) * cos (30.5°)
3460    *  z_2d = --------------------------- + z_near
3461    *                 sin (0.5°)
3462    */
3463 #define _DEG_TO_RAD (G_PI / 180.0)
3464   return z_near * tanf (30.0f * _DEG_TO_RAD) *
3465          sinf (120.0f * _DEG_TO_RAD) * cosf (30.5f * _DEG_TO_RAD) /
3466          sinf (0.5f * _DEG_TO_RAD) +
3467          z_near;
3468 #undef _DEG_TO_RAD
3469    /* We expect the compiler should boil this down to z_near * CONSTANT */
3470 }
3471
3472 void
3473 _clutter_stage_maybe_setup_viewport (ClutterStage *stage)
3474 {
3475   ClutterStagePrivate *priv = stage->priv;
3476
3477   if (priv->dirty_viewport)
3478     {
3479       ClutterPerspective perspective;
3480       float z_2d;
3481
3482       CLUTTER_NOTE (PAINT,
3483                     "Setting up the viewport { w:%f, h:%f }",
3484                     priv->viewport[2], priv->viewport[3]);
3485
3486       cogl_set_viewport (priv->viewport[0],
3487                          priv->viewport[1],
3488                          priv->viewport[2],
3489                          priv->viewport[3]);
3490
3491       perspective = priv->perspective;
3492
3493       /* Ideally we want to regenerate the perspective matrix whenever
3494        * the size changes but if the user has provided a custom matrix
3495        * then we don't want to override it */
3496       if (!priv->has_custom_perspective)
3497         {
3498           perspective.aspect = priv->viewport[2] / priv->viewport[3];
3499           z_2d = calculate_z_translation (perspective.z_near);
3500
3501 #define _DEG_TO_RAD (G_PI / 180.0)
3502           /* NB: z_2d is only enough room for 85% of the stage_height between
3503            * the stage and the z_near plane. For behind the stage plane we
3504            * want a more consistent gap of 10 times the stage_height before
3505            * hitting the far plane so we calculate that relative to the final
3506            * height of the stage plane at the z_2d_distance we got... */
3507           perspective.z_far = z_2d +
3508             tanf ((perspective.fovy / 2.0f) * _DEG_TO_RAD) * z_2d * 20.0f;
3509 #undef _DEG_TO_RAD
3510
3511           clutter_stage_set_perspective_internal (stage, &perspective);
3512         }
3513       else
3514         z_2d = calculate_z_translation (perspective.z_near);
3515
3516       cogl_matrix_init_identity (&priv->view);
3517       cogl_matrix_view_2d_in_perspective (&priv->view,
3518                                           perspective.fovy,
3519                                           perspective.aspect,
3520                                           perspective.z_near,
3521                                           z_2d,
3522                                           priv->viewport[2],
3523                                           priv->viewport[3]);
3524
3525       priv->dirty_viewport = FALSE;
3526     }
3527
3528   if (priv->dirty_projection)
3529     {
3530       cogl_set_projection_matrix (&priv->projection);
3531
3532       priv->dirty_projection = FALSE;
3533     }
3534 }
3535
3536 /**
3537  * clutter_stage_ensure_redraw:
3538  * @stage: a #ClutterStage
3539  *
3540  * Ensures that @stage is redrawn
3541  *
3542  * This function should not be called by applications: it is
3543  * used when embedding a #ClutterStage into a toolkit with
3544  * another windowing system, like GTK+.
3545  *
3546  * Since: 1.0
3547  */
3548 void
3549 clutter_stage_ensure_redraw (ClutterStage *stage)
3550 {
3551   ClutterMasterClock *master_clock;
3552   ClutterStagePrivate *priv;
3553
3554   g_return_if_fail (CLUTTER_IS_STAGE (stage));
3555
3556   priv = stage->priv;
3557   priv->relayout_pending = TRUE;
3558   priv->redraw_pending = TRUE;
3559
3560   master_clock = _clutter_master_clock_get_default ();
3561   _clutter_master_clock_start_running (master_clock);
3562 }
3563
3564 /**
3565  * clutter_stage_queue_redraw:
3566  * @stage: the #ClutterStage
3567  *
3568  * Queues a redraw for the passed stage.
3569  *
3570  * <note>Applications should call clutter_actor_queue_redraw() and not
3571  * this function.</note>
3572  *
3573  * Since: 0.8
3574  *
3575  * Deprecated: 1.10: Use clutter_actor_queue_redraw() instead.
3576  */
3577 void
3578 clutter_stage_queue_redraw (ClutterStage *stage)
3579 {
3580   g_return_if_fail (CLUTTER_IS_STAGE (stage));
3581
3582   clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
3583 }
3584
3585 /**
3586  * clutter_stage_is_default:
3587  * @stage: a #ClutterStage
3588  *
3589  * Checks if @stage is the default stage, or an instance created using
3590  * clutter_stage_new() but internally using the same implementation.
3591  *
3592  * Return value: %TRUE if the passed stage is the default one
3593  *
3594  * Since: 0.8
3595  *
3596  * Deprecated: 1.10: Track the stage pointer inside your application
3597  *   code, or use clutter_actor_get_stage() to retrieve the stage for
3598  *   a given actor.
3599  */
3600 gboolean
3601 clutter_stage_is_default (ClutterStage *stage)
3602 {
3603   g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE);
3604
3605   return stage_is_default (stage);
3606 }
3607
3608 void
3609 _clutter_stage_set_window (ClutterStage       *stage,
3610                            ClutterStageWindow *stage_window)
3611 {
3612   g_return_if_fail (CLUTTER_IS_STAGE (stage));
3613   g_return_if_fail (CLUTTER_IS_STAGE_WINDOW (stage_window));
3614
3615   if (stage->priv->impl != NULL)
3616     g_object_unref (stage->priv->impl);
3617
3618   stage->priv->impl = stage_window;
3619 }
3620
3621 ClutterStageWindow *
3622 _clutter_stage_get_window (ClutterStage *stage)
3623 {
3624   g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL);
3625
3626   return CLUTTER_STAGE_WINDOW (stage->priv->impl);
3627 }
3628
3629 ClutterStageWindow *
3630 _clutter_stage_get_default_window (void)
3631 {
3632   ClutterStageManager *manager = clutter_stage_manager_get_default ();
3633   ClutterStage *stage;
3634
3635   stage = clutter_stage_manager_get_default_stage (manager);
3636   if (stage == NULL)
3637     return NULL;
3638
3639   return _clutter_stage_get_window (stage);
3640 }
3641
3642 /**
3643  * clutter_stage_set_throttle_motion_events:
3644  * @stage: a #ClutterStage
3645  * @throttle: %TRUE to throttle motion events
3646  *
3647  * Sets whether motion events received between redraws should
3648  * be throttled or not. If motion events are throttled, those
3649  * events received by the windowing system between redraws will
3650  * be compressed so that only the last event will be propagated
3651  * to the @stage and its actors.
3652  *
3653  * This function should only be used if you want to have all
3654  * the motion events delivered to your application code.
3655  *
3656  * Since: 1.0
3657  */
3658 void
3659 clutter_stage_set_throttle_motion_events (ClutterStage *stage,
3660                                           gboolean      throttle)
3661 {
3662   ClutterStagePrivate *priv;
3663
3664   g_return_if_fail (CLUTTER_IS_STAGE (stage));
3665
3666   priv = stage->priv;
3667
3668   if (priv->throttle_motion_events != throttle)
3669     priv->throttle_motion_events = throttle;
3670 }
3671
3672 /**
3673  * clutter_stage_get_throttle_motion_events:
3674  * @stage: a #ClutterStage
3675  *
3676  * Retrieves the value set with clutter_stage_set_throttle_motion_events()
3677  *
3678  * Return value: %TRUE if the motion events are being throttled,
3679  *   and %FALSE otherwise
3680  *
3681  * Since: 1.0
3682  */
3683 gboolean
3684 clutter_stage_get_throttle_motion_events (ClutterStage *stage)
3685 {
3686   g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE);
3687
3688   return stage->priv->throttle_motion_events;
3689 }
3690
3691 /**
3692  * clutter_stage_set_use_alpha:
3693  * @stage: a #ClutterStage
3694  * @use_alpha: whether the stage should honour the opacity or the
3695  *   alpha channel of the stage color
3696  *
3697  * Sets whether the @stage should honour the #ClutterActor:opacity and
3698  * the alpha channel of the #ClutterStage:color
3699  *
3700  * Since: 1.2
3701  */
3702 void
3703 clutter_stage_set_use_alpha (ClutterStage *stage,
3704                              gboolean      use_alpha)
3705 {
3706   ClutterStagePrivate *priv;
3707
3708   g_return_if_fail (CLUTTER_IS_STAGE (stage));
3709
3710   priv = stage->priv;
3711
3712   if (priv->use_alpha != use_alpha)
3713     {
3714       priv->use_alpha = use_alpha;
3715
3716       clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
3717
3718       g_object_notify (G_OBJECT (stage), "use-alpha");
3719     }
3720 }
3721
3722 /**
3723  * clutter_stage_get_use_alpha:
3724  * @stage: a #ClutterStage
3725  *
3726  * Retrieves the value set using clutter_stage_set_use_alpha()
3727  *
3728  * Return value: %TRUE if the stage should honour the opacity and the
3729  *   alpha channel of the stage color
3730  *
3731  * Since: 1.2
3732  */
3733 gboolean
3734 clutter_stage_get_use_alpha (ClutterStage *stage)
3735 {
3736   g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE);
3737
3738   return stage->priv->use_alpha;
3739 }
3740
3741 /**
3742  * clutter_stage_set_minimum_size:
3743  * @stage: a #ClutterStage
3744  * @width: width, in pixels
3745  * @height: height, in pixels
3746  *
3747  * Sets the minimum size for a stage window, if the default backend
3748  * uses #ClutterStage inside a window
3749  *
3750  * This is a convenience function, and it is equivalent to setting the
3751  * #ClutterActor:min-width and #ClutterActor:min-height on @stage
3752  *
3753  * If the current size of @stage is smaller than the minimum size, the
3754  * @stage will be resized to the new @width and @height
3755  *
3756  * This function has no effect if @stage is fullscreen
3757  *
3758  * Since: 1.2
3759  */
3760 void
3761 clutter_stage_set_minimum_size (ClutterStage *stage,
3762                                 guint         width,
3763                                 guint         height)
3764 {
3765   g_return_if_fail (CLUTTER_IS_STAGE (stage));
3766   g_return_if_fail ((width > 0) && (height > 0));
3767
3768   g_object_set (G_OBJECT (stage),
3769                 "min-width", (gfloat) width,
3770                 "min-height", (gfloat )height,
3771                 NULL);
3772 }
3773
3774 /**
3775  * clutter_stage_get_minimum_size:
3776  * @stage: a #ClutterStage
3777  * @width: (out): return location for the minimum width, in pixels,
3778  *   or %NULL
3779  * @height: (out): return location for the minimum height, in pixels,
3780  *   or %NULL
3781  *
3782  * Retrieves the minimum size for a stage window as set using
3783  * clutter_stage_set_minimum_size().
3784  *
3785  * The returned size may not correspond to the actual minimum size and
3786  * it is specific to the #ClutterStage implementation inside the
3787  * Clutter backend
3788  *
3789  * Since: 1.2
3790  */
3791 void
3792 clutter_stage_get_minimum_size (ClutterStage *stage,
3793                                 guint        *width_p,
3794                                 guint        *height_p)
3795 {
3796   gfloat width, height;
3797   gboolean width_set, height_set;
3798
3799   g_return_if_fail (CLUTTER_IS_STAGE (stage));
3800
3801   g_object_get (G_OBJECT (stage),
3802                 "min-width", &width,
3803                 "min-width-set", &width_set,
3804                 "min-height", &height,
3805                 "min-height-set", &height_set,
3806                 NULL);
3807
3808   /* if not width or height have been set, then the Stage
3809    * minimum size is defined to be 1x1
3810    */
3811   if (!width_set)
3812     width = 1;
3813
3814   if (!height_set)
3815     height = 1;
3816
3817   if (width_p)
3818     *width_p = (guint) width;
3819
3820   if (height_p)
3821     *height_p = (guint) height;
3822 }
3823
3824 /* Returns the number of swap buffers pending completion for the stage */
3825 int
3826 _clutter_stage_get_pending_swaps (ClutterStage *stage)
3827 {
3828   ClutterStageWindow *stage_window;
3829
3830   if (CLUTTER_ACTOR_IN_DESTRUCTION (stage))
3831     return 0;
3832
3833   stage_window = _clutter_stage_get_window (stage);
3834   if (stage_window == NULL)
3835     return 0;
3836
3837   return _clutter_stage_window_get_pending_swaps (stage_window);
3838 }
3839
3840 /**
3841  * clutter_stage_set_no_clear_hint:
3842  * @stage: a #ClutterStage
3843  * @no_clear: %TRUE if the @stage should not clear itself on every
3844  *   repaint cycle
3845  *
3846  * Sets whether the @stage should clear itself at the beginning
3847  * of each paint cycle or not.
3848  *
3849  * Clearing the #ClutterStage can be a costly operation, especially
3850  * if the stage is always covered - for instance, in a full-screen
3851  * video player or in a game with a background texture.
3852  *
3853  * <note><para>This setting is a hint; Clutter might discard this
3854  * hint depending on its internal state.</para></note>
3855  *
3856  * <warning><para>If parts of the stage are visible and you disable
3857  * clearing you might end up with visual artifacts while painting the
3858  * contents of the stage.</para></warning>
3859  *
3860  * Since: 1.4
3861  */
3862 void
3863 clutter_stage_set_no_clear_hint (ClutterStage *stage,
3864                                  gboolean      no_clear)
3865 {
3866   ClutterStagePrivate *priv;
3867   ClutterStageHint new_hints;
3868
3869   g_return_if_fail (CLUTTER_IS_STAGE (stage));
3870
3871   priv = stage->priv;
3872   new_hints = priv->stage_hints;
3873
3874   if (no_clear)
3875     new_hints |= CLUTTER_STAGE_NO_CLEAR_ON_PAINT;
3876   else
3877     new_hints &= ~CLUTTER_STAGE_NO_CLEAR_ON_PAINT;
3878
3879   if (priv->stage_hints == new_hints)
3880     return;
3881
3882   priv->stage_hints = new_hints;
3883
3884   g_object_notify (G_OBJECT (stage), "no-clear-hint");
3885 }
3886
3887 /**
3888  * clutter_stage_get_no_clear_hint:
3889  * @stage: a #ClutterStage
3890  *
3891  * Retrieves the hint set with clutter_stage_set_no_clear_hint()
3892  *
3893  * Return value: %TRUE if the stage should not clear itself on every paint
3894  *   cycle, and %FALSE otherwise
3895  *
3896  * Since: 1.4
3897  */
3898 gboolean
3899 clutter_stage_get_no_clear_hint (ClutterStage *stage)
3900 {
3901   g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE);
3902
3903   return (stage->priv->stage_hints & CLUTTER_STAGE_NO_CLEAR_ON_PAINT) != 0;
3904 }
3905
3906 ClutterPaintVolume *
3907 _clutter_stage_paint_volume_stack_allocate (ClutterStage *stage)
3908 {
3909   GArray *paint_volume_stack = stage->priv->paint_volume_stack;
3910
3911   g_array_set_size (paint_volume_stack,
3912                     paint_volume_stack->len+1);
3913
3914   return &g_array_index (paint_volume_stack,
3915                          ClutterPaintVolume,
3916                          paint_volume_stack->len - 1);
3917 }
3918
3919 void
3920 _clutter_stage_paint_volume_stack_free_all (ClutterStage *stage)
3921 {
3922   GArray *paint_volume_stack = stage->priv->paint_volume_stack;
3923   int i;
3924
3925   for (i = 0; i < paint_volume_stack->len; i++)
3926     {
3927       ClutterPaintVolume *pv =
3928         &g_array_index (paint_volume_stack, ClutterPaintVolume, i);
3929       clutter_paint_volume_free (pv);
3930     }
3931
3932   g_array_set_size (paint_volume_stack, 0);
3933 }
3934
3935 /* The is an out-of-band paramater available while painting that
3936  * can be used to cull actors. */
3937 const ClutterPlane *
3938 _clutter_stage_get_clip (ClutterStage *stage)
3939 {
3940   return stage->priv->current_clip_planes;
3941 }
3942
3943 /* When an actor queues a redraw we add it to a list on the stage that
3944  * gets processed once all updates to the stage have been finished.
3945  *
3946  * This deferred approach to processing queue_redraw requests means
3947  * that we can avoid redundant transformations of clip volumes if
3948  * something later triggers a full stage redraw anyway. It also means
3949  * we can be more sure that all the referenced actors will have valid
3950  * allocations improving the chance that we can determine the actors
3951  * paint volume so we can clip the redraw request even if the user
3952  * didn't explicitly do so.
3953  */
3954 ClutterStageQueueRedrawEntry *
3955 _clutter_stage_queue_actor_redraw (ClutterStage *stage,
3956                                    ClutterStageQueueRedrawEntry *entry,
3957                                    ClutterActor *actor,
3958                                    ClutterPaintVolume *clip)
3959 {
3960   ClutterStagePrivate *priv = stage->priv;
3961
3962   CLUTTER_NOTE (CLIPPING, "stage_queue_actor_redraw (actor=%s, clip=%p): ",
3963                 _clutter_actor_get_debug_name (actor), clip);
3964
3965   if (!priv->redraw_pending)
3966     {
3967       ClutterMasterClock *master_clock;
3968
3969       CLUTTER_NOTE (PAINT, "First redraw request");
3970
3971       priv->redraw_pending = TRUE;
3972
3973       master_clock = _clutter_master_clock_get_default ();
3974       _clutter_master_clock_start_running (master_clock);
3975     }
3976 #ifdef CLUTTER_ENABLE_DEBUG
3977   else
3978     {
3979       CLUTTER_NOTE (PAINT, "Redraw request number %lu",
3980                     priv->redraw_count + 1);
3981
3982       priv->redraw_count += 1;
3983     }
3984 #endif /* CLUTTER_ENABLE_DEBUG */
3985
3986   /* We have an optimization in _clutter_stage_do_pick to detect when
3987    * the scene is static so we can cache a full, un-clipped pick
3988    * buffer to avoid continuous pick renders.
3989    *
3990    * Currently the assumption is that actors queue a redraw when some
3991    * state changes that affects painting *or* picking so we can use
3992    * this point to invalidate any currently cached pick buffer.
3993    */
3994   _clutter_stage_set_pick_buffer_valid (stage, FALSE, -1);
3995
3996   if (entry)
3997     {
3998       /* Ignore all requests to queue a redraw for an actor if a full
3999        * (non-clipped) redraw of the actor has already been queued. */
4000       if (!entry->has_clip)
4001         {
4002           CLUTTER_NOTE (CLIPPING, "Bail from stage_queue_actor_redraw (%s): "
4003                         "Unclipped redraw of actor already queued",
4004                         _clutter_actor_get_debug_name (actor));
4005           return entry;
4006         }
4007
4008       /* If queuing a clipped redraw and a clipped redraw has
4009        * previously been queued for this actor then combine the latest
4010        * clip together with the existing clip */
4011       if (clip)
4012         clutter_paint_volume_union (&entry->clip, clip);
4013       else
4014         {
4015           clutter_paint_volume_free (&entry->clip);
4016           entry->has_clip = FALSE;
4017         }
4018       return entry;
4019     }
4020   else
4021     {
4022       entry = g_slice_new (ClutterStageQueueRedrawEntry);
4023       entry->actor = g_object_ref (actor);
4024
4025       if (clip)
4026         {
4027           entry->has_clip = TRUE;
4028           _clutter_paint_volume_init_static (&entry->clip, actor);
4029           _clutter_paint_volume_set_from_volume (&entry->clip, clip);
4030         }
4031       else
4032         entry->has_clip = FALSE;
4033
4034       stage->priv->pending_queue_redraws =
4035         g_list_prepend (stage->priv->pending_queue_redraws, entry);
4036
4037       return entry;
4038     }
4039 }
4040
4041 static void
4042 free_queue_redraw_entry (ClutterStageQueueRedrawEntry *entry)
4043 {
4044   if (entry->actor)
4045     g_object_unref (entry->actor);
4046   if (entry->has_clip)
4047     clutter_paint_volume_free (&entry->clip);
4048   g_slice_free (ClutterStageQueueRedrawEntry, entry);
4049 }
4050
4051 void
4052 _clutter_stage_queue_redraw_entry_invalidate (ClutterStageQueueRedrawEntry *entry)
4053 {
4054   if (entry == NULL)
4055     return;
4056
4057   if (entry->actor != NULL)
4058     {
4059       g_object_unref (entry->actor);
4060       entry->actor = NULL;
4061     }
4062
4063   if (entry->has_clip)
4064     {
4065       clutter_paint_volume_free (&entry->clip);
4066       entry->has_clip = FALSE;
4067     }
4068 }
4069
4070 static void
4071 _clutter_stage_maybe_finish_queue_redraws (ClutterStage *stage)
4072 {
4073   /* Note: we have to repeat until the pending_queue_redraws list is
4074    * empty because actors are allowed to queue redraws in response to
4075    * the queue-redraw signal. For example Clone actors or
4076    * texture_new_from_actor actors will have to queue a redraw if
4077    * their source queues a redraw.
4078    */
4079   while (stage->priv->pending_queue_redraws)
4080     {
4081       GList *l;
4082       /* XXX: we need to allow stage->priv->pending_queue_redraws to
4083        * be updated while we process the current entries in the list
4084        * so we steal the list pointer and then reset it to an empty
4085        * list before processing... */
4086       GList *stolen_list = stage->priv->pending_queue_redraws;
4087       stage->priv->pending_queue_redraws = NULL;
4088
4089       for (l = stolen_list; l; l = l->next)
4090         {
4091           ClutterStageQueueRedrawEntry *entry = l->data;
4092           ClutterPaintVolume *clip;
4093
4094           /* NB: Entries may be invalidated if the actor gets destroyed */
4095           if (G_LIKELY (entry->actor != NULL))
4096             {
4097               clip = entry->has_clip ? &entry->clip : NULL;
4098
4099               _clutter_actor_finish_queue_redraw (entry->actor, clip);
4100             }
4101
4102           free_queue_redraw_entry (entry);
4103         }
4104       g_list_free (stolen_list);
4105     }
4106 }
4107
4108 /**
4109  * clutter_stage_set_accept_focus:
4110  * @stage: a #ClutterStage
4111  * @accept_focus: %TRUE to accept focus on show
4112  *
4113  * Sets whether the @stage should accept the key focus when shown.
4114  *
4115  * This function should be called before showing @stage using
4116  * clutter_actor_show().
4117  *
4118  * Since: 1.6
4119  */
4120 void
4121 clutter_stage_set_accept_focus (ClutterStage *stage,
4122                                 gboolean      accept_focus)
4123 {
4124   ClutterStagePrivate *priv;
4125
4126   g_return_if_fail (CLUTTER_IS_STAGE (stage));
4127
4128   accept_focus = !!accept_focus;
4129
4130   priv = stage->priv;
4131
4132   if (priv->accept_focus != accept_focus)
4133     {
4134       _clutter_stage_window_set_accept_focus (priv->impl, accept_focus);
4135       g_object_notify (G_OBJECT (stage), "accept-focus");
4136     }
4137 }
4138
4139 /**
4140  * clutter_stage_get_accept_focus:
4141  * @stage: a #ClutterStage
4142  *
4143  * Retrieves the value set with clutter_stage_set_accept_focus().
4144  *
4145  * Return value: %TRUE if the #ClutterStage should accept focus, and %FALSE
4146  *   otherwise
4147  *
4148  * Since: 1.6
4149  */
4150 gboolean
4151 clutter_stage_get_accept_focus (ClutterStage *stage)
4152 {
4153   g_return_val_if_fail (CLUTTER_IS_STAGE (stage), TRUE);
4154
4155   return stage->priv->accept_focus;
4156 }
4157
4158 void
4159 _clutter_stage_add_device (ClutterStage       *stage,
4160                            ClutterInputDevice *device)
4161 {
4162   ClutterStagePrivate *priv = stage->priv;
4163
4164   if (g_hash_table_lookup (priv->devices, device) != NULL)
4165     return;
4166
4167   g_hash_table_insert (priv->devices, device, GINT_TO_POINTER (1));
4168   _clutter_input_device_set_stage (device, stage);
4169 }
4170
4171 void
4172 _clutter_stage_remove_device (ClutterStage       *stage,
4173                               ClutterInputDevice *device)
4174 {
4175   ClutterStagePrivate *priv = stage->priv;
4176
4177   _clutter_input_device_set_stage (device, NULL);
4178   g_hash_table_remove (priv->devices, device);
4179 }
4180
4181 gboolean
4182 _clutter_stage_has_device (ClutterStage       *stage,
4183                            ClutterInputDevice *device)
4184 {
4185   ClutterStagePrivate *priv = stage->priv;
4186
4187   return g_hash_table_lookup (priv->devices, device) != NULL;
4188 }
4189
4190 /**
4191  * clutter_stage_set_motion_events_enabled:
4192  * @stage: a #ClutterStage
4193  * @enabled: %TRUE to enable the motion events delivery, and %FALSE
4194  *   otherwise
4195  *
4196  * Sets whether per-actor motion events (and relative crossing
4197  * events) should be disabled or not.
4198  *
4199  * The default is %TRUE.
4200  *
4201  * If @enable is %FALSE the following events will not be delivered
4202  * to the actors children of @stage.
4203  *
4204  * <itemizedlist>
4205  *   <listitem><para>#ClutterActor::motion-event</para></listitem>
4206  *   <listitem><para>#ClutterActor::enter-event</para></listitem>
4207  *   <listitem><para>#ClutterActor::leave-event</para></listitem>
4208  * </itemizedlist>
4209  *
4210  * The events will still be delivered to the #ClutterStage.
4211  *
4212  * The main side effect of this function is that disabling the motion
4213  * events will disable picking to detect the #ClutterActor underneath
4214  * the pointer for each motion event. This is useful, for instance,
4215  * when dragging a #ClutterActor across the @stage: the actor underneath
4216  * the pointer is not going to change, so it's meaningless to perform
4217  * a pick.
4218  *
4219  * Since: 1.8
4220  */
4221 void
4222 clutter_stage_set_motion_events_enabled (ClutterStage *stage,
4223                                          gboolean      enabled)
4224 {
4225   ClutterStagePrivate *priv;
4226
4227   g_return_if_fail (CLUTTER_IS_STAGE (stage));
4228
4229   priv = stage->priv;
4230
4231   enabled = !!enabled;
4232
4233   if (priv->motion_events_enabled != enabled)
4234     priv->motion_events_enabled = enabled;
4235 }
4236
4237 /**
4238  * clutter_stage_get_motion_events_enabled:
4239  * @stage: a #ClutterStage
4240  *
4241  * Retrieves the value set using clutter_stage_set_motion_events_enabled().
4242  *
4243  * Return value: %TRUE if the per-actor motion event delivery is enabled
4244  *   and %FALSE otherwise
4245  *
4246  * Since: 1.8
4247  */
4248 gboolean
4249 clutter_stage_get_motion_events_enabled (ClutterStage *stage)
4250 {
4251   g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE);
4252
4253   return stage->priv->motion_events_enabled;
4254 }
4255
4256 /* NB: The presumption shouldn't be that a stage can't be comprised
4257  * of multiple internal framebuffers, so instead of simply naming
4258  * this function _clutter_stage_get_framebuffer(), the "active"
4259  * infix is intended to clarify that it gets the framebuffer that
4260  * is currently in use/being painted.
4261  */
4262 CoglFramebuffer *
4263 _clutter_stage_get_active_framebuffer (ClutterStage *stage)
4264 {
4265   return stage->priv->active_framebuffer;
4266 }
4267
4268 gint32
4269 _clutter_stage_acquire_pick_id (ClutterStage *stage,
4270                                 ClutterActor *actor)
4271 {
4272   ClutterStagePrivate *priv = stage->priv;
4273
4274   g_assert (priv->pick_id_pool != NULL);
4275
4276   return _clutter_id_pool_add (priv->pick_id_pool, actor);
4277 }
4278
4279 void
4280 _clutter_stage_release_pick_id (ClutterStage *stage,
4281                                 gint32        pick_id)
4282 {
4283   ClutterStagePrivate *priv = stage->priv;
4284
4285   g_assert (priv->pick_id_pool != NULL);
4286
4287   _clutter_id_pool_remove (priv->pick_id_pool, pick_id);
4288 }
4289
4290 ClutterActor *
4291 _clutter_stage_get_actor_by_pick_id (ClutterStage *stage,
4292                                      gint32        pick_id)
4293 {
4294   ClutterStagePrivate *priv = stage->priv;
4295
4296   g_assert (priv->pick_id_pool != NULL);
4297
4298   return _clutter_id_pool_lookup (priv->pick_id_pool, pick_id);
4299 }
4300
4301 void
4302 _clutter_stage_add_drag_actor (ClutterStage       *stage,
4303                                ClutterInputDevice *device,
4304                                ClutterActor       *actor)
4305 {
4306   GHashTable *drag_actors;
4307
4308   drag_actors = g_object_get_data (G_OBJECT (stage), "__clutter_stage_drag_actors");
4309   if (drag_actors == NULL)
4310     {
4311       drag_actors = g_hash_table_new (NULL, NULL);
4312       g_object_set_data_full (G_OBJECT (stage), "__clutter_stage_drag_actors",
4313                               drag_actors,
4314                               (GDestroyNotify) g_hash_table_destroy);
4315     }
4316
4317   g_hash_table_replace (drag_actors, device, actor);
4318 }
4319
4320 ClutterActor *
4321 _clutter_stage_get_drag_actor (ClutterStage       *stage,
4322                                ClutterInputDevice *device)
4323 {
4324   GHashTable *drag_actors;
4325
4326   drag_actors = g_object_get_data (G_OBJECT (stage), "__clutter_stage_drag_actors");
4327   if (drag_actors == NULL)
4328     return NULL;
4329
4330   return g_hash_table_lookup (drag_actors, device);
4331 }
4332
4333 void
4334 _clutter_stage_remove_drag_actor (ClutterStage       *stage,
4335                                   ClutterInputDevice *device)
4336 {
4337   GHashTable *drag_actors;
4338
4339   drag_actors = g_object_get_data (G_OBJECT (stage), "__clutter_stage_drag_actors");
4340   if (drag_actors == NULL)
4341     return;
4342
4343   g_hash_table_remove (drag_actors, device);
4344
4345   if (g_hash_table_size (drag_actors) == 0)
4346     g_object_set_data (G_OBJECT (stage), "__clutter_stage_drag_actors", NULL);
4347 }
4348
4349 /*< private >
4350  * _clutter_stage_get_state:
4351  * @stage: a #ClutterStage
4352  *
4353  * Retrieves the current #ClutterStageState flags associated to the @stage.
4354  *
4355  * Return value: a bitwise OR of #ClutterStageState flags
4356  */
4357 ClutterStageState
4358 _clutter_stage_get_state (ClutterStage *stage)
4359 {
4360   return stage->priv->current_state;
4361 }
4362
4363 /*< private >
4364  * _clutter_stage_is_activated:
4365  * @stage: a #ClutterStage
4366  *
4367  * Checks whether the @stage state includes %CLUTTER_STAGE_STATE_ACTIVATED.
4368  *
4369  * Return value: %TRUE if the @stage is active
4370  */
4371 gboolean
4372 _clutter_stage_is_activated (ClutterStage *stage)
4373 {
4374   return (stage->priv->current_state & CLUTTER_STAGE_STATE_ACTIVATED) != 0;
4375 }
4376
4377 /*< private >
4378  * _clutter_stage_is_fullscreen:
4379  * @stage: a #ClutterStage
4380  *
4381  * Checks whether the @stage state includes %CLUTTER_STAGE_STATE_FULLSCREEN.
4382  *
4383  * Return value: %TRUE if the @stage is fullscreen
4384  */
4385 gboolean
4386 _clutter_stage_is_fullscreen (ClutterStage *stage)
4387 {
4388   return (stage->priv->current_state & CLUTTER_STAGE_STATE_FULLSCREEN) != 0;
4389 }
4390
4391 /*< private >
4392  * _clutter_stage_update_state:
4393  * @stage: a #ClutterStage
4394  * @unset_flags: flags to unset
4395  * @set_flags: flags to set
4396  *
4397  * Updates the state of @stage, by unsetting the @unset_flags and setting
4398  * the @set_flags.
4399  *
4400  * If the stage state has been changed, this function will queue a
4401  * #ClutterEvent of type %CLUTTER_STAGE_STATE.
4402  *
4403  * Return value: %TRUE if the state was updated, and %FALSE otherwise
4404  */
4405 gboolean
4406 _clutter_stage_update_state (ClutterStage      *stage,
4407                              ClutterStageState  unset_flags,
4408                              ClutterStageState  set_flags)
4409 {
4410   ClutterStageState new_state;
4411   ClutterEvent *event;
4412
4413   new_state = stage->priv->current_state;
4414   new_state |= set_flags;
4415   new_state &= ~unset_flags;
4416
4417   if (new_state == stage->priv->current_state)
4418     return FALSE;
4419
4420   event = clutter_event_new (CLUTTER_STAGE_STATE);
4421   clutter_event_set_stage (event, stage);
4422
4423   event->stage_state.new_state = new_state;
4424   event->stage_state.changed_mask = new_state ^ stage->priv->current_state;
4425
4426   stage->priv->current_state = new_state;
4427
4428   _clutter_event_push (event, FALSE);
4429
4430   return TRUE;
4431 }