Compare commits

...

4 Commits

Author SHA1 Message Date
Marcel Hollerbach 1dde64922c chaos 2019-08-07 17:26:41 +02:00
Marcel Hollerbach 0ffc51aee0 efl_ui_focus_manager_calc: optimize item deletion
if there is high frequency adding and deleting of items, the deletion
here can be quite heavy, this makes freeing a little bit faster.
2019-08-07 17:20:38 +02:00
Marcel Hollerbach 8a8bdd406a efl_ui_focus_layer: we should cleanup on invalidate
otherwise there will be errors. Lets pray this did not break anything
else.

Differential Revision: https://phab.enlightenment.org/D9521
2019-08-07 15:57:08 +02:00
Marcel Hollerbach f47fdfc072 efl_ui_selectable: add spec test suite for this
this brings a spec test suite for Efl.Ui.Selectable

Differential Revision: https://phab.enlightenment.org/D9518
2019-08-07 15:02:16 +02:00
9 changed files with 130 additions and 40 deletions

View File

@ -76,7 +76,7 @@ efl_main(void *data EINA_UNUSED, const Efl_Event *ev EINA_UNUSED)
efl_ui_collection_position_manager_set(efl_added, list));
efl_content_set(win, item_container);
printf("Building 5000 objects\n");
printf("Building 5000 objects %d\n", getpid());
for (int i = 0; i < 5000; ++i)
{
Eo *il = efl_add(EFL_UI_LIST_DEFAULT_ITEM_CLASS, item_container);

View File

@ -55,10 +55,10 @@ _efl_ui_focus_layer_efl_ui_focus_manager_move(Eo *obj, Efl_Ui_Focus_Layer_Data *
}
EOLIAN static void
_efl_ui_focus_layer_efl_object_destructor(Eo *obj, Efl_Ui_Focus_Layer_Data *pd EINA_UNUSED)
_efl_ui_focus_layer_efl_object_invalidate(Eo *obj, Efl_Ui_Focus_Layer_Data *pd EINA_UNUSED)
{
efl_ui_focus_layer_enable_set(obj, EINA_FALSE);
efl_destructor(efl_super(obj, MY_CLASS));
efl_invalidate(efl_super(obj, MY_CLASS));
}
EOLIAN static Efl_Ui_Focus_Manager*

View File

@ -28,6 +28,6 @@ mixin @beta Efl.Ui.Focus.Layer requires Efl.Ui.Widget extends Efl.Ui.Widget_Focu
Efl.Ui.Focus.Object.focus_manager { get; }
Efl.Ui.Focus.Object.focus_parent { get; }
Efl.Object.constructor;
Efl.Object.destructor;
Efl.Object.invalidate;
}
}

View File

