From 8c5e5134f794c6e25c4a046698a5522f5a24e0ca Mon Sep 17 00:00:00 2001 From: Mike Gorse Date: Thu, 12 Jun 2008 11:59:46 -0400 Subject: [PATCH] Add watches for disconnected applications and clients; fix related issues path -> bus_name in some variables --- registryd/desktop.c | 42 ++++++++++++++---------------- registryd/desktop.h | 6 ++--- registryd/deviceeventcontroller.c | 54 ++++++++++++++++++++++++++++++--------- registryd/deviceeventcontroller.h | 2 ++ registryd/registry.c | 33 +++++++++++++++++++++--- 5 files changed, 96 insertions(+), 41 deletions(-) diff --git a/registryd/desktop.c b/registryd/desktop.c index 94f31f5..9d0ec95 100644 --- a/registryd/desktop.c +++ b/registryd/desktop.c @@ -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[] = diff --git a/registryd/desktop.h b/registryd/desktop.h index a2ecb47..3a0e401 100644 --- a/registryd/desktop.h +++ b/registryd/desktop.h @@ -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 diff --git a/registryd/deviceeventcontroller.c b/registryd/deviceeventcontroller.c index 2af73ae..42b83dd 100644 --- a/registryd/deviceeventcontroller.c +++ b/registryd/deviceeventcontroller.c @@ -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 diff --git a/registryd/deviceeventcontroller.h b/registryd/deviceeventcontroller.h index 3fa5c8e..df8288b 100644 --- a/registryd/deviceeventcontroller.h +++ b/registryd/deviceeventcontroller.h @@ -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_ */ diff --git a/registryd/registry.c b/registryd/registry.c index 25d0ace..7316a05 100644 --- a/registryd/registry.c +++ b/registryd/registry.c @@ -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 * -- 2.7.4