atspi: handle atspi proxy connection at runtime 02/135102/8
authorShinwoo Kim <cinoo.kim@samsung.com>
Wed, 21 Jun 2017 02:39:18 +0000 (11:39 +0900)
committerjunsu choi <jsuya.choi@samsung.com>
Thu, 29 Jun 2017 00:11:02 +0000 (00:11 +0000)
The following cases make atspi proxy work incorrectly.

[case 1]
1. screen reader on, then a11y order would be
   A1(embedding, deputy) - B1(embedded) - B2(embedded) - A2(embedding)
2. make A2 grab highlight
3. go previous, then A1 grabs highlight.
   but expected result is that the B2 grabs highlight

[case 2]
1. screen reader on, then a11y order would be
   A1(embedding, deputy) - B1(embedded) - B2(embedded) - A2(embedding)
2. make A1 grab highlight
3. go next, then B1 grabs highlight.
   This means that the proxy connection is made properly.
4. screen reader off
5. screen reader on, then a11y order is
   A1(embedding, deputy) -  A2(embedding)
   but the following is expected result as step 1
   A1(embedding, deputy) - B1(embedded) - B2(embedded) - A2(embedding)

So far the pory connects if elm_interface_atspi_children_get is called.
So there is no chance to make connection for the [case 1].

When atspi is disabled, then all atspi related interface is closed.
But the proxy related resources are not removed.
If atspi is enabled again, then newly created interface is used on new BUS.
And the proxy related resources are reused.
So the [case 2]  happens.

This patch set depends on screen-connector to use "widget,create" signal to
connect proxy on elementary side. This should be removed, and we have to
provide proper API to be used on screen-connector side to connect proxy.

Change-Id: I86f610504848db816e6db355316f8da06db513df

src/lib/elm_atspi_bridge.c
src/lib/elm_atspi_proxy.c
src/lib/elm_atspi_proxy.eo
src/lib/elm_layout.c
src/lib/elm_priv.h
src/lib/elm_widget.c
src/lib/elm_widget.eo
src/lib/elm_widget.h
src/lib/elm_win.c

index 6cd662688858710a600e9472f8187ae8dd1287e5..05d2fd77a207c819302c628e73d3496a60bcdb42 100644 (file)
@@ -6134,6 +6134,8 @@ _at_spi_client_enabled_get(void *data, const Eldbus_Message *msg, Eldbus_Pending
      _a11y_connection_init(data);
    else
      DBG("AT-SPI2 stack not enabled.");
+
+   _elm_win_atspi(is_enabled);
 }
 //
 
@@ -6386,6 +6388,9 @@ _properties_changed_cb(void *data, Eldbus_Proxy *proxy EINA_UNUSED, void *event)
              ERR("Unable to get " A11Y_DBUS_ENABLED_PROPERTY " property value");
              return;
           }
+
+        _elm_win_atspi(val);
+
         if (val)
           _a11y_connection_init(bridge);
         else
index 2de8dc42d03815156dd862d7115c91771d48faf7..0d86a8f8481a4a07d550e026e92c485218280261 100644 (file)
@@ -162,4 +162,14 @@ _elm_atspi_proxy_socket_list_get(void)
    return eina_list_clone(_socket_list);
 }
 
+EOLIAN static void
+_elm_atspi_proxy_elm_widget_atspi(Eo *obj, Elm_Atspi_Proxy_Data *_pd, Eina_Bool is_atspi)
+{
+   EINA_SAFETY_ON_NULL_RETURN(obj);
+   if (is_atspi && _pd->type == ELM_ATSPI_PROXY_TYPE_PLUG)
+     {
+        elm_atspi_bridge_utils_proxy_connect(obj);
+     }
+}
+
 #include "elm_atspi_proxy.eo.c"
index 76b4c75c1b421fb5ea11df1182055fb20a287498..4c7d634a671bc8812a2aa67ec93c2af680c325e7 100644 (file)
@@ -36,6 +36,7 @@ class Elm_Atspi_Proxy (Elm.Widget)
       Eo.Base.destructor;
       Elm_Interface_Atspi_Accessible.children.get;
       Elm_Interface_Atspi_Accessible.parent.get;
+      Elm.Widget.atspi;
    }
    events {
       connected;
index e770dfca932fbf54434cf8e43c1fafba14f6ba4a..4dd73616e587e29489019d4bd391442c44a28621 100644 (file)
@@ -1827,6 +1827,14 @@ elm_layout_add(Evas_Object *parent)
    return obj;
 }
 
