[at-spi2-atk: 1/2] adaptor: Fix missing events at startup



commit 8cdf4d30c74e475146a47f0bb1c9992f4a3ac372
Author: Colomban Wendling <cwendling hypra fr>
Date:   Tue Dec 3 17:09:55 2019 +0100

    adaptor: Fix missing events at startup
    
    We need to register the application before anything else happens,
    otherwise we might miss some events sent before registration.
    
    As we want to register only from the main loop to avoid registering
    an application that won't respond to calls [1], we used an idle
    callback; but it doesn't run early enough in all cases, e.g. in
    Firefox.  So, switch to a high-priority 0-timeout so that it should be
    dispatched among the first ones in the next main loop iteration, then
    being run before other callbacks that might generate events.
    
    Fixes https://gitlab.gnome.org/GNOME/gtk/issues/2186
    
    [1] https://gitlab.gnome.org/GNOME/at-spi2-core/issues/16

 atk-adaptor/bridge.c | 42 +++++++++++++++++++++++++++++++-----------
 atk-adaptor/bridge.h |  3 ++-
 atk-adaptor/event.c  | 23 ++++++++++++++++++-----
 atk-adaptor/event.h  |  2 ++
 4 files changed, 53 insertions(+), 17 deletions(-)
---
diff --git a/atk-adaptor/bridge.c b/atk-adaptor/bridge.c
index 06407f4..8579185 100644
--- a/atk-adaptor/bridge.c
+++ b/atk-adaptor/bridge.c
@@ -403,8 +403,8 @@ register_reply (DBusPendingCall *pending, void *user_data)
     get_registered_event_listeners (spi_global_app_data);
 }
 
-gboolean
-_atk_bridge_register_application (gpointer data)
+static gboolean
+register_application (gpointer data)
 {
   SpiBridge * app = data;
   DBusMessage *message;
@@ -439,6 +439,31 @@ _atk_bridge_register_application (gpointer data)
   return FALSE;
 }
 
+void
+_atk_bridge_schedule_application_registration (SpiBridge *app)
+{
+  /* We need the callback to be called first thing, before any other of ours
+   * (and possibly of client apps), so use a high priority and a short timeout
+   * to try and be called first by the main loop. */
+  if (!app->registration_pending)
+    app->registration_pending = spi_timeout_add_full (G_PRIORITY_HIGH, 0,
+                                                      register_application,
+                                                      app, NULL);
+}
+
+gboolean
+_atk_bridge_remove_pending_application_registration (SpiBridge *app)
+{
+  if (app->registration_pending)
+  {
+    g_source_remove (app->registration_pending);
+    app->registration_pending = 0;
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
 /*---------------------------------------------------------------------------*/
 
 static void
@@ -470,12 +495,8 @@ deregister_application (SpiBridge * app)
   DBusMessageIter iter;
   const char *uname;
 
-  if (spi_global_app_data->registration_pending)
-  {
-    g_source_remove (spi_global_app_data->registration_pending);
-    spi_global_app_data->registration_pending = 0;
+  if (_atk_bridge_remove_pending_application_registration (spi_global_app_data))
     return;
-  }
 
   message = dbus_message_new_method_call (SPI_DBUS_NAME_REGISTRY,
                                           ATSPI_DBUS_PATH_REGISTRY,
@@ -850,7 +871,7 @@ signal_filter (DBusConnection *bus, DBusMessage *message, void *user_data)
             {
               if (registry_lost && !old[0])
                 {
-                  _atk_bridge_register_application (spi_global_app_data);
+                  register_application (spi_global_app_data);
                   registry_lost = FALSE;
                 }
               else if (!new[0])
@@ -1105,9 +1126,8 @@ atk_bridge_adaptor_init (gint * argc, gchar ** argv[])
                               NULL);
 
   /* Register this app by sending a signal out to AT-SPI registry daemon */
-  if (!atspi_no_register && (!root || !ATK_IS_PLUG (root)) &&
-      !spi_global_app_data->registration_pending)
-    spi_global_app_data->registration_pending = spi_idle_add (_atk_bridge_register_application, 
spi_global_app_data);
+  if (!atspi_no_register && (!root || !ATK_IS_PLUG (root)))
+    _atk_bridge_schedule_application_registration (spi_global_app_data);
   else
     get_registered_event_listeners (spi_global_app_data);
 
diff --git a/atk-adaptor/bridge.h b/atk-adaptor/bridge.h
index c4ceca1..9fc10fd 100644
--- a/atk-adaptor/bridge.h
+++ b/atk-adaptor/bridge.h
@@ -94,7 +94,8 @@ DRoutePropertyFunction _atk_bridge_find_property_func (const char *property,
 
 GType _atk_bridge_type_from_iface (const char *iface);
 
-gboolean _atk_bridge_register_application (gpointer data);
+void _atk_bridge_schedule_application_registration (SpiBridge *app);
+gboolean _atk_bridge_remove_pending_application_registration (SpiBridge *app);
 G_END_DECLS
 
 #endif /* BRIDGE_H */
diff --git a/atk-adaptor/event.c b/atk-adaptor/event.c
index e527d45..bd38eef 100644
--- a/atk-adaptor/event.c
+++ b/atk-adaptor/event.c
@@ -73,11 +73,8 @@ switch_main_context (GMainContext *cnx)
   for (list = spi_global_app_data->direct_connections; list; list = list->next)
     atspi_dbus_connection_setup_with_g_main (list->data, cnx);
 
-  if (spi_global_app_data->registration_pending)
-  {
-    g_source_remove (spi_global_app_data->registration_pending);
-    spi_global_app_data->registration_pending = spi_idle_add (_atk_bridge_register_application, 
spi_global_app_data);
-  }
+  if (_atk_bridge_remove_pending_application_registration (spi_global_app_data))
+    _atk_bridge_schedule_application_registration (spi_global_app_data);
 }
 
 guint
@@ -108,6 +105,22 @@ spi_timeout_add_seconds (gint interval, GSourceFunc function, gpointer    data)
   return id;
 }
 
+guint
+spi_timeout_add_full (gint priority, guint interval, GSourceFunc function,
+                      gpointer data, GDestroyNotify notify)
+{
+  GSource *source;
+  guint id;
+
+  source = g_timeout_source_new (interval);
+  g_source_set_priority (source, priority);
+  g_source_set_callback (source, function, data, notify);
+  id = g_source_attach (source, spi_context);
+  g_source_unref (source);
+
+  return id;
+}
+
 static void
 set_reply (DBusPendingCall * pending, void *user_data)
 {
diff --git a/atk-adaptor/event.h b/atk-adaptor/event.h
index 8b3b30f..fe4aad0 100644
--- a/atk-adaptor/event.h
+++ b/atk-adaptor/event.h
@@ -34,4 +34,6 @@ gboolean spi_event_is_subtype (gchar **needle, gchar **haystack);
 extern GMainContext *spi_context;
 guint spi_idle_add(GSourceFunc    function, gpointer       data);
 guint spi_timeout_add_seconds (gint interval, GSourceFunc function, gpointer    data);
+guint spi_timeout_add_full (gint priority, guint interval, GSourceFunc function,
+                            gpointer data, GDestroyNotify notify);
 #endif /* EVENT_H */


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