Commit 8cdf4d30 authored by Colomban Wendling's avatar Colomban Wendling
Browse files

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 gtk#2186

[1] at-spi2-core#16
parent 057bcaea
......@@ -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);
......
......@@ -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 */
......@@ -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)
{
......
......@@ -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 */
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment