clutter-stage-manager.c 8.92 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
/*
 * Clutter.
 *
 * An OpenGL based 'interactive canvas' library.
 *
 * Copyright (C) 2008 OpenedHand
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
 *
 * Author: Emmanuele Bassi <ebassi@linux.intel.com>
 */

/**
 * SECTION:clutter-stage-manager
 * @short_description: Maintains the list of stages
 *
 * #ClutterStageManager is a singleton object, owned by Clutter, which
 * maintains the list of currently active stages
 *
 * Every newly-created #ClutterStage will cause the emission of the
 * #ClutterStageManager::stage-added signal; once a #ClutterStage has
 * been destroyed, the #ClutterStageManager::stage-removed signal will
 * be emitted
 *
 * #ClutterStageManager is available since Clutter 0.8
 */

39 40 41 42
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

43
#include "clutter-stage-manager-private.h"
44 45 46 47 48 49

#include "clutter-marshal.h"
#include "clutter-debug.h"
#include "clutter-private.h"
#include "clutter-version.h"  

50 51
#include "deprecated/clutter-stage-manager.h"

52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
enum
{
  PROP_0,
  PROP_DEFAULT_STAGE
};

enum
{
  STAGE_ADDED,
  STAGE_REMOVED,

  LAST_SIGNAL
};

static guint manager_signals[LAST_SIGNAL] = { 0, };
static ClutterStage *default_stage = NULL;

G_DEFINE_TYPE (ClutterStageManager, clutter_stage_manager, G_TYPE_OBJECT);

static void
clutter_stage_manager_get_property (GObject    *gobject,
                                    guint       prop_id,
                                    GValue     *value,
                                    GParamSpec *pspec)
{
  switch (prop_id)
    {
    case PROP_DEFAULT_STAGE:
      g_value_set_object (value, default_stage);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
      break;
    }
}

static void
clutter_stage_manager_dispose (GObject *gobject)
{
  ClutterStageManager *stage_manager;

  stage_manager = CLUTTER_STAGE_MANAGER (gobject);

95
  g_slist_foreach (stage_manager->stages, (GFunc) clutter_actor_destroy, NULL);
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
  g_slist_free (stage_manager->stages);
  stage_manager->stages = NULL;

  G_OBJECT_CLASS (clutter_stage_manager_parent_class)->dispose (gobject);
}

static void
clutter_stage_manager_class_init (ClutterStageManagerClass *klass)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);

  gobject_class->dispose      = clutter_stage_manager_dispose;
  gobject_class->get_property = clutter_stage_manager_get_property;

  /**
   * ClutterStageManager:default-stage:
   *
   * The default stage used by Clutter.
   *
115
   * Since: 0.8
116 117 118 119 120 121 122
   */
  g_object_class_install_property (gobject_class,
                                   PROP_DEFAULT_STAGE,
                                   g_param_spec_object ("default-stage",
                                                        "Default Stage",
                                                        "The default stage",
                                                        CLUTTER_TYPE_STAGE,
123
                                                        CLUTTER_PARAM_READABLE));
124 125

  /**
126
   * ClutterStageManager::stage-added:
127 128 129 130 131 132
   * @stage_manager: the object which received the signal
   * @stage: the added stage
   *
   * The ::stage-added signal is emitted each time a new #ClutterStage
   * has been added to the stage manager.
   *
133
   * Since: 0.8
134 135 136 137 138 139 140
   */
  manager_signals[STAGE_ADDED] =
    g_signal_new ("stage-added",
                  G_OBJECT_CLASS_TYPE (gobject_class),
                  G_SIGNAL_RUN_LAST,
                  G_STRUCT_OFFSET (ClutterStageManagerClass, stage_added),
                  NULL, NULL,
Emmanuele Bassi's avatar
Emmanuele Bassi committed
141
                  _clutter_marshal_VOID__OBJECT,
142 143 144 145 146 147 148 149 150 151
                  G_TYPE_NONE, 1,
                  CLUTTER_TYPE_STAGE);
  /**
   * ClutterStageManager::stage-removed:
   * @stage_manager: the object which received the signal
   * @stage: the removed stage
   *
   * The ::stage-removed signal is emitted each time a #ClutterStage
   * has been removed from the stage manager.
   *
152
   * Since: 0.8
153 154 155 156 157 158 159
   */
  manager_signals[STAGE_REMOVED] =
    g_signal_new ("stage-removed",
                  G_OBJECT_CLASS_TYPE (gobject_class),
                  G_SIGNAL_RUN_LAST,
                  G_STRUCT_OFFSET (ClutterStageManagerClass, stage_removed),
                  NULL, NULL,
Emmanuele Bassi's avatar
Emmanuele Bassi committed
160
                  _clutter_marshal_VOID__OBJECT,
161 162 163 164 165 166 167 168 169 170 171 172 173 174
                  G_TYPE_NONE, 1,
                  CLUTTER_TYPE_STAGE);
}

static void
clutter_stage_manager_init (ClutterStageManager *stage_manager)
{
}

