Release Clutter 1.11.4 (snapshot)
[profile/ivi/clutter.git] / clutter / clutter-stage-manager.c
1 /*
2  * Clutter.
3  *
4  * An OpenGL based 'interactive canvas' library.
5  *
6  * Copyright (C) 2008 OpenedHand
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
20  *
21  * Author: Emmanuele Bassi <ebassi@linux.intel.com>
22  */
23
24 /**
25  * SECTION:clutter-stage-manager
26  * @short_description: Maintains the list of stages
27  *
28  * #ClutterStageManager is a singleton object, owned by Clutter, which
29  * maintains the list of currently active stages
30  *
31  * Every newly-created #ClutterStage will cause the emission of the
32  * #ClutterStageManager::stage-added signal; once a #ClutterStage has
33  * been destroyed, the #ClutterStageManager::stage-removed signal will
34  * be emitted
35  *
36  * #ClutterStageManager is available since Clutter 0.8
37  */
38
39 #ifdef HAVE_CONFIG_H
40 #include "config.h"
41 #endif
42
43 #include "clutter-stage-manager-private.h"
44
45 #include "clutter-marshal.h"
46 #include "clutter-debug.h"
47 #include "clutter-private.h"
48 #include "clutter-version.h"  
49
50 #include "deprecated/clutter-stage-manager.h"
51
52 enum
53 {
54   PROP_0,
55   PROP_DEFAULT_STAGE
56 };
57
58 enum
59 {
60   STAGE_ADDED,
61   STAGE_REMOVED,
62
63   LAST_SIGNAL
64 };
65
66 static guint manager_signals[LAST_SIGNAL] = { 0, };
67 static ClutterStage *default_stage = NULL;
68
69 G_DEFINE_TYPE (ClutterStageManager, clutter_stage_manager, G_TYPE_OBJECT);
70
71 static void
72 clutter_stage_manager_get_property (GObject    *gobject,
73                                     guint       prop_id,
74                                     GValue     *value,
75                                     GParamSpec *pspec)
76 {
77   switch (prop_id)
78     {
79     case PROP_DEFAULT_STAGE:
80       g_value_set_object (value, default_stage);
81       break;
82     default:
83       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
84       break;
85     }
86 }
87
88 static void
89 clutter_stage_manager_dispose (GObject *gobject)
90 {
91   ClutterStageManager *stage_manager;
92
93   stage_manager = CLUTTER_STAGE_MANAGER (gobject);
94
95   g_slist_foreach (stage_manager->stages, (GFunc) clutter_actor_destroy, NULL);
96   g_slist_free (stage_manager->stages);
97   stage_manager->stages = NULL;
98
99   G_OBJECT_CLASS (clutter_stage_manager_parent_class)->dispose (gobject);
100 }
101
102 static void
103 clutter_stage_manager_class_init (ClutterStageManagerClass *klass)
104 {
105   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
106
107   gobject_class->dispose      = clutter_stage_manager_dispose;
108   gobject_class->get_property = clutter_stage_manager_get_property;
109
110   /**
111    * ClutterStageManager:default-stage:
112    *
113    * The default stage used by Clutter.
114    *
115    * Since: 0.8
116    */
117   g_object_class_install_property (gobject_class,
118                                    PROP_DEFAULT_STAGE,
119                                    g_param_spec_object ("default-stage",
120                                                         "Default Stage",
121                                                         "The default stage",
122                                                         CLUTTER_TYPE_STAGE,
123                                                         CLUTTER_PARAM_READABLE));
124
125   /**
126    * ClutterStageManager::stage-added:
127    * @stage_manager: the object which received the signal
128    * @stage: the added stage
129    *
130    * The ::stage-added signal is emitted each time a new #ClutterStage
131    * has been added to the stage manager.
132    *
133    * Since: 0.8
134    */
135   manager_signals[STAGE_ADDED] =
136     g_signal_new ("stage-added",
137                   G_OBJECT_CLASS_TYPE (gobject_class),
138                   G_SIGNAL_RUN_LAST,
139                   G_STRUCT_OFFSET (ClutterStageManagerClass, stage_added),
140                   NULL, NULL,
141                   _clutter_marshal_VOID__OBJECT,
142                   G_TYPE_NONE, 1,
143                   CLUTTER_TYPE_STAGE);
144   /**
145    * ClutterStageManager::stage-removed:
146    * @stage_manager: the object which received the signal
147    * @stage: the removed stage
148    *
149    * The ::stage-removed signal is emitted each time a #ClutterStage
150    * has been removed from the stage manager.
151    *
152    * Since: 0.8
153    */
154   manager_signals[STAGE_REMOVED] =
155     g_signal_new ("stage-removed",
156                   G_OBJECT_CLASS_TYPE (gobject_class),
157                   G_SIGNAL_RUN_LAST,
158                   G_STRUCT_OFFSET (ClutterStageManagerClass, stage_removed),
159                   NULL, NULL,
160                   _clutter_marshal_VOID__OBJECT,
161                   G_TYPE_NONE, 1,
162                   CLUTTER_TYPE_STAGE);
163 }
164
165 static void
166 clutter_stage_manager_init (ClutterStageManager *stage_manager)
167 {
168 }
169
170 /**
171  * clutter_stage_manager_get_default:
172  *
173  * Returns the default #ClutterStageManager.
174  *
175  * Return value: (transfer none): the default stage manager instance. The returned
176  *   object is owned by Clutter and you should not reference or unreference it.
177  *
178  * Since: 0.8
179  */
180 ClutterStageManager *
181 clutter_stage_manager_get_default (void)
182 {
183   ClutterMainContext *context = _clutter_context_get_default ();
184
185   if (G_UNLIKELY (context->stage_manager == NULL))
186     context->stage_manager = g_object_new (CLUTTER_TYPE_STAGE_MANAGER, NULL);
187
188   return context->stage_manager;
189 }
190
191 /**
192  * clutter_stage_manager_set_default_stage:
193  * @stage_manager: a #ClutterStageManager
194  * @stage: a #ClutterStage
195  *
196  * Sets @stage as the default stage.
197  *
198  * Since: 0.8
199  *
200  * Deprecated: 1.2: Calling this function has no effect
201  */
202 void
203 clutter_stage_manager_set_default_stage (ClutterStageManager *stage_manager,
204                                          ClutterStage        *stage)
205 {
206 }
207
208 /*< private >
209  * _clutter_stage_manager_set_default_stage:
210  * @stage_manager: a #ClutterStageManager
211  * @stage: a #ClutterStage
212  *
213  * Sets @stage as the default stage
214  *
215  * A no-op if there already is a default stage
216  */
217 void
218 _clutter_stage_manager_set_default_stage (ClutterStageManager *stage_manager,
219                                           ClutterStage        *stage)
220 {
221   if (G_UNLIKELY (default_stage == NULL))
222     {
223       default_stage = stage;
224
225       /* the default stage is immediately realized */
226       clutter_actor_realize (CLUTTER_ACTOR (stage));
227
228       g_object_notify (G_OBJECT (stage_manager), "default-stage");
229     }
230 }
231
232 /**
233  * clutter_stage_manager_get_default_stage:
234  * @stage_manager: a #ClutterStageManager
235  *
236  * Returns the default #ClutterStage.
237  *
238  * Return value: (transfer none): the default stage. The returned object
239  *   is owned by Clutter and you should never reference or unreference it
240  *
241  * Since: 0.8
242  */
243 ClutterStage *
244 clutter_stage_manager_get_default_stage (ClutterStageManager *stage_manager)
245 {
246   return default_stage;
247 }
248
249 /**
250  * clutter_stage_manager_list_stages:
251  * @stage_manager: a #ClutterStageManager
252  *
253  * Lists all currently used stages.
254  *
255  * Return value: (transfer container) (element-type Clutter.Stage): a newly
256  *   allocated list of #ClutterStage objects. Use g_slist_free() to
257  *   deallocate it when done.
258  *
259  * Since: 0.8
260  */
261 GSList *
262 clutter_stage_manager_list_stages (ClutterStageManager *stage_manager)
263 {
264   return g_slist_copy (stage_manager->stages);
265 }
266
267 /**
268  * clutter_stage_manager_peek_stages:
269  * @stage_manager: a #ClutterStageManager
270  *
271  * Lists all currently used stages.
272  *
273  * Return value: (transfer none) (element-type Clutter.Stage): a pointer
274  *   to the internal list of #ClutterStage objects. The returned list
275  *   is owned by the #ClutterStageManager and should never be modified
276  *   or freed
277  *
278  * Since: 1.0
279  */
280 const GSList *
281 clutter_stage_manager_peek_stages (ClutterStageManager *stage_manager)
282 {
283   return stage_manager->stages;
284 }
285
286 void
287 _clutter_stage_manager_add_stage (ClutterStageManager *stage_manager,
288                                   ClutterStage        *stage)
289 {
290   if (g_slist_find (stage_manager->stages, stage))
291     {
292       g_warning ("Trying to add a stage to the list of managed stages, "
293                  "but it is already in it, aborting.");
294       return;
295     }
296
297   g_object_ref_sink (stage);
298
299   stage_manager->stages = g_slist_append (stage_manager->stages, stage);
300
301   g_signal_emit (stage_manager, manager_signals[STAGE_ADDED], 0, stage);
302 }
303
304 void
305 _clutter_stage_manager_remove_stage (ClutterStageManager *stage_manager,
306                                      ClutterStage        *stage)
307 {
308   /* this might be called multiple times from a ::dispose, so it
309    * needs to just return without warning
310    */
311   if (!g_slist_find (stage_manager->stages, stage))
312     return;
313
314   stage_manager->stages = g_slist_remove (stage_manager->stages, stage);
315
316   /* if the default stage is being destroyed then we unset the pointer */
317   if (default_stage == stage)
318     default_stage = NULL;
319
320   g_signal_emit (stage_manager, manager_signals[STAGE_REMOVED], 0, stage);
321
322   g_object_unref (stage);
323 }