clutter/actor: Remove transitions when removing an effect
If there are any in-progress transitions on any properties of the effect, these will cause a crash next time they tick and update, as they will try to access a `@effects.${effect_name}.${property_name}` property on the `ClutterActor` which no longer resolves to an effect. In some cases this will be because `priv->effects` itself is now `NULL` on the `ClutterActor`. This can be triggered by rapidly toggling screen time limits on and off in gnome-shell with a low screen time limit which has already been reached for the day. It will alternately add a desaturation effect and fade-in transition, then remove the effect, then the transition will update and crash. Avoid this by removing relevant transitions when removing an effect. Do the same for the other two groups of metas: constraints and actions, as they will be subject to the same bug (under different reproducer conditions). And the same for when any of these three meta groups are cleared, as that could also trigger the same bug. Signed-off-by: Philip Withnall <pwithnall@gnome.org> Closes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/8168 Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4222>
This commit is contained in:
parent
b674048184
commit
c250f602bd
@ -3251,6 +3251,57 @@ cull_actor (ClutterActor *self,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Remove any transitions on properties with @prefix. */
|
||||||
|
static void
|
||||||
|
_clutter_actor_remove_transitions_for_prefix (ClutterActor *actor,
|
||||||
|
const char *prefix)
|
||||||
|
{
|
||||||
|
ClutterAnimationInfo *info;
|
||||||
|
|
||||||
|
info = _clutter_actor_get_animation_info (actor);
|
||||||
|
|
||||||
|
if (info->transitions != NULL)
|
||||||
|
{
|
||||||
|
GHashTableIter iter;
|
||||||
|
gpointer key, value;
|
||||||
|
g_autoptr (GPtrArray) to_remove = g_ptr_array_new_with_free_func (NULL);
|
||||||
|
|
||||||
|
g_hash_table_iter_init (&iter, info->transitions);
|
||||||
|
|
||||||
|
while (g_hash_table_iter_next (&iter, &key, &value))
|
||||||
|
{
|
||||||
|
if (g_str_has_prefix (key, prefix))
|
||||||
|
g_ptr_array_add (to_remove, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < to_remove->len; i++)
|
||||||
|
clutter_actor_remove_transition (actor, to_remove->pdata[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove any transitions on the properties of @meta.
|
||||||
|
* @section should be "actions", "constraints" or "effects" */
|
||||||
|
static void
|
||||||
|
_clutter_actor_remove_transitions_for_meta_internal (ClutterActor *actor,
|
||||||
|
const char *section,
|
||||||
|
ClutterActorMeta *meta)
|
||||||
|
{
|
||||||
|
g_autofree char *meta_prefix =
|
||||||
|
g_strdup_printf ("@%s.%s.", section,
|
||||||
|
clutter_actor_meta_get_name (meta));
|
||||||
|
_clutter_actor_remove_transitions_for_prefix (actor, meta_prefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove any transitions on the properties of any #ClutterActorMeta in @section.
|
||||||
|
* @section should be "actions", "constraints" or "effects" */
|
||||||
|
static void
|
||||||
|
_clutter_actor_remove_transitions_for_meta_section_internal (ClutterActor *actor,
|
||||||
|
const char *section)
|
||||||
|
{
|
||||||
|
g_autofree char *meta_prefix = g_strdup_printf ("@%s.", section);
|
||||||
|
_clutter_actor_remove_transitions_for_prefix (actor, meta_prefix);
|
||||||
|
}
|
||||||
|
|
||||||
/* This is the same as clutter_actor_add_effect except that it doesn't
|
/* This is the same as clutter_actor_add_effect except that it doesn't
|
||||||
queue a redraw and it doesn't notify on the effect property */
|
queue a redraw and it doesn't notify on the effect property */
|
||||||
static void
|
static void
|
||||||
@ -3279,6 +3330,10 @@ _clutter_actor_remove_effect_internal (ClutterActor *self,
|
|||||||
if (priv->effects == NULL)
|
if (priv->effects == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* Remove any transitions on the effect’s properties. */
|
||||||
|
_clutter_actor_remove_transitions_for_meta_internal (self, "effects",
|
||||||
|
CLUTTER_ACTOR_META (effect));
|
||||||
|
|
||||||
_clutter_meta_group_remove_meta (priv->effects, CLUTTER_ACTOR_META (effect));
|
_clutter_meta_group_remove_meta (priv->effects, CLUTTER_ACTOR_META (effect));
|
||||||
|
|
||||||
if (_clutter_meta_group_peek_metas (priv->effects) == NULL)
|
if (_clutter_meta_group_peek_metas (priv->effects) == NULL)
|
||||||
@ -13728,6 +13783,10 @@ clutter_actor_remove_action (ClutterActor *self,
|
|||||||
if (priv->actions == NULL)
|
if (priv->actions == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* Remove any transitions on the actions’s properties. */
|
||||||
|
_clutter_actor_remove_transitions_for_meta_internal (self, "actions",
|
||||||
|
CLUTTER_ACTOR_META (action));
|
||||||
|
|
||||||
_clutter_meta_group_remove_meta (priv->actions, CLUTTER_ACTOR_META (action));
|
_clutter_meta_group_remove_meta (priv->actions, CLUTTER_ACTOR_META (action));
|
||||||
|
|
||||||
if (_clutter_meta_group_peek_metas (priv->actions) == NULL)
|
if (_clutter_meta_group_peek_metas (priv->actions) == NULL)
|
||||||
@ -13763,6 +13822,9 @@ clutter_actor_remove_action_by_name (ClutterActor *self,
|
|||||||
if (meta == NULL)
|
if (meta == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* Remove any transitions on the actions’s properties. */
|
||||||
|
_clutter_actor_remove_transitions_for_meta_internal (self, "actions", meta);
|
||||||
|
|
||||||
_clutter_meta_group_remove_meta (priv->actions, meta);
|
_clutter_meta_group_remove_meta (priv->actions, meta);
|
||||||
|
|
||||||
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_ACTIONS]);
|
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_ACTIONS]);
|
||||||
@ -13829,6 +13891,7 @@ clutter_actor_clear_actions (ClutterActor *self)
|
|||||||
if (self->priv->actions == NULL)
|
if (self->priv->actions == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
_clutter_actor_remove_transitions_for_meta_section_internal (self, "actions");
|
||||||
_clutter_meta_group_clear_metas_no_internal (self->priv->actions);
|
_clutter_meta_group_clear_metas_no_internal (self->priv->actions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -13920,6 +13983,10 @@ clutter_actor_remove_constraint (ClutterActor *self,
|
|||||||
if (priv->constraints == NULL)
|
if (priv->constraints == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* Remove any transitions on the constraint’s properties. */
|
||||||
|
_clutter_actor_remove_transitions_for_meta_internal (self, "constraints",
|
||||||
|
CLUTTER_ACTOR_META (constraint));
|
||||||
|
|
||||||
_clutter_meta_group_remove_meta (priv->constraints,
|
_clutter_meta_group_remove_meta (priv->constraints,
|
||||||
CLUTTER_ACTOR_META (constraint));
|
CLUTTER_ACTOR_META (constraint));
|
||||||
|
|
||||||
@ -13958,6 +14025,9 @@ clutter_actor_remove_constraint_by_name (ClutterActor *self,
|
|||||||
if (meta == NULL)
|
if (meta == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* Remove any transitions on the constraint’s properties. */
|
||||||
|
_clutter_actor_remove_transitions_for_meta_internal (self, "constraints", meta);
|
||||||
|
|
||||||
_clutter_meta_group_remove_meta (priv->constraints, meta);
|
_clutter_meta_group_remove_meta (priv->constraints, meta);
|
||||||
clutter_actor_queue_relayout (self);
|
clutter_actor_queue_relayout (self);
|
||||||
}
|
}
|
||||||
@ -14023,6 +14093,7 @@ clutter_actor_clear_constraints (ClutterActor *self)
|
|||||||
if (self->priv->constraints == NULL)
|
if (self->priv->constraints == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
_clutter_actor_remove_transitions_for_meta_section_internal (self, "constraints");
|
||||||
_clutter_meta_group_clear_metas_no_internal (self->priv->constraints);
|
_clutter_meta_group_clear_metas_no_internal (self->priv->constraints);
|
||||||
|
|
||||||
clutter_actor_queue_relayout (self);
|
clutter_actor_queue_relayout (self);
|
||||||
@ -14248,6 +14319,7 @@ clutter_actor_clear_effects (ClutterActor *self)
|
|||||||
if (self->priv->effects == NULL)
|
if (self->priv->effects == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
_clutter_actor_remove_transitions_for_meta_section_internal (self, "effects");
|
||||||
_clutter_meta_group_clear_metas_no_internal (self->priv->effects);
|
_clutter_meta_group_clear_metas_no_internal (self->priv->effects);
|
||||||
|
|
||||||
clutter_actor_queue_redraw (self);
|
clutter_actor_queue_redraw (self);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user