diff options
author | Lukasz Stanislawski <lukasz.stanislawski@gmail.com> | 2017-12-15 19:48:41 +0100 |
---|---|---|
committer | Lukasz Stanislawski <lukasz.stanislawski@gmail.com> | 2017-12-17 18:16:14 +0100 |
commit | 34a440738487a3296bb2d71970bea73e7ba8c9cd (patch) | |
tree | 3a8ad59fba5c91400c08a0b659f03d8931693f7e | |
parent | b7a4c27e3655076889a5d142e7bdeb83435225fd (diff) | |
download | efl-34a440738487a3296bb2d71970bea73e7ba8c9cd.tar.gz |
Implement elm_atspi_bus_watcherdevs/stanluk/split2
Summary: Change-Id: If486eee49666640277cfbe9790e1ae5cf5bdb537
Subscribers: cedric, jpeg
Differential Revision: https://phab.enlightenment.org/D5572
-rw-r--r-- | src/Makefile_Elementary.am | 2 | ||||
-rw-r--r-- | src/examples/elementary/Makefile.am | 8 | ||||
-rw-r--r-- | src/examples/elementary/atspi_bus_watcher.c | 89 | ||||
-rw-r--r-- | src/lib/elementary/Elementary.h | 1 | ||||
-rw-r--r-- | src/lib/elementary/elm_atspi_bridge.c | 222 | ||||
-rw-r--r-- | src/lib/elementary/elm_atspi_bus_watcher.c | 227 | ||||
-rw-r--r-- | src/lib/elementary/elm_atspi_bus_watcher.eo | 38 |
7 files changed, 449 insertions, 138 deletions
diff --git a/src/Makefile_Elementary.am b/src/Makefile_Elementary.am index cb283e350d..6ff3304028 100644 --- a/src/Makefile_Elementary.am +++ b/src/Makefile_Elementary.am @@ -94,6 +94,7 @@ elm_public_eolian_files = \ lib/elementary/efl_config_global.eo \ lib/elementary/elm_code_widget.eo \ lib/elementary/elm_bus_watcher.eo \ + lib/elementary/elm_atspi_bus_watcher.eo \ $(NULL) # More public files -- FIXME @@ -749,6 +750,7 @@ lib_elementary_libelementary_la_SOURCES = \ lib/elementary/efl_ui_list_segarray.c \ lib/elementary/efl_ui_layout_factory.c \ lib/elementary/elm_bus_watcher.c \ + lib/elementary/elm_atspi_bus_watcher.c \ $(NULL) diff --git a/src/examples/elementary/Makefile.am b/src/examples/elementary/Makefile.am index 89bbc39d90..0599d3ca38 100644 --- a/src/examples/elementary/Makefile.am +++ b/src/examples/elementary/Makefile.am @@ -184,8 +184,9 @@ efl_thread_win32_3.c \ efl_thread_win32_4.c \ efl_ui_list_example_1.c \ efl_ui_list_example_2.c \ -efl_ui_list_example_3.c -bus_watcher.c +efl_ui_list_example_3.c \ +bus_watcher.c \ +atspi_bus_watcher.c SRCS += \ bg_cxx_example_01.cc \ @@ -379,7 +380,8 @@ efl_thread_6 \ efl_ui_list_example_1 \ efl_ui_list_example_2 \ efl_ui_list_example_3 \ -bus_watcher +bus_watcher \ +atspi_bus_watcher #benchmark3d #sphere-hunter diff --git a/src/examples/elementary/atspi_bus_watcher.c b/src/examples/elementary/atspi_bus_watcher.c new file mode 100644 index 0000000000..472f4de196 --- /dev/null +++ b/src/examples/elementary/atspi_bus_watcher.c @@ -0,0 +1,89 @@ +#define EFL_EO_API_SUPPORT +#define EFL_BETA_API_SUPPORT + +#include <Elementary.h> +#include <stdio.h> + +#define TEST_WRITE 1 + + +static void _cb1(void *data EINA_UNUSED, const Efl_Event *event EINA_UNUSED) +{ + printf("A11y stack enabled\n"); +} + +static void _cb2(void *data EINA_UNUSED, const Efl_Event *event EINA_UNUSED) +{ + printf("A11y stack disabled\n"); +} + +static void _cb3(void *data EINA_UNUSED, const Efl_Event *event) +{ + Atspi_Bus_Property *property = event->info; + switch (*property) + { + case ATSPI_BUS_PROPERTY_SCREENREADERENABLED: + printf("ScreenReaderEnabled property changed\n"); + break; + case ATSPI_BUS_PROPERTY_ISENABLED: + printf("IsEnabled property changed\n"); + break; + } +} + +static Eina_Value +_success(void *data, Eina_Value value) +{ + printf("Getting address successed.\n"); + Eina_Value_Type *type = eina_value_type_get(&value); + + if (type == EINA_VALUE_TYPE_STRUCT) + { + char *address = NULL; + if (!eina_value_struct_get(&value, "arg0", &address)) + printf("failed to get arg0 value.\n"); + printf("address is %s\n", address); + } + else { + printf("invalid answer type\n"); + } + return value; +} + +static Eina_Value +_failed(void *data, Eina_Value value) +{ + printf("Getting address failed.\n"); + return value; +} + +static void _registered(void *data, const Efl_Event *event EINA_UNUSED) +{ + Elm_Atspi_Bus_Watcher *watcher = data; + + elm_atspi_bus_watcher_property_try_set(watcher, ATSPI_BUS_PROPERTY_SCREENREADERENABLED, EINA_TRUE); + Eina_Future *address_feature = elm_atspi_bus_watcher_a11y_bus_address_get(watcher); + eina_future_cance(address_feature); + //eina_future_then_easy(address_feature, _success, NULL, NULL, NULL, NULL); +} + +EAPI_MAIN int +elm_main(int argc EINA_UNUSED, char **argv EINA_UNUSED) +{ + Elm_Atspi_Bus_Watcher *watcher = efl_add(ELM_ATSPI_BUS_WATCHER_CLASS, NULL); + Eldbus_Connection *conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SESSION); + + elm_bus_watcher_connection_set(watcher, conn); + efl_event_callback_add(watcher, ELM_ATSPI_BUS_WATCHER_EVENT_ENABLED, _cb1, watcher); + efl_event_callback_add(watcher, ELM_ATSPI_BUS_WATCHER_EVENT_DISABLED, _cb2, watcher); + efl_event_callback_add(watcher, ELM_ATSPI_BUS_WATCHER_EVENT_PROPERTY_CHANGED, _cb3, watcher); + efl_event_callback_add(watcher, ELM_BUS_WATCHER_EVENT_REGISTERED, _registered, watcher); + + eldbus_connection_unref(conn); + + elm_run(); + efl_unref(watcher); + + return 0; +} +ELM_MAIN() diff --git a/src/lib/elementary/Elementary.h b/src/lib/elementary/Elementary.h index d90c812e8c..87a11cca9d 100644 --- a/src/lib/elementary/Elementary.h +++ b/src/lib/elementary/Elementary.h @@ -323,6 +323,7 @@ EAPI extern Elm_Version *elm_version; # include <efl_ui_list.eo.h> # include <efl_ui_list_pan.eo.h> # include <elm_bus_watcher.eo.h> +# include <elm_atspi_bus_watcher.eo.h> #endif /* include deprecated calls last of all */ diff --git a/src/lib/elementary/elm_atspi_bridge.c b/src/lib/elementary/elm_atspi_bridge.c index 09ea6a1693..931f92cca0 100644 --- a/src/lib/elementary/elm_atspi_bridge.c +++ b/src/lib/elementary/elm_atspi_bridge.c @@ -22,10 +22,6 @@ /* * Accessibility Bus info not defined in atspi-constants.h */ -#define A11Y_DBUS_NAME "org.a11y.Bus" -#define A11Y_DBUS_PATH "/org/a11y/bus" -#define A11Y_DBUS_INTERFACE "org.a11y.Bus" -#define A11Y_DBUS_STATUS_INTERFACE "org.a11y.Status" #define ATSPI_DBUS_INTERFACE_EVENT_WINDOW "org.a11y.atspi.Event.Window" #define CACHE_ITEM_SIGNATURE "((so)(so)(so)a(so)assusau)" @@ -66,8 +62,11 @@ typedef struct Key_Event_Info { typedef struct _Elm_Atspi_Bridge_Data { - Eldbus_Connection *session_bus; + Elm_Atspi_Bus_Watcher *bus_obj; + Eina_Future *bus_address_future; + Eldbus_Connection *a11y_bus; + Eina_List *reemited_events; Eina_Hash *cache; Eldbus_Service_Interface *cache_interface; @@ -79,7 +78,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; @@ -4390,77 +4388,6 @@ _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); } -static void -_a11y_bus_address_get(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending) -{ - 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); - - if (eldbus_message_error_get(msg, &errname, &errmsg)) - { - ERR("%s %s", errname, errmsg); - return; - } - - if (!eldbus_message_arguments_get(msg, "s", &sock_addr) || !sock_addr) - { - ERR("Could not get A11Y Bus socket address."); - return; - } - - _a11y_bus_initialize((Eo*)data, sock_addr); -} - -static void _a11y_connection_init(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); -} - -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; - - pd->pending_requests = eina_list_remove(pd->pending_requests, pending); - - if (eldbus_message_error_get(msg, &errname, &errmsg)) - { - WRN("%s %s", errname, errmsg); - return; - } - if (!eldbus_message_arguments_get(msg, "v", &variant)) - { - ERR("'ScreenReaderEnabled' not packed into variant."); - 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) { ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd); @@ -4659,83 +4586,108 @@ _elm_atspi_bridge_connected_get(Eo *obj EINA_UNUSED, Elm_Atspi_Bridge_Data *pd) return pd->connected; } -static void -_properties_changed_cb(void *data, Eldbus_Proxy *proxy EINA_UNUSED, void *event) +static Eina_Value +_elm_atspi_bridge_bus_address_get_success(void *data, Eina_Value value) { - 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)) - { - 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); - } -} + Elm_Atspi_Bridge *bridge = data; + ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, EINA_VALUE_EMPTY); + const Eina_Value_Type *type; -EOLIAN Efl_Object* -_elm_atspi_bridge_efl_object_constructor(Eo *obj, Elm_Atspi_Bridge_Data *pd) -{ - Eldbus_Proxy *proxy; - Eldbus_Pending *req; + pd->bus_address_future = NULL; - efl_constructor(efl_super(obj, ELM_ATSPI_BRIDGE_CLASS)); + if (elm_obj_atspi_bridge_connected_get(bridge)) + return EINA_VALUE_EMPTY; - elm_need_eldbus(); + type = eina_value_type_get(&value); + if (type != EINA_VALUE_TYPE_STRUCT) + return value; - 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))) + const char *address = NULL; + if (eina_value_struct_get(&value, "arg0", &address)) { - ERR("Could not get /org/a11y/bus object"); - goto obj_err; + _a11y_bus_initialize(bridge, address); } - if (!(proxy = eldbus_proxy_get(pd->bus_obj, A11Y_DBUS_STATUS_INTERFACE))) + else { - ERR("Could not get proxy object for %s interface", A11Y_DBUS_STATUS_INTERFACE); - goto proxy_err; + ERR("Argument arg0 not found. Cannot initialize atspi bridge."); } - if (!(req = eldbus_proxy_property_get(proxy, "ScreenReaderEnabled", _screen_reader_enabled_get, obj))) + + return value; +} + +static Eina_Value +_elm_atspi_bridge_bus_address_get_error(void *data, const Eina_Error error EINA_UNUSED) +{ + Elm_Atspi_Bridge *bridge = data; + ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, EINA_VALUE_EMPTY); + pd->bus_address_future = NULL; + return EINA_VALUE_EMPTY; +} + +static void +_elm_atspi_bridge_a11y_bus_available(void *data, const Efl_Event *event EINA_UNUSED) +{ + Elm_Atspi_Bridge *bridge = data; + ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd); + + if (pd->bus_address_future) { - ERR("Could not send PropertyGet request"); - goto proxy_err; + eina_future_cancel(pd->bus_address_future); + pd->bus_address_future = NULL; } - 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); + Eina_Bool enabled_flag = elm_atspi_bus_watcher_property_get(event->object, + ATSPI_BUS_PROPERTY_SCREENREADERENABLED); - return obj; + if (!enabled_flag) return; -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; + pd->bus_address_future = elm_atspi_bus_watcher_a11y_bus_address_get(event->object); + eina_future_then_easy(pd->bus_address_future, _elm_atspi_bridge_bus_address_get_success, + _elm_atspi_bridge_bus_address_get_error, NULL, NULL, bridge); } -EOLIAN void -_elm_atspi_bridge_efl_object_destructor(Eo *obj, Elm_Atspi_Bridge_Data *pd) +static void +_elm_atspi_bridge_a11y_bus_unavailable(void *data, const Efl_Event *event EINA_UNUSED) { - _a11y_connection_shutdown(obj); + _a11y_connection_shutdown((Eo*)data); +} + +static void +_elm_atspi_bridge_a11y_bus_status_updated(void *data, const Efl_Event *event EINA_UNUSED) +{ + Elm_Atspi_Bridge *bridge = data; + ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd); + +} + +EOLIAN Efl_Object* +_elm_atspi_bridge_efl_object_constructor(Eo *obj, Elm_Atspi_Bridge_Data *pd) +{ + Eldbus_Connection *session_con; + obj = efl_constructor(efl_super(obj, ELM_ATSPI_BRIDGE_CLASS)); + + session_con = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SESSION); + if (!session_con) + return NULL; + + pd->bus_obj = efl_add(ELM_ATSPI_BUS_WATCHER_CLASS, obj); + elm_bus_watcher_connection_set(pd->bus_obj, session_con); - if (pd->bus_obj) eldbus_object_unref(pd->bus_obj); - if (pd->session_bus) eldbus_connection_unref(pd->session_bus); + efl_event_callback_add(pd->bus_obj, ELM_BUS_WATCHER_EVENT_REGISTERED, + _elm_atspi_bridge_a11y_bus_available, obj); + efl_event_callback_add(pd->bus_obj, ELM_BUS_WATCHER_EVENT_UNREGISTERED, + _elm_atspi_bridge_a11y_bus_unavailable, obj); + efl_event_callback_add(pd->bus_obj, ELM_ATSPI_BUS_WATCHER_EVENT_PROPERTY_CHANGED, + _elm_atspi_bridge_a11y_bus_status_updated, obj); + eldbus_connection_unref(session_con); + return obj; +} + +EOLIAN void +_elm_atspi_bridge_efl_object_destructor(Eo *obj, Elm_Atspi_Bridge_Data *pd EINA_UNUSED) +{ + _a11y_connection_shutdown(obj); efl_destructor(efl_super(obj, ELM_ATSPI_BRIDGE_CLASS)); } diff --git a/src/lib/elementary/elm_atspi_bus_watcher.c b/src/lib/elementary/elm_atspi_bus_watcher.c new file mode 100644 index 0000000000..cba6aa9896 --- /dev/null +++ b/src/lib/elementary/elm_atspi_bus_watcher.c @@ -0,0 +1,227 @@ +#ifdef HAVE_CONFIG_H +#include "elementary_config.h" +#endif + +#define ELM_BUS_WATCHER_PROTECTED +#define ELM_ATSPI_BUS_WATCHER_PROTECTED + +// dbus interface description used by at-spi2 accesibility +#define A11Y_DBUS_NAME "org.a11y.Bus" +#define A11Y_DBUS_PATH "/org/a11y/bus" +#define A11Y_DBUS_INTERFACE "org.a11y.Bus" +#define A11Y_DBUS_STATUS_INTERFACE "org.a11y.Status" +#define SCREEN_READER_ENABLED_PROPERTY_NAME "ScreenReaderEnabled" +#define IS_ENABLED_PROPERTY_NAME "IsEnabled" +#define GET_ADDRESS_METHOD_NAME "GetAddress" + +#include <Elementary.h> +#include "elm_priv.h" +#include "elm_atspi_bus_watcher.eo.h" + +typedef struct _Elm_Atspi_Bus_Watcher_Data +{ + Eldbus_Object *bus_object; + Eldbus_Proxy *status_proxy; + + // cached properties values, + Eina_Bool cached_properties[2]; +} Elm_Atspi_Bus_Watcher_Data; + +static void _cached_property_set(Eo *obj, Elm_Atspi_Bus_Watcher_Data *pd, Atspi_Bus_Property property, Eina_Bool val); + +static inline void _is_enabled_try_set(Eo *obj, Elm_Atspi_Bus_Watcher_Data *pd, Eina_Bool val); +static inline void _screen_reader_enabled_try_set(Eo *obj, Elm_Atspi_Bus_Watcher_Data *pd, Eina_Bool val); + +static Eina_Future* _eldbus_object_future_send(Eina_Future_Scheduler *scheduler, Eldbus_Object *proxy, Eldbus_Message *msg, int timeout); +static inline void _eldbus_proxy_boolean_property_set(Eldbus_Proxy *proxy, const char *property_name, Eina_Bool v); + +EOLIAN static Eo* +_elm_atspi_bus_watcher_efl_object_constructor(Eo *obj, Elm_Atspi_Bus_Watcher_Data *pd EINA_UNUSED) +{ + obj = efl_constructor(efl_super(obj, ELM_ATSPI_BUS_WATCHER_CLASS)); + elm_bus_watcher_service_add(obj, A11Y_DBUS_NAME); + return obj; +} + +EOLIAN static void +_elm_atspi_bus_watcher_efl_object_destructor(Eo *obj, Elm_Atspi_Bus_Watcher_Data *pd EINA_UNUSED) +{ + if (pd->status_proxy) eldbus_proxy_unref(pd->status_proxy); + if (pd->bus_object) eldbus_object_unref(pd->bus_object); + efl_destructor(efl_super(obj, ELM_ATSPI_BUS_WATCHER_CLASS)); +} + +// Set cached value of property. Fires property changed and enabled events when neccessary. +static void +_cached_property_set(Eo *obj, Elm_Atspi_Bus_Watcher_Data *pd, Atspi_Bus_Property property, Eina_Bool val) +{ + if (pd->cached_properties[property] == val) + return; + + pd->cached_properties[property] = val; + efl_event_callback_call(obj, ELM_ATSPI_BUS_WATCHER_EVENT_PROPERTY_CHANGED, &property); +} + +static inline void +_screen_reader_enabled_try_set(Eo *obj EINA_UNUSED, Elm_Atspi_Bus_Watcher_Data *pd, Eina_Bool val) +{ + _eldbus_proxy_boolean_property_set(pd->status_proxy, SCREEN_READER_ENABLED_PROPERTY_NAME, val); +} + +static inline void +_is_enabled_try_set(Eo *obj EINA_UNUSED, Elm_Atspi_Bus_Watcher_Data *pd, Eina_Bool val) +{ + _eldbus_proxy_boolean_property_set(pd->status_proxy, IS_ENABLED_PROPERTY_NAME, val); +} + +static Eina_Bool +_proxy_boolean_property_fetch(Eldbus_Proxy *proxy, const char *name, Eina_Bool *out_value) +{ + Eina_Value *val = eldbus_proxy_property_local_get(proxy, name); + if (!val) return EINA_FALSE; + if (eina_value_type_get(val) != EINA_VALUE_TYPE_UCHAR) return EINA_FALSE; + return eina_value_get(val, out_value); +} + +static void +_elm_atspi_bus_watcher_update_all_properties(Elm_Atspi_Bus_Watcher *watcher, Eldbus_Proxy *proxy) +{ + Elm_Atspi_Bus_Watcher_Data *pd = efl_data_scope_get(watcher, ELM_ATSPI_BUS_WATCHER_CLASS); + Eina_Bool val; + + if (_proxy_boolean_property_fetch(proxy, SCREEN_READER_ENABLED_PROPERTY_NAME, &val)) + _cached_property_set(watcher, pd, ATSPI_BUS_PROPERTY_SCREENREADERENABLED, val); + + if (_proxy_boolean_property_fetch(proxy, IS_ENABLED_PROPERTY_NAME, &val)) + _cached_property_set(watcher, pd, ATSPI_BUS_PROPERTY_ISENABLED, val); +} + +static void +_status_proxy_properties_changed_cb(void *data, Eldbus_Proxy *proxy, void *event EINA_UNUSED) +{ + Elm_Atspi_Bus_Watcher *watcher = data; + _elm_atspi_bus_watcher_update_all_properties(watcher, proxy); +} + +EOLIAN static void +_elm_atspi_bus_watcher_elm_bus_watcher_on_registered(Eo *obj, Elm_Atspi_Bus_Watcher_Data *pd, + const char *service_name) +{ + if (!service_name || strcmp(service_name, A11Y_DBUS_NAME)) + return; + + pd->bus_object = eldbus_object_get(elm_bus_watcher_connection_get(obj), + A11Y_DBUS_NAME, A11Y_DBUS_PATH); + pd->status_proxy = eldbus_proxy_get(pd->bus_object, A11Y_DBUS_STATUS_INTERFACE); + + eldbus_proxy_event_callback_add(pd->status_proxy, ELDBUS_PROXY_EVENT_PROPERTY_CHANGED, + _status_proxy_properties_changed_cb, obj); + eldbus_proxy_event_callback_add(pd->status_proxy, ELDBUS_PROXY_EVENT_PROPERTY_LOADED, + _status_proxy_properties_changed_cb, obj); + eldbus_proxy_properties_monitor(pd->status_proxy, EINA_TRUE); +} + +/* Analysis of cohesion + * + * functional + * sequential + * communicational + * procedural + * temporal + * logical + * coincidential + */ +EOLIAN static void +_elm_atspi_bus_watcher_elm_bus_watcher_on_unregistered(Eo *obj, Elm_Atspi_Bus_Watcher_Data *pd, + const char *service_name) +{ + if (!service_name || strcmp(service_name, A11Y_DBUS_NAME)) + return; + + eldbus_proxy_unref(pd->status_proxy); + eldbus_object_unref(pd->bus_object); + pd->bus_object = NULL; + pd->status_proxy = NULL; + + // reset status variables since we lost connection with org.a11y.Bus + _cached_property_set(obj, pd, ATSPI_BUS_PROPERTY_ISENABLED, EINA_FALSE); + _cached_property_set(obj, pd, ATSPI_BUS_PROPERTY_SCREENREADERENABLED, EINA_FALSE); +} + +EOLIAN static Eina_Bool +_elm_atspi_bus_watcher_property_get(Eo *obj EINA_UNUSED, + Elm_Atspi_Bus_Watcher_Data *pd, Atspi_Bus_Property property) +{ + return pd->cached_properties[property]; +} + +EOLIAN static void +_elm_atspi_bus_watcher_property_try_set(Eo *obj EINA_UNUSED, + Elm_Atspi_Bus_Watcher_Data *pd, + Atspi_Bus_Property property, Eina_Bool val) +{ + switch (property) + { + case ATSPI_BUS_PROPERTY_SCREENREADERENABLED: + _screen_reader_enabled_try_set(obj, pd, val); + break; + case ATSPI_BUS_PROPERTY_ISENABLED: + _is_enabled_try_set(obj, pd, val); + break; + default: + ERR("Invalid property value."); + break; + } +} + +static void +_dummy_cancel_cb(void *data EINA_UNUSED, const Eina_Promise *dead_ptr EINA_UNUSED) +{ +} + +static inline void +_eldbus_proxy_boolean_property_set(Eldbus_Proxy *proxy, const char *property_name, + Eina_Bool val) +{ + eldbus_proxy_property_set(proxy, property_name, "b", (void*)val, NULL, NULL); +} + +static void +_eldbus_object_call_cb(void *data, const Eldbus_Message *msg, + Eldbus_Pending *pending EINA_UNUSED) +{ + Eina_Promise *promise = data; + Eina_Value *value = eldbus_message_to_eina_value(msg); + eina_promise_resolve(promise, *value); +} + +static Eina_Future* +_eldbus_object_future_send(Eina_Future_Scheduler *scheduler, Eldbus_Object *obj, + Eldbus_Message *msg, int timeout) +{ + Eina_Promise *p = eina_promise_new(scheduler, _dummy_cancel_cb, NULL); + if (!p) goto on_err; + + if (!eldbus_object_send(obj, msg, _eldbus_object_call_cb, p, timeout)) + goto on_err; + + return eina_future_new(p); + +on_err: + eldbus_message_unref(msg); + return eina_future_rejected(scheduler, -1); +} + +EOLIAN static Eina_Future* +_elm_atspi_bus_watcher_a11y_bus_address_get(Eo *obj EINA_UNUSED, Elm_Atspi_Bus_Watcher_Data *pd) +{ + Eina_Future_Scheduler *scheduler = efl_loop_future_scheduler_get(ecore_main_loop_get()); + Eldbus_Message *msg = eldbus_object_method_call_new(pd->bus_object, + A11Y_DBUS_INTERFACE, + GET_ADDRESS_METHOD_NAME); + if (!msg) return eina_future_rejected(scheduler, -1); //TODO add recent error code + + return _eldbus_object_future_send(scheduler, pd->bus_object, msg, 100); +} + +#include "elm_atspi_bus_watcher.eo.c" diff --git a/src/lib/elementary/elm_atspi_bus_watcher.eo b/src/lib/elementary/elm_atspi_bus_watcher.eo new file mode 100644 index 0000000000..45bea126ce --- /dev/null +++ b/src/lib/elementary/elm_atspi_bus_watcher.eo @@ -0,0 +1,38 @@ +import eina_types; + +enum Atspi.Bus.Property +{ + ScreenReaderEnabled, + IsEnabled +} + +class Elm.Atspi.Bus.Watcher (Elm.Bus.Watcher) +{ + methods { + a11y_bus_address_get { + return: ptr(Eina.Future); + } + property_get { + params { + @in property: Atspi.Bus.Property; + } + return: bool; + } + property_try_set { + params { + @in property: Atspi.Bus.Property; + @in val: bool; + } + } + } + implements { + Efl.Object.constructor; + Efl.Object.destructor; + Elm.Bus.Watcher.on_registered; + + Elm.Bus.Watcher.on_unregistered; + } + events { + property,changed: Atspi.Bus.Property; [[ called when Atspi.Bus properties has been changed]] + } +} |