2009-08-28 Mike Gorse <mgorse@novell.com>
authorMike Gorse <mgorse@novell.com>
Fri, 28 Aug 2009 18:47:28 +0000 (13:47 -0500)
committerMike Gorse <mgorse@novell.com>
Fri, 30 Oct 2009 19:10:58 +0000 (15:10 -0400)
Allow objects to record transient sub-objects which will be dereferenced
when the containing object is removed.
Initial pass at supporting hyperlinks and visible Transient objects.
Transient objects should be removed from memory if they lose visibility.

12 files changed:
atk-adaptor/accessible-adaptor.c
atk-adaptor/accessible-marshaller.c
atk-adaptor/accessible-marshaller.h
atk-adaptor/accessible-register.c
atk-adaptor/accessible-register.h
atk-adaptor/component-adaptor.c
atk-adaptor/event.c
atk-adaptor/hyperlink-adaptor.c
atk-adaptor/hypertext-adaptor.c
atk-adaptor/selection-adaptor.c
atk-adaptor/table-adaptor.c
atk-adaptor/tree-adaptor.c

index c59f39e9c859fbecdeee74681128cc852d16536d..61240806c7da50dafeb1a5c4e4e38bf8150e6ae7 100644 (file)
@@ -114,7 +114,7 @@ impl_getChildAtIndex (DBusConnection *bus,
   if (!dbus_message_get_args (message, &error, DBUS_TYPE_INT32, &i, DBUS_TYPE_INVALID))
       return spi_dbus_general_error (message);
   child = atk_object_ref_accessible_child (object, i);
-  return spi_dbus_return_object (message, child, FALSE);
+  return spi_dbus_return_object (message, child, FALSE, FALSE);
 }
 
 static DBusMessage *
@@ -140,7 +140,7 @@ impl_getChildren (DBusConnection *bus,
   for (i = 0; i < count; i++)
     {
       AtkObject *child = atk_object_ref_accessible_child (object, i);
-      char *path = atk_dbus_object_to_path (child);
+      char *path = atk_dbus_object_to_path (child, FALSE);
       if (path)
        {
          dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_OBJECT_PATH,
@@ -270,7 +270,12 @@ impl_getRelationSet (DBusConnection *bus,
       AtkObject *obj = target->pdata[j];
       char *path;
       if (!obj) continue;
-      path = atk_dbus_object_to_path (obj);
+      path = atk_dbus_object_to_path (obj, FALSE);
+      if (!path)
+      {
+       g_warning ("Unknown object in relation type %d\n", type);
+       continue;
+      }
       dbus_message_iter_append_basic (&iter_targets, DBUS_TYPE_OBJECT_PATH, &path);
     }
     dbus_message_iter_close_container (&iter_struct, &iter_targets);
@@ -543,7 +548,7 @@ impl_getApplication (DBusConnection *bus,
                      void *user_data)
 {
   AtkObject *root = atk_get_root ();
-  return spi_dbus_return_object (message, root, FALSE);
+  return spi_dbus_return_object (message, root, FALSE, FALSE);
 }
 
 static DBusMessage *
index b6b052b27e7281585edd6b3fe55470c5f8ca57e3..4bfb362309876bec6d7c9b66c13b2e172df21113 100644 (file)
  * Unrefs the AtkObject if unref is true.
  */
 DBusMessage *
-spi_dbus_return_object (DBusMessage *message, AtkObject *obj, gboolean unref)
+spi_dbus_return_object (DBusMessage *message, AtkObject *obj, gboolean do_register, gboolean unref)
 {
   DBusMessage *reply;
   gchar *path;
 
-  path = atk_dbus_object_to_path (obj);
+  path = atk_dbus_object_to_path (obj, do_register);
 
   if (obj && unref)
     g_object_unref (obj);
@@ -63,6 +63,38 @@ spi_dbus_return_object (DBusMessage *message, AtkObject *obj, gboolean unref)
   return reply;
 }
 
+DBusMessage *
+spi_dbus_return_hyperlink (DBusMessage *message, AtkHyperlink *link, AtkObject *container, gboolean unref)
+{
+  return spi_dbus_return_sub_object (message, G_OBJECT (link), G_OBJECT (container), unref);
+}
+
+DBusMessage *
+spi_dbus_return_sub_object (DBusMessage *message, GObject *sub, GObject *container, gboolean unref)
+{
+  DBusMessage *reply;
+  gchar *path;
+
+  path = atk_dbus_sub_object_to_path (sub, container);
+
+  if (sub && unref)
+    g_object_unref (sub);
+
+  if (!path)
+    path = g_strdup (SPI_DBUS_PATH_NULL);
+
+  reply = dbus_message_new_method_return (message);
+  if (reply)
+    {
+      dbus_message_append_args (reply, DBUS_TYPE_OBJECT_PATH, &path,
+                                DBUS_TYPE_INVALID);
+    }
+
+  g_free (path);
+
+  return reply;
+}
+
 /*---------------------------------------------------------------------------*/
 
 /*
@@ -76,7 +108,10 @@ spi_dbus_return_v_object (DBusMessageIter *iter, AtkObject *obj, int unref)
 {
   char *path;
 
-  path = atk_dbus_object_to_path (obj);
+  path = atk_dbus_object_to_path (obj, FALSE);
+
+  if (!path)
+    path = g_strdup (SPI_DBUS_PATH_NULL);
 
   if (unref)
     g_object_unref (obj);
@@ -201,7 +236,7 @@ spi_atk_append_accessible(AtkObject *obj, gpointer iter)
       gchar *path, *path_parent;
 
       /* Marshall object path */
-      path = atk_dbus_object_to_path (obj);
+      path = atk_dbus_object_to_path (obj, FALSE);
       dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, &path);
 
       /* Marshall parent */
@@ -212,7 +247,7 @@ spi_atk_append_accessible(AtkObject *obj, gpointer iter)
         }
       else
         {
-          path_parent = atk_dbus_object_to_path (parent);
+          path_parent = atk_dbus_object_to_path (parent, FALSE);
           if (!path_parent)
             {
               /* This should only happen if a widget is re-parented to
@@ -243,7 +278,7 @@ spi_atk_append_accessible(AtkObject *obj, gpointer iter)
               gchar *child_path;
 
               child = atk_object_ref_accessible_child (obj, i);
-              child_path = atk_dbus_object_to_path (child);
+              child_path = atk_dbus_object_to_path (child, FALSE);
               if (child_path)
                 {
                   dbus_message_iter_append_basic (&iter_sub_array, DBUS_TYPE_OBJECT_PATH, &child_path);
index d372537331e14105c8dc2cd6772c61228954e4e7..ed72967e7e1e01af7a4d46eee7a87f420b75e0bc 100644 (file)
 #include <atk/atk.h>
 
 DBusMessage *
-spi_dbus_return_object (DBusMessage *message, AtkObject *obj, gboolean unref);
+spi_dbus_return_object (DBusMessage *message, AtkObject *obj, gboolean do_register, gboolean unref);
+
+DBusMessage *
+spi_dbus_return_hyperlink (DBusMessage *message, AtkHyperlink *link, AtkObject *container, gboolean unref);
+
+DBusMessage *
+spi_dbus_return_sub_object (DBusMessage *message, GObject *sub, GObject *container, gboolean unref);
 
 dbus_bool_t
 spi_dbus_return_v_object (DBusMessageIter *iter, AtkObject *obj, int unref);
index 793e0eaf69e25309130ca04a533f34be7846f041..883a9d9bc193d7e7e8db7459212ceb3f620d45d0 100644 (file)
@@ -127,8 +127,20 @@ assign_reference(void)
 /*
  * Returns the reference of the object, or 0 if it is not registered.
  */
+static guint
+gobject_to_ref (GObject *gobj)
+{
+  return GPOINTER_TO_INT(g_object_get_data (gobj, "dbus-id"));
+}
+
 static guint
 object_to_ref (AtkObject *accessible)
+{
+  return gobject_to_ref (G_OBJECT (accessible));
+}
+
+static guint
+hyperlink_to_ref (AtkHyperlink *accessible)
 {
   return GPOINTER_TO_INT(g_object_get_data (G_OBJECT (accessible), "dbus-id"));
 }
@@ -144,6 +156,12 @@ atk_dbus_ref_to_path (guint ref)
 
 /*---------------------------------------------------------------------------*/
 
+static void
+deregister_sub_accessible (gpointer key, gpointer obj_data, gpointer iter);
+
+static void
+deregister_sub_hyperlink (gpointer key, gpointer obj_data, gpointer iter);
+
 /*
  * Callback for when a registered AtkObject is destroyed.
  *
@@ -151,33 +169,125 @@ atk_dbus_ref_to_path (guint ref)
  * it is no longer exposed over D-Bus.
  */
 static void
-deregister_accessible (gpointer data, GObject *accessible)
+deregister_object (gpointer data, GObject *gobj)
 {
   guint ref;
-  g_return_if_fail (ATK_IS_OBJECT (accessible));
+  GHashTable *subrefs_atk;
+  GHashTable *subrefs_hyperlink;
+  g_return_if_fail (ATK_IS_OBJECT (gobj) || ATK_IS_HYPERLINK (gobj));
+
+  subrefs_atk = (GHashTable *) g_object_get_data (gobj, "dbus-subrefs-atk");
+  if (subrefs_atk)
+    g_hash_table_foreach (subrefs_atk, deregister_sub_accessible, data);
+  
+  subrefs_hyperlink = (GHashTable *) g_object_get_data (gobj, "dbus-subrefs-hyperlink");
+  if (subrefs_hyperlink)
+    g_hash_table_foreach (subrefs_hyperlink, deregister_sub_hyperlink, data);
+  
+  if (ATK_IS_OBJECT (gobj))
+  {
+    ref = object_to_ref (ATK_OBJECT (gobj));
+    if (ref != 0)
+      {
+        spi_emit_cache_removal (ref, atk_adaptor_app_data->bus);
+        g_hash_table_remove(ref2ptr, GINT_TO_POINTER(ref));
+      }
+    }
+  }
+
+static void
+deregister_sub_accessible (gpointer key, gpointer obj_data, gpointer iter)
+{
+  GObject *obj = G_OBJECT (obj_data);
+  deregister_object (NULL, obj);
+  g_object_unref (obj);
+}
 
-  ref = object_to_ref (ATK_OBJECT(accessible));
+static void
+deregister_sub_hyperlink (gpointer key, gpointer obj_data, gpointer iter)
+{
+  guint ref;
+  GObject *ghyperlink = G_OBJECT (obj_data);
+
+  g_return_if_fail (ATK_IS_HYPERLINK (ghyperlink));
+
+  ref = gobject_to_ref (ghyperlink);
   if (ref != 0)
     {
-      spi_emit_cache_removal (ref, atk_adaptor_app_data->bus);
       g_hash_table_remove(ref2ptr, GINT_TO_POINTER(ref));
     }
+  g_object_unref (ghyperlink);
+}
+
+static void
+register_gobject (GObject *gobj, GObject *container)
+{
+  guint ref;
+  g_return_if_fail (G_IS_OBJECT(gobj));
+
+  ref = assign_reference();
+
+  g_hash_table_insert (ref2ptr, GINT_TO_POINTER(ref), gobj);
+  g_object_set_data (G_OBJECT(gobj), "dbus-id", GINT_TO_POINTER(ref));
+  g_object_weak_ref(G_OBJECT(gobj), deregister_object, NULL);
+
+  if (container)
+  {
+    GHashTable *subrefs = (GHashTable *) g_object_get_data (G_OBJECT (container), "dbus-subrefs-atk");
+    if (!subrefs)
+    {
+      subrefs = g_hash_table_new(g_direct_hash, g_direct_equal);
+      g_object_set_data (G_OBJECT (container), "dbus-subrefs-atk", subrefs);
+    }
+    g_hash_table_insert (subrefs, GINT_TO_POINTER(ref), gobj);
+  }
+
+  if (ATK_IS_HYPERLINK (gobj))
+    g_object_ref (gobj);
+  else if (ATK_IS_OBJECT (gobj))
+  {
+    AtkObject *accessible = ATK_OBJECT (gobj);
+    AtkStateSet *state = atk_object_ref_state_set (accessible);
+    if (atk_state_set_contains_state (state, ATK_STATE_TRANSIENT) &&
+        atk_state_set_contains_state (state, ATK_STATE_SHOWING))
+    {
+      g_object_ref (gobj);
+    }
+    g_object_unref (state);
+  }
 }
 
 /*
  * Called to register an AtkObject with AT-SPI and expose it over D-Bus.
  */
 static void
-register_accessible (AtkObject *accessible)
+register_accessible (AtkObject *accessible, AtkObject *container)
 {
-  guint ref;
   g_return_if_fail (ATK_IS_OBJECT(accessible));
 
+  register_gobject (G_OBJECT (accessible), G_OBJECT (container));
+}
+
+static void
+register_hyperlink (AtkHyperlink *hyperlink, AtkObject *container)
+{
+  guint ref;
+  g_return_if_fail (ATK_IS_HYPERLINK (hyperlink));
+  g_return_if_fail (container);
+
   ref = assign_reference();
 
-  g_hash_table_insert (ref2ptr, GINT_TO_POINTER(ref), accessible);
-  g_object_set_data (G_OBJECT(accessible), "dbus-id", GINT_TO_POINTER(ref));
-  g_object_weak_ref(G_OBJECT(accessible), deregister_accessible, NULL);
+  g_hash_table_insert (ref2ptr, GINT_TO_POINTER(ref), hyperlink);
+  g_object_set_data (G_OBJECT(hyperlink), "dbus-id", GINT_TO_POINTER(ref));
+  g_object_ref (G_OBJECT (hyperlink));
+
+  GHashTable *subrefs = (GHashTable *) g_object_get_data (G_OBJECT (container), "dbus-subrefs-hyperlink");
+  if (!subrefs)
+  {
+    subrefs = g_hash_table_new(g_direct_hash, g_direct_equal);
+    g_object_set_data (G_OBJECT (container), "dbus-subrefs-hyperlink", GINT_TO_POINTER(ref));
+  }
+  g_hash_table_insert (subrefs, GINT_TO_POINTER(ref), hyperlink);
 }
 
 /*---------------------------------------------------------------------------*/
@@ -210,8 +320,11 @@ non_owned_accessible (AtkObject *accessible)
 
 /*---------------------------------------------------------------------------*/
 
+/* TRUE if we should not keep this object / tell the AT about it
+ * Currently true if TRANSIENT and not SHOWING
+ */
 static gboolean
-has_manages_descendants (AtkObject *accessible)
+object_is_moot (AtkObject *accessible)
 {
    AtkStateSet *state;
    gboolean result = FALSE;
@@ -221,11 +334,9 @@ has_manages_descendants (AtkObject *accessible)
     * by modifying the tree alot.
     */
    state = atk_object_ref_state_set (accessible);
-   if (atk_state_set_contains_state (state, ATK_STATE_MANAGES_DESCENDANTS))
+   if ( atk_state_set_contains_state (state, ATK_STATE_TRANSIENT) &&
+       !atk_state_set_contains_state (state, ATK_STATE_SHOWING))
      {
-#ifdef SPI_ATK_DEBUG
-       g_warning ("AT-SPI: Object with 'Manages descendants' states not currently handled by AT-SPI");
-#endif
        result = TRUE;
      }
    g_object_unref (state);
@@ -249,7 +360,7 @@ append_children (AtkObject *accessible, GQueue *traversal)
 #ifdef SPI_ATK_DEBUG
           non_owned_accessible (current);
 #endif
-          if (!has_manages_descendants (current))
+          if (!object_is_moot (current))
               g_queue_push_tail (traversal, current);
           else
               g_object_unref (G_OBJECT (current));
@@ -287,7 +398,7 @@ register_subtree (AtkObject *accessible)
       g_queue_push_tail (emit_update, current);
       if (!object_to_ref (current))
         {
-          register_accessible (current);
+          register_accessible (current, NULL);
 #ifdef SPI_ATK_DEBUG
           g_debug ("REG  - %s - %d - %s", atk_object_get_name     (current),
                                           atk_object_get_role     (current),
@@ -338,8 +449,8 @@ atk_dbus_foreach_registered(GHFunc func, gpointer data)
 /*
  * Used to lookup an AtkObject from its D-Bus path.
  */
-AtkObject *
-atk_dbus_path_to_object (const char *path)
+GObject *
+atk_dbus_path_to_gobject (const char *path)
 {
   guint index;
   void *data;
@@ -352,7 +463,7 @@ atk_dbus_path_to_object (const char *path)
   path += SPI_ATK_PATH_PREFIX_LENGTH; /* Skip over the prefix */
 
   if (!g_strcmp0 (SPI_ATK_OBJECT_PATH_DESKTOP, path))
-     return atk_get_root();
+     return G_OBJECT (atk_get_root());
   if (path[0] != '/')
      return NULL;
 
@@ -360,11 +471,17 @@ atk_dbus_path_to_object (const char *path)
   index = atoi (path);
   data = g_hash_table_lookup (ref2ptr, GINT_TO_POINTER(index));
   if (data)
-    return ATK_OBJECT (data);
+    return G_OBJECT (data);
   else
     return NULL;
 }
 
+AtkObject *
+atk_dbus_path_to_object (const char *path)
+{
+  return ATK_OBJECT (atk_dbus_path_to_gobject (path));
+}
+
 /*
  * TODO WARNING HACK This function is dangerous.
  * It should only be called before sending an event on an
@@ -426,11 +543,48 @@ atk_dbus_object_attempt_registration (AtkObject *accessible)
  * Used to lookup a D-Bus path from the AtkObject.
  */
 gchar *
-atk_dbus_object_to_path (AtkObject *accessible)
+atk_dbus_gobject_to_path_internal (GObject *gobj, gboolean do_register, GObject *container)
 {
   guint ref;
 
-  ref = object_to_ref (accessible);
+  ref = gobject_to_ref (gobj);
+  if (!ref && do_register)
+  {
+    register_gobject (gobj, container);
+    ref = gobject_to_ref (gobj);
+  }
+
+  if (!ref)
+      return NULL;
+  else
+      return atk_dbus_ref_to_path (ref);
+}
+
+gchar *
+atk_dbus_object_to_path (AtkObject *accessible, gboolean do_register)
+{
+  AtkObject *container = (accessible && do_register? atk_object_get_parent (accessible): NULL);
+  return atk_dbus_gobject_to_path_internal (G_OBJECT (accessible), do_register, G_OBJECT (container));
+}
+
+gchar *
+atk_dbus_sub_object_to_path (GObject *gobj, GObject *container)
+{
+  return atk_dbus_gobject_to_path_internal (gobj, TRUE, container);
+}
+
+gchar *
+atk_dbus_hyperlink_to_path (AtkHyperlink *hyperlink, AtkObject *container)
+{
+  guint ref;
+
+  ref = gobject_to_ref (G_OBJECT (hyperlink));
+  if (!ref && container)
+  {
+    register_hyperlink (hyperlink, container);
+    ref = hyperlink_to_ref (hyperlink);
+  }
+
   if (!ref)
       return NULL;
   else
@@ -503,6 +657,31 @@ tree_update_state_action (GSignalInvocationHint *signal_hint,
                           gpointer               data,
                           AtkObject             *accessible)
 {
+  const gchar *name;
+  gboolean state;
+
+  if (n_param_values < 3)
+  {
+    g_warning ("at-spi: Not enough params in state-changed signal");
+                               return TRUE;
+  }
+
+  name = g_value_get_string (param_values + 1);
+  state = g_value_get_boolean (param_values + 2);
+  if (!strcmp (name, "visible") && state == 0)
+  {
+    if (object_is_moot (accessible))
+    {
+      int ref_count = G_OBJECT(accessible)->ref_count;
+      g_object_unref (accessible);
+      /* If the ref count was >1, then someone else is still holding a ref,
+         but our ref is gone, so remove from the cache */
+      if (ref_count > 1)
+       deregister_object (NULL, G_OBJECT (accessible));
+      return TRUE;
+    }
+  }
+
       update_accessible (accessible);
   return TRUE;
 }
@@ -559,7 +738,6 @@ tree_update_children_action (GSignalInvocationHint *signal_hint,
       const gchar *detail = NULL;
       AtkObject *child;
 
-      if (has_manages_descendants (accessible)) return TRUE;
       if (signal_hint->detail)
           detail = g_quark_to_string (signal_hint->detail);
 
index b238af7a67e4c223017a86e220140f1f8651f62c..f9f6a9091762789ca80665b503eee5c885c1fbaf 100644 (file)
@@ -32,6 +32,9 @@ atk_dbus_foreach_registered(GHFunc func, gpointer data);
 
 /*---------------------------------------------------------------------------*/
 
+GObject *
+atk_dbus_path_to_gobject (const char *path);
+
 AtkObject *
 atk_dbus_path_to_object (const char *path);
 
@@ -39,7 +42,13 @@ gchar *
 atk_dbus_object_attempt_registration (AtkObject *accessible);
 
 gchar *
-atk_dbus_object_to_path (AtkObject *accessible);
+atk_dbus_object_to_path (AtkObject *accessible, gboolean do_register);
+
+gchar *
+atk_dbus_sub_object_to_path (GObject *accessible, GObject *container);
+
+gchar *
+atk_dbus_hyperlink_to_path (AtkHyperlink *hyperlink, AtkObject *container);
 
 gchar *
 atk_dbus_desktop_object_path ();
index 5f0e10431ede81bf0bbf5b2a405639078f5822db..34a21de42b4d7e26176b8c8656ef09818b4b0a83 100644 (file)
@@ -82,7 +82,7 @@ impl_getAccessibleAtPoint (DBusConnection * bus, DBusMessage * message,
   child =
     atk_component_ref_accessible_at_point (component, x, y,
                                            (AtkCoordType) coord_type);
-  return spi_dbus_return_object (message, child, TRUE);
+  return spi_dbus_return_object (message, child, TRUE, TRUE);
 }
 
 static DBusMessage *
index 58c7e1cad6bc15f42d6948a164b1b09723a06a57..a986f4c28c9bc67a392df025601b6f3a85ece5a7 100644 (file)
@@ -227,7 +227,7 @@ emit_rect(AtkObject  *accessible,
   gchar *path, *cname, *t;
   dbus_int32_t dummy = 0;
 
-  path = atk_dbus_object_to_path (accessible);
+  path = atk_dbus_object_to_path (accessible, FALSE);
 
   /* Tough decision here
    * We won't send events from accessible
@@ -327,7 +327,7 @@ property_event_listener (GSignalInvocationHint *signal_hint,
   if (strcmp (pname, "accessible-table-summary") == 0)
     {
       otemp = atk_table_get_summary(ATK_TABLE (accessible));
-      stemp = atk_dbus_object_to_path (otemp);
+      stemp = atk_dbus_object_to_path (otemp, FALSE);
       if (stemp != NULL)
           emit(accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0, DBUS_TYPE_OBJECT_PATH_AS_STRING, stemp);
     }
@@ -335,7 +335,7 @@ property_event_listener (GSignalInvocationHint *signal_hint,
     {
       i = g_value_get_int (&(values->new_value));
       otemp = atk_table_get_column_header(ATK_TABLE (accessible), i);
-      stemp = atk_dbus_object_to_path (otemp);
+      stemp = atk_dbus_object_to_path (otemp, FALSE);
       if (stemp != NULL)
           emit(accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0, DBUS_TYPE_OBJECT_PATH_AS_STRING, stemp);
     }
@@ -343,7 +343,7 @@ property_event_listener (GSignalInvocationHint *signal_hint,
     {
       i = g_value_get_int (&(values->new_value));
       otemp = atk_table_get_row_header(ATK_TABLE (accessible), i);
-      stemp = atk_dbus_object_to_path (otemp);
+      stemp = atk_dbus_object_to_path (otemp, FALSE);
       if (stemp != NULL)
           emit(accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0, DBUS_TYPE_OBJECT_PATH_AS_STRING, stemp);
     }
@@ -524,7 +524,7 @@ active_descendant_event_listener (GSignalInvocationHint *signal_hint,
   minor = g_quark_to_string (signal_hint->detail);
 
   detail1 = atk_object_get_index_in_parent (child);
-  s = atk_dbus_object_to_path (child);
+  s = atk_dbus_object_to_path (child, FALSE);
   if (s == NULL)
     {
       g_free (s);
index 34d51a786f39da4eb656dd9e28d2b2ce0dd86a06..b839a0ad9685d8e885c289d59d9586a337b043a9 100644 (file)
 #include "accessible-marshaller.h"
 #include "common/spi-dbus.h"
 
+static AtkHyperlink *
+get_hyperlink (void *user_data)
+{
+  if (ATK_IS_HYPERLINK (user_data))
+    return ATK_HYPERLINK (user_data);
+  if (ATK_IS_HYPERLINK_IMPL (user_data))
+    return atk_hyperlink_impl_get_hyperlink (ATK_HYPERLINK_IMPL (user_data));
+  return NULL;
+}
+
 static dbus_bool_t
 impl_get_nAnchors (DBusMessageIter * iter, void *user_data)
 {
@@ -41,7 +51,7 @@ static dbus_bool_t
 impl_get_startIndex (DBusMessageIter * iter,
                      void *user_data)
 {
-  AtkHyperlink *link = (AtkHyperlink *) user_data;
+  AtkHyperlink *link = get_hyperlink (user_data);
   g_return_val_if_fail (ATK_IS_HYPERLINK (user_data), FALSE);
   return droute_return_v_int32 (iter, atk_hyperlink_get_start_index (link));
 }
@@ -49,7 +59,7 @@ impl_get_startIndex (DBusMessageIter * iter,
 static dbus_bool_t
 impl_get_endIndex (DBusMessageIter * iter, void *user_data)
 {
-  AtkHyperlink *link = (AtkHyperlink *) user_data;
+  AtkHyperlink *link = get_hyperlink (user_data);
   g_return_val_if_fail (ATK_IS_HYPERLINK (user_data), FALSE);
   return droute_return_v_int32 (iter, atk_hyperlink_get_end_index (link));
 }
@@ -57,7 +67,7 @@ impl_get_endIndex (DBusMessageIter * iter, void *user_data)
 static DBusMessage *
 impl_getObject (DBusConnection * bus, DBusMessage * message, void *user_data)
 {
-  AtkHyperlink *link = (AtkHyperlink *) user_data;
+  AtkHyperlink *link = get_hyperlink (user_data);
   DBusError error;
   dbus_int32_t i;
   AtkObject *atk_object;
@@ -71,13 +81,13 @@ impl_getObject (DBusConnection * bus, DBusMessage * message, void *user_data)
       return droute_invalid_arguments_error (message);
     }
   atk_object = atk_hyperlink_get_object (link, i);
-  return spi_dbus_return_object (message, atk_object, FALSE);
+  return spi_dbus_return_sub_object (message, G_OBJECT (atk_object), G_OBJECT (link), FALSE);
 }
 
 static DBusMessage *
 impl_getURI (DBusConnection * bus, DBusMessage * message, void *user_data)
 {
-  AtkHyperlink *link = (AtkHyperlink *) user_data;
+  AtkHyperlink *link = get_hyperlink (user_data);
   dbus_int32_t i;
   DBusError error;
   gchar *rv;
@@ -87,8 +97,7 @@ impl_getURI (DBusConnection * bus, DBusMessage * message, void *user_data)
                         droute_not_yet_handled_error (message));
   dbus_error_init (&error);
   if (!dbus_message_get_args
-      (message, &error, DBUS_TYPE_INT32, &i, DBUS_TYPE_INT32, &i,
-       DBUS_TYPE_INVALID))
+      (message, &error, DBUS_TYPE_INT32, &i, DBUS_TYPE_INVALID))
     {
       return droute_invalid_arguments_error (message);
     }
@@ -109,7 +118,7 @@ impl_getURI (DBusConnection * bus, DBusMessage * message, void *user_data)
 static DBusMessage *
 impl_isValid (DBusConnection * bus, DBusMessage * message, void *user_data)
 {
-  AtkHyperlink *link = (AtkHyperlink *) user_data;
+  AtkHyperlink *link = get_hyperlink (user_data);
   dbus_bool_t rv;
   DBusMessage *reply;
 
index af3334eac91120ff1c0253d67ecbd60ee3162511..452cc762c43f994cdeb2a18393bdefaac834b57a 100644 (file)
@@ -26,6 +26,7 @@
 #include <droute/droute.h>
 
 #include "common/spi-dbus.h"
+#include "accessible-marshaller.h"
 
 static DBusMessage *
 impl_getNLinks (DBusConnection * bus, DBusMessage * message, void *user_data)
@@ -63,8 +64,7 @@ impl_getLink (DBusConnection * bus, DBusMessage * message, void *user_data)
       return droute_invalid_arguments_error (message);
     }
   link = atk_hypertext_get_link (hypertext, linkIndex);
-  return NULL; // TODO
-  //return spi_dbus_return_object (message, ATK_OBJECT (link), FALSE);
+  return spi_dbus_return_hyperlink (message, link, ATK_OBJECT(hypertext), TRUE);
 }
 
 static DBusMessage *
index 31b4c84a9ef5e88ca4579d36dd92d22ed0af1f57..1fee2353e626a9a77d4a8ff421a18065d0c6ee92 100644 (file)
@@ -67,7 +67,7 @@ impl_getSelectedChild (DBusConnection * bus, DBusMessage * message,
       return droute_invalid_arguments_error (message);
     }
   atk_object = atk_selection_ref_selection (selection, selectedChildIndex);
-  return spi_dbus_return_object (message, atk_object, TRUE);
+  return spi_dbus_return_object (message, atk_object, TRUE, TRUE);
 }
 
 static DBusMessage *
index 4356e71ddd36a364a9b222dced0b601548235d15..845c1a1476c037afc157bf611f66d30cb0ebdb4a 100644 (file)
@@ -109,7 +109,7 @@ impl_getAccessibleAt (DBusConnection * bus, DBusMessage * message,
       return droute_invalid_arguments_error (message);
     }
   obj = atk_table_ref_at (table, row, column);
-  return spi_dbus_return_object (message, obj, TRUE);
+  return spi_dbus_return_object (message, obj, TRUE, TRUE);
 }
 
 static DBusMessage *
@@ -332,7 +332,7 @@ impl_getRowHeader (DBusConnection * bus, DBusMessage * message,
       return droute_invalid_arguments_error (message);
     }
   obj = atk_table_get_row_header (table, row);
-  return spi_dbus_return_object (message, obj, FALSE);
+  return spi_dbus_return_object (message, obj, TRUE, TRUE);
 }
 
 static DBusMessage *
@@ -353,7 +353,7 @@ impl_getColumnHeader (DBusConnection * bus, DBusMessage * message,
       return droute_invalid_arguments_error (message);
     }
   obj = atk_table_get_column_header (table, column);
-  return spi_dbus_return_object (message, obj, FALSE);
+  return spi_dbus_return_object (message, obj, TRUE, TRUE);
 }
 
 static DBusMessage *
@@ -639,10 +639,10 @@ impl_getRowColumnExtentsAtIndex (DBusConnection * bus, DBusMessage * message,
   reply = dbus_message_new_method_return (message);
   if (reply)
     {
-      dbus_message_append_args (reply, DBUS_TYPE_INT32, row, DBUS_TYPE_INT32,
-                                column, DBUS_TYPE_INT32, row_extents,
-                                DBUS_TYPE_INT32, col_extents,
-                                DBUS_TYPE_BOOLEAN, is_selected,
+      dbus_message_append_args (reply, DBUS_TYPE_INT32, &row, DBUS_TYPE_INT32,
+                                &column, DBUS_TYPE_INT32, &row_extents,
+                                DBUS_TYPE_INT32, &col_extents,
+                                DBUS_TYPE_BOOLEAN, &is_selected,
                                 DBUS_TYPE_BOOLEAN, &ret, DBUS_TYPE_INVALID);
     }
   return reply;
index c292bbdbcee62c326736ee4bfe4afdaff320f6b7..f4cc6604bd78fd439ecb21e28c991ffaa6fbc975 100644 (file)
@@ -39,7 +39,9 @@
 static void
 append_accessible_hf (gpointer key, gpointer obj_data, gpointer iter)
 {
-  spi_atk_append_accessible (ATK_OBJECT(obj_data), iter);
+  /* Make sure it isn't a hyperlink */
+  if (ATK_IS_OBJECT (obj_data))
+    spi_atk_append_accessible (ATK_OBJECT(obj_data), iter);
 }
 
 /*---------------------------------------------------------------------------*/
@@ -102,7 +104,7 @@ impl_getRoot (DBusConnection *bus, DBusMessage *message, void *user_data)
                                       DBUS_ERROR_FAILED,
                                       "No root accessible available");
     }
-  path = atk_dbus_object_to_path (root);
+  path = atk_dbus_object_to_path (root, FALSE);
   if (!path)
     {
       reply = dbus_message_new_error (message,