st: implement ClutterActorClass.has_accessible()

Implement ClutterActorClass.has_accessible() to ensure that CallyActor does not
recreate accessibles during the removal/destruction of an actor.  This relies
on GNOME/mutter!1083 for the ClutterActorClass.has_accessible virtual function.

Running GNOME Shell for about 30 seconds results in a difference between
the two runs.

Before:

    ALLOCATED      TOTAL    FUNCTION
[   52.2 KiB] [   0.05%]    cally_actor_real_remove_actor
[   36.3 KiB] [   0.04%]      st_widget_get_accessible
[    9.8 KiB] [   0.01%]      atk_gobject_accessible_for_object
[    3.2 KiB] [   0.00%]      g_signal_emit_by_name
[    2.9 KiB] [   0.00%]      clutter_actor_get_children

After:

    ALLOCATED      TOTAL    FUNCTION
[    1.8 KiB] [   0.00%]    cally_actor_real_remove_actor
[    1.1 KiB] [   0.00%]      clutter_actor_get_children
[  659 bytes] [   0.00%]      g_signal_emit_by_name

Obviously 50KiB isn't a huge savings.

Although fixing things to avoid re-entrancy on destruction can be very useful
from a correctness standpoint.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/2263
This commit is contained in:
Christian Hergert 2020-02-23 14:08:41 -08:00 committed by Christian Hergert
parent d9f8e04478
commit 24a3fd4c4d

View File

@ -141,6 +141,7 @@ static gboolean st_widget_real_navigate_focus (StWidget *widget,
StDirectionType direction);
static AtkObject * st_widget_get_accessible (ClutterActor *actor);
static gboolean st_widget_has_accessible (ClutterActor *actor);
static void
st_widget_set_property (GObject *gobject,
@ -846,6 +847,7 @@ st_widget_class_init (StWidgetClass *klass)
actor_class->key_press_event = st_widget_key_press_event;
actor_class->get_accessible = st_widget_get_accessible;
actor_class->has_accessible = st_widget_has_accessible;
klass->style_changed = st_widget_real_style_changed;
klass->navigate_focus = st_widget_real_navigate_focus;
@ -2650,6 +2652,20 @@ struct _StWidgetAccessiblePrivate
G_DEFINE_TYPE_WITH_PRIVATE (StWidgetAccessible, st_widget_accessible, CALLY_TYPE_ACTOR)
static gboolean
st_widget_has_accessible (ClutterActor *actor)
{
StWidget *widget;
StWidgetPrivate *priv;
g_return_val_if_fail (ST_IS_WIDGET (actor), FALSE);
widget = ST_WIDGET (actor);
priv = st_widget_get_instance_private (widget);
return priv->accessible != NULL;
}
static AtkObject *
st_widget_get_accessible (ClutterActor *actor)
{