summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcel Hollerbach <marcel-hollerbach@t-online.de>2016-05-29 11:32:23 +0200
committerMarcel Hollerbach <marcel-hollerbach@t-online.de>2016-05-29 11:32:23 +0200
commit1681acef5a05f41a4573452aa33b5d7743cab54c (patch)
treefea0455045366d9e13e0a67a0a51da8e1a86b4ab
parentd26c4652cbe3f808b3c78343fe456019fcb7d1f5 (diff)
downloadefl-devs/bu5hm4n/focus2.tar.gz
win: hook a efl.ui.manager indevs/bu5hm4n/focus2
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.
-rw-r--r--src/lib/elementary/elm_widget.c112
-rw-r--r--src/lib/elementary/elm_widget.h4
-rw-r--r--src/lib/elementary/elm_win.c44
-rw-r--r--src/lib/elementary/elm_win.eo3
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 <Elementary.h>
#include <Elementary_Cursor.h>
@@ -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;