diff options
author | Emmanuele Bassi <ebassi@gmail.com> | 2020-10-19 20:26:57 +0000 |
---|---|---|
committer | Emmanuele Bassi <ebassi@gmail.com> | 2020-10-19 20:26:57 +0000 |
commit | 51f5690ae30b5c35ddfe80b4c41852803acf7df1 (patch) | |
tree | 724e70d0212dd256d5d4e60d19c3a48dd3eb2e88 /gtk/gtkatcontext.c | |
parent | e58e6a0fbe257888e2f065b992016b888fe5fae7 (diff) | |
parent | dfc7d26275f1cf402e207c6e50978cedde267cc2 (diff) | |
download | gtk+-51f5690ae30b5c35ddfe80b4c41852803acf7df1.tar.gz |
Merge branch 'ebassi/for-master' into 'master'
Ebassi/for master
See merge request GNOME/gtk!2720
Diffstat (limited to 'gtk/gtkatcontext.c')
-rw-r--r-- | gtk/gtkatcontext.c | 205 |
1 files changed, 176 insertions, 29 deletions
diff --git a/gtk/gtkatcontext.c b/gtk/gtkatcontext.c index 1925f5bf80..8a62e2821d 100644 --- a/gtk/gtkatcontext.c +++ b/gtk/gtkatcontext.c @@ -739,47 +739,112 @@ gtk_at_context_get_accessible_relation (GtkATContext *self, return gtk_accessible_attribute_set_get_value (self->relations, relation); } -/*< private > - * gtk_at_context_get_label: - * @self: a #GtkATContext - * - * Retrieves the accessible label of the #GtkATContext. - * - * This is a convenience function meant to be used by #GtkATContext implementations. - * - * Returns: (transfer full): the label of the #GtkATContext - */ -char * -gtk_at_context_get_label (GtkATContext *self) +/* See the WAI-ARIA ยง 4.3, "Accessible Name and Description Computation" */ +static void +gtk_at_context_get_name_accumulate (GtkATContext *self, + GPtrArray *names, + gboolean recurse) { - g_return_val_if_fail (GTK_IS_AT_CONTEXT (self), NULL); - GtkAccessibleValue *value = NULL; + if (gtk_accessible_attribute_set_contains (self->properties, GTK_ACCESSIBLE_PROPERTY_LABEL)) + { + value = gtk_accessible_attribute_set_get_value (self->properties, GTK_ACCESSIBLE_PROPERTY_LABEL); + + g_ptr_array_add (names, (char *) gtk_string_accessible_value_get (value)); + } + + if (recurse && gtk_accessible_attribute_set_contains (self->relations, GTK_ACCESSIBLE_RELATION_LABELLED_BY)) + { + value = gtk_accessible_attribute_set_get_value (self->relations, GTK_ACCESSIBLE_RELATION_LABELLED_BY); + + GList *list = gtk_reference_list_accessible_value_get (value); + + for (GList *l = list; l != NULL; l = l->data) + { + GtkAccessible *rel = GTK_ACCESSIBLE (l->data); + GtkATContext *rel_context = gtk_accessible_get_at_context (rel); + + gtk_at_context_get_name_accumulate (rel_context, names, FALSE); + } + } + + GtkAccessibleRole role = gtk_at_context_get_accessible_role (self); + + switch ((int) role) + { + case GTK_ACCESSIBLE_ROLE_RANGE: + { + int range_attrs[] = { + GTK_ACCESSIBLE_PROPERTY_VALUE_TEXT, + GTK_ACCESSIBLE_PROPERTY_VALUE_NOW, + }; + + value = NULL; + for (int i = 0; i < G_N_ELEMENTS (range_attrs); i++) + { + if (gtk_accessible_attribute_set_contains (self->properties, range_attrs[i])) + { + value = gtk_accessible_attribute_set_get_value (self->properties, range_attrs[i]); + break; + } + } + + if (value != NULL) + g_ptr_array_add (names, (char *) gtk_string_accessible_value_get (value)); + } + break; + + default: + break; + } + + /* If there is no label or labelled-by attribute, hidden elements + * have no name + */ if (gtk_accessible_attribute_set_contains (self->states, GTK_ACCESSIBLE_STATE_HIDDEN)) { value = gtk_accessible_attribute_set_get_value (self->states, GTK_ACCESSIBLE_STATE_HIDDEN); if (gtk_boolean_accessible_value_get (value)) - return g_strdup (""); + return; } - if (gtk_accessible_attribute_set_contains (self->properties, GTK_ACCESSIBLE_PROPERTY_LABEL)) + /* This fallback is in place only for unlabelled elements */ + if (names->len != 0) + return; + + if (self->accessible) + g_ptr_array_add (names, (char *)G_OBJECT_TYPE_NAME (self->accessible)); +} + +static void +gtk_at_context_get_description_accumulate (GtkATContext *self, + GPtrArray *labels, + gboolean recurse) +{ + GtkAccessibleValue *value = NULL; + + if (gtk_accessible_attribute_set_contains (self->properties, GTK_ACCESSIBLE_PROPERTY_DESCRIPTION)) { - value = gtk_accessible_attribute_set_get_value (self->properties, GTK_ACCESSIBLE_PROPERTY_LABEL); + value = gtk_accessible_attribute_set_get_value (self->properties, GTK_ACCESSIBLE_PROPERTY_DESCRIPTION); - return g_strdup (gtk_string_accessible_value_get (value)); + g_ptr_array_add (labels, (char *) gtk_string_accessible_value_get (value)); } - if (gtk_accessible_attribute_set_contains (self->relations, GTK_ACCESSIBLE_RELATION_LABELLED_BY)) + if (recurse && gtk_accessible_attribute_set_contains (self->relations, GTK_ACCESSIBLE_RELATION_DESCRIBED_BY)) { - value = gtk_accessible_attribute_set_get_value (self->relations, GTK_ACCESSIBLE_RELATION_LABELLED_BY); + value = gtk_accessible_attribute_set_get_value (self->relations, GTK_ACCESSIBLE_RELATION_DESCRIBED_BY); GList *list = gtk_reference_list_accessible_value_get (value); - GtkAccessible *rel = GTK_ACCESSIBLE (list->data); - GtkATContext *rel_context = gtk_accessible_get_at_context (rel); - return gtk_at_context_get_label (rel_context); + for (GList *l = list; l != NULL; l = l->data) + { + GtkAccessible *rel = GTK_ACCESSIBLE (l->data); + GtkATContext *rel_context = gtk_accessible_get_at_context (rel); + + gtk_at_context_get_description_accumulate (rel_context, labels, FALSE); + } } GtkAccessibleRole role = gtk_at_context_get_accessible_role (self); @@ -793,6 +858,7 @@ gtk_at_context_get_label (GtkATContext *self) GTK_ACCESSIBLE_PROPERTY_VALUE_NOW, }; + value = NULL; for (int i = 0; i < G_N_ELEMENTS (range_attrs); i++) { if (gtk_accessible_attribute_set_contains (self->properties, range_attrs[i])) @@ -803,7 +869,7 @@ gtk_at_context_get_label (GtkATContext *self) } if (value != NULL) - return g_strdup (gtk_string_accessible_value_get (value)); + g_ptr_array_add (labels, (char *) gtk_string_accessible_value_get (value)); } break; @@ -811,13 +877,94 @@ gtk_at_context_get_label (GtkATContext *self) break; } - GEnumClass *enum_class = g_type_class_peek (GTK_TYPE_ACCESSIBLE_ROLE); - GEnumValue *enum_value = g_enum_get_value (enum_class, role); + /* If there is no description or described-by attribute, hidden elements + * have no description + */ + if (gtk_accessible_attribute_set_contains (self->states, GTK_ACCESSIBLE_STATE_HIDDEN)) + { + value = gtk_accessible_attribute_set_get_value (self->states, GTK_ACCESSIBLE_STATE_HIDDEN); + + if (gtk_boolean_accessible_value_get (value)) + return; + } +} + +/*< private > + * gtk_at_context_get_name: + * @self: a #GtkATContext + * + * Retrieves the accessible name of the #GtkATContext. + * + * This is a convenience function meant to be used by #GtkATContext implementations. + * + * Returns: (transfer full): the label of the #GtkATContext + */ +char * +gtk_at_context_get_name (GtkATContext *self) +{ + g_return_val_if_fail (GTK_IS_AT_CONTEXT (self), NULL); + + GPtrArray *names = g_ptr_array_new (); + + gtk_at_context_get_name_accumulate (self, names, TRUE); + + if (names->len == 0) + { + g_ptr_array_unref (names); + return g_strdup (""); + } + + GString *res = g_string_new (""); + g_string_append (res, g_ptr_array_index (names, 0)); + + for (guint i = 1; i < names->len; i++) + { + g_string_append (res, " "); + g_string_append (res, g_ptr_array_index (names, i)); + } + + g_ptr_array_unref (names); + + return g_string_free (res, FALSE); +} + +/*< private > + * gtk_at_context_get_description: + * @self: a #GtkATContext + * + * Retrieves the accessible description of the #GtkATContext. + * + * This is a convenience function meant to be used by #GtkATContext implementations. + * + * Returns: (transfer full): the label of the #GtkATContext + */ +char * +gtk_at_context_get_description (GtkATContext *self) +{ + g_return_val_if_fail (GTK_IS_AT_CONTEXT (self), NULL); + + GPtrArray *names = g_ptr_array_new (); + + gtk_at_context_get_description_accumulate (self, names, TRUE); + + if (names->len == 0) + { + g_ptr_array_unref (names); + return g_strdup (""); + } + + GString *res = g_string_new (""); + g_string_append (res, g_ptr_array_index (names, 0)); + + for (guint i = 1; i < names->len; i++) + { + g_string_append (res, " "); + g_string_append (res, g_ptr_array_index (names, i)); + } - if (enum_value != NULL) - return g_strdup (enum_value->value_nick); + g_ptr_array_unref (names); - return g_strdup ("widget"); + return g_string_free (res, FALSE); } void |