/**
 * clutter_stage_manager_get_default:
 *
 * Returns the default #ClutterStageManager.
 *
175 176
 * Return value: (transfer none): the default stage manager instance. The returned
 *   object is owned by Clutter and you should not reference or unreference it.
177
 *
178
 * Since: 0.8
179 180 181 182
 */
ClutterStageManager *
clutter_stage_manager_get_default (void)
{
183
  ClutterMainContext *context = _clutter_context_get_default ();
184

185 186
  if (G_UNLIKELY (context->stage_manager == NULL))
    context->stage_manager = g_object_new (CLUTTER_TYPE_STAGE_MANAGER, NULL);
187

188
  return context->stage_manager;
189 190
}

191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
/**
 * clutter_stage_manager_set_default_stage:
 * @stage_manager: a #ClutterStageManager
 * @stage: a #ClutterStage
 *
 * Sets @stage as the default stage.
 *
 * Since: 0.8
 *
 * Deprecated: 1.2: Calling this function has no effect
 */
void
clutter_stage_manager_set_default_stage (ClutterStageManager *stage_manager,
                                         ClutterStage        *stage)
{
}

Emmanuele Bassi's avatar
Emmanuele Bassi committed
208
/*< private >
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
 * _clutter_stage_manager_set_default_stage:
 * @stage_manager: a #ClutterStageManager
 * @stage: a #ClutterStage
 *
 * Sets @stage as the default stage
 *
 * A no-op if there already is a default stage
 */
void
_clutter_stage_manager_set_default_stage (ClutterStageManager *stage_manager,
                                          ClutterStage        *stage)
{
  if (G_UNLIKELY (default_stage == NULL))
    {
      default_stage = stage;

Emmanuele Bassi's avatar
Emmanuele Bassi committed
225 226 227
      /* the default stage is immediately realized */
      clutter_actor_realize (CLUTTER_ACTOR (stage));

228 229 230 231
      g_object_notify (G_OBJECT (stage_manager), "default-stage");
    }
}

232 233 234 235 236 237
/**
 * clutter_stage_manager_get_default_stage:
 * @stage_manager: a #ClutterStageManager
 *
 * Returns the default #ClutterStage.
 *
238 239
 * Return value: (transfer none): the default stage. The returned object
 *   is owned by Clutter and you should never reference or unreference it
240
 *
241
 * Since: 0.8
242 243 244 245 246 247 248 249
 */
ClutterStage *
clutter_stage_manager_get_default_stage (ClutterStageManager *stage_manager)
{
  return default_stage;
}

/**
250
 * clutter_stage_manager_list_stages:
251 252 253 254
 * @stage_manager: a #ClutterStageManager
 *
 * Lists all currently used stages.
 *
255
 * Return value: (transfer container) (element-type Clutter.Stage): a newly
256 257
 *   allocated list of #ClutterStage objects. Use g_slist_free() to
 *   deallocate it when done.
258
 *
259
 * Since: 0.8
260 261 262 263 264 265 266
 */
GSList *
clutter_stage_manager_list_stages (ClutterStageManager *stage_manager)
{
  return g_slist_copy (stage_manager->stages);
}

267
/**
268
 * clutter_stage_manager_peek_stages:
269 270 271 272
 * @stage_manager: a #ClutterStageManager
 *
 * Lists all currently used stages.
 *
273
 * Return value: (transfer none) (element-type Clutter.Stage): a pointer
274 275 276 277
 *   to the internal list of #ClutterStage objects. The returned list
 *   is owned by the #ClutterStageManager and should never be modified
 *   or freed
 *
278
 * Since: 1.0
279 280 281 282 283 284 285
 */
const GSList *
clutter_stage_manager_peek_stages (ClutterStageManager *stage_manager)
{
  return stage_manager->stages;
}

286 287 288 289 290 291 292 293 294 295 296
void
_clutter_stage_manager_add_stage (ClutterStageManager *stage_manager,
                                  ClutterStage        *stage)
{
  if (g_slist_find (stage_manager->stages, stage))
    {
      g_warning ("Trying to add a stage to the list of managed stages, "
                 "but it is already in it, aborting.");
      return;
    }

297 298
  g_object_ref_sink (stage);

299 300 301 302 303 304 305 306 307
  stage_manager->stages = g_slist_append (stage_manager->stages, stage);

  g_signal_emit (stage_manager, manager_signals[STAGE_ADDED], 0, stage);
}

void
_clutter_stage_manager_remove_stage (ClutterStageManager *stage_manager,
                                     ClutterStage        *stage)
{
308 309 310
  /* this might be called multiple times from a ::dispose, so it
   * needs to just return without warning
   */
311
  if (!g_slist_find (stage_manager->stages, stage))
312
    return;
313 314 315

  stage_manager->stages = g_slist_remove (stage_manager->stages, stage);

Emmanuele Bassi's avatar
Emmanuele Bassi committed
316
  /* if the default stage is being destroyed then we unset the pointer */
317
  if (default_stage == stage)
Emmanuele Bassi's avatar
Emmanuele Bassi committed
318
    default_stage = NULL;
319 320 321

  g_signal_emit (stage_manager, manager_signals[STAGE_REMOVED], 0, stage);

322
  g_object_unref (stage);
323
}