[g-a-devel]patch to make test-simple work again ...



Hi Bill,

	The appended patch makes my regression tests pass cleanly without
crashing the registryd. I've implemented a 'generic' re-enterancy safe
list iterator, with remove method - this should prolly be pushed down
the dependency stack at some stage; either way - in it's limited way it
should make this scale quite nicely in fact without copying everything
yet again.

	As normal I have a number of stylistic points, and general comments.

	Firstly; I'm surprised to see 'case' being used as a function - mostly
people like to pretend 'return' is a function: "return (3);" or
whatever, seldom have I seen "case (MY_ENUM_VALUE) :" :-) I
re-architected all the code that used that anyway.

	We now track the window manager event listeners since this just dropped
out of the code - removing a number of FIXMEs - I hope it is still
obvious that we don't actually do anything with these listeners yet.

	I'm still rather concerned about registry.c (parse_event_type) this
method is called per event and it does rather a number of curious things
- particularly lots of malloc / free thrash. Also,

What is this in aid of:

  etype->event_name = g_strndup (event_name, 255);

	Why have a built in arbitrary limit ? and do a slower dup ? seems
strange to me.

	Also why do we do:

          etype->major = g_quark_from_string (split_string[1]);
	  etype->minor = etype->major;
	  etype->detail = etype->major;

	Should these not be '0' so the process is at least reversible
mapping to / from the etype structure ?

	The purpose of this function is opaque to me, and it's
efficiency is really not good - what are we trying to achieve here ?
given that we do this per event emitted it might be worth making it
fast. Can you explain what we're trying to achieve here Bill, and I'll
write you an ultra lean, fast unrolled event type parser / quarker.

	On a different track I'm seeing lots of re-enterancy hazards around the
place [ beyond the evil list walking ones I fixed ]:

	It is important to do list tracking operations before poking at the
contents of the list in a way that can cause re-enterancy; ie. we need
to do:

	... = g_list_delete_link (..., obj's element);
	bonobo_object_release_unref (obj, NULL);

	Not:

!	bonobo_object_release_unref (obj, NULL);
!	... = g_list_delete_link (..., obj's element);


	I also removed the double construct referencing issue in accessible.c -
but this seemed to have no nasty side effects - which is nice.

	So; I await your comments :-)

	Regards,

		Michael.

Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/at-spi/ChangeLog,v
retrieving revision 1.133
diff -u -p -u -r1.133 ChangeLog
--- ChangeLog	2002/01/05 17:23:30	1.133
+++ ChangeLog	2002/01/07 11:58:19
@@ -1,3 +1,48 @@
+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.
+	(_get_unique_id): in-line to save symbol table & fr.
+	(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: cspi/spi.h
===================================================================
RCS file: /cvs/gnome/at-spi/cspi/spi.h,v
retrieving revision 1.43
diff -u -p -u -r1.43 spi.h
--- cspi/spi.h	2002/01/02 19:53:18	1.43
+++ cspi/spi.h	2002/01/07 11:58:19
@@ -200,7 +200,8 @@ SPIBoolean SPI_deregisterAccessibleKeyst
 
 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: cspi/spi_event.c
===================================================================
RCS file: /cvs/gnome/at-spi/cspi/spi_event.c,v
retrieving revision 1.17
diff -u -p -u -r1.17 spi_event.c
--- cspi/spi_event.c	2001/12/15 22:53:57	1.17
+++ cspi/spi_event.c	2002/01/07 11:58:19
@@ -69,7 +69,8 @@ SPI_freeAccessibleKeySet (AccessibleKeyS
  *
  **/
 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, con
         {
           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: cspi/spi_registry.c
===================================================================
RCS file: /cvs/gnome/at-spi/cspi/spi_registry.c,v
retrieving revision 1.27
diff -u -p -u -r1.27 spi_registry.c
--- cspi/spi_registry.c	2002/01/01 22:35:28	1.27
+++ cspi/spi_registry.c	2002/01/07 11:58:20
@@ -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: docs/reference/cspi/tmpl/spi_registry.sgml
===================================================================
RCS file: /cvs/gnome/at-spi/docs/reference/cspi/tmpl/spi_registry.sgml,v
retrieving revision 1.6
diff -u -p -u -r1.6 spi_registry.sgml
--- docs/reference/cspi/tmpl/spi_registry.sgml	2002/01/02 21:14:04	1.6
+++ docs/reference/cspi/tmpl/spi_registry.sgml	2002/01/07 11:58:20
@@ -47,8 +47,10 @@ Registry queries
 
 </para>
 
- list: 
+ desktop_list: 
 @Returns: 
+<!-- # Unused Parameters # -->
+ list: 
 

 <!-- ##### USER_FUNCTION AccessibleKeystrokeListenerCB ##### -->
Index: libspi/accessible.c
===================================================================
RCS file: /cvs/gnome/at-spi/libspi/accessible.c,v
retrieving revision 1.34
diff -u -p -u -r1.34 accessible.c
--- libspi/accessible.c	2002/01/03 20:23:00	1.34
+++ libspi/accessible.c	2002/01/07 11:58:20
@@ -454,13 +454,11 @@ 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
      {
        retval = g_object_new (SPI_ACCESSIBLE_TYPE, NULL);
-
-       spi_base_construct (SPI_BASE (retval), G_OBJECT(o));
 
        spi_base_construct (SPI_BASE (retval), G_OBJECT(o));
 
Index: registryd/registry.c
===================================================================
RCS file: /cvs/gnome/at-spi/registryd/registry.c,v
retrieving revision 1.34
diff -u -p -u -r1.34 registry.c
--- registryd/registry.c	2001/12/12 16:08:46	1.34
+++ registryd/registry.c	2002/01/07 11:58:20
@@ -29,6 +29,7 @@
 #  include <stdio.h>
 #endif
 
+#include <bonobo/bonobo-exception.h>
 #include "registry.h"
 
 /* Our parent GObject type  */
@@ -58,17 +59,90 @@ 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);
+typedef struct {
+	GList **list;
+	GList  *iterator;
+} Iteration;
+
+static GSList *working_list = NULL; /* of Iteration */
+
+typedef void (*ReEnterantFn) (GList * const *list, gpointer user_data);
+
+/*
+ *   deletes an element from the list - in a re-enterant
+ * safe fashion; advances the element pointer to the next
+ * element.
+ */
+static void
+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);
 
-static long _get_unique_id();
+  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);
+}
+
+static void
+re_enterant_list_foreach (GList      **list,
+			  ReEnterantFn 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);
+}
+
+/* static function prototypes */
 static gboolean _device_event_controller_hook (gpointer source);
 
 SpiListenerStruct *
@@ -79,24 +153,25 @@ spi_listener_struct_new (Accessibility_E
   return retval;
 }
 
+
 void
 spi_listener_struct_free (SpiListenerStruct *ls, CORBA_Environment *ev)
 {
   bonobo_object_release_unref (ls->listener, 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);
 }
 
+
 /**
  * registerApplication:
  * @application: a reference to the requesting @Application
@@ -111,13 +186,14 @@ impl_accessibility_registry_register_app
                                                   CORBA_Environment * ev)
 {
   SpiRegistry *registry = SPI_REGISTRY (bonobo_object_from_servant (servant));
+  static long id = 0;
 
 #ifdef SPI_DEBUG
   fprintf (stderr, "registering app %p\n", application);
 #endif
   spi_desktop_add_application (registry->desktop, application);
 
-  Accessibility_Application__set_id (application, _get_unique_id(), ev);
+  Accessibility_Application__set_id (application, ++id, ev);
 
   /*
    * TODO: change the implementation below to a WM-aware one;
@@ -125,6 +201,7 @@ impl_accessibility_registry_register_app
    */
 }
 
+#ifdef USE_A_HASH_IN_FUTURE
 static gint
 compare_corba_objects (gconstpointer p1, gconstpointer p2)
 {
@@ -139,6 +216,7 @@ compare_corba_objects (gconstpointer p1,
   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 +245,18 @@ register_with_toolkits (SpiRegistry *spi
 	  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 +265,16 @@ compare_listener_corbaref (gconstpointer
   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_strndup (event_name, 255);
 
   if (!g_ascii_strncasecmp (event_name, "focus:", 6))
     {
@@ -273,134 +354,133 @@ impl_accessibility_registry_deregister_a
 #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;
+
+  list = get_listener_list (registry, etype.type_cat);
 
-  switch (etype.type_cat)
+  if (list)
     {
-    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:
+      *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);
-      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))
+    {
+       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);
+      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;
+
+  registry = SPI_REGISTRY (bonobo_object_from_servant (servant));
 
   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;
-
-  ls.event_type_quark = etype.major;
-  list = g_list_find_custom (*listeners, &ls, compare_listener_quarks);
-
-  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);
-    }
+
+  re_enterant_list_foreach (get_listener_list (registry, etype.type_cat),
+			    remove_listener_cb, listener);
 }
 

@@ -422,6 +502,7 @@ impl_accessibility_registry_get_desktop_
   return n_desktops;
 }
 
+
 /**
  * getDesktop:
  * @n: the index of the requested @Desktop.
@@ -449,6 +530,7 @@ impl_accessibility_registry_get_desktop 
     }
 }
 
+
 /**
  * getDesktopList:
  * return values: a sequence containing references to
@@ -461,104 +543,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));
+
+  parse_event_type (&ctx.etype, e->type);
 
-  e_out = *e_in;
-  parse_event_type (&etype, e_in->type);
+  list = get_listener_list (registry, ctx.etype.type_cat);
 
-  for (l = listeners; l; l = l->next)
+  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
+      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 +694,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: test/simple-at.c
===================================================================
RCS file: /cvs/gnome/at-spi/test/simple-at.c,v
retrieving revision 1.30
diff -u -p -u -r1.30 simple-at.c
--- test/simple-at.c	2002/01/05 17:23:32	1.30
+++ test/simple-at.c	2002/01/07 11:58:20
@@ -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: test/test-simple.c
===================================================================
RCS file: /cvs/gnome/at-spi/test/test-simple.c,v
retrieving revision 1.15
diff -u -p -u -r1.15 test-simple.c
--- test/test-simple.c	2001/12/15 22:54:01	1.15
+++ test/test-simple.c	2002/01/07 11:58:20
@@ -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++) {

-- 
 mmeeks gnu org  <><, Pseudo Engineer, itinerant idiot




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]