From 09e7ffe7f06f4612ea6e3740447bdbdc81a083e9 Mon Sep 17 00:00:00 2001 From: WooHyun Jung Date: Fri, 18 Mar 2016 16:38:26 +0900 Subject: focus: add focus_move_policy_automatic_set/get function Summary: After setting specific focus move policy to one winset object, if it should not follow the system focus move policy change, this new api can be used. @feature --- src/bin/test_focus.c | 96 +++++++++++++++++++++++++++++++++++++++++++-------- src/lib/elm_config.c | 1 + src/lib/elm_focus.h | 30 ++++++++++++++++ src/lib/elm_main.c | 14 ++++++++ src/lib/elm_priv.h | 1 + src/lib/elm_widget.c | 78 +++++++++++++++++++++++++++++++++++++++++ src/lib/elm_widget.eo | 12 +++++++ src/lib/elm_widget.h | 4 +++ src/lib/elm_win.c | 10 ++++++ 9 files changed, 232 insertions(+), 14 deletions(-) diff --git a/src/bin/test_focus.c b/src/bin/test_focus.c index 2782299e6..88e223fd4 100644 --- a/src/bin/test_focus.c +++ b/src/bin/test_focus.c @@ -77,10 +77,23 @@ _focus_anim_changed(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) elm_win_focus_highlight_animate_set(data, EINA_FALSE); } +static void +_rd_changed_cb(void *data EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) +{ + int value = elm_radio_state_value_get(obj); + + if (value == 0) + elm_config_focus_move_policy_set(ELM_FOCUS_MOVE_POLICY_CLICK); + else if (value == 1) + elm_config_focus_move_policy_set(ELM_FOCUS_MOVE_POLICY_IN); + else + elm_config_focus_move_policy_set(ELM_FOCUS_MOVE_POLICY_KEY_ONLY); +} + void test_focus(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { - Evas_Object *win, *tbx, *tbar, *menu; + Evas_Object *win, *tbx, *tbar, *mainbx, *menu, *ttb; Elm_Object_Item *tb_it; Elm_Object_Item *menu_it; unsigned int i, j; @@ -121,8 +134,8 @@ test_focus(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_inf elm_toolbar_item_menu_set(tb_it, EINA_TRUE); elm_toolbar_item_priority_set(tb_it, -9999); elm_toolbar_menu_parent_set(tbar, win); - menu = elm_toolbar_item_menu_get(tb_it); + menu = elm_toolbar_item_menu_get(tb_it); elm_menu_item_add(menu, NULL, "edit-cut", "Shrink", _tb_sel, NULL); menu_it = elm_menu_item_add(menu, NULL, "edit-copy", "Mode", _tb_sel, NULL); elm_menu_item_add(menu, menu_it, "edit-paste", "is set to", _tb_sel, NULL); @@ -131,7 +144,7 @@ test_focus(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_inf elm_box_pack_end(tbx, tbar); evas_object_show(tbar); - Evas_Object *mainbx = elm_box_add(win); + mainbx = elm_box_add(win); elm_box_horizontal_set(mainbx, EINA_TRUE); evas_object_size_hint_weight_set(mainbx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_box_pack_end(tbx, mainbx); @@ -304,8 +317,7 @@ test_focus(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_inf Evas_Object *ly = elm_layout_add(win); snprintf(buf, sizeof(buf), "%s/objects/test.edj", elm_app_data_dir_get()); elm_layout_file_set(ly, buf, "twolines"); - evas_object_size_hint_weight_set(ly, EVAS_HINT_EXPAND, - EVAS_HINT_EXPAND); + evas_object_size_hint_weight_set(ly, EVAS_HINT_EXPAND, 0.0); elm_box_pack_end(mainbx, ly); my_show(ly); @@ -362,6 +374,30 @@ test_focus(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_inf evas_object_smart_callback_add(bt2, "clicked", my_enable, bt); my_show(bt2); elm_object_focus_custom_chain_append(bx2, bt2, NULL); + + Evas_Object *bt3; + bt3 = elm_button_add(win); + elm_object_text_set(bt3, "KeyOnly with Auto"); + elm_object_focus_move_policy_set(bt3, ELM_FOCUS_MOVE_POLICY_KEY_ONLY); + elm_object_focus_move_policy_automatic_set(bt, EINA_TRUE); // EINA_TURE is default + evas_object_size_hint_align_set(bt3, EVAS_HINT_FILL, + EVAS_HINT_FILL); + evas_object_size_hint_weight_set(bt3, 0.0, 0.0); + elm_box_pack_end(bx2, bt3); + my_show(bt3); + elm_object_focus_custom_chain_append(bx2, bt3, NULL); + + Evas_Object *bt4; + bt4 = elm_button_add(win); + elm_object_text_set(bt4, "KeyOnly without Auto"); + elm_object_focus_move_policy_set(bt4, ELM_FOCUS_MOVE_POLICY_KEY_ONLY); + elm_object_focus_move_policy_automatic_set(bt4, EINA_FALSE); + evas_object_size_hint_align_set(bt4, EVAS_HINT_FILL, + EVAS_HINT_FILL); + evas_object_size_hint_weight_set(bt4, 0.0, 0.0); + elm_box_pack_end(bx2, bt4); + my_show(bt4); + elm_object_focus_custom_chain_append(bx2, bt4, NULL); } } @@ -430,33 +466,65 @@ test_focus(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_inf } } - Evas_Object *bx = elm_box_add(win); - evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, - EVAS_HINT_EXPAND); - elm_box_pack_end(tbx, bx); - my_show(bx); + ttb = elm_table_add(win); + evas_object_size_hint_weight_set(ttb, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_box_pack_end(tbx, ttb); + my_show(ttb); { Evas_Object *ck; - ck = elm_check_add(bx); + ck = elm_check_add(ttb); elm_object_text_set(ck, "Focus Highlight Enable"); elm_check_state_set(ck, elm_win_focus_highlight_enabled_get(win)); - elm_box_pack_end(bx, ck); + evas_object_size_hint_align_set(ck, 0.0, EVAS_HINT_FILL); + elm_table_pack(ttb, ck, 0, 0, 1, 1); my_show(ck); evas_object_smart_callback_add(ck, "changed", _focus_highlight_changed, win); - ck = elm_check_add(bx); + ck = elm_check_add(ttb); elm_object_text_set(ck, "Focus Highlight Animation Enable"); elm_check_state_set(ck, elm_win_focus_highlight_animate_get(win)); - elm_box_pack_end(bx, ck); + evas_object_size_hint_align_set(ck, 0.0, EVAS_HINT_FILL); + elm_table_pack(ttb, ck, 0, 1, 1, 1); my_show(ck); evas_object_smart_callback_add(ck, "changed", _focus_anim_changed, win); } + + { + Evas_Object *rd, *rdg; + + for (i = 0; i < 3; i++) + { + rd = elm_radio_add(ttb); + elm_radio_state_value_set(rd, i); + evas_object_size_hint_weight_set(rd, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(rd, 0.0, EVAS_HINT_FILL); + elm_table_pack(ttb, rd, 1, i, 1, 1); + evas_object_show(rd); + evas_object_smart_callback_add(rd, "changed", _rd_changed_cb, NULL); + + if (i == 0) + { + rdg = rd; + elm_object_text_set(rd, "Move Policy: Key+Click(Default)"); + } + else if (i == 1) + { + elm_radio_group_add(rd, rdg); + elm_object_text_set(rd, "Move Policy: Key+Click+In"); + } + else + { + elm_radio_group_add(rd, rdg); + elm_object_text_set(rd, "Move Policy: Key Only"); + } + } + } } /**** focus 2 ****/ diff --git a/src/lib/elm_config.c b/src/lib/elm_config.c index d957aa995..6bb1363bc 100644 --- a/src/lib/elm_config.c +++ b/src/lib/elm_config.c @@ -3103,6 +3103,7 @@ EAPI void elm_config_focus_move_policy_set(Elm_Focus_Move_Policy policy) { _elm_config->focus_move_policy = policy; + _elm_win_focus_reconfigure(); } EAPI Eina_Bool diff --git a/src/lib/elm_focus.h b/src/lib/elm_focus.h index 4864bdd85..7c114ab15 100644 --- a/src/lib/elm_focus.h +++ b/src/lib/elm_focus.h @@ -370,3 +370,33 @@ EAPI void elm_object_focus_region_show_mode_set(Evas_Objec * @ingroup Elm_Focus */ EAPI Elm_Focus_Region_Show_Mode elm_object_focus_region_show_mode_get(const Evas_Object *obj); + +/** + * Returns the widget's focus movement policy mode setting. + * + * @param obj The widget. + * @return focus movement policy mode setting of the object. + * + * @see elm_object_focus_move_policy_automatic_set + * + * @since 1.18 + * + * @ingroup Focus + */ +EAPI Eina_Bool elm_object_focus_move_policy_automatic_get(const Evas_Object *obj); + +/** + * Sets the widget's focus movement policy mode setting. + * When widget in automatic mode, it follows the system focus movement policy mode + * set by elm_config_focus_move_policy_set(). + * @param obj The widget. + * @param automatic @c EINA_TRUE for auto focus_move_policy mode. @c EINA_FALSE for + * manual. + * + * @see elm_object_focus_move_policy_automatic_get + * + * @since 1.18 + * + * @ingroup Focus + */ +EAPI void elm_object_focus_move_policy_automatic_set(Evas_Object *obj, Eina_Bool automatic); diff --git a/src/lib/elm_main.c b/src/lib/elm_main.c index 0bb4c4d4b..d0bbb7d71 100644 --- a/src/lib/elm_main.c +++ b/src/lib/elm_main.c @@ -1523,6 +1523,20 @@ elm_object_focus_move_policy_get(const Evas_Object *obj) return elm_widget_focus_move_policy_get(obj); } +EAPI Eina_Bool +elm_object_focus_move_policy_automatic_get(const Evas_Object *obj) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE); + return elm_widget_focus_move_policy_automatic_get(obj); +} + +EAPI void +elm_object_focus_move_policy_automatic_set(Evas_Object *obj, Eina_Bool automatic) +{ + EINA_SAFETY_ON_NULL_RETURN(obj); + elm_widget_focus_move_policy_automatic_set(obj, automatic); +} + EAPI void elm_object_scroll_hold_push(Evas_Object *obj) { diff --git a/src/lib/elm_priv.h b/src/lib/elm_priv.h index 91b4285a6..f8a57860d 100644 --- a/src/lib/elm_priv.h +++ b/src/lib/elm_priv.h @@ -386,6 +386,7 @@ void _elm_win_rescale(Elm_Theme *th, Eina_Bool use_theme); void _elm_win_access(Eina_Bool is_access); void _elm_win_translate(void); +void _elm_win_focus_reconfigure(void); Ecore_X_Window _elm_ee_xwin_get(const Ecore_Evas *ee); diff --git a/src/lib/elm_widget.c b/src/lib/elm_widget.c index ac7aeb3e7..b110f323a 100644 --- a/src/lib/elm_widget.c +++ b/src/lib/elm_widget.c @@ -342,6 +342,7 @@ _elm_widget_evas_object_smart_add(Eo *obj, Elm_Widget_Smart_Data *priv) priv->obj = obj; priv->mirrored_auto_mode = EINA_TRUE; /* will follow system locale * settings */ + priv->focus_move_policy_auto_mode = EINA_TRUE; priv->focus_region_show_mode = ELM_FOCUS_REGION_SHOW_WIDGET; elm_widget_can_focus_set(obj, EINA_TRUE); priv->is_mirrored = elm_config_mirrored_get(); @@ -3576,6 +3577,46 @@ _elm_widget_translate(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSE return EINA_TRUE; } +/** + * @internal + * + * Resets the focus_move_policy mode from the system one + * for widgets that are in automatic mode. + * + * @param obj The widget. + * + */ +static void +_elm_widget_focus_move_policy_reload(Evas_Object *obj) +{ + API_ENTRY return; + Elm_Focus_Move_Policy focus_move_policy = elm_config_focus_move_policy_get(); + + if (elm_widget_focus_move_policy_automatic_get(obj) && + (sd->focus_move_policy != focus_move_policy)) + { + sd->focus_move_policy = focus_move_policy; + } +} + +EOLIAN static void +_elm_widget_focus_reconfigure(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED) +{ + const Eina_List *l; + Evas_Object *child; + API_ENTRY return; + + EINA_LIST_FOREACH(sd->subobjs, l, child) + { + if (elm_widget_is(child)) + elm_widget_focus_reconfigure(child); + } + + if (sd->hover_obj) elm_widget_focus_reconfigure(sd->hover_obj); + + _elm_widget_focus_move_policy_reload(obj); +} + EAPI void elm_widget_content_part_set(Evas_Object *obj, const char *part, @@ -4244,6 +4285,43 @@ _elm_widget_focus_move_policy_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd if (sd->focus_move_policy == policy) return; sd->focus_move_policy = policy; } + +/** + * Returns the widget's focus_move_policy mode setting. + * + * @param obj The widget. + * @return focus_move_policy mode setting of the object. + * + **/ +EOLIAN static Eina_Bool +_elm_widget_focus_move_policy_automatic_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd) +{ + return sd->focus_move_policy_auto_mode; +} + +/** + * @internal + * + * Sets the widget's focus_move_policy mode setting. + * When widget in automatic mode, it follows the system focus_move_policy mode set by + * elm_config_focus_move_policy_set(). + * @param obj The widget. + * @param automatic EINA_TRUE for auto focus_move_policy mode. EINA_FALSE for manual. + */ +EOLIAN static void +_elm_widget_focus_move_policy_automatic_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool automatic) +{ + if (sd->focus_move_policy_auto_mode != automatic) + { + sd->focus_move_policy_auto_mode = automatic; + + if (automatic) + { + elm_widget_focus_move_policy_set(obj, elm_config_focus_move_policy_get()); + } + } +} + static void _track_obj_del(void *data, Evas *e, Evas_Object *obj, void *event_info); diff --git a/src/lib/elm_widget.eo b/src/lib/elm_widget.eo index e5db7679d..b618b4dcc 100644 --- a/src/lib/elm_widget.eo +++ b/src/lib/elm_widget.eo @@ -820,6 +820,18 @@ abstract Elm.Widget (Evas.Object_Smart, Elm.Interface_Atspi_Accessible, Elm.Inte values { policy: Elm.Focus.Move_Policy; [[Object's focus move policy.]] } + } + @property focus_move_policy_automatic { + [[Control the widget's focus_move_policy mode setting.]] + set { + } + get { + } + values { + automatic: bool; [[$true to follow system focus move policy change, $false otherwise]] + } + } + focus_reconfigure { } } implements { diff --git a/src/lib/elm_widget.h b/src/lib/elm_widget.h index f5b8626e5..e0d5b8e0d 100644 --- a/src/lib/elm_widget.h +++ b/src/lib/elm_widget.h @@ -439,6 +439,7 @@ typedef struct _Elm_Widget_Smart_Data 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; Eina_Bool access_highlight_in_theme : 1; @@ -766,8 +767,11 @@ EAPI void elm_widget_focus_highlight_geometry_get(const Evas_Object void _elm_widget_item_highlight_in_theme(Evas_Object *obj, Elm_Object_Item *it); EAPI void elm_widget_focus_move_policy_set(Evas_Object *obj, Elm_Focus_Move_Policy policy); EAPI Elm_Focus_Move_Policy elm_widget_focus_move_policy_get(const Evas_Object *obj); +EAPI Eina_Bool elm_widget_focus_move_policy_automatic_get(const Evas_Object *obj); +EAPI void elm_widget_focus_move_policy_automatic_set(Evas_Object *obj, Eina_Bool automatic); EAPI void elm_widget_focus_region_show_mode_set(Evas_Object *obj, Elm_Focus_Region_Show_Mode mode); EAPI Elm_Focus_Region_Show_Mode elm_widget_focus_region_show_mode_get(const Evas_Object *obj); +EAPI void elm_widget_focus_reconfigure(Evas_Object *obj); /** * Function to operate on a given widget's scrollabe children when necessary. diff --git a/src/lib/elm_win.c b/src/lib/elm_win.c index c7b23daa9..f903154b2 100644 --- a/src/lib/elm_win.c +++ b/src/lib/elm_win.c @@ -2547,6 +2547,16 @@ _elm_win_translate(void) elm_widget_translate(obj); } +void +_elm_win_focus_reconfigure(void) +{ + const Eina_List *l; + Evas_Object *obj; + + EINA_LIST_FOREACH(_elm_win_list, l, obj) + elm_widget_focus_reconfigure(obj); +} + #ifdef HAVE_ELEMENTARY_X static Eina_Bool _elm_win_client_message(void *data, -- cgit v1.2.1