[mutter] clutter/stage: Add an API for shallow relayouts
- From: Georges Basile Stavracas Neto <gbsneto src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter] clutter/stage: Add an API for shallow relayouts
- Date: Thu, 30 Jan 2020 19:18:26 +0000 (UTC)
commit 5257c6ecc2d2c843ecc1ad5558e6a471eff5c7ee
Author: Daniel van Vugt <daniel van vugt canonical com>
Date: Tue May 7 13:02:55 2019 +0800
clutter/stage: Add an API for shallow relayouts
Where "shallow" means you can specify any actor instead of every relayout
having to start from the stage.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/575
clutter/clutter/clutter-stage-private.h | 3 +
clutter/clutter/clutter-stage.c | 105 +++++++++++++++++++++-----------
2 files changed, 74 insertions(+), 34 deletions(-)
---
diff --git a/clutter/clutter/clutter-stage-private.h b/clutter/clutter/clutter-stage-private.h
index 5ec1af670..7a8429067 100644
--- a/clutter/clutter/clutter-stage-private.h
+++ b/clutter/clutter/clutter-stage-private.h
@@ -141,6 +141,9 @@ void _clutter_stage_presented (ClutterStage *stag
GList * _clutter_stage_peek_stage_views (ClutterStage *stage);
+void clutter_stage_queue_actor_relayout (ClutterStage *stage,
+ ClutterActor *actor);
+
G_END_DECLS
#endif /* __CLUTTER_STAGE_PRIVATE_H__ */
diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c
index 04d619a59..d0668768b 100644
--- a/clutter/clutter/clutter-stage.c
+++ b/clutter/clutter/clutter-stage.c
@@ -120,6 +120,8 @@ struct _ClutterStagePrivate
ClutterPlane current_clip_planes[4];
+ GHashTable *pending_relayouts;
+ unsigned int pending_relayouts_version;
GList *pending_queue_redraws;
gint sync_delay;
@@ -146,7 +148,6 @@ struct _ClutterStagePrivate
int update_freeze_count;
- guint relayout_pending : 1;
guint redraw_pending : 1;
guint is_cursor_visible : 1;
guint throttle_motion_events : 1;
@@ -1287,7 +1288,26 @@ _clutter_stage_needs_update (ClutterStage *stage)
priv = stage->priv;
- return priv->relayout_pending || priv->redraw_pending;
+ return priv->redraw_pending || g_hash_table_size (priv->pending_relayouts) > 0;
+}
+
+void
+clutter_stage_queue_actor_relayout (ClutterStage *stage,
+ ClutterActor *actor)
+{
+ ClutterStagePrivate *priv = stage->priv;
+
+ if (g_hash_table_contains (priv->pending_relayouts, stage))
+ return;
+
+ if (g_hash_table_size (priv->pending_relayouts) == 0)
+ _clutter_stage_schedule_update (stage);
+
+ if (actor == (ClutterActor *) stage)
+ g_hash_table_remove_all (priv->pending_relayouts);
+
+ g_hash_table_add (priv->pending_relayouts, g_object_ref (actor));
+ priv->pending_relayouts_version++;
}
void
@@ -1295,41 +1315,58 @@ _clutter_stage_maybe_relayout (ClutterActor *actor)
{
ClutterStage *stage = CLUTTER_STAGE (actor);
ClutterStagePrivate *priv = stage->priv;
- gfloat natural_width, natural_height;
- ClutterActorBox box = { 0, };
+ GHashTableIter iter;
+ gpointer key;
+ int count = 0;
- if (!priv->relayout_pending)
+ /* No work to do? Avoid the extraneous debug log messages too. */
+ if (g_hash_table_size (priv->pending_relayouts) == 0)
return;
- /* avoid reentrancy */
- if (!CLUTTER_ACTOR_IN_RELAYOUT (stage))
+ CLUTTER_NOTE (ACTOR, ">>> Recomputing layout");
+
+ g_hash_table_iter_init (&iter, priv->pending_relayouts);
+ while (g_hash_table_iter_next (&iter, &key, NULL))
{
- priv->relayout_pending = FALSE;
- priv->stage_was_relayout = TRUE;
+ g_autoptr (ClutterActor) queued_actor = key;
+ unsigned int old_version;
- CLUTTER_NOTE (ACTOR, "Recomputing layout");
+ g_hash_table_iter_steal (&iter);
+ priv->pending_relayouts_version++;
- CLUTTER_SET_PRIVATE_FLAGS (stage, CLUTTER_IN_RELAYOUT);
+ if (CLUTTER_ACTOR_IN_RELAYOUT (queued_actor)) /* avoid reentrancy */
+ continue;
+
+ /* An actor may have been destroyed or hidden between queuing and now */
+ if (clutter_actor_get_stage (queued_actor) != actor)
+ continue;
- natural_width = natural_height = 0;
- clutter_actor_get_preferred_size (CLUTTER_ACTOR (stage),
- NULL, NULL,
- &natural_width, &natural_height);
+ if (queued_actor == actor)
+ CLUTTER_NOTE (ACTOR, " Deep relayout of stage %s",
+ _clutter_actor_get_debug_name (queued_actor));
+ else
+ CLUTTER_NOTE (ACTOR, " Shallow relayout of actor %s",
+ _clutter_actor_get_debug_name (queued_actor));
+
+ CLUTTER_SET_PRIVATE_FLAGS (queued_actor, CLUTTER_IN_RELAYOUT);
- box.x1 = 0;
- box.y1 = 0;
- box.x2 = natural_width;
- box.y2 = natural_height;
+ old_version = priv->pending_relayouts_version;
+ clutter_actor_allocate_preferred_size (queued_actor,
+ CLUTTER_ALLOCATION_NONE);
- CLUTTER_NOTE (ACTOR, "Allocating (0, 0 - %d, %d) for the stage",
- (int) natural_width,
- (int) natural_height);
+ CLUTTER_UNSET_PRIVATE_FLAGS (queued_actor, CLUTTER_IN_RELAYOUT);
- clutter_actor_allocate (CLUTTER_ACTOR (stage),
- &box, CLUTTER_ALLOCATION_NONE);
+ count++;
- CLUTTER_UNSET_PRIVATE_FLAGS (stage, CLUTTER_IN_RELAYOUT);
+ /* Prevent using an iterator that's been invalidated */
+ if (old_version != priv->pending_relayouts_version)
+ g_hash_table_iter_init (&iter, priv->pending_relayouts);
}
+
+ CLUTTER_NOTE (ACTOR, "<<< Completed recomputing layout of %d subtrees", count);
+
+ if (count)
+ priv->stage_was_relayout = TRUE;
}
static void
@@ -1511,14 +1548,9 @@ static void
clutter_stage_real_queue_relayout (ClutterActor *self)
{
ClutterStage *stage = CLUTTER_STAGE (self);
- ClutterStagePrivate *priv = stage->priv;
ClutterActorClass *parent_class;
- if (!priv->relayout_pending)
- {
- _clutter_stage_schedule_update (stage);
- priv->relayout_pending = TRUE;
- }
+ clutter_stage_queue_actor_relayout (stage, self);
/* chain up */
parent_class = CLUTTER_ACTOR_CLASS (clutter_stage_parent_class);
@@ -1912,6 +1944,8 @@ clutter_stage_dispose (GObject *object)
(GDestroyNotify) free_queue_redraw_entry);
priv->pending_queue_redraws = NULL;
+ g_clear_pointer (&priv->pending_relayouts, g_hash_table_destroy);
+
/* this will release the reference on the stage */
stage_manager = clutter_stage_manager_get_default ();
_clutter_stage_manager_remove_stage (stage_manager, stage);
@@ -2271,7 +2305,11 @@ clutter_stage_init (ClutterStage *self)
clutter_actor_set_background_color (CLUTTER_ACTOR (self),
&default_stage_color);
- priv->relayout_pending = TRUE;
+ priv->pending_relayouts = g_hash_table_new_full (NULL,
+ NULL,
+ g_object_unref,
+ NULL);
+ clutter_stage_queue_actor_relayout (self, CLUTTER_ACTOR (self));
clutter_actor_set_reactive (CLUTTER_ACTOR (self), TRUE);
clutter_stage_set_title (self, g_get_prgname ());
@@ -3346,10 +3384,9 @@ clutter_stage_ensure_redraw (ClutterStage *stage)
priv = stage->priv;
- if (!priv->relayout_pending && !priv->redraw_pending)
+ if (!_clutter_stage_needs_update (stage))
_clutter_stage_schedule_update (stage);
- priv->relayout_pending = TRUE;
priv->redraw_pending = TRUE;
master_clock = _clutter_master_clock_get_default ();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]