diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c index f676d5e3b..b291cd2b8 100644 --- a/clutter/clutter-actor.c +++ b/clutter/clutter-actor.c @@ -3001,8 +3001,14 @@ clutter_actor_dispose (GObject *object) { ClutterActor *parent = priv->parent_actor; - if (CLUTTER_IS_CONTAINER (parent)) - clutter_container_remove_actor (CLUTTER_CONTAINER (parent), self); + /* go through the Container implementation unless this + * is an internal child and has been marked as such + */ + if (CLUTTER_IS_CONTAINER (parent) && + !(CLUTTER_PRIVATE_FLAGS (self) & CLUTTER_ACTOR_INTERNAL_CHILD)) + { + clutter_container_remove_actor (CLUTTER_CONTAINER (parent), self); + } else priv->parent_actor = NULL; } @@ -6619,6 +6625,7 @@ clutter_actor_set_parent (ClutterActor *self, { ClutterActorPrivate *priv; ClutterTextDirection text_dir; + ClutterMainContext *ctx; g_return_if_fail (CLUTTER_IS_ACTOR (self)); g_return_if_fail (CLUTTER_IS_ACTOR (parent)); @@ -6648,6 +6655,14 @@ clutter_actor_set_parent (ClutterActor *self, g_object_ref_sink (self); priv->parent_actor = parent; + ctx = _clutter_context_get_default (); + + /* if push_internal() has been called then we automatically set + * the flag on the actor + */ + if (ctx->internal_child) + CLUTTER_SET_PRIVATE_FLAGS (self, CLUTTER_ACTOR_INTERNAL_CHILD); + /* clutter_actor_reparent() will emit ::parent-set for us */ if (!(CLUTTER_PRIVATE_FLAGS (self) & CLUTTER_ACTOR_IN_REPARENT)) g_signal_emit (self, actor_signals[PARENT_SET], 0, NULL); @@ -6825,17 +6840,22 @@ clutter_actor_reparent (ClutterActor *self, g_object_ref (self); - if (CLUTTER_IS_CONTAINER (priv->parent_actor)) + /* go through the Container implementation if this is a regular + * child and not an internal one + */ + if (CLUTTER_IS_CONTAINER (priv->parent_actor) && + !(CLUTTER_PRIVATE_FLAGS (self) & CLUTTER_ACTOR_INTERNAL_CHILD)) { ClutterContainer *parent = CLUTTER_CONTAINER (priv->parent_actor); - /* Note, will call unparent() */ + + /* this will have to call unparent() */ clutter_container_remove_actor (parent, self); } else clutter_actor_unparent (self); - if (CLUTTER_IS_CONTAINER (new_parent)) /* Note, will call parent() */ + if (CLUTTER_IS_CONTAINER (new_parent)) clutter_container_add_actor (CLUTTER_CONTAINER (new_parent), self); else clutter_actor_set_parent (self, new_parent); @@ -9471,3 +9491,83 @@ clutter_actor_get_text_direction (ClutterActor *self) return priv->text_direction; } + +/** + * clutter_actor_push_internal: + * + * Should be used by actors implementing the #ClutterContainer and with + * internal children added through clutter_actor_set_parent(), for instance: + * + * |[ + * static void + * my_actor_init (MyActor *self) + * { + * self->priv = SELF_ACTOR_GET_PRIVATE (self); + * + * clutter_actor_push_internal (); + * + * /* calling clutter_actor_set_parent() now will result in + * * the internal flag being set on a child of MyActor + * */ + * + * /* internal child: a background texture */ + * self->priv->background_tex = clutter_texture_new (); + * clutter_actor_set_parent (self->priv->background_tex, + * CLUTTER_ACTOR (self)); + * + * /* internal child: a label */ + * self->priv->label = clutter_text_new (); + * clutter_actor_set_parent (self->priv->label, + * CLUTTER_ACTOR (self)); + * + * clutter_actor_pop_internal (); + * + * /* calling clutter_actor_set_parent() now will not result in + * * the internal flag being set on a child of MyActor + * */ + * } + * ]| + * + * This function will be used by Clutter to toggle an "internal child" + * flag whenever clutter_actor_set_parent() is called; internal children + * are handled differently by Clutter, specifically when destroying their + * parent. + * + * Call clutter_actor_pop_internal() when you finished adding internal + * children. + * + * Nested calls to clutter_actor_push_internal() are allowed, but each + * one must by followed by a clutter_actor_pop_internal() call. + * + * Since: 1.2 + */ +void +clutter_actor_push_internal (void) +{ + ClutterMainContext *ctx = _clutter_context_get_default (); + + ctx->internal_child += 1; +} + +/** + * clutter_actor_pop_internal: + * + * Disables the effects of clutter_actor_pop_internal() + * + * Since: 1.2 + */ +void +clutter_actor_pop_internal (void) +{ + ClutterMainContext *ctx = _clutter_context_get_default (); + + if (ctx->internal_child == 0) + { + g_warning ("Mismatched %s: you need to call " + "clutter_actor_push_composite() at least once before " + "calling this function", G_STRFUNC); + return; + } + + ctx->internal_child -= 1; +} diff --git a/clutter/clutter-actor.h b/clutter/clutter-actor.h index 2f190a5ed..33c3ae773 100644 --- a/clutter/clutter-actor.h +++ b/clutter/clutter-actor.h @@ -532,6 +532,9 @@ void clutter_actor_set_text_direction (ClutterActor *sel ClutterTextDirection text_dir); ClutterTextDirection clutter_actor_get_text_direction (ClutterActor *self); +void clutter_actor_push_internal (void); +void clutter_actor_pop_internal (void); + G_END_DECLS #endif /* __CLUTTER_ACTOR_H__ */ diff --git a/clutter/clutter-private.h b/clutter/clutter-private.h index db9a6d2d0..d272ca9a4 100644 --- a/clutter/clutter-private.h +++ b/clutter/clutter-private.h @@ -58,13 +58,26 @@ typedef enum { CLUTTER_ACTOR_IN_DESTRUCTION = 1 << 0, CLUTTER_ACTOR_IS_TOPLEVEL = 1 << 1, CLUTTER_ACTOR_IN_REPARENT = 1 << 2, - CLUTTER_ACTOR_SYNC_MATRICES = 1 << 3, /* Used by stage to indicate GL - * viewport / perspective etc - * needs (re)setting. - */ - CLUTTER_ACTOR_IN_PAINT = 1 << 4, /* Used to avoid recursion */ - CLUTTER_ACTOR_IN_RELAYOUT = 1 << 5, /* Used to avoid recursion */ - CLUTTER_STAGE_IN_RESIZE = 1 << 6 + + /* Used by the stage to indicate GL viewport / perspective etc needs + * (re)setting. + */ + CLUTTER_ACTOR_SYNC_MATRICES = 1 << 3, + + /* Used to avoid recursion */ + CLUTTER_ACTOR_IN_PAINT = 1 << 4, + + /* Used to avoid recursion */ + CLUTTER_ACTOR_IN_RELAYOUT = 1 << 5, + + /* Used by the stage if resizing is an asynchronous operation (like on + * X11) to delay queueing relayouts until we got a notification from the + * event handling + */ + CLUTTER_STAGE_IN_RESIZE = 1 << 6, + + /* a flag for internal children of Containers */ + CLUTTER_ACTOR_INTERNAL_CHILD = 1 << 7 } ClutterPrivateFlags; struct _ClutterInputDevice @@ -133,6 +146,8 @@ struct _ClutterMainContext gulong redraw_count; GList *repaint_funcs; + + gint internal_child; }; #define CLUTTER_CONTEXT() (_clutter_context_get_default ()) diff --git a/doc/reference/clutter/clutter-sections.txt b/doc/reference/clutter/clutter-sections.txt index e7dafd772..ef125b011 100644 --- a/doc/reference/clutter/clutter-sections.txt +++ b/doc/reference/clutter/clutter-sections.txt @@ -352,6 +352,8 @@ clutter_actor_lower clutter_actor_raise_top clutter_actor_lower_bottom clutter_actor_get_stage +clutter_actor_push_internal +clutter_actor_pop_internal clutter_actor_set_depth