clutter/actor: Don't emit the parent-set signal on destruction
Clutter actors unset their parent on dispose, after emitting the ::destroy signal, however this could cause ::parent-set signal emission. Since we assume that after the destruction has been completed the actor isn't valid anymore, and that during the destroy phase we do all the signal / source disconnections, this might create unwanted behaviors, as in the signal callbacks we always assume that the actor isn't in disposed yet. To avoid this, don't emit ::parent-set signal if the actor is being destroyed. Update the actor-destroy test to verify this behavior. https://gitlab.gnome.org/GNOME/mutter/merge_requests/769
This commit is contained in:
parent
4b88c1832a
commit
f376a318ba
@ -4436,7 +4436,8 @@ clutter_actor_remove_child_internal (ClutterActor *self,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* clutter_actor_reparent() will emit ::parent-set for us */
|
/* clutter_actor_reparent() will emit ::parent-set for us */
|
||||||
if (emit_parent_set && !CLUTTER_ACTOR_IN_REPARENT (child))
|
if (emit_parent_set && !CLUTTER_ACTOR_IN_REPARENT (child) &&
|
||||||
|
!CLUTTER_ACTOR_IN_DESTRUCTION (child))
|
||||||
{
|
{
|
||||||
child->priv->needs_compute_resource_scale = TRUE;
|
child->priv->needs_compute_resource_scale = TRUE;
|
||||||
g_signal_emit (child, actor_signals[PARENT_SET], 0, self);
|
g_signal_emit (child, actor_signals[PARENT_SET], 0, self);
|
||||||
|
@ -161,15 +161,28 @@ on_destroy (ClutterActor *actor,
|
|||||||
{
|
{
|
||||||
gboolean *destroy_called = data;
|
gboolean *destroy_called = data;
|
||||||
|
|
||||||
|
g_assert_true (CLUTTER_IS_ACTOR (clutter_actor_get_parent (actor)));
|
||||||
|
|
||||||
*destroy_called = TRUE;
|
*destroy_called = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_parent_set (ClutterActor *actor,
|
||||||
|
ClutterActor *old_parent,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
gboolean *parent_set_called = data;
|
||||||
|
|
||||||
|
*parent_set_called = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
actor_destruction (void)
|
actor_destruction (void)
|
||||||
{
|
{
|
||||||
ClutterActor *test = g_object_new (TEST_TYPE_DESTROY, NULL);
|
ClutterActor *test = g_object_new (TEST_TYPE_DESTROY, NULL);
|
||||||
ClutterActor *child = clutter_rectangle_new ();
|
ClutterActor *child = clutter_rectangle_new ();
|
||||||
gboolean destroy_called = FALSE;
|
gboolean destroy_called = FALSE;
|
||||||
|
gboolean parent_set_called = FALSE;
|
||||||
|
|
||||||
g_object_ref_sink (test);
|
g_object_ref_sink (test);
|
||||||
|
|
||||||
@ -181,6 +194,8 @@ actor_destruction (void)
|
|||||||
|
|
||||||
clutter_actor_set_name (child, "Child");
|
clutter_actor_set_name (child, "Child");
|
||||||
clutter_container_add_actor (CLUTTER_CONTAINER (test), child);
|
clutter_container_add_actor (CLUTTER_CONTAINER (test), child);
|
||||||
|
g_signal_connect (child, "parent-set", G_CALLBACK (on_parent_set),
|
||||||
|
&parent_set_called);
|
||||||
g_signal_connect (child, "destroy", G_CALLBACK (on_destroy), &destroy_called);
|
g_signal_connect (child, "destroy", G_CALLBACK (on_destroy), &destroy_called);
|
||||||
|
|
||||||
if (g_test_verbose ())
|
if (g_test_verbose ())
|
||||||
@ -188,6 +203,7 @@ actor_destruction (void)
|
|||||||
|
|
||||||
clutter_actor_destroy (test);
|
clutter_actor_destroy (test);
|
||||||
g_assert (destroy_called);
|
g_assert (destroy_called);
|
||||||
|
g_assert_false (parent_set_called);
|
||||||
g_assert_null (child);
|
g_assert_null (child);
|
||||||
g_assert_null (test);
|
g_assert_null (test);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user