Remove X related lines
[platform/core/uifw/at-spi2-atk.git] / atk-adaptor / adaptors / collection-adaptor.c
index efefa43..af45afc 100644 (file)
@@ -26,6 +26,7 @@
 
 #include <atk/atk.h>
 #include <droute/droute.h>
+#include "bridge.h"
 
 #include "bitarray.h"
 #include "spi-dbus.h"
@@ -119,7 +120,7 @@ match_states_any_p (AtkObject * child, gint * set)
 
   for (i = 0; set[i] != BITARRAY_SEQ_TERM; i++)
     {
-      if (!atk_state_set_contains_state (chs, set[i]))
+      if (atk_state_set_contains_state (chs, set[i]))
         {
           ret = TRUE;
           break;
@@ -609,7 +610,7 @@ query_exec (MatchRulePrivate * mrp, AtspiCollectionSortOrder sortby,
 }
 
 static gboolean
-bitarray_to_seq (int *array, int array_count, int **ret)
+bitarray_to_seq (dbus_uint32_t *array, int array_count, int **ret)
 {
   int out_size = 4;
   int out_count = 0;
@@ -650,8 +651,6 @@ read_mr (DBusMessageIter * iter, MatchRulePrivate * mrp)
   int array_count;
   AtkAttribute *attr;
   int i;
-  const char *str;
-  char *interfaces = NULL;
 
   dbus_message_iter_recurse (iter, &iter_struct);
 
@@ -674,14 +673,38 @@ read_mr (DBusMessageIter * iter, MatchRulePrivate * mrp)
   while (dbus_message_iter_get_arg_type (&iter_dict) != DBUS_TYPE_INVALID)
     {
       const char *key, *val;
+      const char *p, *q;
       dbus_message_iter_recurse (&iter_dict, &iter_dict_entry);
       dbus_message_iter_get_basic (&iter_dict_entry, &key);
       dbus_message_iter_next (&iter_dict_entry);
       dbus_message_iter_get_basic (&iter_dict_entry, &val);
-      attr = g_new (AtkAttribute, 1);
-      attr->name = g_strdup (key);
-      attr->value = g_strdup (val);
-      mrp->attributes = g_slist_prepend (mrp->attributes, attr);
+      p = q = val;
+      for (;;)
+      {
+        if (*q == '\0' || (*q == ':' && (q == val || q[-1] != '\\')))
+        {
+          char *tmp;
+          attr = g_new (AtkAttribute, 1);
+          attr->name = g_strdup (key);
+          attr->value = g_strdup (p);
+          attr->value[q - p] = '\0';
+          tmp = attr->value;
+          while (*tmp != '\0')
+          {
+            if (*tmp == '\\')
+              memmove (tmp, tmp + 1, strlen (tmp));
+            else
+              tmp++;
+          }
+          mrp->attributes = g_slist_prepend (mrp->attributes, attr);
+          if (*q == '\0')
+            break;
+          else
+            p = ++q;
+        }
+        else
+          q++;
+      }
       dbus_message_iter_next (&iter_dict);
     }
   dbus_message_iter_next (&iter_struct);
@@ -768,19 +791,18 @@ GetMatchesFrom (DBusMessage * message,
   GList *ls = NULL;
   AtkObject *parent;
   glong index = atk_object_get_index_in_parent (current_object);
-  gint kount = 0;
 
   ls = g_list_append (ls, current_object);
 
   if (!isrestrict)
     {
       parent = atk_object_get_parent (current_object);
-      kount = query_exec (mrp, sortby, ls, 0, count, parent, index,
-                          FALSE, NULL, TRUE, traverse);
+      query_exec (mrp, sortby, ls, 0, count, parent, index,
+                  FALSE, NULL, TRUE, traverse);
     }
   else
-    kount = query_exec (mrp, sortby, ls, 0, count,
-                        current_object, 0, FALSE, NULL, TRUE, traverse);
+    query_exec (mrp, sortby, ls, 0, count,
+                current_object, 0, FALSE, NULL, TRUE, traverse);
 
   ls = g_list_remove (ls, ls->data);
 
@@ -808,7 +830,7 @@ inorder (AtkObject * collection, MatchRulePrivate * mrp,
                                 NULL, TRUE, TRUE);
 
   /* Next, we look through the right subtree */
-  while ((max == 0 || kount < max) && obj != collection)
+  while ((max == 0 || kount < max) && obj && obj != collection)
     {
       AtkObject *parent = atk_object_get_parent (obj);
       i = atk_object_get_index_in_parent (obj);
@@ -840,14 +862,13 @@ GetMatchesInOrder (DBusMessage * message,
 {
   GList *ls = NULL;
   AtkObject *obj;
-  gint kount = 0;
 
   ls = g_list_append (ls, current_object);
 
   obj = ATK_OBJECT(spi_register_path_to_object (spi_global_register, dbus_message_get_path (message)));
 
-  kount = inorder (obj, mrp, ls, 0, count,
-                   current_object, TRUE, NULL, traverse);
+  inorder (obj, mrp, ls, 0, count,
+           current_object, TRUE, NULL, traverse);
 
   ls = g_list_remove (ls, ls->data);
 
@@ -872,14 +893,13 @@ GetMatchesInBackOrder (DBusMessage * message,
 {
   GList *ls = NULL;
   AtkObject *collection;
-  gint kount = 0;
 
   ls = g_list_append (ls, current_object);
 
   collection = ATK_OBJECT(spi_register_path_to_object (spi_global_register, dbus_message_get_path (message)));
 
-  kount = sort_order_rev_canonical (mrp, ls, 0, count, current_object,
-                                    FALSE, collection);
+  sort_order_rev_canonical (mrp, ls, 0, count, current_object,
+                            FALSE, collection);
 
   ls = g_list_remove (ls, ls->data);
 
@@ -901,20 +921,19 @@ GetMatchesTo (DBusMessage * message,
 {
   GList *ls = NULL;
   AtkObject *obj;
-  gint kount = 0;
   ls = g_list_append (ls, current_object);
 
   if (recurse)
     {
       obj = ATK_OBJECT (atk_object_get_parent (current_object));
-      kount = query_exec (mrp, sortby, ls, 0, count,
-                          obj, 0, TRUE, current_object, TRUE, traverse);
+      query_exec (mrp, sortby, ls, 0, count,
+                  obj, 0, TRUE, current_object, TRUE, traverse);
     }
   else
     {
       obj = ATK_OBJECT (spi_register_path_to_object (spi_global_register, dbus_message_get_path (message)));
-      kount = query_exec (mrp, sortby, ls, 0, count,
-                          obj, 0, TRUE, current_object, TRUE, traverse);
+      query_exec (mrp, sortby, ls, 0, count,
+                  obj, 0, TRUE, current_object, TRUE, traverse);
 
     }
 
@@ -939,7 +958,6 @@ impl_GetMatchesFrom (DBusConnection * bus, DBusMessage * message,
   dbus_uint32_t tree;
   dbus_int32_t count;
   dbus_bool_t traverse;
-  GList *ls = NULL;
   const char *signature;
 
   signature = dbus_message_get_signature (message);
@@ -1002,7 +1020,6 @@ impl_GetMatchesTo (DBusConnection * bus, DBusMessage * message,
   dbus_bool_t recurse;
   dbus_int32_t count;
   dbus_bool_t traverse;
-  GList *ls = NULL;
   const char *signature;
 
   signature = dbus_message_get_signature (message);
@@ -1054,6 +1071,224 @@ impl_GetMatchesTo (DBusConnection * bus, DBusMessage * message,
     }
 }
 
+static void
+append_accessible_properties (DBusMessageIter *iter, AtkObject *obj,
+                              GArray *properties)
+{
+  DBusMessageIter iter_struct, iter_dict, iter_dict_entry;
+  AtkStateSet *set;
+  gint i;
+  gint count;
+
+  dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, NULL, &iter_struct);
+  spi_object_append_reference (&iter_struct, obj);
+  dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "{sv}", &iter_dict);
+  if (properties && properties->len)
+  {
+    gint i;
+    for (i = 0; i < properties->len; i++)
+    {
+      gchar *prop = g_array_index (properties, char *, i);
+      DRoutePropertyFunction func;
+      GType type;
+      func = _atk_bridge_find_property_func (prop, &type);
+      if (func && G_TYPE_CHECK_INSTANCE_TYPE (obj, type))
+      {
+        dbus_message_iter_open_container (&iter_dict, DBUS_TYPE_DICT_ENTRY,
+                                          NULL, &iter_dict_entry);
+        dbus_message_iter_append_basic (&iter_dict_entry, DBUS_TYPE_STRING, &prop);
+        func (&iter_dict_entry, obj);
+        dbus_message_iter_close_container (&iter_dict, &iter_dict_entry);
+      }
+    }
+  }
+  else
+  {
+    GHashTableIter hi;
+    gpointer key, value;
+    g_hash_table_iter_init (&hi, spi_global_app_data->property_hash);
+    while (g_hash_table_iter_next (&hi, &key, &value))
+    {
+      const DRouteProperty *prop = value;
+      GType type = _atk_bridge_type_from_iface (key);
+      if (!G_TYPE_CHECK_INSTANCE_TYPE (obj, type))
+        continue;
+      for (;prop->name; prop++)
+      {
+        const char *p = key + strlen (key);
+        gchar *property_name;
+        while (p[-1] != '.')
+          p--;
+        if (!strcmp (p, "Accessible"))
+          property_name = g_strdup (prop->name);
+        else
+          property_name = g_strconcat (p, ".", prop->name, NULL);
+        dbus_message_iter_open_container (&iter_dict, DBUS_TYPE_DICT_ENTRY,
+                                          NULL, &iter_dict_entry);
+        dbus_message_iter_append_basic (&iter_dict_entry, DBUS_TYPE_STRING, &property_name);
+        g_free (property_name);
+        prop->get (&iter_dict_entry, obj);
+        dbus_message_iter_close_container (&iter_dict, &iter_dict_entry);
+      }
+    }
+  }
+  dbus_message_iter_close_container (&iter_struct, &iter_dict);
+  dbus_message_iter_close_container (iter, &iter_struct);
+
+  set = atk_object_ref_state_set (obj);
+  if (set)
+  {
+    gboolean md = atk_state_set_contains_state (set, ATK_STATE_MANAGES_DESCENDANTS);
+    g_object_unref (set);
+    if (md)
+      return;
+  }
+  count = atk_object_get_n_accessible_children (obj);
+  for (i = 0; i < count; i++)
+  {
+    AtkObject *child = atk_object_ref_accessible_child (obj, i);
+    if (child)
+    {
+      append_accessible_properties (iter, child, properties);
+      g_object_unref (child);
+    }
+  }
+}
+
+static void
+skip (const char **p)
+{
+  const char *sig = *p;
+  gint nest = (*sig != 'a');
+
+  sig++;
+  while (*sig)
+  {
+    if (*sig == '(' || *sig == '{')
+      nest++;
+    else if (*sig == ')' || *sig == '}')
+      nest--;
+    sig++;
+  }
+  *p = sig;
+}
+static gboolean
+types_match (DBusMessageIter *iter, char c)
+{
+  char t = dbus_message_iter_get_arg_type (iter);
+
+  if (t == 'r' && c == '(')
+    return TRUE;
+  else if (t != c)
+    return FALSE;
+}
+
+static void
+walk (DBusMessageIter *iter, const char *sig, gboolean array)
+{
+  while (*sig && *sig != ')' && *sig != '}')
+  {
+    if (array && dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_INVALID)
+    break;
+    if (!types_match (iter, *sig))
+    {
+      g_error ("Expected %s, got %c", sig, dbus_message_iter_get_arg_type (iter));
+    }
+    switch (*sig)
+    {
+    case 's':
+      {
+        const char *str;
+        DBusError error;
+        dbus_error_init (&error);
+        dbus_message_iter_get_basic (iter, &str);
+        g_print ("%s\n", str);
+        if (!dbus_validate_utf8 (str, &error))
+          g_error ("Bad UTF-8 string");
+      }
+      break;
+    case 'a':
+      {
+        DBusMessageIter iter_array;
+        dbus_message_iter_recurse (iter, &iter_array);
+        walk (&iter_array, sig + 1, TRUE);
+        skip (&sig);
+      }
+      break;
+    case DBUS_TYPE_STRUCT:
+    case DBUS_TYPE_DICT_ENTRY:
+      {
+        DBusMessageIter iter_struct;
+        dbus_message_iter_recurse (iter, &iter_struct);
+        walk (&iter_struct, sig + 1, FALSE);
+        skip (&sig);
+      }   
+    }
+    dbus_message_iter_next (iter);
+    if (!array)
+      sig++;
+  }
+  if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_INVALID)
+    g_error ("Unexpected data '%c'", dbus_message_iter_get_arg_type (iter));
+}
+
+static void
+walkm (DBusMessage *message)
+{
+  DBusMessageIter iter;
+  const char *sig = dbus_message_get_signature (message);
+
+  g_print ("sig: %s\n", sig);
+  dbus_message_iter_init (message, &iter);
+  walk (&iter, sig, FALSE);
+}
+
+static DBusMessage *
+impl_GetTree (DBusConnection * bus,
+              DBusMessage * message, void *user_data)
+{
+  AtkObject *object = (AtkObject *) user_data;
+  DBusMessage *reply;
+  DBusMessageIter iter, iter_array;
+  MatchRulePrivate rule;
+  GArray *properties;
+
+  g_return_val_if_fail (ATK_IS_OBJECT (user_data),
+                        droute_not_yet_handled_error (message));
+
+  if (strcmp (dbus_message_get_signature (message), "(aiia{ss}iaiiasib)as") != 0)
+    return droute_invalid_arguments_error (message);
+
+  properties = g_array_new (TRUE, TRUE, sizeof (char *));
+  dbus_message_iter_init (message, &iter);
+  if (!read_mr (&iter, &rule))
+    {
+      return spi_dbus_general_error (message);
+    }
+
+  dbus_message_iter_recurse (&iter, &iter_array);
+  while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID)
+  {
+    const char *prop;
+    dbus_message_iter_get_basic (&iter_array, &prop);
+    g_array_append_val (properties, prop);
+    dbus_message_iter_next (&iter_array);
+  }
+
+  reply = dbus_message_new_method_return (message);
+  if (reply)
+    {
+      dbus_message_iter_init_append (reply, &iter);
+      dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "((so)a{sv})",
+                                        &iter_array);
+      append_accessible_properties (&iter_array, object, properties);
+      dbus_message_iter_close_container (&iter, &iter_array);
+    }
+//walkm (reply);
+  return reply;
+}
+
 static DBusMessage *
 impl_GetMatches (DBusConnection * bus, DBusMessage * message, void *user_data)
 {
@@ -1097,6 +1332,7 @@ impl_GetMatches (DBusConnection * bus, DBusMessage * message, void *user_data)
 static DRouteMethod methods[] = {
   {impl_GetMatchesFrom, "GetMatchesFrom"},
   {impl_GetMatchesTo, "GetMatchesTo"},
+  {impl_GetTree, "GetTree"},
   {impl_GetMatches, "GetMatches"},
   {NULL, NULL}
 };
@@ -1104,6 +1340,6 @@ static DRouteMethod methods[] = {
 void
 spi_initialize_collection (DRoutePath * path)
 {
-  droute_path_add_interface (path,
-                             ATSPI_DBUS_INTERFACE_COLLECTION, spi_org_a11y_atspi_Collection, methods, NULL);
+  spi_atk_add_interface (path,
+                         ATSPI_DBUS_INTERFACE_COLLECTION, spi_org_a11y_atspi_Collection, methods, NULL);
 };