[gtk/ebassi/issue-4825-backport] a11y: Defer object registration after root registration




commit e41a4ced8bc589cbbac68f82b4f45264aa3bac87
Author: Emmanuele Bassi <ebassi gnome org>
Date:   Tue Apr 19 16:12:08 2022 +0100

    a11y: Defer object registration after root registration
    
    The root accessible object is registered asynchronously, as it needs to
    call a method on the AT-SPI registry daemon. This means we need to defer
    registering the GtkAtSpiContext on the accessibility bus and in the
    cache until after the registration is complete.
    
    Fixes: #4825

 gtk/a11y/gtkatspicontext.c     | 32 +++++++++++++++++------------
 gtk/a11y/gtkatspiroot.c        | 46 ++++++++++++++++++++++++++++++++----------
 gtk/a11y/gtkatspirootprivate.h |  6 +++++-
 3 files changed, 59 insertions(+), 25 deletions(-)
---
diff --git a/gtk/a11y/gtkatspicontext.c b/gtk/a11y/gtkatspicontext.c
index 43d40ee257..7c49929aff 100644
--- a/gtk/a11y/gtkatspicontext.c
+++ b/gtk/a11y/gtkatspicontext.c
@@ -1418,7 +1418,7 @@ gtk_at_spi_context_unregister_object (GtkAtSpiContext *self)
   g_clear_pointer (&self->interfaces, g_variant_unref);
 }
 /* }}} */
