summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmmanuele Bassi <ebassi@gnome.org>2022-04-19 16:12:08 +0100
committerEmmanuele Bassi <ebassi@gnome.org>2022-04-19 16:35:27 +0100
commit17262d1572c9e994927f1db798f9f0f2da1a39ef (patch)
tree2bc05a293a85c33675fd97b8143beb03cdd77dc0
parent4dcd02e85315f487310e2e01fe9412706a77dc35 (diff)
downloadgtk+-17262d1572c9e994927f1db798f9f0f2da1a39ef.tar.gz
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
-rw-r--r--gtk/a11y/gtkatspicontext.c32
-rw-r--r--gtk/a11y/gtkatspiroot.c46
-rw-r--r--gtk/a11y/gtkatspirootprivate.h6
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)
{
@@ -1444,6 +1444,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)
{
GtkAtSpiContext *self = GTK_AT_SPI_CONTEXT (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,