diff --git a/gtk/gtkaccessible.c b/gtk/gtkaccessible.c index d8187b60c0..c6e576c329 100644 --- a/gtk/gtkaccessible.c +++ b/gtk/gtkaccessible.c @@ -18,9 +18,36 @@ * License along with this library; if not, see . */ +/** + * SECTION:gtkaccessible + * @Title: GtkAccessible + * @Short_description: Accessible interface + * + * GtkAccessible provides an interface for describing a UI element, like a + * #GtkWidget, in a way that can be consumed by Assistive Technologies, or + * “AT”. Every accessible implementation has: + * + * - a “role”, represented by a value of the #GtkAccessibleRole enumeration + * - a “state”, represented by a set of #GtkAccessibleState and + * #GtkAccessibleProperty values + * + * The role cannot be changed after instantiating a #GtkAccessible + * implementation. + * + * The state is updated every time a UI element's state changes in a way that + * should be reflected by assistive technologies. For instance, if a #GtkWidget + * visibility changes, the %GTK_ACCESSIBLE_STATE_HIDDEN state will also change + * to reflect the #GtkWidget:visible property. + */ + #include "config.h" -#include "gtkaccessible.h" +#include "gtkaccessibleprivate.h" + +#include "gtkatcontextprivate.h" +#include "gtkenums.h" + +#include G_DEFINE_INTERFACE (GtkAccessible, gtk_accessible, G_TYPE_OBJECT) @@ -28,3 +55,97 @@ static void gtk_accessible_default_init (GtkAccessibleInterface *iface) { } + +GtkATContext * +gtk_accessible_get_at_context (GtkAccessible *self) +{ + g_return_val_if_fail (GTK_IS_ACCESSIBLE (self), NULL); + + return GTK_ACCESSIBLE_GET_IFACE (self)->get_at_context (self); +} + +/** + * gtk_accessible_update_state: + * @self: a #GtkAccessible + * @first_state: the first #GtkAccessibleState + * @...: a list of state and value pairs, terminated by %GTK_ACCESSIBLE_STATE_NONE + * + * Updates a list of accessible states. + * + * This function should be called by #GtkWidget types whenever an accessible + * state change must be communicated to assistive technologies. + */ +void +gtk_accessible_update_state (GtkAccessible *self, + GtkAccessibleState first_state, + ...) +{ + GtkAccessibleState state; + 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_state); + + state = first_state; + + while (state != GTK_ACCESSIBLE_STATE_NONE) + { + GtkAccessibleValue *value = gtk_accessible_value_collect_for_state (state, &args); + + if (value == NULL) + goto out; + + gtk_at_context_set_state (context, state, value); + gtk_accessible_value_unref (value); + + state = va_arg (args, int); + } + + gtk_at_context_update_state (context); + +out: + va_end (args); +} + +/** + * gtk_accessible_update_state_value: + * @self: a #GtkAccessible + * @state: a #GtkAccessibleState + * @value: a #GValue with the value for @state + * + * Updates an accessible state. + * + * This function should be called by #GtkWidget types whenever an accessible + * state change must be communicated to assistive technologies. + * + * This function is meant to be used by language bindings. + */ +void +gtk_accessible_update_state_value (GtkAccessible *self, + GtkAccessibleState state, + 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_state_value (state, value); + + if (real_value == NULL) + return; + + gtk_at_context_set_state (context, state, real_value); + gtk_accessible_value_unref (real_value); + gtk_at_context_update_state (context); +} diff --git a/gtk/gtkaccessible.h b/gtk/gtkaccessible.h index d54d21a2d0..9fe16616e5 100644 --- a/gtk/gtkaccessible.h +++ b/gtk/gtkaccessible.h @@ -31,9 +31,13 @@ G_BEGIN_DECLS GDK_AVAILABLE_IN_ALL G_DECLARE_INTERFACE (GtkAccessible, gtk_accessible, GTK, ACCESSIBLE, GObject) -struct _GtkAccessibleInterface -{ - GTypeInterface g_iface; -}; +GDK_AVAILABLE_IN_ALL +void gtk_accessible_update_state (GtkAccessible *self, + GtkAccessibleState first_state, + ...); +GDK_AVAILABLE_IN_ALL +void gtk_accessible_update_state_value (GtkAccessible *self, + GtkAccessibleState state, + const GValue *value); G_END_DECLS diff --git a/gtk/gtkaccessibleprivate.h b/gtk/gtkaccessibleprivate.h new file mode 100644 index 0000000000..aa5701cf50 --- /dev/null +++ b/gtk/gtkaccessibleprivate.h @@ -0,0 +1,37 @@ +/* gtkaccessibleprivate.h: Accessible interface + * + * 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 . + */ + +#pragma once + +#include "gtkaccessible.h" +#include "gtkatcontext.h" + +G_BEGIN_DECLS + +struct _GtkAccessibleInterface +{ + GTypeInterface g_iface; + + GtkATContext * (* get_at_context) (GtkAccessible *self); +}; + +GtkATContext * gtk_accessible_get_at_context (GtkAccessible *self); + +G_END_DECLS