X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=atk-adaptor%2Ftree.c;h=8652f774de89631553f6c53ae6d8a3bcc799325f;hb=f01ffde94695198fe9e68df3b07eea59d563c495;hp=5c127471fc86bbb194f7f83c63ceaf7e5fd63a50;hpb=0649430a8d6186fb070600b6704b7e9f959ca792;p=platform%2Fcore%2Fuifw%2Fat-spi2-atk.git diff --git a/atk-adaptor/tree.c b/atk-adaptor/tree.c index 5c12747..8652f77 100644 --- a/atk-adaptor/tree.c +++ b/atk-adaptor/tree.c @@ -26,148 +26,215 @@ #include #include "accessible.h" +#include "bridge.h" -#define get_object(message) spi_dbus_get_object(dbus_message_get_path(message)) +extern SpiAppData *app_data; +static gboolean update_pending = FALSE; -static dbus_bool_t -append_update (DBusMessageIter * iter_array, AtkObject * obj, - dbus_bool_t include_children, DRouteData * data) +/*---------------------------------------------------------------------------*/ + +static const char *dumm = "/APath/1"; + +/* + * Marshals the given AtkObject into the provided D-Bus iterator. + * + * The object is marshalled including all its client side cache data. + * The format of the strucuture is (ooaoassus). + * This is used in the updateTree signal and the getTree method + * of the org.freedesktop.atspi.Tree interface. + */ +static void +append_accessible(gpointer ref, gpointer obj_data, gpointer iter) { + AtkObject *obj; + DBusMessageIter *iter_array; DBusMessageIter iter_struct, iter_sub_array; - char *path = NULL; - char *path_parent; + DRouteData *data; + const char *name, *desc; int i; dbus_uint32_t role; - - gint childcount; GSList *l; - g_assert(data != NULL); - - dbus_message_iter_open_container (iter_array, DBUS_TYPE_STRUCT, NULL, - &iter_struct); - path = spi_dbus_get_path (obj); - dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, &path); - path_parent = spi_dbus_get_path (atk_object_get_parent(obj)); - if (!path_parent) path_parent = g_strdup("/"); - dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, &path_parent); - g_free(path_parent); - dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "o", - &iter_sub_array); - childcount = atk_object_get_n_accessible_children (obj); - for (i = 0; i < childcount; i++) - { - AtkObject *child = atk_object_ref_accessible_child (obj, i); - char *child_path = spi_dbus_get_path (child); - if (child_path) - { - dbus_message_iter_append_basic (&iter_sub_array, - DBUS_TYPE_OBJECT_PATH, &child_path); - g_free (child_path); - } - if (child) - g_object_unref (child); - } - if (!dbus_message_iter_close_container (&iter_struct, &iter_sub_array)) - goto oom; - dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "s", - &iter_sub_array); - if (data) for (l = data->interfaces; l; l = g_slist_next (l)) - { - DRouteInterface *iface_def = (DRouteInterface *) l->data; - void *datum = NULL; - if (iface_def->get_datum) - { - datum = (*iface_def->get_datum) (path, data->user_data); - if (!datum) - continue; - } - dbus_message_iter_append_basic (&iter_sub_array, DBUS_TYPE_STRING, - &iface_def->name); - if (iface_def->free_datum) - (*iface_def->free_datum) (datum); - } - if (!dbus_message_iter_close_container (&iter_struct, &iter_sub_array)) - goto oom; - name = atk_object_get_name (obj); - if (!name) - name = ""; - dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &name); - role = spi_accessible_role_from_atk_role (atk_object_get_role (obj)); - dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &role); - desc = atk_object_get_description (obj); - if (!desc) - desc = ""; - dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &desc); - if (!dbus_message_iter_close_container (iter_array, &iter_struct)) - goto oom; - if (!include_children) childcount = 0; - for (i = 0; i < childcount; i++) + obj = ATK_OBJECT(obj_data); + iter_array = (DBusMessageIter *) iter; + data = &(app_data->droute); + + dbus_message_iter_open_container (iter_array, DBUS_TYPE_STRUCT, NULL, &iter_struct); { - AtkObject *child = atk_object_ref_accessible_child (obj, i); - dbus_bool_t result; - if (!child) - continue; - result = append_update (iter_array, child, TRUE, data); - g_object_unref (child); - if (!result) - goto oom; - } - g_free (path); - return TRUE; -oom: - if (path) g_free(path); - return FALSE; + AtkObject *parent; + gchar *path, *path_parent; + + path = atk_dbus_get_path_from_ref(GPOINTER_TO_INT(ref)); + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, &path); + + parent = atk_object_get_parent(obj); + if (parent == NULL) + path_parent = g_strdup("/"); + else + path_parent = atk_dbus_get_path (parent); + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, &path_parent); + g_free(path_parent); + + dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "o", &iter_sub_array); + { + gint childcount, i; + + childcount = atk_object_get_n_accessible_children (obj); + for (i = 0; i < childcount; i++) + { + AtkObject *child; + gchar *child_path; + + child = atk_object_ref_accessible_child (obj, i); + child_path = atk_dbus_get_path (child); + g_object_unref(G_OBJECT(child)); + dbus_message_iter_append_basic (&iter_sub_array, DBUS_TYPE_OBJECT_PATH, &child_path); + g_free (child_path); + } + } + dbus_message_iter_close_container (&iter_struct, &iter_sub_array); + + dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "s", &iter_sub_array); + { + for (l = data->interfaces; l; l = g_slist_next (l)) + { + DRouteInterface *iface_def = (DRouteInterface *) l->data; + void *datum = NULL; + + if (iface_def->get_datum) + { + datum = (*iface_def->get_datum) (path, data->user_data); + if (!datum) + continue; + } + dbus_message_iter_append_basic (&iter_sub_array, DBUS_TYPE_STRING, &iface_def->name); + if (iface_def->free_datum) + (*iface_def->free_datum) (datum); + } + } + dbus_message_iter_close_container (&iter_struct, &iter_sub_array); + + name = atk_object_get_name (obj); + if (!name) + name = ""; + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &name); + + role = spi_accessible_role_from_atk_role (atk_object_get_role (obj)); + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &role); + + desc = atk_object_get_description (obj); + if (!desc) + desc = ""; + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &desc); + + g_free(path); + } + dbus_message_iter_close_container (iter_array, &iter_struct); +} + +/*---------------------------------------------------------------------------*/ + +/* + * Used to marshal array of objects to remove. + * Marshalls an object path onto the iter provided. + */ +static void +append_accessible_path(gpointer ref_data, gpointer null, gpointer data) +{ + guint ref; + gchar *path; + DBusMessageIter *iter_array; + + iter_array = (DBusMessageIter *) data; + ref = GPOINTER_TO_INT(ref_data); + path = atk_dbus_get_path_from_ref(ref); + dbus_message_iter_append_basic (iter_array, DBUS_TYPE_OBJECT_PATH, &path); + g_free(path); } -dbus_bool_t -spi_dbus_append_tree (DBusMessage * message, AtkObject * obj, - DRouteData * data) +/*---------------------------------------------------------------------------*/ + +static gboolean +send_cache_update(gpointer d) { - DBusMessageIter iter, iter_array; - dbus_bool_t result; + DBusMessage *message; + DBusMessageIter iter; + DBusMessageIter iter_array; + DRouteData *data; + + data = &(app_data->droute); - g_assert(data != NULL); + message = dbus_message_new_signal ("/org/freedesktop/atspi/tree", SPI_DBUS_INTERFACE_TREE, "updateTree"); dbus_message_iter_init_append (message, &iter); - dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "(ooaoassus)", - &iter_array); - result = append_update (&iter_array, obj, TRUE, data); - if (result) - result = dbus_message_iter_close_container (&iter, &iter_array); - return result; + + dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "(ooaoassus)", &iter_array); + atk_dbus_foreach_update_list(append_accessible, &iter_array); + dbus_message_iter_close_container(&iter, &iter_array); + + dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "o", &iter_array); + atk_dbus_foreach_remove_list(append_accessible_path, &iter_array); + dbus_message_iter_close_container(&iter, &iter_array); + + dbus_connection_send(data->bus, message, NULL); + update_pending = FALSE; + + return FALSE; } +/*---------------------------------------------------------------------------*/ + +void +atk_tree_cache_needs_update(void) +{ + if (!update_pending) + { + g_idle_add(send_cache_update, NULL); + update_pending = TRUE; + } +} + +/*---------------------------------------------------------------------------*/ + static DBusMessage * -impl_getRoot (DBusConnection * bus, DBusMessage * message, void *user_data) +impl_getRoot (DBusConnection *bus, DBusMessage *message, void *user_data) { AtkObject *root = atk_get_root(); char *path; DBusMessage *reply; - if (root) path = spi_dbus_get_path(root); + if (root) path = atk_dbus_get_path(root); if (!root || !path) return spi_dbus_general_error (message); reply = dbus_message_new_method_return (message); - dbus_message_append_args (reply, DBUS_TYPE_OBJECT_PATH, &path, - DBUS_TYPE_INVALID); + dbus_message_append_args (reply, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID); g_free (path); return reply; } +/*---------------------------------------------------------------------------*/ + static DBusMessage * -impl_getTree (DBusConnection * bus, DBusMessage * message, void *user_data) +impl_getTree (DBusConnection *bus, DBusMessage *message, void *user_data) { DBusMessage *reply; + DBusMessageIter iter, iter_array; AtkObject *root = atk_get_root(); - if (!root) return spi_dbus_general_error(message); + if (!root) + return spi_dbus_general_error(message); reply = dbus_message_new_method_return (message); - spi_dbus_append_tree (reply, root, (DRouteData *) user_data); + + dbus_message_iter_init_append (reply, &iter); + dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ooaoassus)", &iter_array); + atk_dbus_foreach_registered(append_accessible, &iter_array); + dbus_message_iter_close_container(&iter, &iter_array); return reply; } +/*---------------------------------------------------------------------------*/ + static DBusMessage * impl_introspect (DBusConnection *bus, DBusMessage *message, void *user_data) { @@ -183,7 +250,7 @@ impl_introspect (DBusConnection *bus, DBusMessage *message, void *user_data) g_string_append_printf(output, spi_introspection_node_element, path); - spi_append_interface(output, "org.freedesktop.atspi.Tree"); + spi_append_interface(output, SPI_DBUS_INTERFACE_TREE); g_string_append(output, spi_introspection_footer); final = g_string_free(output, FALSE); @@ -197,6 +264,8 @@ impl_introspect (DBusConnection *bus, DBusMessage *message, void *user_data) return reply; } +/*---------------------------------------------------------------------------*/ + static DBusHandlerResult message_handler (DBusConnection *bus, DBusMessage *message, void *user_data) { @@ -207,7 +276,7 @@ message_handler (DBusConnection *bus, DBusMessage *message, void *user_data) g_return_val_if_fail(iface != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); - if (!strcmp(iface, "org.freedesktop.atspi.Tree")) + if (!strcmp(iface, SPI_DBUS_INTERFACE_TREE)) { if (!strcmp(member, "getRoot")) { @@ -237,6 +306,8 @@ message_handler (DBusConnection *bus, DBusMessage *message, void *user_data) return DBUS_HANDLER_RESULT_HANDLED; } +/*---------------------------------------------------------------------------*/ + static DBusObjectPathVTable tree_vtable = { NULL, @@ -244,6 +315,8 @@ static DBusObjectPathVTable tree_vtable = NULL, NULL, NULL, NULL }; +/*---------------------------------------------------------------------------*/ + void spi_register_tree_object(DBusConnection *bus, DRouteData *data, @@ -254,147 +327,4 @@ spi_register_tree_object(DBusConnection *bus, g_assert(mem == TRUE); } -static GHashTable *cache_list; - -#define UPDATE_NEW 1 -#define UPDATE_REFRESH 2 -#define UPDATE_REMOVE 3 - -static int update_pending = 0; -static gint update_pending_id; - -typedef struct -{ - DBusMessageIter iter; - DRouteData *droute; - gboolean removing; -} CacheIterData; - -static void handle_cache_item(char *path, guint action, CacheIterData *d) -{ - AtkObject *obj; - - switch (action) - { - case UPDATE_NEW: - case UPDATE_REFRESH: - default: - if (d->removing) return; - obj = spi_dbus_get_object(path); -//printf("update %s\n", path); - append_update(&d->iter, obj, FALSE, d->droute); - break; - case UPDATE_REMOVE: -//printf("remove: %s\n", path); - if (!d->removing) return; - dbus_message_iter_append_basic(&d->iter, DBUS_TYPE_OBJECT_PATH, &path); - break; - } - g_hash_table_remove(cache_list, path); -} - -gboolean spi_dbus_update_cache(DRouteData *data) -{ - DBusMessage *message; - DBusMessageIter iter; - CacheIterData d; - - g_assert(data != NULL); - - if (update_pending == 0) return FALSE; -//printf("Sending cache\n"); - message = dbus_message_new_signal("/org/freedesktop/atspi/tree", "org.freedesktop.atspi.Tree", "UpdateTree"); - if (!message) goto done; - dbus_message_iter_init_append (message, &iter); - dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "(ooaoassus)", - &d.iter); - d.droute = data; - d.removing = FALSE; - do - { - /* This loop is needed because appending an item may cause new children - * to be registered and consequently added to the hash, so they, too, - * will need to be sent with the update */ - update_pending = 0; - g_hash_table_foreach(cache_list, (GHFunc)handle_cache_item, &d); - } while (update_pending); - dbus_message_iter_close_container(&iter, &d.iter); - dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "o", &d.iter); - d.removing = TRUE; - g_hash_table_foreach(cache_list, (GHFunc)handle_cache_item, &d); - dbus_message_iter_close_container(&iter, &d.iter); - dbus_connection_send(data->bus, message, NULL); -done: - return FALSE; -} - -void spi_dbus_notify_change(AtkObject *obj, gboolean new, DRouteData *data) -{ - guint action = (new? UPDATE_NEW: UPDATE_REFRESH); - char *path = spi_dbus_get_path(obj); - - if (!cache_list) - { - cache_list = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); - if (!cache_list) - { - g_free(path); - return; - } - } - if (g_hash_table_lookup(cache_list, path)) - { - g_free(path); - return; - } -//printf("change: %s\n", path); - g_hash_table_insert(cache_list, path, (gpointer)action); - if (update_pending != 2 && data) - { - update_pending_id = g_idle_add((GSourceFunc)spi_dbus_update_cache, data); - update_pending = 2; - } - else if (!update_pending) update_pending = 1; -} - -void spi_dbus_notify_remove(AtkObject *obj, DRouteData *data) -{ - guint action = UPDATE_REMOVE; - guint cur_action; - gchar *path = spi_dbus_get_path(obj); - -//printf("notify remove: %s\n", path); - if (!cache_list) - { - g_free(path); - return; - } - cur_action = (guint)g_hash_table_lookup(cache_list, path); - if (cur_action == UPDATE_NEW) - { - /* No one knew that this object ever existed, so just remove it */ -//printf("Removing object from send queue\n"); - g_hash_table_remove(cache_list, path); - g_free(path); - } - else - { - g_hash_table_insert(cache_list, path, (gpointer)action); - if (update_pending != 2 && data) - { - update_pending_id = g_idle_add((GSourceFunc)spi_dbus_update_cache, data); - update_pending = 2; - } - else if (!update_pending) update_pending = 1; - } -} - -gboolean spi_dbus_object_is_known(AtkObject *obj) -{ - guint cur_action; - char *path = spi_dbus_get_path(obj); - if (!path) return FALSE; - cur_action = (guint)g_hash_table_lookup(cache_list, path); - g_free(path); - return (cur_action != UPDATE_NEW); -} +/*END------------------------------------------------------------------------*/