forked from enlightenment/efl
efl_ui: introduce a focus manager and sub manager object
The Efl.Ui.Focus.Manager abstracts the creation of a localization graph and a logical tree. The localization graph is used to find a object right left up or down of a given object. The logical tree is used to iterate throuw the containers which are used to build a ui. Those managers can be used bound to some layer in the ui, so for example the window is a layer, the content of a scroller is a layer. With those layers, we can make sure that movements of a scroller for example just means that this graph of objects in the scroller needs to be recalculated, and not the complete ui. The advantage of having this to layer bound datastructures is that you can easily debug those graphs, since the complete layer of this managerobject can be calculated completly.
This commit is contained in:
parent
2cd1326c8d
commit
01f46ae205
|
@ -118,6 +118,10 @@ elm_public_eolian_files = \
|
||||||
lib/elementary/efl_config_global.eo \
|
lib/elementary/efl_config_global.eo \
|
||||||
lib/elementary/efl_ui_clock.eo \
|
lib/elementary/efl_ui_clock.eo \
|
||||||
lib/elementary/efl_ui_image_factory.eo \
|
lib/elementary/efl_ui_image_factory.eo \
|
||||||
|
lib/elementary/efl_ui_focus_manager.eo \
|
||||||
|
lib/elementary/efl_ui_focus_manager_sub.eo \
|
||||||
|
lib/elementary/efl_ui_focus_object.eo \
|
||||||
|
lib/elementary/efl_ui_focus_user.eo \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
# Private classes (not exposed or shipped)
|
# Private classes (not exposed or shipped)
|
||||||
|
@ -669,6 +673,9 @@ lib_elementary_libelementary_la_SOURCES = \
|
||||||
lib/elementary/efl_ui_clock.c \
|
lib/elementary/efl_ui_clock.c \
|
||||||
lib/elementary/efl_ui_clock_private.h \
|
lib/elementary/efl_ui_clock_private.h \
|
||||||
lib/elementary/efl_ui_image_factory.c \
|
lib/elementary/efl_ui_image_factory.c \
|
||||||
|
lib/elementary/efl_ui_focus_manager.c \
|
||||||
|
lib/elementary/efl_ui_focus_manager_sub.c \
|
||||||
|
lib/elementary/efl_ui_focus_object.c \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1332,7 +1339,14 @@ tests_elementary_elm_suite_SOURCES = \
|
||||||
tests/elementary/elm_code_test_widget.c \
|
tests/elementary/elm_code_test_widget.c \
|
||||||
tests/elementary/elm_code_test_widget_text.c \
|
tests/elementary/elm_code_test_widget_text.c \
|
||||||
tests/elementary/elm_code_test_widget_selection.c \
|
tests/elementary/elm_code_test_widget_selection.c \
|
||||||
tests/elementary/elm_code_test_widget_undo.c
|
tests/elementary/elm_code_test_widget_undo.c \
|
||||||
|
tests/elementary/elm_test_focus_common.c \
|
||||||
|
tests/elementary/elm_test_focus.c \
|
||||||
|
tests/elementary/elm_test_focus_sub.c
|
||||||
|
|
||||||
|
tests/elementary/tests_elementary_elm_suite-elm_test_focus.$(OBJEXT): tests/elementary/focus_test.eo.c tests/elementary/focus_test.eo.h
|
||||||
|
|
||||||
|
tests/elementary/tests_elementary_elm_suite-elm_test_focus_sub.$(OBJEXT): tests/elementary/focus_test_sub.eo.c tests/elementary/focus_test_sub.eo.h
|
||||||
|
|
||||||
tests_elementary_elm_suite_CPPFLAGS = \
|
tests_elementary_elm_suite_CPPFLAGS = \
|
||||||
-DTESTS_BUILD_DIR=\"${top_builddir}/src/tests/elementary\" \
|
-DTESTS_BUILD_DIR=\"${top_builddir}/src/tests/elementary\" \
|
||||||
|
|
|
@ -136,11 +136,25 @@ typedef struct _Elm_Version
|
||||||
|
|
||||||
EAPI extern Elm_Version *elm_version;
|
EAPI extern Elm_Version *elm_version;
|
||||||
|
|
||||||
|
|
||||||
/* include these first for general used definitions */
|
/* include these first for general used definitions */
|
||||||
#include <elm_gen.h>
|
#include <elm_gen.h>
|
||||||
#include <elm_general.h>
|
#include <elm_general.h>
|
||||||
#include <elm_config.h>
|
#include <elm_config.h>
|
||||||
#include <elm_focus.h>
|
#include <elm_focus.h>
|
||||||
|
|
||||||
|
#ifdef EFL_EO_API_SUPPORT
|
||||||
|
# include "efl_ui_focus_object.eo.h"
|
||||||
|
# include "efl_ui_focus_manager.eo.h"
|
||||||
|
# include "efl_ui_focus_manager_sub.eo.h"
|
||||||
|
# include "efl_ui_focus_user.eo.h"
|
||||||
|
#else
|
||||||
|
# include "efl_ui_focus_object.eo.legacy.h"
|
||||||
|
# include "efl_ui_focus_manager.eo.legacy.h"
|
||||||
|
# include "efl_ui_focus_manager_sub.eo.legacy.h"
|
||||||
|
# include "efl_ui_focus_user.eo.legacy.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <elm_tooltip.h>
|
#include <elm_tooltip.h>
|
||||||
#include <elm_object_item.h>
|
#include <elm_object_item.h>
|
||||||
#include <elm_focus_item.h>
|
#include <elm_focus_item.h>
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,129 @@
|
||||||
|
enum Efl.Ui.Focus.Direction {
|
||||||
|
right = 0,
|
||||||
|
left = 1,
|
||||||
|
down = 2,
|
||||||
|
up = 3,
|
||||||
|
next = 4,
|
||||||
|
prev = 5,
|
||||||
|
last = 6
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Efl.Ui.Focus.Manager (Efl.Object) {
|
||||||
|
methods {
|
||||||
|
move {
|
||||||
|
[[Move the focus into the given direction
|
||||||
|
|
||||||
|
This call flushes all changes.
|
||||||
|
This means all changes between the last flush and now are computed
|
||||||
|
]]
|
||||||
|
params {
|
||||||
|
direction : Efl.Ui.Focus.Direction; [[The direction to move to]]
|
||||||
|
}
|
||||||
|
return : Efl.Ui.Focus.Object; [[The element which is now focused]]
|
||||||
|
}
|
||||||
|
request_move {
|
||||||
|
[[Returns the object which would be the next object to focus in the given direction]]
|
||||||
|
params {
|
||||||
|
direction : Efl.Ui.Focus.Direction;
|
||||||
|
}
|
||||||
|
return : Efl.Ui.Focus.Object;
|
||||||
|
}
|
||||||
|
register {
|
||||||
|
[[Register a new item in the graph.
|
||||||
|
|
||||||
|
The parent has to be none null, it will be used as the parent in the logical tree.
|
||||||
|
The redirect argument will be set as redirect property on that manager, once child gets focused.
|
||||||
|
]]
|
||||||
|
params {
|
||||||
|
child : Efl.Ui.Focus.Object @nonull; [[The object to register]]
|
||||||
|
parent : Efl.Ui.Focus.Object @nonull; [[The parent to use in the logical tree]]
|
||||||
|
redirect : Efl.Ui.Focus.Manager; [[The redirect manager to set once this child is focused can be NULL for no redirect]]
|
||||||
|
}
|
||||||
|
return : bool; [[$true if it was successfull $false if not]]
|
||||||
|
}
|
||||||
|
update_redirect {
|
||||||
|
[[Set a new redirect object for the given child
|
||||||
|
|
||||||
|
Once the child is focused the redirect manager will be set in the redirect property.
|
||||||
|
Set to $null if nothing should happen
|
||||||
|
]]
|
||||||
|
params {
|
||||||
|
child : Efl.Ui.Focus.Object @nonull;
|
||||||
|
redirect : Efl.Ui.Focus.Manager; [[Once $child got focused this element will be set as redirect]]
|
||||||
|
}
|
||||||
|
return : bool;
|
||||||
|
}
|
||||||
|
update_parent {
|
||||||
|
[[Set a new logical parent for the given child]]
|
||||||
|
params {
|
||||||
|
child : Efl.Ui.Focus.Object @nonull; [[The child to update]]
|
||||||
|
parent : Efl.Ui.Focus.Object @nonull; [[The parent which now will be the logical parent of child]]
|
||||||
|
}
|
||||||
|
return : bool;
|
||||||
|
}
|
||||||
|
update_children {
|
||||||
|
[[Give the list of children a different order]]
|
||||||
|
params {
|
||||||
|
parent : Efl.Ui.Focus.Object @nonull; [[the parent to update]]
|
||||||
|
children : list<Efl.Ui.Focus.Object>; [[the list with the new order]]
|
||||||
|
}
|
||||||
|
return : bool;
|
||||||
|
}
|
||||||
|
unregister {
|
||||||
|
[[unregister the given item from the graph]]
|
||||||
|
params {
|
||||||
|
child : Efl.Ui.Focus.Object;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
focus {
|
||||||
|
[[Make the given object the currently focused object in this manager.
|
||||||
|
|
||||||
|
The object has to be part of this manager object.
|
||||||
|
If you want to focus something in the redirect manager, just call the function on the redirect manager]]
|
||||||
|
params {
|
||||||
|
focus : Efl.Ui.Focus.Object @nonull;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@property redirect {
|
||||||
|
[[Add a another manager to serve the move requests.
|
||||||
|
|
||||||
|
If this value is set all move requests are redirected to this manager object.
|
||||||
|
Set it to $null once nothing should be redirected anymore.]]
|
||||||
|
values {
|
||||||
|
redirect : Efl.Ui.Focus.Manager;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@property border_elements {
|
||||||
|
[[The list of elements which are at the border of the graph
|
||||||
|
This means one of the relations right,left or down,up are not set.
|
||||||
|
|
||||||
|
This call flushes all changes. see @Efl.Ui.Focus.Manager.move
|
||||||
|
]]
|
||||||
|
get {
|
||||||
|
}
|
||||||
|
values {
|
||||||
|
border_elements : iterator<Efl.Ui.Focus.Object>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@property root {
|
||||||
|
[[Root node for all logical subtrees.
|
||||||
|
|
||||||
|
This property can only be set once.
|
||||||
|
]]
|
||||||
|
values {
|
||||||
|
root : Efl.Ui.Focus.Object @nonull; [[Will be registered into this manager object]]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
implements {
|
||||||
|
Efl.Object.constructor;
|
||||||
|
Efl.Object.finalize;
|
||||||
|
Efl.Object.provider_find;
|
||||||
|
Efl.Object.destructor;
|
||||||
|
}
|
||||||
|
events {
|
||||||
|
pre,flush; [[Emitted once the graph calculationg will be performed]]
|
||||||
|
coords,dirty; [[Emitted once the graph is dirty, this means there are potential changes in border_elements you want to know about]]
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,188 @@
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "elementary_config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <Elementary.h>
|
||||||
|
#include "elm_priv.h"
|
||||||
|
|
||||||
|
#define MY_CLASS EFL_UI_FOCUS_MANAGER_SUB_CLASS
|
||||||
|
#define MY_DATA(o, p) Efl_Ui_Focus_Manager_Sub_Data *pd = efl_data_scope_get(o, MY_CLASS);
|
||||||
|
typedef struct {
|
||||||
|
Efl_Ui_Focus_Manager *manager;
|
||||||
|
Efl_Ui_Focus_Manager *parent;
|
||||||
|
Eina_Bool self_dirty;
|
||||||
|
Eina_List *current_border;
|
||||||
|
} Efl_Ui_Focus_Manager_Sub_Data;
|
||||||
|
|
||||||
|
static Eina_List*
|
||||||
|
_set_a_without_b(Eina_List *a, Eina_List *b)
|
||||||
|
{
|
||||||
|
Eina_List *a_out = NULL, *node;
|
||||||
|
void *data;
|
||||||
|
|
||||||
|
a_out = eina_list_clone(a);
|
||||||
|
|
||||||
|
EINA_LIST_FOREACH(b, node, data)
|
||||||
|
{
|
||||||
|
a_out = eina_list_remove(a_out, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return a_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_border_flush(Eo *obj, Efl_Ui_Focus_Manager_Sub_Data *pd)
|
||||||
|
{
|
||||||
|
Eina_Iterator *borders;
|
||||||
|
Eina_List *selection, *tmp;
|
||||||
|
Efl_Ui_Focus_Object *node;
|
||||||
|
|
||||||
|
borders = efl_ui_focus_manager_border_elements_get(obj);
|
||||||
|
selection = efl_ui_focus_manager_sub_select_set(obj, borders);
|
||||||
|
|
||||||
|
//elements which are not in the current border elements
|
||||||
|
tmp = eina_list_clone(pd->current_border);
|
||||||
|
tmp = _set_a_without_b(tmp , selection);
|
||||||
|
|
||||||
|
EINA_LIST_FREE(tmp, node)
|
||||||
|
{
|
||||||
|
efl_ui_focus_manager_unregister(pd->manager, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
//set of the elements which are new without those which are currently registered
|
||||||
|
tmp = eina_list_clone(selection);
|
||||||
|
tmp = _set_a_without_b(tmp, pd->current_border);
|
||||||
|
|
||||||
|
EINA_LIST_FREE(tmp, node)
|
||||||
|
{
|
||||||
|
efl_ui_focus_manager_register(pd->manager, node, obj, obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
eina_list_free(pd->current_border);
|
||||||
|
pd->current_border = selection;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_border_unregister(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Manager_Sub_Data *pd)
|
||||||
|
{
|
||||||
|
Efl_Ui_Focus_Object *node;
|
||||||
|
|
||||||
|
EINA_LIST_FREE(pd->current_border, node)
|
||||||
|
{
|
||||||
|
efl_ui_focus_manager_unregister(pd->manager, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
pd->current_border = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_parent_manager_pre_flush(void *data, const Efl_Event *ev EINA_UNUSED)
|
||||||
|
{
|
||||||
|
MY_DATA(data, pd);
|
||||||
|
|
||||||
|
if (!pd->self_dirty) return; //we are not interested
|
||||||
|
|
||||||
|
_border_flush(data, pd);
|
||||||
|
}
|
||||||
|
|
||||||
|
EFL_CALLBACKS_ARRAY_DEFINE(parent_manager,
|
||||||
|
{EFL_UI_FOCUS_MANAGER_EVENT_PRE_FLUSH, _parent_manager_pre_flush}
|
||||||
|
);
|
||||||
|
|
||||||
|
static void
|
||||||
|
_parent_set(Eo *obj, Efl_Ui_Focus_Manager_Sub_Data *pd, Efl_Ui_Focus_Manager *manager)
|
||||||
|
{
|
||||||
|
if (pd->manager)
|
||||||
|
{
|
||||||
|
//remove ourself from the manager
|
||||||
|
efl_ui_focus_manager_unregister(pd->manager, obj);
|
||||||
|
|
||||||
|
|
||||||
|
efl_event_callback_array_del(pd->manager, parent_manager(), obj);
|
||||||
|
_border_unregister(obj, pd);
|
||||||
|
}
|
||||||
|
|
||||||
|
pd->manager = manager;
|
||||||
|
|
||||||
|
if (pd->manager)
|
||||||
|
{
|
||||||
|
//register our own root in the upper manager
|
||||||
|
efl_ui_focus_manager_register(pd->manager, obj, pd->parent, obj);
|
||||||
|
|
||||||
|
//listen to the manager
|
||||||
|
efl_event_callback_array_add(pd->manager, parent_manager(), obj);
|
||||||
|
_border_flush(obj, pd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_self_parent_change(void *data EINA_UNUSED, const Efl_Event *ev)
|
||||||
|
{
|
||||||
|
MY_DATA(ev->object , pd);
|
||||||
|
|
||||||
|
if (pd->manager == ev->info) return;
|
||||||
|
|
||||||
|
_parent_set(ev->object, pd, ev->info);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_self_manager_dirty(void *data EINA_UNUSED, const Efl_Event *ev)
|
||||||
|
{
|
||||||
|
MY_DATA(ev->object , pd);
|
||||||
|
|
||||||
|
pd->self_dirty = EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFL_CALLBACKS_ARRAY_DEFINE(self_manager,
|
||||||
|
{EFL_UI_FOCUS_USER_EVENT_MANAGER_CHANGED, _self_parent_change},
|
||||||
|
{EFL_UI_FOCUS_MANAGER_EVENT_COORDS_DIRTY, _self_manager_dirty},
|
||||||
|
);
|
||||||
|
EOLIAN static void
|
||||||
|
_efl_ui_focus_manager_sub_parent_set(Eo *obj, Efl_Ui_Focus_Manager_Sub_Data *pd, Efl_Ui_Focus_Object *node)
|
||||||
|
{
|
||||||
|
if (node == pd->parent) return;
|
||||||
|
|
||||||
|
pd->parent = node;
|
||||||
|
|
||||||
|
efl_ui_focus_manager_update_parent(pd->manager, obj, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
EOLIAN static Efl_Ui_Focus_Object*
|
||||||
|
_efl_ui_focus_manager_sub_parent_get(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Manager_Sub_Data *pd EINA_UNUSED)
|
||||||
|
{
|
||||||
|
return pd->parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
EOLIAN static Efl_Object*
|
||||||
|
_efl_ui_focus_manager_sub_efl_object_constructor(Eo *obj, Efl_Ui_Focus_Manager_Sub_Data *pd EINA_UNUSED)
|
||||||
|
{
|
||||||
|
efl_event_callback_array_add(obj, self_manager(), NULL);
|
||||||
|
|
||||||
|
return efl_constructor(efl_super(obj, MY_CLASS));
|
||||||
|
}
|
||||||
|
|
||||||
|
EOLIAN static void
|
||||||
|
_efl_ui_focus_manager_sub_efl_object_destructor(Eo *obj, Efl_Ui_Focus_Manager_Sub_Data *pd)
|
||||||
|
{
|
||||||
|
efl_event_callback_array_del(obj, self_manager(), NULL);
|
||||||
|
|
||||||
|
_parent_set(obj, pd, NULL);
|
||||||
|
|
||||||
|
return efl_destructor(efl_super(obj, MY_CLASS));
|
||||||
|
}
|
||||||
|
|
||||||
|
EOLIAN static Efl_Object*
|
||||||
|
_efl_ui_focus_manager_sub_efl_object_finalize(Eo *obj, Efl_Ui_Focus_Manager_Sub_Data *pd)
|
||||||
|
{
|
||||||
|
Efl_Ui_Focus_Manager *manager;
|
||||||
|
|
||||||
|
manager = efl_ui_focus_user_manager_get(obj);
|
||||||
|
|
||||||
|
_parent_set(obj, pd, manager);
|
||||||
|
|
||||||
|
return efl_finalize(efl_super(obj, MY_CLASS));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "efl_ui_focus_manager_sub.eo.c"
|
|
@ -0,0 +1,25 @@
|
||||||
|
abstract Efl.Ui.Focus.Manager.Sub (Efl.Ui.Focus.Manager, Efl.Ui.Focus.Object, Efl.Ui.Focus.User)
|
||||||
|
{
|
||||||
|
methods {
|
||||||
|
select_set {
|
||||||
|
params {
|
||||||
|
objects : iterator<Efl.Ui.Focus.Object>;
|
||||||
|
}
|
||||||
|
return : list<Efl.Ui.Focus.Object>;
|
||||||
|
}
|
||||||
|
@property parent {
|
||||||
|
values {
|
||||||
|
node : Efl.Ui.Focus.Object;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
implements {
|
||||||
|
@empty .select_set;
|
||||||
|
@empty Efl.Ui.Focus.Object.geometry_get;
|
||||||
|
@empty Efl.Ui.Focus.Object.focus.get;
|
||||||
|
@empty Efl.Ui.Focus.User.manager.get;
|
||||||
|
Efl.Object.constructor;
|
||||||
|
Efl.Object.destructor;
|
||||||
|
Efl.Object.finalize;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "elementary_config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <Elementary.h>
|
||||||
|
#include "elm_priv.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
|
||||||
|
} Efl_Ui_Focus_Object_Data;
|
||||||
|
|
||||||
|
EOLIAN static void
|
||||||
|
_efl_ui_focus_object_focus_set(Eo *obj, Efl_Ui_Focus_Object_Data *pd EINA_UNUSED, Eina_Bool focus)
|
||||||
|
{
|
||||||
|
const Efl_Event_Description *desc;
|
||||||
|
|
||||||
|
if (focus)
|
||||||
|
desc = EFL_UI_FOCUS_OBJECT_EVENT_FOCUS;
|
||||||
|
else
|
||||||
|
desc = EFL_UI_FOCUS_OBJECT_EVENT_UNFOCUS;
|
||||||
|
|
||||||
|
efl_event_callback_call(obj, desc, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#include "efl_ui_focus_object.eo.c"
|
||||||
|
typedef struct {
|
||||||
|
|
||||||
|
} Efl_Ui_Focus_User_Data;
|
||||||
|
#include "efl_ui_focus_user.eo.c"
|
|
@ -0,0 +1,28 @@
|
||||||
|
mixin Efl.Ui.Focus.Object
|
||||||
|
{
|
||||||
|
[[Functions of focusable objects]]
|
||||||
|
methods {
|
||||||
|
geometry_get {
|
||||||
|
params {
|
||||||
|
@out rect : Eina.Rectangle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@property focus {
|
||||||
|
[[This gets called by the manager and should never be called by someone else
|
||||||
|
|
||||||
|
It can be used by a implementation of a focus object to adapt to changes which are needed
|
||||||
|
]]
|
||||||
|
values {
|
||||||
|
focus : bool;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
implements {
|
||||||
|
@empty .geometry_get;
|
||||||
|
@empty .focus.get;
|
||||||
|
}
|
||||||
|
events {
|
||||||
|
focus;
|
||||||
|
unfocus;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
mixin Efl.Ui.Focus.User {
|
||||||
|
methods {
|
||||||
|
@property manager {
|
||||||
|
get {
|
||||||
|
|
||||||
|
}
|
||||||
|
values {
|
||||||
|
manager : Efl.Ui.Focus.Manager;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
implements {
|
||||||
|
@empty .manager.get;
|
||||||
|
}
|
||||||
|
events {
|
||||||
|
manager,changed : Efl.Ui.Focus.Manager; [[emitted if a new manager is the parent for this one]]
|
||||||
|
}
|
||||||
|
}
|
|
@ -83,6 +83,8 @@ static const Efl_Test_Case etc[] = {
|
||||||
{ "elm_code_widget_text", elm_code_test_widget_text },
|
{ "elm_code_widget_text", elm_code_test_widget_text },
|
||||||
{ "elm_code_widget_selection", elm_code_test_widget_selection },
|
{ "elm_code_widget_selection", elm_code_test_widget_selection },
|
||||||
{ "elm_code_widget_undo", elm_code_test_widget_undo },
|
{ "elm_code_widget_undo", elm_code_test_widget_undo },
|
||||||
|
{ "elm_focus", elm_test_focus},
|
||||||
|
{ "elm_focus_sub", elm_test_focus_sub},
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,8 @@ void elm_test_panes(TCase *tc);
|
||||||
void elm_test_slideshow(TCase *tc);
|
void elm_test_slideshow(TCase *tc);
|
||||||
void elm_test_spinner(TCase *tc);
|
void elm_test_spinner(TCase *tc);
|
||||||
void elm_test_plug(TCase *tc);
|
void elm_test_plug(TCase *tc);
|
||||||
|
void elm_test_focus(TCase *tc);
|
||||||
|
void elm_test_focus_sub(TCase *tc);
|
||||||
|
|
||||||
void elm_code_file_test_load(TCase *tc);
|
void elm_code_file_test_load(TCase *tc);
|
||||||
void elm_code_file_test_memory(TCase *tc);
|
void elm_code_file_test_memory(TCase *tc);
|
||||||
|
|
|
@ -0,0 +1,347 @@
|
||||||
|
#include "elm_test_focus_common.h"
|
||||||
|
|
||||||
|
START_TEST(focus_unregister_twice)
|
||||||
|
{
|
||||||
|
elm_init(1, NULL);
|
||||||
|
Efl_Ui_Focus_Object *r1 = efl_add(FOCUS_TEST_CLASS, NULL);
|
||||||
|
Efl_Ui_Focus_Object *r2 = efl_add(FOCUS_TEST_CLASS, NULL);
|
||||||
|
|
||||||
|
Efl_Ui_Focus_Manager *m = efl_add(EFL_UI_FOCUS_MANAGER_CLASS, NULL,
|
||||||
|
efl_ui_focus_manager_root_set(efl_added, r1)
|
||||||
|
);
|
||||||
|
|
||||||
|
fail_if(!efl_ui_focus_manager_register(m, r2, r1, NULL));
|
||||||
|
|
||||||
|
efl_ui_focus_manager_unregister(m, r1);
|
||||||
|
efl_ui_focus_manager_unregister(m, r1);
|
||||||
|
efl_ui_focus_manager_unregister(m, r1);
|
||||||
|
|
||||||
|
efl_del(r2);
|
||||||
|
efl_del(r1);
|
||||||
|
efl_del(m);
|
||||||
|
|
||||||
|
elm_shutdown();
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(focus_register_twice)
|
||||||
|
{
|
||||||
|
elm_init(1, NULL);
|
||||||
|
|
||||||
|
Efl_Ui_Focus_Object *r1 = elm_focus_test_object_new("r1", 0, 0, 10, 10);
|
||||||
|
Efl_Ui_Focus_Object *r2 = elm_focus_test_object_new("r2", 0, 10, 10, 10);
|
||||||
|
|
||||||
|
Efl_Ui_Focus_Manager *m = efl_add(EFL_UI_FOCUS_MANAGER_CLASS, NULL,
|
||||||
|
efl_ui_focus_manager_root_set(efl_added, r1)
|
||||||
|
);
|
||||||
|
|
||||||
|
fail_if(!efl_ui_focus_manager_register(m, r2, r1, NULL));
|
||||||
|
fail_if(efl_ui_focus_manager_register(m, r2, r1, NULL));
|
||||||
|
|
||||||
|
efl_del(r1);
|
||||||
|
efl_del(m);
|
||||||
|
|
||||||
|
elm_shutdown();
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(pos_check)
|
||||||
|
{
|
||||||
|
Efl_Ui_Focus_Manager *m;
|
||||||
|
Efl_Ui_Focus_Object *middle, *east, *west, *north, *south;
|
||||||
|
|
||||||
|
elm_init(1, NULL);
|
||||||
|
|
||||||
|
elm_focus_test_setup_cross(&middle, &south, &north, &east, &west);
|
||||||
|
|
||||||
|
m = efl_add(EFL_UI_FOCUS_MANAGER_CLASS, NULL,
|
||||||
|
efl_ui_focus_manager_root_set(efl_added, middle)
|
||||||
|
);
|
||||||
|
|
||||||
|
efl_ui_focus_manager_register(m, north, middle, NULL);
|
||||||
|
efl_ui_focus_manager_register(m, south, middle, NULL);
|
||||||
|
efl_ui_focus_manager_register(m, west, middle, NULL);
|
||||||
|
efl_ui_focus_manager_register(m, east, middle, NULL);
|
||||||
|
|
||||||
|
#define CHECK(obj, r,l,u,d) \
|
||||||
|
efl_ui_focus_manager_focus(m, obj); \
|
||||||
|
ck_assert_ptr_eq(efl_ui_focus_manager_move(m, EFL_UI_FOCUS_DIRECTION_RIGHT), r); \
|
||||||
|
efl_ui_focus_manager_focus(m, obj); \
|
||||||
|
ck_assert_ptr_eq(efl_ui_focus_manager_move(m, EFL_UI_FOCUS_DIRECTION_LEFT), l); \
|
||||||
|
efl_ui_focus_manager_focus(m, obj); \
|
||||||
|
ck_assert_ptr_eq(efl_ui_focus_manager_move(m, EFL_UI_FOCUS_DIRECTION_UP), u); \
|
||||||
|
efl_ui_focus_manager_focus(m, obj); \
|
||||||
|
ck_assert_ptr_eq(efl_ui_focus_manager_move(m, EFL_UI_FOCUS_DIRECTION_DOWN), d); \
|
||||||
|
efl_ui_focus_manager_focus(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)
|
||||||
|
|
||||||
|
efl_del(middle);
|
||||||
|
efl_del(south);
|
||||||
|
efl_del(north);
|
||||||
|
efl_del(east);
|
||||||
|
efl_del(west);
|
||||||
|
|
||||||
|
elm_shutdown();
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(redirect)
|
||||||
|
{
|
||||||
|
elm_init(1, NULL);
|
||||||
|
|
||||||
|
TEST_OBJ_NEW(root, 0, 0, 20, 20);
|
||||||
|
TEST_OBJ_NEW(one, 0, 0, 20, 20);
|
||||||
|
TEST_OBJ_NEW(two, 20, 0, 20, 20);
|
||||||
|
|
||||||
|
Efl_Ui_Focus_Manager *m = efl_add(EFL_UI_FOCUS_MANAGER_CLASS, NULL,
|
||||||
|
efl_ui_focus_manager_root_set(efl_added, root)
|
||||||
|
);
|
||||||
|
|
||||||
|
Efl_Ui_Focus_Manager *m2 = efl_add(EFL_UI_FOCUS_MANAGER_CLASS, NULL,
|
||||||
|
efl_ui_focus_manager_root_set(efl_added, one)
|
||||||
|
);
|
||||||
|
|
||||||
|
efl_ui_focus_manager_register(m2, two, one, NULL);
|
||||||
|
|
||||||
|
efl_ui_focus_manager_redirect_set(m, m2);
|
||||||
|
efl_ui_focus_manager_focus(m2, one);
|
||||||
|
|
||||||
|
ck_assert_ptr_eq(efl_ui_focus_manager_move(m, EFL_UI_FOCUS_DIRECTION_RIGHT), two);
|
||||||
|
|
||||||
|
elm_shutdown();
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(border_check)
|
||||||
|
{
|
||||||
|
Efl_Ui_Focus_Manager *m;
|
||||||
|
Efl_Ui_Focus_Object *middle, *east, *west, *north, *south;
|
||||||
|
Eina_List *list = NULL;
|
||||||
|
Eina_Iterator *iter;
|
||||||
|
Efl_Ui_Focus_Object *obj;
|
||||||
|
|
||||||
|
elm_init(1, NULL);
|
||||||
|
|
||||||
|
elm_focus_test_setup_cross(&middle, &south, &north, &east, &west);
|
||||||
|
|
||||||
|
m = efl_add(EFL_UI_FOCUS_MANAGER_CLASS, NULL,
|
||||||
|
efl_ui_focus_manager_root_set(efl_added, middle)
|
||||||
|
);
|
||||||
|
efl_ui_focus_manager_register(m, south, middle, NULL);
|
||||||
|
efl_ui_focus_manager_register(m, north, middle, NULL);
|
||||||
|
efl_ui_focus_manager_register(m, east, middle, NULL);
|
||||||
|
efl_ui_focus_manager_register(m, west, middle, NULL);
|
||||||
|
|
||||||
|
iter = efl_ui_focus_manager_border_elements_get(m);
|
||||||
|
|
||||||
|
EINA_ITERATOR_FOREACH(iter, obj)
|
||||||
|
{
|
||||||
|
list = eina_list_append(list, obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
eina_iterator_free(iter);
|
||||||
|
|
||||||
|
ck_assert(eina_list_data_find(list, east) == east);
|
||||||
|
ck_assert(eina_list_data_find(list, north) == north);
|
||||||
|
ck_assert(eina_list_data_find(list, west) == west);
|
||||||
|
ck_assert(eina_list_data_find(list, east) == east);
|
||||||
|
ck_assert(eina_list_data_find(list, middle) == NULL);
|
||||||
|
ck_assert(eina_list_count(list) == 4);
|
||||||
|
|
||||||
|
elm_shutdown();
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(logical_chain)
|
||||||
|
{
|
||||||
|
Efl_Ui_Focus_Manager *m;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
elm_init(1, NULL);
|
||||||
|
|
||||||
|
TEST_OBJ_NEW(root, 0, 0, 20, 20);
|
||||||
|
|
||||||
|
m = efl_add(EFL_UI_FOCUS_MANAGER_CLASS, NULL,
|
||||||
|
efl_ui_focus_manager_root_set(efl_added, root)
|
||||||
|
);
|
||||||
|
fail_if(!m);
|
||||||
|
|
||||||
|
efl_ui_focus_manager_focus(m, root);
|
||||||
|
|
||||||
|
i++;
|
||||||
|
TEST_OBJ_NEW(child1, 0, i*20, 20, 20);
|
||||||
|
i++;
|
||||||
|
TEST_OBJ_NEW(child2, 0, i*20, 20, 20);
|
||||||
|
i++;
|
||||||
|
TEST_OBJ_NEW(child3, 0, i*20, 20, 20);
|
||||||
|
|
||||||
|
i++;
|
||||||
|
TEST_OBJ_NEW(subchild11, 0, i*20, 20, 20);
|
||||||
|
i++;
|
||||||
|
TEST_OBJ_NEW(subchild12, 0, i*20, 20, 20);
|
||||||
|
i++;
|
||||||
|
TEST_OBJ_NEW(subchild13, 0, i*20, 20, 20);
|
||||||
|
|
||||||
|
i++;
|
||||||
|
TEST_OBJ_NEW(subchild21, 0, i*20, 20, 20);
|
||||||
|
i++;
|
||||||
|
TEST_OBJ_NEW(subchild22, 0, i*20, 20, 20);
|
||||||
|
i++;
|
||||||
|
TEST_OBJ_NEW(subchild23, 0, i*20, 20, 20);
|
||||||
|
|
||||||
|
//register everything
|
||||||
|
efl_ui_focus_manager_register(m, child1, root, NULL);
|
||||||
|
efl_ui_focus_manager_register(m, child2, root, NULL);
|
||||||
|
efl_ui_focus_manager_register(m, child3, root, NULL);
|
||||||
|
efl_ui_focus_manager_register(m, subchild11, child1, NULL);
|
||||||
|
efl_ui_focus_manager_register(m, subchild12, child1, NULL);
|
||||||
|
efl_ui_focus_manager_register(m, subchild13, child1, NULL);
|
||||||
|
efl_ui_focus_manager_register(m, subchild21, child3, NULL);
|
||||||
|
efl_ui_focus_manager_register(m, subchild22, child3, NULL);
|
||||||
|
efl_ui_focus_manager_register(m, subchild23, child3, NULL);
|
||||||
|
|
||||||
|
Efl_Object *logical_chain[] = {
|
||||||
|
child1, subchild11, subchild12, subchild13,
|
||||||
|
child2, child3, subchild21, subchild22, subchild23, root, NULL
|
||||||
|
};
|
||||||
|
for (i = 0; logical_chain[i]; ++i)
|
||||||
|
{
|
||||||
|
ck_assert_ptr_eq(logical_chain[i], efl_ui_focus_manager_move(m, EFL_UI_FOCUS_DIRECTION_NEXT));
|
||||||
|
}
|
||||||
|
i-= 2;
|
||||||
|
for (; i > 0; --i)
|
||||||
|
{
|
||||||
|
ck_assert_ptr_eq(logical_chain[i], efl_ui_focus_manager_move(m, EFL_UI_FOCUS_DIRECTION_PREV));
|
||||||
|
}
|
||||||
|
elm_shutdown();
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(finalize_check)
|
||||||
|
{
|
||||||
|
Efl_Ui_Focus_Manager *m;
|
||||||
|
|
||||||
|
elm_init(1, NULL);
|
||||||
|
|
||||||
|
m = efl_add(EFL_UI_FOCUS_MANAGER_CLASS, NULL);
|
||||||
|
fail_if(m);
|
||||||
|
|
||||||
|
elm_shutdown();
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(redirect_param)
|
||||||
|
{
|
||||||
|
Efl_Ui_Focus_Manager *m, *m2;
|
||||||
|
|
||||||
|
elm_init(1, NULL);
|
||||||
|
|
||||||
|
TEST_OBJ_NEW(root, 0, 20, 20, 20);
|
||||||
|
TEST_OBJ_NEW(root2, 0, 20, 20, 20);
|
||||||
|
TEST_OBJ_NEW(child, 0, 20, 20, 20);
|
||||||
|
|
||||||
|
m = efl_add(EFL_UI_FOCUS_MANAGER_CLASS, NULL,
|
||||||
|
efl_ui_focus_manager_root_set(efl_added, root)
|
||||||
|
);
|
||||||
|
|
||||||
|
m2 = efl_add(EFL_UI_FOCUS_MANAGER_CLASS, NULL,
|
||||||
|
efl_ui_focus_manager_root_set(efl_added, root2)
|
||||||
|
);
|
||||||
|
|
||||||
|
efl_ui_focus_manager_register(m, child, root, m2);
|
||||||
|
efl_ui_focus_manager_focus(m, child);
|
||||||
|
|
||||||
|
ck_assert_ptr_eq(efl_ui_focus_manager_redirect_get(m), m2);
|
||||||
|
|
||||||
|
elm_shutdown();
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(invalid_args_check)
|
||||||
|
{
|
||||||
|
Efl_Ui_Focus_Manager *m;
|
||||||
|
|
||||||
|
elm_init(1, NULL);
|
||||||
|
|
||||||
|
TEST_OBJ_NEW(root, 0, 20, 20, 20);
|
||||||
|
TEST_OBJ_NEW(child, 0, 20, 20, 20);
|
||||||
|
TEST_OBJ_NEW(child2, 0, 20, 20, 20);
|
||||||
|
|
||||||
|
m = efl_add(EFL_UI_FOCUS_MANAGER_CLASS, NULL,
|
||||||
|
efl_ui_focus_manager_root_set(efl_added, root)
|
||||||
|
);
|
||||||
|
|
||||||
|
//no child and no parent
|
||||||
|
ck_assert_int_eq(efl_ui_focus_manager_register(m, NULL, NULL, NULL), 0);
|
||||||
|
ck_assert_int_eq(efl_ui_focus_manager_register(m, child, NULL, NULL), 0);
|
||||||
|
ck_assert_int_eq(efl_ui_focus_manager_register(m, NULL, root, NULL), 0);
|
||||||
|
|
||||||
|
ck_assert_int_eq(efl_ui_focus_manager_register(m, child, root, NULL), 1);
|
||||||
|
|
||||||
|
ck_assert_int_eq(efl_ui_focus_manager_update_parent(m, child, NULL), 0);
|
||||||
|
ck_assert_int_eq(efl_ui_focus_manager_update_parent(m, NULL, NULL), 0);
|
||||||
|
ck_assert_int_eq(efl_ui_focus_manager_update_parent(m, child, child2), 0);
|
||||||
|
|
||||||
|
ck_assert_int_eq(efl_ui_focus_manager_register(m, child2, root, NULL), 1);
|
||||||
|
ck_assert_int_eq(efl_ui_focus_manager_update_parent(m, child, child2), 1);
|
||||||
|
|
||||||
|
elm_shutdown();
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(order_check)
|
||||||
|
{
|
||||||
|
Efl_Ui_Focus_Manager *m;
|
||||||
|
Eina_List *order = NULL;
|
||||||
|
|
||||||
|
elm_init(1, NULL);
|
||||||
|
|
||||||
|
TEST_OBJ_NEW(root, 0, 20, 20, 20);
|
||||||
|
TEST_OBJ_NEW(child1, 0, 20, 20, 20);
|
||||||
|
TEST_OBJ_NEW(child2, 0, 20, 20, 20);
|
||||||
|
TEST_OBJ_NEW(child3, 0, 20, 20, 20);
|
||||||
|
|
||||||
|
m = efl_add(EFL_UI_FOCUS_MANAGER_CLASS, NULL,
|
||||||
|
efl_ui_focus_manager_root_set(efl_added, root)
|
||||||
|
);
|
||||||
|
|
||||||
|
//no child and no parent
|
||||||
|
efl_ui_focus_manager_register(m, child1, root, NULL);
|
||||||
|
efl_ui_focus_manager_register(m, child2, root, NULL);
|
||||||
|
efl_ui_focus_manager_register(m, child3, root, NULL);
|
||||||
|
|
||||||
|
//positiv check
|
||||||
|
order = eina_list_append(order, child2);
|
||||||
|
order = eina_list_append(order, child3);
|
||||||
|
order = eina_list_append(order, child1);
|
||||||
|
ck_assert_int_eq(efl_ui_focus_manager_update_children(m, root, order), 1);
|
||||||
|
|
||||||
|
eina_list_free(order);
|
||||||
|
order = NULL;
|
||||||
|
|
||||||
|
//negativ check
|
||||||
|
order = eina_list_append(order, child1);
|
||||||
|
order = eina_list_append(order, child2);
|
||||||
|
ck_assert_int_eq(efl_ui_focus_manager_update_children(m, root, order), 0);
|
||||||
|
|
||||||
|
elm_shutdown();
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
void elm_test_focus(TCase *tc)
|
||||||
|
{
|
||||||
|
tcase_add_test(tc, focus_register_twice);
|
||||||
|
tcase_add_test(tc, focus_unregister_twice);
|
||||||
|
tcase_add_test(tc, pos_check);
|
||||||
|
tcase_add_test(tc, redirect);
|
||||||
|
tcase_add_test(tc, border_check);
|
||||||
|
tcase_add_test(tc, finalize_check);
|
||||||
|
tcase_add_test(tc, logical_chain);
|
||||||
|
tcase_add_test(tc, redirect_param);
|
||||||
|
tcase_add_test(tc, invalid_args_check);
|
||||||
|
tcase_add_test(tc, order_check);
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
#include "elm_test_focus_common.h"
|
||||||
|
|
||||||
|
#define Q(o,_x,_y,_w,_h) \
|
||||||
|
do {\
|
||||||
|
Eina_Rectangle rect = EINA_RECTANGLE_INIT; \
|
||||||
|
rect.x = _x; \
|
||||||
|
rect.y = _y; \
|
||||||
|
rect.w = _w; \
|
||||||
|
rect.h = _h; \
|
||||||
|
focus_test_size(o, rect); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
Efl_Ui_Focus_Object*
|
||||||
|
elm_focus_test_object_new(const char *name, int x, int y, int w, int h)
|
||||||
|
{
|
||||||
|
Efl_Ui_Focus_Object *ret;
|
||||||
|
|
||||||
|
ret = efl_add(FOCUS_TEST_CLASS, NULL,
|
||||||
|
efl_name_set(efl_added, name)
|
||||||
|
);
|
||||||
|
Q(ret, x, y, w, h);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
elm_focus_test_setup_cross(Efl_Ui_Focus_Object **middle,
|
||||||
|
Efl_Ui_Focus_Object **south,
|
||||||
|
Efl_Ui_Focus_Object **north,
|
||||||
|
Efl_Ui_Focus_Object **east,
|
||||||
|
Efl_Ui_Focus_Object **west)
|
||||||
|
{
|
||||||
|
|
||||||
|
*middle = elm_focus_test_object_new("middle", 40, 40, 20, 20);
|
||||||
|
*south = elm_focus_test_object_new("south", 40, 80, 20, 20);
|
||||||
|
*north = elm_focus_test_object_new("north", 40, 0, 20, 20);
|
||||||
|
*east = elm_focus_test_object_new("east", 80, 40, 20, 20);
|
||||||
|
*west = elm_focus_test_object_new("west", 0, 40, 20, 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Test class implementation
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Eina_Rectangle rect;
|
||||||
|
Eina_Bool focus;
|
||||||
|
} Focus_Test_Data;
|
||||||
|
|
||||||
|
EOLIAN static Efl_Object*
|
||||||
|
_focus_test_efl_object_constructor(Eo *obj, Focus_Test_Data *pd)
|
||||||
|
{
|
||||||
|
Eo *eo;
|
||||||
|
|
||||||
|
eo = efl_constructor(efl_super(obj, FOCUS_TEST_CLASS));
|
||||||
|
eina_rectangle_coords_from(&pd->rect, 0, 0, 0, 0);
|
||||||
|
return eo;
|
||||||
|
}
|
||||||
|
|
||||||
|
EOLIAN static void
|
||||||
|
_focus_test_efl_ui_focus_object_focus_set(Eo *obj, Focus_Test_Data *pd, Eina_Bool focus)
|
||||||
|
{
|
||||||
|
pd->focus = focus;
|
||||||
|
printf("Object %p now focused\n", obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
EOLIAN static void
|
||||||
|
_focus_test_efl_ui_focus_object_geometry_get(Eo *obj EINA_UNUSED, Focus_Test_Data *pd, Eina_Rectangle *rect)
|
||||||
|
{
|
||||||
|
if (!rect) return;
|
||||||
|
|
||||||
|
*rect = pd->rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
EOLIAN static void
|
||||||
|
_focus_test_size(Eo *obj EINA_UNUSED, Focus_Test_Data *pd, Eina_Rectangle rect)
|
||||||
|
{
|
||||||
|
pd->rect = rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "focus_test.eo.c"
|
|
@ -0,0 +1,28 @@
|
||||||
|
#ifndef ELM_TEST_FOCUS_COMMON_H
|
||||||
|
#define ELM_TEST_FOCUS_COMMON_H
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "elementary_config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ELM_INTERFACE_ATSPI_ACCESSIBLE_PROTECTED
|
||||||
|
#define ELM_INTERNAL_API_ARGESFSDFEFC
|
||||||
|
#include <Elementary.h>
|
||||||
|
#include "elm_suite.h"
|
||||||
|
#include "elm_widget.h"
|
||||||
|
#include "focus_test.eo.h"
|
||||||
|
|
||||||
|
#define TEST_OBJ_NEW(name, x, y, w, h) \
|
||||||
|
Efl_Ui_Focus_Object* name; \
|
||||||
|
name = elm_focus_test_object_new("" #name "",x, y, w, h); \
|
||||||
|
|
||||||
|
|
||||||
|
Efl_Ui_Focus_Object* elm_focus_test_object_new(const char *name, int x, int y, int w, int h);
|
||||||
|
|
||||||
|
void elm_focus_test_setup_cross(Efl_Ui_Focus_Object **middle,
|
||||||
|
Efl_Ui_Focus_Object **south,
|
||||||
|
Efl_Ui_Focus_Object **north,
|
||||||
|
Efl_Ui_Focus_Object **east,
|
||||||
|
Efl_Ui_Focus_Object **west);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,242 @@
|
||||||
|
#include "elm_test_focus_common.h"
|
||||||
|
#include "focus_test_sub.eo.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
|
||||||
|
} Focus_Test_Sub_Data;
|
||||||
|
|
||||||
|
EOLIAN static Eina_List*
|
||||||
|
_focus_test_sub_efl_ui_focus_manager_sub_select_set(Eo *obj EINA_UNUSED, Focus_Test_Sub_Data *pd EINA_UNUSED, Eina_Iterator *objects)
|
||||||
|
{
|
||||||
|
Eina_List *list = NULL;
|
||||||
|
Efl_Ui_Focus_Object *o;
|
||||||
|
|
||||||
|
EINA_ITERATOR_FOREACH(objects, o)
|
||||||
|
{
|
||||||
|
list = eina_list_append(list, o);
|
||||||
|
}
|
||||||
|
|
||||||
|
eina_iterator_free(objects);
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
EOLIAN static void
|
||||||
|
_focus_test_sub_efl_ui_focus_object_geometry_get(Eo *obj EINA_UNUSED, Focus_Test_Sub_Data *pd EINA_UNUSED, Eina_Rectangle *rect EINA_UNUSED)
|
||||||
|
{
|
||||||
|
rect->y = rect->x = 0;
|
||||||
|
rect->w = rect->h = 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
EOLIAN static Eina_Bool
|
||||||
|
_focus_test_sub_efl_ui_focus_object_focus_get(Eo *obj EINA_UNUSED, Focus_Test_Sub_Data *pd EINA_UNUSED)
|
||||||
|
{
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
EOLIAN static Efl_Ui_Focus_Manager*
|
||||||
|
_focus_test_sub_efl_ui_focus_user_manager_get(Eo *obj, Focus_Test_Sub_Data *pd EINA_UNUSED)
|
||||||
|
{
|
||||||
|
return efl_parent_get(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_List *registered;
|
||||||
|
static Eina_List *unregistered;
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_register(Eo *eo, void* data EINA_UNUSED, Efl_Ui_Focus_Object *child, Efl_Ui_Focus_Object *parent, Efl_Ui_Focus_Manager *manager)
|
||||||
|
{
|
||||||
|
registered = eina_list_append(registered, child);
|
||||||
|
printf("REGISTERED %p %s\n", child, efl_name_get(child));
|
||||||
|
|
||||||
|
return efl_ui_focus_manager_register(efl_super(eo, EFL_OBJECT_OVERRIDE_CLASS) , child, parent, manager);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_unregister(Eo *eo, void* data EINA_UNUSED, Efl_Ui_Focus_Object *child)
|
||||||
|
{
|
||||||
|
unregistered = eina_list_append(unregistered, child);
|
||||||
|
printf("UNREGISTERED %p %s\n", child, efl_name_get(child));
|
||||||
|
|
||||||
|
efl_ui_focus_manager_unregister(efl_super(eo, EFL_OBJECT_OVERRIDE_CLASS) , child);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_set_equal(Eina_List *a, Eina_List *b)
|
||||||
|
{
|
||||||
|
Eina_List *n;
|
||||||
|
void *d;
|
||||||
|
|
||||||
|
if (eina_list_count(a) != eina_list_count(b)) return EINA_FALSE;
|
||||||
|
|
||||||
|
EINA_LIST_FOREACH(a, n, d)
|
||||||
|
{
|
||||||
|
if (!eina_list_data_find(b, d)) return EINA_FALSE;
|
||||||
|
}
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "focus_test_sub.eo.c"
|
||||||
|
|
||||||
|
static void
|
||||||
|
_setup(Efl_Ui_Focus_Manager **m, Efl_Ui_Focus_Manager_Sub **sub, Efl_Ui_Focus_Object **r)
|
||||||
|
{
|
||||||
|
|
||||||
|
TEST_OBJ_NEW(root, 10, 10, 10, 10);
|
||||||
|
TEST_OBJ_NEW(root_manager, 0, 20, 20, 20);
|
||||||
|
|
||||||
|
EFL_OPS_DEFINE(manager_tracker,
|
||||||
|
EFL_OBJECT_OP_FUNC(efl_ui_focus_manager_register, _register),
|
||||||
|
EFL_OBJECT_OP_FUNC(efl_ui_focus_manager_unregister, _unregister),
|
||||||
|
);
|
||||||
|
|
||||||
|
Efl_Ui_Focus_Manager *manager = efl_add(EFL_UI_FOCUS_MANAGER_CLASS, NULL,
|
||||||
|
efl_ui_focus_manager_root_set(efl_added, root_manager)
|
||||||
|
);
|
||||||
|
//flush now all changes
|
||||||
|
efl_event_callback_call(manager, EFL_UI_FOCUS_MANAGER_EVENT_PRE_FLUSH, NULL);
|
||||||
|
registered = NULL;
|
||||||
|
unregistered = NULL;
|
||||||
|
|
||||||
|
efl_object_override(manager, &manager_tracker);
|
||||||
|
|
||||||
|
Efl_Ui_Focus_Manager_Sub *subm = efl_add(FOCUS_TEST_SUB_CLASS, manager,
|
||||||
|
efl_ui_focus_manager_sub_parent_set(efl_added, root_manager),
|
||||||
|
efl_ui_focus_manager_root_set(efl_added, root)
|
||||||
|
);
|
||||||
|
|
||||||
|
efl_event_callback_call(manager, EFL_UI_FOCUS_MANAGER_EVENT_PRE_FLUSH, NULL);
|
||||||
|
|
||||||
|
*sub = subm;
|
||||||
|
*m = manager;
|
||||||
|
*r = root;
|
||||||
|
}
|
||||||
|
|
||||||
|
START_TEST(correct_register)
|
||||||
|
{
|
||||||
|
Eina_List *set1 = NULL;
|
||||||
|
Efl_Ui_Focus_Object *root;
|
||||||
|
Efl_Ui_Focus_Manager *manager, *sub;
|
||||||
|
elm_init(0, NULL);
|
||||||
|
|
||||||
|
_setup(&manager, &sub, &root);
|
||||||
|
|
||||||
|
TEST_OBJ_NEW(child1, 0, 0, 10, 10);
|
||||||
|
TEST_OBJ_NEW(child2, 10, 0, 10, 10);
|
||||||
|
TEST_OBJ_NEW(child3, 0, 10, 10, 10);
|
||||||
|
|
||||||
|
set1 = eina_list_append(set1, sub);
|
||||||
|
set1 = eina_list_append(set1, root);
|
||||||
|
set1 = eina_list_append(set1, child1);
|
||||||
|
set1 = eina_list_append(set1, child2);
|
||||||
|
set1 = eina_list_append(set1, child3);
|
||||||
|
|
||||||
|
//test register stuff
|
||||||
|
efl_ui_focus_manager_register(sub, child1, root, NULL);
|
||||||
|
efl_ui_focus_manager_register(sub, child2, root, NULL);
|
||||||
|
efl_ui_focus_manager_register(sub, child3, root, NULL);
|
||||||
|
//now force submanager to flush things
|
||||||
|
efl_event_callback_call(manager, EFL_UI_FOCUS_MANAGER_EVENT_PRE_FLUSH, NULL);
|
||||||
|
ck_assert_ptr_eq(unregistered, NULL);
|
||||||
|
fail_if(!_set_equal(registered, set1));
|
||||||
|
|
||||||
|
efl_del(sub);
|
||||||
|
efl_del(manager);
|
||||||
|
efl_del(root);
|
||||||
|
efl_del(child1);
|
||||||
|
efl_del(child2);
|
||||||
|
efl_del(child3);
|
||||||
|
elm_shutdown();
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(correct_unregister)
|
||||||
|
{
|
||||||
|
Eina_List *set = NULL;
|
||||||
|
Efl_Ui_Focus_Object *root;
|
||||||
|
Efl_Ui_Focus_Manager *manager, *sub;
|
||||||
|
elm_init(0, NULL);
|
||||||
|
|
||||||
|
_setup(&manager, &sub, &root);
|
||||||
|
|
||||||
|
TEST_OBJ_NEW(child1, 0, 0, 10, 10);
|
||||||
|
TEST_OBJ_NEW(child2, 10, 0, 10, 10);
|
||||||
|
TEST_OBJ_NEW(child3, 0, 10, 10, 10);
|
||||||
|
|
||||||
|
set = eina_list_append(set, child3);
|
||||||
|
|
||||||
|
//test register stuff
|
||||||
|
efl_ui_focus_manager_register(sub, child1, root, NULL);
|
||||||
|
efl_ui_focus_manager_register(sub, child2, root, NULL);
|
||||||
|
efl_ui_focus_manager_register(sub, child3, root, NULL);
|
||||||
|
efl_event_callback_call(manager, EFL_UI_FOCUS_MANAGER_EVENT_PRE_FLUSH, NULL);
|
||||||
|
eina_list_free(unregistered);
|
||||||
|
unregistered = NULL;
|
||||||
|
eina_list_free(registered);
|
||||||
|
registered = NULL;
|
||||||
|
|
||||||
|
//test unregister stuff
|
||||||
|
efl_ui_focus_manager_unregister(sub, child3);
|
||||||
|
efl_event_callback_call(manager, EFL_UI_FOCUS_MANAGER_EVENT_PRE_FLUSH, NULL);
|
||||||
|
ck_assert_ptr_eq(registered, NULL);
|
||||||
|
fail_if(!_set_equal(unregistered, set));
|
||||||
|
eina_list_free(unregistered);
|
||||||
|
unregistered = NULL;
|
||||||
|
|
||||||
|
efl_del(sub);
|
||||||
|
efl_del(manager);
|
||||||
|
efl_del(root);
|
||||||
|
efl_del(child1);
|
||||||
|
efl_del(child2);
|
||||||
|
efl_del(child3);
|
||||||
|
elm_shutdown();
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(correct_un_register)
|
||||||
|
{
|
||||||
|
Eina_List *set_add = NULL, *set_del = NULL;
|
||||||
|
Efl_Ui_Focus_Object *root;
|
||||||
|
Efl_Ui_Focus_Manager *manager, *sub;
|
||||||
|
elm_init(0, NULL);
|
||||||
|
|
||||||
|
_setup(&manager, &sub, &root);
|
||||||
|
|
||||||
|
TEST_OBJ_NEW(child1, 0, 0, 10, 10);
|
||||||
|
TEST_OBJ_NEW(child2, 10, 0, 10, 10);
|
||||||
|
TEST_OBJ_NEW(child3, 0, 10, 10, 10);
|
||||||
|
|
||||||
|
set_add = eina_list_append(set_add, child2);
|
||||||
|
set_del = eina_list_append(set_del, child3);
|
||||||
|
//test register stuff
|
||||||
|
efl_ui_focus_manager_register(sub, child1, root, NULL);
|
||||||
|
efl_ui_focus_manager_register(sub, child3, root, NULL);
|
||||||
|
efl_event_callback_call(manager, EFL_UI_FOCUS_MANAGER_EVENT_PRE_FLUSH, NULL);
|
||||||
|
eina_list_free(unregistered);
|
||||||
|
unregistered = NULL;
|
||||||
|
eina_list_free(registered);
|
||||||
|
registered = NULL;
|
||||||
|
|
||||||
|
//test unregister stuff
|
||||||
|
efl_ui_focus_manager_unregister(sub, child3);
|
||||||
|
efl_ui_focus_manager_register(sub, child2, root, NULL);
|
||||||
|
efl_event_callback_call(manager, EFL_UI_FOCUS_MANAGER_EVENT_PRE_FLUSH, NULL);
|
||||||
|
fail_if(!_set_equal(registered, set_add));
|
||||||
|
fail_if(!_set_equal(unregistered, set_del));
|
||||||
|
|
||||||
|
efl_del(sub);
|
||||||
|
efl_del(manager);
|
||||||
|
efl_del(root);
|
||||||
|
efl_del(child1);
|
||||||
|
efl_del(child2);
|
||||||
|
efl_del(child3);
|
||||||
|
elm_shutdown();
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
void elm_test_focus_sub(TCase *tc)
|
||||||
|
{
|
||||||
|
tcase_add_test(tc, correct_register);
|
||||||
|
tcase_add_test(tc, correct_unregister);
|
||||||
|
tcase_add_test(tc, correct_un_register);
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
class Focus.Test(Efl.Object, Efl.Ui.Focus.Object) {
|
||||||
|
methods {
|
||||||
|
size {
|
||||||
|
params {
|
||||||
|
rect : Eina.Rectangle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
implements {
|
||||||
|
Efl.Object.constructor;
|
||||||
|
Efl.Ui.Focus.Object.geometry_get;
|
||||||
|
Efl.Ui.Focus.Object.focus.set;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
class Focus.Test.Sub(Efl.Ui.Focus.Manager.Sub) {
|
||||||
|
implements {
|
||||||
|
Efl.Ui.Focus.Manager.Sub.select_set;
|
||||||
|
Efl.Ui.Focus.Object.geometry_get;
|
||||||
|
Efl.Ui.Focus.Object.focus.get;
|
||||||
|
Efl.Ui.Focus.User.manager.get;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue