[at-spi2-atk] Only register for events when something is listening



commit d0f7dd49eebedc8c3993a116411f5a8320965968
Author: Mike Gorse <mgorse novell com>
Date:   Tue Jun 21 17:16:07 2011 -0500

    Only register for events when something is listening
    
    Track whether clients are listening, based on calls to GetItems and
    event listener registrations, and disable event handlers if no clients
    are listening.  Note that this currently handles event listeners in bulk
    and could be refined to only connect to individual signals that are
    being listened to.

 atk-adaptor/adaptors/application-adaptor.c |    3 +
 atk-adaptor/adaptors/cache-adaptor.c       |    3 +
 atk-adaptor/bridge.c                       |   75 ++++++++++++++++++++++++++-
 atk-adaptor/bridge.h                       |    3 +
 atk-adaptor/event.c                        |   18 +++++--
 5 files changed, 95 insertions(+), 7 deletions(-)
---
diff --git a/atk-adaptor/adaptors/application-adaptor.c b/atk-adaptor/adaptors/application-adaptor.c
index 897ed55..c686c31 100644
--- a/atk-adaptor/adaptors/application-adaptor.c
+++ b/atk-adaptor/adaptors/application-adaptor.c
@@ -101,6 +101,9 @@ impl_get_app_bus(DBusConnection *bus, DBusMessage *msg, void *data)
 {
 DBusMessage *reply;
 
+  if (bus == spi_global_app_data->bus)
+    spi_atk_add_client (dbus_message_get_sender (msg));
+
 reply = dbus_message_new_method_return(msg);
 if (reply)
     {
diff --git a/atk-adaptor/adaptors/cache-adaptor.c b/atk-adaptor/adaptors/cache-adaptor.c
index 3b6b28c..0aff2bd 100644
--- a/atk-adaptor/adaptors/cache-adaptor.c
+++ b/atk-adaptor/adaptors/cache-adaptor.c
@@ -291,6 +291,9 @@ impl_GetItems (DBusConnection * bus, DBusMessage * message, void *user_data)
   DBusMessage *reply;
   DBusMessageIter iter, iter_array;
 
+  if (bus == spi_global_app_data->bus)
+    spi_atk_add_client (dbus_message_get_sender (message));
+
   reply = dbus_message_new_method_return (message);
 
   dbus_message_iter_init_append (reply, &iter);
diff --git a/atk-adaptor/bridge.c b/atk-adaptor/bridge.c
index 51b12bc..6aacd12 100644
--- a/atk-adaptor/bridge.c
+++ b/atk-adaptor/bridge.c
@@ -117,6 +117,7 @@ add_event (const char *bus_name, const char *event)
   gchar **data;
   GList *new_list;
 
+  spi_atk_add_client (bus_name);
   evdata = (event_data *) g_malloc (sizeof (*evdata));
   if (!evdata)
     return;
@@ -133,6 +134,8 @@ add_event (const char *bus_name, const char *event)
     spi_global_app_data->events = new_list;
 }
 
+static GSList *clients = NULL;
+
 static void
 get_registered_event_listeners (SpiBridge *app)
 {
@@ -143,18 +146,21 @@ get_registered_event_listeners (SpiBridge *app)
                                          SPI_DBUS_PATH_REGISTRY,
                                          SPI_DBUS_INTERFACE_REGISTRY,
                                          "GetRegisteredEvents");
-  spi_global_app_data->events_initialized = TRUE;
   if (!message)
     return;
 
   reply = dbus_connection_send_with_reply_and_block (app->bus, message, 5000, NULL);
   dbus_message_unref (message);
   if (!reply)
-    return;
+    {
+      spi_global_app_data->events_initialized = TRUE;
+      return;
+    }
   if (strcmp (dbus_message_get_signature (reply), "a(ss)") != 0)
     {
-      /* TODO: Add a warning when it's okay to add strings */
+      g_warning ("atk-bridge: GetRegisteredEvents returned message with unknown signature");
       dbus_message_unref (reply);
+      spi_global_app_data->events_initialized = TRUE;
       return;
     }
   dbus_message_iter_init (reply, &iter);
@@ -170,6 +176,10 @@ get_registered_event_listeners (SpiBridge *app)
       dbus_message_iter_next (&iter_array);
     }
   dbus_message_unref (reply);
+
+  if (!clients)
+    spi_atk_deregister_event_listeners ();
+  spi_global_app_data->events_initialized = TRUE;
 }
 
 static void
@@ -628,6 +638,23 @@ signal_filter (DBusConnection *bus, DBusMessage *message, void *user_data)
       else
         result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
     }
