}
+static inline Eina_Position2D
+_relative_position_rects(Eina_Rect *a, Eina_Rect *b)
+{
+ Eina_Position2D a_pos = {a->rect.x + a->rect.w/2, a->rect.y + a->rect.h/2};
+ Eina_Position2D b_pos = {b->rect.x + b->rect.w/2, b->rect.y + b->rect.h/2};
+
+ return (Eina_Position2D){b_pos.x - a_pos.x, b_pos.y - b_pos.y};
+}
+
+static inline Eina_Rectangle_Outside
+_direction_to_outside(Efl_Ui_Focus_Direction direction)
+{
+ if (direction == EFL_UI_FOCUS_DIRECTION_RIGHT) return EINA_RECTANGLE_OUTSIDE_RIGHT;
+ if (direction == EFL_UI_FOCUS_DIRECTION_LEFT) return EINA_RECTANGLE_OUTSIDE_LEFT;
+ if (direction == EFL_UI_FOCUS_DIRECTION_DOWN) return EINA_RECTANGLE_OUTSIDE_BOTTOM;
+ if (direction == EFL_UI_FOCUS_DIRECTION_UP) return EINA_RECTANGLE_OUTSIDE_TOP;
+
+ return -1;
+}
+
+static inline void
+_calculate_node_stage2(Efl_Ui_Focus_Manager_Calc_Data *pd, Efl_Ui_Focus_Object *node, Eina_Rect rect, Efl_Ui_Focus_Direction direction, Eina_List **lst)
+{
+ Efl_Ui_Focus_Object *op;
+ Eina_Iterator *nodes;
+ int min_distance = 0;
+ Node *n;
+
+ nodes = eina_hash_iterator_data_new(pd->node_hash);
+
+ EINA_ITERATOR_FOREACH(nodes, n)
+ {
+ Eina_Rectangle_Outside outside, outside_dir;
+ Eina_Position2D pos;
+ int distance;
+ Eina_Rect op_rect;
+
+ op = n->focusable;
+
+ if (op == node) continue;
+ if (n->type == NODE_TYPE_ONLY_LOGICAL) continue;
+
+ op_rect = efl_ui_focus_object_focus_geometry_get(op);
+ outside = eina_rectangle_outside_position(&rect.rect, &op_rect.rect);
+ outside_dir = _direction_to_outside(direction);
+ //calculate relative position of the nodes
+ pos = _relative_position_rects(&rect, &op_rect);
+ //calculate distance
+ distance = sqrt(powerof2(pos.x) + powerof2(pos.y));
+
+ if (outside & outside_dir)
+ {
+ if (min_distance == 0 || min_distance > distance)
+ {
+ min_distance = distance;
+ *lst = eina_list_free(*lst);
+ *lst = eina_list_append(*lst, op);
+ }
+ else if (min_distance == distance)
+ {
+ *lst = eina_list_append(*lst, op);
+ }
+ }
+ }
+}
+
static inline void
_calculate_node(Efl_Ui_Focus_Manager_Calc_Data *pd, Efl_Ui_Focus_Object *node, Dimension dim, Eina_List **pos, Eina_List **neg)
{
Eina_Rect rect;
+ Efl_Ui_Focus_Direction direction;
rect = efl_ui_focus_object_focus_geometry_get(node);
*neg = NULL;
_calculate_node_stage1(pd, node, rect, dim, pos, neg);
+
+ if (!*pos)
+ {
+ if (dim == DIMENSION_Y)
+ direction = EFL_UI_FOCUS_DIRECTION_DOWN;
+ else
+ direction = EFL_UI_FOCUS_DIRECTION_RIGHT;
+ _calculate_node_stage2(pd, node, rect, direction, pos);
+ }
+
+ if (!*neg)
+ {
+ if (dim == DIMENSION_Y)
+ direction = EFL_UI_FOCUS_DIRECTION_UP;
+ else
+ direction = EFL_UI_FOCUS_DIRECTION_LEFT;
+
+ _calculate_node_stage2(pd, node, rect, direction, neg);
+ }
}
#ifdef CALC_DEBUG
efl_ui_focus_manager_focus_set(m, obj);
CHECK(middle, east, west, north, south)
- CHECK(east, NULL, middle, NULL, NULL)
- CHECK(west, middle, NULL, NULL, NULL)
- CHECK(north, NULL, NULL, NULL, middle)
- CHECK(south, NULL, NULL, middle, NULL)
+ CHECK(east, NULL, middle, north, south)
+ CHECK(west, middle, NULL, north, south)
+ CHECK(north, east, west, NULL, middle)
+ CHECK(south, east, west, middle, NULL)
efl_del(middle);
efl_del(south);
}
END_TEST
+static Eina_Bool
+_equal_set(Eina_List *elems, Efl_Ui_Focus_Object *lst[])
+{
+ unsigned int i = 0;
+
+ for (i = 0; lst[i]; ++i)
+ {
+ Eina_Bool found = EINA_FALSE;
+ Eina_List *n;
+ Efl_Ui_Focus_Object *elem;
+
+ EINA_LIST_FOREACH(elems, n, elem)
+ {
+ if (lst[i] != elem) continue;
+
+ found = EINA_TRUE;
+ break;
+ }
+
+ if (!found) return EINA_FALSE;
+ }
+
+ if (eina_list_count(elems) != i) return EINA_FALSE;
+ return EINA_TRUE;
+}
+
+START_TEST(pos_check2)
+{
+ Efl_Ui_Focus_Manager *m;
+ Efl_Ui_Focus_Relations *rel;
+ Efl_Ui_Focus_Object *root, *middle, *north_east, *north_west, *south_east, *south_west;
+
+ elm_init(1, NULL);
+
+ middle = elm_focus_test_object_new("middle", 40, 40, 5, 5);
+
+ north_east = elm_focus_test_object_new("north_east", 60, 20, 5, 5);
+ north_west = elm_focus_test_object_new("north_west", 20, 20, 5, 5);
+ south_east = elm_focus_test_object_new("south_east", 60, 60, 5, 5);
+ south_west = elm_focus_test_object_new("south_west", 20, 60, 5, 5);
+
+ m = elm_focus_test_manager_new(&root);
+ efl_ui_focus_manager_calc_register(m, middle, root, NULL);
+ efl_ui_focus_manager_calc_register(m, north_east, root, NULL);
+ efl_ui_focus_manager_calc_register(m, north_west, root, NULL);
+ efl_ui_focus_manager_calc_register(m, south_east, root, NULL);
+ efl_ui_focus_manager_calc_register(m, south_west, root, NULL);
+
+ rel = efl_ui_focus_manager_fetch(m, middle);
+
+#define ck_assert_set_eq(set, ...) \
+ { \
+ Efl_Ui_Focus_Object *tmp[] = { __VA_ARGS__ }; \
+ ck_assert_int_eq(_equal_set(set, tmp), EINA_TRUE); \
+ }
+
+ ck_assert_set_eq(rel->left, north_west, south_west, NULL);
+ ck_assert_set_eq(rel->right, north_east, south_east, NULL);
+ ck_assert_set_eq(rel->top, north_west, north_east, NULL);
+ ck_assert_set_eq(rel->down, south_west, south_east, NULL);
+
+#undef ck_assert_set_eq
+
+ efl_del(middle);
+ efl_del(north_east);
+ efl_del(north_west);
+ efl_del(south_east);
+ efl_del(south_west);
+
+ elm_shutdown();
+}
+END_TEST
START_TEST(redirect)
{
elm_init(1, NULL);
tcase_add_test(tc, focus_register_twice);
tcase_add_test(tc, focus_unregister_twice);
tcase_add_test(tc, pos_check);
+ tcase_add_test(tc, pos_check2);
tcase_add_test(tc, redirect);
tcase_add_test(tc, border_check);
tcase_add_test(tc, finalize_check);