#include "introspection.h"
#include <string.h>
#include <stdint.h>
-
-
-
-
-
-
-
-
-
-
-
-
+#include <stdlib.h>
// 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:
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);
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;
}
{
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)
{
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;
}
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;
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();
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)
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;
}
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"},