summaryrefslogtreecommitdiff
path: root/gtk/gtkatcontext.c
diff options
context:
space:
mode:
authorEmmanuele Bassi <ebassi@gmail.com>2020-10-19 20:26:57 +0000
committerEmmanuele Bassi <ebassi@gmail.com>2020-10-19 20:26:57 +0000
commit51f5690ae30b5c35ddfe80b4c41852803acf7df1 (patch)
tree724e70d0212dd256d5d4e60d19c3a48dd3eb2e88 /gtk/gtkatcontext.c
parente58e6a0fbe257888e2f065b992016b888fe5fae7 (diff)
parentdfc7d26275f1cf402e207c6e50978cedde267cc2 (diff)
downloadgtk+-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.c205
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