mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-28 06:21:14 +00:00
Merge branch 'redo-a11y-name-computation' into 'main'
Reimplement a11y name computation See merge request GNOME/gtk!6119
This commit is contained in:
commit
72e5697804
@ -121,10 +121,7 @@ gtk_at_context_set_property (GObject *gobject,
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_ACCESSIBLE_ROLE:
|
||||
if (!self->realized)
|
||||
self->accessible_role = g_value_get_enum (value);
|
||||
else
|
||||
g_critical ("The accessible role cannot be set on a realized AT context");
|
||||
gtk_at_context_set_accessible_role (self, g_value_get_enum (value));
|
||||
break;
|
||||
|
||||
case PROP_ACCESSIBLE:
|
||||
@ -1010,10 +1007,6 @@ gtk_at_context_get_accessible_relation (GtkATContext *self,
|
||||
return gtk_accessible_attribute_set_get_value (self->relations, relation);
|
||||
}
|
||||
|
||||
/* See the WAI-ARIA § 4.3, "Accessible Name and Description Computation",
|
||||
* and https://www.w3.org/TR/accname-1.2/
|
||||
*/
|
||||
|
||||
/* See ARIA 5.2.8.4, 5.2.8.5 and 5.2.8.6 for the prohibited, from author
|
||||
* and from content parts, and the table in
|
||||
* https://www.w3.org/WAI/ARIA/apg/practices/names-and-descriptions/
|
||||
@ -1150,172 +1143,6 @@ gtk_accessible_role_get_naming (GtkAccessibleRole role)
|
||||
return (GtkAccessibleNaming) (naming[role] & ~(NAME_FROM_AUTHOR|NAME_FROM_CONTENT));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_at_context_get_name_accumulate (GtkATContext *self,
|
||||
GPtrArray *names,
|
||||
gboolean recurse)
|
||||
{
|
||||
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->next)
|
||||
{
|
||||
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);
|
||||
|
||||
g_object_unref (rel_context);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (names->len == 0)
|
||||
{
|
||||
if (GTK_IS_WIDGET (self->accessible))
|
||||
{
|
||||
const char *tooltip = gtk_widget_get_tooltip_text (GTK_WIDGET (self->accessible));
|
||||
if (tooltip)
|
||||
g_ptr_array_add (names, (char *) tooltip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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_DESCRIPTION);
|
||||
|
||||
g_ptr_array_add (labels, (char *) gtk_string_accessible_value_get (value));
|
||||
}
|
||||
|
||||
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_DESCRIBED_BY);
|
||||
|
||||
GList *list = gtk_reference_list_accessible_value_get (value);
|
||||
|
||||
for (GList *l = list; l != NULL; l = l->next)
|
||||
{
|
||||
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);
|
||||
|
||||
g_object_unref (rel_context);
|
||||
}
|
||||
}
|
||||
|
||||
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 (labels, (char *) gtk_string_accessible_value_get (value));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
if (labels->len == 0)
|
||||
{
|
||||
if (GTK_IS_WIDGET (self->accessible))
|
||||
{
|
||||
const char *tooltip = gtk_widget_get_tooltip_text (GTK_WIDGET (self->accessible));
|
||||
if (tooltip)
|
||||
g_ptr_array_add (labels, (char *) tooltip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_nested_button (GtkATContext *self)
|
||||
{
|
||||
@ -1366,24 +1193,185 @@ get_parent_context (GtkATContext *self)
|
||||
return g_object_ref (self);
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
not_just_space (const char *text)
|
||||
{
|
||||
for (const char *p = text; *p; p = g_utf8_next_char (p))
|
||||
{
|
||||
if (!g_unichar_isspace (g_utf8_get_char (p)))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*< 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`
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static inline void
|
||||
append_with_space (GString *str,
|
||||
const char *text)
|
||||
{
|
||||
if (str->len > 0)
|
||||
g_string_append (str, " ");
|
||||
g_string_append (str, text);
|
||||
}
|
||||
|
||||
/* See the WAI-ARIA § 4.3, "Accessible Name and Description Computation",
|
||||
* and https://www.w3.org/TR/accname-1.2/
|
||||
*/
|
||||
char *
|
||||
gtk_at_context_get_name (GtkATContext *self)
|
||||
|
||||
static void
|
||||
gtk_at_context_get_text_accumulate (GtkATContext *self,
|
||||
GPtrArray *nodes,
|
||||
GString *res,
|
||||
GtkAccessibleProperty property,
|
||||
GtkAccessibleRelation relation,
|
||||
gboolean is_ref,
|
||||
gboolean is_child)
|
||||
{
|
||||
GtkAccessibleValue *value = NULL;
|
||||
|
||||
g_warn_if_fail (self->realized);
|
||||
|
||||
/* Step 2.A */
|
||||
if (!is_ref)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (gtk_accessible_role_supports_name_from_author (self->accessible_role))
|
||||
{
|
||||
/* Step 2.B */
|
||||
if (!is_ref && gtk_accessible_attribute_set_contains (self->relations, relation))
|
||||
{
|
||||
value = gtk_accessible_attribute_set_get_value (self->relations, relation);
|
||||
|
||||
GList *list = gtk_reference_list_accessible_value_get (value);
|
||||
|
||||
for (GList *l = list; l != NULL; l = l->next)
|
||||
{
|
||||
GtkAccessible *rel = GTK_ACCESSIBLE (l->data);
|
||||
if (!g_ptr_array_find (nodes, rel, NULL))
|
||||
{
|
||||
GtkATContext *rel_context = gtk_accessible_get_at_context (rel);
|
||||
|
||||
g_ptr_array_add (nodes, rel);
|
||||
gtk_at_context_get_text_accumulate (rel_context, nodes, res, property, relation, TRUE, FALSE);
|
||||
|
||||
g_object_unref (rel_context);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Step 2.C */
|
||||
if (gtk_accessible_attribute_set_contains (self->properties, property))
|
||||
{
|
||||
value = gtk_accessible_attribute_set_get_value (self->properties, property);
|
||||
|
||||
char *str = (char *) gtk_string_accessible_value_get (value);
|
||||
if (str[0] != '\0')
|
||||
{
|
||||
append_with_space (res, gtk_string_accessible_value_get (value));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Step 2.E */
|
||||
if (self->accessible_role == GTK_ACCESSIBLE_ROLE_TEXT_BOX)
|
||||
{
|
||||
if (GTK_IS_EDITABLE (self->accessible))
|
||||
{
|
||||
const char *text = gtk_editable_get_text (GTK_EDITABLE (self->accessible));
|
||||
if (text && not_just_space (text))
|
||||
append_with_space (res, text);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (gtk_accessible_role_is_range_subclass (self->accessible_role))
|
||||
{
|
||||
if (gtk_accessible_attribute_set_contains (self->properties, GTK_ACCESSIBLE_PROPERTY_VALUE_TEXT))
|
||||
{
|
||||
value = gtk_accessible_attribute_set_get_value (self->properties, GTK_ACCESSIBLE_PROPERTY_VALUE_TEXT);
|
||||
append_with_space (res, gtk_string_accessible_value_get (value));
|
||||
}
|
||||
else if (gtk_accessible_attribute_set_contains (self->properties, GTK_ACCESSIBLE_PROPERTY_VALUE_NOW))
|
||||
{
|
||||
value = gtk_accessible_attribute_set_get_value (self->properties, GTK_ACCESSIBLE_PROPERTY_VALUE_NOW);
|
||||
if (res->len > 0)
|
||||
g_string_append (res, " ");
|
||||
g_string_append_printf (res, "%g", gtk_number_accessible_value_get (value));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Step 2.F */
|
||||
if (gtk_accessible_role_supports_name_from_content (self->accessible_role) || is_ref || is_child)
|
||||
{
|
||||
if (GTK_IS_WIDGET (self->accessible))
|
||||
{
|
||||
gboolean has_child = FALSE;
|
||||
|
||||
for (GtkWidget *child = gtk_widget_get_first_child (GTK_WIDGET (self->accessible));
|
||||
child != NULL;
|
||||
child = gtk_widget_get_next_sibling (child))
|
||||
{
|
||||
GtkAccessible *rel = GTK_ACCESSIBLE (child);
|
||||
GtkATContext *rel_context = gtk_accessible_get_at_context (rel);
|
||||
|
||||
gtk_at_context_get_text_accumulate (rel_context, nodes, res, property, relation, FALSE, TRUE);
|
||||
|
||||
has_child = TRUE;
|
||||
}
|
||||
|
||||
if (has_child)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Step 2.G */
|
||||
if (GTK_IS_LABEL (self->accessible))
|
||||
{
|
||||
const char *text = gtk_label_get_text (GTK_LABEL (self->accessible));
|
||||
if (text && not_just_space (text))
|
||||
append_with_space (res, text);
|
||||
return;
|
||||
}
|
||||
else if (GTK_IS_INSCRIPTION (self->accessible))
|
||||
{
|
||||
const char *text = gtk_inscription_get_text (GTK_INSCRIPTION (self->accessible));
|
||||
if (text && not_just_space (text))
|
||||
append_with_space (res, text);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Step 2.I */
|
||||
if (GTK_IS_WIDGET (self->accessible))
|
||||
{
|
||||
const char *text = gtk_widget_get_tooltip_text (GTK_WIDGET (self->accessible));
|
||||
if (text && not_just_space (text))
|
||||
append_with_space (res, text);
|
||||
}
|
||||
}
|
||||
|
||||
static char *
|
||||
gtk_at_context_get_text (GtkATContext *self,
|
||||
GtkAccessibleProperty property,
|
||||
GtkAccessibleRelation relation)
|
||||
{
|
||||
GtkATContext *parent = NULL;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_AT_CONTEXT (self), NULL);
|
||||
g_warn_if_fail (self->realized);
|
||||
|
||||
/* Step 1 */
|
||||
if (gtk_accessible_role_get_naming (self->accessible_role) == GTK_ACCESSIBLE_NAME_PROHIBITED)
|
||||
return g_strdup ("");
|
||||
|
||||
@ -1405,33 +1393,35 @@ gtk_at_context_get_name (GtkATContext *self)
|
||||
}
|
||||
}
|
||||
|
||||
GPtrArray *names = g_ptr_array_new ();
|
||||
|
||||
gtk_at_context_get_name_accumulate (self, names, TRUE);
|
||||
|
||||
if (names->len == 0)
|
||||
{
|
||||
g_ptr_array_unref (names);
|
||||
g_clear_object (&parent);
|
||||
return g_strdup ("");
|
||||
}
|
||||
|
||||
GPtrArray *nodes = g_ptr_array_new ();
|
||||
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));
|
||||
}
|
||||
/* Step 2 */
|
||||
gtk_at_context_get_text_accumulate (self, nodes, res, property, relation, FALSE, FALSE);
|
||||
|
||||
g_ptr_array_unref (names);
|
||||
g_ptr_array_unref (nodes);
|
||||
|
||||
g_clear_object (&parent);
|
||||
|
||||
return g_string_free (res, FALSE);
|
||||
}
|
||||
|
||||
/*< 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)
|
||||
{
|
||||
return gtk_at_context_get_text (self, GTK_ACCESSIBLE_PROPERTY_LABEL, GTK_ACCESSIBLE_RELATION_LABELLED_BY);
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* gtk_at_context_get_description:
|
||||
* @self: a `GtkATContext`
|
||||
@ -1445,49 +1435,7 @@ gtk_at_context_get_name (GtkATContext *self)
|
||||
char *
|
||||
gtk_at_context_get_description (GtkATContext *self)
|
||||
{
|
||||
GtkATContext *parent = NULL;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_AT_CONTEXT (self), NULL);
|
||||
|
||||
if (gtk_accessible_role_get_naming (self->accessible_role) == GTK_ACCESSIBLE_NAME_PROHIBITED)
|
||||
return g_strdup ("");
|
||||
|
||||
/* We special case this here since it is a common pattern:
|
||||
* We have a 'wrapper' object, like a GtkDropdown which
|
||||
* contains a toggle button. The dropdown appears in the
|
||||
* ui file and carries all the a11y attributes, but the
|
||||
* focus ends up on the toggle button.
|
||||
*/
|
||||
if (is_nested_button (self))
|
||||
{
|
||||
parent = get_parent_context (self);
|
||||
self = parent;
|
||||
}
|
||||
|
||||
GPtrArray *names = g_ptr_array_new ();
|
||||
|
||||
gtk_at_context_get_description_accumulate (self, names, TRUE);
|
||||
|
||||
if (names->len == 0)
|
||||
{
|
||||
g_ptr_array_unref (names);
|
||||
g_clear_object (&parent);
|
||||
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);
|
||||
|
||||
g_clear_object (&parent);
|
||||
return g_string_free (res, FALSE);
|
||||
return gtk_at_context_get_text (self, GTK_ACCESSIBLE_PROPERTY_DESCRIPTION, GTK_ACCESSIBLE_RELATION_DESCRIBED_BY);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -797,11 +797,6 @@ gtk_inscription_set_text (GtkInscription *self,
|
||||
g_free (self->text);
|
||||
self->text = g_strdup (text);
|
||||
|
||||
gtk_accessible_update_property (GTK_ACCESSIBLE (self),
|
||||
GTK_ACCESSIBLE_PROPERTY_LABEL, self->text,
|
||||
-1);
|
||||
|
||||
|
||||
pango_layout_set_text (self->layout,
|
||||
self->text ? self->text : "",
|
||||
-1);
|
||||
|
@ -3067,10 +3067,6 @@ gtk_label_set_text_internal (GtkLabel *self,
|
||||
g_free (self->text);
|
||||
self->text = str;
|
||||
|
||||
gtk_accessible_update_property (GTK_ACCESSIBLE (self),
|
||||
GTK_ACCESSIBLE_PROPERTY_LABEL, self->text,
|
||||
-1);
|
||||
|
||||
gtk_label_select_region_index (self, 0, 0);
|
||||
}
|
||||
|
||||
|
@ -2397,7 +2397,8 @@ gtk_widget_root_at_context (GtkWidget *self)
|
||||
}
|
||||
|
||||
gtk_at_context_set_accessible_role (priv->at_context, role);
|
||||
gtk_at_context_set_display (priv->at_context, gtk_root_get_display (priv->root));
|
||||
if (priv->root)
|
||||
gtk_at_context_set_display (priv->at_context, gtk_root_get_display (priv->root));
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -45,11 +45,13 @@ label_properties (void)
|
||||
|
||||
g_object_ref_sink (label);
|
||||
|
||||
gtk_test_accessible_assert_property (label, GTK_ACCESSIBLE_PROPERTY_LABEL, "a");
|
||||
gtk_label_set_selectable (GTK_LABEL (label), TRUE);
|
||||
|
||||
gtk_label_set_label (GTK_LABEL (label), "b");
|
||||
gtk_test_accessible_assert_property (GTK_ACCESSIBLE (label), GTK_ACCESSIBLE_PROPERTY_HAS_POPUP, TRUE);
|
||||
|
||||
gtk_test_accessible_assert_property (label, GTK_ACCESSIBLE_PROPERTY_LABEL, "b");
|
||||
gtk_label_set_selectable (GTK_LABEL (label), FALSE);
|
||||
|
||||
g_assert_false (gtk_test_accessible_has_property (GTK_ACCESSIBLE (label), GTK_ACCESSIBLE_PROPERTY_HAS_POPUP));
|
||||
|
||||
g_object_unref (label);
|
||||
}
|
||||
|
@ -33,6 +33,9 @@ tests = [
|
||||
{ 'name': 'window' },
|
||||
]
|
||||
|
||||
internal_tests = [
|
||||
{ 'name': 'names' },
|
||||
]
|
||||
|
||||
is_debug = get_option('buildtype').startswith('debug')
|
||||
|
||||
@ -80,3 +83,31 @@ foreach t : tests
|
||||
suite: ['a11y'] + test_extra_suites,
|
||||
)
|
||||
endforeach
|
||||
|
||||
foreach t : internal_tests
|
||||
test_name = t.get('name')
|
||||
test_srcs = ['@0@.c'.format(test_name)] + t.get('sources', [])
|
||||
test_extra_cargs = t.get('c_args', [])
|
||||
test_extra_ldflags = t.get('link_args', [])
|
||||
test_extra_suites = t.get('suites', [])
|
||||
test_timeout = 60
|
||||
|
||||
test_exe = executable(test_name,
|
||||
sources: test_srcs,
|
||||
c_args: test_cargs + test_extra_cargs + ['-DGTK_COMPILATION'],
|
||||
link_args: test_extra_ldflags,
|
||||
dependencies: libgtk_static_dep,
|
||||
)
|
||||
|
||||
if test_extra_suites.contains('slow')
|
||||
test_timeout = 90
|
||||
endif
|
||||
|
||||
test(test_name, test_exe,
|
||||
args: [ '--tap', '-k' ],
|
||||
protocol: 'tap',
|
||||
timeout: test_timeout,
|
||||
env: test_env,
|
||||
suite: ['a11y'] + test_extra_suites,
|
||||
)
|
||||
endforeach
|
||||
|
158
testsuite/a11y/names.c
Normal file
158
testsuite/a11y/names.c
Normal file
@ -0,0 +1,158 @@
|
||||
#include <gtk/gtk.h>
|
||||
#include "gtk/gtkatcontextprivate.h"
|
||||
#include "gtk/gtkwidgetprivate.h"
|
||||
|
||||
static void
|
||||
test_name_content (void)
|
||||
{
|
||||
GtkWidget *label1, *label2, *box, *button;
|
||||
char *name;
|
||||
|
||||
label1 = gtk_label_new ("a");
|
||||
label2 = gtk_label_new ("b");
|
||||
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
||||
button = gtk_button_new ();
|
||||
|
||||
gtk_box_append (GTK_BOX (box), label1);
|
||||
gtk_box_append (GTK_BOX (box), label2);
|
||||
gtk_button_set_child (GTK_BUTTON (button), box);
|
||||
g_object_ref_sink (button);
|
||||
|
||||
/* gtk_at_context_get_name only works on realized contexts */
|
||||
gtk_widget_realize_at_context (label1);
|
||||
gtk_widget_realize_at_context (label2);
|
||||
gtk_widget_realize_at_context (box);
|
||||
gtk_widget_realize_at_context (button);
|
||||
|
||||
name = gtk_at_context_get_name (gtk_accessible_get_at_context (GTK_ACCESSIBLE (label1)));
|
||||
g_assert_cmpstr (name, ==, "a");
|
||||
g_free (name);
|
||||
|
||||
/* this is because generic doesn't allow naming */
|
||||
name = gtk_at_context_get_name (gtk_accessible_get_at_context (GTK_ACCESSIBLE (box)));
|
||||
g_assert_cmpstr (name, ==, "");
|
||||
g_free (name);
|
||||
|
||||
name = gtk_at_context_get_name (gtk_accessible_get_at_context (GTK_ACCESSIBLE (button)));
|
||||
g_assert_cmpstr (name, ==, "a b");
|
||||
g_free (name);
|
||||
|
||||
gtk_widget_set_visible (label2, FALSE);
|
||||
|
||||
name = gtk_at_context_get_name (gtk_accessible_get_at_context (GTK_ACCESSIBLE (button)));
|
||||
g_assert_cmpstr (name, ==, "a");
|
||||
g_free (name);
|
||||
|
||||
g_object_unref (button);
|
||||
}
|
||||
|
||||
static void
|
||||
test_name_tooltip (void)
|
||||
{
|
||||
GtkWidget *image = gtk_image_new ();
|
||||
char *name;
|
||||
|
||||
g_object_ref_sink (image);
|
||||
gtk_widget_realize_at_context (image);
|
||||
|
||||
gtk_widget_set_tooltip_text (image, "tooltip");
|
||||
|
||||
name = gtk_at_context_get_name (gtk_accessible_get_at_context (GTK_ACCESSIBLE (image)));
|
||||
g_assert_cmpstr (name, ==, "tooltip");
|
||||
g_free (name);
|
||||
|
||||
g_object_unref (image);
|
||||
}
|
||||
|
||||
static void
|
||||
test_name_label (void)
|
||||
{
|
||||
GtkWidget *image = gtk_image_new ();
|
||||
char *name;
|
||||
char *desc;
|
||||
|
||||
g_object_ref_sink (image);
|
||||
gtk_widget_realize_at_context (image);
|
||||
|
||||
gtk_widget_set_tooltip_text (image, "tooltip");
|
||||
|
||||
gtk_accessible_update_property (GTK_ACCESSIBLE (image),
|
||||
GTK_ACCESSIBLE_PROPERTY_LABEL, "label",
|
||||
-1);
|
||||
|
||||
name = gtk_at_context_get_name (gtk_accessible_get_at_context (GTK_ACCESSIBLE (image)));
|
||||
desc = gtk_at_context_get_description (gtk_accessible_get_at_context (GTK_ACCESSIBLE (image)));
|
||||
|
||||
g_assert_cmpstr (name, ==, "label");
|
||||
g_assert_cmpstr (desc, ==, "tooltip");
|
||||
|
||||
g_free (name);
|
||||
g_free (desc);
|
||||
|
||||
g_object_unref (image);
|
||||
}
|
||||
|
||||
static void
|
||||
test_name_prohibited (void)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
char *name;
|
||||
char *desc;
|
||||
|
||||
widget = g_object_new (GTK_TYPE_BUTTON,
|
||||
"accessible-role", GTK_ACCESSIBLE_ROLE_TIME,
|
||||
"label", "too late",
|
||||
NULL);
|
||||
|
||||
g_object_ref_sink (widget);
|
||||
gtk_widget_realize_at_context (widget);
|
||||
|
||||
name = gtk_at_context_get_name (gtk_accessible_get_at_context (GTK_ACCESSIBLE (widget)));
|
||||
desc = gtk_at_context_get_description (gtk_accessible_get_at_context (GTK_ACCESSIBLE (widget)));
|
||||
|
||||
g_assert_cmpstr (name, ==, "");
|
||||
g_assert_cmpstr (desc, ==, "");
|
||||
|
||||
g_free (name);
|
||||
g_free (desc);
|
||||
|
||||
g_object_unref (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
test_name_range (void)
|
||||
{
|
||||
GtkWidget *scale;
|
||||
char *name;
|
||||
|
||||
scale = gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL, 0, 100, 10);
|
||||
|
||||
g_object_ref_sink (scale);
|
||||
gtk_widget_realize_at_context (scale);
|
||||
|
||||
g_assert_true (gtk_accessible_get_accessible_role (GTK_ACCESSIBLE (scale)) == GTK_ACCESSIBLE_ROLE_SLIDER);
|
||||
g_assert_true (gtk_at_context_get_accessible_role (gtk_accessible_get_at_context (GTK_ACCESSIBLE (scale))) == GTK_ACCESSIBLE_ROLE_SLIDER);
|
||||
|
||||
gtk_range_set_value (GTK_RANGE (scale), 50);
|
||||
|
||||
name = gtk_at_context_get_name (gtk_accessible_get_at_context (GTK_ACCESSIBLE (scale)));
|
||||
g_assert_cmpstr (name, ==, "50");
|
||||
|
||||
g_free (name);
|
||||
|
||||
g_object_unref (scale);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
gtk_test_init (&argc, &argv, NULL);
|
||||
|
||||
g_test_add_func ("/a11y/name/content", test_name_content);
|
||||
g_test_add_func ("/a11y/name/tooltip", test_name_tooltip);
|
||||
g_test_add_func ("/a11y/name/label", test_name_label);
|
||||
g_test_add_func ("/a11y/name/prohibited", test_name_prohibited);
|
||||
g_test_add_func ("/a11y/name/range", test_name_range);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
Loading…
Reference in New Issue
Block a user