elm: atspi - make atspi_proxy work
authorShinwoo Kim <cinoo.kim@samsung.com>
Wed, 8 Nov 2017 11:17:45 +0000 (20:17 +0900)
committerJiyoun Park <jy0703.park@samsung.com>
Tue, 19 Dec 2017 06:50:38 +0000 (15:50 +0900)
1. atspi: make possible to merge two atspi subtrees from different processes.
  - commit 15b749312eb34f5c47ca28d5ba05cb854c766046
  - Author: Lukasz Stanislawski <l.stanislaws@samsung.com>
  - Date:   Wed May 6 14:21:31 2015 +0200

2. [atspi] enable atspi_proxy to work
  - commit ffb22851f98d229f72318dba2318e86750c269a0
  - Author: Shinwoo Kim <cinoo.kim@samsung.com>
  - Date:   Tue Jul 5 09:22:42 2016 +0900

Change-Id: If37d92344d404442d53445d9f73e604332250a0e

15 files changed:
src/Makefile_Elementary.am
src/lib/elementary/Elementary.h
src/lib/elementary/efl_ui_win_socket.c
src/lib/elementary/efl_ui_win_socket.eo
src/lib/elementary/elm_atspi_app_object.c
src/lib/elementary/elm_atspi_bridge.c
src/lib/elementary/elm_atspi_bridge.eo
src/lib/elementary/elm_atspi_proxy.c [new file with mode: 0644]
src/lib/elementary/elm_atspi_proxy.eo [new file with mode: 0644]
src/lib/elementary/elm_atspi_proxy.h [new file with mode: 0644]
src/lib/elementary/elm_plug.c
src/lib/elementary/elm_plug.eo
src/lib/elementary/elm_priv.h
src/lib/elementary/elm_widget.c
src/lib/elementary/elm_widget.h

index 6e4b3be..7d5e03f 100644 (file)
@@ -101,6 +101,7 @@ elm_public_eolian_files += \
        lib/elementary/elm_multibuttonentry_item.eo \
        lib/elementary/elm_interface_scrollable.eo \
        lib/elementary/elm_atspi_bridge.eo \
+       lib/elementary/elm_atspi_ewk_wrapper.eo \
        lib/elementary/elm_atspi_app_object.eo \
        lib/elementary/efl_ui_image_zoomable_pan.eo \
        lib/elementary/elm_pan.eo \
@@ -263,6 +264,7 @@ includesdir = $(includedir)/elementary-@VMAJ@
 includesunstable_HEADERS = \
        lib/elementary/elm_gen_common.h \
        lib/elementary/elm_atspi_bridge.h \
+       lib/elementary/elm_atspi_ewk_wrapper.h \
        lib/elementary/efl_access.h \
        lib/elementary/efl_access_text.h \
        lib/elementary/efl_access_widget_action.h \
@@ -392,6 +394,7 @@ includesub_HEADERS = \
        lib/elementary/elm_actionslider_legacy.h \
        lib/elementary/elm_app.h \
        lib/elementary/elm_atspi_app_object.h \
+        lib/elementary/elm_atspi_proxy.h \
        lib/elementary/elm_authors.h \
        lib/elementary/elm_bg.h \
        lib/elementary/efl_ui_bg_eo.h \
@@ -597,6 +600,7 @@ lib_elementary_libelementary_la_SOURCES = \
        lib/elementary/elm_actionslider.c \
        lib/elementary/elm_atspi_app_object.c \
        lib/elementary/elm_atspi_bridge.c \
+       lib/elementary/elm_atspi_ewk_wrapper.c \
        lib/elementary/efl_ui_bg.c \
        lib/elementary/elm_box.c \
        lib/elementary/elm_bubble.c \
index e404d6b..eabcf66 100644 (file)
@@ -185,6 +185,9 @@ EAPI extern Elm_Version *elm_version;
 #include <elm_app.h>
 #include <elm_atspi_app_object.h>
 #include <elm_atspi_bridge.h>
+//TIZEN_ONLY(20171108): make atspi_proxy work
+#include <elm_atspi_proxy.h>
+//
 #include <elm_bg.h>
 #include <elm_box.h>
 
index 8c0485a..2bed6cd 100644 (file)
@@ -6,12 +6,19 @@
 #define EFL_UI_WIN_SOCKET_PROTECTED
 
 #include <Elementary.h>
+//TIZEN_ONLY(20171108): make atspi_proxy work
+// _elm_config
+#include "elm_priv.h"
+//
 
 #define MY_CLASS EFL_UI_WIN_SOCKET_CLASS
 #define MY_CLASS_NAME "Efl.Ui.Win_Socket"
 
 typedef struct
 {
+   //TIZEN_ONLY(20171108): make atspi_proxy work
+   Eo *socket_proxy; /* reference object to atspi object in separate process @since 1.15 */
+   //
 } Efl_Ui_Win_Socket_Data;
 
 EOLIAN static Efl_Object *
@@ -29,7 +36,54 @@ _efl_ui_win_socket_socket_listen(Eo *obj, Efl_Ui_Win_Socket_Data *pd EINA_UNUSED
    Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
 
    if (!ee) return EINA_FALSE;
+   /* TIZEN_ONLY(20171108): make atspi_proxy work
    return ecore_evas_extn_socket_listen(ee, svcname, svcnum, svcsys);
+   */
+   //TIZEN_ONLY(20171108): make atspi_proxy work
+   if (!ecore_evas_extn_socket_listen(ee, svcname, svcnum, svcsys))
+     return EINA_FALSE;
+
+   if (_elm_config->atspi_mode)
+     {
+        if (pd->socket_proxy)
+          efl_unref(pd->socket_proxy);
+        pd->socket_proxy = _elm_atspi_bridge_utils_proxy_create(obj, svcname, svcnum, ELM_ATSPI_PROXY_TYPE_SOCKET);
+        elm_atspi_bridge_utils_proxy_listen(pd->socket_proxy);
+     }
+
+   return EINA_TRUE;
+   //
 }
 
+//TIZEN_ONLY(20171108): make atspi_proxy work
+EOLIAN static void
+_efl_ui_win_socket_efl_gfx_visible_set(Eo *obj, Efl_Ui_Win_Socket_Data *sd, Eina_Bool vis)
+{
+   efl_gfx_visible_set(efl_super(obj, EFL_UI_WIN_SOCKET_CLASS), vis);
+
+   const char *plug_id_2;
+   if (vis)
+     {
+        if ((plug_id_2 = evas_object_data_get(obj, "___PLUGID")) != NULL)
+          {
+             char *svcname, *svcnum;
+             if (!sd->socket_proxy && _elm_atspi_bridge_plug_id_split(plug_id_2, &svcname, &svcnum))
+               {
+                  sd->socket_proxy = _elm_atspi_bridge_utils_proxy_create(obj, svcname, atoi(svcnum), ELM_ATSPI_PROXY_TYPE_SOCKET);
+                  elm_atspi_bridge_utils_proxy_listen(sd->socket_proxy);
+                  free(svcname);
+                  free(svcnum);
+               }
+          }
+     }
+}
+
+EOLIAN static Eo*
+_efl_ui_win_socket_elm_interface_atspi_accessible_parent_get(Eo *obj, Efl_Ui_Win_Socket_Data *pd)
+{
+   if (pd->socket_proxy) return pd->socket_proxy;
+
+   return elm_interface_atspi_accessible_parent_get(efl_super(obj, EFL_UI_WIN_SOCKET_CLASS));
+}
+//
 #include "efl_ui_win_socket.eo.c"
index 154ae70..ed288fa 100644 (file)
@@ -27,5 +27,9 @@ class Efl.Ui.Win_Socket (Efl.Ui.Win)
    }
    implements {
       Efl.Object.finalize;
+      //TIZEN_ONLY(20171108): make atspi_proxy work
+      Efl.Gfx.visible { set; }
+      Elm.Interface.Atspi_Accessible.parent { get; }
+      //
    }
 }
index b1d45c1..3a98ab5 100644 (file)
@@ -37,7 +37,13 @@ _elm_atspi_app_object_efl_access_children_get(Eo *obj EINA_UNUSED, Elm_Atspi_App
         if (!efl_isa(win, EFL_ACCESS_MIXIN))
           continue;
         type = efl_access_type_get(win);
+        /* TIZEN_ONLY(20171108): make atspi_proxy work
         if (type == EFL_ACCESS_TYPE_REGULAR)
+        */
+        //TIZEN_ONLY(20171108): make atspi_proxy work
+        if (type == EFL_ACCESS_TYPE_REGULAR &&
+            (elm_win_type_get(win) != ELM_WIN_SOCKET_IMAGE))
+        //
           accs = eina_list_append(accs, win);
      }
 
index 56ca460..0143a4f 100644 (file)
 #define ELM_ACCESS_OBJECT_PATH_PREFIX2  "/org/a11y/atspi/accessible"
 #define ELM_ACCESS_OBJECT_REFERENCE_TEMPLATE ELM_ACCESS_OBJECT_PATH_PREFIX "%llu"
 
+//TIZEN_ONLY(20171108): make atspi_proxy work
+#define ELM_ATSPI_DBUS_INTERFACE_PROXY "elm.atspi.bridge.proxy.Socket"
+//
+
 #define SIZE(x) sizeof(x)/sizeof(x[0])
 #define ELM_ATSPI_BRIDGE_CLASS_NAME "__Elm_Atspi_Bridge"
 
@@ -94,9 +98,18 @@ typedef struct _Elm_Atspi_Bridge_Data
         Eldbus_Service_Interface *selection;
         Eldbus_Service_Interface *text;
         Eldbus_Service_Interface *value;
+        //TIZEN_ONLY(20171108): make atspi_proxy work
+        Eldbus_Service_Interface *socket;
+        //
    } interfaces;
    Efl_Access_Event_Handler *event_hdlr;
    Eina_Hash *event_hash;
+   //TIZEN_ONLY(20171108): make atspi_proxy work
+   Eo *root;
+   Eina_List *socket_queue;
+   Eina_List *plug_queue;
+   Evas_Point socket_offset;
+   //
    Eina_Bool connected : 1;
 } Elm_Atspi_Bridge_Data;
 
@@ -115,6 +128,9 @@ struct collection_match_rule {
 
 static Eo *_instance;
 static int _init_count = 0;
+//TIZEN_ONLY(20171108): make atspi_proxy work
+static const char *_a11y_socket_address;
+//
 
 // Object Event handlers
 static void _state_changed_signal_send(void *data, const Efl_Event *event);
@@ -131,6 +147,9 @@ static void _text_caret_moved_send(void *data, const Efl_Event *event);
 static void _text_selection_changed_send(void *data, const Efl_Event *event);
 
 // bridge private methods
+//TIZEN_ONLY(20171108): make atspi_proxy work
+static void _bridge_cache_build(Eo *bridge, void *obj);
+//
 static void _bridge_object_register(Eo *bridge, Eo *obj);
 static void _bridge_object_unregister(Eo *bridge, Eo *obj);
 static const char * _path_from_object(const Eo *eo);
@@ -145,6 +164,11 @@ static void _object_desktop_reference_append(Eldbus_Message_Iter *iter);
 static void _on_object_add(void *data, const Efl_Event *event);
 static void _on_object_del(void *data, const Efl_Event *event);
 
+//TIZEN_ONLY(20171108): make atspi_proxy work
+static void _plug_connect(Eldbus_Connection *conn, Eo *proxy);
+static void _socket_ifc_create(Eldbus_Connection *conn, Eo *proxy);
+//
+
 typedef struct {
      const Efl_Event_Description *desc;
      const Efl_Event_Cb callback;
@@ -2002,6 +2026,80 @@ _editable_text_text_paste(const Eldbus_Service_Interface *iface, const Eldbus_Me
    return ret;
 }
 
+//TIZEN_ONLY(20171108): make atspi_proxy work
+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 EINA_UNUSED, const Eldbus_Message *msg)
+{
+   Eo *proxy;
+   // TIZEN_ONLY(20160705) - enable atspi_proxy to work
+   const char *obj_path = eldbus_message_path_get(msg);
+   //
+   const char *bus, *path;
+   Eo *bridge = _elm_atspi_bridge_get();
+   Eo *obj = _bridge_object_from_path(bridge, obj_path);
+   proxy = elm_interface_atspi_accessible_parent_get(obj);
+
+   if (!efl_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);
+
+   elm_obj_atspi_proxy_address_set(proxy, bus, path);
+
+   _bridge_cache_build(bridge, proxy);
+
+   return eldbus_message_method_return_new(msg);
+}
+//
+
+// TIZEN_ONLY(20160705) - enable atspi_proxy to work
+static Eldbus_Message *
+_socket_offset_set(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
+{
+   int x, y;
+   Eo *bridge = _elm_atspi_bridge_get();
+   ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, NULL);
+
+   if (!eldbus_message_arguments_get(msg, "ii", &x, &y))
+     return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
+
+   pd->socket_offset.x = x;
+   pd->socket_offset.y = y;
+
+   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 },
@@ -2012,6 +2110,20 @@ static const Eldbus_Method editable_text_methods[] = {
    { NULL, NULL, NULL, NULL, 0 }
 };
 
+//TIZEN_ONLY(20171108): make atspi_proxy work
+static const Eldbus_Method socket_methods[] = {
+   { "Embedded", ELDBUS_ARGS({"s", "id"}), ELDBUS_ARGS({NULL, NULL}), _socket_embedded, 0 },
+   // TIZEN_ONLY(20160705) - enable atspi_proxy to work
+   { "SetOffset", ELDBUS_ARGS({"i", "x"}, {"i", "y"}), ELDBUS_ARGS({NULL, NULL}), _socket_offset_set, 0 },
+   //
+   { NULL, NULL, NULL, NULL, 0 }
+};
+
+static const Eldbus_Service_Interface_Desc socket_iface_desc = {
+   ATSPI_DBUS_INTERFACE_SOCKET, socket_methods, NULL, NULL, NULL, NULL
+};
+//
+
 static Eo *
 _bridge_object_from_path(Eo *bridge, const char *path)
 {
@@ -3093,10 +3205,39 @@ _bridge_iter_object_reference_append(Eo *bridge, Eldbus_Message_Iter *iter, cons
    ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
    Eldbus_Message_Iter *iter_struct = eldbus_message_iter_container_new(iter, 'r', NULL);
    EINA_SAFETY_ON_NULL_RETURN(iter);
+   /* TIZEN_ONLY(20171108): make atspi_proxy work
    const char *path = _path_from_object(obj);
    eldbus_message_iter_basic_append(iter_struct, 's', eldbus_connection_unique_name_get(pd->a11y_bus));
    eldbus_message_iter_basic_append(iter_struct, 'o', path);
    eldbus_message_iter_container_close(iter, iter_struct);
+   */
+   //TIZEN_ONLY(20171108): make atspi_proxy work
+   if (efl_isa(obj, ELM_ATSPI_PROXY_CLASS))
+     {
+        const char *pbus = "", *ppath = ATSPI_DBUS_PATH_NULL;
+        elm_obj_atspi_proxy_address_get(obj, &pbus, &ppath);
+        if (!pbus || !ppath)
+          {
+             ERR("Invalid proxy address! Address not set before connecting/listening?");
+             const char *path = _path_from_object(obj);
+             eldbus_message_iter_basic_append(iter_struct, 's', eldbus_connection_unique_name_get(pd->a11y_bus));
+             eldbus_message_iter_basic_append(iter_struct, 'o', path);
+          }
+        else
+          {
+             eldbus_message_iter_basic_append(iter_struct, 's', pbus);
+             eldbus_message_iter_basic_append(iter_struct, 'o', ppath);
+          }
+     }
+   else
+     {
+        const char *path = _path_from_object(obj);
+        eldbus_message_iter_basic_append(iter_struct, 's', eldbus_connection_unique_name_get(pd->a11y_bus));
+        eldbus_message_iter_basic_append(iter_struct, 'o', path);
+     }
+
+    eldbus_message_iter_container_close(iter, iter_struct);
+   //
 }
 
 static void
@@ -3320,6 +3461,9 @@ _component_get_accessible_at_point(const Eldbus_Service_Interface *iface EINA_UN
 {
    const char *obj_path = eldbus_message_path_get(msg);
    Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
+   // TIZEN_ONLY(20160705) - enable atspi_proxy to work
+   ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, NULL);
+   //
    Eo *obj = _bridge_object_from_path(bridge, obj_path);
    int x, y;
    Eo *accessible = NULL;
@@ -3332,6 +3476,11 @@ _component_get_accessible_at_point(const Eldbus_Service_Interface *iface EINA_UN
    if (!eldbus_message_arguments_get(msg, "iiu", &x, &y, &coord_type))
      return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid index type.");
 
+   // TIZEN_ONLY(20160705) - enable atspi_proxy to work
+   x = x - pd->socket_offset.x;
+   y = y - pd->socket_offset.y;
+   //
+
    ret = eldbus_message_method_return_new(msg);
    EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
 
@@ -3498,7 +3647,7 @@ _component_grab_highlight(const Eldbus_Service_Interface *iface EINA_UNUSED, con
 
    ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, EFL_ACCESS_COMPONENT_MIXIN, msg);
 
-   eo_do(obj, highlight = elm_interface_atspi_component_highlight_grab());
+   highlight = efl_access_component_highlight_grab(obj);
 
    ret = eldbus_message_method_return_new(msg);
    EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
@@ -3519,7 +3668,7 @@ _component_clear_highlight(const Eldbus_Service_Interface *iface EINA_UNUSED, co
 
    ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, EFL_ACCESS_COMPONENT_MIXIN, msg);
 
-   eo_do(obj, highlight = elm_interface_atspi_component_highlight_clear());
+   highlight = efl_access_component_highlight_clear(obj);
 
    ret = eldbus_message_method_return_new(msg);
    EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
@@ -3644,6 +3793,10 @@ static const Eldbus_Method component_methods[] = {
    { "SetExtents", ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"i", "width"}, {"i", "height"}, {"u", "coord_type"}), ELDBUS_ARGS({"b", "result"}), _component_set_extends, 0 },
    { "SetPosition", ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"u", "coord_type"}), ELDBUS_ARGS({"b", "result"}), _component_set_position, 0 },
    { "SetSize", ELDBUS_ARGS({"i", "width"}, {"i", "height"}), ELDBUS_ARGS({"b", "result"}), _component_set_size, 0 },
+   //TIZEN_ONLY(20171108): bring HIGHLIGHT related changes
+   { "GrabHighlight", NULL, ELDBUS_ARGS({"b", "result"}), _component_grab_highlight, 0 },
+   { "ClearHighlight", NULL, ELDBUS_ARGS({"b", "result"}), _component_clear_highlight, 0 },
+   //
    { NULL, NULL, NULL, NULL, 0 }
 };
 
