X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=libspi%2Fregistry.c;h=51a3cb460f18b953bb1e386770d0bb02c8520f2a;hb=4328426aeae1eeed7c2e696536351b224eeddbce;hp=6063ce24c47b961620cdeb5826e3d25440004929;hpb=1ae1f2194e9c209450a5df907e18b9a7e9af6699;p=platform%2Fcore%2Fuifw%2Fat-spi2-atk.git diff --git a/libspi/registry.c b/libspi/registry.c index 6063ce2..51a3cb4 100644 --- a/libspi/registry.c +++ b/libspi/registry.c @@ -20,47 +20,75 @@ * Boston, MA 02111-1307, USA. */ -/* - * registry.c: test for accessibility implementation - * - */ +/* registry.c: the main accessibility service registry implementation */ +#include #ifdef SPI_DEBUG -#include +# include #endif -#include -#include /* - * This pulls the CORBA definitions for the "Accessibility::Registry" server + * 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 "Registry.h" - -/* - * 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; +#include +#include +#include + +#include + +/* Our parent GObject type */ +#define PARENT_TYPE SPI_LISTENER_TYPE + +/* A pointer to our parent object class */ +static SpiListenerClass *spi_registry_parent_class; + +typedef enum { + ETYPE_FOCUS, + ETYPE_OBJECT, + ETYPE_PROPERTY, + ETYPE_WINDOW, + ETYPE_TOOLKIT, + ETYPE_KEYBOARD, + + 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; +} SpiListenerStruct; + +/* 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) +spi_registry_object_finalize (GObject *object) { -/* Registry *registry = REGISTRY (object); */ +/* SpiRegistry *registry = SPI_REGISTRY (object); */ GObjectClass *object_class = G_OBJECT_GET_CLASS( object); - printf("registry_object_finalize called\n"); + printf("spi_registry_object_finalize called\n"); object_class->finalize (object); } @@ -78,18 +106,141 @@ impl_accessibility_registry_register_application (PortableServer_Servant servant const Accessibility_Application application, CORBA_Environment * ev) { - Registry *registry = REGISTRY (bonobo_object_from_servant (servant)); + SpiRegistry *registry = SPI_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); - registry->desktop->applications = g_list_append (registry->desktop->applications, CORBA_Object_duplicate (application, ev)); /* * TODO: change the implementation below to a WM-aware one; - * e.g. don't add all apps to the Desktop + * e.g. don't add all apps to the SpiDesktop */ - /* registry->desktop->applications = registry->applications;*/ +} + +static gint +compare_corba_objects (gconstpointer p1, gconstpointer p2) +{ + CORBA_Environment ev; + gint retval; + +#ifdef SPI_DEBUG + fprintf (stderr, "comparing %p to %p\n", + p1, p2); +#endif + + retval = !CORBA_Object_is_equivalent ((CORBA_Object) p1, (CORBA_Object) p2, &ev); + return retval; +} + +static void +register_with_toolkits (SpiRegistry *spi_registry_bonobo_object, EventTypeStruct *etype, CORBA_Environment *ev) +{ + gint n_desktops; + gint n_apps; + gint i, j; + Accessibility_Desktop desktop; + Accessibility_Application app; + Accessibility_Registry registry; + registry = BONOBO_OBJREF (spi_registry_bonobo_object); + + /* for each app in each desktop, call ...Application_registerToolkitEventListener */ + + n_desktops = Accessibility_Registry_getDesktopCount (registry, ev); + + for (i=0; ievent_name), + + ev); + } + } +} + +static gint +compare_listener_hash (gconstpointer p1, gconstpointer p2) +{ + return (((SpiListenerStruct *)p2)->event_type_hash - ((SpiListenerStruct *)p1)->event_type_hash); +} + +static gint +compare_listener_corbaref (gconstpointer p1, gconstpointer p2) +{ + return compare_corba_objects (((SpiListenerStruct *)p2)->listener, + ((SpiListenerStruct *)p1)->listener); +} + +static void +parse_event_type (EventTypeStruct *etype, char *event_name) +{ + gchar **split_string; + + 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; + } + + if (split_string[1]) + { + 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 + { + etype->minor = g_strdup (""); + etype->hash = g_str_hash ( split_string[1]); + } + } + else + { + etype->major = g_strdup (""); + etype->minor = g_strdup (""); + etype->detail = g_strdup (""); + etype->hash = g_str_hash (""); + } + + /* TODO: don't forget to free the strings from caller when done ! */ } /** @@ -106,50 +257,162 @@ impl_accessibility_registry_deregister_application (PortableServer_Servant serva const Accessibility_Application application, CORBA_Environment * ev) { - Registry *registry = REGISTRY (bonobo_object_from_servant (servant)); - registry->applications = g_list_remove (registry->applications, application); + SpiRegistry *registry = SPI_REGISTRY (bonobo_object_from_servant (servant)); + GList *list = g_list_find_custom (registry->desktop->applications, application, compare_corba_objects); + +#ifdef SPI_DEBUG + gint i; +#endif + + if (list) + { +#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 + } + else + { + fprintf (stderr, "could not deregister application %p\n", application); + } } /* * CORBA Accessibility::Registry::registerGlobalEventListener method implementation */ static void -impl_accessibility_registry_register_global_event_listener - (PortableServer_Servant servant, +impl_accessibility_registry_register_global_event_listener ( + PortableServer_Servant servant, Accessibility_EventListener listener, const CORBA_char *event_name, CORBA_Environment *ev) { - /** - * TODO: - * - * distinguish between event types - * register with app toolkits only for requested event types - * maintain list of requested types and number of listeners - * find non-strcmp method of matching event types to listeners - * - **/ - - Registry *registry = REGISTRY (bonobo_object_from_servant (servant)); - /* fprintf(stderr, "registering %x/%x\n", listener, *listener); */ - registry->listeners = g_list_append (registry->listeners, CORBA_Object_duplicate(listener, ev)); - /* fprintf(stderr, "there are now %d listeners registered.\n", g_list_length(registry->listeners)); */ - /* should use hashtable and CORBA_Object_hash (...) */ + SpiRegistry *registry = SPI_REGISTRY (bonobo_object_from_servant (servant)); + SpiListenerStruct *ls = g_malloc (sizeof (SpiListenerStruct)); + EventTypeStruct etype; + + fprintf(stderr, "registering for events of type %s\n", event_name); + + /* parse, check major event type and add listener accordingly */ + parse_event_type (&etype, (char*) event_name); + ls->event_type_hash = etype.hash; + ls->event_type_cat = etype.type_cat; + + switch (etype.type_cat) + { + 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; + } +} + +/* + * 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) +{ + SpiRegistry *registry = SPI_REGISTRY (bonobo_object_from_servant (servant)); + SpiListenerStruct *ls = g_malloc (sizeof (SpiListenerStruct)); + GList *list; + ls->listener = listener; + list = g_list_find_custom (registry->object_listeners, ls, + compare_listener_corbaref); + + /* + * TODO : de-register with toolkit if the last instance of a listener + * to a particular toolkit event type has been deregistered. + */ + + 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, ls, compare_listener_corbaref); + } + list = g_list_find_custom (registry->toolkit_listeners, ls, compare_listener_corbaref); + while (list) + { + fprintf (stderr, "deregistering listener\n"); + registry->toolkit_listeners = g_list_delete_link (registry->toolkit_listeners, list); + list = g_list_find_custom (registry->toolkit_listeners, ls, compare_listener_corbaref); + } } /* * CORBA Accessibility::Registry::deregisterGlobalEventListener method implementation */ static void -impl_accessibility_registry_deregister_global_event_listener - (PortableServer_Servant servant, +impl_accessibility_registry_deregister_global_event_listener ( + PortableServer_Servant servant, Accessibility_EventListener listener, + const CORBA_char * event_name, CORBA_Environment *ev) { - Registry *registry = REGISTRY (bonobo_object_from_servant (servant)); - /* TODO: this won't work since 'listener' is a duplicate ref */ - registry->listeners = g_list_remove (registry->listeners, listener); - /* fprintf(stderr, "deregister\n"); */ + SpiRegistry *registry = SPI_REGISTRY (bonobo_object_from_servant (servant)); + SpiListenerStruct ls; + EventTypeStruct etype; + GList *list; + GList **listeners; + + parse_event_type (&etype, (char *) 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: + listeners = NULL; + break; + } + + if (!listeners) + return; + + ls.event_type_hash = etype.hash; + list = g_list_find_custom (*listeners, &ls, compare_listener_hash); + + while (list) + { + fprintf (stderr, "deregistering listener\n"); + *listeners = g_list_delete_link (*listeners, list); + list = g_list_find_custom (*listeners, &ls, compare_listener_hash); + } } @@ -184,14 +447,13 @@ impl_accessibility_registry_get_desktop (PortableServer_Servant servant, const CORBA_short n, CORBA_Environment * ev) { - Registry *registry = REGISTRY (bonobo_object_from_servant (servant)); + SpiRegistry *registry = SPI_REGISTRY (bonobo_object_from_servant (servant)); /* TODO: implement support for multiple virtual desktops */ if (n == 0) { return (Accessibility_Desktop) - CORBA_Object_duplicate ( - bonobo_object_corba_objref (bonobo_object (registry->desktop)), ev); + CORBA_Object_duplicate (BONOBO_OBJREF (registry->desktop), ev); } else { @@ -215,12 +477,15 @@ impl_accessibility_registry_get_desktop_list (PortableServer_Servant servant, return (Accessibility_DesktopSeq *) NULL; } -static CORBA_Object +static Accessibility_DeviceEventController impl_accessibility_registry_get_device_event_controller (PortableServer_Servant servant, CORBA_Environment * ev) { - /* TODO: not yet implemented! */ - return CORBA_OBJECT_NIL; + SpiRegistry *registry = SPI_REGISTRY (bonobo_object_from_servant (servant)); + if (!registry->device_event_controller) + registry->device_event_controller = spi_device_event_controller_new (registry); + + return CORBA_Object_duplicate (BONOBO_OBJREF (registry->device_event_controller), ev); } static void @@ -228,103 +493,137 @@ impl_registry_notify_event (PortableServer_Servant servant, const Accessibility_Event *e, CORBA_Environment *ev) { - int n; - int len; - Registry *registry = REGISTRY (bonobo_object_from_servant (servant)); + SpiRegistry *registry = SPI_REGISTRY (bonobo_object_from_servant (servant)); + EventTypeStruct etype; - /** - * TODO: - * - * distinguish between event types - * find non-strcmp method of matching event types to listeners - * - **/ + parse_event_type (&etype, e->type); - len = g_list_length (registry->listeners); - /* fprintf(stderr, "%d listeners registered\n", len); */ + 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; + case (ETYPE_KEYBOARD) : + default: + break; + } + /* Accessibility_Accessible_unref (e->source, ev);*/ /* This should be here! */ +} + +static long +_get_unique_id () +{ + static long id = 0; + return ++id; +} + +static void +_registry_notify_listeners (GList *listeners, + const Accessibility_Event *e_in, + CORBA_Environment *ev) +{ + int n; + int len; + SpiListenerStruct *ls; + EventTypeStruct etype; + Accessibility_Event *e_out; + guint minor_hash; + parse_event_type (&etype, e_in->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)) + { #ifdef SPI_DEBUG - fprintf(stderr, "notifying listener #%d\n", n); - fprintf(stderr, "event name %s\n", Accessibility_Accessible__get_name(e->target, ev)); + fprintf(stderr, "notifying listener #%d\n", n); + fprintf(stderr, "event source name %s\n", Accessibility_Accessible__get_name(e_in->source, ev)); #endif - Accessibility_EventListener_notifyEvent ( - (Accessibility_EventListener) g_list_nth_data (registry->listeners, n), - e, - ev); + e_out = ORBit_copy_value (e_in, TC_Accessibility_Event); + e_out->source = CORBA_Object_duplicate (e_in->source, ev); + Accessibility_Accessible_ref ( e_out->source, ev); + Accessibility_EventListener_notifyEvent ((Accessibility_EventListener) ls->listener, + e_out, + ev); + /* is it safe to free e_out now ? notifyEvent is a oneway... */ + CORBA_free (e_out); + if (ev->_major != CORBA_NO_EXCEPTION) { + fprintf(stderr, + ("Accessibility app error: exception during event notification: %s\n"), + CORBA_exception_id(ev)); + exit(-1); + } + } } } +static gboolean +_device_event_controller_hook (gpointer p) +{ + SpiRegistry *registry = (SpiRegistry *)p; + SpiDeviceEventController *controller = registry->device_event_controller; + if (controller) + spi_device_event_controller_check_key_event (controller); + return TRUE; +} + static void -registry_class_init (RegistryClass *klass) +spi_registry_class_init (SpiRegistryClass *klass) { GObjectClass * object_class = (GObjectClass *) klass; POA_Accessibility_Registry__epv *epv = &klass->epv; - registry_parent_class = g_type_class_ref (LISTENER_TYPE); + spi_registry_parent_class = g_type_class_ref (SPI_LISTENER_TYPE); - object_class->finalize = registry_object_finalize; + object_class->finalize = spi_registry_object_finalize; 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; - epv->getDeviceEventController = impl_accessibility_registry_get_device_event_controller; - ((ListenerClass *) klass)->epv.notifyEvent = impl_registry_notify_event; + + ((SpiListenerClass *) klass)->epv.notifyEvent = impl_registry_notify_event; } static void -registry_init (Registry *registry) +spi_registry_init (SpiRegistry *registry) { - registry->listeners = NULL; + registry->object_listeners = NULL; + registry->window_listeners = NULL; + registry->toolkit_listeners = NULL; registry->applications = NULL; - registry->desktop = desktop_new(); + registry->desktop = spi_desktop_new(); + registry->device_event_controller = NULL; + registry->kbd_event_hook = _device_event_controller_hook; } -GType -registry_get_type (void) -{ - 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_x_type_unique instead of - * gtk_type_unique, this auto-generates a load of - * CORBA structures for us. All derived types must - * use bonobo_x_type_unique. - */ - type = bonobo_x_type_unique ( - PARENT_TYPE, - POA_Accessibility_Registry__init, - NULL, - G_STRUCT_OFFSET (RegistryClass, epv), - &tinfo, - "Registry"); - } - - return type; -} +BONOBO_TYPE_FUNC_FULL (SpiRegistry, + Accessibility_Registry, + PARENT_TYPE, + spi_registry); -Registry * -registry_new (void) +SpiRegistry * +spi_registry_new (void) { - Registry *retval = - REGISTRY (g_object_new (registry_get_type (), NULL)); + SpiRegistry *retval = g_object_new (SPI_REGISTRY_TYPE, NULL); return retval; }