summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukasz Stanislawski <l.stanislaws@samsung.com>2015-05-06 14:21:31 +0200
committerLukasz Stanislawski <lukasz.stanislawski@gmail.com>2015-05-21 23:40:02 +0200
commite42959163ecddc38df2bee354eeda0383229d6bb (patch)
treec50a8f54f2b276777a237781094666a457cc3a05
parentb16ab94b37d1c06eea05e4b8c124ec1a2f1d0b07 (diff)
downloadelementary-devs/stanluk/eo_object_items_atspi.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.in1
-rw-r--r--src/lib/Makefile.am4
-rw-r--r--src/lib/elm_atspi_app_object.c3
-rw-r--r--src/lib/elm_atspi_bridge.c422
-rw-r--r--src/lib/elm_atspi_proxy.c101
-rw-r--r--src/lib/elm_atspi_proxy.eo43
-rw-r--r--src/lib/elm_atspi_proxy.h15
-rw-r--r--src/lib/elm_plug.c15
-rw-r--r--src/lib/elm_plug.eo1
-rw-r--r--src/lib/elm_priv.h3
-rw-r--r--src/lib/elm_web.eo1
-rw-r--r--src/lib/elm_web2.c33
-rw-r--r--src/lib/elm_widget.c2
-rw-r--r--src/lib/elm_widget.h2
-rw-r--r--src/lib/elm_widget_web.h2
-rw-r--r--src/lib/elm_win.c19
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*