[at-spi2-core] Make the registry implement the accessible interface and add a socket interface for adding chilren t



commit f8893786b2a61f8294e6cc73d3bdc2ae18264a7b
Author: Mark Doffman <mark doffman codethink co uk>
Date:   Wed Jan 20 12:14:53 2010 -0800

    Make the registry implement the accessible interface and add
    a socket interface for adding chilren to its accessible object.

 registryd/deviceeventcontroller.c |    2 +-
 registryd/paths.h                 |   43 +--
 registryd/registry.c              |  821 +++++++++++++++++++++++++++++++------
 registryd/registry.h              |    2 +-
 4 files changed, 708 insertions(+), 160 deletions(-)
---
diff --git a/registryd/deviceeventcontroller.c b/registryd/deviceeventcontroller.c
index d094f2c..30d8774 100644
--- a/registryd/deviceeventcontroller.c
+++ b/registryd/deviceeventcontroller.c
@@ -398,7 +398,7 @@ static void emit(SpiDEController *controller, const char *interface, const char
   DBusMessage *signal = NULL;
   DBusMessageIter iter, iter_variant;
   int nil = 0;
-  const char *path = SPI_DBUS_PATH_DESKTOP;
+  const char *path = SPI_DBUS_PATH_ROOT;
 
   signal = dbus_message_new_signal (path, interface, name);
 
diff --git a/registryd/paths.h b/registryd/paths.h
index 0d1ed40..49758e5 100644
--- a/registryd/paths.h
+++ b/registryd/paths.h
@@ -24,35 +24,26 @@
 #ifndef SPI_PATHS_H_
 #define SPI_PATHS_H_
 
-#define SPI_DBUS_NAME_REGISTRY                   "org.freedesktop.atspi.Registry"
-#define SPI_DBUS_PATH_REGISTRY                   "/org/freedesktop/atspi/registry"
-#define SPI_DBUS_INTERFACE_REGISTRY              "org.freedesktop.atspi.Registry"
+#define SPI_DBUS_NAME_PREFIX                     "org.freedesktop.atspi."
+#define SPI_DBUS_PATH_PREFIX                     "/org/freedesktop/atspi/"
+#define SPI_DBUS_INTERFACE_PREFIX                "org.freedesktop.atspi."
 
-#define SPI_DBUS_PATH_DESKTOP                    "/org/freedesktop/atspi/accessible/desktop"
-#define SPI_DBUS_INTERFACE_DESKTOP               "org.freedesktop.atspi.Desktop"
+#define SPI_DBUS_PATH_NULL                       SPI_DBUS_PATH_PREFIX "null"
+#define SPI_DBUS_PATH_ROOT                       SPI_DBUS_PATH_PREFIX "root"
 
-#define SPI_DBUS_PATH_DEC                        "/org/freedesktop/atspi/registry/deviceeventcontroller"
-#define SPI_DBUS_PATH_NULL                       "/org/freedesktop/accessible/null"
+#define SPI_DBUS_NAME_REGISTRY                   SPI_DBUS_NAME_PREFIX "org.freedesktop.atspi.Registry"
+#define SPI_DBUS_PATH_REGISTRY                   SPI_DBUS_PATH_PREFIX "registry"
+#define SPI_DBUS_INTERFACE_REGISTRY              SPI_DBUS_INTERFACE_PREFIX "Registry"
 
-#define SPI_DBUS_INTERFACE_DEC                   "org.freedesktop.atspi.DeviceEventController"
-#define SPI_DBUS_INTERFACE_DEVICE_EVENT_LISTENER "org.freedesktop.atspi.DeviceEventListener"
+#define SPI_DBUS_PATH_DEC                        SPI_DBUS_PATH_PREFIX "registry/deviceeventcontroller"
+#define SPI_DBUS_INTERFACE_DEC                   SPI_DBUS_INTERFACE_PREFIX "DeviceEventController"
+#define SPI_DBUS_INTERFACE_DEVICE_EVENT_LISTENER SPI_DBUS_INTERFACE_PREFIX "DeviceEventListener"
 
-#define SPI_DBUS_INTERFACE_TREE                  "org.freedesktop.atspi.Tree"
-#define SPI_DBUS_INTERFACE_ACCESSIBLE            "org.freedesktop.atspi.Accessible"
-#define SPI_DBUS_INTERFACE_ACTION                "org.freedesktop.atspi.Action"
-#define SPI_DBUS_INTERFACE_APPLICATION           "org.freedesktop.atspi.Application"
-#define SPI_DBUS_INTERFACE_COLLECTION            "org.freedesktop.atspi.Collection"
-#define SPI_DBUS_INTERFACE_COMPONENT             "org.freedesktop.atspi.Component"
-#define SPI_DBUS_INTERFACE_DOCUMENT              "org.freedesktop.atspi.Document"
-#define SPI_DBUS_INTERFACE_EDITABLE_TEXT         "org.freedesktop.atspi.EditableText"
-#define SPI_DBUS_INTERFACE_EVENT_KEYBOARD        "org.freedesktop.atspi.Event.Keyboard"
-#define SPI_DBUS_INTERFACE_EVENT_MOUSE           "org.freedesktop.atspi.Event.Mouse"
-#define SPI_DBUS_INTERFACE_HYPERLINK             "org.freedesktop.atspi.Hyperlink"
-#define SPI_DBUS_INTERFACE_HYPERTEXT             "org.freedesktop.atspi.Hypertext"
-#define SPI_DBUS_INTERFACE_IMAGE                 "org.freedesktop.atspi.Image"
-#define SPI_DBUS_INTERFACE_SELECTION             "org.freedesktop.atspi.Selection"
-#define SPI_DBUS_INTERFACE_TABLE                 "org.freedesktop.atspi.Table"
-#define SPI_DBUS_INTERFACE_TEXT                  "org.freedesktop.atspi.Text"
-#define SPI_DBUS_INTERFACE_VALUE                 "org.freedesktop.atspi.Value"
+#define SPI_DBUS_INTERFACE_ACCESSIBLE            SPI_DBUS_INTERFACE_PREFIX "Accessible"
+#define SPI_DBUS_INTERFACE_COMPONENT             SPI_DBUS_INTERFACE_PREFIX "Component"
+#define SPI_DBUS_INTERFACE_EVENT_KEYBOARD        SPI_DBUS_INTERFACE_PREFIX "Keyboard"
+#define SPI_DBUS_INTERFACE_EVENT_MOUSE           SPI_DBUS_INTERFACE_PREFIX "Event.Mouse"
+#define SPI_DBUS_INTERFACE_EVENT_OBJECT          SPI_DBUS_INTERFACE_PREFIX "Event.Object"
+#define SPI_DBUS_INTERFACE_SOCKET                SPI_DBUS_INTERFACE_PREFIX "Socket"
 
 #endif /* SPI_PATHS_H_ */
diff --git a/registryd/registry.c b/registryd/registry.c
index f720920..92406e0 100644
--- a/registryd/registry.c
+++ b/registryd/registry.c
@@ -2,7 +2,7 @@
  * AT-SPI - Assistive Technology Service Provider Interface
  * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
  *
- * Copyright 2008, Codethink Ltd.
+ * Copyright 2008, 2010 Codethink Ltd.
  * Copyright 2001, 2002 Sun Microsystems Inc.,
  * Copyright 2001, 2002 Ximian, Inc.
  *
@@ -29,11 +29,45 @@
 #include "paths.h"
 #include "registry.h"
 
-enum
+static gboolean
+children_added_listener (DBusConnection * bus,
+                         gint             index,
+                         const gchar    * name,
+                         const gchar    * path);
+
+static gboolean
+children_removed_listener (DBusConnection * bus,
+                           gint             index,
+                           const gchar    * name,
+                           const gchar    * path);
+
+/*---------------------------------------------------------------------------*/
+
+typedef struct _SpiReference
 {
-  REGISTRY_APPLICATION_REMOVE = 0,
-  REGISTRY_APPLICATION_ADD = 1
-};
+  gchar *name;
+  gchar *path;
+} SpiReference;
+
+static SpiReference *
+spi_reference_new (const gchar *name, const gchar *path)
+{
+  SpiReference *ref;
+
+  ref = g_new0 (SpiReference, 1);
+  ref->name = g_strdup (name);
+  ref->path = g_strdup (path);
+
+  return ref;
+}
+
+static void
+spi_reference_free (SpiReference *ref)
+{
+  g_free (ref->name);
+  g_free (ref->path);
+  g_free (ref);
+}
 
 /*---------------------------------------------------------------------------*/
 
