It is possilbe to get a target object as a return value of get_object_at_point.
In this case _elm_widget_elm_interface_atspi_component_accessible_at_point_get
works again with the target which is same with root object.
[Enhanced]
- We do not have to go parent if the bottom up logic meets root object.
- Visiblity of panel is always true. So we are checking its SHOWING state.
If the panel is not SHOWING, remove it from valid children list.
Change-Id: I2edeefdc9a0c5955f1c28926321b74424c71bc40
+/* The target cannot be a parent of root */
+static Eina_Bool _target_validation_check(Eo *target, Eo *root)
+{
+ Eo *parent;
+ eo_do(root, parent = elm_interface_atspi_accessible_parent_get());
+
+ while (parent)
+ {
+ if (parent == target) return EINA_FALSE;
+ eo_do(parent, parent = elm_interface_atspi_accessible_parent_get());
+ }
+
+ 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;
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;
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;
// always return proxy, so atspi lib can call on it again
if (CALL(object_is_proxy, target)) return target;
-_is_acceptable_leaf(Eo *obj)
+_acceptable_child_is(Eo *obj)
{
Elm_Atspi_Role role;
Eina_List *children;
{
Elm_Atspi_Role role;
Eina_List *children;
+ Elm_Atspi_State_Set ss;
eo_do(obj, role = elm_interface_atspi_accessible_role_get());
switch (role)
{
case ELM_ATSPI_ROLE_IMAGE:
case ELM_ATSPI_ROLE_ICON:
eo_do(obj, role = elm_interface_atspi_accessible_role_get());
switch (role)
{
case ELM_ATSPI_ROLE_IMAGE:
case ELM_ATSPI_ROLE_ICON:
+ /* remove unacceptable leaf node */
eo_do(obj, children = elm_interface_atspi_accessible_children_get());
if (!children) return EINA_FALSE;
break;
eo_do(obj, children = elm_interface_atspi_accessible_children_get());
if (!children) return EINA_FALSE;
break;
+ case ELM_ATSPI_ROLE_PANEL:
+ /* remove closed panel fron children list */
+ eo_do(obj, ss = elm_interface_atspi_accessible_state_set_get());
+ if (!STATE_TYPE_GET(ss, ELM_ATSPI_STATE_SHOWING)) return EINA_FALSE;
+ break;
+
EINA_LIST_FOREACH(children, l2, child)
{
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);
}
valid_children = eina_list_append(valid_children, child);
}
Evas_Object *smart_parent = stack_item;
while (smart_parent)
{
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;
Evas_Object *ao = elm_access_object_get(smart_parent);
if (ao) return ao;