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=14622fddacec622c74dda53a55af058a6b839f5a;hb=95ac4886d1b6649d54daffa7191be1b2bbaf2989;hpb=7ff7c0d0b863f7346f21e03b6d170e8c7c6f9878 diff --git a/registryd/registry.c b/registryd/registry.c index 14622fd..51aaa4d 100644 --- a/registryd/registry.c +++ b/registryd/registry.c @@ -2,7 +2,9 @@ * AT-SPI - Assistive Technology Service Provider Interface * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) * - * Copyright 2001 Sun Microsystems Inc. + * Copyright 2008, Codethink Ltd. + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -20,631 +22,263 @@ * Boston, MA 02111-1307, USA. */ -/* - * registry.c: the main accessibility service registry implementation - */ - -#ifdef SPI_DEBUG -#include -#endif #include -#include - -/* - * This pulls the CORBA definitions for the "Accessibility::Registry" server - */ -#include - -/* - * We'd like to replace the dependance on X-isms with a wrapper layer, - * to the extent that it can't be done with pure GDK. - * Anyone want to help? - */ -#include -#include +#include +#include -/* - * This pulls the definition for the BonoboObject (GType) - */ #include "registry.h" -/* - * Our parent GObject type - */ -#define PARENT_TYPE LISTENER_TYPE - -/* - * A pointer to our parent object class - */ -static ListenerClass *registry_parent_class; - -typedef enum { - ETYPE_FOCUS, - ETYPE_OBJECT, - ETYPE_PROPERTY, - ETYPE_WINDOW, - ETYPE_TOOLKIT, - ETYPE_LAST_DEFINED -} EventTypeCategory; - -typedef struct { - char *event_name; - EventTypeCategory type_cat; - char * major; - char * minor; - char * detail; - guint hash; -} EventTypeStruct; - -typedef struct { - Accessibility_EventListener listener; - guint event_type_hash; - EventTypeCategory event_type_cat; -} ListenerStruct; - -/* static function prototypes */ -static void _registry_notify_listeners ( GList *listeners, - const Accessibility_Event *e, - CORBA_Environment *ev); - -static long _get_unique_id(); - -static gboolean _device_event_controller_hook (gpointer source); - -/* - * Implemented GObject::finalize - */ -static void -registry_object_finalize (GObject *object) +enum { -/* Registry *registry = REGISTRY (object); */ - GObjectClass *object_class = G_OBJECT_GET_CLASS( object); + REGISTRY_APPLICATION_REMOVE = 0, + REGISTRY_APPLICATION_ADD = 1 +}; - printf("registry_object_finalize called\n"); +/*---------------------------------------------------------------------------*/ - object_class->finalize (object); -} +G_DEFINE_TYPE(SpiRegistry, spi_registry, G_TYPE_OBJECT) -/** - * registerApplication: - * @application: a reference to the requesting @Application - * return values: void - * - * Register a new application with the accessibility broker. - * - **/ static void -impl_accessibility_registry_register_application (PortableServer_Servant servant, - const Accessibility_Application application, - CORBA_Environment * ev) +spi_registry_class_init (SpiRegistryClass *klass) { - Registry *registry = REGISTRY (bonobo_object_from_servant (servant)); - -#ifdef SPI_DEBUG - fprintf (stderr, "registering app %p\n", application); -#endif - registry->desktop->applications = g_list_append (registry->desktop->applications, - bonobo_object_dup_ref (application, ev)); - - /* TODO: create unique string here (with libuuid call ?) and hash ? */ - Accessibility_Application__set_id (application, _get_unique_id(), ev); + GObjectClass * object_class = (GObjectClass *) klass; - /* - * TODO: change the implementation below to a WM-aware one; - * e.g. don't add all apps to the Desktop - */ -} - -static gint -compare_corba_objects (gconstpointer p1, gconstpointer p2) -{ - CORBA_Environment ev; - gint retval; - retval = !CORBA_Object_is_equivalent ((CORBA_Object) p1, (CORBA_Object) p2, &ev); - -#ifdef SPI_DEBUG - fprintf (stderr, "comparing %p to %p; result %d\n", - p1, p2, - retval); -#endif - return retval; + spi_registry_parent_class = g_type_class_ref (G_TYPE_OBJECT); } static void -register_with_toolkits (Registry *registry_bonobo_object, EventTypeStruct *etype, CORBA_Environment *ev) +spi_registry_init (SpiRegistry *registry) { - gint n_desktops; - gint n_apps; - gint i, j; - Accessibility_Desktop desktop; - Accessibility_Application app; - Accessibility_Registry registry; - registry = BONOBO_OBJREF (registry_bonobo_object); + registry->apps = g_sequence_new (g_free); +} - /* for each app in each desktop, call ...Application_registerToolkitEventListener */ +/*---------------------------------------------------------------------------*/ - n_desktops = Accessibility_Registry_getDesktopCount (registry, ev); +static void emit(SpiRegistry *reg, const char *itf, const char *name, int ftype, ...) +{ + va_list arg; - for (i=0; ievent_name), - - ev); - } - } + va_start(arg, ftype); + spi_dbus_emit_valist(reg->bus, SPI_DBUS_PATH_DEC, itf, name, ftype, arg); + va_end(arg); } +/*---------------------------------------------------------------------------*/ + static gint -compare_listener_hash (gconstpointer p1, gconstpointer p2) +data_str_cmp (gpointer a, gpointer b, gpointer data) { - return (((ListenerStruct *)p2)->event_type_hash - ((ListenerStruct *)p1)->event_type_hash); + return g_strcmp0(a, b); } -static void -parse_event_type (EventTypeStruct *etype, char *event_name) +static gboolean +seq_add_string (GSequence *seq, gchar *str) { - guint nbytes = 0; - gchar **split_string; + GSequenceIter *iter; + gchar *item; + gboolean res = FALSE; - split_string = g_strsplit(event_name, ":", 4); - etype->event_name = g_strndup(event_name, 255); - - if (!g_ascii_strncasecmp (event_name, "focus:", 6)) - { - etype->type_cat = ETYPE_FOCUS; - } - else if (!g_ascii_strncasecmp (event_name, "object:", 7)) - { - etype->type_cat = ETYPE_OBJECT; - } - else if (!g_ascii_strncasecmp (event_name, "window:", 7)) - { - etype->type_cat = ETYPE_WINDOW; - } - else - { - etype->type_cat = ETYPE_TOOLKIT; - } + iter = g_sequence_search (seq, str, (GCompareDataFunc) data_str_cmp, NULL); + iter = g_sequence_iter_prev (iter); - if (split_string[1]) + if (!g_sequence_iter_is_end (iter)) { - etype->major = split_string[1]; - if (split_string[2]) - { - etype->minor = split_string[2]; - if (split_string[3]) - { - etype->detail = split_string[3]; - etype->hash = g_str_hash ( g_strconcat (split_string[1], split_string[2], split_string[3], NULL)); - } - else - { - etype->detail = g_strdup (""); - etype->hash = g_str_hash ( g_strconcat (split_string[1], split_string[2], NULL)); - } - } - else + item = g_sequence_get (iter); + if (g_strcmp0 (item, str)) { - etype->minor = g_strdup (""); - etype->hash = g_str_hash ( split_string[1]); + g_sequence_insert_sorted (seq, g_strdup(str), (GCompareDataFunc) data_str_cmp, NULL); + res = TRUE; } } else { - etype->major = g_strdup (""); - etype->minor = g_strdup (""); - etype->detail = g_strdup (""); - etype->hash = g_str_hash (""); + g_sequence_insert_sorted (seq, g_strdup(str), (GCompareDataFunc) data_str_cmp, NULL); + res = TRUE; } - /* TODO: don't forget to free the strings from caller when done ! */ + 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 void -impl_accessibility_registry_deregister_application (PortableServer_Servant servant, - const Accessibility_Application application, - CORBA_Environment * ev) +static gboolean +seq_remove_string (GSequence *seq, gchar *str) { - Registry *registry = REGISTRY (bonobo_object_from_servant (servant)); - GList *list = g_list_find_custom (registry->desktop->applications, application, compare_corba_objects); + GSequenceIter *iter; + gchar *item; + gboolean res = FALSE; -#ifdef SPI_DEBUG - gint i; -#endif + iter = g_sequence_search (seq, str, (GCompareDataFunc) data_str_cmp, NULL); + iter = g_sequence_iter_prev (iter); - if (list) + if (!g_sequence_iter_is_end (iter)) { -#ifdef SPI_DEBUG - fprintf (stderr, "deregistering application %p\n", application); -#endif - registry->desktop->applications = g_list_delete_link (registry->desktop->applications, list); -#ifdef SPI_DEBUG - fprintf (stderr, "there are now %d apps registered.\n", g_list_length (registry->desktop->applications)); - for (i = 0; i < g_list_length (registry->desktop->applications); ++i) { - fprintf (stderr, "getting application %d\n", i); - fprintf (stderr, "object address %p\n", - g_list_nth_data (registry->desktop->applications, i)); - } -#endif + item = g_sequence_get (iter); + if (!g_strcmp0 (item, str)) + { + g_sequence_remove (iter); + res = TRUE; + } } - else - fprintf (stderr, "could not deregister application\n"); + return res; } -/* - * CORBA Accessibility::Registry::registerGlobalEventListener method implementation - */ static void -impl_accessibility_registry_register_global_event_listener ( - PortableServer_Servant servant, - Accessibility_EventListener listener, - const CORBA_char *event_name, - CORBA_Environment *ev) +add_application (DBusConnection *bus, SpiRegistry *reg, gchar *app) { - Registry *registry = REGISTRY (bonobo_object_from_servant (servant)); - ListenerStruct *ls = g_malloc (sizeof (ListenerStruct)); - EventTypeStruct etype; - gboolean is_toolkit_specific = TRUE; - - fprintf(stderr, "registering for events of type %s\n", event_name); + guint add = REGISTRY_APPLICATION_ADD; - /* parse, check major event type and add listener accordingly */ - parse_event_type (&etype, event_name); - ls->event_type_hash = etype.hash; - ls->event_type_cat = etype.type_cat; - - switch (etype.type_cat) + if (seq_add_string (reg->apps, app)) { - case (ETYPE_FOCUS) : - case (ETYPE_OBJECT) : - case (ETYPE_PROPERTY) : - ls->listener = CORBA_Object_duplicate (listener, ev); - registry->object_listeners = - g_list_append (registry->object_listeners, ls); - break; - case (ETYPE_WINDOW) : - /* Support for Window Manager Events is not yet implemented */ - break; - case (ETYPE_TOOLKIT) : - ls->listener = CORBA_Object_duplicate (listener, ev); - registry->toolkit_listeners = - g_list_append (registry->toolkit_listeners, ls); - register_with_toolkits (registry, &etype, ev); - break; - default: - break; + emit (reg, + SPI_DBUS_INTERFACE_REGISTRY, + "updateApplications", + DBUS_TYPE_INT32, + &add, + DBUS_TYPE_STRING, + &app, + DBUS_TYPE_INVALID); } } -/* - * CORBA Accessibility::Registry::deregisterGlobalEventListenerAll method implementation - */ static void -impl_accessibility_registry_deregister_global_event_listener_all ( - PortableServer_Servant servant, - Accessibility_EventListener listener, - CORBA_Environment *ev) +remove_application (DBusConnection *bus, SpiRegistry *reg, gchar *app) { - Registry *registry = REGISTRY (bonobo_object_from_servant (servant)); - GList *list = g_list_find_custom (registry->object_listeners, listener, compare_corba_objects); - - /* - * TODO : de-register with toolkit if the last instance of a listener - * to a particular toolkit event type has been deregistered. - */ + guint remove = REGISTRY_APPLICATION_REMOVE; - while (list) - { - fprintf (stderr, "deregistering listener\n"); - registry->object_listeners = g_list_delete_link (registry->object_listeners, list); - list = g_list_find_custom (registry->object_listeners, listener, compare_corba_objects); - } - list = g_list_find_custom (registry->toolkit_listeners, listener, compare_corba_objects); - while (list) + if (seq_remove_string (reg->apps, app)) { - fprintf (stderr, "deregistering listener\n"); - registry->toolkit_listeners = g_list_delete_link (registry->toolkit_listeners, list); - list = g_list_find_custom (registry->toolkit_listeners, listener, compare_corba_objects); + /*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); } } -/* - * CORBA Accessibility::Registry::deregisterGlobalEventListener method implementation - */ +/*---------------------------------------------------------------------------*/ + static void -impl_accessibility_registry_deregister_global_event_listener ( - PortableServer_Servant servant, - Accessibility_EventListener listener, - const CORBA_char * event_name, - CORBA_Environment *ev) +add_bus_name_cb (gpointer item, gpointer data) { - Registry *registry = REGISTRY (bonobo_object_from_servant (servant)); - ListenerStruct ls; - EventTypeStruct etype; - GList *list; - GList **listeners; - - parse_event_type (&etype, event_name); - switch (etype.type_cat) - { - case (ETYPE_OBJECT) : - case (ETYPE_PROPERTY) : - case (ETYPE_FOCUS) : - listeners = ®istry->object_listeners; - break; - case (ETYPE_WINDOW) : - /* Support for Window Manager Events is not yet implemented */ - break; - case (ETYPE_TOOLKIT) : - listeners = ®istry->toolkit_listeners; - break; - default: - break; - } - - ls.event_type_hash = etype.hash; - list = g_list_find_custom (*listeners, &ls, compare_listener_hash); + DBusMessageIter *iter_array = (DBusMessageIter *) data; - while (list) - { - fprintf (stderr, "deregistering listener\n"); - *listeners = g_list_delete_link (*listeners, list); - list = g_list_find_custom (*listeners, &ls, compare_listener_hash); - } + dbus_message_iter_append_basic (iter_array, DBUS_TYPE_STRING, (gchar **) &item); } - -/** - * getDesktopCount: - * return values: a short integer indicating the current number of - * @Desktops. - * - * Get the current number of desktops. - * - **/ -static short -impl_accessibility_registry_get_desktop_count (PortableServer_Servant servant, - CORBA_Environment * ev) +static DBusMessage * +impl_getApplications (DBusConnection *bus, DBusMessage *message, void *user_data) { - /* TODO: implement support for multiple virtual desktops */ - CORBA_short n_desktops; - n_desktops = (CORBA_short) 1; - return n_desktops; -} + DBusMessage *reply; + DBusMessageIter iter, iter_array; + SpiRegistry *reg = SPI_REGISTRY (user_data); -/** - * getDesktop: - * @n: the index of the requested @Desktop. - * return values: a reference to the requested @Desktop. - * - * Get the nth accessible desktop. - * - **/ -static Accessibility_Desktop -impl_accessibility_registry_get_desktop (PortableServer_Servant servant, - const CORBA_short n, - CORBA_Environment * ev) -{ - Registry *registry = REGISTRY (bonobo_object_from_servant (servant)); + reply = dbus_message_new_method_return (message); - /* TODO: implement support for multiple virtual desktops */ - if (n == 0) - { - return (Accessibility_Desktop) - CORBA_Object_duplicate (BONOBO_OBJREF (registry->desktop), ev); - } - else - { - return (Accessibility_Desktop) CORBA_OBJECT_NIL; - } + 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; } -/** - * getDesktopList: - * return values: a sequence containing references to - * the @Desktops. - * - * Get a list of accessible desktops. - * - **/ -static Accessibility_DesktopSeq * -impl_accessibility_registry_get_desktop_list (PortableServer_Servant servant, - CORBA_Environment * ev) -{ - /* TODO: implement support for multiple virtual desktops */ - return (Accessibility_DesktopSeq *) NULL; -} +/*---------------------------------------------------------------------------*/ -static Accessibility_DeviceEventController -impl_accessibility_registry_get_device_event_controller (PortableServer_Servant servant, - CORBA_Environment * ev) +static void +impl_registerApplication (DBusConnection *bus, DBusMessage *message, void *user_data) { - Registry *registry = REGISTRY (bonobo_object_from_servant (servant)); - if (!registry->device_event_controller) - registry->device_event_controller = g_object_new (DEVICE_EVENT_CONTROLLER_TYPE, NULL); - return CORBA_Object_duplicate (BONOBO_OBJREF (registry->device_event_controller), ev); + gchar *app_name; + SpiRegistry *reg = SPI_REGISTRY (user_data); + + if (dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &app_name, DBUS_TYPE_INVALID)) + add_application(bus, reg, app_name); } static void -impl_registry_notify_event (PortableServer_Servant servant, - const Accessibility_Event *e, - CORBA_Environment *ev) +impl_deregisterApplication (DBusConnection *bus, DBusMessage *message, void *user_data) { - Registry *registry = REGISTRY (bonobo_object_from_servant (servant)); - EventTypeStruct etype; - - parse_event_type (&etype, e->type); + gchar *app_name; + SpiRegistry *reg = SPI_REGISTRY (user_data); - switch (etype.type_cat) - { - case (ETYPE_OBJECT) : - case (ETYPE_PROPERTY) : - case (ETYPE_FOCUS) : - _registry_notify_listeners (registry->object_listeners, e, ev); - break; - case (ETYPE_WINDOW) : - _registry_notify_listeners (registry->window_listeners, e, ev); - break; - case (ETYPE_TOOLKIT) : - _registry_notify_listeners (registry->toolkit_listeners, e, ev); - break; - default: - break; - } - /* Accessibility_Accessible_unref (e->source, ev);*/ /* This should be here! */ + if (dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &app_name, DBUS_TYPE_INVALID)) + remove_application(bus, reg, app_name); } -static long -_get_unique_id () -{ - static long id = 0; - return ++id; -} +/*---------------------------------------------------------------------------*/ static void -_registry_notify_listeners ( GList *listeners, - const Accessibility_Event *e, - CORBA_Environment *ev) +handle_disconnection (DBusConnection *bus, DBusMessage *message, void *user_data) { - int n; - int len; - ListenerStruct *ls; - EventTypeStruct etype; - guint minor_hash; - parse_event_type (&etype, e->type); - minor_hash = g_str_hash (g_strconcat (etype.major, etype.minor, NULL)); - len = g_list_length (listeners); - - for (n=0; nevent_type_hash, etype.hash, minor_hash); - fprintf(stderr, "event name: %s\n", etype.event_name); -#endif - if ((ls->event_type_hash == etype.hash) || (ls->event_type_hash == minor_hash)) + if (*old != '\0' && *new == '\0') { -#ifdef SPI_DEBUG - fprintf(stderr, "notifying listener #%d\n", n); - fprintf(stderr, "event source name %s\n", Accessibility_Accessible__get_name(e->source, ev)); -#endif - e->source = CORBA_Object_duplicate (e->source, ev); - Accessibility_Accessible_ref ( e->source, ev); - Accessibility_EventListener_notifyEvent ((Accessibility_EventListener) ls->listener, - e, - ev); - if (ev->_major != CORBA_NO_EXCEPTION) { - fprintf(stderr, - ("Accessibility app error: exception during event notification: %s\n"), - CORBA_exception_id(ev)); - exit(-1); - } + remove_application(bus, reg, old); } } } -static gboolean _device_event_controller_hook (gpointer p) -{ - Registry *registry = (Registry *)p; - DeviceEventController *controller = registry->device_event_controller; - if (controller) - device_event_controller_check_key_event (controller); - return TRUE; -} +/*---------------------------------------------------------------------------*/ -static void -registry_class_init (RegistryClass *klass) +static DBusHandlerResult +signal_filter (DBusConnection *bus, DBusMessage *message, void *user_data) { - GObjectClass * object_class = (GObjectClass *) klass; - POA_Accessibility_Registry__epv *epv = &klass->epv; + 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); - registry_parent_class = g_type_class_ref (LISTENER_TYPE); + 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; - object_class->finalize = registry_object_finalize; + return res; +} - epv->registerApplication = impl_accessibility_registry_register_application; - epv->deregisterApplication = impl_accessibility_registry_deregister_application; - epv->registerGlobalEventListener = impl_accessibility_registry_register_global_event_listener; - epv->deregisterGlobalEventListener = impl_accessibility_registry_deregister_global_event_listener; - epv->deregisterGlobalEventListenerAll = impl_accessibility_registry_deregister_global_event_listener_all; - epv->getDeviceEventController = impl_accessibility_registry_get_device_event_controller; - epv->getDesktopCount = impl_accessibility_registry_get_desktop_count; - epv->getDesktop = impl_accessibility_registry_get_desktop; - epv->getDesktopList = impl_accessibility_registry_get_desktop_list; +/*---------------------------------------------------------------------------*/ - ((ListenerClass *) klass)->epv.notifyEvent = impl_registry_notify_event; -} +static gchar *app_sig_match_name_owner = + "type='signal', interface='org.freedesktop.DBus', member='NameOwnerChanged'"; -static void -registry_init (Registry *registry) +static DRouteMethod dev_methods[] = { - registry->object_listeners = NULL; - registry->window_listeners = NULL; - registry->toolkit_listeners = NULL; - registry->applications = NULL; - registry->desktop = desktop_new(); - registry->device_event_controller = NULL; - registry->kbd_event_hook = _device_event_controller_hook; -} - -GType -registry_get_type (void) + { impl_getApplications, "getApplications" }, + { impl_registerApplication, "registerApplication" }, + { impl_deregisterApplication, "deregisterApplication" }, + { NULL, NULL } +}; + +SpiRegistry * +spi_registry_new (DBusConnection *bus, DRouteContext *droute) { - static GType type = 0; - - if (!type) { - static const GTypeInfo tinfo = { - sizeof (RegistryClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) registry_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class data */ - sizeof (Registry), - 0, /* n preallocs */ - (GInstanceInitFunc) registry_init, - NULL /* value table */ - }; - /* - * Here we use bonobo_type_unique instead of - * gtk_type_unique, this auto-generates a load of - * CORBA structures for us. All derived types must - * use bonobo_type_unique. - */ - type = bonobo_type_unique ( - PARENT_TYPE, - POA_Accessibility_Registry__init, - NULL, - G_STRUCT_OFFSET (RegistryClass, epv), - &tinfo, - "Registry"); - } + SpiRegistry *reg = g_object_new (SPI_REGISTRY_TYPE, NULL); + DRoutePath *path; - return type; -} + reg->bus = bus; -Registry * -registry_new (void) -{ - Registry *retval = - REGISTRY (g_object_new (registry_get_type (), NULL)); - return retval; + 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------------------------------------------------------------------------*/