Allow setting the accessible role at construction

Some widgets have different accessible roles depending on some
parameter, so we cannot set the role at class init time. For those
widgets, we add an "accessible-role" property to GtkAccessible, and we
allow setting it (only) at construction time.
This commit is contained in:
Emmanuele Bassi 2020-07-13 15:20:19 +01:00
parent 5a173df3da
commit 572861be27
5 changed files with 114 additions and 10 deletions

View File

@ -46,6 +46,7 @@
#include "gtkatcontextprivate.h"
#include "gtkenums.h"
#include "gtktypebuiltins.h"
#include <stdarg.h>
@ -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

View File

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

View File

@ -512,7 +512,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, };
@ -1335,6 +1338,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
@ -1715,6 +1720,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;
@ -1845,6 +1853,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;
@ -2258,6 +2276,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;
@ -8076,9 +8096,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;
@ -12139,3 +12173,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;
}

View File

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

View File

@ -193,7 +193,8 @@ struct _GtkWidgetPrivate
char *tooltip_markup;
char *tooltip_text;
/* Accessible context */
/* Accessibility */
GtkAccessibleRole accessible_role;
GtkATContext *at_context;
};