Add watches for disconnected applications and clients; fix related issues
authorMike Gorse <mgorse@boston.site>
Thu, 12 Jun 2008 15:59:46 +0000 (11:59 -0400)
committerMike Gorse <mgorse@boston.site>
Thu, 12 Jun 2008 15:59:46 +0000 (11:59 -0400)
path -> bus_name in some variables

registryd/desktop.c
registryd/desktop.h
registryd/deviceeventcontroller.c
registryd/deviceeventcontroller.h
registryd/registry.c

index 94f31f5..9d0ec95 100644 (file)
@@ -162,7 +162,7 @@ spi_desktop_dispose (GObject *object)
     {
       SpiDesktopApplication *app = desktop->applications->data;
       g_assert (app != NULL);
-      spi_desktop_remove_application (desktop, app->path);
+      spi_desktop_remove_application (desktop, app->bus_name);
     }
 
   G_OBJECT_CLASS (parent_class)->dispose (object); 
@@ -191,7 +191,7 @@ impl_desktop_get_child_at_index (DBusConnection *bus, DBusMessage *message, void
   DBusError error;
   dbus_int32_t index;
   SpiDesktopApplication *app;
-  const char *path;
+  const char *bus_name;
   DBusMessage *reply;
 
   dbus_error_init (&error);
@@ -200,12 +200,12 @@ impl_desktop_get_child_at_index (DBusConnection *bus, DBusMessage *message, void
     return spi_dbus_general_error (message);
   }
   app = g_list_nth_data (desktop->applications, index);
-  path = (app? app->path: SPI_DBUS_PATH_NULL);
+  bus_name = (app? app->bus_name: "");
 
   reply = dbus_message_new_method_return (message);
   if (reply)
     {
-      dbus_message_append_args (reply, DBUS_TYPE_STRING, &path, DBUS_TYPE_INVALID);
+      dbus_message_append_args (reply, DBUS_TYPE_STRING, &bus_name, DBUS_TYPE_INVALID);
     }
 
   return reply;
@@ -219,7 +219,7 @@ impl_desktop_get_children (DBusConnection *bus, DBusMessage *message, void *user
   gint count;
   gint i;
   SpiDesktopApplication *app;
-  const char *path;
+  const char *bus_name;
   DBusMessage *reply;
   DBusMessageIter iter, iter_array;
 
@@ -234,8 +234,8 @@ impl_desktop_get_children (DBusConnection *bus, DBusMessage *message, void *user
   for (i = 0; i < count; i++)
   {
     app = g_list_nth_data (desktop->applications, i);
-    path = (app? app->path: SPI_DBUS_PATH_NULL);
-    dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_STRING, &path);
+    bus_name = (app? app->bus_name: "");
+    dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_STRING, &bus_name);
   }
   if (!dbus_message_iter_close_container (&iter, &iter_array))
   {
@@ -295,7 +295,7 @@ abnormal_application_termination (gpointer object, SpiDesktopApplication *app)
   g_return_if_fail (SPI_IS_DESKTOP (app->desktop));
 
   if (!exiting)
-    spi_desktop_remove_application (app->desktop, app->path);
+    spi_desktop_remove_application (app->desktop, app->bus_name);
 }
 
 void
@@ -306,11 +306,9 @@ spi_desktop_add_application (SpiDesktop *desktop,
 
   g_return_if_fail (SPI_IS_DESKTOP (desktop));
 
-  spi_desktop_remove_application (desktop, application);
-
   app = g_new (SpiDesktopApplication, 1);
   app->desktop = desktop;
-  app->path = application;
+  app->bus_name = application;
 
       desktop->applications = g_list_append (desktop->applications, app);
 
@@ -323,12 +321,12 @@ spi_desktop_add_application (SpiDesktop *desktop,
 
 void
 spi_desktop_remove_application (SpiDesktop *desktop,
-                               const char *path)
+                               const char *bus_name)
 {
   guint idx;
   GList *l;
 
-  g_return_if_fail (path != NULL);
+  g_return_if_fail (  bus_name != NULL);
   g_return_if_fail (SPI_IS_DESKTOP (desktop));
 
   idx = 0;
@@ -336,24 +334,22 @@ spi_desktop_remove_application (SpiDesktop *desktop,
     {
       SpiDesktopApplication *app = (SpiDesktopApplication *) l->data;
 
-      if (!strcmp(app->path, path))
+      if (!strcmp(app->bus_name, bus_name))
         {
          break;
        }
       idx++;
     }
 
-  if (l)
-    {
-      SpiDesktopApplication *app = (SpiDesktopApplication *) l->data;
+  if (!l) return;
 
-      desktop->applications = g_list_delete_link (desktop->applications, l);
+  g_signal_emit (G_OBJECT (desktop), spi_desktop_signals[APPLICATION_REMOVED], 0, idx);
 
-      // TODO: unlisten for broken app, if appropriate
-      g_free (app);
-      
-      g_signal_emit (G_OBJECT (desktop), spi_desktop_signals[APPLICATION_REMOVED], 0, idx);
-    }
+  SpiDesktopApplication *app = (SpiDesktopApplication *) l->data;
+
+  desktop->applications = g_list_delete_link (desktop->applications, l);
+
+  g_free (app);
 }
 
 static DRouteMethod methods[] =
index a2ecb47..3a0e401 100644 (file)
@@ -51,13 +51,13 @@ typedef struct {
 GType       spi_desktop_get_type           (void);
 SpiDesktop *spi_desktop_new                (void);
 void        spi_desktop_add_application    (SpiDesktop *desktop,
-                                           const char *app_path);
+                                           const char *bus_name);
 void        spi_desktop_remove_application (SpiDesktop *desktop,
-                                           const char *app_path);
+                                           const char *bus_name);
 
 typedef struct {
        SpiDesktop *desktop;
-       const char *path;
+       const char *bus_name;
 } SpiDesktopApplication;
 
 G_END_DECLS
index 2af73ae..42b83dd 100644 (file)
@@ -107,7 +107,7 @@ typedef struct {
 } DEControllerGrabMask;
 
 typedef struct {
-  char *app_path;
+  char *bus_name;
   char *path;
   SpiDeviceTypeCategory type;
   gulong types;
@@ -649,7 +649,7 @@ spi_dec_translate_mask (Accessibility_ControllerEventMask mask)
 }
 
 static DEControllerKeyListener *
-spi_dec_key_listener_new (const char *app_path,
+spi_dec_key_listener_new (const char *bus_name,
                          const char *path,
                          GSList *keys,
                          const Accessibility_ControllerEventMask mask,
@@ -657,7 +657,7 @@ spi_dec_key_listener_new (const char *app_path,
                          const Accessibility_EventListenerMode  *mode)
 {
   DEControllerKeyListener *key_listener = g_new0 (DEControllerKeyListener, 1);
-  key_listener->listener.app_path = g_strdup(app_path);
+  key_listener->listener.bus_name = g_strdup(bus_name);
   key_listener->listener.path = g_strdup(path);
   key_listener->listener.type = SPI_DEVICE_TYPE_KBD;
   key_listener->keys = keys;
@@ -683,12 +683,12 @@ spi_dec_key_listener_new (const char *app_path,
 }
 
 static DEControllerListener *
-spi_dec_listener_new (const char *app_path,
+spi_dec_listener_new (const char *bus_name,
                      const char *path,
                      dbus_uint32_t types)
 {
   DEControllerListener *listener = g_new0 (DEControllerListener, 1);
-  listener->app_path = g_strdup(app_path);
+  listener->bus_name = g_strdup(bus_name);
   listener->path = g_strdup(path);
   listener->type = SPI_DEVICE_TYPE_MOUSE;
   listener->types = types;
@@ -699,7 +699,7 @@ static DEControllerListener *
 spi_listener_clone (DEControllerListener *listener)
 {
   DEControllerListener *clone = g_new0 (DEControllerListener, 1);
-  clone->app_path = g_strdup (listener->app_path);
+  clone->bus_name = g_strdup (listener->bus_name);
   clone->path = g_strdup (listener->path);
   clone->type = listener->type;
   clone->types = listener->types;
@@ -730,7 +730,7 @@ static DEControllerKeyListener *
 spi_key_listener_clone (DEControllerKeyListener *key_listener)
 {
   DEControllerKeyListener *clone = g_new0 (DEControllerKeyListener, 1);
-  clone->listener.app_path = g_strdup (key_listener->listener.app_path);
+  clone->listener.bus_name = g_strdup (key_listener->listener.bus_name);
   clone->listener.path = g_strdup (key_listener->listener.path);
   clone->listener.type = SPI_DEVICE_TYPE_KBD;
   clone->keys = keylist_clone (key_listener->keys);
@@ -777,14 +777,14 @@ static void
 spi_listener_clone_free (DEControllerListener *clone)
 {
   g_free (clone->path);
-  g_free (clone->app_path);
+  g_free (clone->bus_name);
   g_free (clone);
 }
 
 static void
 spi_dec_listener_free (DEControllerListener    *listener)
 {
-  g_free (listener->app_path);
+  g_free (listener->bus_name);
   g_free (listener->path);
   if (listener->type == SPI_DEVICE_TYPE_KBD) 
     spi_key_listener_data_free ((DEControllerKeyListener *) listener);
@@ -917,6 +917,7 @@ spi_controller_register_device_listener (SpiDEController      *controller,
 
       controller->key_listeners = g_list_prepend (controller->key_listeners,
                                                  key_listener);
+      spi_dbus_add_disconnect_match (controller->registry->droute.bus, key_listener->listener.bus_name);
       if (key_listener->mode->global)
         {
          return spi_controller_register_global_keygrabs (controller, key_listener);    
@@ -926,6 +927,7 @@ spi_controller_register_device_listener (SpiDEController      *controller,
       break;
   case SPI_DEVICE_TYPE_MOUSE:
       controller->mouse_listeners = g_list_prepend (controller->mouse_listeners, listener);
+      spi_dbus_add_disconnect_match (controller->registry->droute.bus, listener->bus_name);
       break;
   default:
       DBG (1, g_warning ("listener registration for unknown device type.\n"));
@@ -936,7 +938,7 @@ spi_controller_register_device_listener (SpiDEController      *controller,
 
 static gboolean Accessibility_DeviceEventListener_notifyEvent(SpiRegistry *registry, DEControllerListener *listener, const Accessibility_DeviceEvent *key_event)
 {
-  DBusMessage *message = dbus_message_new_method_call(listener->app_path, listener->path, "org.freedesktop.atspi.Registry", "notifyEvent");
+  DBusMessage *message = dbus_message_new_method_call(listener->bus_name, listener->path, "org.freedesktop.atspi.Registry", "notifyEvent");
   DBusError error;
   dbus_bool_t consumed = FALSE;
 
@@ -1874,10 +1876,11 @@ remove_listener_cb (GList * const *list,
   DEControllerListener  *listener = (*list)->data;
   RemoveListenerClosure *ctx = user_data;
 
-  if (!strcmp(ctx->listener->app_path, listener->app_path) &&
+  if (!strcmp(ctx->listener->bus_name, listener->bus_name) &&
       !strcmp(ctx->listener->path, listener->path))
     {
       spi_re_entrant_list_delete_link (list);
+      spi_dbus_remove_disconnect_match (ctx->bus, listener->bus_name);
       spi_dec_listener_free (listener);
     }
 
@@ -1891,7 +1894,7 @@ copy_key_listener_cb (GList * const *list,
   DEControllerKeyListener  *key_listener = (*list)->data;
   RemoveListenerClosure    *ctx = user_data;
 
-  if (!strcmp(ctx->listener->app_path, key_listener->listener.app_path) &&
+  if (!strcmp(ctx->listener->bus_name, key_listener->listener.bus_name) &&
       !strcmp(ctx->listener->path, key_listener->listener.path))
     {
       /* TODO: FIXME aggregate keys in case the listener is registered twice */
@@ -1940,6 +1943,33 @@ spi_deregister_controller_key_listener (SpiDEController            *controller,
 
 }
 
+void
+spi_remove_device_listeners (SpiDEController *controller, const char *bus_name)
+{
+  GList *l, *tmp;
+
+  for (l = controller->mouse_listeners; l; l = tmp)
+  {
+    DEControllerListener *listener = l->data;
+    tmp = l->next;
+    if (!strcmp (listener->bus_name, bus_name))
+    {
+printf("Removing mouse listener %s %s\n", listener->bus_name, listener->path);
+      spi_controller_deregister_device_listener (controller, listener);
+    }
+  }
+  for (l = controller->key_listeners; l; l = tmp)
+  {
+    DEControllerKeyListener *key_listener = l->data;
+    tmp = l->next;
+    if (!strcmp (key_listener->listener.bus_name, bus_name))
+    {
+printf("Removing key listener: %s %s\n", key_listener->listener.bus_name, key_listener->listener.path);
+      spi_deregister_controller_key_listener (controller, key_listener);
+    }
+  }
+}
+
 /*
  * DBus Accessibility::DEController::deregisterKeystrokeListener
  *     method implementation
index 3fa5c8e..df8288b 100644 (file)
@@ -57,6 +57,8 @@ typedef struct {
 GType            spi_device_event_controller_get_type (void);
 SpiDEController *spi_device_event_controller_new      (SpiRegistry *registry);
 
+void spi_remove_device_listeners (SpiDEController *controller, const char *bus_name);
+
 G_END_DECLS
 
 #endif /* DEVICEEVENTCONTROLLER_H_ */
index 25d0ace..7316a05 100644 (file)
@@ -86,7 +86,7 @@ desktop_add_application (SpiDesktop *desktop,
   SpiRegistry *registry = SPI_REGISTRY (data);
   const SpiDesktopApplication *app = g_list_nth_data(desktop->applications, index);
   
-  emit(registry, "ApplicationAdd", DBUS_TYPE_UINT32, &index, DBUS_TYPE_STRING, &app->path, DBUS_TYPE_INVALID);
+  emit(registry, "ApplicationAdd", DBUS_TYPE_UINT32, &index, DBUS_TYPE_STRING, &app->bus_name, DBUS_TYPE_INVALID);
 }
 
 
@@ -96,9 +96,10 @@ desktop_remove_application (SpiDesktop *desktop,
                            guint index, gpointer data)
 {
   SpiRegistry *registry = SPI_REGISTRY (data);
-  const char *name = g_list_nth_data(desktop->applications, index);
+  SpiDesktopApplication *app = g_list_nth_data(desktop->applications, index);
   
-  emit(registry, "ApplicationRemove", DBUS_TYPE_UINT32, &index, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID);
+  spi_dbus_remove_disconnect_match (registry->droute.bus, app->bus_name);
+  emit(registry, "ApplicationRemove", DBUS_TYPE_UINT32, &index, DBUS_TYPE_STRING, &app->bus_name, DBUS_TYPE_INVALID);
 }
 
 
@@ -130,6 +131,8 @@ impl_accessibility_registry_register_application (DBusConnection *bus, DBusMessa
 #endif
   spi_desktop_add_application (registry->desktop, application);
 
+  spi_dbus_add_disconnect_match (registry->droute.bus, application);
+
   /*
    * TODO: change the implementation below to a WM-aware one;
    * e.g. don't add all apps to the SpiDesktop
@@ -275,6 +278,28 @@ static DBusObjectPathVTable droute_vtable =
   NULL, NULL, NULL, NULL
 };
 
+DBusHandlerResult
+disconnect_watch (DBusConnection *bus, DBusMessage *message, void *user_data)
+{
+  SpiRegistry *registry = SPI_REGISTRY (user_data);
+  const char *name, *old, *new;
+
+  if (!dbus_message_is_signal (message, DBUS_INTERFACE_DBUS, "NameOwnerChanged"))
+  {
+    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+  }
+  if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &old, DBUS_TYPE_STRING, &new, DBUS_TYPE_INVALID))
+  {
+    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+  }
+  if (*old != '\0' && *new == '\0')
+  {
+    spi_desktop_remove_application (registry->desktop, old);
+    spi_remove_device_listeners (registry->de_controller, old);
+  }
+  return DBUS_HANDLER_RESULT_HANDLED;
+}
+
 static void
 spi_registry_init (SpiRegistry *registry)
 {
@@ -323,6 +348,8 @@ spi_registry_init (SpiRegistry *registry)
                    registry);
 
   registry->de_controller = spi_device_event_controller_new (registry);
+
+  dbus_connection_add_filter (registry->droute.bus, disconnect_watch, registry, NULL);
 }
 
 SpiRegistry *