diff options
author | Lukasz Stanislawski <l.stanislaws@samsung.com> | 2017-12-19 23:58:36 +0100 |
---|---|---|
committer | Lukasz Stanislawski <lukasz.stanislawski@gmail.com> | 2017-12-19 23:58:36 +0100 |
commit | 949a8bb4293356d37281e5a55ccab9a817677ada (patch) | |
tree | 2760bfad586497fabcf3d1517f3cb451409c6050 | |
parent | 453361cac12d587cedb9854a0747b75a598e160e (diff) | |
download | efl-949a8bb4293356d37281e5a55ccab9a817677ada.tar.gz |
elm: refactor initialization process
Summary: Change-Id: I0d4723718509e2f5f775f398d58d4d1231a10dee
Subscribers: cedric, jpeg
Differential Revision: https://phab.enlightenment.org/D5684
-rw-r--r-- | src/lib/elementary/elm_atspi_bridge.c | 201 |
1 files changed, 107 insertions, 94 deletions
diff --git a/src/lib/elementary/elm_atspi_bridge.c b/src/lib/elementary/elm_atspi_bridge.c index 09ea6a1693..2de63c7487 100644 --- a/src/lib/elementary/elm_atspi_bridge.c +++ b/src/lib/elementary/elm_atspi_bridge.c @@ -26,6 +26,8 @@ #define A11Y_DBUS_PATH "/org/a11y/bus" #define A11Y_DBUS_INTERFACE "org.a11y.Bus" #define A11Y_DBUS_STATUS_INTERFACE "org.a11y.Status" +#define A11Y_DBUS_SCREEN_READER_ENABLED_PROPERTY_NAME "ScreenReaderEnabled" +#define A11Y_DBUS_A11Y_STACK_ENABLING_PROPERTY_NAME A11Y_DBUS_SCREEN_READER_ENABLED_PROPERTY_NAME #define ATSPI_DBUS_INTERFACE_EVENT_WINDOW "org.a11y.atspi.Event.Window" #define CACHE_ITEM_SIGNATURE "((so)(so)(so)a(so)assusau)" @@ -67,7 +69,12 @@ typedef struct Key_Event_Info { typedef struct _Elm_Atspi_Bridge_Data { Eldbus_Connection *session_bus; + Eldbus_Proxy *status_proxy; + Eldbus_Object *bus_obj; + Eldbus_Pending *get_address_pending; + Eldbus_Connection *a11y_bus; + Eina_List *reemited_events; Eina_Hash *cache; Eldbus_Service_Interface *cache_interface; @@ -79,7 +86,6 @@ typedef struct _Elm_Atspi_Bridge_Data unsigned long long object_state_broadcast_mask; unsigned long long window_signal_broadcast_mask; Ecore_Event_Filter *key_flr; - Eldbus_Object *bus_obj; Eina_List *pending_requests; int id; Eina_Hash *state_hash; @@ -3789,10 +3795,6 @@ _registered_listeners_get(void *data, const Eldbus_Message *msg, Eldbus_Pending ERR("Cannot get bus and event from registered listener"); else _set_broadcast_flag(event, data); } - - if (!pd->connected) - efl_event_callback_legacy_call(data, ELM_ATSPI_BRIDGE_EVENT_CONNECTED, NULL); - pd->connected = EINA_TRUE; } static void @@ -4255,16 +4257,21 @@ _interfaces_unregister(Eo *bridge) } static void -_a11y_connection_shutdown(Eo *bridge) +_elm_atspi_bridge_disconnect(Eo *bridge) { ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd); Eldbus_Pending *pending; + if (pd->get_address_pending) + eldbus_pending_cancel(pd->get_address_pending); + pd->get_address_pending = NULL; + if (pd->connected) _elm_atspi_bridge_app_unregister(bridge); if (pd->cache) eina_hash_free(pd->cache); + pd->cache = NULL; if (pd->cache_interface) @@ -4304,7 +4311,7 @@ _a11y_connection_shutdown(Eo *bridge) static void _disconnect_cb(void *data, Eldbus_Connection *conn EINA_UNUSED, void *event_info EINA_UNUSED) { - _a11y_connection_shutdown(data); + _elm_atspi_bridge_disconnect(data); } static void @@ -4365,16 +4372,10 @@ _bridge_accessible_event_dispatch(void *data, const Efl_Event *event) } static void -_a11y_bus_initialize(Eo *obj, const char *socket_addr) +_a11y_bus_initialize(Eo *obj) { ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(obj, pd); - pd->a11y_bus = eldbus_private_address_connection_get(socket_addr); - if (!pd->a11y_bus) - return; - - eldbus_connection_event_callback_add(pd->a11y_bus, ELDBUS_CONNECTION_EVENT_DISCONNECTED, _disconnect_cb, obj); - // init data structures pd->cache = eina_hash_pointer_new(NULL); pd->state_hash = _elm_atspi_state_hash_build(); @@ -4390,13 +4391,14 @@ _a11y_bus_initialize(Eo *obj, const char *socket_addr) pd->event_hdlr = efl_access_event_handler_add(EFL_ACCESS_MIXIN, _bridge_accessible_event_dispatch, obj); } +// 2nd step of initialization process. Make real connection with accessibility bus. static void -_a11y_bus_address_get(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending) +_a11y_bus_address_get(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED) { const char *errname, *errmsg, *sock_addr = NULL; ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(data, pd); - pd->pending_requests = eina_list_remove(pd->pending_requests, pending); + pd->get_address_pending = NULL; if (eldbus_message_error_get(msg, &errname, &errmsg)) { @@ -4410,55 +4412,41 @@ _a11y_bus_address_get(void *data, const Eldbus_Message *msg, Eldbus_Pending *pen return; } - _a11y_bus_initialize((Eo*)data, sock_addr); + pd->a11y_bus = eldbus_private_address_connection_get(sock_addr); + if (!pd->a11y_bus) + return; + + _a11y_bus_initialize((Eo*)data); + eldbus_connection_event_callback_add(pd->a11y_bus, ELDBUS_CONNECTION_EVENT_DISCONNECTED, _disconnect_cb, data); + + pd->connected = EINA_TRUE; } -static void _a11y_connection_init(Eo *bridge) +/* + * Initialize dbus connection with accessibility dbus daemon. Initialization + * consists of two steps. In first address of dbus daemon is fetched + * asynchronously from org.a11y.Bus interface. In second step the connection + * is made and internal data of bridge get initialized. + */ +static void _elm_atspi_bridge_connect(Eo *bridge) { ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd); - Eina_Bool is_connected; - is_connected = elm_obj_atspi_bridge_connected_get(bridge); - - if (is_connected) return; - - Eldbus_Message *m = eldbus_object_method_call_new(pd->bus_obj, A11Y_DBUS_INTERFACE, "GetAddress"); - Eldbus_Pending *p = eldbus_object_send(pd->bus_obj, m, _a11y_bus_address_get, bridge, 100); - - if (p) - pd->pending_requests = eina_list_append(pd->pending_requests, p); -} + if (elm_obj_atspi_bridge_connected_get(bridge)) + return; -static void -_screen_reader_enabled_get(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending) -{ - ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(data, pd); - const char *errname, *errmsg; - Eina_Bool is_enabled; - Eldbus_Message_Iter *variant; + if (pd->get_address_pending) + eldbus_pending_cancel(pd->get_address_pending); - pd->pending_requests = eina_list_remove(pd->pending_requests, pending); + Eldbus_Message *msg = eldbus_object_method_call_new(pd->bus_obj, A11Y_DBUS_INTERFACE, "GetAddress"); + if (!msg) return; - if (eldbus_message_error_get(msg, &errname, &errmsg)) - { - WRN("%s %s", errname, errmsg); - return; - } - if (!eldbus_message_arguments_get(msg, "v", &variant)) + pd->get_address_pending = eldbus_object_send(pd->bus_obj, msg, _a11y_bus_address_get, bridge, 100); + if (!pd->get_address_pending) { - ERR("'ScreenReaderEnabled' not packed into variant."); + eldbus_message_unref(msg); return; } - if (!eldbus_message_iter_arguments_get(variant, "b", &is_enabled)) - { - ERR("Could not get 'ScreenReaderEnabled' boolean property"); - return; - } - - if (is_enabled) - _a11y_connection_init(data); - else - DBG("AT-SPI2 stack not enabled."); } static void _bridge_object_register(Eo *bridge, Eo *obj) @@ -4659,82 +4647,107 @@ _elm_atspi_bridge_connected_get(Eo *obj EINA_UNUSED, Elm_Atspi_Bridge_Data *pd) return pd->connected; } +static Eina_Bool +_proxy_get_boolean_property(Eldbus_Proxy *proxy, const char *property_name, Eina_Bool *out) +{ + Eina_Value *value; + if (!proxy) return EINA_FALSE; + value = eldbus_proxy_property_local_get(proxy, property_name); + if (!value) return EINA_FALSE; + if (eina_value_type_get(value) != EINA_VALUE_TYPE_UCHAR) + return EINA_FALSE; + if (!eina_value_get(value, out)) + return EINA_FALSE; + return EINA_TRUE; +} + static void -_properties_changed_cb(void *data, Eldbus_Proxy *proxy EINA_UNUSED, void *event) +_status_proxy_property_changed(void *data, Eldbus_Proxy *proxy, void *event) { Eldbus_Proxy_Event_Property_Changed *ev = event; Eo *bridge = data; - Eina_Bool val; - const char *ifc = eldbus_proxy_interface_get(ev->proxy); - if (ev->name && !strcmp(ev->name, "ScreenReaderEnabled" ) && - ifc && !strcmp(A11Y_DBUS_STATUS_INTERFACE, ifc)) + Eina_Bool enabled; + + if (!ev || !ev->name || strcmp(ev->name, A11Y_DBUS_A11Y_STACK_ENABLING_PROPERTY_NAME)) + return; + + if (!_proxy_get_boolean_property(proxy, A11Y_DBUS_A11Y_STACK_ENABLING_PROPERTY_NAME, &enabled)) { - if (!eina_value_get(ev->value, &val)) - { - ERR("Unable to get ScreenReaderEnabled property value"); - return; - } - if (val) - _a11y_connection_init(bridge); - else - _a11y_connection_shutdown(bridge); + ERR("Failed to get " A11Y_DBUS_A11Y_STACK_ENABLING_PROPERTY_NAME " property"); + return; } + + if (enabled) + _elm_atspi_bridge_connect(bridge); + else + _elm_atspi_bridge_disconnect(bridge); +} + +static void +_status_proxy_property_loaded(void *data, Eldbus_Proxy *proxy, void *event EINA_UNUSED) +{ + Eo *bridge = data; + Eina_Bool enabled; + + if (!_proxy_get_boolean_property(proxy, A11Y_DBUS_A11Y_STACK_ENABLING_PROPERTY_NAME, &enabled)) + { + ERR("Failed to get " A11Y_DBUS_A11Y_STACK_ENABLING_PROPERTY_NAME " property"); + return; + } + + if (enabled) + _elm_atspi_bridge_connect(bridge); + else + _elm_atspi_bridge_disconnect(bridge); } EOLIAN Efl_Object* _elm_atspi_bridge_efl_object_constructor(Eo *obj, Elm_Atspi_Bridge_Data *pd) { - Eldbus_Proxy *proxy; - Eldbus_Pending *req; - efl_constructor(efl_super(obj, ELM_ATSPI_BRIDGE_CLASS)); elm_need_eldbus(); - if (!(pd->session_bus = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SESSION))) - { - ERR("Unable to connect to Session Bus"); - return NULL; - } - if (!(pd->bus_obj = eldbus_object_get(pd->session_bus, A11Y_DBUS_NAME, A11Y_DBUS_PATH))) + pd->session_bus = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SESSION); + if (!pd->session_bus) + return NULL; + + pd->bus_obj = eldbus_object_get(pd->session_bus, A11Y_DBUS_NAME, A11Y_DBUS_PATH); + if (!pd->bus_obj) { - ERR("Could not get /org/a11y/bus object"); + ERR("Could not get " A11Y_DBUS_PATH " object"); goto obj_err; } - if (!(proxy = eldbus_proxy_get(pd->bus_obj, A11Y_DBUS_STATUS_INTERFACE))) + pd->status_proxy = eldbus_proxy_get(pd->bus_obj, A11Y_DBUS_STATUS_INTERFACE); + if (!pd->status_proxy) { - ERR("Could not get proxy object for %s interface", A11Y_DBUS_STATUS_INTERFACE); + ERR("Could not get proxy object for " A11Y_DBUS_STATUS_INTERFACE " interface"); goto proxy_err; } - if (!(req = eldbus_proxy_property_get(proxy, "ScreenReaderEnabled", _screen_reader_enabled_get, obj))) - { - ERR("Could not send PropertyGet request"); - goto proxy_err; - } - pd->pending_requests = eina_list_append(pd->pending_requests, req); - eldbus_proxy_properties_monitor(proxy, EINA_TRUE); - eldbus_proxy_event_callback_add(proxy, ELDBUS_PROXY_EVENT_PROPERTY_CHANGED, - _properties_changed_cb, obj); + eldbus_proxy_event_callback_add(pd->status_proxy, ELDBUS_PROXY_EVENT_PROPERTY_CHANGED, + _status_proxy_property_changed, obj); + eldbus_proxy_event_callback_add(pd->status_proxy, ELDBUS_PROXY_EVENT_PROPERTY_LOADED, + _status_proxy_property_loaded, obj); + eldbus_proxy_properties_monitor(pd->status_proxy, EINA_TRUE); return obj; proxy_err: eldbus_object_unref(pd->bus_obj); - pd->bus_obj = NULL; obj_err: eldbus_connection_unref(pd->session_bus); - pd->session_bus = NULL; return NULL; } EOLIAN void _elm_atspi_bridge_efl_object_destructor(Eo *obj, Elm_Atspi_Bridge_Data *pd) { - _a11y_connection_shutdown(obj); + _elm_atspi_bridge_disconnect(obj); - if (pd->bus_obj) eldbus_object_unref(pd->bus_obj); - if (pd->session_bus) eldbus_connection_unref(pd->session_bus); + eldbus_proxy_unref(pd->status_proxy); + eldbus_object_unref(pd->bus_obj); + eldbus_connection_unref(pd->session_bus); efl_destructor(efl_super(obj, ELM_ATSPI_BRIDGE_CLASS)); } |