return 1;
}
+/* The target cannot be a parent of root */
+static Eina_Bool _target_validation_check(Eo *target, Eo *root)
+{
+ Eo *parent;
+ parent = efl_access_parent_get(root);
+
+ while (parent)
+ {
+ if (parent == target) return EINA_FALSE;
+ parent = efl_access_parent_get(parent);
+ }
+
+ return EINA_TRUE;
+}
+
static void *_calculate_navigable_accessible_at_point_impl(accessibility_navigation_pointer_table *table,
void *root, int x, int y, unsigned char coordinates_are_screen_based)
{
if (!root) return NULL;
+ void *prev_root = root;
void *return_value = NULL;
while (1)
{
void *target = CALL(get_object_at_point, root, x, y, coordinates_are_screen_based);
if (!target) break;
+ if (target == root || target == prev_root) break;
+ if (!_target_validation_check(target, root)) break;
// always return proxy, so atspi lib can call on it again
if (CALL(object_is_proxy, target)) return target;
}
static Eina_Bool
-_is_acceptable_leaf(Eo *obj)
+_acceptable_child_is(Eo *obj)
{
Efl_Access_Role role;
Eina_List *children;
+ Efl_Access_State_Set ss;
role = efl_access_role_get(obj);
switch (role)
{
case EFL_ACCESS_ROLE_IMAGE:
case EFL_ACCESS_ROLE_ICON:
+ /* remove unacceptable leaf node */
children = efl_access_children_get(obj);
if (!children) return EINA_FALSE;
break;
+ case EFL_ACCESS_ROLE_PANEL:
+ /* remove closed panel fron children list */
+ ss = efl_access_state_set_get(obj);
+ if (!STATE_TYPE_GET(ss, EFL_ACCESS_STATE_SHOWING)) return EINA_FALSE;
+ break;
+
default:
break;
}
EINA_LIST_FOREACH(children, l2, child)
{
- if (_is_inside(child, x, y) && _is_acceptable_leaf(child))
+ if (_is_inside(child, x, y) && _acceptable_child_is(child))
valid_children = eina_list_append(valid_children, child);
}
Evas_Object *smart_parent = stack_item;
while (smart_parent)
{
+ /* If parent equals to obj, it is not necessary to go upper.
+ So the top down logic would be better than NULL return. */
+ if (smart_parent == obj)
+ return _accessible_at_point_top_down_get(obj, _pd, screen_coords, x, y);
+
Evas_Object *ao = elm_access_object_get(smart_parent);
if (ao) return ao;