From 88bb80616a218c95fb78e4f2dbe873eb2cccceb1 Mon Sep 17 00:00:00 2001 From: Radoslaw Cybulski Date: Fri, 24 Mar 2017 18:50:16 +0100 Subject: [PATCH] Add navigation helper functions for screen-reader and friends (part 2) Change-Id: Ia9fd6d9743fddcb24801df596d2834b076408ea9 --- atk-adaptor/adaptors/accessible-adaptor.c | 566 +++++++++++++++++++++++------- atk-adaptor/bridge.c | 6 +- droute/droute.c | 4 +- 3 files changed, 448 insertions(+), 128 deletions(-) diff --git a/atk-adaptor/adaptors/accessible-adaptor.c b/atk-adaptor/adaptors/accessible-adaptor.c index a84052a..b0a7d8b 100644 --- a/atk-adaptor/adaptors/accessible-adaptor.c +++ b/atk-adaptor/adaptors/accessible-adaptor.c @@ -34,131 +34,84 @@ #include "introspection.h" #include #include - - - - - - - - - - - - +#include // TIZEN_ONLY(20170310) - implementation of get object under coordinates for accessibility -static AtspiRelationType spi_relation_type_from_atk_relation_type (AtkRelationType type); +typedef struct { + void **objects; + unsigned int capacity; + unsigned int size; +} vector; + +typedef enum { + NEIGHBOR_SEARCH_MODE_NORMAL = 0, + NEIGHBOR_SEARCH_MODE_RECURSE_FROM_ROOT = 1, + NEIGHBOR_SEARCH_MODE_CONTINUE_AFTER_FAILED_RECURSING = 2, +} GetNeighborSearchMode; + +typedef struct accessibility_navigation_pointer_table { + AtspiRole (*object_get_role)(struct accessibility_navigation_pointer_table *t, void *ptr); + uint64_t (*object_get_state_set)(struct accessibility_navigation_pointer_table *t, void *ptr); + void *(*get_object_in_relation_by_type)(struct accessibility_navigation_pointer_table *t, void *ptr, AtspiRelationType type); + unsigned char (*object_is_zero_size)(struct accessibility_navigation_pointer_table *t, void *ptr); + void *(*get_parent)(struct accessibility_navigation_pointer_table *t, void *ptr); + unsigned char (*object_is_scrollable)(struct accessibility_navigation_pointer_table *t, void *ptr); + void *(*get_object_at_point)(struct accessibility_navigation_pointer_table *t, void *ptr, int x, int y, unsigned char coordinates_are_screen_based); + unsigned char (*object_contains)(struct accessibility_navigation_pointer_table *t, void *ptr, int x, int y, unsigned char coordinates_are_screen_based); + unsigned char (*object_is_proxy)(struct accessibility_navigation_pointer_table *t, void *ptr); + void (*get_children)(struct accessibility_navigation_pointer_table *t, void *ptr, vector *v); +} accessibility_navigation_pointer_table; -static AtspiRole _object_get_role_impl(void *ptr) +static vector vector_init(void) { - AtkObject *obj = (AtkObject*)ptr; - AtkRole role = atk_object_get_role (obj); - AtspiRole rv = spi_accessible_role_from_atk_role (role); - return rv; + vector v; + v.objects = NULL; + v.capacity = 0; + v.size = 0; + return v; } -static uint64_t _object_get_state_set_impl(void *ptr) +static void vector_free(vector *v) { - dbus_uint32_t array[2]; - spi_atk_state_to_dbus_array((AtkObject*)ptr, array); - uint64_t res = array[0] | ((uint64_t)array[1] << 32); - return res; + free(v->objects); + v->objects = NULL; + v->capacity = 0; + v->size = 0; } - -static void *_get_object_in_relation_by_type_impl(void *ptr, AtspiRelationType expected_relation_type) +static void vector_reserve(vector *v, unsigned int s) { - if (ptr) { - g_return_val_if_fail (ATK_IS_OBJECT (ptr), NULL); - AtkRelationSet *set = atk_object_ref_relation_set (ptr); - if (!set) - return NULL; - gint count = atk_relation_set_get_n_relations (set), i; - for (i = 0; i < count; i++) - { - AtkRelation *r = atk_relation_set_get_relation (set, i); - if (!r) - continue; - AtkRelationType rt = atk_relation_get_relation_type (r); - AtspiRelationType type = spi_relation_type_from_atk_relation_type (rt); - if (expected_relation_type == type) - { - GPtrArray *target = atk_relation_get_target (r); - if (target && target->len > 0) - return target->pdata[0]; - } - } - g_object_unref (set); - } - return NULL; + if (s > v->capacity) + { + v->objects = (void**)realloc(v->objects, sizeof(v->objects[0]) * s); + v->capacity = s; + } } -static unsigned char _object_is_zero_size_impl(void *ptr) +static void vector_resize(vector *v, unsigned int s) { - AtkObject *obj = (AtkObject*)obj; - g_return_val_if_fail(ATK_IS_COMPONENT (obj), 0); - gint x, y, w, h; - atk_component_get_extents (ATK_COMPONENT(obj), &x, &y, &w, &h, ATSPI_COORD_TYPE_SCREEN); - return w == 0 || h == 0; + vector_reserve(v, s); + v->size = s; } -unsigned char _object_is_scrollable_impl(void *ptr) +static void *vector_get(vector *v, unsigned int index) { - AtspiRole role = _object_get_role_impl(ptr); - switch (role) { - case ATSPI_ROLE_SCROLL_PANE: //scroller - case ATSPI_ROLE_LIST: //genlist, list - case ATSPI_ROLE_TREE_TABLE: //gengrid - case ATSPI_ROLE_TOOL_BAR: //toolbar - return 1; - default: - break; - } - return 0; + return v->objects[index]; } -void *_get_parent_impl(void *ptr) +static void vector_set(vector *v, unsigned int index, void *data) { - return atk_object_get_parent((AtkObject*)ptr); + v->objects[index] = data; } -void *_object_at_point_get_impl(void *ptr, int x, int y, unsigned char coordinates_are_screen_based) +static unsigned int vector_size(vector *v) { - AtkObject *obj = (AtkObject*)ptr; - g_return_val_if_fail(ATK_IS_COMPONENT (obj), 0); - return atk_component_ref_accessible_at_point (ATK_COMPONENT(obj), x, y, - coordinates_are_screen_based ? ATSPI_COORD_TYPE_SCREEN : ATSPI_COORD_TYPE_WINDOW); + return v->size; } -unsigned char _object_contains_impl(void *ptr, int x, int y, unsigned char coordinates_are_screen_based) -{ - AtkObject *obj = (AtkObject*)ptr; - g_return_val_if_fail(ATK_IS_COMPONENT (obj), 0); - - return atk_component_contains (ATK_COMPONENT(obj), x, y, - coordinates_are_screen_based ? ATSPI_COORD_TYPE_SCREEN : ATSPI_COORD_TYPE_WINDOW); -} - -unsigned char _object_is_proxy_impl(void *ptr) -{ - return 0; -} - -typedef struct { - AtspiRole (*object_get_role)(void *ptr); - uint64_t (*object_get_state_set)(void *ptr); - void *(*get_object_in_relation_by_type)(void *ptr, AtspiRelationType type); - unsigned char (*object_is_zero_size)(void *ptr); - void *(*get_parent)(void *ptr); - unsigned char (*object_is_scrollable)(void *ptr); - void *(*object_at_point_get)(void *ptr, int x, int y, unsigned char coordinates_are_screen_based); - unsigned char (*object_contains)(void *ptr, int x, int y, unsigned char coordinates_are_screen_based); - unsigned char (*object_is_proxy)(void *ptr); -} accessibility_navigation_pointer_table; - +#define CALL(fncname, ...) table->fncname(table, __VA_ARGS__) static unsigned char _accept_object_check_role(accessibility_navigation_pointer_table *table, void *obj) { - AtspiRole role = table->object_get_role(obj); + AtspiRole role = CALL(object_get_role, obj); switch (role) { case ATSPI_ROLE_APPLICATION: @@ -193,27 +146,44 @@ static unsigned char _state_set_is_set(uint64_t state_set, AtspiStateType state) return (state_set & ((uint64_t)1 << (unsigned int)state)) != 0; } +static unsigned char _object_is_defunct(accessibility_navigation_pointer_table *table, void *ptr) +{ + uint64_t states = CALL(object_get_state_set, ptr); + return _state_set_is_set(states, ATSPI_STATE_DEFUNCT); +} + +static unsigned char _object_role_is_acceptable_when_navigating_next_prev(accessibility_navigation_pointer_table *table, void *obj) +{ + AtspiRole role = CALL(object_get_role, obj); + return role != ATSPI_ROLE_POPUP_MENU && role != ATSPI_ROLE_DIALOG; +} + +static void *_get_object_in_relation_flow(accessibility_navigation_pointer_table *table, void *source, unsigned char forward) +{ + return CALL(get_object_in_relation_by_type, source, forward ? ATSPI_RELATION_FLOWS_TO : ATSPI_RELATION_FLOWS_FROM); +} + static unsigned char _object_is_item(accessibility_navigation_pointer_table *table, void *obj) { - AtspiRole role = table->object_get_role(obj); + AtspiRole role = CALL(object_get_role, obj); return role == ATSPI_ROLE_LIST_ITEM || role == ATSPI_ROLE_MENU_ITEM; } static unsigned char _object_is_highlightable(accessibility_navigation_pointer_table *table, void *obj) { - uint64_t state_set = table->object_get_state_set(obj); + uint64_t state_set = CALL(object_get_state_set, obj); return _state_set_is_set(state_set, ATSPI_STATE_HIGHLIGHTABLE); } static unsigned char _object_is_showing(accessibility_navigation_pointer_table *table, void *obj) { - uint64_t state_set = table->object_get_state_set(obj); + uint64_t state_set = CALL(object_get_state_set, obj); return _state_set_is_set(state_set, ATSPI_STATE_SHOWING); } static unsigned char _object_is_collapsed(accessibility_navigation_pointer_table *table, void *obj) { - uint64_t state_set = table->object_get_state_set(obj); + uint64_t state_set = CALL(object_get_state_set, obj); return _state_set_is_set(state_set, ATSPI_STATE_EXPANDABLE) && !_state_set_is_set(state_set, ATSPI_STATE_EXPANDED); @@ -221,21 +191,21 @@ static unsigned char _object_is_collapsed(accessibility_navigation_pointer_table static unsigned char _object_has_modal_state(accessibility_navigation_pointer_table *table, void *obj) { - uint64_t state_set = table->object_get_state_set(obj); + uint64_t state_set = CALL(object_get_state_set, obj); return _state_set_is_set(state_set, ATSPI_STATE_MODAL); } static unsigned char _object_is_zero_size(accessibility_navigation_pointer_table *table, void *obj) { - return table->object_is_zero_size(obj); + return CALL(object_is_zero_size, obj); } static void *_get_scrollable_parent(accessibility_navigation_pointer_table *table, void *obj) { while(obj) { - obj = table->get_parent(obj); - if (obj && table->object_is_scrollable(obj)) return obj; + obj = CALL(get_parent, obj); + if (obj && CALL(object_is_scrollable, obj)) return obj; } return NULL; } @@ -243,12 +213,12 @@ static unsigned char _accept_object(accessibility_navigation_pointer_table *tabl { if (!obj) return 0; if (!_accept_object_check_role(table, obj)) return 0; - if (table->get_object_in_relation_by_type(obj, ATSPI_RELATION_CONTROLLED_BY) != NULL) return 0; + if (CALL(get_object_in_relation_by_type, obj, ATSPI_RELATION_CONTROLLED_BY) != NULL) return 0; if (!_object_is_highlightable(table, obj)) return 0; if (_get_scrollable_parent(table, obj) != NULL) { - void *parent = table->get_parent(obj); + void *parent = CALL(get_parent, obj); if (parent) { @@ -271,18 +241,18 @@ static void *_calculate_navigable_accessible_at_point_impl(accessibility_navigat void *return_value = NULL; while (1) { - void *target = table->object_at_point_get(root, x, y, coordinates_are_screen_based); + void *target = CALL(get_object_at_point, root, x, y, coordinates_are_screen_based); if (!target) break; // always return proxy, so atspi lib can call on it again - if (table->object_is_proxy(target)) return target; + if (CALL(object_is_proxy, target)) return target; root = target; - void *relation_obj = table->get_object_in_relation_by_type(root, ATSPI_RELATION_CONTROLLED_BY); + void *relation_obj = CALL(get_object_in_relation_by_type, root, ATSPI_RELATION_CONTROLLED_BY); unsigned char contains = 0; if (relation_obj) { - contains = table->object_contains(relation_obj, x, y, coordinates_are_screen_based); + contains = CALL(object_contains, relation_obj, x, y, coordinates_are_screen_based); if (contains) root = relation_obj; } @@ -297,6 +267,329 @@ static void *_calculate_navigable_accessible_at_point_impl(accessibility_navigat return return_value; } + + + + + + +static void *_find_non_defunct_child(accessibility_navigation_pointer_table *table, + vector *objects, unsigned int current_index, unsigned char forward) +{ + for(; current_index < vector_size(objects); forward ? ++current_index : --current_index) + { + void *n = vector_get(objects, current_index); + if (n && !_object_is_defunct(table, n)) return n; + } + return NULL; +} + +static void *_directional_depth_first_search_try_non_defunct_child(accessibility_navigation_pointer_table *table, + void *node, vector *children, unsigned char forward) +{ + if (vector_size(children) > 0) + { + unsigned char is_showing = _get_scrollable_parent(table, node) == NULL ? _object_is_showing(table, node) : 1; + if (is_showing) + { + return _find_non_defunct_child(table, children, forward ? 0 : vector_size(children) - 1, forward); + } + } + return NULL; +} + +static void *_get_next_non_defunct_sibling(accessibility_navigation_pointer_table *table, + void *obj, unsigned char forward) +{ + if (!obj) return NULL; + void *parent = CALL(get_parent, obj); + if (!parent) return NULL; + + vector children = vector_init(); + CALL(get_children, parent, &children); + if (vector_size(&children) == 0) + { + vector_free(&children); + return NULL; + } + unsigned int current = 0; + for(; current < vector_size(&children) && vector_get(&children, current) != obj; ++current) ; + if (current >= vector_size(&children)) + { + vector_free(&children); + return NULL; + } + forward ? ++current : --current; + void *ret = _find_non_defunct_child(table, &children, current, forward); + vector_free(&children); + return ret; +} + +static void *_directional_depth_first_search_try_non_defunct_sibling(accessibility_navigation_pointer_table *table, + unsigned char *all_children_visited_ptr, void *node, void *root, unsigned char forward) +{ + while(1) + { + void *sibling = _get_next_non_defunct_sibling(table, node, forward); + if (sibling != NULL) + { + node = sibling; + *all_children_visited_ptr = 0; + break; + } + + // walk up... + node = CALL(get_parent, node); + if (node == NULL || node == root) return NULL; + + // in backward traversing stop the walk up on parent + if (!forward) break; + } + return node; +} + +typedef struct { + const void *key; + unsigned int current_search_size; + unsigned int counter; +} cycle_detection_data; + +void cycle_detection_initialize(cycle_detection_data *data, const void *key) +{ + if (!data) return; + data->key = key; + data->current_search_size = 1; + data->counter = 1; +} + +unsigned char cycle_detection_check_if_in_cycle(cycle_detection_data *data, const void *key) +{ + if (!data) return 1; + if (data->key == key) return 1; + if (--data->counter == 0) + { + data->current_search_size <<= 1; + if (data->current_search_size == 0) return 1; + data->counter = data->current_search_size; + data->key = key; + } + return 0; +} + +static void *_calculate_neighbor_impl(accessibility_navigation_pointer_table *table, void *root, void *start, unsigned char forward, GetNeighborSearchMode search_mode) +{ + if (root && _object_is_defunct(table, root)) return NULL; + if (start && _object_is_defunct(table, start)) + { + start = root; + forward = 1; + } + void *node = start; + if (!node) return NULL; + + // initialization of all-children-visiten flag for start node - we assume + // that when we begin at start node and we navigate backward, then all children + // are visited, so navigation will ignore start's children and go to + // previous sibling available. + unsigned char all_children_visited = search_mode != NEIGHBOR_SEARCH_MODE_RECURSE_FROM_ROOT && !forward; + unsigned char force_next = search_mode == NEIGHBOR_SEARCH_MODE_CONTINUE_AFTER_FAILED_RECURSING; + + cycle_detection_data cycle_detection; + cycle_detection_initialize(&cycle_detection, node); + while (node) + { + if (_object_is_defunct(table, node)) return NULL; + + // always accept proxy object from different world + if (!force_next && CALL(object_is_proxy, node)) return node; + + vector children = vector_init(); + CALL(get_children, node, &children); + + // do accept: + // 1. not start node + // 2. parent after all children in backward traversing + // 3. Nodes with roles: ATSPI_ROLE_PAGE_TAB, ATSPI_ROLE_POPUP_MENU and ATSPI_ROLE_DIALOG, only when looking for first or last element. + // Objects with those roles shouldnt be reachable, when navigating next / prev. + unsigned char all_children_visited_or_moving_forward = (vector_size(&children) == 0 || forward || all_children_visited); + if (!force_next && node != start && all_children_visited_or_moving_forward && _accept_object(table, node)) + { + if (start == NULL || _object_role_is_acceptable_when_navigating_next_prev(table, node)) + { + vector_free(&children); + return node; + } + } + + void *next_related_in_direction = !force_next ? _get_object_in_relation_flow(table, node, forward) : NULL; + + if (next_related_in_direction && _object_is_defunct(table, next_related_in_direction)) + next_related_in_direction = NULL; + unsigned char want_cycle_detection = 0; + if (next_related_in_direction) + { + node = next_related_in_direction; + want_cycle_detection = 1; + } + else { + void *child = !force_next && !all_children_visited ? + _directional_depth_first_search_try_non_defunct_child(table, node, &children, forward) : NULL; + if (child != NULL) want_cycle_detection = 1; + else + { + if (!force_next && node == root) + { + vector_free(&children); + return NULL; + } + all_children_visited = 1; + child = _directional_depth_first_search_try_non_defunct_sibling(table, &all_children_visited, node, root, forward); + } + node = child; + } + + force_next = 0; + if (want_cycle_detection && cycle_detection_check_if_in_cycle(&cycle_detection, node)) + { + vector_free(&children); + return NULL; + } + vector_free(&children); + } + return NULL; +} + + + + +static AtspiRelationType spi_relation_type_from_atk_relation_type (AtkRelationType type); +#define MARK_AS_UNUSED(v) do { (void)(v); } while(0) + +static AtspiRole _object_get_role_impl(accessibility_navigation_pointer_table *table, void *ptr) +{ + MARK_AS_UNUSED(table); + AtkObject *obj = (AtkObject*)ptr; + AtkRole role = atk_object_get_role (obj); + AtspiRole rv = spi_accessible_role_from_atk_role (role); + return rv; +} + +static uint64_t _object_get_state_set_impl(accessibility_navigation_pointer_table *table, void *ptr) +{ + MARK_AS_UNUSED(table); + dbus_uint32_t array[2]; + spi_atk_state_to_dbus_array((AtkObject*)ptr, array); + uint64_t res = array[0] | ((uint64_t)array[1] << 32); + return res; +} + +static void *_get_object_in_relation_by_type_impl(accessibility_navigation_pointer_table *table, void *ptr, AtspiRelationType expected_relation_type) +{ + MARK_AS_UNUSED(table); + if (ptr) { + g_return_val_if_fail (ATK_IS_OBJECT (ptr), NULL); + AtkRelationSet *set = atk_object_ref_relation_set (ptr); + if (!set) + return NULL; + gint count = atk_relation_set_get_n_relations (set), i; + for (i = 0; i < count; i++) + { + AtkRelation *r = atk_relation_set_get_relation (set, i); + if (!r) + continue; + AtkRelationType rt = atk_relation_get_relation_type (r); + AtspiRelationType type = spi_relation_type_from_atk_relation_type (rt); + if (expected_relation_type == type) + { + GPtrArray *target = atk_relation_get_target (r); + if (target && target->len > 0) + return target->pdata[0]; + } + } + g_object_unref (set); + } + return NULL; +} + +static unsigned char _object_is_zero_size_impl(accessibility_navigation_pointer_table *table, void *ptr) +{ + MARK_AS_UNUSED(table); + AtkObject *obj = (AtkObject*)ptr; + g_return_val_if_fail(ATK_IS_COMPONENT (obj), 0); + gint x, y, w, h; + atk_component_get_extents (ATK_COMPONENT(obj), &x, &y, &w, &h, ATSPI_COORD_TYPE_SCREEN); + return w == 0 || h == 0; +} + +unsigned char _object_is_scrollable_impl(accessibility_navigation_pointer_table *table, void *ptr) +{ + AtspiRole role = _object_get_role_impl(table, ptr); + switch (role) { + case ATSPI_ROLE_SCROLL_PANE: //scroller + case ATSPI_ROLE_LIST: //genlist, list + case ATSPI_ROLE_TREE_TABLE: //gengrid + case ATSPI_ROLE_TOOL_BAR: //toolbar + return 1; + default: + break; + } + return 0; +} + +void *_get_parent_impl(accessibility_navigation_pointer_table *table, void *ptr) +{ + MARK_AS_UNUSED(table); + return atk_object_get_parent((AtkObject*)ptr); +} + +void *_get_object_at_point_impl(accessibility_navigation_pointer_table *table, void *ptr, int x, int y, unsigned char coordinates_are_screen_based) +{ + MARK_AS_UNUSED(table); + AtkObject *obj = (AtkObject*)ptr; + g_return_val_if_fail(ATK_IS_COMPONENT (obj), 0); + return atk_component_ref_accessible_at_point (ATK_COMPONENT(obj), x, y, + coordinates_are_screen_based ? ATSPI_COORD_TYPE_SCREEN : ATSPI_COORD_TYPE_WINDOW); +} + +unsigned char _object_contains_impl(accessibility_navigation_pointer_table *table, void *ptr, int x, int y, unsigned char coordinates_are_screen_based) +{ + MARK_AS_UNUSED(table); + AtkObject *obj = (AtkObject*)ptr; + g_return_val_if_fail(ATK_IS_COMPONENT (obj), 0); + + return atk_component_contains (ATK_COMPONENT(obj), x, y, + coordinates_are_screen_based ? ATSPI_COORD_TYPE_SCREEN : ATSPI_COORD_TYPE_WINDOW); +} + +unsigned char _object_is_proxy_impl(accessibility_navigation_pointer_table *table, void *ptr) +{ + MARK_AS_UNUSED(table); + return 0; +} + +void _get_children_impl(accessibility_navigation_pointer_table *table, void *ptr, vector *v) +{ + MARK_AS_UNUSED(table); + AtkObject *obj = (AtkObject*)ptr; + gint count = atk_object_get_n_accessible_children (obj); + vector_resize(v, (unsigned int)count); + + gint i, index = 0; + for (i = 0; i < count; i++) { + AtkObject *child = atk_object_ref_accessible_child (obj, i); + if (child) { + vector_set(v, index, child); + ++index; + g_object_unref (child); + } + } + vector_resize(v, index); +} + + + + + accessibility_navigation_pointer_table construct_accessibility_navigation_pointer_table(void) { accessibility_navigation_pointer_table table; @@ -307,12 +600,16 @@ accessibility_navigation_pointer_table construct_accessibility_navigation_pointe INIT(object_is_zero_size); INIT(get_parent); INIT(object_is_scrollable); - INIT(object_at_point_get); + INIT(get_object_at_point); INIT(object_contains); INIT(object_is_proxy); + INIT(get_children); #undef INIT return table; } + + + static AtkObject *_calculate_navigable_accessible_at_point(AtkObject *root, unsigned char coord_type, int x, int y) { accessibility_navigation_pointer_table table = construct_accessibility_navigation_pointer_table(); @@ -320,6 +617,35 @@ static AtkObject *_calculate_navigable_accessible_at_point(AtkObject *root, unsi return result; } +static AtkObject *_calculate_neighbor(AtkObject *root, AtkObject *start, unsigned char forward, GetNeighborSearchMode search_mode) +{ + accessibility_navigation_pointer_table table = construct_accessibility_navigation_pointer_table(); + AtkObject *result = (AtkObject*)_calculate_neighbor_impl(&table, root, start, forward ? 1 : 0, search_mode); + return result; +} + +static DBusMessage * +impl_GetNeighbor (DBusConnection * bus, DBusMessage * message, void *user_data) +{ + AtkObject *start = (AtkObject *) user_data; + dbus_uint32_t direction, search_mode; + const char *root_path = NULL; + DBusMessage *reply; + AtkObject *child; + + if (!dbus_message_get_args + (message, NULL, DBUS_TYPE_STRING, &root_path, DBUS_TYPE_INT32, &direction, DBUS_TYPE_INT32, &search_mode, DBUS_TYPE_INVALID)) + { + return droute_invalid_arguments_error (message); + } + + AtkObject *root_object = (AtkObject*)spi_global_register_path_to_object(root_path); + child = _calculate_neighbor (root_object, start, direction == 1, search_mode); + reply = spi_object_return_reference_and_recurse_flag (message, child, 0); + + return reply; +} + static DBusMessage * impl_GetNavigableAtPoint (DBusConnection * bus, DBusMessage * message, void *user_data) @@ -330,21 +656,14 @@ impl_GetNavigableAtPoint (DBusConnection * bus, DBusMessage * message, DBusMessage *reply; AtkObject *child; - g_return_val_if_fail (ATK_IS_COMPONENT (object), - droute_not_yet_handled_error (message)); - if (!dbus_message_get_args (message, NULL, DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32, &y, DBUS_TYPE_UINT32, &coord_type, DBUS_TYPE_INVALID)) { return droute_invalid_arguments_error (message); } - child = (AtkObject*) - _calculate_navigable_accessible_at_point (object, coord_type == ATSPI_COORD_TYPE_SCREEN, x, y); - + child = _calculate_navigable_accessible_at_point (object, coord_type == ATSPI_COORD_TYPE_SCREEN, x, y); reply = spi_object_return_reference_and_recurse_flag (message, child, 0); - if (child) - g_object_unref (child); return reply; } @@ -843,6 +1162,7 @@ impl_GetInterfaces (DBusConnection * bus, static DRouteMethod methods[] = { // TIZEN_ONLY(20170310) - implementation of get object under coordinates for accessibility {impl_GetNavigableAtPoint, "GetNavigableAtPoint"}, + {impl_GetNeighbor, "GetNeighbor"}, // {impl_GetChildAtIndex, "GetChildAtIndex"}, {impl_GetChildren, "GetChildren"}, diff --git a/atk-adaptor/bridge.c b/atk-adaptor/bridge.c index c40ef38..d39a8e9 100644 --- a/atk-adaptor/bridge.c +++ b/atk-adaptor/bridge.c @@ -429,7 +429,7 @@ register_application (SpiBridge * app) dbus_message_iter_init_append (message, &iter); spi_object_append_reference (&iter, app->root); - + if (!dbus_connection_send_with_reply (app->bus, message, &pending, -1) || !pending) { @@ -753,7 +753,6 @@ remove_events (const char *bus_name, const char *event) g_strfreev (evdata->data); g_free (evdata->bus_name); g_slist_free_full (evdata->properties, free_property_definition); - g_free (evdata); if (list->prev) { GList *next = list->next; @@ -765,6 +764,7 @@ remove_events (const char *bus_name, const char *event) spi_global_app_data->events = g_list_remove (events, evdata); list = spi_global_app_data->events; } + g_free (evdata); } else { @@ -1047,7 +1047,7 @@ atk_bridge_adaptor_init (gint * argc, gchar ** argv[]) /* Hook our plug-and socket functions */ install_plug_hooks (); - /* + /* * Create the leasing, register and cache objects. * The order is important here, the cache depends on the * register object. diff --git a/droute/droute.c b/droute/droute.c index 838aacd..fa6d353 100644 --- a/droute/droute.c +++ b/droute/droute.c @@ -353,7 +353,7 @@ impl_prop_GetSet (DBusMessage *message, if (get && prop_funcs->get) { - + DBusMessageIter iter; _DROUTE_DEBUG ("DRoute (handle prop Get): %s|%s on %s\n", pair.one, pair.two, pathstr); @@ -602,7 +602,7 @@ handle_message (DBusConnection *bus, DBusMessage *message, void *user_data) if (result == DBUS_HANDLER_RESULT_NOT_YET_HANDLED) g_print ("DRoute | Unhandled message: %s|%s of type %d on %s\n", member, iface, type, pathstr); #endif - + return result; } -- 2.7.4