diff --git a/ChangeLog b/ChangeLog index bd5c27837..e3da71719 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,70 @@ +2006-07-06 Emmanuele Bassi + + Big rework of the actor management semantics: now ClutterActor + objects behave like GtkObjects - that is they have an initial + "floating" reference that gets "sunk" when they are added to + a ClutterGroup. This makes a group responsible of de-allocating + each actor inside it, so you just have to destroy the group to + get every child actor destroyed. Also, now you can do: + + clutter_group_add (group, clutter_video_texture_new ()); + + without having to care about reference counting and explicit + unreffing. + + * clutter/clutter-private.h: Add private flags setter and + getter macros. + + * clutter/clutter-actor.h: + * clutter/clutter-actor.c: Clean up; inherit from GInitiallyUnowned; + add a "visible" property; add the "destroy", "show" and "hide" + signals to ClutterActorClass. + + (clutter_actor_show), (clutter_actor_hide): Refactor a bit; emit + the "show" and "hide" signals. + + (clutter_actor_set_property), (clutter_actor_get_property), + (clutter_actor_class_init): Implement the "visible" property; add + signals. + + (clutter_actor_finalize): Do not leak the actor's name, if it is + set. + + (clutter_actor_dispose): Emit the "destroy" signal here. + + (clutter_actor_init): Sink the initial floating flag if needed. + + (clutter_actor_destroy): Add a function to explicitely destroy + a ClutterActor. + + (clutter_actor_set_parent), (clutter_actor_get_parent), + (clutter_actor_unparent): Make set_parent require a valid parent; + add unparent; check on get_parent; ref_sink the actor when + setting its parent and unref it when unsetting it. Probably we'll + need a function that does reparenting as unparent+set_parent in + a single shot. + + * clutter/clutter-group.h: + * clutter/clutter-group.c (clutter_group_dispose), + (clutter_group_finalize), (clutter_group_add), + (clutter_group_remove): Make the group destroy its children when + disposing it; clean up, and use the newly-available + clutter_actor_unparent(). + + * clutter/clutter-stage.h: + * clutter/clutter-stage.c (clutter_stage_init): ClutterStage is + a top-level actor; clean up. + + * clutter/clutter-video-texture.h: + * clutter/clutter-video-texture.c: Clean up. + + * examples/super-oh.c: + * examples/test.c: + * examples/video-player.c: + * examples/test-text.c: + * examples/video-cube.c: Remove the g_object_unref() call, as the + ClutterStage object is destroyed on clutter_main_quit(). + 2006-06-23 Matthew Allum * examples/super-oh.c: @@ -7,7 +74,7 @@ * examples/video-player.c: (size_change): cast stage height to gint avoiding wierdness for when - video height greater than half display height. Fixed #99 + video height greater than half display height. Fixed #99 2006-06-23 Matthew Allum diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c index e0812163e..d56f21dd0 100644 --- a/clutter/clutter-actor.c +++ b/clutter/clutter-actor.c @@ -34,30 +34,38 @@ #include "clutter-actor.h" #include "clutter-main.h" +#include "clutter-enum-types.h" +#include "clutter-marshal.h" #include "clutter-private.h" -G_DEFINE_ABSTRACT_TYPE (ClutterActor, clutter_actor, G_TYPE_OBJECT); +G_DEFINE_ABSTRACT_TYPE (ClutterActor, + clutter_actor, + G_TYPE_INITIALLY_UNOWNED); static guint32 __id = 0; + #define CLUTTER_ACTOR_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), CLUTTER_TYPE_ACTOR, ClutterActorPrivate)) struct _ClutterActorPrivate { - ClutterActorBox coords; + ClutterActorBox coords; - ClutterGeometry clip; - gboolean has_clip; + ClutterGeometry clip; + guint has_clip : 1; - gfloat rxang, ryang, rzang; /* Rotation foo. */ - gint rzx, rzy, rxy, rxz, ryx, ryz; - gint z; /* to actor box ? */ + gfloat rxang, ryang, rzang; /* Rotation foo. */ + gint rzx, rzy, rxy, rxz, ryx, ryz; + gint z; /* to actor box ? */ - guint8 opacity; - ClutterActor *parent_actor; /* This should always be a group */ - gchar *name; - guint32 id; /* Unique ID */ + guint8 opacity; + + ClutterActor *parent_actor; /* This should always be a group */ + + gchar *name; + + guint32 id; /* Unique ID */ }; enum @@ -67,11 +75,24 @@ enum PROP_Y, PROP_WIDTH, PROP_HEIGHT, - /* PROP_CLIP FIXME: add */ + PROP_CLIP, + PROP_HAS_CLIP, PROP_OPACITY, PROP_NAME, + PROP_VISIBLE }; +enum +{ + SHOW, + HIDE, + DESTROY, + + LAST_SIGNAL +}; + +static guint actor_signals[LAST_SIGNAL] = { 0, }; + static gboolean redraw_update_idle (gpointer data) { @@ -102,23 +123,29 @@ redraw_update_idle (gpointer data) void clutter_actor_show (ClutterActor *self) { - ClutterActorClass *klass; + if (!CLUTTER_ACTOR_IS_VISIBLE (self)) + { + ClutterActorClass *klass; - if (CLUTTER_ACTOR_IS_VISIBLE (self)) - return; + g_object_ref (self); + + if (!CLUTTER_ACTOR_IS_REALIZED (self)) + clutter_actor_realize(self); - if (!CLUTTER_ACTOR_IS_REALIZED (self)) - clutter_actor_realize(self); + CLUTTER_ACTOR_SET_FLAGS (self, CLUTTER_ACTOR_MAPPED); - CLUTTER_ACTOR_SET_FLAGS (self, CLUTTER_ACTOR_MAPPED); + klass = CLUTTER_ACTOR_GET_CLASS (self); + if (klass->show) + (klass->show) (self); - klass = CLUTTER_ACTOR_GET_CLASS (self); + if (CLUTTER_ACTOR_IS_VISIBLE (self)) + clutter_actor_queue_redraw (self); - if (klass->show) - (klass->show) (self); + g_signal_emit (self, actor_signals[SHOW], 0); + g_object_notify (G_OBJECT (self), "visible"); - if (CLUTTER_ACTOR_IS_VISIBLE (self)) - clutter_actor_queue_redraw (self); + g_object_unref (self); + } } /** @@ -131,19 +158,25 @@ clutter_actor_show (ClutterActor *self) void clutter_actor_hide (ClutterActor *self) { - ClutterActorClass *klass; + if (CLUTTER_ACTOR_IS_VISIBLE (self)) + { + ClutterActorClass *klass; - if (!CLUTTER_ACTOR_IS_VISIBLE (self)) - return; + g_object_ref (self); - CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_MAPPED); + CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_MAPPED); - klass = CLUTTER_ACTOR_GET_CLASS (self); + klass = CLUTTER_ACTOR_GET_CLASS (self); + if (klass->hide) + (klass->hide) (self); - if (klass->hide) - (klass->hide) (self); + clutter_actor_queue_redraw (self); - clutter_actor_queue_redraw (self); + g_signal_emit (self, actor_signals[HIDE], 0); + g_object_notify (G_OBJECT (self), "visible"); + + g_object_unref (self); + } } /** @@ -315,16 +348,16 @@ clutter_actor_paint (ClutterActor *self) **/ void clutter_actor_request_coords (ClutterActor *self, - ClutterActorBox *box) + ClutterActorBox *box) { ClutterActorClass *klass; - gboolean x_change, y_change, width_change, height_change; + gboolean x_change, y_change, width_change, height_change; klass = CLUTTER_ACTOR_GET_CLASS (self); /* FIXME: Kludgy see allocate co-ords */ if (klass->request_coords) - klass->request_coords(self, box); + klass->request_coords (self, box); x_change = (self->priv->coords.x1 != box->x1); y_change = (self->priv->coords.y1 != box->y1); @@ -437,6 +470,12 @@ clutter_actor_set_property (GObject *object, case PROP_NAME: clutter_actor_set_name (actor, g_value_get_string (value)); break; + case PROP_VISIBLE: + if (g_value_get_boolean (value) == TRUE) + clutter_actor_show (actor); + else + clutter_actor_hide (actor); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -475,6 +514,10 @@ clutter_actor_get_property (GObject *object, case PROP_NAME: g_value_set_string (value, priv->name); break; + case PROP_VISIBLE: + g_value_set_boolean (value, + (CLUTTER_ACTOR_IS_VISIBLE (actor) != FALSE)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -484,19 +527,31 @@ clutter_actor_get_property (GObject *object, static void clutter_actor_dispose (GObject *object) { - ClutterActor *self = CLUTTER_ACTOR(object); + ClutterActor *self = CLUTTER_ACTOR (object); - if (self->priv->parent_actor) + CLUTTER_DBG ("Disposing of object (id=%d) of type `%s'", + self->priv->id, + g_type_name (G_OBJECT_TYPE (self))); + + if (!(CLUTTER_PRIVATE_FLAGS (self) & CLUTTER_ACTOR_IN_DESTRUCTION)) { - clutter_group_remove (CLUTTER_GROUP(self->priv->parent_actor), self); - } + CLUTTER_SET_PRIVATE_FLAGS (self, CLUTTER_ACTOR_IN_DESTRUCTION); + g_signal_emit (self, actor_signals[DESTROY], 0); + + CLUTTER_UNSET_PRIVATE_FLAGS (self, CLUTTER_ACTOR_IN_DESTRUCTION); + } + G_OBJECT_CLASS (clutter_actor_parent_class)->dispose (object); } static void clutter_actor_finalize (GObject *object) { + ClutterActor *actor = CLUTTER_ACTOR (object); + + g_free (actor->priv->name); + G_OBJECT_CLASS (clutter_actor_parent_class)->finalize (object); } @@ -512,8 +567,7 @@ clutter_actor_class_init (ClutterActorClass *klass) g_type_class_add_private (klass, sizeof (ClutterActorPrivate)); - g_object_class_install_property - (object_class, PROP_X, + g_object_class_install_property (object_class, PROP_X, g_param_spec_int ("x", "X co-ord", "X co-ord of actor", @@ -522,8 +576,7 @@ clutter_actor_class_init (ClutterActorClass *klass) 0, G_PARAM_READWRITE)); - g_object_class_install_property - (object_class, PROP_Y, + g_object_class_install_property (object_class, PROP_Y, g_param_spec_int ("y", "Y co-ord", "Y co-ord of actor", @@ -532,8 +585,7 @@ clutter_actor_class_init (ClutterActorClass *klass) 0, G_PARAM_READWRITE)); - g_object_class_install_property - (object_class, PROP_WIDTH, + g_object_class_install_property (object_class, PROP_WIDTH, g_param_spec_int ("width", "Width", "Width of actor in pixels", @@ -542,8 +594,7 @@ clutter_actor_class_init (ClutterActorClass *klass) 0, G_PARAM_READWRITE)); - g_object_class_install_property - (object_class, PROP_HEIGHT, + g_object_class_install_property (object_class, PROP_HEIGHT, g_param_spec_int ("height", "Height", "Height of actor in pixels", @@ -552,8 +603,7 @@ clutter_actor_class_init (ClutterActorClass *klass) 0, G_PARAM_READWRITE)); - g_object_class_install_property - (object_class, PROP_OPACITY, + g_object_class_install_property (object_class, PROP_OPACITY, g_param_spec_uchar ("opacity", "Opacity", "Opacity of actor", @@ -562,22 +612,79 @@ clutter_actor_class_init (ClutterActorClass *klass) 0xff, G_PARAM_CONSTRUCT | G_PARAM_READWRITE)); + g_object_class_install_property (object_class, PROP_VISIBLE, + g_param_spec_boolean ("visible", + "Visible", + "Whether the actor is visible or not", + FALSE, + G_PARAM_READABLE)); + + actor_signals[DESTROY] = + g_signal_new ("destroy", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_CLEANUP | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, + G_STRUCT_OFFSET (ClutterActorClass, destroy), + NULL, NULL, + clutter_marshal_VOID__VOID, + G_TYPE_NONE, 0); + actor_signals[SHOW] = + g_signal_new ("show", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (ClutterActorClass, show), + NULL, NULL, + clutter_marshal_VOID__VOID, + G_TYPE_NONE, 0); + actor_signals[HIDE] = + g_signal_new ("hide", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (ClutterActorClass, hide), + NULL, NULL, + clutter_marshal_VOID__VOID, + G_TYPE_NONE, 0); } static void clutter_actor_init (ClutterActor *self) { + gboolean was_floating; + + /* sink the GInitiallyUnowned floating flag */ + was_floating = g_object_is_floating (G_OBJECT (self)); + if (was_floating) + g_object_force_floating (G_OBJECT (self)); + self->priv = CLUTTER_ACTOR_GET_PRIVATE (self); self->priv->parent_actor = NULL; - self->priv->has_clip = FALSE; - self->priv->opacity = 0xff; - self->priv->id = __id++; + self->priv->has_clip = FALSE; + self->priv->opacity = 0xff; + self->priv->id = __id++; clutter_actor_set_position (self, 0, 0); clutter_actor_set_size (self, 0, 0); } +/** + * clutter_actor_destroy: + * @self: a #ClutterActor + * + * Destroys an actor. When an actor is destroyed, it will break any + * references it holds to other objects. If the actor is inside a + * group, the actor will be removed from the group. + * + * When you destroy a group its children will be destroyed as well. + */ +void +clutter_actor_destroy (ClutterActor *self) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + if (!(CLUTTER_PRIVATE_FLAGS (self) & CLUTTER_ACTOR_IN_DESTRUCTION)) + g_object_run_dispose (G_OBJECT (self)); +} + /** * clutter_actor_queue_redraw: * @self: A #ClutterActor @@ -614,8 +721,8 @@ clutter_actor_queue_redraw (ClutterActor *self) * Sets the actors geometry in pixels relative to any parent actor. */ void -clutter_actor_set_geometry (ClutterActor *self, - ClutterGeometry *geom) +clutter_actor_set_geometry (ClutterActor *self, + const ClutterGeometry *geom) { ClutterActorBox box; @@ -635,8 +742,8 @@ clutter_actor_set_geometry (ClutterActor *self, * Gets the actors geometry in pixels relative to any parent actor. */ void -clutter_actor_get_geometry (ClutterActor *self, - ClutterGeometry *geom) +clutter_actor_get_geometry (ClutterActor *self, + ClutterGeometry *geom) { ClutterActorBox box; @@ -902,14 +1009,14 @@ clutter_actor_get_opacity (ClutterActor *self) */ void clutter_actor_set_name (ClutterActor *self, - const gchar *name) + const gchar *name) { g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_free (self->priv->name); + if (name || name[0] != '\0') { - g_free (self->priv->name); - self->priv->name = g_strdup(name); } } @@ -924,7 +1031,7 @@ clutter_actor_set_name (ClutterActor *self, * returned string is owned by the actor and should not * be modified or freed. */ -const gchar* +G_CONST_RETURN gchar * clutter_actor_get_name (ClutterActor *self) { g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL); @@ -1088,7 +1195,7 @@ clutter_actor_set_clip (ClutterActor *self, g_return_if_fail (CLUTTER_IS_ACTOR (self)); - clip = &self->priv->clip; + clip = &(self->priv->clip); clip->x = xoff; clip->y = yoff; @@ -1115,28 +1222,42 @@ clutter_actor_remove_clip (ClutterActor *self) /** * clutter_actor_set_parent: * @self: A #ClutterActor - * @parent: A new #ClutterActor parent or NULL + * @parent: A new #ClutterActor parent * - * Sets the parent of @self to @parent. + * Sets the parent of @self to @parent. The opposite function is + * clutter_actor_unparent(). + * * This function should not be used by applications. */ void clutter_actor_set_parent (ClutterActor *self, - ClutterActor *parent) + ClutterActor *parent) { g_return_if_fail (CLUTTER_IS_ACTOR (self)); - g_return_if_fail ((parent == NULL) || CLUTTER_IS_ACTOR (parent)); + g_return_if_fail (CLUTTER_IS_ACTOR (parent)); + g_return_if_fail (self != parent); - if (self->priv->parent_actor == parent) - return; - - if (self->priv->parent_actor && self->priv->parent_actor != parent) - g_object_unref (self->priv->parent_actor); - + if (self->priv->parent_actor != NULL) + { + g_warning ("Cannot set a parent on an actor which has a parent.\n" + "You must use clutter_actor_unparent() first.\n"); + + return; + } + + if (CLUTTER_PRIVATE_FLAGS (self) & CLUTTER_ACTOR_IS_TOPLEVEL) + { + g_warning ("Cannot set a parent on a toplevel actor\n"); + + return; + } + + g_object_ref_sink (self); self->priv->parent_actor = parent; - if (self->priv->parent_actor) - g_object_ref (self->priv->parent_actor); + if (CLUTTER_ACTOR_IS_VISIBLE (self->priv->parent_actor) && + CLUTTER_ACTOR_IS_VISIBLE (self)) + clutter_actor_queue_redraw (self); } /** @@ -1147,12 +1268,33 @@ clutter_actor_set_parent (ClutterActor *self, * * Return Value: The #ClutterActor parent or NULL */ -ClutterActor* +ClutterActor * clutter_actor_get_parent (ClutterActor *self) { + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL); + return self->priv->parent_actor; } +/** + * clutter_actor_unparent: + * @self: a #ClutterActor + * + * This function should not be used in applications. It should be called by + * implementations of group actors, to dissociate a child from the container. + */ +void +clutter_actor_unparent (ClutterActor *self) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + if (self->priv->parent_actor == NULL) + return; + + self->priv->parent_actor = NULL; + g_object_unref (self); +} + /** * clutter_actor_raise: * @self: A #ClutterActor diff --git a/clutter/clutter-actor.h b/clutter/clutter-actor.h index c997afdc8..35e9a8f8d 100644 --- a/clutter/clutter-actor.h +++ b/clutter/clutter-actor.h @@ -63,6 +63,7 @@ typedef struct _ClutterActorPrivate ClutterActorPrivate; typedef struct _ClutterGeometry ClutterGeometry; typedef void (*ClutterCallback) (ClutterActor *actor, gpointer data); +#define CLUTTER_CALLBACK(f) ((ClutterCallback) (f)) struct _ClutterGeometry { @@ -87,183 +88,122 @@ GType clutter_actor_box_get_type (void) G_GNUC_CONST; struct _ClutterActor { /*< public >*/ - GObject parent; - guint32 flags; + GObject parent_instance; + guint32 flags; /*< private >*/ - ClutterActorPrivate *priv; + guint32 private_flags; + + ClutterActorPrivate *priv; }; struct _ClutterActorClass { GObjectClass parent_class; - void (* show) (ClutterActor *actor); - void (* hide) (ClutterActor *actor); - void (* realize) (ClutterActor *actor); - void (* unrealize) (ClutterActor *actor); - void (* paint) (ClutterActor *actor); - void (* request_coords) (ClutterActor *actor, - ClutterActorBox *box); - void (* allocate_coords) (ClutterActor *actor, - ClutterActorBox *box); - void (* set_depth) (ClutterActor *actor, - gint depth); - gint (* get_depth) (ClutterActor *actor); + void (* show) (ClutterActor *actor); + void (* hide) (ClutterActor *actor); + void (* realize) (ClutterActor *actor); + void (* unrealize) (ClutterActor *actor); + void (* paint) (ClutterActor *actor); + void (* request_coords) (ClutterActor *actor, + ClutterActorBox *box); + void (* allocate_coords) (ClutterActor *actor, + ClutterActorBox *box); + void (* set_depth) (ClutterActor *actor, + gint depth); + gint (* get_depth) (ClutterActor *actor); + + void (*destroy) (ClutterActor *actor); /* to go ? */ - void (* show_all) (ClutterActor *actor); - void (* hide_all) (ClutterActor *actor); - void (* queue_redraw) (ClutterActor *actor); + void (* show_all) (ClutterActor *actor); + void (* hide_all) (ClutterActor *actor); + void (* queue_redraw) (ClutterActor *actor); /* padding for future expansion */ - void (*_clutter_actor_1) (void); - void (*_clutter_actor_2) (void); - void (*_clutter_actor_3) (void); - void (*_clutter_actor_4) (void); - void (*_clutter_actor_5) (void); - void (*_clutter_actor_6) (void); + void (*_clutter_actor_1) (void); + void (*_clutter_actor_2) (void); + void (*_clutter_actor_3) (void); + void (*_clutter_actor_4) (void); + void (*_clutter_actor_5) (void); + void (*_clutter_actor_6) (void); }; -GType clutter_actor_get_type (void); - -void -clutter_actor_show (ClutterActor *self); - -void -clutter_actor_hide (ClutterActor *self); - -void -clutter_actor_realize (ClutterActor *self); - -void -clutter_actor_unrealize (ClutterActor *self); - -void -clutter_actor_paint (ClutterActor *self); - -void -clutter_actor_queue_redraw (ClutterActor *self); - -void -clutter_actor_request_coords (ClutterActor *self, - ClutterActorBox *box); - -void -clutter_actor_allocate_coords (ClutterActor *self, - ClutterActorBox *box); - -void -clutter_actor_set_geometry (ClutterActor *self, - ClutterGeometry *geom); - -void -clutter_actor_get_geometry (ClutterActor *self, - ClutterGeometry *geom); - -void -clutter_actor_get_coords (ClutterActor *self, - gint *x1, - gint *y1, - gint *x2, - gint *y2); - -void -clutter_actor_set_position (ClutterActor *self, - gint x, - gint y); - -void -clutter_actor_set_size (ClutterActor *self, - gint width, - gint height); - -void -clutter_actor_get_abs_position (ClutterActor *self, - gint *x, - gint *y); - -guint -clutter_actor_get_width (ClutterActor *self); - -guint -clutter_actor_get_height (ClutterActor *self); - -gint -clutter_actor_get_x (ClutterActor *self); - -gint -clutter_actor_get_y (ClutterActor *self); - -void -clutter_actor_rotate_z (ClutterActor *self, - gfloat angle, - gint x, - gint y); - -void -clutter_actor_rotate_x (ClutterActor *self, - gfloat angle, - gint y, - gint z); - -void -clutter_actor_rotate_y (ClutterActor *self, - gfloat angle, - gint x, - gint z); - -void -clutter_actor_set_opacity (ClutterActor *self, - guint8 opacity); - -guint8 -clutter_actor_get_opacity (ClutterActor *self); - -void -clutter_actor_set_name (ClutterActor *self, - const gchar *id); - -const gchar* -clutter_actor_get_name (ClutterActor *self); - -guint32 -clutter_actor_get_id (ClutterActor *self); - -void -clutter_actor_set_clip (ClutterActor *self, - gint xoff, - gint yoff, - gint width, - gint height); - -void -clutter_actor_remove_clip (ClutterActor *self); - -void -clutter_actor_set_parent (ClutterActor *self, ClutterActor *parent); - -ClutterActor* -clutter_actor_get_parent (ClutterActor *self); - -void -clutter_actor_raise (ClutterActor *self, ClutterActor *below); - -void -clutter_actor_lower (ClutterActor *self, ClutterActor *above); - -void -clutter_actor_raise_top (ClutterActor *self); - -void -clutter_actor_lower_bottom (ClutterActor *self); - -void -clutter_actor_set_depth (ClutterActor *self, - gint depth); - -gint -clutter_actor_get_depth (ClutterActor *self); +GType clutter_actor_get_type (void) G_GNUC_CONST; +void clutter_actor_show (ClutterActor *self); +void clutter_actor_hide (ClutterActor *self); +void clutter_actor_realize (ClutterActor *self); +void clutter_actor_unrealize (ClutterActor *self); +void clutter_actor_paint (ClutterActor *self); +void clutter_actor_queue_redraw (ClutterActor *self); +void clutter_actor_destroy (ClutterActor *self); +void clutter_actor_request_coords (ClutterActor *self, + ClutterActorBox *box); +void clutter_actor_allocate_coords (ClutterActor *self, + ClutterActorBox *box); +void clutter_actor_set_geometry (ClutterActor *self, + const ClutterGeometry *geometry); +void clutter_actor_get_geometry (ClutterActor *self, + ClutterGeometry *geometry); +void clutter_actor_get_coords (ClutterActor *self, + gint *x1, + gint *y1, + gint *x2, + gint *y2); +void clutter_actor_set_size (ClutterActor *self, + gint width, + gint height); +void clutter_actor_set_position (ClutterActor *self, + gint x, + gint y); +void clutter_actor_get_abs_position (ClutterActor *self, + gint *x, + gint *y); +guint clutter_actor_get_width (ClutterActor *self); +guint clutter_actor_get_height (ClutterActor *self); +gint clutter_actor_get_x (ClutterActor *self); +gint clutter_actor_get_y (ClutterActor *self); +void clutter_actor_rotate_x (ClutterActor *self, + gfloat angle, + gint y, + gint z); +void clutter_actor_rotate_y (ClutterActor *self, + gfloat angle, + gint x, + gint z); +void clutter_actor_rotate_z (ClutterActor *self, + gfloat angle, + gint x, + gint y); +void clutter_actor_set_opacity (ClutterActor *self, + guint8 opacity); +guint8 clutter_actor_get_opacity (ClutterActor *self); +void clutter_actor_set_name (ClutterActor *self, + const gchar *name); +G_CONST_RETURN gchar *clutter_actor_get_name (ClutterActor *self); +guint32 clutter_actor_get_id (ClutterActor *self); +void clutter_actor_set_clip (ClutterActor *self, + gint xoff, + gint yoff, + gint width, + gint height); +void clutter_actor_remove_clip (ClutterActor *self); +void clutter_actor_set_parent (ClutterActor *self, + ClutterActor *parent); +ClutterActor * clutter_actor_get_parent (ClutterActor *self); +void clutter_actor_reparent (ClutterActor *self, + ClutterActor *new_parent); +void clutter_actor_unparent (ClutterActor *self); +void clutter_actor_raise (ClutterActor *self, + ClutterActor *below); +void clutter_actor_lower (ClutterActor *self, + ClutterActor *above); +void clutter_actor_raise_top (ClutterActor *self); +void clutter_actor_lower_bottom (ClutterActor *self); +void clutter_actor_set_depth (ClutterActor *self, + gint depth); +gint clutter_actor_get_depth (ClutterActor *self); G_END_DECLS diff --git a/clutter/clutter-group.c b/clutter/clutter-group.c index 6b35a54e2..58c467836 100644 --- a/clutter/clutter-group.c +++ b/clutter/clutter-group.c @@ -200,16 +200,12 @@ clutter_group_allocate_coords (ClutterActor *self, static void clutter_group_dispose (GObject *object) { - ClutterGroup *self = CLUTTER_GROUP(object); - - if (self->priv) - { - /* FIXME: Do we need to actually free anything here ? - * Children ref us so this wont get called till - * they are all removed. - */ - } + ClutterGroup *self = CLUTTER_GROUP (object); + clutter_group_foreach (self, + CLUTTER_CALLBACK (clutter_actor_destroy), + NULL); + G_OBJECT_CLASS (clutter_group_parent_class)->dispose (object); } @@ -217,17 +213,6 @@ clutter_group_dispose (GObject *object) static void clutter_group_finalize (GObject *object) { - ClutterGroup *group = CLUTTER_GROUP (object); - - /* XXX - if something survives ::dispose then there's something - * wrong; but, at least, we won't leak stuff around. - */ - if (group->priv->children) - { - g_list_foreach (group->priv->children, (GFunc) g_object_unref, NULL); - g_list_free (group->priv->children); - } - G_OBJECT_CLASS (clutter_group_parent_class)->finalize (object); } @@ -285,7 +270,7 @@ clutter_group_init (ClutterGroup *self) * * returns a new #ClutterGroup **/ -ClutterGroup* +ClutterActor * clutter_group_new (void) { return g_object_new (CLUTTER_TYPE_GROUP, NULL); @@ -405,14 +390,16 @@ clutter_group_add (ClutterGroup *self, return; } - self->priv->children = g_list_append (self->priv->children, actor); - /* below refs */ - clutter_actor_set_parent (actor, CLUTTER_ACTOR(self)); g_object_ref (actor); + self->priv->children = g_list_append (self->priv->children, actor); + clutter_actor_set_parent (actor, CLUTTER_ACTOR (self)); + clutter_group_sort_depth_order (self); g_signal_emit (self, group_signals[ADD], 0, actor); + + g_object_unref (actor); } /** @@ -425,9 +412,9 @@ clutter_group_add (ClutterGroup *self, * function inside bindings. */ void -clutter_group_add_many_valist (ClutterGroup *group, +clutter_group_add_many_valist (ClutterGroup *group, ClutterActor *first_actor, - va_list args) + va_list args) { ClutterActor *actor; @@ -452,7 +439,7 @@ clutter_group_add_many_valist (ClutterGroup *group, * equivalent to calling clutter_group_add() for each member of the list. */ void -clutter_group_add_many (ClutterGroup *self, +clutter_group_add_many (ClutterGroup *self, ClutterActor *first_actor, ...) { @@ -479,6 +466,8 @@ clutter_group_remove (ClutterGroup *self, g_return_if_fail (CLUTTER_IS_GROUP (self)); g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + g_object_ref (actor); + parent = clutter_actor_get_parent (actor); if (parent != CLUTTER_ACTOR (self)) { @@ -489,11 +478,17 @@ clutter_group_remove (ClutterGroup *self, g_type_name (G_OBJECT_TYPE (self))); return; } + + g_object_ref (actor); self->priv->children = g_list_remove (self->priv->children, actor); - clutter_actor_set_parent (actor, NULL); + clutter_actor_unparent (actor); g_signal_emit (self, group_signals[REMOVE], 0, actor); + + if (CLUTTER_ACTOR_IS_VISIBLE (CLUTTER_ACTOR (self))) + clutter_actor_queue_redraw (CLUTTER_ACTOR (self)); + g_object_unref (actor); } diff --git a/clutter/clutter-group.h b/clutter/clutter-group.h index b2abf2854..bda2f70ad 100644 --- a/clutter/clutter-group.h +++ b/clutter/clutter-group.h @@ -59,20 +59,20 @@ typedef struct _ClutterGroupPrivate ClutterGroupPrivate; struct _ClutterGroup { - ClutterActor parent; + ClutterActor parent_instance; /*< private >*/ - ClutterGroupPrivate *priv; + ClutterGroupPrivate *priv; }; struct _ClutterGroupClass { /*< private >*/ - ClutterActorClass parent_class; + ClutterActorClass parent_class; - void (*add) (ClutterGroup *group, + void (*add) (ClutterGroup *group, ClutterActor *child); - void (*remove) (ClutterGroup *group, + void (*remove) (ClutterGroup *group, ClutterActor *child); /* padding for future expansion */ @@ -84,57 +84,33 @@ struct _ClutterGroupClass void (*_clutter_group_6) (void); }; -GType clutter_group_get_type (void); - -ClutterGroup *clutter_group_new (void); - -GList* -clutter_group_get_children (ClutterGroup *self); - -void -clutter_group_foreach (ClutterGroup *self, - ClutterCallback callback, - gpointer user_data); - -void -clutter_group_add (ClutterGroup *self, - ClutterActor *actor); - -void -clutter_group_add_many_valist (ClutterGroup *self, - ClutterActor *first_actor, - va_list args); - -void -clutter_group_add_many (ClutterGroup *self, - ClutterActor *first_actor, - ...) G_GNUC_NULL_TERMINATED; - -void -clutter_group_remove (ClutterGroup *self, - ClutterActor *actor); - -void -clutter_group_show_all (ClutterGroup *self); - -void -clutter_group_hide_all (ClutterGroup *self); - -ClutterActor * -clutter_group_find_child_by_id (ClutterGroup *self, guint id); - -void -clutter_group_raise (ClutterGroup *self, - ClutterActor *actor, - ClutterActor *sibling); - -void -clutter_group_lower (ClutterGroup *self, - ClutterActor *actor, - ClutterActor *sibling); - -void -clutter_group_sort_depth_order (ClutterGroup *self); +GType clutter_group_get_type (void) G_GNUC_CONST; +ClutterActor *clutter_group_new (void); +GList * clutter_group_get_children (ClutterGroup *self); +void clutter_group_foreach (ClutterGroup *self, + ClutterCallback callback, + gpointer user_data); +void clutter_group_add (ClutterGroup *self, + ClutterActor *actor); +void clutter_group_add_many_valist (ClutterGroup *self, + ClutterActor *first_actor, + va_list args); +void clutter_group_add_many (ClutterGroup *self, + ClutterActor *first_actor, + ...) G_GNUC_NULL_TERMINATED; +void clutter_group_remove (ClutterGroup *self, + ClutterActor *actor); +void clutter_group_show_all (ClutterGroup *self); +void clutter_group_hide_all (ClutterGroup *self); +ClutterActor *clutter_group_find_child_by_id (ClutterGroup *self, + guint id); +void clutter_group_raise (ClutterGroup *self, + ClutterActor *actor, + ClutterActor *sibling); +void clutter_group_lower (ClutterGroup *self, + ClutterActor *actor, + ClutterActor *sibling); +void clutter_group_sort_depth_order (ClutterGroup *self); G_END_DECLS diff --git a/clutter/clutter-private.h b/clutter/clutter-private.h index db7537d30..0c2825e77 100644 --- a/clutter/clutter-private.h +++ b/clutter/clutter-private.h @@ -26,8 +26,6 @@ #ifndef _HAVE_CLUTTER_PRIVATE_H #define _HAVE_CLUTTER_PRIVATE_H -#include - #include #include #include @@ -45,6 +43,8 @@ #include +G_BEGIN_DECLS + typedef struct _ClutterMainContext ClutterMainContext; struct _ClutterMainContext @@ -70,4 +70,18 @@ struct _ClutterMainContext #define CLUTTER_CONTEXT() (clutter_context_get_default ()) ClutterMainContext *clutter_context_get_default (void); + +typedef enum { + CLUTTER_ACTOR_UNUSED_FLAG = 0, + + CLUTTER_ACTOR_IN_DESTRUCTION = 1 << 0, + CLUTTER_ACTOR_IS_TOPLEVEL = 1 << 1 +} ClutterPrivateFlags; + +#define CLUTTER_PRIVATE_FLAGS(a) (CLUTTER_ACTOR ((a))->private_flags) +#define CLUTTER_SET_PRIVATE_FLAGS(a,f) G_STMT_START{ (CLUTTER_PRIVATE_FLAGS (a) |= (f)); }G_STMT_END +#define CLUTTER_UNSET_PRIVATE_FLAGS(a,f) G_STMT_START{ (CLUTTER_PRIVATE_FLAGS (a) &= ~(f)); }G_STMT_END + +G_END_DECLS + #endif diff --git a/clutter/clutter-stage.c b/clutter/clutter-stage.c index 4b37a72c4..2eb13c65f 100644 --- a/clutter/clutter-stage.c +++ b/clutter/clutter-stage.c @@ -730,6 +730,9 @@ static void clutter_stage_init (ClutterStage *self) { ClutterStagePrivate *priv; + + /* a stage is a top-level object */ + CLUTTER_SET_PRIVATE_FLAGS (self, CLUTTER_ACTOR_IS_TOPLEVEL); self->priv = priv = CLUTTER_STAGE_GET_PRIVATE (self); diff --git a/clutter/clutter-stage.h b/clutter/clutter-stage.h index b6d38a482..6e305deff 100644 --- a/clutter/clutter-stage.h +++ b/clutter/clutter-stage.h @@ -39,7 +39,7 @@ G_BEGIN_DECLS -#define CLUTTER_TYPE_STAGE clutter_stage_get_type() +#define CLUTTER_TYPE_STAGE (clutter_stage_get_type()) #define CLUTTER_STAGE_WIDTH() \ clutter_actor_get_width(CLUTTER_ACTOR(clutter_stage_get_default())) @@ -106,30 +106,23 @@ struct _ClutterStageClass void (*_clutter_stage6) (void); }; -GType clutter_stage_get_type (void); - -ClutterActor *clutter_stage_get_default (void); - -Window clutter_stage_get_xwindow (ClutterStage *stage); - -gboolean clutter_stage_set_xwindow_foreign (ClutterStage *stage, - Window xid); - -void clutter_stage_set_color (ClutterStage *stage, - const ClutterColor *color); - -void clutter_stage_get_color (ClutterStage *stage, - ClutterColor *color); - -ClutterActor *clutter_stage_get_actor_at_pos (ClutterStage *stage, - gint x, - gint y); - -GdkPixbuf * clutter_stage_snapshot (ClutterStage *stage, - gint x, - gint y, - gint width, - gint height); +GType clutter_stage_get_type (void) G_GNUC_CONST; +ClutterActor *clutter_stage_get_default (void); +Window clutter_stage_get_xwindow (ClutterStage *stage); +gboolean clutter_stage_set_xwindow_foreign (ClutterStage *stage, + Window xid); +void clutter_stage_set_color (ClutterStage *stage, + const ClutterColor *color); +void clutter_stage_get_color (ClutterStage *stage, + ClutterColor *color); +ClutterActor *clutter_stage_get_actor_at_pos (ClutterStage *stage, + gint x, + gint y); +GdkPixbuf * clutter_stage_snapshot (ClutterStage *stage, + gint x, + gint y, + gint width, + gint height); G_END_DECLS diff --git a/clutter/clutter-video-texture.c b/clutter/clutter-video-texture.c index eeda06710..bf069e412 100644 --- a/clutter/clutter-video-texture.c +++ b/clutter/clutter-video-texture.c @@ -44,7 +44,7 @@ #include -struct ClutterVideoTexturePrivate +struct _ClutterVideoTexturePrivate { GstElement *playbin; char *uri; @@ -101,8 +101,7 @@ set_uri (ClutterMedia *media, if (!priv->playbin) return; - if (priv->uri) - g_free (priv->uri); + g_free (priv->uri); if (uri) { diff --git a/clutter/clutter-video-texture.h b/clutter/clutter-video-texture.h index 08481c854..51f7fceac 100644 --- a/clutter/clutter-video-texture.h +++ b/clutter/clutter-video-texture.h @@ -56,9 +56,9 @@ G_BEGIN_DECLS (G_TYPE_INSTANCE_GET_CLASS ((obj), \ CLUTTER_TYPE_VIDEO_TEXTURE, ClutterVideoTextureClass)) -typedef struct _ClutterVideoTexture ClutterVideoTexture; -typedef struct _ClutterVideoTextureClass ClutterVideoTextureClass; -typedef struct ClutterVideoTexturePrivate ClutterVideoTexturePrivate; +typedef struct _ClutterVideoTexture ClutterVideoTexture; +typedef struct _ClutterVideoTextureClass ClutterVideoTextureClass; +typedef struct _ClutterVideoTexturePrivate ClutterVideoTexturePrivate; /* #define CLUTTER_VIDEO_TEXTURE_ERROR clutter_video_texture_error_quark() */ @@ -88,10 +88,8 @@ struct _ClutterVideoTextureClass void (* _clutter_reserved6) (void); }; -GType clutter_video_texture_get_type (void); - -ClutterActor* -clutter_video_texture_new (void); +GType clutter_video_texture_get_type (void) G_GNUC_CONST; +ClutterActor *clutter_video_texture_new (void); G_END_DECLS diff --git a/doc/reference/tmpl/clutter-main.sgml b/doc/reference/tmpl/clutter-main.sgml index b10345316..c56f93d34 100644 --- a/doc/reference/tmpl/clutter-main.sgml +++ b/doc/reference/tmpl/clutter-main.sgml @@ -71,6 +71,7 @@ clutter-main @a...: @a...: @a...: +@a...: @a...: diff --git a/examples/super-oh.c b/examples/super-oh.c index 819c57d35..daebc1780 100644 --- a/examples/super-oh.c +++ b/examples/super-oh.c @@ -10,8 +10,8 @@ typedef struct SuperOH { ClutterActor *hand[NHANDS], *bgtex; - ClutterGroup *group; - GdkPixbuf *bgpixb; + ClutterActor *group; + GdkPixbuf *bgpixb; } SuperOH; @@ -183,14 +183,14 @@ main (int argc, char *argv[]) clutter_actor_set_position (oh->hand[i], x, y); /* Add to our group group */ - clutter_group_add (oh->group, oh->hand[i]); + clutter_group_add (CLUTTER_GROUP (oh->group), oh->hand[i]); } /* Add the group to the stage */ clutter_group_add (CLUTTER_GROUP (stage), CLUTTER_ACTOR(oh->group)); /* Show everying ( and map window ) */ - clutter_group_show_all (oh->group); + clutter_group_show_all (CLUTTER_GROUP (oh->group)); clutter_group_show_all (CLUTTER_GROUP (stage)); g_signal_connect (stage, "button-press-event", @@ -212,7 +212,5 @@ main (int argc, char *argv[]) clutter_main(); - g_object_unref (stage); - return 0; } diff --git a/examples/test-text.c b/examples/test-text.c index af04d528f..7bac8afb3 100644 --- a/examples/test-text.c +++ b/examples/test-text.c @@ -50,8 +50,6 @@ main (int argc, char *argv[]) g_signal_connect (stage, "key-press-event", G_CALLBACK (clutter_main_quit), NULL); - g_object_unref (stage); - clutter_main(); return 0; diff --git a/examples/test.c b/examples/test.c index 5a9e7b311..a6614cb83 100644 --- a/examples/test.c +++ b/examples/test.c @@ -119,7 +119,5 @@ main (int argc, char *argv[]) clutter_main(); - g_object_unref (stage); - return 0; } diff --git a/examples/video-cube.c b/examples/video-cube.c index 336fea0e6..87c4b9502 100644 --- a/examples/video-cube.c +++ b/examples/video-cube.c @@ -268,9 +268,5 @@ main (int argc, char *argv[]) clutter_main(); - g_object_unref (stage); - return 0; } - - diff --git a/examples/video-player.c b/examples/video-player.c index 81dd5c234..6d496111b 100644 --- a/examples/video-player.c +++ b/examples/video-player.c @@ -377,7 +377,5 @@ main (int argc, char *argv[]) clutter_main(); - g_object_unref (stage); - return 0; }