[at-spi2-core/gi] Various fixes



commit 702d6a97cf7ecae7cd58fe051a2ace197351a3a4
Author: Mike Gorse <mgorse novell com>
Date:   Mon Nov 29 16:10:22 2010 -0500

    Various fixes
    
    Events and DeviceEvents are now sent with transfer full to work around
    a possible pygi bug.
    
    Various other fixes.

 atspi/Makefile.am               |    1 +
 atspi/atspi-accessible.c        |   75 ++++++++++++++++++--------
 atspi/atspi-accessible.h        |    6 ++-
 atspi/atspi-constants.h         |    2 +-
 atspi/atspi-device-listener.c   |  114 +++++++++++++++++++++++++++++++++++----
 atspi/atspi-device-listener.h   |   21 ++++++-
 atspi/atspi-event-listener.c    |   52 +++++++++++-------
 atspi/atspi-event-listener.h    |    6 ++-
 atspi/atspi-matchrule-private.h |   36 ++++++++++++
 atspi/atspi-matchrule.h         |    3 -
 atspi/atspi-misc.c              |    5 +-
 atspi/atspi-private.h           |    1 +
 atspi/atspi-registry.c          |   50 +++++++++++++----
 atspi/atspi-registry.h          |    6 ++-
 dbind/dbind-any.c               |   37 ++++++++++++-
 dbind/dbind.c                   |   14 +++++
 16 files changed, 349 insertions(+), 80 deletions(-)
---
diff --git a/atspi/Makefile.am b/atspi/Makefile.am
index 6c8105a..e4788ba 100644
--- a/atspi/Makefile.am
+++ b/atspi/Makefile.am
@@ -43,6 +43,7 @@ libatspi_la_SOURCES =		\
 	atspi-image.h \
 	atspi-matchrule.c \
 	atspi-matchrule.h \
+	atspi-matchrule-private.h \
 	atspi-misc.c \
 	atspi-misc.h \
 	atspi-misc-private.h \
diff --git a/atspi/atspi-accessible.c b/atspi/atspi-accessible.c
index 383732b..4d2ea4b 100644
--- a/atspi/atspi-accessible.c
+++ b/atspi/atspi-accessible.c
@@ -233,7 +233,8 @@ atspi_accessible_get_name (AtspiAccessible *obj, GError **error)
   g_return_val_if_fail (obj != NULL, NULL);
   if (!(obj->cached_properties & ATSPI_CACHE_NAME))
   {
-    if (!_atspi_dbus_get_property (obj, atspi_interface_accessible, "Name", NULL, "s", &obj->name))
+    if (!_atspi_dbus_get_property (obj, atspi_interface_accessible, "Name", error,
+                                   "s", &obj->name))
       return NULL;
     obj->cached_properties |= ATSPI_CACHE_NAME;
   }
@@ -511,7 +512,7 @@ atspi_accessible_get_localized_role_name (AtspiAccessible *obj, GError **error)
 AtspiStateSet *
 atspi_accessible_get_state_set (AtspiAccessible *obj)
 {
-  return obj->states;
+  return g_object_ref (obj->states);
 }
 
 /**
@@ -562,12 +563,13 @@ atspi_accessible_get_attributes_as_array (AtspiAccessible *obj, GError **error)
 
   message = _atspi_dbus_call_partial (obj, atspi_interface_accessible, "GetAttributes", error, "");
   ret = _atspi_dbus_attribute_array_from_message (message);
-  dbus_message_unref (message);
+  if (message)
+    dbus_message_unref (message);
   return ret;
 }
 
 /**
- * atspi_accessible_get_host_application:
+ * atspi_accessible_get_application:
  * @obj: The #AtspiAccessible being queried.
  *
  * Get the containing #AtspiApplication for an object.
@@ -576,7 +578,7 @@ atspi_accessible_get_attributes_as_array (AtspiAccessible *obj, GError **error)
  *          this object.
  */
 AtspiAccessible *
-atspi_accessible_get_host_application (AtspiAccessible *obj, GError **error)
+atspi_accessible_get_application (AtspiAccessible *obj, GError **error)
 {
   AtspiAccessible *parent;
 
@@ -585,11 +587,56 @@ atspi_accessible_get_host_application (AtspiAccessible *obj, GError **error)
     parent = atspi_accessible_get_parent (obj, NULL);
     if (!parent || parent == obj ||
         atspi_accessible_get_role (parent, NULL) == ATSPI_ROLE_DESKTOP_FRAME)
-    return obj;
+    return g_object_ref (obj);
     obj = parent;
   }
 }
 
