Fix accessibility of root apps on Linux
[platform/core/uifw/at-spi2-atk.git] / atk-adaptor / adaptors / accessible-adaptor.c
index 434223e..d0d77e7 100644 (file)
@@ -27,8 +27,8 @@
 
 #include "common/spi-dbus.h"
 #include "common/spi-stateset.h"
-#include "accessible-marshaller.h"
-#include "accessible-register.h"
+#include "object.h"
+#include "introspection.h"
 
 static dbus_bool_t
 impl_get_Name (DBusMessageIter * iter, void *user_data)
@@ -77,24 +77,78 @@ impl_set_Description (DBusMessageIter * iter, void *user_data)
 static dbus_bool_t
 impl_get_Parent (DBusMessageIter * iter, void *user_data)
 {
-  AtkObject *object = (AtkObject *) user_data;
+  AtkObject *obj = (AtkObject *) user_data;
+  AtkObject *parent;
+  DBusMessageIter iter_variant;
+  dbus_uint32_t role;
 
   g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
 
-  return spi_dbus_return_v_object (iter,
-                                   atk_object_get_parent (object), FALSE);
+  role = spi_accessible_role_from_atk_role (atk_object_get_role (obj));
+
+  dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, "(so)",
+                                    &iter_variant);
+
+  parent = atk_object_get_parent (obj);
+  if (parent == NULL)
+    {
+      /* TODO, move in to a 'Plug' wrapper. */
+      if (ATK_IS_PLUG (obj))
+        {
+          char *id = g_object_get_data (G_OBJECT (obj), "dbus-plug-parent");
+          char *bus_parent;
+          char *path_parent;
+
+          if (id)
+            {
+              bus_parent = g_strdup (id);
+              if (bus_parent && (path_parent = g_utf8_strchr (bus_parent + 1, -1, ':')))
+                {
+                  DBusMessageIter iter_parent;
+                  *(path_parent++) = '\0';
+                  dbus_message_iter_open_container (&iter_variant, DBUS_TYPE_STRUCT, NULL,
+                                                    &iter_parent);
+                  dbus_message_iter_append_basic (&iter_parent, DBUS_TYPE_STRING, &bus_parent);
+                  dbus_message_iter_append_basic (&iter_parent, DBUS_TYPE_OBJECT_PATH, &path_parent);
+                  dbus_message_iter_close_container (&iter_variant, &iter_parent);
+                }
+              else
+                {
+                  spi_object_append_null_reference (&iter_variant);
+                }
+            }
+          else
+            {
+              spi_object_append_null_reference (&iter_variant);
+            }
+        }
+      else if (role != Accessibility_ROLE_APPLICATION)
+         spi_object_append_null_reference (&iter_variant);
+      else
+         spi_object_append_desktop_reference (&iter_variant);
+      }
+  else
+    {
+      spi_object_append_reference (&iter_variant, parent);
+    }
+
+
+  dbus_message_iter_close_container (iter, &iter_variant);
+  return TRUE;
 }
 
 static dbus_bool_t
 impl_get_ChildCount (DBusMessageIter * iter, void *user_data)
 {
   AtkObject *object = (AtkObject *) user_data;
+  int childCount;
 
   g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
 
-  return droute_return_v_int32 (iter,
-                                atk_object_get_n_accessible_children
-                                (object));
+  childCount = (ATK_IS_SOCKET (object) && atk_socket_is_occupied (ATK_SOCKET (object)))
+               ? 1
+               : atk_object_get_n_accessible_children (object);
+  return droute_return_v_int32 (iter, childCount);
 }
 
 static DBusMessage *