@@ -3834,9 +3987,26 @@ _registered_listeners_get(void *data, const Eldbus_Message *msg, Eldbus_Pending
         else _set_broadcast_flag(event, data);
      }
 
+   /* TIZEN_ONLY(20171108): make atspi_proxy work
    if (!pd->connected)
       efl_event_callback_legacy_call(data, ELM_ATSPI_BRIDGE_EVENT_CONNECTED, NULL);
    pd->connected = EINA_TRUE;
+   */
+   //TIZEN_ONLY(20171108): make atspi_proxy work
+   if (!pd->connected)
+     {
+        pd->connected = EINA_TRUE;
+
+        // initialize pending proxy
+        Eo *pr;
+        EINA_LIST_FREE(pd->socket_queue, pr)
+           _socket_ifc_create(pd->a11y_bus, pr);
+        EINA_LIST_FREE(pd->plug_queue, pr)
+           _plug_connect(pd->a11y_bus, pr);
+
+        pd->socket_queue = pd->plug_queue = NULL;
+     }
+   //
 }
 
 static void
@@ -4002,6 +4172,12 @@ _children_changed_signal_send(void *data, const Efl_Event *event)
         atspi_desc = "remove";
      }
 
+   //TIZEN_ONLY(20171108): make atspi_proxy work
+   // update cached objects
+   if (ev_data->is_added)
+     _bridge_cache_build(data, ev_data->child);
+   //
+
    if (!STATE_TYPE_GET(pd->object_children_broadcast_mask, type))
      {
         efl_event_callback_stop(event->object);
@@ -4276,6 +4452,42 @@ _on_object_del(void *data, const Efl_Event *event)
    eldbus_service_signal_send(pd->cache_interface, sig);
 }
 
+//TIZEN_ONLY(20171108): make atspi_proxy work
+static void
+_bridge_cache_build(Eo *bridge, void *obj)
+{
+   Eina_List *children;
+   Elm_Atspi_State_Set ss;
+   Eo *child;
+
+   ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
+
+   if (!efl_isa(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
+     return;
+
+   if (!efl_isa(obj, ELM_ATSPI_PROXY_CLASS))
+      _bridge_object_register(bridge, obj);
+
+   ss = elm_interface_atspi_accessible_state_set_get(obj);
+   if (STATE_TYPE_GET(ss, ELM_ATSPI_STATE_MANAGES_DESCENDANTS))
+     return;
+   if (efl_isa(obj, EFL_ACCESS_WINDOW_INTERFACE))
+     {
+        if (STATE_TYPE_GET(ss, ELM_ATSPI_STATE_ACTIVE))
+          {
+             efl_access_window_activated_signal_emit(obj);
+          }
+        else
+          {
+             efl_access_window_deactivated_signal_emit(obj);
+          }
+     }
+   children = elm_interface_atspi_accessible_children_get(obj);
+   EINA_LIST_FREE(children, child)
+      _bridge_cache_build(bridge, child);
+}
+//
+
 static void
 _interfaces_unregister(Eo *bridge)
 {
@@ -4413,6 +4625,9 @@ _a11y_bus_initialize(Eo *obj, const char *socket_addr)
 {
    ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(obj, pd);
 
+   //TIZEN_ONLY(20171108): make atspi_proxy work
+   Eo *root;
+   //
    pd->a11y_bus = eldbus_private_address_connection_get(socket_addr);
    if (!pd->a11y_bus)
      return;
@@ -4428,10 +4643,29 @@ _a11y_bus_initialize(Eo *obj, const char *socket_addr)
    _cache_register(obj);
    _interfaces_register(obj);
    _event_handlers_register(obj);
+   /* TIZEN_ONLY(20171108): make atspi_proxy work
    _elm_atspi_bridge_app_register(obj);
+   */
+   //TIZEN_ONLY(20171108): make atspi_proxy work
+   if (!getenv("ELM_ATSPI_NO_EMBED"))
+     _elm_atspi_bridge_app_register(obj);
+
+   // buid cache
+   root = elm_obj_atspi_bridge_root_get(obj);
+   _bridge_cache_build(obj, root);
+   //
 
    // register accessible object event listener
    pd->event_hdlr = efl_access_event_handler_add(EFL_ACCESS_MIXIN, _bridge_accessible_event_dispatch, obj);
+
+   //TIZEN_ONLY(20171108): make atspi_proxy work
+   // additionally register all socket objects and its descendants
+   EINA_LIST_FREE(pd->plug_queue, obj)
+   _plug_connect(pd->a11y_bus, obj);
+   EINA_LIST_FREE(pd->socket_queue, obj)
+   _socket_ifc_create(pd->a11y_bus, obj);
+   pd->plug_queue = pd->socket_queue = NULL;
+   //
 }
 
 static void
@@ -4454,6 +4688,9 @@ _a11y_bus_address_get(void *data, const Eldbus_Message *msg, Eldbus_Pending *pen
         return;
      }
 
+   //TIZEN_ONLY(20171108): make atspi_proxy work
+   _a11y_socket_address = eina_stringshare_add(sock_addr);
+   //
    _a11y_bus_initialize((Eo*)data, sock_addr);
 }
 
@@ -4545,6 +4782,12 @@ _elm_atspi_bridge_shutdown(void)
         efl_del(_instance);
         _init_count = 0;
      }
+
+   //TIZEN_ONLY(20171108): make atspi_proxy work
+   if (_a11y_socket_address)
+     eina_stringshare_del(_a11y_socket_address);
+   _a11y_socket_address = NULL;
+   //
    _efl_access_shutdown();
 }
 
