Add elm_app_service/client class
authorJosé Roberto de Souza <jose.souza@intel.com>
Fri, 16 Aug 2013 21:18:07 +0000 (18:18 -0300)
committerJosé Roberto de Souza <jose.souza@intel.com>
Thu, 19 Sep 2013 18:48:25 +0000 (15:48 -0300)
These classes are the implementation of Enlightenment Application spec,
proposed by k-s.
https://phab.enlightenment.org/w/enlightenmentappspecproposal/

To test play with Message, Phone and Task switcher in elementary_test.

22 files changed:
src/bin/Makefile.am
src/bin/test.c
src/bin/test_application_server.c [new file with mode: 0644]
src/bin/test_task_switcher.c [new file with mode: 0644]
src/lib/Elementary.h.in
src/lib/Makefile.am
src/lib/elm_app_client.c [new file with mode: 0644]
src/lib/elm_app_client.h [new file with mode: 0644]
src/lib/elm_app_client_eo.h [new file with mode: 0644]
src/lib/elm_app_client_view.c [new file with mode: 0644]
src/lib/elm_app_client_view.h [new file with mode: 0644]
src/lib/elm_app_client_view_eo.h [new file with mode: 0644]
src/lib/elm_app_common.c [new file with mode: 0644]
src/lib/elm_app_common.h [new file with mode: 0644]
src/lib/elm_app_server.c [new file with mode: 0644]
src/lib/elm_app_server.h [new file with mode: 0644]
src/lib/elm_app_server_eet.c [new file with mode: 0644]
src/lib/elm_app_server_eet.h [new file with mode: 0644]
src/lib/elm_app_server_eo.h [new file with mode: 0644]
src/lib/elm_app_server_view.c [new file with mode: 0644]
src/lib/elm_app_server_view.h [new file with mode: 0644]
src/lib/elm_app_server_view_eo.h [new file with mode: 0644]

index 9677a50..9069050 100644 (file)
@@ -48,6 +48,7 @@ test_3d.c \
 test_access.c \
 test_actionslider.c \
 test_anim.c \
+test_application_server.c \
 test_bg.c \
 test_box.c \
 test_bubble.c \
@@ -126,6 +127,7 @@ test_spinner.c \
 test_store.c \
 test_sys_notify.c \
 test_systray.c \
+test_task_switcher.c \
 test_table.c \
 test_thumb.c \
 test_toolbar.c \
@@ -267,4 +269,4 @@ elementary_testql_LDFLAGS =
 endif
 
 EXTRA_DIST = \
-test_factory.c
+test_factory.c
\ No newline at end of file
index 2e69866..ad63798 100644 (file)
@@ -226,6 +226,9 @@ void test_web_mobile(void *data, Evas_Object *obj, void *event_info);
 void test_dnd_genlist_default_anim(void *data, Evas_Object *obj, void *event_info);
 void test_dnd_genlist_user_anim(void *data, Evas_Object *obj, void *event_info);
 void test_dnd_genlist_gengrid(void *data, Evas_Object *obj, void *event_info);
+void test_task_switcher(void *data, Evas_Object *obj, void *event_info);
+void test_application_server_message(void *data, Evas_Object *obj, void *event_info);
+void test_application_server_phone(void *data, Evas_Object *obj, void *event_info);
 
 Evas_Object *win, *tbx; // TODO: refactoring
 void *tt;
@@ -795,6 +798,11 @@ add_tests:
    ADD_TEST(NULL, "Miscellaneous", "Accessibility2", test_access2);
    ADD_TEST(NULL, "Miscellaneous", "Accessibility3", test_access3);
 
+   //------------------------------//
+   ADD_TEST(NULL, "Application client/server", "Task switcher", test_task_switcher);
+   ADD_TEST(NULL, "Application client/server", "Phone", test_application_server_phone);
+   ADD_TEST(NULL, "Application client/server", "Message", test_application_server_message);
+
 #undef ADD_TEST
 
    if (autorun)
