a11y: Add relations API

Since we split relation attributes from the generic properties, we need
to add API for setting and retrieving their values.
This commit is contained in:
Emmanuele Bassi 2020-07-17 12:00:31 +01:00
parent d37511f76b
commit 1124f2507d
10 changed files with 646 additions and 22 deletions

View File

@ -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);
}

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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);
}
/* }}} */

View File

@ -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);

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -17,6 +17,7 @@ gtk_private_sources = files([
'tools/gdkpixbufutils.c',
'gsettings-mapping.c',
'gtkaccessiblepropertyset.c',
'gtkaccessiblerelationset.c',
'gtkaccessiblestateset.c',
'gtkaccessiblevalue.c',
'gtkaccessiblevaluestatic.c',