Add missing files vs @64925
authorMike McCormack <mj.mccormack@samsung.com>
Tue, 8 Nov 2011 07:38:30 +0000 (16:38 +0900)
committerMike McCormack <mj.mccormack@samsung.com>
Tue, 8 Nov 2011 09:46:02 +0000 (18:46 +0900)
14 files changed:
src/bin/test_factory.c [new file with mode: 0644]
src/bin/test_icon_animated.c [new file with mode: 0644]
src/bin/test_web.c [new file with mode: 0644]
src/edje_externals/elm_actionslider.c [new file with mode: 0644]
src/edje_externals/elm_frame.c [new file with mode: 0644]
src/edje_externals/elm_video.c [new file with mode: 0644]
src/edje_externals/elm_web.c [new file with mode: 0644]
src/lib/elm_access.c [new file with mode: 0644]
src/lib/elm_gen.c [new file with mode: 0644]
src/lib/elm_gen.h [new file with mode: 0644]
src/lib/elm_web.c [new file with mode: 0644]
src/lib/elu_ews_wm.c [new file with mode: 0644]
src/modules/access_output/Makefile.am [new file with mode: 0644]
src/modules/access_output/mod.c [new file with mode: 0644]

diff --git a/src/bin/test_factory.c b/src/bin/test_factory.c
new file mode 100644 (file)
index 0000000..a6e96eb
--- /dev/null
@@ -0,0 +1,189 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+
+// 16 ^ 4 = 65k
+#define BLOK 16
+// homogenous layout
+//#define HOMOG 1
+// aligned to top of box
+#define ZEROALIGN 1
+#define DEFSZ 64
+
+static void
+fac_unrealize(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   // setting factory content to null deletes it
+   printf("--------DELETE for factory %p [f: %p]\n", elm_object_content_get(obj), obj);
+   elm_object_content_set(obj, NULL);
+}
+
+static void
+fac_realize_end(void *data, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Evas_Object *win = data;
+   Evas_Object *bx, *bt;
+   int i;
+
+   bx = elm_box_add(win);
+   printf("   ADD lv 3 = %p [%i]\n", bx, (BLOK * (int)evas_object_data_get(obj, "num")));
+#ifdef HOMOG
+   elm_box_homogeneous_set(bx, EINA_TRUE);
+#endif
+#ifdef ZEROALIGN
+   elm_box_align_set(bx, 0.0, 0.0);
+#endif
+
+   for (i = 0; i < BLOK; i++)
+     {
+        char buf[32];
+
+        snprintf(buf, sizeof(buf), "%i",
+                 (i + (BLOK * (int)evas_object_data_get(obj, "num"))));
+
+        bt = elm_button_add(win);
+        evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+        evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+        elm_object_text_set(bt, buf);
+        elm_box_pack_end(bx, bt);
+        evas_object_show(bt);
+     }
+
+   elm_object_content_set(obj, bx);
+   evas_object_show(bx);
+}
+
+static void
+fac_realize2(void *data, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Evas_Object *win = data;
+   Evas_Object *bx, *fc;
+   int i;
+
+   bx = elm_box_add(win);
+   printf("  ADD lv 2 = %p [%i]\n", bx, (BLOK * (int)evas_object_data_get(obj, "num")));
+#ifdef HOMOG
+   elm_box_homogeneous_set(bx, EINA_TRUE);
+#endif
+#ifdef ZEROALIGN
+   elm_box_align_set(bx, 0.0, 0.0);
+#endif
+
+   for (i = 0; i < BLOK; i++)
+     {
+        fc = elm_factory_add(win);
+        elm_factory_maxmin_mode_set(fc, EINA_TRUE);
+        // initial height per factory of DEFSZ
+        // scrollbar will be wrong until enough
+        // children have been realized and the
+        // real size is known
+        evas_object_data_set(fc, "num", (void *)(i + (BLOK * (int)evas_object_data_get(obj, "num"))));
+        evas_object_size_hint_min_set(fc, 0, DEFSZ);
+        evas_object_size_hint_weight_set(fc, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+        evas_object_size_hint_align_set(fc, EVAS_HINT_FILL, EVAS_HINT_FILL);
+        evas_object_smart_callback_add(fc, "realize", fac_realize_end, win);
+        evas_object_smart_callback_add(fc, "unrealize", fac_unrealize, win);
+        elm_box_pack_end(bx, fc);
+        evas_object_show(fc);
+     }
+
+   elm_object_content_set(obj, bx);
+   evas_object_show(bx);
+}
+
+static void
+fac_realize1(void *data, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Evas_Object *win = data;
+   Evas_Object *bx, *fc;
+   int i;
+
+   bx = elm_box_add(win);
+   printf(" ADD lv 1 = %p [%i]\n", bx, (BLOK * (int)evas_object_data_get(obj, "num")));
+#ifdef HOMOG
+   elm_box_homogeneous_set(bx, EINA_TRUE);
+#endif
+#ifdef ZEROALIGN
+   elm_box_align_set(bx, 0.0, 0.0);
+#endif
+
+   for (i = 0; i < BLOK; i++)
+     {
+        fc = elm_factory_add(win);
+        elm_factory_maxmin_mode_set(fc, EINA_TRUE);
+        // initial height per factory of DEFSZ
+        // scrollbar will be wrong until enough
+        // children have been realized and the
+        // real size is known
+        evas_object_data_set(fc, "num", (void *)(i + (BLOK * (int)evas_object_data_get(obj, "num"))));
+        evas_object_size_hint_min_set(fc, 0, DEFSZ);
+        evas_object_size_hint_weight_set(fc, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+        evas_object_size_hint_align_set(fc, EVAS_HINT_FILL, EVAS_HINT_FILL);
+        evas_object_smart_callback_add(fc, "realize", fac_realize2, win);
+//        evas_object_smart_callback_add(fc, "unrealize", fac_unrealize, win);
+        elm_box_pack_end(bx, fc);
+        evas_object_show(fc);
+     }
+
+   elm_object_content_set(obj, bx);
+   evas_object_show(bx);
+}
+
+void
+test_factory(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *sc, *fc;
+   int i;
+
+   win = elm_win_add(NULL, "factory", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Factory");
+   elm_win_autodel_set(win, EINA_TRUE);
+
+   bg = elm_bg_add(win);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bg);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+#ifdef HOMOG
+   elm_box_homogeneous_set(bx, EINA_TRUE);
+#endif
+#ifdef ZEROALIGN
+   elm_box_align_set(bx, 0.0, 0.0);
+#endif
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, 0.0);
+
+   for (i = 0; i < BLOK; i++)
+     {
+        fc = elm_factory_add(win);
+        elm_factory_maxmin_mode_set(fc, EINA_TRUE);
+        // initial height per factory of DEFSZ
+        // scrollbar will be wrong until enough
+        // children have been realized and the
+        // real size is known
+        evas_object_data_set(fc, "num", (void *)i);
+        evas_object_size_hint_min_set(fc, 0, DEFSZ);
+        evas_object_size_hint_weight_set(fc, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+        evas_object_size_hint_align_set(fc, EVAS_HINT_FILL, EVAS_HINT_FILL);
+        evas_object_smart_callback_add(fc, "realize", fac_realize1, win);
+//        evas_object_smart_callback_add(fc, "unrealize", fac_unrealize, win);
+        elm_box_pack_end(bx, fc);
+        evas_object_show(fc);
+     }
+
+   sc = elm_scroller_add(win);
+   elm_scroller_bounce_set(sc, EINA_FALSE, EINA_TRUE);
+   evas_object_size_hint_weight_set(sc, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, sc);
+
+   elm_object_content_set(sc, bx);
+   evas_object_show(bx);
+
+   evas_object_show(sc);
+
+   evas_object_resize(win, 320, 480);
+   evas_object_show(win);
+}
+#endif
diff --git a/src/bin/test_icon_animated.c b/src/bin/test_icon_animated.c
new file mode 100644 (file)
index 0000000..d970f90
--- /dev/null
@@ -0,0 +1,49 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+static void
+icon_clicked(void *data , Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *ic;
+   ic = data;
+   Eina_Bool rec;
+   rec = elm_icon_animated_play_get(ic);
+   rec = !rec;
+   printf("clicked!rec =%d\n",rec);
+   elm_icon_animated_play_set(ic, rec);
+}
+
+void
+test_icon_animated(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *ic;
+   char buf[PATH_MAX];
+
+   win = elm_win_add(NULL, "icon-animated-gif", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Icon Animated Gif");
+   elm_win_autodel_set(win, EINA_TRUE);
+   elm_win_alpha_set(win, 1);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/animated_logo.gif", elm_app_data_dir_get());
+   elm_icon_file_set(ic, buf, NULL);
+   if (elm_icon_animated_available_get(ic))
+     {
+        printf("============Support animator==============\n");
+        elm_icon_animated_set(ic, EINA_TRUE);
+        elm_icon_animated_play_set(ic, EINA_TRUE);
+     }
+   elm_icon_scale_set(ic, 0, 0);
+   elm_icon_no_scale_set(ic, 1);
+   evas_object_size_hint_weight_set(ic, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_fill_set(ic, 0.5, 0.5);
+   elm_win_resize_object_add(win, ic);
+   evas_object_show(ic);
+
+   evas_object_smart_callback_add(ic, "clicked", icon_clicked, ic);
+
+   evas_object_show(win);
+}
+#endif
diff --git a/src/bin/test_web.c b/src/bin/test_web.c
new file mode 100644 (file)
index 0000000..7dbf45d
--- /dev/null
@@ -0,0 +1,484 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+
+typedef struct
+{
+   Evas_Object *web;
+   Evas_Object *btn_back;
+   Evas_Object *btn_fwd;
+   Evas_Object *url_entry;
+   Eina_List *sub_wins;
+   Eina_Bool js_hooks : 1;
+} Web_Test;
+
+static void
+_btn_back_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *web = data;
+
+   elm_web_back(web);
+}
+
+static void
+_btn_fwd_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *web = data;
+
+   elm_web_forward(web);
+}
+
+static void
+_btn_reload_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *web = data;
+
+   elm_web_reload(web);
+}
+
+static void
+_url_change_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Evas_Object *web = data;
+   const char *uri = elm_object_text_get(obj);
+
+   elm_web_uri_set(web, uri);
+}
+
+static void
+_toggle_inwin_mode_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   elm_web_inwin_mode_set(data, !elm_web_inwin_mode_get(data));
+}
+
+static void
+_title_changed_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   char buf[512];
+   snprintf(buf, sizeof(buf), "Web - %s", (const char *)event_info);
+   elm_win_title_set(data, buf);
+}
+
+static void
+_uri_changed_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Web_Test *wt = data;
+
+   elm_entry_entry_set(wt->url_entry, event_info);
+
+   elm_object_disabled_set(wt->btn_back, !elm_web_back_possible(wt->web));
+   elm_object_disabled_set(wt->btn_fwd, !elm_web_forward_possible(wt->web));
+}
+
+static void
+_new_win_del_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Web_Test *wt = data;
+   wt->sub_wins = eina_list_remove(wt->sub_wins, obj);
+}
+
+static void
+_web_win_close_request_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   evas_object_del(data);
+}
+
+static Evas_Object *
+_new_window_hook(void *data, Evas_Object *obj __UNUSED__, Eina_Bool js __UNUSED__, const Elm_Web_Window_Features *wf __UNUSED__)
+{
+   Web_Test *wt = data;
+   Evas_Object *new_win, *new_web, *bg;
+
+   new_win = elm_win_add(NULL, "elm-web-test-popup", ELM_WIN_BASIC);
+   elm_win_autodel_set(new_win, EINA_TRUE);
+   evas_object_resize(new_win, 300, 300);
+   evas_object_show(new_win);
+
+   bg = elm_bg_add(new_win);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(new_win, bg);
+   evas_object_show(bg);
+
+   new_web = elm_web_add(new_win);
+   evas_object_size_hint_weight_set(new_web, EVAS_HINT_EXPAND,
+                                    EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(new_win, new_web);
+   evas_object_show(new_web);
+
+   evas_object_smart_callback_add(new_win, "delete,request", _new_win_del_cb,
+                                  wt);
+   evas_object_smart_callback_add(new_web, "windows,close,request",
+                                  _web_win_close_request_cb, new_win);
+   wt->sub_wins = eina_list_append(wt->sub_wins, new_win);
+
+   return new_web;
+}
+
+static void
+_alert_del(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   evas_object_del(obj);
+}
+
+static Evas_Object *
+_alert_hook(void *data __UNUSED__, Evas_Object *obj, const char *message)
+{
+   Evas_Object *popup, *label;
+
+   popup = elm_notify_add(obj);
+   elm_notify_orient_set(popup, ELM_NOTIFY_ORIENT_CENTER);
+   // Using the timeout doesn't seem to go well with the second main loop
+   //elm_notify_timeout_set(popup, 2.0);
+   elm_notify_repeat_events_set(popup, EINA_FALSE);
+   evas_object_show(popup);
+
+   evas_object_smart_callback_add(popup, "block,clicked", _alert_del, NULL);
+
+   label = elm_label_add(obj);
+   elm_object_text_set(label, message);
+   elm_object_content_set(popup, label);
+   evas_object_show(label);
+
+   return popup;
+}
+
+static void
+_confirm_ok_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Eina_Bool *response = data;
+   *response = EINA_TRUE;
+}
+
+static void
+_confirm_cancel_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Eina_Bool *response = data;
+   *response = EINA_FALSE;
+}
+
+static void
+_confirm_dismiss_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   evas_object_del(data);
+}
+
+static Evas_Object *
+_confirm_hook(void *data __UNUSED__, Evas_Object *obj, const char *message, Eina_Bool *response)
+{
+   Evas_Object *popup, *box, *box2, *label, *btn_ok, *btn_cancel;
+
+   popup = elm_notify_add(obj);
+   elm_notify_orient_set(popup, ELM_NOTIFY_ORIENT_CENTER);
+   elm_notify_repeat_events_set(popup, EINA_FALSE);
+   evas_object_show(popup);
+
+   box = elm_box_add(obj);
+   elm_object_content_set(popup, box);
+   evas_object_show(box);
+
+   label = elm_label_add(obj);
+   elm_object_text_set(label, message);
+   elm_box_pack_end(box, label);
+   evas_object_show(label);
+
+   box2 = elm_box_add(obj);
+   elm_box_horizontal_set(box2, EINA_TRUE);
+   elm_box_pack_end(box, box2);
+   evas_object_show(box2);
+
+   btn_ok = elm_button_add(obj);
+   elm_object_text_set(btn_ok, "Ok");
+   elm_box_pack_end(box2, btn_ok);
+   evas_object_show(btn_ok);
+
+   btn_cancel = elm_button_add(obj);
+   elm_object_text_set(btn_cancel, "Cancel");
+   elm_box_pack_end(box2, btn_cancel);
+   evas_object_show(btn_cancel);
+
+   evas_object_smart_callback_add(btn_ok, "clicked", _confirm_dismiss_cb,
+                                  popup);
+   evas_object_smart_callback_add(btn_cancel, "clicked", _confirm_dismiss_cb,
+                                  popup);
+   evas_object_smart_callback_add(btn_ok, "clicked", _confirm_ok_cb, response);
+   evas_object_smart_callback_add(btn_cancel, "clicked", _confirm_cancel_cb,
+                                  response);
+
+   return popup;
+}
+
+static Evas_Object *
+_prompt_hook(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const char *message __UNUSED__, const char *default_value, char **value, Eina_Bool *response)
+{
+   *response = EINA_TRUE;
+   *value = default_value ? strdup(default_value) : "No default!";
+   return NULL;
+}
+
+static Evas_Object *
+_file_selector_hook(void *data __UNUSED__, Evas_Object *obj __UNUSED__, Eina_Bool allow_multiple __UNUSED__, Eina_List *accept_types __UNUSED__, Eina_List **selected_files, Eina_Bool *response)
+{
+   *selected_files = eina_list_append(NULL,
+                                      strdup("/path/to/non_existing_file"));
+   *response = EINA_TRUE;
+   return NULL;
+}
+
+static void
+_console_message_hook(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const char *message, unsigned int line_number, const char *source_id)
+{
+   printf("CONSOLE: %s:%d:%s\n", source_id, line_number, message);
+}
+
+static void
+_js_popup_hooks_set(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Web_Test *wt = data;
+
+   wt->js_hooks = !wt->js_hooks;
+   if (wt->js_hooks)
+     {
+        elm_web_dialog_alert_hook_set(wt->web, _alert_hook, NULL);
+        elm_web_dialog_confirm_hook_set(wt->web, _confirm_hook, NULL);
+        elm_web_dialog_prompt_hook_set(wt->web, _prompt_hook, NULL);
+        elm_web_dialog_file_selector_hook_set(wt->web, _file_selector_hook,
+                                              NULL);
+        elm_web_console_message_hook_set(wt->web, _console_message_hook, NULL);
+     }
+   else
+     {
+        elm_web_dialog_alert_hook_set(wt->web, NULL, NULL);
+        elm_web_dialog_confirm_hook_set(wt->web, NULL, NULL);
+        elm_web_dialog_prompt_hook_set(wt->web, NULL, NULL);
+        elm_web_dialog_file_selector_hook_set(wt->web, NULL, NULL);
+        elm_web_console_message_hook_set(wt->web, NULL, NULL);
+     }
+}
+
+static void
+_zoom_out_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Web_Test *wt = data;
+   double zoom;
+
+   zoom = elm_web_zoom_get(wt->web);
+   if (zoom > 1)
+     zoom -= .5;
+   else
+     zoom /= 2;
+   if (zoom < .05)
+     zoom = .05;
+   elm_web_zoom_set(wt->web, zoom);
+}
+
+static void
+_zoom_in_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Web_Test *wt = data;
+   double zoom;
+
+   zoom = elm_web_zoom_get(wt->web);
+
+   if (zoom < 1)
+     zoom *= 2;
+   else
+     zoom += .5;
+   if (zoom > 4)
+     zoom = 4;
+   elm_web_zoom_set(wt->web, zoom);
+}
+
+static void
+_zoom_mode_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Web_Test *wt = data;
+   Elm_Hoversel_Item *it = event_info;
+   const char *lbl = elm_hoversel_item_label_get(it);
+
+   if (!strcmp(lbl, "Manual"))
+     elm_web_zoom_mode_set(wt->web, ELM_WEB_ZOOM_MODE_MANUAL);
+   else if (!strcmp(lbl, "Fit"))
+     elm_web_zoom_mode_set(wt->web, ELM_WEB_ZOOM_MODE_AUTO_FIT);
+   else
+     elm_web_zoom_mode_set(wt->web, ELM_WEB_ZOOM_MODE_AUTO_FILL);
+}
+
+static void
+_show_region_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Web_Test *wt = data;
+   elm_web_region_show(wt->web, 300, 300, 1, 1);
+}
+
+static void
+_bring_in_region_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Web_Test *wt = data;
+   elm_web_region_bring_in(wt->web, 50, 0, 1, 1);
+}
+
+static void
+_main_web_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Web_Test *wt = data;
+   Evas_Object *sub_win;
+
+   EINA_LIST_FREE(wt->sub_wins, sub_win)
+      evas_object_del(sub_win);
+
+   free(wt);
+}
+
+void
+test_web(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *bx2, *bt, *web, *url;
+   Web_Test *wt;
+
+   elm_need_web();
+
+   wt = calloc(1, sizeof(*wt));
+
+   win = elm_win_add(NULL, "web", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Web");
+   elm_win_autodel_set(win, EINA_TRUE);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   elm_win_resize_object_add(win, bx);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bx);
+
+   bx2 = elm_box_add(win);
+   elm_box_horizontal_set(bx2, EINA_TRUE);
+   evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, 0);
+   evas_object_size_hint_align_set(bx2, EVAS_HINT_FILL, 0.0);
+   elm_box_pack_end(bx, bx2);
+   evas_object_show(bx2);
+
+   web = elm_web_add(win);
+   evas_object_size_hint_weight_set(web, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(web, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(bx, web);
+   evas_object_show(web);
+
+   bt = elm_button_add(win);
+   elm_object_text_set(bt, "<");
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   evas_object_smart_callback_add(bt, "clicked", _btn_back_cb, web);
+   wt->btn_back = bt;
+
+   bt = elm_button_add(win);
+   elm_object_text_set(bt, "R");
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   evas_object_smart_callback_add(bt, "clicked", _btn_reload_cb, web);
+
+   bt = elm_button_add(win);
+   elm_object_text_set(bt, ">");
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   evas_object_smart_callback_add(bt, "clicked", _btn_fwd_cb, web);
+   wt->btn_fwd = bt;
+
+   url = elm_entry_add(win);
+   elm_entry_single_line_set(url, EINA_TRUE);
+   elm_entry_scrollable_set(url, EINA_TRUE);
+   evas_object_size_hint_weight_set(url, EVAS_HINT_EXPAND, 0);
+   evas_object_size_hint_align_set(url, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(bx2, url);
+   evas_object_show(url);
+
+   evas_object_smart_callback_add(url, "activated", _url_change_cb, web);
+   wt->url_entry = url;
+
+   bx2 = elm_box_add(win);
+   elm_box_horizontal_set(bx2, EINA_TRUE);
+   evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, 0);
+   evas_object_size_hint_align_set(bx2, EVAS_HINT_FILL, 0);
+   elm_box_pack_end(bx, bx2);
+   evas_object_show(bx2);
+
+   bt = elm_button_add(win);
+   elm_object_text_set(bt, "Inwin Mode");
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   evas_object_smart_callback_add(bt, "clicked", _toggle_inwin_mode_cb, web);
+
+   bt = elm_button_add(win);
+   elm_object_text_set(bt, "Custom Hooks");
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   evas_object_smart_callback_add(bt, "clicked", _js_popup_hooks_set, wt);
+
+   bt = elm_button_add(win);
+   elm_object_text_set(bt, "-");
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   evas_object_smart_callback_add(bt, "clicked", _zoom_out_cb, wt);
+
+   bt = elm_button_add(win);
+   elm_object_text_set(bt, "+");
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   evas_object_smart_callback_add(bt, "clicked", _zoom_in_cb, wt);
+
+   bt = elm_hoversel_add(win);
+   elm_object_text_set(bt, "Zoom Mode");
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   elm_hoversel_item_add(bt, "Manual", NULL, ELM_ICON_NONE, _zoom_mode_cb, wt);
+   elm_hoversel_item_add(bt, "Fit", NULL, ELM_ICON_NONE, _zoom_mode_cb, wt);
+   elm_hoversel_item_add(bt, "Fill", NULL, ELM_ICON_NONE, _zoom_mode_cb, wt);
+
+   bx2 = elm_box_add(win);
+   elm_box_horizontal_set(bx2, EINA_TRUE);
+   evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, 0);
+   evas_object_size_hint_align_set(bx2, EVAS_HINT_FILL, 0);
+   elm_box_pack_end(bx, bx2);
+   evas_object_show(bx2);
+
+   bt = elm_button_add(win);
+   elm_object_text_set(bt, "Show 300, 300");
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   evas_object_smart_callback_add(bt, "clicked", _show_region_cb, wt);
+
+   bt = elm_button_add(win);
+   elm_object_text_set(bt, "Bring in 50, 0");
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   evas_object_smart_callback_add(bt, "clicked", _bring_in_region_cb, wt);
+
+   evas_object_smart_callback_add(web, "title,changed", _title_changed_cb, win);
+   evas_object_smart_callback_add(web, "uri,changed", _uri_changed_cb, wt);
+
+   evas_object_event_callback_add(web, EVAS_CALLBACK_DEL, _main_web_del_cb, wt);
+
+   wt->web = web;
+
+   elm_web_uri_set(web, "http://www.enlightenment.org");
+
+   elm_web_window_create_hook_set(web, _new_window_hook, wt);
+
+   evas_object_resize(win, 320, 480);
+   evas_object_show(win);
+}
+#endif
diff --git a/src/edje_externals/elm_actionslider.c b/src/edje_externals/elm_actionslider.c
new file mode 100644 (file)
index 0000000..aeef27e
--- /dev/null
@@ -0,0 +1,99 @@
+#include "private.h"
+
+typedef struct _Elm_Params_Actionslider
+{
+   Elm_Params base;
+   const char *label;
+} Elm_Params_Actionslider;
+
+static void
+external_actionslider_state_set(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const void *from_params, const void *to_params, float pos __UNUSED__)
+{
+   const Elm_Params_Actionslider *p;
+
+   if (to_params) p = to_params;
+   else if (from_params) p = from_params;
+   else return;
+
+   if (p->label)
+     elm_object_text_set(obj, p->label);
+}
+
+static Eina_Bool
+external_actionslider_param_set(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const Edje_External_Param *param)
+{
+   if ((param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+       && (!strcmp(param->name, "label")))
+     {
+        elm_object_text_set(obj, param->s);
+        return EINA_TRUE;
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+external_actionslider_param_get(void *data __UNUSED__, const Evas_Object *obj __UNUSED__, Edje_External_Param *param)
+{
+   if ((param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+       && (!strcmp(param->name, "label")))
+     {
+        param->s = elm_object_text_get(obj);
+        return EINA_TRUE;
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static void *
+external_actionslider_params_parse(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const Eina_List *params)
+{
+   Elm_Params_Actionslider *mem;
+   Edje_External_Param *param;
+   const Eina_List *l;
+
+   mem = ELM_NEW(Elm_Params_Actionslider);
+   if (!mem)
+     return NULL;
+
+   EINA_LIST_FOREACH(params, l, param)
+     {
+        if (!strcmp(param->name, "label"))
+          {
+             mem->label = eina_stringshare_add(param->s);
+             break;
+          }
+     }
+
+   return mem;
+}
+
+static Evas_Object *external_actionslider_content_get(void *data __UNUSED__,
+               const Evas_Object *obj __UNUSED__, const char *content __UNUSED__)
+{
+   ERR("No content.");
+   return NULL;
+}
+
+static void
+external_actionslider_params_free(void *params)
+{
+   Elm_Params_Actionslider *mem = params;
+   if (mem->label)
+     eina_stringshare_del(mem->label);
+   free(mem);
+}
+
+static Edje_External_Param_Info external_actionslider_params[] = {
+   DEFINE_EXTERNAL_COMMON_PARAMS,
+   EDJE_EXTERNAL_PARAM_INFO_SENTINEL
+};
+
+DEFINE_EXTERNAL_ICON_ADD(actionslider, "actionslider")
+DEFINE_EXTERNAL_TYPE_SIMPLE(actionslider, "Actionslider");
diff --git a/src/edje_externals/elm_frame.c b/src/edje_externals/elm_frame.c
new file mode 100644 (file)
index 0000000..22a4b34
--- /dev/null
@@ -0,0 +1,125 @@
+#include "private.h"
+
+typedef struct _Elm_Params_Frame
+{
+   Elm_Params base;
+   const char *label;
+   Evas_Object *content; /* part name whose obj is to be set as content */
+} Elm_Params_Frame;
+
+static void
+external_frame_state_set(void *data __UNUSED__, Evas_Object *obj, const void *from_params, const void *to_params, float pos __UNUSED__)
+{
+   const Elm_Params_Frame *p;
+
+   if (to_params) p = to_params;
+   else if (from_params) p = from_params;
+   else return;
+
+   if (p->label) elm_object_text_set(obj, p->label);
+   if (p->content) elm_object_content_set(obj, p->content);
+}
+
+static Eina_Bool
+external_frame_param_set(void *data __UNUSED__, Evas_Object *obj, const Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "label"))
+     {
+        if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+          {
+             elm_object_text_set(obj, param->s);
+             return EINA_TRUE;
+          }
+     }
+   else if (!strcmp(param->name, "content"))
+     {
+        if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+          {
+             Evas_Object *content =
+                external_common_param_edje_object_get(obj,param);
+             if ((strcmp(param->s, "")) && (!content)) return EINA_FALSE;
+             elm_object_content_set(obj, content);
+             return EINA_TRUE;
+          }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+external_frame_param_get(void *data __UNUSED__, const Evas_Object *obj, Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "label"))
+     {
+        if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+          {
+             param->s = elm_object_text_get(obj);
+             return EINA_TRUE;
+          }
+     }
+   else if (!strcmp(param->name, "content"))
+     {
+        /* not easy to get content name back from live object */
+        return EINA_FALSE;
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static void *
+external_frame_params_parse(void *data __UNUSED__, Evas_Object *obj, const Eina_List *params)
+{
+   Elm_Params_Frame *mem;
+   Edje_External_Param *param;
+   const Eina_List *l;
+
+   mem = calloc(1, sizeof(Elm_Params_Frame));
+   if (!mem)
+     return NULL;
+
+   EINA_LIST_FOREACH(params, l, param)
+     {
+        if (!strcmp(param->name, "content"))
+          mem->content = external_common_param_edje_object_get(obj, param);
+        else if (!strcmp(param->name, "label"))
+          mem->label = eina_stringshare_add(param->s);
+     }
+
+   return mem;
+}
+
+static Evas_Object *external_frame_content_get(void *data __UNUSED__,
+                                               const Evas_Object *obj __UNUSED__, const char *content __UNUSED__)
+{
+   if (!strcmp(content, "content"))
+     return elm_object_content_get(obj);
+
+   ERR("unknown content '%s'", content);
+   return NULL;
+}
+
+static void
+external_frame_params_free(void *params)
+{
+   Elm_Params_Frame *mem = params;
+
+   if (mem->label)
+      eina_stringshare_del(mem->label);
+   free(params);
+}
+
+static Edje_External_Param_Info external_frame_params[] = {
+   DEFINE_EXTERNAL_COMMON_PARAMS,
+   EDJE_EXTERNAL_PARAM_INFO_STRING("label"),
+   EDJE_EXTERNAL_PARAM_INFO_STRING("content"),
+   EDJE_EXTERNAL_PARAM_INFO_SENTINEL
+};
+
+DEFINE_EXTERNAL_ICON_ADD(frame, "frame");
+DEFINE_EXTERNAL_TYPE_SIMPLE(frame, "Frame");
diff --git a/src/edje_externals/elm_video.c b/src/edje_externals/elm_video.c
new file mode 100644 (file)
index 0000000..41c9192
--- /dev/null
@@ -0,0 +1,261 @@
+#include "private.h"
+
+typedef struct _Elm_Params_Video
+{
+   Elm_Params base;
+   const char *file;
+   const char *uri;
+   Eina_Bool play:1;
+   Eina_Bool play_exists:1;
+   Eina_Bool pause:1;
+   Eina_Bool pause_exists:1;
+   Eina_Bool stop:1;
+   Eina_Bool stop_exists:1;
+   Eina_Bool audio_mute:1;
+   Eina_Bool audio_mute_exists:1;
+   double audio_level;
+   Eina_Bool audio_level_exists:1;
+   double play_position;
+   Eina_Bool play_position_exists:1;
+   Eina_Bool remember_position:1;
+   Eina_Bool remember_position_exists:1;
+} Elm_Params_Video;
+
+static void
+external_video_state_set(void *data __UNUSED__, Evas_Object *obj, const void *from_params, const void *to_params, float pos __UNUSED__)
+{
+   const Elm_Params_Video *p;
+
+   if (to_params) p = to_params;
+   else if (from_params) p = from_params;
+   else return;
+
+   if (p->file) elm_video_file_set(obj, p->file);
+   if (p->uri) elm_video_uri_set(obj, p->uri);
+   if (p->play_exists && p->play) elm_video_play(obj);
+   if (p->pause_exists && p->pause) elm_video_pause(obj);
+   if (p->stop_exists && p->stop) elm_video_stop(obj);
+   if (p->audio_mute_exists) elm_video_audio_mute_set(obj, p->audio_mute);
+   if (p->audio_level_exists) elm_video_audio_level_set(obj, p->audio_level);
+   if (p->play_position_exists)
+     elm_video_play_position_set(obj, p->play_position);
+   if (p->remember_position_exists)
+     elm_video_remember_position_set(obj, p->remember_position);
+}
+
+static Eina_Bool
+external_video_param_set(void *data __UNUSED__, Evas_Object *obj, const Edje_External_Param *param)
+{
+   if ((param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+       && (!strcmp(param->name, "file")))
+     {
+        elm_video_file_set(obj, param->s);
+        return EINA_TRUE;
+     }
+   else if ((param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+       && (!strcmp(param->name, "uri")))
+     {
+        elm_video_uri_set(obj, param->s);
+        return EINA_TRUE;
+     }
+   else if ((param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+       && (!strcmp(param->name, "play")))
+     {
+        if (param->i)
+          elm_video_play(obj);
+        return EINA_TRUE;
+     }
+   else if ((param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+       && (!strcmp(param->name, "pause")))
+     {
+        if (param->i)
+          elm_video_pause(obj);
+        return EINA_TRUE;
+     }
+   else if ((param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+       && (!strcmp(param->name, "stop")))
+     {
+        if (param->i)
+          elm_video_stop(obj);
+        return EINA_TRUE;
+     }
+   else if ((param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+       && (!strcmp(param->name, "audio mute")))
+     {
+        elm_video_audio_mute_set(obj, param->i);
+        return EINA_TRUE;
+     }
+   else if ((param->type == EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
+       && (!strcmp(param->name, "audio level")))
+     {
+        elm_video_audio_level_set(obj, param->d);
+        return EINA_TRUE;
+     }
+   else if ((param->type == EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
+       && (!strcmp(param->name, "play position")))
+     {
+        elm_video_play_position_set(obj, param->d);
+        return EINA_TRUE;
+     }
+   else if ((param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+       && (!strcmp(param->name, "remember position")))
+     {
+        elm_video_remember_position_set(obj, param->i);
+        return EINA_TRUE;
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+external_video_param_get(void *data __UNUSED__, const Evas_Object *obj, Edje_External_Param *param)
+{
+   if ((param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+       && (!strcmp(param->name, "file")))
+     {
+        //        param->s = elm_video_file_get(obj);
+        //        return EINA_TRUE;
+        return EINA_FALSE;
+     }
+   else if ((param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+                && (!strcmp(param->name, "uri")))
+     {
+        //        elm_video_uri_get(obj, param->s);
+        //        return EINA_TRUE;
+        return EINA_FALSE;
+     }
+   else if ((param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+            && (!strcmp(param->name, "play")))
+     {
+        //        param->i = elm_video_play_get(obj); return EINA_TRUE;
+        return EINA_FALSE;
+     }
+   else if ((param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+            && (!strcmp(param->name, "pause")))
+     {
+             //        param->i = elm_video_pause_get(obj); return EINA_TRUE;
+        return EINA_FALSE;
+     }
+   else if ((param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+            && (!strcmp(param->name, "stop")))
+     {
+        //        param->i = elm_video_stop_get(obj); return EINA_TRUE;
+        return EINA_FALSE;
+     }
+   else if ((param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+            && (!strcmp(param->name, "audio mute")))
+     {
+        param->i = elm_video_audio_mute_get(obj);
+        return EINA_TRUE;
+     }
+   else if ((param->type == EDJE_EXTERNAL_PARAM_TYPE_DOUBLE) &&
+            (!strcmp(param->name, "audio level")))
+     {
+        param->d = elm_video_audio_level_get(obj);
+        return EINA_TRUE;
+     }
+   else if ((param->type == EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
+            && (!strcmp(param->name, "play position")))
+     {
+        param->d = elm_video_play_position_get(obj);
+        return EINA_TRUE;
+     }
+   else if ((param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+            && (!strcmp(param->name, "remember position")))
+     {
+        param->i = elm_video_remember_position_get(obj);
+        return EINA_TRUE;
+     }
+
+   ERR("unknown parameter '%s' of type '%s'", param->name,
+       edje_external_param_type_str(param->type));
+
+   return EINA_FALSE; }
+
+static void * external_video_params_parse(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const Eina_List *params)
+{
+   Elm_Params_Video *mem;
+   Edje_External_Param *param;
+   const Eina_List *l;
+
+   mem = calloc(1, sizeof(Elm_Params_Video));
+   if (!mem) return NULL;
+
+   EINA_LIST_FOREACH(params, l, param)
+     {
+        if (!strcmp(param->name, "file"))
+          mem->file = eina_stringshare_add(param->s);
+        else if (!strcmp(param->name, "uri"))
+          mem->uri = eina_stringshare_add(param->s);
+        else if (!strcmp(param->name, "play"))
+          {
+             mem->play = param->i;
+             mem->play_exists = EINA_TRUE;
+          }
+        else if (!strcmp(param->name, "pause"))
+          {
+             mem->pause = param->i;
+             mem->pause_exists = EINA_TRUE;
+          }
+        else if (!strcmp(param->name, "stop"))
+          {
+             mem->stop = param->i;
+             mem->stop_exists = EINA_TRUE;
+          }
+        else if (!strcmp(param->name, "audio mute"))
+          {
+             mem->audio_mute = param->i;
+             mem->audio_mute_exists = EINA_TRUE;
+          }
+        else if (!strcmp(param->name, "audio level"))
+          {
+             mem->audio_level = param->d;
+             mem->audio_level_exists = EINA_TRUE;
+          }
+        else if (!strcmp(param->name, "play position"))
+          {
+             mem->play_position = param->d;
+             mem->play_position_exists = EINA_TRUE;
+          }
+        else if (!strcmp(param->name, "remember position"))
+          {
+             mem->remember_position = param->i;
+             mem->remember_position = EINA_TRUE;
+          }
+     }
+   return mem;
+}
+
+static Evas_Object *external_video_content_get(void *data __UNUSED__, const Evas_Object *obj __UNUSED__, const char *content __UNUSED__)
+{
+   ERR("No content.");
+   return NULL;
+}
+
+static void external_video_params_free(void *params)
+{
+   Elm_Params_Video *mem = params;
+
+   if (mem->file) eina_stringshare_del(mem->file);
+   if (mem->uri) eina_stringshare_del(mem->uri);
+   free(params);
+}
+
+static Edje_External_Param_Info external_video_params[] = {
+     DEFINE_EXTERNAL_COMMON_PARAMS, EDJE_EXTERNAL_PARAM_INFO_STRING("file"),
+     EDJE_EXTERNAL_PARAM_INFO_STRING("uri"),
+     EDJE_EXTERNAL_PARAM_INFO_BOOL("play"),
+     EDJE_EXTERNAL_PARAM_INFO_BOOL("pause"),
+     EDJE_EXTERNAL_PARAM_INFO_BOOL("stop"),
+     EDJE_EXTERNAL_PARAM_INFO_BOOL("audio mute"),
+     EDJE_EXTERNAL_PARAM_INFO_DOUBLE("audio level"),
+     EDJE_EXTERNAL_PARAM_INFO_DOUBLE("play position"),
+     EDJE_EXTERNAL_PARAM_INFO_BOOL("remember position"),
+     EDJE_EXTERNAL_PARAM_INFO_SENTINEL
+};
+
+DEFINE_EXTERNAL_ICON_ADD(video, "video");
+DEFINE_EXTERNAL_TYPE_SIMPLE(video, "Video");
diff --git a/src/edje_externals/elm_web.c b/src/edje_externals/elm_web.c
new file mode 100644 (file)
index 0000000..64fd373
--- /dev/null
@@ -0,0 +1,208 @@
+#include "private.h"
+
+typedef struct _Elm_Params_Web
+{
+   Elm_Params base;
+   const char *uri;
+   double zoom;
+   Elm_Web_Zoom_Mode zoom_mode;
+   Eina_Bool inwin_mode;
+   Eina_Bool zoom_set:1;
+   Eina_Bool inwin_mode_set:1;
+} Elm_Params_Web;
+
+static const char *zoom_choices[] = {"manual", "auto fit", "auto fill", NULL};
+
+static Elm_Web_Zoom_Mode
+_zoom_mode_get(const char *zoom)
+{
+   unsigned int i;
+
+   for (i = 0; i < ELM_WEB_ZOOM_MODE_LAST; i++)
+     if (!strcmp(zoom, zoom_choices[i])) return i;
+
+   return ELM_WEB_ZOOM_MODE_LAST;
+}
+
+static void
+external_web_state_set(void *data __UNUSED__, Evas_Object *obj, const void *from_params, const void *to_params, float pos __UNUSED__)
+{
+   const Elm_Params_Web *p;
+
+   if (to_params) p = to_params;
+   else if (from_params) p = from_params;
+   else return;
+
+   if (p->uri)
+     elm_web_uri_set(obj, p->uri);
+   if (p->zoom_mode < ELM_WEB_ZOOM_MODE_LAST)
+     elm_web_zoom_mode_set(obj, p->zoom_mode);
+   if (p->zoom_set)
+     elm_web_zoom_set(obj, p->zoom);
+   if (p->inwin_mode_set)
+     elm_web_inwin_mode_set(obj, p->inwin_mode);
+}
+
+static Eina_Bool
+external_web_param_set(void *data __UNUSED__, Evas_Object *obj, const Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "uri"))
+     {
+        if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+          {
+             elm_web_uri_set(obj, param->s);
+             return EINA_TRUE;
+          }
+     }
+   else if (!strcmp(param->name, "zoom level"))
+     {
+        if (param->type == EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
+          {
+             elm_web_zoom_set(obj, param->d);
+             return EINA_TRUE;
+          }
+     }
+   else if (!strcmp(param->name, "zoom mode"))
+     {
+        if (param->type == EDJE_EXTERNAL_PARAM_TYPE_CHOICE)
+          {
+             Elm_Web_Zoom_Mode mode = _zoom_mode_get(param->s);
+             if (mode == ELM_WEB_ZOOM_MODE_LAST)
+               return EINA_FALSE;
+             elm_web_zoom_mode_set(obj, mode);
+             return EINA_TRUE;
+          }
+     }
+   else if (!strcmp(param->name, "inwin mode"))
+     {
+        if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+          {
+             elm_web_inwin_mode_set(obj, !!param->i);
+             return EINA_TRUE;
+          }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+external_web_param_get(void *data __UNUSED__, const Evas_Object *obj, Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "uri"))
+     {
+        if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+          {
+             param->s = elm_web_uri_get(obj);
+             return EINA_TRUE;
+          }
+     }
+   else if (!strcmp(param->name, "zoom level"))
+     {
+        if (param->type == EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
+          {
+             param->d = elm_web_zoom_get(obj);
+             return EINA_TRUE;
+          }
+     }
+   else if (!strcmp(param->name, "zoom mode"))
+     {
+        if (param->type == EDJE_EXTERNAL_PARAM_TYPE_CHOICE)
+          {
+             Elm_Web_Zoom_Mode mode = elm_web_zoom_mode_get(obj);
+             if (mode == ELM_WEB_ZOOM_MODE_LAST)
+               return EINA_FALSE;
+             param->s = zoom_choices[mode];
+             return EINA_TRUE;
+          }
+     }
+   else if (!strcmp(param->name, "inwin mode"))
+     {
+        if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+          {
+             param->i = elm_web_inwin_mode_get(obj);
+             return EINA_TRUE;
+          }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static void *
+external_web_params_parse(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const Eina_List *params)
+{
+   Elm_Params_Web *mem;
+   Edje_External_Param *param;
+   const Eina_List *l;
+
+   mem = calloc(1, sizeof(Elm_Params_Web));
+   if (!mem) return NULL;
+
+   mem->zoom_mode = ELM_WEB_ZOOM_MODE_LAST;
+
+   EINA_LIST_FOREACH(params, l, param)
+     {
+        if (!strcmp(param->name, "zoom level"))
+          {
+             mem->zoom = param->d;
+             mem->zoom_set = EINA_TRUE;
+          }
+        else if (!strcmp(param->name, "zoom mode"))
+          mem->zoom_mode = _zoom_mode_get(param->s);
+        else if (!strcmp(param->name, "uri"))
+          mem->uri = eina_stringshare_add(param->s);
+        else if (!strcmp(param->name, "inwin mode"))
+          {
+             mem->inwin_mode = !!param->i;
+             mem->inwin_mode_set = EINA_TRUE;
+          }
+     }
+
+   return mem;
+}
+
+static void
+external_web_params_free(void *params)
+{
+   Elm_Params_Web *mem = params;
+
+   if (mem->uri)
+     eina_stringshare_del(mem->uri);
+   free(mem);
+}
+
+static Evas_Object *
+external_web_content_get(void *data __UNUSED__, const Evas_Object *obj __UNUSED__, const char *content __UNUSED__)
+{
+   return NULL;
+}
+
+static Edje_External_Param_Info external_web_params[] =
+{
+   EDJE_EXTERNAL_PARAM_INFO_STRING("uri"),
+   EDJE_EXTERNAL_PARAM_INFO_DOUBLE_DEFAULT("zoom level", 1.0),
+   EDJE_EXTERNAL_PARAM_INFO_CHOICE_FULL("zoom mode", "manual", zoom_choices),
+   EDJE_EXTERNAL_PARAM_INFO_BOOL_DEFAULT("inwin mode", EINA_FALSE),
+   EDJE_EXTERNAL_PARAM_INFO_SENTINEL
+};
+
+static Evas_Object *
+external_web_add(void *data __UNUSED__, Evas *evas __UNUSED__, Evas_Object *edje, const Eina_List *params __UNUSED__, const char *part_name)
+{
+   Evas_Object *parent, *obj;
+   external_elm_init();
+   parent = elm_widget_parent_widget_get(edje);
+   if (!parent) parent = edje;
+   elm_need_web(); /* extra command needed */
+   obj = elm_web_add(parent);
+   external_signals_proxy(obj, edje, part_name);
+   return obj;
+}
+
+DEFINE_EXTERNAL_ICON_ADD(web, "web")
+DEFINE_EXTERNAL_TYPE(web, "Web")
diff --git a/src/lib/elm_access.c b/src/lib/elm_access.c
new file mode 100644 (file)
index 0000000..79c2b5a
--- /dev/null
@@ -0,0 +1,524 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+typedef struct _Mod_Api Mod_Api;
+
+struct _Mod_Api
+{
+   void (*out_read) (const char *txt);
+   void (*out_read_done) (void);
+   void (*out_cancel) (void);
+   void (*out_done_callback_set) (void (*func) (void *data), const void *data);
+};
+
+static int initted = 0;
+static Mod_Api *mapi = NULL;
+
+static void
+_access_init(void)
+{
+   Elm_Module *m;
+   initted++;
+   if (initted > 1) return;
+   if (!(m = _elm_module_find_as("access/api"))) return;
+   m->api = malloc(sizeof(Mod_Api));
+   if (!m->api) return;
+   m->init_func(m);
+   ((Mod_Api *)(m->api)      )->out_read = // called to read out some text
+      _elm_module_symbol_get(m, "out_read");
+   ((Mod_Api *)(m->api)      )->out_read_done = // called to set a done marker so when it is reached the done callback is called
+      _elm_module_symbol_get(m, "out_read_done");
+   ((Mod_Api *)(m->api)      )->out_cancel = // called to read out some text
+      _elm_module_symbol_get(m, "out_cancel");
+   ((Mod_Api *)(m->api)      )->out_done_callback_set = // called when last read done
+      _elm_module_symbol_get(m, "out_done_callback_set");
+   mapi = m->api;
+}
+
+static Elm_Access_Item *
+_access_add_set(Elm_Access_Info *ac, int type)
+{
+   Elm_Access_Item *ai;
+   Eina_List *l;
+
+   if (!ac) return NULL;
+   EINA_LIST_FOREACH(ac->items, l, ai)
+     {
+        if (ai->type == type)
+          {
+             if (!ai->func)
+               {
+                  if (ai->data) eina_stringshare_del(ai->data);
+               }
+             ai->func = NULL;
+             ai->data = NULL;
+             return ai;
+          }
+     }
+   ai = calloc(1, sizeof(Elm_Access_Item));
+   ai->type = type;
+   ac->items = eina_list_prepend(ac->items, ai);
+   return ai;
+}
+
+static Eina_Bool
+_access_obj_over_timeout_cb(void *data)
+{
+   Elm_Access_Info *ac = evas_object_data_get(data, "_elm_access");
+   if (!ac) return EINA_FALSE;
+   if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF)
+     {
+        _elm_access_object_hilight(data);
+        _elm_access_read(ac, ELM_ACCESS_CANCEL, data, NULL);
+        _elm_access_read(ac, ELM_ACCESS_TYPE,   data, NULL);
+        _elm_access_read(ac, ELM_ACCESS_INFO,   data, NULL);
+        _elm_access_read(ac, ELM_ACCESS_STATE,  data, NULL);
+        _elm_access_read(ac, ELM_ACCESS_DONE,   data, NULL);
+     }
+   ac->delay_timer = NULL;
+   return EINA_FALSE;
+}
+
+static void
+_access_obj_mouse_in_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info  __UNUSED__)
+{
+   Elm_Access_Info *ac = evas_object_data_get(data, "_elm_access");
+   if (!ac) return;
+
+   if (ac->delay_timer)
+     {
+        ecore_timer_del(ac->delay_timer);
+        ac->delay_timer = NULL;
+     }
+   if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF)
+      ac->delay_timer = ecore_timer_add(0.2, _access_obj_over_timeout_cb, data);
+}
+
+static void
+_access_obj_mouse_out_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Elm_Access_Info *ac = evas_object_data_get(data, "_elm_access");
+   if (!ac) return;
+   _elm_access_object_unhilight(data);
+   if (ac->delay_timer)
+     {
+        ecore_timer_del(ac->delay_timer);
+        ac->delay_timer = NULL;
+     }
+}
+
+static void
+_access_obj_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Elm_Access_Info *ac;
+
+   evas_object_event_callback_del_full(obj, EVAS_CALLBACK_MOUSE_IN,
+                                       _access_obj_mouse_in_cb, data);
+   evas_object_event_callback_del_full(obj, EVAS_CALLBACK_MOUSE_OUT,
+                                       _access_obj_mouse_out_cb, data);
+   evas_object_event_callback_del_full(obj, EVAS_CALLBACK_DEL,
+                                       _access_obj_del_cb, data);
+   ac = evas_object_data_get(data, "_elm_access");
+   evas_object_data_del(data, "_elm_access");
+   if (ac)
+     {
+        _elm_access_clear(ac);
+        free(ac);
+     }
+}
+
+static void
+_access_read_done(void *data __UNUSED__)
+{
+   printf("read done\n");
+   // FIXME: produce event here
+}
+
+static void
+_access_2nd_click_del_cb(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Ecore_Timer *t;
+
+   evas_object_event_callback_del_full(obj, EVAS_CALLBACK_DEL,
+                                       _access_2nd_click_del_cb, NULL);
+   t = evas_object_data_get(obj, "_elm_2nd_timeout");
+   if (t)
+     {
+        ecore_timer_del(t);
+        evas_object_data_del(obj, "_elm_2nd_timeout");
+     }
+}
+
+static Eina_Bool
+_access_2nd_click_timeout_cb(void *data)
+{
+   evas_object_event_callback_del_full(data, EVAS_CALLBACK_DEL,
+                                       _access_2nd_click_del_cb, NULL);
+   evas_object_data_del(data, "_elm_2nd_timeout");
+   return EINA_FALSE;
+}
+
+static void
+_access_obj_hilight_del_cb(void *data __UNUSED__, Evas *e, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   _elm_access_object_hilight_disable(e);
+}
+
+static void
+_access_obj_hilight_hide_cb(void *data __UNUSED__, Evas *e, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   _elm_access_object_hilight_disable(e);
+}
+
+static void
+_access_obj_hilight_move_cb(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Evas_Coord x, y;
+   Evas_Object *o;
+
+   o = evas_object_name_find(evas_object_evas_get(obj), "_elm_access_disp");
+   if (!o) return;
+   evas_object_geometry_get(obj, &x, &y, NULL, NULL);
+   evas_object_move(o, x, y);
+}
+
+static void
+_access_obj_hilight_resize_cb(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Evas_Coord w, h;
+   Evas_Object *o;
+
+   o = evas_object_name_find(evas_object_evas_get(obj), "_elm_access_disp");
+   if (!o) return;
+   evas_object_geometry_get(obj, NULL, NULL, &w, &h);
+   evas_object_resize(o, w, h);
+}
+
+
+
+//-------------------------------------------------------------------------//
+
+EAPI void
+_elm_access_clear(Elm_Access_Info *ac)
+{
+   Elm_Access_Item *ai;
+
+   if (!ac) return;
+   if (ac->delay_timer)
+     {
+        ecore_timer_del(ac->delay_timer);
+        ac->delay_timer = NULL;
+     }
+   EINA_LIST_FREE(ac->items, ai)
+     {
+        if (!ai->func)
+          {
+             if (ai->data) eina_stringshare_del(ai->data);
+          }
+        free(ai);
+     }
+}
+
+EAPI void
+_elm_access_text_set(Elm_Access_Info *ac, int type, const char *text)
+{
+   Elm_Access_Item *ai = _access_add_set(ac, type);
+   if (!ai) return;
+   ai->data = eina_stringshare_add(text);
+}
+
+EAPI void
+_elm_access_callback_set(Elm_Access_Info *ac, int type, Elm_Access_Content_Cb func, const void *data)
+{
+   Elm_Access_Item *ai = _access_add_set(ac, type);
+   if (!ai) return;
+   ai->func = func;
+   ai->data = data;
+}
+
+EAPI char *
+_elm_access_text_get(Elm_Access_Info *ac, int type, Evas_Object *obj, Elm_Widget_Item *item)
+{
+   Elm_Access_Item *ai;
+   Eina_List *l;
+
+   if (!ac) return NULL;
+   EINA_LIST_FOREACH(ac->items, l, ai)
+     {
+        if (ai->type == type)
+          {
+             if (ai->func) return ai->func((void *)(ai->data), obj, item);
+             else if (ai->data) return strdup(ai->data);
+             return NULL;
+          }
+     }
+   return NULL;
+}
+
+EAPI void
+_elm_access_read(Elm_Access_Info *ac, int type, Evas_Object *obj, Elm_Widget_Item *item)
+{
+   char *txt = _elm_access_text_get(ac, type, obj, item);
+
+   _access_init();
+   if (mapi)
+     {
+        if (mapi->out_done_callback_set)
+           mapi->out_done_callback_set(_access_read_done, NULL);
+        if (type == ELM_ACCESS_DONE)
+          {
+             if (mapi->out_read_done) mapi->out_read_done();
+          }
+        else if (type == ELM_ACCESS_CANCEL)
+          {
+             if (mapi->out_cancel) mapi->out_cancel();
+          }
+        else
+          {
+             if (txt)
+               {
+                  if (mapi->out_read) mapi->out_read(txt);
+                  if (mapi->out_read) mapi->out_read(".\n");
+               }
+          }
+     }
+   if (txt) free(txt);
+}
+
+EAPI void
+_elm_access_say(const char *txt)
+{
+   _access_init();
+   if (mapi)
+     {
+        if (mapi->out_done_callback_set)
+           mapi->out_done_callback_set(_access_read_done, NULL);
+        if (mapi->out_cancel) mapi->out_cancel();
+        if (txt)
+          {
+             if (mapi->out_read) mapi->out_read(txt);
+             if (mapi->out_read) mapi->out_read(".\n");
+          }
+        if (mapi->out_read_done) mapi->out_read_done();
+     }
+}
+
+EAPI Elm_Access_Info *
+_elm_access_object_get(Evas_Object *obj)
+{
+   return evas_object_data_get(obj, "_elm_access");
+}
+
+EAPI Elm_Access_Info *
+_elm_access_item_get(Elm_Widget_Item *it)
+{
+   return it->access;
+}
+
+EAPI void
+_elm_access_object_hilight(Evas_Object *obj)
+{
+   Evas_Object *o;
+   Evas_Coord x, y, w, h;
+
+   o = evas_object_name_find(evas_object_evas_get(obj), "_elm_access_disp");
+   if (!o)
+     {
+        o = edje_object_add(evas_object_evas_get(obj));
+        evas_object_name_set(o, "_elm_access_disp");
+        evas_object_layer_set(o, ELM_OBJECT_LAYER_TOOLTIP);
+     }
+   else
+     {
+        Evas_Object *ptarget = evas_object_data_get(o, "_elm_access_target");
+        if (ptarget)
+          {
+             evas_object_data_del(o, "_elm_access_target");
+             evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_DEL,
+                                                 _access_obj_hilight_del_cb, NULL);
+             evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_HIDE,
+                                                 _access_obj_hilight_hide_cb, NULL);
+             evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_MOVE,
+                                                 _access_obj_hilight_move_cb, NULL);
+             evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_RESIZE,
+                                                 _access_obj_hilight_resize_cb, NULL);
+          }
+     }
+   evas_object_data_set(o, "_elm_access_target", obj);
+   _elm_theme_object_set(obj, o, "access", "base", "default");
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
+                                  _access_obj_hilight_del_cb, NULL);
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE,
+                                  _access_obj_hilight_hide_cb, NULL);
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE,
+                                  _access_obj_hilight_move_cb, NULL);
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE,
+                                  _access_obj_hilight_resize_cb, NULL);
+   evas_object_raise(o);
+   evas_object_geometry_get(obj, &x, &y, &w, &h);
+   evas_object_move(o, x, y);
+   evas_object_resize(o, w, h);
+   evas_object_show(o);
+}
+
+EAPI void
+_elm_access_object_unhilight(Evas_Object *obj)
+{
+   Evas_Object *o, *ptarget;
+
+   o = evas_object_name_find(evas_object_evas_get(obj), "_elm_access_disp");
+   if (!o) return;
+   ptarget = evas_object_data_get(o, "_elm_access_target");
+   if (ptarget == obj)
+     {
+        evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_DEL,
+                                            _access_obj_hilight_del_cb, NULL);
+        evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_HIDE,
+                                            _access_obj_hilight_hide_cb, NULL);
+        evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_MOVE,
+                                            _access_obj_hilight_move_cb, NULL);
+        evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_RESIZE,
+                                            _access_obj_hilight_resize_cb, NULL);
+        evas_object_del(o);
+     }
+}
+
+EAPI void
+_elm_access_object_hilight_disable(Evas *e)
+{
+   Evas_Object *o, *ptarget;
+
+   o = evas_object_name_find(e, "_elm_access_disp");
+   if (!o) return;
+   ptarget = evas_object_data_get(o, "_elm_access_target");
+   if (ptarget)
+     {
+        evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_DEL,
+                                            _access_obj_hilight_del_cb, NULL);
+        evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_HIDE,
+                                            _access_obj_hilight_hide_cb, NULL);
+        evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_MOVE,
+                                            _access_obj_hilight_move_cb, NULL);
+        evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_RESIZE,
+                                            _access_obj_hilight_resize_cb, NULL);
+     }
+   evas_object_del(o);
+}
+
+EAPI void
+_elm_access_object_register(Evas_Object *obj, Evas_Object *hoverobj)
+{
+   Elm_Access_Info *ac;
+
+   evas_object_event_callback_add(hoverobj, EVAS_CALLBACK_MOUSE_IN,
+                                  _access_obj_mouse_in_cb, obj);
+   evas_object_event_callback_add(hoverobj, EVAS_CALLBACK_MOUSE_OUT,
+                                  _access_obj_mouse_out_cb, obj);
+   evas_object_event_callback_add(hoverobj, EVAS_CALLBACK_DEL,
+                                  _access_obj_del_cb, obj);
+   ac = calloc(1, sizeof(Elm_Access_Info));
+   evas_object_data_set(obj, "_elm_access", ac);
+}
+
+static Eina_Bool
+_access_item_over_timeout_cb(void *data)
+{
+   Elm_Access_Info *ac = ((Elm_Widget_Item *)data)->access;
+   if (!ac) return EINA_FALSE;
+   if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF)
+     {
+        _elm_access_object_hilight(((Elm_Widget_Item *)data)->view);
+        _elm_access_read(ac, ELM_ACCESS_CANCEL, NULL, data);
+        _elm_access_read(ac, ELM_ACCESS_TYPE,   NULL, data);
+        _elm_access_read(ac, ELM_ACCESS_INFO,   NULL, data);
+        _elm_access_read(ac, ELM_ACCESS_STATE,  NULL, data);
+        _elm_access_read(ac, ELM_ACCESS_DONE,   NULL, data);
+     }
+   ac->delay_timer = NULL;
+   return EINA_FALSE;
+}
+
+static void
+_access_item_mouse_in_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info  __UNUSED__)
+{
+   Elm_Access_Info *ac = ((Elm_Widget_Item *)data)->access;
+   if (!ac) return;
+
+   if (ac->delay_timer)
+     {
+        ecore_timer_del(ac->delay_timer);
+        ac->delay_timer = NULL;
+     }
+   if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF)
+      ac->delay_timer = ecore_timer_add(0.2, _access_item_over_timeout_cb, data);
+}
+
+static void
+_access_item_mouse_out_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Elm_Access_Info *ac = ((Elm_Widget_Item *)data)->access;
+   if (!ac) return;
+
+   _elm_access_object_unhilight(((Elm_Widget_Item *)data)->view);
+   if (ac->delay_timer)
+     {
+        ecore_timer_del(ac->delay_timer);
+        ac->delay_timer = NULL;
+     }
+}
+
+static void
+_access_item_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Elm_Access_Info *ac;
+
+   evas_object_event_callback_del_full(obj, EVAS_CALLBACK_MOUSE_IN,
+                                       _access_item_mouse_in_cb, data);
+   evas_object_event_callback_del_full(obj, EVAS_CALLBACK_MOUSE_OUT,
+                                       _access_item_mouse_out_cb, data);
+   evas_object_event_callback_del_full(obj, EVAS_CALLBACK_DEL,
+                                       _access_item_del_cb, data);
+   ac = ((Elm_Widget_Item *)data)->access;
+   ((Elm_Widget_Item *)data)->access = NULL;
+   if (ac)
+     {
+        _elm_access_clear(ac);
+        free(ac);
+     }
+}
+
+EAPI void
+_elm_access_item_register(Elm_Widget_Item *item, Evas_Object *hoverobj)
+{
+   Elm_Access_Info *ac;
+
+   evas_object_event_callback_add(hoverobj, EVAS_CALLBACK_MOUSE_IN,
+                                  _access_item_mouse_in_cb, item);
+   evas_object_event_callback_add(hoverobj, EVAS_CALLBACK_MOUSE_OUT,
+                                  _access_item_mouse_out_cb, item);
+   evas_object_event_callback_add(hoverobj, EVAS_CALLBACK_DEL,
+                                  _access_item_del_cb, item);
+   ac = calloc(1, sizeof(Elm_Access_Info));
+   item->access = ac;
+}
+
+EAPI Eina_Bool
+_elm_access_2nd_click_timeout(Evas_Object *obj)
+{
+   Ecore_Timer *t;
+
+   t = evas_object_data_get(obj, "_elm_2nd_timeout");
+   if (t)
+     {
+        ecore_timer_del(t);
+        evas_object_data_del(obj, "_elm_2nd_timeout");
+        evas_object_event_callback_del_full(obj, EVAS_CALLBACK_DEL,
+                                            _access_2nd_click_del_cb, NULL);
+        return EINA_TRUE;
+     }
+   t = ecore_timer_add(0.3, _access_2nd_click_timeout_cb, obj);
+   evas_object_data_set(obj, "_elm_2nd_timeout", t);
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
+                                  _access_2nd_click_del_cb, NULL);
+   return EINA_FALSE;
+}
diff --git a/src/lib/elm_gen.c b/src/lib/elm_gen.c
new file mode 100644 (file)
index 0000000..08b5a0c
--- /dev/null
@@ -0,0 +1,757 @@
+#include <Elementary.h>
+#include <Elementary_Cursor.h>
+#include "elm_priv.h"
+#include "els_scroller.h"
+#include "elm_gen.h"
+
+/* TEMPORARY */
+#undef ELM_CHECK_WIDTYPE
+#define ELM_CHECK_WIDTYPE(obj, widtype) \
+   if ((!obj) || (!elm_gen_type_check((obj), __func__))) return
+#undef ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN
+#define ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, ...)                \
+   ELM_WIDGET_ITEM_CHECK_OR_RETURN((Elm_Widget_Item *)it, __VA_ARGS__); \
+   ELM_CHECK_WIDTYPE(WIDGET((it)), widtype) __VA_ARGS__;
+
+static const char *_gengrid = NULL;
+static const char *_genlist = NULL;
+
+struct _Widget_Data
+{
+   Eina_Inlist_Sorted_State *state;
+   Evas_Object      *obj;
+   Evas_Object      *scr; /* a smart scroller object which is used internally in genlist */
+   Evas_Object      *pan_smart; /* "elm_genlist_pan" evas smart object. this is an extern pan of smart scroller(scr). */
+   Eina_List        *selected;
+   Eina_List        *group_items;
+   Eina_Inlist      *items; /* inlist of all items */
+   Elm_Gen_Item     *reorder_it; /* item currently being repositioned */
+   Elm_Gen_Item     *last_selected_item;
+   Pan              *pan; /* pan_smart object's smart data */
+   Ecore_Job        *calc_job;
+   int               walking;
+   int               item_width, item_height;
+   int               group_item_width, group_item_height;
+   int               minw, minh;
+   long              count;
+   Evas_Coord        pan_x, pan_y;
+   Eina_Bool         reorder_mode : 1;
+   Eina_Bool         on_hold : 1;
+   Eina_Bool         multi : 1;
+   Eina_Bool         no_select : 1;
+   Eina_Bool         wasselected : 1;
+   Eina_Bool         always_select : 1;
+   Eina_Bool         clear_me : 1;
+   Eina_Bool         h_bounce : 1;
+   Eina_Bool         v_bounce : 1;
+   Ecore_Cb          del_cb, calc_cb, sizing_cb;
+   Ecore_Cb          clear_cb;
+};
+
+static const char SIG_ACTIVATED[] = "activated";
+static const char SIG_CLICKED_DOUBLE[] = "clicked,double";
+static const char SIG_SELECTED[] = "selected";
+static const char SIG_UNSELECTED[] = "unselected";
+static const char SIG_EXPANDED[] = "expanded";
+static const char SIG_CONTRACTED[] = "contracted";
+static const char SIG_EXPAND_REQUEST[] = "expand,request";
+static const char SIG_CONTRACT_REQUEST[] = "contract,request";
+static const char SIG_REALIZED[] = "realized";
+static const char SIG_UNREALIZED[] = "unrealized";
+static const char SIG_DRAG_START_UP[] = "drag,start,up";
+static const char SIG_DRAG_START_DOWN[] = "drag,start,down";
+static const char SIG_DRAG_START_LEFT[] = "drag,start,left";
+static const char SIG_DRAG_START_RIGHT[] = "drag,start,right";
+static const char SIG_DRAG_STOP[] = "drag,stop";
+static const char SIG_DRAG[] = "drag";
+static const char SIG_LONGPRESSED[] = "longpressed";
+static const char SIG_SCROLL_ANIM_START[] = "scroll,anim,start";
+static const char SIG_SCROLL_ANIM_STOP[] = "scroll,anim,stop";
+static const char SIG_SCROLL_DRAG_START[] = "scroll,drag,start";
+static const char SIG_SCROLL_DRAG_STOP[] = "scroll,drag,stop";
+static const char SIG_SCROLL_EDGE_TOP[] = "scroll,edge,top"; // TODO : remove this
+static const char SIG_SCROLL_EDGE_BOTTOM[] = "scroll,edge,bottom"; // TODO : remove this
+static const char SIG_SCROLL_EDGE_LEFT[] = "scroll,edge,left"; // TODO : remove this
+static const char SIG_SCROLL_EDGE_RIGHT[] = "scroll,edge,right"; // TODO : remove this
+static const char SIG_EDGE_TOP[] = "edge,top";
+static const char SIG_EDGE_BOTTOM[] = "edge,bottom";
+static const char SIG_EDGE_LEFT[] = "edge,left";
+static const char SIG_EDGE_RIGHT[] = "edge,right";
+static const char SIG_MULTI_SWIPE_LEFT[] = "multi,swipe,left";
+static const char SIG_MULTI_SWIPE_RIGHT[] = "multi,swipe,right";
+static const char SIG_MULTI_SWIPE_UP[] = "multi,swipe,up";
+static const char SIG_MULTI_SWIPE_DOWN[] = "multi,swipe,down";
+static const char SIG_MULTI_PINCH_OUT[] = "multi,pinch,out";
+static const char SIG_MULTI_PINCH_IN[] = "multi,pinch,in";
+static const char SIG_SWIPE[] = "swipe";
+static const char SIG_MOVED[] = "moved";
+
+/* THIS FUNCTION IS HACKY AND TEMPORARY!!! */
+Eina_Bool
+elm_gen_type_check(const Evas_Object *obj,
+                   const char        *func)
+{
+   const char *provided, *expected = "(unknown)";
+   static int abort_on_warn = -1;
+   provided = elm_widget_type_get(obj);
+   if (!_genlist) _genlist = eina_stringshare_add("genlist");
+   if (!_gengrid) _gengrid = eina_stringshare_add("gengrid");
+   if (EINA_LIKELY(provided == _genlist) || EINA_LIKELY(provided == _gengrid))
+     return EINA_TRUE;
+   if ((!provided) || (!provided[0]))
+     {
+        provided = evas_object_type_get(obj);
+        if ((!provided) || (!provided[0]))
+          provided = "(unknown)";
+     }
+   ERR("Passing Object: %p in function: %s, of type: '%s' when expecting type: '%s'", obj, func, provided, expected);
+   if (abort_on_warn == -1)
+     {
+        if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
+        else abort_on_warn = 0;
+     }
+   if (abort_on_warn == 1) abort();
+   return EINA_FALSE;
+}
+
+static const char *
+_item_label_hook(Elm_Gen_Item *it, const char *part)
+{
+   if (!it->itc->func.label_get) return NULL;
+   return edje_object_part_text_get(VIEW(it), part);
+}
+
+static Evas_Object *
+_item_content_get_hook(Elm_Gen_Item *it, const char *part)
+{
+   return edje_object_part_swallow_get(VIEW(it), part);
+}
+
+static void
+_item_content_set_hook(Elm_Gen_Item *it, const char *part, Evas_Object *content)
+{
+   edje_object_part_swallow(VIEW(it), part, content);
+}
+
+static Evas_Object *
+_item_content_unset_hook(Elm_Gen_Item *it, const char *part)
+{
+   Evas_Object *obj;
+
+   obj = edje_object_part_swallow_get(VIEW(it), part);
+   if (!obj) return NULL;
+   edje_object_part_unswallow(VIEW(it), obj);
+   return obj;
+}
+
+#if 0
+static Eina_Bool
+_deselect_all_items(Widget_Data *wd)
+{
+   if (!wd->selected) return EINA_FALSE;
+   while (wd->selected)
+     elm_gengrid_item_selected_set(wd->selected->data, EINA_FALSE);
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_item_multi_select_left(Widget_Data *wd)
+{
+   if (!wd->selected) return EINA_FALSE;
+
+   Elm_Gengrid_Item *prev = elm_gengrid_item_prev_get(wd->last_selected_item);
+   if (!prev) return EINA_TRUE;
+   if (elm_gengrid_item_selected_get(prev))
+     {
+        elm_gengrid_item_selected_set(wd->last_selected_item, EINA_FALSE);
+        wd->last_selected_item = prev;
+        elm_gengrid_item_show(wd->last_selected_item);
+     }
+   else
+     {
+        elm_gengrid_item_selected_set(prev, EINA_TRUE);
+        elm_gengrid_item_show(prev);
+     }
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_item_multi_select_right(Widget_Data *wd)
+{
+   if (!wd->selected) return EINA_FALSE;
+
+   Elm_Gengrid_Item *next = elm_gengrid_item_next_get(wd->last_selected_item);
+   if (!next) return EINA_TRUE;
+   if (elm_gengrid_item_selected_get(next))
+     {
+        elm_gengrid_item_selected_set(wd->last_selected_item, EINA_FALSE);
+        wd->last_selected_item = next;
+        elm_gengrid_item_show(wd->last_selected_item);
+     }
+   else
+     {
+        elm_gengrid_item_selected_set(next, EINA_TRUE);
+        elm_gengrid_item_show(next);
+     }
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_item_multi_select_up(Widget_Data *wd)
+{
+   unsigned int i;
+   Eina_Bool r = EINA_TRUE;
+
+   if (!wd->selected) return EINA_FALSE;
+
+   for (i = 0; (r) && (i < wd->nmax); i++)
+     r &= _item_multi_select_left(wd);
+
+   return r;
+}
+
+static Eina_Bool
+_item_multi_select_down(Widget_Data *wd)
+{
+   unsigned int i;
+   Eina_Bool r = EINA_TRUE;
+
+   if (!wd->selected) return EINA_FALSE;
+
+   for (i = 0; (r) && (i < wd->nmax); i++)
+     r &= _item_multi_select_right(wd);
+
+   return r;
+}
+
+static Eina_Bool
+_item_single_select_up(Widget_Data *wd)
+{
+   unsigned int i;
+
+   Elm_Gengrid_Item *prev;
+
+   if (!wd->selected)
+     {
+        prev = ELM_GENGRID_ITEM_FROM_INLIST(wd->items->last);
+        while ((prev) && (prev->delete_me))
+          prev = ELM_GENGRID_ITEM_FROM_INLIST(EINA_INLIST_GET(prev)->prev);
+        elm_gengrid_item_selected_set(prev, EINA_TRUE);
+        elm_gengrid_item_show(prev);
+        return EINA_TRUE;
+     }
+   else prev = elm_gengrid_item_prev_get(wd->last_selected_item);
+
+   if (!prev) return EINA_FALSE;
+
+   for (i = 1; i < wd->nmax; i++)
+     {
+        Elm_Gengrid_Item *tmp = elm_gengrid_item_prev_get(prev);
+        if (!tmp) return EINA_FALSE;
+        prev = tmp;
+     }
+
+   _deselect_all_items(wd);
+
+   elm_gengrid_item_selected_set(prev, EINA_TRUE);
+   elm_gengrid_item_show(prev);
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_item_single_select_down(Widget_Data *wd)
+{
+   unsigned int i;
+
+   Elm_Gengrid_Item *next;
+
+   if (!wd->selected)
+     {
+        next = ELM_GENGRID_ITEM_FROM_INLIST(wd->items);
+        while ((next) && (next->delete_me))
+          next = ELM_GENGRID_ITEM_FROM_INLIST(EINA_INLIST_GET(next)->next);
+        elm_gengrid_item_selected_set(next, EINA_TRUE);
+        elm_gengrid_item_show(next);
+        return EINA_TRUE;
+     }
+   else next = elm_gengrid_item_next_get(wd->last_selected_item);
+
+   if (!next) return EINA_FALSE;
+
+   for (i = 1; i < wd->nmax; i++)
+     {
+        Elm_Gengrid_Item *tmp = elm_gengrid_item_next_get(next);
+        if (!tmp) return EINA_FALSE;
+        next = tmp;
+     }
+
+   _deselect_all_items(wd);
+
+   elm_gengrid_item_selected_set(next, EINA_TRUE);
+   elm_gengrid_item_show(next);
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_item_single_select_left(Widget_Data *wd)
+{
+   Elm_Gengrid_Item *prev;
+   if (!wd->selected)
+     {
+        prev = ELM_GENGRID_ITEM_FROM_INLIST(wd->items->last);
+        while ((prev) && (prev->delete_me))
+          prev = ELM_GENGRID_ITEM_FROM_INLIST(EINA_INLIST_GET(prev)->prev);
+     }
+   else prev = elm_gengrid_item_prev_get(wd->last_selected_item);
+
+   if (!prev) return EINA_FALSE;
+
+   _deselect_all_items(wd);
+
+   elm_gengrid_item_selected_set(prev, EINA_TRUE);
+   elm_gengrid_item_show(prev);
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_item_single_select_right(Widget_Data *wd)
+{
+   Elm_Gengrid_Item *next;
+   if (!wd->selected)
+     {
+        next = ELM_GENGRID_ITEM_FROM_INLIST(wd->items);
+        while ((next) && (next->delete_me))
+          next = ELM_GENGRID_ITEM_FROM_INLIST(EINA_INLIST_GET(next)->next);
+     }
+   else next = elm_gengrid_item_next_get(wd->last_selected_item);
+
+   if (!next) return EINA_FALSE;
+
+   _deselect_all_items(wd);
+
+   elm_gengrid_item_selected_set(next, EINA_TRUE);
+   elm_gengrid_item_show(next);
+   return EINA_TRUE;
+}
+#endif
+
+
+static void
+_item_select(Elm_Gen_Item *it)
+{
+   if ((it->wd->no_select) || (it->delete_me) || (it->mode_set)) return;
+   if (!it->selected)
+     {
+        it->selected = EINA_TRUE;
+        it->wd->selected = eina_list_append(it->wd->selected, it);
+     }
+   else if (!it->wd->always_select) return;
+
+   evas_object_ref(WIDGET(it));
+   it->walking++;
+   it->wd->walking++;
+   if (it->func.func) it->func.func((void *)it->func.data, WIDGET(it), it);
+   if (!it->delete_me)
+     evas_object_smart_callback_call(WIDGET(it), SIG_SELECTED, it);
+   it->walking--;
+   it->wd->walking--;
+   evas_object_unref(WIDGET(it));
+   if ((it->wd->clear_me) && (!it->wd->walking))
+     elm_gen_clear(WIDGET(it));
+   else
+     {
+        if ((!it->walking) && (it->delete_me))
+          {
+             if (!it->relcount) it->del_cb(it);
+          }
+        else
+          it->wd->last_selected_item = it;
+     }
+}
+/******************************************************************************/
+void
+elm_gen_item_unrealize(Elm_Gen_Item *it,
+                       Eina_Bool     calc)
+{
+   Evas_Object *content;
+
+   if (!it->realized) return;
+   if (it->wd->reorder_it == it) return;
+   evas_event_freeze(evas_object_evas_get(WIDGET(it)));
+   if (!calc)
+     evas_object_smart_callback_call(WIDGET(it), SIG_UNREALIZED, it);
+   if (it->long_timer)
+     {
+        ecore_timer_del(it->long_timer);
+        it->long_timer = NULL;
+     }
+
+   elm_widget_stringlist_free(it->labels);
+   it->labels = NULL;
+   elm_widget_stringlist_free(it->contents);
+   it->contents = NULL;
+   elm_widget_stringlist_free(it->states);
+   it->states = NULL;
+
+   EINA_LIST_FREE(it->content_objs, content)
+     evas_object_del(content);
+
+   it->unrealize_cb(it);
+
+   it->realized = EINA_FALSE;
+   it->want_unrealize = EINA_FALSE;
+   evas_event_thaw(evas_object_evas_get(WIDGET(it)));
+   evas_event_thaw_eval(evas_object_evas_get(WIDGET(it)));
+}
+
+void
+elm_gen_item_del_notserious(Elm_Gen_Item *it)
+{
+   elm_widget_item_pre_notify_del(it);
+   it->delete_me = EINA_TRUE;
+   if (it->selected) it->wd->selected = eina_list_remove(it->wd->selected, it);
+
+   if (it->itc->func.del)
+     it->itc->func.del((void *)it->base.data, WIDGET(it));
+}
+
+void
+elm_gen_item_del_serious(Elm_Gen_Item *it)
+{
+   elm_gen_item_del_notserious(it);
+   it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
+   if (it->tooltip.del_cb)
+     it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it);
+   it->wd->walking -= it->walking;
+   if (it->long_timer) ecore_timer_del(it->long_timer);
+   if (it->group)
+     it->wd->group_items = eina_list_remove(it->wd->group_items, it);
+
+   if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
+   it->wd->calc_job = ecore_job_add(it->wd->calc_cb, it->wd);
+   free(it->item);
+   it->item = NULL;
+   elm_widget_item_del(it);
+}
+
+Elm_Gen_Item *
+elm_gen_item_new(Widget_Data              *wd,
+                 const Elm_Gen_Item_Class *itc,
+                 const void               *data,
+                 Elm_Gen_Item             *parent,
+                 Evas_Smart_Cb             func,
+                 const void               *func_data)
+{
+   Elm_Gen_Item *it;
+
+   it = elm_widget_item_new(wd->obj, Elm_Gen_Item);
+   if (!it) return NULL;
+   it->wd = wd;
+   it->itc = itc;
+   it->base.data = data;
+   it->parent = parent;
+   it->func.func = func;
+   it->func.data = func_data;
+   elm_widget_item_content_get_hook_set(it, _item_content_get_hook);
+   elm_widget_item_content_set_hook_set(it, _item_content_set_hook);
+   elm_widget_item_content_unset_hook_set(it, _item_content_unset_hook);
+   /* TEMPORARY */
+   it->sel_cb = (Ecore_Cb)_item_select;
+
+   elm_widget_item_text_get_hook_set(it, _item_label_hook);
+   return it;
+}
+/******************************************************************************/
+
+EAPI void
+elm_gen_item_selected_set(Elm_Gen_Item *it,
+                          Eina_Bool     selected)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
+   Widget_Data *wd = it->wd;
+   if (!wd) return;
+   if ((it->delete_me) || (it->disabled)) return;
+   selected = !!selected;
+   if (it->selected == selected) return;
+
+   if (selected)
+     {
+        if (!wd->multi)
+          {
+             while (wd->selected)
+               {
+                  if (it->unhighlight_cb) it->unhighlight_cb(wd->selected->data);
+                  it->unsel_cb(wd->selected->data);
+               }
+          }
+        it->highlight_cb(it);
+        _item_select(it);
+        return;
+     }
+   if (it->unhighlight_cb) it->unhighlight_cb(it);
+   it->unsel_cb(it);
+}
+
+EAPI void
+elm_gen_clear(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+
+   if (wd->state)
+     {
+        eina_inlist_sorted_state_free(wd->state);
+        wd->state = NULL;
+     }
+
+   if (wd->walking > 0)
+     {
+        Elm_Gen_Item *it;
+        wd->clear_me = 1;
+        EINA_INLIST_FOREACH(wd->items, it)
+           it->delete_me = 1;
+        return;
+     }
+   evas_event_freeze(evas_object_evas_get(wd->obj));
+   while (wd->items)
+     {
+        Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(wd->items);
+        it->del_cb(it);
+     }
+   wd->clear_me = 0;
+   if (wd->calc_job)
+     {
+        ecore_job_del(wd->calc_job);
+        wd->calc_job = NULL;
+     }
+   if (wd->selected) wd->selected = eina_list_free(wd->selected);
+   if (wd->clear_cb) wd->clear_cb(wd);
+   wd->pan_x = 0;
+   wd->pan_y = 0;
+   wd->minw = 0;
+   wd->minh = 0;
+   wd->count = 0;
+   if (wd->pan_smart)
+     {
+        evas_object_size_hint_min_set(wd->pan_smart, wd->minw, wd->minh);
+        evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
+     }
+   if (wd->sizing_cb) wd->sizing_cb(wd->obj);
+   elm_smart_scroller_child_region_show(wd->scr, 0, 0, 0, 0);
+   evas_event_thaw(evas_object_evas_get(wd->obj));
+   evas_event_thaw_eval(evas_object_evas_get(wd->obj));
+}
+
+EAPI Eina_Bool
+elm_gen_item_selected_get(const Elm_Gen_Item *it)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
+   return it->selected;
+}
+
+EAPI void
+elm_gen_always_select_mode_set(Evas_Object *obj,
+                                   Eina_Bool    always_select)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->always_select = always_select;
+}
+
+EAPI Eina_Bool
+elm_gen_always_select_mode_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   return wd->always_select;
+}
+
+EAPI void
+elm_gen_no_select_mode_set(Evas_Object *obj,
+                               Eina_Bool    no_select)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->no_select = no_select;
+}
+
+EAPI Eina_Bool
+elm_gen_no_select_mode_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   return wd->no_select;
+}
+
+EAPI void
+elm_gen_bounce_set(Evas_Object *obj,
+                       Eina_Bool    h_bounce,
+                       Eina_Bool    v_bounce)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_smart_scroller_bounce_allow_set(wd->scr, h_bounce, v_bounce);
+   wd->h_bounce = h_bounce;
+   wd->v_bounce = v_bounce;
+}
+
+EAPI void
+elm_gen_bounce_get(const Evas_Object *obj,
+                       Eina_Bool         *h_bounce,
+                       Eina_Bool         *v_bounce)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (h_bounce) *h_bounce = wd->h_bounce;
+   if (v_bounce) *v_bounce = wd->v_bounce;
+}
+
+EAPI void
+elm_gen_page_relative_set(Evas_Object *obj,
+                              double       h_pagerel,
+                              double       v_pagerel)
+{
+   Evas_Coord pagesize_h;
+   Evas_Coord pagesize_v;
+
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+
+   elm_smart_scroller_paging_get(wd->scr, NULL, NULL, &pagesize_h, &pagesize_v);
+   elm_smart_scroller_paging_set(wd->scr, h_pagerel, v_pagerel, pagesize_h,
+                                 pagesize_v);
+}
+
+EAPI void
+elm_gen_page_relative_get(const Evas_Object *obj, double *h_pagerel, double *v_pagerel)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+
+   elm_smart_scroller_paging_get(wd->scr, h_pagerel, v_pagerel, NULL, NULL);
+}
+
+EAPI void
+elm_gen_page_size_set(Evas_Object *obj,
+                          Evas_Coord   h_pagesize,
+                          Evas_Coord   v_pagesize)
+{
+   double pagerel_h;
+   double pagerel_v;
+
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_smart_scroller_paging_get(wd->scr, &pagerel_h, &pagerel_v, NULL, NULL);
+   elm_smart_scroller_paging_set(wd->scr, pagerel_h, pagerel_v, h_pagesize,
+                                 v_pagesize);
+}
+
+EAPI void
+elm_gen_current_page_get(const Evas_Object *obj, int *h_pagenumber, int *v_pagenumber)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->scr)
+     elm_smart_scroller_current_page_get(wd->scr, h_pagenumber, v_pagenumber);
+}
+
+EAPI void
+elm_gen_last_page_get(const Evas_Object *obj, int *h_pagenumber, int *v_pagenumber)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->scr)
+     elm_smart_scroller_last_page_get(wd->scr, h_pagenumber, v_pagenumber);
+}
+
+EAPI void
+elm_gen_page_show(const Evas_Object *obj, int h_pagenumber, int v_pagenumber)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->scr)
+     elm_smart_scroller_page_show(wd->scr, h_pagenumber, v_pagenumber);
+}
+
+EAPI void
+elm_gen_page_bring_in(const Evas_Object *obj, int h_pagenumber, int v_pagenumber)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->scr)
+     elm_smart_scroller_page_bring_in(wd->scr, h_pagenumber, v_pagenumber);
+}
+
+EAPI Elm_Gen_Item *
+elm_gen_first_item_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   if (!wd->items) return NULL;
+   Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(wd->items);
+   while ((it) && (it->delete_me))
+     it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
+   return it;
+}
+
+EAPI Elm_Gen_Item *
+elm_gen_last_item_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   if (!wd->items) return NULL;
+   Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(wd->items->last);
+   while ((it) && (it->delete_me))
+     it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
+   return it;
+}
+
+EAPI Elm_Gen_Item *
+elm_gen_item_next_get(const Elm_Gen_Item *it)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
+   while (it)
+     {
+        it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
+        if ((it) && (!it->delete_me)) break;
+     }
+   return (Elm_Gen_Item *)it;
+}
+
+EAPI Elm_Gen_Item *
+elm_gen_item_prev_get(const Elm_Gen_Item *it)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
+   while (it)
+     {
+        it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
+        if ((it) && (!it->delete_me)) break;
+     }
+   return (Elm_Gen_Item *)it;
+}
+
+EAPI Evas_Object *
+elm_gen_item_widget_get(const Elm_Gen_Item *it)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
+   return WIDGET(it);
+}
diff --git a/src/lib/elm_gen.h b/src/lib/elm_gen.h
new file mode 100644 (file)
index 0000000..e36af59
--- /dev/null
@@ -0,0 +1,84 @@
+#include <Elementary.h>
+#include <Elementary_Cursor.h>
+#include "elm_priv.h"
+
+#define ELM_GEN_ITEM_FROM_INLIST(it) \
+   ((it) ? EINA_INLIST_CONTAINER_GET(it, Elm_Gen_Item) : NULL)
+
+typedef struct Elm_Gen_Item_Type Elm_Gen_Item_Type;
+typedef struct Elm_Gen_Item_Tooltip Elm_Gen_Item_Tooltip;
+typedef struct _Widget_Data Widget_Data;
+typedef struct _Pan Pan;
+
+struct Elm_Gen_Item_Tooltip
+{
+   const void                 *data;
+   Elm_Tooltip_Item_Content_Cb content_cb;
+   Evas_Smart_Cb               del_cb;
+   const char                 *style;
+   Eina_Bool                   free_size : 1;
+};
+
+struct _Pan
+{
+   Evas_Object_Smart_Clipped_Data __clipped_data;
+   Widget_Data                   *wd;
+   Ecore_Job                     *resize_job;
+};
+
+struct Elm_Gen_Item
+{
+   ELM_WIDGET_ITEM;
+   EINA_INLIST;
+   Widget_Data                  *wd;
+   Elm_Gen_Item_Type            *item;
+   const Elm_Gen_Item_Class     *itc;
+   Evas_Coord                    x, y, dx, dy;
+   Evas_Object                  *spacer;
+   Elm_Gen_Item                 *parent;
+   Eina_List                    *labels, *contents, *states, *content_objs;
+   Ecore_Timer                  *long_timer;
+   int                           relcount;
+   int                           walking;
+   const char                   *mouse_cursor;
+
+   struct
+   {
+      Evas_Smart_Cb func;
+      const void   *data;
+   } func;
+
+   Elm_Gen_Item_Tooltip tooltip;
+   Ecore_Cb    del_cb, sel_cb, highlight_cb;
+   Ecore_Cb    unsel_cb, unhighlight_cb, unrealize_cb;
+
+   Eina_Bool   want_unrealize : 1;
+   Eina_Bool   display_only : 1;
+   Eina_Bool   realized : 1;
+   Eina_Bool   selected : 1;
+   Eina_Bool   highlighted : 1;
+   Eina_Bool   disabled : 1;
+   Eina_Bool   dragging : 1;
+   Eina_Bool   delete_me : 1;
+   Eina_Bool   down : 1;
+   Eina_Bool   group : 1;
+   Eina_Bool   reorder : 1;
+   Eina_Bool   mode_set : 1; /* item uses style mode for highlight/select */
+};
+
+Elm_Gen_Item *
+elm_gen_item_new(Widget_Data              *wd,
+                 const Elm_Gen_Item_Class *itc,
+                 const void               *data,
+                 Elm_Gen_Item             *parent,
+                 Evas_Smart_Cb             func,
+                 const void               *func_data);
+
+void
+elm_gen_item_unrealize(Elm_Gen_Item *it,
+                       Eina_Bool     calc);
+void
+elm_gen_item_del_serious(Elm_Gen_Item *it);
+
+void
+elm_gen_item_del_notserious(Elm_Gen_Item *it);
diff --git a/src/lib/elm_web.c b/src/lib/elm_web.c
new file mode 100644 (file)
index 0000000..b230f2e
--- /dev/null
@@ -0,0 +1,1840 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+// TODO:
+//  1 - easy to use zoom like elm_photocam API
+//  2 - review scrolling to match elm_scroller. Maybe in future use elm_scroller
+
+#ifdef HAVE_ELEMENTARY_WEB
+#include <EWebKit.h>
+
+/* Similar to iPhone */
+// TODO: switch between iPhone, iPad or Chrome/Safari based on some elm setting?
+#define ELM_WEB_USER_AGENT "Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A543a Safari/419.3 " PACKAGE_NAME "/" PACKAGE_VERSION
+
+static Ewk_View_Smart_Class _parent_sc = EWK_VIEW_SMART_CLASS_INIT_NULL;
+
+typedef struct _View_Smart_Data View_Smart_Data;
+struct _View_Smart_Data
+{
+   Ewk_View_Smart_Data base;
+   struct {
+      Evas_Event_Mouse_Down event;
+      Evas_Coord x, y;
+      unsigned int move_count;
+      Ecore_Timer *longpress_timer;
+      Ecore_Animator *pan_anim;
+   } mouse;
+};
+#endif
+
+typedef struct _Widget_Data Widget_Data;
+struct _Widget_Data
+{
+   Evas_Object *self;
+#ifdef HAVE_ELEMENTARY_WEB
+   Evas_Object *ewk_view;
+   struct {
+      Elm_Web_Window_Open window_create;
+      void *window_create_data;
+      Elm_Web_Dialog_Alert alert;
+      void *alert_data;
+      Elm_Web_Dialog_Confirm confirm;
+      void *confirm_data;
+      Elm_Web_Dialog_Prompt prompt;
+      void *prompt_data;
+      Elm_Web_Dialog_File_Selector file_selector;
+      void *file_selector_data;
+      Elm_Web_Console_Message console_message;
+      void *console_message_data;
+   } hook;
+   Elm_Win_Keyboard_Mode input_method;
+   struct {
+        Elm_Web_Zoom_Mode mode;
+        float current;
+        float min, max;
+        Eina_Bool no_anim;
+        Ecore_Timer *timer;
+   } zoom;
+   struct {
+        struct {
+             int x, y;
+        } start, end;
+        Ecore_Animator *animator;
+   } bring_in;
+   Eina_Bool tab_propagate : 1;
+   Eina_Bool inwin_mode : 1;
+#else
+   Evas_Object *label;
+#endif
+};
+
+enum Dialog_Type
+{
+   DIALOG_ALERT,
+   DIALOG_CONFIRM,
+   DIALOG_PROMPT,
+   DIALOG_FILE_SELECTOR
+};
+
+typedef struct _Dialog_Data Dialog_Data;
+struct _Dialog_Data
+{
+   enum Dialog_Type type;
+   Evas_Object *dialog;
+   Evas_Object *box;
+   Evas_Object *bt_ok, *bt_cancel;
+   Evas_Object *entry;
+   Evas_Object *file_sel;
+
+   Eina_Bool   *response;
+   char       **entry_value;
+   Eina_List  **selected_files;
+};
+
+struct _Elm_Web_Callback_Proxy_Context
+{
+   const char *name;
+   Evas_Object *obj;
+};
+typedef struct _Elm_Web_Callback_Proxy_Context Elm_Web_Callback_Proxy_Context;
+
+static const char *widtype = NULL;
+static const Evas_Smart_Cb_Description _elm_web_callback_names[] = {
+   { "download,request", "p" },
+   { "editorclient,contents,changed", "" },
+   { "editorclient,selection,changed", "" },
+   { "frame,created", "p" },
+   { "icon,received", "" },
+   { "inputmethod,changed", "b" },
+   { "js,windowobject,clear", "" },
+   { "link,hover,in", "p" },
+   { "link,hover,out", "" },
+   { "load,document,finished", "p" },
+   { "load,error", "p" },
+   { "load,finished", "p" },
+   { "load,newwindow,show", "" },
+   { "load,progress", "d" },
+   { "load,provisional", "" },
+   { "load,started", "" },
+   { "menubar,visible,get", "b" },
+   { "menubar,visible,set", "b" },
+   { "popup,created", "p" },
+   { "popup,willdelete", "p" },
+   { "ready", "" },
+   { "scrollbars,visible,get", "b" },
+   { "scrollbars,visible,set", "b" },
+   { "statusbar,text,set", "s" },
+   { "statusbar,visible,get", "b" },
+   { "statusbar,visible,set", "b" },
+   { "title,changed", "s" },
+   { "toolbars,visible,get", "b" },
+   { "toolbars,visible,set", "b" },
+   { "tooltip,text,set", "s" },
+   { "uri,changed", "s" },
+   { "view,resized", "" },
+   { "windows,close,request", ""},
+   { "zoom,animated,end", "" },
+   { NULL, NULL }
+};
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+#ifdef HAVE_ELEMENTARY_WEB
+   Elm_Theme *theme = elm_object_theme_get(obj);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   const Eina_List *themes, *l;
+   const char *th;
+   char *view_theme = NULL;
+
+   themes = elm_theme_list_get(theme);
+   EINA_LIST_FOREACH(themes, l, th)
+     {
+        char *path = elm_theme_list_item_path_get(th, NULL);
+        if (!path) continue;
+        if (edje_file_group_exists(path, "webkit/base"))
+          {
+             view_theme = path;
+             break;
+          }
+        free(path);
+     }
+
+   if (view_theme)
+     {
+        ewk_view_theme_set(wd->ewk_view, view_theme);
+        free(view_theme);
+     }
+   else
+     ewk_view_theme_set(wd->ewk_view, WEBKIT_DATADIR"/themes/default.edj");
+#else
+   (void)obj;
+#endif
+}
+
+static void
+_on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
+{
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Object *top = elm_widget_top_get(obj);
+
+   if (!wd) return;
+
+   if (elm_object_focus_get(obj))
+     {
+        evas_object_focus_set(wd->ewk_view, EINA_TRUE);
+        if (top) elm_win_keyboard_mode_set(top, wd->input_method);
+     }
+   else
+     {
+        evas_object_focus_set(wd->ewk_view, EINA_FALSE);
+        if (top) elm_win_keyboard_mode_set(top, ELM_WIN_KEYBOARD_OFF);
+     }
+#else
+   (void)obj;
+#endif
+}
+
+static Eina_Bool
+_event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
+{
+#ifdef HAVE_ELEMENTARY_WEB
+   Evas_Event_Key_Down *ev = event_info;
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return EINA_FALSE;
+   if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
+   if (elm_widget_disabled_get(obj)) return EINA_FALSE;
+
+   if ((!strcmp(ev->keyname, "Tab")) && (!wd->tab_propagate))
+     {
+        ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+        return EINA_TRUE;
+     }
+   else
+     return EINA_FALSE;
+#else
+   return EINA_FALSE;
+   (void)obj;
+   (void)type;
+   (void)event_info;
+#endif
+}
+
+#ifdef HAVE_ELEMENTARY_WEB
+static Eina_Bool
+_view_pan_animator(void *data)
+{
+   View_Smart_Data *sd = data;
+   Evas_Coord x, y, dx, dy;
+
+   evas_pointer_canvas_xy_get(sd->base.base.evas, &x, &y);
+
+   dx = sd->mouse.x - x;
+   dy = sd->mouse.y - y;
+
+   if ((dx == 0) && (dy == 0))
+     goto end;
+
+   ewk_frame_scroll_add(sd->base.main_frame, dx, dy);
+
+   sd->mouse.x = x;
+   sd->mouse.y = y;
+
+ end:
+   return EINA_TRUE;
+}
+
+static void
+_view_smart_add(Evas_Object *obj)
+{
+   View_Smart_Data *sd;
+
+   sd = calloc(1, sizeof(View_Smart_Data));
+   evas_object_smart_data_set(obj, sd);
+
+   _parent_sc.sc.add(obj);
+
+   ewk_view_history_enable_set(obj, EINA_TRUE);
+   ewk_history_limit_set(ewk_view_history_get(obj), 100);
+   // TODO: auto toggle between smooth/nearest during bring-in animations
+   //ewk_view_zoom_weak_smooth_scale_set(obj, EINA_TRUE);
+}
+
+static void
+_view_smart_del(Evas_Object *obj)
+{
+   View_Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+
+   if (sd->mouse.pan_anim)
+     ecore_animator_del(sd->mouse.pan_anim);
+
+   _parent_sc.sc.del(obj);
+}
+
+static Eina_Bool
+_view_longpress_timer(void *data)
+{
+   View_Smart_Data *sd = data;
+
+   sd->mouse.move_count = 0;
+   sd->mouse.longpress_timer = NULL;
+   return ECORE_CALLBACK_CANCEL;
+}
+
+static Eina_Bool
+_view_smart_mouse_down(Ewk_View_Smart_Data *esd, const Evas_Event_Mouse_Down *event)
+{
+   // TODO: mimic elm_scroller and like
+   // TODO-minor: offer hook?
+   View_Smart_Data *sd = (View_Smart_Data *)esd;
+
+   if (event->button != 1)
+     return _parent_sc.mouse_down(esd, event);
+
+   sd->mouse.pan_anim = ecore_animator_add(_view_pan_animator, sd);
+   sd->mouse.longpress_timer = ecore_timer_add(_elm_config->longpress_timeout, _view_longpress_timer, sd);
+   sd->mouse.move_count = 1;
+   sd->mouse.x = event->canvas.x;
+   sd->mouse.y = event->canvas.y;
+   sd->mouse.event = *event;
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_view_smart_mouse_up(Ewk_View_Smart_Data *esd, const Evas_Event_Mouse_Up *event)
+{
+   // TODO: mimic elm_scroller and like
+   // TODO-minor: offer hook?
+   View_Smart_Data *sd = (View_Smart_Data *)esd;
+
+   if (sd->mouse.pan_anim)
+     {
+        ecore_animator_del(sd->mouse.pan_anim);
+        sd->mouse.pan_anim = NULL;
+
+        if (sd->mouse.longpress_timer)
+          _parent_sc.mouse_down(esd, &sd->mouse.event);
+        else
+          return EINA_TRUE;
+     }
+
+   if (sd->mouse.longpress_timer)
+     {
+        ecore_timer_del(sd->mouse.longpress_timer);
+        sd->mouse.longpress_timer = NULL;
+     }
+
+   sd->mouse.move_count = 0;
+   return _parent_sc.mouse_up(esd, event);
+}
+
+static Eina_Bool
+_view_smart_mouse_move(Ewk_View_Smart_Data *esd, const Evas_Event_Mouse_Move *event)
+{
+   // TODO: mimic elm_scroller and like
+   // TODO-minor: offer hook?
+   View_Smart_Data *sd = (View_Smart_Data *)esd;
+   sd->mouse.move_count++;
+
+   if (sd->mouse.longpress_timer &&
+       (((sd->mouse.x ^ sd->mouse.event.canvas.x) |
+         (sd->mouse.y ^ sd->mouse.event.canvas.y)) & (~0x07)))
+     {
+        ecore_timer_del(sd->mouse.longpress_timer);
+        sd->mouse.longpress_timer = NULL;
+     }
+
+   if (sd->mouse.pan_anim)
+     {
+        return EINA_FALSE;
+     }
+
+   return _parent_sc.mouse_move(esd, event);
+}
+
+static Evas_Object *
+_view_smart_window_create(Ewk_View_Smart_Data *sd, Eina_Bool javascript, const Ewk_Window_Features *window_features)
+{
+   Evas_Object *new;
+   Evas_Object *obj = evas_object_smart_parent_get(sd->self);
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd->hook.window_create) return NULL;
+   new = wd->hook.window_create(wd->hook.window_create_data, obj, javascript,
+                        (const Elm_Web_Window_Features *)window_features);
+   if (new) return elm_web_webkit_view_get(new);
+
+   return NULL;
+}
+
+static void
+_view_smart_window_close(Ewk_View_Smart_Data *sd)
+{
+   Evas_Object *obj = evas_object_smart_parent_get(sd->self);
+   evas_object_smart_callback_call(obj, "windows,close,request", NULL);
+}
+
+static void
+_bt_close(void *data, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Dialog_Data *d = data;
+
+   *d->response = (obj == d->bt_ok);
+   if ((d->type == DIALOG_PROMPT) && (*d->response == EINA_TRUE))
+     *d->entry_value = strdup(elm_entry_entry_get(d->entry));
+   evas_object_del(d->dialog);
+}
+
+static void
+_file_sel_done(void *data, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Dialog_Data *d = data;
+   if (event_info)
+     {
+        *d->selected_files = eina_list_append(NULL, strdup(event_info));
+        *d->response = EINA_TRUE;
+     }
+   else
+     *d->response = EINA_FALSE;
+   evas_object_del(d->dialog);
+   free(d);
+}
+
+static Dialog_Data *
+_dialog_new(Evas_Object *parent)
+{
+   Dialog_Data *d;
+   Widget_Data *wd = elm_widget_data_get(parent);
+
+   d = calloc(1, sizeof(Dialog_Data));
+   if (!d) return NULL;
+
+   if (!parent || wd->inwin_mode)
+     {
+        Evas_Object *bg;
+
+        d->dialog = elm_win_add(NULL, "elm-web-popup", ELM_WIN_DIALOG_BASIC);
+        evas_object_smart_callback_add(d->dialog, "delete,request",
+                                       _bt_close, d);
+
+        bg = elm_bg_add(d->dialog);
+        evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND,
+                                         EVAS_HINT_EXPAND);
+        elm_win_resize_object_add(d->dialog, bg);
+        evas_object_show(bg);
+
+        d->box = elm_box_add(d->dialog);
+        evas_object_size_hint_weight_set(d->box, EVAS_HINT_EXPAND,
+                                         EVAS_HINT_EXPAND);
+        elm_win_resize_object_add(d->dialog, d->box);
+        evas_object_show(d->box);
+     }
+   else
+     {
+        Evas_Object *win = elm_widget_top_get(parent);
+        d->dialog = elm_win_inwin_add(win);
+        elm_object_style_set(d->dialog, "minimal");
+        evas_object_size_hint_weight_set(d->dialog, EVAS_HINT_EXPAND,
+                                         EVAS_HINT_EXPAND);
+
+        d->box = elm_box_add(win);
+        evas_object_size_hint_weight_set(d->box, EVAS_HINT_EXPAND,
+                                         EVAS_HINT_EXPAND);
+        elm_win_inwin_content_set(d->dialog, d->box);
+        evas_object_show(d->box);
+     }
+
+   return d;
+}
+
+static Evas_Object *
+_run_dialog(Evas_Object *parent, enum Dialog_Type type, const char *message, const char *default_entry_value, char **entry_value, Eina_Bool allows_multiple_files __UNUSED__, Eina_List *accept_types __UNUSED__, Eina_List **selected_filenames, Eina_Bool *response)
+{
+   EINA_SAFETY_ON_TRUE_RETURN_VAL((type != DIALOG_PROMPT) && (!!default_entry_value), EINA_FALSE);
+   EINA_SAFETY_ON_TRUE_RETURN_VAL((type != DIALOG_PROMPT) && (!!entry_value), EINA_FALSE);
+
+   Dialog_Data *dialog_data = _dialog_new(evas_object_smart_parent_get(parent));
+   Evas_Object *lb;
+
+   if (type != DIALOG_FILE_SELECTOR)
+     {
+        lb = elm_label_add(dialog_data->box);
+        elm_object_text_set(lb, message);
+        elm_box_pack_end(dialog_data->box, lb);
+        evas_object_show(lb);
+     }
+
+   dialog_data->type = type;
+   dialog_data->response = response;
+   dialog_data->entry_value = entry_value;
+   dialog_data->selected_files = selected_filenames;
+
+   if (type == DIALOG_ALERT)
+     {
+        dialog_data->bt_ok = elm_button_add(dialog_data->box);
+        elm_object_text_set(dialog_data->bt_ok, "Close");
+        elm_box_pack_end(dialog_data->box, dialog_data->bt_ok);
+        evas_object_size_hint_align_set(dialog_data->bt_ok, EVAS_HINT_FILL, EVAS_HINT_FILL);
+        evas_object_smart_callback_add(dialog_data->bt_ok, "clicked", _bt_close, dialog_data);
+        evas_object_show(dialog_data->bt_ok);
+     }
+   else if (type == DIALOG_FILE_SELECTOR)
+     {
+        dialog_data->file_sel = elm_fileselector_add(dialog_data->dialog);
+        evas_object_size_hint_weight_set(dialog_data->file_sel,
+                                         EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+        evas_object_size_hint_align_set(dialog_data->file_sel, EVAS_HINT_FILL,
+                                        EVAS_HINT_FILL);
+        elm_box_pack_end(dialog_data->box, dialog_data->file_sel);
+        evas_object_show(dialog_data->file_sel);
+
+        elm_fileselector_path_set(dialog_data->file_sel, ".");
+        elm_fileselector_is_save_set(dialog_data->file_sel, EINA_FALSE);
+        elm_fileselector_folder_only_set(dialog_data->file_sel, EINA_FALSE);
+        elm_fileselector_buttons_ok_cancel_set(dialog_data->file_sel,
+                                               EINA_TRUE);
+        elm_fileselector_expandable_set(dialog_data->file_sel, EINA_FALSE);
+        evas_object_smart_callback_add(dialog_data->file_sel, "done",
+                                       _file_sel_done, dialog_data);
+        // fileselector can't set it's minimum size correctly
+        evas_object_size_hint_min_set(dialog_data->file_sel, 300, 400);
+     }
+   else
+     {
+        if (type == DIALOG_PROMPT)
+          {
+             dialog_data->entry = elm_entry_add(dialog_data->box);
+             elm_entry_single_line_set(dialog_data->entry, EINA_TRUE);
+             elm_entry_scrollable_set(dialog_data->entry, EINA_TRUE);
+             elm_entry_entry_set(dialog_data->entry, default_entry_value);
+             evas_object_size_hint_align_set(dialog_data->entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
+             evas_object_size_hint_weight_set(dialog_data->entry, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+             elm_box_pack_end(dialog_data->box, dialog_data->entry);
+             evas_object_show(dialog_data->entry);
+          }
+
+        if (type == DIALOG_PROMPT || type == DIALOG_CONFIRM)
+          {
+             Evas_Object *bx_h = elm_box_add(dialog_data->box);
+             elm_box_horizontal_set(bx_h, 1);
+             elm_box_pack_end(dialog_data->box, bx_h);
+             evas_object_size_hint_weight_set(bx_h, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+             evas_object_size_hint_align_set(bx_h, EVAS_HINT_FILL, EVAS_HINT_FILL);
+             evas_object_show(bx_h);
+
+             dialog_data->bt_cancel = elm_button_add(bx_h);
+             elm_object_text_set(dialog_data->bt_cancel, "Cancel");
+             elm_box_pack_end(bx_h, dialog_data->bt_cancel);
+             evas_object_size_hint_weight_set(dialog_data->bt_cancel, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+             evas_object_size_hint_align_set(dialog_data->bt_cancel, EVAS_HINT_FILL, EVAS_HINT_FILL);
+             evas_object_smart_callback_add(dialog_data->bt_cancel, "clicked", _bt_close, dialog_data);
+             evas_object_show(dialog_data->bt_cancel);
+
+             dialog_data->bt_ok = elm_button_add(bx_h);
+             elm_object_text_set(dialog_data->bt_ok, "Ok");
+             elm_box_pack_end(bx_h, dialog_data->bt_ok);
+             evas_object_size_hint_weight_set(dialog_data->bt_ok, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+             evas_object_size_hint_align_set(dialog_data->bt_ok, EVAS_HINT_FILL, EVAS_HINT_FILL);
+             evas_object_smart_callback_add(dialog_data->bt_ok, "clicked", _bt_close, dialog_data);
+             evas_object_show(dialog_data->bt_ok);
+          }
+        else
+           return EINA_FALSE;
+     }
+
+   evas_object_show(dialog_data->dialog);
+
+   return dialog_data->dialog;
+}
+
+static void
+_dialog_del_cb(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   ecore_main_loop_quit();
+}
+
+static void
+_exec_dialog(Evas_Object *dialog)
+{
+   evas_object_event_callback_add(dialog, EVAS_CALLBACK_DEL, _dialog_del_cb,
+                                  NULL);
+   ecore_main_loop_begin();
+}
+
+/* called by ewk_view when javascript called alert()
+ *
+ */
+static void
+_view_smart_run_javascript_alert(Ewk_View_Smart_Data *esd, Evas_Object *frame __UNUSED__, const char *message)
+{
+   View_Smart_Data *sd = (View_Smart_Data *)esd;
+   Evas_Object *view = sd->base.self;
+   Evas_Object *obj = evas_object_smart_parent_get(view);
+   Evas_Object *diag = NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Eina_Bool response = EINA_FALSE;
+
+   if (wd->hook.alert)
+     diag = wd->hook.alert(wd->hook.alert_data, obj, message);
+   else
+     diag = _run_dialog(view, DIALOG_ALERT, message, NULL, NULL, EINA_FALSE,
+                        NULL, NULL, &response);
+   if (diag) _exec_dialog(diag);
+}
+
+/* called by ewk_view when javascript called confirm()
+ *
+ */
+static Eina_Bool
+_view_smart_run_javascript_confirm(Ewk_View_Smart_Data *esd, Evas_Object *frame __UNUSED__, const char *message)
+{
+   View_Smart_Data *sd = (View_Smart_Data *)esd;
+   Evas_Object *view = sd->base.self;
+   Evas_Object *obj = evas_object_smart_parent_get(view);
+   Evas_Object *diag = NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Eina_Bool response = EINA_FALSE;
+
+   if (wd->hook.confirm)
+     diag = wd->hook.confirm(wd->hook.confirm_data, obj, message, &response);
+   else
+    diag = _run_dialog(view, DIALOG_CONFIRM, message, NULL, NULL, EINA_FALSE,
+                       NULL, NULL, &response);
+   if (diag) _exec_dialog(diag);
+   return response;
+}
+
+/* called by ewk_view when javascript called confirm()
+ *
+ */
+static Eina_Bool
+_view_smart_run_javascript_prompt(Ewk_View_Smart_Data *esd, Evas_Object *frame __UNUSED__, const char *message, const char *default_value, char **value)
+{
+   View_Smart_Data *sd = (View_Smart_Data *)esd;
+   Evas_Object *view = sd->base.self;
+   Evas_Object *obj = evas_object_smart_parent_get(view);
+   Evas_Object *diag = NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Eina_Bool response = EINA_FALSE;
+
+   if (wd->hook.prompt)
+     diag = wd->hook.prompt(wd->hook.prompt_data, obj, message, default_value,
+                            value, &response);
+   else
+     diag = _run_dialog(view, DIALOG_PROMPT, message, default_value, value,
+                        EINA_FALSE, NULL, NULL, &response);
+   if (diag) _exec_dialog(diag);
+   if (!response)
+      *value = NULL;
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_view_smart_run_open_panel(Ewk_View_Smart_Data *esd, Evas_Object *frame __UNUSED__, Eina_Bool allows_multiple_files, Eina_List *accept_types, Eina_List **selected_filenames)
+{
+   View_Smart_Data *sd = (View_Smart_Data *)esd;
+   Evas_Object *view = sd->base.self;
+   Evas_Object *obj = evas_object_smart_parent_get(view);
+   Evas_Object *diag = NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Eina_Bool response = EINA_FALSE;
+
+   if (wd->hook.file_selector)
+     diag = wd->hook.file_selector(wd->hook.file_selector_data, obj,
+                                   allows_multiple_files, accept_types,
+                                   selected_filenames, &response);
+   else
+     diag = _run_dialog(view, DIALOG_FILE_SELECTOR, NULL, NULL, NULL,
+                        allows_multiple_files, accept_types, selected_filenames,
+                        &response);
+   if (diag) _exec_dialog(diag);
+
+   return response;
+}
+
+static void
+_view_smart_add_console_message(Ewk_View_Smart_Data *esd, const char *message, unsigned int line_number, const char *source_id)
+{
+   Evas_Object *obj = evas_object_smart_parent_get(esd->self);
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (wd->hook.console_message)
+     wd->hook.console_message(wd->hook.console_message_data, obj, message,
+                              line_number, source_id);
+}
+
+static Eina_Bool
+_view_smart_focus_can_cycle(Ewk_View_Smart_Data *sd, Ewk_Focus_Direction direction)
+{
+   Evas_Object *obj = evas_object_smart_parent_get(sd->self);
+   Elm_Focus_Direction dir;
+
+   switch (direction)
+     {
+      case EWK_FOCUS_DIRECTION_FORWARD:
+         dir = ELM_FOCUS_NEXT;
+         break;
+      case EWK_FOCUS_DIRECTION_BACKWARD:
+         dir = ELM_FOCUS_PREVIOUS;
+         break;
+      default:
+         return EINA_FALSE;
+     }
+
+   elm_widget_focus_cycle(elm_widget_parent_get(obj), dir);
+
+   return EINA_TRUE;
+}
+
+/**
+ * Creates a new view object given the parent.
+ *
+ * @param parent object to use as parent.
+ *
+ * @return newly added Evas_Object or @c NULL on errors.
+ */
+Evas_Object *
+_view_add(Evas_Object *parent)
+{
+   static Evas_Smart *smart = NULL;
+   Evas *canvas = evas_object_evas_get(parent);
+   Evas_Object *view;
+
+   if (!smart)
+     {
+        static Ewk_View_Smart_Class api = EWK_VIEW_SMART_CLASS_INIT_NAME_VERSION("EWK_View_Elementary");
+
+#ifndef TILED_BACKING_STORE
+        ewk_view_single_smart_set(&api);
+#else
+        ewk_view_tiled_smart_set(&api);
+#endif
+
+        _parent_sc = api;
+
+        // TODO: check every api method and provide overrides with hooks!
+        // TODO: hooks should provide extension points
+        // TODO: extension should have some kind of "default implementation",
+        // TODO: that can be replaced or controlled by hooks.
+        // TODO: ie: run_javascript_alert() should present an elm_win
+        // TODO: by default, but user could override it to show as inwin.
+        api.sc.add = _view_smart_add;
+        api.sc.del = _view_smart_del;
+        //api.sc.calculate = _view_smart_calculate;
+        api.mouse_down = _view_smart_mouse_down;
+        api.mouse_up = _view_smart_mouse_up;
+        api.mouse_move = _view_smart_mouse_move;
+        api.add_console_message = _view_smart_add_console_message;
+        api.window_create = _view_smart_window_create;
+        api.window_close = _view_smart_window_close;
+        api.run_javascript_alert = _view_smart_run_javascript_alert;
+        api.run_javascript_confirm = _view_smart_run_javascript_confirm;
+        api.run_javascript_prompt = _view_smart_run_javascript_prompt;
+        api.run_open_panel = _view_smart_run_open_panel;
+        api.focus_can_cycle = _view_smart_focus_can_cycle;
+
+        smart = evas_smart_class_new(&api.sc);
+        if (!smart)
+          {
+             CRITICAL("Could not create smart class");
+             return NULL;
+          }
+     }
+
+   view = evas_object_smart_add(canvas, smart);
+   if (!view)
+     {
+        ERR("Could not create smart object object for view");
+        return NULL;
+     }
+
+   return view;
+}
+
+static void
+_ewk_view_inputmethod_change_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Widget_Data *wd = data;
+   Evas_Object *top = elm_widget_top_get(wd->self);
+   if (!top) return;
+
+   if (event_info)
+     wd->input_method = ELM_WIN_KEYBOARD_ON;
+   else
+     wd->input_method = ELM_WIN_KEYBOARD_OFF;
+   elm_win_keyboard_mode_set(top, wd->input_method);
+}
+
+static void
+_ewk_view_load_started_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   _ewk_view_inputmethod_change_cb(data, obj, (void *)(long)EINA_FALSE);
+}
+
+static void
+_ewk_view_load_finished_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Widget_Data *wd = data;
+
+   if (event_info)
+     return;
+
+   if (wd->zoom.mode != ELM_WEB_ZOOM_MODE_MANUAL)
+     {
+        float tz = wd->zoom.current;
+        wd->zoom.current = 0.0;
+        elm_web_zoom_set(wd->self, tz);
+     }
+}
+
+static void
+_ewk_view_viewport_changed_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = data;
+
+   if (wd->zoom.mode != ELM_WEB_ZOOM_MODE_MANUAL)
+     {
+        ewk_view_zoom_set(obj, 1.0, 0, 0);
+        wd->zoom.no_anim = EINA_TRUE;
+     }
+}
+
+static Eina_Bool
+_restore_zoom_mode_timer_cb(void *data)
+{
+   Widget_Data *wd = data;
+   float tz = wd->zoom.current;
+   wd->zoom.timer = NULL;
+   wd->zoom.current = 0.0;
+   wd->zoom.no_anim = EINA_TRUE;
+   elm_web_zoom_set(wd->self, tz);
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+_reset_zoom_timer_cb(void *data)
+{
+   Widget_Data *wd = data;
+   wd->zoom.timer = ecore_timer_add(0.0, _restore_zoom_mode_timer_cb, wd);
+   ewk_view_zoom_set(wd->ewk_view, 1.0, 0, 0);
+   return EINA_FALSE;
+}
+
+static void
+_ewk_view_resized_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = data;
+   if (!(wd->zoom.mode != ELM_WEB_ZOOM_MODE_MANUAL))
+     return;
+   if (wd->zoom.timer)
+     ecore_timer_del(wd->zoom.timer);
+   wd->zoom.timer = ecore_timer_add(0.5, _reset_zoom_timer_cb, wd);
+}
+
+static void
+_popup_del_job(void *data)
+{
+   evas_object_del(data);
+}
+
+static void
+_popup_will_delete(void *data, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   ecore_job_add(_popup_del_job, data);
+   evas_object_smart_callback_del(obj, "popup,willdelete", _popup_will_delete);
+}
+
+static void
+_popup_item_selected(void *data, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Evas_Object *view = data;
+   Elm_List_Item *it = elm_list_selected_item_get(obj);
+   const Eina_List *itr, *list = elm_list_items_get(obj);
+   void *d;
+   int i = 0;
+
+   EINA_LIST_FOREACH(list, itr, d)
+   {
+      if (d == it)
+         break;
+
+      i++;
+   }
+
+   ewk_view_popup_selected_set(view, i);
+   ewk_view_popup_destroy(view);
+}
+
+static void
+_popup_dismiss_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   ewk_view_popup_destroy(data);
+}
+
+static void
+_ewk_view_popup_create_cb(void *data, Evas_Object *obj, void *event_info)
+{
+   Widget_Data *wd = data;
+   Ewk_Menu *m = event_info;
+   Elm_Web_Menu m2;
+   Ewk_Menu_Item *it;
+   Eina_List *itr;
+   Evas_Object *notify, *list;
+
+   m2.items = m->items;
+   m2.x = m->x;
+   m2.y = m->y;
+   m2.width = m->width;
+   m2.height = m->height;
+   m2.handled = EINA_FALSE;
+   evas_object_smart_callback_call(wd->self, "popup,create", &m2);
+   if (m2.handled)
+     return;
+
+   notify = elm_notify_add(obj);
+   elm_notify_repeat_events_set(notify, EINA_FALSE);
+   elm_notify_orient_set(notify, ELM_NOTIFY_ORIENT_BOTTOM);
+
+   list = elm_list_add(obj);
+   elm_list_always_select_mode_set(list, EINA_TRUE);
+   elm_list_bounce_set(list, EINA_FALSE, EINA_FALSE);
+   elm_list_mode_set(list, ELM_LIST_EXPAND);
+   evas_object_size_hint_weight_set(list, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(list, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_object_content_set(notify, list);
+   evas_object_show(list);
+
+   EINA_LIST_FOREACH(m->items, itr, it)
+      elm_list_item_append(list, it->text, NULL, NULL, _popup_item_selected,
+                           obj);
+   elm_list_go(list);
+
+   evas_object_show(notify);
+
+   evas_object_smart_callback_add(obj, "popup,willdelete", _popup_will_delete,
+                                  notify);
+   evas_object_smart_callback_add(notify, "block,clicked", _popup_dismiss_cb,
+                                  obj);
+}
+
+static void
+_view_smart_callback_proxy_free_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   free(data);
+}
+
+static void
+_view_smart_callback_proxy_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Elm_Web_Callback_Proxy_Context *ctxt = data;
+
+   evas_object_smart_callback_call(ctxt->obj, ctxt->name, event_info);
+}
+
+static void
+_view_smart_callback_proxy(Evas_Object *view, Evas_Object *parent)
+{
+   const Evas_Smart_Cb_Description **cls_descs, **inst_descs;
+   unsigned int cls_count, inst_count, total;
+   Elm_Web_Callback_Proxy_Context *ctxt;
+
+   evas_object_smart_callbacks_descriptions_get(view, &cls_descs, &cls_count,
+                                                &inst_descs, &inst_count);
+   total = cls_count + inst_count;
+   if (!total) return;
+   ctxt = malloc(sizeof(Elm_Web_Callback_Proxy_Context) * total);
+   if (!ctxt) return;
+   evas_object_event_callback_add(view, EVAS_CALLBACK_FREE,
+                                  _view_smart_callback_proxy_free_cb, ctxt);
+
+   for (; cls_count > 0; cls_count--, cls_descs++, ctxt++)
+     {
+        const Evas_Smart_Cb_Description *d = *cls_descs;
+        if (!strcmp(d->name, "popup,create"))
+          continue;
+        ctxt->name = d->name;
+        ctxt->obj = parent;
+        evas_object_smart_callback_add(view, d->name,
+                                       _view_smart_callback_proxy_cb, ctxt);
+     }
+
+   for (; inst_count > 0; inst_count--, inst_descs++, ctxt++)
+     {
+        const Evas_Smart_Cb_Description *d = *inst_descs;
+        ctxt->name = d->name;
+        ctxt->obj = parent;
+        evas_object_smart_callback_add(view, d->name,
+                                       _view_smart_callback_proxy_cb, ctxt);
+     }
+}
+
+static Eina_Bool
+_bring_in_anim_cb(void *data, double pos)
+{
+   Widget_Data *wd = data;
+   Evas_Object *frame = ewk_view_frame_main_get(wd->ewk_view);
+   int sx, sy, rx, ry;
+
+   sx = wd->bring_in.start.x;
+   sy = wd->bring_in.start.y;
+   rx = (wd->bring_in.end.x - sx) * pos;
+   ry = (wd->bring_in.end.y - sy) * pos;
+
+   ewk_frame_scroll_set(frame, rx + sx, ry + sy);
+
+   if (pos == 1.0)
+     {
+        wd->bring_in.end.x = wd->bring_in.end.y = wd->bring_in.start.x =
+           wd->bring_in.start.y = 0;
+        wd->bring_in.animator = NULL;
+     }
+
+   return EINA_TRUE;
+}
+#endif
+
+#ifdef HAVE_ELEMENTARY_WEB
+static int _elm_need_web = 0;
+#endif
+
+void
+_elm_unneed_web(void)
+{
+#ifdef HAVE_ELEMENTARY_WEB
+   if (--_elm_need_web) return;
+
+   _elm_need_web = 0;
+   ewk_shutdown();
+#endif
+}
+
+EAPI Eina_Bool
+elm_need_web(void)
+{
+#ifdef HAVE_ELEMENTARY_WEB
+   if (_elm_need_web++) return EINA_TRUE;
+   ewk_init();
+   return EINA_TRUE;
+#else
+   return EINA_FALSE;
+#endif
+}
+
+EAPI Evas_Object *
+elm_web_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Widget_Data *wd;
+   Evas *e;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = calloc(1, sizeof(Widget_Data));
+   e = evas_object_evas_get(parent);
+   if (!e)
+     return NULL;
+   obj = elm_widget_add(e);
+   wd->self = obj;
+
+   if (!widtype)
+     {
+        widtype = eina_stringshare_add("web");
+        elm_widget_type_register(&widtype);
+     }
+
+   elm_widget_type_set(obj, widtype);
+   elm_widget_sub_object_add(parent, obj);
+   elm_widget_theme_hook_set(obj, _theme_hook);
+   elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
+   elm_widget_event_hook_set(obj, _event_hook);
+   elm_widget_data_set(obj, wd);
+   elm_widget_can_focus_set(obj, EINA_TRUE);
+
+#ifdef HAVE_ELEMENTARY_WEB
+   wd->ewk_view = _view_add(obj);
+   ewk_view_setting_user_agent_set(wd->ewk_view, ELM_WEB_USER_AGENT);
+
+   wd->input_method = ELM_WIN_KEYBOARD_OFF;
+   evas_object_smart_callback_add(wd->ewk_view, "inputmethod,changed",
+                                  _ewk_view_inputmethod_change_cb, wd);
+   evas_object_smart_callback_add(wd->ewk_view, "load,started",
+                                  _ewk_view_load_started_cb, wd);
+   evas_object_smart_callback_add(wd->ewk_view, "popup,create",
+                                  _ewk_view_popup_create_cb, wd);
+   evas_object_smart_callback_add(wd->ewk_view, "load,finished",
+                                  _ewk_view_load_finished_cb, wd);
+   evas_object_smart_callback_add(wd->ewk_view, "viewport,changed",
+                                  _ewk_view_viewport_changed_cb, wd);
+   evas_object_smart_callback_add(wd->ewk_view, "view,resized",
+                                  _ewk_view_resized_cb, wd);
+
+   elm_widget_resize_object_set(obj, wd->ewk_view);
+
+   wd->tab_propagate = EINA_FALSE;
+   wd->inwin_mode = _elm_config->inwin_dialogs_enable;
+   wd->zoom.min = ewk_view_zoom_range_min_get(wd->ewk_view);
+   wd->zoom.max = ewk_view_zoom_range_max_get(wd->ewk_view);
+   wd->zoom.current = 1.0;
+
+   _view_smart_callback_proxy(wd->ewk_view, wd->self);
+   evas_object_smart_callbacks_descriptions_set(obj, _elm_web_callback_names);
+
+   _theme_hook(obj);
+
+#else
+   wd->label = elm_label_add(obj);
+   elm_object_text_set(wd->label, "WebKit not supported!");
+   evas_object_show(wd->label);
+   elm_widget_resize_object_set(obj, wd->label);
+#endif
+
+   return obj;
+}
+
+EAPI Evas_Object *
+elm_web_webkit_view_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   return wd->ewk_view;
+#else
+   ERR("Elementary not compiled with EWebKit support.");
+   return NULL;
+#endif
+}
+
+EAPI void
+elm_web_window_create_hook_set(Evas_Object *obj, Elm_Web_Window_Open func, void *data)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->hook.window_create = func;
+   wd->hook.window_create_data = data;
+#else
+   (void)func;
+   (void)data;
+#endif
+}
+
+EAPI void
+elm_web_dialog_alert_hook_set(Evas_Object *obj, Elm_Web_Dialog_Alert func, void *data)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->hook.alert = func;
+   wd->hook.alert_data = data;
+#else
+   (void)func;
+   (void)data;
+#endif
+}
+
+EAPI void
+elm_web_dialog_confirm_hook_set(Evas_Object *obj, Elm_Web_Dialog_Confirm func, void *data)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->hook.confirm = func;
+   wd->hook.confirm_data = data;
+#else
+   (void)func;
+   (void)data;
+#endif
+}
+
+EAPI void
+elm_web_dialog_prompt_hook_set(Evas_Object *obj, Elm_Web_Dialog_Prompt func, void *data)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->hook.prompt = func;
+   wd->hook.prompt_data = data;
+#else
+   (void)func;
+   (void)data;
+#endif
+}
+
+EAPI void
+elm_web_dialog_file_selector_hook_set(Evas_Object *obj, Elm_Web_Dialog_File_Selector func, void *data)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->hook.file_selector = func;
+   wd->hook.file_selector_data = data;
+#else
+   (void)func;
+   (void)data;
+#endif
+}
+
+EAPI void
+elm_web_console_message_hook_set(Evas_Object *obj, Elm_Web_Console_Message func, void *data)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->hook.console_message = func;
+   wd->hook.console_message_data = data;
+#else
+   (void)func;
+   (void)data;
+#endif
+}
+
+EAPI Eina_Bool
+elm_web_tab_propagate_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   return wd->tab_propagate;
+#else
+   return EINA_FALSE;
+#endif
+}
+
+EAPI void
+elm_web_tab_propagate_set(Evas_Object *obj, Eina_Bool propagate)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->tab_propagate = propagate;
+#else
+   (void)propagate;
+#endif
+}
+
+EAPI Eina_Bool
+elm_web_uri_set(Evas_Object *obj, const char *uri)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   return ewk_view_uri_set(wd->ewk_view, uri);
+#else
+   (void)uri;
+   return EINA_FALSE;
+#endif
+}
+
+EAPI const char *
+elm_web_uri_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   return ewk_view_uri_get(wd->ewk_view);
+#else
+   return NULL;
+#endif
+}
+
+EAPI const char *
+elm_web_title_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   return ewk_view_title_get(wd->ewk_view);
+#else
+   return NULL;
+#endif
+}
+
+EAPI void
+elm_web_bg_color_set(Evas_Object *obj, int r, int g, int b, int a)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   ewk_view_bg_color_set(wd->ewk_view, r, g, b, a);
+#else
+   (void)r;
+   (void)g;
+   (void)b;
+   (void)a;
+#endif
+}
+
+EAPI void
+elm_web_bg_color_get(const Evas_Object *obj, int *r, int *g, int *b, int *a)
+{
+   if (r) *r = 0;
+   if (g) *g = 0;
+   if (b) *b = 0;
+   if (a) *a = 0;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   return ewk_view_bg_color_get(wd->ewk_view, r, g, b, a);
+#endif
+}
+
+EAPI char *
+elm_web_selection_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   return ewk_view_selection_get(wd->ewk_view);
+#else
+   return NULL;
+#endif
+}
+
+EAPI void
+elm_web_popup_selected_set(Evas_Object *obj, int idx)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+   ewk_view_popup_selected_set(wd->ewk_view, idx);
+#else
+   (void)idx;
+#endif
+}
+
+EAPI Eina_Bool
+elm_web_popup_destroy(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+   return ewk_view_popup_destroy(wd->ewk_view);
+#else
+   return EINA_FALSE;
+#endif
+}
+
+EAPI Eina_Bool
+elm_web_text_search(const Evas_Object *obj, const char *string, Eina_Bool case_sensitive, Eina_Bool forward, Eina_Bool wrap)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   return ewk_view_text_search
+     (wd->ewk_view, string, case_sensitive, forward, wrap);
+#else
+   (void)string;
+   (void)case_sensitive;
+   (void)forward;
+   (void)wrap;
+   return EINA_FALSE;
+#endif
+}
+
+EAPI unsigned int
+elm_web_text_matches_mark(Evas_Object *obj, const char *string, Eina_Bool case_sensitive, Eina_Bool highlight, unsigned int limit)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) 0;
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return 0;
+   return ewk_view_text_matches_mark
+     (wd->ewk_view, string, case_sensitive, highlight, limit);
+#else
+   (void)string;
+   (void)case_sensitive;
+   (void)highlight;
+   (void)limit;
+   return 0;
+#endif
+}
+
+EAPI Eina_Bool
+elm_web_text_matches_unmark_all(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   return ewk_view_text_matches_unmark_all(wd->ewk_view);
+#else
+   return EINA_FALSE;
+#endif
+}
+
+EAPI Eina_Bool
+elm_web_text_matches_highlight_set(Evas_Object *obj, Eina_Bool highlight)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   return ewk_view_text_matches_highlight_set(wd->ewk_view, highlight);
+#else
+   (void)highlight;
+   return EINA_FALSE;
+#endif
+}
+
+EAPI Eina_Bool
+elm_web_text_matches_highlight_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   return ewk_view_text_matches_highlight_get(wd->ewk_view);
+#else
+   return EINA_FALSE;
+#endif
+}
+
+EAPI double
+elm_web_load_progress_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) -1.0;
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return -1.0;
+   return ewk_view_load_progress_get(wd->ewk_view);
+#else
+   return EINA_FALSE;
+#endif
+}
+
+EAPI Eina_Bool
+elm_web_stop(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   return ewk_view_stop(wd->ewk_view);
+#else
+   return EINA_FALSE;
+#endif
+}
+
+EAPI Eina_Bool
+elm_web_reload(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   return ewk_view_reload(wd->ewk_view);
+#else
+   return EINA_FALSE;
+#endif
+}
+
+EAPI Eina_Bool
+elm_web_reload_full(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   return ewk_view_reload_full(wd->ewk_view);
+#else
+   return EINA_FALSE;
+#endif
+}
+
+
+EAPI Eina_Bool
+elm_web_back(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   return ewk_view_back(wd->ewk_view);
+#else
+   return EINA_FALSE;
+#endif
+}
+
+EAPI Eina_Bool
+elm_web_forward(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   return ewk_view_forward(wd->ewk_view);
+#else
+   return EINA_FALSE;
+#endif
+}
+
+EAPI Eina_Bool
+elm_web_navigate(Evas_Object *obj, int steps)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   return ewk_view_navigate(wd->ewk_view, steps);
+#else
+   return EINA_FALSE;
+   (void)steps;
+#endif
+}
+
+EAPI Eina_Bool
+elm_web_back_possible(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   return ewk_view_back_possible(wd->ewk_view);
+#else
+   return EINA_FALSE;
+#endif
+}
+
+EAPI Eina_Bool
+elm_web_forward_possible(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   return ewk_view_forward_possible(wd->ewk_view);
+#else
+   return EINA_FALSE;
+#endif
+}
+
+EAPI Eina_Bool
+elm_web_navigate_possible(Evas_Object *obj, int steps)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   return ewk_view_navigate_possible(wd->ewk_view, steps);
+#else
+   return EINA_FALSE;
+   (void)steps;
+#endif
+}
+
+EAPI Eina_Bool
+elm_web_history_enable_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   return ewk_view_history_enable_get(wd->ewk_view);
+#else
+   return EINA_FALSE;
+#endif
+}
+
+EAPI void
+elm_web_history_enable_set(Evas_Object *obj, Eina_Bool enable)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   ewk_view_history_enable_set(wd->ewk_view, enable);
+#else
+   (void)enable;
+#endif
+}
+
+//EAPI Ewk_History *ewk_view_history_get(const Evas_Object *obj); // TODO:
+
+EAPI void
+elm_web_zoom_set(Evas_Object *obj, double zoom)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+   int vw, vh, cx, cy;
+   float z = 1.0;
+   evas_object_geometry_get(wd->ewk_view, NULL, NULL, &vw, &vh);
+   cx = vw / 2;
+   cy = vh / 2;
+   if (zoom > wd->zoom.max)
+     zoom = wd->zoom.max;
+   else if (zoom < wd->zoom.min)
+     zoom = wd->zoom.min;
+   if (zoom == wd->zoom.current) return;
+   wd->zoom.current = zoom;
+   if (wd->zoom.mode == ELM_WEB_ZOOM_MODE_MANUAL)
+     z = zoom;
+   else if (wd->zoom.mode == ELM_WEB_ZOOM_MODE_AUTO_FIT)
+     {
+        Evas_Object *frame = ewk_view_frame_main_get(wd->ewk_view);
+        Evas_Coord fw, fh, pw, ph;
+        if (!ewk_frame_contents_size_get(frame, &fw, &fh))
+          return;
+        z = ewk_frame_page_zoom_get(frame);
+        fw /= z;
+        fh /= z;
+        if ((fw > 0) && (fh > 0))
+          {
+             ph = (fh * vw) / fw;
+             if (ph > vh)
+               {
+                  pw = (fw * vh) / fh;
+                  ph = vh;
+               }
+             else
+               pw = vw;
+             if (fw > fh)
+               z = (float)pw / fw;
+             else
+               z = (float)ph / fh;
+          }
+     }
+   else if (wd->zoom.mode == ELM_WEB_ZOOM_MODE_AUTO_FILL)
+     {
+        Evas_Object *frame = ewk_view_frame_main_get(wd->ewk_view);
+        Evas_Coord fw, fh, pw, ph;
+        if (!ewk_frame_contents_size_get(frame, &fw, &fh))
+          return;
+        z = ewk_frame_page_zoom_get(frame);
+        fw /= z;
+        fh /= z;
+        if ((fw > 0) && (fh > 0))
+          {
+             ph = (fh * vw) / fw;
+             if (ph < vh)
+               {
+                  pw = (fw * vh) / fh;
+                  ph = vh;
+               }
+             else
+               pw = vw;
+             if (fw > fh)
+               z = (float)pw / fw;
+             else
+               z = (float)ph / fh;
+          }
+     }
+   if (wd->zoom.no_anim)
+     ewk_view_zoom_set(wd->ewk_view, z, cx, cy);
+   else
+     ewk_view_zoom_animated_set(wd->ewk_view, z, _elm_config->zoom_friction,
+                                cx, cy);
+   wd->zoom.no_anim = EINA_FALSE;
+#else
+   (void)zoom;
+#endif
+}
+
+EAPI double
+elm_web_zoom_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) -1.0;
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+   return wd->zoom.current;
+#else
+   return -1.0;
+#endif
+}
+
+EAPI void
+elm_web_zoom_mode_set(Evas_Object *obj, Elm_Web_Zoom_Mode mode)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+   float tz;
+   if (mode >= ELM_WEB_ZOOM_MODE_LAST)
+     return;
+   if (mode == wd->zoom.mode)
+     return;
+   wd->zoom.mode = mode;
+   tz = wd->zoom.current;
+   wd->zoom.current = 0.0;
+   elm_web_zoom_set(obj, tz);
+#else
+   (void)mode;
+#endif
+}
+
+EAPI Elm_Web_Zoom_Mode
+elm_web_zoom_mode_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) ELM_WEB_ZOOM_MODE_LAST;
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+   return wd->zoom.mode;
+#else
+   return ELM_WEB_ZOOM_MODE_LAST;
+#endif
+}
+
+EAPI void
+elm_web_region_show(Evas_Object *obj, int x, int y, int w __UNUSED__, int h __UNUSED__)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Object *frame = ewk_view_frame_main_get(wd->ewk_view);
+   int fw, fh, zw, zh, rx, ry;
+   float zoom;
+   ewk_frame_contents_size_get(frame, &fw, &fh);
+   zoom = ewk_frame_page_zoom_get(frame);
+   zw = fw / zoom;
+   zh = fh / zoom;
+   rx = (x * fw) / zw;
+   ry = (y * fh) / zh;
+   if (wd->bring_in.animator)
+     {
+        ecore_animator_del(wd->bring_in.animator);
+        wd->bring_in.animator = NULL;
+     }
+   ewk_frame_scroll_set(frame, rx, ry);
+#else
+   (void)x;
+   (void)y;
+#endif
+}
+
+EAPI void
+elm_web_region_bring_in(Evas_Object *obj, int x, int y, int w __UNUSED__, int h __UNUSED__)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Object *frame = ewk_view_frame_main_get(wd->ewk_view);
+   int fw, fh, zw, zh, rx, ry, sx, sy;
+   float zoom;
+   ewk_frame_contents_size_get(frame, &fw, &fh);
+   ewk_frame_scroll_pos_get(frame, &sx, &sy);
+   zoom = ewk_frame_page_zoom_get(frame);
+   zw = fw / zoom;
+   zh = fh / zoom;
+   rx = (x * fw) / zw;
+   ry = (y * fh) / zh;
+   if ((wd->bring_in.end.x == rx) && (wd->bring_in.end.y == ry))
+     return;
+   wd->bring_in.start.x = sx;
+   wd->bring_in.start.y = sy;
+   wd->bring_in.end.x = rx;
+   wd->bring_in.end.y = ry;
+   if (wd->bring_in.animator)
+     ecore_animator_del(wd->bring_in.animator);
+   wd->bring_in.animator = ecore_animator_timeline_add(
+      _elm_config->bring_in_scroll_friction, _bring_in_anim_cb, wd);
+#else
+   (void)x;
+   (void)y;
+#endif
+}
+
+EAPI void
+elm_web_inwin_mode_set(Evas_Object *obj, Eina_Bool value)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   wd->inwin_mode = value;
+#else
+   (void)value;
+#endif
+}
+
+EAPI Eina_Bool
+elm_web_inwin_mode_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   return wd->inwin_mode;
+#else
+   return EINA_FALSE;
+#endif
+}
+
+EAPI void
+elm_web_window_features_ref(Elm_Web_Window_Features *wf)
+{
+#ifdef HAVE_ELEMENTARY_WEB
+   ewk_window_features_ref((Ewk_Window_Features *)wf);
+#else
+   (void)wf;
+#endif
+}
+
+EAPI void
+elm_web_window_features_unref(Elm_Web_Window_Features *wf)
+{
+#ifdef HAVE_ELEMENTARY_WEB
+   ewk_window_features_unref((Ewk_Window_Features *)wf);
+#else
+   (void)wf;
+#endif
+}
+
+EAPI void
+elm_web_window_features_bool_property_get(const Elm_Web_Window_Features *wf, Eina_Bool *toolbar_visible, Eina_Bool *statusbar_visible, Eina_Bool *scrollbars_visible, Eina_Bool *menubar_visible, Eina_Bool *locationbar_visible, Eina_Bool *fullscreen)
+{
+#ifdef HAVE_ELEMENTARY_WEB
+   ewk_window_features_bool_property_get((const Ewk_Window_Features *)wf,
+                                         toolbar_visible, statusbar_visible,
+                                         scrollbars_visible, menubar_visible,
+                                         locationbar_visible, fullscreen);
+#else
+   (void)wf;
+   (void)toolbar_visible;
+   (void)statusbar_visible;
+   (void)scrollbars_visible;
+   (void)menubar_visible;
+   (void)locationbar_visible;
+   (void)fullscreen;
+#endif
+}
+
+EAPI void
+elm_web_window_features_int_property_get(const Elm_Web_Window_Features *wf, int *x, int *y, int *w, int *h)
+{
+#ifdef HAVE_ELEMENTARY_WEB
+   ewk_window_features_int_property_get((const Ewk_Window_Features *)wf,
+                                        x, y, w, h);
+#else
+   (void)wf;
+   (void)x;
+   (void)y;
+   (void)w;
+   (void)h;
+#endif
+}
+
+// TODO: use all ewk_view_zoom stuff to implement bring-in and animated zoom like elm_photocam. Should be simple to use, must not expose every single bit to users!
diff --git a/src/lib/elu_ews_wm.c b/src/lib/elu_ews_wm.c
new file mode 100644 (file)
index 0000000..0ea3c19
--- /dev/null
@@ -0,0 +1,545 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+static Eina_Bool _ews_used = EINA_FALSE;
+static Eina_List *_ews_ev_handlers = NULL;
+static Eina_Hash *_ews_borders = NULL;
+static Eina_Hash *_ews_borders_geo = NULL;
+static Evas_Object *_ews_bg = NULL;
+static Ecore_Animator *_ews_border_mover = NULL;
+static Evas_Object *_ews_border_mover_obj = NULL;
+static Evas_Point _ews_border_mover_off = {0, 0};
+
+static void
+_elm_ews_border_usable_screen_geometry_get(int *x, int *y, int *w, int *h)
+{
+   Ecore_Evas *ee = ecore_evas_ews_ecore_evas_get();
+   ecore_evas_geometry_get(ee, NULL, NULL, w, h);
+   if (x) *x = 0;
+   if (y) *y = 0;
+   // TODO: when add a shelf for iconified, subtract its area here.
+}
+
+static void
+_elm_ews_wm_border_del(void *data)
+{
+   Evas_Object *deco = data;
+   evas_object_del(deco);
+
+   if (_ews_border_mover_obj == deco)
+     {
+        if (_ews_border_mover)
+          {
+             ecore_animator_del(_ews_border_mover);
+             _ews_border_mover = NULL;
+          }
+        _ews_border_mover_obj = NULL;
+     }
+}
+
+static Evas_Object *
+_elm_ews_wm_border_find(const Ecore_Evas *ee)
+{
+   return eina_hash_find(_ews_borders, &ee);
+}
+
+static Eina_Rectangle *
+_elm_ews_wm_border_geo_find(const Ecore_Evas *ee)
+{
+   return eina_hash_find(_ews_borders_geo, &ee);
+}
+
+static void
+_elm_ews_border_geo_apply(Ecore_Evas *ee, Evas_Object *o)
+{
+   int x, y, w, h;
+   ecore_evas_geometry_get(ee, &x, &y, &w, &h);
+   evas_object_move(o, x, y);
+   evas_object_resize(o, w, h);
+}
+
+static void
+_elm_ews_border_focus_apply(Ecore_Evas *ee, Evas_Object *o)
+{
+   const char *sig;
+   if (ecore_evas_focus_get(ee))
+     sig = "elm,state,focus,on";
+   else
+     sig = "elm,state,focus,off";
+   edje_object_signal_emit(o, sig, "elm");
+}
+
+static void
+_elm_ews_border_stack_apply(Ecore_Evas *ee, Evas_Object *o)
+{
+   Evas_Object *bs_o = ecore_evas_ews_backing_store_get(ee);
+   evas_object_stack_below(o, bs_o);
+}
+
+static void
+_elm_ews_border_iconified_apply(Ecore_Evas *ee, Evas_Object *o)
+{
+   const char *sig;
+   if (ecore_evas_iconified_get(ee))
+     sig = "elm,state,iconified,on";
+   else
+     sig = "elm,state,iconified,off";
+   edje_object_signal_emit(o, sig, "elm");
+
+   // TODO: add to some taskbar? and actually hide it?
+   DBG("EWS does not implement iconified yet");
+}
+
+static void
+_elm_ews_border_maximized_apply(Ecore_Evas *ee, Evas_Object *o)
+{
+   int x, y, w, h;
+   if (ecore_evas_maximized_get(ee))
+     {
+        Eina_Rectangle *r;
+        int ex, ey, ew, eh;
+
+        edje_object_signal_emit(o, "elm,state,maximized,on", "elm");
+        edje_object_message_signal_process(o);
+        ecore_evas_geometry_get(ee, &x, &y, &w, &h);
+
+        r = _elm_ews_wm_border_geo_find(ee);
+        if (!r)
+          {
+             r = malloc(sizeof(Eina_Rectangle));
+             eina_hash_add(_ews_borders_geo, &ee, r);
+          }
+
+        r->x = x;
+        r->y = y;
+        r->w = w;
+        r->h = h;
+        _elm_ews_border_usable_screen_geometry_get(&x, &y, &w, &h);
+        edje_object_parts_extends_calc(o, &ex, &ey, &ew, &eh);
+        x -= ex;
+        y -= ey;
+        w -= ew - r->w;
+        h -= eh - r->h;
+     }
+   else
+     {
+        Eina_Rectangle *r = _elm_ews_wm_border_geo_find(ee);
+        edje_object_signal_emit(o, "elm,state,maximized,off", "elm");
+
+        if (!r) ecore_evas_geometry_get(ee, &x, &y, &w, &h);
+        else
+          {
+             x = r->x;
+             y = r->y;
+             w = r->w;
+             h = r->h;
+          }
+     }
+
+   ecore_evas_move_resize(ee, x, y, w, h);
+   _elm_ews_border_geo_apply(ee, o);
+}
+
+static void
+_elm_ews_border_layer_apply(Ecore_Evas *ee, Evas_Object *o)
+{
+   Evas_Object *bs_o = ecore_evas_ews_backing_store_get(ee);
+   evas_object_layer_set(o, evas_object_layer_get(bs_o));
+   _elm_ews_border_stack_apply(ee, o);
+}
+
+static void
+_elm_ews_border_fullscreen_apply(Ecore_Evas *ee, Evas_Object *o)
+{
+   const char *sig;
+   if (ecore_evas_fullscreen_get(ee))
+     sig = "elm,state,fullscreen,on";
+   else
+     sig = "elm,state,fullscreen,off";
+   edje_object_signal_emit(o, sig, "elm");
+   _elm_ews_border_geo_apply(ee, o);
+}
+
+static void
+_elm_ews_border_config_apply(Ecore_Evas *ee, Evas_Object *o, Elm_Theme *th)
+{
+   const char *title, *name = NULL, *class = NULL, *style = NULL;
+   const char *sig;
+
+   if (ecore_evas_borderless_get(ee))
+     style = "borderless";
+
+   _elm_theme_set(th, o, "ews", "decoration", style ? style : "default");
+
+   if (ecore_evas_shaped_get(ee) || ecore_evas_alpha_get(ee) ||
+       ecore_evas_transparent_get(ee))
+     sig = "elm,state,alpha,on";
+   else
+     sig = "elm,state,alpha,off";
+   edje_object_signal_emit(o, sig, "elm");
+
+   title = ecore_evas_title_get(ee);
+   ecore_evas_name_class_get(ee, &name, &class);
+   edje_object_part_text_set(o, "elm.text.title", title);
+   edje_object_part_text_set(o, "elm.text.name", name);
+   edje_object_part_text_set(o, "elm.text.class", class);
+
+   _elm_ews_border_geo_apply(ee, o);
+   _elm_ews_border_focus_apply(ee, o);
+   _elm_ews_border_stack_apply(ee, o);
+   _elm_ews_border_iconified_apply(ee, o);
+   _elm_ews_border_maximized_apply(ee, o);
+   _elm_ews_border_layer_apply(ee, o);
+   _elm_ews_border_fullscreen_apply(ee, o);
+}
+
+static Eina_Bool
+_elm_ews_wm_border_theme_set(Ecore_Evas *ee, Evas_Object *o, Elm_Theme *th)
+{
+   _elm_ews_border_config_apply(ee, o, th);
+   return EINA_TRUE;
+}
+
+static void
+_elm_ews_border_sig_focus(void *data, Evas_Object *o __UNUSED__, const char *sig __UNUSED__, const char *source __UNUSED__)
+{
+   Ecore_Evas *ee = data;
+   ecore_evas_focus_set(ee, EINA_TRUE);
+}
+
+static void
+_elm_ews_border_sig_iconify(void *data, Evas_Object *o __UNUSED__, const char *sig __UNUSED__, const char *source __UNUSED__)
+{
+   Ecore_Evas *ee = data;
+   ecore_evas_iconified_set(ee, EINA_TRUE);
+}
+
+static void
+_elm_ews_border_sig_maximize(void *data, Evas_Object *o __UNUSED__, const char *sig __UNUSED__, const char *source __UNUSED__)
+{
+   Ecore_Evas *ee = data;
+   ecore_evas_maximized_set(ee, EINA_TRUE);
+}
+
+static void
+_elm_ews_border_sig_fullscreen(void *data, Evas_Object *o __UNUSED__, const char *sig __UNUSED__, const char *source __UNUSED__)
+{
+   Ecore_Evas *ee = data;
+   ecore_evas_fullscreen_set(ee, EINA_TRUE);
+}
+
+static void
+_elm_ews_border_sig_restore(void *data, Evas_Object *o __UNUSED__, const char *sig __UNUSED__, const char *source __UNUSED__)
+{
+   Ecore_Evas *ee = data;
+   ecore_evas_iconified_set(ee, EINA_FALSE);
+   ecore_evas_maximized_set(ee, EINA_FALSE);
+   ecore_evas_fullscreen_set(ee, EINA_FALSE);
+}
+
+static void
+_elm_ews_border_sig_close(void *data, Evas_Object *o __UNUSED__, const char *sig __UNUSED__, const char *source __UNUSED__)
+{
+   Ecore_Evas *ee = data;
+   ecore_evas_ews_delete_request(ee);
+}
+
+static void
+_elm_ews_border_sig_menu(void *data, Evas_Object *o __UNUSED__, const char *sig __UNUSED__, const char *source __UNUSED__)
+{
+   // TODO: show some menu?
+   ERR("EWS does not implement menu yet");
+   (void)data;
+}
+
+static Eina_Bool
+_elm_ews_border_mover(void *data)
+{
+   Ecore_Evas *ee = data;
+   Evas_Object *o = _elm_ews_wm_border_find(ee);
+   int x, y;
+
+   evas_pointer_output_xy_get(ecore_evas_ews_evas_get(), &x, &y);
+   x -= _ews_border_mover_off.x;
+   y -= _ews_border_mover_off.y;
+   ecore_evas_move(ee, x, y);
+   evas_object_move(o, x, y);
+
+   return EINA_TRUE;
+}
+
+static void
+_elm_ews_border_sig_move_start(void *data, Evas_Object *o __UNUSED__, const char *sig __UNUSED__, const char *source __UNUSED__)
+{
+   Ecore_Evas *ee = data;
+   Evas_Object *bs_o = ecore_evas_ews_backing_store_get(ee);
+   int x, y, ox, oy;
+
+   if (_ews_border_mover) ecore_animator_del(_ews_border_mover);
+
+   evas_pointer_output_xy_get(evas_object_evas_get(bs_o), &x, &y);
+   evas_object_geometry_get(bs_o, &ox, &oy, NULL, NULL);
+   _ews_border_mover_off.x = x - ox;
+   _ews_border_mover_off.y = y - oy;
+   _ews_border_mover_obj = bs_o;
+   _ews_border_mover = ecore_animator_add(_elm_ews_border_mover, ee);
+}
+
+static void
+_elm_ews_border_sig_move_stop(void *data __UNUSED__, Evas_Object *o __UNUSED__, const char *sig __UNUSED__, const char *source __UNUSED__)
+{
+   if (!_ews_border_mover) return;
+   ecore_animator_del(_ews_border_mover);
+   _ews_border_mover = NULL;
+   _ews_border_mover_obj = NULL;
+}
+
+static Eina_Bool
+_elm_ews_wm_add_cb(void *data __UNUSED__, int type __UNUSED__, void *event_info)
+{
+   Ecore_Evas *ee = event_info;
+   Evas_Object *o = edje_object_add(ecore_evas_ews_evas_get());
+   Evas_Coord x, y, w, h, sw, sh;
+
+   edje_object_signal_callback_add
+     (o, "elm,action,focus", "elm", _elm_ews_border_sig_focus, ee);
+   edje_object_signal_callback_add
+     (o, "elm,action,iconify", "elm", _elm_ews_border_sig_iconify, ee);
+   edje_object_signal_callback_add
+     (o, "elm,action,maximize", "elm", _elm_ews_border_sig_maximize, ee);
+   edje_object_signal_callback_add
+     (o, "elm,action,fullscreen", "elm", _elm_ews_border_sig_fullscreen, ee);
+   edje_object_signal_callback_add
+     (o, "elm,action,restore", "elm", _elm_ews_border_sig_restore, ee);
+   edje_object_signal_callback_add
+     (o, "elm,action,close", "elm", _elm_ews_border_sig_close, ee);
+   edje_object_signal_callback_add
+     (o, "elm,action,menu", "elm", _elm_ews_border_sig_menu, ee);
+   edje_object_signal_callback_add
+     (o, "elm,action,move,start", "elm", _elm_ews_border_sig_move_start, ee);
+   edje_object_signal_callback_add
+     (o, "elm,action,move,stop", "elm", _elm_ews_border_sig_move_stop, ee);
+
+   eina_hash_add(_ews_borders, &ee, o);
+   _elm_ews_wm_border_theme_set(ee, o, NULL);
+
+   ecore_evas_screen_geometry_get(ee, NULL, NULL, &sw, &sh);
+   ecore_evas_geometry_get(ee, NULL, NULL, &w, &h);
+   x = (sw - w) / 2;
+   y = (sh - h) / 2;
+   ecore_evas_move(ee, x, y);
+   ecore_evas_focus_set(ee, EINA_TRUE);
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_elm_ews_wm_del_cb(void *data __UNUSED__, int type __UNUSED__, void *event_info)
+{
+   Ecore_Evas *ee = event_info;
+   eina_hash_del(_ews_borders, &ee, NULL);
+   eina_hash_del(_ews_borders_geo, &ee, NULL);
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_elm_ews_wm_geo_cb(void *data __UNUSED__, int type __UNUSED__, void *event_info)
+{
+   Ecore_Evas *ee = event_info;
+   Evas_Object *o = _elm_ews_wm_border_find(ee);
+   _elm_ews_border_geo_apply(ee, o);
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_elm_ews_wm_show_cb(void *data __UNUSED__, int type __UNUSED__, void *event_info)
+{
+   Ecore_Evas *ee = event_info;
+   Evas_Object *o = _elm_ews_wm_border_find(ee);
+   evas_object_show(o);
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_elm_ews_wm_hide_cb(void *data __UNUSED__, int type __UNUSED__, void *event_info)
+{
+   Ecore_Evas *ee = event_info;
+   Evas_Object *o = _elm_ews_wm_border_find(ee);
+   evas_object_hide(o);
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_elm_ews_wm_focus_cb(void *data __UNUSED__, int type __UNUSED__, void *event_info)
+{
+   Ecore_Evas *ee = event_info;
+   Evas_Object *o = _elm_ews_wm_border_find(ee);
+   _elm_ews_border_focus_apply(ee, o);
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_elm_ews_wm_stack_cb(void *data __UNUSED__, int type __UNUSED__, void *event_info)
+{
+   Ecore_Evas *ee = event_info;
+   Evas_Object *o = _elm_ews_wm_border_find(ee);
+   _elm_ews_border_stack_apply(ee, o);
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_elm_ews_wm_iconified_change_cb(void *data __UNUSED__, int type __UNUSED__, void *event_info)
+{
+   Ecore_Evas *ee = event_info;
+   Evas_Object *o = _elm_ews_wm_border_find(ee);
+   _elm_ews_border_iconified_apply(ee, o);
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_elm_ews_wm_maximized_change_cb(void *data __UNUSED__, int type __UNUSED__, void *event_info)
+{
+   Ecore_Evas *ee = event_info;
+   Evas_Object *o = _elm_ews_wm_border_find(ee);
+   _elm_ews_border_maximized_apply(ee, o);
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_elm_ews_wm_layer_change_cb(void *data __UNUSED__, int type __UNUSED__, void *event_info)
+{
+   Ecore_Evas *ee = event_info;
+   Evas_Object *o = _elm_ews_wm_border_find(ee);
+   _elm_ews_border_layer_apply(ee, o);
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_elm_ews_wm_fullscreen_change_cb(void *data __UNUSED__, int type __UNUSED__, void *event_info)
+{
+   Ecore_Evas *ee = event_info;
+   Evas_Object *o = _elm_ews_wm_border_find(ee);
+   _elm_ews_border_fullscreen_apply(ee, o);
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_elm_ews_wm_config_change_cb(void *data __UNUSED__, int type __UNUSED__, void *event_info)
+{
+   Ecore_Evas *ee = event_info;
+   Evas_Object *o = _elm_ews_wm_border_find(ee);
+   _elm_ews_border_config_apply(ee, o, NULL);
+   return EINA_TRUE;
+}
+
+void
+_elm_ews_wm_rescale(Elm_Theme *th, Eina_Bool use_theme)
+{
+   Eina_Iterator *it;
+   Eina_Hash_Tuple *tp = NULL;
+
+   if (!_ews_borders) return;
+   it = eina_hash_iterator_tuple_new(_ews_borders);
+   if (!use_theme)
+     {
+        EINA_ITERATOR_FOREACH(it, tp)
+          _elm_ews_wm_border_theme_set(*(void**)tp->key, tp->data, NULL);
+
+        if (_ews_bg)
+          _elm_theme_set(NULL, _ews_bg, "ews", "background", "default");
+     }
+   else
+     {
+        EINA_ITERATOR_FOREACH(it, tp)
+          _elm_ews_wm_border_theme_set(*(void**)tp->key, tp->data, th);
+
+        if (_ews_bg)
+          _elm_theme_set(th, _ews_bg, "ews", "background", "default");
+     }
+
+   eina_iterator_free(it);
+}
+
+int
+_elm_ews_wm_init(void)
+{
+   Evas *e;
+   Evas_Object *o;
+
+   if (strcmp(_elm_config->engine, ELM_EWS) != 0)
+     {
+        _ews_used = EINA_FALSE;
+        return EINA_TRUE;
+     }
+
+   e = ecore_evas_ews_evas_get();
+   if (!e) return EINA_FALSE;
+   o = edje_object_add(e);
+   if (!o) return EINA_FALSE;
+
+   if (!_elm_theme_set(NULL, o, "ews", "background", "default"))
+     {
+        ERR("Could not set background theme, fallback to rectangle");
+        evas_object_del(o);
+        _ews_bg = o = NULL;
+     }
+   else
+     _ews_bg = o;
+   ecore_evas_ews_background_set(o);
+
+
+#define ADD_EH(ev, cb)                                          \
+   _ews_ev_handlers = eina_list_append                          \
+     (_ews_ev_handlers, ecore_event_handler_add(ev, cb, NULL))
+   ADD_EH(ECORE_EVAS_EWS_EVENT_ADD, _elm_ews_wm_add_cb);
+   ADD_EH(ECORE_EVAS_EWS_EVENT_DEL, _elm_ews_wm_del_cb);
+   ADD_EH(ECORE_EVAS_EWS_EVENT_RESIZE, _elm_ews_wm_geo_cb);
+   ADD_EH(ECORE_EVAS_EWS_EVENT_MOVE, _elm_ews_wm_geo_cb);
+   ADD_EH(ECORE_EVAS_EWS_EVENT_SHOW, _elm_ews_wm_show_cb);
+   ADD_EH(ECORE_EVAS_EWS_EVENT_HIDE, _elm_ews_wm_hide_cb);
+   ADD_EH(ECORE_EVAS_EWS_EVENT_FOCUS, _elm_ews_wm_focus_cb);
+   ADD_EH(ECORE_EVAS_EWS_EVENT_UNFOCUS, _elm_ews_wm_focus_cb);
+   ADD_EH(ECORE_EVAS_EWS_EVENT_RAISE, _elm_ews_wm_stack_cb);
+   ADD_EH(ECORE_EVAS_EWS_EVENT_LOWER, _elm_ews_wm_stack_cb);
+   ADD_EH(ECORE_EVAS_EWS_EVENT_ICONIFIED_CHANGE, _elm_ews_wm_iconified_change_cb);
+   ADD_EH(ECORE_EVAS_EWS_EVENT_MAXIMIZED_CHANGE, _elm_ews_wm_maximized_change_cb);
+   ADD_EH(ECORE_EVAS_EWS_EVENT_LAYER_CHANGE, _elm_ews_wm_layer_change_cb);
+   ADD_EH(ECORE_EVAS_EWS_EVENT_FULLSCREEN_CHANGE, _elm_ews_wm_fullscreen_change_cb);
+   ADD_EH(ECORE_EVAS_EWS_EVENT_CONFIG_CHANGE, _elm_ews_wm_config_change_cb);
+#undef ADD_EH
+
+   if (!_ews_borders)
+     _ews_borders = eina_hash_pointer_new(_elm_ews_wm_border_del);
+
+   if (!_ews_borders_geo)
+     _ews_borders_geo = eina_hash_pointer_new(free);
+
+   _ews_used = EINA_TRUE;
+   return EINA_TRUE;
+}
+
+void
+_elm_ews_wm_shutdown(void)
+{
+   Ecore_Event_Handler *eh;
+
+   if (_ews_border_mover)
+     {
+        ecore_animator_del(_ews_border_mover);
+        _ews_border_mover = NULL;
+     }
+   _ews_border_mover_obj = NULL;
+
+   EINA_LIST_FREE(_ews_ev_handlers, eh) ecore_event_handler_del(eh);
+   if (_ews_borders)
+     {
+        eina_hash_free(_ews_borders);
+        _ews_borders = NULL;
+     }
+   if (_ews_borders_geo)
+     {
+        eina_hash_free(_ews_borders_geo);
+        _ews_borders_geo = NULL;
+     }
+   _ews_bg = NULL;
+}
diff --git a/src/modules/access_output/Makefile.am b/src/modules/access_output/Makefile.am
new file mode 100644 (file)
index 0000000..0cf2187
--- /dev/null
@@ -0,0 +1,33 @@
+
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CPPFLAGS = \
+-I. \
+-I$(top_builddir) \
+-I$(top_srcdir) \
+-I$(top_srcdir)/src/lib \
+-I$(top_builddir)/src/lib \
+-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \
+-DPACKAGE_LIB_DIR=\"$(libdir)\" \
+@ELEMENTARY_CFLAGS@ \
+@ELEMENTARY_X_CFLAGS@ \
+@ELEMENTARY_FB_CFLAGS@ \
+@ELEMENTARY_WIN32_CFLAGS@ \
+@ELEMENTARY_WINCE_CFLAGS@ \
+@ELEMENTARY_EDBUS_CFLAGS@ \
+@ELEMENTARY_EFREET_CFLAGS@ \
+@ELEMENTARY_ETHUMB_CFLAGS@ \
+@ELEMENTARY_EMAP_CFLAGS@
+
+if ELEMENTARY_WINDOWS_BUILD
+AM_CPPFLAGS += -DELEMENTARY_BUILD
+endif
+
+pkgdir = $(libdir)/elementary/modules/access_output/$(MODULE_ARCH)
+pkg_LTLIBRARIES = module.la
+
+module_la_SOURCES = mod.c
+
+module_la_LIBADD = $(top_builddir)/src/lib/libelementary.la
+module_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -module -avoid-version
+module_la_LIBTOOLFLAGS = --tag=disable-static
diff --git a/src/modules/access_output/mod.c b/src/modules/access_output/mod.c
new file mode 100644 (file)
index 0000000..3956a40
--- /dev/null
@@ -0,0 +1,119 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+
+/* to enable this module
+export ELM_MODULES="access_output>access/api"
+export ELM_ACCESS_MODE=1
+ */
+
+static void (*cb_func) (void *data);
+static void *cb_data;
+static Ecore_Exe *espeak = NULL;
+static Ecore_Event_Handler *exe_exit_handler = NULL;
+static char *tmpf = NULL;
+static int tmpfd = -1;
+
+static Eina_Bool
+_exe_del(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Exe_Event_Del *ev = event;
+
+   if ((espeak) && (ev->exe == espeak))
+     {
+        if (tmpf)
+          {
+             unlink(tmpf);
+             free(tmpf);
+             tmpf = NULL;
+             close(tmpfd);
+          }
+        espeak = NULL;
+        if (cb_func) cb_func(cb_data);
+     }
+   return ECORE_CALLBACK_RENEW;
+}
+
+// module api funcs needed
+EAPI int
+elm_modapi_init(void *m __UNUSED__)
+{
+   exe_exit_handler =
+      ecore_event_handler_add(ECORE_EXE_EVENT_DEL,
+                              _exe_del, NULL);
+   return 1; // succeed always
+}
+
+EAPI int
+elm_modapi_shutdown(void *m __UNUSED__)
+{
+   if (exe_exit_handler)
+     {
+        ecore_event_handler_del(exe_exit_handler);
+        exe_exit_handler = NULL;
+     }
+   return 1; // succeed always
+}
+
+// module fucns for the specific module type
+EAPI void
+out_read(const char *txt)
+{
+   if (!tmpf)
+     {
+        char buf[PATH_MAX];
+
+        snprintf(buf, sizeof(buf), "/tmp/.elm-speak-XXXXXX");
+        tmpfd = mkstemp(buf);
+        if (tmpfd >= 0) tmpf = strdup(buf);
+        else return;
+     }
+   if (write(tmpfd, txt, strlen(txt)) < 0) perror("write to tmpfile (espeak)");
+}
+
+EAPI void
+out_read_done(void)
+{
+   char buf[PATH_MAX];
+
+   if (espeak)
+     {
+        ecore_exe_interrupt(espeak);
+        espeak = NULL;
+     }
+   if (tmpf)
+     {
+        // FIXME: espeak supporets -v XX for voice locale. should provide this
+        // based on actual lang/locale
+        close(tmpfd);
+        snprintf(buf, sizeof(buf), "espeak -p 2 -s 120 -k 10 -m -f %s", tmpf);
+        espeak = ecore_exe_pipe_run(buf,
+                                    ECORE_EXE_NOT_LEADER,
+                                    NULL);
+     }
+}
+
+EAPI void
+out_cancel(void)
+{
+   if (espeak)
+     {
+        ecore_exe_interrupt(espeak);
+        espeak = NULL;
+     }
+   if (tmpf)
+     {
+        unlink(tmpf);
+        free(tmpf);
+        tmpf = NULL;
+        close(tmpfd);
+     }
+}
+
+EAPI void
+out_done_callback_set(void (*func) (void *data), const void *data)
+{
+   cb_func = func;
+   cb_data = (void *)data;
+}