clutter/timeline: Listen to 'stage-view-changed' on picked actor

When we pick the frame clock given the associated actor, that frame
clock in fact comes from a picked actor. In order to not end up with
stale frame clocks, which may happen on e.g. hotplugs, monitor layout
changes, or non-optimal frame clocks, which may happen when the parent
used for picking the clock moves to another view, lets listen to
'stage-views-changed' on the actor used for picking the clock too.

Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1327
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1404
This commit is contained in:
Jonas Ådahl 2020-08-12 19:27:47 +02:00
parent c6fc3a8953
commit 06c4841e22

View File

@ -114,6 +114,8 @@ struct _ClutterTimelinePrivate
ClutterFrameClock *custom_frame_clock; ClutterFrameClock *custom_frame_clock;
ClutterFrameClock *frame_clock; ClutterFrameClock *frame_clock;
ClutterActor *frame_clock_actor;
gulong frame_clock_actor_stage_views_handler_id;
ClutterActor *actor; ClutterActor *actor;
gulong actor_destroy_handler_id; gulong actor_destroy_handler_id;
@ -383,19 +385,40 @@ on_stage_stage_views_changed (ClutterActor *stage,
update_frame_clock (timeline); update_frame_clock (timeline);
} }
static void
on_frame_clock_actor_stage_views_changed (ClutterActor *frame_clock_actor,
ClutterTimeline *timeline)
{
update_frame_clock (timeline);
}
static void static void
update_frame_clock (ClutterTimeline *timeline) update_frame_clock (ClutterTimeline *timeline)
{ {
ClutterTimelinePrivate *priv = timeline->priv; ClutterTimelinePrivate *priv = timeline->priv;
ClutterFrameClock *frame_clock = NULL; ClutterFrameClock *frame_clock = NULL;
ClutterActor *stage; ClutterActor *stage;
ClutterActor *frame_clock_actor;
if (!priv->actor) if (!priv->actor)
goto out; goto out;
frame_clock = clutter_actor_pick_frame_clock (priv->actor, NULL); if (priv->frame_clock_actor)
{
g_clear_signal_handler (&priv->frame_clock_actor_stage_views_handler_id,
priv->frame_clock_actor);
g_clear_weak_pointer (&priv->frame_clock_actor);
}
frame_clock = clutter_actor_pick_frame_clock (priv->actor, &frame_clock_actor);
if (frame_clock) if (frame_clock)
{ {
g_set_weak_pointer (&priv->frame_clock_actor, frame_clock_actor);
priv->frame_clock_actor_stage_views_handler_id =
g_signal_connect (frame_clock_actor, "stage-views-changed",
G_CALLBACK (on_frame_clock_actor_stage_views_changed),
timeline);
g_clear_signal_handler (&priv->stage_stage_views_handler_id, priv->stage); g_clear_signal_handler (&priv->stage_stage_views_handler_id, priv->stage);
goto out; goto out;
} }
@ -737,6 +760,13 @@ clutter_timeline_dispose (GObject *object)
priv->actor = NULL; priv->actor = NULL;
} }
if (priv->frame_clock_actor)
{
g_clear_signal_handler (&priv->frame_clock_actor_stage_views_handler_id,
priv->frame_clock_actor);
g_clear_weak_pointer (&priv->frame_clock_actor);
}
if (priv->progress_notify != NULL) if (priv->progress_notify != NULL)
{ {
priv->progress_notify (priv->progress_data); priv->progress_notify (priv->progress_data);