@@ -50,209 +84,617 @@ spi_registry_class_init (SpiRegistryClass *klass)
 static void
 spi_registry_init (SpiRegistry *registry)
 {
-  registry->apps = g_sequence_new (g_free);
+  registry->apps = g_ptr_array_new_with_free_func ((GDestroyNotify) spi_reference_free);
 }
 
 /*---------------------------------------------------------------------------*/
 
-static void emit_update_applications(SpiRegistry *reg, guint sigtype, const char *app)
+static dbus_bool_t
+return_v_string (DBusMessageIter * iter, const gchar * str)
 {
-  DBusMessage *msg = NULL;
-  DBusError error;
-
-  dbus_error_init (&error);
+  DBusMessageIter variant;
 
-  if ((msg = dbus_message_new_signal (SPI_DBUS_PATH_REGISTRY,
-                                      SPI_DBUS_INTERFACE_REGISTRY,
-                                      "UpdateApplications"))) {
-    dbus_message_append_args(msg, DBUS_TYPE_INT32, &sigtype,
-                                  DBUS_TYPE_STRING, &app, DBUS_TYPE_INVALID);
-
-    dbus_connection_send (reg->bus, msg, NULL);
+  dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, "s",
+                                    &variant);
+    dbus_message_iter_append_basic (&variant, DBUS_TYPE_STRING, &str);
+  dbus_message_iter_close_container (iter, &variant);
+}
 
-    dbus_message_unref (msg);
-  }
+static void
+append_reference (DBusMessageIter * iter, const char * name, const char * path)
+{
+  DBusMessageIter iter_struct;
 
-  dbus_error_free (&error);
+  dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, NULL,
+                                    &iter_struct);
+  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &name);
+  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, &path);
+  dbus_message_iter_close_container (iter, &iter_struct);
 }
 
-
 /*---------------------------------------------------------------------------*/
 
