diff --git a/legacy/elementary/ChangeLog b/legacy/elementary/ChangeLog index 88d211ffdf..481a6c1de8 100644 --- a/legacy/elementary/ChangeLog +++ b/legacy/elementary/ChangeLog @@ -1487,3 +1487,7 @@ * Change the method to calculate a distance which be scrolled from linear to sine curve. And add the configuration thumbscroll_flick_distance_tolerance. It's the max flick distance. + +2013-07-06 Shinwoo Kim + + * Add elm_access_highlight_next_set, export elm_widget_focus_region_show diff --git a/legacy/elementary/NEWS b/legacy/elementary/NEWS index fb6563f268..235910b2d3 100644 --- a/legacy/elementary/NEWS +++ b/legacy/elementary/NEWS @@ -79,6 +79,7 @@ Additions: * Add the elm_scrollable_interface_content_viewport_resize_cb_set. * added callback call "scroll", "scroll,anim,start", "scroll,anim,stop", "scroll,drag,start", "scroll,drag,stop" in toolar widget. * Add the configuration thumbscroll_flick_distance_tolerance. + * Add elm_access_highlight_next_set, export elm_widget_focus_region_show Improvements: diff --git a/legacy/elementary/data/objects/test.edc b/legacy/elementary/data/objects/test.edc index d03b342f31..6c303334d5 100644 --- a/legacy/elementary/data/objects/test.edc +++ b/legacy/elementary/data/objects/test.edc @@ -803,4 +803,52 @@ collections { } } } + group { name: "access_color_page"; + parts { + part { name: "red"; type: RECT; + description { state: "default" 0.0; + rel1 { relative: 0.1 0.1; + } + rel2 { relative: 0.35 0.35; + } + color: 255 0 0 255; + } + } + part { name: "green"; type: RECT; + description { state: "default" 0.0; + rel1 { relative: 0.65 0.1; + } + rel2 { relative: 0.9 0.35; + } + color: 0 255 0 255; + } + } + part { name: "blue"; type: RECT; + description { state: "default" 0.0; + rel1 { relative: 0.1 0.65; + } + rel2 { relative: 0.35. 0.9; + } + color: 0 0 255 255; + } + } + part { name: "black"; type: RECT; + description { state: "default" 0.0; + rel1 { relative: 0.65 0.65; + } + rel2 { relative: 0.9 0.9; + } + color: 0 0 0 255; + } + } + part { name: "center"; type: SWALLOW; + description { state: "default" 0.0; + rel1 { relative: 0.35 0.35; + } + rel2 { relative: 0.65 0.65; + } + } + } + } + } } diff --git a/legacy/elementary/src/bin/test.c b/legacy/elementary/src/bin/test.c index 67804b7dd9..339610a8f2 100644 --- a/legacy/elementary/src/bin/test.c +++ b/legacy/elementary/src/bin/test.c @@ -12,6 +12,7 @@ int _log_domain = -1; /* all tests prototypes */ void test_access(void *data, Evas_Object *obj, void *event_info); void test_access2(void *data, Evas_Object *obj, void *event_info); +void test_access3(void *data, Evas_Object *obj, void *event_info); void test_bg_plain(void *data, Evas_Object *obj, void *event_info); void test_bg_image(void *data, Evas_Object *obj, void *event_info); void test_bg_options(void *data, Evas_Object *obj, void *event_info); @@ -764,6 +765,7 @@ add_tests: ADD_TEST(NULL, "Miscellaneous", "Configuration", test_config); ADD_TEST(NULL, "Miscellaneous", "Accessibility", test_access); ADD_TEST(NULL, "Miscellaneous", "Accessibility2", test_access2); + ADD_TEST(NULL, "Miscellaneous", "Accessibility3", test_access3); #undef ADD_TEST diff --git a/legacy/elementary/src/bin/test_access.c b/legacy/elementary/src/bin/test_access.c index 8d02ca9e7f..5acb97caa3 100644 --- a/legacy/elementary/src/bin/test_access.c +++ b/legacy/elementary/src/bin/test_access.c @@ -305,4 +305,87 @@ test_access2(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_inf evas_object_resize(win, 300, 300); evas_object_show(win); } + +static Eina_Bool +_key_down_cb(void *data, int type __UNUSED__, void *ei) +{ + Elm_Access_Action_Info *a; + Ecore_Event_Key *ev = ei; + + a = calloc(1, sizeof(Elm_Access_Action_Info)); + if (!a) return EINA_TRUE; + + if (ev && ev->keyname) + { + if (!strcmp(ev->keyname, "F1")) + { + a->highlight_cycle = EINA_TRUE; + elm_access_action(data, ELM_ACCESS_ACTION_HIGHLIGHT_NEXT, a); + free(a); + } + } + return EINA_TRUE; +} + +static char * +_access_info_cb(void *data, Evas_Object *obj __UNUSED__) +{ + if (data) return strdup(data); + return NULL; +} + +void +test_access3(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + char buf[PATH_MAX]; + Evas_Object *win, *ly, *btn; + Evas_Object *red_ao, *green_ao, *blue_ao, *black_ao, *to; + + win = elm_win_util_standard_add("access", "Access"); + elm_win_autodel_set(win, EINA_TRUE); + evas_object_event_callback_add(win, EVAS_CALLBACK_FREE, _cleanup_cb, NULL); + + elm_config_access_set(EINA_TRUE); + + ly = elm_layout_add(win); + snprintf(buf, sizeof(buf), "%s/objects/test.edj", elm_app_data_dir_get()); + elm_layout_file_set(ly, buf, "access_color_page"); + evas_object_size_hint_weight_set(ly, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(ly, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_show(ly); + + btn = elm_button_add(win); + elm_object_text_set(btn, "action"); + evas_object_size_hint_weight_set(btn, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(btn, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_show(btn); + + elm_object_part_content_set(ly, "center", btn); + + to = (Evas_Object *)edje_object_part_object_get(elm_layout_edje_get(ly), "red"); + red_ao = elm_access_object_register(to, ly); + elm_access_info_cb_set(red_ao, ELM_ACCESS_INFO, _access_info_cb, "red"); + elm_access_highlight_next_set(btn, ELM_HIGHLIGHT_DIR_NEXT, red_ao); + + to = (Evas_Object *)edje_object_part_object_get(elm_layout_edje_get(ly), "green"); + green_ao = elm_access_object_register(to, ly); + elm_access_info_cb_set(green_ao, ELM_ACCESS_INFO, _access_info_cb, "green"); + elm_access_highlight_next_set(red_ao, ELM_HIGHLIGHT_DIR_NEXT, green_ao); + + to = (Evas_Object *)edje_object_part_object_get(elm_layout_edje_get(ly), "blue"); + blue_ao = elm_access_object_register(to, ly); + elm_access_info_cb_set(blue_ao, ELM_ACCESS_INFO, _access_info_cb, "blue"); + elm_access_highlight_next_set(green_ao, ELM_HIGHLIGHT_DIR_NEXT, blue_ao); + + to = (Evas_Object *)edje_object_part_object_get(elm_layout_edje_get(ly), "black"); + black_ao = elm_access_object_register(to, ly); + elm_access_info_cb_set(black_ao, ELM_ACCESS_INFO, _access_info_cb, "black"); + elm_access_highlight_next_set(blue_ao, ELM_HIGHLIGHT_DIR_NEXT, black_ao); + + ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, _key_down_cb, win); + + elm_win_resize_object_add(win, ly); + evas_object_resize(win, 300, 300); + evas_object_show(win); +} #endif diff --git a/legacy/elementary/src/lib/elm_access.c b/legacy/elementary/src/lib/elm_access.c index 7d88085504..9c90d0f3ec 100644 --- a/legacy/elementary/src/lib/elm_access.c +++ b/legacy/elementary/src/lib/elm_access.c @@ -509,26 +509,42 @@ _access_highlight_next_get(Evas_Object *obj, Elm_Focus_Direction dir) _elm_access_read_mode_set(EINA_TRUE); - ret = elm_widget_focus_next_get(obj, dir, &target); - if (ret && target) + if (dir == ELM_FOCUS_NEXT) + type = ELM_ACCESS_ACTION_HIGHLIGHT_NEXT; + else + type = ELM_ACCESS_ACTION_HIGHLIGHT_PREV; + + /* this value is used in _elm_access_object_highlight(); + to inform the target object of how to get highlight */ + action_by = type; + + if (!_access_action_callback_call(ho, type, NULL)) { - if (dir == ELM_FOCUS_NEXT) - type = ELM_ACCESS_ACTION_HIGHLIGHT_NEXT; - else - type = ELM_ACCESS_ACTION_HIGHLIGHT_PREV; - - if (!_access_action_callback_call(ho, type, NULL)) + if (ho) { - /* this value is used in _elm_access_object_highlight(); - to inform the target object of how to get highlight */ - action_by = type; + Elm_Access_Info *info = _elm_access_object_get(ho); + if (type == ELM_ACCESS_ACTION_HIGHLIGHT_NEXT && info->next) + target = info->next; + else if (type == ELM_ACCESS_ACTION_HIGHLIGHT_PREV && info->prev) + target = info->prev; + } + if (target) + { _elm_access_highlight_set(target); - - action_by = ELM_ACCESS_ACTION_FIRST; + elm_widget_focus_region_show(target); + ret = EINA_TRUE; + } + else + { + ret = elm_widget_focus_next_get(obj, dir, &target); + if (ret && target) + _elm_access_highlight_set(target); } } + action_by = ELM_ACCESS_ACTION_FIRST; + _elm_access_read_mode_set(EINA_FALSE); return ret; @@ -659,8 +675,27 @@ _elm_access_highlight_cycle(Evas_Object *obj, Elm_Focus_Direction dir) action_by = type; - if (!_access_action_callback_call(ho, type, NULL)) - elm_widget_focus_cycle(obj, dir); + if (!ho) elm_widget_focus_cycle(obj, dir); + else if (!_access_action_callback_call(ho, type, NULL)) + { + Elm_Access_Info *info = _elm_access_object_get(ho); + Evas_Object *comming = NULL; + if (type == ELM_ACCESS_ACTION_HIGHLIGHT_NEXT) + { + if ((info) && (info->next)) comming = info->next; + } + else + { + if ((info) && (info->prev)) comming = info->prev; + } + if (comming) + { + _elm_access_highlight_set(comming); + elm_widget_focus_region_show(comming); + } + else + elm_widget_focus_cycle(obj, dir); + } action_by = ELM_ACCESS_ACTION_FIRST; @@ -1287,6 +1322,35 @@ elm_access_external_info_get(const Evas_Object *obj) return _elm_access_text_get(ac, ELM_ACCESS_CONTEXT_INFO, obj); } +EAPI void +elm_access_highlight_next_set(Evas_Object *obj, Elm_Highlight_Direction dir, Evas_Object *next) +{ + EINA_SAFETY_ON_FALSE_RETURN(obj); + EINA_SAFETY_ON_FALSE_RETURN(next); + + Elm_Access_Info *info = _elm_access_object_get(obj); + Elm_Access_Info *info_next = _elm_access_object_get(next); + + if (!info || !info_next) + { + ERR("There is no access information"); + return; + } + + if (dir == ELM_HIGHLIGHT_DIR_NEXT) + { + info_next->prev = obj; + info->next = next; + } + else if (dir == ELM_HIGHLIGHT_DIR_PREVIOUS) + { + info_next->next = obj; + info->prev = next; + } + else + ERR("Not supported focus direction for access highlight [%d]", dir); +} + static void _elm_access_smart_access(Eo *obj, void *_pd EINA_UNUSED, va_list *list) { diff --git a/legacy/elementary/src/lib/elm_access.h b/legacy/elementary/src/lib/elm_access.h index dba781b20c..8125b369b1 100644 --- a/legacy/elementary/src/lib/elm_access.h +++ b/legacy/elementary/src/lib/elm_access.h @@ -78,6 +78,19 @@ struct _Elm_Access_Action_Info */ typedef struct _Elm_Access_Action_Info Elm_Access_Action_Info; +enum _Elm_Highlight_Direction +{ + ELM_HIGHLIGHT_DIR_FIRST = -1, + ELM_HIGHLIGHT_DIR_NEXT, + ELM_HIGHLIGHT_DIR_PREVIOUS +}; + +/** + * @since 1.8 + * @typedef Elm_Highlight_Direction + */ +typedef enum _Elm_Highlight_Direction Elm_Highlight_Direction; + /** * @since 1.8 * @typedef Elm_Access_Action_Cb @@ -241,3 +254,21 @@ EAPI Eina_Bool elm_access_action(Evas_Object *obj, const Elm_Access_Action_Type * @ingroup Access */ EAPI void elm_access_action_cb_set(Evas_Object *obj, const Elm_Access_Action_Type type, const Elm_Access_Action_Cb cb, const void *data); + +/** + * @brief Set the next access object for highlight. + * @since 1.8 + * + * @param obj The object is previous access object of next for hilight. + * @param dir Access direction same as Focus direction + * @param next The object is next access object of obj for hilight. + * + * Currently focus chain is used for access highlight chain. Use this API to + * customize highlight chain. If highlight chain is already established, you can + * change one object's highlight chain and do not break the other object's + * highlight chain. + * + * @ingroup Access + */ +EAPI void +elm_access_highlight_next_set(Evas_Object *obj, Elm_Highlight_Direction dir, Evas_Object *next); diff --git a/legacy/elementary/src/lib/elm_widget.c b/legacy/elementary/src/lib/elm_widget.c index 051a6abb3c..54266ee58a 100644 --- a/legacy/elementary/src/lib/elm_widget.c +++ b/legacy/elementary/src/lib/elm_widget.c @@ -578,6 +578,12 @@ _propagate_event(void *data, elm_widget_event_propagate(obj, type, event_info, event_flags); } +EAPI void +elm_widget_focus_region_show(const Evas_Object *obj) +{ + ELM_WIDGET_CHECK(obj); + eo_do((Eo *) obj, elm_wdg_focus_region_show()); +} /** * @internal * @@ -585,13 +591,11 @@ _propagate_event(void *data, * ignore region show action. */ static void -_elm_widget_focus_region_show(const Evas_Object *obj) +_elm_widget_focus_region_show(Eo *obj, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED) { Evas_Coord x, y, w, h, ox, oy; Evas_Object *o; - API_ENTRY return; - o = elm_widget_parent_get(obj); if (!o) return; @@ -650,7 +654,7 @@ _parent_focus(Evas_Object *obj) { sd->focused = EINA_TRUE; eo_do(obj, elm_wdg_on_focus(NULL)); - _elm_widget_focus_region_show(obj); + elm_widget_focus_region_show(obj); } sd->focus_order_on_calc = EINA_FALSE; @@ -2027,7 +2031,7 @@ _elm_widget_focus_cycle(Eo *obj, void *_pd EINA_UNUSED, va_list *list) if (_elm_config->access_mode && _elm_access_read_mode_get()) { _elm_access_highlight_set(target); - _elm_widget_focus_region_show(target); + elm_widget_focus_region_show(target); } else elm_widget_focus_steal(target); } @@ -6070,6 +6074,7 @@ _class_constructor(Eo_Class *klass) EO_OP_FUNC(ELM_WIDGET_ID(ELM_WIDGET_SUB_ID_FOCUS_DISABLED_HANDLE), _elm_widget_focus_disabled_handle), EO_OP_FUNC(ELM_WIDGET_ID(ELM_WIDGET_SUB_ID_FOCUS_ORDER_GET), _elm_widget_focus_order_get), EO_OP_FUNC(ELM_WIDGET_ID(ELM_WIDGET_SUB_ID_FOCUS_REGION_GET), _elm_widget_focus_region_get), + EO_OP_FUNC(ELM_WIDGET_ID(ELM_WIDGET_SUB_ID_FOCUS_REGION_SHOW), _elm_widget_focus_region_show), EO_OP_FUNC(ELM_WIDGET_ID(ELM_WIDGET_SUB_ID_THEME_OBJECT_SET), _elm_widget_theme_object_set), @@ -6217,6 +6222,7 @@ static const Eo_Op_Description op_desc[] = { EO_OP_DESCRIPTION(ELM_WIDGET_SUB_ID_FOCUS_DISABLED_HANDLE, "description here"), EO_OP_DESCRIPTION(ELM_WIDGET_SUB_ID_FOCUS_ORDER_GET, "description here"), EO_OP_DESCRIPTION(ELM_WIDGET_SUB_ID_FOCUS_REGION_GET, "Get the focus region of the given widget."), + EO_OP_DESCRIPTION(ELM_WIDGET_SUB_ID_FOCUS_REGION_SHOW, "Show the focus region of the given widget."), EO_OP_DESCRIPTION(ELM_WIDGET_SUB_ID_THEME_OBJECT_SET, "description here"), EO_OP_DESCRIPTION(ELM_WIDGET_SUB_ID_ORIENTATION_SET, "description here"), diff --git a/legacy/elementary/src/lib/elm_widget.h b/legacy/elementary/src/lib/elm_widget.h index 0a24c9ec6a..20bb47a3b4 100644 --- a/legacy/elementary/src/lib/elm_widget.h +++ b/legacy/elementary/src/lib/elm_widget.h @@ -493,6 +493,9 @@ struct _Elm_Access_Info /* the owner part object that owns this access info */ Evas_Object *part_object; + + Evas_Object *next; + Evas_Object *prev; }; void _elm_access_shutdown(); @@ -664,6 +667,7 @@ EAPI Eina_Bool elm_widget_disabled_get(const Evas_Object *obj); EAPI void elm_widget_show_region_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h, Eina_Bool forceshow); EAPI void elm_widget_show_region_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h); EAPI Eina_Bool elm_widget_focus_region_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h); +EAPI void elm_widget_focus_region_show(const Evas_Object *obj); EAPI void elm_widget_parents_bounce_get(Evas_Object *obj, Eina_Bool *horiz, Eina_Bool *vert); EAPI void elm_widget_scroll_hold_push(Evas_Object *obj); EAPI void elm_widget_scroll_hold_pop(Evas_Object *obj); @@ -1141,6 +1145,7 @@ enum ELM_WIDGET_SUB_ID_FOCUS_DISABLED_HANDLE, ELM_WIDGET_SUB_ID_FOCUS_ORDER_GET, ELM_WIDGET_SUB_ID_FOCUS_REGION_GET, + ELM_WIDGET_SUB_ID_FOCUS_REGION_SHOW, ELM_WIDGET_SUB_ID_THEME_OBJECT_SET, ELM_WIDGET_SUB_ID_ORIENTATION_SET, @@ -2232,6 +2237,14 @@ typedef void * (*list_data_get_func_type)(const Eina_List * l); */ #define elm_wdg_focus_region_get(x, y, w, h, ret) ELM_WIDGET_ID(ELM_WIDGET_SUB_ID_FOCUS_REGION_GET), EO_TYPECHECK(Evas_Coord *, x), EO_TYPECHECK(Evas_Coord *, y), EO_TYPECHECK(Evas_Coord *, w), EO_TYPECHECK(Evas_Coord *, h), EO_TYPECHECK(Eina_Bool *, ret) +/** + * @def elm_wdg_focus_region_show + * @since 1.8 + * + * No description supplied by the EAPI. + * + */ +#define elm_wdg_focus_region_show() ELM_WIDGET_ID(ELM_WIDGET_SUB_ID_FOCUS_REGION_SHOW) /** * @def elm_wdg_theme_object_set