From: billh Date: Mon, 9 Jun 2003 22:32:50 +0000 (+0000) Subject: Added API for client-side interception and handling of exceptions. X-Git-Tag: AT_SPI2_ATK_0_1_3~785 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=6befa495c5fe3d09f475cc82367ff2d1d252da68;p=platform%2Fupstream%2Fat-spi2-atk.git Added API for client-side interception and handling of exceptions. Added a window-listener-test program for window event tracking. Added very basic implementation of client-side exception API in cspi/bonobo/cspi-bonobo and cspi/spi_main. git-svn-id: http://svn.gnome.org/svn/at-spi/trunk@436 e2bd861d-eb25-0410-b326-f6ed22b6b98c --- diff --git a/ChangeLog b/ChangeLog index dbb6d4b..889ad5b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,36 @@ +2003-06-09 Bill Haneman + + * configure.in: Revved to 1.3.3. (lt-version 9:2:9, .so.0.9.2) + + * cspi/spi.h: + (SPI_dupString): Allow dup-ing of a string such that it's safe to + SPI_freeString it. + New methods for client exception handling and interception. + (SPI_exceptionHandlerPush): New - push a handler onto the stack. + (SPI_exceptionHandlerPop): You guessed it... + (SPI_getSourceType): Return the type of object which offended. + (SPI_getExceptionCode): Return an enum code telling, possibly, + what sort of thing went wrong, i.e. DISCONNECT (object died), etc. + (SPIAccessibleException_getSource): get the source object for + exceptions that come from Accessibles, if SPIExceptionSourceType is + SPI_EXCEPTION_SOURCE_ACCESSIBLE. + (SPIException_getDescription): New, returns a string description of + the problem. [Not yet a stable ABI, strings are not frozen] + + * cspi/spi-private.h: + Added implementation details of opaque SPIException + structure. + + * cspi/spi_main.c: + Implementations of above. Also + (_cspi_exception_throw): new private method that + dispatches exceptions to handlers, called from cspi-bonobo.c + + * cspi/bonobo/cspi-bonobo.c: + (cspi_check_ev): call _cspi_exception_throw. + Don't print a warning message if the exception has been + handled by _cspi_exception_throw. + 2003-06-05 Padraig O'Briain * cspi/atk-bridge/bridge.c (spi_atk_bridge_exit_func): Check if diff --git a/cspi/bonobo/cspi-bonobo.c b/cspi/bonobo/cspi-bonobo.c index 8c56407..2422dda 100644 --- a/cspi/bonobo/cspi-bonobo.c +++ b/cspi/bonobo/cspi-bonobo.c @@ -49,8 +49,10 @@ cspi_check_ev (const char *error_string) err = bonobo_exception_get_text (ev); - fprintf (stderr, "Warning: AT-SPI error: %s: %s\n", - error_string, err); + if (!_cspi_exception_throw (ev, error_string)) { + fprintf (stderr, "Warning: AT-SPI error: %s: %s\n", + error_string, err); + } g_free (err); diff --git a/cspi/spi-private.h b/cspi/spi-private.h index 45525d1..feec495 100644 --- a/cspi/spi-private.h +++ b/cspi/spi-private.h @@ -57,6 +57,14 @@ typedef struct { void *data; } InternalEvent; +struct _SPIException { + SPIExceptionType type; + CORBA_Object source; + CORBA_Environment *ev; + SPIExceptionCode code; + char * desc; +}; + #define CSPI_OBJREF(a) (((Accessible *)(a))->objref) CORBA_Environment *cspi_ev (void); diff --git a/cspi/spi.h b/cspi/spi.h index 095d64f..639e61e 100644 --- a/cspi/spi.h +++ b/cspi/spi.h @@ -179,6 +179,27 @@ typedef enum { SPI_KEYLISTENER_ALL_WINDOWS = 4 } AccessibleKeyListenerSyncType; + +typedef struct _SPIException SPIException; + +typedef SPIBoolean +(* SPIExceptionHandler) (SPIException *err, SPIBoolean is_fatal); + +typedef enum { + SPI_EXCEPTION_UNSPECIFIED, + SPI_EXCEPTION_DISCONNECT, + SPI_EXCEPTION_NO_IMPL, + SPI_EXCEPTION_IO, + SPI_EXCEPTION_BAD_DATA +} SPIExceptionCode; + +typedef enum { + SPI_EXCEPTION_SOURCE_UNSPECIFIED, + SPI_EXCEPTION_SOURCE_ACCESSIBLE, + SPI_EXCEPTION_SOURCE_REGISTRY, + SPI_EXCEPTION_SOURCE_DEVICE +} SPIExceptionType; + typedef unsigned long AccessibleKeyEventMask; typedef unsigned long AccessibleDeviceEventMask; @@ -953,9 +974,23 @@ char * AccessibleDescriptionChangedEvent_getDescriptionString (const Acces char * AccessibleNameChangedEvent_getNameString (const AccessibleEvent *e); -/* Misc methods */ +/* Misc methods and error handling */ void SPI_freeString (char *s); +char* SPI_dupString (char *s); + +SPIBoolean SPI_exceptionHandlerPush (SPIExceptionHandler *handler); + +SPIExceptionHandler* SPI_exceptionHandlerPop (void); + +SPIExceptionType SPIException_getSourceType (SPIException *err); + +SPIExceptionCode SPIException_getExceptionCode (SPIException *err); + +Accessible* SPIAccessibleException_getSource (SPIException *err); + +char* SPIException_getDescription (SPIException *err); + #ifdef __cplusplus } #endif diff --git a/cspi/spi_accessible.c b/cspi/spi_accessible.c index 4530e7e..377db0f 100644 --- a/cspi/spi_accessible.c +++ b/cspi/spi_accessible.c @@ -232,7 +232,7 @@ AccessibleRole_getName (AccessibleRole role) } else { - return g_strdup (""); + return CORBA_string_dup (""); } } @@ -501,8 +501,6 @@ Accessible_getRoleName (Accessible *obj) * Accessible_getStateSet: * @obj: a pointer to the #Accessible object on which to operate. * - * Not Yet Implemented. - * * Returns: a pointer to an #AccessibleStateSet representing the object's current state. **/ AccessibleStateSet * @@ -518,6 +516,8 @@ Accessible_getStateSet (Accessible *obj) CSPI_OBJREF (obj), cspi_ev ()); cspi_return_val_if_ev ("getState", NULL); + cspi_return_val_if_fail (corba_stateset != NULL, NULL); + cspi_return_val_if_fail (cspi_ping (corba_stateset), NULL); corba_seq = Accessibility_StateSet_getStates (corba_stateset, cspi_ev ()); cspi_return_val_if_ev ("getState", NULL); diff --git a/cspi/spi_main.c b/cspi/spi_main.c index 36da0cd..8d7e50f 100644 --- a/cspi/spi_main.c +++ b/cspi/spi_main.c @@ -31,12 +31,14 @@ #include #include #include +#include "spi.h" #undef DEBUG_OBJECTS static CORBA_Environment ev = { 0 }; static Accessibility_Registry registry = CORBA_OBJECT_NIL; static GHashTable *live_refs = NULL; +static GQueue *exception_handlers = NULL; static guint cspi_object_hash (gconstpointer key) @@ -77,6 +79,34 @@ cspi_object_release (gpointer value) #endif } +gboolean +_cspi_exception_throw (CORBA_Environment *ev, char *desc_prefix) +{ + SPIExceptionHandler *handler = NULL; + SPIException ex; + if (exception_handlers) handler = g_queue_peek_head (exception_handlers); + + ex.type = SPI_EXCEPTION_SOURCE_UNSPECIFIED; + ex.source = CORBA_OBJECT_NIL; /* can we get this from here? */ + ex.ev = CORBA_exception__copy (ev); + switch (ev->_major) { + case CORBA_SYSTEM_EXCEPTION: + ex.code = SPI_EXCEPTION_UNSPECIFIED; + break; + case CORBA_USER_EXCEPTION: /* help! how to interpret this? */ + ex.code = SPI_EXCEPTION_UNSPECIFIED; + break; + default: + ex.code = SPI_EXCEPTION_UNSPECIFIED; + break; + } + + if (handler) + return (*handler) (&ex, FALSE); + else + return FALSE; /* means exception was not handled */ +} + SPIBoolean cspi_accessible_is_a (Accessible *accessible, const char *interface_name) @@ -489,3 +519,76 @@ SPI_freeString (char *s) CORBA_free (s); } } + +/** + * DOCUMENT_ME! + **/ +char * +SPI_dupString (char *s) +{ + if (s) + { + return CORBA_string_dup (s); + } + else + return NULL; +} + +/** + * DOCUMENT_ME! + **/ +SPIBoolean SPI_exceptionHandlerPush (SPIExceptionHandler *handler) +{ + if (!exception_handlers) + exception_handlers = g_queue_new (); + g_queue_push_head (exception_handlers, handler); + return TRUE; +} + +/** + * DOCUMENT_ME! + **/ +SPIExceptionHandler* SPI_exceptionHandlerPop (void) +{ + return (SPIExceptionHandler *) g_queue_pop_head (exception_handlers); +} + +/** + * DOCUMENT_ME! + **/ +SPIExceptionType SPIException_getSourceType (SPIException *err) +{ + if (err) + return err->type; + else + return SPI_EXCEPTION_UNSPECIFIED; +} + +/** + * DOCUMENT_ME! + **/ +SPIExceptionCode SPIException_getExceptionCode (SPIException *err) +{ + return err->code; +} + +/** + * DOCUMENT_ME! + **/ +Accessible* SPIAccessibleException_getSource (SPIException *err) +{ + if (err->type == SPI_EXCEPTION_SOURCE_ACCESSIBLE) + return cspi_object_get_ref (err->source, FALSE); + return NULL; +} + +/** + * DOCUMENT_ME! + **/ +char* SPIException_getDescription (SPIException *err) +{ + /* TODO: friendlier error messages? */ + if (err->ev) + return CORBA_exception_id (err->ev); + return NULL; +} diff --git a/test/Makefile.am b/test/Makefile.am index 3d0f9ed..4d18d5a 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,9 +1,11 @@ NULL= -noinst_PROGRAMS = test-simple at app simple-at stress-test keysynth-demo key-listener-test event-listener-test screen-review-test visual-bell keypad-test +noinst_PROGRAMS = test-simple at app simple-at stress-test keysynth-demo key-listener-test event-listener-test window-listener-test screen-review-test visual-bell keypad-test stress_test_SOURCES = stress-test.c +window_listener_test_SOURCES = window-listener-test.c + keypad_test_SOURCES = keypad-test.c key_listener_test_SOURCES = key-listener-test.c diff --git a/test/window-listener-test.c b/test/window-listener-test.c new file mode 100644 index 0000000..e99c5b3 --- /dev/null +++ b/test/window-listener-test.c @@ -0,0 +1,85 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001, 2002, 2003 Sun Microsystems Inc., + * Copyright 2001, 2002, 2003 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. + */ + +#include +#include +#include "../cspi/spi-private.h" /* A hack for now */ + +static void report_window_event (const AccessibleEvent *event, void *user_data); +static AccessibleEventListener *window_listener; + +int +main (int argc, char **argv) +{ + SPI_init (); + + window_listener = SPI_createAccessibleEventListener ( + report_window_event, NULL); + + SPI_registerGlobalEventListener (window_listener, + "window:minimize"); + SPI_registerGlobalEventListener (window_listener, + "window:maximize"); + SPI_registerGlobalEventListener (window_listener, + "window:restore"); + SPI_registerGlobalEventListener (window_listener, + "window:activate"); + SPI_registerGlobalEventListener (window_listener, + "window:deactivate"); + SPI_registerGlobalEventListener (window_listener, + "window:create"); + SPI_registerGlobalEventListener (window_listener, + "window:destroy"); + SPI_registerGlobalEventListener (window_listener, + "window:lower"); + SPI_registerGlobalEventListener (window_listener, + "window:raise"); + SPI_registerGlobalEventListener (window_listener, + "window:resize"); + SPI_registerGlobalEventListener (window_listener, + "window:shade"); + SPI_registerGlobalEventListener (window_listener, + "window:unshade"); + SPI_event_main (); + + putenv ("AT_BRIDGE_SHUTDOWN=1"); + + /* + * TODO: Add a key event listener that calls test_exit, to + * deregister and cleanup appropriately. + */ + + return SPI_exit (); +} + +void +report_window_event (const AccessibleEvent *event, void *user_data) +{ + char *t, *s = Accessible_getName (event->source); + t = AccessibleWindowEvent_getTitleString (event); + if (t == NULL) t = ""; + fprintf (stderr, "%s %s\n", event->type, s, t); + SPI_freeString (s); + SPI_freeString (t); +} +