@@ -102,6 +156,7 @@ impl_GetChildAtIndex (DBusConnection * bus,
                       DBusMessage * message, void *user_data)
 {
   AtkObject *object = (AtkObject *) user_data;
+  DBusMessage *reply;
   DBusError error;
   dbus_int32_t i;
   AtkObject *child;
@@ -114,8 +169,35 @@ impl_GetChildAtIndex (DBusConnection * bus,
     {
       return droute_invalid_arguments_error (message);
     }
+
+  if (ATK_IS_SOCKET (object) && atk_socket_is_occupied (ATK_SOCKET (object)) && i == 0)
+    {
+      AtkSocket *socket = ATK_SOCKET (object);
+      gchar *child_name, *child_path;
+      child_name = g_strdup (socket->embedded_plug_id);
+      child_path = g_utf8_strchr (child_name + 1, -1, ':');
+      if (child_path)
+        {
+          DBusMessageIter iter, iter_socket;
+          *(child_path++) = '\0';
+          reply = dbus_message_new_method_return (message);
+          if (!reply)
+            return NULL;
+          dbus_message_iter_init_append (reply, &iter);
+          dbus_message_iter_open_container (&iter, DBUS_TYPE_STRUCT, NULL,
+                                            &iter_socket);
+          dbus_message_iter_append_basic (&iter_socket, DBUS_TYPE_STRING, &child_name);
+          dbus_message_iter_append_basic (&iter_socket, DBUS_TYPE_OBJECT_PATH, &child_path);
+          dbus_message_iter_close_container (&iter, &iter_socket);
+          return reply;
+        }
+      g_free (child_name);
+    }
   child = atk_object_ref_accessible_child (object, i);
-  return spi_dbus_return_object (message, child, TRUE, TRUE);
+  reply = spi_object_return_reference (message, child);
+  g_object_unref (child);
+
+  return reply;
 }
 
 static DBusMessage *
@@ -136,18 +218,12 @@ impl_GetChildren (DBusConnection * bus,
     goto oom;
   dbus_message_iter_init_append (reply, &iter);
   if (!dbus_message_iter_open_container
-      (&iter, DBUS_TYPE_ARRAY, "o", &iter_array))
+      (&iter, DBUS_TYPE_ARRAY, "(so)", &iter_array))
     goto oom;
   for (i = 0; i < count; i++)
     {
       AtkObject *child = atk_object_ref_accessible_child (object, i);
-      char *path = atk_dbus_object_to_path (child, FALSE);
-      if (path)
-        {
-          dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_OBJECT_PATH,
-                                          &path);
-          g_free (path);
-        }
+      spi_object_append_reference (&iter_array, child); 
       if (child)
         g_object_unref (child);
     }
@@ -169,13 +245,10 @@ impl_GetIndexInParent (DBusConnection * bus,
 
   g_return_val_if_fail (ATK_IS_OBJECT (user_data),
                         droute_not_yet_handled_error (message));
+
   rv = atk_object_get_index_in_parent (object);
   reply = dbus_message_new_method_return (message);
-  if (reply)
-    {
-      dbus_message_append_args (reply, DBUS_TYPE_UINT32, &rv,
-                                DBUS_TYPE_INVALID);
-    }
+  dbus_message_append_args (reply, DBUS_TYPE_UINT32, &rv, DBUS_TYPE_INVALID);
   return reply;
 }
 
