X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fat-spi2-atk.git;a=blobdiff_plain;f=registryd%2Fregistry.c;h=51aaa4d3cb7e7f10560073a5bf6eef96267e501d;hp=92b481f6d9fbf13daedf43e102c03b91db946cd6;hb=95ac4886d1b6649d54daffa7191be1b2bbaf2989;hpb=f6ca06461319b20463f96a5b37544a540aee11ca diff --git a/registryd/registry.c b/registryd/registry.c index 92b481f..51aaa4d 100644 --- a/registryd/registry.c +++ b/registryd/registry.c @@ -2,6 +2,7 @@ * AT-SPI - Assistive Technology Service Provider Interface * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) * + * Copyright 2008, Codethink Ltd. * Copyright 2001, 2002 Sun Microsystems Inc., * Copyright 2001, 2002 Ximian, Inc. * @@ -21,334 +22,263 @@ * Boston, MA 02111-1307, USA. */ -/* registry.c: the main accessibility service registry implementation */ - -#undef SPI_LISTENER_DEBUG -#undef SPI_DEBUG -#undef SPI_QUEUE_DEBUG - #include -#ifdef SPI_DEBUG -# include -#endif - #include +#include #include "registry.h" -#include "dbus/dbus-glib-lowlevel.h" - -/* Our parent GObject type */ -#define PARENT_TYPE G_OBJECT_TYPE -<<<<<<< HEAD:registryd/registry.c -======= - ->>>>>>> 6d509d490749c6bac3149a5ec45862352ffcf290:registryd/registry.c - -int _dbg = 0; - -typedef enum { - ETYPE_FOCUS, - ETYPE_OBJECT, - ETYPE_PROPERTY, - ETYPE_WINDOW, - ETYPE_TOOLKIT, - ETYPE_KEYBOARD, - ETYPE_MOUSE, - ETYPE_LAST_DEFINED -} EventTypeCategory; - -typedef struct { - const char *event_name; - EventTypeCategory type_cat; - GQuark major; /* from string segment[1] */ - GQuark minor; /* from string segment[1]+segment[2] */ - GQuark detail; /* from string segment[3] (not concatenated) */ -} EventTypeStruct; + +enum +{ + REGISTRY_APPLICATION_REMOVE = 0, + REGISTRY_APPLICATION_ADD = 1 +}; + +/*---------------------------------------------------------------------------*/ G_DEFINE_TYPE(SpiRegistry, spi_registry, G_TYPE_OBJECT) static void -spi_registry_set_debug (const char *debug_flag_string) -{ - if (debug_flag_string) - _dbg = (int) g_ascii_strtod (debug_flag_string, NULL); -} - -static void emit(SpiRegistry *registry, const char *name, int first_type, ...) +spi_registry_class_init (SpiRegistryClass *klass) { - va_list arg; + GObjectClass * object_class = (GObjectClass *) klass; - va_start(arg, first_type); - spi_dbus_emit_valist(registry->droute.bus, SPI_DBUS_PATH_REGISTRY, SPI_DBUS_INTERFACE_REGISTRY, name, first_type, arg); - va_end(arg); + spi_registry_parent_class = g_type_class_ref (G_TYPE_OBJECT); } static void -desktop_add_application (SpiDesktop *desktop, - guint index, gpointer data) +spi_registry_init (SpiRegistry *registry) { - SpiRegistry *registry = SPI_REGISTRY (data); - const char *name = g_list_nth_data(desktop->applications, index); - - emit(registry, "ApplicationAdd", DBUS_TYPE_UINT32, &index, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID); + registry->apps = g_sequence_new (g_free); } +/*---------------------------------------------------------------------------*/ - -static void -desktop_remove_application (SpiDesktop *desktop, - guint index, gpointer data) +static void emit(SpiRegistry *reg, const char *itf, const char *name, int ftype, ...) { - SpiRegistry *registry = SPI_REGISTRY (data); - const char *name = g_list_nth_data(desktop->applications, index); - - emit(registry, "ApplicationRemove", DBUS_TYPE_UINT32, &index, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID); + va_list arg; + + va_start(arg, ftype); + spi_dbus_emit_valist(reg->bus, SPI_DBUS_PATH_DEC, itf, name, ftype, arg); + va_end(arg); } +/*---------------------------------------------------------------------------*/ -static void -spi_registry_object_finalize (GObject *object) +static gint +data_str_cmp (gpointer a, gpointer b, gpointer data) { - DBG (1, g_warning ("spi_registry_object_finalize called\n")); - g_object_unref (SPI_REGISTRY (object)->de_controller); - - G_OBJECT_CLASS (spi_registry_parent_class)->finalize (object); + return g_strcmp0(a, b); } -/** - * registerApplication: - * @application: a reference to the requesting @Application - * return values: void - * - * Register a new application with the accessibility broker. - * - **/ -static DBusMessage * -impl_accessibility_registry_register_application (DBusConnection *bus, DBusMessage *message, void *user_data) +static gboolean +seq_add_string (GSequence *seq, gchar *str) { - SpiRegistry *registry = SPI_REGISTRY (user_data); - const char *application = dbus_message_get_sender (message); - -#ifdef SPI_DEBUG - fprintf (stderr, "registering app %s\n", application); -#endif - spi_desktop_add_application (registry->desktop, application); - - /* - * TODO: change the implementation below to a WM-aware one; - * e.g. don't add all apps to the SpiDesktop - */ - return dbus_message_new_method_return (message); + GSequenceIter *iter; + gchar *item; + gboolean res = FALSE; + + iter = g_sequence_search (seq, str, (GCompareDataFunc) data_str_cmp, NULL); + iter = g_sequence_iter_prev (iter); + + if (!g_sequence_iter_is_end (iter)) + { + item = g_sequence_get (iter); + if (g_strcmp0 (item, str)) + { + g_sequence_insert_sorted (seq, g_strdup(str), (GCompareDataFunc) data_str_cmp, NULL); + res = TRUE; + } + } + else + { + g_sequence_insert_sorted (seq, g_strdup(str), (GCompareDataFunc) data_str_cmp, NULL); + res = TRUE; + } + + return res; } -/** - * deregisterApplication: - * @application: a reference to the @Application - * to be deregistered. - * return values: void - * - * De-register an application previously registered with the broker. - * - **/ -static DBusMessage * -impl_accessibility_registry_deregister_application (DBusConnection *bus, DBusMessage *message, void *user_data) +static gboolean +seq_remove_string (GSequence *seq, gchar *str) { - SpiRegistry *registry = SPI_REGISTRY (user_data); - const char *application = dbus_message_get_sender (message); - - spi_desktop_remove_application (registry->desktop, application); - -#ifdef SPI_DEBUG - fprintf (stderr, "de-registered app %s\n", application); -#endif - return dbus_message_new_method_return (message); + GSequenceIter *iter; + gchar *item; + gboolean res = FALSE; + + iter = g_sequence_search (seq, str, (GCompareDataFunc) data_str_cmp, NULL); + iter = g_sequence_iter_prev (iter); + + if (!g_sequence_iter_is_end (iter)) + { + item = g_sequence_get (iter); + if (!g_strcmp0 (item, str)) + { + g_sequence_remove (iter); + res = TRUE; + } + } + return res; } -/** - * getDesktopCount: - * return values: a short integer indicating the current number of - * @Desktops. - * - * Get the current number of desktops. - * - **/ -static DBusMessage * -impl_accessibility_registry_get_desktop_count (DBusConnection *bus, DBusMessage *message, void *user_data) +static void +add_application (DBusConnection *bus, SpiRegistry *reg, gchar *app) { - dbus_int16_t n_desktops = 1; - DBusMessage *reply; + guint add = REGISTRY_APPLICATION_ADD; + + if (seq_add_string (reg->apps, app)) + { + emit (reg, + SPI_DBUS_INTERFACE_REGISTRY, + "updateApplications", + DBUS_TYPE_INT32, + &add, + DBUS_TYPE_STRING, + &app, + DBUS_TYPE_INVALID); + } +} - /* TODO: implement support for multiple virtual desktops */ - reply = dbus_message_new_method_return (message); - if (reply) - { - dbus_message_append_args (reply, DBUS_TYPE_INT16, &n_desktops, DBUS_TYPE_INVALID); - } - return reply; +static void +remove_application (DBusConnection *bus, SpiRegistry *reg, gchar *app) +{ + guint remove = REGISTRY_APPLICATION_REMOVE; + + if (seq_remove_string (reg->apps, app)) + { + /*TODO spi_remove_device_listeners (registry->de_controller, old);*/ + emit (reg, + SPI_DBUS_INTERFACE_REGISTRY, + "updateApplications", + DBUS_TYPE_INT32, + &remove, + DBUS_TYPE_STRING, + &app, + DBUS_TYPE_INVALID); + } } -/** - * getDesktop: - * @n: the index of the requested @Desktop. - * return values: a reference to the requested @Desktop. - * - * Get the nth accessible desktop. - * - **/ -static DBusMessage * -impl_accessibility_registry_get_desktop (DBusConnection *bus, DBusMessage *message, void *user_data) +/*---------------------------------------------------------------------------*/ + +static void +add_bus_name_cb (gpointer item, gpointer data) { - DBusError error; - dbus_int16_t n; - const char *path; - DBusMessage *reply; + DBusMessageIter *iter_array = (DBusMessageIter *) data; - /* TODO: implement support for multiple virtual desktops */ - dbus_error_init (&error); - if (!dbus_message_get_args (message, &error, DBUS_TYPE_INT16, &n, DBUS_TYPE_INVALID)) - { - return spi_dbus_general_error (message); - } - path = (n == 0? SPI_DBUS_PATH_DESKTOP: "/"); - reply = dbus_message_new_method_return (message); - if (reply) - { - dbus_message_append_args (reply, DBUS_TYPE_STRING, &path, DBUS_TYPE_INVALID); - } - return reply; + dbus_message_iter_append_basic (iter_array, DBUS_TYPE_STRING, (gchar **) &item); } - -/** - * getDesktopList: - * return values: a sequence containing references to - * the @Desktops. - * - * Get a list of accessible desktops. - * - **/ static DBusMessage * -impl_accessibility_registry_get_desktop_list (DBusConnection *bus, DBusMessage *message, void *user_data) +impl_getApplications (DBusConnection *bus, DBusMessage *message, void *user_data) { DBusMessage *reply; DBusMessageIter iter, iter_array; - const char *path = SPI_DBUS_PATH_DESKTOP; + SpiRegistry *reg = SPI_REGISTRY (user_data); reply = dbus_message_new_method_return (message); - if (!reply) return NULL; - dbus_message_iter_init_append(reply, &iter); - if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "o", &iter_array)) goto oom; - dbus_message_iter_append_basic(&iter_array, DBUS_TYPE_STRING, &path); - if (!dbus_message_iter_close_container (&iter, &iter_array)) goto oom; - return reply; -oom: - // TODO: handle out-of-memory + + dbus_message_iter_init_append (reply, &iter); + dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &iter_array); + g_sequence_foreach (reg->apps, add_bus_name_cb, &iter_array); + dbus_message_iter_close_container(&iter, &iter_array); return reply; } +/*---------------------------------------------------------------------------*/ -static DBusMessage * -impl_accessibility_registry_get_device_event_controller (DBusConnection *bus, DBusMessage *message, void *user_data) +static void +impl_registerApplication (DBusConnection *bus, DBusMessage *message, void *user_data) { - DBusMessage *reply; - const char *path = SPI_DBUS_PATH_DEC; + gchar *app_name; + SpiRegistry *reg = SPI_REGISTRY (user_data); - reply = dbus_message_new_method_return (message); - if (reply) - { - dbus_message_append_args (reply, DBUS_TYPE_STRING, &path, DBUS_TYPE_INVALID); - } - return reply; + if (dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &app_name, DBUS_TYPE_INVALID)) + add_application(bus, reg, app_name); } - static void -spi_registry_class_init (SpiRegistryClass *klass) +impl_deregisterApplication (DBusConnection *bus, DBusMessage *message, void *user_data) { - GObjectClass * object_class = (GObjectClass *) klass; + gchar *app_name; + SpiRegistry *reg = SPI_REGISTRY (user_data); - spi_registry_parent_class = g_type_class_ref (G_TYPE_OBJECT); - - object_class->finalize = spi_registry_object_finalize; + if (dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &app_name, DBUS_TYPE_INVALID)) + remove_application(bus, reg, app_name); } -static DBusObjectPathVTable droute_vtable = -{ - NULL, - &droute_message, - NULL, NULL, NULL, NULL -}; +/*---------------------------------------------------------------------------*/ static void -spi_registry_init (SpiRegistry *registry) +handle_disconnection (DBusConnection *bus, DBusMessage *message, void *user_data) { - DBusError error; - - spi_registry_set_debug (g_getenv ("AT_SPI_DEBUG")); - /* - * TODO: FIXME, this module makes the foolish assumptions that - * registryd uses the same display as the apps, and that the - * DISPLAY environment variable is set. - */ - gdk_init (NULL, NULL); - - registry->exit_notify_timeout = 200; - registry->queue_handler_id = 0; - - dbus_error_init (&error); - registry->droute.bus = dbus_bus_get(DBUS_BUS_SESSION, &error); - if (!registry->droute.bus) - { - g_warning("Couldn't connect to dbus: %s\n", error.message); - return; - } - spi_registry_initialize_registry_interface (®istry->droute); - spi_registry_initialize_desktop_interface (®istry->droute); - spi_registry_initialize_dec_interface (®istry->droute); - // todo: initialize accessible and component interfaces, for desktop? - if (!dbus_connection_try_register_fallback (registry->droute.bus, "/org/freedesktop/atspi", &droute_vtable, ®istry->droute, &error)) - { - g_warning("Couldn't register droute.\n"); - } - dbus_connection_setup_with_g_main(registry->droute.bus, g_main_context_default()); - - // TODO: decide whether focus_object is still relevant - registry->desktop = spi_desktop_new (); - /* Register callback notification for application addition and removal */ - g_signal_connect (G_OBJECT (registry->desktop), - "application_added", - G_CALLBACK (desktop_add_application), - registry); - - g_signal_connect (G_OBJECT (registry->desktop), - "application_removed", - G_CALLBACK (desktop_remove_application), - registry); - - registry->de_controller = spi_device_event_controller_new (registry); + char *name, *old, *new; + SpiRegistry *reg = SPI_REGISTRY (user_data); + + 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') + { + remove_application(bus, reg, old); + } + } } -SpiRegistry * -spi_registry_new (void) +/*---------------------------------------------------------------------------*/ + +static DBusHandlerResult +signal_filter (DBusConnection *bus, DBusMessage *message, void *user_data) { - SpiRegistry *retval = g_object_new (SPI_REGISTRY_TYPE, NULL); - return retval; + SpiRegistry *registry = SPI_REGISTRY (user_data); + guint res = DBUS_HANDLER_RESULT_HANDLED; + const char *iface = dbus_message_get_interface (message); + const char *member = dbus_message_get_member (message); + + if (!g_strcmp0(iface, DBUS_INTERFACE_DBUS) && !g_strcmp0(member, "NameOwnerChanged")) + handle_disconnection (bus, message, user_data); + else + res = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + return res; } -static DRouteMethod methods[] = +/*---------------------------------------------------------------------------*/ + +static gchar *app_sig_match_name_owner = + "type='signal', interface='org.freedesktop.DBus', member='NameOwnerChanged'"; + +static DRouteMethod dev_methods[] = { - { impl_accessibility_registry_register_application , "registerApplication" }, - { impl_accessibility_registry_deregister_application, "deregisterApplication" }, - { impl_accessibility_registry_get_desktop_count, "getDesktopCount" }, - { impl_accessibility_registry_get_desktop, "getDesktop" }, - { impl_accessibility_registry_get_desktop_list, "getDesktopList" }, - { impl_accessibility_registry_get_device_event_controller, "getDeviceEventController" }, + { impl_getApplications, "getApplications" }, + { impl_registerApplication, "registerApplication" }, + { impl_deregisterApplication, "deregisterApplication" }, { NULL, NULL } }; -void -spi_registry_initialize_registry_interface (DRouteData * data) +SpiRegistry * +spi_registry_new (DBusConnection *bus, DRouteContext *droute) { - droute_add_interface (data, "org.freedesktop.atspi.Registry", methods, - NULL, NULL, NULL); -}; + SpiRegistry *reg = g_object_new (SPI_REGISTRY_TYPE, NULL); + DRoutePath *path; + + reg->bus = bus; + + dbus_bus_add_match (bus, app_sig_match_name_owner, NULL); + dbus_connection_add_filter (bus, signal_filter, reg, NULL); + + path = droute_add_one (droute, + SPI_DBUS_PATH_REGISTRY, + reg); + + droute_path_add_interface (path, + SPI_DBUS_INTERFACE_DEC, + dev_methods, + NULL); + + return reg; +} + +/*END------------------------------------------------------------------------*/