[gtk/ebassi/new-a11y: 26/32] a11y: Add relations API
- From: Emmanuele Bassi <ebassi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/ebassi/new-a11y: 26/32] a11y: Add relations API
- Date: Fri, 17 Jul 2020 16:40:45 +0000 (UTC)
commit 8f6d080816d2691b2f750ac264c9b260f1f65373
Author: Emmanuele Bassi <ebassi gnome org>
Date: Fri Jul 17 12:00:31 2020 +0100
a11y: Add relations API
Since we split relation attributes from the generic properties, we need
to add API for setting and retrieving their values.
gtk/gtkaccessible.c | 87 ++++++++++++++
gtk/gtkaccessible.h | 8 ++
gtk/gtkaccessiblerelationset.c | 217 ++++++++++++++++++++++++++++++++++
gtk/gtkaccessiblerelationsetprivate.h | 49 ++++++++
gtk/gtkaccessiblevalue.c | 183 ++++++++++++++++++++++++++++
gtk/gtkaccessiblevalueprivate.h | 6 +
gtk/gtkatcontext.c | 49 +++++++-
gtk/gtkatcontextprivate.h | 54 +++++++--
gtk/gtktestatcontext.c | 14 ++-
gtk/meson.build | 1 +
10 files changed, 646 insertions(+), 22 deletions(-)
---
diff --git a/gtk/gtkaccessible.c b/gtk/gtkaccessible.c
index 8cace46611..4f90d04e24 100644
--- a/gtk/gtkaccessible.c
+++ b/gtk/gtkaccessible.c
@@ -276,3 +276,90 @@ gtk_accessible_update_property_value (GtkAccessible *self,
gtk_accessible_value_unref (real_value);
gtk_at_context_update (context);
}
+
+/**
+ * gtk_accessible_update_relation:
+ * @self: a #GtkAccessible
+ * @first_relation: the first #GtkAccessibleRelation
+ * @...: a list of relation and value pairs, terminated by -1
+ *
+ * Updates a list of accessible relations.
+ *
+ * This function should be called by #GtkWidget types whenever an accessible
+ * relation change must be communicated to assistive technologies.
+ */
+void
+gtk_accessible_update_relation (GtkAccessible *self,
+ GtkAccessibleRelation first_relation,
+ ...)
+{
+ GtkAccessibleRelation relation;
+ GtkATContext *context;
+ va_list args;
+
+ g_return_if_fail (GTK_IS_ACCESSIBLE (self));
+
+ context = gtk_accessible_get_at_context (self);
+ if (context == NULL)
+ return;
+
+ va_start (args, first_relation);
+
+ relation = first_relation;
+
+ while (relation != -1)
+ {
+ GtkAccessibleValue *value = gtk_accessible_value_collect_for_relation (relation, &args);
+
+ /* gtk_accessible_value_collect_for_relation() will warn for us */
+ if (value == NULL)
+ goto out;
+
+ gtk_at_context_set_accessible_relation (context, relation, value);
+ gtk_accessible_value_unref (value);
+
+ relation = va_arg (args, int);
+ }
+
+ gtk_at_context_update (context);
+
+out:
+ va_end (args);
+}
+
+/**
+ * gtk_accessible_update_relation_value:
+ * @self: a #GtkAccessible
+ * @relation: a #GtkAccessibleRelation
+ * @value: a #GValue with the value for @relation
+ *
+ * Updates an accessible relation.
+ *
+ * This function should be called by #GtkWidget types whenever an accessible
+ * relation change must be communicated to assistive technologies.
+ *
+ * This function is meant to be used by language bindings.
+ */
+void
+gtk_accessible_update_relation_value (GtkAccessible *self,
+ GtkAccessibleRelation relation,
+ const GValue *value)
+{
+ GtkATContext *context;
+
+ g_return_if_fail (GTK_IS_ACCESSIBLE (self));
+
+ context = gtk_accessible_get_at_context (self);
+ if (context == NULL)
+ return;
+
+ GtkAccessibleValue *real_value =
+ gtk_accessible_value_collect_for_relation_value (relation, value);
+
+ if (real_value == NULL)
+ return;
+
+ gtk_at_context_set_accessible_relation (context, relation, real_value);
+ gtk_accessible_value_unref (real_value);
+ gtk_at_context_update (context);
+}
diff --git a/gtk/gtkaccessible.h b/gtk/gtkaccessible.h
index 9ad56784c7..d0a115d205 100644
--- a/gtk/gtkaccessible.h
+++ b/gtk/gtkaccessible.h
@@ -43,6 +43,10 @@ void gtk_accessible_update_property (GtkAccessible
GtkAccessibleProperty first_property,
...);
GDK_AVAILABLE_IN_ALL
+void gtk_accessible_update_relation (GtkAccessible *self,
+ GtkAccessibleRelation first_relation,
+ ...);
+GDK_AVAILABLE_IN_ALL
void gtk_accessible_update_state_value (GtkAccessible *self,
GtkAccessibleState state,
const GValue *value);
@@ -50,5 +54,9 @@ GDK_AVAILABLE_IN_ALL
void gtk_accessible_update_property_value (GtkAccessible *self,
GtkAccessibleProperty property,
const GValue *value);
+GDK_AVAILABLE_IN_ALL
+void gtk_accessible_update_relation_value (GtkAccessible *self,
+ GtkAccessibleRelation relation,
+ const GValue *value);
G_END_DECLS
diff --git a/gtk/gtkaccessiblerelationset.c b/gtk/gtkaccessiblerelationset.c
new file mode 100644
index 0000000000..2e6a64b41f
--- /dev/null
+++ b/gtk/gtkaccessiblerelationset.c
@@ -0,0 +1,217 @@
+/* gtkaccessiblerelationset.c: Accessible relation set
+ *
+ * Copyright 2020 GNOME Foundation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "gtkaccessiblerelationsetprivate.h"
+
+#include "gtkbitmaskprivate.h"
+#include "gtkenums.h"
+
+/* Keep in sync with GtkAccessibleRelation in gtkenums.h */
+#define LAST_RELATION GTK_ACCESSIBLE_RELATION_SET_SIZE
+
+struct _GtkAccessibleRelationSet
+{
+ GtkBitmask *relation_set;
+
+ GtkAccessibleValue **relation_values;
+};
+
+static GtkAccessibleRelationSet *
+gtk_accessible_relation_set_init (GtkAccessibleRelationSet *self)
+{
+ self->relation_set = _gtk_bitmask_new ();
+ self->relation_values = g_new (GtkAccessibleValue *, LAST_RELATION);
+
+ /* Initialize all relation values, so we can always get the full set */
+ for (int i = 0; i < LAST_RELATION; i++)
+ self->relation_values[i] = gtk_accessible_value_get_default_for_relation (i);
+
+ return self;
+}
+
+GtkAccessibleRelationSet *
+gtk_accessible_relation_set_new (void)
+{
+ GtkAccessibleRelationSet *set = g_rc_box_new0 (GtkAccessibleRelationSet);
+
+ return gtk_accessible_relation_set_init (set);
+}
+
+GtkAccessibleRelationSet *
+gtk_accessible_relation_set_ref (GtkAccessibleRelationSet *self)
+{
+ g_return_val_if_fail (self != NULL, NULL);
+
+ return g_rc_box_acquire (self);
+}
+
+static void
+gtk_accessible_relation_set_free (gpointer data)
+{
+ GtkAccessibleRelationSet *self = data;
+
+ for (int i = 0; i < LAST_RELATION; i++)
+ {
+ if (self->relation_values[i] != NULL)
+ gtk_accessible_value_unref (self->relation_values[i]);
+ }
+
+ g_free (self->relation_values);
+
+ _gtk_bitmask_free (self->relation_set);
+}
+
+void
+gtk_accessible_relation_set_unref (GtkAccessibleRelationSet *self)
+{
+ g_rc_box_release_full (self, gtk_accessible_relation_set_free);
+}
+
+void
+gtk_accessible_relation_set_add (GtkAccessibleRelationSet *self,
+ GtkAccessibleRelation relation,
+ GtkAccessibleValue *value)
+{
+ g_return_if_fail (relation >= GTK_ACCESSIBLE_RELATION_ACTIVE_DESCENDANT &&
+ relation <= GTK_ACCESSIBLE_RELATION_SET_SIZE);
+
+ if (gtk_accessible_relation_set_contains (self, relation))
+ gtk_accessible_value_unref (self->relation_values[relation]);
+ else
+ self->relation_set = _gtk_bitmask_set (self->relation_set, relation, TRUE);
+
+ self->relation_values[relation] = gtk_accessible_value_ref (value);
+}
+
+void
+gtk_accessible_relation_set_remove (GtkAccessibleRelationSet *self,
+ GtkAccessibleRelation relation)
+{
+ g_return_if_fail (relation >= GTK_ACCESSIBLE_RELATION_ACTIVE_DESCENDANT &&
+ relation <= GTK_ACCESSIBLE_RELATION_SET_SIZE);
+
+ if (gtk_accessible_relation_set_contains (self, relation))
+ {
+ g_clear_pointer (&(self->relation_values[relation]), gtk_accessible_value_unref);
+ self->relation_set = _gtk_bitmask_set (self->relation_set, relation, FALSE);
+ }
+}
+
+gboolean
+gtk_accessible_relation_set_contains (GtkAccessibleRelationSet *self,
+ GtkAccessibleRelation relation)
+{
+ g_return_val_if_fail (relation >= GTK_ACCESSIBLE_RELATION_ACTIVE_DESCENDANT &&
+ relation <= GTK_ACCESSIBLE_RELATION_SET_SIZE,
+ FALSE);
+
+ return _gtk_bitmask_get (self->relation_set, relation);
+}
+
+GtkAccessibleValue *
+gtk_accessible_relation_set_get_value (GtkAccessibleRelationSet *self,
+ GtkAccessibleRelation relation)
+{
+ g_return_val_if_fail (relation >= GTK_ACCESSIBLE_RELATION_ACTIVE_DESCENDANT &&
+ relation <= GTK_ACCESSIBLE_RELATION_SET_SIZE,
+ NULL);
+
+ return self->relation_values[relation];
+}
+
+static const char *relation_names[] = {
+ [GTK_ACCESSIBLE_RELATION_ACTIVE_DESCENDANT] = "activedescendant",
+ [GTK_ACCESSIBLE_RELATION_COL_COUNT] = "colcount",
+ [GTK_ACCESSIBLE_RELATION_COL_INDEX] = "colindex",
+ [GTK_ACCESSIBLE_RELATION_COL_INDEX_TEXT] = "colindextext",
+ [GTK_ACCESSIBLE_RELATION_COL_SPAN] = "colspan",
+ [GTK_ACCESSIBLE_RELATION_CONTROLS] = "controls",
+ [GTK_ACCESSIBLE_RELATION_DESCRIBED_BY] = "describedby",
+ [GTK_ACCESSIBLE_RELATION_DETAILS] = "details",
+ [GTK_ACCESSIBLE_RELATION_ERROR_MESSAGE] = "errormessage",
+ [GTK_ACCESSIBLE_RELATION_FLOW_TO] = "flowto",
+ [GTK_ACCESSIBLE_RELATION_LABELLED_BY] = "labelledby",
+ [GTK_ACCESSIBLE_RELATION_OWNS] = "owns",
+ [GTK_ACCESSIBLE_RELATION_POS_IN_SET] = "posinset",
+ [GTK_ACCESSIBLE_RELATION_ROW_COUNT] = "rowcount",
+ [GTK_ACCESSIBLE_RELATION_ROW_INDEX] = "rowindex",
+ [GTK_ACCESSIBLE_RELATION_ROW_INDEX_TEXT] = "rowindextext",
+ [GTK_ACCESSIBLE_RELATION_ROW_SPAN] = "rowspan",
+ [GTK_ACCESSIBLE_RELATION_SET_SIZE] = "setsize",
+};
+
+/*< private >
+ * gtk_accessible_relation_set_print:
+ * @self: a #GtkAccessibleRelationSet
+ * @only_set: %TRUE if only the set relations should be printed
+ * @buffer: a #GString
+ *
+ * Prints the contents of the #GtkAccessibleRelationSet into @buffer.
+ */
+void
+gtk_accessible_relation_set_print (GtkAccessibleRelationSet *self,
+ gboolean only_set,
+ GString *buffer)
+{
+ if (only_set && _gtk_bitmask_is_empty (self->relation_set))
+ {
+ g_string_append (buffer, "{}");
+ return;
+ }
+
+ g_string_append (buffer, "{\n");
+
+ for (int i = 0; i < G_N_ELEMENTS (relation_names); i++)
+ {
+ if (only_set && !_gtk_bitmask_get (self->relation_set, i))
+ continue;
+
+ g_string_append (buffer, " ");
+ g_string_append (buffer, relation_names[i]);
+ g_string_append (buffer, ": ");
+
+ gtk_accessible_value_print (self->relation_values[i], buffer);
+
+ g_string_append (buffer, ",\n");
+ }
+
+ g_string_append (buffer, "}");
+}
+
+/*< private >
+ * gtk_accessible_relation_set_to_string:
+ * @self: a #GtkAccessibleRelationSet
+ *
+ * Prints the contents of a #GtkAccessibleRelationSet into a string.
+ *
+ * Returns: (transfer full): a newly allocated string with the contents
+ * of the #GtkAccessibleRelationSet
+ */
+char *
+gtk_accessible_relation_set_to_string (GtkAccessibleRelationSet *self)
+{
+ GString *buf = g_string_new (NULL);
+
+ gtk_accessible_relation_set_print (self, TRUE, buf);
+
+ return g_string_free (buf, FALSE);
+}
diff --git a/gtk/gtkaccessiblerelationsetprivate.h b/gtk/gtkaccessiblerelationsetprivate.h
new file mode 100644
index 0000000000..a2a33f9717
--- /dev/null
+++ b/gtk/gtkaccessiblerelationsetprivate.h
@@ -0,0 +1,49 @@
+/* gtkaccessiblerelationsetprivate.h: Accessible relations set
+ *
+ * Copyright 2020 GNOME Foundation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "gtkaccessibleprivate.h"
+#include "gtkaccessiblevalueprivate.h"
+
+G_BEGIN_DECLS
+
+typedef struct _GtkAccessibleRelationSet GtkAccessibleRelationSet;
+
+GtkAccessibleRelationSet * gtk_accessible_relation_set_new (void);
+GtkAccessibleRelationSet * gtk_accessible_relation_set_ref (GtkAccessibleRelationSet *self);
+void gtk_accessible_relation_set_unref (GtkAccessibleRelationSet *self);
+
+void gtk_accessible_relation_set_add (GtkAccessibleRelationSet *self,
+ GtkAccessibleRelation state,
+ GtkAccessibleValue *value);
+void gtk_accessible_relation_set_remove (GtkAccessibleRelationSet *self,
+ GtkAccessibleRelation state);
+gboolean gtk_accessible_relation_set_contains (GtkAccessibleRelationSet *self,
+ GtkAccessibleRelation state);
+GtkAccessibleValue * gtk_accessible_relation_set_get_value (GtkAccessibleRelationSet *self,
+ GtkAccessibleRelation state);
+
+void gtk_accessible_relation_set_print (GtkAccessibleRelationSet *self,
+ gboolean only_set,
+ GString *string);
+char * gtk_accessible_relation_set_to_string (GtkAccessibleRelationSet *self);
+
+G_END_DECLS
diff --git a/gtk/gtkaccessiblevalue.c b/gtk/gtkaccessiblevalue.c
index 58e3dd15d1..4ccd8a837d 100644
--- a/gtk/gtkaccessiblevalue.c
+++ b/gtk/gtkaccessiblevalue.c
@@ -665,6 +665,100 @@ static const GtkAccessibleCollect collect_props[] = {
},
};
+/* § 6.6.4 Relationship Attributes */
+static const GtkAccessibleCollect collect_rels[] = {
+ [GTK_ACCESSIBLE_RELATION_ACTIVE_DESCENDANT] = {
+ .value = GTK_ACCESSIBLE_RELATION_ACTIVE_DESCENDANT,
+ .ctype = GTK_ACCESSIBLE_COLLECT_REFERENCE,
+ .name = "activedescendant"
+ },
+ [GTK_ACCESSIBLE_RELATION_COL_COUNT] = {
+ .value = GTK_ACCESSIBLE_RELATION_COL_COUNT,
+ .ctype = GTK_ACCESSIBLE_COLLECT_INTEGER,
+ .name = "colcount"
+ },
+ [GTK_ACCESSIBLE_RELATION_COL_INDEX] = {
+ .value = GTK_ACCESSIBLE_RELATION_COL_INDEX,
+ .ctype = GTK_ACCESSIBLE_COLLECT_INTEGER,
+ .name = "colindex"
+ },
+ [GTK_ACCESSIBLE_RELATION_COL_INDEX_TEXT] = {
+ .value = GTK_ACCESSIBLE_RELATION_COL_INDEX_TEXT,
+ .ctype = GTK_ACCESSIBLE_COLLECT_STRING,
+ .name = "colindextext"
+ },
+ [GTK_ACCESSIBLE_RELATION_COL_SPAN] = {
+ .value = GTK_ACCESSIBLE_RELATION_COL_SPAN,
+ .ctype = GTK_ACCESSIBLE_COLLECT_INTEGER,
+ .name = "colspan"
+ },
+ [GTK_ACCESSIBLE_RELATION_CONTROLS] = {
+ .value = GTK_ACCESSIBLE_RELATION_CONTROLS,
+ .ctype = GTK_ACCESSIBLE_COLLECT_REFERENCE,
+ .name = "controls"
+ },
+ [GTK_ACCESSIBLE_RELATION_DESCRIBED_BY] = {
+ .value = GTK_ACCESSIBLE_RELATION_DESCRIBED_BY,
+ .ctype = GTK_ACCESSIBLE_COLLECT_REFERENCE,
+ .name = "describedby"
+ },
+ [GTK_ACCESSIBLE_RELATION_DETAILS] = {
+ .value = GTK_ACCESSIBLE_RELATION_DETAILS,
+ .ctype = GTK_ACCESSIBLE_COLLECT_REFERENCE,
+ .name = "details"
+ },
+ [GTK_ACCESSIBLE_RELATION_ERROR_MESSAGE] = {
+ .value = GTK_ACCESSIBLE_RELATION_ERROR_MESSAGE,
+ .ctype = GTK_ACCESSIBLE_COLLECT_REFERENCE,
+ .name = "errormessage"
+ },
+ [GTK_ACCESSIBLE_RELATION_FLOW_TO] = {
+ .value = GTK_ACCESSIBLE_RELATION_FLOW_TO,
+ .ctype = GTK_ACCESSIBLE_COLLECT_REFERENCE,
+ .name = "flowto"
+ },
+ [GTK_ACCESSIBLE_RELATION_LABELLED_BY] = {
+ .value = GTK_ACCESSIBLE_RELATION_LABELLED_BY,
+ .ctype = GTK_ACCESSIBLE_COLLECT_REFERENCE,
+ .name = "labelledby"
+ },
+ [GTK_ACCESSIBLE_RELATION_OWNS] = {
+ .value = GTK_ACCESSIBLE_RELATION_OWNS,
+ .ctype = GTK_ACCESSIBLE_COLLECT_REFERENCE,
+ .name = "owns"
+ },
+ [GTK_ACCESSIBLE_RELATION_POS_IN_SET] = {
+ .value = GTK_ACCESSIBLE_RELATION_POS_IN_SET,
+ .ctype = GTK_ACCESSIBLE_COLLECT_INTEGER,
+ .name = "posinset"
+ },
+ [GTK_ACCESSIBLE_RELATION_ROW_COUNT] = {
+ .value = GTK_ACCESSIBLE_RELATION_ROW_COUNT,
+ .ctype = GTK_ACCESSIBLE_COLLECT_INTEGER,
+ .name = "rowcount"
+ },
+ [GTK_ACCESSIBLE_RELATION_ROW_INDEX] = {
+ .value = GTK_ACCESSIBLE_RELATION_ROW_INDEX,
+ .ctype = GTK_ACCESSIBLE_COLLECT_INTEGER,
+ .name = "rowindex"
+ },
+ [GTK_ACCESSIBLE_RELATION_ROW_INDEX_TEXT] = {
+ .value = GTK_ACCESSIBLE_RELATION_ROW_INDEX_TEXT,
+ .ctype = GTK_ACCESSIBLE_COLLECT_STRING,
+ .name = "rowindextext"
+ },
+ [GTK_ACCESSIBLE_RELATION_ROW_SPAN] = {
+ .value = GTK_ACCESSIBLE_RELATION_ROW_SPAN,
+ .ctype = GTK_ACCESSIBLE_COLLECT_INTEGER,
+ .name = "rowspan"
+ },
+ [GTK_ACCESSIBLE_RELATION_SET_SIZE] = {
+ .value = GTK_ACCESSIBLE_RELATION_SET_SIZE,
+ .ctype = GTK_ACCESSIBLE_COLLECT_INTEGER,
+ .name = "posinset"
+ },
+};
+
typedef GtkAccessibleValue * (* GtkAccessibleValueBooleanCtor) (gboolean value);
typedef GtkAccessibleValue * (* GtkAccessibleValueIntCtor) (int value);
typedef GtkAccessibleValue * (* GtkAccessibleValueTristateCtor) (int value);
@@ -1117,4 +1211,93 @@ gtk_accessible_value_collect_for_property_value (GtkAccessibleProperty property
return gtk_accessible_value_collect_value (cstate, value);
}
+/*< private >
+ * gtk_accessible_value_get_default_for_relation:
+ * @relation: a #GtkAccessibleRelation
+ *
+ * Retrieves the #GtkAccessibleValue that contains the default for the
+ * given @relation.
+ *
+ * Returns: (transfer full): the #GtkAccessibleValue
+ */
+GtkAccessibleValue *
+gtk_accessible_value_get_default_for_relation (GtkAccessibleRelation relation)
+{
+ const GtkAccessibleCollect *cstate = &collect_rels[relation];
+
+ switch (cstate->value)
+ {
+ /* References */
+ case GTK_ACCESSIBLE_RELATION_ACTIVE_DESCENDANT:
+ case GTK_ACCESSIBLE_RELATION_CONTROLS:
+ case GTK_ACCESSIBLE_RELATION_DESCRIBED_BY:
+ case GTK_ACCESSIBLE_RELATION_DETAILS:
+ case GTK_ACCESSIBLE_RELATION_ERROR_MESSAGE:
+ case GTK_ACCESSIBLE_RELATION_FLOW_TO:
+ case GTK_ACCESSIBLE_RELATION_LABELLED_BY:
+ case GTK_ACCESSIBLE_RELATION_OWNS:
+ return NULL;
+
+ /* Integers */
+ case GTK_ACCESSIBLE_RELATION_COL_COUNT:
+ case GTK_ACCESSIBLE_RELATION_COL_INDEX:
+ case GTK_ACCESSIBLE_RELATION_COL_SPAN:
+ case GTK_ACCESSIBLE_RELATION_POS_IN_SET:
+ case GTK_ACCESSIBLE_RELATION_ROW_COUNT:
+ case GTK_ACCESSIBLE_RELATION_ROW_INDEX:
+ case GTK_ACCESSIBLE_RELATION_ROW_SPAN:
+ case GTK_ACCESSIBLE_RELATION_SET_SIZE:
+ return gtk_int_accessible_value_new (0);
+
+ /* Strings */
+ case GTK_ACCESSIBLE_RELATION_ROW_INDEX_TEXT:
+ case GTK_ACCESSIBLE_RELATION_COL_INDEX_TEXT:
+ return gtk_string_accessible_value_new ("");
+
+ default:
+ g_critical ("Unknown value for accessible property “%s”", cstate->name);
+ break;
+ }
+
+ return NULL;
+}
+
+/*< private >
+ * gtk_accessible_value_collect_for_relation:
+ * @relation: a #GtkAccessibleRelation
+ * @args: a `va_list` reference
+ *
+ * Collects and consumes the next item in the @args variadic arguments list,
+ * and returns a #GtkAccessibleValue for it.
+ *
+ * Returns: (transfer full): a #GtkAccessibleValue
+ */
+GtkAccessibleValue *
+gtk_accessible_value_collect_for_relation (GtkAccessibleRelation relation,
+ va_list *args)
+{
+ const GtkAccessibleCollect *cstate = &collect_rels[relation];
+
+ return gtk_accessible_value_collect_valist (cstate, args);
+}
+
+/*< private >
+ * gtk_accessible_value_collect_for_relation_value:
+ * @relation: a #GtkAccessibleRelation
+ * @value: a #GValue
+ *
+ * Retrieves the value stored inside @value and returns a #GtkAccessibleValue
+ * for the given @relation.
+ *
+ * Returns: (transfer full): a #GtkAccessibleValue
+ */
+GtkAccessibleValue *
+gtk_accessible_value_collect_for_relation_value (GtkAccessibleRelation relation,
+ const GValue *value)
+{
+ const GtkAccessibleCollect *cstate = &collect_rels[relation];
+
+ return gtk_accessible_value_collect_value (cstate, value);
+}
+
/* }}} */
diff --git a/gtk/gtkaccessiblevalueprivate.h b/gtk/gtkaccessiblevalueprivate.h
index 9f80edac92..30648d1fb0 100644
--- a/gtk/gtkaccessiblevalueprivate.h
+++ b/gtk/gtkaccessiblevalueprivate.h
@@ -102,6 +102,12 @@ GtkAccessibleValue * gtk_accessible_value_collect_for_property (GtkAcce
GtkAccessibleValue * gtk_accessible_value_collect_for_property_value (GtkAccessibleProperty
property,
const GValue
*value);
+GtkAccessibleValue * gtk_accessible_value_get_default_for_relation (GtkAccessibleRelation
relation);
+GtkAccessibleValue * gtk_accessible_value_collect_for_relation (GtkAccessibleRelation
relation,
+ va_list
*args);
+GtkAccessibleValue * gtk_accessible_value_collect_for_relation_value (GtkAccessibleRelation
relation,
+ const GValue
*value);
+
/* Basic values */
GtkAccessibleValue * gtk_undefined_accessible_value_new (void);
int gtk_undefined_accessible_value_get (const GtkAccessibleValue *value);
diff --git a/gtk/gtkatcontext.c b/gtk/gtkatcontext.c
index 4fe0b8176f..6466678ad7 100644
--- a/gtk/gtkatcontext.c
+++ b/gtk/gtkatcontext.c
@@ -56,8 +56,9 @@ gtk_at_context_finalize (GObject *gobject)
{
GtkATContext *self = GTK_AT_CONTEXT (gobject);
- gtk_accessible_state_set_unref (self->states);
gtk_accessible_property_set_unref (self->properties);
+ gtk_accessible_relation_set_unref (self->relations);
+ gtk_accessible_state_set_unref (self->states);
G_OBJECT_CLASS (gtk_at_context_parent_class)->finalize (gobject);
}
@@ -111,9 +112,11 @@ gtk_at_context_get_property (GObject *gobject,
static void
gtk_at_context_real_state_change (GtkATContext *self,
GtkAccessibleStateChange changed_states,
- GtkAccessiblePropertyChange changed_properies,
+ GtkAccessiblePropertyChange changed_properties,
+ GtkAccessibleRelationChange changed_relations,
GtkAccessibleStateSet *states,
- GtkAccessiblePropertySet *properties)
+ GtkAccessiblePropertySet *properties,
+ GtkAccessibleRelationSet *relations)
{
}
@@ -168,8 +171,9 @@ gtk_at_context_init (GtkATContext *self)
{
self->accessible_role = GTK_ACCESSIBLE_ROLE_WIDGET;
- self->states = gtk_accessible_state_set_new ();
self->properties = gtk_accessible_property_set_new ();
+ self->relations = gtk_accessible_relation_set_new ();
+ self->states = gtk_accessible_state_set_new ();
}
/**
@@ -269,6 +273,7 @@ gtk_at_context_update (GtkATContext *self)
GtkAccessibleStateChange changed_states = 0;
GtkAccessiblePropertyChange changed_properties = 0;
+ GtkAccessibleRelationChange changed_relations = 0;
for (int i = 0; i < GTK_ACCESSIBLE_STATE_SELECTED; i++)
{
@@ -282,11 +287,19 @@ gtk_at_context_update (GtkATContext *self)
changed_properties |= (1 << i);
}
+ for (int i = 0; i < GTK_ACCESSIBLE_RELATION_SET_SIZE; i++)
+ {
+ if (gtk_accessible_relation_set_contains (self->relations, i))
+ changed_relations |= (1 << i);
+ }
+
GTK_AT_CONTEXT_GET_CLASS (self)->state_change (self,
changed_states,
changed_properties,
+ changed_relations,
self->states,
- self->properties);
+ self->properties,
+ self->relations);
}
/*< private >
@@ -340,3 +353,29 @@ gtk_at_context_set_accessible_property (GtkATContext *self,
else
gtk_accessible_property_set_remove (self->properties, property);
}
+
+/*< private >
+ * gtk_at_context_set_accessible_relation:
+ * @self: a #GtkATContext
+ * @relation: a #GtkAccessibleRelation
+ * @value: (nullable): #GtkAccessibleValue
+ *
+ * Sets the @value for the given @relation of a #GtkATContext.
+ *
+ * If @value is %NULL, the relation is unset.
+ *
+ * This function will accumulate relation changes until gtk_at_context_update_state()
+ * is called.
+ */
+void
+gtk_at_context_set_accessible_relation (GtkATContext *self,
+ GtkAccessibleRelation relation,
+ GtkAccessibleValue *value)
+{
+ g_return_if_fail (GTK_IS_AT_CONTEXT (self));
+
+ if (value != NULL)
+ gtk_accessible_relation_set_add (self->relations, relation, value);
+ else
+ gtk_accessible_relation_set_remove (self->relations, relation);
+}
diff --git a/gtk/gtkatcontextprivate.h b/gtk/gtkatcontextprivate.h
index ec152a2060..ee7a6dea7c 100644
--- a/gtk/gtkatcontextprivate.h
+++ b/gtk/gtkatcontextprivate.h
@@ -22,22 +22,12 @@
#include "gtkatcontext.h"
-#include "gtkaccessiblestatesetprivate.h"
#include "gtkaccessiblepropertysetprivate.h"
+#include "gtkaccessiblerelationsetprivate.h"
+#include "gtkaccessiblestatesetprivate.h"
G_BEGIN_DECLS
-typedef enum {
- GTK_ACCESSIBLE_STATE_CHANGE_BUSY = 1 << GTK_ACCESSIBLE_STATE_BUSY,
- GTK_ACCESSIBLE_STATE_CHANGE_CHECKED = 1 << GTK_ACCESSIBLE_STATE_CHECKED,
- GTK_ACCESSIBLE_STATE_CHANGE_DISABLED = 1 << GTK_ACCESSIBLE_STATE_DISABLED,
- GTK_ACCESSIBLE_STATE_CHANGE_EXPANDED = 1 << GTK_ACCESSIBLE_STATE_EXPANDED,
- GTK_ACCESSIBLE_STATE_CHANGE_HIDDEN = 1 << GTK_ACCESSIBLE_STATE_HIDDEN,
- GTK_ACCESSIBLE_STATE_CHANGE_INVALID = 1 << GTK_ACCESSIBLE_STATE_INVALID,
- GTK_ACCESSIBLE_STATE_CHANGE_PRESSED = 1 << GTK_ACCESSIBLE_STATE_PRESSED,
- GTK_ACCESSIBLE_STATE_CHANGE_SELECTED = 1 << GTK_ACCESSIBLE_STATE_SELECTED
-} GtkAccessibleStateChange;
-
typedef enum {
GTK_ACCESSIBLE_PROPERTY_CHANGE_AUTOCOMPLETE = 1 << GTK_ACCESSIBLE_PROPERTY_AUTOCOMPLETE,
GTK_ACCESSIBLE_PROPERTY_CHANGE_DESCRIPTION = 1 << GTK_ACCESSIBLE_PROPERTY_DESCRIPTION,
@@ -60,6 +50,38 @@ typedef enum {
GTK_ACCESSIBLE_PROPERTY_CHANGE_VALUE_TEXT = 1 << GTK_ACCESSIBLE_PROPERTY_VALUE_TEXT
} GtkAccessiblePropertyChange;
+typedef enum {
+ GTK_ACCESSIBLE_RELATION_CHANGE_ACTIVE_DESCENDANT = 1 << GTK_ACCESSIBLE_RELATION_ACTIVE_DESCENDANT,
+ GTK_ACCESSIBLE_RELATION_CHANGE_COL_COUNT = 1 << GTK_ACCESSIBLE_RELATION_COL_COUNT,
+ GTK_ACCESSIBLE_RELATION_CHANGE_COL_INDEX = 1 << GTK_ACCESSIBLE_RELATION_COL_INDEX,
+ GTK_ACCESSIBLE_RELATION_CHANGE_COL_INDEX_TEXT = 1 << GTK_ACCESSIBLE_RELATION_COL_INDEX_TEXT,
+ GTK_ACCESSIBLE_RELATION_CHANGE_COL_SPAN = 1 << GTK_ACCESSIBLE_RELATION_COL_SPAN,
+ GTK_ACCESSIBLE_RELATION_CHANGE_CONTROLS = 1 << GTK_ACCESSIBLE_RELATION_CONTROLS,
+ GTK_ACCESSIBLE_RELATION_CHANGE_DESCRIBED_BY = 1 << GTK_ACCESSIBLE_RELATION_DESCRIBED_BY,
+ GTK_ACCESSIBLE_RELATION_CHANGE_DETAILS = 1 << GTK_ACCESSIBLE_RELATION_DETAILS,
+ GTK_ACCESSIBLE_RELATION_CHANGE_ERROR_MESSAGE = 1 << GTK_ACCESSIBLE_RELATION_ERROR_MESSAGE,
+ GTK_ACCESSIBLE_RELATION_CHANGE_FLOW_TO = 1 << GTK_ACCESSIBLE_RELATION_FLOW_TO,
+ GTK_ACCESSIBLE_RELATION_CHANGE_LABELLED_BY = 1 << GTK_ACCESSIBLE_RELATION_LABELLED_BY,
+ GTK_ACCESSIBLE_RELATION_CHANGE_OWNS = 1 << GTK_ACCESSIBLE_RELATION_OWNS,
+ GTK_ACCESSIBLE_RELATION_CHANGE_POS_IN_SET = 1 << GTK_ACCESSIBLE_RELATION_POS_IN_SET,
+ GTK_ACCESSIBLE_RELATION_CHANGE_ROW_COUNT = 1 << GTK_ACCESSIBLE_RELATION_ROW_COUNT,
+ GTK_ACCESSIBLE_RELATION_CHANGE_ROW_INDEX = 1 << GTK_ACCESSIBLE_RELATION_ROW_INDEX,
+ GTK_ACCESSIBLE_RELATION_CHANGE_ROW_INDEX_TEXT = 1 << GTK_ACCESSIBLE_RELATION_ROW_INDEX_TEXT,
+ GTK_ACCESSIBLE_RELATION_CHANGE_ROW_SPAN = 1 << GTK_ACCESSIBLE_RELATION_ROW_SPAN,
+ GTK_ACCESSIBLE_RELATION_CHANGE_SET_SIZE = 1 << GTK_ACCESSIBLE_RELATION_SET_SIZE
+} GtkAccessibleRelationChange;
+
+typedef enum {
+ GTK_ACCESSIBLE_STATE_CHANGE_BUSY = 1 << GTK_ACCESSIBLE_STATE_BUSY,
+ GTK_ACCESSIBLE_STATE_CHANGE_CHECKED = 1 << GTK_ACCESSIBLE_STATE_CHECKED,
+ GTK_ACCESSIBLE_STATE_CHANGE_DISABLED = 1 << GTK_ACCESSIBLE_STATE_DISABLED,
+ GTK_ACCESSIBLE_STATE_CHANGE_EXPANDED = 1 << GTK_ACCESSIBLE_STATE_EXPANDED,
+ GTK_ACCESSIBLE_STATE_CHANGE_HIDDEN = 1 << GTK_ACCESSIBLE_STATE_HIDDEN,
+ GTK_ACCESSIBLE_STATE_CHANGE_INVALID = 1 << GTK_ACCESSIBLE_STATE_INVALID,
+ GTK_ACCESSIBLE_STATE_CHANGE_PRESSED = 1 << GTK_ACCESSIBLE_STATE_PRESSED,
+ GTK_ACCESSIBLE_STATE_CHANGE_SELECTED = 1 << GTK_ACCESSIBLE_STATE_SELECTED
+} GtkAccessibleStateChange;
+
struct _GtkATContext
{
GObject parent_instance;
@@ -69,6 +91,7 @@ struct _GtkATContext
GtkAccessibleStateSet *states;
GtkAccessiblePropertySet *properties;
+ GtkAccessibleRelationSet *relations;
};
struct _GtkATContextClass
@@ -78,8 +101,10 @@ struct _GtkATContextClass
void (* state_change) (GtkATContext *self,
GtkAccessibleStateChange changed_states,
GtkAccessiblePropertyChange changed_properties,
+ GtkAccessibleRelationChange changed_relations,
GtkAccessibleStateSet *states,
- GtkAccessiblePropertySet *properties);
+ GtkAccessiblePropertySet *properties,
+ GtkAccessibleRelationSet *relations);
};
GtkATContext * gtk_at_context_create (GtkAccessibleRole accessible_role,
@@ -93,5 +118,8 @@ void gtk_at_context_set_accessible_state (GtkATContext *
void gtk_at_context_set_accessible_property (GtkATContext *self,
GtkAccessibleProperty property,
GtkAccessibleValue *value);
+void gtk_at_context_set_accessible_relation (GtkATContext *self,
+ GtkAccessibleRelation property,
+ GtkAccessibleValue *value);
G_END_DECLS
diff --git a/gtk/gtktestatcontext.c b/gtk/gtktestatcontext.c
index f89e354451..e9b7e8c0b4 100644
--- a/gtk/gtktestatcontext.c
+++ b/gtk/gtktestatcontext.c
@@ -36,24 +36,30 @@ static void
gtk_test_at_context_state_change (GtkATContext *self,
GtkAccessibleStateChange changed_states,
GtkAccessiblePropertyChange changed_properties,
+ GtkAccessibleRelationChange changed_relations,
GtkAccessibleStateSet *states,
- GtkAccessiblePropertySet *properties)
+ GtkAccessiblePropertySet *properties,
+ GtkAccessibleRelationSet *relations)
{
GtkAccessible *accessible = gtk_at_context_get_accessible (self);
GtkAccessibleRole role = gtk_at_context_get_accessible_role (self);
char *states_str = gtk_accessible_state_set_to_string (states);
char *properties_str = gtk_accessible_property_set_to_string (properties);
+ char *relations_str = gtk_accessible_relation_set_to_string (relations);
g_print ("*** Accessible state changed for accessible “%s”, with role %d:\n"
- "*** states = %s\n"
- "*** properties = %s\n",
+ "*** states = %s\n"
+ "*** properties = %s\n"
+ "*** relations = %s\n",
G_OBJECT_TYPE_NAME (accessible),
role,
states_str,
- properties_str);
+ properties_str,
+ relations_str);
g_free (states_str);
g_free (properties_str);
+ g_free (relations_str);
}
static void
diff --git a/gtk/meson.build b/gtk/meson.build
index 432029a1ed..440be6f55c 100644
--- a/gtk/meson.build
+++ b/gtk/meson.build
@@ -17,6 +17,7 @@ gtk_private_sources = files([
'tools/gdkpixbufutils.c',
'gsettings-mapping.c',
'gtkaccessiblepropertyset.c',
+ 'gtkaccessiblerelationset.c',
'gtkaccessiblestateset.c',
'gtkaccessiblevalue.c',
'gtkaccessiblevaluestatic.c',
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]