X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=atk-adaptor%2Faccessible-register.c;h=3595f3e81800871e670506ebeaaabab29b2e5fb5;hb=0b5f4db64d874cfef13ca62bc0c5413358af0d4e;hp=9a095f600d0594745527c57cf07433a7534fe8fc;hpb=5d30ed4afc98e7f19f35dfcfc1fbd534966e8344;p=platform%2Fcore%2Fuifw%2Fat-spi2-atk.git diff --git a/atk-adaptor/accessible-register.c b/atk-adaptor/accessible-register.c index 9a095f6..3595f3e 100644 --- a/atk-adaptor/accessible-register.c +++ b/atk-adaptor/accessible-register.c @@ -28,10 +28,6 @@ #include "bridge.h" #include "accessible-register.h" -#define ATK_BRIDGE_OBJECT_PATH_PREFIX "/org/freedesktop/atspi/accessible" -#define ATK_BRIDGE_OBJECT_REFERENCE_TEMPLATE ATK_BRIDGE_OBJECT_PATH_PREFIX "/%d" -#define ATK_BRIDGE_PATH_PREFIX_LENGTH 33 - /* * This module is responsible for keeping track of all the AtkObjects in * the application, so that they can be accessed remotely and placed in @@ -39,7 +35,7 @@ * * To access an AtkObject remotely we need to provide a D-Bus object * path for it. The D-Bus object paths used have a standard prefix - * (ATK_BRIDGE_OBJECT_PATH_PREFIX). Appended to this prefix is a string + * (SPI_ATK_OBJECT_PATH_PREFIX). Appended to this prefix is a string * representation of an integer reference. So to access an AtkObject * remotely we keep a Hashtable that maps the given reference to * the AtkObject pointer. An object in this hash table is said to be 'registered'. @@ -59,22 +55,29 @@ /* * FIXME * - * While traversing the ATK tree we may modify it unintentionally. - * This is either a bug in the Gail implementation or this module. - * If a change is caused that recurses, via a signal into this module - * we should catch it. + * This code seems very brittle. + * I would prefer changes to be made to + * gail and the ATK interface so that all Accessible + * objects are registered with an exporting module. * - * Things could also be changed that do not cause signal emission, - * but do cause a failure. Not sure what these would be. + * This is the same system as Qt has with the QAccessibleBridge + * and QAccessibleBridgePlugin. It entails some rather + * large structural changes to ATK though: * - * The other option is that there are threads that modify the GUI. - * This IS A BUG IN THE PROGRAM. But it may happen. If seeing very - * odd bugs change this to take the GDK lock. Just to make sure. + * Removing infinite spaces (Child access no longer references child). + * Removing lazy creation of accessible objects. */ +#define SPI_ATK_OBJECT_PATH_PREFIX "/org/freedesktop/atspi/accessible" +#define SPI_ATK_OBJECT_PATH_DESKTOP "/root" + +#define SPI_ATK_PATH_PREFIX_LENGTH 33 +#define SPI_ATK_OBJECT_REFERENCE_TEMPLATE SPI_ATK_OBJECT_PATH_PREFIX "/%d" + + static GHashTable *ref2ptr = NULL; /* Used for converting a D-Bus path (Reference) to the object pointer */ -static guint counter = 1; +static guint reference_counter = 0; static GStaticRecMutex registration_mutex = G_STATIC_REC_MUTEX_INIT; @@ -113,10 +116,11 @@ recursion_check_unset () static guint assign_reference(void) { - counter++; + reference_counter++; /* Reference of 0 not allowed as used as direct key in hash table */ - if (counter == 0) - counter++; + if (reference_counter == 0) + reference_counter++; + return reference_counter; } /* @@ -134,7 +138,7 @@ object_to_ref (AtkObject *accessible) static gchar * ref_to_path (guint ref) { - return g_strdup_printf(ATK_BRIDGE_OBJECT_REFERENCE_TEMPLATE, ref); + return g_strdup_printf(SPI_ATK_OBJECT_REFERENCE_TEMPLATE, ref); } /*---------------------------------------------------------------------------*/ @@ -149,7 +153,7 @@ static void deregister_accessible (gpointer data, GObject *accessible) { guint ref; - g_assert (ATK_IS_OBJECT (accessible)); + g_return_if_fail (ATK_IS_OBJECT (accessible)); ref = object_to_ref (ATK_OBJECT(accessible)); if (ref != 0) @@ -165,7 +169,7 @@ static void register_accessible (AtkObject *accessible) { guint ref; - g_assert(ATK_IS_OBJECT(accessible)); + g_return_if_fail (ATK_IS_OBJECT(accessible)); ref = assign_reference(); @@ -227,6 +231,29 @@ has_manages_descendants (AtkObject *accessible) return result; } +static void +append_children (AtkObject *accessible, GQueue *traversal) +{ + AtkObject *current; + guint i; + + for (i =0; i < atk_object_get_n_accessible_children (accessible); i++) + { + current = atk_object_ref_accessible_child (accessible, i); +#ifdef SPI_ATK_DEBUG + non_owned_accessible (current); +#endif + if (!has_manages_descendants (current)) + { + g_queue_push_tail (traversal, current); + } + else + { + g_object_unref (G_OBJECT (current)); + } + } +} + /* * Registers a subtree of accessible objects * rooted at the accessible object provided. @@ -239,88 +266,41 @@ has_manages_descendants (AtkObject *accessible) void register_subtree (AtkObject *accessible) { - AtkObject *current, *tmp; - GQueue *stack; - guint i; - gboolean recurse; - - - current = g_object_ref (accessible); - if (has_manages_descendants (current)) - { - g_object_unref (current); - return; - } + AtkObject *current; + GQueue *traversal; + GQueue *emit_update; - stack = g_queue_new (); + traversal = g_queue_new (); + emit_update = g_queue_new (); - register_accessible (current); - g_queue_push_head (stack, GINT_TO_POINTER (0)); + g_object_ref (accessible); + g_queue_push_tail (traversal, accessible); - /* - * The index held on the stack is the next child node - * that needs processing at the corresponding level in the tree. - */ - while (!g_queue_is_empty (stack)) + while (!g_queue_is_empty (traversal)) { - /* Find the next child node that needs processing */ - - i = GPOINTER_TO_INT(g_queue_peek_head (stack)); - recurse = FALSE; - - while (i < atk_object_get_n_accessible_children (current) && - recurse == FALSE) + current = g_queue_pop_head (traversal); + g_queue_push_tail (emit_update, current); + if (!object_to_ref (current)) { - tmp = atk_object_ref_accessible_child (current, i); - + register_accessible (current); #ifdef SPI_ATK_DEBUG - non_owned_accessible (tmp); + g_debug ("REG - %s - %d - %s", atk_object_get_name (current), + atk_object_get_role (current), + atk_dbus_object_to_path (current)); #endif - - if (object_to_ref (tmp)) - { - /* If its already registered, just update */ - spi_emit_cache_update (tmp, atk_adaptor_app_data->bus); - } - else if (has_manages_descendants (tmp)) - { - /* If it has manages descendants, just register and update */ - register_accessible (tmp); - spi_emit_cache_update (tmp, atk_adaptor_app_data->bus); - } - else - { - recurse = TRUE; - } - - if (!recurse) - { - g_object_unref (G_OBJECT (tmp)); - } - - i++; + append_children (current, traversal); } + } - if (recurse) - { - /* Push onto stack */ - current = tmp; - register_accessible (current); - - g_queue_peek_head_link (stack)->data = GINT_TO_POINTER (i); - g_queue_push_head (stack, GINT_TO_POINTER (0)); - } - else - { - /* Pop from stack */ - spi_emit_cache_update (current, atk_adaptor_app_data->bus); - tmp = current; - current = atk_object_get_parent (current); - g_object_unref (G_OBJECT (tmp)); - g_queue_pop_head (stack); - } + while (!g_queue_is_empty (emit_update)) + { + current = g_queue_pop_head (emit_update); + spi_emit_cache_update (current, atk_adaptor_app_data->bus); + g_object_unref (G_OBJECT (current)); } - g_queue_free (stack); + + g_queue_free (traversal); + g_queue_free (emit_update); } /*---------------------------------------------------------------------------*/ @@ -333,7 +313,7 @@ static void update_accessible (AtkObject *accessible) { guint ref = 0; - g_assert(ATK_IS_OBJECT(accessible)); + g_return_if_fail (ATK_IS_OBJECT(accessible)); ref = object_to_ref (accessible); if (ref) @@ -359,14 +339,14 @@ atk_dbus_path_to_object (const char *path) guint index; void *data; - g_assert (path); + g_return_val_if_fail (path, NULL); - if (strncmp(path, ATK_BRIDGE_OBJECT_PATH_PREFIX, ATK_BRIDGE_PATH_PREFIX_LENGTH) != 0) + if (strncmp(path, SPI_ATK_OBJECT_PATH_PREFIX, SPI_ATK_PATH_PREFIX_LENGTH) != 0) return NULL; - path += ATK_BRIDGE_PATH_PREFIX_LENGTH; /* Skip over the prefix */ + path += SPI_ATK_PATH_PREFIX_LENGTH; /* Skip over the prefix */ - if (path[0] == '\0') + if (!g_strcmp0 (SPI_ATK_OBJECT_PATH_DESKTOP, path)) return atk_get_root(); if (path[0] != '/') return NULL; @@ -395,6 +375,12 @@ atk_dbus_object_to_path (AtkObject *accessible) return ref_to_path (ref); } +gchar * +atk_dbus_desktop_object_path () +{ + return g_strdup (SPI_ATK_OBJECT_PATH_PREFIX SPI_ATK_OBJECT_PATH_DESKTOP); +} + /*---------------------------------------------------------------------------*/ /* @@ -422,15 +408,18 @@ tree_update_listener (GSignalInvocationHint *signal_hint, * have their signals processed. */ accessible = g_value_get_object (¶m_values[0]); - g_assert (ATK_IS_OBJECT (accessible)); + g_return_val_if_fail (ATK_IS_OBJECT (accessible), TRUE); if (object_to_ref (accessible)) { #ifdef SPI_ATK_DEBUG if (recursion_check_and_set ()) g_warning ("AT-SPI: Recursive use of registration module"); + + g_debug ("AT-SPI: Tree update listener"); #endif + values = (AtkPropertyValues*) g_value_get_pointer (¶m_values[1]); pname = values[0].property_name; if (strcmp (pname, "accessible-name") == 0 || @@ -470,13 +459,15 @@ tree_update_children_listener (GSignalInvocationHint *signal_hint, * have their signals processed. */ accessible = g_value_get_object (¶m_values[0]); - g_assert (ATK_IS_OBJECT (accessible)); + g_return_val_if_fail (ATK_IS_OBJECT (accessible), TRUE); if (object_to_ref (accessible)) { #ifdef SPI_ATK_DEBUG if (recursion_check_and_set ()) g_warning ("AT-SPI: Recursive use of registration module"); + + g_debug ("AT-SPI: Tree update children listener"); #endif if (signal_hint->detail) @@ -521,6 +512,8 @@ atk_dbus_initialize (AtkObject *root) #ifdef SPI_ATK_DEBUG if (g_thread_supported ()) g_message ("AT-SPI: Threads enabled"); + + g_debug ("AT-SPI: Initial Atk tree regisration"); #endif register_subtree (root);