@ -68,6 +68,7 @@ struct _Node{
} graph;
Eina_Bool on_list : 1;
Eina_Bool unused : 1;
};
#define T(n) (n->tree)
@ -237,42 +238,49 @@ node_item_free(Node *item)
/*cleanup graph parts*/
//add all neighbors of the node to the dirty list
for(int i = EFL_UI_FOCUS_DIRECTION_UP; i < EFL_UI_FOCUS_DIRECTION_LAST; i++)
if (!item->unused)
{
Node *partner;
for(int i = EFL_UI_FOCUS_DIRECTION_UP; i < EFL_UI_FOCUS_DIRECTION_LAST; i++)
{
Node *partner;
#define MAKE_LIST_DIRTY(node, field) \
EINA_LIST_FOREACH(DIRECTION_ACCESS(node, i).field, l, partner) \
{ \
if (partner->type != NODE_TYPE_ONLY_LOGICAL) \
EINA_LIST_FOREACH(DIRECTION_ACCESS(node, i).field, l, partner) \
{ \
dirty_add(obj, pd, partner); \
dirty_added = EINA_TRUE; \
} \
if (partner->type != NODE_TYPE_ONLY_LOGICAL) \
{ \
dirty_add(obj, pd, partner); \
dirty_added = EINA_TRUE; \
} \
}
MAKE_LIST_DIRTY(item, one_direction)
MAKE_LIST_DIRTY(item, cleanup_nodes)
border_onedirection_cleanup(item, i);
border_onedirection_set(item, i, NULL);
}
MAKE_LIST_DIRTY(item, one_direction)
MAKE_LIST_DIRTY(item, cleanup_nodes)
border_onedirection_cleanup(item, i);
border_onedirection_set(item, i, NULL);
}
//the unregistering of a item should ever result in atleast a coords_dirty call
if (!dirty_added)
if (dirty_added)
efl_event_callback_call(obj, EFL_UI_FOCUS_MANAGER_EVENT_COORDS_DIRTY, NULL);
/*cleanup manager householdings*/
//remove from the focus stack
pd->focus_stack = eina_list_remove(pd->focus_stack, item);
if (!item->unused)
pd->focus_stack = eina_list_remove(pd->focus_stack, item);
//if this is the entry for redirect, NULL them out!
if (pd->redirect_entry == item->focusable)
pd->redirect_entry = NULL;
//remove from the dirty parts
pd->dirty = eina_list_remove(pd->dirty, item);
if (item->on_list)
pd->dirty = eina_list_remove(pd->dirty, item);
item->on_list = EINA_FALSE;
/*merge tree items*/
@ -375,7 +383,7 @@ dirty_flush_node(Efl_Ui_Focus_Manager *obj EINA_UNUSED, Efl_Ui_Focus_Manager_Cal
Efl_Ui_Focus_Graph_Calc_Result result;
efl_ui_focus_graph_calc(&pd->graph_ctx, eina_iterator_filter_new(eina_hash_iterator_data_new(pd->node_hash), _no_logical, NULL, NULL) , (Opaque_Graph_Member*) node, &result);
node->unused = EINA_FALSE;
for (int i = 0; i < 4; ++i)
{
Efl_Ui_Focus_Direction direction = -1;
@ -506,7 +514,7 @@ _register(Eo *obj, Efl_Ui_Focus_Manager_Calc_Data *pd, Efl_Ui_Focus_Object *chil
node = node_new(child, obj);
eina_hash_add(pd->node_hash, &child, node);
node->unused = EINA_TRUE;
//add the parent
if (parent)
{
@ -1460,6 +1468,7 @@ _efl_ui_focus_manager_calc_efl_ui_focus_manager_manager_focus_set(Eo *obj, Efl_U
node = node_get(obj, pd, focus);
if (!node) return;
node->unused = EINA_FALSE;
if (node->type == NODE_TYPE_ONLY_LOGICAL && !node->redirect_manager)
{
Node *target = NULL;

View File

@ -184,7 +184,6 @@ _elm_scrollable_is(const Evas_Object *obj)
static void
_on_sub_obj_del(void *data, const Efl_Event *event);
static void _propagate_event(void *data, const Efl_Event *eo_event);
static void _elm_widget_focus_tree_unfocusable_handle(Eo *obj);
static void _elm_widget_shadow_update(Efl_Ui_Widget *obj);
EFL_CALLBACKS_ARRAY_DEFINE(elm_widget_subitems_callbacks,
@ -273,7 +272,10 @@ _candidacy_exam(Eo *obj)
Elm_Widget_Smart_Data *wid_pd;
wid_pd = efl_data_scope_get(wid, MY_CLASS);
do {
if (wid_pd->disabled > 0) return EINA_TRUE;
if (wid_pd->tree_unfocusable > 0) return EINA_TRUE;
/* do {
if (wid_pd->disabled) return EINA_TRUE;
if (wid_pd->tree_unfocusable) return EINA_TRUE;
@ -293,9 +295,9 @@ _candidacy_exam(Eo *obj)
}
}
} while (1);
} while (1);*/
return !efl_isa(top, EFL_UI_WIN_CLASS);
return EINA_FALSE;
}
static void _full_eval(Eo *obj, Elm_Widget_Smart_Data *pd);
@ -1675,6 +1677,15 @@ elm_widget_child_can_focus_get(const Eo *obj)
return sd->logical.child_count > 0;
}
static int
_tree_unfocusable_counter_get(Eo *widget)
{
ELM_WIDGET_DATA_GET_OR_RETURN(widget, pd, -1);
return pd->tree_unfocusable;
}
/**
* @internal
*
@ -1693,16 +1704,33 @@ elm_widget_child_can_focus_get(const Eo *obj)
EAPI void
elm_widget_tree_unfocusable_set(Eo *obj, Eina_Bool tree_unfocusable)
{
Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
if (!sd) return;
Efl_Ui_Widget *subs;
Eina_List *n;
Elm_Widget_Smart_Data *pd = efl_data_scope_safe_get(obj, MY_CLASS);
if (!pd) return;
int distance, parent_counter = (pd->parent_obj ? _tree_unfocusable_counter_get(pd->parent_obj) : 0);
tree_unfocusable = !!tree_unfocusable;
if (sd->tree_unfocusable == tree_unfocusable) return;
sd->tree_unfocusable = tree_unfocusable;
_elm_widget_focus_tree_unfocusable_handle(obj);
if (tree_unfocusable)
pd->tree_unfocusable ++;
else
pd->tree_unfocusable --;
distance = pd->disabled - parent_counter;
if ((distance < 0) || (distance > 1))
{
distance = MAX(MIN(tree_unfocusable, 1), 0);
pd->disabled = parent_counter + distance;
}
EINA_LIST_FOREACH(pd->subobjs, n, subs)
{
if (efl_isa(subs, EFL_UI_WIDGET_CLASS))
efl_ui_widget_disabled_set(subs, elm_widget_tree_unfocusable_get(obj));
}
//focus state eval on all children
_elm_widget_full_eval_children(obj, sd);
_elm_widget_full_eval_children(obj, pd);
}
/**
@ -2910,12 +2938,6 @@ elm_widget_focus_mouse_up_handle(Eo *obj)
}
}
static void
_elm_widget_focus_tree_unfocusable_handle(Eo *obj EINA_UNUSED)
{
//FIXME
}
/*
* @internal
*

View File

@ -355,6 +355,7 @@ typedef struct _Elm_Widget_Smart_Data
int child_drag_x_locked;
int child_drag_y_locked;
int disabled;
int tree_unfocusable;
Eina_Inlist *translate_strings;
Eina_List *focus_chain;
@ -397,7 +398,6 @@ typedef struct _Elm_Widget_Smart_Data
Eina_Bool can_focus : 1;
Eina_Bool focused : 1;
Eina_Bool top_win_focused : 1;
Eina_Bool tree_unfocusable : 1;
Eina_Bool focus_move_policy_auto_mode : 1; /* This is TRUE by default */
Eina_Bool highlight_ignore : 1;
Eina_Bool highlight_in_theme : 1;

View File

@ -0,0 +1,57 @@
#ifdef HAVE_CONFIG_H
# include "elementary_config.h"
#endif
#include <Efl_Ui.h>
#include "efl_ui_spec_suite.h"
#include "suite_helpers.h"
/* spec-meta-start
{"test-interface":"Efl.Ui.Selectable",
"test-widgets": ["Efl.Ui.Item.Realized", "Efl.Ui.Check"]}
spec-meta-end */
static void
_callback_assert_called_once(void *data, const Efl_Event *ev EINA_UNUSED)
{
int *callback_called = data;
ck_assert_int_eq(*callback_called, 0);
*callback_called = *callback_called + 1;
}
EFL_START_TEST(selectable_events)
{
int callback_called = 0;
efl_event_callback_add(widget, EFL_UI_EVENT_SELECTED_CHANGED, _callback_assert_called_once, &callback_called);
efl_ui_selectable_selected_set(widget, EINA_TRUE);
ck_assert_int_eq(efl_ui_selectable_selected_get(widget), EINA_TRUE);
ck_assert_int_eq(callback_called, 1);
callback_called = 0;
efl_ui_selectable_selected_set(widget, EINA_FALSE);
ck_assert_int_eq(efl_ui_selectable_selected_get(widget), EINA_FALSE);
ck_assert_int_eq(callback_called, 1);
callback_called = 0;
efl_ui_selectable_selected_set(widget, EINA_TRUE);
callback_called = 0;
efl_ui_selectable_selected_set(widget, EINA_TRUE);
ck_assert_int_eq(callback_called, 0);
}
EFL_END_TEST
EFL_START_TEST(selectable_set)
{
ck_assert_int_eq(efl_ui_selectable_selected_get(widget), EINA_FALSE);
efl_ui_selectable_selected_set(widget, EINA_TRUE);
ck_assert_int_eq(efl_ui_selectable_selected_get(widget), EINA_TRUE);
efl_ui_selectable_selected_set(widget, EINA_FALSE);
ck_assert_int_eq(efl_ui_selectable_selected_get(widget), EINA_FALSE);
}
EFL_END_TEST
void
efl_ui_selectable_behavior_test(TCase *tc)
{
tcase_add_test(tc, selectable_set);
tcase_add_test(tc, selectable_events);
}

View File

@ -21,6 +21,7 @@ void efl_ui_range_display_interactive_behavior_test(TCase *tc);
void efl_ui_view_behavior_test(TCase *tc);
void efl_ui_single_selectable_behavior_test(TCase *tc);
void efl_ui_multi_selectable_behavior_test(TCase *tc);
void efl_ui_selectable_behavior_test(TCase *tc);
void efl_test_container_content_equal(Efl_Ui_Widget **wid, unsigned int len);
void efl_test_container_expect_evt_content_added(Efl_Ui_Widget *widget, const Efl_Event_Description *ev, Eina_Bool *flag, void *event_data);

View File

@ -10,6 +10,7 @@ efl_ui_suite_behavior_test_files = files([
'efl_test_ui_view.c',
'efl_test_single_selectable.c',
'efl_test_multi_selectable.c',
'efl_test_selectable.c',
])
efl_ui_suite_behavior_src = files([