+
+  if (!g_strcmp0(interface, DBUS_INTERFACE_DBUS) &&
+      !g_strcmp0(member, "NameOwnerChanged"))
+    {
+      char *name, *old, *new;
+      result = DBUS_HANDLER_RESULT_HANDLED;
+      if (dbus_message_get_args (message, NULL,
+                                 DBUS_TYPE_STRING, &name,
+                                 DBUS_TYPE_STRING, &old,
+                                 DBUS_TYPE_STRING, &new,
+                                 DBUS_TYPE_INVALID))
+        {
+          if (*old != '\0' && *new == '\0')
+              spi_atk_remove_client (old);
+        }
+    }
+
   return result;
 }
 
@@ -828,4 +855,46 @@ gnome_accessibility_module_shutdown (void)
   exit_func ();
 }
 
+static gchar *name_match_tmpl =
+       "type='signal', interface='org.freedesktop.DBus', member='NameOwnerChanged', arg0='%s'";
+
+void
+spi_atk_add_client (const char *bus_name)
+{
+  GSList *l;
+  gchar *match;
+
+  for (l = clients; l; l = l->next)
+  {
+    if (!g_strcmp0 (l->data, bus_name))
+      return;
+  }
+  if (!clients && spi_global_app_data->events_initialized)
+    spi_atk_register_event_listeners ();
+  clients = g_slist_append (clients, g_strdup (bus_name));
+  match = g_strdup_printf (name_match_tmpl, bus_name);
+  dbus_bus_add_match (spi_global_app_data->bus, match, NULL);
+  g_free (match);
+}
+
+void
+spi_atk_remove_client (const char *bus_name)
+{
+  GSList *l;
+
+  for (l = clients; l; l = l->next)
+  {
+    if (!g_strcmp0 (l->data, bus_name))
+    {
+      gchar *match = g_strdup_printf (name_match_tmpl, l->data);
+      dbus_bus_remove_match (spi_global_app_data->bus, match, NULL);
+  g_free (match);
+      g_free (l->data);
+      clients = g_slist_remove_link (clients, l);
+      if (!clients)
+        spi_atk_deregister_event_listeners ();
+    }
+  }
+}
+
 /*END------------------------------------------------------------------------*/
diff --git a/atk-adaptor/bridge.h b/atk-adaptor/bridge.h
index 1a3ebee..c24183e 100644
--- a/atk-adaptor/bridge.h
+++ b/atk-adaptor/bridge.h
@@ -66,6 +66,9 @@ char *app_bus_addr;
 
 extern SpiBridge *spi_global_app_data;
 
+void spi_atk_add_client (const char *bus_name);
+void spi_atk_remove_client (const char *bus_name);
+
 G_END_DECLS
 
 #endif /* BRIDGE_H */
diff --git a/atk-adaptor/event.c b/atk-adaptor/event.c
index a616879..e882edf 100644
--- a/atk-adaptor/event.c
+++ b/atk-adaptor/event.c
@@ -1096,6 +1096,12 @@ spi_atk_register_event_listeners (void)
   g_object_unref (G_OBJECT (bo));
   g_object_unref (ao);
 
+  if (listener_ids)
+  {
+    g_warning ("atk_bridge: spi_atk-register_event_listeners called multiple times");
+    return;
+  }
+
   /* Register for focus event notifications, and register app with central registry  */
   listener_ids = g_array_sized_new (FALSE, TRUE, sizeof (guint), 16);
 
@@ -1149,10 +1155,7 @@ spi_atk_register_event_listeners (void)
                        "Gtk:AtkTable:column-reordered");
   add_signal_listener (generic_event_listener, "Gtk:AtkTable:column-deleted");
   add_signal_listener (generic_event_listener, "Gtk:AtkTable:model-changed");
-
-  /* Children signal listeners */
-  atk_add_global_event_listener (children_changed_event_listener,
-                                 "Gtk:AtkObject:children-changed");
+  add_signal_listener (children_changed_event_listener, "Gtk:AtkObject:children-changed");
 
 #if 0
   g_signal_connect (G_OBJECT (spi_global_app_data->root),
@@ -1187,15 +1190,22 @@ spi_atk_deregister_event_listeners (void)
   listener_ids = NULL;
 
   if (atk_bridge_focus_tracker_id)
+  {
     atk_remove_focus_tracker (atk_bridge_focus_tracker_id);
+    atk_bridge_focus_tracker_id = 0;
+  }
 
   for (i = 0; ids && i < ids->len; i++)
     {
       atk_remove_global_event_listener (g_array_index (ids, guint, i));
     }
+  g_array_free (ids, TRUE);
 
   if (atk_bridge_key_event_listener_id)
+  {
     atk_remove_key_event_listener (atk_bridge_key_event_listener_id);
+    atk_bridge_key_event_listener_id = 0;
+  }
 }
 
 /*---------------------------------------------------------------------------*/



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