diff --git a/gtk/gtkaccessible.c b/gtk/gtkaccessible.c index 3d3839cb68..873094a474 100644 --- a/gtk/gtkaccessible.c +++ b/gtk/gtkaccessible.c @@ -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); } diff --git a/gtk/gtkatcontext.c b/gtk/gtkatcontext.c index e4ca7217d4..e4e66e82aa 100644 --- a/gtk/gtkatcontext.c +++ b/gtk/gtkatcontext.c @@ -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); } } diff --git a/gtk/gtkmodelbutton.c b/gtk/gtkmodelbutton.c index a7ce337968..064583623a 100644 --- a/gtk/gtkmodelbutton.c +++ b/gtk/gtkmodelbutton.c @@ -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); diff --git a/gtk/gtktestatcontext.c b/gtk/gtktestatcontext.c index 3e30b27d10..fc8f84b191 100644 --- a/gtk/gtktestatcontext.c +++ b/gtk/gtktestatcontext.c @@ -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; } diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index f67893837f..3c9537e985 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -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 diff --git a/gtk/inspector/a11y.c b/gtk/inspector/a11y.c index f184489204..7fbaec0c92 100644 --- a/gtk/inspector/a11y.c +++ b/gtk/inspector/a11y.c @@ -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); diff --git a/testsuite/a11y/accessible.c b/testsuite/a11y/accessible.c index 2ea857ac3e..695221d565 100644 --- a/testsuite/a11y/accessible.c +++ b/testsuite/a11y/accessible.c @@ -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