-/* {{{ GObject boilerplate */ 
+/* {{{ GObject boilerplate */
 static void
 gtk_at_spi_context_finalize (GObject *gobject)
 {
@@ -1443,6 +1443,22 @@ gtk_at_spi_context_constructed (GObject *gobject)
 
 static const char *get_bus_address (GdkDisplay *display);
 
+static void
+register_object (GtkAtSpiRoot *root,
+                 GtkAtSpiContext *context)
+{
+  GtkAccessible *accessible = gtk_at_context_get_accessible (GTK_AT_CONTEXT (context));
+
+  gtk_atspi_connect_text_signals (accessible,
+                                  (GtkAtspiTextChangedCallback *)emit_text_changed,
+                                  (GtkAtspiTextSelectionCallback *)emit_text_selection_changed,
+                                  context);
+  gtk_atspi_connect_selection_signals (accessible,
+                                       (GtkAtspiSelectionCallback *)emit_selection_changed,
+                                       context);
+  gtk_at_spi_context_register_object (context);
+}
+
 static void
 gtk_at_spi_context_realize (GtkATContext *context)
 {
@@ -1489,11 +1505,10 @@ gtk_at_spi_context_realize (GtkATContext *context)
   if (self->connection == NULL)
     return;
 
-  GtkAccessible *accessible = gtk_at_context_get_accessible (context);
-
 #ifdef G_ENABLE_DEBUG
   if (GTK_DEBUG_CHECK (A11Y))
     {
+      GtkAccessible *accessible = gtk_at_context_get_accessible (context);
       GtkAccessibleRole role = gtk_at_context_get_accessible_role (context);
       char *role_name = g_enum_to_string (GTK_TYPE_ACCESSIBLE_ROLE, role);
       g_message ("Realizing ATSPI context “%s” for accessible “%s”, with role: “%s”",
@@ -1504,16 +1519,7 @@ gtk_at_spi_context_realize (GtkATContext *context)
     }
 #endif
 
-  gtk_atspi_connect_text_signals (accessible,
-                                  (GtkAtspiTextChangedCallback *)emit_text_changed,
-                                  (GtkAtspiTextSelectionCallback *)emit_text_selection_changed,
-                                  self);
-  gtk_atspi_connect_selection_signals (accessible,
-                                       (GtkAtspiSelectionCallback *)emit_selection_changed,
-                                       self);
-  gtk_at_spi_context_register_object (self);
-
-  gtk_at_spi_root_queue_register (self->root, self);
+  gtk_at_spi_root_queue_register (self->root, self, register_object);
 }
 
 static void
diff --git a/gtk/a11y/gtkatspiroot.c b/gtk/a11y/gtkatspiroot.c
index 88a366c05f..bffc632c18 100644
--- a/gtk/a11y/gtkatspiroot.c
+++ b/gtk/a11y/gtkatspiroot.c
@@ -474,16 +474,24 @@ gtk_at_spi_root_child_changed (GtkAtSpiRoot             *self,
                                     window_ref);
 }
 
+typedef struct {
+  GtkAtSpiRoot *root;
+  GtkAtSpiRootRegisterFunc register_func;
+} RegistrationData;
+
 static void
 on_registration_reply (GObject      *gobject,
                        GAsyncResult *result,
                        gpointer      user_data)
 {
-  GtkAtSpiRoot *self = user_data;
+  RegistrationData *data = user_data;
+  GtkAtSpiRoot *self = data->root;
 
   GError *error = NULL;
   GVariant *reply = g_dbus_connection_call_finish (G_DBUS_CONNECTION (gobject), result, &error);
 
+  self->register_id = 0;
+
   if (error != NULL)
     {
       g_critical ("Unable to register the application: %s", error->message);
@@ -509,19 +517,27 @@ on_registration_reply (GObject      *gobject,
   /* Drain the list of queued GtkAtSpiContexts, and add them to the cache */
   if (self->queued_contexts != NULL)
     {
-      for (GList *l = self->queued_contexts; l != NULL; l = l->next)
-        gtk_at_spi_cache_add_context (self->cache, l->data);
+      for (GList *l = g_list_reverse (self->queued_contexts); l != NULL; l = l->next)
+        {
+          if (data->register_func != NULL)
+            data->register_func (self, l->data);
+
+          gtk_at_spi_cache_add_context (self->cache, l->data);
+        }
 
       g_clear_pointer (&self->queued_contexts, g_list_free);
     }
 
   self->toplevels = gtk_window_get_toplevels ();
+
+  g_free (data);
 }
 
 static gboolean
-root_register (gpointer data)
+root_register (gpointer user_data)
 {
-  GtkAtSpiRoot *self = data;
+  RegistrationData *data = user_data;
+  GtkAtSpiRoot *self = data->root;
   const char *unique_name;
 
   /* Register the root element; every application has a single root, so we only
@@ -577,9 +593,7 @@ root_register (gpointer data)
                           G_DBUS_CALL_FLAGS_NONE, -1,
                           NULL,
                           on_registration_reply,
-                          self);
-
-  self->register_id = 0;
+                          data);
 
   return G_SOURCE_REMOVE;
 }
@@ -587,18 +601,24 @@ root_register (gpointer data)
 /*< private >
  * gtk_at_spi_root_queue_register:
  * @self: a `GtkAtSpiRoot`
+ * @context: the AtSpi context to register
+ * @func: the function to call when the root has been registered
  *
  * Queues the registration of the root object on the AT-SPI bus.
  */
 void
-gtk_at_spi_root_queue_register (GtkAtSpiRoot    *self,
-                                GtkAtSpiContext *context)
+gtk_at_spi_root_queue_register (GtkAtSpiRoot             *self,
+                                GtkAtSpiContext          *context,
+                                GtkAtSpiRootRegisterFunc  func)
 {
   /* The cache is available if the root has finished registering itself; if we
    * are still waiting for the registration to finish, add the context to a queue
    */
   if (self->cache != NULL)
     {
+      if (func != NULL)
+        func (self, context);
+
       gtk_at_spi_cache_add_context (self->cache, context);
       return;
     }
@@ -612,7 +632,11 @@ gtk_at_spi_root_queue_register (GtkAtSpiRoot    *self,
   if (self->register_id != 0)
     return;
 
-  self->register_id = g_idle_add (root_register, self);
+  RegistrationData *data = g_new (RegistrationData, 1);
+  data->root = self;
+  data->register_func = func;
+
+  self->register_id = g_idle_add (root_register, data);
   gdk_source_set_static_name_by_id (self->register_id, "[gtk] ATSPI root registration");
 }
 
diff --git a/gtk/a11y/gtkatspirootprivate.h b/gtk/a11y/gtkatspirootprivate.h
index d8d42c0e26..7b626fc28e 100644
--- a/gtk/a11y/gtkatspirootprivate.h
+++ b/gtk/a11y/gtkatspirootprivate.h
@@ -34,9 +34,13 @@ G_DECLARE_FINAL_TYPE (GtkAtSpiRoot, gtk_at_spi_root, GTK, AT_SPI_ROOT, GObject)
 GtkAtSpiRoot *
 gtk_at_spi_root_new (const char *bus_address);
 
+typedef void (* GtkAtSpiRootRegisterFunc) (GtkAtSpiRoot *root,
+                                           GtkAtSpiContext *context);
+
 void
 gtk_at_spi_root_queue_register (GtkAtSpiRoot *self,
-                                GtkAtSpiContext *context);
+                                GtkAtSpiContext *context,
+                                GtkAtSpiRootRegisterFunc func);
 
 void
 gtk_at_spi_root_unregister (GtkAtSpiRoot *self,


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