From b2437c03390423347f1c386a817765dc20978081 Mon Sep 17 00:00:00 2001 From: Marcel Hollerbach Date: Wed, 2 May 2018 18:24:14 +0200 Subject: [PATCH] efl_ui_focus_graph: add a new way for calculating relations this fixes the testsuite, and brings better relations back. --- src/lib/elementary/efl_ui_focus_graph.c | 139 +++++++++++++++++++----- src/lib/elementary/efl_ui_focus_graph.h | 1 + 2 files changed, 113 insertions(+), 27 deletions(-) diff --git a/src/lib/elementary/efl_ui_focus_graph.c b/src/lib/elementary/efl_ui_focus_graph.c index b7d365e98a..7604c7b18f 100644 --- a/src/lib/elementary/efl_ui_focus_graph.c +++ b/src/lib/elementary/efl_ui_focus_graph.c @@ -8,6 +8,12 @@ #include "elm_priv.h" #include "efl_ui_focus_graph.h" +typedef enum { + Q_TOP = 1, Q_RIGHT = 2, Q_LEFT = 4, Q_BOTTOM = 8, Q_LAST = 16 +} Quadrant; + +Quadrant q_helper[] = {Q_TOP, Q_RIGHT, Q_LEFT, Q_BOTTOM}; + static inline Efl_Ui_Focus_Object* _convert(Efl_Ui_Focus_Graph_Context *ctx, Opaque_Graph_Member *member) { @@ -28,64 +34,143 @@ _minus(Eina_Position2D r1, Eina_Position2D r2) } static inline unsigned int -_order(Eina_Position2D pos) +_distance(Eina_Rect o, Eina_Rect r2, Quadrant q) { - return pow(pos.x, 2) + pow(pos.y, 2); + int res = INT_MAX; + if (q == Q_TOP) + res = o.y - eina_rectangle_max_y(&r2.rect); + else if (q == Q_LEFT) + res = o.x - eina_rectangle_max_x(&r2.rect); + else if (q == Q_BOTTOM) + res = r2.y - eina_rectangle_max_y(&o.rect); + else if (q == Q_RIGHT) + res = r2.x - eina_rectangle_max_x(&o.rect); + + return res; } static inline Efl_Ui_Focus_Graph_Calc_Direction_Result* -_quadrant_get(Eina_Position2D pos, Efl_Ui_Focus_Graph_Calc_Result *result) +_result_get(Quadrant q, Efl_Ui_Focus_Graph_Calc_Result *result) { - if (pos.y > abs(pos.x)) return &result->top; - else if (pos.x >= abs(pos.y)) return &result->left; - else if (pos.y < -abs(pos.x)) return &result->bottom; - else if (pos.y >= -abs(pos.x)) return &result->right; + if (q == Q_TOP) return &result->top; + else if (q == Q_LEFT) return &result->left; + else if (q == Q_BOTTOM) return &result->bottom; + else if (q == Q_RIGHT) return &result->right; else return NULL; } -typedef struct { - unsigned int distance; -} Direction_Calc_Result; +static inline void +_quadrant_get(Eina_Rect origin, Eina_Rect elem, Quadrant *all, Quadrant *clean) +{ + int dis = 0; + + *clean = 0; + *all = 0; + + if (eina_rectangle_max_y(&elem.rect) <= origin.y) + { + dis = origin.y - elem.y; + + if (eina_spans_intersect(origin.x - dis, 2*dis + origin.w, elem.x, elem.w)) + *all |= Q_TOP; + if (eina_spans_intersect(origin.x, origin.w, elem.x, elem.w)) + *clean |= Q_TOP; + } + if (elem.y >= eina_rectangle_max_y(&origin.rect)) + { + dis = eina_rectangle_max_y(&elem.rect) - origin.y; + + if (eina_spans_intersect(origin.x - dis, 2*dis + origin.w, elem.x, elem.w)) + *all |= Q_BOTTOM; + if (eina_spans_intersect(origin.x, origin.w, elem.x, elem.w)) + *clean |= Q_BOTTOM; + } + if (elem.x >= eina_rectangle_max_x(&origin.rect)) + { + dis = eina_rectangle_max_x(&elem.rect) - origin.x; + + if (eina_spans_intersect(origin.y - dis, 2*dis + origin.h, elem.y, elem.h)) + *all |= Q_RIGHT; + if (eina_spans_intersect(origin.y, origin.h, elem.y, elem.h)) + *clean |= Q_RIGHT; + } + if (eina_rectangle_max_x(&elem.rect) <= origin.x) + { + dis = origin.x - elem.x; + + if (eina_spans_intersect(origin.y - dis, 2*dis + origin.h, elem.y, elem.h)) + *all |= Q_LEFT; + if (eina_spans_intersect(origin.y, origin.h, elem.y, elem.h)) + *clean |= Q_LEFT; + } + +} void efl_ui_focus_graph_calc(Efl_Ui_Focus_Graph_Context *ctx, Eina_Iterator *nodes, Opaque_Graph_Member *origin_obj, Efl_Ui_Focus_Graph_Calc_Result *result) { Opaque_Graph_Member *elem_obj; - Eina_Position2D origin_pos, elem_pos, relative_pos; Eina_Rect origin, elem; - memset(result, 0, sizeof(Efl_Ui_Focus_Graph_Calc_Result)); + for (int i = 0; i < 4; ++i) + { + Efl_Ui_Focus_Graph_Calc_Direction_Result *res; + + res = _result_get(q_helper[i], result); + + res->clean = EINA_FALSE; + res->distance = INT_MAX; + res->relation = NULL; + } origin = efl_ui_focus_object_focus_geometry_get(_convert(ctx, origin_obj)); - origin_pos = _middle(origin); + + //printf("=========> CALCING %p %s\n", _convert(ctx, origin_obj), elm_object_text_get(_convert(ctx, origin_obj))); EINA_ITERATOR_FOREACH(nodes, elem_obj) { Efl_Ui_Focus_Graph_Calc_Direction_Result *res; unsigned int distance; + Quadrant all; + Quadrant clean; if (elem_obj == origin_obj) continue; elem = efl_ui_focus_object_focus_geometry_get(_convert(ctx, elem_obj)); - elem_pos = _middle(elem); - relative_pos = _minus(elem_pos, origin_pos); - distance = _order(relative_pos); - res = _quadrant_get(relative_pos, result); - EINA_SAFETY_ON_NULL_GOTO(res, cont); - if (res->distance > distance || res->distance == 0) + if (eina_rectangle_intersection(&origin.rect, &elem.rect)) continue; + + _quadrant_get(origin, elem, &all, &clean); + + for (int i = 0; i < 4; ++i) { - res->relation = eina_list_free(res->relation); - res->relation = eina_list_append(res->relation, elem_obj); - res->distance = distance; - } - else if (res->distance == distance) - { - res->relation = eina_list_append(res->relation, elem_obj); + if (q_helper[i] & all) + { + res = _result_get(q_helper[i], result); + EINA_SAFETY_ON_NULL_GOTO(res, cont); + + distance = _distance(origin, elem, q_helper[i]); + + + if ((res->distance > distance && res->clean == (q_helper[i] & clean)) || + (!res->clean && q_helper[i] & clean)) + { + res->relation = eina_list_free(res->relation); + res->relation = eina_list_append(res->relation, elem_obj); + res->distance = distance; + res->clean = q_helper[i] & clean; + //printf("=========> %p BETTER_NOW %d \t %p %s\n", res, distance, origin_obj, elm_object_text_get(_convert(ctx, elem_obj))); + } + else if (res->distance == distance) + { + res->relation = eina_list_append(res->relation, elem_obj); + //printf("=========> %p BETTER_NOW_ADD %d \t %p %s\n", res, distance, origin_obj, elm_object_text_get(_convert(ctx, elem_obj))); + } + } } + continue; cont: - printf("%d - %d\n", relative_pos.x, relative_pos.y); continue; } } diff --git a/src/lib/elementary/efl_ui_focus_graph.h b/src/lib/elementary/efl_ui_focus_graph.h index 2910e66fbd..84a48b810c 100644 --- a/src/lib/elementary/efl_ui_focus_graph.h +++ b/src/lib/elementary/efl_ui_focus_graph.h @@ -10,6 +10,7 @@ typedef struct _Opaque_Graph_Memeber Opaque_Graph_Member; typedef struct { Eina_List *relation; + Eina_Bool clean; unsigned int distance; } Efl_Ui_Focus_Graph_Calc_Direction_Result;