From 1681acef5a05f41a4573452aa33b5d7743cab54c Mon Sep 17 00:00:00 2001 From: Marcel Hollerbach Date: Sun, 29 May 2016 11:32:23 +0200 Subject: win: hook a efl.ui.manager in this is just a prove of concept and a hack to get the events on the window. Feel free to play arround with the right->left->top->down focus, and see how it performce. Its just tested on elementary_test. --- src/lib/elementary/elm_widget.c | 112 ++++++++++++++++++++++++++++++++++++++-- src/lib/elementary/elm_widget.h | 4 ++ src/lib/elementary/elm_win.c | 44 ++++++++++++---- src/lib/elementary/elm_win.eo | 3 +- 4 files changed, 149 insertions(+), 14 deletions(-) diff --git a/src/lib/elementary/elm_widget.c b/src/lib/elementary/elm_widget.c index 56e175aa47..d25eb030ed 100644 --- a/src/lib/elementary/elm_widget.c +++ b/src/lib/elementary/elm_widget.c @@ -1084,6 +1084,106 @@ elm_widget_sub_object_parent_add(Evas_Object *sobj) return ret; } +static Eo* +_find_focus_manager(Eo *obj) +{ + Eo *cantidate; + + cantidate = obj; + + while (elm_widget_parent_get(cantidate)) + { + cantidate = elm_widget_parent_get(cantidate); + if (eo_isa(cantidate, EFL_UI_FOCUS_MANAGER_CLASS)) + { + return cantidate; + } + } + return NULL; +} + +static Eina_Bool +_find_focusable(Elm_Widget *widget) +{ + Eina_List *node; + Elm_Widget *sub; + + ELM_WIDGET_DATA_GET(widget, pd); + + EINA_LIST_FOREACH(pd->subobjs, node, sub) + { + if (!elm_widget_is(sub)) continue; + + if (_find_focusable(sub)) + return EINA_TRUE; + { + ELM_WIDGET_DATA_GET(sub, wd); + if (wd->can_focus) + return EINA_TRUE; + } + } + + return EINA_FALSE; +} + +static void +_focus_manager_check_state(Eo *obj) +{ + ELM_WIDGET_DATA_GET(obj, pd); + + if (efl_ui_focus_object_can_focus_get(obj) + && !_find_focusable(obj)) + { + if (!pd->focus.registered) + { + printf("REGISTER %p %s\n", obj, elm_widget_type_get(obj)); + efl_ui_focus_manager_register(pd->focus.manager, obj); + pd->focus.registered = EINA_TRUE; + } + } + else + { + if (pd->focus.registered) + { + printf("UNREGISTER %p\n", obj); + efl_ui_focus_manager_unregister(pd->focus.manager, obj); + pd->focus.registered = EINA_FALSE; + } + + } +} + +static void +_focus_manager_reregister(Eo *obj) +{ + ELM_WIDGET_DATA_GET(obj, pd); + Efl_Ui_Focus_Manager *manager; + + manager = _find_focus_manager(obj); + + if (manager == pd->focus.manager) return; + if (!manager) + { + ERR("Failed to find a manager"); + } + + //search the next higher focus manager + if (pd->focus.manager) + { + efl_ui_focus_manager_unregister(pd->focus.manager, obj); + pd->focus.manager = NULL; + pd->focus.registered = EINA_FALSE; + } + + pd->focus.manager = manager; + + if (pd->focus.manager) + { + _focus_manager_check_state(obj); + } +} + + /* * @internal * @@ -1126,6 +1226,8 @@ _elm_widget_sub_object_add(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *sobj return EINA_FALSE; } sdc->parent_obj = obj; + printf("REREGISTER %s\n", elm_widget_type_get(sobj)); + _focus_manager_reregister(sobj); if (!sdc->on_create) elm_obj_widget_orientation_set(sobj, sd->orient_mode); @@ -1171,6 +1273,8 @@ _elm_widget_sub_object_add(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *sobj } } sd->subobjs = eina_list_append(sd->subobjs, sobj); + _focus_manager_check_state(obj); + evas_object_data_set(sobj, "elm-parent", obj); _callbacks_add(sobj, obj); @@ -1292,12 +1396,13 @@ _elm_widget_sub_object_del(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *sobj ELM_WIDGET_DATA_GET(sobj, sdc); sdc->parent_obj = elm_widget_top_get(obj); + _focus_manager_reregister(sobj); } if (sd->resize_obj == sobj) sd->resize_obj = NULL; sd->subobjs = eina_list_remove(sd->subobjs, sobj); - + _focus_manager_check_state(obj); _callbacks_del(sobj, obj); return EINA_TRUE; @@ -1430,6 +1535,7 @@ _elm_widget_efl_ui_focus_object_can_focus_set(Eo *obj, Elm_Widget_Smart_Data *sd } eo_event_callback_array_del(obj, focus_callbacks(), NULL); } + _focus_manager_check_state(obj); } EOLIAN static Eina_Bool @@ -2910,6 +3016,8 @@ _elm_widget_efl_ui_focus_object_focus_set(Eo *obj, Elm_Widget_Smart_Data *sd, Ei break; } } + // we have unfocused all children set the focusflag on our self + sd->focused = EINA_FALSE; } } @@ -2939,8 +3047,6 @@ _focused_object_clear(Elm_Widget_Smart_Data *sd) break; } } - // we have unfocused all children set the focusflag on our self - sd->focused = EINA_FALSE; } } diff --git a/src/lib/elementary/elm_widget.h b/src/lib/elementary/elm_widget.h index 3afe9a601d..74ac04c6ba 100644 --- a/src/lib/elementary/elm_widget.h +++ b/src/lib/elementary/elm_widget.h @@ -454,6 +454,10 @@ typedef struct _Elm_Widget_Smart_Data Eina_Bool on_translate : 1; /**< This is true when any types of elm translate function is being called. */ Eina_Bool on_create : 1; /**< This is true when the widget is on creation(general widget constructor). */ Eina_Bool on_destroy: 1; /**< This is true when the widget is on destruction(general widget destructor). */ + struct { + Efl_Ui_Focus_Manager *manager; + Eina_Bool registered; + } focus; } Elm_Widget_Smart_Data; /** diff --git a/src/lib/elementary/elm_win.c b/src/lib/elementary/elm_win.c index 80feeeb7bd..b93179bfa0 100644 --- a/src/lib/elementary/elm_win.c +++ b/src/lib/elementary/elm_win.c @@ -5,6 +5,7 @@ #define ELM_INTERFACE_ATSPI_ACCESSIBLE_PROTECTED #define ELM_INTERFACE_ATSPI_WIDGET_ACTION_PROTECTED #define ELM_WIN_PROTECTED +#define EO_BASE_BETA #include #include @@ -237,6 +238,7 @@ struct _Elm_Win_Data Eina_Bool noblank : 1; Eina_Bool theme_alpha : 1; /**< alpha value fetched by a theme. this has higher priority than application_alpha */ Eina_Bool application_alpha : 1; /**< alpha value set by an elm_win_alpha_set() api. this has lower priority than theme_alpha */ + Efl_Ui_Focus_Manager *manager; }; struct _Box_Item_Iterator @@ -1607,14 +1609,7 @@ _key_action_move(Evas_Object *obj, const char *params) else if (!strcmp(dir, "next")) elm_widget_focus_cycle(obj, ELM_FOCUS_NEXT); else if (!strcmp(dir, "left")) - elm_widget_focus_cycle(obj, ELM_FOCUS_LEFT); - else if (!strcmp(dir, "right")) - elm_widget_focus_cycle(obj, ELM_FOCUS_RIGHT); - else if (!strcmp(dir, "up")) - elm_widget_focus_cycle(obj, ELM_FOCUS_UP); - else if (!strcmp(dir, "down")) - elm_widget_focus_cycle(obj, ELM_FOCUS_DOWN); - else return EINA_FALSE; + return EINA_FALSE; return EINA_TRUE; } @@ -1974,7 +1969,7 @@ _elm_win_evas_object_smart_del(Eo *obj, Elm_Win_Data *sd) DECREMENT_MODALITY() } - if ((sd->modal) && (sd->modal_count > 0)) + if ((sd->modal) && (sd->modal_count > 0)) ERR("Deleted modal win was blocked by another modal win which was created after creation of that win."); evas_object_event_callback_del_full(sd->edje, @@ -3435,6 +3430,24 @@ _accel_is_gl(void) return EINA_FALSE; } +static void +_focus_movement(void *data, Evas *e, Evas_Object *obj, void *event_info) +{ + Evas_Event_Key_Down *down = event_info; + ELM_WIN_DATA_GET(data, pd); + Eo *r = NULL; + + if (!strcmp(down->keyname, "Left")) + r = efl_ui_focus_manager_move(pd->manager, EFL_UI_FOCUS_DIRECTION_LEFT); + else if (!strcmp(down->keyname, "Right")) + r = efl_ui_focus_manager_move(pd->manager, EFL_UI_FOCUS_DIRECTION_RIGHT); + else if (!strcmp(down->keyname, "Up")) + r = efl_ui_focus_manager_move(pd->manager, EFL_UI_FOCUS_DIRECTION_UP); + else if (!strcmp(down->keyname, "Down")) + r = efl_ui_focus_manager_move(pd->manager, EFL_UI_FOCUS_DIRECTION_DOWN); +} + + static Eo * _elm_win_finalize_internal(Eo *obj, Elm_Win_Data *sd, const char *name, Elm_Win_Type type) { @@ -4037,6 +4050,14 @@ _elm_win_finalize_internal(Eo *obj, Elm_Win_Data *sd, const char *name, Elm_Win_ if (_elm_config->atspi_mode) elm_interface_atspi_window_created_signal_emit(obj); + evas_object_key_grab(sd->edje, "Right", 0, 0, EINA_TRUE); + evas_object_key_grab(sd->edje, "Left", 0, 0, EINA_TRUE); + evas_object_key_grab(sd->edje, "Up", 0, 0, EINA_TRUE); + evas_object_key_grab(sd->edje, "Down", 0, 0, EINA_TRUE); + + evas_object_event_callback_add + (sd->edje, EVAS_CALLBACK_KEY_DOWN, _focus_movement, obj); + evas_object_show(sd->edje); if (type == ELM_WIN_FAKE) @@ -4059,11 +4080,14 @@ _elm_win_eo_base_finalize(Eo *obj, Elm_Win_Data *_pd) } EOLIAN static Eo * -_elm_win_eo_base_constructor(Eo *obj, Elm_Win_Data *_pd EINA_UNUSED) +_elm_win_eo_base_constructor(Eo *obj, Elm_Win_Data *_pd) { /* Do nothing. */ /* XXX: We are calling the constructor chain from the finalizer. It's * really bad and hacky. Needs fixing. */ + _pd->manager = eo_add(EFL_UI_FOCUS_MANAGER_CLASS, NULL); + + eo_composite_attach(obj, _pd->manager); return obj; } diff --git a/src/lib/elementary/elm_win.eo b/src/lib/elementary/elm_win.eo index 69571bf9db..7205580e39 100644 --- a/src/lib/elementary/elm_win.eo +++ b/src/lib/elementary/elm_win.eo @@ -177,7 +177,8 @@ enum Elm.Illume_Command } class Elm.Win (Elm.Widget, Elm.Interface.Atspi.Window, - Elm.Interface.Atspi_Widget_Action, Efl.Pack) + Elm.Interface.Atspi_Widget_Action, Efl.Pack, + Efl.Ui.Focus.Manager) { legacy_prefix: elm_win; eo_prefix: elm_obj_win; -- cgit v1.2.1