diff --git a/clutter/clutter-actor-meta-private.h b/clutter/clutter-actor-meta-private.h index 39c76265b..e4d77316a 100644 --- a/clutter/clutter-actor-meta-private.h +++ b/clutter/clutter-actor-meta-private.h @@ -50,6 +50,20 @@ struct _ClutterMetaGroupClass GObjectClass parent_class; }; +/* Each actor meta has a priority with zero as a default. A higher + number means higher priority. Higher priority metas stay at the + beginning of the list. The priority can be negative to give lower + priority than the default. */ + +#define CLUTTER_ACTOR_META_PRIORITY_DEFAULT 0 + +/* Any value greater than this is considered an 'internal' priority + and if we expose the priority property publicly then an application + would not be able to use these values. */ + +#define CLUTTER_ACTOR_META_PRIORITY_INTERNAL_HIGH (G_MAXINT / 2) +#define CLUTTER_ACTOR_META_PRIORITY_INTERNAL_LOW (G_MININT / 2) + GType _clutter_meta_group_get_type (void) G_GNUC_CONST; void _clutter_meta_group_add_meta (ClutterMetaGroup *group, @@ -61,12 +75,24 @@ void _clutter_meta_group_clear_metas (ClutterMetaGroup *group); ClutterActorMeta * _clutter_meta_group_get_meta (ClutterMetaGroup *group, const gchar *name); +GList * +_clutter_meta_group_get_metas_no_internal (ClutterMetaGroup *group); + +void +_clutter_meta_group_clear_metas_no_internal (ClutterMetaGroup *group); + /* ActorMeta */ void _clutter_actor_meta_set_actor (ClutterActorMeta *meta, ClutterActor *actor); const gchar * _clutter_actor_meta_get_debug_name (ClutterActorMeta *meta); +void _clutter_actor_meta_set_priority (ClutterActorMeta *meta, + gint priority); +int _clutter_actor_meta_get_priority (ClutterActorMeta *meta); + +gboolean _clutter_actor_meta_is_internal (ClutterActorMeta *meta); + G_END_DECLS #endif /* __CLUTTER_ACTOR_META_PRIVATE_H__ */ diff --git a/clutter/clutter-actor-meta.c b/clutter/clutter-actor-meta.c index e2ebdaadf..68f856026 100644 --- a/clutter/clutter-actor-meta.c +++ b/clutter/clutter-actor-meta.c @@ -58,6 +58,8 @@ struct _ClutterActorMetaPrivate gchar *name; guint is_enabled : 1; + + gint priority; }; enum @@ -237,6 +239,8 @@ clutter_actor_meta_init (ClutterActorMeta *self) ClutterActorMetaPrivate); self->priv->is_enabled = TRUE; + + self->priv->priority = CLUTTER_ACTOR_META_PRIORITY_DEFAULT; } /** @@ -367,6 +371,40 @@ clutter_actor_meta_get_actor (ClutterActorMeta *meta) return meta->priv->actor; } +void +_clutter_actor_meta_set_priority (ClutterActorMeta *meta, + gint priority) +{ + g_return_if_fail (CLUTTER_IS_ACTOR_META (meta)); + + /* This property shouldn't be modified after the actor meta is in + use because ClutterMetaGroup doesn't resort the list when it + changes. If we made the priority public then we could either make + the priority a construct-only property or listen for + notifications on the property from the ClutterMetaGroup and + resort. */ + g_return_if_fail (meta->priv->actor == NULL); + + meta->priv->priority = priority; +} + +gint +_clutter_actor_meta_get_priority (ClutterActorMeta *meta) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR_META (meta), 0); + + return meta->priv->priority; +} + +gboolean +_clutter_actor_meta_is_internal (ClutterActorMeta *meta) +{ + gint priority = meta->priv->priority; + + return (priority <= CLUTTER_ACTOR_META_PRIORITY_INTERNAL_LOW || + priority >= CLUTTER_ACTOR_META_PRIORITY_INTERNAL_HIGH); +} + /* * ClutterMetaGroup: a collection of ClutterActorMeta instances */ @@ -408,6 +446,8 @@ void _clutter_meta_group_add_meta (ClutterMetaGroup *group, ClutterActorMeta *meta) { + GList *prev = NULL, *l; + if (meta->priv->actor != NULL) { g_warning ("The meta of type '%s' with name '%s' is " @@ -422,7 +462,22 @@ _clutter_meta_group_add_meta (ClutterMetaGroup *group, return; } - group->meta = g_list_append (group->meta, meta); + /* Find a meta that has lower priority and insert before that */ + for (l = group->meta; l; l = l->next) + if (_clutter_actor_meta_get_priority (l->data) < + _clutter_actor_meta_get_priority (meta)) + break; + else + prev = l; + + if (prev == NULL) + group->meta = g_list_prepend (group->meta, meta); + else + { + prev->next = g_list_prepend (prev->next, meta); + prev->next->prev = prev; + } + g_object_ref_sink (meta); _clutter_actor_meta_set_actor (meta, group->actor); @@ -473,6 +528,30 @@ _clutter_meta_group_peek_metas (ClutterMetaGroup *group) return group->meta; } +/* + * _clutter_meta_group_get_metas_no_internal: + * @group: a #ClutterMetaGroup + * + * Returns a new allocated list containing all of the metas that don't + * have an internal priority. + * + * Return value: A GList containing non-internal metas. Free with + * g_list_free. + */ +GList * +_clutter_meta_group_get_metas_no_internal (ClutterMetaGroup *group) +{ + GList *ret = NULL; + GList *l; + + /* Build a new list filtering out the internal metas */ + for (l = group->meta; l; l = l->next) + if (!_clutter_actor_meta_is_internal (l->data)) + ret = g_list_prepend (ret, l->data); + + return g_list_reverse (ret); +} + /* * _clutter_meta_group_clear_metas: * @group: a #ClutterMetaGroup @@ -490,6 +569,42 @@ _clutter_meta_group_clear_metas (ClutterMetaGroup *group) group->meta = NULL; } +/* + * _clutter_meta_group_clear_metas_no_internal: + * @group: a #ClutterMetaGroup + * + * Clears @group of all #ClutterActorMeta instances that don't have an + * internal priority and releases the reference on them + */ +void +_clutter_meta_group_clear_metas_no_internal (ClutterMetaGroup *group) +{ + GList *internal_list = NULL; + GList *l, *next; + + for (l = group->meta; l; l = next) + { + next = l->next; + + if (_clutter_actor_meta_is_internal (l->data)) + { + if (internal_list) + internal_list->prev = l; + l->next = internal_list; + l->prev = NULL; + internal_list = l; + } + else + { + _clutter_actor_meta_set_actor (l->data, NULL); + g_object_unref (l->data); + g_list_free_1 (l); + } + } + + group->meta = g_list_reverse (internal_list); +} + /* * _clutter_meta_group_get_meta: * @group: a #ClutterMetaGroup diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c index 7dcaf7eba..2e0680f85 100644 --- a/clutter/clutter-actor.c +++ b/clutter/clutter-actor.c @@ -11239,16 +11239,12 @@ clutter_actor_remove_action_by_name (ClutterActor *self, GList * clutter_actor_get_actions (ClutterActor *self) { - const GList *actions; - g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL); if (self->priv->actions == NULL) return NULL; - actions = _clutter_meta_group_peek_metas (self->priv->actions); - - return g_list_copy ((GList *) actions); + return _clutter_meta_group_get_metas_no_internal (self->priv->actions); } /** @@ -11294,7 +11290,7 @@ clutter_actor_clear_actions (ClutterActor *self) if (self->priv->actions == NULL) return; - _clutter_meta_group_clear_metas (self->priv->actions); + _clutter_meta_group_clear_metas_no_internal (self->priv->actions); } /** @@ -11447,16 +11443,12 @@ clutter_actor_remove_constraint_by_name (ClutterActor *self, GList * clutter_actor_get_constraints (ClutterActor *self) { - const GList *constraints; - g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL); if (self->priv->constraints == NULL) return NULL; - constraints = _clutter_meta_group_peek_metas (self->priv->constraints); - - return g_list_copy ((GList *) constraints); + return _clutter_meta_group_get_metas_no_internal (self->priv->constraints); } /** @@ -11502,7 +11494,7 @@ clutter_actor_clear_constraints (ClutterActor *self) if (self->priv->constraints == NULL) return; - _clutter_meta_group_clear_metas (self->priv->constraints); + _clutter_meta_group_clear_metas_no_internal (self->priv->constraints); } /** @@ -11704,7 +11696,6 @@ GList * clutter_actor_get_effects (ClutterActor *self) { ClutterActorPrivate *priv; - const GList *effects; g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL); @@ -11713,9 +11704,7 @@ clutter_actor_get_effects (ClutterActor *self) if (priv->effects == NULL) return NULL; - effects = _clutter_meta_group_peek_metas (priv->effects); - - return g_list_copy ((GList *) effects); + return _clutter_meta_group_get_metas_no_internal (priv->effects); } /** @@ -11761,7 +11750,7 @@ clutter_actor_clear_effects (ClutterActor *self) if (self->priv->effects == NULL) return; - _clutter_meta_group_clear_metas (self->priv->effects); + _clutter_meta_group_clear_metas_no_internal (self->priv->effects); } /**