ee33357fd5
The introduction of the StageManager in 0.8 implied that the first Stage instance to be created was automatically assigned the status of "default stage". This was all well and good, since the default stage was created behind the curtains by the initialization sequence. Now that the initialization sequence does not create a default stage any longer, it means that the first stage created using clutter_stage_new() gets to be the default, and all special and warm and fuzzy - which also means that the first stage created by clutter_stage_new() cannot be destroyed or handled as any other stage. Whoopsie. Let's go back to the old semantics: the stage created by the first invocation of clutter_stage_get_default() is the default stage, and nothing else can be set as default. One day we'll be able to break the API and the whole default stage business will be a thing of the past.
333 lines
9.1 KiB
C
333 lines
9.1 KiB
C
/*
|
|
* 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
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
|
|
#include "clutter-marshal.h"
|
|
#include "clutter-debug.h"
|
|
#include "clutter-private.h"
|
|
#include "clutter-version.h"
|
|
#include "clutter-stage-manager.h"
|
|
|
|
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;
|
|
GSList *l, *next;
|
|
|
|
stage_manager = CLUTTER_STAGE_MANAGER (gobject);
|
|
|
|
for (l = stage_manager->stages; l; l = next)
|
|
{
|
|
ClutterActor *stage = l->data;
|
|
next = l->next;
|
|
|
|
if (stage)
|
|
clutter_actor_destroy (stage);
|
|
}
|
|
|
|
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.
|
|
*
|
|
* Since: 0.8
|
|
*/
|
|
g_object_class_install_property (gobject_class,
|
|
PROP_DEFAULT_STAGE,
|
|
g_param_spec_object ("default-stage",
|
|
"Default Stage",
|
|
"The default stage",
|
|
CLUTTER_TYPE_STAGE,
|
|
CLUTTER_PARAM_READABLE));
|
|
|
|
/**
|
|
* ClutterStageManager::stage-added:
|
|
* @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.
|
|
*
|
|
* Since: 0.8
|
|
*/
|
|
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,
|
|
clutter_marshal_VOID__OBJECT,
|
|
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.
|
|
*
|
|
* Since: 0.8
|
|
*/
|
|
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,
|
|
clutter_marshal_VOID__OBJECT,
|
|
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.
|
|
*
|
|
* Return value: (transfer none): the default stage manager instance. The returned
|
|
* object is owned by Clutter and you should not reference or unreference it.
|
|
*
|
|
* Since: 0.8
|
|
*/
|
|
ClutterStageManager *
|
|
clutter_stage_manager_get_default (void)
|
|
{
|
|
static ClutterStageManager *stage_manager = NULL;
|
|
|
|
if (G_UNLIKELY (stage_manager == NULL))
|
|
stage_manager = g_object_new (CLUTTER_TYPE_STAGE_MANAGER, NULL);
|
|
|
|
return stage_manager;
|
|
}
|
|
|
|
/**
|
|
* 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)
|
|
{
|
|
}
|
|
|
|
/*
|
|
* _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
|
|
*
|
|
* This is called by clutter_stage_get_default() and should be removed
|
|
* along with #ClutterStageManager:default-stage when we stop having
|
|
* the default stage
|
|
*/
|
|
void
|
|
_clutter_stage_manager_set_default_stage (ClutterStageManager *stage_manager,
|
|
ClutterStage *stage)
|
|
{
|
|
if (G_UNLIKELY (default_stage == NULL))
|
|
{
|
|
default_stage = stage;
|
|
|
|
g_object_notify (G_OBJECT (stage_manager), "default-stage");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* clutter_stage_manager_get_default_stage:
|
|
* @stage_manager: a #ClutterStageManager
|
|
*
|
|
* Returns the default #ClutterStage.
|
|
*
|
|
* Return value: (transfer none): the default stage. The returned object
|
|
* is owned by Clutter and you should never reference or unreference it
|
|
*
|
|
* Since: 0.8
|
|
*/
|
|
ClutterStage *
|
|
clutter_stage_manager_get_default_stage (ClutterStageManager *stage_manager)
|
|
{
|
|
return default_stage;
|
|
}
|
|
|
|
/**
|
|
* clutter_stage_manager_list_stages:
|
|
* @stage_manager: a #ClutterStageManager
|
|
*
|
|
* Lists all currently used stages.
|
|
*
|
|
* Return value: (transfer container) (element-type ClutterStage): a newly
|
|
* allocated list of #ClutterStage objects. Use g_slist_free() to
|
|
* deallocate it when done.
|
|
*
|
|
* Since: 0.8
|
|
*/
|
|
GSList *
|
|
clutter_stage_manager_list_stages (ClutterStageManager *stage_manager)
|
|
{
|
|
return g_slist_copy (stage_manager->stages);
|
|
}
|
|
|
|
/**
|
|
* clutter_stage_manager_peek_stages:
|
|
* @stage_manager: a #ClutterStageManager
|
|
*
|
|
* Lists all currently used stages.
|
|
*
|
|
* Return value: (transfer none) (element-type ClutterStage): a pointer
|
|
* to the internal list of #ClutterStage objects. The returned list
|
|
* is owned by the #ClutterStageManager and should never be modified
|
|
* or freed
|
|
*
|
|
* Since: 1.0
|
|
*/
|
|
const GSList *
|
|
clutter_stage_manager_peek_stages (ClutterStageManager *stage_manager)
|
|
{
|
|
return stage_manager->stages;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
g_object_ref_sink (stage);
|
|
|
|
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)
|
|
{
|
|
/* this might be called multiple times from a ::dispose, so it
|
|
* needs to just return without warning
|
|
*/
|
|
if (!g_slist_find (stage_manager->stages, stage))
|
|
return;
|
|
|
|
stage_manager->stages = g_slist_remove (stage_manager->stages, stage);
|
|
|
|
/* if it's the default stage, get the first available from the list */
|
|
if (default_stage == stage)
|
|
default_stage = stage_manager->stages ? stage_manager->stages->data
|
|
: NULL;
|
|
|
|
g_signal_emit (stage_manager, manager_signals[STAGE_REMOVED], 0, stage);
|
|
|
|
g_object_unref (stage);
|
|
}
|