diff --git a/src/bin/test_application_server.c b/src/bin/test_application_server.c
new file mode 100644 (file)
index 0000000..dbb34a5
--- /dev/null
@@ -0,0 +1,211 @@
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#include <Elementary.h>
+#ifndef ELM_LIB_QUICKLAUNCH
+
+typedef struct {
+   Evas_Object *win, *label;
+   Eina_Stringshare *view_name;
+} App_View_Context;
+
+static Elm_App_Server *phone_server = NULL, *msg_server = NULL;
+
+static void _text_update(App_View_Context *ctx, const char *state)
+{
+   char buffer[1024];
+
+   if (!ctx->label)
+     return;
+   snprintf(buffer, sizeof(buffer), "%s - state=%s", ctx->view_name, state);
+   elm_object_text_set(ctx->label, buffer);
+}
+
+static void
+_window_create(App_View_Context *ctx)
+{
+   ctx->win = elm_win_util_standard_add("app_view", ctx->view_name);
+
+   ctx->label = elm_label_add(ctx->win);
+   evas_object_size_hint_weight_set(ctx->label, EVAS_HINT_EXPAND,
+                                    EVAS_HINT_EXPAND);
+   evas_object_data_set(ctx->win, "label", ctx->label);
+
+   _text_update(ctx, "alive");
+
+   elm_win_resize_object_add(ctx->win, ctx->label);
+   evas_object_show(ctx->label);
+
+   evas_object_resize(ctx->win, 400, 300);
+   evas_object_show(ctx->win);
+}
+
+static Eina_Bool
+_close_cb(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   App_View_Context *ctx = data;
+   if (ctx->win)
+     evas_object_del(ctx->win);
+   eo_del(obj);
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_pause_cb(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   App_View_Context *ctx = data;
+   _text_update(ctx, "paused");
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_resume_cb(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   App_View_Context *ctx = data;
+
+   //shallow state
+   if (!ctx->win)
+     {
+        _window_create(ctx);
+        eo_do(obj, elm_app_server_view_window_set(ctx->win));
+     }
+
+   _text_update(ctx, "alive");
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_view_del_cb(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   App_View_Context *ctx = data;
+
+   if (ctx->win)
+     evas_object_del(ctx->win);
+   eo_do(obj, elm_app_server_view_window_set(NULL));
+   eina_stringshare_del(ctx->view_name);
+   free(ctx);
+   return EINA_TRUE;
+}
+
+static Elm_App_Server_View *
+_create_view_cb(Elm_App_Server *app_server, const Eina_Value *args EINA_UNUSED, Eina_Stringshare **error_name, Eina_Stringshare **error_message EINA_UNUSED)
+{
+   Elm_App_Server_View *view;
+   const char *id, *pkg;
+   App_View_Context *ctx;
+
+   ctx = calloc(1, sizeof(App_View_Context));
+   if (!ctx)
+     {
+        *error_name = eina_stringshare_add("No memory available");
+        return NULL;
+     }
+
+   view = eo_add_custom(ELM_APP_SERVER_VIEW_CLASS, app_server,
+                        elm_app_server_view_constructor(NULL));
+
+   eo_do(view, elm_app_server_view_id_get(&id));
+   eo_do(app_server, elm_app_server_package_get(&pkg));
+   ctx->view_name = eina_stringshare_printf("%s %s", pkg, id);
+
+   _window_create(ctx);
+
+   eo_do(view, elm_app_server_view_title_set(ctx->view_name),
+         elm_app_server_view_new_events_set(5),
+         elm_app_server_view_window_set(ctx->win),
+         elm_app_server_view_resume(),
+         eo_event_callback_add(ELM_APP_SERVER_VIEW_EV_CLOSED, _close_cb, ctx),
+         eo_event_callback_add(ELM_APP_SERVER_VIEW_EV_PAUSED, _pause_cb, ctx),
+         eo_event_callback_add(ELM_APP_SERVER_VIEW_EV_RESUMED, _resume_cb, ctx),
+         eo_event_callback_add(EO_EV_DEL, _view_del_cb, ctx));
+
+   return view;
+}
+
+static Eina_Bool
+_terminate_cb(void *data EINA_UNUSED, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   const char *title;
+
+   printf("terminate cb\n");
+   eo_do(obj, elm_app_server_save(),
+        elm_app_server_title_get(&title));
+
+   printf("Closing: %s\n", title);
+   eo_unref(obj);
+   return EINA_TRUE;
+}
+
+Elm_App_Server *
+test_application_server_common(const char *pkg)
+{
+   Eina_Iterator *views_iter;
+   Elm_App_Server_View *view;
+   Elm_App_Server *server;
+
+   server = eo_add_custom(ELM_APP_SERVER_CLASS, NULL,
+                          elm_app_server_constructor(pkg, _create_view_cb));
+   eo_do(server, elm_app_server_title_set(pkg),
+         elm_app_server_views_get(&views_iter),
+         eo_event_callback_add(ELM_APP_SERVER_EV_TERMINATE, _terminate_cb, NULL));
+
+   //views create in shallow state
+   EINA_ITERATOR_FOREACH(views_iter, view)
+     {
+        App_View_Context *ctx;
+        const char *id;
+
+        ctx = calloc(1, sizeof(App_View_Context));
+
+        eo_do(view, elm_app_server_view_id_get(&id));
+        ctx->view_name = eina_stringshare_printf("%s %s", pkg, id);
+
+        eo_do(view,
+              eo_event_callback_add(ELM_APP_SERVER_VIEW_EV_CLOSED, _close_cb, ctx),
+              eo_event_callback_add(ELM_APP_SERVER_VIEW_EV_PAUSED, _pause_cb, ctx),
+              eo_event_callback_add(ELM_APP_SERVER_VIEW_EV_RESUMED, _resume_cb, ctx),
+              eo_event_callback_add(EO_EV_DEL, _view_del_cb, ctx));
+     }
+   eina_iterator_free(views_iter);
+
+   return server;
+}
+
+static Eina_Bool
+_server_del_cb(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   Elm_App_Server **server = data;
+   *server = NULL;
+   return EINA_TRUE;
+}
+
+void
+test_application_server_phone(void *data EINA_UNUSED,
+                              Evas_Object *obj EINA_UNUSED,
+                              void *event_info EINA_UNUSED)
+{
+   if (phone_server)
+     {
+        printf("Phone already running\n");
+        return;
+     }
+   printf("Starting phone\n");
+   phone_server = test_application_server_common("org.enlightenment.phone");
+   eo_do(phone_server, eo_event_callback_add(EO_EV_DEL, _server_del_cb, &phone_server));
+}
+
+void
+test_application_server_message(void *data EINA_UNUSED,
+                                Evas_Object *obj EINA_UNUSED,
+                                void *event_info EINA_UNUSED)
+{
+   if (msg_server)
+     {
+        printf("Message already running\n");
+        return;
+     }
+   printf("Starting message\n");
+   msg_server = test_application_server_common( "org.enlightenment.message");
+   eo_do(msg_server, eo_event_callback_add(EO_EV_DEL, _server_del_cb, &msg_server));
+}
+#endif
diff --git a/src/bin/test_task_switcher.c b/src/bin/test_task_switcher.c
new file mode 100644 (file)
index 0000000..7cb9084
--- /dev/null
@@ -0,0 +1,408 @@
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#include <Elementary.h>
+#include <Eina.h>
+#ifndef ELM_LIB_QUICKLAUNCH
+
+#define APPS_COL 0
+#define VIEWS_COL 1
+#define PROPS_VIEW_COL 2
+
+static Evas_Object *table = NULL;
+static Elm_App_Client *app_selected = NULL;
+static Eina_List *apps_list = NULL;
+
+static void _app_view_clicked(void *data, Evas_Object *obj, void *event_info);
+static void _apps_list_update(void);
+
+static void _btn_close_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   Elm_App_Client_View *view = data;
+   eo_do(view, elm_app_client_view_close(NULL, NULL));
+}
+
+static void _btn_pause_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   Elm_App_Client_View *view = data;
+   eo_do(view, elm_app_client_view_pause(NULL, NULL));
+}
+
+static void _btn_resume_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   Elm_App_Client_View *view = data;
+   eo_do(view, elm_app_client_view_resume(NULL, NULL));
+}
+
+static Eina_Bool
+_app_view_prop_changed_cb(void *data EINA_UNUSED, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   Elm_App_View_State state;
+
+   eo_do(obj, elm_app_client_view_state_get(&state));
+
+   if (state == ELM_APP_VIEW_STATE_CLOSED)
+     {
+        Evas_Object *props = elm_table_child_get(table, PROPS_VIEW_COL, 0);
+        elm_table_unpack(table, props);
+        evas_object_del(props);
+     }
+   else
+     _app_view_clicked(obj, NULL, NULL);
+
+   return EINA_TRUE;
+}
+
+static void
+_app_view_clicked(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   Elm_App_Client_View *view = data;
+   Evas_Object *view_props, *close_btn, *resume_btn, *pause_btn;
+   const char *title, *icon;
+   int new_events, window;
+   unsigned short progress;
+   Elm_App_View_State state;
+   char buffer[1024];
+
+   view_props = elm_table_child_get(table, PROPS_VIEW_COL, 0);
+   if (view_props)
+     {
+        Elm_App_Client_View *old_view;
+
+        old_view = evas_object_data_del(view_props, "view");
+        eo_do(old_view,
+              eo_event_callback_del(ELM_APP_CLIENT_VIEW_EV_PROPERTY_CHANGED,
+                                    _app_view_prop_changed_cb, table));
+        elm_list_clear(view_props);
+     }
+   else
+     {
+        view_props = elm_list_add(table);
+        evas_object_size_hint_align_set(view_props, EVAS_HINT_FILL,
+                                        EVAS_HINT_FILL);
+        evas_object_show(view_props);
+        elm_table_pack(table, view_props, PROPS_VIEW_COL, 0, 1, 1);
+     }
+
+   evas_object_data_set(view_props, "view", view);
+
+   eo_do(view, elm_app_client_view_title_get(&title),
+         elm_app_client_view_icon_get(&icon),
+         elm_app_client_view_progress_get(&progress),
+         elm_app_client_view_new_events_get(&new_events),
+         elm_app_client_view_window_get(&window),
+         eo_event_callback_add(ELM_APP_CLIENT_VIEW_EV_PROPERTY_CHANGED,
+                               _app_view_prop_changed_cb, table));
+
+   snprintf(buffer, sizeof(buffer), "Title=%s", title);
+   elm_list_item_append(view_props, buffer, NULL, NULL, NULL, NULL);
+
+   snprintf(buffer, sizeof(buffer), "Icon=%s", icon);
+   elm_list_item_append(view_props, buffer, NULL, NULL, NULL, NULL);
+
+   snprintf(buffer, sizeof(buffer), "Progress=%d", progress);
+   elm_list_item_append(view_props, buffer, NULL, NULL, NULL, NULL);
+
+   snprintf(buffer, sizeof(buffer), "New events=%d", new_events);
+   elm_list_item_append(view_props, buffer, NULL, NULL, NULL, NULL);
+
+   snprintf(buffer, sizeof(buffer), "WindowID=%d", window);
+   elm_list_item_append(view_props, buffer, NULL, NULL, NULL, NULL);
+
+   eo_do(view, elm_app_client_view_state_get(&state));
+   if (state == ELM_APP_VIEW_STATE_LIVE)
+     snprintf(buffer, sizeof(buffer), "State=alive");
+   else if (state == ELM_APP_VIEW_STATE_PAUSED)
+     snprintf(buffer, sizeof(buffer), "State=paused");
+   else if (state == ELM_APP_VIEW_STATE_CLOSED)
+     snprintf(buffer, sizeof(buffer), "State=closed");
+   else if (state == ELM_APP_VIEW_STATE_SHALLOW)
+     snprintf(buffer, sizeof(buffer), "State=shallow");
+   else
+     snprintf(buffer, sizeof(buffer), "State=unknown");
+   elm_list_item_append(view_props, buffer, NULL, NULL, NULL, NULL);
+
+   close_btn = elm_button_add(view_props);
+   elm_object_text_set(close_btn, "Close view");
+   evas_object_smart_callback_add(close_btn, "clicked", _btn_close_cb, view);
+   elm_list_item_append(view_props, NULL, close_btn, NULL, NULL, NULL);
+
+   pause_btn = elm_button_add(view_props);
+   elm_object_text_set(pause_btn, "Pause view");
+   evas_object_smart_callback_add(pause_btn, "clicked", _btn_pause_cb, view);
+   elm_list_item_append(view_props, NULL, pause_btn, NULL, NULL, NULL );
+
+   resume_btn = elm_button_add(view_props);
+   elm_object_text_set(resume_btn, "Resume view");
+   evas_object_smart_callback_add(resume_btn, "clicked", _btn_resume_cb, view);
+   elm_list_item_append(view_props, NULL, resume_btn, NULL, NULL, NULL );
+
+   elm_list_go(view_props);
+}
+
+static void
+_popup_close_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   evas_object_del(data);
+}
+
+static void app_client_view_open_cb(void *data EINA_UNUSED, Elm_App_Client_View *view, const char *error, const char *error_message)
+{
+   Evas_Object *popup, *btn_ok;
+   char buf[1024];
+
+   popup = elm_popup_add(table);
+
+   if (view)
+     {
+        _app_view_clicked(view, NULL, NULL);
+        return;
+     }
+
+   snprintf(buf, sizeof(buf), "Some error happen opening view: %s %s", error, error_message);
+   elm_object_part_text_set(popup, "default", buf);
+
+   btn_ok = elm_button_add(popup);
+   elm_object_text_set(btn_ok, "Ok");
+   elm_object_part_content_set(popup, "button1", btn_ok);
+   evas_object_smart_callback_add(btn_ok, "clicked", _popup_close_cb, popup);
+
+   elm_popup_orient_set(popup, ELM_POPUP_ORIENT_TOP);
+   evas_object_show(popup);
+}
+
+static void _popup_btn_open_view_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   Evas_Object *popup = data;
+   Eina_Value *args = NULL;//TODO fill with args of popup
+   Elm_App_Client *app = evas_object_data_get(popup, "app");
+
+   eo_do(app, elm_app_client_view_open(args, app_client_view_open_cb, NULL, NULL));
+
+   evas_object_del(popup);
+}
+
+static void
+_app_view_open(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   Elm_App_Client *app = data;
+   Evas_Object *popup, *btn_open, *btn_cancel, *args_box;
+
+   popup = elm_popup_add(table);
+   elm_object_part_text_set(popup, "title,text", "Open a view");
+
+   btn_open = elm_button_add(popup);
+   elm_object_text_set(btn_open, "Open");
+   elm_object_part_content_set(popup, "button1", btn_open);
+   evas_object_smart_callback_add(btn_open, "clicked", _popup_btn_open_view_cb, popup);
+   evas_object_show(btn_open);
+
+   btn_cancel = elm_button_add(popup);
+   elm_object_text_set(btn_cancel, "Cancel");
+   elm_object_part_content_set(popup, "button2", btn_cancel);
+   evas_object_smart_callback_add(btn_cancel, "clicked", _popup_close_cb, popup);
+   evas_object_show(btn_cancel);
+
+   args_box = elm_box_add(popup);
+   elm_object_part_content_set(popup, "default", args_box);
+   elm_object_part_text_set(popup, "default", "TODO: add some entrys to add some parameters to view.");
+
+   evas_object_data_set(popup, "app", app);
+   elm_popup_orient_set(popup, ELM_POPUP_ORIENT_TOP);
+   evas_object_show(popup);
+}
+
+static void _app_close_all_views_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   Elm_App_Client *app = data;
+   eo_do(app, elm_app_client_view_all_close());
+}
+
+static void
+_app_terminate_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   Elm_App_Client *app = data;
+   eo_do(app, elm_app_client_terminate());
+}
+
+static void
+_app_clicked(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   Evas_Object *views, *btn_close_all, *btn_terminate, *btn_open_view;
+   Eina_Iterator *views_iter;
+   Elm_App_Client_View *client_view;
+   Elm_App_Client *app = data;
+
+   app_selected = app;
+
+   views = elm_table_child_get(table, VIEWS_COL, 0);
+   if (!views)
+     {
+        views = elm_list_add(table);
+        evas_object_size_hint_align_set(views, EVAS_HINT_FILL, EVAS_HINT_FILL);
+        evas_object_show(views);
+        elm_table_pack(table, views, VIEWS_COL, 0, 1, 1);
+     }
+   else
+     elm_list_clear(views);
+
+   btn_open_view = elm_button_add(views);
+   elm_object_text_set(btn_open_view, "Open a view");
+   evas_object_smart_callback_add(btn_open_view, "clicked", _app_view_open, app);
+   elm_list_item_append(views, NULL, btn_open_view, NULL, NULL, NULL);
+
+   eo_do(app, elm_app_client_views_get(&views_iter));
+   EINA_ITERATOR_FOREACH(views_iter, client_view)
+     {
+        const char *path;
+
+        eo_do(client_view, elm_app_client_view_path_get(&path));
+        elm_list_item_append(views, path, NULL, NULL, _app_view_clicked, client_view);
+     }
+   eina_iterator_free(views_iter);
+
+   btn_close_all = elm_button_add(views);
+   elm_object_text_set(btn_close_all, "Close all views");
+   evas_object_smart_callback_add(btn_close_all, "clicked", _app_close_all_views_cb, app);
+   elm_list_item_append(views, NULL, btn_close_all, NULL, NULL, NULL);
+
+   btn_terminate = elm_button_add(views);
+   elm_object_text_set(btn_terminate, "Terminate application");
+   evas_object_smart_callback_add(btn_terminate, "clicked", _app_terminate_cb, app);
+   elm_list_item_append(views, NULL, btn_terminate, NULL, NULL, NULL);
+
+   elm_list_go(views);
+}
+
+static Eina_Bool
+_view_list_update_cb(void *data EINA_UNUSED, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   if (app_selected == obj)
+     _app_clicked(obj, NULL, NULL);
+   return EINA_TRUE;
+}
+
+static void
+_win_del(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
+{
+   Elm_App_Client *app;
+   EINA_LIST_FREE(apps_list, app)
+     eo_unref(app);
+}
+
+static void
+_app_open(const char *package)
+{
+   Elm_App_Client *app;
+   Eina_List *l;
+
+   EINA_LIST_FOREACH(apps_list, l, app)
+     {
+        const char *app_package;
+
+        eo_do(app, elm_app_client_package_get(&app_package));
+        if (!strcmp(package, app_package))
+          return;
+     }
+
+   app = eo_add_custom(ELM_APP_CLIENT_CLASS, NULL,
+                       elm_app_client_constructor(package));
+   eo_do(app,
+         eo_event_callback_add(ELM_APP_CLIENT_EV_VIEW_LIST_LOADED,
+                               _view_list_update_cb, table),
+         eo_event_callback_add(ELM_APP_CLIENT_EV_VIEW_CREATED,
+                               _view_list_update_cb, table),
+         eo_event_callback_add(ELM_APP_CLIENT_EV_VIEW_DELETED,
+                               _view_list_update_cb, table));
+   apps_list = eina_list_append(apps_list, app);
+}
+
+static void
+_btn_app_open_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   Evas_Object *entry = data;
+   const char *pkg = elm_object_text_get(entry);
+
+   if (!pkg || !pkg[0])
+     return;
+
+   _app_open(pkg);
+   _apps_list_update();
+}
+
+static void
+_open_custom_app_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
+{
+   elm_list_item_selected_set(event_info, EINA_FALSE);
+   elm_object_focus_set(data, EINA_TRUE);
+}
+
+static void
+_apps_list_update(void)
+{
+   Evas_Object *entry, *btn_open, *apps;
+   Elm_App_Client *app;
+   Eina_List *l;
+
+   apps = elm_table_child_get(table, APPS_COL, 0);
+   elm_list_clear(apps);
+
+   EINA_LIST_FOREACH(apps_list, l, app)
+     {
+        const char *app_package;
+        eo_do(app, elm_app_client_package_get(&app_package));
+        elm_list_item_append(apps, app_package, NULL, NULL, _app_clicked, app);
+     }
+
+   entry = elm_entry_add(apps);
+   elm_entry_single_line_set(entry, EINA_TRUE);
+   evas_object_size_hint_weight_set(entry, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(entry, EVAS_HINT_FILL, 0.5);
+
+   btn_open = elm_button_add(apps);
+   elm_object_text_set(btn_open, "Open");
+   evas_object_smart_callback_add(btn_open, "clicked", _btn_app_open_cb, entry);
+   elm_list_item_append(apps, NULL, entry, btn_open, _open_custom_app_cb, entry);
+
+   elm_list_go(apps);
+}
+
+void
+test_task_switcher(void *data EINA_UNUSED,
+             Evas_Object *obj EINA_UNUSED,
+             void *event_info EINA_UNUSED)
+{
+   Evas_Object *win, *apps;
+
+   if (apps_list)
+     {
+        printf("Task switcher already open.\n");
+        return;
+     }
+
+   win = elm_win_util_standard_add("task switcher", "Task switcher");
+   elm_win_autodel_set(win, EINA_TRUE);
+
+   evas_object_smart_callback_add(win, "delete,request", _win_del, NULL);
+
+   table = elm_table_add(win);
+   elm_win_resize_object_add(win, table);
+   elm_table_padding_set(table, 0, 0);
+   elm_table_homogeneous_set(table, EINA_TRUE);
+   evas_object_size_hint_weight_set(table, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(table, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   _app_open("org.enlightenment.message");
+   _app_open("org.enlightenment.phone");
+
+   apps = elm_list_add(table);
+   evas_object_size_hint_align_set(apps, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_show(apps);
+   elm_table_pack(table, apps, APPS_COL, 0, 1, 1);
+   _apps_list_update();
+
+   evas_object_show(table);
+   evas_object_show(win);
+   evas_object_resize(win, 1024, 768);
+}
+#endif
index e4ed289..fc562c4 100644 (file)
@@ -183,6 +183,11 @@ EAPI extern Elm_Version *elm_version;
 #include <elc_naviframe.h>
 #include <elc_popup.h>
 #include <elm_actionslider.h>
+#include <elm_app_common.h>
+#include <elm_app_server.h>
+#include <elm_app_server_view.h>
+#include <elm_app_client.h>
+#include <elm_app_client_view.h>
 #include <elm_app.h>
 #include <elm_bg.h>
 #include <elm_box.h>
index e87794b..fedc1fc 100644 (file)
@@ -147,6 +147,15 @@ elm_actionslider.h \
 elm_actionslider_eo.h \
 elm_actionslider_legacy.h \
 elm_actionslider_common.h \
+elm_app_common.h \
+elm_app_server_eo.h \
+elm_app_server_view_eo.h \
+elm_app_server_view.h \
+elm_app_server.h \
+elm_app_client_eo.h \
+elm_app_client.h \
+elm_app_client_view_eo.h \
+elm_app_client_view.h \
 elm_app.h \
 elm_authors.h \
 elm_bg.h \
@@ -394,6 +403,12 @@ elc_popup.c \
 elc_scrolled_entry.c \
 elm_access.c \
 elm_actionslider.c \
+elm_app_common.c \
+elm_app_server_eet.c \
+elm_app_server.c \
+elm_app_server_view.c \
+elm_app_client.c \
+elm_app_client_view.c \
 elm_bg.c \
 elm_box.c \
 elm_bubble.c \
diff --git a/src/lib/elm_app_client.c b/src/lib/elm_app_client.c
new file mode 100644 (file)
index 0000000..dc4f557
--- /dev/null
@@ -0,0 +1,432 @@
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+
+#include <Elementary.h>
+#include "elm_priv.h"
+
+EAPI Eo_Op ELM_APP_CLIENT_BASE_ID = EO_NOOP;
+
+#define MY_CLASS ELM_APP_CLIENT_CLASS
+
+#define MY_CLASS_NAME "elm_app_client"
+
+EAPI const Eo_Event_Description _ELM_APP_CLIENT_EV_VIEW_CREATED =
+         EO_EVENT_DESCRIPTION("view,created",
+                              "Called when a view of this application is created.");
+
+EAPI const Eo_Event_Description _ELM_APP_CLIENT_EV_VIEW_DELETED =
+         EO_EVENT_DESCRIPTION("view,deleted",
+                              "Called when a view of this application is deleted.");
+
+EAPI const Eo_Event_Description _ELM_APP_CLIENT_EV_VIEW_LIST_LOADED =
+         EO_EVENT_DESCRIPTION("view_list,loaded",
+                              "Called when list of view is loaded.");
+
+EAPI const Eo_Event_Description _ELM_APP_CLIENT_EV_TERMINATED =
+         EO_EVENT_DESCRIPTION("application,terminated",
+                              "Called when application is terminated.");
+
+typedef struct
+{
+   Eldbus_Proxy *app_proxy;
+   Eina_Hash *views;
+} Elm_App_Client_Data;
+
+static void
+_sub_path_process(Elm_App_Client *eo, Eldbus_Message_Iter *obj_iter, Elm_App_Client_Data *data, Eina_Bool loading_list)
+{
+   const char *obj_path;
+   Eldbus_Message_Iter *array_iface, *iface;
+
+   eldbus_message_iter_arguments_get(obj_iter, "oa{sa{sv}}", &obj_path, &array_iface);
+   while (eldbus_message_iter_get_and_next(array_iface, '{', &iface))
+     {
+        const char *iface_name;
+        Eldbus_Message_Iter *array_props;
+        Elm_App_Client_View *view;
+
+        eldbus_message_iter_arguments_get(iface, "sa{sv}", &iface_name,
+                                          &array_props);
+        if (strcmp(iface_name, "org.enlightenment.ApplicationView1"))
+          continue;
+
+        view = eina_hash_find(data->views, obj_path);
+        if (view)
+          continue;
+
+        view = eo_add_custom(ELM_APP_CLIENT_VIEW_CLASS, eo,
+                             elm_app_client_view_constructor(obj_path));
+        eina_hash_add(data->views, obj_path, view);
+        if (!loading_list)
+          eo_do(eo, eo_event_callback_call(ELM_APP_CLIENT_EV_VIEW_CREATED, view, NULL));
+     }
+}
+
+static void
+_objects_get(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
+{
+   Eo *eo = data;
+   Elm_App_Client_Data *cdata = eo_data_scope_get(eo, MY_CLASS);
+   Eldbus_Message_Iter *array_path, *path;
+
+   if (eldbus_message_error_get(msg, NULL, NULL))
+     return;
+
+   if (!eldbus_message_arguments_get(msg, "a{oa{sa{sv}}}", &array_path))
+     return;
+   while (eldbus_message_iter_get_and_next(array_path, '{', &path))
+     _sub_path_process(eo, path, cdata, EINA_TRUE);
+
+   eo_do(eo, eo_event_callback_call(ELM_APP_CLIENT_EV_VIEW_LIST_LOADED,
+                                    NULL, NULL));
+}
+
+static void _iface_add(void *data, const Eldbus_Message *msg)
+{
+   Eo *eo = data;
+   Elm_App_Client_Data *cdata = eo_data_scope_get(eo, MY_CLASS);
+   Eldbus_Message_Iter *main_iter;
+
+   main_iter = eldbus_message_iter_get(msg);
+   _sub_path_process(eo, main_iter, cdata, EINA_FALSE);
+}
+
+static void
+_iface_del(void *data, const Eldbus_Message *msg)
+{
+   Eo *eo = data;
+   Elm_App_Client_Data *cdata = eo_data_scope_get(eo, MY_CLASS);
+   const char *path, *iface;
+   Eldbus_Message_Iter *array_iface;
+
+   if (!eldbus_message_arguments_get(msg, "oas", &path, &array_iface))
+     return;
+   while (eldbus_message_iter_get_and_next(array_iface, 's', &iface))
+     {
+        Elm_App_Client_View *view;
+        Elm_App_View_State view_state;
+
+        if (strcmp(iface, "org.enlightenment.ApplicationView1"))
+          continue;
+
+        view = eina_hash_find(cdata->views, path);
+        if (!view)
+          continue;
+
+        eo_do(view, elm_app_client_view_state_get(&view_state));
+        if (view_state != ELM_APP_VIEW_STATE_CLOSED)
+          {
+             elm_app_client_view_internal_state_set(view,
+                                                    ELM_APP_VIEW_STATE_SHALLOW);
+             continue;
+          }
+
+        eina_hash_del(cdata->views, path, NULL);
+        eo_do(eo, eo_event_callback_call(ELM_APP_CLIENT_EV_VIEW_DELETED,
+                                         view, NULL));
+        eo_del(view);
+     }
+}
+
+static void
+_pkg_name_owner_changed_cb(void *data, const char *bus EINA_UNUSED, const char *old_id EINA_UNUSED, const char *new_id)
+{
+   Elm_App_Client *eo = data;
+   Elm_App_Client_Data *cdata = eo_data_scope_get(eo, MY_CLASS);
+   Eina_Iterator *iter;
+   Elm_App_Client_View *view;
+   Eina_List *views_list = NULL;
+
+   if (!new_id || (new_id[0] == '\0'))
+     return;
+
+   iter = eina_hash_iterator_data_new(cdata->views);
+   EINA_ITERATOR_FOREACH(iter, view)
+     views_list = eina_list_append(views_list, view);
+   eina_iterator_free(iter);
+
+   /*
+    * remove all views that are closed of the views hash
+    * views not closed, only set they to SHALLOW
+    */
+   EINA_LIST_FREE(views_list, view)
+     {
+        Elm_App_View_State view_state;
+        const char *path;
+
+        eo_do(view, elm_app_client_view_state_get(&view_state),
+              elm_app_client_view_path_get(&path));
+        if (view_state != ELM_APP_VIEW_STATE_CLOSED)
+          {
+             elm_app_client_view_internal_state_set(view,
+                                                    ELM_APP_VIEW_STATE_SHALLOW);
+             continue;
+          }
+
+        eina_hash_del(cdata->views, path, NULL);
+        eo_do(eo, eo_event_callback_call(ELM_APP_CLIENT_EV_VIEW_DELETED,
+                                         view, NULL));
+        eo_del(view);
+     }
+}
+
+static void
+_app_client_constructor(Eo *eo, void *_pd, va_list *list)
+{
+   Elm_App_Client_Data *data = _pd;
+   const char *pkg = va_arg(*list, const char *);
+   Eldbus_Connection *conn;
+   Eldbus_Object *obj;
+   char *path;
+
+   EINA_SAFETY_ON_NULL_GOTO(pkg, error);
+
+   eo_do_super(eo, MY_CLASS, eo_constructor());
+
+   data->views = eina_hash_string_small_new(NULL);
+
+   path = _dbus_package_to_path(pkg);
+
+   eldbus_init();
+   conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SESSION);
+   obj = eldbus_object_get(conn, pkg, path);
+   data->app_proxy = eldbus_proxy_get(obj, "org.enlightenment.Application1");
+   eldbus_object_managed_objects_get(obj, _objects_get, eo);
+   eldbus_object_manager_interfaces_added(obj, _iface_add, eo);
+   eldbus_object_manager_interfaces_removed(obj, _iface_del, eo);
+   eldbus_name_owner_changed_callback_add(conn, pkg, _pkg_name_owner_changed_cb,
+                                          eo, EINA_FALSE);
+
+   free(path);
+
+   return;
+error:
+   eo_error_set(eo);
+}
+
+static void
+_create_view_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
+{
+   Elm_App_Client_Open_View_Cb cb = eldbus_pending_data_del(pending, "user_cb");
+   void *user_data = eldbus_pending_data_del(pending, "user_data");
+   const char *error_name, *error_message, *view_path;
+   Elm_App_Client *eo = data;
+   Elm_App_Client_View *view;
+   Elm_App_Client_Data *cdata = eo_data_scope_get(eo, MY_CLASS);
+
+   if (eldbus_message_error_get(msg, &error_name, &error_message))
+     {
+        if (!cb)
+          return;
+        if (error_name && !strcmp(error_name, ELDBUS_ERROR_PENDING_CANCELED))
+          cb(user_data, NULL, ELM_APP_CLIENT_VIEW_OPEN_CANCELED, NULL);
+        else if (error_name && !strcmp(error_name, ELDBUS_ERROR_PENDING_TIMEOUT))
+          cb(user_data, NULL, ELM_APP_CLIENT_VIEW_OPEN_TIMEOUT, error_message);
+        else
+          cb(user_data, NULL, error_name, error_message);
+        return;
+     }
+
+   if (!eldbus_message_arguments_get(msg, "o", &view_path))
+     {
+        if (cb)
+          cb(user_data, NULL, "Unknow error", NULL);
+        return;
+     }
+
+   /**
+    * Because a IntefaceAdd signal could arrive first
+    */
+   view = eina_hash_find(cdata->views, view_path);
+   if (!view)
+     {
+        view = eo_add_custom(ELM_APP_CLIENT_VIEW_CLASS, eo,
+                             elm_app_client_view_constructor(view_path));
+        eina_hash_add(cdata->views, view_path, view);
+        eo_do(eo, eo_event_callback_call(ELM_APP_CLIENT_EV_VIEW_CREATED,
+                                         view, NULL));
+     }
+
+   if (!view)
+     {
+        if (cb)
+          cb(user_data, NULL, ELM_APP_CLEINT_VIEW_OPEN_ERROR, NULL);
+        return;
+     }
+   if (cb)
+     cb(user_data, view, NULL, NULL);
+}
+
+static void
+_view_open(Eo *eo, void *_pd, va_list *list)
+{
+   Elm_App_Client_Data *data = _pd;
+   Eina_Value *args = va_arg(*list, Eina_Value *);
+   Elm_App_Client_Open_View_Cb cb = va_arg(*list, Elm_App_Client_Open_View_Cb);
+   const void *user_data = va_arg(*list, const void *);
+   Elm_App_Client_Pending **view_open_pending = va_arg(*list, Elm_App_Client_Pending**);
+   Eldbus_Message *msg;
+   Eldbus_Pending *pending;
+
+   msg = eldbus_proxy_method_call_new(data->app_proxy, "CreateView");
+
+   if (args)
+     {
+        if (!eldbus_message_from_eina_value("a{sv}", msg, args))
+          {
+             eldbus_message_unref(msg);
+             //TODO test to find out what type eina_value must be
+             ERR("Eina_Value of args don't have a structure of a{sv}");
+             return;
+          }
+     }
+   else
+    {
+       Eldbus_Message_Iter *main_iter = eldbus_message_iter_get(msg);
+       Eldbus_Message_Iter *array;
+
+       eldbus_message_iter_arguments_append(main_iter, "a{sv}", &array);
+       eldbus_message_iter_container_close(main_iter, array);
+    }
+
+   pending = eldbus_proxy_send(data->app_proxy, msg, _create_view_cb, eo, -1);
+   if (user_data)
+     eldbus_pending_data_set(pending, "user_data", user_data);
+   if (cb)
+     eldbus_pending_data_set(pending, "user_cb", cb);
+
+   if (view_open_pending)
+     *view_open_pending = pending;
+}
+
+static void
+_views_get(Eo *eo EINA_UNUSED, void *_pd, va_list *list)
+{
+   Elm_App_Client_Data *data = _pd;
+   Eina_Iterator **view_iter = va_arg(*list, Eina_Iterator **);
+
+   *view_iter = eina_hash_iterator_data_new(data->views);
+}
+
+static void
+_all_close(Eo *eo EINA_UNUSED, void *_pd, va_list *list EINA_UNUSED)
+{
+   Elm_App_Client_Data *data = _pd;
+   eldbus_proxy_call(data->app_proxy, "CloseAllViews", NULL, NULL, -1, "");
+}
+
+static void
+_terminate(Eo *eo EINA_UNUSED, void *_pd, va_list *list EINA_UNUSED)
+{
+   Elm_App_Client_Data *data = _pd;
+   eldbus_proxy_call(data->app_proxy, "Terminate", NULL, NULL, -1, "");
+}
+
+static void
+_package_get(Eo *eo EINA_UNUSED, void *_pd, va_list *list)
+{
+   Elm_App_Client_Data *data = _pd;
+   Eldbus_Object *obj;
+   const char **package = va_arg(*list, const char **);
+
+   obj = eldbus_proxy_object_get(data->app_proxy);
+   *package = eldbus_object_bus_name_get(obj);
+}
+
+static void
+_view_open_cancel(Eo *eo EINA_UNUSED, void *_pd EINA_UNUSED, va_list *list)
+{
+   Elm_App_Client_Pending *pending = va_arg(*list, Elm_App_Client_Pending *);
+   eldbus_pending_cancel(pending);
+}
+
+static void
+_constructor(Eo *obj, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
+{
+   eo_error_set(obj);
+   ERR("Only custom constructor can be used with '%s' class", MY_CLASS_NAME);
+}
+
+static void
+_destructor(Eo *eo, void *_pd, va_list *list EINA_UNUSED)
+{
+   Elm_App_Client_Data *data = _pd;
+   Eldbus_Object *obj;
+   Eldbus_Connection *conn;
+   Eina_Iterator *iter;
+   Elm_App_Client_View *view;
+
+   iter = eina_hash_iterator_data_new(data->views);
+   EINA_ITERATOR_FOREACH(iter, view)
+     eo_del(view);
+   eina_iterator_free(iter);
+   eina_hash_free(data->views);
+
+   obj = eldbus_proxy_object_get(data->app_proxy);
+   conn = eldbus_object_connection_get(obj);
+   eldbus_name_owner_changed_callback_del(conn, eldbus_object_bus_name_get(obj),
+                                          _pkg_name_owner_changed_cb, eo);
+   eldbus_proxy_unref(data->app_proxy);
+   eldbus_object_unref(obj);
+   eldbus_connection_unref(conn);
+   eldbus_shutdown();
+
+   eo_do_super(eo, MY_CLASS, eo_destructor());
+}
+
+static void
+_class_constructor(Eo_Class *klass)
+{
+   const Eo_Op_Func_Description func_desc[] = {
+      EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_CONSTRUCTOR), _constructor),
+      EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_DESTRUCTOR), _destructor),
+      EO_OP_FUNC(ELM_APP_CLIENT_ID(ELM_APP_CLIENT_SUB_ID_CONSTRUCTOR), _app_client_constructor),
+      EO_OP_FUNC(ELM_APP_CLIENT_ID(ELM_APP_CLIENT_SUB_ID_VIEW_OPEN), _view_open),
+      EO_OP_FUNC(ELM_APP_CLIENT_ID(ELM_APP_CLIENT_SUB_ID_VIEWS_GET), _views_get),
+      EO_OP_FUNC(ELM_APP_CLIENT_ID(ELM_APP_CLIENT_SUB_ID_VIEWS_ALL_CLOSE), _all_close),
+      EO_OP_FUNC(ELM_APP_CLIENT_ID(ELM_APP_CLIENT_SUB_ID_TERMINATE), _terminate),
+      EO_OP_FUNC(ELM_APP_CLIENT_ID(ELM_APP_CLIENT_SUB_ID_PACKAGE_GET), _package_get),
+      EO_OP_FUNC(ELM_APP_CLIENT_ID(ELM_APP_CLIENT_SUB_ID_VIEW_OPEN_CANCEL), _view_open_cancel),
+      EO_OP_FUNC_SENTINEL
+   };
+   eo_class_funcs_set(klass, func_desc);
+}
+
+static const Eo_Op_Description op_desc[] = {
+     EO_OP_DESCRIPTION(ELM_APP_CLIENT_SUB_ID_CONSTRUCTOR,
+                       "Constructor of elm_app_client."),
+     EO_OP_DESCRIPTION(ELM_APP_CLIENT_SUB_ID_VIEW_OPEN, "Open a view."),
+     EO_OP_DESCRIPTION(ELM_APP_CLIENT_SUB_ID_VIEWS_GET,
+                       "Return a iterator with all views of application."),
+     EO_OP_DESCRIPTION(ELM_APP_CLIENT_SUB_ID_VIEWS_ALL_CLOSE,
+                       "Close all views of application."),
+     EO_OP_DESCRIPTION(ELM_APP_CLIENT_SUB_ID_TERMINATE,
+                       "Terminate applicaiton"),
+     EO_OP_DESCRIPTION(ELM_APP_CLIENT_SUB_ID_PACKAGE_GET,
+                       "Return the package name of application"),
+     EO_OP_DESCRIPTION(ELM_APP_CLIENT_SUB_ID_VIEW_OPEN_CANCEL,
+                       "Cancel view opening."),
+     EO_OP_DESCRIPTION_SENTINEL
+};
+
+static const Eo_Event_Description *event_desc[] = {
+     ELM_APP_CLIENT_EV_VIEW_CREATED,
+     ELM_APP_CLIENT_EV_VIEW_DELETED,
+     ELM_APP_CLIENT_EV_VIEW_LIST_LOADED,
+     ELM_APP_CLIENT_EV_TERMINATED,
+     NULL
+};
+
+static const Eo_Class_Description class_desc = {
+     EO_VERSION,
+     MY_CLASS_NAME,
+     EO_CLASS_TYPE_REGULAR,
+     EO_CLASS_DESCRIPTION_OPS(&ELM_APP_CLIENT_BASE_ID, op_desc, ELM_APP_CLIENT_SUB_ID_LAST),
+     event_desc,
+     sizeof(Elm_App_Client_Data),
+     _class_constructor,
+     NULL
+};
+
+EO_DEFINE_CLASS(elm_app_client_class_get, &class_desc, EO_BASE_CLASS, NULL);
diff --git a/src/lib/elm_app_client.h b/src/lib/elm_app_client.h
new file mode 100644 (file)
index 0000000..8669332
--- /dev/null
@@ -0,0 +1,3 @@
+#ifdef EFL_EO_API_SUPPORT
+#include "elm_app_client_eo.h"
+#endif
diff --git a/src/lib/elm_app_client_eo.h b/src/lib/elm_app_client_eo.h
new file mode 100644 (file)
index 0000000..dae6dd8
--- /dev/null
@@ -0,0 +1,111 @@
+#define ELM_APP_CLIENT_CLASS elm_app_client_class_get()
+
+const Eo_Class *elm_app_client_class_get(void) EINA_CONST;
+
+extern EAPI Eo_Op ELM_APP_CLIENT_BASE_ID;
+
+enum
+{
+   ELM_APP_CLIENT_SUB_ID_CONSTRUCTOR,
+   ELM_APP_CLIENT_SUB_ID_VIEW_OPEN,
+   ELM_APP_CLIENT_SUB_ID_VIEWS_GET,
+   ELM_APP_CLIENT_SUB_ID_VIEWS_ALL_CLOSE,
+   ELM_APP_CLIENT_SUB_ID_TERMINATE,
+   ELM_APP_CLIENT_SUB_ID_PACKAGE_GET,
+   ELM_APP_CLIENT_SUB_ID_VIEW_OPEN_CANCEL,
+   ELM_APP_CLIENT_SUB_ID_LAST
+};
+
+typedef Eo Elm_App_Client;
+typedef Eo Elm_App_Client_View;
+
+typedef Eldbus_Pending Elm_App_Client_Pending;
+
+typedef void (*Elm_App_Client_Open_View_Cb)(void *data, Elm_App_Client_View *view, const char *error, const char *error_message);
+
+#define ELM_APP_CLIENT_ID(sub_id) (ELM_APP_CLIENT_BASE_ID + sub_id)
+
+/**
+ * @def elm_app_client_constructor
+ * @since 1.8
+ *
+ * Class constructor of elm_app_client.
+ *
+ * @param[in] package of application
+ */
+#define elm_app_client_constructor(package) ELM_APP_CLIENT_ID(ELM_APP_CLIENT_SUB_ID_CONSTRUCTOR), EO_TYPECHECK(const char *, package)
+
+
+/**
+ * @def elm_app_client_view_open
+ * @since 1.8
+ *
+ * Open a application view.
+ *
+ * @param[in] arg an array of<string,data> containing the arguments of view
+ * @param[in] view_open_cb callback to be called when view open
+ * @param[in] data calback user data
+ * @param[out] pending handler to cancel the view opening if it takes to long
+ */
+#define elm_app_client_view_open(args, view_open_cb, data, pending) ELM_APP_CLIENT_ID(ELM_APP_CLIENT_SUB_ID_VIEW_OPEN), EO_TYPECHECK(Eina_Value *, args), EO_TYPECHECK(Elm_App_Client_Open_View_Cb, view_open_cb), EO_TYPECHECK(const void *, data), EO_TYPECHECK(Elm_App_Client_Pending **, pending)
+
+/**
+ * @def elm_app_client_views_get
+ * @since 1.8
+ *
+ * Return a iterator with all views of application.
+ *
+ * @param[out] ret the iterator with all views, must be freed after use
+ */
+#define elm_app_client_views_get(ret) ELM_APP_CLIENT_ID(ELM_APP_CLIENT_SUB_ID_VIEWS_GET), EO_TYPECHECK(Eina_Iterator **, ret)
+
+/**
+ * @def elm_app_client_view_all_close
+ * @since 1.8
+ *
+ * Close all views of application.
+ */
+#define elm_app_client_view_all_close() ELM_APP_CLIENT_ID(ELM_APP_CLIENT_SUB_ID_VIEWS_ALL_CLOSE)
+
+/**
+ * @def elm_app_client_terminate
+ * @since 1.8
+ *
+ * Terminate application.
+ */
+#define elm_app_client_terminate() ELM_APP_CLIENT_ID(ELM_APP_CLIENT_SUB_ID_TERMINATE)
+
+/**
+ * @def elm_app_client_package_get
+ * @since 1.8
+ *
+ * Return the application package.
+ *
+ * @param[out] ret application package
+ */
+#define elm_app_client_package_get(ret) ELM_APP_CLIENT_ID(ELM_APP_CLIENT_SUB_ID_PACKAGE_GET), EO_TYPECHECK(const char **, ret)
+
+/**
+ * @def elm_app_client_view_open_cancel
+ * @since 1.8
+ *
+ * Cancel a pending elm_app_client_view_open().
+ *
+ * @param[in] pending the view open handler.
+ */
+#define elm_app_client_view_open_cancel(pending) ELM_APP_CLIENT_ID(ELM_APP_CLIENT_SUB_ID_VIEW_OPEN_CANCEL), EO_TYPECHECK(Elm_App_Client_Pending **, pending)
+
+/**
+ * Events
+ */
+extern const Eo_Event_Description _ELM_APP_CLIENT_EV_VIEW_CREATED;
+#define ELM_APP_CLIENT_EV_VIEW_CREATED (&(_ELM_APP_CLIENT_EV_VIEW_CREATED))
+
+extern const Eo_Event_Description _ELM_APP_CLIENT_EV_VIEW_DELETED;
+#define ELM_APP_CLIENT_EV_VIEW_DELETED (&(_ELM_APP_CLIENT_EV_VIEW_DELETED))
+
+extern const Eo_Event_Description _ELM_APP_CLIENT_EV_VIEW_LIST_LOADED;
+#define ELM_APP_CLIENT_EV_VIEW_LIST_LOADED (&(_ELM_APP_CLIENT_EV_VIEW_LIST_LOADED))
+
+extern const Eo_Event_Description _ELM_APP_CLIENT_EV_TERMINATED;
+#define ELM_APP_CLIENT_EV_TERMINATED (&(_ELM_APP_CLIENT_EV_TERMINATED))
diff --git a/src/lib/elm_app_client_view.c b/src/lib/elm_app_client_view.c
new file mode 100644 (file)
index 0000000..2b8880c
--- /dev/null
@@ -0,0 +1,425 @@
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+
+#include <Elementary.h>
+#include "elm_priv.h"
+
+EAPI Eo_Op ELM_APP_CLIENT_VIEW_BASE_ID = EO_NOOP;
+
+#define MY_CLASS ELM_APP_CLIENT_VIEW_CLASS
+
+#define MY_CLASS_NAME "elm_app_client_view"
+
+EAPI const Eo_Event_Description _ELM_APP_CLIENT_VIEW_EV_STATE_CHANGED =
+         EO_EVENT_DESCRIPTION("state,changed", "State of view changed.");
+
+EAPI const Eo_Event_Description _ELM_APP_CLIENT_VIEW_EV_TITLE_CHANGED =
+         EO_EVENT_DESCRIPTION("title,changed", "Title of view changed.");
+
+EAPI const Eo_Event_Description _ELM_APP_CLIENT_VIEW_EV_ICON_CHANGED =
+         EO_EVENT_DESCRIPTION("icon,changed", "Icon of view changed.");
+
+EAPI const Eo_Event_Description _ELM_APP_CLIENT_VIEW_EV_ICON_PIXELS_CHANGED =
+         EO_EVENT_DESCRIPTION("icon,pixels,changed", "Icons pixels of view changed.");
+
+EAPI const Eo_Event_Description _ELM_APP_CLIENT_VIEW_EV_PROGRESS_CHANGED =
+         EO_EVENT_DESCRIPTION("progress,changed", "Progress of view changed.");
+
+EAPI const Eo_Event_Description _ELM_APP_CLIENT_VIEW_EV_NEW_EVENTS_CHANGED =
+         EO_EVENT_DESCRIPTION("new_events,changed", "New events of view changed.");
+
+EAPI const Eo_Event_Description _ELM_APP_CLIENT_VIEW_EV_WINDOW_CHANGED =
+         EO_EVENT_DESCRIPTION("window,changed", "Window of view changed.");
+
+EAPI const Eo_Event_Description _ELM_APP_CLIENT_VIEW_EV_PROPERTY_CHANGED =
+         EO_EVENT_DESCRIPTION("property,changed", "One of view properties changed.");
+
+typedef struct
+{
+   Eldbus_Proxy *view_proxy;
+   Elm_App_View_State state;
+} Elm_App_Client_View_Data;
+
+static const char *_string_prop_get(const Eina_Value *v)
+{
+   const char *str;
+
+   if (!v)
+     return "";
+
+   eina_value_get(v, &str);
+   return str;
+}
+
+static int _int_prop_get(const Eina_Value *v)
+{
+   int num;
+
+   if (!v)
+     return 0;
+
+   eina_value_get(v, &num);
+   return num;
+}
+
+static short _short_prop_get(const Eina_Value *v)
+{
+   short num;
+
+   if (!v)
+     return 0;
+
+   eina_value_get(v, &num);
+   return num;
+}
+
+static void
+_prop_changed(void *user_data, Eldbus_Proxy *proxy EINA_UNUSED, void *event_info)
+{
+   Eldbus_Proxy_Event_Property_Changed *prop_event = event_info;
+   Elm_App_Client_View *eo = user_data;
+   const Eina_Value *v = prop_event->value;
+   Elm_App_Client_View_Data *cdata = eo_data_scope_get(eo, MY_CLASS);
+
+   if (!strcmp(prop_event->name, "Title"))
+     eo_do(eo, eo_event_callback_call(ELM_APP_CLIENT_VIEW_EV_TITLE_CHANGED,
+                                      _string_prop_get(v), NULL));
+   else if (!strcmp(prop_event->name, "IconName"))
+     eo_do(eo, eo_event_callback_call(ELM_APP_CLIENT_VIEW_EV_ICON_CHANGED,
+                                      _string_prop_get(v), NULL));
+   else if (!strcmp(prop_event->name, "IconPixels"))
+     eo_do(eo, eo_event_callback_call(ELM_APP_CLIENT_VIEW_EV_ICON_PIXELS_CHANGED,
+                                      NULL, NULL));
+   else if (!strcmp(prop_event->name, "NewEvents"))
+     eo_do(eo, eo_event_callback_call(ELM_APP_CLIENT_VIEW_EV_NEW_EVENTS_CHANGED,
+                                      (void *)(long)_int_prop_get(v), NULL));
+   else if (!strcmp(prop_event->name, "Progress"))
+     eo_do(eo, eo_event_callback_call(ELM_APP_CLIENT_VIEW_EV_PROGRESS_CHANGED,
+                                      (void *)(long)_short_prop_get(v), NULL));
+   else if (!strcmp(prop_event->name, "State"))
+     {
+        cdata->state = _string_state_to_id(_string_prop_get(v));
+        eo_do(eo, eo_event_callback_call(ELM_APP_CLIENT_VIEW_EV_STATE_CHANGED,
+                                         (void *)(long)cdata->state, NULL));
+     }
+   else if (!strcmp(prop_event->name, "WindowId"))
+     eo_do(eo, eo_event_callback_call(ELM_APP_CLIENT_VIEW_EV_WINDOW_CHANGED,
+                                      (void *)(long)_int_prop_get(v), NULL));
+   else
+      return;
+
+   eo_do(eo, eo_event_callback_call(ELM_APP_CLIENT_VIEW_EV_PROPERTY_CHANGED,
+                                    prop_event->name, NULL));
+}
+
+static void
+_props_loaded(void *user_data, Eldbus_Proxy *proxy EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   const Eina_Hash *props = eldbus_proxy_property_local_get_all(proxy);
+   Eina_Iterator *iter;
+   Eina_Hash_Tuple *t;
+
+   iter = eina_hash_iterator_tuple_new(props);
+   EINA_ITERATOR_FOREACH(iter, t)
+     {
+        Eldbus_Proxy_Event_Property_Changed event;
+
+        event.name = t->key;
+        event.proxy = proxy;
+        event.value = t->data;
+
+        _prop_changed(user_data, proxy, &event);
+     }
+   eina_iterator_free(iter);
+}
+
+void
+elm_app_client_view_internal_state_set(Eo *eo, Elm_App_View_State state)
+{
+   Elm_App_Client_View_Data *cdata;
+   Eina_Bool changed = EINA_FALSE;
+
+   EINA_SAFETY_ON_NULL_RETURN(eo);
+   EINA_SAFETY_ON_FALSE_RETURN(eo_isa(eo, ELM_APP_CLIENT_VIEW_CLASS));
+
+   cdata = eo_data_scope_get(eo, MY_CLASS);
+   changed = cdata->state != state;
+   cdata->state = state;
+   if (!changed)
+     return;
+   eo_do(eo, eo_event_callback_call(ELM_APP_CLIENT_VIEW_EV_STATE_CHANGED,
+                                    (void *)(long)cdata->state, NULL));
+}
+
+static void
+_app_client_view_constructor(Eo *eo, void *_pd, va_list *list)
+{
+   Elm_App_Client_View_Data *data = _pd;
+   Elm_App_Client *parent;
+   const char *package, *path = va_arg(*list, const char *);
+   Eldbus_Connection *conn;
+   Eldbus_Object *obj;
+
+   EINA_SAFETY_ON_NULL_GOTO(path, error);
+   eo_do_super(eo, MY_CLASS, eo_constructor());
+
+   parent = eo_parent_get(eo);
+   EINA_SAFETY_ON_TRUE_GOTO((!parent) ||
+                            (!eo_isa(parent, ELM_APP_CLIENT_CLASS)), error);
+
+   eo_do(parent, elm_app_client_package_get(&package));
+
+   eldbus_init();
+   conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SESSION);
+   obj = eldbus_object_get(conn, package, path);
+   data->view_proxy = eldbus_proxy_get(obj,
+                                       "org.enlightenment.ApplicationView1");
+   eldbus_proxy_properties_monitor(data->view_proxy, EINA_TRUE);
+   eldbus_proxy_event_callback_add(data->view_proxy,
+                                   ELDBUS_PROXY_EVENT_PROPERTY_CHANGED,
+                                   _prop_changed, eo);
+   eldbus_proxy_event_callback_add(data->view_proxy,
+                                   ELDBUS_PROXY_EVENT_PROPERTY_LOADED,
+                                   _props_loaded, eo);
+
+   return;
+
+error:
+   eo_error_set(eo);
+}
+
+static void
+_dbus_state_set_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
+{
+   Elm_App_Client_View *eo = data;
+   Elm_App_Client_View_Cb cb = eldbus_pending_data_del(pending, "cb");
+   void *user_data = eldbus_pending_data_del(pending, "user_data");
+   const char *error = NULL, *error_message = NULL;
+
+   eldbus_message_error_get(msg, &error, &error_message);
+
+   cb(user_data, eo, error, error_message);
+}
+
+static void
+_dbus_action_do(Eo *eo, Eldbus_Proxy *proxy, const char *action, Elm_App_Client_View_Cb cb, const void *data)
+{
+   Eldbus_Pending *pending;
+
+   if (!cb)
+     {
+        eldbus_proxy_call(proxy, action, NULL, NULL, -1, "");
+        return;
+     }
+
+   pending = eldbus_proxy_call(proxy, action, _dbus_state_set_cb, eo, -1, "");
+   eldbus_pending_data_set(pending, "cb", cb);
+   eldbus_pending_data_set(pending, "user_data", data);
+}
+
+static void
+_resume(Eo *eo, void *_pd, va_list *list)
+{
+   Elm_App_Client_View_Data *data = _pd;
+   Elm_App_Client_View_Cb cb = va_arg(*list, Elm_App_Client_View_Cb);
+   const void *user_data = va_arg(*list, const void *);
+
+   _dbus_action_do(eo, data->view_proxy, "Resume", cb, user_data);
+}
+
+static void
+_pause(Eo *eo, void *_pd, va_list *list)
+{
+   Elm_App_Client_View_Data *data = _pd;
+   Elm_App_Client_View_Cb cb = va_arg(*list, Elm_App_Client_View_Cb);
+   const void *user_data = va_arg(*list, const void *);
+
+   _dbus_action_do(eo, data->view_proxy, "Pause", cb, user_data);
+}
+
+static void
+_close(Eo *eo, void *_pd, va_list *list)
+{
+   Elm_App_Client_View_Data *data = _pd;
+   Elm_App_Client_View_Cb cb = va_arg(*list, Elm_App_Client_View_Cb);
+   const void *user_data = va_arg(*list, const void *);
+
+   _dbus_action_do(eo, data->view_proxy, "Close", cb, user_data);
+}
+
+static void _eo_string_prop_get(void *_pd, va_list *list, const char *prop)
+{
+   Elm_App_Client_View_Data *data = _pd;
+   const char **title = va_arg(*list, const char **);
+   Eina_Value *v;
+
+   v = eldbus_proxy_property_local_get(data->view_proxy, prop);
+   *title = _string_prop_get(v);
+}
+
+static void _title_get(Eo *eo EINA_UNUSED, void *_pd, va_list *list)
+{
+   _eo_string_prop_get(_pd, list, "Title");
+}
+
+static void _icon_get(Eo *eo EINA_UNUSED, void *_pd, va_list *list)
+{
+   _eo_string_prop_get(_pd, list, "IconName");
+}
+
+static void _icon_pixels_get(Eo *eo EINA_UNUSED, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
+{
+   //Elm_App_Client_View_Data *data = _pd;
+   //TODO
+}
+
+static void _progress_get(Eo *eo EINA_UNUSED, void *_pd, va_list *list)
+{
+   Elm_App_Client_View_Data *data = _pd;
+   short *progress = va_arg(*list, short *);
+   Eina_Value *v;
+
+   v = eldbus_proxy_property_local_get(data->view_proxy, "Progress");
+   *progress = _short_prop_get(v);
+}
+
+static void _new_events_get(Eo *eo EINA_UNUSED, void *_pd, va_list *list)
+{
+   Elm_App_Client_View_Data *data = _pd;
+   int *new_events = va_arg(*list, int *);
+   Eina_Value *v;
+
+   v = eldbus_proxy_property_local_get(data->view_proxy, "NewEvents");
+   *new_events = _int_prop_get(v);
+}
+
+static void _state_get(Eo *eo EINA_UNUSED, void *_pd, va_list *list)
+{
+   Elm_App_Client_View_Data *data = _pd;
+   Elm_App_View_State *state = va_arg(*list, Elm_App_View_State *);
+
+   *state = data->state;
+}
+
+static void _window_get(Eo *eo EINA_UNUSED, void *_pd, va_list *list)
+{
+   Elm_App_Client_View_Data *data = _pd;
+   int *window = va_arg(*list, int *);
+   Eina_Value *v;
+
+   v = eldbus_proxy_property_local_get(data->view_proxy, "WindowId");
+   *window = _int_prop_get(v);
+}
+
+static void _path_get(Eo *eo EINA_UNUSED, void *_pd, va_list *list)
+{
+   Elm_App_Client_View_Data *data = _pd;
+   const char **ret = va_arg(*list, const char **);
+   Eldbus_Object *obj;
+
+   obj = eldbus_proxy_object_get(data->view_proxy);
+   *ret = eldbus_object_path_get(obj);
+}
+
+static void _package_get(Eo *eo EINA_UNUSED, void *_pd, va_list *list)
+{
+   Elm_App_Client_View_Data *data = _pd;
+   const char **ret = va_arg(*list, const char **);
+   Eldbus_Object *obj;
+
+   obj = eldbus_proxy_object_get(data->view_proxy);
+   *ret = eldbus_object_bus_name_get(obj);
+}
+
+static void
+_destructor(Eo *eo, void *_pd, va_list *list EINA_UNUSED)
+{
+   Elm_App_Client_View_Data *data = _pd;
+   Eldbus_Object *obj;
+   Eldbus_Connection *conn;
+
+   eldbus_proxy_properties_monitor(data->view_proxy, EINA_FALSE);
+   obj = eldbus_proxy_object_get(data->view_proxy);
+   conn = eldbus_object_connection_get(obj);
+
+   eldbus_proxy_unref(data->view_proxy);
+   eldbus_object_unref(obj);
+   eldbus_connection_unref(conn);
+   eldbus_shutdown();
+
+   eo_do_super(eo, MY_CLASS, eo_destructor());
+}
+
+static void
+_constructor(Eo *obj, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
+{
+   eo_error_set(obj);
+   ERR("Only custom constructor can be used with '%s' class", MY_CLASS_NAME);
+}
+
+static void
+_class_constructor(Eo_Class *klass)
+{
+   const Eo_Op_Func_Description func_desc[] = {
+      EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_CONSTRUCTOR), _constructor),
+      EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_DESTRUCTOR), _destructor),
+      EO_OP_FUNC(ELM_APP_CLIENT_VIEW_ID(ELM_APP_CLIENT_VIEW_SUB_ID_CONSTRUCTOR), _app_client_view_constructor),
+      EO_OP_FUNC(ELM_APP_CLIENT_VIEW_ID(ELM_APP_CLIENT_VIEW_SUB_ID_CLOSE), _close),
+      EO_OP_FUNC(ELM_APP_CLIENT_VIEW_ID(ELM_APP_CLIENT_VIEW_SUB_ID_PAUSE), _pause),
+      EO_OP_FUNC(ELM_APP_CLIENT_VIEW_ID(ELM_APP_CLIENT_VIEW_SUB_ID_RESUME), _resume),
+      EO_OP_FUNC(ELM_APP_CLIENT_VIEW_ID(ELM_APP_CLIENT_VIEW_SUB_ID_TITLE_GET), _title_get),
+      EO_OP_FUNC(ELM_APP_CLIENT_VIEW_ID(ELM_APP_CLIENT_VIEW_SUB_ID_ICON_GET), _icon_get),
+      EO_OP_FUNC(ELM_APP_CLIENT_VIEW_ID(ELM_APP_CLIENT_VIEW_SUB_ID_ICON_PIXELS_GET), _icon_pixels_get),
+      EO_OP_FUNC(ELM_APP_CLIENT_VIEW_ID(ELM_APP_CLIENT_VIEW_SUB_ID_PROGRESS_GET), _progress_get),
+      EO_OP_FUNC(ELM_APP_CLIENT_VIEW_ID(ELM_APP_CLIENT_VIEW_SUB_ID_NEW_EVENTS_GET), _new_events_get),
+      EO_OP_FUNC(ELM_APP_CLIENT_VIEW_ID(ELM_APP_CLIENT_VIEW_SUB_ID_STATE_GET), _state_get),
+      EO_OP_FUNC(ELM_APP_CLIENT_VIEW_ID(ELM_APP_CLIENT_VIEW_SUB_ID_WINDOW_GET), _window_get),
+      EO_OP_FUNC(ELM_APP_CLIENT_VIEW_ID(ELM_APP_CLIENT_VIEW_SUB_ID_PATH_GET), _path_get),
+      EO_OP_FUNC(ELM_APP_CLIENT_VIEW_ID(ELM_APP_CLIENT_VIEW_SUB_ID_PACKAGE_GET), _package_get),
+      EO_OP_FUNC_SENTINEL
+   };
+   eo_class_funcs_set(klass, func_desc);
+}
+
+static const Eo_Op_Description op_desc[] = {
+     EO_OP_DESCRIPTION(ELM_APP_CLIENT_VIEW_SUB_ID_CONSTRUCTOR, "Constructor of elm_app_client_view."),
+     EO_OP_DESCRIPTION(ELM_APP_CLIENT_VIEW_SUB_ID_CLOSE, "Close view."),
+     EO_OP_DESCRIPTION(ELM_APP_CLIENT_VIEW_SUB_ID_PAUSE, "Pause view."),
+     EO_OP_DESCRIPTION(ELM_APP_CLIENT_VIEW_SUB_ID_RESUME, "Resume view."),
+     EO_OP_DESCRIPTION(ELM_APP_CLIENT_VIEW_SUB_ID_TITLE_GET, "Get view title."),
+     EO_OP_DESCRIPTION(ELM_APP_CLIENT_VIEW_SUB_ID_ICON_GET, "Get view icon."),
+     EO_OP_DESCRIPTION(ELM_APP_CLIENT_VIEW_SUB_ID_ICON_PIXELS_GET, "Get view icon pixels."),
+     EO_OP_DESCRIPTION(ELM_APP_CLIENT_VIEW_SUB_ID_PROGRESS_GET, "Get view progress."),
+     EO_OP_DESCRIPTION(ELM_APP_CLIENT_VIEW_SUB_ID_NEW_EVENTS_GET, "Get view new events."),
+     EO_OP_DESCRIPTION(ELM_APP_CLIENT_VIEW_SUB_ID_STATE_GET, "Get view state."),
+     EO_OP_DESCRIPTION(ELM_APP_CLIENT_VIEW_SUB_ID_WINDOW_GET, "Get view window id."),
+     EO_OP_DESCRIPTION(ELM_APP_CLIENT_VIEW_SUB_ID_PATH_GET, "Get view dbus path."),
+     EO_OP_DESCRIPTION(ELM_APP_CLIENT_VIEW_SUB_ID_PACKAGE_GET, "Get application package."),
+     EO_OP_DESCRIPTION_SENTINEL
+};
+
+static const Eo_Event_Description *event_desc[] = {
+     ELM_APP_CLIENT_VIEW_EV_STATE_CHANGED,
+     ELM_APP_CLIENT_VIEW_EV_TITLE_CHANGED,
+     ELM_APP_CLIENT_VIEW_EV_ICON_CHANGED,
+     ELM_APP_CLIENT_VIEW_EV_ICON_PIXELS_CHANGED,
+     ELM_APP_CLIENT_VIEW_EV_NEW_EVENTS_CHANGED,
+     ELM_APP_CLIENT_VIEW_EV_PROGRESS_CHANGED,
+     ELM_APP_CLIENT_VIEW_EV_WINDOW_CHANGED,
+     ELM_APP_CLIENT_VIEW_EV_PROPERTY_CHANGED,
+     NULL
+};
+
+static const Eo_Class_Description class_desc = {
+     EO_VERSION,
+     MY_CLASS_NAME,
+     EO_CLASS_TYPE_REGULAR,
+     EO_CLASS_DESCRIPTION_OPS(&ELM_APP_CLIENT_VIEW_BASE_ID, op_desc, ELM_APP_CLIENT_VIEW_SUB_ID_LAST),
+     event_desc,
+     sizeof(Elm_App_Client_View_Data),
+     _class_constructor,
+     NULL
+};
+
+EO_DEFINE_CLASS(elm_app_client_view_class_get, &class_desc, EO_BASE_CLASS, NULL);
diff --git a/src/lib/elm_app_client_view.h b/src/lib/elm_app_client_view.h
new file mode 100644 (file)
index 0000000..e124359
--- /dev/null
@@ -0,0 +1,3 @@
+#ifdef EFL_EO_API_SUPPORT
+#include "elm_app_client_view_eo.h"
+#endif
diff --git a/src/lib/elm_app_client_view_eo.h b/src/lib/elm_app_client_view_eo.h
new file mode 100644 (file)
index 0000000..add2899
--- /dev/null
@@ -0,0 +1,194 @@
+#define ELM_APP_CLIENT_VIEW_CLASS elm_app_client_view_class_get()
+
+const Eo_Class *elm_app_client_view_class_get(void) EINA_CONST;
+
+extern EAPI Eo_Op ELM_APP_CLIENT_VIEW_BASE_ID;
+
+enum
+{
+   ELM_APP_CLIENT_VIEW_SUB_ID_CONSTRUCTOR,
+   ELM_APP_CLIENT_VIEW_SUB_ID_CLOSE,
+   ELM_APP_CLIENT_VIEW_SUB_ID_PAUSE,
+   ELM_APP_CLIENT_VIEW_SUB_ID_RESUME,
+   ELM_APP_CLIENT_VIEW_SUB_ID_TITLE_GET,
+   ELM_APP_CLIENT_VIEW_SUB_ID_ICON_GET,
+   ELM_APP_CLIENT_VIEW_SUB_ID_ICON_PIXELS_GET,
+   ELM_APP_CLIENT_VIEW_SUB_ID_PROGRESS_GET,
+   ELM_APP_CLIENT_VIEW_SUB_ID_NEW_EVENTS_GET,
+   ELM_APP_CLIENT_VIEW_SUB_ID_STATE_GET,
+   ELM_APP_CLIENT_VIEW_SUB_ID_WINDOW_GET,
+   ELM_APP_CLIENT_VIEW_SUB_ID_PATH_GET,
+   ELM_APP_CLIENT_VIEW_SUB_ID_PACKAGE_GET,
+   ELM_APP_CLIENT_VIEW_SUB_ID_LAST
+};
+
+typedef void *(*Elm_App_Client_View_Cb)(void *data, Elm_App_Client_View *view, const char *error, const char *error_message);
+
+#define ELM_APP_CLIENT_VIEW_ID(sub_id) (ELM_APP_CLIENT_VIEW_BASE_ID + sub_id)
+
+/**
+ * @def elm_app_client_view_constructor
+ * @since 1.8
+ *
+ * Class constructor of elm_app_client_view
+ *
+ * @param[out] path DBus path of view
+ *
+ * @note You must supply elm_app_client as parent.
+ */
+#define elm_app_client_view_constructor(path) ELM_APP_CLIENT_VIEW_ID(ELM_APP_CLIENT_VIEW_SUB_ID_CONSTRUCTOR), EO_TYPECHECK(const char *, path)
+
+/**
+ * @def elm_app_client_view_close
+ * @since 1.8
+ *
+ * Close view
+ *
+ * @param[in] cb callback to be called when view was closed
+ * @param[in] data callback user data
+ */
+#define elm_app_client_view_close(cb, data) ELM_APP_CLIENT_VIEW_ID(ELM_APP_CLIENT_VIEW_SUB_ID_CLOSE), EO_TYPECHECK(Elm_App_Client_View_Cb, cb), EO_TYPECHECK(const void *, data)
+
+/**
+ * @def elm_app_client_view_pause
+ * @since 1.8
+ *
+ * Pause view
+ *
+ * @param[in] cb callback to be called when view was paused
+ * @param[in] data callback user data
+ */
+#define elm_app_client_view_pause(cb, data) ELM_APP_CLIENT_VIEW_ID(ELM_APP_CLIENT_VIEW_SUB_ID_PAUSE), EO_TYPECHECK(Elm_App_Client_View_Cb, cb), EO_TYPECHECK(const void *, data)
+
+/**
+ * @def elm_app_client_view_resume
+ * @since 1.8
+ *
+ * Resume view
+ *
+ * @param[in] cb callback to be called when view was resumed
+ * @param[in] data callback user data
+ */
+#define elm_app_client_view_resume(cb, data) ELM_APP_CLIENT_VIEW_ID(ELM_APP_CLIENT_VIEW_SUB_ID_RESUME), EO_TYPECHECK(Elm_App_Client_View_Cb, cb), EO_TYPECHECK(const void *, data)
+
+/**
+ * @def elm_app_client_view_title_get
+ * @since 1.8
+ *
+ * Get title of view
+ *
+ * @param[out] ret title of view
+ */
+#define elm_app_client_view_title_get(ret) ELM_APP_CLIENT_VIEW_ID(ELM_APP_CLIENT_VIEW_SUB_ID_TITLE_GET), EO_TYPECHECK(const char **, ret)
+
+/**
+ * @def elm_app_client_view_icon_get
+ * @since 1.8
+ *
+ * Get icon path of view
+ *
+ * @param[out] ret icon path of view
+ */
+#define elm_app_client_view_icon_get(ret) ELM_APP_CLIENT_VIEW_ID(ELM_APP_CLIENT_VIEW_SUB_ID_ICON_GET), EO_TYPECHECK(const char **, ret)
+
+/**
+ * @def elm_app_client_view_icon_pixels_get
+ * @since 1.8
+ *
+ * Get icon pixels of view, view could have a icon in raw format
+ * not saved in disk.
+ *
+ * @param[out] w icon width
+ * @param[out] h icon height
+ * @param[out] has_alpha if icon have alpha channel
+ * @param[out] pixels unsigned char array, with all bytes of icon
+ */
+#define elm_app_client_view_icon_pixels_get(w, h, has_alpha, pixels) ELM_APP_CLIENT_VIEW_ID(ELM_APP_CLIENT_VIEW_SUB_ID_ICON_PIXELS_GET), EO_TYPECHECK(unsigned int *, h), EO_TYPECHECK(Eina_Bool *, has_alpha), EO_TYPECHECK(const unsigned char **, pixels)
+
+/**
+ * @def elm_app_client_view_progress_get
+ * @since 1.8
+ *
+ * Get progress of view, should be -1 if there nothing in progress or something
+ * between 0-100
+ *
+ * @param[out] progress progress of view
+ */
+#define elm_app_client_view_progress_get(progress) ELM_APP_CLIENT_VIEW_ID(ELM_APP_CLIENT_VIEW_SUB_ID_PROGRESS_GET), EO_TYPECHECK(unsigned short *, progress)
+
+/**
+ * @def elm_app_client_view_new_events_get
+ * @since 1.8
+ *
+ * Get new events of view
+ *
+ * @param[out] events number of events of view
+ */
+#define elm_app_client_view_new_events_get(events) ELM_APP_CLIENT_VIEW_ID(ELM_APP_CLIENT_VIEW_SUB_ID_NEW_EVENTS_GET), EO_TYPECHECK(int *, events)
+
+/**
+ * @def elm_app_client_view_state_get
+ * @since 1.8
+ *
+ * Get state of view
+ *
+ * @param[out] state state of view
+ */
+#define elm_app_client_view_state_get(state) ELM_APP_CLIENT_VIEW_ID(ELM_APP_CLIENT_VIEW_SUB_ID_STATE_GET), EO_TYPECHECK(Elm_App_View_State *, state)
+
+/**
+ * @def elm_app_client_view_window_get
+ * @since 1.8
+ *
+ * Get window of view
+ *
+ * @param[out] window window of view
+ */
+#define elm_app_client_view_window_get(window) ELM_APP_CLIENT_VIEW_ID(ELM_APP_CLIENT_VIEW_SUB_ID_WINDOW_GET), EO_TYPECHECK(int *, window)
+
+/**
+ * @def elm_app_client_view_path_get
+ * @since 1.8
+ *
+ * Get DBus path of view
+ *
+ * @param[out] ret DBus path of view
+ */
+#define elm_app_client_view_path_get(ret) ELM_APP_CLIENT_VIEW_ID(ELM_APP_CLIENT_VIEW_SUB_ID_PATH_GET), EO_TYPECHECK(const char **, ret)
+
+/**
+ * @def elm_app_client_view_package_get
+ * @since 1.8
+ *
+ * Get application package
+ *
+ * @param[out] ret Package of application
+ */
+#define elm_app_client_view_package_get(ret) ELM_APP_CLIENT_VIEW_ID(ELM_APP_CLIENT_VIEW_SUB_ID_PACKAGE_GET), EO_TYPECHECK(const char **, ret)
+
+/**
+ * Events
+ */
+extern const Eo_Event_Description _ELM_APP_CLIENT_VIEW_EV_STATE_CHANGED;
+#define ELM_APP_CLIENT_VIEW_EV_STATE_CHANGED (&(_ELM_APP_CLIENT_VIEW_EV_STATE_CHANGED))
+
+extern const Eo_Event_Description _ELM_APP_CLIENT_VIEW_EV_TITLE_CHANGED;
+#define ELM_APP_CLIENT_VIEW_EV_TITLE_CHANGED (&(_ELM_APP_CLIENT_VIEW_EV_TITLE_CHANGED))
+
+extern const Eo_Event_Description _ELM_APP_CLIENT_VIEW_EV_ICON_CHANGED;
+#define ELM_APP_CLIENT_VIEW_EV_ICON_CHANGED (&(_ELM_APP_CLIENT_VIEW_EV_ICON_CHANGED))
+
+extern const Eo_Event_Description _ELM_APP_CLIENT_VIEW_EV_ICON_PIXELS_CHANGED;
+#define ELM_APP_CLIENT_VIEW_EV_ICON_PIXELS_CHANGED (&(_ELM_APP_CLIENT_VIEW_EV_ICON_PIXELS_CHANGED))
+
+extern const Eo_Event_Description _ELM_APP_CLIENT_VIEW_EV_NEW_EVENTS_CHANGED;
+#define ELM_APP_CLIENT_VIEW_EV_NEW_EVENTS_CHANGED (&(_ELM_APP_CLIENT_VIEW_EV_NEW_EVENTS_CHANGED))
+
+extern const Eo_Event_Description _ELM_APP_CLIENT_VIEW_EV_PROGRESS_CHANGED;
+#define ELM_APP_CLIENT_VIEW_EV_PROGRESS_CHANGED (&(_ELM_APP_CLIENT_VIEW_EV_PROGRESS_CHANGED))
+
+extern const Eo_Event_Description _ELM_APP_CLIENT_VIEW_EV_WINDOW_CHANGED;
+#define ELM_APP_CLIENT_VIEW_EV_WINDOW_CHANGED (&(_ELM_APP_CLIENT_VIEW_EV_WINDOW_CHANGED))
+
+extern const Eo_Event_Description _ELM_APP_CLIENT_VIEW_EV_PROPERTY_CHANGED;
+#define ELM_APP_CLIENT_VIEW_EV_PROPERTY_CHANGED (&(_ELM_APP_CLIENT_VIEW_EV_PROPERTY_CHANGED))
diff --git a/src/lib/elm_app_common.c b/src/lib/elm_app_common.c
new file mode 100644 (file)
index 0000000..31537f6
--- /dev/null
@@ -0,0 +1,56 @@
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+
+#include <Elementary.h>
+#include "elm_priv.h"
+
+char *
+_dbus_package_to_path(const char *pkg)
+{
+   Eina_Strbuf *buffer;
+   char *ret;
+
+   buffer = eina_strbuf_new();
+   eina_strbuf_append_char(buffer, '/');
+   for (; *pkg != '\0'; pkg++)
+     {
+        if (*pkg == '.')
+          eina_strbuf_append_char(buffer, '/');
+        else if(isalnum(*pkg))
+          eina_strbuf_append_char(buffer, *pkg);
+        else
+          eina_strbuf_append_printf(buffer, "_%02x", *pkg);
+     }
+
+   ret = eina_strbuf_string_steal(buffer);
+   eina_strbuf_free(buffer);
+
+   return ret;
+}
+
+static const char *_string_states[] = {
+   "unknown",
+   "live",
+   "paused",
+   "closed",
+   "shallow",
+   NULL
+};
+
+Elm_App_View_State _string_state_to_id(const char *state)
+{
+   int i;
+
+   for (i = 0; _string_states[i]; i++)
+     {
+        if (!strcmp(state, _string_states[i]))
+          return i;
+     }
+   return 0;
+}
+
+const char *_state_id_to_string(Elm_App_View_State state)
+{
+   return _string_states[state];
+}
diff --git a/src/lib/elm_app_common.h b/src/lib/elm_app_common.h
new file mode 100644 (file)
index 0000000..29b7bb9
--- /dev/null
@@ -0,0 +1,17 @@
+typedef enum
+{
+   ELM_APP_VIEW_STATE_UNKNOWN = 0,
+   ELM_APP_VIEW_STATE_LIVE,
+   ELM_APP_VIEW_STATE_PAUSED,
+   ELM_APP_VIEW_STATE_CLOSED,
+   ELM_APP_VIEW_STATE_SHALLOW
+} Elm_App_View_State;
+
+char *_dbus_package_to_path(const char *package);
+
+Elm_App_View_State _string_state_to_id(const char *state);
+
+const char *_state_id_to_string(Elm_App_View_State state);
+
+void elm_app_client_view_internal_state_set(Eo *eo, Elm_App_View_State state);
+
diff --git a/src/lib/elm_app_server.c b/src/lib/elm_app_server.c
new file mode 100644 (file)
index 0000000..1fff5b7
--- /dev/null
@@ -0,0 +1,571 @@
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+
+#include <Elementary.h>
+#include "elm_priv.h"
+#include "elm_app_server_eet.h"
+
+EAPI Eo_Op ELM_APP_SERVER_BASE_ID = EO_NOOP;
+
+#define MY_CLASS ELM_APP_SERVER_CLASS
+
+#define MY_CLASS_NAME "elm_app_server"
+
+EAPI const Eo_Event_Description _ELM_APP_SERVER_EV_TERMINATE =
+         EO_EVENT_DESCRIPTION("terminate",
+                              "Called when application must be terminated.");
+
+typedef struct
+{
+   Eldbus_Connection *conn;
+   Eldbus_Service_Interface *iface;
+   Elm_App_Server_Create_View_Cb create_view_cb;
+   Eina_Hash *views;
+
+   int PID;
+   Eina_Stringshare *title;
+   Eina_Stringshare *icon_name;
+   Eina_Stringshare *pkg;
+   struct {
+      unsigned int w, h;
+      Eina_Bool has_alpha;
+      unsigned char *raw;
+   } image_raw;
+} Elm_App_Server_Data;
+
+static Eina_Bool
+_view_del_cb(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   Elm_App_Server_Data *cdata = data;
+   eina_hash_del(cdata->views, NULL, obj);
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_view_append(Elm_App_Server_Data *data, Elm_App_Server_View *view)
+{
+   Eina_Stringshare *view_id;
+
+   eo_do(view, elm_app_server_view_id_get(&view_id));
+
+   if (eina_hash_find(data->views, view_id))
+     {
+        ERR("%p already have a view with id=%s", data->pkg, view_id);
+        eo_del(view);
+        return EINA_FALSE;
+     }
+
+   eina_hash_add(data->views, view_id, view);
+   eo_do(view, eo_event_callback_add(EO_EV_DEL, _view_del_cb, data));
+   return EINA_TRUE;
+}
+
+static Eldbus_Message *
+_method_create_view(const Eldbus_Service_Interface *iface, const Eldbus_Message *message)
+{
+   Eo *eo = eldbus_service_object_data_get(iface, MY_CLASS_NAME);
+   Elm_App_Server_Data *data = eo_data_scope_get(eo, MY_CLASS);
+   Eina_Value *args;
+   Eina_Stringshare *error_name, *error_message, *view_path;
+   Elm_App_Server_View *view;
+   Eldbus_Message *reply;
+
+   args = eldbus_message_to_eina_value(message);
+   if (!args)
+     return eldbus_message_error_new(message, ELM_APP_CLEINT_VIEW_OPEN_ERROR, "");
+
+   view = data->create_view_cb(eo, args, &error_name, &error_message);
+   eina_value_free(args);
+
+   if (!view)
+     {
+        reply = eldbus_message_error_new(message, error_name, error_message);
+        eina_stringshare_del(error_name);
+        eina_stringshare_del(error_message);
+        return reply;
+     }
+
+   if (!_view_append(data, view))
+     {
+        reply = eldbus_message_error_new(message,
+                                         ELM_APP_SERVER_VIEW_CREATE_DUPLICATE,
+                                         NULL);
+        return reply;
+     }
+   eo_do(view, elm_app_server_view_path_get(&view_path));
+
+   reply = eldbus_message_method_return_new(message);
+   eldbus_message_arguments_append(reply, "o", view_path);
+
+   return reply;
+}
+
+static void
+_close_all_views(Elm_App_Server_Data *data)
+{
+   Eina_Iterator *iter;
+   Elm_App_Server_View *view;
+   Eina_List *view_list = NULL;
+
+   /*
+    * need do this because hash will be modified when called
+    * elm_app_server_view_close()
+    */
+   iter = eina_hash_iterator_data_new(data->views);
+   EINA_ITERATOR_FOREACH(iter, view)
+     view_list = eina_list_append(view_list, view);
+   eina_iterator_free(iter);
+
+   EINA_LIST_FREE(view_list, view)
+     eo_do(view, elm_app_server_view_close());
+}
+
+static Eldbus_Message *
+_method_close_all_views(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *message EINA_UNUSED)
+{
+   Eo *eo = eldbus_service_object_data_get(iface, MY_CLASS_NAME);
+   Elm_App_Server_Data *data = eo_data_scope_get(eo, MY_CLASS);
+
+   _close_all_views(data);
+
+   return eldbus_message_method_return_new(message);
+}
+
+static Eldbus_Message *
+_method_terminate(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *message EINA_UNUSED)
+{
+   Eo *eo = eldbus_service_object_data_get(iface, MY_CLASS_NAME);
+
+   eo_do(eo, eo_event_callback_call(ELM_APP_SERVER_EV_TERMINATE, NULL, NULL));
+
+   return eldbus_message_method_return_new(message);
+}
+
+static const Eldbus_Method _methods[] = {
+   { "CreateView", ELDBUS_ARGS({"a{sv}", "arguments"}),
+     ELDBUS_ARGS({"o", "view_path"}), _method_create_view, 0 },
+   { "CloseAllViews", NULL, NULL, _method_close_all_views, 0},
+   { "Terminate", NULL, NULL, _method_terminate, 0 },
+   { NULL, NULL, NULL, NULL, 0 }
+};
+
+static Eina_Bool
+_prop_pid_get(const Eldbus_Service_Interface *iface, const char *propname EINA_UNUSED, Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg EINA_UNUSED, Eldbus_Message **error EINA_UNUSED)
+{
+   Eo *eo = eldbus_service_object_data_get(iface, MY_CLASS_NAME);
+   Elm_App_Server_Data *data = eo_data_scope_get(eo, MY_CLASS);
+
+   eldbus_message_iter_basic_append(iter, 'i', data->PID);
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_prop_title_get(const Eldbus_Service_Interface *iface, const char *propname EINA_UNUSED, Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg EINA_UNUSED, Eldbus_Message **error EINA_UNUSED)
+{
+   Eo *eo = eldbus_service_object_data_get(iface, MY_CLASS_NAME);
+   Elm_App_Server_Data *data = eo_data_scope_get(eo, MY_CLASS);
+
+   eldbus_message_iter_basic_append(iter, 's', data->title);
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_prop_icon_get(const Eldbus_Service_Interface *iface, const char *propname EINA_UNUSED, Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg EINA_UNUSED, Eldbus_Message **error EINA_UNUSED)
+{
+   Eo *eo = eldbus_service_object_data_get(iface, MY_CLASS_NAME);
+   Elm_App_Server_Data *data = eo_data_scope_get(eo, MY_CLASS);
+
+   eldbus_message_iter_basic_append(iter, 's', data->icon_name);
+   return EINA_TRUE;
+}
+
+/*static Eina_Bool
+_prop_icon_pixels_get(const Eldbus_Service_Interface *iface EINA_UNUSED, const char *propname EINA_UNUSED, Eldbus_Message_Iter *iter EINA_UNUSED, const Eldbus_Message *request_msg EINA_UNUSED, Eldbus_Message **error EINA_UNUSED)
+{
+   //TODO
+   return EINA_FALSE;
+}*/
+
+static const Eldbus_Property _props[] = {
+   { "PID", "i", _prop_pid_get, NULL, 0 },
+   { "Title", "s", _prop_title_get, NULL, 0 },
+   { "IconName", "s", _prop_icon_get, NULL, 0 },
+   //{ "IconPixels", "(uubay)", _prop_icon_pixels_get, NULL, 0 },
+   { NULL, NULL, NULL, NULL, 0 }
+};
+
+static const Eldbus_Service_Interface_Desc iface_desc = {
+   "org.enlightenment.Application1", _methods, NULL, _props, NULL, NULL
+};
+
+static void
+_app_server_constructor(Eo *obj, void *_pd, va_list *list)
+{
+   Elm_App_Server_Data *data = _pd;
+   const char *pkg = va_arg(*list, const char *);
+   char *path;
+   Elm_App_Server_Views_Eet *views_eet;
+   char buf[PATH_MAX];
+
+   data->create_view_cb = va_arg(*list, Elm_App_Server_Create_View_Cb);
+
+   EINA_SAFETY_ON_NULL_GOTO(data->create_view_cb, error);
+   EINA_SAFETY_ON_TRUE_GOTO(!pkg, error);
+
+   eo_do_super(obj, MY_CLASS, eo_constructor());
+
+   data->views = eina_hash_string_small_new(NULL);
+   data->PID = getpid();
+   data->title = eina_stringshare_add("");
+   data->icon_name = eina_stringshare_add("");
+   data->pkg = eina_stringshare_add(pkg);
+
+   path = _dbus_package_to_path(pkg);
+
+   eldbus_init();
+   data->conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SESSION);
+   eldbus_name_request(data->conn, pkg, 0, NULL, NULL);
+   data->iface = eldbus_service_interface_register(data->conn,
+                                                   path,
+                                                   &iface_desc);
+   eldbus_service_object_data_set(data->iface, MY_CLASS_NAME, obj);
+   eldbus_service_object_manager_attach(data->iface);
+
+   free(path);
+
+   //Check if there a saved list of views
+   app_server_views_eet_init();
+
+   _elm_config_user_dir_snprintf(buf, sizeof(buf), "apps/%s.eet",
+                                 data->pkg);
+   views_eet = elm_app_server_views_eet_load(buf);
+   if (views_eet)
+     {
+        Elm_App_Server_View_Props *view_eet_props;
+        Eina_List *l, *views_list;
+
+        views_list = elm_app_server_views_eet_views_entries_list_get(views_eet);
+        if (!views_list)
+          goto free_views_eet;
+
+        EINA_LIST_FOREACH(views_list, l, view_eet_props)
+          {
+             Elm_App_Server_View *view;
+             const char *view_id, *title, *icon_name;
+             int new_events;
+             short progress;
+
+             view_id = elm_app_server_view_props_id_get(view_eet_props);
+
+             if (eina_hash_find(data->views, view_id))
+               continue;
+             title = elm_app_server_view_props_title_get(view_eet_props);
+             icon_name = elm_app_server_view_props_icon_name_get(view_eet_props);
+             new_events = elm_app_server_view_props_new_events_get(view_eet_props);
+             progress = elm_app_server_view_props_progress_get(view_eet_props);
+
+             view = eo_add_custom(ELM_APP_SERVER_VIEW_CLASS, obj,
+                                  elm_app_server_view_constructor(view_id));
+             if (!view)
+               continue;
+
+             eo_do(view, elm_app_server_view_title_set(title),
+                   elm_app_server_view_icon_set(icon_name),
+                   elm_app_server_view_progress_set(progress),
+                   elm_app_server_view_new_events_set(new_events),
+                   eo_event_callback_add(EO_EV_DEL, _view_del_cb, data),
+                   elm_app_server_view_shallow());
+
+             eina_hash_add(data->views, view_id, view);
+          }
+
+free_views_eet:
+         elm_app_server_views_eet_free(views_eet);
+     }
+
+   app_server_views_eet_shutdown();
+
+   return;
+
+error:
+   eo_error_set(obj);
+}
+
+static void
+_save(Eo *obj EINA_UNUSED, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
+{
+   Elm_App_Server_Data *data = _pd;
+   Eina_Iterator *iter;
+   Elm_App_Server_View *view;
+   Elm_App_Server_Views_Eet *views_eet;
+   char buf[PATH_MAX];
+
+   app_server_views_eet_init();
+
+   views_eet = elm_app_server_views_eet_new(1, NULL);
+
+   iter = eina_hash_iterator_data_new(data->views);
+   EINA_ITERATOR_FOREACH(iter, view)
+     {
+        Elm_App_Server_View_Props *view_props;
+        const char *id, *title, *icon_name;
+        int new_events;
+        short progress;
+
+        eo_do(view, elm_app_server_view_id_get(&id),
+              elm_app_server_view_title_get(&title),
+              elm_app_server_view_icon_get(&icon_name),
+              elm_app_server_view_new_events_get(&new_events),
+              elm_app_server_view_progress_get(&progress),
+              eo_event_callback_call(ELM_APP_SERVER_VIEW_EV_SAVE, NULL, NULL));
+
+        view_props = elm_app_server_view_props_new(id, title, icon_name,
+                                                   new_events, progress);
+        elm_app_server_views_eet_views_entries_add(views_eet, view_props);
+     }
+   eina_iterator_free(iter);
+
+   _elm_config_user_dir_snprintf(buf, sizeof(buf), "apps/");
+   if (!ecore_file_is_dir(buf))
+     ecore_file_mkpath(buf);
+   _elm_config_user_dir_snprintf(buf, sizeof(buf), "apps/%s.eet", data->pkg);
+   elm_app_server_views_eet_save(views_eet, buf);
+   elm_app_server_views_eet_free(views_eet);
+   app_server_views_eet_shutdown();
+}
+
+static void
+_close_all(Eo *obj EINA_UNUSED, void *_pd, va_list *list EINA_UNUSED)
+{
+   Elm_App_Server_Data *data = _pd;
+   _close_all_views(data);
+}
+
+static void
+_view_check(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
+{
+   Elm_App_Server_Data *data = _pd;
+   const char *id = va_arg(*list, const char *);
+   Eina_Bool *ret = va_arg(*list, Eina_Bool *);
+   const char *ptr;
+
+   *ret = EINA_FALSE;
+   EINA_SAFETY_ON_NULL_RETURN(id);
+
+   for (ptr = id; *ptr; ptr++)
+     {
+        if (!isalnum(*ptr))
+          break;
+     }
+
+   if (!eina_hash_find(data->views, id))
+     *ret = EINA_TRUE;
+}
+
+static void
+_title_set(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
+{
+   Elm_App_Server_Data *data = _pd;
+   const char *title = va_arg(*list, const char *);
+
+   title = title ? title : "";
+
+   if (eina_stringshare_replace(&data->title, title))
+     eldbus_service_property_changed(data->iface, "Title");
+}
+
+static void
+_title_get(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
+{
+   Elm_App_Server_Data *data = _pd;
+   Eina_Stringshare **ret = va_arg(*list, Eina_Stringshare **);
+
+   *ret = data->title;
+}
+
+static void
+_icon_set(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
+{
+   Elm_App_Server_Data *data = _pd;
+   const char *icon = va_arg(*list, const char *);
+
+   icon = icon ? icon : "";
+
+   if (eina_stringshare_replace(&data->icon_name, icon))
+     eldbus_service_property_changed(data->iface, "IconName");
+}
+
+static void
+_icon_get(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
+{
+   Elm_App_Server_Data *data = _pd;
+   Eina_Stringshare **ret = va_arg(*list, Eina_Stringshare **);
+
+   *ret = data->icon_name;
+}
+
+static void
+_icon_pixels_set(Eo *obj EINA_UNUSED, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
+{
+   //TODO
+}
+
+static void
+_icon_pixels_get(Eo *obj EINA_UNUSED, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
+{
+   //TODO
+}
+
+static void
+_package_get(Eo *obj EINA_UNUSED, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
+{
+   Elm_App_Server_Data *data = _pd;
+   Eina_Stringshare **ret = va_arg(*list, Eina_Stringshare **);
+
+   *ret = data->pkg;
+}
+
+static void
+_views_get(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
+{
+   Elm_App_Server_Data *data = _pd;
+   Eina_Iterator **ret = va_arg(*list, Eina_Iterator **);
+
+   *ret = eina_hash_iterator_data_new(data->views);
+}
+
+static void
+_path_get(Eo *obj EINA_UNUSED, void *_pd EINA_UNUSED, va_list *list)
+{
+   Elm_App_Server_Data *data = _pd;
+   const char **path = va_arg(*list, const char **);
+
+   *path = eldbus_service_object_path_get(data->iface);
+}
+
+static void
+_view_add(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
+{
+   Elm_App_Server_Data *data = _pd;
+   Elm_App_Server_View *view = va_arg(*list, Elm_App_Server_View *);
+   _view_append(data, view);
+}
+
+static void
+_destructor(Eo *obj, void *_pd, va_list *list EINA_UNUSED)
+{
+   Elm_App_Server_Data *data = _pd;
+   Eina_Iterator *iter;
+   Elm_App_Server_View *view;
+
+   iter = eina_hash_iterator_data_new(data->views);
+   EINA_ITERATOR_FOREACH(iter, view)
+     {
+        //do not modify hash when iterating
+        eo_do(view, eo_event_callback_del(EO_EV_DEL, _view_del_cb, data));
+        eo_del(view);
+     }
+   eina_iterator_free(iter);
+   eina_hash_free(data->views);
+
+   eina_stringshare_del(data->title);
+   eina_stringshare_del(data->icon_name);
+   eina_stringshare_del(data->pkg);
+
+   eldbus_service_object_manager_detach(data->iface);
+   eldbus_service_interface_unregister(data->iface);
+   eldbus_connection_unref(data->conn);
+   eldbus_shutdown();
+   eo_do_super(obj, MY_CLASS, eo_destructor());
+}
+
+static void
+_constructor(Eo *obj, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
+{
+   eo_error_set(obj);
+   ERR("Only custom constructor can be used with '%s' class", MY_CLASS_NAME);
+}
+
+static void
+_class_constructor(Eo_Class *klass)
+{
+   const Eo_Op_Func_Description func_desc[] = {
+      EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_CONSTRUCTOR), _constructor),
+      EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_DESTRUCTOR), _destructor),
+      EO_OP_FUNC(ELM_APP_SERVER_ID(ELM_APP_SERVER_SUB_ID_CONSTRUCTOR),
+                 _app_server_constructor),
+      EO_OP_FUNC(ELM_APP_SERVER_ID(ELM_APP_SERVER_SUB_ID_SAVE), _save),
+      EO_OP_FUNC(ELM_APP_SERVER_ID(ELM_APP_SERVER_SUB_ID_CLOSE_ALL),
+                 _close_all),
+      EO_OP_FUNC(ELM_APP_SERVER_ID(ELM_APP_SERVER_SUB_ID_VIEW_CHECK),
+                 _view_check),
+      EO_OP_FUNC(ELM_APP_SERVER_ID(ELM_APP_SERVER_SUB_ID_TITLE_SET),
+                 _title_set),
+      EO_OP_FUNC(ELM_APP_SERVER_ID(ELM_APP_SERVER_SUB_ID_TITLE_GET),
+                 _title_get),
+      EO_OP_FUNC(ELM_APP_SERVER_ID(ELM_APP_SERVER_SUB_ID_ICON_SET), _icon_set),
+      EO_OP_FUNC(ELM_APP_SERVER_ID(ELM_APP_SERVER_SUB_ID_ICON_GET), _icon_get),
+      EO_OP_FUNC(ELM_APP_SERVER_ID(ELM_APP_SERVER_SUB_ID_ICON_PIXELS_SET),
+                 _icon_pixels_set),
+      EO_OP_FUNC(ELM_APP_SERVER_ID(ELM_APP_SERVER_SUB_ID_ICON_PIXELS_GET),
+                 _icon_pixels_get),
+      EO_OP_FUNC(ELM_APP_SERVER_ID(ELM_APP_SERVER_SUB_ID_PACKAGE_GET),
+                 _package_get),
+      EO_OP_FUNC(ELM_APP_SERVER_ID(ELM_APP_SERVER_SUB_ID_VIEWS_GET),
+                 _views_get),
+      EO_OP_FUNC(ELM_APP_SERVER_ID(ELM_APP_SERVER_SUB_ID_PATH_GET), _path_get),
+      EO_OP_FUNC(ELM_APP_SERVER_ID(ELM_APP_SERVER_SUB_ID_VIEW_ADD), _view_add),
+      EO_OP_FUNC_SENTINEL
+   };
+   eo_class_funcs_set(klass, func_desc);
+}
+
+static const Eo_Op_Description op_desc[] = {
+     EO_OP_DESCRIPTION(ELM_APP_SERVER_SUB_ID_CONSTRUCTOR,
+                       "Constructor of elm_app_server."),
+     EO_OP_DESCRIPTION(ELM_APP_SERVER_SUB_ID_SAVE,
+                       "Save current state of applications views."),
+     EO_OP_DESCRIPTION(ELM_APP_SERVER_SUB_ID_CLOSE_ALL, "Close all views."),
+     EO_OP_DESCRIPTION(ELM_APP_SERVER_SUB_ID_VIEW_CHECK,
+                       "Return the view dbus object path if id available."),
+     EO_OP_DESCRIPTION(ELM_APP_SERVER_SUB_ID_TITLE_SET,
+                       "Set title of application."),
+     EO_OP_DESCRIPTION(ELM_APP_SERVER_SUB_ID_TITLE_GET,
+                       "Get title of application."),
+     EO_OP_DESCRIPTION(ELM_APP_SERVER_SUB_ID_ICON_SET,
+                       "Set icon of applicaiton."),
+     EO_OP_DESCRIPTION(ELM_APP_SERVER_SUB_ID_ICON_GET,
+                       "Get icon of applicaiton."),
+     EO_OP_DESCRIPTION(ELM_APP_SERVER_SUB_ID_ICON_PIXELS_SET,
+                       "Set icon to application, using the raw pixels of image."),
+     EO_OP_DESCRIPTION(ELM_APP_SERVER_SUB_ID_ICON_PIXELS_GET,
+                       "Get application raw icon."),
+     EO_OP_DESCRIPTION(ELM_APP_SERVER_SUB_ID_PACKAGE_GET,
+                       "Get application package."),
+     EO_OP_DESCRIPTION(ELM_APP_SERVER_SUB_ID_VIEWS_GET,
+                       "Return iterator with all views of application."),
+     EO_OP_DESCRIPTION(ELM_APP_SERVER_SUB_ID_PATH_GET,
+                       "Get application DBus path."),
+     EO_OP_DESCRIPTION(ELM_APP_SERVER_SUB_ID_VIEW_ADD,
+                       "Add a view to application."),
+     EO_OP_DESCRIPTION_SENTINEL
+};
+
+static const Eo_Event_Description *event_desc[] = {
+     ELM_APP_SERVER_EV_TERMINATE,
+     NULL
+};
+
+static const Eo_Class_Description class_desc = {
+     EO_VERSION,
+     MY_CLASS_NAME,
+     EO_CLASS_TYPE_REGULAR,
+     EO_CLASS_DESCRIPTION_OPS(&ELM_APP_SERVER_BASE_ID, op_desc, ELM_APP_SERVER_SUB_ID_LAST),
+     event_desc,
+     sizeof(Elm_App_Server_Data),
+     _class_constructor,
+     NULL
+};
+
+EO_DEFINE_CLASS(elm_app_server_class_get, &class_desc, EO_BASE_CLASS, NULL);
diff --git a/src/lib/elm_app_server.h b/src/lib/elm_app_server.h
new file mode 100644 (file)
index 0000000..48ca221
--- /dev/null
@@ -0,0 +1,3 @@
+#ifdef EFL_EO_API_SUPPORT
+#include "elm_app_server_eo.h"
+#endif
diff --git a/src/lib/elm_app_server_eet.c b/src/lib/elm_app_server_eet.c
new file mode 100644 (file)
index 0000000..350ea58
--- /dev/null
@@ -0,0 +1,312 @@
+#include "elm_app_server_eet.h"
+
+struct _Elm_App_Server_View_Props {
+    const char * id;
+    const char * title;
+    const char * icon_name;
+    int new_events;
+    char progress;
+};
+
+struct _Elm_App_Server_Views_Eet {
+    unsigned int version;
+    Eina_List * views_entries;
+    const char *__eet_filename;
+};
+
+static const char ELM_APP_SERVER_VIEW_PROPS_ENTRY[] = "elm_app_server_view_props";
+static const char ELM_APP_SERVER_VIEWS_EET_ENTRY[] = "elm_app_server_views_eet";
+
+static Eet_Data_Descriptor *_elm_app_server_view_props_descriptor = NULL;
+static Eet_Data_Descriptor *_elm_app_server_views_eet_descriptor = NULL;
+
+static inline void
+_elm_app_server_view_props_init(void)
+{
+    Eet_Data_Descriptor_Class eddc;
+
+    if (_elm_app_server_view_props_descriptor) return;
+
+    EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Elm_App_Server_View_Props);
+    _elm_app_server_view_props_descriptor = eet_data_descriptor_stream_new(&eddc);
+
+    EET_DATA_DESCRIPTOR_ADD_BASIC(_elm_app_server_view_props_descriptor, Elm_App_Server_View_Props, "id", id, EET_T_STRING);
+    EET_DATA_DESCRIPTOR_ADD_BASIC(_elm_app_server_view_props_descriptor, Elm_App_Server_View_Props, "title", title, EET_T_STRING);
+    EET_DATA_DESCRIPTOR_ADD_BASIC(_elm_app_server_view_props_descriptor, Elm_App_Server_View_Props, "icon_name", icon_name, EET_T_STRING);
+    EET_DATA_DESCRIPTOR_ADD_BASIC(_elm_app_server_view_props_descriptor, Elm_App_Server_View_Props, "new_events", new_events, EET_T_INT);
+    EET_DATA_DESCRIPTOR_ADD_BASIC(_elm_app_server_view_props_descriptor, Elm_App_Server_View_Props, "progress", progress, EET_T_CHAR);
+}
+
+static inline void
+_elm_app_server_view_props_shutdown(void)
+{
+    if (!_elm_app_server_view_props_descriptor) return;
+    eet_data_descriptor_free(_elm_app_server_view_props_descriptor);
+    _elm_app_server_view_props_descriptor = NULL;
+}
+
+Elm_App_Server_View_Props *
+elm_app_server_view_props_new(const char * id, const char * title, const char * icon_name, int new_events, char progress)
+{
+    Elm_App_Server_View_Props *elm_app_server_view_props = calloc(1, sizeof(Elm_App_Server_View_Props));
+
+    if (!elm_app_server_view_props)
+       {
+          fprintf(stderr, "ERROR: could not calloc Elm_App_Server_View_Props\n");
+          return NULL;
+       }
+
+    elm_app_server_view_props->id = eina_stringshare_add(id ? id : "");
+    elm_app_server_view_props->title = eina_stringshare_add(title ? title : "");
+    elm_app_server_view_props->icon_name = eina_stringshare_add(icon_name ? icon_name : "");
+    elm_app_server_view_props->new_events = new_events;
+    elm_app_server_view_props->progress = progress;
+
+    return elm_app_server_view_props;
+}
+
+void
+elm_app_server_view_props_free(Elm_App_Server_View_Props *elm_app_server_view_props)
+{
+    eina_stringshare_del(elm_app_server_view_props->id);
+    eina_stringshare_del(elm_app_server_view_props->title);
+    eina_stringshare_del(elm_app_server_view_props->icon_name);
+    free(elm_app_server_view_props);
+}
+
+inline const char *
+elm_app_server_view_props_id_get(const Elm_App_Server_View_Props *elm_app_server_view_props)
+{
+    return elm_app_server_view_props->id;
+}
+
+inline void
+elm_app_server_view_props_id_set(Elm_App_Server_View_Props *elm_app_server_view_props, const char *id)
+{
+    EINA_SAFETY_ON_NULL_RETURN(elm_app_server_view_props);
+    eina_stringshare_replace(&(elm_app_server_view_props->id), id);
+}
+
+inline const char *
+elm_app_server_view_props_title_get(const Elm_App_Server_View_Props *elm_app_server_view_props)
+{
+    return elm_app_server_view_props->title;
+}
+
+inline void
+elm_app_server_view_props_title_set(Elm_App_Server_View_Props *elm_app_server_view_props, const char *title)
+{
+    EINA_SAFETY_ON_NULL_RETURN(elm_app_server_view_props);
+    eina_stringshare_replace(&(elm_app_server_view_props->title), title);
+}
+
+inline const char *
+elm_app_server_view_props_icon_name_get(const Elm_App_Server_View_Props *elm_app_server_view_props)
+{
+    return elm_app_server_view_props->icon_name;
+}
+
+inline void
+elm_app_server_view_props_icon_name_set(Elm_App_Server_View_Props *elm_app_server_view_props, const char *icon_name)
+{
+    EINA_SAFETY_ON_NULL_RETURN(elm_app_server_view_props);
+    eina_stringshare_replace(&(elm_app_server_view_props->icon_name), icon_name);
+}
+
+inline int
+elm_app_server_view_props_new_events_get(const Elm_App_Server_View_Props *elm_app_server_view_props)
+{
+    return elm_app_server_view_props->new_events;
+}
+
+inline void
+elm_app_server_view_props_new_events_set(Elm_App_Server_View_Props *elm_app_server_view_props, int new_events)
+{
+    EINA_SAFETY_ON_NULL_RETURN(elm_app_server_view_props);
+    elm_app_server_view_props->new_events = new_events;
+}
+
+inline char
+elm_app_server_view_props_progress_get(const Elm_App_Server_View_Props *elm_app_server_view_props)
+{
+    return elm_app_server_view_props->progress;
+}
+
+inline void
+elm_app_server_view_props_progress_set(Elm_App_Server_View_Props *elm_app_server_view_props, char progress)
+{
+    EINA_SAFETY_ON_NULL_RETURN(elm_app_server_view_props);
+    elm_app_server_view_props->progress = progress;
+}
+
+
+static inline void
+_elm_app_server_views_eet_init(void)
+{
+    Eet_Data_Descriptor_Class eddc;
+
+    if (_elm_app_server_views_eet_descriptor) return;
+
+    EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Elm_App_Server_Views_Eet);
+    _elm_app_server_views_eet_descriptor = eet_data_descriptor_stream_new(&eddc);
+
+    EET_DATA_DESCRIPTOR_ADD_BASIC(_elm_app_server_views_eet_descriptor, Elm_App_Server_Views_Eet, "version", version, EET_T_UINT);
+    EET_DATA_DESCRIPTOR_ADD_LIST(_elm_app_server_views_eet_descriptor, Elm_App_Server_Views_Eet, "views_entries", views_entries, _elm_app_server_view_props_descriptor);
+}
+
+static inline void
+_elm_app_server_views_eet_shutdown(void)
+{
+    if (!_elm_app_server_views_eet_descriptor) return;
+    eet_data_descriptor_free(_elm_app_server_views_eet_descriptor);
+    _elm_app_server_views_eet_descriptor = NULL;
+}
+
+Elm_App_Server_Views_Eet *
+elm_app_server_views_eet_new(unsigned int version, Eina_List * views_entries)
+{
+    Elm_App_Server_Views_Eet *elm_app_server_views_eet = calloc(1, sizeof(Elm_App_Server_Views_Eet));
+
+    if (!elm_app_server_views_eet)
+       {
+          fprintf(stderr, "ERROR: could not calloc Elm_App_Server_Views_Eet\n");
+          return NULL;
+       }
+
+    elm_app_server_views_eet->version = version;
+    elm_app_server_views_eet->views_entries = views_entries;
+
+    return elm_app_server_views_eet;
+}
+
+void
+elm_app_server_views_eet_free(Elm_App_Server_Views_Eet *elm_app_server_views_eet)
+{
+    if (elm_app_server_views_eet->views_entries)
+       {
+          Elm_App_Server_View_Props *views_entries_elem;
+          EINA_LIST_FREE(elm_app_server_views_eet->views_entries, views_entries_elem)
+             elm_app_server_view_props_free(views_entries_elem);
+       }
+    free(elm_app_server_views_eet);
+}
+
+inline unsigned int
+elm_app_server_views_eet_version_get(const Elm_App_Server_Views_Eet *elm_app_server_views_eet)
+{
+    return elm_app_server_views_eet->version;
+}
+
+inline void
+elm_app_server_views_eet_version_set(Elm_App_Server_Views_Eet *elm_app_server_views_eet, unsigned int version)
+{
+    EINA_SAFETY_ON_NULL_RETURN(elm_app_server_views_eet);
+    elm_app_server_views_eet->version = version;
+}
+
+inline void
+elm_app_server_views_eet_views_entries_add(Elm_App_Server_Views_Eet *elm_app_server_views_eet, Elm_App_Server_View_Props *elm_app_server_view_props)
+{
+    EINA_SAFETY_ON_NULL_RETURN(elm_app_server_views_eet);
+    elm_app_server_views_eet->views_entries = eina_list_append(elm_app_server_views_eet->views_entries, elm_app_server_view_props);
+}
+
+inline void
+elm_app_server_views_eet_views_entries_del(Elm_App_Server_Views_Eet *elm_app_server_views_eet, Elm_App_Server_View_Props *elm_app_server_view_props)
+{
+    EINA_SAFETY_ON_NULL_RETURN(elm_app_server_views_eet);
+    elm_app_server_views_eet->views_entries = eina_list_remove(elm_app_server_views_eet->views_entries, elm_app_server_view_props);
+}
+
+inline Elm_App_Server_View_Props *
+elm_app_server_views_eet_views_entries_get(const Elm_App_Server_Views_Eet *elm_app_server_views_eet, unsigned int nth)
+{
+    EINA_SAFETY_ON_NULL_RETURN_VAL(elm_app_server_views_eet, NULL);
+    return eina_list_nth(elm_app_server_views_eet->views_entries, nth);
+}
+
+inline unsigned int
+elm_app_server_views_eet_views_entries_count(const Elm_App_Server_Views_Eet *elm_app_server_views_eet)
+{
+    EINA_SAFETY_ON_NULL_RETURN_VAL(elm_app_server_views_eet, 0);
+    return eina_list_count(elm_app_server_views_eet->views_entries);
+}
+
+void
+elm_app_server_views_eet_views_entries_list_clear(Elm_App_Server_Views_Eet *elm_app_server_views_eet)
+{
+    EINA_SAFETY_ON_NULL_RETURN(elm_app_server_views_eet);
+    Elm_App_Server_View_Props *data;
+    EINA_LIST_FREE(elm_app_server_views_eet->views_entries, data) elm_app_server_view_props_free(data);
+}
+
+inline Eina_List *
+elm_app_server_views_eet_views_entries_list_get(const Elm_App_Server_Views_Eet *elm_app_server_views_eet)
+{
+    EINA_SAFETY_ON_NULL_RETURN_VAL(elm_app_server_views_eet, NULL);
+    return elm_app_server_views_eet->views_entries;
+}
+
+inline void
+elm_app_server_views_eet_views_entries_list_set(Elm_App_Server_Views_Eet *elm_app_server_views_eet, Eina_List *list)
+{
+    EINA_SAFETY_ON_NULL_RETURN(elm_app_server_views_eet);
+    elm_app_server_views_eet->views_entries = list;
+}
+
+Elm_App_Server_Views_Eet *
+elm_app_server_views_eet_load(const char *filename)
+{
+    Elm_App_Server_Views_Eet *elm_app_server_views_eet = NULL;
+    Eet_File *ef = eet_open(filename, EET_FILE_MODE_READ);
+    if (!ef)
+      {
+        fprintf(stderr, "ERROR: could not open '%s' for read\n", filename);
+        return NULL;
+      }
+
+    elm_app_server_views_eet = eet_data_read(ef, _elm_app_server_views_eet_descriptor, ELM_APP_SERVER_VIEWS_EET_ENTRY);
+    if (!elm_app_server_views_eet) goto end;
+    elm_app_server_views_eet->__eet_filename = eina_stringshare_add(filename);
+
+end:
+    eet_close(ef);
+    return elm_app_server_views_eet;
+}
+
+Eina_Bool
+elm_app_server_views_eet_save(Elm_App_Server_Views_Eet *elm_app_server_views_eet, const char *filename)
+{
+    Eet_File *ef;
+    Eina_Bool ret;
+
+    if (filename) eina_stringshare_replace(&(elm_app_server_views_eet->__eet_filename), filename);
+    else if (elm_app_server_views_eet->__eet_filename) filename = elm_app_server_views_eet->__eet_filename;
+    else return EINA_FALSE;
+
+    ef = eet_open(filename, EET_FILE_MODE_READ_WRITE);
+    if (!ef)
+       {
+          fprintf(stderr, "ERROR: could not open '%s' for write\n", filename);
+          return EINA_FALSE;
+       }
+
+    ret = !!eet_data_write(ef, _elm_app_server_views_eet_descriptor, ELM_APP_SERVER_VIEWS_EET_ENTRY, elm_app_server_views_eet, EINA_TRUE);
+    eet_close(ef);
+
+    return ret;
+}
+
+void
+app_server_views_eet_init(void)
+{
+    _elm_app_server_view_props_init();
+    _elm_app_server_views_eet_init();
+}
+
+void
+app_server_views_eet_shutdown(void)
+{
+    _elm_app_server_view_props_shutdown();
+    _elm_app_server_views_eet_shutdown();
+}
diff --git a/src/lib/elm_app_server_eet.h b/src/lib/elm_app_server_eet.h
new file mode 100644 (file)
index 0000000..8d35e5c
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef _ELM_APP_SERVER_EET_H_
+#define _ELM_APP_SERVER_EET_H_
+
+#include <Eina.h>
+#include <Eet.h>
+
+typedef struct _Elm_App_Server_View_Props Elm_App_Server_View_Props;
+typedef struct _Elm_App_Server_Views_Eet Elm_App_Server_Views_Eet;
+
+/* Elm_App_Server_View_Props */
+Elm_App_Server_View_Props *elm_app_server_view_props_new(const char * id, const char * title, const char * icon_name, int new_events, char progress);
+void elm_app_server_view_props_free(Elm_App_Server_View_Props *elm_app_server_view_props);
+
+void elm_app_server_view_props_id_set(Elm_App_Server_View_Props *elm_app_server_view_props, const char * id);
+const char * elm_app_server_view_props_id_get(const Elm_App_Server_View_Props *elm_app_server_view_props);
+void elm_app_server_view_props_title_set(Elm_App_Server_View_Props *elm_app_server_view_props, const char * title);
+const char * elm_app_server_view_props_title_get(const Elm_App_Server_View_Props *elm_app_server_view_props);
+void elm_app_server_view_props_icon_name_set(Elm_App_Server_View_Props *elm_app_server_view_props, const char * icon_name);
+const char * elm_app_server_view_props_icon_name_get(const Elm_App_Server_View_Props *elm_app_server_view_props);
+void elm_app_server_view_props_new_events_set(Elm_App_Server_View_Props *elm_app_server_view_props, int new_events);
+int elm_app_server_view_props_new_events_get(const Elm_App_Server_View_Props *elm_app_server_view_props);
+void elm_app_server_view_props_progress_set(Elm_App_Server_View_Props *elm_app_server_view_props, char progress);
+char elm_app_server_view_props_progress_get(const Elm_App_Server_View_Props *elm_app_server_view_props);
+
+/* Elm_App_Server_Views_Eet */
+Elm_App_Server_Views_Eet *elm_app_server_views_eet_new(unsigned int version, Eina_List * views_entries);
+void elm_app_server_views_eet_free(Elm_App_Server_Views_Eet *elm_app_server_views_eet);
+
+void elm_app_server_views_eet_version_set(Elm_App_Server_Views_Eet *elm_app_server_views_eet, unsigned int version);
+unsigned int elm_app_server_views_eet_version_get(const Elm_App_Server_Views_Eet *elm_app_server_views_eet);
+void elm_app_server_views_eet_views_entries_add(Elm_App_Server_Views_Eet *elm_app_server_views_eet, Elm_App_Server_View_Props *elm_app_server_view_props);
+void elm_app_server_views_eet_views_entries_del(Elm_App_Server_Views_Eet *elm_app_server_views_eet, Elm_App_Server_View_Props *elm_app_server_view_props);
+Elm_App_Server_View_Props *elm_app_server_views_eet_views_entries_get(const Elm_App_Server_Views_Eet *elm_app_server_views_eet, unsigned int nth);
+unsigned int elm_app_server_views_eet_views_entries_count(const Elm_App_Server_Views_Eet *elm_app_server_views_eet);
+Eina_List *elm_app_server_views_eet_views_entries_list_get(const Elm_App_Server_Views_Eet *elm_app_server_views_eet);
+void elm_app_server_views_eet_views_entries_list_clear(Elm_App_Server_Views_Eet *elm_app_server_views_eet);
+void elm_app_server_views_eet_views_entries_list_set(Elm_App_Server_Views_Eet *elm_app_server_views_eet, Eina_List *list);
+
+Elm_App_Server_Views_Eet *elm_app_server_views_eet_load(const char *filename);
+Eina_Bool elm_app_server_views_eet_save(Elm_App_Server_Views_Eet *elm_app_server_views_eet, const char *filename);
+
+/* Global initializer / shutdown functions */
+void app_server_views_eet_init(void);
+void app_server_views_eet_shutdown(void);
+
+#endif
diff --git a/src/lib/elm_app_server_eo.h b/src/lib/elm_app_server_eo.h
new file mode 100644 (file)
index 0000000..d474f10
--- /dev/null
@@ -0,0 +1,137 @@
+#define ELM_APP_SERVER_CLASS elm_app_server_class_get()
+
+const Eo_Class *elm_app_server_class_get(void) EINA_CONST;
+
+extern EAPI Eo_Op ELM_APP_SERVER_BASE_ID;
+
+#define ELM_APP_CLIENT_VIEW_OPEN_CANCELED "org.enlightenment.Application.ViewOpenCanceled"
+#define ELM_APP_CLIENT_VIEW_OPEN_TIMEOUT "org.enlightenment.Application.ViewOpenTimeout"
+#define ELM_APP_CLEINT_VIEW_OPEN_ERROR "org.enlightenment.Application.CouldNotCreateView"
+
+enum
+{
+   ELM_APP_SERVER_SUB_ID_CONSTRUCTOR,
+   ELM_APP_SERVER_SUB_ID_SAVE,
+   ELM_APP_SERVER_SUB_ID_CLOSE_ALL,
+   ELM_APP_SERVER_SUB_ID_VIEW_CHECK,
+   ELM_APP_SERVER_SUB_ID_TITLE_SET,
+   ELM_APP_SERVER_SUB_ID_TITLE_GET,
+   ELM_APP_SERVER_SUB_ID_ICON_SET,
+   ELM_APP_SERVER_SUB_ID_ICON_GET,
+   ELM_APP_SERVER_SUB_ID_ICON_PIXELS_SET,
+   ELM_APP_SERVER_SUB_ID_ICON_PIXELS_GET,
+   ELM_APP_SERVER_SUB_ID_PACKAGE_GET,
+   ELM_APP_SERVER_SUB_ID_VIEWS_GET,
+   ELM_APP_SERVER_SUB_ID_PATH_GET,
+   ELM_APP_SERVER_SUB_ID_VIEW_ADD,
+   ELM_APP_SERVER_SUB_ID_LAST
+};
+
+#define ELM_APP_SERVER_VIEW_CREATE_DUPLICATE "org.enlightenment.Application.ViewDuplicate"
+
+typedef Eo Elm_App_Server;
+typedef Eo Elm_App_Server_View;
+
+typedef Elm_App_Server_View *(*Elm_App_Server_Create_View_Cb)(Elm_App_Server *app, const Eina_Value *args, Eina_Stringshare **error_name, Eina_Stringshare **error_message);
+
+#define ELM_APP_SERVER_ID(sub_id) (ELM_APP_SERVER_BASE_ID + sub_id)
+
+/**
+ * @def elm_app_server_constructor
+ * @since 1.8
+ *
+ * Class constructor of elm_app_server
+ *
+ * @param[in] packageid package of application
+ * @param[in] create_view_cb callback to be called when user whants to
+ * open some application view
+ */
+#define elm_app_server_constructor(packageid, create_view_cb) ELM_APP_SERVER_ID(ELM_APP_SERVER_SUB_ID_CONSTRUCTOR), EO_TYPECHECK(const char *, packageid), EO_TYPECHECK(Elm_App_Server_Create_View_Cb, create_view_cb)
+
+/**
+ * @def elm_app_server_save
+ * @since 1.8
+ *
+ * Save the state of all views
+ */
+#define elm_app_server_save() ELM_APP_SERVER_ID(ELM_APP_SERVER_SUB_ID_SAVE)
+
+/**
+ * @def elm_app_server_close_all
+ * @since 1.8
+ *
+ * Close all views of application
+ */
+#define elm_app_server_close_all() ELM_APP_SERVER_ID(ELM_APP_SERVER_SUB_ID_CLOSE_ALL)
+
+/**
+ * @def elm_app_server_title_set
+ * @since 1.8
+ *
+ * Set a title to application.
+ *
+ * @param[in] title title of application
+ */
+#define elm_app_server_title_set(title) ELM_APP_SERVER_ID(ELM_APP_SERVER_SUB_ID_TITLE_SET), EO_TYPECHECK(const char *, title)
+
+/**
+ * @def elm_app_server_title_get
+ * @since 1.8
+ *
+ * Get title of application
+ *
+ * @param[out] ret title of application
+ */
+#define elm_app_server_title_get(ret) ELM_APP_SERVER_ID(ELM_APP_SERVER_SUB_ID_TITLE_GET), EO_TYPECHECK(Eina_Stringshare **, ret)
+
+#define elm_app_server_icon_set(icon) ELM_APP_SERVER_ID(ELM_APP_SERVER_SUB_ID_ICON_SET), EO_TYPECHECK(const char*, icon)
+
+#define elm_app_server_icon_get(ret) ELM_APP_SERVER_ID(ELM_APP_SERVER_SUB_ID_ICON_GET), EO_TYPECHECK(Eina_Stringshare **, ret)
+
+#define elm_app_server_icon_pixels_set(w, h, has_alpha, pixels) ELM_APP_SERVER_ID(ELM_APP_SERVER_SUB_ID_ICON_PIXELS_SET), EO_TYPECHECK(unsigned int, w), EO_TYPECHECK(unsigned int, h), EO_TYPECHECK(Eina_Bool, has_alpha), EO_TYPECHECK(const unsigned char *, pixels)
+
+#define elm_app_server_icon_pixels_get(w, h, has_alpha, pixels) ELM_APP_SERVER_ID(ELM_APP_SERVER_SUB_ID_ICON_PIXELS_GET), EO_TYPECHECK(unsigned int *, w), EO_TYPECHECK(unsigned int *, h), EO_TYPECHECK(Eina_Bool *, has_alpha), EO_TYPECHECK(const unsigned char **, pixels)
+
+#define elm_app_server_package_get(ret) ELM_APP_SERVER_ID(ELM_APP_SERVER_SUB_ID_PACKAGE_GET), EO_TYPECHECK(Eina_Stringshare **, ret)
+
+#define elm_app_server_path_get(ret) ELM_APP_SERVER_ID(ELM_APP_SERVER_SUB_ID_PATH_GET), EO_TYPECHECK(const char **, ret)
+
+/**
+ * @def elm_app_server_views_get
+ * @since 1.8
+ *
+ * Return a iterator with all views of application
+ *
+ * @param[out] ret Iterator with all views of application, you must free
+ * iterator after use.
+ */
+#define elm_app_server_views_get(ret) ELM_APP_SERVER_ID(ELM_APP_SERVER_SUB_ID_VIEWS_GET), EO_TYPECHECK(Eina_Iterator **, ret)
+
+/**
+ * @def elm_app_server_view_check
+ * @since 1.8
+ *
+ * If view id is available and unique, return the full DBus object path of view
+ *
+ * @param[in] id view identifier
+ * @param[out] ret EINA_TRUE if id is valid or EINA_FALSE if not
+ */
+#define elm_app_server_view_check(id, ret) ELM_APP_SERVER_ID(ELM_APP_SERVER_SUB_ID_VIEW_CHECK), EO_TYPECHECK(const char *, id), EO_TYPECHECK(Eina_Bool *, ret)
+
+/**
+ * @def elm_app_server_view_add
+ * @since 1.8
+ *
+ * Add a view to elm_app_server.
+ * This should only be used if the application open a view
+ * that was not requested by create_view_cb.
+ *
+ * @param[in] view elm_app_server_view
+ */
+#define elm_app_server_view_add(view) ELM_APP_SERVER_ID(ELM_APP_SERVER_SUB_ID_VIEW_ADD), EO_TYPECHECK(Elm_App_Server_View *, view)
+
+/**
+ * Events
+ */
+extern const Eo_Event_Description _ELM_APP_SERVER_EV_TERMINATE;
+#define ELM_APP_SERVER_EV_TERMINATE (&(_ELM_APP_SERVER_EV_TERMINATE))
diff --git a/src/lib/elm_app_server_view.c b/src/lib/elm_app_server_view.c
new file mode 100644 (file)
index 0000000..e734540
--- /dev/null
@@ -0,0 +1,526 @@
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+
+#include <Elementary.h>
+#include "elm_priv.h"
+
+EAPI Eo_Op ELM_APP_SERVER_VIEW_BASE_ID = EO_NOOP;
+
+#define MY_CLASS ELM_APP_SERVER_VIEW_CLASS
+
+#define MY_CLASS_NAME "elm_app_server_view"
+
+EAPI const Eo_Event_Description _ELM_APP_SERVER_VIEW_EV_RESUMED =
+         EO_EVENT_DESCRIPTION("resume", "Called when view must be resumed");
+
+EAPI const Eo_Event_Description _ELM_APP_SERVER_VIEW_EV_PAUSED =
+         EO_EVENT_DESCRIPTION("paused", "Called when view must be paused");
+
+EAPI const Eo_Event_Description _ELM_APP_SERVER_VIEW_EV_CLOSED =
+         EO_EVENT_DESCRIPTION("closed", "Called when view must be closed");
+
+EAPI const Eo_Event_Description _ELM_APP_SERVER_VIEW_EV_SHALLOW =
+         EO_EVENT_DESCRIPTION("shallow", "Called when view state is set to shallow");
+
+EAPI const Eo_Event_Description _ELM_APP_SERVER_VIEW_EV_SAVE =
+         EO_EVENT_DESCRIPTION("save", "Called when view state should be saved");
+
+typedef struct
+{
+   Eldbus_Connection *conn;
+   Eldbus_Service_Interface *iface;
+
+   Eina_Stringshare *id;
+   Eina_Stringshare *title;
+   Eina_Stringshare *icon_name;
+   int new_events;
+   short progress;
+   Elm_App_View_State state;
+   int window_id;
+   struct {
+      unsigned int w, h;
+      Eina_Bool has_alpha;
+      unsigned char *raw;
+   } image_raw;
+} Elm_App_Server_View_Data;
+
+static void
+_state_set(Elm_App_Server_View_Data *data, Elm_App_View_State state)
+{
+   if (data->state != state)
+     eldbus_service_property_changed(data->iface, "State");
+   data->state = state;
+}
+
+static Eldbus_Message *
+_method_close(const Eldbus_Service_Interface *iface, const Eldbus_Message *message)
+{
+   Eo *eo = eldbus_service_object_data_get(iface, MY_CLASS_NAME);
+   Elm_App_Server_View_Data *data = eo_data_scope_get(eo, MY_CLASS);
+
+   _state_set(data, ELM_APP_VIEW_STATE_CLOSED);
+   eo_do(eo, eo_event_callback_call(ELM_APP_SERVER_VIEW_EV_CLOSED, NULL, NULL));
+
+   return eldbus_message_method_return_new(message);
+}
+
+static Eldbus_Message *
+_method_pause(const Eldbus_Service_Interface *iface, const Eldbus_Message *message)
+{
+   Eo *eo = eldbus_service_object_data_get(iface, MY_CLASS_NAME);
+   Elm_App_Server_View_Data *data = eo_data_scope_get(eo, MY_CLASS);
+
+   _state_set(data, ELM_APP_VIEW_STATE_PAUSED);
+   eo_do(eo, eo_event_callback_call(ELM_APP_SERVER_VIEW_EV_PAUSED, NULL, NULL));
+
+   return eldbus_message_method_return_new(message);
+}
+
+static Eldbus_Message *
+_method_resume(const Eldbus_Service_Interface *iface, const Eldbus_Message *message)
+{
+   Eo *eo = eldbus_service_object_data_get(iface, MY_CLASS_NAME);
+   Elm_App_Server_View_Data *data = eo_data_scope_get(eo, MY_CLASS);
+
+   _state_set(data, ELM_APP_VIEW_STATE_LIVE);
+   eo_do(eo, eo_event_callback_call(ELM_APP_SERVER_VIEW_EV_RESUMED, NULL, NULL));
+
+   return eldbus_message_method_return_new(message);
+}
+
+static const Eldbus_Method _methods[] = {
+   { "Close", NULL, NULL, _method_close, 0 },
+   { "Pause", NULL, NULL, _method_pause, 0 },
+   { "Resume", NULL, NULL, _method_resume, 0 },
+   { NULL, NULL, NULL, NULL, 0 }
+};
+
+static Eina_Bool
+_prop_title_get(const Eldbus_Service_Interface *iface, const char *propname EINA_UNUSED, Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg EINA_UNUSED, Eldbus_Message **error EINA_UNUSED)
+{
+   Eo *eo = eldbus_service_object_data_get(iface, MY_CLASS_NAME);
+   Elm_App_Server_View_Data *data = eo_data_scope_get(eo, MY_CLASS);
+
+   eldbus_message_iter_basic_append(iter, 's', data->title);
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_prop_icon_get(const Eldbus_Service_Interface *iface, const char *propname EINA_UNUSED, Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg EINA_UNUSED, Eldbus_Message **error EINA_UNUSED)
+{
+   Eo *eo = eldbus_service_object_data_get(iface, MY_CLASS_NAME);
+   Elm_App_Server_View_Data *data = eo_data_scope_get(eo, MY_CLASS);
+
+   eldbus_message_iter_basic_append(iter, 's', data->icon_name);
+   return EINA_TRUE;
+}
+
+/*static Eina_Bool
+_prop_icon_pixels_get(const Eldbus_Service_Interface *iface, const char *propname EINA_UNUSED, Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg EINA_UNUSED, Eldbus_Message **error EINA_UNUSED)
+{
+   //TODO
+   return EINA_FALSE;
+}*/
+
+static Eina_Bool
+_prop_events_get(const Eldbus_Service_Interface *iface, const char *propname EINA_UNUSED, Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg EINA_UNUSED, Eldbus_Message **error EINA_UNUSED)
+{
+   Eo *eo = eldbus_service_object_data_get(iface, MY_CLASS_NAME);
+   Elm_App_Server_View_Data *data = eo_data_scope_get(eo, MY_CLASS);
+
+   eldbus_message_iter_basic_append(iter, 'i', data->new_events);
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_prop_progress_get(const Eldbus_Service_Interface *iface, const char *propname EINA_UNUSED, Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg EINA_UNUSED, Eldbus_Message **error EINA_UNUSED)
+{
+   Eo *eo = eldbus_service_object_data_get(iface, MY_CLASS_NAME);
+   Elm_App_Server_View_Data *data = eo_data_scope_get(eo, MY_CLASS);
+
+   eldbus_message_iter_basic_append(iter, 'n', data->progress);
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_prop_state_get(const Eldbus_Service_Interface *iface, const char *propname EINA_UNUSED, Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg EINA_UNUSED, Eldbus_Message **error EINA_UNUSED)
+{
+   Eo *eo = eldbus_service_object_data_get(iface, MY_CLASS_NAME);
+   Elm_App_Server_View_Data *data = eo_data_scope_get(eo, MY_CLASS);
+
+   eldbus_message_iter_basic_append(iter, 's', _state_id_to_string(data->state));
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_prop_window_get(const Eldbus_Service_Interface *iface, const char *propname EINA_UNUSED, Eldbus_Message_Iter *iter, const Eldbus_Message *request_msg EINA_UNUSED, Eldbus_Message **error EINA_UNUSED)
+{
+   Eo *eo = eldbus_service_object_data_get(iface, MY_CLASS_NAME);
+   Elm_App_Server_View_Data *data = eo_data_scope_get(eo, MY_CLASS);
+
+   eldbus_message_iter_basic_append(iter, 'i', data->window_id);
+   return EINA_TRUE;
+}
+
+static const Eldbus_Property _props[] = {
+   { "Title", "s", _prop_title_get, NULL, 0 },
+   { "IconName", "s", _prop_icon_get, NULL, 0 },
+   //{ "IconPixels", "(uubay)", _prop_icon_pixels_get, NULL, 0 },
+   { "NewEvents", "i", _prop_events_get, NULL, 0 },
+   { "Progress", "n", _prop_progress_get, NULL, 0 },
+   { "State", "s", _prop_state_get, NULL, 0 },
+   { "WindowId", "i", _prop_window_get, NULL, 0 },
+   { NULL, NULL, NULL, NULL, 0 }
+};
+
+static const Eldbus_Signal _signals[] = {
+   { "Result", ELDBUS_ARGS({"a{sv}", "arguments"}), 0 },
+   { NULL, NULL, 0}
+};
+
+static const Eldbus_Service_Interface_Desc iface_desc = {
+   "org.enlightenment.ApplicationView1", _methods, _signals, _props, NULL, NULL
+};
+
+static void
+_resume(Eo *obj, void *_pd, va_list *list EINA_UNUSED)
+{
+   Elm_App_Server_View_Data *data = _pd;
+
+   _state_set(data, ELM_APP_VIEW_STATE_LIVE);
+   eo_do(obj, eo_event_callback_call(ELM_APP_SERVER_VIEW_EV_RESUMED, NULL, NULL));
+}
+
+static void
+_pause(Eo *obj, void *_pd, va_list *list EINA_UNUSED)
+{
+   Elm_App_Server_View_Data *data = _pd;
+
+   _state_set(data, ELM_APP_VIEW_STATE_PAUSED);
+   eo_do(obj, eo_event_callback_call(ELM_APP_SERVER_VIEW_EV_PAUSED, NULL, NULL));
+}
+
+static void
+_close(Eo *obj, void *_pd, va_list *list EINA_UNUSED)
+{
+   Elm_App_Server_View_Data *data = _pd;
+
+   _state_set(data, ELM_APP_VIEW_STATE_CLOSED);
+   eo_do(obj, eo_event_callback_call(ELM_APP_SERVER_VIEW_EV_CLOSED, NULL, NULL));
+}
+
+static void
+_shallow(Eo *obj, void *_pd, va_list *list EINA_UNUSED)
+{
+   Elm_App_Server_View_Data *data = _pd;
+
+   _state_set(data, ELM_APP_VIEW_STATE_SHALLOW);
+   eo_do(obj, eo_event_callback_call(ELM_APP_SERVER_VIEW_EV_SHALLOW, NULL, NULL));
+}
+
+static void
+_state_get(Eo *obj EINA_UNUSED, void *_pd, va_list *list EINA_UNUSED)
+{
+   Elm_App_Server_View_Data *data = _pd;
+   Elm_App_View_State *ret = va_arg(*list, Elm_App_View_State *);
+   *ret = data->state;
+}
+
+static void
+_window_set(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
+{
+   Elm_App_Server_View_Data *data = _pd;
+   Evas_Object *win = va_arg(*list, Evas_Object *);
+   int before = data->window_id;
+
+   data->window_id = elm_win_window_id_get(win);
+
+   if (data->window_id != before)
+     eldbus_service_property_changed(data->iface, "WindowId");
+}
+
+static void
+_title_set(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
+{
+   Elm_App_Server_View_Data *data = _pd;
+   const char *title = va_arg(*list, const char *);
+
+   title = title ? title : "";
+
+   if (eina_stringshare_replace(&data->title, title))
+     eldbus_service_property_changed(data->iface, "Title");
+}
+
+static void
+_title_get(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
+{
+   Elm_App_Server_View_Data *data = _pd;
+   const char **ret = va_arg(*list, const char **);
+   *ret = data->title;
+}
+
+static void
+_icon_name_set(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
+{
+   Elm_App_Server_View_Data *data = _pd;
+   const char *icon = va_arg(*list, const char *);
+
+   icon = icon ? icon : "";
+
+   if (eina_stringshare_replace(&data->icon_name, icon))
+     eldbus_service_property_changed(data->iface, "IconName");
+}
+
+static void
+_icon_name_get(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
+{
+   Elm_App_Server_View_Data *data = _pd;
+   const char **ret = va_arg(*list, const char **);
+   *ret = data->icon_name;
+}
+
+static void
+_icon_pixels_set(Eo *obj EINA_UNUSED, void *_pd, va_list *list EINA_UNUSED)
+{
+   Elm_App_Server_View_Data *data = _pd;
+   //TODO
+   eldbus_service_property_changed(data->iface, "IconPixels");
+}
+
+static void
+_icon_pixels_get(Eo *obj EINA_UNUSED, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
+{
+   //TODO
+}
+
+static void
+_progress_set(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
+{
+   Elm_App_Server_View_Data *data = _pd;
+   short progress = va_arg(*list, int);
+
+   if (data->progress != progress)
+     eldbus_service_property_changed(data->iface, "Progress");
+   data->progress = progress;
+}
+
+static void
+_progress_get(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
+{
+   Elm_App_Server_View_Data *data = _pd;
+   short *ret = va_arg(*list, short *);
+
+   *ret = data->progress;
+}
+
+static void
+_new_events_set(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
+{
+   Elm_App_Server_View_Data *data = _pd;
+   int events = va_arg(*list, int);
+
+   if (data->new_events != events)
+     eldbus_service_property_changed(data->iface, "NewEvents");
+   data->new_events = events;
+}
+
+static void
+_new_events_get(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
+{
+   Elm_App_Server_View_Data *data = _pd;
+   int *ret = va_arg(*list, int *);
+
+   *ret = data->new_events;
+}
+
+static void
+_id_get(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
+{
+   Elm_App_Server_View_Data *data = _pd;
+   Eina_Stringshare **ret = va_arg(*list, Eina_Stringshare **);
+
+   *ret = data->id;
+}
+
+static void
+_path_get(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
+{
+   Elm_App_Server_View_Data *data = _pd;
+   const char **ret = va_arg(*list, const char **);
+
+   *ret = eldbus_service_object_path_get(data->iface);
+}
+
+static void
+_app_server_view_constructor(Eo *obj, void *_pd, va_list *list)
+{
+   Elm_App_Server_View_Data *data = _pd;
+   Elm_App_Server *server;
+   const char *id = va_arg(*list, const char *), *server_path;
+   char view_path[PATH_MAX];
+
+   eo_do_super(obj, MY_CLASS, eo_constructor());
+
+   server = eo_parent_get(obj);
+   EINA_SAFETY_ON_TRUE_GOTO(!server || !eo_isa(server, ELM_APP_SERVER_CLASS), error);
+
+   if (!id)
+     {
+        int i;
+        for (i = 1; i < 99999; i++)
+          {
+             char buf[64];
+             Eina_Bool valid;
+
+             snprintf(buf, sizeof(buf), "view_%d", i);
+             eo_do(server, elm_app_server_view_check(buf, &valid));
+             if (valid)
+               {
+                  data->id = eina_stringshare_add(buf);
+                  break;
+               }
+          }
+     }
+   else
+     {
+        Eina_Bool valid;
+        eo_do(server, elm_app_server_view_check(id, &valid));
+        if (valid)
+          data->id = eina_stringshare_add(id);
+     }
+
+   EINA_SAFETY_ON_NULL_GOTO(data->id, error);
+
+   eo_do(server, elm_app_server_path_get(&server_path));
+   snprintf(view_path, sizeof(view_path), "%s/%s", server_path, data->id);
+
+   eldbus_init();
+   data->conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SESSION);
+   data->iface = eldbus_service_interface_register(data->conn, view_path,
+                                                   &iface_desc);
+   eldbus_service_object_data_set(data->iface, MY_CLASS_NAME, obj);
+
+   data->state = ELM_APP_VIEW_STATE_UNKNOWN;
+   data->title = eina_stringshare_add("");
+   data->icon_name = eina_stringshare_add("");
+
+   return;
+
+error:
+   eo_error_set(obj);
+}
+
+static void
+_destructor(Eo *obj, void *_pd, va_list *list EINA_UNUSED)
+{
+   Elm_App_Server_View_Data *data = _pd;
+
+   eina_stringshare_del(data->title);
+   eina_stringshare_del(data->icon_name);
+
+   eina_stringshare_del(data->id);
+   eldbus_service_object_unregister(data->iface);
+   eldbus_connection_unref(data->conn);
+   eldbus_shutdown();
+
+   eo_do_super(obj, MY_CLASS, eo_destructor());
+}
+
+static void
+_constructor(Eo *obj, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
+{
+   eo_error_set(obj);
+   ERR("Only custom constructor can be used with '%s' class", MY_CLASS_NAME);
+}
+
+static void
+_class_constructor(Eo_Class *klass)
+{
+   const Eo_Op_Func_Description func_desc[] = {
+      EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_CONSTRUCTOR), _constructor),
+      EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_DESTRUCTOR), _destructor),
+      EO_OP_FUNC(ELM_APP_SERVER_VIEW_ID(ELM_APP_SERVER_VIEW_SUB_ID_CONSTRUCTOR), _app_server_view_constructor),
+      EO_OP_FUNC(ELM_APP_SERVER_VIEW_ID(ELM_APP_SERVER_VIEW_SUB_ID_RESUME), _resume),
+      EO_OP_FUNC(ELM_APP_SERVER_VIEW_ID(ELM_APP_SERVER_VIEW_SUB_ID_PAUSE), _pause),
+      EO_OP_FUNC(ELM_APP_SERVER_VIEW_ID(ELM_APP_SERVER_VIEW_SUB_ID_CLOSE), _close),
+      EO_OP_FUNC(ELM_APP_SERVER_VIEW_ID(ELM_APP_SERVER_VIEW_SUB_ID_SHALLOW), _shallow),
+      EO_OP_FUNC(ELM_APP_SERVER_VIEW_ID(ELM_APP_SERVER_VIEW_SUB_ID_STATE_GET), _state_get),
+      EO_OP_FUNC(ELM_APP_SERVER_VIEW_ID(ELM_APP_SERVER_VIEW_SUB_ID_WINDOW_SET), _window_set),
+      EO_OP_FUNC(ELM_APP_SERVER_VIEW_ID(ELM_APP_SERVER_VIEW_SUB_ID_TITLE_SET), _title_set),
+      EO_OP_FUNC(ELM_APP_SERVER_VIEW_ID(ELM_APP_SERVER_VIEW_SUB_ID_TITLE_GET), _title_get),
+      EO_OP_FUNC(ELM_APP_SERVER_VIEW_ID(ELM_APP_SERVER_VIEW_SUB_ID_ICON_NAME_SET), _icon_name_set),
+      EO_OP_FUNC(ELM_APP_SERVER_VIEW_ID(ELM_APP_SERVER_VIEW_SUB_ID_ICON_NAME_GET), _icon_name_get),
+      EO_OP_FUNC(ELM_APP_SERVER_VIEW_ID(ELM_APP_SERVER_VIEW_SUB_ID_ICON_PIXELS_SET), _icon_pixels_set),
+      EO_OP_FUNC(ELM_APP_SERVER_VIEW_ID(ELM_APP_SERVER_VIEW_SUB_ID_ICON_PIXELS_GET), _icon_pixels_get),
+      EO_OP_FUNC(ELM_APP_SERVER_VIEW_ID(ELM_APP_SERVER_VIEW_SUB_ID_PROGRESS_SET), _progress_set),
+      EO_OP_FUNC(ELM_APP_SERVER_VIEW_ID(ELM_APP_SERVER_VIEW_SUB_ID_PROGRESS_GET), _progress_get),
+      EO_OP_FUNC(ELM_APP_SERVER_VIEW_ID(ELM_APP_SERVER_VIEW_SUB_ID_NEW_EVENTS_SET), _new_events_set),
+      EO_OP_FUNC(ELM_APP_SERVER_VIEW_ID(ELM_APP_SERVER_VIEW_SUB_ID_NEW_EVENTS_GET), _new_events_get),
+      EO_OP_FUNC(ELM_APP_SERVER_VIEW_ID(ELM_APP_SERVER_VIEW_SUB_ID_ID_GET), _id_get),
+      EO_OP_FUNC(ELM_APP_SERVER_VIEW_ID(ELM_APP_SERVER_VIEW_SUB_ID_PATH_GET), _path_get),
+      EO_OP_FUNC_SENTINEL
+   };
+   eo_class_funcs_set(klass, func_desc);
+}
+
+static const Eo_Op_Description op_desc[] = {
+     EO_OP_DESCRIPTION(ELM_APP_SERVER_VIEW_SUB_ID_CONSTRUCTOR,
+                       "Constructor of elm_app_server_view."),
+     EO_OP_DESCRIPTION(ELM_APP_SERVER_VIEW_SUB_ID_RESUME, "Resume view."),
+     EO_OP_DESCRIPTION(ELM_APP_SERVER_VIEW_SUB_ID_PAUSE, "Pause view."),
+     EO_OP_DESCRIPTION(ELM_APP_SERVER_VIEW_SUB_ID_CLOSE, "Close view."),
+     EO_OP_DESCRIPTION(ELM_APP_SERVER_VIEW_SUB_ID_SHALLOW,
+                       "Shallow view, that means that view is open but dont have a window(X or Wayland)."),
+     EO_OP_DESCRIPTION(ELM_APP_SERVER_VIEW_SUB_ID_STATE_GET,
+                       "Get state of view."),
+     EO_OP_DESCRIPTION(ELM_APP_SERVER_VIEW_SUB_ID_WINDOW_SET,
+                       "Set window of view."),
+     EO_OP_DESCRIPTION(ELM_APP_SERVER_VIEW_SUB_ID_TITLE_SET,
+                       "Set title of view."),
+     EO_OP_DESCRIPTION(ELM_APP_SERVER_VIEW_SUB_ID_TITLE_GET,
+                       "Get title of view."),
+     EO_OP_DESCRIPTION(ELM_APP_SERVER_VIEW_SUB_ID_ICON_NAME_SET,
+                       "Set icon name or path of view."),
+     EO_OP_DESCRIPTION(ELM_APP_SERVER_VIEW_SUB_ID_ICON_NAME_GET,
+                       "Get icon name or path of view."),
+     EO_OP_DESCRIPTION(ELM_APP_SERVER_VIEW_SUB_ID_ICON_PIXELS_SET,
+                       "Set icon to view, using the raw pixels of image."),
+     EO_OP_DESCRIPTION(ELM_APP_SERVER_VIEW_SUB_ID_ICON_PIXELS_GET,
+                       "Get raw icon of view."),
+     EO_OP_DESCRIPTION(ELM_APP_SERVER_VIEW_SUB_ID_PROGRESS_SET,
+                       "Set progress of view."),
+     EO_OP_DESCRIPTION(ELM_APP_SERVER_VIEW_SUB_ID_PROGRESS_GET,
+                       "Get progress of view."),
+     EO_OP_DESCRIPTION(ELM_APP_SERVER_VIEW_SUB_ID_NEW_EVENTS_SET,
+                       "Set new events of view."),
+     EO_OP_DESCRIPTION(ELM_APP_SERVER_VIEW_SUB_ID_NEW_EVENTS_GET,
+                       "Get events of view."),
+     EO_OP_DESCRIPTION(ELM_APP_SERVER_VIEW_SUB_ID_ID_GET,
+                       "Get view identifier."),
+     EO_OP_DESCRIPTION(ELM_APP_SERVER_VIEW_SUB_ID_PATH_GET,
+                       "Get view DBus path."),
+     EO_OP_DESCRIPTION_SENTINEL
+};
+
+static const Eo_Event_Description *event_desc[] = {
+     ELM_APP_SERVER_VIEW_EV_RESUMED,
+     ELM_APP_SERVER_VIEW_EV_PAUSED,
+     ELM_APP_SERVER_VIEW_EV_CLOSED,
+     ELM_APP_SERVER_VIEW_EV_SHALLOW,
+     ELM_APP_SERVER_VIEW_EV_SAVE,
+     NULL
+};
+
+static const Eo_Class_Description class_desc = {
+     EO_VERSION,
+     MY_CLASS_NAME,
+     EO_CLASS_TYPE_REGULAR,
+     EO_CLASS_DESCRIPTION_OPS(&ELM_APP_SERVER_VIEW_BASE_ID, op_desc, ELM_APP_SERVER_VIEW_SUB_ID_LAST),
+     event_desc,
+     sizeof(Elm_App_Server_View_Data),
+     _class_constructor,
+     NULL
+};
+
+EO_DEFINE_CLASS(elm_app_server_view_class_get, &class_desc, EO_BASE_CLASS, NULL);
diff --git a/src/lib/elm_app_server_view.h b/src/lib/elm_app_server_view.h
new file mode 100644 (file)
index 0000000..9b6789e
--- /dev/null
@@ -0,0 +1,3 @@
+#ifdef EFL_EO_API_SUPPORT
+#include "elm_app_server_view_eo.h"
+#endif
diff --git a/src/lib/elm_app_server_view_eo.h b/src/lib/elm_app_server_view_eo.h
new file mode 100644 (file)
index 0000000..48ec32e
--- /dev/null
@@ -0,0 +1,97 @@
+#define ELM_APP_SERVER_VIEW_CLASS elm_app_server_view_class_get()
+
+const Eo_Class *elm_app_server_view_class_get(void) EINA_CONST;
+
+extern EAPI Eo_Op ELM_APP_SERVER_VIEW_BASE_ID;
+
+enum
+{
+   ELM_APP_SERVER_VIEW_SUB_ID_CONSTRUCTOR,
+   ELM_APP_SERVER_VIEW_SUB_ID_RESUME,
+   ELM_APP_SERVER_VIEW_SUB_ID_PAUSE,
+   ELM_APP_SERVER_VIEW_SUB_ID_CLOSE,
+   ELM_APP_SERVER_VIEW_SUB_ID_SHALLOW,
+   ELM_APP_SERVER_VIEW_SUB_ID_STATE_GET,
+   ELM_APP_SERVER_VIEW_SUB_ID_WINDOW_SET,
+   ELM_APP_SERVER_VIEW_SUB_ID_TITLE_SET,
+   ELM_APP_SERVER_VIEW_SUB_ID_TITLE_GET,
+   ELM_APP_SERVER_VIEW_SUB_ID_ICON_NAME_SET,
+   ELM_APP_SERVER_VIEW_SUB_ID_ICON_NAME_GET,
+   ELM_APP_SERVER_VIEW_SUB_ID_ICON_PIXELS_SET,
+   ELM_APP_SERVER_VIEW_SUB_ID_ICON_PIXELS_GET,
+   ELM_APP_SERVER_VIEW_SUB_ID_PROGRESS_SET,
+   ELM_APP_SERVER_VIEW_SUB_ID_PROGRESS_GET,
+   ELM_APP_SERVER_VIEW_SUB_ID_NEW_EVENTS_SET,
+   ELM_APP_SERVER_VIEW_SUB_ID_NEW_EVENTS_GET,
+   ELM_APP_SERVER_VIEW_SUB_ID_ID_GET,
+   ELM_APP_SERVER_VIEW_SUB_ID_PATH_GET,
+   ELM_APP_SERVER_VIEW_SUB_ID_LAST
+};
+
+#define ELM_APP_SERVER_VIEW_ID(sub_id) (ELM_APP_SERVER_VIEW_BASE_ID + sub_id)
+
+/**
+ * @def elm_app_server_view_constructor
+ * @since 1.8
+ *
+ * Class constructor of elm_app_server_view
+ *
+ * @param[in] id identifier of view
+ *
+ * @note You must supply the elm_app_server as parent.
+ */
+#define elm_app_server_view_constructor(id) ELM_APP_SERVER_VIEW_ID(ELM_APP_SERVER_VIEW_SUB_ID_CONSTRUCTOR), EO_TYPECHECK(const char *, id)
+
+#define elm_app_server_view_resume() ELM_APP_SERVER_VIEW_ID(ELM_APP_SERVER_VIEW_SUB_ID_RESUME)
+
+#define elm_app_server_view_pause() ELM_APP_SERVER_VIEW_ID(ELM_APP_SERVER_VIEW_SUB_ID_PAUSE)
+
+#define elm_app_server_view_close() ELM_APP_SERVER_VIEW_ID(ELM_APP_SERVER_VIEW_SUB_ID_CLOSE)
+
+#define elm_app_server_view_shallow() ELM_APP_SERVER_VIEW_ID(ELM_APP_SERVER_VIEW_SUB_ID_SHALLOW)
+
+#define elm_app_server_view_state_get(ret) ELM_APP_SERVER_VIEW_ID(ELM_APP_SERVER_VIEW_SUB_ID_STATE_GET), EO_TYPECHECK(Elm_App_View_State *, ret)
+
+#define elm_app_server_view_window_set(win) ELM_APP_SERVER_VIEW_ID(ELM_APP_SERVER_VIEW_SUB_ID_WINDOW_SET), EO_TYPECHECK(Evas_Object *, win)
+
+#define elm_app_server_view_title_set(title) ELM_APP_SERVER_VIEW_ID(ELM_APP_SERVER_VIEW_SUB_ID_TITLE_SET), EO_TYPECHECK(const char *, title)
+
+#define elm_app_server_view_title_get(ret) ELM_APP_SERVER_VIEW_ID(ELM_APP_SERVER_VIEW_SUB_ID_TITLE_GET), EO_TYPECHECK(const char **, ret)
+
+#define elm_app_server_view_icon_set(icon) ELM_APP_SERVER_VIEW_ID(ELM_APP_SERVER_VIEW_SUB_ID_ICON_NAME_SET), EO_TYPECHECK(const char *, icon)
+
+#define elm_app_server_view_icon_get(ret) ELM_APP_SERVER_VIEW_ID(ELM_APP_SERVER_VIEW_SUB_ID_ICON_NAME_GET), EO_TYPECHECK(const char **, ret)
+
+#define elm_app_server_view_icon_pixels_set(w, h, has_alpha, pixels) ELM_APP_SERVER_VIEW_ID(ELM_APP_SERVER_VIEW_ICON_PIXELS_SET), EO_TYPECHECK(unsigned int, w), EO_TYPE_CHECK(unsigned int, h), EO_TYPE_CHECK(Eina_Bool, has_alpha), EO_TYPE_CHECK(const unsigned char *, pixels)
+
+#define elm_app_server_view_icon_pixels_get(w, h, has_alpha, pixels) ELM_APP_SERVER_VIEW_ID(ELM_APP_SERVER_VIEW_ICON_PIXELS_GET), EO_TYPECHECK(unsigned int *, w), EO_TYPE_CHECK(unsigned int *, h), EO_TYPE_CHECK(Eina_Bool *, has_alpha), EO_TYPE_CHECK(const unsigned char **, pixels)
+
+#define elm_app_server_view_progress_set(progress) ELM_APP_SERVER_VIEW_ID(ELM_APP_SERVER_VIEW_SUB_ID_PROGRESS_SET), EO_TYPECHECK(short, progress)
+
+#define elm_app_server_view_progress_get(ret) ELM_APP_SERVER_VIEW_ID(ELM_APP_SERVER_VIEW_SUB_ID_PROGRESS_GET), EO_TYPECHECK(short *, ret)
+
+#define elm_app_server_view_new_events_set(events) ELM_APP_SERVER_VIEW_ID(ELM_APP_SERVER_VIEW_SUB_ID_NEW_EVENTS_SET), EO_TYPECHECK(int, events)
+
+#define elm_app_server_view_new_events_get(ret) ELM_APP_SERVER_VIEW_ID(ELM_APP_SERVER_VIEW_SUB_ID_NEW_EVENTS_GET), EO_TYPECHECK(int *, ret)
+
+#define elm_app_server_view_id_get(ret) ELM_APP_SERVER_VIEW_ID(ELM_APP_SERVER_VIEW_SUB_ID_ID_GET), EO_TYPECHECK(Eina_Stringshare **, ret)
+
+#define elm_app_server_view_path_get(ret) ELM_APP_SERVER_VIEW_ID(ELM_APP_SERVER_VIEW_SUB_ID_PATH_GET), EO_TYPECHECK(const char **, ret)
+
+/**
+ * Events
+ */
+extern const Eo_Event_Description _ELM_APP_SERVER_VIEW_EV_RESUMED;
+#define ELM_APP_SERVER_VIEW_EV_RESUMED (&(_ELM_APP_SERVER_VIEW_EV_RESUMED))
+
+extern const Eo_Event_Description _ELM_APP_SERVER_VIEW_EV_PAUSED;
+#define ELM_APP_SERVER_VIEW_EV_PAUSED (&(_ELM_APP_SERVER_VIEW_EV_PAUSED))
+
+extern const Eo_Event_Description _ELM_APP_SERVER_VIEW_EV_CLOSED;
+#define ELM_APP_SERVER_VIEW_EV_CLOSED (&(_ELM_APP_SERVER_VIEW_EV_CLOSED))
+
+extern const Eo_Event_Description _ELM_APP_SERVER_VIEW_EV_SHALLOW;
+#define ELM_APP_SERVER_VIEW_EV_SHALLOW (&(_ELM_APP_SERVER_VIEW_EV_SHALLOW))
+
+extern const Eo_Event_Description _ELM_APP_SERVER_VIEW_EV_SAVE;
+#define ELM_APP_SERVER_VIEW_EV_SAVE (&(_ELM_APP_SERVER_VIEW_EV_SAVE))