From 17262d1572c9e994927f1db798f9f0f2da1a39ef Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Tue, 19 Apr 2022 16:12:08 +0100 Subject: 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, -- cgit v1.2.1