2002-01-08 Michael Meeks <michael@ximian.com>
authormichael <michael@e2bd861d-eb25-0410-b326-f6ed22b6b98c>
Tue, 8 Jan 2002 09:11:47 +0000 (09:11 +0000)
committermichael <michael@e2bd861d-eb25-0410-b326-f6ed22b6b98c>
Tue, 8 Jan 2002 09:11:47 +0000 (09:11 +0000)
* registryd/registry.c (parse_event_type): remove strndup.

* libspi/Makefile.am (libspi_la_SOURCES): remove
sources already included in the headers section.

* libspi/util.c: add.

* libspi/spi-private.h: add.

* registryd/registry.c: update to moved list iterators.

2002-01-05  Michael Meeks  <michael@ximian.com>

* test/simple-at.c (main): upd. auto-module set to atk-bridge

* test/test-simple.c (main): ditto.

2002-01-04  Michael Meeks  <michael@ximian.com>

* libspi/accessible.c (spi_accessible_new): remove 2nd,
redundant construct.

* registryd/registry.c
(get_listener_list): impl.
(impl_accessibility_registry_register_global_event_listener):
re-impl. to simplify using ~, remove dodgy const cast off.
(parse_event_type): constify.
(impl_accessibility_registry_deregister_global_event_listener_all):
re-write, more efficiency and simplicity, kill re-enterancy
hazard.
(compare_listener_corbaref, compare_corba_objects),
(compare_listener_quarks): define out.
(impl_accessibility_registry_deregister_global_event_listener):
re-write for effiency, and nail re-enterancy hazard.
(impl_accessibility_registry_get_desktop_list): impl.
(re_enterant_list_delete_link): impl.
(re_enterant_list_foreach): impl.
(remove_listener_cb): impl.
(_registry_notify_listeners): kill.
(notify_listeners_cb): impl.

* cspi/spi_registry.c (SPI_freeDesktopList): impl.
(SPI_getDesktopList): impl.

* test/test-simple.c (test_desktop): test the methods.

2002-01-03  Michael Meeks  <michael@ximian.com>

* cspi/spi_event.c (SPI_createAccessibleKeySet): dup the
keystrings since we free them
(SPI_freeAccessibleKeySet): in here.

* libspi/accessible.c (spi_accessible_new): kill warning,
wonder what is going on with the constructor here.

git-svn-id: http://svn.gnome.org/svn/at-spi/trunk@203 e2bd861d-eb25-0410-b326-f6ed22b6b98c

13 files changed:
ChangeLog
cspi/spi.h
cspi/spi_event.c
cspi/spi_registry.c
docs/reference/cspi/tmpl/spi_registry.sgml
libspi/Makefile.am
libspi/accessible.c
libspi/spi-private.h [new file with mode: 0644]
libspi/util.c [new file with mode: 0644]
registryd/deviceeventcontroller.c
registryd/registry.c
test/simple-at.c
test/test-simple.c

index 1c35935..ae22c96 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,60 @@
+2002-01-08  Michael Meeks  <michael@ximian.com>
+
+       * registryd/registry.c (parse_event_type): remove strndup.
+
+       * libspi/Makefile.am (libspi_la_SOURCES): remove
+       sources already included in the headers section.
+
+       * libspi/util.c: add.
+
+       * libspi/spi-private.h: add.
+
+       * registryd/registry.c: update to moved list iterators.
+
+2002-01-05  Michael Meeks  <michael@ximian.com>
+
+       * test/simple-at.c (main): upd. auto-module set to atk-bridge
+
+       * test/test-simple.c (main): ditto.
+
+2002-01-04  Michael Meeks  <michael@ximian.com>
+
+       * libspi/accessible.c (spi_accessible_new): remove 2nd,
+       redundant construct.
+
+       * registryd/registry.c
+       (get_listener_list): impl.
+       (impl_accessibility_registry_register_global_event_listener):
+       re-impl. to simplify using ~, remove dodgy const cast off.
+       (parse_event_type): constify.
+       (impl_accessibility_registry_deregister_global_event_listener_all): 
+       re-write, more efficiency and simplicity, kill re-enterancy
+       hazard.
+       (compare_listener_corbaref, compare_corba_objects),
+       (compare_listener_quarks): define out.
+       (impl_accessibility_registry_deregister_global_event_listener): 
+       re-write for effiency, and nail re-enterancy hazard.
+       (impl_accessibility_registry_get_desktop_list): impl.
+       (re_enterant_list_delete_link): impl.
+       (re_enterant_list_foreach): impl.
+       (remove_listener_cb): impl.
+       (_registry_notify_listeners): kill.
+       (notify_listeners_cb): impl.
+
+       * cspi/spi_registry.c (SPI_freeDesktopList): impl.
+       (SPI_getDesktopList): impl.
+
+       * test/test-simple.c (test_desktop): test the methods.
+
+2002-01-03  Michael Meeks  <michael@ximian.com>
+
+       * cspi/spi_event.c (SPI_createAccessibleKeySet): dup the
+       keystrings since we free them
+       (SPI_freeAccessibleKeySet): in here.
+
+       * libspi/accessible.c (spi_accessible_new): kill warning,
+       wonder what is going on with the constructor here.
+
 2002-03-01  Bill Haneman <bill.haneman@sun.com>
 
        * libspi/accessible.c (spi_accessible_new ()) :