@@ -4703,6 +4946,20 @@ _elm_atspi_bridge_connected_get(Eo *obj EINA_UNUSED, Elm_Atspi_Bridge_Data *pd)
    return pd->connected;
 }
 
+//TIZEN_ONLY(20171108): make atspi_proxy work
+EOLIAN Eo*
+_elm_atspi_bridge_root_get(Eo *obj EINA_UNUSED, Elm_Atspi_Bridge_Data *pd)
+{
+   if (!pd->root)
+     {
+        pd->root = efl_add(ELM_ATSPI_APP_OBJECT_CLASS, NULL);
+        elm_interface_atspi_accessible_added(pd->root);
+     }
+
+   return pd->root;
+}
+//
+
 static void
 _properties_changed_cb(void *data, Eldbus_Proxy *proxy EINA_UNUSED, void *event)
 {
@@ -4783,4 +5040,367 @@ _elm_atspi_bridge_efl_object_destructor(Eo *obj, Elm_Atspi_Bridge_Data *pd)
    efl_destructor(efl_super(obj, ELM_ATSPI_BRIDGE_CLASS));
 }
 
+//TIZEN_ONLY(20171108): make atspi_proxy work
+EAPI Eina_Bool
+elm_atspi_bridge_object_address_get(Eo *obj, char **bus, char **path)
+{
+   Eo *bridge = _elm_atspi_bridge_get();
+   if (!bridge)
+     {
+        ERR("Connection with accessibility bus not established.");
+        return EINA_FALSE;
+     }
+   ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, EINA_FALSE);
+   if (!efl_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(pd->a11y_bus));
+   if (path) *path = strdup(_path_from_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;
+       parent = efl_parent_get(obj);
+       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);
+        efl_event_callback_call(proxy, ELM_ATSPI_PROXY_EVENT_DISCONNECTED, NULL);
+        return;
+     }
+   efl_event_callback_call(proxy, ELM_ATSPI_PROXY_EVENT_CONNECTED, NULL);
+
+   parent = efl_parent_get(proxy);
+   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;
+
+   parent = efl_parent_get(proxy);
+   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);
+   efl_event_callback_call(proxy, ELM_ATSPI_PROXY_EVENT_DISCONNECTED, NULL);
+}
+
+// TIZEN_ONLY(20160705) - enable atspi_proxy to work
+static void
+_offset_set_reply_cb(void *data EINA_UNUSED, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
+{
+   const char *err, *txt;
+
+   if (eldbus_message_error_get(msg, &err, &txt))
+     {
+        ERR("AT-SPI: SetOffset method call failed: %s %s", err, txt);
+        return;
+     }
+}
+
+static void
+_plug_offset_set_send(Eldbus_Connection *conn, const char *bus, const char *path, int x, int y)
+{
+   Eldbus_Message *msg = NULL;
+
+   msg = eldbus_message_method_call_new(bus, path, ATSPI_DBUS_INTERFACE_SOCKET, "SetOffset");
+   if (!msg) goto fail;
+
+   if (!eldbus_message_arguments_append(msg, "i", x))
+     goto fail;
+
+   if (!eldbus_message_arguments_append(msg, "i", y))
+     goto fail;
+
+   if (!eldbus_connection_send(conn, msg, _offset_set_reply_cb, NULL, 100))
+     goto fail;
+
+   return;
+
+fail:
+   ERR("AT-SPI: Unable to send SetOffset request.");
+   if (msg) eldbus_message_unref(msg);
+}
+//
+
+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;
+
+   ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(proxy, pd);
+
+   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;
+     }
+
+   elm_obj_atspi_proxy_address_set(proxy, bus, path);
+
+   _plug_embedded_send(pd->a11y_bus, proxy, bus, path);
+
+   return;
+
+fail:
+   efl_event_callback_call(proxy, ELM_ATSPI_PROXY_EVENT_DISCONNECTED, NULL);
+}
+
+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;
+
+   bus = efl_key_data_get(proxy, "__svc_bus");
+   path = efl_key_data_get(proxy, "__svc_path");
+
+   if (bus && path)
+     {
+        _plug_address_discover(conn, proxy, bus, path);
+        return;
+     }
+   else
+     {
+        elm_obj_atspi_proxy_address_get(proxy, &bus, &path);
+        if (!bus || !path)
+          {
+             ERR("AT-SPI: Elm_Atspi_Proxy bus or path not set. Unable to connect");
+             efl_event_callback_call(proxy, ELM_ATSPI_PROXY_EVENT_DISCONNECTED, NULL);
+             return;
+          }
+        _plug_embedded_send(conn, proxy, bus, path);
+     }
+   return;
+}
+
+static void _from_list_remove(void *data, const Efl_Event *event)
+{
+   Eina_List **list = data;
+   *list = eina_list_remove(*list, event->object);
+}
+
+EAPI void elm_atspi_bridge_utils_proxy_connect(Eo *proxy)
+{
+   Eo *bridge = _elm_atspi_bridge_get();
+
+   if (!bridge)
+     {
+        ERR("AT-SPI: Atspi bridge is not enabled.");
+        efl_event_callback_call(proxy, ELM_ATSPI_PROXY_EVENT_DISCONNECTED, NULL);
+        return;
+     }
+   ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
+
+   if (!pd->a11y_bus)
+     {
+        if (!eina_list_data_find(pd->plug_queue, proxy))
+          {
+             pd->plug_queue = eina_list_append(pd->plug_queue, proxy);
+             efl_event_callback_add(proxy, EFL_EVENT_DEL, _from_list_remove, &pd->plug_queue);
+          }
+        return;
+     }
+   _plug_connect(pd->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 = efl_add(ELM_ATSPI_PROXY_CLASS, parent, elm_obj_atspi_proxy_constructor(efl_added, 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);
+
+   efl_key_data_set(ret, "__svc_bus", eina_stringshare_add(bus));
+   efl_key_data_set(ret, "__svc_path", eina_stringshare_add(path));
+
+   return ret;
+}
+
+static void
+_on_socket_del(void *data, const Efl_Event *event)
+{
+   Eldbus_Service_Interface *ifc = data;
+   const char *bus;
+   Eldbus_Connection *conn = eldbus_service_connection_get(ifc);
+   bus = efl_key_data_get(event->object, "__svc_bus");
+   eldbus_name_release(conn, bus, NULL, NULL);
+   eldbus_service_interface_unregister(ifc);
+}
+
+static void
+_proxy_interface_register(Eldbus_Connection *conn, Eo *proxy, const char *bus, const char *path)
+{
+   Eldbus_Service_Interface *proxy_infc;
+   ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(proxy, pd);
+   eldbus_name_request(conn, bus, ELDBUS_NAME_REQUEST_FLAG_DO_NOT_QUEUE, NULL, NULL);
+   proxy_infc = eldbus_service_interface_register(pd->a11y_bus, path, &_proxy_iface_desc);
+   if (!proxy_infc)
+     ERR("AT-SPI: Proxy interface registration failed");
+   efl_event_callback_add(proxy, EFL_EVENT_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;
+   // TIZEN_ONLY(20160705) - enable atspi_proxy to work
+   Eo *bridge = _elm_atspi_bridge_get();
+   ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
+   //
+
+   bus = efl_key_data_get(proxy, "__svc_bus");
+   path = efl_key_data_get(proxy, "__svc_path");
+
+   if (bus && path)
+     _proxy_interface_register(conn, proxy, bus, path);
+
+   // TIZEN_ONLY(20160705) - enable atspi_proxy to work
+   pd->interfaces.socket =
+      eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &socket_iface_desc);
+   //
+}
+
+EAPI void elm_atspi_bridge_utils_proxy_listen(Eo *proxy)
+{
+   Eo *bridge = _elm_atspi_bridge_get();
+   if (!bridge)
+     {
+        ERR("AT-SPI: Atspi bridge is not enabled.");
+        return;
+     }
+   ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
+   if (!pd->a11y_bus)
+     {
+        if (!eina_list_data_find(pd->socket_queue, proxy))
+          {
+             pd->socket_queue = eina_list_append(pd->socket_queue, proxy);
+             efl_event_callback_add(proxy, EFL_EVENT_DEL, _from_list_remove, &pd->socket_queue);
+          }
+        return;
+     }
+   _socket_ifc_create(pd->a11y_bus, proxy);
+}
+//
+
+// TIZEN_ONLY(20160705) - enable atspi_proxy to work
+void elm_atspi_bridge_utils_proxy_offset_set(Eo *proxy, int x, int y)
+{
+   const char *bus, *path;
+   Eo *bridge = _elm_atspi_bridge_get();
+   if (!bridge) return;
+
+   ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd);
+
+   if (!pd->a11y_bus) return;
+
+   elm_obj_atspi_proxy_address_get(proxy, &bus, &path);
+   if (!bus || !path)
+     {
+        ERR("AT-SPI: Elm_Atspi_Proxy bus or path not set.");
+        return;
+     }
+   _plug_offset_set_send(pd->a11y_bus, bus, path, x, y);
+}
+//
 #include "elm_atspi_bridge.eo.c"
index c1e7e5d..e068426 100644 (file)
@@ -13,6 +13,19 @@ class Elm.Atspi.Bridge (Efl.Object)
             }
          }
       }