-static gint
-data_str_cmp (gpointer a, gpointer b, gpointer data)
+static gboolean
+compare_reference (SpiReference *one, SpiReference *two)
 {
-  return g_strcmp0(a, b);
+  if (g_strcmp0 (one->name, two->name) == 0 &&
+      g_strcmp0 (one->path, two->path) == 0)
+    return TRUE;
+  else
+    return FALSE;
 }
 
 static gboolean
-seq_add_string (GSequence *seq, gchar *str)
+find_index_of_reference (GPtrArray *arr, const gchar *name, const gchar * path, guint *index)
 {
-  GSequenceIter *iter;
-  gchar *item;
-  gboolean res = FALSE;
+  SpiReference *ref;
+  gboolean found = FALSE;
+  guint i = 0;
 
-  iter = g_sequence_search (seq, str, (GCompareDataFunc) data_str_cmp, NULL);
-  iter = g_sequence_iter_prev (iter);
+  ref = spi_reference_new (name, path);
 
-  if (!g_sequence_iter_is_end (iter))
+  for (i = 0; i < arr->len && found == FALSE; i++)
     {
-      item = g_sequence_get (iter);
-      if (g_strcmp0 (item, str))
+      if (compare_reference (ref, g_ptr_array_index (arr, i)));
         {
-          g_sequence_insert_sorted (seq, g_strdup(str), (GCompareDataFunc) data_str_cmp, NULL);
-          res = TRUE;
+          found = TRUE;
         }
     }
-  else
-    {
-      g_sequence_insert_sorted (seq, g_strdup(str), (GCompareDataFunc) data_str_cmp, NULL);
-      res = TRUE;
-    }
 
-  return res;
+  spi_reference_free (ref);
+
+  *index = i;
+  return found;
 }
 
-static gboolean
-seq_remove_string (GSequence *seq, gchar *str)
+static void
+add_application (SpiRegistry *reg, DBusConnection *bus, const gchar *name, const gchar *path)
+{
+  g_ptr_array_add (reg->apps, spi_reference_new (name, path));
+  children_added_listener (bus, reg->apps->len - 1, name, path);
+}
+
+static void
+remove_application (SpiRegistry *reg, DBusConnection *bus, guint index)
 {
-  GSequenceIter *iter;
-  gchar *item;
-  gboolean res = FALSE;
+  const gchar *name = "";
+  g_ptr_array_remove_index (reg->apps, index);
+  /*TODO spi_remove_device_listeners (registry->de_controller, old);*/
+  children_removed_listener (bus, index, name, SPI_DBUS_PATH_NULL);
+}
 
-  iter = g_sequence_search (seq, str, (GCompareDataFunc) data_str_cmp, NULL);
-  iter = g_sequence_iter_prev (iter);
+static void
+handle_disconnection (DBusConnection *bus, DBusMessage *message, void *user_data)
+{
+  char *name, *old, *new;
+  SpiRegistry *reg = SPI_REGISTRY (user_data);
 
-  if (!g_sequence_iter_is_end (iter))
+  if (dbus_message_get_args (message, NULL,
+                             DBUS_TYPE_STRING, &name,
+                             DBUS_TYPE_STRING, &old,
+                             DBUS_TYPE_STRING, &new,
+                             DBUS_TYPE_INVALID))
     {
-      item = g_sequence_get (iter);
-      if (!g_strcmp0 (item, str))
+      if (*old != '\0' && *new == '\0')
         {
-          g_sequence_remove (iter);
-          res = TRUE;
+          /* Remove all children with the application name the same as the disconnected application. */
+          guint i;
+          for (i = 0; i < reg->apps->len; i++)
+            {
+              while (g_strcmp0 (old, g_ptr_array_index (reg->apps, i)))
+                {
+                  const gchar *rname = "";
+                  g_ptr_array_remove_index (reg->apps, i);
+                  children_removed_listener (bus, i, rname, SPI_DBUS_PATH_NULL);
+                }
+            } 
         }
     }
+}
+
+static DBusHandlerResult
+signal_filter (DBusConnection *bus, DBusMessage *message, void *user_data)
+{
+  SpiRegistry *registry = SPI_REGISTRY (user_data);
+  guint res = DBUS_HANDLER_RESULT_HANDLED;
+  const char *iface = dbus_message_get_interface (message);
+  const char *member = dbus_message_get_member (message);
+
+  if (!g_strcmp0(iface, DBUS_INTERFACE_DBUS) && !g_strcmp0(member, "NameOwnerChanged"))
+      handle_disconnection (bus, message, user_data);
+  else
+      res = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
   return res;
 }
 
-static void
-add_application (DBusConnection *bus, SpiRegistry *reg, gchar *app)
+/* org.at_spi.Socket interface */
+/*---------------------------------------------------------------------------*/
+
+static DBusMessage*
+impl_Embed (DBusConnection *bus, DBusMessage *message, void *user_data)
 {
-  if (seq_add_string (reg->apps, app))
-    {
-      emit_update_applications (reg, REGISTRY_APPLICATION_ADD, app);
-    }
+  gchar *app_name, *obj_path;
+  SpiRegistry *reg = SPI_REGISTRY (user_data);
+
+  if (dbus_message_get_args (message, NULL,
+                             DBUS_TYPE_STRING, &app_name,
+                             DBUS_TYPE_STRING, &obj_path,
+                             DBUS_TYPE_INVALID))
+      add_application(reg, bus, app_name, obj_path);
+  return NULL;
 }
 
