a11y: Plug reference leaks

The gtk_accessible_get_at_context() getter is now transfer full, which
means we need to drop the reference when getting the GtkATContext.
This commit is contained in:
Emmanuele Bassi 2023-03-03 19:07:16 +00:00
parent 9b98426e71
commit 500128d186
7 changed files with 184 additions and 50 deletions

View File

@ -127,7 +127,10 @@ gtk_accessible_get_accessible_parent (GtkAccessible *self)
context = gtk_accessible_get_at_context (self);
if (context != NULL)
parent = gtk_at_context_get_accessible_parent (context);
{
parent = gtk_at_context_get_accessible_parent (context);
g_object_unref (context);
}
if (parent != NULL)
return g_object_ref (parent);
@ -161,6 +164,7 @@ gtk_accessible_set_accessible_parent (GtkAccessible *self,
g_return_if_fail (GTK_IS_ACCESSIBLE (self));
g_return_if_fail (parent == NULL || GTK_IS_ACCESSIBLE (parent));
g_return_if_fail (next_sibling == NULL || GTK_IS_ACCESSIBLE (parent));
GtkATContext *context;
context = gtk_accessible_get_at_context (self);
@ -168,6 +172,7 @@ gtk_accessible_set_accessible_parent (GtkAccessible *self,
{
gtk_at_context_set_accessible_parent (context, parent);
gtk_at_context_set_next_accessible_sibling (context, next_sibling);
g_object_unref (context);
}
}
@ -188,20 +193,26 @@ gtk_accessible_update_next_accessible_sibling (GtkAccessible *self,
GtkAccessible *new_sibling)
{
GtkATContext *context;
GtkAccessible *parent;
g_return_if_fail (GTK_IS_ACCESSIBLE (self));
context = gtk_accessible_get_at_context (self);
if (!context)
if (context == NULL)
return;
if (gtk_at_context_get_accessible_parent (context) == NULL)
{
g_critical ("Failed to update next accessible sibling: no parent accessible set for this accessible");
return;
}
parent = gtk_at_context_get_accessible_parent (context);
if (parent == NULL)
{
g_object_unref (context);
g_critical ("Failed to update next accessible sibling: no parent accessible set for this accessible");
return;
}
gtk_at_context_set_next_accessible_sibling (context, new_sibling);
g_object_unref (parent);
g_object_unref (context);
}
/**
@ -240,14 +251,20 @@ gtk_accessible_get_next_accessible_sibling (GtkAccessible *self)
GtkATContext *context;
context = gtk_accessible_get_at_context (self);
if (context != NULL && gtk_at_context_get_accessible_parent (context) != NULL)
if (context != NULL)
{
GtkAccessible *sibling = gtk_at_context_get_next_accessible_sibling (context);
GtkAccessible *sibling = NULL;
if (sibling != NULL)
return g_object_ref (sibling);
if (gtk_at_context_get_accessible_parent (context) != NULL)
{
sibling = gtk_at_context_get_next_accessible_sibling (context);
if (sibling != NULL)
sibling = g_object_ref (sibling);
}
return NULL;
g_object_unref (context);
return sibling;
}
else
return GTK_ACCESSIBLE_GET_IFACE (self)->get_next_accessible_sibling (self);
@ -264,13 +281,21 @@ gtk_accessible_get_next_accessible_sibling (GtkAccessible *self)
GtkAccessibleRole
gtk_accessible_get_accessible_role (GtkAccessible *self)
{
GtkAccessibleRole role;
GtkAccessibleRole role = GTK_ACCESSIBLE_ROLE_NONE;
g_return_val_if_fail (GTK_IS_ACCESSIBLE (self), GTK_ACCESSIBLE_ROLE_NONE);
GtkATContext *context = gtk_accessible_get_at_context (self);
if (context != NULL && gtk_at_context_is_realized (context))
return gtk_at_context_get_accessible_role (context);
if (context != NULL)
{
if (gtk_at_context_is_realized (context))
role = gtk_at_context_get_accessible_role (context);
g_object_unref (context);
if (role != GTK_ACCESSIBLE_ROLE_NONE)
return role;
}
g_object_get (G_OBJECT (self), "accessible-role", &role, NULL);
@ -344,6 +369,8 @@ gtk_accessible_update_state (GtkAccessible *self,
out:
va_end (args);
g_object_unref (context);
}
/**
@ -397,6 +424,7 @@ gtk_accessible_update_state_value (GtkAccessible *self,
}
gtk_at_context_update (context);
g_object_unref (context);
}
/**
@ -420,6 +448,7 @@ gtk_accessible_reset_state (GtkAccessible *self,
gtk_at_context_set_accessible_state (context, state, NULL);
gtk_at_context_update (context);
g_object_unref (context);
}
/**
@ -491,6 +520,8 @@ gtk_accessible_update_property (GtkAccessible *self,
out:
va_end (args);
g_object_unref (context);
}
/**
@ -544,6 +575,7 @@ gtk_accessible_update_property_value (GtkAccessible *self,
}
gtk_at_context_update (context);
g_object_unref (context);
}
/**
@ -567,6 +599,7 @@ gtk_accessible_reset_property (GtkAccessible *self,
gtk_at_context_set_accessible_property (context, property, NULL);
gtk_at_context_update (context);
g_object_unref (context);
}
/**
@ -638,6 +671,8 @@ gtk_accessible_update_relation (GtkAccessible *self,
out:
va_end (args);
g_object_unref (context);
}
/**
@ -666,6 +701,8 @@ gtk_accessible_update_relation_value (GtkAccessible *self,
g_return_if_fail (n_relations > 0);
context = gtk_accessible_get_at_context (self);
if (context == NULL)
return;
for (int i = 0; i < n_relations; i++)
{
@ -684,15 +721,14 @@ gtk_accessible_update_relation_value (GtkAccessible *self,
break;
}
if (context)
gtk_at_context_set_accessible_relation (context, relation, real_value);
gtk_at_context_set_accessible_relation (context, relation, real_value);
if (real_value != NULL)
gtk_accessible_value_unref (real_value);
}
if (context)
gtk_at_context_update (context);
gtk_at_context_update (context);
g_object_unref (context);
}
/**
@ -716,6 +752,7 @@ gtk_accessible_reset_relation (GtkAccessible *self,
gtk_at_context_set_accessible_relation (context, relation, NULL);
gtk_at_context_update (context);
g_object_unref (context);
}
static const char *role_names[] = {
@ -876,13 +913,22 @@ gtk_accessible_platform_changed (GtkAccessible *self,
/* propagate changes up from ignored widgets */
if (gtk_accessible_get_accessible_role (self) == GTK_ACCESSIBLE_ROLE_NONE)
context = gtk_accessible_get_at_context (gtk_accessible_get_accessible_parent (self));
{
GtkAccessible *parent = gtk_accessible_get_accessible_parent (self);
if (parent != NULL)
{
context = gtk_accessible_get_at_context (parent);
g_object_unref (parent);
}
}
if (context == NULL)
return;
gtk_at_context_platform_changed (context, change);
gtk_at_context_update (context);
g_object_unref (context);
}
/**
@ -936,6 +982,7 @@ gtk_accessible_bounds_changed (GtkAccessible *self)
return;
gtk_at_context_bounds_changed (context);
g_object_unref (context);
}
/**
@ -988,6 +1035,7 @@ gtk_accessible_should_present (GtkAccessible *self)
{
GtkAccessibleRole role;
GtkATContext *context;
gboolean res = TRUE;
if (GTK_IS_WIDGET (self) &&
!gtk_widget_get_visible (GTK_WIDGET (self)))
@ -1008,10 +1056,12 @@ gtk_accessible_should_present (GtkAccessible *self)
value = gtk_at_context_get_accessible_state (context, GTK_ACCESSIBLE_STATE_HIDDEN);
if (gtk_boolean_accessible_value_get (value))
return FALSE;
res = FALSE;
}
return TRUE;
g_object_unref (context);
return res;
}
void
@ -1025,15 +1075,24 @@ gtk_accessible_update_children (GtkAccessible *self,
gtk_widget_get_root (GTK_WIDGET (self)) == NULL)
return;
context = gtk_accessible_get_at_context (self);
/* propagate changes up from ignored widgets */
if (gtk_accessible_get_accessible_role (self) == GTK_ACCESSIBLE_ROLE_NONE)
context = gtk_accessible_get_at_context (gtk_accessible_get_accessible_parent (self));
{
GtkAccessible *parent = gtk_accessible_get_accessible_parent (self);
context = gtk_accessible_get_at_context (parent);
g_object_unref (parent);
}
else
{
context = gtk_accessible_get_at_context (self);
}
if (context == NULL)
return;
gtk_at_context_child_changed (context, 1 << state, child);
gtk_at_context_update (context);
g_object_unref (context);
}