@@ -249,7 +322,9 @@ impl_GetRelationSet (DBusConnection * bus,
     {
       goto oom;
     }
-  count = atk_relation_set_get_n_relations (set);
+  count = 0;
+  if (set)
+    count = atk_relation_set_get_n_relations (set);
   for (i = 0; i < count; i++)
     {
       AtkRelation *r = atk_relation_set_get_relation (set, i);
@@ -278,13 +353,7 @@ impl_GetRelationSet (DBusConnection * bus,
           char *path;
           if (!obj)
             continue;
-          path = atk_dbus_object_to_path (obj, FALSE);
-          if (!path)
-            {
-              g_warning ("Unknown object in relation type %d\n", type);
-              continue;
-            }
-          spi_dbus_append_name_and_path_inner (&iter_targets, NULL, path);
+          spi_object_append_reference (&iter_targets, obj);
         }
       dbus_message_iter_close_container (&iter_struct, &iter_targets);
       dbus_message_iter_close_container (&iter_array, &iter_struct);
@@ -295,133 +364,6 @@ oom:
   return reply;
 }
 
-static gboolean
-spi_init_role_lookup_table (Accessibility_Role * role_table)
-{
-  int i;
-  /* if it's not in the list below, dunno what it is */
-  for (i = 0; i < ATK_ROLE_LAST_DEFINED; ++i)
-    {
-      role_table[i] = Accessibility_ROLE_UNKNOWN;
-    }
-
-  role_table[ATK_ROLE_INVALID] = Accessibility_ROLE_INVALID;
-  role_table[ATK_ROLE_ACCEL_LABEL] = Accessibility_ROLE_ACCELERATOR_LABEL;
-  role_table[ATK_ROLE_ALERT] = Accessibility_ROLE_ALERT;
-  role_table[ATK_ROLE_ANIMATION] = Accessibility_ROLE_ANIMATION;
-  role_table[ATK_ROLE_ARROW] = Accessibility_ROLE_ARROW;
-  role_table[ATK_ROLE_CALENDAR] = Accessibility_ROLE_CALENDAR;
-  role_table[ATK_ROLE_CANVAS] = Accessibility_ROLE_CANVAS;
-  role_table[ATK_ROLE_CHECK_BOX] = Accessibility_ROLE_CHECK_BOX;
-  role_table[ATK_ROLE_CHECK_MENU_ITEM] = Accessibility_ROLE_CHECK_MENU_ITEM;
-  role_table[ATK_ROLE_COLOR_CHOOSER] = Accessibility_ROLE_COLOR_CHOOSER;
-  role_table[ATK_ROLE_COLUMN_HEADER] = Accessibility_ROLE_COLUMN_HEADER;
-  role_table[ATK_ROLE_COMBO_BOX] = Accessibility_ROLE_COMBO_BOX;
-  role_table[ATK_ROLE_DATE_EDITOR] = Accessibility_ROLE_DATE_EDITOR;
-  role_table[ATK_ROLE_DESKTOP_ICON] = Accessibility_ROLE_DESKTOP_ICON;
-  role_table[ATK_ROLE_DESKTOP_FRAME] = Accessibility_ROLE_DESKTOP_FRAME;
-  role_table[ATK_ROLE_DIAL] = Accessibility_ROLE_DIAL;
-  role_table[ATK_ROLE_DIALOG] = Accessibility_ROLE_DIALOG;
-  role_table[ATK_ROLE_DIRECTORY_PANE] = Accessibility_ROLE_DIRECTORY_PANE;
-  role_table[ATK_ROLE_DRAWING_AREA] = Accessibility_ROLE_DRAWING_AREA;
-  role_table[ATK_ROLE_FILE_CHOOSER] = Accessibility_ROLE_FILE_CHOOSER;
-  role_table[ATK_ROLE_FILLER] = Accessibility_ROLE_FILLER;
-  role_table[ATK_ROLE_FONT_CHOOSER] = Accessibility_ROLE_FONT_CHOOSER;
-  role_table[ATK_ROLE_FRAME] = Accessibility_ROLE_FRAME;
-  role_table[ATK_ROLE_GLASS_PANE] = Accessibility_ROLE_GLASS_PANE;
-  role_table[ATK_ROLE_HTML_CONTAINER] = Accessibility_ROLE_HTML_CONTAINER;
-  role_table[ATK_ROLE_ICON] = Accessibility_ROLE_ICON;
-  role_table[ATK_ROLE_IMAGE] = Accessibility_ROLE_IMAGE;
-  role_table[ATK_ROLE_INTERNAL_FRAME] = Accessibility_ROLE_INTERNAL_FRAME;
-  role_table[ATK_ROLE_LABEL] = Accessibility_ROLE_LABEL;
-  role_table[ATK_ROLE_LAYERED_PANE] = Accessibility_ROLE_LAYERED_PANE;
-  role_table[ATK_ROLE_LIST] = Accessibility_ROLE_LIST;
-  role_table[ATK_ROLE_LIST_ITEM] = Accessibility_ROLE_LIST_ITEM;
-  role_table[ATK_ROLE_MENU] = Accessibility_ROLE_MENU;
-  role_table[ATK_ROLE_MENU_BAR] = Accessibility_ROLE_MENU_BAR;
-  role_table[ATK_ROLE_MENU_ITEM] = Accessibility_ROLE_MENU_ITEM;
-  role_table[ATK_ROLE_OPTION_PANE] = Accessibility_ROLE_OPTION_PANE;
-  role_table[ATK_ROLE_PAGE_TAB] = Accessibility_ROLE_PAGE_TAB;
-  role_table[ATK_ROLE_PAGE_TAB_LIST] = Accessibility_ROLE_PAGE_TAB_LIST;
-  role_table[ATK_ROLE_PANEL] = Accessibility_ROLE_PANEL;
-  role_table[ATK_ROLE_PASSWORD_TEXT] = Accessibility_ROLE_PASSWORD_TEXT;
-  role_table[ATK_ROLE_POPUP_MENU] = Accessibility_ROLE_POPUP_MENU;
-  role_table[ATK_ROLE_PROGRESS_BAR] = Accessibility_ROLE_PROGRESS_BAR;
-  role_table[ATK_ROLE_PUSH_BUTTON] = Accessibility_ROLE_PUSH_BUTTON;
-  role_table[ATK_ROLE_RADIO_BUTTON] = Accessibility_ROLE_RADIO_BUTTON;
-  role_table[ATK_ROLE_RADIO_MENU_ITEM] = Accessibility_ROLE_RADIO_MENU_ITEM;
-  role_table[ATK_ROLE_ROOT_PANE] = Accessibility_ROLE_ROOT_PANE;
-  role_table[ATK_ROLE_ROW_HEADER] = Accessibility_ROLE_ROW_HEADER;
-  role_table[ATK_ROLE_SCROLL_BAR] = Accessibility_ROLE_SCROLL_BAR;
-  role_table[ATK_ROLE_SCROLL_PANE] = Accessibility_ROLE_SCROLL_PANE;
-  role_table[ATK_ROLE_SEPARATOR] = Accessibility_ROLE_SEPARATOR;
-  role_table[ATK_ROLE_SLIDER] = Accessibility_ROLE_SLIDER;
-  role_table[ATK_ROLE_SPIN_BUTTON] = Accessibility_ROLE_SPIN_BUTTON;
-  role_table[ATK_ROLE_SPLIT_PANE] = Accessibility_ROLE_SPLIT_PANE;
-  role_table[ATK_ROLE_STATUSBAR] = Accessibility_ROLE_STATUS_BAR;
-  role_table[ATK_ROLE_TABLE] = Accessibility_ROLE_TABLE;
-  role_table[ATK_ROLE_TABLE_CELL] = Accessibility_ROLE_TABLE_CELL;
-  role_table[ATK_ROLE_TABLE_COLUMN_HEADER] =
-    Accessibility_ROLE_TABLE_COLUMN_HEADER;
-  role_table[ATK_ROLE_TABLE_ROW_HEADER] = Accessibility_ROLE_TABLE_ROW_HEADER;
-  role_table[ATK_ROLE_TEAR_OFF_MENU_ITEM] =
-    Accessibility_ROLE_TEAROFF_MENU_ITEM;
-  role_table[ATK_ROLE_TERMINAL] = Accessibility_ROLE_TERMINAL;
-  role_table[ATK_ROLE_TEXT] = Accessibility_ROLE_TEXT;
-  role_table[ATK_ROLE_TOGGLE_BUTTON] = Accessibility_ROLE_TOGGLE_BUTTON;
-  role_table[ATK_ROLE_TOOL_BAR] = Accessibility_ROLE_TOOL_BAR;
-  role_table[ATK_ROLE_TOOL_TIP] = Accessibility_ROLE_TOOL_TIP;
-  role_table[ATK_ROLE_TREE] = Accessibility_ROLE_TREE;
-  role_table[ATK_ROLE_TREE_TABLE] = Accessibility_ROLE_TREE_TABLE;
-  role_table[ATK_ROLE_UNKNOWN] = Accessibility_ROLE_UNKNOWN;
-  role_table[ATK_ROLE_VIEWPORT] = Accessibility_ROLE_VIEWPORT;
-  role_table[ATK_ROLE_WINDOW] = Accessibility_ROLE_WINDOW;
-  role_table[ATK_ROLE_HEADER] = Accessibility_ROLE_HEADER;
-  role_table[ATK_ROLE_FOOTER] = Accessibility_ROLE_FOOTER;
-  role_table[ATK_ROLE_PARAGRAPH] = Accessibility_ROLE_PARAGRAPH;
-  role_table[ATK_ROLE_RULER] = Accessibility_ROLE_RULER;
-  role_table[ATK_ROLE_APPLICATION] = Accessibility_ROLE_APPLICATION;
-  role_table[ATK_ROLE_AUTOCOMPLETE] = Accessibility_ROLE_AUTOCOMPLETE;
-  role_table[ATK_ROLE_EDITBAR] = Accessibility_ROLE_EDITBAR;
-  role_table[ATK_ROLE_EMBEDDED] = Accessibility_ROLE_EMBEDDED;
-  role_table[ATK_ROLE_ENTRY] = Accessibility_ROLE_ENTRY;
-  role_table[ATK_ROLE_CHART] = Accessibility_ROLE_CHART;
-  role_table[ATK_ROLE_CAPTION] = Accessibility_ROLE_CAPTION;
-  role_table[ATK_ROLE_DOCUMENT_FRAME] = Accessibility_ROLE_DOCUMENT_FRAME;
-  role_table[ATK_ROLE_HEADING] = Accessibility_ROLE_HEADING;
-  role_table[ATK_ROLE_PAGE] = Accessibility_ROLE_PAGE;
-  role_table[ATK_ROLE_SECTION] = Accessibility_ROLE_SECTION;
-  role_table[ATK_ROLE_FORM] = Accessibility_ROLE_FORM;
-  role_table[ATK_ROLE_REDUNDANT_OBJECT] = Accessibility_ROLE_REDUNDANT_OBJECT;
-  role_table[ATK_ROLE_LINK] = Accessibility_ROLE_LINK;
-  role_table[ATK_ROLE_INPUT_METHOD_WINDOW] =
-    Accessibility_ROLE_INPUT_METHOD_WINDOW;
-  return TRUE;
-}
-
-Accessibility_Role
-spi_accessible_role_from_atk_role (AtkRole role)
-{
-  static gboolean is_initialized = FALSE;
-  static Accessibility_Role spi_role_table[ATK_ROLE_LAST_DEFINED];
-  Accessibility_Role spi_role;
-
-  if (!is_initialized)
-    {
-      is_initialized = spi_init_role_lookup_table (spi_role_table);
-    }
-
-  if (role >= 0 && role < ATK_ROLE_LAST_DEFINED)
-    {
-      spi_role = spi_role_table[role];
-    }
-  else
-    {
-      spi_role = Accessibility_ROLE_EXTENDED;
-    }
-  return spi_role;
-}
-
 static DBusMessage *
 impl_GetRole (DBusConnection * bus, DBusMessage * message, void *user_data)
 {
@@ -534,9 +476,8 @@ impl_GetAttributes (DBusConnection * bus,
                     DBusMessage * message, void *user_data)
 {
   AtkObject *object = (AtkObject *) user_data;
-  DBusMessage *reply = NULL;
-
   AtkAttributeSet *attributes;
+  DBusMessage *reply = NULL;
   DBusMessageIter iter;
 
   g_return_val_if_fail (ATK_IS_OBJECT (user_data),
@@ -546,10 +487,9 @@ impl_GetAttributes (DBusConnection * bus,
 
   reply = dbus_message_new_method_return (message);
   dbus_message_iter_init_append (reply, &iter);
-  spi_atk_append_attribute_set (&iter, attributes);
+  spi_object_append_attribute_set (&iter, attributes);
 
-  if (attributes)
-    atk_attribute_set_free (attributes);
+  atk_attribute_set_free (attributes);
 
   return reply;
 }
@@ -558,8 +498,7 @@ static DBusMessage *
 impl_GetApplication (DBusConnection * bus,
                      DBusMessage * message, void *user_data)
 {
-  AtkObject *root = atk_get_root ();
-  return spi_dbus_return_object (message, root, FALSE, FALSE);
+  return spi_object_return_reference (message, atk_get_root ());
 }
 
 static DBusMessage *
@@ -567,8 +506,6 @@ impl_GetInterfaces (DBusConnection * bus,
                     DBusMessage * message, void *user_data)
 {
   AtkObject *object = (AtkObject *) user_data;
-  gint role;
-  const char *role_name;
   DBusMessage *reply;
   DBusMessageIter iter, iter_array;
 
@@ -580,33 +517,12 @@ impl_GetInterfaces (DBusConnection * bus,
       dbus_message_iter_init_append (reply, &iter);
       dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "s",
                                         &iter_array);
-      append_atk_object_interfaces (object, &iter_array);
+      spi_object_append_interfaces (&iter_array, object);
       dbus_message_iter_close_container (&iter, &iter_array);
     }
   return reply;
 }
 
-static DBusMessage *
-impl_Embedded (DBusConnection *bus,
-                    DBusMessage *message,
-                    void *user_data)
-{
-  AtkObject *object = (AtkObject *) user_data;
-  char *path;
-  gchar *id;
-
-  if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &path, DBUS_TYPE_INVALID))
-    {
-      return droute_invalid_arguments_error (message);
-    }
-  id = g_object_get_data (G_OBJECT (object), "dbus-plug-parent");
-  if (id)
-    g_free (id);
-  id = g_strconcat (dbus_message_get_sender (message), ":", path, NULL);
-  g_object_set_data (G_OBJECT (object), "dbus-plug-parent", id);
-  return dbus_message_new_method_return (message);
-}
-
 static DRouteMethod methods[] = {
   {impl_GetChildAtIndex, "GetChildAtIndex"},
   {impl_GetChildren, "GetChildren"},
@@ -619,7 +535,6 @@ static DRouteMethod methods[] = {
   {impl_GetAttributes, "GetAttributes"},
   {impl_GetApplication, "GetApplication"},
   {impl_GetInterfaces, "GetInterfaces"},
-  {impl_Embedded, "Embedded"},
   {NULL, NULL}
 };
 
@@ -636,5 +551,6 @@ spi_initialize_accessible (DRoutePath * path)
 {
   droute_path_add_interface (path,
                              SPI_DBUS_INTERFACE_ACCESSIBLE,
+                             spi_org_a11y_atspi_Accessible,    
                              methods, properties);
 };