-static void
-remove_application (DBusConnection *bus, SpiRegistry *reg, gchar *app)
+static DBusMessage*
+impl_Unembed (DBusConnection *bus, DBusMessage *message, void *user_data)
 {
-  if (seq_remove_string (reg->apps, app))
+  gchar *app_name, *obj_path;
+  SpiRegistry *reg = SPI_REGISTRY (user_data);
+
+  if (dbus_message_get_args (message, NULL,
+                             DBUS_TYPE_STRING, &app_name,
+                             DBUS_TYPE_STRING, &obj_path,
+                             DBUS_TYPE_INVALID))
     {
-      /*TODO spi_remove_device_listeners (registry->de_controller, old);*/
-      emit_update_applications (reg, REGISTRY_APPLICATION_REMOVE, app);
+      guint index;
+      if (find_index_of_reference (reg->apps, app_name, obj_path, &index))
+          remove_application(reg, bus, index);
     }
+  return NULL;
 }
 
+/* org.at_spi.Component interface */
 /*---------------------------------------------------------------------------*/
 
-static void
-add_bus_name_cb (gpointer item, gpointer data)
+static DBusMessage *
+impl_Contains (DBusConnection * bus, DBusMessage * message, void *user_data)
+{
+  dbus_bool_t retval = FALSE;
+  DBusMessage *reply;
+
+  reply = dbus_message_new_method_return (message);
+  dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &retval,
+                            DBUS_TYPE_INVALID);
+  return reply;
+}
+
+static DBusMessage *
+impl_GetAccessibleAtPoint (DBusConnection * bus, DBusMessage * message,
+                           void *user_data)
+{
+  DBusMessage *reply = NULL;
+  DBusMessageIter iter;
+
+  reply = dbus_message_new_method_return (message);
+  dbus_message_iter_init_append (reply, &iter);
+  append_reference (&iter, 
+                    dbus_bus_get_unique_name (bus),
+                    SPI_DBUS_PATH_NULL);
+
+  return reply;
+}
+
+static DBusMessage *
+impl_GetExtents (DBusConnection * bus, DBusMessage * message, void *user_data)
+{
+  dbus_uint32_t coord_type;
+  dbus_int32_t x = 0, y = 0, width = 1024, height = 768;
+  DBusMessage *reply;
+  DBusMessageIter iter, iter_struct;
+
+  reply = dbus_message_new_method_return (message);
+  dbus_message_iter_init_append (message, &iter);
+  dbus_message_iter_open_container (&iter, DBUS_TYPE_STRUCT, NULL,
+                                    &iter_struct);
+    dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &x);
+    dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &y);
+    dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &width);
+    dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &height);
+  dbus_message_iter_close_container (&iter, &iter_struct);
+  return reply;
+}
+
+static DBusMessage *
+impl_GetPosition (DBusConnection * bus, DBusMessage * message,
+                  void *user_data)
+{
+  DBusMessage *reply;
+  dbus_int32_t x = 0, y = 0;
+
+  reply = dbus_message_new_method_return (message);
+  dbus_message_append_args (reply, DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32,
+                            &y, DBUS_TYPE_INVALID);
+  return reply;
+}
+
+static DBusMessage *
+impl_GetSize (DBusConnection * bus, DBusMessage * message, void *user_data)
+{
+  /* TODO - Get the screen size */
+  DBusMessage *reply;
+  dbus_int32_t width = 1024, height = 768;
+
+  reply = dbus_message_new_method_return (message);
+  dbus_message_append_args (reply, DBUS_TYPE_INT32, &width,
+                            DBUS_TYPE_INT32, &height, DBUS_TYPE_INVALID);
+  return reply;
+}
+
+#define LAYER_WIDGET 3;
+
+static DBusMessage *
+impl_GetLayer (DBusConnection * bus, DBusMessage * message, void *user_data)
+{
+  DBusMessage *reply;
+  dbus_uint32_t rv = LAYER_WIDGET;
+
+  reply = dbus_message_new_method_return (message);
+  dbus_message_append_args (reply, DBUS_TYPE_UINT32, &rv,
+                            DBUS_TYPE_INVALID);
+  return reply;
+}
+
+static DBusMessage *
+impl_GetMDIZOrder (DBusConnection * bus, DBusMessage * message,
+                   void *user_data)
+{
+  DBusMessage *reply;
+  dbus_int16_t rv = 0;
+
+  reply = dbus_message_new_method_return (message);
+  dbus_message_append_args (reply, DBUS_TYPE_INT16, &rv,
+                            DBUS_TYPE_INVALID);
+  return reply;
+}
+
+static DBusMessage *
+impl_GrabFocus (DBusConnection * bus, DBusMessage * message, void *user_data)
+{
+  DBusMessage *reply;
+  dbus_bool_t retval = FALSE;
+
+  reply = dbus_message_new_method_return (message);
+  dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &retval,
+                            DBUS_TYPE_INVALID);
+  return reply;
+}
+
+static DBusMessage *
+impl_GetAlpha (DBusConnection * bus, DBusMessage * message, void *user_data)
+{
+  double rv = 1.0;
+  DBusMessage *reply;
+
+  reply = dbus_message_new_method_return (message);
+  dbus_message_append_args (reply, DBUS_TYPE_DOUBLE, &rv,
+                            DBUS_TYPE_INVALID);
+  return reply;
+}
+
+/* org.at_spi.Accessible interface */
+/*---------------------------------------------------------------------------*/
+
+static dbus_bool_t
+impl_get_Name (DBusMessageIter * iter, void *user_data)
+{
+  const gchar *name = "main";
+  return return_v_string (iter, name);
+}
+
+static dbus_bool_t
+impl_get_Description (DBusMessageIter * iter, void *user_data)
+{
+  const gchar *description = "";
+  return return_v_string (iter, description);
+}
+
+static dbus_bool_t
+impl_get_Parent (DBusMessageIter * iter, void *user_data)
+{
+  const gchar *name = "";
+  append_reference (iter, 
+                    name,
+                    SPI_DBUS_PATH_NULL);
+  return TRUE;
+}
+
+static dbus_bool_t
+impl_get_ChildCount (DBusMessageIter * iter, void *user_data)
+{
+  SpiRegistry *reg = SPI_REGISTRY (user_data);
+  dbus_int32_t rv = reg->apps->len;
+
+  dbus_message_iter_append_basic (iter, DBUS_TYPE_INT32, &rv);
+}
+
+static DBusMessage *
+impl_GetChildAtIndex (DBusConnection * bus,
+                      DBusMessage * message, void *user_data)
 {
-  DBusMessageIter *iter_array = (DBusMessageIter *) data;
+  SpiRegistry *reg = SPI_REGISTRY (user_data);
+  DBusMessage *reply;
+  DBusMessageIter iter;
+  DBusError error;
+  SpiReference *ref;
+  dbus_int32_t i;
+
+  dbus_error_init (&error);
+  if (!dbus_message_get_args 
+       (message, &error, DBUS_TYPE_INT32, &i, DBUS_TYPE_INVALID))
+    {
+      return dbus_message_new_error (message, DBUS_ERROR_FAILED, "Invalid arguments");
+    }
 
-  dbus_message_iter_append_basic (iter_array, DBUS_TYPE_STRING, (gchar **) &item);
+  reply = dbus_message_new_method_return (message);
+  dbus_message_iter_init_append (reply, &iter);
+
+  ref = g_ptr_array_index (reg->apps, i);
+  append_reference (&iter, ref->name, ref->path);
+
+  return reply;
 }
 
 static DBusMessage *
-impl_GetApplications (DBusConnection *bus, DBusMessage *message, void *user_data)
+impl_GetChildren (DBusConnection * bus,
+                  DBusMessage * message, void *user_data)
 {
   DBusMessage *reply = NULL;
   DBusMessageIter iter, iter_array;
   SpiRegistry *reg = SPI_REGISTRY (user_data);
+  int i;
 
   reply = dbus_message_new_method_return (message);
 
   dbus_message_iter_init_append (reply, &iter);
-  dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &iter_array);
-  g_sequence_foreach (reg->apps, add_bus_name_cb, &iter_array);
+  dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(so)", &iter_array);
+  for (i=0; i < reg->apps->len; i++)
+    {
+      SpiReference *current = g_ptr_array_index (reg->apps, i);
+      append_reference (&iter_array, current->name, current->path);
+    }
   dbus_message_iter_close_container(&iter, &iter_array);
   return reply;
 }
 
-/*---------------------------------------------------------------------------*/
+static DBusMessage *
+impl_GetIndexInParent (DBusConnection * bus,
+                       DBusMessage * message, void *user_data)
+{
+  DBusMessage *reply;
+  dbus_uint32_t rv = 0;
 
-static DBusMessage*
-impl_RegisterApplication (DBusConnection *bus, DBusMessage *message, void *user_data)
+  reply = dbus_message_new_method_return (message);
+  dbus_message_append_args (reply, DBUS_TYPE_UINT32, &rv, DBUS_TYPE_INVALID);
+  return reply;
+}
+
+static DBusMessage *
+impl_GetRelationSet (DBusConnection * bus,
+                     DBusMessage * message, void *user_data)
 {
-  gchar *app_name;
-  SpiRegistry *reg = SPI_REGISTRY (user_data);
+  DBusMessage *reply;
+  DBusMessageIter iter, iter_array;
 
-  if (dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &app_name, DBUS_TYPE_INVALID))
-      add_application(bus, reg, app_name);
-  return NULL;
+  reply = dbus_message_new_method_return (message);
+  dbus_message_iter_init_append (reply, &iter);
+  dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "(ua(so))", &iter_array);
+  dbus_message_iter_close_container (&iter, &iter_array);
+
+  return reply;
 }
 
-static DBusMessage*
-impl_DeregisterApplication (DBusConnection *bus, DBusMessage *message, void *user_data)
+static DBusMessage *
+impl_GetRole (DBusConnection * bus, DBusMessage * message, void * user_data)
 {
-  gchar *app_name;
-  SpiRegistry *reg = SPI_REGISTRY (user_data);
+  DBusMessage *reply;
+  dbus_uint32_t rv = 0;
 
-  if (dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &app_name, DBUS_TYPE_INVALID))
-      remove_application(bus, reg, app_name);
-  return NULL;
+  reply = dbus_message_new_method_return (message);
+  dbus_message_append_args (reply, DBUS_TYPE_UINT32, &rv, DBUS_TYPE_INVALID);
+  return reply;
 }
 
-/*---------------------------------------------------------------------------*/
+static DBusMessage *
+impl_GetRoleName (DBusConnection * bus,
+                  DBusMessage * message, void *user_data)
+{
+  DBusMessage *reply;
+  const char *role_name = "unknown";
 
-static void
-handle_disconnection (DBusConnection *bus, DBusMessage *message, void *user_data)
+  reply = dbus_message_new_method_return (message);
+  dbus_message_append_args (reply, DBUS_TYPE_STRING, &role_name,
+                            DBUS_TYPE_INVALID);
+  return reply;
+}
+
+static DBusMessage *
+impl_GetLocalizedRoleName (DBusConnection * bus,
+                           DBusMessage * message, void *user_data)
 {
-  char *name, *old, *new;
-  SpiRegistry *reg = SPI_REGISTRY (user_data);
+  /* TODO - Localize this */
+  DBusMessage *reply;
+  const char *role_name = "unknown";
 
-  if (dbus_message_get_args (message, NULL,
-                             DBUS_TYPE_STRING, &name,
-                             DBUS_TYPE_STRING, &old,
-                             DBUS_TYPE_STRING, &new,
-                             DBUS_TYPE_INVALID))
+  reply = dbus_message_new_method_return (message);
+  dbus_message_append_args (reply, DBUS_TYPE_STRING, &role_name,
+                            DBUS_TYPE_INVALID);
+  return reply;
+}
+
+static DBusMessage *
+impl_GetState (DBusConnection * bus, DBusMessage * message, void *user_data)
+{
+  DBusMessage *reply = NULL;
+  DBusMessageIter iter, iter_array;
+
+  dbus_uint32_t states[2] = {0, 0};
+  guint count;
+
+  reply = dbus_message_new_method_return (message);
+  dbus_message_iter_init_append (reply, &iter);
+
+  dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "u", &iter_array);
+  for (count = 0; count < 2; count++)
     {
-      if (*old != '\0' && *new == '\0')
-        {
-          remove_application(bus, reg, old);
-        }
+      dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_UINT32,
+                                      &states[count]);
     }
+  dbus_message_iter_close_container (&iter, &iter_array);
+  return reply;
+}
+
+static DBusMessage *
+impl_GetAttributes (DBusConnection * bus,
+                    DBusMessage * message, void *user_data)
+{
+  DBusMessage *reply = NULL;
+  DBusMessageIter iter, array;
+
+  reply = dbus_message_new_method_return (message);
+  dbus_message_iter_init_append (reply, &iter);
+  dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "{ss}", &array);
+  dbus_message_iter_close_container (&iter, &array);
+
+  return reply;
+}
+
+static DBusMessage *
+impl_GetApplication (DBusConnection * bus,
+                     DBusMessage * message, void *user_data)
+{
+  DBusMessage *reply = NULL;
+  DBusMessageIter iter;
+
+  reply = dbus_message_new_method_return (message);
+  dbus_message_iter_init_append (reply, &iter);
+  append_reference (&iter,
+                    dbus_bus_get_unique_name (bus),
+                    SPI_DBUS_PATH_NULL);
+
+  return reply;
+}
+
+static DBusMessage *
+impl_GetInterfaces (DBusConnection * bus,
+                    DBusMessage * message, void *user_data)
+{
+  DBusMessage *reply;
+  DBusMessageIter iter, iter_array;
+
+  const char *acc = SPI_DBUS_INTERFACE_ACCESSIBLE;
+  const char *com = SPI_DBUS_INTERFACE_COMPONENT;
+
+  reply = dbus_message_new_method_return (message);
+
+  dbus_message_iter_init_append (reply, &iter);
+  dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "s",
+                                    &iter_array);
+    dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_STRING, &acc);
+    dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_STRING, &com);
+  dbus_message_iter_close_container (&iter, &iter_array);
+
+  return reply;
 }
 
 /*---------------------------------------------------------------------------*/
 
-static DBusHandlerResult
-signal_filter (DBusConnection *bus, DBusMessage *message, void *user_data)
+static void 
+emit_Available (DBusConnection * bus)
 {
-  SpiRegistry *registry = SPI_REGISTRY (user_data);
-  guint res = DBUS_HANDLER_RESULT_HANDLED;
-  const char *iface = dbus_message_get_interface (message);
-  const char *member = dbus_message_get_member (message);
+  DBusMessage *sig;
+  DBusMessageIter iter;
+  
+  sig = dbus_message_new_signal(SPI_DBUS_PATH_ROOT, SPI_DBUS_INTERFACE_SOCKET, "Available");
 
-  if (!g_strcmp0(iface, DBUS_INTERFACE_DBUS) && !g_strcmp0(member, "NameOwnerChanged"))
-      handle_disconnection (bus, message, user_data);
-  else
-      res = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+  dbus_message_iter_init_append(sig, &iter);
+  append_reference (&iter, SPI_DBUS_NAME_REGISTRY, SPI_DBUS_PATH_ROOT);
 
-  return res;
+  dbus_connection_send(bus, sig, NULL);
+  dbus_message_unref(sig);
 }
 
 /*---------------------------------------------------------------------------*/
 
-#define _SPI_DEBUG(format, args...) g_print (format , ## args)
+/*
+ * Emits an AT-SPI event.
+ * AT-SPI events names are split into three parts:
+ * class:major:minor
+ * This is mapped onto D-Bus events as:
+ * D-Bus Interface:Signal Name:Detail argument
+ *
+ * Marshals a basic type into the 'any_data' attribute of
+ * the AT-SPI event.
+ */
+static void 
+emit_event (DBusConnection *bus,
+            const char *klass,
+            const char *major,
+            const char *minor,
+            dbus_int32_t detail1,
+            dbus_int32_t detail2,
+            const char *name,
+            const char *path)
+{
+  DBusMessage *sig;
+  DBusMessageIter iter, iter_variant;
+  
+  sig = dbus_message_new_signal(SPI_DBUS_PATH_ROOT, klass, major);
 
-static gchar *app_sig_match_name_owner =
-       "type='signal', interface='org.freedesktop.DBus', member='NameOwnerChanged'";
+  dbus_message_iter_init_append(sig, &iter);
+
+  dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &minor);
+  dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &detail1);
+  dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &detail2);
+
+  dbus_message_iter_open_container (&iter, DBUS_TYPE_VARIANT, "(so)",
+                                    &iter_variant);
+    append_reference (&iter_variant, name, path);
+  dbus_message_iter_close_container (&iter, &iter_variant);
+
+  dbus_connection_send(bus, sig, NULL);
+  dbus_message_unref(sig);
+}
+
+/*---------------------------------------------------------------------------*/
+
+/*
+ * Children changed signal converter and forwarder.
+ *
+ * Klass (Interface) org.freedesktop.atspi.Event.Object
+ * Major is the signal name.
+ * Minor is 'add' or 'remove'
+ * detail1 is the index.
+ * detail2 is 0.
+ * any_data is the child reference.
+ */
+
+static gboolean
+children_added_listener (DBusConnection * bus,
+                         gint             index,
+                         const gchar    * name,
+                         const gchar    * path)
+{
+  emit_event (bus, SPI_DBUS_INTERFACE_EVENT_OBJECT, "ChildrenChanged", "add", index, 0,
+              name, path);
+}
+
+static gboolean
+children_removed_listener (DBusConnection * bus,
+                           gint             index,
+                           const gchar    * name,
+                           const gchar    * path)
+{
+  emit_event (bus, SPI_DBUS_INTERFACE_EVENT_OBJECT, "ChildrenChanged", "remove", index, 0,
+              name, SPI_DBUS_PATH_NULL);
+}
+
+/*---------------------------------------------------------------------------*/
 
 static DBusHandlerResult
-handle_registry_method (DBusConnection *bus, DBusMessage *message, void *user_data)
+handle_method (DBusConnection *bus, DBusMessage *message, void *user_data)
 {
+  DBusHandlerResult result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
   const gchar *iface   = dbus_message_get_interface (message);
   const gchar *member  = dbus_message_get_member (message);
   const gint   type    = dbus_message_get_type (message);
@@ -265,35 +707,148 @@ handle_registry_method (DBusConnection *bus, DBusMessage *message, void *user_da
       iface  == NULL)
       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 
-  if (strcmp (iface, SPI_DBUS_INTERFACE_REGISTRY))
-      return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+  if (!strcmp (iface, "org.freedesktop.DBus.Properties"))
+    {
+      if (!strcmp (member, "Get"))
+        {
+          const gchar *prop_iface;
+          const gchar *prop_member;
+          DBusError error;
+
+          dbus_error_init (&error);
+          if (dbus_message_get_args (message,
+                                     &error,
+                                     DBUS_TYPE_STRING,
+                                     &prop_iface,
+                                     DBUS_TYPE_STRING,
+                                     &prop_member,
+                                     DBUS_TYPE_INVALID))
+            {
+              DBusMessageIter iter;
+
+              reply = dbus_message_new_method_return (message);
+              dbus_message_iter_init_append (reply, &iter);
+
+              if (strcmp (iface, SPI_DBUS_INTERFACE_ACCESSIBLE))
+                {
+                  if      (!strcmp (member, "Name"))
+                    impl_get_Name (&iter, user_data);
+                  else if (!strcmp (member, "Description"))
+                    impl_get_Description (&iter, user_data);
+                  else if (!strcmp (member, "Parent"))
+                    impl_get_Parent (&iter, user_data);
+                  else if (!strcmp (member, "ChildCount"))
+                    impl_get_ChildCount (&iter, user_data);
+                  else
+                    {
+                      dbus_message_unref (reply); 
+                      reply = dbus_message_new_error (message, DBUS_ERROR_FAILED, "Property unavailable");
+                    }
+                }
+            }
+          else
+            {
+              reply = dbus_message_new_error (message, DBUS_ERROR_FAILED, error.message);
+            }
+          result = DBUS_HANDLER_RESULT_HANDLED;
+        }
+      else if (!strcmp (member, "GetAll"))
+        {
+          result = DBUS_HANDLER_RESULT_HANDLED;
+        }
+    }
 
-  if      (!strcmp (member, "GetApplications"))
-      reply = impl_GetApplications (bus, message, user_data);
-  else if (!strcmp (member, "RegisterApplication"))
-      reply = impl_RegisterApplication (bus, message, user_data);
-  else if (!strcmp (member, "DeregisterApplication"))
-      reply = impl_DeregisterApplication (bus, message, user_data);
-  else
-      return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+  if (strcmp (iface, SPI_DBUS_INTERFACE_ACCESSIBLE))
+    {
+      result = DBUS_HANDLER_RESULT_HANDLED;
+      if      (!strcmp (member, "GetChildAtIndex"))
+          reply = impl_GetChildAtIndex (bus, message, user_data);
+      else if (!strcmp (member, "GetChildren"))
+          reply = impl_GetChildren (bus, message, user_data);
+      else if (!strcmp (member, "GetIndexInParent"))
+          reply = impl_GetIndexInParent (bus, message, user_data);
+      else if (!strcmp (member, "GetRelationSet"))
+          reply = impl_GetRelationSet (bus, message, user_data);
+      else if (!strcmp (member, "GetRole"))
+          reply = impl_GetRole (bus, message, user_data);
+      else if (!strcmp (member, "GetRoleName"))
+          reply = impl_GetRoleName (bus, message, user_data);
+      else if (!strcmp (member, "GetLocalizedRoleName"))
+          reply = impl_GetLocalizedRoleName (bus, message, user_data);
+      else if (!strcmp (member, "GetState"))
+          reply = impl_GetState (bus, message, user_data);
+      else if (!strcmp (member, "GetAttributes"))
+          reply = impl_GetAttributes (bus, message, user_data);
+      else if (!strcmp (member, "GetApplication"))
+          reply = impl_GetApplication (bus, message, user_data);
+      else if (!strcmp (member, "GetInterfaces"))
+          reply = impl_GetInterfaces (bus, message, user_data);
+      else
+         result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+    }
+
+  if (strcmp (iface, SPI_DBUS_INTERFACE_COMPONENT))
+    {
+      result = DBUS_HANDLER_RESULT_HANDLED;
+      if      (!strcmp (member, "Contains"))
+          reply = impl_Contains (bus, message, user_data);
+      else if (!strcmp (member, "GetAccessibleAtPoint"))
+          reply = impl_GetAccessibleAtPoint (bus, message, user_data);
+      else if (!strcmp (member, "GetExtents"))
+          reply = impl_GetExtents (bus, message, user_data);
+      else if (!strcmp (member, "GetPosition"))
+          reply = impl_GetPosition (bus, message, user_data);
+      else if (!strcmp (member, "GetSize"))
+          reply = impl_GetSize (bus, message, user_data);
+      else if (!strcmp (member, "GetLayer"))
+          reply = impl_GetLayer (bus, message, user_data);
+      else if (!strcmp (member, "GetMDIZOrder"))
+          reply = impl_GetMDIZOrder (bus, message, user_data);
+      else if (!strcmp (member, "GrabFocus"))
+          reply = impl_GrabFocus (bus, message, user_data);
+      else if (!strcmp (member, "GetAlpha"))
+          reply = impl_GetAlpha (bus, message, user_data);
+      else
+         result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+    }
+
+  if (strcmp (iface, SPI_DBUS_INTERFACE_SOCKET))
+    {
+      result = DBUS_HANDLER_RESULT_HANDLED;
+      if      (!strcmp (member, "Embed"))
+          reply = impl_Embed (bus, message, user_data);
+      else if (!strcmp (member, "Unembed"))
+          reply = impl_Unembed (bus, message, user_data);
+      else
+         result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+    }
 
-  if (!reply)
+  if (result == DBUS_HANDLER_RESULT_HANDLED)
     {
-      reply = dbus_message_new_method_return (message);
+      if (!reply)
+        {
+          reply = dbus_message_new_method_return (message);
+        }
+
+      dbus_connection_send (bus, reply, NULL);
+      dbus_message_unref (reply);
     }
-  dbus_connection_send (bus, reply, NULL);
-  dbus_message_unref (reply);
   
-  return DBUS_HANDLER_RESULT_HANDLED;
+  return result;
 }
 
+/*---------------------------------------------------------------------------*/
+
 static DBusObjectPathVTable registry_vtable =
 {
   NULL,
-  &handle_registry_method,
+  &handle_method,
   NULL, NULL, NULL, NULL
 };
 
+static gchar *app_sig_match_name_owner =
+       "type='signal', interface='org.freedesktop.DBus', member='NameOwnerChanged'";
+
 SpiRegistry *
 spi_registry_new (DBusConnection *bus)
 {
@@ -306,6 +861,8 @@ spi_registry_new (DBusConnection *bus)
 
   dbus_connection_register_object_path (bus, SPI_DBUS_PATH_REGISTRY, &registry_vtable, reg);
 
+  emit_Available (bus);
+
   return reg;
 }
 
diff --git a/registryd/registry.h b/registryd/registry.h
index 6d1be2a..ec33618 100644
--- a/registryd/registry.h
+++ b/registryd/registry.h
@@ -42,7 +42,7 @@ G_BEGIN_DECLS
 
 struct _SpiRegistry {
   GObject      parent;
-  GSequence   *apps;
+  GPtrArray   *apps;
 
   DBusConnection *bus;
 };



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