+//TIZEN_ONLY(20170621) handle atspi proxy connection at runtime
+static void
+_widget_created_cb(void *data EINA_UNUSED, Evas_Object *obj, void *ev EINA_UNUSED)
+{
+   elm_widget_atspi_plug_type_proxy_get(obj);
+}
+//
+
 EOLIAN static Eo *
 _elm_layout_eo_base_constructor(Eo *obj, Elm_Layout_Smart_Data *sd)
 {
@@ -1837,6 +1845,12 @@ _elm_layout_eo_base_constructor(Eo *obj, Elm_Layout_Smart_Data *sd)
          evas_obj_smart_callbacks_descriptions_set(_smart_callbacks),
          elm_interface_atspi_accessible_role_set(ELM_ATSPI_ROLE_FILLER));
 
+   //TIZEN_ONLY(20170621) handle atspi proxy connection at runtime
+   /* FIXME: This makes dependency on screen-connector. The screen-connector
+      should use new API to handle atspi proxy connection at runtime. */
+   evas_object_smart_callback_add(obj, "widget,created", _widget_created_cb, NULL);
+   //
+
    return obj;
 }
 
index 4c90196ab4bec23d08d6f49a207337444939b110..9409ad3cb248284d5540b0ed39688dfcbdb623a0 100644 (file)
@@ -394,6 +394,7 @@ void                 _elm_win_access(Eina_Bool is_access);
 //register/unregister access objects accordingly.
 // TIZEN_ONLY(20170516): connect to at-spi dbus based on org.a11y.Status.IsEnabled property
 void                 _elm_win_screen_reader(Eina_Bool is_screen_reader);
+void                 _elm_win_atspi(Eina_Bool is_atspi);
 //
 //
 void                 _elm_win_translate(void);
index 436fe37a9511338d19ad8fb7a61d3f427ffeb36f..fbbcae98d9ca4e7f8b641150d4875f8d1eca6163 100644 (file)
@@ -976,6 +976,31 @@ EOLIAN static void
 _elm_widget_screen_reader(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Eina_Bool is_screen_reader EINA_UNUSED)
 {
 }
+
+//TIZEN_ONLY(20170621) handle atspi proxy connection at runtime
+EAPI Eina_Bool
+elm_widget_atspi(Evas_Object *obj, Eina_Bool is_atspi)
+{
+   Eina_List *l, *children;
+   Evas_Object *child;
+   Eina_Bool ret = EINA_TRUE;
+
+   API_ENTRY return EINA_FALSE;
+   eo_do(obj, children = elm_interface_atspi_accessible_children_get());
+   EINA_LIST_FOREACH(children, l, child)
+     {
+        ret &= elm_widget_atspi(child, is_atspi);
+     }
+   eo_do(obj, elm_obj_widget_atspi(is_atspi));
+
+   return ret;
+}
+
+EOLIAN static void
+_elm_widget_atspi(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Eina_Bool is_atspi EINA_UNUSED)
+{
+}
+//
 //
 //
 
@@ -6739,6 +6764,58 @@ _on_proxy_connected_cb(void *data, Eo *obj, const Eo_Event_Description *desc EIN
 //
 // TIZEN ONLY - END
 
+//TIZEN_ONLY(20170621) handle atspi proxy connection at runtime
+static Eo *
+_plug_type_proxy_get(Eo *obj, Evas_Object *widget)
+{
+   Eo *proxy = NULL;
+   const char *plug_id;
+   char *svcname, *svcnum;
+
+   if ((plug_id = evas_object_data_get(widget, "___PLUGID")) != NULL)
+     {
+        // TIZEN_ONLY(20160930) : endless recursion fix
+        eo_do_super(obj, MY_CLASS, elm_interface_atspi_accessible_attribute_append("___PlugID", plug_id));
+
+        proxy = evas_object_data_get(widget, "__widget_proxy");
+        if (proxy) return proxy;
+
+        if (_elm_atspi_bridge_plug_id_split(plug_id, &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);
+             eo_do(widget, eo_event_callback_add(EO_EV_DEL, _on_widget_del, proxy));
+             eo_do(proxy, eo_event_callback_add(ELM_ATSPI_PROXY_EVENT_CONNECTED, _on_proxy_connected_cb, widget));
+             elm_atspi_bridge_utils_proxy_connect(proxy);
+             free(svcname);
+             free(svcnum);
+          }
+     }
+
+   return proxy;
+}
+
+EAPI Eo *
+elm_widget_atspi_plug_type_proxy_get(Evas_Object *obj)
+{
+   Elm_Widget_Smart_Data *wd;
+   Evas_Object *widget;
+   Eina_List *l;
+
+   wd = eo_data_scope_get(obj, ELM_WIDGET_CLASS);
+   if (!wd) return NULL;
+
+   Eo *proxy = NULL;
+   EINA_LIST_FOREACH(wd->subobjs, l, widget)
+     {
+        if (evas_object_data_get(widget, "___PLUGID"))
+           proxy = _plug_type_proxy_get(obj, widget);
+        if (proxy) break;
+     }
+   return proxy;
+}
+//
+
 EOLIAN static Eina_List*
 _elm_widget_elm_interface_atspi_accessible_children_get(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
 {
@@ -6773,33 +6850,15 @@ _elm_widget_elm_interface_atspi_accessible_children_get(Eo *obj, Elm_Widget_Smar
         }
 
         // TIZEN_ONLY(20160705) - enable atspi_proxy to work
-        const char *plug_id_2;
-        if ((plug_id_2 = evas_object_data_get(widget, "___PLUGID")) != NULL)
+        /* This assumes that only one proxy exists in obj */
+        if (!proxy)
           {
-            // TIZEN_ONLY(20160930) : endless recursion fix
-            eo_do_super(obj, MY_CLASS, elm_interface_atspi_accessible_attribute_append("___PlugID", plug_id_2));
-
-             char *svcname, *svcnum;
-
-             proxy = evas_object_data_get(widget, "__widget_proxy");
+             proxy = _plug_type_proxy_get(obj, widget);
              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);
-                  eo_do(widget, eo_event_callback_add(EO_EV_DEL, _on_widget_del, proxy));
-                  eo_do(proxy, eo_event_callback_add(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;
           }
         //
         // TIZEN ONLY - END
index 2f5ad8cab635ba81d84a8df01a183709868b677c..b50f53c92a1c66b5be347a07c558acc9219708bc 100644 (file)
@@ -520,12 +520,21 @@ abstract Elm.Widget (Evas.Object_Smart, Elm_Interface_Atspi_Accessible,
       //register/unregister access objects accordingly.
       // TIZEN_ONLY(20170516): connect to at-spi dbus based on org.a11y.Status.IsEnabled property
       screen_reader {
-         [['Virtual' function on the widget being set access.]]
+         [['Virtual' function on the widget being set screen reader.]]
          params {
             @in is_screen_reader: bool;
          }
          legacy: null;
       }
+      //TIZEN_ONLY(20170621) handle atspi proxy connection at runtime
+      atspi {
+         [['Virtual' function on the widget being set atspi.]]
+         params {
+            @in is_atspi: bool;
+         }
+         legacy: null;
+      }
+      //
       //
       //
       cursor_del {
index 2ff0dffb7c320c010ee5907eef9ee8b796196b1d..da289e9e1084f3eecbc5bbb84e2ece06c5ab78b6 100644 (file)
@@ -707,6 +707,10 @@ EAPI Eina_Bool        elm_widget_access(Evas_Object *obj, Eina_Bool is_access);
 //register/unregister access objects accordingly.
 // TIZEN_ONLY(20170516): connect to at-spi dbus based on org.a11y.Status.IsEnabled property
 EAPI Eina_Bool        elm_widget_screen_reader(Evas_Object *obj, Eina_Bool is_access);
+EAPI Eina_Bool        elm_widget_atspi(Evas_Object *obj, Eina_Bool is_atspi);
+//TIZEN_ONLY(20170621) handle atspi proxy connection at runtime
+EAPI Eo              *elm_widget_atspi_plug_type_proxy_get(Evas_Object *obj);
+//
 //
 //
 EAPI Elm_Theme_Apply  elm_widget_theme(Evas_Object *obj);
index 90b5eae2b96decec0d1651c85fa9ef4a7cfe00dc..e5a73be187c904ae6d4403266480e91f00566d0f 100644 (file)
@@ -3029,16 +3029,38 @@ _elm_win_screen_reader(Eina_Bool is_screen_reader)
           {
              eo_do(obj, elm_interface_atspi_component_highlight_clear());
           }
-        //TIZEN_ONLY(20170613) -listen if atspi is enabled
+     }
+}
+
+//TIZEN_ONLY(20170621) handle atspi proxy connection at runtime
+void
+_elm_win_atspi(Eina_Bool is_atspi)
+{
+   const Eina_List *l;
+   Evas_Object *obj;
+
+   EINA_LIST_FOREACH(_elm_win_list, l, obj)
+     {
+        elm_widget_atspi(obj, is_atspi);
+
+        if (!is_atspi)
+          {
+             ELM_WIN_DATA_GET(obj, sd);
+             if (sd->socket_proxy)
+               {
+                  eo_unref(sd->socket_proxy);
+                  sd->socket_proxy = NULL;
+               }
+          }
         else
           {
              _atspi_socket_proxy_listen(obj);
           }
-        //
      }
 }
 //
 //
+//
 
 void
 _elm_win_translate(void)