diff options
author | Lukasz Stanislawski <l.stanislaws@samsung.com> | 2015-05-06 14:21:31 +0200 |
---|---|---|
committer | Lukasz Stanislawski <lukasz.stanislawski@gmail.com> | 2015-05-21 23:40:02 +0200 |
commit | e42959163ecddc38df2bee354eeda0383229d6bb (patch) | |
tree | c50a8f54f2b276777a237781094666a457cc3a05 | |
parent | b16ab94b37d1c06eea05e4b8c124ec1a2f1d0b07 (diff) | |
download | elementary-e42959163ecddc38df2bee354eeda0383229d6bb.tar.gz |
atspi: make possible to merge two atspi subtrees from different processes.devs/stanluk/eo_object_items_atspi
-rw-r--r-- | src/lib/Elementary.h.in | 1 | ||||
-rw-r--r-- | src/lib/Makefile.am | 4 | ||||
-rw-r--r-- | src/lib/elm_atspi_app_object.c | 3 | ||||
-rw-r--r-- | src/lib/elm_atspi_bridge.c | 422 | ||||
-rw-r--r-- | src/lib/elm_atspi_proxy.c | 101 | ||||
-rw-r--r-- | src/lib/elm_atspi_proxy.eo | 43 | ||||
-rw-r--r-- | src/lib/elm_atspi_proxy.h | 15 | ||||
-rw-r--r-- | src/lib/elm_plug.c | 15 | ||||
-rw-r--r-- | src/lib/elm_plug.eo | 1 | ||||
-rw-r--r-- | src/lib/elm_priv.h | 3 | ||||
-rw-r--r-- | src/lib/elm_web.eo | 1 | ||||
-rw-r--r-- | src/lib/elm_web2.c | 33 | ||||
-rw-r--r-- | src/lib/elm_widget.c | 2 | ||||
-rw-r--r-- | src/lib/elm_widget.h | 2 | ||||
-rw-r--r-- | src/lib/elm_widget_web.h | 2 | ||||
-rw-r--r-- | src/lib/elm_win.c | 19 |
16 files changed, 651 insertions, 16 deletions
diff --git a/src/lib/Elementary.h.in b/src/lib/Elementary.h.in index 87d904595..69f8de111 100644 --- a/src/lib/Elementary.h.in +++ b/src/lib/Elementary.h.in @@ -187,6 +187,7 @@ EAPI extern Elm_Version *elm_version; #include <elm_app_client_view.h> #include <elm_app.h> #include <elm_atspi_app_object.h> +#include <elm_atspi_proxy.h> #include <elm_bg.h> #include <elm_box.h> diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 2a5243672..0902adc9e 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -154,6 +154,7 @@ elm_app_client_view_eo.h \ elm_app_client_view.h \ elm_app.h \ elm_atspi_app_object.h \ +elm_atspi_proxy.h \ elm_authors.h \ elm_bg.h \ elm_bg_eo.h \ @@ -419,6 +420,7 @@ elm_app_server_view.c \ elm_app_client.c \ elm_app_client_view.c \ elm_atspi_app_object.c \ +elm_atspi_proxy.c \ elm_atspi_bridge.c \ elm_bg.c \ elm_box.c \ @@ -542,6 +544,7 @@ elm_app_client_view.eo \ elm_app_server.eo \ elm_app_server_view.eo \ elm_atspi_app_object.eo \ +elm_atspi_proxy.eo \ elm_bg.eo \ elm_box.eo \ elm_bubble.eo \ @@ -685,6 +688,7 @@ elementaryeolianfiles_DATA = \ elm_app_server.eo \ elm_app_server_view.eo \ elm_atspi_app_object.eo \ + elm_atspi_proxy.eo \ elm_interface_atspi_accessible.eo \ elm_interface_atspi_action.eo \ elm_interface_atspi_component.eo \ diff --git a/src/lib/elm_atspi_app_object.c b/src/lib/elm_atspi_app_object.c index 6e4989137..882174ad4 100644 --- a/src/lib/elm_atspi_app_object.c +++ b/src/lib/elm_atspi_app_object.c @@ -33,7 +33,8 @@ _elm_atspi_app_object_elm_interface_atspi_accessible_children_get(Eo *obj EINA_U EINA_LIST_FOREACH(_elm_win_list, l, win) { - if (eo_isa(win, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN)) + if (eo_isa(win, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN) && + (elm_win_type_get(win) != ELM_WIN_SOCKET_IMAGE)) accs = eina_list_append(accs, win); } diff --git a/src/lib/elm_atspi_bridge.c b/src/lib/elm_atspi_bridge.c index ec9e2db15..20cba5332 100644 --- a/src/lib/elm_atspi_bridge.c +++ b/src/lib/elm_atspi_bridge.c @@ -33,6 +33,8 @@ #define ELM_ACCESS_OBJECT_PATH_PREFIX "/org/a11y/atspi/accessible/" #define ELM_ACCESS_OBJECT_REFERENCE_TEMPLATE ELM_ACCESS_OBJECT_PATH_PREFIX "%llu" +#define ELM_ATSPI_DBUS_INTERFACE_PROXY "elm.atspi.bridge.proxy.Socket" + #define SIZE(x) sizeof(x)/sizeof(x[0]) typedef struct Key_Event_Info { @@ -56,6 +58,9 @@ static unsigned long _object_children_broadcast_mask; static unsigned long long _object_state_broadcast_mask; static unsigned long long _window_signal_broadcast_mask; static Ecore_Event_Filter *_key_flr; +static const char *_a11y_socket_address; +static Eina_List *socket_queue; +static Eina_List *plug_queue; static Eina_Bool _state_changed_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc, void *event_info); static Eina_Bool _property_changed_signal_send(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info); @@ -75,6 +80,8 @@ static void _object_register(Eo *obj, char *path); static void _iter_interfaces_append(Eldbus_Message_Iter *iter, const Eo *obj); static Eina_Bool _elm_atspi_bridge_key_filter(void *data, void *loop, int type, void *event); static void _object_signal_send(Eldbus_Service_Interface *infc, int sig_id, const char *minor, unsigned int det1, unsigned int det2, const char *variant_sig, ...); +static void _plug_connect(Eldbus_Connection *conn, Eo *proxy); +static void _socket_ifc_create(Eldbus_Connection *conn, Eo *proxy); EO_CALLBACKS_ARRAY_DEFINE(_events_cb, { ELM_INTERFACE_ATSPI_ACCESSIBLE_EVENT_PROPERTY_CHANGED, _property_changed_signal_send}, @@ -1720,6 +1727,56 @@ _editable_text_text_paste(const Eldbus_Service_Interface *iface, const Eldbus_Me return ret; } +Eina_Bool +_elm_atspi_bridge_plug_id_split(const char *plug_id, char **bus, char **path) +{ + if (!plug_id || !strcmp(plug_id, "")) return EINA_FALSE; + unsigned int tokens = 0; + char **split = eina_str_split_full(plug_id, ":", 0, &tokens); + Eina_Bool ret = EINA_FALSE; + if (tokens == 2) + { + if (bus) *bus = strdup(split[1]); + if (path) *path = strdup(split[2]); + ret = EINA_TRUE; + } + else if (tokens == 3) + { + char buf[128]; + snprintf(buf, sizeof(buf), ":%s", split[1]); + if (bus) *bus = strdup(buf); + if (path) *path = strdup(split[2]); + ret = EINA_TRUE; + } + + free(split[0]); + free(split); + return ret; +} + +static Eldbus_Message * +_socket_embedded(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg) +{ + Eo *proxy; + const char *obj_path = eldbus_service_object_path_get(iface); + const char *bus, *path; + Eo *obj = _access_object_from_path(obj_path); + eo_do(obj, proxy = elm_interface_atspi_accessible_parent_get()); + if (!eo_isa(proxy, ELM_ATSPI_PROXY_CLASS)) + return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Unable to embed object."); + + if (!eldbus_message_arguments_get(msg, "s", &path)) + return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Plug id expected."); + + bus = eldbus_message_sender_get(msg); + + eo_do(proxy, elm_obj_atspi_proxy_address_set(bus, path)); + + _cache_build(proxy); + + return eldbus_message_method_return_new(msg); +} + static const Eldbus_Method editable_text_methods[] = { { "SetTextContents", ELDBUS_ARGS({"s", "newcontents"}), ELDBUS_ARGS({"b", NULL}), _editable_text_text_content_set, 0 }, { "InsertText", ELDBUS_ARGS({"i", "position"}, {"s", "text"}, {"i", "length"}), ELDBUS_ARGS({"b", NULL}), _editable_text_text_insert, 0 }, @@ -1730,6 +1787,11 @@ static const Eldbus_Method editable_text_methods[] = { { NULL, NULL, NULL, NULL, 0 } }; +static const Eldbus_Method socket_methods[] = { + { "Embedded", ELDBUS_ARGS({"s", "id"}), ELDBUS_ARGS({NULL, NULL}), _socket_embedded, 0 }, + { NULL, NULL, NULL, NULL, 0 } +}; + static Eo * _access_object_from_path(const char *path) { @@ -2049,16 +2111,32 @@ static const Eldbus_Service_Interface_Desc editable_text_iface_desc = { ATSPI_DBUS_INTERFACE_EDITABLE_TEXT, editable_text_methods, NULL, NULL, NULL, NULL }; +static const Eldbus_Service_Interface_Desc socket_iface_desc = { + ATSPI_DBUS_INTERFACE_SOCKET, socket_methods, NULL, NULL, NULL, NULL +}; + static void _iter_object_reference_append(Eldbus_Message_Iter *iter, const Eo *obj) { Eldbus_Message_Iter *iter_struct = eldbus_message_iter_container_new(iter, 'r', NULL); EINA_SAFETY_ON_NULL_RETURN(iter); - char *path = _path_from_access_object(obj); - eldbus_message_iter_basic_append(iter_struct, 's', eldbus_connection_unique_name_get(_a11y_bus)); - eldbus_message_iter_basic_append(iter_struct, 'o', path); + if (eo_isa(obj, ELM_ATSPI_PROXY_CLASS)) + { + const char *pbus, *ppath; + eo_do(obj, elm_obj_atspi_proxy_address_get(&pbus, &ppath)); + if (!pbus || !ppath) + CRI("Invalid proxy address!. This should never happen"); + eldbus_message_iter_basic_append(iter_struct, 's', pbus); + eldbus_message_iter_basic_append(iter_struct, 'o', ppath); + } + else + { + char *path = _path_from_access_object(obj); + eldbus_message_iter_basic_append(iter_struct, 's', eldbus_connection_unique_name_get(_a11y_bus)); + eldbus_message_iter_basic_append(iter_struct, 'o', path); + free(path); + } eldbus_message_iter_container_close(iter, iter_struct); - free(path); } static void @@ -3072,15 +3150,17 @@ _cache_build(void *obj) if (!eo_isa(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN)) return; - path = _path_from_access_object(obj); - if (!eina_hash_find(_cache, path)) + if (!eo_isa(obj, ELM_ATSPI_PROXY_CLASS)) { - eina_hash_add(_cache, path, obj); - _object_register(obj, path); - eo_do(obj, eo_event_callback_add(EO_EV_DEL, _on_cache_item_del, NULL)); + path = _path_from_access_object(obj); + if (!eina_hash_find(_cache, path)) + { + eina_hash_add(_cache, path, obj); + _object_register(obj, path); + eo_do(obj, eo_event_callback_add(EO_EV_DEL, _on_cache_item_del, NULL)); + } + free(path); } - free(path); - eo_do(obj, children = elm_interface_atspi_accessible_children_get()); EINA_LIST_FREE(children, child) _cache_build(child); @@ -3089,12 +3169,20 @@ _cache_build(void *obj) static void _a11y_bus_initialize(const char *socket_addr) { + Eo *obj; _a11y_bus = eldbus_address_connection_get(socket_addr); _cache_register(); _event_handlers_register(); - _elm_atspi_bridge_app_register(); + if (!getenv("ELM_ATSPI_NO_EMBED")) + _elm_atspi_bridge_app_register(); _cache_build(_root); + // additionally register all socket objects and its descendants + EINA_LIST_FREE(plug_queue, obj) + _plug_connect(_a11y_bus, obj); + EINA_LIST_FREE(socket_queue, obj) + _socket_ifc_create(_a11y_bus, obj); + plug_queue = socket_queue = NULL; } static void @@ -3115,12 +3203,26 @@ _a11y_bus_address_get(void *data, const Eldbus_Message *msg, Eldbus_Pending *pen goto end; } + _a11y_socket_address = eina_stringshare_add(sock_addr); _a11y_bus_initialize(sock_addr); end: eldbus_connection_unref(session_bus); } +static void _socket_interface_register(Eldbus_Connection *conn, Eo *proxy) +{ + Eo *parent; + + eo_do(proxy, parent = eo_parent_get()); + if (!eo_isa(parent, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN)) + return; + + char *path = _path_from_access_object(parent); + eldbus_service_interface_register(conn, path, &socket_iface_desc); + free(path); +} + static void _object_register(Eo *obj, char *path) { Eldbus_Service_Interface *infc = NULL, *event_infc; @@ -3256,6 +3358,10 @@ _elm_atspi_bridge_shutdown(void) ecore_event_filter_del(_key_flr); _key_flr = NULL; + if (_a11y_socket_address) + eina_stringshare_del(_a11y_socket_address); + + _a11y_socket_address = NULL; _init_count = 0; _root = NULL; } @@ -3381,3 +3487,295 @@ _elm_atspi_bridge_key_filter(void *data EINA_UNUSED, void *loop EINA_UNUSED, int return EINA_FALSE; } + +EAPI Eina_Bool +elm_atspi_bridge_object_address_get(Eo *obj, char **bus, char **path) +{ + if (!_a11y_bus) + { + ERR("Connection with accessibility bus not established."); + return EINA_FALSE; + } + if (!eo_isa(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN)) + { + ERR("Connection with accessibility bus not established."); + return EINA_FALSE; + } + if (bus) *bus = strdup(eldbus_connection_unique_name_get(_a11y_bus)); + if (path) *path = _path_from_access_object(obj); + + return EINA_TRUE; +} + +static Eina_Bool +_proxy_property_get(const Eldbus_Service_Interface *interface, const char *property, + Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg EINA_UNUSED, + Eldbus_Message **error EINA_UNUSED) +{ + char *bus, *path; + Eo *obj = eldbus_service_object_data_get(interface, "_atspi_obj"); + EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE); + + if (!strcmp(property, "Object")) + { + Eo *parent; + eo_do(obj, parent = eo_parent_get()); + if (!elm_atspi_bridge_object_address_get(parent, &bus, &path)) + return EINA_FALSE; + + Eldbus_Message_Iter *iter_struct = eldbus_message_iter_container_new(iter, 'r', NULL); + if (iter_struct) + { + eldbus_message_iter_basic_append(iter_struct, 's', bus); + eldbus_message_iter_basic_append(iter_struct, 'o', path); + eldbus_message_iter_container_close(iter, iter_struct); + } + free(bus); + free(path); + return EINA_TRUE; + } + return EINA_FALSE; +} + +static const Eldbus_Property proxy_properties[] = { + { "Object", "(so)", _proxy_property_get, NULL, 0 }, + { NULL, NULL, NULL, NULL, 0 } +}; + +static const Eldbus_Service_Interface_Desc _proxy_iface_desc = { + ELM_ATSPI_DBUS_INTERFACE_PROXY, NULL, NULL, proxy_properties, NULL, NULL +}; + +static void _embedded_reply_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED) +{ + Eo *parent, *proxy = data; + const char *err, *txt; + + if (eldbus_message_error_get(msg, &err, &txt)) + { + ERR("AT-SPI: Embedded method call failed: %s %s", err, txt); + eo_do(proxy, eo_event_callback_call(ELM_ATSPI_PROXY_EVENT_DISCONNECTED, NULL)); + return; + } + eo_do(proxy, eo_event_callback_call(ELM_ATSPI_PROXY_EVENT_CONNECTED, NULL)); + + eo_do(proxy, parent = eo_parent_get()); + if (parent) + elm_interface_atspi_accessible_children_changed_added_signal_emit(parent, proxy) +} + +static void +_plug_embedded_send(Eldbus_Connection *conn, Eo *proxy, const char *bus, const char *path) +{ + char *obj_path = NULL; + Eo *parent; + Eldbus_Message *msg = NULL; + + eo_do(proxy, parent = eo_parent_get()); + if (!parent) goto fail; + + msg = eldbus_message_method_call_new(bus, path, ATSPI_DBUS_INTERFACE_SOCKET, "Embedded"); + if (!msg) goto fail; + + if (!elm_atspi_bridge_object_address_get(parent, NULL, &obj_path)) + goto fail; + + if (!eldbus_message_arguments_append(msg, "s", obj_path)) + goto fail; + + free(obj_path); + + if (!eldbus_connection_send(conn, msg, _embedded_reply_cb, proxy, 100)) + goto fail; + + return; + +fail: + ERR("AT-SPI: Unable to send Embedded request."); + if (msg) eldbus_message_unref(msg); + free(obj_path); + eo_do(proxy, eo_event_callback_call(ELM_ATSPI_PROXY_EVENT_DISCONNECTED, NULL)); +} + +static void _socket_addr_get_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED) +{ + Eo *proxy = data; + const char *bus, *path, *err, *txt; + Eldbus_Message_Iter *iter, *iter_variant, *iter_struct; + + if (eldbus_message_error_get(msg, &err, &txt)) + { + ERR("Unable to connect to socket: %s %s", err, txt); + goto fail; + } + + iter = eldbus_message_iter_get(msg); + if (!eldbus_message_iter_arguments_get(iter, "v", &iter_variant)) + { + ERR("Unable to get variant parameter"); + goto fail; + } + + if (!eldbus_message_iter_arguments_get(iter_variant, "(so)", &iter_struct)) + { + ERR("Unable to get so parameters"); + goto fail; + } + + if (!eldbus_message_iter_arguments_get(iter_struct, "so", &bus, &path)) + { + ERR("Unable to get so parameters"); + goto fail; + } + + eo_do(proxy, elm_obj_atspi_proxy_address_set(bus, path)); + + _plug_embedded_send(_a11y_bus, proxy, bus, path); + + return; + +fail: + eo_do(proxy, eo_event_callback_call(ELM_ATSPI_PROXY_EVENT_DISCONNECTED, NULL)); +} + +static void _free_stringshared(void *data) +{ + eina_stringshare_del(data); +} + +static void +_plug_address_discover(Eldbus_Connection *conn, Eo *proxy, const char *svc_bus, const char *svc_path) +{ + Eldbus_Object *dobj; + dobj = eldbus_object_get(conn, svc_bus, svc_path); + + Eldbus_Message *msg = eldbus_object_method_call_new(dobj, ELDBUS_FDO_INTERFACE_PROPERTIES, "Get"); + eldbus_message_arguments_append(msg, "ss", ELM_ATSPI_DBUS_INTERFACE_PROXY, "Object"); + eldbus_object_send(dobj, msg, _socket_addr_get_cb, proxy, 100); +} + +static void _plug_connect(Eldbus_Connection *conn, Eo *proxy) +{ + const char *bus, *path; + + eo_do(proxy, bus = eo_key_data_get("__svc_bus")); + eo_do(proxy, path = eo_key_data_get("__svc_path")); + + if (bus && path) + { + _plug_address_discover(conn, proxy, bus, path); + return; + } + else + { + eo_do(proxy, elm_obj_atspi_proxy_address_get(&bus, &path)); + if (!bus || !path) + { + ERR("AT-SPI: Elm_Atspi_Proxy bus or path not set. Unable to connect"); + eo_do(proxy, eo_event_callback_call(ELM_ATSPI_PROXY_EVENT_DISCONNECTED, NULL)); + return; + } + _plug_embedded_send(conn, proxy, bus, path); + } + return; +} + +static Eina_Bool _from_list_remove(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Eina_List **list = data; + *list = eina_list_remove(*list, obj); + return EINA_TRUE; +} + +EAPI void elm_atspi_bridge_utils_proxy_connect(Eo *proxy) +{ + if (!_init_count) + { + ERR("AT-SPI: Atspi bridge is not enabled."); + eo_do(proxy, eo_event_callback_call(ELM_ATSPI_PROXY_EVENT_DISCONNECTED, NULL)); + return; + } + if (!_a11y_bus) + { + if (!eina_list_data_find(plug_queue, proxy)) + { + plug_queue = eina_list_append(plug_queue, proxy); + eo_do(proxy, eo_event_callback_add(EO_EV_DEL, _from_list_remove, &plug_queue)); + } + return; + } + _plug_connect(_a11y_bus, proxy); +} + +Eo* _elm_atspi_bridge_utils_proxy_create(Eo *parent, const char *svcname, int svcnum, Elm_Atspi_Proxy_Type type) +{ + Eo *ret; + char bus[64], path[64]; + + ret = eo_add(ELM_ATSPI_PROXY_CLASS, parent, elm_obj_atspi_proxy_constructor(type)); + if (!ret) return NULL; + + snprintf(bus, sizeof(bus), "elm.atspi.proxy.socket.%s-%d", svcname, svcnum); + snprintf(path, sizeof(path), "/elm/atspi/proxy/socket/%s/%d", svcname, svcnum); + + eo_do(ret, eo_key_data_set("__svc_bus", eina_stringshare_add(bus), _free_stringshared)); + eo_do(ret, eo_key_data_set("__svc_path", eina_stringshare_add(path), _free_stringshared)); + + return ret; +} + +static Eina_Bool +_on_socket_del(void *data, Eo *obj, const Eo_Event_Description *event EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Eldbus_Service_Interface *ifc = data; + const char *bus; + Eldbus_Connection *conn = eldbus_service_connection_get(ifc); + eo_do(obj, bus = eo_key_data_get("__svc_bus")); + eldbus_name_release(conn, bus, NULL, NULL); + eldbus_service_interface_unregister(ifc); + return EINA_TRUE; +} + +static void +_proxy_interface_register(Eldbus_Connection *conn, Eo *proxy, const char *bus, const char *path) +{ + Eldbus_Service_Interface *proxy_infc; + eldbus_name_request(conn, bus, ELDBUS_NAME_REQUEST_FLAG_DO_NOT_QUEUE, NULL, NULL); + proxy_infc = eldbus_service_interface_register(_a11y_bus, path, &_proxy_iface_desc); + if (!proxy_infc) + ERR("AT-SPI: Proxy interface registration failed"); + eo_do(proxy, eo_event_callback_add(EO_EV_DEL, _on_socket_del, proxy_infc)); + eldbus_service_object_data_set(proxy_infc, "_atspi_obj", proxy); +} + +static void _socket_ifc_create(Eldbus_Connection *conn, Eo *proxy) +{ + const char *bus, *path; + + eo_do(proxy, bus = eo_key_data_get("__svc_bus")); + eo_do(proxy, path = eo_key_data_get("__svc_path")); + + if (bus && path) + _proxy_interface_register(conn, proxy, bus, path); + + _socket_interface_register(conn, proxy); +} + +EAPI void elm_atspi_bridge_utils_proxy_listen(Eo *proxy) +{ + if (!_init_count) + { + ERR("AT-SPI: Atspi bridge is not enabled."); + return; + } + if (!_a11y_bus) + { + if (!eina_list_data_find(socket_queue, proxy)) + { + socket_queue = eina_list_append(socket_queue, proxy); + eo_do(proxy, eo_event_callback_add(EO_EV_DEL, _from_list_remove, &socket_queue)); + } + return; + } + _socket_ifc_create(_a11y_bus, proxy); +} diff --git a/src/lib/elm_atspi_proxy.c b/src/lib/elm_atspi_proxy.c new file mode 100644 index 000000000..3aac6d589 --- /dev/null +++ b/src/lib/elm_atspi_proxy.c @@ -0,0 +1,101 @@ +#ifdef HAVE_CONFIG_H + #include "elementary_config.h" +#endif + +#define ELM_INTERFACE_ATSPI_ACCESSIBLE_PROTECTED + +#include <Elementary.h> +#include "elm_widget.h" +#include "elm_priv.h" + + +static Eina_List *_socket_list; + +typedef struct _Elm_Atspi_Proxy_Data Elm_Atspi_Proxy_Data; + +struct _Elm_Atspi_Proxy_Data +{ + Elm_Atspi_Proxy_Type type; + const char *bus; + const char *path; +}; + +EOLIAN static void +_elm_atspi_proxy_eo_base_destructor(Eo *obj, Elm_Atspi_Proxy_Data *_pd) +{ + if (_pd->type == ELM_ATSPI_PROXY_TYPE_SOCKET) + _socket_list = eina_list_remove(_socket_list, obj); + + if (_pd->bus) eina_stringshare_del(_pd->bus); + if (_pd->path) eina_stringshare_del(_pd->path); + + eo_do_super(obj, ELM_ATSPI_PROXY_CLASS, eo_destructor()); +} + +EOLIAN static void +_elm_atspi_proxy_constructor(Eo *obj, Elm_Atspi_Proxy_Data *_pd, Elm_Atspi_Proxy_Type type) +{ + Eo *parent; + + _pd->type = type; + eo_do(obj, parent = eo_parent_get()); + if (!parent || !eo_isa(parent, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN)) + { + CRI("Elm_Atspi_Proxy parent (%s) must implement ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN", eo_class_name_get(eo_class_get(parent))); + abort(); + } + if (type == ELM_ATSPI_PROXY_TYPE_SOCKET) + _socket_list = eina_list_append(_socket_list, obj); +} + +EOLIAN Elm_Atspi_Proxy_Type +_elm_atspi_proxy_type_get(Eo *obj EINA_UNUSED, Elm_Atspi_Proxy_Data *_pd) +{ + return _pd->type; +} + +EOLIAN void +_elm_atspi_proxy_address_get(Eo *obj EINA_UNUSED, Elm_Atspi_Proxy_Data *_pd, const char **bus, const char **path) +{ + if (bus) *bus = _pd->bus; + if (path) *path = _pd->path; +} + +EOLIAN void +_elm_atspi_proxy_address_set(Eo *obj EINA_UNUSED, Elm_Atspi_Proxy_Data *_pd, const char *bus, const char *path) +{ + if (bus) eina_stringshare_replace(&_pd->bus, bus); + if (path) eina_stringshare_replace(&_pd->path, path); +} + +EOLIAN Eina_List* +_elm_atspi_proxy_elm_interface_atspi_accessible_children_get(Eo *obj EINA_UNUSED, Elm_Atspi_Proxy_Data *_pd) +{ + Eina_List *ret = NULL; + if (_pd->type == ELM_ATSPI_PROXY_TYPE_SOCKET) + { + Eo *parent; + eo_do(obj, parent = eo_parent_get()); + ret = eina_list_append(ret, parent); + } + return ret; +} + +EOLIAN Eo* +_elm_atspi_proxy_elm_interface_atspi_accessible_parent_get(Eo *obj EINA_UNUSED, Elm_Atspi_Proxy_Data *_pd) +{ + Eo *ret = NULL; + if (_pd->type == ELM_ATSPI_PROXY_TYPE_PLUG) + { + eo_do(obj, ret = eo_parent_get()); + } + return ret; +} + +Eina_List* +_elm_atspi_proxy_socket_list_get(void) +{ + return eina_list_clone(_socket_list); +} + +#include "elm_atspi_proxy.eo.c" diff --git a/src/lib/elm_atspi_proxy.eo b/src/lib/elm_atspi_proxy.eo new file mode 100644 index 000000000..fab923f79 --- /dev/null +++ b/src/lib/elm_atspi_proxy.eo @@ -0,0 +1,43 @@ +class Elm_Atspi_Proxy (Eo.Base, Elm_Interface_Atspi_Accessible) +{ + eo_prefix: elm_obj_atspi_proxy; + data: Elm_Atspi_Proxy_Data; + methods { + constructor { + /*@ No description supplied by the EAPI. */ + legacy: null; + params { + @in type: Elm_Atspi_Proxy_Type; + } + } + @property address { + set { + } + get { + } + values { + bus: const(char)*; + path: const(char)*; + } + } + @property type { + get { + } + values { + ret: Elm_Atspi_Proxy_Type; + } + } + } + constructors { + .constructor; + } + implements { + Eo.Base.destructor; + Elm_Interface_Atspi_Accessible.children.get; + Elm_Interface_Atspi_Accessible.parent.get; + } + events { + connected; + disconnected; + } +} diff --git a/src/lib/elm_atspi_proxy.h b/src/lib/elm_atspi_proxy.h new file mode 100644 index 000000000..47cb538ea --- /dev/null +++ b/src/lib/elm_atspi_proxy.h @@ -0,0 +1,15 @@ + +enum _Elm_Atspi_Proxy_Type +{ + ELM_ATSPI_PROXY_TYPE_SOCKET, + ELM_ATSPI_PROXY_TYPE_PLUG +}; +typedef enum _Elm_Atspi_Proxy_Type Elm_Atspi_Proxy_Type; + +#ifdef EFL_EO_API_SUPPORT +#include "elm_atspi_proxy.eo.h" +#endif +#ifndef EFL_NOLEGACY_API_SUPPORT +#include "elm_atspi_proxy.eo.legacy.h" +#endif + diff --git a/src/lib/elm_plug.c b/src/lib/elm_plug.c index d7f4448ef..c0c447279 100644 --- a/src/lib/elm_plug.c +++ b/src/lib/elm_plug.c @@ -178,12 +178,27 @@ _elm_plug_connect(Eo *obj, void *sd EINA_UNUSED, const char *svcname, int svcnum ecore_evas_data_set(ee, PLUG_KEY, obj); ecore_evas_callback_delete_request_set(ee, _elm_plug_disconnected); ecore_evas_callback_resize_set(ee, _elm_plug_resized); + + if (_elm_config->atspi_mode) + { + Eo *proxy = _elm_atspi_bridge_utils_proxy_create(obj, svcname, svcnum, ELM_ATSPI_PROXY_TYPE_PLUG); + elm_atspi_bridge_utils_proxy_connect(proxy); + } + return EINA_TRUE; } return EINA_FALSE; } +EOLIAN static Eina_List* +_elm_plug_elm_interface_atspi_accessible_children_get(Eo *obj, void *sd EINA_UNUSED) +{ + Eina_List *ret; + eo_do_super(obj, ELM_WIDGET_CLASS, ret = elm_interface_atspi_accessible_children_get()); + return ret; +} + EOLIAN static void _elm_plug_class_constructor(Eo_Class *klass) { diff --git a/src/lib/elm_plug.eo b/src/lib/elm_plug.eo index 1cb2808cc..6f3e8c7d8 100644 --- a/src/lib/elm_plug.eo +++ b/src/lib/elm_plug.eo @@ -43,6 +43,7 @@ class Elm.Plug (Elm.Widget) Evas.Object_Smart.add; Elm.Widget.theme_apply; Elm.Widget.on_focus; + Elm_Interface_Atspi_Accessible.children.get; } events { clicked; diff --git a/src/lib/elm_priv.h b/src/lib/elm_priv.h index 9e7bc42ba..5d8145389 100644 --- a/src/lib/elm_priv.h +++ b/src/lib/elm_priv.h @@ -526,6 +526,7 @@ void *_elm_icon_signal_callback_del(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb); +Eo* _elm_atspi_bridge_utils_proxy_create(Eo *parent, const char *svcname, int svcnum, Elm_Atspi_Proxy_Type type); /* end of DEPRECATED */ @@ -577,4 +578,6 @@ void _elm_entry_entry_paste(Evas_Object *obj, const char *entry); double _elm_atof(const char *s); +Eina_List* _elm_atspi_proxy_socket_list_get(void); + #endif diff --git a/src/lib/elm_web.eo b/src/lib/elm_web.eo index 1a0825684..dd18b2e10 100644 --- a/src/lib/elm_web.eo +++ b/src/lib/elm_web.eo @@ -669,6 +669,7 @@ class Elm.Web (Elm.Widget) Elm.Widget.theme_apply; Elm.Widget.on_focus; Elm.Widget.event; + Elm_Interface_Atspi_Accessible.children.get; } events { uri,changed; /*@ s */ diff --git a/src/lib/elm_web2.c b/src/lib/elm_web2.c index 40a00a6ba..15746e767 100644 --- a/src/lib/elm_web2.c +++ b/src/lib/elm_web2.c @@ -579,9 +579,32 @@ _view_smart_url_changed_cb(void *data, } static void +_view_smart_load_finished(void *data, + Evas_Object *obj, + void *event_info EINA_UNUSED) +{ + Eo *eo = data; + Elm_Web_Data *wd = eo_data_scope_get(eo, ELM_WEB_CLASS); + if (_elm_config->atspi_mode && !wd->atspi_plug) + { + char *bus, *path; + const char *address = ewk_view_accessibility_plug_id_get(obj); + if (_elm_atspi_bridge_plug_id_split(address, &bus, &path)) + { + wd->atspi_plug = eo_add(ELM_ATSPI_PROXY_CLASS, eo, elm_obj_atspi_proxy_constructor(ELM_ATSPI_PROXY_TYPE_PLUG)); + eo_do(wd->atspi_plug, elm_obj_atspi_proxy_address_set(bus, path)); + elm_atspi_bridge_utils_proxy_connect(wd->atspi_plug); + free(bus); + free(path); + } + } +} + +static void _view_smart_callback_proxy(Evas_Object *view, Evas_Object *parent) { evas_object_smart_callback_add(view, SIG_URL_CHANGED, _view_smart_url_changed_cb, parent); + evas_object_smart_callback_add(view, "load,finished", _view_smart_load_finished, parent); } static Eina_Bool _elm_need_web = EINA_FALSE; @@ -610,6 +633,16 @@ elm_need_web(void) #endif } +EOLIAN static Eina_List* +_elm_web_elm_interface_atspi_accessible_children_get(Eo *obj EINA_UNUSED, Elm_Web_Data *sd) +{ +#ifdef HAVE_ELEMENTARY_WEB + if (sd->atspi_plug) + return eina_list_append(NULL, sd->atspi_plug); +#endif + return NULL; +} + EOLIAN static Eina_Bool _elm_web_elm_widget_theme_apply(Eo *obj, Elm_Web_Data *sd EINA_UNUSED) { diff --git a/src/lib/elm_widget.c b/src/lib/elm_widget.c index 1fe8a99f4..40eb7a3ba 100644 --- a/src/lib/elm_widget.c +++ b/src/lib/elm_widget.c @@ -547,7 +547,7 @@ _elm_widget_evas_object_smart_show(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUS { Eo *parent; eo_do(obj, parent = elm_interface_atspi_accessible_parent_get()); - elm_interface_atspi_accessible_children_changed_added_signal_emit(parent, obj); + if (parent) elm_interface_atspi_accessible_children_changed_added_signal_emit(parent, obj); } it = evas_object_smart_iterator_new(obj); diff --git a/src/lib/elm_widget.h b/src/lib/elm_widget.h index 784c317cb..6a315f8e4 100644 --- a/src/lib/elm_widget.h +++ b/src/lib/elm_widget.h @@ -775,6 +775,8 @@ EAPI void elm_widget_orientation_mode_disabled_set(Evas_Object *obj, 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); void _elm_widget_item_highlight_in_theme(Evas_Object *obj, Elm_Object_Item *it); +EAPI Eo* _elm_atspi_bridge_utils_plug_create(Eo *parent, const char *svcname, int svcnum); +EAPI Eo* _elm_atspi_bridge_utils_socket_create(Eo *parent, const char *svcname, int svcnum); /** * Function to operate on a given widget's scrollabe children when necessary. diff --git a/src/lib/elm_widget_web.h b/src/lib/elm_widget_web.h index 6eceacd41..431785fd7 100644 --- a/src/lib/elm_widget_web.h +++ b/src/lib/elm_widget_web.h @@ -66,6 +66,8 @@ struct _Elm_Web_Data Ecore_Animator *animator; } bring_in; + Eo *atspi_plug; // @since 1.15 + Eina_Bool tab_propagate : 1; Eina_Bool inwin_mode : 1; #endif diff --git a/src/lib/elm_win.c b/src/lib/elm_win.c index 4a84e3851..1ba74123d 100644 --- a/src/lib/elm_win.c +++ b/src/lib/elm_win.c @@ -195,6 +195,8 @@ struct _Elm_Win_Data Eina_Bool use : 1; /* set ture when application use window manager rotation. */ } wm_rot; + Eo *socket_proxy; /* reference object to atspi object in separate process @since 1.15 */ + void *trap_data; struct @@ -3731,7 +3733,7 @@ _elm_win_finalize_internal(Eo *obj, Elm_Win_Data *sd, const char *name, Elm_Win_ eo_do(obj, elm_interface_atspi_accessible_role_set(ELM_ATSPI_ROLE_WINDOW)); if (_elm_config->atspi_mode == ELM_ATSPI_MODE_ON) { - elm_interface_atspi_accessible_children_changed_added_signal_emit(_elm_atspi_bridge_root_get(), obj); + eo_do(obj, eo_event_callback_call(ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_CREATED, NULL)); } evas_object_show(sd->edje); @@ -5178,6 +5180,14 @@ _elm_win_socket_listen(Eo *obj EINA_UNUSED, Elm_Win_Data *sd, const char *svcnam if (!ecore_evas_extn_socket_listen(sd->ee, svcname, svcnum, svcsys)) return EINA_FALSE; + if (_elm_config->atspi_mode) + { + if (sd->socket_proxy) + eo_unref(sd->socket_proxy); + sd->socket_proxy = _elm_atspi_bridge_utils_proxy_create(obj, svcname, svcnum, ELM_ATSPI_PROXY_TYPE_SOCKET); + elm_atspi_bridge_utils_proxy_listen(sd->socket_proxy); + } + return EINA_TRUE; } @@ -5413,7 +5423,12 @@ EOLIAN static Eo* _elm_win_elm_interface_atspi_accessible_parent_get(Eo *obj EINA_UNUSED, Elm_Win_Data *sd EINA_UNUSED) { // attach all kinds of windows directly to ATSPI application root object - return _elm_atspi_bridge_root_get(); + if (sd->type == ELM_WIN_SOCKET_IMAGE) + { + return sd->socket_proxy; + } + else + return _elm_atspi_bridge_root_get(); } EOLIAN static const Elm_Atspi_Action* |