+/* Applicatio-specific methods */
+
+/**
+ * atspi_accessible_get_toolkit_name:
+ * @obj: a pointer to the #AtspiAccessible object on which to operate.
+ *
+ * Get the toolkit for a #AtspiAccessible object.
+ * Only works on application root objects.
+ *
+ * Returns: a UTF-8 string indicating the toolkit name for the #AtspiAccessible object.
+ * or NULL on exception
+ **/
+gchar *
+atspi_accessible_get_toolkit_name (AtspiAccessible *obj, GError **error)
+{
+  gchar *ret = NULL;
+
+  g_return_val_if_fail (obj != NULL, NULL);
+
+  if (!_atspi_dbus_get_property (obj, atspi_interface_application, "ToolkitName", error, "s", &ret))
+      return NULL;
+  return g_strdup (ret);
+}
+
+/**
+ * atspi_accessible_get_toolkit_version:
+ * @obj: a pointer to the #AtspiAccessible object on which to operate.
+ *
+ * Get the toolkit version for a #AtspiAccessible object.
+ * Only works on application root objects.
+ *
+ * Returns: a UTF-8 string indicating the toolkit ersion for the #AtspiAccessible object.
+ * or NULL on exception
+ **/
+gchar *
+atspi_accessible_get_toolkit_version (AtspiAccessible *obj, GError **error)
+{
+  gchar *ret = NULL;
+
+  g_return_val_if_fail (obj != NULL, NULL);
+
+  if (!_atspi_dbus_get_property (obj, atspi_interface_application, "ToolkitVersion", error, "s", &ret))
+      return NULL;
+  return g_strdup (ret);
+}
 /* Interface query methods */
 
 /**
@@ -810,22 +857,6 @@ atspi_accessible_is_value (AtspiAccessible *obj)
 }
 
 /**
- * atspi_accessible_get_application:
- * @obj: a pointer to the #AtspiAccessible instance to query.
- *
- * Get the #AtspiApplication interface for an #AtspiAccessible.
- *
- * Returns: a pointer to an #AtspiApplication interface instance, or
- *          NULL if @obj does not implement #AtspiApplication.
- **/
-AtspiApplication *
-atspi_accessible_get_application (AtspiAccessible *accessible)
-{
-  return (_atspi_accessible_is_a (accessible, atspi_interface_application) ?
-          g_object_ref (ATSPI_ACTION (accessible)) : NULL);  
-}
-
-/**
  * atspi_accessible_get_action:
  * @obj: a pointer to the #AtspiAccessible instance to query.
  *
diff --git a/atspi/atspi-accessible.h b/atspi/atspi-accessible.h
index edb5c1d..7c3f1df 100644
--- a/atspi/atspi-accessible.h
+++ b/atspi/atspi-accessible.h
@@ -92,7 +92,11 @@ GHashTable * atspi_accessible_get_attributes (AtspiAccessible *obj, GError **err
 
 GArray * atspi_accessible_get_attributes_as_array (AtspiAccessible *obj, GError **error);
 
-AtspiAccessible * atspi_accessible_get_host_application (AtspiAccessible *obj, GError **error);
+gchar * atspi_accessible_get_toolkit_name (AtspiAccessible *obj, GError **error);
+
+gchar * atspi_accessible_get_toolkit_version (AtspiAccessible *obj, GError **error);
+
+AtspiAccessible * atspi_accessible_get_application (AtspiAccessible *obj, GError **error);
 
 AtspiAction * atspi_accessible_get_action (AtspiAccessible *obj);
 
diff --git a/atspi/atspi-constants.h b/atspi/atspi-constants.h
index 42dc120..462b89b 100644
--- a/atspi/atspi-constants.h
+++ b/atspi/atspi-constants.h
@@ -494,7 +494,7 @@ typedef enum {
     ATSPI_MODIFIER_META2,
     ATSPI_MODIFIER_META3,
     ATSPI_MODIFIER_NUMLOCK,
-} AtspimodifierType;
+} AtspiModifierType;
 
 /**
  * ATSPI_MODIFIERTYPE_COUNT:
diff --git a/atspi/atspi-device-listener.c b/atspi/atspi-device-listener.c
index 31bb270..235d6b2 100644
--- a/atspi/atspi-device-listener.c
+++ b/atspi/atspi-device-listener.c
@@ -27,6 +27,7 @@ typedef struct
 {
   AtspiDeviceListenerCB    callback;
   gpointer user_data;
+  GDestroyNotify callback_destroyed;
 } DeviceEventHandler;
 
 GObjectClass *device_parent_class;
@@ -38,16 +39,41 @@ static guint32 _e_id = 0;
  */
 
 static DeviceEventHandler *
-device_event_handler_new (AtspiDeviceListenerCB callback, gpointer user_data)
+device_event_handler_new (AtspiDeviceListenerCB callback,
+                          GDestroyNotify callback_destroyed,
+                          gpointer user_data)
 {
   DeviceEventHandler *eh = g_new0 (DeviceEventHandler, 1);
 
   eh->callback = callback;
+  eh->callback_destroyed = callback_destroyed;
   eh->user_data = user_data;
 
   return eh;
 }
 
