Commit 8c184800 authored by Emmanuele Bassi's avatar Emmanuele Bassi 👣
Browse files

a11y: Add a display to GtkATContext

Since we need to check at run time what kind of AT context to use, we
need a hook into the whole GDK backend machinery. The display connection
seems to be the best choice, in this case, as it allows us to determine
whether we're running on an X11 or Wayland system, and thus whether we
should create a GtkAtSpiContext.

This requires some surgery to fix the GtkATContext creation function, in
order to include a GdkDisplay instance.
parent 8f19bb08
......@@ -22,6 +22,13 @@
#include "gtkatspicontextprivate.h"
#if defined(GDK_WINDOWING_WAYLAND)
# include <gdk/wayland/gdkwaylanddisplay.h>
#endif
#if defined(GDK_WINDOWING_X11)
# include <gdk/x11/gdkx11display.h>
#endif
struct _GtkAtSpiContext
{
GtkATContext parent_instance;
......@@ -62,24 +69,30 @@ gtk_at_spi_context_init (GtkAtSpiContext *self)
{
}
/*< private >
* gtk_at_spi_context_new:
* @accessible_role: the accessible role for the AT context
* @accessible: the #GtkAccessible instance which owns the context
*
* Creates a new #GtkAtSpiContext instance for @accessible, using the
* given @accessible_role.
*
* Returns: (transfer full): the newly created #GtkAtSpiContext
*/
GtkATContext *
gtk_at_spi_context_new (GtkAccessibleRole accessible_role,
GtkAccessible * accessible)
gtk_at_spi_create_context (GtkAccessibleRole accessible_role,
GtkAccessible *accessible,
GdkDisplay *display)
{
g_return_val_if_fail (GTK_IS_ACCESSIBLE (accessible), NULL);
g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
#if defined(GDK_WINDOWING_WAYLAND)
if (GDK_IS_WAYLAND_DISPLAY (display))
return g_object_new (GTK_TYPE_AT_SPI_CONTEXT,
"accessible-role", accessible_role,
"accessible", accessible,
"display", display,
NULL);
#endif
#if defined(GDK_WINDOWING_X11)
if (GDK_IS_X11_DISPLAY (display))
return g_object_new (GTK_TYPE_AT_SPI_CONTEXT,
"accessible-role", accessible_role,
"accessible", accessible,
"display", display,
NULL);
#endif
return g_object_new (GTK_TYPE_AT_SPI_CONTEXT,
"accessible-role", accessible_role,
"accessible", accessible,
NULL);
return NULL;
}
......@@ -29,7 +29,8 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (GtkAtSpiContext, gtk_at_spi_context, GTK, AT_SPI_CONTEXT, GtkATContext)
GtkATContext *
gtk_at_spi_context_new (GtkAccessibleRole accessible_role,
GtkAccessible *accessible);
gtk_at_spi_create_context (GtkAccessibleRole accessible_role,
GtkAccessible *accessible,
GdkDisplay *display);
G_END_DECLS
......@@ -50,6 +50,7 @@ enum
{
PROP_ACCESSIBLE_ROLE = 1,
PROP_ACCESSIBLE,
PROP_DISPLAY,
N_PROPS
};
......@@ -95,6 +96,10 @@ gtk_at_context_set_property (GObject *gobject,
self->accessible = g_value_get_object (value);
break;
case PROP_DISPLAY:
self->display = g_value_get_object (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
}
......@@ -118,6 +123,10 @@ gtk_at_context_get_property (GObject *gobject,
g_value_set_object (value, self->accessible);
break;
case PROP_DISPLAY:
g_value_set_object (value, self->display);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
}
......@@ -177,6 +186,20 @@ gtk_at_context_class_init (GtkATContextClass *klass)
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
/**
* GtkATContext:display:
*
* The #GdkDisplay for the #GtkATContext.
*/
obj_props[PROP_DISPLAY] =
g_param_spec_object ("display",
"Display",
"The display connection",
GDK_TYPE_DISPLAY,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
/**
* GtkATContext::state-change:
* @self: the #GtkATContext
......@@ -359,16 +382,33 @@ gtk_at_context_get_accessible_role (GtkATContext *self)
return self->accessible_role;
}
/*< private >
* gtk_at_context_get_display:
* @self: a #GtkATContext
*
* Retrieves the #GdkDisplay used to create the context.
*
* Returns: (transfer none): a #GdkDisplay
*/
GdkDisplay *
gtk_at_context_get_display (GtkATContext *self)
{
g_return_val_if_fail (GTK_IS_AT_CONTEXT (self), NULL);
return self->display;
}
static const struct {
const char *name;
GtkATContext * (* create_context) (GtkAccessibleRole accessible_role,
GtkAccessible *accessible);
GtkAccessible *accessible,
GdkDisplay *display);
} a11y_backends[] = {
#if defined(GDK_WINDOWING_WAYLAND)
{ "AT-SPI", _gtk_at_spi_context_new },
{ "AT-SPI (Wayland)", gtk_at_spi_create_context },
#endif
#if defined(GDK_WINDOWING_X11)
{ "AT-SPI", gtk_at_spi_context_new },
{ "AT-SPI (X11)", gtk_at_spi_create_context },
#endif
{ NULL, NULL },
};
......@@ -377,9 +417,10 @@ static const struct {
* gtk_at_context_create: (constructor)
* @accessible_role: the accessible role used by the #GtkATContext
* @accessible: the #GtkAccessible implementation using the #GtkATContext
* @display: the #GdkDisplay used by the #GtkATContext
*
* Creates a new #GtkATContext instance for the given accessible role and
* accessible instance.
* Creates a new #GtkATContext instance for the given accessible role,
* accessible instance, and display connection.
*
* The #GtkATContext implementation being instantiated will depend on the
* platform.
......@@ -388,7 +429,8 @@ static const struct {
*/
GtkATContext *
gtk_at_context_create (GtkAccessibleRole accessible_role,
GtkAccessible *accessible)
GtkAccessible *accessible,
GdkDisplay *display)
{
static const char *gtk_test_accessible;
static const char *gtk_no_a11y;
......@@ -424,16 +466,25 @@ gtk_at_context_create (GtkAccessibleRole accessible_role,
for (guint i = 0; i < G_N_ELEMENTS (a11y_backends); i++)
{
if (a11y_backends[i].name == NULL)
break;
GTK_NOTE (A11Y, g_message ("Trying %s a11y backend", a11y_backends[i].name));
if (a11y_backends[i].create_context != NULL)
{
res = a11y_backends[i].create_context (accessible_role, accessible);
break;
res = a11y_backends[i].create_context (accessible_role, accessible, display);
if (res != NULL)
break;
}
}
/* Fall back to the test context, so we can get debugging data */
if (res == NULL)
res = gtk_test_at_context_new (accessible_role, accessible);
res = g_object_new (GTK_TYPE_TEST_AT_CONTEXT,
"accessible_role", accessible_role,
"accessible", accessible,
"display", display,
NULL);
/* FIXME: Add GIOExtension for AT contexts */
return res;
......
......@@ -42,6 +42,7 @@ GtkAccessibleRole gtk_at_context_get_accessible_role (GtkATContext
GDK_AVAILABLE_IN_ALL
GtkATContext * gtk_at_context_create (GtkAccessibleRole accessible_role,
GtkAccessible *accessible);
GtkAccessible *accessible,
GdkDisplay *display);
G_END_DECLS
......@@ -86,6 +86,7 @@ struct _GtkATContext
GtkAccessibleRole accessible_role;
GtkAccessible *accessible;
GdkDisplay *display;
GtkAccessibleAttributeSet *states;
GtkAccessibleAttributeSet *properties;
......@@ -109,6 +110,8 @@ struct _GtkATContextClass
GtkAccessibleAttributeSet *relations);
};
GdkDisplay * gtk_at_context_get_display (GtkATContext *self);
void gtk_at_context_update (GtkATContext *self);
void gtk_at_context_set_accessible_state (GtkATContext *self,
......
......@@ -8095,6 +8095,7 @@ gtk_widget_accessible_get_at_context (GtkAccessible *accessible)
{
GtkWidgetClass *widget_class = GTK_WIDGET_GET_CLASS (self);
GtkWidgetClassPrivate *class_priv = widget_class->priv;
GdkDisplay *display = _gtk_widget_get_display (self);
GtkAccessibleRole role;
/* Widgets have two options to set the accessible role: either they
......@@ -8111,7 +8112,7 @@ gtk_widget_accessible_get_at_context (GtkAccessible *accessible)
role = class_priv->accessible_role;
priv->accessible_role = role;
priv->at_context = gtk_at_context_create (role, accessible);
priv->at_context = gtk_at_context_create (role, accessible, display);
}
return priv->at_context;
......
......@@ -29,7 +29,9 @@ test_object_accessible_get_at_context (GtkAccessible *accessible)
TestObject *self = (TestObject*)accessible;
if (self->at_context == NULL)
self->at_context = gtk_at_context_create (self->role, accessible);
self->at_context = gtk_at_context_create (self->role,
accessible,
gdk_display_get_default ());
return self->at_context;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment