Temporary commit. Non working changes to the registration
[platform/core/uifw/at-spi2-atk.git] / atk-adaptor / tree.c
index eaf5cbe..8652f77 100644 (file)
 #include <droute/introspect-loader.h>
 
 #include "accessible.h"
+#include "bridge.h"
 
-#define get_object(message) spi_dbus_get_object(dbus_message_get_path(message))
+extern SpiAppData *app_data;
+static gboolean update_pending = FALSE;
 
-static dbus_bool_t
-append_update (DBusMessageIter * iter_array, AtkObject * obj,
-                            dbus_bool_t include_children, DRouteData * data)
+/*---------------------------------------------------------------------------*/
+
+static const char *dumm = "/APath/1";
+
+/*
+ * Marshals the given AtkObject into the provided D-Bus iterator.
+ *
+ * The object is marshalled including all its client side cache data.
+ * The format of the strucuture is (ooaoassus).
+ * This is used in the updateTree signal and the getTree method
+ * of the org.freedesktop.atspi.Tree interface.
+ */
+static void
+append_accessible(gpointer ref, gpointer obj_data, gpointer iter)
 {
+  AtkObject *obj;
+  DBusMessageIter *iter_array;
   DBusMessageIter iter_struct, iter_sub_array;
-  char *path = NULL;
-  char *path_parent;
+  DRouteData *data;
+
   const char *name, *desc;
   int i;
   dbus_uint32_t role;
-
-  gint childcount;
   GSList *l;
 
-  g_assert(data != NULL);
-
-  dbus_message_iter_open_container (iter_array, DBUS_TYPE_STRUCT, NULL,
-                                   &iter_struct);
-  path = spi_dbus_get_path (obj);
-  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, &path);
-  path_parent = spi_dbus_get_path (atk_object_get_parent(obj));
-  if (!path_parent) path_parent = g_strdup("/");
-  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, &path_parent);
-  g_free(path_parent);
-  dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "o",
-                                   &iter_sub_array);
-  childcount = atk_object_get_n_accessible_children (obj);
-  for (i = 0; i < childcount; i++)
-    {
-      AtkObject *child = atk_object_ref_accessible_child (obj, i);
-      char *child_path = spi_dbus_get_path (child);
-      if (child_path)
-       {
-         dbus_message_iter_append_basic (&iter_sub_array,
-                                         DBUS_TYPE_OBJECT_PATH, &child_path);
-         g_free (child_path);
-       }
-      if (child)
-       g_object_unref (child);
-    }
-  if (!dbus_message_iter_close_container (&iter_struct, &iter_sub_array))
-    goto oom;
-  dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "s",
-                                   &iter_sub_array);
-  if (data) for (l = data->interfaces; l; l = g_slist_next (l))
-    {
-      DRouteInterface *iface_def = (DRouteInterface *) l->data;
-      void *datum = NULL;
-      if (iface_def->get_datum)
-       {
-         datum = (*iface_def->get_datum) (path, data->user_data);
-         if (!datum)
-           continue;
-       }
-      dbus_message_iter_append_basic (&iter_sub_array, DBUS_TYPE_STRING,
-                                     &iface_def->name);
-      if (iface_def->free_datum)
-       (*iface_def->free_datum) (datum);
-    }
-  if (!dbus_message_iter_close_container (&iter_struct, &iter_sub_array))
-    goto oom;
-  name = atk_object_get_name (obj);
-  if (!name)
-    name = "";
-  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &name);
-  role = spi_accessible_role_from_atk_role (atk_object_get_role (obj));
-  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &role);
-  desc = atk_object_get_description (obj);
-  if (!desc)
-    desc = "";
-  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &desc);
-  if (!dbus_message_iter_close_container (iter_array, &iter_struct))
-    goto oom;
-  if (!include_children) childcount = 0;
-  for (i = 0; i < childcount; i++)
+  obj = ATK_OBJECT(obj_data);
+  iter_array = (DBusMessageIter *) iter;
+  data = &(app_data->droute);
+
+  dbus_message_iter_open_container (iter_array, DBUS_TYPE_STRUCT, NULL, &iter_struct);
     {
-      AtkObject *child = atk_object_ref_accessible_child (obj, i);
-      dbus_bool_t result;
-      if (!child)
-       continue;
-      result = append_update (iter_array, child, TRUE, data);
-      g_object_unref (child);
-      if (!result)
-       goto oom;
-    }
-  g_free (path);
-  return TRUE;
-oom:
-  if (path) g_free(path);
-  return FALSE;
+      AtkObject *parent;
+      gchar *path, *path_parent;
+
+      path = atk_dbus_get_path_from_ref(GPOINTER_TO_INT(ref));
+      dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, &path);
+
+      parent = atk_object_get_parent(obj);
+      if (parent == NULL)
+        path_parent = g_strdup("/");
+      else
+        path_parent = atk_dbus_get_path (parent);
+      dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, &path_parent);
+      g_free(path_parent);
+
+      dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "o", &iter_sub_array);
+        {
+          gint childcount, i;
+
+          childcount = atk_object_get_n_accessible_children (obj);
+          for (i = 0; i < childcount; i++)
+            {
+              AtkObject *child;
+              gchar *child_path;
+             
+              child = atk_object_ref_accessible_child (obj, i);
+             child_path = atk_dbus_get_path (child);
+             g_object_unref(G_OBJECT(child));
+             dbus_message_iter_append_basic (&iter_sub_array, DBUS_TYPE_OBJECT_PATH, &child_path);
+             g_free (child_path);
+           }
+        }
+      dbus_message_iter_close_container (&iter_struct, &iter_sub_array);
+
+      dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "s", &iter_sub_array);
+        {
+          for (l = data->interfaces; l; l = g_slist_next (l))
+            {
+              DRouteInterface *iface_def = (DRouteInterface *) l->data;
+              void *datum = NULL;
+
+              if (iface_def->get_datum)
+               {
+                 datum = (*iface_def->get_datum) (path, data->user_data);
+                 if (!datum)
+                   continue;
+               }
+              dbus_message_iter_append_basic (&iter_sub_array, DBUS_TYPE_STRING, &iface_def->name);
+              if (iface_def->free_datum)
+               (*iface_def->free_datum) (datum);
+            }
+        }
+      dbus_message_iter_close_container (&iter_struct, &iter_sub_array);
+
+      name = atk_object_get_name (obj);
+      if (!name)
+        name = "";
+      dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &name);
+
+      role = spi_accessible_role_from_atk_role (atk_object_get_role (obj));
+      dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &role);
+
+      desc = atk_object_get_description (obj);
+      if (!desc)
+        desc = "";
+      dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &desc);
+
+      g_free(path);
+    }      
+  dbus_message_iter_close_container (iter_array, &iter_struct);
 }
 
-dbus_bool_t
-spi_dbus_append_tree (DBusMessage * message, AtkObject * obj,
-                     DRouteData * data)
+/*---------------------------------------------------------------------------*/
+
+/*
+ * Used to marshal array of objects to remove.
+ * Marshalls an object path onto the iter provided.
+ */
+static void
+append_accessible_path(gpointer ref_data, gpointer null, gpointer data)
 {
-  DBusMessageIter iter, iter_array;
-  dbus_bool_t result;
+  guint ref;
+  gchar *path;
+  DBusMessageIter *iter_array;
+
+  iter_array = (DBusMessageIter *) data;
+  ref = GPOINTER_TO_INT(ref_data);
+  path = atk_dbus_get_path_from_ref(ref);
+  dbus_message_iter_append_basic (iter_array, DBUS_TYPE_OBJECT_PATH, &path);
+  g_free(path);
+}
+
+/*---------------------------------------------------------------------------*/
+
+static gboolean
+send_cache_update(gpointer d)
+{
+  DBusMessage *message;
+  DBusMessageIter iter;
+  DBusMessageIter iter_array;
+  DRouteData *data;
 
-  g_assert(data != NULL);
+  data = &(app_data->droute);
+
+  message = dbus_message_new_signal ("/org/freedesktop/atspi/tree", SPI_DBUS_INTERFACE_TREE, "updateTree");
 
   dbus_message_iter_init_append (message, &iter);
-  dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "(ooaoassus)",
-                                   &iter_array);
-  result = append_update (&iter_array, obj, TRUE, data);
-  if (result)
-    result = dbus_message_iter_close_container (&iter, &iter_array);
-  return result;
+
+  dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "(ooaoassus)", &iter_array);
+  atk_dbus_foreach_update_list(append_accessible, &iter_array);
+  dbus_message_iter_close_container(&iter, &iter_array);
+
+  dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "o", &iter_array);
+  atk_dbus_foreach_remove_list(append_accessible_path, &iter_array);
+  dbus_message_iter_close_container(&iter, &iter_array);
+
+  dbus_connection_send(data->bus, message, NULL);
+  update_pending = FALSE;
+
+  return FALSE;
 }
 
+/*---------------------------------------------------------------------------*/
+
+void
+atk_tree_cache_needs_update(void)
+{
+  if (!update_pending)
+    {
+      g_idle_add(send_cache_update, NULL);
+      update_pending = TRUE;
+    }
+}
+
+/*---------------------------------------------------------------------------*/
+
 static DBusMessage *
-impl_getRoot (DBusConnection * bus, DBusMessage * message, void *user_data)
+impl_getRoot (DBusConnection *bus, DBusMessage *message, void *user_data)
 {
   AtkObject *root = atk_get_root();
   char *path;
   DBusMessage *reply;
 
-  if (root) path = spi_dbus_get_path(root);
+  if (root) path = atk_dbus_get_path(root);
   if (!root || !path)
     return spi_dbus_general_error (message);
   reply = dbus_message_new_method_return (message);
-  dbus_message_append_args (reply, DBUS_TYPE_OBJECT_PATH, &path,
-                           DBUS_TYPE_INVALID);
+  dbus_message_append_args (reply, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID);
   g_free (path);
   return reply;
 }
 
+/*---------------------------------------------------------------------------*/
+
 static DBusMessage *
-impl_getTree (DBusConnection * bus, DBusMessage * message, void *user_data)
+impl_getTree (DBusConnection *bus, DBusMessage *message, void *user_data)
 {
   DBusMessage *reply;
+  DBusMessageIter iter, iter_array;
   AtkObject *root = atk_get_root();
 
-  if (!root) return spi_dbus_general_error(message);
+  if (!root) 
+     return spi_dbus_general_error(message);
   reply = dbus_message_new_method_return (message);
-  spi_dbus_append_tree (reply, root, (DRouteData *) user_data);
+
+  dbus_message_iter_init_append (reply, &iter);
+  dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ooaoassus)", &iter_array);
+  atk_dbus_foreach_registered(append_accessible, &iter_array);
+  dbus_message_iter_close_container(&iter, &iter_array);
   return reply;
 }
 
+/*---------------------------------------------------------------------------*/
+
 static DBusMessage *
 impl_introspect (DBusConnection *bus, DBusMessage *message, void *user_data)
 {
@@ -197,6 +264,8 @@ impl_introspect (DBusConnection *bus, DBusMessage *message, void *user_data)
   return reply;
 }
 
+/*---------------------------------------------------------------------------*/
+
 static DBusHandlerResult
 message_handler (DBusConnection *bus, DBusMessage *message, void *user_data)
 {
@@ -237,6 +306,8 @@ message_handler (DBusConnection *bus, DBusMessage *message, void *user_data)
   return DBUS_HANDLER_RESULT_HANDLED;
 }
 
+/*---------------------------------------------------------------------------*/
+
 static DBusObjectPathVTable tree_vtable =
 {
   NULL,
@@ -244,6 +315,8 @@ static DBusObjectPathVTable tree_vtable =
   NULL, NULL, NULL, NULL
 };
 
+/*---------------------------------------------------------------------------*/
+
 void
 spi_register_tree_object(DBusConnection *bus,
                         DRouteData *data,
@@ -254,147 +327,4 @@ spi_register_tree_object(DBusConnection *bus,
   g_assert(mem == TRUE);
 }
 
-static GHashTable *cache_list;
-
-#define UPDATE_NEW     1
-#define UPDATE_REFRESH 2
-#define UPDATE_REMOVE 3
-
-static int update_pending = 0;
-static gint update_pending_id;
-
-typedef struct
-{
-  DBusMessageIter iter;
-  DRouteData *droute;
-  gboolean removing;
-} CacheIterData;
-
-static void handle_cache_item(char *path, guint action, CacheIterData *d)
-{
-  AtkObject *obj;
-
-  switch (action)
-  {
-  case UPDATE_NEW:
-  case UPDATE_REFRESH:
-  default:
-    if (d->removing) return;
-    obj = spi_dbus_get_object(path);
-//printf("update %s\n", path);
-    append_update(&d->iter, obj, FALSE, d->droute);
-    break;
-  case UPDATE_REMOVE:
-//printf("remove: %s\n", path);
-    if (!d->removing) return;
-    dbus_message_iter_append_basic(&d->iter, DBUS_TYPE_OBJECT_PATH, &path);
-    break;
-  }
-  g_hash_table_remove(cache_list, path);
-}
-
-gboolean spi_dbus_update_cache(DRouteData *data)
-{
-  DBusMessage *message;
-  DBusMessageIter iter;
-  CacheIterData d;
-
-  g_assert(data != NULL);
-
-  if (update_pending == 0) return FALSE;
-//printf("Sending cache\n");
-  message = dbus_message_new_signal ("/org/freedesktop/atspi/tree", SPI_DBUS_INTERFACE_TREE, "updateTree");
-  if (!message) goto done;
-  dbus_message_iter_init_append (message, &iter);
-  dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "(ooaoassus)",
-                                   &d.iter);
-  d.droute = data;
-  d.removing = FALSE;
-  do
-  {
-    /* This loop is needed because appending an item may cause new children
-     * to be registered and consequently added to the hash, so they, too,
-     * will need to be sent with the update */
-    update_pending = 0;
-    g_hash_table_foreach(cache_list, (GHFunc)handle_cache_item, &d);
-  } while (update_pending);
-  dbus_message_iter_close_container(&iter, &d.iter);
-  dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "o", &d.iter);
-  d.removing = TRUE;
-  g_hash_table_foreach(cache_list, (GHFunc)handle_cache_item, &d);
-  dbus_message_iter_close_container(&iter, &d.iter);
-  dbus_connection_send(data->bus, message, NULL);
-done:
-  return FALSE;
-}
-
-void spi_dbus_notify_change(AtkObject *obj, gboolean new, DRouteData *data)
-{
-  guint action = (new? UPDATE_NEW: UPDATE_REFRESH);
-  char *path = spi_dbus_get_path(obj);
-
-  if (!cache_list)
-  {
-    cache_list = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
-    if (!cache_list)
-    {
-      g_free(path);
-      return;
-    }
-  }
-  if (g_hash_table_lookup(cache_list, path))
-  {
-    g_free(path);
-    return;
-  }
-//printf("change: %s\n", path);
-  g_hash_table_insert(cache_list, path, (gpointer)action);
-  if (update_pending != 2 && data)
-  {
-    update_pending_id = g_idle_add((GSourceFunc)spi_dbus_update_cache, data);
-    update_pending = 2;
-  }
-  else if (!update_pending) update_pending = 1;
-}
-
-void spi_dbus_notify_remove(AtkObject *obj, DRouteData *data)
-{
-  guint action = UPDATE_REMOVE;
-  guint cur_action;
-  gchar *path = spi_dbus_get_path(obj);
-
-//printf("notify remove: %s\n", path);
-  if (!cache_list)
-  {
-    g_free(path);
-    return;
-  }
-  cur_action = (guint)g_hash_table_lookup(cache_list, path);
-  if (cur_action == UPDATE_NEW)
-  {
-    /* No one knew that this object ever existed, so just remove it */
-//printf("Removing object from send queue\n");
-    g_hash_table_remove(cache_list, path);
-    g_free(path);
-  }
-  else
-  {
-    g_hash_table_insert(cache_list, path, (gpointer)action);
-    if (update_pending != 2 && data)
-    {
-      update_pending_id = g_idle_add((GSourceFunc)spi_dbus_update_cache, data);
-      update_pending = 2;
-    }
-    else if (!update_pending) update_pending = 1;
-  }
-}
-
-gboolean spi_dbus_object_is_known(AtkObject *obj)
-{
-  guint cur_action;
-  char *path = spi_dbus_get_path(obj);
-  if (!path) return FALSE;
-  cur_action = (guint)g_hash_table_lookup(cache_list, path);
-  g_free(path);
-  return (cur_action != UPDATE_NEW);
-}
+/*END------------------------------------------------------------------------*/