+static gboolean
+device_remove_datum (const AtspiDeviceEvent *event, void *user_data)
+{
+  AtspiDeviceListenerSimpleCB cb = user_data;
+  return cb (event);
+}
+  
+static void
+device_event_handler_free (DeviceEventHandler *eh)
+{
+#if 0
+  /* TODO; Test this; it will probably crash with pyatspi for unknown reasons */
+  if (eh->callback_destroyed)
+  {
+    gpointer rea_callback = (eh->callback == device_remove_datum ?
+                            eh->user_data : eh->callback);
+    (*eh->callback_destroyed) (real_callback);
+  }
+#endif
+  g_free (eh);
+}
+
 static GList *
 event_list_remove_by_cb (GList *list, AtspiDeviceListenerCB callback)
 {
@@ -61,7 +87,7 @@ event_list_remove_by_cb (GList *list, AtspiDeviceListenerCB callback)
       if (eh->callback == callback)
       {
         list = g_list_delete_link (list, l);
-	g_free (eh);
+        device_event_handler_free (eh);
       }
     }
 
@@ -94,6 +120,31 @@ remove_listener (GObject *obj, gpointer data)
   device_listeners = g_list_remove (device_listeners, obj);
 }
 
+static AtspiDeviceEvent *
+atspi_device_event_copy (AtspiDeviceEvent *src)
+{
+  AtspiDeviceEvent *dst = g_new0 (AtspiDeviceEvent, 1);
+  if (!dst)
+    return NULL;
+  dst->type = src->type;
+  dst->id = src->id;
+  dst->hw_code = src->hw_code;
+  dst->modifiers = src->modifiers;
+  dst->timestamp = src->timestamp;
+  if (src->event_string)
+    dst->event_string = g_strdup (src->event_string);
+  dst->is_text = src->is_text;
+  return dst;
+}
+
+void
+atspi_device_event_free (AtspiDeviceEvent *event)
+{
+  if (event->event_string)
+    g_free (event->event_string);
+  g_free (event);
+}
+
 /* 
  * Device event handler
  */
