mirror of
https://github.com/brl/mutter.git
synced 2024-11-21 15:40:41 -05:00
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
This commit is contained in:
parent
5723bd8ec7
commit
5257c6ecc2
@ -141,6 +141,9 @@ void _clutter_stage_presented (ClutterStage *stag
|
|||||||
|
|
||||||
GList * _clutter_stage_peek_stage_views (ClutterStage *stage);
|
GList * _clutter_stage_peek_stage_views (ClutterStage *stage);
|
||||||
|
|
||||||
|
void clutter_stage_queue_actor_relayout (ClutterStage *stage,
|
||||||
|
ClutterActor *actor);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __CLUTTER_STAGE_PRIVATE_H__ */
|
#endif /* __CLUTTER_STAGE_PRIVATE_H__ */
|
||||||
|
@ -120,6 +120,8 @@ struct _ClutterStagePrivate
|
|||||||
|
|
||||||
ClutterPlane current_clip_planes[4];
|
ClutterPlane current_clip_planes[4];
|
||||||
|
|
||||||
|
GHashTable *pending_relayouts;
|
||||||
|
unsigned int pending_relayouts_version;
|
||||||
GList *pending_queue_redraws;
|
GList *pending_queue_redraws;
|
||||||
|
|
||||||
gint sync_delay;
|
gint sync_delay;
|
||||||
@ -146,7 +148,6 @@ struct _ClutterStagePrivate
|
|||||||
|
|
||||||
int update_freeze_count;
|
int update_freeze_count;
|
||||||
|
|
||||||
guint relayout_pending : 1;
|
|
||||||
guint redraw_pending : 1;
|
guint redraw_pending : 1;
|
||||||
guint is_cursor_visible : 1;
|
guint is_cursor_visible : 1;
|
||||||
guint throttle_motion_events : 1;
|
guint throttle_motion_events : 1;
|
||||||
@ -1287,7 +1288,26 @@ _clutter_stage_needs_update (ClutterStage *stage)
|
|||||||
|
|
||||||
priv = stage->priv;
|
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
|
void
|
||||||
@ -1295,41 +1315,58 @@ _clutter_stage_maybe_relayout (ClutterActor *actor)
|
|||||||
{
|
{
|
||||||
ClutterStage *stage = CLUTTER_STAGE (actor);
|
ClutterStage *stage = CLUTTER_STAGE (actor);
|
||||||
ClutterStagePrivate *priv = stage->priv;
|
ClutterStagePrivate *priv = stage->priv;
|
||||||
gfloat natural_width, natural_height;
|
GHashTableIter iter;
|
||||||
ClutterActorBox box = { 0, };
|
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;
|
return;
|
||||||
|
|
||||||
/* avoid reentrancy */
|
CLUTTER_NOTE (ACTOR, ">>> Recomputing layout");
|
||||||
if (!CLUTTER_ACTOR_IN_RELAYOUT (stage))
|
|
||||||
|
g_hash_table_iter_init (&iter, priv->pending_relayouts);
|
||||||
|
while (g_hash_table_iter_next (&iter, &key, NULL))
|
||||||
{
|
{
|
||||||
priv->relayout_pending = FALSE;
|
g_autoptr (ClutterActor) queued_actor = key;
|
||||||
priv->stage_was_relayout = TRUE;
|
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;
|
||||||
|
|
||||||
natural_width = natural_height = 0;
|
/* An actor may have been destroyed or hidden between queuing and now */
|
||||||
clutter_actor_get_preferred_size (CLUTTER_ACTOR (stage),
|
if (clutter_actor_get_stage (queued_actor) != actor)
|
||||||
NULL, NULL,
|
continue;
|
||||||
&natural_width, &natural_height);
|
|
||||||
|
|
||||||
box.x1 = 0;
|
if (queued_actor == actor)
|
||||||
box.y1 = 0;
|
CLUTTER_NOTE (ACTOR, " Deep relayout of stage %s",
|
||||||
box.x2 = natural_width;
|
_clutter_actor_get_debug_name (queued_actor));
|
||||||
box.y2 = natural_height;
|
else
|
||||||
|
CLUTTER_NOTE (ACTOR, " Shallow relayout of actor %s",
|
||||||
|
_clutter_actor_get_debug_name (queued_actor));
|
||||||
|
|
||||||
CLUTTER_NOTE (ACTOR, "Allocating (0, 0 - %d, %d) for the stage",
|
CLUTTER_SET_PRIVATE_FLAGS (queued_actor, CLUTTER_IN_RELAYOUT);
|
||||||
(int) natural_width,
|
|
||||||
(int) natural_height);
|
|
||||||
|
|
||||||
clutter_actor_allocate (CLUTTER_ACTOR (stage),
|
old_version = priv->pending_relayouts_version;
|
||||||
&box, CLUTTER_ALLOCATION_NONE);
|
clutter_actor_allocate_preferred_size (queued_actor,
|
||||||
|
CLUTTER_ALLOCATION_NONE);
|
||||||
|
|
||||||
CLUTTER_UNSET_PRIVATE_FLAGS (stage, CLUTTER_IN_RELAYOUT);
|
CLUTTER_UNSET_PRIVATE_FLAGS (queued_actor, CLUTTER_IN_RELAYOUT);
|
||||||
|
|
||||||
|
count++;
|
||||||
|
|
||||||
|
/* 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
|
static void
|
||||||
@ -1511,14 +1548,9 @@ static void
|
|||||||
clutter_stage_real_queue_relayout (ClutterActor *self)
|
clutter_stage_real_queue_relayout (ClutterActor *self)
|
||||||
{
|
{
|
||||||
ClutterStage *stage = CLUTTER_STAGE (self);
|
ClutterStage *stage = CLUTTER_STAGE (self);
|
||||||
ClutterStagePrivate *priv = stage->priv;
|
|
||||||
ClutterActorClass *parent_class;
|
ClutterActorClass *parent_class;
|
||||||
|
|
||||||
if (!priv->relayout_pending)
|
clutter_stage_queue_actor_relayout (stage, self);
|
||||||
{
|
|
||||||
_clutter_stage_schedule_update (stage);
|
|
||||||
priv->relayout_pending = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* chain up */
|
/* chain up */
|
||||||
parent_class = CLUTTER_ACTOR_CLASS (clutter_stage_parent_class);
|
parent_class = CLUTTER_ACTOR_CLASS (clutter_stage_parent_class);
|
||||||
@ -1912,6 +1944,8 @@ clutter_stage_dispose (GObject *object)
|
|||||||
(GDestroyNotify) free_queue_redraw_entry);
|
(GDestroyNotify) free_queue_redraw_entry);
|
||||||
priv->pending_queue_redraws = NULL;
|
priv->pending_queue_redraws = NULL;
|
||||||
|
|
||||||
|
g_clear_pointer (&priv->pending_relayouts, g_hash_table_destroy);
|
||||||
|
|
||||||
/* this will release the reference on the stage */
|
/* this will release the reference on the stage */
|
||||||
stage_manager = clutter_stage_manager_get_default ();
|
stage_manager = clutter_stage_manager_get_default ();
|
||||||
_clutter_stage_manager_remove_stage (stage_manager, stage);
|
_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),
|
clutter_actor_set_background_color (CLUTTER_ACTOR (self),
|
||||||
&default_stage_color);
|
&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_actor_set_reactive (CLUTTER_ACTOR (self), TRUE);
|
||||||
clutter_stage_set_title (self, g_get_prgname ());
|
clutter_stage_set_title (self, g_get_prgname ());
|
||||||
@ -3346,10 +3384,9 @@ clutter_stage_ensure_redraw (ClutterStage *stage)
|
|||||||
|
|
||||||
priv = stage->priv;
|
priv = stage->priv;
|
||||||
|
|
||||||
if (!priv->relayout_pending && !priv->redraw_pending)
|
if (!_clutter_stage_needs_update (stage))
|
||||||
_clutter_stage_schedule_update (stage);
|
_clutter_stage_schedule_update (stage);
|
||||||
|
|
||||||
priv->relayout_pending = TRUE;
|
|
||||||
priv->redraw_pending = TRUE;
|
priv->redraw_pending = TRUE;
|
||||||
|
|
||||||
master_clock = _clutter_master_clock_get_default ();
|
master_clock = _clutter_master_clock_get_default ();
|
||||||
|
Loading…
Reference in New Issue
Block a user