diff --git a/gtk/gtkaccessible.c b/gtk/gtkaccessible.c index c6e576c329..47bebc7543 100644 --- a/gtk/gtkaccessible.c +++ b/gtk/gtkaccessible.c @@ -46,6 +46,7 @@ #include "gtkatcontextprivate.h" #include "gtkenums.h" +#include "gtktypebuiltins.h" #include @@ -54,8 +55,27 @@ G_DEFINE_INTERFACE (GtkAccessible, gtk_accessible, G_TYPE_OBJECT) static void gtk_accessible_default_init (GtkAccessibleInterface *iface) { + GParamSpec *pspec = + g_param_spec_enum ("accessible-role", + "Accessible Role", + "The role of the accessible object", + GTK_TYPE_ACCESSIBLE_ROLE, + GTK_ACCESSIBLE_ROLE_WIDGET, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + + g_object_interface_install_property (iface, pspec); } +/*< private > + * gtk_accessible_get_at_context: + * @self: a #GtkAccessible + * + * Retrieves the #GtkATContext for the given #GtkAccessible. + * + * Returns: (transfer none): the #GtkATContext + */ GtkATContext * gtk_accessible_get_at_context (GtkAccessible *self) { @@ -64,6 +84,26 @@ gtk_accessible_get_at_context (GtkAccessible *self) return GTK_ACCESSIBLE_GET_IFACE (self)->get_at_context (self); } +/** + * gtk_accessible_get_accessible_role: + * @self: a #GtkAccessible + * + * Retrieves the #GtkAccessibleRole for the given #GtkAccessible. + * + * Returns: a #GtkAccessibleRole + */ +GtkAccessibleRole +gtk_accessible_get_accessible_role (GtkAccessible *self) +{ + g_return_val_if_fail (GTK_IS_ACCESSIBLE (self), GTK_ACCESSIBLE_ROLE_WIDGET); + + GtkATContext *context = gtk_accessible_get_at_context (self); + if (context == NULL) + return GTK_ACCESSIBLE_ROLE_WIDGET; + + return gtk_at_context_get_accessible_role (context); +} + /** * gtk_accessible_update_state: * @self: a #GtkAccessible diff --git a/gtk/gtkaccessible.h b/gtk/gtkaccessible.h index 9fe16616e5..5b943f89a2 100644 --- a/gtk/gtkaccessible.h +++ b/gtk/gtkaccessible.h @@ -32,12 +32,15 @@ GDK_AVAILABLE_IN_ALL G_DECLARE_INTERFACE (GtkAccessible, gtk_accessible, GTK, ACCESSIBLE, GObject) GDK_AVAILABLE_IN_ALL -void gtk_accessible_update_state (GtkAccessible *self, - GtkAccessibleState first_state, - ...); +GtkAccessibleRole gtk_accessible_get_accessible_role (GtkAccessible *self); + GDK_AVAILABLE_IN_ALL -void gtk_accessible_update_state_value (GtkAccessible *self, - GtkAccessibleState state, - const GValue *value); +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/gtkwidget.c b/gtk/gtkwidget.c index cebf881abf..d19bbe958e 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -511,7 +511,10 @@ enum { PROP_CSS_NAME, PROP_CSS_CLASSES, PROP_LAYOUT_MANAGER, - NUM_PROPERTIES + NUM_PROPERTIES, + + /* GtkAccessible */ + PROP_ACCESSIBLE_ROLE }; static GParamSpec *widget_props[NUM_PROPERTIES] = { NULL, }; @@ -1334,6 +1337,8 @@ gtk_widget_class_init (GtkWidgetClass *klass) g_object_class_install_properties (gobject_class, NUM_PROPERTIES, widget_props); + g_object_class_override_property (gobject_class, PROP_ACCESSIBLE_ROLE, "accessible-role"); + /** * GtkWidget::destroy: * @object: the object which received the signal @@ -1714,6 +1719,9 @@ gtk_widget_set_property (GObject *object, case PROP_LAYOUT_MANAGER: gtk_widget_set_layout_manager (widget, g_value_dup_object (value)); break; + case PROP_ACCESSIBLE_ROLE: + priv->accessible_role = g_value_get_enum (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1844,6 +1852,16 @@ gtk_widget_get_property (GObject *object, case PROP_LAYOUT_MANAGER: g_value_set_object (value, gtk_widget_get_layout_manager (widget)); break; + case PROP_ACCESSIBLE_ROLE: + { + GtkAccessibleRole role = priv->accessible_role; + + if (priv->accessible_role == GTK_ACCESSIBLE_ROLE_WIDGET) + role = gtk_widget_class_get_accessible_role (GTK_WIDGET_GET_CLASS (widget)); + + g_value_set_enum (value, role); + } + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -2257,6 +2275,8 @@ gtk_widget_init (GTypeInstance *instance, gpointer g_class) priv->halign = GTK_ALIGN_FILL; priv->valign = GTK_ALIGN_FILL; + priv->accessible_role = GTK_ACCESSIBLE_ROLE_WIDGET; + priv->width_request = -1; priv->height_request = -1; @@ -8075,9 +8095,23 @@ gtk_widget_accessible_get_at_context (GtkAccessible *accessible) { GtkWidgetClass *widget_class = GTK_WIDGET_GET_CLASS (self); GtkWidgetClassPrivate *class_priv = widget_class->priv; + GtkAccessibleRole role; - priv->at_context = - gtk_at_context_create (class_priv->accessible_role, accessible); + /* Widgets have two options to set the accessible role: either they + * define it in their class_init() function, and the role applies to + * all instances; or an instance is created with the :accessible-role + * property (from GtkAccessible) set to anything other than the default + * GTK_ACCESSIBLE_ROLE_WIDGET value. + * + * In either case, the accessible role cannot be set post-construction. + */ + if (priv->accessible_role != GTK_ACCESSIBLE_ROLE_WIDGET) + role = priv->accessible_role; + else + role = class_priv->accessible_role; + + priv->at_context = gtk_at_context_create (role, accessible); + priv->accessible_role = role; } return priv->at_context; @@ -12138,3 +12172,27 @@ gtk_widget_class_set_accessible_role (GtkWidgetClass *widget_class, priv = widget_class->priv; priv->accessible_role = accessible_role; } + +/** + * gtk_widget_class_get_accessible_role: + * @widget_class: a #GtkWidgetClass + * + * Retrieves the accessible role used by the given #GtkWidget class. + * + * Different accessible roles have different states, and are rendered + * differently by assistive technologies. + * + * See also: gtk_accessible_get_accessible_role() + * + * Returns: the accessible role for the widget class + */ +GtkAccessibleRole +gtk_widget_class_get_accessible_role (GtkWidgetClass *widget_class) +{ + GtkWidgetClassPrivate *priv; + + g_return_val_if_fail (GTK_IS_WIDGET_CLASS (widget_class), GTK_ACCESSIBLE_ROLE_WIDGET); + + priv = widget_class->priv; + return priv->accessible_role; +} diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h index a897237860..08b9bf2de2 100644 --- a/gtk/gtkwidget.h +++ b/gtk/gtkwidget.h @@ -980,6 +980,8 @@ void gtk_widget_action_set_enabled (GtkWidget *widget, GDK_AVAILABLE_IN_ALL void gtk_widget_class_set_accessible_role (GtkWidgetClass *widget_class, GtkAccessibleRole accessible_role); +GDK_AVAILABLE_IN_ALL +GtkAccessibleRole gtk_widget_class_get_accessible_role (GtkWidgetClass *widget_class); G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkWidget, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkRequisition, gtk_requisition_free) diff --git a/gtk/gtkwidgetprivate.h b/gtk/gtkwidgetprivate.h index f0df306bde..d417edc77c 100644 --- a/gtk/gtkwidgetprivate.h +++ b/gtk/gtkwidgetprivate.h @@ -191,7 +191,8 @@ struct _GtkWidgetPrivate char *tooltip_markup; char *tooltip_text; - /* Accessible context */ + /* Accessibility */ + GtkAccessibleRole accessible_role; GtkATContext *at_context; };