@@ -102,7 +153,6 @@ atspi_device_event_dispatch (AtspiDeviceListener               *listener,
 		   const AtspiDeviceEvent *event)
 {
   GList *l;
-  AtspiDeviceEvent anevent;
   gboolean handled = FALSE;
 
   /* FIXME: re-enterancy hazard on this list */
@@ -110,7 +160,7 @@ atspi_device_event_dispatch (AtspiDeviceListener               *listener,
     {
       DeviceEventHandler *eh = l->data;
 
-      if ((handled = eh->callback (&anevent, eh->user_data)))
+      if ((handled = eh->callback (atspi_device_event_copy (event), eh->user_data)))
         {
 	  break;
 	}
@@ -140,7 +190,7 @@ atspi_device_listener_finalize (GObject *object)
   
   for (l = listener->callbacks; l; l = l->next)
     {
-      g_free (l->data);
+      device_event_handler_free (l->data);
     }
   
   g_list_free (listener->callbacks);
@@ -164,8 +214,10 @@ G_DEFINE_TYPE (AtspiDeviceListener, atspi_device_listener,
 
 /**
  * atspi_device_listener_new:
- * @callback: (scope call): an #AtspiDeviceListenerCB callback function,
+ * @callback: (scope notify): an #AtspiDeviceListenerCB callback function,
  *            or NULL.
+ * @callback_destroyed: A #GDestroyNotify called when the listener is freed
+ * and data associated with the callback should be freed.  Can be NULL.
  * @user_data: (closure): a pointer to data which will be passed to the
  * callback when invoked.
  *
@@ -175,19 +227,46 @@ G_DEFINE_TYPE (AtspiDeviceListener, atspi_device_listener,
  *
  **/
 AtspiDeviceListener *
-atspi_device_listener_new (AtspiDeviceListenerCB callback)
+atspi_device_listener_new (AtspiDeviceListenerCB callback,
+                           GDestroyNotify callback_destroyed,
+                           void *user_data)
 {
   AtspiDeviceListener *listener = g_object_new (atspi_device_listener_get_type (), NULL);
 
+  if (callback)
+    atspi_device_listener_add_callback (listener, callback, callback_destroyed,
+                                       user_data);
   return listener;
 }
 
 /**
+ * atspi_device_listener_new_simple:
+ * @callback: (scope notify): an #AtspiDeviceListenerCB callback function,
+ *            or NULL.
+ * @callback_destroyed: A #GDestroyNotify called when the listener is freed
+ * and data associated with the callback should be freed.  Can be NULL.
+ *
+ * Create a new #AtspiDeviceListener with a specified callback function.
+ * Like atspi_device_listener_new, but callback takes no user data.
+ *
+ * Returns: a pointer to a newly-created #AtspiDeviceListener.
+ *
+ **/
+AtspiDeviceListener *
+atspi_device_listener_new_simple (AtspiDeviceListenerSimpleCB callback,
+                           GDestroyNotify callback_destroyed)
+{
+  return atspi_device_listener_new (device_remove_datum, callback_destroyed, callback);
+}
+
+/**
  * atspi_device_listener_add_callback:
  * @listener: the #AtspiDeviceListener instance to modify.
- * @callback: (scope call): an #AtspiDeviceListenerCB function pointer.
+ * @callback: (scope notify): an #AtspiDeviceListenerCB function pointer.
  * @user_data: (closure): a pointer to data which will be passed to the
  *             callback when invoked.
+ * @callback_destroyed: A #GDestroyNotify called when the listener is freed
+ * and data associated with the callback should be freed.  Can be NULL.
  *
  * Add an in-process callback function to an existing #AtspiDeviceListener.
  *
@@ -197,12 +276,22 @@ atspi_device_listener_new (AtspiDeviceListenerCB callback)
 void
 atspi_device_listener_add_callback (AtspiDeviceListener  *listener,
 			     AtspiDeviceListenerCB callback,
+			     GDestroyNotify callback_destroyed,
 			     void                      *user_data)
 {
   g_return_if_fail (ATSPI_IS_DEVICE_LISTENER (listener));
+  DeviceEventHandler *new_handler;
 
-  listener->callbacks = g_list_prepend (listener->callbacks,
-					device_event_handler_new ((void *)callback, user_data));
+  new_handler = device_event_handler_new (callback,
+                                          callback_destroyed, user_data);
+
+  if (new_handler)
+  {
+    GList *new_list;
+    new_list = g_list_prepend (listener->callbacks, new_handler);
+    if (new_list)
+      listener->callbacks = new_list;
+  }
 }
 
 /**
@@ -329,3 +418,8 @@ _atspi_device_listener_get_path (AtspiDeviceListener *listener)
 {
   return g_strdup_printf ("/org/a11y/atspi/listeners/%d", listener->id);
 }
+
+G_DEFINE_BOXED_TYPE (AtspiDeviceEvent,
+                     atspi_device_event,
+                     atspi_device_event_copy,
+                     atspi_device_event_free)
diff --git a/atspi/atspi-device-listener.h b/atspi/atspi-device-listener.h
index bf78935..07571ec 100644
--- a/atspi/atspi-device-listener.h
+++ b/atspi/atspi-device-listener.h
@@ -31,7 +31,8 @@
 
 /**
  * AtspiDeviceListenerCB:
- * @stroke: The #AtspiDeviceEvent for which notification is being received.
+ * @stroke: (transfer full): The #AtspiDeviceEvent for which notification is
+ *          being received.
  * @user_data: Data which is passed to the client each time this callback is notified.
  *
  * A callback function prototype via which clients receive device event notifications.
@@ -42,6 +43,18 @@
 typedef gboolean (*AtspiDeviceListenerCB)    (const AtspiDeviceEvent *stroke,
 						     void                      *user_data);
 
+/**
+ * AtspiDeviceListenerSimpleCB:
+ * @stroke: (transfer full): The #AtspiDeviceEvent for which notification is
+ *          being received.
+ *
+ * Like #AtspiDeviceListenerCB but with no user data.
+ *
+ * Returns: %TRUE if the client wishes to consume/preempt the event, preventing it from being
+ * relayed to the currently focussed application, %FALSE if the event delivery should proceed as normal.
+ **/
+typedef gboolean (*AtspiDeviceListenerSimpleCB)    (const AtspiDeviceEvent *stroke);
+
 #define ATSPI_TYPE_DEVICE_LISTENER                        (atspi_device_listener_get_type ())
 #define ATSPI_DEVICE_LISTENER(obj)                        (G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_DEVICE_LISTENER, AtspiDeviceListener))
 #define ATSPI_DEVICE_LISTENER_CLASS(klass)                (G_TYPE_CHECK_CLASS_CAST ((klass), ATSPI_TYPE_DEVICE_LISTENER, AtspiDeviceListenerClass))
@@ -66,9 +79,11 @@ struct _AtspiDeviceListenerClass
 
 GType atspi_device_listener_get_type (void);
 
-AtspiDeviceListener *atspi_device_listener_new (AtspiDeviceListenerCB callback);
+AtspiDeviceListener *atspi_device_listener_new (AtspiDeviceListenerCB callback, GDestroyNotify callback_destroyed, void *user_data);
+
+AtspiDeviceListener *atspi_device_listener_new_simple (AtspiDeviceListenerSimpleCB callback, GDestroyNotify callback_destroyed);
 
-void atspi_device_listener_add_callback (AtspiDeviceListener  *listener, AtspiDeviceListenerCB callback, void                      *user_data);
+void atspi_device_listener_add_callback (AtspiDeviceListener *listener, AtspiDeviceListenerCB callback, GDestroyNotify callback_destroyed, void *user_data);
 
 void atspi_device_listener_remove_callback (AtspiDeviceListener  *listener, AtspiDeviceListenerCB callback);
 #endif	/* _ATSPI_DEVICE_LISTENER_H_ */
diff --git a/atspi/atspi-event-listener.c b/atspi/atspi-event-listener.c
index b134233..3aa69df 100644
--- a/atspi/atspi-event-listener.c
+++ b/atspi/atspi-event-listener.c
@@ -132,6 +132,7 @@ atspi_event_listener_new_simple (AtspiEventListenerSimpleCB callback,
   callback_ref (remove_datum, callback_destroyed);
   listener->user_data = callback;
   listener->cb_destroyed = callback_destroyed;
+  return listener;
 }
 
 static GList *event_listeners = NULL;
@@ -271,6 +272,7 @@ strdup_and_adjust_for_dbus (const char *s)
 {
   gchar *d = g_strdup (s);
   gchar *p;
+  int parts = 0;
 
   if (!d)
     return NULL;
@@ -284,6 +286,9 @@ strdup_and_adjust_for_dbus (const char *s)
     }
     else if (*p == ':')
     {
+      parts++;
+      if (parts == 2)
+        break;
       p [1] = toupper (p [1]);
     }
   }
@@ -667,6 +672,28 @@ atspi_event_listener_deregister_no_data (AtspiEventListenerSimpleCB callback,
                                                         event_type);
 }
 
+static AtspiEvent *
+atspi_event_copy (AtspiEvent *src)
+{
+  AtspiEvent *dst = g_new0 (AtspiEvent, 1);
+  dst->type = g_strdup (src->type);
+  dst->source = g_object_ref (src->source);
+  dst->detail1 = src->detail1;
+  dst->detail2 = src->detail2;
+  dst->any_data.g_type = src->any_data.g_type;
+  g_value_copy (&dst->any_data, &src->any_data);
+  return dst;
+}
+
+static void
+atspi_event_free (AtspiEvent *event)
+{
+  g_object_unref (event->source);
+  g_free (event->type);
+  g_value_unset (&event->any_data);
+  g_free (event);
+}
+
 void
 _atspi_send_event (AtspiEvent *e)
 {
@@ -676,7 +703,10 @@ _atspi_send_event (AtspiEvent *e)
   /* Ensure that the value is set to avoid a Python exception */
   /* TODO: Figure out how to do this without using a private field */
   if (e->any_data.g_type == 0)
+  {
+    g_value_init (&e->any_data, G_TYPE_INT);
     g_value_set_int (&e->any_data, 0);
+  }
 
   if (!convert_event_type_to_dbus (e->type, &category, &name, &detail, NULL))
   {
@@ -690,7 +720,7 @@ _atspi_send_event (AtspiEvent *e)
         (entry->name == NULL || !strcmp (name, entry->name)) &&
         (entry->detail == NULL || !strcmp (detail, entry->detail)))
     {
-        entry->callback (e, entry->user_data);
+        entry->callback (atspi_event_copy (e), entry->user_data);
     }
   }
   if (detail) g_free (detail);
@@ -785,6 +815,7 @@ atspi_dbus_handle_event (DBusConnection *bus, DBusMessage *message, void *data)
     case DBUS_TYPE_STRING:
     {
       dbus_message_iter_get_basic (&iter_variant, &p);
+      g_value_init (&e.any_data, G_TYPE_STRING);
       g_value_set_string (&e.any_data, p);
       break;
     }
@@ -814,23 +845,4 @@ atspi_dbus_handle_event (DBusConnection *bus, DBusMessage *message, void *data)
   return DBUS_HANDLER_RESULT_HANDLED;
 }
 
-static AtspiEvent *
-atspi_event_copy (AtspiEvent *src)
-{
-  AtspiEvent *dst = g_new0 (AtspiEvent, 1);
-  dst->type = g_strdup (src->type);
-  dst->detail1 = src->detail1;
-  dst->detail2 = src->detail2;
-  g_value_copy (&dst->any_data, &src->any_data);
-}
-
-static void
-atspi_event_free (AtspiEvent *event)
-{
-  g_object_unref (event->source);
-  g_free (event->type);
-  g_value_unset (&event->any_data);
-  g_free (event);
-}
-
 G_DEFINE_BOXED_TYPE (AtspiEvent, atspi_event, atspi_event_copy, atspi_event_free)
diff --git a/atspi/atspi-event-listener.h b/atspi/atspi-event-listener.h
index 25c1b40..64f31d7 100644
--- a/atspi/atspi-event-listener.h
+++ b/atspi/atspi-event-listener.h
@@ -29,9 +29,11 @@
 
 #include "atspi-types.h"
 
+GType atspi_event_get_type (void);
+
 /**
  * AtspiEventListenerCB:
- * @event: The event for which notification is sent.
+ * @event: (transfer full): The event for which notification is sent.
  * @user_data: User data which is passed to the callback each time a notification takes place.
  *
  * A function prototype for callbacks via which clients are notified of AT-SPI events.
@@ -42,7 +44,7 @@ typedef void       (*AtspiEventListenerCB)     (const AtspiEvent     *event,
 
 /**
  * AtspiEventListenerSimpleCB:
- * @event: The event for which notification is sent.
+ * @event: (transfer full): The event for which notification is sent.
  *
  * Like #AtspiEventlistenerCB, but with no user_data.
  * 
diff --git a/atspi/atspi-matchrule-private.h b/atspi/atspi-matchrule-private.h
new file mode 100644
index 0000000..3d91448
--- /dev/null
+++ b/atspi/atspi-matchrule-private.h
@@ -0,0 +1,36 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2002 Ximian, Inc.
+ *           2002 Sun Microsystems 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.
+ */
+
+#ifndef _ATSPI_MATCH_RULE_PRIVATE_H_
+#define _ATSPI_MATCH_RULE_PRIVATE_H_
+
+#include "glib-object.h"
+
+#include "atspi-matchrule.h"
+#include "dbus/dbus.h"
+
+gboolean
+_atspi_match_rule_marshal (AtspiMatchRule *rule, DBusMessageIter *iter);
+
+#endif	/* _ATSPI_MATCH_RULE_PRIVATE_H_ */
diff --git a/atspi/atspi-matchrule.h b/atspi/atspi-matchrule.h
index 074bf9f..596e8cc 100644
--- a/atspi/atspi-matchrule.h
+++ b/atspi/atspi-matchrule.h
@@ -72,7 +72,4 @@ atspi_match_rule_new (AtspiStateSet *states,
                       AtspiCollectionMatchType interfacematchtype,
                       gboolean invert);
 
-gboolean
-_atspi_match_rule_marshal (AtspiMatchRule *rule, DBusMessageIter *iter);
-
 #endif	/* _ATSPI_MATCH_RULE_H_ */
diff --git a/atspi/atspi-misc.c b/atspi/atspi-misc.c
index a9fb7f7..a8f0ac9 100644
--- a/atspi/atspi-misc.c
+++ b/atspi/atspi-misc.c
@@ -624,10 +624,9 @@ atspi_dbus_filter (DBusConnection *bus, DBusMessage *message, void *data)
   {
     return atspi_dbus_handle_event (bus, message, data);
   }
-  if (dbus_message_is_method_call (message, atspi_interface_device_event_listener, "notifyEvent"))
+  if (dbus_message_is_method_call (message, atspi_interface_device_event_listener, "NotifyEvent"))
   {
-    g_warning ("atspi: TODO: DeviceEvent");
-    //return handle_device_event (bus, message, data);
+    return atspi_dbus_handle_DeviceEvent (bus, message, data);
   }
   if (dbus_message_is_signal (message, atspi_interface_cache, "AddAccessible"))
   {
diff --git a/atspi/atspi-private.h b/atspi/atspi-private.h
index bab5349..b396be8 100644
--- a/atspi/atspi-private.h
+++ b/atspi/atspi-private.h
@@ -27,6 +27,7 @@
 
 #include "atspi-device-listener-private.h"
 #include "atspi-event-listener-private.h"
+#include "atspi-matchrule-private.h"
 #include "atspi-misc-private.h"
 
 #include "atspi.h"
diff --git a/atspi/atspi-registry.c b/atspi/atspi-registry.c
index cf49d3d..86bde7d 100644
--- a/atspi/atspi-registry.c
+++ b/atspi/atspi-registry.c
@@ -87,16 +87,16 @@ atspi_get_desktop_list ()
 
 /**
  * ATSPI_KEYSET_ALL_KEYS:
- * @ATSPI_KEYSET_ALL_KEYS: A special value for an AccessibleKeySet type, which tacitly
+ * @ATSPI_KEYSET_ALL_KEYS: A special value for an AtspiKeySet type, which tacitly
  *                       includes all keycodes and keyvals for the specified modifier set.
  **/
 
 /**
- * atspi_register_accessible_keystroke_listener:
- * @listener:  a pointer to the #AccessibleKeystrokeListener for which
+ * atspi_register_keystroke_listener:
+ * @listener:  a pointer to the #AtspiDeviceListener for which
  *             keystroke events are requested.
- * @key_set: (type: AtspiKeyDefinition): a pointer to the
- *        #AccessibleKeyDefinition array indicating which keystroke events are requested, or #ATSPI_KEYSET_ALL_KEYS
+ * @key_set: (element-type AtspiKeyDefinition): a pointer to the
+ *        #AtspiKeyDefinition array indicating which keystroke events are requested, or #ATSPI_KEYSET_ALL_KEYS
  *             to indicate that all keycodes and keyvals for the specified
  *             modifier set are to be included.
  * @modmask:   an #AtspiKeyMaskType mask indicating which
@@ -104,7 +104,7 @@ atspi_get_desktop_list ()
  *             events will only be reported for key events for which all
  *             modifiers in @modmask are set.  If you wish to listen for
  *             events with multiple modifier combinations you must call
- *             register_accessible_keystroke_listener() once for each
+ *             register_keystroke_listener() once for each
  *             combination.
  * @eventmask: an #AtspiKeyMaskType mask indicating which
  *             types of key events are requested (#ATSPI_KEY_PRESSED, etc.).
@@ -122,7 +122,7 @@ atspi_get_desktop_list ()
  * Returns: #TRUE if successful, otherwise #FALSE.
  **/
 gboolean
-atspi_register_accessible_keystroke_listener (AtspiDeviceListener  *listener,
+atspi_register_keystroke_listener (AtspiDeviceListener  *listener,
 					 GArray             *key_set,
 					 AtspiKeyMaskType         modmask,
 					 AtspiKeyEventMask        event_types,
@@ -178,15 +178,15 @@ atspi_register_accessible_keystroke_listener (AtspiDeviceListener  *listener,
     dbus_error_init (&d_error);
     dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry, atspi_path_dec, atspi_interface_dec, "RegisterKeystrokeListener", &d_error, "oa(iisi)uu(bbb)=>b", path, d_key_set, d_modmask, d_event_types, &listener_mode, &retval);
 
-  g_array_free (key_set, TRUE);
+  g_array_free (d_key_set, TRUE);
   g_free (path);
 
   return retval;
 }
 
 /**
- * atspi_deregister_accessible_keystroke_listener:
- * @listener: a pointer to the #AccessibleKeystrokeListener for which
+ * atspi_deregister_keystroke_listener:
+ * @listener: a pointer to the #AtspiDeviceListener for which
  *            keystroke events are requested.
  * @modmask:  the key modifier mask for which this listener is to be
  *            'deregistered' (of type #AtspiKeyMaskType).
@@ -197,7 +197,7 @@ atspi_register_accessible_keystroke_listener (AtspiDeviceListener  *listener,
  * Returns: #TRUE if successful, otherwise #FALSE.
  **/
 gboolean
-atspi_deregister_accessible_keystroke_listener (AtspiDeviceListener *listener,
+atspi_deregister_keystroke_listener (AtspiDeviceListener *listener,
 					   AtspiKeyMaskType        modmask, AtspiKeyEventMask event_types, GError **error)
 {
   gchar *path = _atspi_device_listener_get_path (listener);
@@ -295,7 +295,7 @@ atspi_deregister_device_event_listener (AtspiDeviceListener *listener,
  *           being synthesized; this type of keyboard event synthesis does
  *           not emulate hardware keypresses but injects the string 
  *           as though a composing input method (such as XIM) were used.
- * @synth_type: a #AccessibleKeySynthType flag indicating whether @keyval
+ * @synth_type: a #AtspiKeySynthType flag indicating whether @keyval
  *           is to be interpreted as a keysym rather than a keycode
  *           (ATSPI_KEYSYM), or whether to synthesize
  *           ATSPI_KEY_PRESS, ATSPI_KEY_RELEASE, or both (ATSPI_KEY_PRESSRELEASE).
@@ -347,3 +347,29 @@ atspi_generate_mouse_event (glong x, glong y, const gchar *name, GError **error)
     dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry, atspi_path_dec, atspi_interface_dec, "GenerateMouseEvent", &d_error, "iis", x, y, name);
   return TRUE;
 }
+
+AtspiKeyDefinition *
+atspi_key_definition_copy (AtspiKeyDefinition *src)
+{
+  AtspiKeyDefinition *dst;
+
+  dst = g_new0 (AtspiKeyDefinition, 1);
+  if (!dst)
+    return NULL;
+  dst->keycode = src->keycode;
+  dst->keysym = src->keysym;
+  if (src->keystring)
+    dst->keystring = g_strdup (src->keystring);
+  dst->unused = src->unused;
+  return dst;
+}
+
+void
+atspi_key_definition_free (AtspiKeyDefinition *kd)
+{
+  if (kd->keystring)
+    g_free (kd->keystring);
+  g_free (kd);
+}
+
+G_DEFINE_BOXED_TYPE (AtspiKeyDefinition, atspi_key_definition, atspi_key_definition_copy, atspi_key_definition_free)
diff --git a/atspi/atspi-registry.h b/atspi/atspi-registry.h
index c070d87..b1bf44b 100644
--- a/atspi/atspi-registry.h
+++ b/atspi/atspi-registry.h
@@ -29,6 +29,8 @@
 #include "atspi-types.h"
 #include "atspi-device-listener.h"
 
+GType atspi_key_definition_get_type ();
+
 gint atspi_get_desktop_count ();
 
 AtspiAccessible* atspi_get_desktop (gint i);
@@ -36,14 +38,14 @@ AtspiAccessible* atspi_get_desktop (gint i);
 GArray *atspi_get_desktop_list ();
 
 gboolean
-atspi_register_accessible_keystroke_listener (AtspiDeviceListener  *listener,
+atspi_register_keystroke_listener (AtspiDeviceListener  *listener,
 					 GArray *key_set,
 					 AtspiKeyMaskType         modmask,
 					 AtspiKeyEventMask        event_types,
 					 AtspiKeyListenerSyncType sync_type, GError **error);
 
 gboolean
-atspi_deregister_accessible_keystroke_listener (AtspiDeviceListener *listener,
+atspi_deregister_keystroke_listener (AtspiDeviceListener *listener,
 					        AtspiKeyMaskType         modmask,
 					        AtspiKeyEventMask        event_types,
 					        GError **error);
diff --git a/dbind/dbind-any.c b/dbind/dbind-any.c
index 088a207..083420d 100644
--- a/dbind/dbind-any.c
+++ b/dbind/dbind-any.c
@@ -630,6 +630,41 @@ dbind_any_demarshal (DBusMessageIter *iter,
     dbus_message_iter_next (iter);
 }
 
+static const char *
+pass_complex_arg (const char *p, char begin, char end)
+{
+  int level = 1;
+
+  p++;
+  while (*p && level > 0)
+  {
+    if (*p == begin)
+      level++;
+    else if (*p == end)
+      level--;
+    p++;
+  }
+  if (*p == end)
+    p++;
+  return p;
+}
+
+static const char *
+pass_arg (const char *p)
+{
+  switch (*p)
+  {
+  case '(':
+    return pass_complex_arg (p, '(', ')');
+  case '{':
+    return pass_complex_arg (p, '{', '}');
+  case 'a':
+    return pass_arg (p+1);
+  default:
+    return p + 1;
+  }
+}
+
 /*---------------------------------------------------------------------------*/
 
 void
@@ -686,7 +721,7 @@ dbind_any_demarshal_va (DBusMessageIter *iter,
             fprintf (stderr, "Unknown / invalid arg type %c\n", *p);
             break;
         }
-      p++;
+      p = pass_arg (p);
     }
 
     if (p [0] == '=' && p[1] == '>')
diff --git a/dbind/dbind.c b/dbind/dbind.c
index a5da81d..294f6c1 100644
--- a/dbind/dbind.c
+++ b/dbind/dbind.c
@@ -20,6 +20,7 @@ typedef struct _SpiReentrantCallClosure
 {
   GMainLoop   *loop;
   DBusMessage *reply;
+  guint timeout;
 } SpiReentrantCallClosure;
 
 static void
@@ -31,6 +32,14 @@ set_reply (DBusPendingCall * pending, void *user_data)
   g_main_loop_quit (closure->loop);
 }
 
+gboolean
+main_loop_timeout (SpiReentrantCallClosure *closure)
+{
+  g_main_loop_quit (closure->loop);
+  /* Returning TRUE because caller will remove the timer */
+  return TRUE;
+}
+
 DBusMessage *
 dbind_send_and_allow_reentry (DBusConnection * bus, DBusMessage * message, DBusError *error)
 {
@@ -41,15 +50,20 @@ dbind_send_and_allow_reentry (DBusConnection * bus, DBusMessage * message, DBusE
               dbus_bus_get_unique_name (bus)) != 0)
     return dbus_connection_send_with_reply_and_block (bus, message, dbind_timeout, error);
 
+  /* TODO: Figure out why this isn't working */
+  return NULL;
   if (!dbus_connection_send_with_reply (bus, message, &pending, dbind_timeout))
       return NULL;
   dbus_pending_call_set_notify (pending, set_reply, (void *) &closure, NULL);
   closure.loop = g_main_loop_new (NULL, FALSE);
+  closure.reply = NULL;
   dbus_connection_setup_with_g_main(bus, NULL);
 
   if (1)
     {
+      closure.timeout = g_timeout_add_seconds (2, main_loop_timeout, &closure);
       g_main_loop_run  (closure.loop);
+      g_source_remove (closure.timeout);
     }
   else
     {



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