View File

@ -996,6 +996,8 @@ gtk_at_context_get_name_accumulate (GtkATContext *self,
GtkATContext *rel_context = gtk_accessible_get_at_context (rel);
gtk_at_context_get_name_accumulate (rel_context, names, FALSE);
g_object_unref (rel_context);
}
}
@ -1068,6 +1070,8 @@ gtk_at_context_get_description_accumulate (GtkATContext *self,
GtkATContext *rel_context = gtk_accessible_get_at_context (rel);
gtk_at_context_get_description_accumulate (rel_context, labels, FALSE);
g_object_unref (rel_context);
}
}

View File

@ -329,6 +329,8 @@ update_at_context (GtkModelButton *button)
if (was_realized)
gtk_at_context_realize (context);
g_object_unref (context);
}
static void
@ -1199,7 +1201,7 @@ gtk_model_button_class_init (GtkModelButtonClass *class)
* A GIcon that will be used if iconic appearance for the button is
* desired.
*/
properties[PROP_ICON] =
properties[PROP_ICON] =
g_param_spec_object ("icon", NULL, NULL,
G_TYPE_ICON,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);

View File

@ -172,6 +172,7 @@ gtk_test_accessible_has_property (GtkAccessible *accessible,
GtkAccessibleProperty property)
{
GtkATContext *context;
gboolean res;
g_return_val_if_fail (GTK_IS_ACCESSIBLE (accessible), FALSE);
@ -179,7 +180,11 @@ gtk_test_accessible_has_property (GtkAccessible *accessible,
if (context == NULL)
return FALSE;
return gtk_at_context_has_accessible_property (context, property);
res = gtk_at_context_has_accessible_property (context, property);
g_object_unref (context);
return res;
}
/**
@ -230,6 +235,7 @@ gtk_test_accessible_check_property (GtkAccessible *accessible,
out:
gtk_accessible_value_unref (check_value);
g_object_unref (context);
return res;
}
@ -248,6 +254,7 @@ gtk_test_accessible_has_state (GtkAccessible *accessible,
GtkAccessibleState state)
{
GtkATContext *context;
gboolean res;
g_return_val_if_fail (GTK_IS_ACCESSIBLE (accessible), FALSE);
@ -255,7 +262,11 @@ gtk_test_accessible_has_state (GtkAccessible *accessible,
if (context == NULL)
return FALSE;
return gtk_at_context_has_accessible_state (context, state);
res = gtk_at_context_has_accessible_state (context, state);
g_object_unref (context);
return res;
}
/**
@ -306,6 +317,7 @@ gtk_test_accessible_check_state (GtkAccessible *accessible,
out:
gtk_accessible_value_unref (check_value);
g_object_unref (context);
return res;
}
@ -324,6 +336,7 @@ gtk_test_accessible_has_relation (GtkAccessible *accessible,
GtkAccessibleRelation relation)
{
GtkATContext *context;
gboolean res;
g_return_val_if_fail (GTK_IS_ACCESSIBLE (accessible), FALSE);
@ -331,7 +344,11 @@ gtk_test_accessible_has_relation (GtkAccessible *accessible,
if (context == NULL)
return FALSE;
return gtk_at_context_has_accessible_relation (context, relation);
res = gtk_at_context_has_accessible_relation (context, relation);
g_object_unref (context);
return res;
}
/**
@ -382,6 +399,7 @@ gtk_test_accessible_check_relation (GtkAccessible *accessible,
out:
gtk_accessible_value_unref (check_value);
g_object_unref (context);
return res;
}

View File

@ -633,6 +633,7 @@ static void remove_parent_surface_transform_changed_listener (GtkWidget *wid
static void add_parent_surface_transform_changed_listener (GtkWidget *widget);
static void gtk_widget_queue_compute_expand (GtkWidget *widget);
static GtkATContext *create_at_context (GtkWidget *self);
static int GtkWidget_private_offset = 0;
@ -904,8 +905,18 @@ gtk_widget_get_accessible_role (GtkWidget *self)
GtkATContext *context = gtk_accessible_get_at_context (GTK_ACCESSIBLE (self));
GtkWidgetClassPrivate *class_priv;
if (context != NULL && gtk_at_context_is_realized (context))
return gtk_at_context_get_accessible_role (context);
if (context != NULL)
{
GtkAccessibleRole role = GTK_ACCESSIBLE_ROLE_NONE;
if (gtk_at_context_is_realized (context))
role = gtk_at_context_get_accessible_role (context);
g_object_unref (context);
if (role != GTK_ACCESSIBLE_ROLE_NONE)
return role;
}
if (priv->accessible_role != GTK_ACCESSIBLE_ROLE_WIDGET)
return priv->accessible_role;
@ -2361,7 +2372,7 @@ gtk_widget_init (GTypeInstance *instance, gpointer g_class)
gtk_widget_add_controller (widget, controller);
}
priv->at_context = gtk_accessible_get_at_context (GTK_ACCESSIBLE (widget));
priv->at_context = create_at_context (widget);
}
static void
@ -7353,7 +7364,6 @@ gtk_widget_dispose (GObject *object)
GtkWidget *widget = GTK_WIDGET (object);
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
GSList *sizegroups;
GtkATContext *at_context;
if (priv->muxer != NULL)
g_object_run_dispose (G_OBJECT (priv->muxer));
@ -7403,9 +7413,11 @@ gtk_widget_dispose (GObject *object)
gtk_size_group_remove_widget (size_group, widget);
}
at_context = gtk_accessible_get_at_context (GTK_ACCESSIBLE (widget));
if (at_context != NULL)
gtk_at_context_unrealize (at_context);
if (priv->at_context != NULL)
{
gtk_at_context_unrealize (priv->at_context);
g_clear_object (&priv->at_context);
}
g_clear_object (&priv->muxer);
@ -8428,9 +8440,8 @@ gtk_widget_set_vexpand_set (GtkWidget *widget,
*/
static GtkATContext *
gtk_widget_accessible_get_at_context (GtkAccessible *accessible)
create_at_context (GtkWidget *self)
{
GtkWidget *self = GTK_WIDGET (accessible);
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (self);
GtkWidgetClass *widget_class = GTK_WIDGET_GET_CLASS (self);
GtkWidgetClassPrivate *class_priv = widget_class->priv;
@ -8444,9 +8455,6 @@ gtk_widget_accessible_get_at_context (GtkAccessible *accessible)
return NULL;
}
if (priv->at_context != NULL)
return priv->at_context;
/* Widgets have two options to set the accessible role: either they
* define it in their class_init() function, and the role applies to
* all instances; or an instance is created with the :accessible-role
@ -8461,9 +8469,35 @@ gtk_widget_accessible_get_at_context (GtkAccessible *accessible)
role = class_priv->accessible_role;
priv->accessible_role = role;
priv->at_context = gtk_at_context_create (role, accessible, gdk_display_get_default ());
priv->at_context = gtk_at_context_create (role, GTK_ACCESSIBLE (self), gdk_display_get_default ());
if (priv->at_context != NULL)
return g_object_ref (priv->at_context);
return priv->at_context;
return NULL;
}
static GtkATContext *
gtk_widget_accessible_get_at_context (GtkAccessible *accessible)
{
GtkWidget *self = GTK_WIDGET (accessible);
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (self);
if (priv->in_destruction)
{
GTK_DEBUG (A11Y, "ATContext for widget “%s” [%p] accessed during destruction",
G_OBJECT_TYPE_NAME (self),
self);
return NULL;
}
if (priv->at_context != NULL)
return g_object_ref (priv->at_context);
priv->at_context = create_at_context (self);
if (priv->at_context != NULL)
return g_object_ref (priv->at_context);
return NULL;
}
static gboolean
@ -9300,6 +9334,8 @@ gtk_widget_buildable_finish_accessibility_properties (GtkWidget *widget,
}
g_slist_free_full (attributes, accessibility_attribute_info_free);
g_object_unref (context);
}
static void

View File

@ -244,6 +244,8 @@ update_path (GtkInspectorA11y *sl)
}
else
path = "not on bus";
g_clear_object (&context);
#endif
gtk_label_set_label (GTK_LABEL (sl->path), path);
@ -270,7 +272,7 @@ update_attributes (GtkInspectorA11y *sl)
gboolean has_value;
context = gtk_accessible_get_at_context (GTK_ACCESSIBLE (sl->object));
if (!context)
if (context == NULL)
return;
store = g_list_store_new (G_TYPE_OBJECT);
@ -347,6 +349,8 @@ update_attributes (GtkInspectorA11y *sl)
g_object_unref (selection);
gtk_widget_set_visible (sl->attributes, g_list_model_get_n_items (G_LIST_MODEL (filter_model)) > 0);
g_object_unref (context);
}
static void
@ -420,8 +424,11 @@ gtk_inspector_a11y_set_object (GtkInspectorA11y *sl,
if (sl->object && GTK_IS_ACCESSIBLE (sl->object))
{
context = gtk_accessible_get_at_context (GTK_ACCESSIBLE (sl->object));
if (context)
g_signal_handlers_disconnect_by_func (context, refresh_all, sl);
if (context != NULL)
{
g_signal_handlers_disconnect_by_func (context, refresh_all, sl);
g_object_unref (context);
}
}
g_set_object (&sl->object, object);
@ -432,8 +439,12 @@ gtk_inspector_a11y_set_object (GtkInspectorA11y *sl,
if (GTK_IS_ACCESSIBLE (sl->object))
{
context = gtk_accessible_get_at_context (GTK_ACCESSIBLE (sl->object));
if (context)
g_signal_connect_swapped (context, "state-change", G_CALLBACK (refresh_all), sl);
if (context != NULL)
{
g_signal_connect_swapped (context, "state-change", G_CALLBACK (refresh_all), sl);
g_object_unref (context);
}
gtk_stack_page_set_visible (page, TRUE);
update_role (sl);
update_path (sl);
@ -461,7 +472,11 @@ dispose (GObject *o)
GtkATContext *context;
context = gtk_accessible_get_at_context (GTK_ACCESSIBLE (sl->object));
g_signal_handlers_disconnect_by_func (context, refresh_all, sl);
if (context != NULL)
{
g_signal_handlers_disconnect_by_func (context, refresh_all, sl);
g_object_unref (context);
}
}
g_clear_object (&sl->object);

View File

@ -33,7 +33,7 @@ test_object_accessible_get_at_context (GtkAccessible *accessible)
accessible,
gdk_display_get_default ());
return self->at_context;
return g_object_ref (self->at_context);
}
static void