diff options
author | Lukasz Stanislawski <l.stanislaws@samsung.com> | 2017-12-01 23:13:02 +0100 |
---|---|---|
committer | Lukasz Stanislawski <lukasz.stanislawski@gmail.com> | 2017-12-01 23:13:02 +0100 |
commit | 2d4917a48ae7ebeb89acfbf6cdcef1900a808d6c (patch) | |
tree | 2c38a696241956312845d3035dbf21206340bdc0 | |
parent | 76c2520efd6060ad7a1a14a2243c6acef722905e (diff) | |
download | efl-2d4917a48ae7ebeb89acfbf6cdcef1900a808d6c.tar.gz |
elm: implement elm_bus_watcher class
Summary:
Purpose of this class it to create base class for
Change-Id: Id28e43ba43caa9c3290d462d807acde710fce7d6
Subscribers: cedric, jpeg
Differential Revision: https://phab.enlightenment.org/D5560
-rw-r--r-- | src/Makefile_Elementary.am | 1 | ||||
-rw-r--r-- | src/examples/elementary/Makefile.am | 9 | ||||
-rw-r--r-- | src/examples/elementary/bus_watcher.c | 52 | ||||
-rw-r--r-- | src/lib/elementary/Elementary.h | 1 | ||||
-rw-r--r-- | src/lib/elementary/a11y/elm_atspi_bus_watcher.eo | 8 | ||||
-rw-r--r-- | src/lib/elementary/a11y/elm_bus_watcher.c | 158 | ||||
-rw-r--r-- | src/lib/elementary/a11y/elm_bus_watcher.eo | 47 | ||||
-rw-r--r-- | src/lib/elementary/a11y/elm_bus_watcher.h | 8 | ||||
-rw-r--r-- | src/lib/elementary/a11y/elm_bus_watcher_private.x | 71 |
9 files changed, 342 insertions, 13 deletions
diff --git a/src/Makefile_Elementary.am b/src/Makefile_Elementary.am index 7b63a5dfb5..3c637bef70 100644 --- a/src/Makefile_Elementary.am +++ b/src/Makefile_Elementary.am @@ -728,6 +728,7 @@ lib_elementary_libelementary_la_SOURCES = \ lib/elementary/efl_ui_focus_parent_provider_gen.c \ lib/elementary/efl_ui_focus_util.c \ lib/elementary/elm_widget_item_static_focus.c \ + lib/elementary/a11y/elm_bus_watcher.c \ $(NULL) diff --git a/src/examples/elementary/Makefile.am b/src/examples/elementary/Makefile.am index c4b5944c71..79f8e42f96 100644 --- a/src/examples/elementary/Makefile.am +++ b/src/examples/elementary/Makefile.am @@ -67,7 +67,8 @@ $(top_builddir)/src/lib/embryo/libembryo.la \ $(top_builddir)/src/lib/edje/libedje.la \ $(top_builddir)/src/lib/elementary/libelementary.la \ $(top_builddir)/src/lib/ethumb_client/libethumb_client.la \ -$(top_builddir)/src/lib/elocation/libelocation.la +$(top_builddir)/src/lib/elocation/libelocation.la \ +$(top_builddir)/src/lib/eldbus/libeldbus.la SRCS = \ actionslider_example_01.c \ @@ -176,7 +177,8 @@ efl_thread_2.c \ efl_thread_3.c \ efl_thread_4.c \ efl_thread_5.c \ -efl_thread_6.c +efl_thread_6.c \ +bus_watcher.c if HAVE_CXX11 SRCS += \ @@ -364,7 +366,8 @@ efl_thread_2 \ efl_thread_3 \ efl_thread_4 \ efl_thread_5 \ -efl_thread_6 +efl_thread_6 \ +bus_watcher #benchmark3d #sphere-hunter diff --git a/src/examples/elementary/bus_watcher.c b/src/examples/elementary/bus_watcher.c new file mode 100644 index 0000000000..3897b49193 --- /dev/null +++ b/src/examples/elementary/bus_watcher.c @@ -0,0 +1,52 @@ +#define EFL_EO_API_SUPPORT +#define EFL_BETA_API_SUPPORT + +#include <Elementary.h> +#include <stdio.h> + +static void _cb(void *data EINA_UNUSED, const Efl_Event *event) +{ + Elm_Bus_Watcher_Service_Change_Info *info = event->info; + printf("Registered %s by %s\n", info->service_name, info->new_id); +} + +static void _cb2(void *data EINA_UNUSED, const Efl_Event *event EINA_UNUSED) +{ + Elm_Bus_Watcher_Service_Change_Info *info = event->info; + printf("Unregistered %s by %s\n", info->service_name, info->old_id); +} + +static void parse_args(Elm_Bus_Watcher *watcher, int argc, char **argv) +{ + int i; + if (argc < 2) + { + fprintf(stderr, "Invalid usage:\n%s <dbus-service-name>\n", argv[0]); + exit(1); + } + for (i = 1; i < argc; ++i) + { + elm_bus_watcher_service_add(watcher, argv[i]); + elm_bus_watcher_service_add(watcher, argv[i]); + } +} + +EAPI_MAIN int +elm_main(int argc EINA_UNUSED, char **argv EINA_UNUSED) +{ + Elm_Bus_Watcher *watcher = efl_add(ELM_BUS_WATCHER_CLASS, NULL); + Eldbus_Connection *conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SESSION); + + parse_args(watcher, argc, argv); + + elm_bus_watcher_connection_set(watcher, conn); + efl_event_callback_add(watcher, ELM_BUS_WATCHER_EVENT_REGISTERED, _cb, watcher); + efl_event_callback_add(watcher, ELM_BUS_WATCHER_EVENT_UNREGISTERED, _cb2, 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 64367cadc8..2bfc98ceb7 100644 --- a/src/lib/elementary/Elementary.h +++ b/src/lib/elementary/Elementary.h @@ -307,6 +307,7 @@ EAPI extern Elm_Version *elm_version; # include <efl_ui_spin.eo.h> # include <efl_ui_spin_button.eo.h> # include <efl_ui_image_factory.eo.h> +# include <a11y/elm_bus_watcher.eo.h> #endif /* include deprecated calls last of all */ diff --git a/src/lib/elementary/a11y/elm_atspi_bus_watcher.eo b/src/lib/elementary/a11y/elm_atspi_bus_watcher.eo index c38da26dea..7940be3371 100644 --- a/src/lib/elementary/a11y/elm_atspi_bus_watcher.eo +++ b/src/lib/elementary/a11y/elm_atspi_bus_watcher.eo @@ -9,19 +9,19 @@ class Elm.Atspi.Bus.Watcher (Elm.Bus.Watcher) set { } values { - conn: Eldbus.Connection; + conn: ptr(Eldbus.Connection); } } ref_a11y_bus_connection { - return: Eldbus.Connection; + return: ptr(Eldbus.Connection); } } constructors { .connection; } implements { - Elm.Bus.Watcher.OnRegistered; - Elm.Bus.Watcher.OnUnregistered; + Elm.Bus.Watcher.on_registered; + Elm.Bus.Watcher.on_unregistered; } events { enabled; diff --git a/src/lib/elementary/a11y/elm_bus_watcher.c b/src/lib/elementary/a11y/elm_bus_watcher.c new file mode 100644 index 0000000000..ae950aacee --- /dev/null +++ b/src/lib/elementary/a11y/elm_bus_watcher.c @@ -0,0 +1,158 @@ +#ifdef HAVE_CONFIG_H + #include "elementary_config.h" +#endif + +#define ELM_BUS_WATCHER_PROTECTED + +#include <Elementary.h> +#include "elm_widget.h" +#include "elm_priv.h" + +#include "elm_bus_watcher.eo.h" +#include "elm_bus_watcher_private.x" + +static Eina_Bool _bus_watcher_service_unregister_callback(const void *container, void *data, void *gdata); +static Eina_Bool _bus_watcher_service_register_callback(const void *container, void *data, void *gdata); + +typedef struct _Elm_Bus_Watcher_Data +{ + Eina_Array *service_names; + Eldbus_Connection *connection; +} Elm_Bus_Watcher_Data; + +EOLIAN static Eo* +_elm_bus_watcher_efl_object_constructor(Eo *obj, Elm_Bus_Watcher_Data *pd) +{ + obj = efl_constructor(efl_super(obj, ELM_BUS_WATCHER_CLASS)); + pd->service_names = eina_array_new(2); // make step small since in most cases watchers will have 1-2 names. + return obj; +} + +EOLIAN static void +_elm_bus_watcher_efl_object_destructor(Eo *obj, Elm_Bus_Watcher_Data *pd) +{ + elm_bus_watcher_connection_set(obj, NULL); + _eina_array_strings_clear(pd->service_names); + eina_array_free(pd->service_names); + + efl_destructor(efl_super(obj, ELM_BUS_WATCHER_CLASS)); +} + +static void +_elm_atspi_bus_watcher_name_owner_changed_callback(void *data, const char *bus, const char *old_id, const char *new_id) +{ + Elm_Bus_Watcher *watcher = data; + Elm_Bus_Watcher_Data *pd = efl_data_scope_get(watcher, ELM_BUS_WATCHER_CLASS); + Elm_Bus_Watcher_Service_Change_Info info = { .service_name = bus, .old_id = old_id, .new_id = new_id }; + + if (!_eina_array_string_contains(pd->service_names, bus)) return; + + /** + Dbus deamon in case when service gets unregisted sends NameChanged signal with "newid" + parameter set to empty string "". + */ + if (!new_id || !strcmp(new_id, "")) + { + elm_bus_watcher_on_unregistered(watcher, bus, old_id); + efl_event_callback_call(watcher, ELM_BUS_WATCHER_EVENT_UNREGISTERED, &info); + } + else if (new_id) + { + elm_bus_watcher_on_registered(watcher, bus, old_id, new_id); + efl_event_callback_call(watcher, ELM_BUS_WATCHER_EVENT_REGISTERED, &info); + } +} + +static void +_elm_bus_watcher_dbus_setup(Eo *obj, Eldbus_Connection *conn, const char *service_name) +{ + eldbus_name_owner_changed_callback_add(conn, service_name, _elm_atspi_bus_watcher_name_owner_changed_callback, obj, EINA_TRUE); +} + +static void +_elm_bus_watcher_dbus_teardown(Eo *obj, Eldbus_Connection *conn, const char *service_name) +{ + eldbus_name_owner_changed_callback_del(conn, service_name, _elm_atspi_bus_watcher_name_owner_changed_callback, obj); +} + +EOLIAN static void +_elm_bus_watcher_service_add(Eo *obj, Elm_Bus_Watcher_Data *pd, const char *service) +{ + if (!service || _eina_array_string_contains(pd->service_names, service)) + return; + + _eina_array_string_push(pd->service_names, service); + if (pd->connection) _elm_bus_watcher_dbus_setup(obj, pd->connection, service); +} + +EOLIAN static void +_elm_bus_watcher_service_remove(Eo *obj EINA_UNUSED, Elm_Bus_Watcher_Data *pd, const char *service) +{ + if (!_eina_array_string_contains(pd->service_names, service)) + return; + + _eina_array_string_remove(pd->service_names, service); + if (pd->connection) _elm_bus_watcher_dbus_teardown(obj, pd->connection, service); +} + +static Eina_Bool +_bus_watcher_service_register_callback(const void *container EINA_UNUSED, void *data, void *gdata) +{ + Elm_Bus_Watcher *watcher = gdata; + Elm_Bus_Watcher_Data *pd = efl_data_scope_get(watcher, ELM_BUS_WATCHER_CLASS); + const char *service_name = data; + + _elm_bus_watcher_dbus_setup(watcher, pd->connection, service_name); + return EINA_TRUE; +} + +static Eina_Bool +_bus_watcher_service_unregister_callback(const void *container EINA_UNUSED, void *data, void *gdata) +{ + Elm_Bus_Watcher *watcher = gdata; + Elm_Bus_Watcher_Data *pd = efl_data_scope_get(watcher, ELM_BUS_WATCHER_CLASS); + const char *service_name = data; + + _elm_bus_watcher_dbus_teardown(watcher, pd->connection, service_name); + return EINA_TRUE; +} + +EOLIAN static void +_elm_bus_watcher_connection_set(Eo *obj, Elm_Bus_Watcher_Data *pd, Eldbus_Connection *conn) +{ + if (pd->connection) + { + eina_array_foreach(pd->service_names, _bus_watcher_service_unregister_callback, obj); + eldbus_connection_unref(pd->connection); + pd->connection = NULL; + } + if (conn) + { + pd->connection = eldbus_connection_ref(conn); + eina_array_foreach(pd->service_names, _bus_watcher_service_register_callback, obj); + } +} + +EOLIAN static Eldbus_Connection* +_elm_bus_watcher_connection_get(Eo *obj EINA_UNUSED, Elm_Bus_Watcher_Data *pd) +{ + return pd->connection; +} + +EOLIAN static Eina_Iterator* +_elm_bus_watcher_services_get(Eo *obj EINA_UNUSED, Elm_Bus_Watcher_Data *pd) +{ + return eina_array_iterator_new(pd->service_names); +} + +EOLIAN static void +_elm_bus_watcher_on_registered(Eo *obj EINA_UNUSED, Elm_Bus_Watcher_Data *pd EINA_UNUSED, const char *service EINA_UNUSED, const char *oldid EINA_UNUSED, const char *newid EINA_UNUSED) +{ +} + +EOLIAN static void +_elm_bus_watcher_on_unregistered(Eo *obj EINA_UNUSED, Elm_Bus_Watcher_Data *pd EINA_UNUSED, const char *service EINA_UNUSED, const char *oldid EINA_UNUSED) +{ +} + +#include "elm_bus_watcher.eo.c"
\ No newline at end of file diff --git a/src/lib/elementary/a11y/elm_bus_watcher.eo b/src/lib/elementary/a11y/elm_bus_watcher.eo index 0b6fd8728c..1ca104edf4 100644 --- a/src/lib/elementary/a11y/elm_bus_watcher.eo +++ b/src/lib/elementary/a11y/elm_bus_watcher.eo @@ -1,27 +1,62 @@ import eldbus_types; +struct Elm.Bus.Watcher.Service.Change.Info +{ + service_name: string; + old_id: string; + new_id: string; +} + class Elm.Bus.Watcher (Efl.Object) { methods { - @property service { - values { - bus: string; + service_add { + params { + @in bus: string; + } + } + service_remove { + params { + @in bus: string; } } + @property services { + get { + } + values { + services: iterator<string>; + } + } @property connection { get { } set { } values { - conn: Eldbus.Connection; + conn: ptr(Eldbus.Connection); } } - OnRegistered @protected { + on_registered @protected { + params { + @in bus_name: string; + @in old_id: string; + @in new_id: string; + } } - OnUnregistered @protected { + on_unregistered @protected { + params { + @in bus_name: string; + @in old_id: string; + } } } + implements { + Efl.Object.constructor; + Efl.Object.destructor; + } + constructors { + .connection; + } events { registered; unregistered; diff --git a/src/lib/elementary/a11y/elm_bus_watcher.h b/src/lib/elementary/a11y/elm_bus_watcher.h new file mode 100644 index 0000000000..329543cfb2 --- /dev/null +++ b/src/lib/elementary/a11y/elm_bus_watcher.h @@ -0,0 +1,8 @@ +#ifndef ELM_BUS_WATCHER_H +#define ELM_BUS_WATCHER_H + +#ifdef EFL_EO_API_SUPPORT +#include "elm_bus_watcher.eo.h" +#endif + +#endif diff --git a/src/lib/elementary/a11y/elm_bus_watcher_private.x b/src/lib/elementary/a11y/elm_bus_watcher_private.x new file mode 100644 index 0000000000..a3f297e805 --- /dev/null +++ b/src/lib/elementary/a11y/elm_bus_watcher_private.x @@ -0,0 +1,71 @@ +#include <Eina.h> + +/** + @brief Helpers for manipulating eina_array of stringshared strings. +*/ + +typedef struct _Eina_Array_Foreach_Closure_Data +{ + const char *searched_string; + Eina_Bool *return_value; +} Eina_Array_Foreach_Closure_Data; + +static void +_eina_array_string_push(Eina_Array *array, const char *string) +{ + EINA_SAFETY_ON_NULL_RETURN(string); + eina_array_push(array, eina_stringshare_add(string)); +} + +static Eina_Bool +_eina_stringshare_foreach(const void *container EINA_UNUSED, void *data, void *gdata) +{ + Eina_Array_Foreach_Closure_Data *closure = gdata; + const char *str = data; + + if (str && closure->searched_string && !strcmp(str, closure->searched_string)) + *closure->return_value = EINA_TRUE; + + return EINA_TRUE; +} + +static Eina_Bool +_eina_array_string_contains(Eina_Array *array, const char *string) +{ + Eina_Bool found = EINA_FALSE; + Eina_Array_Foreach_Closure_Data closure = { .searched_string = string, .return_value = &found }; + return eina_array_foreach(array, _eina_stringshare_foreach, &closure) && found; +} + +static Eina_Bool +_eina_stringshare_remove(void *data, void *gdata) +{ + const char *string = data; + const char *string_to_remove = gdata; + + if (string && string_to_remove && !strcmp(string, string_to_remove)) + return EINA_FALSE; + + return EINA_TRUE; +} + +static Eina_Bool +_eina_array_string_remove(Eina_Array *array, const char *string) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(string, EINA_FALSE); + return eina_array_remove(array, _eina_stringshare_remove, (void*)string); +} + +static Eina_Bool +_eina_stringshare_del_stringshare(const void *container EINA_UNUSED, void *data, void *gdata EINA_UNUSED) +{ + const char *string = data; + eina_stringshare_del(string); + return EINA_TRUE; +} + +static void +_eina_array_strings_clear(Eina_Array *array) +{ + eina_array_foreach(array, _eina_stringshare_del_stringshare, NULL); +}
\ No newline at end of file |