+      //TIZEN_ONLY(20171108): make atspi_proxy work
+      @property root {
+         get {
+            [[Get root object of accessible object hierarchy
+
+              \@internal
+            ]]
+            values {
+               return: Efl.Object;
+            }
+         }
+      }
+      //
    }
    implements {
       Efl.Object.constructor;
diff --git a/src/lib/elementary/elm_atspi_proxy.c b/src/lib/elementary/elm_atspi_proxy.c
new file mode 100644 (file)
index 0000000..894dbfe
--- /dev/null
@@ -0,0 +1,165 @@
+#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;
+   Ecore_Timer *retry_timer;
+   int retry_count;
+};
+
+#define ELM_ATSPI_PROXY_RETRY_TIME 1.0
+#define ELM_ATSPI_PROXY_RETRY_COUNT_LIMIT 5
+static Eina_Bool
+_retry_timer_cb(void *data)
+{
+   Eo *proxy;
+
+   proxy = data;
+   Elm_Atspi_Proxy_Data *_pd = efl_data_scope_get(proxy, ELM_ATSPI_PROXY_CLASS);
+
+   if (_pd->bus && _pd->path)
+     {
+        DBG("Address allocated: %s, %s", _pd->bus, _pd->path);
+        _pd->retry_count = 0;
+        _pd->retry_timer = NULL;
+        return ECORE_CALLBACK_CANCEL;
+     }
+
+   if (_pd->retry_count < ELM_ATSPI_PROXY_RETRY_COUNT_LIMIT)
+     {
+        elm_atspi_bridge_utils_proxy_connect(proxy);
+        _pd->retry_count++;
+        return ECORE_CALLBACK_RENEW;
+     }
+
+   _pd->retry_count = 0;
+   _pd->retry_timer = NULL;
+   return ECORE_CALLBACK_CANCEL;
+}
+
+EOLIAN static void
+_elm_atspi_proxy_address_get_retry_timer_add(Eo *obj, Elm_Atspi_Proxy_Data *_pd)
+{
+   if (_pd->type != ELM_ATSPI_PROXY_TYPE_PLUG)
+     {
+        ERR("Proxy type is not ELM_ATSPI_PROXY_TYPE_PLUG");
+        return;
+     }
+
+   if (_pd->retry_timer)
+     {
+        DBG("Retry timer is already added");
+        return;
+     }
+
+   _pd->retry_timer = ecore_timer_add(ELM_ATSPI_PROXY_RETRY_TIME,
+                                      _retry_timer_cb, obj);
+}
+
+EOLIAN static void
+_elm_atspi_proxy_efl_object_destructor(Eo *obj, Elm_Atspi_Proxy_Data *_pd)
+{
+   if (_pd->retry_timer)
+     {
+        ecore_timer_del(_pd->retry_timer);
+        _pd->retry_timer = NULL;
+     }
+   if (_pd->type == ELM_ATSPI_PROXY_TYPE_SOCKET)
+      _socket_list = eina_list_remove(_socket_list, obj);
+
+   if (_pd->bus)
+     {
+        eina_stringshare_del(_pd->bus);
+        _pd->bus = NULL;
+     }
+   if (_pd->path)
+     {
+        eina_stringshare_del(_pd->path);
+        _pd->path = NULL;
+     }
+
+   efl_destructor(efl_super(obj, ELM_CTXPOPUP_ITEM_CLASS));
+}
+
+EOLIAN static void
+_elm_atspi_proxy_constructor(Eo *obj, Elm_Atspi_Proxy_Data *_pd, Elm_Atspi_Proxy_Type type)
+{
+   Eo *parent;
+
+   _pd->type = type;
+   parent = efl_parent_get(obj);
+   if (!parent || !efl_isa(parent, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
+     {
+        CRI("Elm_Atspi_Proxy parent (%s) must implement ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN", efl_class_name_get(efl_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;
+        parent = efl_parent_get(obj);
+        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)
+     {
+        ret = efl_parent_get(obj);
+     }
+   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/elementary/elm_atspi_proxy.eo b/src/lib/elementary/elm_atspi_proxy.eo
new file mode 100644 (file)
index 0000000..66eda87
--- /dev/null
@@ -0,0 +1,51 @@
+enum Elm.Atspi.Proxy_Type
+{
+   SOCKET,
+   PLUG
+}
+
+class Elm.Atspi.Proxy (Elm.Widget)
+{
+   eo_prefix: elm_obj_atspi_proxy;
+   event_prefix: elm_atspi_proxy;
+   data: Elm_Atspi_Proxy_Data;
+   methods {
+      constructor {
+         [[ No description supplied by the EAPI.]]
+         params {
+            @in type: Elm.Atspi.Proxy_Type;
+         }
+      }
+      @property address {
+         set {
+         }
+         get {
+         }
+         values {
+            bus: string;
+            path: string;
+         }
+      }
+      @property type {
+         get {
+         }
+         values {
+            ret:Elm.Atspi.Proxy_Type;
+         }
+      }
+      address_get_retry_timer_add {
+      }
+   }
+   constructors {
+      .constructor;
+   }
+   implements {
+      Efl.Object.destructor;
+      Elm.Interface.Atspi_Accessible.children { get; }
+      Elm.Interface.Atspi_Accessible.parent { get; }
+   }
+   events {
+      connected;
+      disconnected;
+   }
+}
diff --git a/src/lib/elementary/elm_atspi_proxy.h b/src/lib/elementary/elm_atspi_proxy.h
new file mode 100644 (file)
index 0000000..e062580
--- /dev/null
@@ -0,0 +1,7 @@
+#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
+
index 62bb83b..aca665c 100644 (file)
@@ -176,12 +176,31 @@ _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);
+
+        //TIZEN_ONLY(20171108): make atspi_proxy work
+        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;
 }
 
+//TIZEN_ONLY(20171108): make atspi_proxy work
+EOLIAN static Eina_List*
+_elm_plug_elm_interface_atspi_accessible_children_get(Eo *obj, void *sd EINA_UNUSED)
+{
+   Eina_List *ret;
+   ret = elm_interface_atspi_accessible_children_get(efl_super(obj, ELM_WIDGET_CLASS));
+   return ret;
+}
+//
+
 EOLIAN static void
 _elm_plug_class_constructor(Efl_Class *klass)
 {
index f1e4d29..3985136 100644 (file)
@@ -35,6 +35,9 @@ class Elm.Plug (Elm.Widget, Efl.Ui.Clickable)
       Efl.Object.constructor;
       Elm.Widget.theme_apply;
       Elm.Widget.on_focus_update;
+      //TIZEN_ONLY(20171108): make atspi_proxy work
+      Elm.Interface.Atspi_Accessible.children { get; }
+      //
    }
    events {
       image,deleted; [[Called when image was deleted]]
index 135b06b..eb17ede 100644 (file)
@@ -706,6 +706,13 @@ void                *_elm_icon_signal_callback_del(Evas_Object *obj,
                                                    const char *source,
                                                    Edje_Signal_Cb func_cb);
  void                _efl_ui_image_sizing_eval(Evas_Object *obj);
+//TIZEN_ONLY(20171108): make atspi_proxy work
+Eo*                  _elm_atspi_bridge_utils_proxy_create(Eo *parent, const char *svcname, int svcnum, Elm_Atspi_Proxy_Type type);
+void                 elm_atspi_bridge_utils_proxy_listen(Eo *proxy);
+void                 elm_atspi_bridge_utils_proxy_connect(Eo *proxy);
+void                 elm_atspi_bridge_utils_proxy_offset_set(Eo *proxy, int x, int y);
+Eina_Bool            _elm_atspi_bridge_plug_id_split(const char *plug_id, char **bus, char **path);
+//
 /* end of DEPRECATED */
 
 /* DO NOT USE THIS this is only for performance optimization! */
index 40b226e..3476e9f 100644 (file)
@@ -5313,6 +5313,39 @@ _elm_widget_efl_access_name_get(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
    return _elm_widget_accessible_plain_name_get(obj, ret);
 }
 
+//TIZEN_ONLY(20171108): make atspi_proxy work
+static void
+_proxy_widget_move_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
+{
+   Evas_Coord x, y;
+   Eo *proxy = data;
+
+   evas_object_geometry_get(obj, &x, &y, NULL, NULL);
+   elm_atspi_bridge_utils_proxy_offset_set(proxy, x, y);
+}
+
+static void
+_on_widget_del(void *data, const Efl_Event *event)
+{
+   Eo *plug = data;
+   evas_object_event_callback_del_full(event->object, EVAS_CALLBACK_MOVE,
+                                       _proxy_widget_move_cb, plug);
+   efl_del(plug);
+}
+
+static void
+_on_proxy_connected_cb(void *data, const Efl_Event *event)
+{
+   Evas_Coord x, y;
+   Evas_Object *widget = data;
+
+   evas_object_geometry_get(widget, &x, &y, NULL, NULL);
+   elm_atspi_bridge_utils_proxy_offset_set(event->object, x, y);
+
+   evas_object_event_callback_add(widget, EVAS_CALLBACK_MOVE, _proxy_widget_move_cb, event->object);
+}
+//
+
 EOLIAN static Eina_List*
 _elm_widget_efl_access_children_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *pd)
 {
@@ -5322,6 +5355,34 @@ _elm_widget_efl_access_children_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *
 
    EINA_LIST_FOREACH(pd->subobjs, l, widget)
      {
+        //TIZEN_ONLY(20171108): make atspi_proxy work
+        const char *plug_id_2;
+        if ((plug_id_2 = evas_object_data_get(widget, "___PLUGID")) != NULL)
+          {
+             Eo *proxy;
+             char *svcname, *svcnum;
+
+             proxy = evas_object_data_get(widget, "__widget_proxy");
+             if (proxy)
+               {
+                  accs = eina_list_append(accs, proxy);
+                  continue;
+               }
+
+             if (_elm_atspi_bridge_plug_id_split(plug_id_2, &svcname, &svcnum))
+               {
+                  proxy = _elm_atspi_bridge_utils_proxy_create(obj, svcname, atoi(svcnum), ELM_ATSPI_PROXY_TYPE_PLUG);
+                  evas_object_data_set(widget, "__widget_proxy", proxy);
+                  efl_event_callback_add(widget, EFL_EVENT_DEL, _on_widget_del, proxy);
+                  efl_event_callback_add(proxy, ELM_ATSPI_PROXY_EVENT_CONNECTED,  _on_proxy_connected_cb, widget);
+                  elm_atspi_bridge_utils_proxy_connect(proxy);
+                  accs = eina_list_append(accs, proxy);
+                  free(svcname);
+                  free(svcnum);
+               }
+             continue;
+          }
+        //
         if (!elm_object_widget_check(widget)) continue;
         if (!efl_isa(widget, EFL_ACCESS_MIXIN)) continue;
         type = efl_access_type_get(widget);
@@ -6035,6 +6096,10 @@ _elm_widget_efl_access_component_accessible_at_point_get(Eo *obj, Elm_Widget_Sma
    Eo *child;
    Evas_Object *stack_item;
    Eo *compare_obj;
+   // TIZEN_ONLY(20160705) - enable atspi_proxy to work
+   Eo *proxy;
+   Evas_Coord px, py, pw, ph;
+   //
    int ee_x, ee_y;
 
    if (screen_coords)
@@ -6050,7 +6115,6 @@ _elm_widget_efl_access_component_accessible_at_point_get(Eo *obj, Elm_Widget_Sma
 
    /* Get evas_object stacked at given x,y coordinates starting from top */
    Eina_List *stack = evas_tree_objects_at_xy_get(evas_object_evas_get(obj), NULL, x, y);
-
    /* Foreach stacked object starting from top */
    EINA_LIST_FOREACH(stack, l, stack_item)
      {
@@ -6084,6 +6148,20 @@ _elm_widget_efl_access_component_accessible_at_point_get(Eo *obj, Elm_Widget_Sma
                         eina_list_free(stack);
                         return child;
                      }
+
+                   // TIZEN_ONLY(20160705) - enable atspi_proxy to work
+                   proxy = evas_object_data_get(smart_parent, "__widget_proxy");
+                   if (proxy)
+                     {
+                        evas_object_geometry_get(smart_parent, &px, &py, &pw, &ph);
+                        if (x >= px && x <= px + pw && y >= py && y <= py +ph)
+                          {
+                             eina_list_free(children);
+                             eina_list_free(stack);
+                             return proxy;
+                          }
+                     }
+                   //
                    smart_parent = evas_object_smart_parent_get(smart_parent);
                }
           }
index 1571074..6ff5741 100644 (file)
@@ -756,6 +756,10 @@ EAPI const char      *elm_widget_theme_element_get(const Evas_Object *obj);
 EAPI Eina_Bool        elm_widget_theme_style_set(Evas_Object *obj, const char *name);
 EAPI const char      *elm_widget_theme_style_get(const Evas_Object *obj);
 EAPI Efl_Ui_Theme_Apply elm_widget_element_update(Evas_Object *obj, Evas_Object *component, const char *name);
+//TIZEN_ONLY(20171108): make atspi_proxy work
+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);
+//
 
 /* debug function. don't use it unless you are tracking parenting issues */
 EAPI void             elm_widget_tree_dump(const Evas_Object *top);