diff options
author | Lukasz Stanislawski <l.stanislaws@samsung.com> | 2015-04-17 13:59:08 +0200 |
---|---|---|
committer | Lukasz Stanislawski <l.stanislaws@samsung.com> | 2015-05-15 10:15:27 +0200 |
commit | 015df8afe94011f07883cb6a7bc3a69e7ba7de79 (patch) | |
tree | 90ad7a3a0d4a1bb050e8f5b29b819397bc473542 | |
parent | 9c8ddce6179253487dd01730a55de1f5273b498e (diff) | |
download | elementary-devs/stanluk/relations.tar.gz |
atspi: add new APIs for setting atspi relationship.devs/stanluk/relations
Introduce new APIs elm_object_atspi_relationship_append and
elm_object_atspi_relationship_remove allowing to set developer-defined
accessibility relationships between widgets.
-rw-r--r-- | src/lib/elm_atspi_bridge.c | 11 | ||||
-rw-r--r-- | src/lib/elm_interface_atspi_accessible.c | 102 | ||||
-rw-r--r-- | src/lib/elm_interface_atspi_accessible.eo | 2 | ||||
-rw-r--r-- | src/lib/elm_interface_atspi_accessible.h | 39 | ||||
-rw-r--r-- | src/lib/elm_main.c | 11 | ||||
-rw-r--r-- | src/lib/elm_object.h | 28 | ||||
-rw-r--r-- | src/lib/elm_widget.c | 43 | ||||
-rw-r--r-- | src/lib/elm_widget.eo | 15 | ||||
-rw-r--r-- | src/lib/elm_widget.h | 3 | ||||
-rw-r--r-- | src/tests/elm_test_atspi.c | 84 |
10 files changed, 300 insertions, 38 deletions
diff --git a/src/lib/elm_atspi_bridge.c b/src/lib/elm_atspi_bridge.c index ec9e2db15..4961f3033 100644 --- a/src/lib/elm_atspi_bridge.c +++ b/src/lib/elm_atspi_bridge.c @@ -652,7 +652,8 @@ _accessible_get_relation_set(const Eldbus_Service_Interface *iface EINA_UNUSED, Eldbus_Message *ret = NULL; Eldbus_Message_Iter *iter = NULL, *iter_array = NULL, *iter_array2 = NULL, *iter_struct; Elm_Atspi_Relation *rel; - Eina_List *rels; + Eina_List *l; + Elm_Atspi_Relation_Set rels; ret = eldbus_message_method_return_new(msg); EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL); @@ -663,17 +664,19 @@ _accessible_get_relation_set(const Eldbus_Service_Interface *iface EINA_UNUSED, eo_do(obj, rels = elm_interface_atspi_accessible_relation_set_get()); - EINA_LIST_FREE(rels, rel) + EINA_LIST_FOREACH(rels, l, rel) { + Eo *rel_obj; iter_struct = eldbus_message_iter_container_new(iter_array, 'r', NULL); eldbus_message_iter_basic_append(iter_struct, 'u', _elm_relation_to_atspi_relation(rel->type)); iter_array2 = eldbus_message_iter_container_new(iter_struct, 'a', "(so)"); EINA_SAFETY_ON_NULL_GOTO(iter_array2, fail); - _iter_object_reference_append(iter_array2, rel->obj); + EINA_LIST_FOREACH(rel->objects, l, rel_obj) + _iter_object_reference_append(iter_array2, rel_obj); eldbus_message_iter_container_close(iter_struct, iter_array2); eldbus_message_iter_container_close(iter_array, iter_struct); - free(rel); } + elm_atspi_relation_set_free(&rels); eldbus_message_iter_container_close(iter, iter_array); return ret; diff --git a/src/lib/elm_interface_atspi_accessible.c b/src/lib/elm_interface_atspi_accessible.c index 36e0cc042..ac0480072 100644 --- a/src/lib/elm_interface_atspi_accessible.c +++ b/src/lib/elm_interface_atspi_accessible.c @@ -262,12 +262,13 @@ _elm_interface_atspi_accessible_state_set_get(Eo *obj EINA_UNUSED, void *pd EINA return ret; } -EOLIAN Eina_List* +EOLIAN Elm_Atspi_Relation_Set _elm_interface_atspi_accessible_relation_set_get(Eo *obj EINA_UNUSED, void *pd EINA_UNUSED) { + Elm_Atspi_Relation_Set ret = 0; WRN("The %s object does not implement the \"accessible_relation_set\" function.", eo_class_name_get(eo_class_get(obj))); - return NULL; + return ret; } EAPI void elm_atspi_attributes_list_free(Eina_List *list) @@ -281,4 +282,101 @@ EAPI void elm_atspi_attributes_list_free(Eina_List *list) } } +EAPI void elm_atspi_relation_free(Elm_Atspi_Relation *relation) +{ + eina_list_free(relation->objects); + free(relation); +} + +EAPI Elm_Atspi_Relation *elm_atspi_relation_clone(const Elm_Atspi_Relation *relation) +{ + Elm_Atspi_Relation *ret = calloc(sizeof(Elm_Atspi_Relation), 1); + ret->type = relation->type; + ret->objects = eina_list_clone(relation->objects); + return ret; +} + +EAPI Eina_Bool elm_atspi_relation_set_relation_append(Elm_Atspi_Relation_Set *set, Elm_Atspi_Relation_Type type, const Eo *rel_obj) +{ + Elm_Atspi_Relation *rel; + Eina_List *l; + + if (!eo_isa(rel_obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN)) + return EINA_FALSE; + + EINA_LIST_FOREACH(*set, l, rel) + { + if (rel->type == type) + { + if (!eina_list_data_find(rel->objects, rel_obj)) + rel->objects = eina_list_append(rel->objects, rel_obj); + return EINA_TRUE; + } + } + + rel = calloc(sizeof(Elm_Atspi_Relation), 1); + rel->type = type; + rel->objects = eina_list_append(rel->objects, rel_obj); + *set = eina_list_append(*set, rel); + return EINA_TRUE; +} + +EAPI void elm_atspi_relation_set_relation_remove(Elm_Atspi_Relation_Set *set, Elm_Atspi_Relation_Type type, const Eo *rel_obj) +{ + Eina_List *l; + Elm_Atspi_Relation *rel; + + EINA_LIST_FOREACH(*set, l, rel) + { + if (rel->type == type) + { + rel->objects = eina_list_remove(rel->objects, rel_obj); + if (!rel->objects) + { + *set = eina_list_remove(*set, rel); + elm_atspi_relation_free(rel); + } + return; + } + } +} + +EAPI void elm_atspi_relation_set_relation_type_remove(Elm_Atspi_Relation_Set *set, Elm_Atspi_Relation_Type type) +{ + Eina_List *l; + Elm_Atspi_Relation *rel; + + EINA_LIST_FOREACH(*set, l, rel) + { + if (rel->type == type) + { + *set = eina_list_remove(*set, rel); + elm_atspi_relation_free(rel); + return; + } + } +} + +EAPI void elm_atspi_relation_set_free(Elm_Atspi_Relation_Set *set) +{ + Elm_Atspi_Relation *rel; + EINA_LIST_FREE(*set, rel) + elm_atspi_relation_free(rel); +} + +EAPI Elm_Atspi_Relation_Set elm_atspi_relation_set_clone(const Elm_Atspi_Relation_Set *set) +{ + Elm_Atspi_Relation_Set ret = NULL; + Eina_List *l; + Elm_Atspi_Relation *rel; + + EINA_LIST_FOREACH(*set, l, rel) + { + Elm_Atspi_Relation *cpy = elm_atspi_relation_clone(rel); + ret = eina_list_append(ret, cpy); + } + + return ret; +} + #include "elm_interface_atspi_accessible.eo.c" diff --git a/src/lib/elm_interface_atspi_accessible.eo b/src/lib/elm_interface_atspi_accessible.eo index 9556e5739..5e0c1b3e1 100644 --- a/src/lib/elm_interface_atspi_accessible.eo +++ b/src/lib/elm_interface_atspi_accessible.eo @@ -29,7 +29,7 @@ mixin Elm_Interface_Atspi_Accessible () elements Should be free by a user. */ } values { - own(list<own(Elm_Atspi_Relation *)> *) relations; + Elm_Atspi_Relation_Set relations; } } @property role @protected { diff --git a/src/lib/elm_interface_atspi_accessible.h b/src/lib/elm_interface_atspi_accessible.h index acd152e1b..293a79f08 100644 --- a/src/lib/elm_interface_atspi_accessible.h +++ b/src/lib/elm_interface_atspi_accessible.h @@ -246,16 +246,53 @@ typedef struct _Elm_Atspi_Attribute Elm_Atspi_Attribute; struct _Elm_Atspi_Relation { Elm_Atspi_Relation_Type type; - const Eo *obj; + Eina_List *objects; }; typedef struct _Elm_Atspi_Relation Elm_Atspi_Relation; +typedef Eina_List *Elm_Atspi_Relation_Set; + /** * Free Elm_Atspi_Attributes_List */ EAPI void elm_atspi_attributes_list_free(Eina_List *list); +/** + * Free Elm_Atspi_Relation + */ +EAPI void elm_atspi_relation_free(Elm_Atspi_Relation *rel); + +/** + * Clones relation + */ +EAPI Elm_Atspi_Relation *elm_atspi_relation_clone(const Elm_Atspi_Relation *relation); + +/** + * Appends relation to relation set + */ +EAPI Eina_Bool elm_atspi_relation_set_relation_append(Elm_Atspi_Relation_Set *set, Elm_Atspi_Relation_Type type, const Eo *rel_obj); + +/** + * Removes relation from relation set + */ +EAPI void elm_atspi_relation_set_relation_remove(Elm_Atspi_Relation_Set *set, Elm_Atspi_Relation_Type type, const Eo *rel_obj); + +/** + * Removes all relation from relation set of a given type + */ +EAPI void elm_atspi_relation_set_relation_type_remove(Elm_Atspi_Relation_Set *set, Elm_Atspi_Relation_Type type); + +/** + * Frees Elm_Atspi_State_Set + */ +EAPI void elm_atspi_relation_set_free(Elm_Atspi_Relation_Set *set); + +/** + * Makes a deep copy of Elm_Atspi_State_Set + */ +EAPI Elm_Atspi_Relation_Set elm_atspi_relation_set_clone(const Elm_Atspi_Relation_Set *set); + #ifdef EFL_EO_API_SUPPORT /** diff --git a/src/lib/elm_main.c b/src/lib/elm_main.c index c1f57c777..4ec0aa263 100644 --- a/src/lib/elm_main.c +++ b/src/lib/elm_main.c @@ -1731,3 +1731,14 @@ elm_object_focused_item_get(const Evas_Object *obj) return elm_widget_focused_item_get(obj); } +EAPI Eina_Bool +elm_object_atspi_relationship_append(Evas_Object *obj, Elm_Atspi_Relation_Type type, const Evas_Object *relation_obj) +{ + return elm_widget_atspi_relationship_append(obj, type, relation_obj); +} + +EAPI void +elm_object_atspi_relationship_remove(Evas_Object *obj, Elm_Atspi_Relation_Type type, const Evas_Object *relation_obj) +{ + elm_widget_atspi_relationship_remove(obj, type, relation_obj); +} diff --git a/src/lib/elm_object.h b/src/lib/elm_object.h index df066d07b..e94664175 100644 --- a/src/lib/elm_object.h +++ b/src/lib/elm_object.h @@ -508,3 +508,31 @@ EAPI void elm_object_orientation_mode_disabled_set(Evas_Object *obj, Eina */ EAPI Eina_Bool elm_object_orientation_mode_disabled_get(const Evas_Object *obj); +#ifdef ELM_BETA_API_SUPPORT + +/** + * Set ATSPI2 relationship between two elementary widgets. + * + * @param obj The Elementary widget. + * @param type Type of relationship. + * @param relation_obj object being second side of the relation. + * + * @since 1.15 + * + * @ingroup General + */ +EAPI Eina_Bool elm_object_atspi_relationship_append(Evas_Object *obj, Elm_Atspi_Relation_Type type, Evas_Object *relation_obj); + +/** + * Removes ATSPI2 relationship between widgets. + * + * @param obj The Elementary widget. + * @param type Type of relationship. + * @param relation_obj object being second side of the relation. + * + * @since 1.15 + * + * @ingroup General + */ +EAPI void elm_object_atspi_relationship_remove(Evas_Object *obj, Elm_Atspi_Relation_Type type, Evas_Object *relation_obj); +#endif diff --git a/src/lib/elm_widget.c b/src/lib/elm_widget.c index 27221d55b..44e03fced 100644 --- a/src/lib/elm_widget.c +++ b/src/lib/elm_widget.c @@ -5456,6 +5456,9 @@ _elm_widget_eo_base_destructor(Eo *obj, Elm_Widget_Smart_Data *sd) if (parent && !eo_destructed_is(parent)) elm_interface_atspi_accessible_children_changed_del_signal_emit(parent, obj); + if (sd->atspi_custom_relations) + elm_atspi_relation_set_free(&sd->atspi_custom_relations); + eo_do_super(obj, ELM_WIDGET_CLASS, eo_destructor()); } @@ -5662,40 +5665,22 @@ _elm_widget_elm_interface_atspi_accessible_attributes_get(Eo *obj, Elm_Widget_Sm return ret; } -static Elm_Atspi_Relation* -_relation_new(Elm_Atspi_Relation_Type type, Eo *obj) +EOLIAN static Elm_Atspi_Relation_Set +_elm_widget_elm_interface_atspi_accessible_relation_set_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd) { - Elm_Atspi_Relation *rel = calloc(1, sizeof(Elm_Atspi_Relation)); - if (!rel) return NULL; - - rel->type = type; - rel->obj = obj; - - return rel; + return elm_atspi_relation_set_clone(&sd->atspi_custom_relations); } -EOLIAN static Eina_List* -_elm_widget_elm_interface_atspi_accessible_relation_set_get(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED) +EOLIAN static Eina_Bool +_elm_widget_atspi_relationship_append(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Atspi_Relation_Type type, const Eo *relation_obj) { - Eina_List *list = NULL; - Elm_Atspi_Relation *rel; - Evas_Object *rel_obj; - - rel_obj = elm_object_focus_next_object_get(obj, ELM_FOCUS_NEXT); - if (eo_isa(rel_obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN)) - { - rel = _relation_new(ELM_ATSPI_RELATION_FLOWS_TO, rel_obj); - list = eina_list_append(list, rel); - } - - rel_obj = elm_object_focus_next_object_get(obj, ELM_FOCUS_PREVIOUS); - if (eo_isa(rel_obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN)) - { - rel = _relation_new(ELM_ATSPI_RELATION_FLOWS_FROM, rel_obj); - list = eina_list_append(list, rel); - } + return elm_atspi_relation_set_relation_append(&sd->atspi_custom_relations, type, relation_obj); +} - return list; +EOLIAN static void +_elm_widget_atspi_relationship_remove(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Atspi_Relation_Type type, const Eo *relation_obj) +{ + elm_atspi_relation_set_relation_remove(&sd->atspi_custom_relations, type, relation_obj); } EOLIAN static void diff --git a/src/lib/elm_widget.eo b/src/lib/elm_widget.eo index 75bc7d924..dd3efe985 100644 --- a/src/lib/elm_widget.eo +++ b/src/lib/elm_widget.eo @@ -790,6 +790,21 @@ abstract Elm.Widget (Evas.Object_Smart, Elm_Interface_Atspi_Accessible, Elm_Inte @in Evas_Object *relative_child @optional; } } + atspi_relationship_append { + /*@ No description supplied by the EAPI. */ + return: bool; + params { + @in Elm_Atspi_Relation_Type type; + @in const(Eo) *relation_object; + } + } + atspi_relationship_remove { + /*@ No description supplied by the EAPI. */ + params { + @in Elm_Atspi_Relation_Type type; + @in const(Eo) *relation_object; + } + } } implements { class.constructor; diff --git a/src/lib/elm_widget.h b/src/lib/elm_widget.h index a0189a80f..5350442de 100644 --- a/src/lib/elm_widget.h +++ b/src/lib/elm_widget.h @@ -410,6 +410,7 @@ typedef struct _Elm_Widget_Smart_Data int role; /**< Accessibility role */ const char *description; /**< Accessibility description */ Eo *atspi_custom_parent; /**< Accessibility parent if different then parent_obj */ + Elm_Atspi_Relation_Set atspi_custom_relations; /**< Developer-defined accessiblity relations @since 1.15 */ /* this is a hook to be set on-the-fly on widgets. this is code * handling the request of showing a specific region from an inner @@ -776,6 +777,8 @@ EAPI Elm_Object_Item *elm_widget_focused_item_get(const Evas_Object *obj); EAPI void elm_widget_orientation_mode_disabled_set(Evas_Object *obj, Eina_Bool disabled); EAPI Eina_Bool elm_widget_orientation_mode_disabled_get(const Evas_Object *obj); EAPI void elm_widget_focus_highlight_geometry_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h); +EAPI Eina_Bool elm_widget_atspi_relationship_append(Evas_Object *obj, Elm_Atspi_Relation_Type type, const Evas_Object *relation_obj); +EAPI void elm_widget_atspi_relationship_remove(Evas_Object *obj, Elm_Atspi_Relation_Type type, const Evas_Object *relation_obj); void _elm_widget_item_highlight_in_theme(Evas_Object *obj, Elm_Object_Item *it); /** diff --git a/src/tests/elm_test_atspi.c b/src/tests/elm_test_atspi.c index da616ff07..e4e18fc3c 100644 --- a/src/tests/elm_test_atspi.c +++ b/src/tests/elm_test_atspi.c @@ -9,7 +9,7 @@ #include "elm_priv.h" #include "elm_suite.h" -static Evas_Object *g_win, *g_btn, *g_bg; +static Evas_Object *g_win, *g_btn, *g_bg, *g_btn2, *g_btn3, *g_box, *g_lbl; void generate_app(void) { @@ -25,6 +25,34 @@ void generate_app(void) evas_object_show(g_win); } +void generate_app2(void) +{ + g_win = elm_win_add(NULL, "Title", ELM_WIN_BASIC); + evas_object_geometry_set(g_win, 100, 100, 100, 100); + + g_bg = elm_bg_add(g_win); + + g_box = elm_box_add(g_win); + + g_btn = elm_button_add(g_win); + g_btn2 = elm_button_add(g_win); + g_btn3 = elm_button_add(g_win); + g_lbl = elm_label_add(g_win); + + elm_box_pack_end(g_box, g_btn); + elm_box_pack_end(g_box, g_btn2); + elm_box_pack_end(g_box, g_btn3); + elm_box_pack_end(g_box, g_lbl); + + evas_object_show(g_btn); + evas_object_show(g_bg); + evas_object_show(g_win); + evas_object_show(g_box); + evas_object_show(g_btn2); + evas_object_show(g_btn3); + evas_object_show(g_lbl); +} + START_TEST (elm_atspi_name_get) { elm_init(0, NULL); @@ -184,6 +212,59 @@ START_TEST (elm_atspi_children_and_parent2) } END_TEST +START_TEST (elm_atspi_elm_widget_custom_relations) +{ + Elm_Atspi_Relation_Set set; + Elm_Atspi_Relation *rel, *rel_to, *rel_from; + Eina_List *l; + + elm_init(0, NULL); + generate_app2(); + + eo_do(g_btn, set = elm_interface_atspi_accessible_relation_set_get()); + ck_assert(set == NULL); + + elm_widget_atspi_relationship_append(g_btn, ELM_ATSPI_RELATION_FLOWS_TO, g_lbl); + elm_widget_atspi_relationship_append(g_btn, ELM_ATSPI_RELATION_FLOWS_FROM, g_win); + + eo_do(g_btn, set = elm_interface_atspi_accessible_relation_set_get()); + ck_assert(set != NULL); + ck_assert(eina_list_count(set) >= 2); + + rel_to = rel_from = NULL; + EINA_LIST_FOREACH(set, l, rel) + { + if (rel->type == ELM_ATSPI_RELATION_FLOWS_TO) + rel_to = rel; + if (rel->type == ELM_ATSPI_RELATION_FLOWS_FROM) + rel_from = rel; + } + + ck_assert(rel_to != NULL); + ck_assert(rel_from != NULL); + ck_assert(eina_list_data_find(rel_to->objects, g_lbl) != NULL); + ck_assert(eina_list_data_find(rel_from->objects, g_win) != NULL); + + elm_atspi_relation_set_free(&set); + + elm_widget_atspi_relationship_remove(g_btn, ELM_ATSPI_RELATION_FLOWS_TO, g_lbl); + eo_do(g_btn, set = elm_interface_atspi_accessible_relation_set_get()); + ck_assert(set != NULL); + ck_assert(eina_list_count(set) >= 1); + + rel_to = rel_from = NULL; + EINA_LIST_FOREACH(set, l, rel) + { + if (rel->type == ELM_ATSPI_RELATION_FLOWS_TO) + ck_assert(EINA_FALSE); + } + + elm_atspi_relation_set_free(&set); + + elm_shutdown(); +} +END_TEST + void elm_test_atspi(TCase *tc) { tcase_add_test(tc, elm_atspi_name_get); @@ -193,4 +274,5 @@ void elm_test_atspi(TCase *tc) tcase_add_test(tc, elm_atspi_description_set); tcase_add_test(tc, elm_atspi_children_and_parent); tcase_add_test(tc, elm_atspi_children_and_parent2); + tcase_add_test(tc, elm_atspi_elm_widget_custom_relations); } |