From: Shinwoo Kim Date: Wed, 21 Jun 2017 02:39:18 +0000 (+0900) Subject: atspi: handle atspi proxy connection at runtime X-Git-Tag: submit/tizen_3.0/20170705.022822~8 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=6618afe68c1d110649fb0fae4bacb2e69a649eaf;p=platform%2Fupstream%2Felementary.git atspi: handle atspi proxy connection at runtime 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 --- diff --git a/src/lib/elm_atspi_bridge.c b/src/lib/elm_atspi_bridge.c index 6cd662688..05d2fd77a 100644 --- a/src/lib/elm_atspi_bridge.c +++ b/src/lib/elm_atspi_bridge.c @@ -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 diff --git a/src/lib/elm_atspi_proxy.c b/src/lib/elm_atspi_proxy.c index 2de8dc42d..0d86a8f84 100644 --- a/src/lib/elm_atspi_proxy.c +++ b/src/lib/elm_atspi_proxy.c @@ -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" diff --git a/src/lib/elm_atspi_proxy.eo b/src/lib/elm_atspi_proxy.eo index 76b4c75c1..4c7d634a6 100644 --- a/src/lib/elm_atspi_proxy.eo +++ b/src/lib/elm_atspi_proxy.eo @@ -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; diff --git a/src/lib/elm_layout.c b/src/lib/elm_layout.c index e770dfca9..4dd73616e 100644 --- a/src/lib/elm_layout.c +++ b/src/lib/elm_layout.c @@ -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; } diff --git a/src/lib/elm_priv.h b/src/lib/elm_priv.h index 4c90196ab..9409ad3cb 100644 --- a/src/lib/elm_priv.h +++ b/src/lib/elm_priv.h @@ -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); diff --git a/src/lib/elm_widget.c b/src/lib/elm_widget.c index 436fe37a9..fbbcae98d 100644 --- a/src/lib/elm_widget.c +++ b/src/lib/elm_widget.c @@ -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 diff --git a/src/lib/elm_widget.eo b/src/lib/elm_widget.eo index 2f5ad8cab..b50f53c92 100644 --- a/src/lib/elm_widget.eo +++ b/src/lib/elm_widget.eo @@ -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 { diff --git a/src/lib/elm_widget.h b/src/lib/elm_widget.h index 2ff0dffb7..da289e9e1 100644 --- a/src/lib/elm_widget.h +++ b/src/lib/elm_widget.h @@ -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); diff --git a/src/lib/elm_win.c b/src/lib/elm_win.c index 90b5eae2b..e5a73be18 100644 --- a/src/lib/elm_win.c +++ b/src/lib/elm_win.c @@ -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)