X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=cspi%2Fspi_main.c;h=51174861241b48481d5c66099f34dccf67bb03bb;hb=345cb4da5a1c04d511fab3c6c287a9f0bcd3dad8;hp=2eb15ce92cadbe118f25da626d03d58dca057dbc;hpb=fa9134cfafbbbb69a4aaa5ea280cd507c8e510ba;p=platform%2Fcore%2Fuifw%2Fat-spi2-atk.git diff --git a/cspi/spi_main.c b/cspi/spi_main.c index 2eb15ce..5117486 100644 --- a/cspi/spi_main.c +++ b/cspi/spi_main.c @@ -1,312 +1,488 @@ -#include -#include -#include "spi.h" - -static CORBA_Environment ev; -static AccessibilityRegistry registry; - -Accessible * -Obj_Add (Accessible object) -{ - /* TODO: keep list of live object refs */ - Accessible *oref = g_malloc (sizeof (Accessible)); - *oref = object; - return oref; -} +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * 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 + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ /* * * Basic SPI initialization and event loop function prototypes * */ +#include +#include +#include -int -SPI_init (void) +#undef DEBUG_OBJECTS + +static CORBA_Environment ev = { 0 }; +static Accessibility_Registry registry = CORBA_OBJECT_NIL; +static GHashTable *live_refs = NULL; + +static guint +cspi_object_hash (gconstpointer key) { - int argc = 0; - CORBA_Object oclient; - char *obj_id; + CORBA_Object object = (CORBA_Object) key; - CORBA_exception_init(&ev); + return CORBA_Object_hash (object, 0, &ev); +} - if (!bonobo_init (&argc, NULL)) - { - g_error ("Could not initialize Bonobo"); - } +static gboolean +cspi_object_equal (gconstpointer a, gconstpointer b) +{ + CORBA_Object objecta = (CORBA_Object) a; + CORBA_Object objectb = (CORBA_Object) b; - obj_id = "OAFIID:Accessibility_Registry:proto0.1"; + return CORBA_Object_is_equivalent (objecta, objectb, &ev); +} + +static void +cspi_object_release (gpointer value) +{ + Accessible *a = (Accessible *) value; - oclient = bonobo_activation_activate_from_id (obj_id, 0, NULL, &ev); - if (ev._major != CORBA_NO_EXCEPTION) { - fprintf (stderr, - ("AT-SPI error: during registry activation: %s\n"), - CORBA_exception_id(&ev)); - CORBA_exception_free(&ev); - exit(-1); - } +#ifdef DEBUG_OBJECTS + g_print ("releasing %p => %p\n", a, a->objref); +#endif - if (CORBA_Object_is_nil (oclient, &ev)) + if (!a->on_loan) { - g_error ("Could not locate registry"); - exit(-1); + cspi_release_unref (a->objref); } - registry = (Accessibility_Registry) oclient; + memset (a, 0xaa, sizeof (Accessible)); + a->ref_count = -1; - bonobo_activate (); - - return 0; +#ifndef DEBUG_OBJECTS + free (a); +#endif } -void -SPI_event_main (boolean isGNOMEApp) +SPIBoolean +cspi_accessible_is_a (Accessible *accessible, + const char *interface_name) { - if (isGNOMEApp) bonobo_main(); - else CORBA_ORB_run (bonobo_orb(), &ev); -} + SPIBoolean retval; + Bonobo_Unknown unknown; -/* Not Yet Implemented */ -boolean -SPI_eventIsReady () -{ - return FALSE; + if (accessible == NULL) + { + return FALSE; + } + + unknown = Bonobo_Unknown_queryInterface (CSPI_OBJREF (accessible), + interface_name, cspi_ev ()); + + if (ev._major != CORBA_NO_EXCEPTION) + { + g_error ("Exception '%s' checking if is '%s'", + cspi_exception_get_text (), + interface_name); + } + + if (unknown != CORBA_OBJECT_NIL) + { + retval = TRUE; + cspi_release_unref (unknown); + } + else + { + retval = FALSE; + } + + return retval; } -/* Not Yet Implemented */ -AccessibleEvent * -SPI_nextEvent (boolean waitForEvent) +static GHashTable * +cspi_get_live_refs (void) { - return NULL; + if (!live_refs) + { + live_refs = g_hash_table_new_full (cspi_object_hash, + cspi_object_equal, + NULL, + cspi_object_release); + } + return live_refs; } -void -SPI_exit (void) +CORBA_Environment * +cspi_ev (void) { - exit(0); + CORBA_exception_init (&ev); + return &ev; } -AccessibleEventListener * -CreateEventListener (AccessibleEventListenerCB callback) +Accessibility_Registry +cspi_registry (void) { - AccessibleEventListener *listener = accessible_event_listener_new (); - if (callback) + if (!cspi_ping (registry)) { - accessible_event_listener_add_callback (listener, callback); + registry = cspi_init (); } + return registry; } -boolean -EventListener_addCallback (AccessibleEventListener *listener, - AccessibleEventListenerCB callback) +SPIBoolean +cspi_exception (void) { - accessible_event_listener_add_callback (listener, callback); - return TRUE; -} + SPIBoolean retval; -boolean -EventListener_removeCallback (AccessibleEventListener *listener, - AccessibleEventListenerCB callback) -{ - accessible_event_listener_remove_callback (listener, callback); - return TRUE; + if (ev._major != CORBA_NO_EXCEPTION) + { + CORBA_exception_free (&ev); + retval = TRUE; + } + else + { + retval = FALSE; + } + + return retval; } /* - * - * Global functions serviced by the registry - * + * This method swallows the corba_object BonoboUnknown + * reference, and returns an Accessible associated with it. + * If the reference is loaned, it means it is only valid + * between a borrow / return pair. */ - -boolean -RegisterGlobalEventListener (AccessibleEventListener *listener, - char *eventType) +static Accessible * +cspi_object_get_ref (CORBA_Object corba_object, gboolean on_loan) { - Accessibility_Registry_registerGlobalEventListener ( - registry, - (Accessibility_EventListener) - bonobo_object_corba_objref (bonobo_object (listener)), - eventType, - &ev); + Accessible *ref; - if (ev._major != CORBA_NO_EXCEPTION) + if (corba_object == CORBA_OBJECT_NIL) + { + ref = NULL; + } + else if (!cspi_check_ev ("pre method check: add")) { - return FALSE; + ref = NULL; } else { - return TRUE; + if ((ref = g_hash_table_lookup (cspi_get_live_refs (), corba_object))) + { + g_assert (ref->ref_count > 0); + ref->ref_count++; + if (!on_loan) + { + if (ref->on_loan) /* Convert to a permanant ref */ + { + ref->on_loan = FALSE; + } + else + { + cspi_release_unref (corba_object); + } + } +#ifdef DEBUG_OBJECTS + g_print ("returning cached %p => %p\n", ref, ref->objref); +#endif + } + else + { + ref = malloc (sizeof (Accessible)); + ref->objref = corba_object; + ref->ref_count = 1; + ref->on_loan = on_loan; +#ifdef DEBUG_OBJECTS + g_print ("allocated %p => %p\n", ref, corba_object); +#endif + g_hash_table_insert (cspi_get_live_refs (), ref->objref, ref); + } } -} -int -GetDesktopCount () -{ - return Accessibility_Registry_getDesktopCount (registry, &ev); + return ref; } -Accessible -*getDesktop (int n) +Accessible * +cspi_object_add (CORBA_Object corba_object) { - return Obj_Add (Accessibility_Registry_getDesktop (registry, (CORBA_short) n, &ev)); + return cspi_object_get_ref (corba_object, FALSE); } -int -getDesktopList (Accessible **list) +Accessible * +cspi_object_borrow (CORBA_Object corba_object) { - *list = NULL; - return 0; + return cspi_object_get_ref (corba_object, TRUE); } -/* Not Yet Implemented */ void -registerKeystrokeListener (KeystrokeListener *listener) +cspi_object_return (Accessible *accessible) { - ; + g_return_if_fail (accessible != NULL); + + if (!accessible->on_loan || + accessible->ref_count == 1) + { + cspi_object_unref (accessible); + } + else /* Convert to a permanant ref */ + { + accessible->on_loan = FALSE; + accessible->objref = cspi_dup_ref (accessible->objref); + accessible->ref_count--; + } +} + +Accessible * +cspi_object_take (CORBA_Object corba_object) +{ + Accessible *accessible; + accessible = cspi_object_borrow (corba_object); + + cspi_object_ref (accessible); + /* + * if the remote object is dead, + * cspi_object_return will throw an exception. + * FIXME: what clears that exception context ever ? + */ + cspi_object_return (accessible); + if (cspi_exception ()) + { + cspi_object_unref (accessible); + accessible = NULL; + } + return accessible; } -/* Not Yet Implemented */ void -generateKeyEvent (long keyCode, long meta) +cspi_object_ref (Accessible *accessible) { - ; + g_return_if_fail (accessible != NULL); + + accessible->ref_count++; } -/* Not Yet Implemented */ void -generateMouseEvent (long x, long y, char *name) +cspi_object_unref (Accessible *accessible) { - ; -} + if (accessible == NULL) + { + return; + } -/* - * - * Accessible function prototypes - * - */ + if (--accessible->ref_count == 0) + { + g_hash_table_remove (cspi_get_live_refs (), accessible->objref); + } +} -int -Accessible_ref (Accessible *obj) +static void +cspi_cleanup (void) { - Accessibility_Accessible_ref (*obj, &ev); - return 0; + GHashTable *refs; + + refs = live_refs; + live_refs = NULL; + if (refs) + { + g_hash_table_destroy (refs); + } + + if (registry != CORBA_OBJECT_NIL) + { + cspi_release_unref (registry); + registry = CORBA_OBJECT_NIL; + } } +static gboolean SPI_inited = FALSE; +/** + * SPI_init: + * + * Connects to the accessibility registry and initializes the SPI. + * + * Returns: 0 on success, otherwise an integer error code. + **/ int -Accessible_unref (Accessible *obj) +SPI_init (void) { - Accessibility_Accessible_unref (*obj, &ev); - return 0; -} + if (SPI_inited) + { + return 1; + } -char * -Accessible_getName (Accessible *obj) -{ - return Accessibility_Accessible__get_name (*obj, &ev); -} + SPI_inited = TRUE; -char * -Accessible_getDescription (Accessible *obj) -{ - return Accessibility_Accessible__get_description (*obj, &ev); -} + CORBA_exception_init (&ev); -Accessible * -Accessible_getParent (Accessible *obj) -{ - return Obj_Add (Accessibility_Accessible__get_parent (*obj, &ev)); + registry = cspi_init (); + + g_atexit (cspi_cleanup); + + return 0; } -long -Accessible_getChildCount (Accessible *obj) +/** + * SPI_event_main: + * + * Starts/enters the main event loop for the SPI services. + * + * (NOTE: This method does not return control, it is exited via a call to + * SPI_event_quit () from within an event handler). + * + **/ +void +SPI_event_main (void) { - return Accessibility_Accessible_getChildCount (*obj, &ev); + cspi_main (); } -Accessible * -Accessible_getChildAtIndex (Accessible *obj, - long childIndex) +/** + * SPI_event_quit: + * + * Quits the last main event loop for the SPI services, + * see SPI_event_main + **/ +void +SPI_event_quit (void) { - return Obj_Add (Accessibility_Accessible_getChildAtIndex (*obj, childIndex, &ev)); + cspi_main_quit (); } -long -Accessible_getIndexInParent (Accessible *obj) +/** + * SPI_eventIsReady: + * + * Checks to see if an SPI event is waiting in the event queue. + * Used by clients that don't wish to use SPI_event_main(). + * + * Not Yet Implemented. + * + * Returns: #TRUE if an event is waiting, otherwise #FALSE. + * + **/ +SPIBoolean +SPI_eventIsReady () { - return Accessibility_Accessible_getIndexInParent (*obj, &ev); + return FALSE; } -/* Not Yet Implemented */ -AccessibleRelation ** -Accessible_getRelationSet (Accessible *obj) +/** + * SPI_nextEvent: + * @waitForEvent: a #SPIBoolean indicating whether to block or not. + * + * Gets the next event in the SPI event queue; blocks if no event + * is pending and @waitForEvent is #TRUE. + * Used by clients that don't wish to use SPI_event_main(). + * + * Not Yet Implemented. + * + * Returns: the next #AccessibleEvent in the SPI event queue. + **/ +AccessibleEvent * +SPI_nextEvent (SPIBoolean waitForEvent) { return NULL; } -/* Not Yet Implemented */ -char * -Accessible_getRole (Accessible *obj) +static void +report_leaked_ref (gpointer key, gpointer val, gpointer user_data) { - return ""; -} + char *name, *role; + Accessible *a = (Accessible *) val; + + name = Accessible_getName (a); + if (cspi_exception ()) + { + name = NULL; + } -/* Not Yet Implemented */ -AccessibleStateSet * -Accessible_getStateSet (Accessible *obj) -{ - return NULL; + role = Accessible_getRoleName (a); + if (cspi_exception ()) + { + role = NULL; + } + + fprintf (stderr, "leaked %d references to object %s, role %s %p\n", + a->ref_count, name ? name : "", role ? role : "", a); + + SPI_freeString (name); } -/* +/** + * SPI_exit: * - * AccessibleApplication function prototypes + * Disconnects from the Accessibility Registry and releases + * any floating resources. Call only once at exit. * - */ - + * Returns: 0 if there were no leaks, otherwise non zero. + **/ int -AccessibleApplication_ref (AccessibleApplication *obj) +SPI_exit (void) { - Accessibility_Application_ref (*obj, &ev); - return 0; -} + int leaked; -int -AccessibleApplication_unref (AccessibleApplication *obj) -{ - Accessibility_Application_unref (*obj, &ev); - return 0; -} + if (!SPI_inited) + { + return 0; + } -char * -AccessibleApplication_getToolkitName (AccessibleApplication *obj) -{ - return Accessibility_Application__get_toolkitName (*obj, &ev); -} + SPI_inited = FALSE; -char * -AccessibleApplication_getVersion (AccessibleApplication *obj) -{ - return Accessibility_Application__get_version (*obj, &ev); -} + if (live_refs) + { + leaked = g_hash_table_size (live_refs); +#define PRINT_LEAKS +#ifdef PRINT_LEAKS + g_hash_table_foreach (live_refs, report_leaked_ref, NULL); +#endif + } + else + { + leaked = 0; + } -long -AccessibleApplication_getID (AccessibleApplication *obj) -{ - return Accessibility_Application__getID (*obj, &ev); -} +#ifdef DEBUG_OBJECTS + if (leaked) + { + fprintf (stderr, "Leaked %d SPI handles\n", leaked); + } +#endif -/* Not Yet Implemented */ -boolean -AccessibleApplication_pause (AccessibleApplication *obj) -{ - return FALSE; + cspi_cleanup (); + + fprintf (stderr, "bye-bye!\n"); + + return leaked; } -/* Not Yet Implemented */ -boolean -AccessibleApplication_resume (AccessibleApplication *obj) +/** + * SPI_freeString: + * @s: a character string returned from another at-spi call. + * + * Free a character string returned from an at-spi call. Clients of + * at-spi should use this function instead of free () or g_free(). + * A NULL string @s will be silently ignored. + * This API should not be used to free strings + * from other libraries or allocated by the client. + **/ +void +SPI_freeString (char *s) { - return FALSE; + if (s) + { + CORBA_free (s); + } } -