X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=registryd%2Fregistry.c;h=466489b8d3010fa5b9663311bb1e1743e1d6a2f3;hb=dd2980f16fdc1dc64eaf04f5d4df0ae12307b00a;hp=6ef142f9cecd2725ed58fbc20980ee474e29fddc;hpb=5d480319bfc6e106a9cfda9cd4509ec626e9f50d;p=platform%2Fcore%2Fuifw%2Fat-spi2-atk.git diff --git a/registryd/registry.c b/registryd/registry.c index 6ef142f..466489b 100644 --- a/registryd/registry.c +++ b/registryd/registry.c @@ -20,49 +20,123 @@ * Boston, MA 02111-1307, USA. */ -/* - * registry.c: test for accessibility implementation - * - */ -#define DEBUG_PRINTSTUFF -#ifdef DEBUG_PRINTSTUFF -#include -#endif -#include -#include +/* registry.c: the main accessibility service registry implementation */ -/* - * This pulls the CORBA definitions for the "Accessibility::Registry" server - */ -#include "Registry.h" +#undef SPI_LISTENER_DEBUG -/* - * This pulls the definition for the BonoboObject (GType) - */ +#include +#ifdef SPI_DEBUG +# include +#endif + +#include +#include "../libspi/spi-private.h" #include "registry.h" -/* - * Our parent GObject type - */ -#define PARENT_TYPE LISTENER_TYPE +/* 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; + GQuark major; /* from string segment[1] */ + GQuark minor; /* from string segment[1]+segment[2] */ + GQuark detail; /* from string segment[3] (not concatenated) */ +} EventTypeStruct; + +typedef struct { + Accessibility_EventListener listener; + GQuark event_type_quark; + EventTypeCategory event_type_cat; +} SpiListenerStruct; + + +SpiListenerStruct * +spi_listener_struct_new (Accessibility_EventListener listener, CORBA_Environment *ev) +{ + SpiListenerStruct *retval = g_malloc (sizeof (SpiListenerStruct)); + retval->listener = bonobo_object_dup_ref (listener, ev); + return retval; +} + + +void +spi_listener_struct_free (SpiListenerStruct *ls, CORBA_Environment *ev) +{ + bonobo_object_release_unref (ls->listener, ev); + g_free (ls); +} -/* - * A pointer to our parent object class - */ -static ListenerClass *registry_parent_class; -/* - * Implemented GObject::finalize - */ static void -registry_object_finalize (GObject *object) +desktop_add_application (SpiDesktop *desktop, + guint index, gpointer data) { -/* Registry *registry = REGISTRY (object); */ - GObjectClass *object_class = G_OBJECT_GET_CLASS( object); + BonoboObject *registry = BONOBO_OBJECT (data); + Accessibility_Event e; + CORBA_Environment ev; + + e.type = g_strdup ("object:children-changed::add"); + e.source = BONOBO_OBJREF (desktop); + e.detail1 = index; + e.detail2 = 0; + CORBA_exception_init (&ev); + Accessibility_Registry_notifyEvent (BONOBO_OBJREF (registry), + &e, &ev); + CORBA_exception_free (&ev); +} + - printf("registry_object_finalize called\n"); - object_class->finalize (object); +static void +desktop_remove_application (SpiDesktop *desktop, + guint index, gpointer data) +{ + BonoboObject *registry = BONOBO_OBJECT (data); + Accessibility_Event e; + CORBA_Environment ev; + + e.type = g_strdup ("object:children-changed::remove"); + e.source = BONOBO_OBJREF (desktop); + e.detail1 = index; + e.detail2 = 0; + CORBA_exception_init (&ev); + Accessibility_Registry_notifyEvent (BONOBO_OBJREF (registry), + &e, &ev); + CORBA_exception_free (&ev); +} + + + +static void +spi_registry_object_finalize (GObject *object) +{ + printf ("spi_registry_object_finalize called\n"); + + /* TODO: unref deviceeventcontroller, which disconnects key listener */ + G_OBJECT_CLASS (spi_registry_parent_class)->finalize (object); +} + +static long +_get_unique_id (void) +{ + static long id = 0; + + return ++id; } /** @@ -78,15 +152,149 @@ 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); - registry->desktop->applications = g_list_append (registry->desktop->applications, CORBA_Object_duplicate (application, ev)); +#endif + spi_desktop_add_application (registry->desktop, application); + + Accessibility_Application__set_id (application, _get_unique_id (), 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;*/ +} + +#ifdef USE_A_HASH_IN_FUTURE +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; +} +#endif + +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); + } + } +} + +#ifdef USE_A_HASH_IN_FUTURE + +static gint +compare_listener_quarks (gconstpointer p1, gconstpointer p2) +{ + return (((SpiListenerStruct *)p2)->event_type_quark != + ((SpiListenerStruct *)p1)->event_type_quark); +} + +static gint +compare_listener_corbaref (gconstpointer p1, gconstpointer p2) +{ + return compare_corba_objects (((SpiListenerStruct *)p2)->listener, + ((SpiListenerStruct *)p1)->listener); +} +#endif + +static void +parse_event_type (EventTypeStruct *etype, const char *event_name) +{ + gchar **split_string; + gchar *s; + + split_string = g_strsplit (event_name, ":", 4); + etype->event_name = g_strdup (event_name); + + 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]) + { + if (split_string[2]) + { + etype->minor = g_quark_from_string (s = g_strconcat (split_string[1], split_string[2], NULL)); + g_free (s); + if (split_string[3]) + { + etype->detail = g_quark_from_string (split_string[3]); + s = g_strconcat (split_string[1], split_string[2], split_string[3], NULL); + etype->major = g_quark_from_string (s); + g_free (s); + } + else + { + etype->detail = g_quark_from_static_string (""); + s = g_strconcat (split_string[1], split_string[2], NULL); + etype->major = g_quark_from_string (s); + g_free (s); + } + } + else + { + etype->major = g_quark_from_string (split_string[1]); + etype->minor = etype->major; + etype->detail = etype->major; + } + } + else + { + etype->major = g_quark_from_static_string (""); + etype->minor = etype->major; + etype->detail = etype->major; + } + + g_strfreev (split_string); } /** @@ -103,50 +311,146 @@ 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)); + + spi_desktop_remove_application (registry->desktop, application); + +#ifdef SPI_DEBUG + fprintf (stderr, "de-registered app %p\n", application); +#endif +} + +static GList ** +get_listener_list (SpiRegistry *registry, + EventTypeCategory cat) +{ + GList **ret; + + switch (cat) + { + case ETYPE_OBJECT: + case ETYPE_PROPERTY: + case ETYPE_FOCUS: + ret = ®istry->object_listeners; + break; + case ETYPE_WINDOW: + ret = ®istry->window_listeners; + break; + case ETYPE_TOOLKIT: + ret = ®istry->toolkit_listeners; + break; + case ETYPE_KEYBOARD: + default: + ret = NULL; + break; + } + return ret; } /* * 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) +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 = spi_listener_struct_new (listener, ev); + EventTypeStruct etype; + GList **list; + +#ifdef SPI_DEBUG + fprintf (stderr, "registering for events of type %s\n", event_name); +#endif + + /* parse, check major event type and add listener accordingly */ + parse_event_type (&etype, event_name); + ls->event_type_quark = etype.major; + ls->event_type_cat = etype.type_cat; + + list = get_listener_list (registry, etype.type_cat); + + if (list) + { + *list = g_list_prepend (*list, ls); + + if (etype.type_cat == ETYPE_TOOLKIT) + { + register_with_toolkits (registry, &etype, ev); + } + } + else + { + spi_listener_struct_free (ls, ev); + } +} + +static SpiReEntrantContinue +remove_listener_cb (GList * const *list, gpointer user_data) +{ + SpiListenerStruct *ls = (SpiListenerStruct *) (*list)->data; + CORBA_Environment ev; + Accessibility_EventListener listener = user_data; + + CORBA_exception_init (&ev); + + if (CORBA_Object_is_equivalent (ls->listener, listener, &ev)) + { + spi_re_entrant_list_delete_link (list); + spi_listener_struct_free (ls, &ev); + } + + CORBA_exception_free (&ev); + + return SPI_RE_ENTRANT_CONTINUE; +} + +/* + * 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) +{ + int i; + GList **lists[2]; + SpiRegistry *registry = SPI_REGISTRY (bonobo_object_from_servant (servant)); + + lists[0] = ®istry->object_listeners; + lists[1] = ®istry->window_listeners; + lists[2] = ®istry->toolkit_listeners; + + for (i = 0; i < sizeof (lists) / sizeof (lists[0]); i++) + { + spi_re_entrant_list_foreach (lists [i], remove_listener_cb, listener); + } } + /* * CORBA Accessibility::Registry::deregisterGlobalEventListener method implementation */ static void -impl_accessibility_registry_deregister_global_event_listener - (PortableServer_Servant servant, - Accessibility_EventListener listener, - CORBA_Environment *ev) +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; + EventTypeStruct etype; + + registry = SPI_REGISTRY (bonobo_object_from_servant (servant)); + + parse_event_type (&etype, (char *) event_name); + + spi_re_entrant_list_foreach (get_listener_list (registry, etype.type_cat), + remove_listener_cb, listener); } @@ -168,6 +472,7 @@ impl_accessibility_registry_get_desktop_count (PortableServer_Servant servant, return n_desktops; } + /** * getDesktop: * @n: the index of the requested @Desktop. @@ -181,14 +486,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); + bonobo_object_dup_ref (BONOBO_OBJREF (registry->desktop), ev); } else { @@ -196,6 +500,7 @@ impl_accessibility_registry_get_desktop (PortableServer_Servant servant, } } + /** * getDesktopList: * return values: a sequence containing references to @@ -208,118 +513,176 @@ 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; + SpiRegistry *registry = SPI_REGISTRY (bonobo_object_from_servant (servant)); + Accessibility_DesktopSeq *desktops; + + desktops = Accessibility_DesktopSeq__alloc (); + desktops->_length = desktops->_maximum = 1; + desktops->_buffer = Accessibility_DesktopSeq_allocbuf (desktops->_length); + desktops->_buffer [0] = bonobo_object_dup_ref (BONOBO_OBJREF (registry->desktop), ev); + + return desktops; } -static CORBA_Object + +static Accessibility_DeviceEventController impl_accessibility_registry_get_device_event_controller (PortableServer_Servant servant, - CORBA_Environment * ev) + CORBA_Environment *ev) { - /* TODO: not yet implemented! */ - return CORBA_OBJECT_NIL; + SpiRegistry *registry = SPI_REGISTRY (bonobo_object_from_servant (servant)); + + if (!registry->de_controller) + { + registry->de_controller = spi_device_event_controller_new (registry); + } + + return bonobo_object_dup_ref (BONOBO_OBJREF (registry->de_controller), ev); +} + +typedef struct { + CORBA_Environment *ev; + Bonobo_Unknown source; + EventTypeStruct etype; + Accessibility_Event e_out; +} NotifyContext; + +static SpiReEntrantContinue +notify_listeners_cb (GList * const *list, gpointer user_data) +{ + SpiListenerStruct *ls; + NotifyContext *ctx = user_data; +#ifdef SPI_DEBUG + CORBA_string s; +#endif + + ls = (*list)->data; + +#ifdef SPI_LISTENER_DEBUG + fprintf (stderr, "event quarks: %lx %lx %lx\n", ls->event_type_quark, etype.major, etype.minor); + fprintf (stderr, "event name: %s\n", etype.event_name); +#endif + + if ((ls->event_type_quark == ctx->etype.major) || + (ls->event_type_quark == ctx->etype.minor)) + { +#ifdef SPI_DEBUG + fprintf (stderr, "notifying listener %d\n", g_list_index (listeners, l->data)); + s = Accessibility_Accessible__get_name (ctx->source, ev); + fprintf (stderr, "event source name %s\n", s); + CORBA_free (s); +#endif + + ctx->e_out.source = bonobo_object_dup_ref (ctx->source, ctx->ev); + if (BONOBO_EX (ctx->ev)) + { + return SPI_RE_ENTRANT_CONTINUE;; + } + + if ((*list) && (*list)->data == ls) + { + Accessibility_EventListener_notifyEvent ( + (Accessibility_EventListener) ls->listener, &ctx->e_out, ctx->ev); + if (ctx->ev->_major != CORBA_NO_EXCEPTION) + { + g_warning ("Accessibility app error: exception during " + "event notification: %s\n", + CORBA_exception_id (ctx->ev)); + } + } + else /* dup re-entered */ + { + bonobo_object_release_unref (ctx->e_out.source, ctx->ev); + } + } + + return SPI_RE_ENTRANT_CONTINUE; } static void -impl_registry_notify_event (PortableServer_Servant servant, +impl_registry_notify_event (PortableServer_Servant servant, const Accessibility_Event *e, - CORBA_Environment *ev) + CORBA_Environment *ev) { - int n; - int len; - Registry *registry = REGISTRY (bonobo_object_from_servant (servant)); - - /** - * TODO: - * - * distinguish between event types - * find non-strcmp method of matching event types to listeners - * - **/ - - len = g_list_length (registry->listeners); - /* fprintf(stderr, "%d listeners registered\n", len); */ - - for (n=0; ntype); + + list = get_listener_list (registry, ctx.etype.type_cat); + + if (list) + { + ctx.ev = ev; + ctx.e_out = *e; + ctx.source = e->source; + parse_event_type (&ctx.etype, e->type); + + spi_re_entrant_list_foreach (list, notify_listeners_cb, &ctx); + } + + if (e->source != CORBA_OBJECT_NIL) { - /* fprintf(stderr, "notifying listener #%d\n", n);*/ - /* fprintf(stderr, "event name %s\n", Accessibility_Accessible__get_name(e->target, ev));*/ - Accessibility_EventListener_notifyEvent ( - (Accessibility_EventListener) g_list_nth_data (registry->listeners, n), - e, - ev); + Accessibility_Accessible_unref (e->source, ev); } } + 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); - - object_class->finalize = 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->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; + GObjectClass * object_class = (GObjectClass *) klass; + POA_Accessibility_Registry__epv *epv = &klass->epv; + + spi_registry_parent_class = g_type_class_ref (SPI_LISTENER_TYPE); + + object_class->finalize = spi_registry_object_finalize; + + klass->parent_class.epv.notifyEvent = impl_registry_notify_event; + + 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; } static void -registry_init (Registry *registry) +spi_registry_init (SpiRegistry *registry) { - registry->listeners = NULL; - registry->applications = NULL; - registry->desktop = desktop_new(); + registry->object_listeners = NULL; + registry->window_listeners = NULL; + registry->toolkit_listeners = NULL; + 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 = NULL; } -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)); - return retval; + SpiRegistry *retval = g_object_new (SPI_REGISTRY_TYPE, NULL); + bonobo_object_set_immortal (BONOBO_OBJECT (retval), TRUE); + return retval; }