From 4ac4e0d4876bd1535748e8dc8ccf35db1e173673 Mon Sep 17 00:00:00 2001 From: Mark Doffman Date: Thu, 23 Apr 2009 16:01:08 +0100 Subject: [PATCH] 2009-04-23 Mark Doffman Add a hack for registering objects when an event needs to be sent on them and they are not already registered. --- atk-adaptor/accessible-register.c | 72 ++++++++++++++++++++++++++++++++++----- atk-adaptor/accessible-register.h | 3 ++ atk-adaptor/event.c | 19 +++++++++-- 3 files changed, 84 insertions(+), 10 deletions(-) diff --git a/atk-adaptor/accessible-register.c b/atk-adaptor/accessible-register.c index c6c7328..63fc106 100644 --- a/atk-adaptor/accessible-register.c +++ b/atk-adaptor/accessible-register.c @@ -240,16 +240,15 @@ append_children (AtkObject *accessible, GQueue *traversal) for (i =0; i < atk_object_get_n_accessible_children (accessible); i++) { current = atk_object_ref_accessible_child (accessible, i); + if (current) + { #ifdef SPI_ATK_DEBUG - non_owned_accessible (current); + non_owned_accessible (current); #endif - if (!has_manages_descendants (current)) - { - g_queue_push_tail (traversal, current); - } - else - { - g_object_unref (G_OBJECT (current)); + if (!has_manages_descendants (current)) + g_queue_push_tail (traversal, current); + else + g_object_unref (G_OBJECT (current)); } } } @@ -363,6 +362,63 @@ atk_dbus_path_to_object (const char *path) } /* + * TODO WARNING HACK This function is dangerous. + * It should only be called before sending an event on an + * object that has not already been registered. + */ +gchar * +atk_dbus_object_attempt_registration (AtkObject *accessible) +{ + guint ref; + + ref = object_to_ref (accessible); + if (!ref) + { + /* See if the object is attached to the main tree */ + AtkObject *current, *prev = NULL; + guint cref = 0; + + /* This should iterate until it hits a NULL or registered parent */ + prev = accessible; + current = atk_object_get_parent (accessible); + if (current) + cref = object_to_ref (current); + while (current && !cref) + { + prev = current; + current = atk_object_get_parent (current); + if (current) + cref = object_to_ref (current); + } + + /* A registered parent, with non-registered child, has been found */ + if (current) + { + register_subtree (prev); + } + + /* The object SHOULD be registered now. If it isn't - I give up */ + ref = object_to_ref (accessible); + if (ref) + { + return ref_to_path (ref); + } + else + { +#ifdef SPI_ATK_DEBUG + g_debug ("AT-SPI: Could not register a non-attached accessible object"); +#endif + return NULL; + } + } + else + { + return ref_to_path (ref); + } +} + + +/* * Used to lookup a D-Bus path from the AtkObject. */ gchar * diff --git a/atk-adaptor/accessible-register.h b/atk-adaptor/accessible-register.h index a594413..e14886a 100644 --- a/atk-adaptor/accessible-register.h +++ b/atk-adaptor/accessible-register.h @@ -36,6 +36,9 @@ AtkObject * atk_dbus_path_to_object (const char *path); gchar * +atk_dbus_object_attempt_registration (AtkObject *accessible); + +gchar * atk_dbus_object_to_path (AtkObject *accessible); gchar * diff --git a/atk-adaptor/event.c b/atk-adaptor/event.c index a201b37..3d1250e 100644 --- a/atk-adaptor/event.c +++ b/atk-adaptor/event.c @@ -187,14 +187,23 @@ emit(AtkObject *accessible, { gchar *path; - path = atk_dbus_object_to_path (accessible); + /* TODO this is a hack, used becuase child-added events are not guaranteed. + * On recieving an event from a non-registered object we check if it can be safely + * registered before sending the event. + */ + path = atk_dbus_object_attempt_registration (accessible); /* Tough decision here * We won't send events from accessible * objects that have not yet been added to the accessible tree. */ if (path == NULL) + { +#ifdef SPI_ATK_DEBUG + g_debug ("AT-SPI: Event recieved from non-registered object"); +#endif return; + } spi_dbus_emit_signal (atk_adaptor_app_data->bus, path, klass, major, minor, detail1, detail2, type, val); g_free(path); @@ -298,11 +307,17 @@ property_event_listener (GSignalInvocationHint *signal_hint, AtkObject *otemp; const gchar *stemp; gint i; - + accessible = g_value_get_object (¶m_values[0]); values = (AtkPropertyValues*) g_value_get_pointer (¶m_values[1]); pname = values[0].property_name; + if (strcmp (pname, "accessible-name") == 0 || + strcmp (pname, "accessible-description") == 0 || + strcmp (pname, "accessible-parent") == 0) + { + return TRUE; + } /* TODO Could improve this control statement by matching * on only the end of the signal names, -- 2.7.4