[gtk/a11y/atspi: 4/28] a11y: Add a display to GtkATContext




commit 8c18480092868bdd5f5460cbd3e74504b2879b88
Author: Emmanuele Bassi <ebassi gnome org>
Date:   Tue Sep 29 18:40:44 2020 +0100

    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.

 gtk/a11y/gtkatspicontext.c        | 45 ++++++++++++++++---------
 gtk/a11y/gtkatspicontextprivate.h |  5 +--
 gtk/gtkatcontext.c                | 69 ++++++++++++++++++++++++++++++++++-----
 gtk/gtkatcontext.h                |  3 +-
 gtk/gtkatcontextprivate.h         |  3 ++
 gtk/gtkwidget.c                   |  3 +-
 testsuite/a11y/accessible.c       |  4 ++-
 7 files changed, 102 insertions(+), 30 deletions(-)
---
diff --git a/gtk/a11y/gtkatspicontext.c b/gtk/a11y/gtkatspicontext.c
index 95fc342917..104458020b 100644
--- a/gtk/a11y/gtkatspicontext.c
+++ b/gtk/a11y/gtkatspicontext.c
@@ -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;
 }
diff --git a/gtk/a11y/gtkatspicontextprivate.h b/gtk/a11y/gtkatspicontextprivate.h
index 28205f1fbc..d7457af0ba 100644
--- a/gtk/a11y/gtkatspicontextprivate.h
+++ b/gtk/a11y/gtkatspicontextprivate.h
@@ -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
diff --git a/gtk/gtkatcontext.c b/gtk/gtkatcontext.c
index 4d86a2346d..9b586c26bb 100644
--- a/gtk/gtkatcontext.c
+++ b/gtk/gtkatcontext.c
@@ -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;
diff --git a/gtk/gtkatcontext.h b/gtk/gtkatcontext.h
index e6b742ffb0..2372f04b94 100644
--- a/gtk/gtkatcontext.h
+++ b/gtk/gtkatcontext.h
@@ -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
diff --git a/gtk/gtkatcontextprivate.h b/gtk/gtkatcontextprivate.h
index 2b916187fd..115a057cb7 100644
--- a/gtk/gtkatcontextprivate.h
+++ b/gtk/gtkatcontextprivate.h
@@ -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,
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 2ea7fb9c3a..b6489a284a 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -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;
diff --git a/testsuite/a11y/accessible.c b/testsuite/a11y/accessible.c
index b8daf9e182..b353d9e94e 100644
--- a/testsuite/a11y/accessible.c
+++ b/testsuite/a11y/accessible.c
@@ -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;
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]