forked from enlightenment/efl
atspi: add new relationship append/remove/clear API
Allow to add some extra contextul information about accessibility objects which can be used by Assistive Technology to provide better user experience. API is still marked as beta. @feature
This commit is contained in:
parent
83fd91edf5
commit
0c8a75442a
|
@ -786,11 +786,12 @@ _accessible_get_relation_set(const Eldbus_Service_Interface *iface EINA_UNUSED,
|
|||
{
|
||||
const char *obj_path = eldbus_message_path_get(msg);
|
||||
Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
|
||||
Eo *obj = _bridge_object_from_path(bridge, obj_path);
|
||||
Eo *rel_obj, *obj = _bridge_object_from_path(bridge, obj_path);
|
||||
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, *l2;
|
||||
Elm_Atspi_Relation_Set rels;
|
||||
|
||||
ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
|
||||
|
||||
|
@ -803,17 +804,18 @@ _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)
|
||||
{
|
||||
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);
|
||||
_bridge_iter_object_reference_append(bridge, iter_array2, rel->obj);
|
||||
EINA_LIST_FOREACH(rel->objects, l2, rel_obj)
|
||||
_bridge_iter_object_reference_append(bridge, 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;
|
||||
|
|
|
@ -127,6 +127,7 @@ struct _Elm_Interface_Atspi_Accessible_Data
|
|||
const char *name;
|
||||
const char *description;
|
||||
const char *translation_domain;
|
||||
Elm_Atspi_Relation_Set relations;
|
||||
Elm_Interface_Atspi_Accessible *parent;
|
||||
};
|
||||
|
||||
|
@ -290,12 +291,10 @@ _elm_interface_atspi_accessible_state_set_get(Eo *obj EINA_UNUSED, Elm_Interface
|
|||
return 0;
|
||||
}
|
||||
|
||||
EOLIAN Eina_List*
|
||||
EOLIAN Elm_Atspi_Relation_Set
|
||||
_elm_interface_atspi_accessible_relation_set_get(Eo *obj EINA_UNUSED, Elm_Interface_Atspi_Accessible_Data *pd EINA_UNUSED)
|
||||
{
|
||||
WRN("The %s object does not implement the \"accessible_relation_set\" function.",
|
||||
eo_class_name_get(eo_class_get(obj)));
|
||||
return NULL;
|
||||
return elm_atspi_relation_set_clone(pd->relations);
|
||||
}
|
||||
|
||||
EAPI void elm_atspi_attributes_list_free(Eina_List *list)
|
||||
|
@ -369,4 +368,177 @@ _elm_interface_atspi_accessible_translation_domain_get(Eo *obj EINA_UNUSED, Elm_
|
|||
return pd->translation_domain;
|
||||
}
|
||||
|
||||
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);
|
||||
if (!ret) return NULL;
|
||||
|
||||
ret->type = relation->type;
|
||||
ret->objects = eina_list_clone(relation->objects);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_on_rel_obj_del(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
|
||||
{
|
||||
Elm_Atspi_Relation_Set *set = data;
|
||||
Elm_Atspi_Relation *rel;
|
||||
Eina_List *l, *l2, *p, *p2;
|
||||
Eo *rel_obj;
|
||||
|
||||
EINA_LIST_FOREACH_SAFE(*set, l, l2, rel)
|
||||
{
|
||||
EINA_LIST_FOREACH_SAFE(rel->objects, p, p2, rel_obj)
|
||||
{
|
||||
if (rel_obj == obj)
|
||||
rel->objects = eina_list_remove_list(rel->objects, p);
|
||||
}
|
||||
if (!rel->objects)
|
||||
{
|
||||
*set = eina_list_remove_list(*set, l);
|
||||
free(rel);
|
||||
}
|
||||
}
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
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);
|
||||
eo_do(rel_obj, eo_event_callback_add(EO_BASE_EVENT_DEL, _on_rel_obj_del, set));
|
||||
}
|
||||
return EINA_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
rel = calloc(sizeof(Elm_Atspi_Relation), 1);
|
||||
if (!rel) return EINA_FALSE;
|
||||
|
||||
rel->type = type;
|
||||
rel->objects = eina_list_append(rel->objects, rel_obj);
|
||||
*set = eina_list_append(*set, rel);
|
||||
|
||||
eo_do(rel_obj, eo_event_callback_add(EO_BASE_EVENT_DEL, _on_rel_obj_del, set));
|
||||
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)
|
||||
{
|
||||
if (eina_list_data_find(rel->objects, rel_obj))
|
||||
{
|
||||
eo_do(rel_obj, eo_event_callback_del(EO_BASE_EVENT_DEL, _on_rel_obj_del, set));
|
||||
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;
|
||||
Eo *obj;
|
||||
|
||||
EINA_LIST_FOREACH(*set, l, rel)
|
||||
{
|
||||
if (rel->type == type)
|
||||
{
|
||||
EINA_LIST_FOREACH(rel->objects, l, obj)
|
||||
eo_do(obj, eo_event_callback_del(EO_BASE_EVENT_DEL, _on_rel_obj_del, set));
|
||||
*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 *l;
|
||||
Eo *obj;
|
||||
|
||||
EINA_LIST_FREE(set, rel)
|
||||
{
|
||||
EINA_LIST_FOREACH(rel->objects, l, obj)
|
||||
eo_do(obj, eo_event_callback_del(EO_BASE_EVENT_DEL, _on_rel_obj_del, set));
|
||||
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;
|
||||
}
|
||||
|
||||
EOLIAN static Eina_Bool
|
||||
_elm_interface_atspi_accessible_relationship_append(Eo *obj EINA_UNUSED, Elm_Interface_Atspi_Accessible_Data *sd, Elm_Atspi_Relation_Type type, const Elm_Interface_Atspi_Accessible *relation_obj)
|
||||
{
|
||||
return elm_atspi_relation_set_relation_append(&sd->relations, type, relation_obj);
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_elm_interface_atspi_accessible_relationship_remove(Eo *obj EINA_UNUSED, Elm_Interface_Atspi_Accessible_Data *sd, Elm_Atspi_Relation_Type type, const Elm_Interface_Atspi_Accessible *relation_obj)
|
||||
{
|
||||
if (relation_obj)
|
||||
elm_atspi_relation_set_relation_remove(&sd->relations, type, relation_obj);
|
||||
else
|
||||
elm_atspi_relation_set_relation_type_remove(&sd->relations, type);
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_elm_interface_atspi_accessible_relationships_clear(Eo *obj EINA_UNUSED, Elm_Interface_Atspi_Accessible_Data *sd)
|
||||
{
|
||||
elm_atspi_relation_set_free(sd->relations);
|
||||
sd->relations = NULL;
|
||||
}
|
||||
|
||||
#include "elm_interface_atspi_accessible.eo.c"
|
||||
|
|
|
@ -27,7 +27,7 @@ mixin Elm_Interface_Atspi_Accessible ()
|
|||
[[Gets an string describing ATSPI widget role name. Lists and elements Should be free by a user.]]
|
||||
}
|
||||
values {
|
||||
relations: own(list<own(Elm_Atspi_Relation *)> *);
|
||||
relations: Elm_Atspi_Relation_Set;
|
||||
}
|
||||
}
|
||||
@property role @protected {
|
||||
|
@ -147,6 +147,42 @@ mixin Elm_Interface_Atspi_Accessible ()
|
|||
domain: const(char)*; [[ translation domain ]]
|
||||
}
|
||||
}
|
||||
relationship_append @protected {
|
||||
[[Defines the relationship between two accessible objects.
|
||||
|
||||
Adds unique relation between source object and relation_object of a
|
||||
given type.
|
||||
|
||||
Relationships can be queried by Assistive Technology clients to
|
||||
provide customized feedback, improving overall user experience.
|
||||
|
||||
Relationship_append API is asymmetric, which means that
|
||||
appending, for example, relation ELM_ATSPI_RELATION_FLOWS_TO from object A to B,
|
||||
do NOT append relation ELM_ATSPI_RELATION_FLOWS_FROM from object B to
|
||||
object A.
|
||||
|
||||
return: EINA_TRUE is relationship was successfully appended, EINA_FALSE
|
||||
otherwise]]
|
||||
return: bool;
|
||||
params {
|
||||
@in type: Elm_Atspi_Relation_Type;
|
||||
@in relation_object: const(Elm_Interface_Atspi_Accessible)*;
|
||||
}
|
||||
}
|
||||
relationship_remove @protected {
|
||||
[[Removes the relationship between two accessible objects.
|
||||
|
||||
If relation_object is NULL function removes all relations
|
||||
of given type.
|
||||
]]
|
||||
params {
|
||||
@in type: Elm_Atspi_Relation_Type;
|
||||
@in relation_object: const(Elm_Interface_Atspi_Accessible)*;
|
||||
}
|
||||
}
|
||||
relationships_clear @protected {
|
||||
[[Removes all relationships in accessible object.]]
|
||||
}
|
||||
}
|
||||
events {
|
||||
property,changed: const(char)*;
|
||||
|
|
|
@ -252,7 +252,7 @@ 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;
|
||||
|
@ -262,6 +262,43 @@ typedef struct _Elm_Atspi_Relation Elm_Atspi_Relation;
|
|||
*/
|
||||
EAPI void elm_atspi_attributes_list_free(Eina_List *list);
|
||||
|
||||
typedef Eina_List *Elm_Atspi_Relation_Set;
|
||||
|
||||
/**
|
||||
* Frees relation.
|
||||
*/
|
||||
EAPI void elm_atspi_relation_free(Elm_Atspi_Relation *relation);
|
||||
|
||||
/**
|
||||
* 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_Relation_Set
|
||||
*/
|
||||
EAPI void elm_atspi_relation_set_free(Elm_Atspi_Relation_Set set);
|
||||
|
||||
/**
|
||||
* Clones Elm_Atspi_Relation_Set
|
||||
*/
|
||||
EAPI Elm_Atspi_Relation_Set elm_atspi_relation_set_clone(const Elm_Atspi_Relation_Set set);
|
||||
|
||||
#ifdef EFL_EO_API_SUPPORT
|
||||
|
||||
/**
|
||||
|
|
|
@ -4431,9 +4431,12 @@ _elm_widget_item_eo_base_destructor(Eo *eo_item, Elm_Widget_Item_Data *item)
|
|||
}
|
||||
eina_hash_free(item->labels);
|
||||
|
||||
eo_do(eo_item, elm_interface_atspi_accessible_description_set(NULL));
|
||||
eo_do(eo_item, elm_interface_atspi_accessible_name_set(NULL));
|
||||
eo_do(eo_item, elm_interface_atspi_accessible_translation_domain_set(NULL));
|
||||
eo_do(eo_item,
|
||||
elm_interface_atspi_accessible_description_set(NULL),
|
||||
elm_interface_atspi_accessible_name_set(NULL),
|
||||
elm_interface_atspi_accessible_translation_domain_set(NULL),
|
||||
elm_interface_atspi_accessible_relationships_clear()
|
||||
);
|
||||
|
||||
if (_elm_config->atspi_mode && item->widget)
|
||||
elm_interface_atspi_accessible_children_changed_del_signal_emit(item->widget, eo_item);
|
||||
|
@ -5706,9 +5709,12 @@ _elm_widget_eo_base_constructor(Eo *obj, Elm_Widget_Smart_Data *sd EINA_UNUSED)
|
|||
EOLIAN static void
|
||||
_elm_widget_eo_base_destructor(Eo *obj, Elm_Widget_Smart_Data *sd EINA_UNUSED)
|
||||
{
|
||||
eo_do(obj, elm_interface_atspi_accessible_description_set(NULL));
|
||||
eo_do(obj, elm_interface_atspi_accessible_name_set(NULL));
|
||||
eo_do(obj, elm_interface_atspi_accessible_translation_domain_set(NULL));
|
||||
eo_do(obj,
|
||||
elm_interface_atspi_accessible_description_set(NULL),
|
||||
elm_interface_atspi_accessible_name_set(NULL),
|
||||
elm_interface_atspi_accessible_translation_domain_set(NULL),
|
||||
elm_interface_atspi_accessible_relationships_clear()
|
||||
);
|
||||
elm_interface_atspi_accessible_removed(obj);
|
||||
|
||||
eo_do_super(obj, ELM_WIDGET_CLASS, eo_destructor());
|
||||
|
@ -5881,42 +5887,6 @@ _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)
|
||||
{
|
||||
Elm_Atspi_Relation *rel = calloc(1, sizeof(Elm_Atspi_Relation));
|
||||
if (!rel) return NULL;
|
||||
|
||||
rel->type = type;
|
||||
rel->obj = obj;
|
||||
|
||||
return rel;
|
||||
}
|
||||
|
||||
EOLIAN static Eina_List*
|
||||
_elm_widget_elm_interface_atspi_accessible_relation_set_get(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
|
||||
{
|
||||
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 list;
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_elm_widget_item_elm_interface_atspi_component_extents_get(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd EINA_UNUSED, Eina_Bool screen_coords, int *x, int *y, int *w, int *h)
|
||||
{
|
||||
|
|
|
@ -771,7 +771,6 @@ abstract Elm.Widget (Evas.Object_Smart, Elm_Interface_Atspi_Accessible, Elm_Inte
|
|||
Elm_Interface_Atspi_Accessible.children.get;
|
||||
Elm_Interface_Atspi_Accessible.parent.get;
|
||||
Elm_Interface_Atspi_Accessible.attributes.get;
|
||||
Elm_Interface_Atspi_Accessible.relation_set.get;
|
||||
Elm_Interface_Atspi_Component.focus_grab;
|
||||
}
|
||||
events {
|
||||
|
|
Loading…
Reference in New Issue