From 93e1d8e7a35afd0f1c08022bdf0f04154ad08ef1 Mon Sep 17 00:00:00 2001 From: "Owen W. Taylor" Date: Fri, 7 Aug 2009 21:16:04 -0400 Subject: [PATCH] Add ::queue-relayout signal to ClutterActor for ClutterClone ClutterClone bases its preferred size on the preferred size of the source actor, so it needs to invalid its cached preferred size when the preferred size of the source actor changes. In order for this to work, we need to have notification when the size of the source actor changes, so add a ::queue-relayout signal to ClutterActor. Then connect to this from ClutterClone and queue a relayout on the clone when a relayout is queued on the source. http://bugzilla.openedhand.com/show_bug.cgi?id=1755 Signed-off-by: Emmanuele Bassi --- clutter/clutter-actor.c | 56 +++++++++++++++++++++++++++++++++-------- clutter/clutter-actor.h | 5 +++- clutter/clutter-clone.c | 12 +++++++++ 3 files changed, 62 insertions(+), 11 deletions(-) diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c index a152f8389..9b7eacbfa 100644 --- a/clutter/clutter-actor.c +++ b/clutter/clutter-actor.c @@ -425,6 +425,7 @@ enum REALIZE, UNREALIZE, QUEUE_REDRAW, + QUEUE_RELAYOUT, EVENT, CAPTURED_EVENT, BUTTON_PRESS_EVENT, @@ -1609,6 +1610,23 @@ clutter_actor_real_queue_redraw (ClutterActor *self, } } +void +clutter_actor_real_queue_relayout (ClutterActor *self) +{ + ClutterActorPrivate *priv = self->priv; + + priv->needs_width_request = TRUE; + priv->needs_height_request = TRUE; + priv->needs_allocation = TRUE; + + /* always repaint also (no-op if not mapped) */ + clutter_actor_queue_redraw (self); + + /* We need to go all the way up the hierarchy */ + if (priv->parent_actor) + clutter_actor_queue_relayout (priv->parent_actor); +} + /* like ClutterVertex, but with a w component */ typedef struct { gfloat x; @@ -3851,6 +3869,32 @@ clutter_actor_class_init (ClutterActorClass *klass) G_TYPE_NONE, 1, CLUTTER_TYPE_ACTOR); + /** + * ClutterActor::queue-relayout + * @actor: the actor being queued for relayout + * + * The ::queue_layout signal is emitted when clutter_actor_queue_relayout() + * is called on an actor. + * + * The default implementation for #ClutterActor chains up to the + * parent actor and queues a relayout on the parent, thus "bubbling" + * the relayout queue up through the actor graph. + * + * The main purpose of this signal is to allow relayout to be propagated + * properly in the procense of #ClutterClone actors. Applications will + * not normally need to connect to this signal. + * + * Since: 1.2 + */ + actor_signals[QUEUE_RELAYOUT] = + g_signal_new (I_("queue-relayout"), + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterActorClass, queue_relayout), + NULL, NULL, + clutter_marshal_VOID__VOID, + G_TYPE_NONE, 0); + /** * ClutterActor::event: * @actor: the actor which received the event @@ -4262,6 +4306,7 @@ clutter_actor_class_init (ClutterActorClass *klass) klass->get_preferred_height = clutter_actor_real_get_preferred_height; klass->allocate = clutter_actor_real_allocate; klass->queue_redraw = clutter_actor_real_queue_redraw; + klass->queue_relayout = clutter_actor_real_queue_relayout; klass->apply_transform = clutter_actor_real_apply_transform; } @@ -4385,16 +4430,7 @@ clutter_actor_queue_relayout (ClutterActor *self) priv->needs_allocation) return; /* save some cpu cycles */ - priv->needs_width_request = TRUE; - priv->needs_height_request = TRUE; - priv->needs_allocation = TRUE; - - /* always repaint also (no-op if not mapped) */ - clutter_actor_queue_redraw (self); - - /* We need to go all the way up the hierarchy */ - if (priv->parent_actor) - clutter_actor_queue_relayout (priv->parent_actor); + g_signal_emit (self, actor_signals[QUEUE_RELAYOUT], 0); } /** diff --git a/clutter/clutter-actor.h b/clutter/clutter-actor.h index bd3407b71..d3e28a91b 100644 --- a/clutter/clutter-actor.h +++ b/clutter/clutter-actor.h @@ -202,6 +202,7 @@ struct _ClutterActor * @captured_event: signal class closure for #ClutterActor::captured-event * @key_focus_in: signal class closure for #ClutterActor::focus-in * @key_focus_out: signal class closure for #ClutterActor::focus-out + * @queue_relayout: class handler for #ClutterActor::queue-relayout * * Base class for actors. */ @@ -271,9 +272,11 @@ struct _ClutterActorClass void (* key_focus_in) (ClutterActor *actor); void (* key_focus_out) (ClutterActor *actor); + void (* queue_relayout) (ClutterActor *actor); + /*< private >*/ /* padding for future expansion */ - gpointer _padding_dummy[32]; + gpointer _padding_dummy[31]; }; GType clutter_actor_get_type (void) G_GNUC_CONST; diff --git a/clutter/clutter-clone.c b/clutter/clutter-clone.c index 78bc4148a..a7cc1b5a7 100644 --- a/clutter/clutter-clone.c +++ b/clutter/clutter-clone.c @@ -313,6 +313,13 @@ clone_source_queue_redraw_cb (ClutterActor *source, clutter_actor_queue_redraw (CLUTTER_ACTOR (clone)); } +static void +clone_source_queue_relayout_cb (ClutterActor *source, + ClutterClone *clone) +{ + clutter_actor_queue_relayout (CLUTTER_ACTOR (clone)); +} + static void clutter_clone_set_source_internal (ClutterClone *clone, ClutterActor *source) @@ -329,6 +336,9 @@ clutter_clone_set_source_internal (ClutterClone *clone, g_signal_handlers_disconnect_by_func (priv->clone_source, (void *) clone_source_queue_redraw_cb, clone); + g_signal_handlers_disconnect_by_func (priv->clone_source, + (void *) clone_source_queue_relayout_cb, + clone); g_object_unref (priv->clone_source); priv->clone_source = NULL; } @@ -338,6 +348,8 @@ clutter_clone_set_source_internal (ClutterClone *clone, priv->clone_source = g_object_ref (source); g_signal_connect (priv->clone_source, "queue-redraw", G_CALLBACK (clone_source_queue_redraw_cb), clone); + g_signal_connect (priv->clone_source, "queue-relayout", + G_CALLBACK (clone_source_queue_relayout_cb), clone); } g_object_notify (G_OBJECT (clone), "source");