index 7ebe098..4afe11e 100644 (file)
@@ -200,7 +200,8 @@ SPIBoolean SPI_deregisterAccessibleKeystrokeListener (
 
 int         SPI_getDesktopCount                  (void);
 Accessible *SPI_getDesktop                       (int i);
-int         SPI_getDesktopList                   (Accessible **list);
+int         SPI_getDesktopList                   (Accessible ***desktop_list);
+void        SPI_freeDesktopList                  (Accessible  **desktop_list);
 
 SPIBoolean  SPI_generateKeyboardEvent            (long int                    keyval,
                                                  char                       *keystring,
index 8550a9a..469dedc 100644 (file)
@@ -69,7 +69,8 @@ SPI_freeAccessibleKeySet (AccessibleKeySet *keyset)
  *
  **/
 AccessibleKeySet *
-SPI_createAccessibleKeySet (int len, const char *keysyms, short *keycodes, const char **keystrings)
+SPI_createAccessibleKeySet (int len, const char *keysyms, short *keycodes,
+                           const char **keystrings)
 {
   AccessibleKeySet *keyset = g_new0 (AccessibleKeySet, 1);
   int i, keysym_len = 0;
@@ -93,8 +94,14 @@ SPI_createAccessibleKeySet (int len, const char *keysyms, short *keycodes, const
         {
           keyset->keysyms [i] = 0;
         }
-      if (keycodes) keyset->keycodes [i] = keycodes [i];
-      if (keystrings) keyset->keystrings [i] = keystrings [i];
+      if (keycodes)
+        {
+         keyset->keycodes [i] = keycodes [i];
+       }
+      if (keystrings)
+        {
+         keyset->keystrings [i] = g_strdup (keystrings [i]);
+       }
     }
   return keyset;       
 }
index 6771576..287bc0e 100644 (file)
@@ -219,10 +219,11 @@ SPI_getDesktop (int i)
 
 /**
  * SPI_getDesktopList:
- * @list: a pointer to an array of #Accessible objects.
+ * @desktop_list: a pointer to an array of #Accessible references.
  *
  * Get the list of virtual desktops.  On return, @list will point
- *     to a newly-created array of virtual desktop pointers.
+ *     to a newly-created, NULL terminated array of virtual desktop
+ *     pointers.
  *     It is the responsibility of the caller to free this array when
  *     it is no longer needed.
  *
@@ -233,10 +234,55 @@ SPI_getDesktop (int i)
  *          placed in the list pointed to by parameter @list.
  **/
 int
-SPI_getDesktopList (Accessible **list)
+SPI_getDesktopList (Accessible ***desktop_list)
 {
-  *list = NULL;
-  return 0;
+  int i;
+  Accessible **list;
+  Accessibility_DesktopSeq *desktops;
+
+  if (!desktop_list)
+         return 0;
+
+  *desktop_list = NULL;
+
+  desktops = Accessibility_Registry_getDesktopList (cspi_registry (),
+                                                   cspi_ev ());
+
+  cspi_return_val_if_ev ("getting desktop list", 0);
+
+  list = g_new0 (Accessible *, desktops->_length + 1);
+
+  for (i = 0; i < desktops->_length; i++)
+    {
+      list [i] = cspi_object_add (
+             CORBA_Object_duplicate (desktops->_buffer [i], cspi_ev ()));
+    }
+  list [i] = NULL;
+
+  CORBA_free (desktops);
+
+  *desktop_list = list;
+
+  return i;
+}
+
+/**
+ * SPI_freeDesktopList:
+ * @desktop_list: a pointer to an array of #Accessible objects
+ * as returned from @SPI_getDesktopList
+ * 
+ * This routine frees the memory associated with the list.
+ **/
+void
+SPI_freeDesktopList (Accessible **desktop_list)
+{
+  Accessible **p;
+  
+  for (p = desktop_list; p && *p; p++)
+    {
+      cspi_object_unref (*p);
+    }
+  g_free (desktop_list);
 }
 
 /**
index 9b7abaf..e00a45f 100644 (file)
@@ -47,8 +47,10 @@ Registry queries
 
 </para>
 
-@list: 
+@desktop_list: 
 @Returns: 
+<!-- # Unused Parameters # -->
+@list: 
 
 
 <!-- ##### USER_FUNCTION AccessibleKeystrokeListenerCB ##### -->
index 53235c3..2b51828 100644 (file)
@@ -12,27 +12,28 @@ CFLAGS += $(DEBUG_CFLAGS)
 
 libspiincludedir = $(includedir)/at-spi-1.0/libspi
 
-libspiinclude_HEADERS = Accessibility.h \
-                       accessible.h \
-                       eventlistener.h \
-                       action.h \
-                        application.h \
-                       base.h \
-                       component.h \
-                       editabletext.h\
-                       hyperlink.h\
-                       hypertext.h\
-                       image.h \
-                       keystrokelistener.h \
-                       keymasks.h \
-                       libspi.h \
-                        listener.h \
-                       relation.h \
-                       remoteobject.h \
-                       selection.h \
-                       table.h \
-                       text.h \
-                       value.h
+libspiinclude_HEADERS =                \
+       Accessibility.h         \
+       accessible.h            \
+       eventlistener.h         \
+       action.h                \
+       application.h           \
+       base.h                  \
+       component.h             \
+       editabletext.h          \
+       hyperlink.h             \
+       hypertext.h             \
+       image.h                 \
+       keystrokelistener.h     \
+       keymasks.h              \
+       libspi.h                \
+       listener.h              \
+       relation.h              \
+       remoteobject.h          \
+       selection.h             \
+       table.h                 \
+       text.h                  \
+       value.h
 
 IDL_OUT = Accessibility.h Accessibility-stubs.c Accessibility-skels.c Accessibility-common.c
 
@@ -59,46 +60,31 @@ IDL_DEPS = \
        $(top_srcdir)/idl/Accessibility_Value.idl
 
 
-
 BUILT_SOURCES = $(IDL_OUT) Accessibility-imodule.c
 CLEANFILES+=$(IDL_OUT) Accessibility-imodule.c
 
-libspi_la_SOURCES = accessible.c         \
-                    accessible.h         \
-                    action.c\
-                   action.h\
-                   application.c        \
-                    application.h        \
-                   base.c               \
-                   component.c          \
-                   component.h          \
-                   editabletext.c\
-                   editabletext.h\
-                   hyperlink.c\
-                   hyperlink.h\
-                   hypertext.c\
-                   hypertext.h\
-                   image.c\
-                   image.h\
-                   keystrokelistener.c\
-                   keystrokelistener.h\
-                   relation.c\
-                   relation.h\
-                   remoteobject.c\
-                   remoteobject.h\
-                   selection.c\
-                   selection.h\
-                   table.c\
-                   table.h\
-                   text.c\
-                   text.h\
-                   value.c\
-                   value.h\
-                    listener.c           \
-                    listener.h           \
-                   eventlistener.c      \
-                   keymasks.h          \
-                    $(IDL_OUT)
+libspi_la_SOURCES =            \
+       accessible.c            \
+       action.c                \
+       application.c           \
+       base.c                  \
+       component.c             \
+       editabletext.c          \
+       hyperlink.c             \
+       hypertext.c             \
+       image.c                 \
+       keystrokelistener.c     \
+       relation.c              \
+       remoteobject.c          \
+       selection.c             \
+       spi-private.h           \
+       table.c                 \
+       text.c                  \
+       util.c                  \
+       value.c                 \
+       listener.c              \
+       eventlistener.c         \
+       $(IDL_OUT)
 
 IDLFLAGS = -I$(BONOBO_ACTIVATION_IDL_DIR) \
           -I$(LIBBONOBO_IDL_DIR)         \
index 4f408f2..445b5fd 100644 (file)
@@ -454,7 +454,7 @@ spi_accessible_new (AtkObject *o)
 
    else if (SPI_IS_REMOTE_OBJECT (o))
      {
-       retval = spi_remote_object_get_accessible (o); 
+       retval = spi_remote_object_get_accessible (SPI_REMOTE_OBJECT (o)); 
      }
    else
      {
@@ -462,8 +462,6 @@ spi_accessible_new (AtkObject *o)
 
        spi_base_construct (SPI_BASE (retval), G_OBJECT(o));
 
-       spi_base_construct (SPI_BASE (retval), G_OBJECT(o));
-
        /* aggregate appropriate SPI interfaces based on ATK interfaces */
  
        if (ATK_IS_ACTION (o))
diff --git a/libspi/spi-private.h b/libspi/spi-private.h
new file mode 100644 (file)
index 0000000..f69f8a8
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef SPI_PRIVATE_H_
+#define SPI_PRIVATE_H_
+
+#include <glib/glist.h>
+
+G_BEGIN_DECLS
+
+typedef enum {
+       SPI_RE_ENTERANT_CONTINUE = 0,
+       SPI_RE_ENTERANT_TERMINATE
+} SpiReEnterantContinue;
+
+typedef SpiReEnterantContinue (*SpiReEnterantFn) (GList * const *list,
+                                                 gpointer       user_data);
+
+void spi_re_enterant_list_delete_link (GList * const *element_ptr);
+void spi_re_enterant_list_foreach     (GList         **list,
+                                      SpiReEnterantFn func,
+                                      gpointer        user_data);
+
+G_END_DECLS
+
+#endif /* SPI_PRIVATE_H_ */
diff --git a/libspi/util.c b/libspi/util.c
new file mode 100644 (file)
index 0000000..ea6873c
--- /dev/null
@@ -0,0 +1,81 @@
+#include <glib/gmessages.h>
+#include <glib/gslist.h>
+
+#include "spi-private.h"
+
+typedef struct {
+       GList **list;
+       GList  *iterator;
+} Iteration;
+
+static GSList *working_list = NULL; /* of Iteration */
+
+/*
+ *   deletes an element from the list - in a re-enterant
+ * safe fashion; advances the element pointer to the next
+ * element.
+ */
+void
+spi_re_enterant_list_delete_link (GList * const *element_ptr)
+{
+  GSList    *l;
+  GList     *next;
+  GList     *element;
+  gboolean   first_item;
+
+  g_return_if_fail (element_ptr != NULL);
+
+  element = *element_ptr;
+  g_return_if_fail (element != NULL);
+
+  next = element->next;
+  first_item = (element->prev == NULL);
+
+  g_list_remove_link (NULL, element);
+
+  for (l = working_list; l; l = l->next)
+    {
+       Iteration *i = l->data;
+
+       if (i->iterator == element)
+         {
+           i->iterator = next;
+         }
+
+       if (first_item && *(i->list) == element)
+         {
+           *(i->list) = next;
+         }
+    }
+
+  g_list_free_1 (element);
+}
+
+void
+spi_re_enterant_list_foreach (GList         **list,
+                             SpiReEnterantFn func,
+                             gpointer        user_data)
+{
+       Iteration i;
+
+       if (!list)
+         {
+            return;
+         }
+
+       i.list = list;
+       i.iterator = *list;
+
+       working_list = g_slist_prepend (working_list, &i);
+
+       while (i.iterator) {
+               GList *l = i.iterator;
+
+               func (&i.iterator, user_data);
+
+               if (i.iterator == l)
+                       i.iterator = i.iterator->next;
+       }
+
+       working_list = g_slist_remove (working_list, &i);
+}
index 16daff6..23587fa 100644 (file)
@@ -370,8 +370,8 @@ spi_key_set_contains_key (Accessibility_KeySet *key_set, const Accessibility_Dev
 }
 
 static gboolean
-spi_key_eventtype_seq_contains_event (Accessibility_KeyEventTypeSeq *type_seq,
-                                 const Accessibility_DeviceEvent *key_event)
+spi_key_eventtype_seq_contains_event (Accessibility_KeyEventTypeSeq   *type_seq,
+                                     const Accessibility_DeviceEvent *key_event)
 {
   gint i;
   gint len;
@@ -400,8 +400,8 @@ spi_key_eventtype_seq_contains_event (Accessibility_KeyEventTypeSeq *type_seq,
 
 static gboolean
 spi_key_event_matches_listener (const Accessibility_DeviceEvent *key_event,
-                           DEControllerKeyListener *listener,
-                           CORBA_boolean is_system_global)
+                               DEControllerKeyListener         *listener,
+                               CORBA_boolean                    is_system_global)
 {
   g_print ("checking keycode %d\n", (int) key_event->hw_code);
   if ((key_event->modifiers == (CORBA_unsigned_short) (listener->mask & 0xFFFF)) &&
index b482255..50b6aeb 100644 (file)
@@ -29,6 +29,7 @@
 #  include <stdio.h>
 #endif
 
+#include <bonobo/bonobo-exception.h>
 #include "registry.h"
 
 /* Our parent GObject type  */
@@ -58,17 +59,11 @@ typedef struct {
 
 typedef struct {
   Accessibility_EventListener listener;
-  GQuark event_type_quark;
+  GQuark            event_type_quark;
   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);
 
 SpiListenerStruct *
@@ -79,6 +74,7 @@ spi_listener_struct_new (Accessibility_EventListener listener, CORBA_Environment
   return retval;
 }
 
+
 void
 spi_listener_struct_free (SpiListenerStruct *ls, CORBA_Environment *ev)
 {
@@ -86,15 +82,22 @@ spi_listener_struct_free (SpiListenerStruct *ls, CORBA_Environment *ev)
   g_free (ls);
 }
 
-/* GObject::finalize */
+
 static void
 spi_registry_object_finalize (GObject *object)
 {
-        SpiRegistry *registry = SPI_REGISTRY (object);
+  printf ("spi_registry_object_finalize called\n");
 
-        printf("spi_registry_object_finalize called\n");
-       /* TODO: unref deviceeventcontroller, which disconnects key listener */
-        G_OBJECT_CLASS (spi_registry_parent_class)->finalize (object);
+  /* 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;
 }
 
 /**
@@ -117,7 +120,7 @@ impl_accessibility_registry_register_application (PortableServer_Servant servant
 #endif
   spi_desktop_add_application (registry->desktop, application);
 
-  Accessibility_Application__set_id (application, _get_unique_id(), ev);
+  Accessibility_Application__set_id (application, _get_unique_id (), ev);
 
   /*
    * TODO: change the implementation below to a WM-aware one;
@@ -125,6 +128,7 @@ impl_accessibility_registry_register_application (PortableServer_Servant servant
    */
 }
 
+#ifdef USE_A_HASH_IN_FUTURE
 static gint
 compare_corba_objects (gconstpointer p1, gconstpointer p2)
 {
@@ -139,6 +143,7 @@ compare_corba_objects (gconstpointer p1, gconstpointer p2)
   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)
@@ -167,16 +172,18 @@ register_with_toolkits (SpiRegistry *spi_registry_bonobo_object, EventTypeStruct
          Accessibility_Application_registerToolkitEventListener (app,
                                                                  registry,
                                                                  CORBA_string_dup (etype->event_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);
+       return (((SpiListenerStruct *)p2)->event_type_quark !=
+               ((SpiListenerStruct *)p1)->event_type_quark);
 }
 
 static gint
@@ -185,15 +192,16 @@ 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, char *event_name)
+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_strndup(event_name, 255);
+  split_string = g_strsplit (event_name, ":", 4);
+  etype->event_name = g_strdup (event_name);
 
   if (!g_ascii_strncasecmp (event_name, "focus:", 6))
     {
@@ -273,134 +281,133 @@ impl_accessibility_registry_deregister_application (PortableServer_Servant serva
 #endif
 }
 
+static GList **
+get_listener_list (SpiRegistry      *registry,
+                  EventTypeCategory cat)
+{
+  GList **ret;
+  
+  switch (cat)
+    {
+      case ETYPE_OBJECT:
+      case ETYPE_PROPERTY:
+      case ETYPE_FOCUS:
+        ret = &registry->object_listeners;
+       break;
+      case ETYPE_WINDOW:
+       ret = &registry->window_listeners;
+       break;
+      case ETYPE_TOOLKIT:
+       ret = &registry->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)
+       PortableServer_Servant      servant,
+       Accessibility_EventListener listener,
+       const CORBA_char           *event_name,
+       CORBA_Environment          *ev)
 {
   SpiRegistry *registry = SPI_REGISTRY (bonobo_object_from_servant (servant));
   SpiListenerStruct *ls = spi_listener_struct_new (listener, ev);
   EventTypeStruct etype;
+  GList          **list;
 
   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);
+  parse_event_type (&etype, event_name);
   ls->event_type_quark = etype.major;
   ls->event_type_cat = etype.type_cat;
 
-  switch (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
     {
-    case (ETYPE_FOCUS) :
-    case (ETYPE_OBJECT) :
-    case (ETYPE_PROPERTY) :
-      registry->object_listeners =
-        g_list_append (registry->object_listeners, ls);
-      break;
-    case (ETYPE_WINDOW) :
-      /* Support for Window Manager Events is not yet implemented */
-      spi_listener_struct_free (ls, ev);
-      break;
-    case (ETYPE_TOOLKIT) :
-      registry->toolkit_listeners =
-        g_list_append (registry->toolkit_listeners, ls);
-      register_with_toolkits (registry, &etype, ev);
-      break;
-    default:
       spi_listener_struct_free (ls, ev);
-      break;
     }
 }
 
+static void
+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_enterant_list_delete_link (list);
+       spi_listener_struct_free (ls, &ev);
+    }
+
+  CORBA_exception_free (&ev);
+}
+
 /*
  * 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)
+       PortableServer_Servant      servant,
+       Accessibility_EventListener listener,
+       CORBA_Environment          *ev)
 {
+  int i;
+  GList **lists[2];
   SpiRegistry *registry = SPI_REGISTRY (bonobo_object_from_servant (servant));
-  SpiListenerStruct *ls = spi_listener_struct_new (listener, ev);
-  GList *list;
-  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.
-   */
+  lists[0] = &registry->object_listeners;
+  lists[1] = &registry->window_listeners;
+  lists[2] = &registry->toolkit_listeners;
 
-  while (list)
-    {
-      spi_listener_struct_free ((SpiListenerStruct *) list->data, ev);
-      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)
+  for (i = 0; i < sizeof (lists) / sizeof (lists[0]); i++)
     {
-      spi_listener_struct_free ((SpiListenerStruct *) list->data, ev);
-      registry->toolkit_listeners = g_list_delete_link (registry->toolkit_listeners, list);
-      list = g_list_find_custom (registry->toolkit_listeners, ls, compare_listener_corbaref);
+      spi_re_enterant_list_foreach (lists [i], remove_listener_cb, listener);
     }
-  spi_listener_struct_free (ls, ev);
 }
 
+
 /*
  * CORBA Accessibility::Registry::deregisterGlobalEventListener method implementation
  */
 static void
 impl_accessibility_registry_deregister_global_event_listener (
-                                                    PortableServer_Servant  servant,
-                                                    Accessibility_EventListener listener,
-                                                    const CORBA_char * event_name,
-                                                    CORBA_Environment      *ev)
+       PortableServer_Servant      servant,
+       Accessibility_EventListener listener,
+       const CORBA_char           *event_name,
+       CORBA_Environment          *ev)
 {
-  SpiRegistry *registry = SPI_REGISTRY (bonobo_object_from_servant (servant));
-  SpiListenerStruct ls;
+  SpiRegistry    *registry;
   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 = &registry->object_listeners;
-      break;
-    case (ETYPE_WINDOW) :
-      /* Support for Window Manager Events is not yet implemented */
-      listeners = NULL;
-      break;
-    case (ETYPE_TOOLKIT) :
-      listeners = &registry->toolkit_listeners;
-      break;
-    default:
-      listeners = NULL;
-      break;
-    }
 
-  if (!listeners)
-         return;
+  registry = SPI_REGISTRY (bonobo_object_from_servant (servant));
 
-  ls.event_type_quark = etype.major;
-  list = g_list_find_custom (*listeners, &ls, compare_listener_quarks);
+  parse_event_type (&etype, (char *) event_name);
 
-  while (list)
-    {
-      spi_listener_struct_free ((SpiListenerStruct *) list->data, ev);
-      *listeners = g_list_delete_link (*listeners, list);
-      list = g_list_find_custom (*listeners, &ls, compare_listener_quarks);
-    }
+  spi_re_enterant_list_foreach (get_listener_list (registry, etype.type_cat),
+                           remove_listener_cb, listener);
 }
 
 
@@ -422,6 +429,7 @@ impl_accessibility_registry_get_desktop_count (PortableServer_Servant servant,
   return n_desktops;
 }
 
+
 /**
  * getDesktop:
  * @n: the index of the requested @Desktop.
@@ -449,6 +457,7 @@ impl_accessibility_registry_get_desktop (PortableServer_Servant servant,
     }
 }
 
+
 /**
  * getDesktopList:
  * return values: a sequence containing references to
@@ -461,104 +470,115 @@ 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 Accessibility_DeviceEventController
 impl_accessibility_registry_get_device_event_controller (PortableServer_Servant servant,
-                                                         CORBA_Environment ev)
+                                                         CORBA_Environment     *ev)
 {
   SpiRegistry *registry = SPI_REGISTRY (bonobo_object_from_servant (servant));
+
   if (!registry->device_event_controller)
-    registry->device_event_controller = spi_device_event_controller_new (registry);
+    {
+      registry->device_event_controller = spi_device_event_controller_new (registry);
+    }
 
   return bonobo_object_dup_ref (BONOBO_OBJREF (registry->device_event_controller), ev);
 }
 
+typedef struct {
+  CORBA_Environment  *ev;
+  Bonobo_Unknown      source;
+  EventTypeStruct     etype;
+  Accessibility_Event e_out;
+} NotifyContext;
+
 static void
-impl_registry_notify_event (PortableServer_Servant servant,
-                            const Accessibility_Event *e,
-                            CORBA_Environment *ev)
+notify_listeners_cb (GList * const *list, gpointer user_data)
 {
-  SpiRegistry *registry = SPI_REGISTRY (bonobo_object_from_servant (servant));
-  EventTypeStruct etype;
+  SpiListenerStruct *ls;
+  NotifyContext     *ctx = user_data;
+#ifdef SPI_DEBUG
+  CORBA_string       s;
+#endif
 
-  parse_event_type (&etype, e->type);
+  ls = (*list)->data;
 
-  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;
-    }
-  if (e->source != CORBA_OBJECT_NIL)
+#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))
     {
-      Accessibility_Accessible_unref (e->source, ev);
-    }
-}
+#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;
 
-static long
-_get_unique_id ()
-{
-  static long id = 0;
-  return ++id;
+      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);
+       }
+    }  
 }
 
 static void
-_registry_notify_listeners (GList *listeners,
-                            const Accessibility_Event *e_in,
-                            CORBA_Environment *ev)
+impl_registry_notify_event (PortableServer_Servant     servant,
+                            const Accessibility_Event *e,
+                            CORBA_Environment         *ev)
 {
-  GList              *l;
-  Accessibility_Event e_out;
-  SpiListenerStruct  *ls;
-  EventTypeStruct     etype;
-#ifdef SPI_DEBUG
-  CORBA_string        s;
-#endif
+  SpiRegistry  *registry;
+  GList       **list;
+  NotifyContext ctx;
+
+  registry = SPI_REGISTRY (bonobo_object_from_servant (servant));
 
-  e_out = *e_in;
-  parse_event_type (&etype, e_in->type);
+  parse_event_type (&ctx.etype, e->type);
 
-  for (l = listeners; l; l = l->next)
+  list = get_listener_list (registry, ctx.etype.type_cat);
+
+  if (list)
     {
-      ls = (SpiListenerStruct *) l->data;
+      ctx.ev = ev;
+      ctx.e_out = *e;
+      ctx.source = e->source;
+      parse_event_type (&ctx.etype, e->type);
 
-#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
+      spi_re_enterant_list_foreach (list, notify_listeners_cb, &ctx);
+    }
 
-      if ((ls->event_type_quark == etype.major) || (ls->event_type_quark == etype.minor))
-        {
-#ifdef SPI_DEBUG
-          fprintf (stderr, "notifying listener %d\n", g_list_index (listeners, l->data));
-          s = Accessibility_Accessible__get_name (e_in->source, ev);
-         fprintf (stderr, "event source name %s\n", s);
-         CORBA_free (s);
-#endif
-         e_out.source = bonobo_object_dup_ref (e_in->source, ev);
-          Accessibility_EventListener_notifyEvent ((Accessibility_EventListener) ls->listener,
-                                                   &e_out,
-                                                   ev);
-          if (ev->_major != CORBA_NO_EXCEPTION)
-            {
-              g_warning ("Accessibility app error: exception during event notification: %s\n",
-                      CORBA_exception_id (ev));
-           }
-        }
+  if (e->source != CORBA_OBJECT_NIL)
+    {
+      Accessibility_Accessible_unref (e->source, ev);
     }
 }
 
@@ -601,7 +621,7 @@ spi_registry_init (SpiRegistry *registry)
   registry->object_listeners = NULL;
   registry->window_listeners = NULL;
   registry->toolkit_listeners = NULL;
-  registry->desktop = spi_desktop_new();
+  registry->desktop = spi_desktop_new ();
   registry->device_event_controller = NULL;
   registry->kbd_event_hook = _device_event_controller_hook;
 }
index 149a5f4..8b2c94a 100644 (file)
@@ -73,7 +73,7 @@ main (int argc, char **argv)
   modules = g_getenv ("GTK_MODULES");
   if (!modules || modules [0] == '\0')
     {
-      putenv ("GTK_MODULES=gail:at-bridge");
+      putenv ("GTK_MODULES=gail:atk-bridge");
     }
   modules = NULL;
 
index 47cad07..fa70a6b 100644 (file)
@@ -174,7 +174,7 @@ test_action (AccessibleAction *action)
                fprintf (stderr, "%d: %s (%s);  ", i, s, sd);
                SPI_freeString (s);
                SPI_freeString (sd);
-               /* g_assert (AccessibleAction_doAction (action, i)); */
+               g_assert (AccessibleAction_doAction (action, i));
        }
        fprintf (stderr, "\n");
 }
@@ -182,8 +182,10 @@ test_action (AccessibleAction *action)
 static void
 test_desktop (void)
 {
-       Accessible *desktop;
-       Accessible *application;
+       Accessible  *desktop;
+       Accessible  *application;
+       int          length;
+       Accessible **list;
 
        fprintf (stderr, "Testing desktop...\n");
 
@@ -191,6 +193,10 @@ test_desktop (void)
        desktop = SPI_getDesktop (0);
        g_assert (desktop != NULL);
 
+       g_assert ((length = SPI_getDesktopList (&list)) > 0);
+       g_assert (list[0] == desktop);
+       SPI_freeDesktopList (list);
+
        validate_accessible (desktop, FALSE, FALSE);
 
        application = Accessible_getChildAtIndex (desktop, 0);
@@ -647,7 +653,7 @@ main (int argc, char **argv)
 
        modules = g_getenv ("GTK_MODULES");
        if (!modules || modules [0] == '\0')
-               putenv ("GTK_MODULES=gail:at-bridge");
+               putenv ("GTK_MODULES=gail:atk-bridge");
        modules = NULL;
 
        for (i = 1; i < argc; i++) {