Added API for client-side interception and handling of exceptions.
authorbillh <billh@e2bd861d-eb25-0410-b326-f6ed22b6b98c>
Mon, 9 Jun 2003 22:32:50 +0000 (22:32 +0000)
committerbillh <billh@e2bd861d-eb25-0410-b326-f6ed22b6b98c>
Mon, 9 Jun 2003 22:32:50 +0000 (22:32 +0000)
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

ChangeLog
cspi/bonobo/cspi-bonobo.c
cspi/spi-private.h
cspi/spi.h
cspi/spi_accessible.c
cspi/spi_main.c
test/Makefile.am
test/window-listener-test.c [new file with mode: 0644]

index dbb6d4b..889ad5b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,36 @@
+2003-06-09  Bill Haneman <bill.haneman@sun.com>
+
+       * 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 <padraig.obriain@sun.com>
 
        * cspi/atk-bridge/bridge.c (spi_atk_bridge_exit_func): Check if 
index 8c56407..2422dda 100644 (file)
@@ -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);
 
index 45525d1..feec495 100644 (file)
@@ -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);
index 095d64f..639e61e 100644 (file)
@@ -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
index 4530e7e..377db0f 100644 (file)
@@ -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);
 
index 36da0cd..8d7e50f 100644 (file)
 #include <string.h>
 #include <stdlib.h>
 #include <cspi/spi-private.h>
+#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;
+}
index 3d0f9ed..4d18d5a 100644 (file)
@@ -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 (file)
index 0000000..e99c5b3
--- /dev/null
@@ -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 <stdlib.h>
+#include <unistd.h>
+#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);
+}
+