People from Earth: Welcome Elm_Web
authorsachiel <sachiel@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 29 Sep 2011 20:58:22 +0000 (20:58 +0000)
committersachiel <sachiel@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 29 Sep 2011 20:58:22 +0000 (20:58 +0000)
Started by glima as a thin wrapper around ewk_view to make webkit
work better integrated with Elementary, then grew up as a more complete
widget thanks to k-s' magic fingers, and now I screwed it up but it looks
like it works, so there..

Build WebKit-EFL, rebuild Elementary and enjoy elm_web.

git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/elementary@63676 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

13 files changed:
configure.ac
doc/Makefile.am
doc/index.doxy
doc/widgets/Makefile.am
doc/widgets/widget_preview_web.c [new file with mode: 0644]
src/bin/Makefile.am
src/bin/test.c
src/bin/test_web.c [new file with mode: 0644]
src/lib/Elementary.h.in
src/lib/Makefile.am
src/lib/elm_main.c
src/lib/elm_priv.h
src/lib/elm_web.c [new file with mode: 0644]

index c06bdf5..7247235 100644 (file)
@@ -511,6 +511,38 @@ if test "x$want_elementary_ethumb" = "xyes" -a "x$have_elementary_ethumb" = "xno
 fi
 AC_SUBST(ELM_ETHUMB_DEF)
 
+ELM_WEB_DEF="#undef"
+have_elementary_web="no"
+want_elementary_web="auto"
+AC_ARG_ENABLE([web],
+   [AC_HELP_STRING([--disable-web], [disable web (WebKit) support. @<:@default=detect@:>@])],
+   [want_elementary_web=$enableval], [])
+
+if test "x$want_elementary_web" != "xno"; then
+    PKG_CHECK_MODULES([ELEMENTARY_WEB],
+       [
+        ewebkit
+       ],
+       [
+        AC_DEFINE(HAVE_ELEMENTARY_WEB, 1, [Web support for Elementary])
+        webkit_datadir=$($PKG_CONFIG ewebkit --variable=datadir)
+        AC_DEFINE_UNQUOTED(WEBKIT_DATADIR,
+                           "$webkit_datadir",
+                           "WebKit's data dir")
+        have_elementary_web="yes"
+        ELM_WEB_DEF="#define"
+        requirement_elm="web_client ${requirement_elm}"
+       ],
+       [have_elementary_web="no"]
+    )
+else
+    have_elementary_web="no"
+fi
+if test "x$want_elementary_web" = "xyes" -a "x$have_elementary_web" = "xno"; then
+    AC_MSG_ERROR([Web support requested, but no ewebkit found by pkg-config.])
+fi
+AC_SUBST(ELM_WEB_DEF)
+
 ELM_DEBUG_DEF="#undef"
 want_elementary_debug="no"
 AC_ARG_ENABLE([debug],
@@ -625,6 +657,7 @@ echo "    EFreet.................: ${have_elementary_efreet}"
 echo "    EWeather...............: ${have_elementary_eweather}"
 echo "    EMap...................: ${have_elementary_emap}"
 echo "    Ethumb.................: ${have_elementary_ethumb}"
+echo "    Web (WebKit)...........: ${have_elementary_web}"
 echo "    Quick Launch...........: ${have_fork}"
 echo "    EIO....................: ${have_eio}"
 echo "    Emotion................: ${have_emotion}"
index f304a1f..e59ad9f 100644 (file)
@@ -80,7 +80,8 @@ WGT_PREVIEW = \
        win:preview-00.png:widget_preview_win:200:200 \
        table:preview-00.png:widget_preview_table:100:100 \
        menu:preview-00.png:widget_preview_menu:100:100 \
-       thumb:preview-00.png:widget_preview_thumb:100:100
+       thumb:preview-00.png:widget_preview_thumb:100:100 \
+       web:preview-00.png:widget_preview_web:300:300
 
 widget-build:
        @$(MAKE) -C widgets
index caebcd7..0f73202 100644 (file)
  * @image latex img/toolbar.eps
  * @li @ref Tooltips
  * @li @ref Video
+ * @li @ref Web
+ *
+ * @image html img/widget/web/preview-00.png
+ * @image latex img/widget/web/preview-00.eps
  * @li @ref Win
  *
  * @image html img/widget/win/preview-00.png
index 86343c8..33e02a0 100644 (file)
@@ -91,7 +91,8 @@ widget_preview_scroller \
 widget_preview_table \
 widget_preview_win \
 widget_preview_menu \
-widget_preview_thumb
+widget_preview_thumb \
+widget_preview_web
 
 LDADD = $(top_builddir)/src/lib/libelementary.la @ELEMENTARY_EWEATHER_LIBS@ @ELEMENTARY_EDBUS_LIBS@ @ELEMENTARY_EFREET_LIBS@ @ELEMENTARY_EMAP_LIBS@ @ELEMENTARY_LIBS@ @EIO_LIBS@ @my_libs@
 
@@ -168,5 +169,6 @@ EXTRA_DIST = \
        widget_preview_win.c \
        widget_preview_menu.c \
        widget_preview_thumb.c \
+       widget_preview_web.c \
        widget_preview_tmpl_foot.c \
        widget_preview_tmpl_head.c
diff --git a/doc/widgets/widget_preview_web.c b/doc/widgets/widget_preview_web.c
new file mode 100644 (file)
index 0000000..1169074
--- /dev/null
@@ -0,0 +1,12 @@
+#include "widget_preview_tmpl_head.c"
+
+elm_need_web();
+
+Evas_Object *o = elm_web_add(win);
+evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+elm_win_resize_object_add(win, o);
+evas_object_show(o);
+
+elm_web_uri_set(o, "http://www.enlightenment.org");
+
+#include "widget_preview_tmpl_foot.c"
index 43fa6c3..8833197 100644 (file)
@@ -19,7 +19,8 @@ AM_CPPFLAGS = \
 @ELEMENTARY_EWEATHER_CFLAGS@ \
 @ELEMENTARY_ETHUMB_CFLAGS@ \
 @ELEMENTARY_EMAP_CFLAGS@ \
-@EIO_CFLAGS@
+@EIO_CFLAGS@ \
+@ELEMENTARY_WEB_CFLAGS@
 
 bin_PROGRAMS = @ELEMENTARY_TEST_PRG@ @ELEMENTARY_CONFIG_PRG@
 if BUILD_QUICKLAUNCH
@@ -103,6 +104,7 @@ test_toolbar.c \
 test_tooltip.c \
 test_transit.c \
 test_weather.c \
+test_web.c \
 test_win_inline.c \
 test_win_state.c
 
@@ -117,6 +119,7 @@ elementary_test_LDADD = $(top_builddir)/src/lib/libelementary.la \
        @ELEMENTARY_EMAP_LIBS@ \
        @ELEMENTARY_LIBS@ \
        @EIO_LIBS@ \
+       @ELEMENTARY_WEB_LIBS@ \
        @my_libs@
 elementary_test_LDFLAGS =
 
@@ -159,7 +162,8 @@ elementary_testql_LTLIBRARIES = elementary_testql.la
 elementary_testql_la_SOURCES = $(elementary_test_SOURCES)
 elementary_testql_la_LIBADD = $(top_builddir)/src/lib/libelementary.la \
        @ELEMENTARY_EWEATHER_LIBS@ \
-       @EIO_LIBS@
+       @EIO_LIBS@ \
+       @ELEMENTARY_WEB_LIBS@
 
 elementary_testql_la_CFLAGS =
 elementary_testql_la_LDFLAGS = -module -avoid-version -no-undefined
@@ -170,7 +174,8 @@ elementary_testql_LDADD = $(top_builddir)/src/lib/libelementary.la \
        @ELEMENTARY_EFREET_LIBS@ \
        @ELEMENTARY_EMAP_LIBS@ \
        @ELEMENTARY_LIBS@ \
-       @EIO_LIBS@
+       @EIO_LIBS@ \
+       @ELEMENTARY_WEB_LIBS@ \
        @my_libs@
 
 elementary_testql_CFLAGS = -DELM_LIB_QUICKLAUNCH=1
index 8bb1c42..3bf5f53 100644 (file)
@@ -147,6 +147,9 @@ void test_factory(void *data, Evas_Object *obj, void *event_info);
 #ifdef HAVE_EIO
 void test_eio(void *data, Evas_Object *obj, void *event_info);
 #endif
+#ifdef HAVE_ELEMENTARY_WEB
+void test_web(void *data, Evas_Object *obj, void *event_info);
+#endif
 
 struct elm_test
 {
@@ -429,6 +432,9 @@ add_tests:
    ADD_TEST("Gesture Layer", test_gesture_layer);
    ADD_TEST("Naviframe", test_naviframe);
    ADD_TEST("Factory", test_factory);
+#ifdef HAVE_ELEMENTARY_WEB
+   ADD_TEST("Web", test_web);
+#endif
 #undef ADD_TEST
 
    if (autorun)
@@ -477,6 +483,8 @@ elm_main(int argc, char **argv)
    Eina_Bool test_win_only = EINA_FALSE;
    char *autorun = NULL;
 
+   elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);
+
    /* tell elm about our app so it can figure out where to get files */
    elm_app_compile_bin_dir_set(PACKAGE_BIN_DIR);
    elm_app_compile_data_dir_set(PACKAGE_DATA_DIR);
diff --git a/src/bin/test_web.c b/src/bin/test_web.c
new file mode 100644 (file)
index 0000000..ebbf297
--- /dev/null
@@ -0,0 +1,370 @@
+#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_notify_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_notify_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__, const char *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
+_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);
+     }
+   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);
+     }
+}
+
+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);
+
+   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
index aa5cc0c..984e4a1 100644 (file)
@@ -321,6 +321,7 @@ contact with the developers and maintainers.
 @ELM_EDBUS_DEF@ ELM_EDBUS
 @ELM_EFREET_DEF@ ELM_EFREET
 @ELM_ETHUMB_DEF@ ELM_ETHUMB
+@ELM_WEB_DEF@ ELM_WEB
 @ELM_EMAP_DEF@ ELM_EMAP
 @ELM_DEBUG_DEF@ ELM_DEBUG
 @ELM_ALLOCA_H_DEF@ ELM_ALLOCA_H
@@ -906,6 +907,14 @@ extern "C" {
    EAPI Eina_Bool    elm_need_ethumb(void);
 
    /**
+    * This must be called before any other function that handle with
+    * elm_web objects or ewk_view instances.
+    *
+    * @ingroup Web
+    */
+   EAPI Eina_Bool    elm_need_web(void);
+
+   /**
     * Set a new policy's value (for a given policy group/identifier).
     *
     * @param policy policy identifier, as in @ref Elm_Policy.
@@ -12847,6 +12856,797 @@ extern "C" {
     */
 
    /**
+    * @defgroup Web Web
+    *
+    * @image html img/widget/web/preview-00.png
+    * @image latex img/widget/web/preview-00.eps
+    *
+    * A web object is used for displaying web pages (HTML/CSS/JS)
+    * using WebKit-EFL. You must have compiled Elementary with
+    * ewebkit support.
+    *
+    * Signals that you can add callbacks for are:
+    * @li "download,request": A file download has been requested. Event info is
+    * a pointer to a Elm_Web_Download
+    * @li "editorclient,contents,changed": Editor client's contents changed
+    * @li "editorclient,selection,changed": Editor client's selection changed
+    * @li "frame,created": A new frame was created. Event info is an
+    * Evas_Object which can be handled with WebKit's ewk_frame API
+    * @li "icon,received": An icon was received by the main frame
+    * @li "inputmethod,changed": Input method changed. Event info is an
+    * Eina_Bool indicating whether it's enabled or not
+    * @li "js,windowobject,clear": JS window object has been cleared
+    * @li "link,hover,in": Mouse cursor is hovering over a link. Event info
+    * is a char *link[2], where the first string contains the URL the link
+    * points to, and the second one the title of the link
+    * @li "link,hover,out": Mouse cursor left the link
+    * @li "load,document,finished": Loading of a document finished. Event info
+    * is the frame that finished loading
+    * @li "load,error": Load failed. Event info is a pointer to
+    * Elm_Web_Frame_Load_Error
+    * @li "load,finished": Load finished. Event info is NULL on success, on
+    * error it's a pointer to Elm_Web_Frame_Load_Error
+    * @li "load,newwindow,show": A new window was created and is ready to be
+    * shown
+    * @li "load,progress": Overall load progress. Event info is a pointer to
+    * a double containing a value between 0.0 and 1.0
+    * @li "load,provisional": Started provisional load
+    * @li "load,started": Loading of a document started
+    * @li "menubar,visible,get": Queries if the menubar is visible. Event info
+    * is a pointer to Eina_Bool where the callback should set EINA_TRUE if
+    * the menubar is visible, or EINA_FALSE in case it's not
+    * @li "menubar,visible,set": Informs menubar visibility. Event info is
+    * an Eina_Bool indicating the visibility
+    * @li "popup,created": A dropdown widget was activated, requesting its
+    * popup menu to be created. Event info is a pointer to Elm_Web_Menu
+    * @li "popup,willdelete": The web object is ready to destroy the popup
+    * object created. Event info is a pointer to Elm_Web_Menu
+    * @li "ready": Page is fully loaded
+    * @li "scrollbars,visible,get": Queries visibility of scrollbars. Event
+    * info is a pointer to Eina_Bool where the visibility state should be set
+    * @li "scrollbars,visible,set": Informs scrollbars visibility. Event info
+    * is an Eina_Bool with the visibility state set
+    * @li "statusbar,text,set": Text of the statusbar changed. Even info is
+    * a string with the new text
+    * @li "statusbar,visible,get": Queries visibility of the status bar.
+    * Event info is a pointer to Eina_Bool where the visibility state should be
+    * set.
+    * @li "statusbar,visible,set": Informs statusbar visibility. Event info is
+    * an Eina_Bool with the visibility value
+    * @li "title,changed": Title of the main frame changed. Event info is a
+    * string with the new title
+    * @li "toolbars,visible,get": Queries visibility of toolbars. Event info
+    * is a pointer to Eina_Bool where the visibility state should be set
+    * @li "toolbars,visible,set": Informs the visibility of toolbars. Event
+    * info is an Eina_Bool with the visibility state
+    * @li "tooltip,text,set": Show and set text of a tooltip. Event info is
+    * a string with the text to show
+    * @li "uri,changed": URI of the main frame changed. Event info is a string
+    * with the new URI
+    * @li "view,resized": The web object internal's view changed sized
+    * @li "windows,close,request": A JavaScript request to close the current
+    * window was requested
+    * @li "zoom,animated,end": Animated zoom finished
+    *
+    * available styles:
+    * - default
+    *
+    * An example of use of web:
+    *
+    * - @ref web_example_01 TBD
+    */
+
+   /**
+    * @addtogroup Web
+    * @{
+    */
+
+   /**
+    * Structure used to report load errors.
+    *
+    * Load errors are reported as signal by elm_web. All the strings are
+    * temporary references and should @b not be used after the signal
+    * callback returns. If it's required, make copies with strdup() or
+    * eina_stringshare_add() (they are not even guaranteed to be
+    * stringshared, so must use eina_stringshare_add() and not
+    * eina_stringshare_ref()).
+    */
+   typedef struct _Elm_Web_Frame_Load_Error Elm_Web_Frame_Load_Error;
+   /**
+    * Structure used to report load errors.
+    *
+    * Load errors are reported as signal by elm_web. All the strings are
+    * temporary references and should @b not be used after the signal
+    * callback returns. If it's required, make copies with strdup() or
+    * eina_stringshare_add() (they are not even guaranteed to be
+    * stringshared, so must use eina_stringshare_add() and not
+    * eina_stringshare_ref()).
+    */
+   struct _Elm_Web_Frame_Load_Error
+     {
+        int code; /**< Numeric error code */
+        Eina_Bool is_cancellation; /**< Error produced by cancelling a request */
+        const char *domain; /**< Error domain name */
+        const char *description; /**< Error description (already localized) */
+        const char *failing_url; /**< The URL that failed to load */
+        Evas_Object *frame; /**< Frame object that produced the error */
+     };
+
+   /**
+    * The possibles types that the items in a menu can be
+    */
+   typedef enum _Elm_Web_Menu_Item_Type Elm_Web_Menu_Item_Type;
+   /**
+    * The possibles types that the items in a menu can be
+    */
+   enum _Elm_Web_Menu_Item_Type
+     {
+        ELM_WEB_MENU_SEPARATOR,
+        ELM_WEB_MENU_GROUP,
+        ELM_WEB_MENU_OPTION
+     };
+
+   /**
+    * Structure describing the items in a menu
+    */
+   typedef struct _Elm_Web_Menu_Item Elm_Web_Menu_Item;
+   /**
+    * Structure describing the items in a menu
+    */
+   struct _Elm_Web_Menu_Item
+     {
+        const char *text; /**< The text for the item */
+        Elm_Web_Menu_Item_Type type; /**< The type of the item */
+     };
+
+   /**
+    * Structure describing the menu of a popup
+    *
+    * This structure will be passed as the @c event_info for the "popup,create"
+    * signal, which is emitted when a dropdown menu is opened. Users wanting
+    * to handle these popups by themselves should listen to this signal and
+    * set the @c handled property of the struct to @c EINA_TRUE. Leaving this
+    * property as @c EINA_FALSE means that the user will not handle the popup
+    * and the default implementation will be used.
+    *
+    * When the popup is ready to be dismissed, a "popup,willdelete" signal
+    * will be emitted to notify the user that it can destroy any objects and
+    * free all data related to it.
+    *
+    * @see elm_web_popup_selected_set()
+    * @see elm_web_popup_destroy()
+    */
+   typedef struct _Elm_Web_Menu Elm_Web_Menu;
+   /**
+    * Structure describing the menu of a popup
+    *
+    * This structure will be passed as the @c event_info for the "popup,create"
+    * signal, which is emitted when a dropdown menu is opened. Users wanting
+    * to handle these popups by themselves should listen to this signal and
+    * set the @c handled property of the struct to @c EINA_TRUE. Leaving this
+    * property as @c EINA_FALSE means that the user will not handle the popup
+    * and the default implementation will be used.
+    *
+    * When the popup is ready to be dismissed, a "popup,willdelete" signal
+    * will be emitted to notify the user that it can destroy any objects and
+    * free all data related to it.
+    *
+    * @see elm_web_popup_selected_set()
+    * @see elm_web_popup_destroy()
+    */
+   struct _Elm_Web_Menu
+     {
+        Eina_List *items; /**< List of #Elm_Web_Menu_Item */
+        int x; /**< The X position of the popup, relative to the elm_web object */
+        int y; /**< The Y position of the popup, relative to the elm_web object */
+        int width; /**< Width of the popup menu */
+        int height; /**< Height of the popup menu */
+
+        Eina_Bool handled : 1; /**< Set to @c EINA_TRUE by the user to indicate that the popup has been handled and the default implementation should be ignored. Leave as @c EINA_FALSE otherwise. */
+     };
+
+   typedef struct _Elm_Web_Download Elm_Web_Download;
+   struct _Elm_Web_Download
+     {
+        const char *url;
+     };
+
+   /**
+    * Opaque handler containing the features (such as statusbar, menubar, etc)
+    * that are to be set on a newly requested window.
+    */
+   typedef struct _Elm_Web_Window_Features Elm_Web_Window_Features;
+   /**
+    * Callback type for the create_window hook.
+    *
+    * The function parameters are:
+    * @li @p data User data pointer set when setting the hook function
+    * @li @p obj The elm_web object requesting the new window
+    * @li @p js Set to @c EINA_TRUE if the request was originated from
+    * JavaScript. @c EINA_FALSE otherwise.
+    * @li @p window_features A pointer of #Elm_Web_Window_Features indicating
+    * the features requested for the new window.
+    *
+    * The returned value of the function should be the @c elm_web widget where
+    * the request will be loaded. That is, if a new window or tab is created,
+    * the elm_web widget in it should be returned, and @b NOT the window
+    * object.
+    * Returning @c NULL should cancel the request.
+    *
+    * @see elm_web_window_create_hook_set()
+    */
+   typedef Evas_Object *(*Elm_Web_Window_Open)(void *data, Evas_Object *obj, Eina_Bool js, const Elm_Web_Window_Features *window_features);
+   /**
+    * Callback type for the JS alert hook.
+    *
+    * The function parameters are:
+    * @li @p data User data pointer set when setting the hook function
+    * @li @p obj The elm_web object requesting the new window
+    * @li @p message The message to show in the alert dialog
+    *
+    * The function should return the object representing the alert dialog.
+    * Elm_Web will run a second main loop to handle the dialog and normal
+    * flow of the application will be restored when the object is deleted, so
+    * the user should handle the popup properly in order to delete the object
+    * when the action is finished.
+    * If the function returns @c NULL the popup will be ignored.
+    *
+    * @see elm_web_dialog_alert_hook_set()
+    */
+   typedef Evas_Object *(*Elm_Web_Dialog_Alert)(void *data, Evas_Object *obj, const char *message);
+   /**
+    * Callback type for the JS confirm hook.
+    *
+    * The function parameters are:
+    * @li @p data User data pointer set when setting the hook function
+    * @li @p obj The elm_web object requesting the new window
+    * @li @p message The message to show in the confirm dialog
+    * @li @p ret Pointer where to store the user selection. @c EINA_TRUE if
+    * the user selected @c Ok, @c EINA_FALSE otherwise.
+    *
+    * The function should return the object representing the confirm dialog.
+    * Elm_Web will run a second main loop to handle the dialog and normal
+    * flow of the application will be restored when the object is deleted, so
+    * the user should handle the popup properly in order to delete the object
+    * when the action is finished.
+    * If the function returns @c NULL the popup will be ignored.
+    *
+    * @see elm_web_dialog_confirm_hook_set()
+    */
+   typedef Evas_Object *(*Elm_Web_Dialog_Confirm)(void *data, Evas_Object *obj, const char *message, Eina_Bool *ret);
+   /**
+    * Callback type for the JS prompt hook.
+    *
+    * The function parameters are:
+    * @li @p data User data pointer set when setting the hook function
+    * @li @p obj The elm_web object requesting the new window
+    * @li @p message The message to show in the prompt dialog
+    * @li @p def_value The default value to present the user in the entry
+    * @li @p value Pointer where to store the value given by the user. Must
+    * be a malloc'ed string or @c NULL if the user cancelled the popup.
+    * @li @p ret Pointer where to store the user selection. @c EINA_TRUE if
+    * the user selected @c Ok, @c EINA_FALSE otherwise.
+    *
+    * The function should return the object representing the prompt dialog.
+    * Elm_Web will run a second main loop to handle the dialog and normal
+    * flow of the application will be restored when the object is deleted, so
+    * the user should handle the popup properly in order to delete the object
+    * when the action is finished.
+    * If the function returns @c NULL the popup will be ignored.
+    *
+    * @see elm_web_dialog_prompt_hook_set()
+    */
+   typedef Evas_Object *(*Elm_Web_Dialog_Prompt)(void *data, Evas_Object *obj, const char *message, const char *def_value, char **value, Eina_Bool *ret);
+   /**
+    * Callback type for the JS file selector hook.
+    *
+    * The function parameters are:
+    * @li @p data User data pointer set when setting the hook function
+    * @li @p obj The elm_web object requesting the new window
+    * @li @p allows_multiple @c EINA_TRUE if multiple files can be selected.
+    * @li @p accept_types Mime types accepted
+    * @li @p selected Pointer where to store the list of malloc'ed strings
+    * containing the path to each file selected. Must be @c NULL if the file
+    * dialog is cancelled
+    * @li @p ret Pointer where to store the user selection. @c EINA_TRUE if
+    * the user selected @c Ok, @c EINA_FALSE otherwise.
+    *
+    * The function should return the object representing the file selector
+    * dialog.
+    * Elm_Web will run a second main loop to handle the dialog and normal
+    * flow of the application will be restored when the object is deleted, so
+    * the user should handle the popup properly in order to delete the object
+    * when the action is finished.
+    * If the function returns @c NULL the popup will be ignored.
+    *
+    * @see elm_web_dialog_file selector_hook_set()
+    */
+   typedef Evas_Object *(*Elm_Web_Dialog_File_Selector)(void *data, Evas_Object *obj, Eina_Bool allows_multiple, const char *accept_types, Eina_List **selected, Eina_Bool *ret);
+   /**
+    * Callback type for the JS console message hook.
+    *
+    * When a console message is added from JavaScript, any set function to the
+    * console message hook will be called for the user to handle. There is no
+    * default implementation of this hook.
+    *
+    * The function parameters are:
+    * @li @p data User data pointer set when setting the hook function
+    * @li @p obj The elm_web object that originated the message
+    * @li @p message The message sent
+    * @li @p line_number The line number
+    * @li @p source_id Source id
+    *
+    * @see elm_web_console_message_hook_set()
+    */
+   typedef void (*Elm_Web_Console_Message)(void *data, Evas_Object *obj, const char *message, unsigned int line_number, const char *source_id);
+   /**
+    * Add a new web object to the parent.
+    *
+    * @param parent The parent object.
+    * @return The new object or NULL if it cannot be created.
+    *
+    * @see elm_web_uri_set()
+    * @see elm_web_webkit_view_get()
+    */
+   EAPI Evas_Object                 *elm_web_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+
+   /**
+    * Get internal ewk_view object from web object.
+    *
+    * Elementary may not provide some low level features of EWebKit,
+    * instead of cluttering the API with proxy methods we opted to
+    * return the internal reference. Be careful using it as it may
+    * interfere with elm_web behavior.
+    *
+    * @param obj The web object.
+    * @return The internal ewk_view object or NULL if it does not
+    *         exist. (Failure to create or Elementary compiled without
+    *         ewebkit)
+    *
+    * @see elm_web_add()
+    */
+   EAPI Evas_Object                 *elm_web_webkit_view_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+
+   /**
+    * Sets the function to call when a new window is requested
+    *
+    * This hook will be called when a request to create a new window is
+    * issued from the web page loaded.
+    * There is no default implementation for this feature, so leaving this
+    * unset or passing @c NULL in @p func will prevent new windows from
+    * opening.
+    *
+    * @param obj The web object where to set the hook function
+    * @param func The hook function to be called when a window is requested
+    * @param data User data
+    */
+   EAPI void                         elm_web_window_create_hook_set(Evas_Object *obj, Elm_Web_Window_Open func, void *data);
+   /**
+    * Sets the function to call when an alert dialog
+    *
+    * This hook will be called when a JavaScript alert dialog is requested.
+    * If no function is set or @c NULL is passed in @p func, the default
+    * implementation will take place.
+    *
+    * @param obj The web object where to set the hook function
+    * @param func The callback function to be used
+    * @param data User data
+    *
+    * @see elm_web_inwin_mode_set()
+    */
+   EAPI void                         elm_web_dialog_alert_hook_set(Evas_Object *obj, Elm_Web_Dialog_Alert func, void *data);
+   /**
+    * Sets the function to call when an confirm dialog
+    *
+    * This hook will be called when a JavaScript confirm dialog is requested.
+    * If no function is set or @c NULL is passed in @p func, the default
+    * implementation will take place.
+    *
+    * @param obj The web object where to set the hook function
+    * @param func The callback function to be used
+    * @param data User data
+    *
+    * @see elm_web_inwin_mode_set()
+    */
+   EAPI void                         elm_web_dialog_confirm_hook_set(Evas_Object *obj, Elm_Web_Dialog_Confirm func, void *data);
+   /**
+    * Sets the function to call when an prompt dialog
+    *
+    * This hook will be called when a JavaScript prompt dialog is requested.
+    * If no function is set or @c NULL is passed in @p func, the default
+    * implementation will take place.
+    *
+    * @param obj The web object where to set the hook function
+    * @param func The callback function to be used
+    * @param data User data
+    *
+    * @see elm_web_inwin_mode_set()
+    */
+   EAPI void                         elm_web_dialog_prompt_hook_set(Evas_Object *obj, Elm_Web_Dialog_Prompt func, void *data);
+   /**
+    * Sets the function to call when an file selector dialog
+    *
+    * This hook will be called when a JavaScript file selector dialog is
+    * requested.
+    * If no function is set or @c NULL is passed in @p func, the default
+    * implementation will take place.
+    *
+    * @param obj The web object where to set the hook function
+    * @param func The callback function to be used
+    * @param data User data
+    *
+    * @see elm_web_inwin_mode_set()
+    */
+   EAPI void                         elm_web_dialog_file_selector_hook_set(Evas_Object *obj, Elm_Web_Dialog_File_Selector func, void *data);
+   /**
+    * Sets the function to call when a console message is emitted from JS
+    *
+    * This hook will be called when a console message is emitted from
+    * JavaScript. There is no default implementation for this feature.
+    *
+    * @param obj The web object where to set the hook function
+    * @param func The callback function to be used
+    * @param data User data
+    */
+   EAPI void                         elm_web_console_message_hook_set(Evas_Object *obj, Elm_Web_Console_Message func, void *data);
+   /**
+    * Gets the status of the tab propagation
+    *
+    * @param obj The web object to query
+    * @return EINA_TRUE if tab propagation is enabled, EINA_FALSE otherwise
+    *
+    * @see elm_web_tab_propagate_set()
+    */
+   EAPI Eina_Bool                    elm_web_tab_propagate_get(const Evas_Object *obj);
+   /**
+    * Sets whether to use tab propagation
+    *
+    * If tab propagation is enabled, whenever the user presses the Tab key,
+    * Elementary will handle it and switch focus to the next widget.
+    * The default value is disabled, where WebKit will handle the Tab key to
+    * cycle focus though its internal objects, jumping to the next widget
+    * only when that cycle ends.
+    *
+    * @param obj The web object
+    * @param propagate Whether to propagate Tab keys to Elementary or not
+    */
+   EAPI void                         elm_web_tab_propagate_set(Evas_Object *obj, Eina_Bool propagate);
+   /**
+    * Sets the URI for the web object
+    *
+    * It must be a full URI, with resource included, in the form
+    * http://www.enlightenment.org or file:///tmp/something.html
+    *
+    * @param obj The web object
+    * @param uri The URI to set
+    * @return EINA_TRUE if the URI could be, EINA_FALSE if an error occurred
+    */
+   EAPI Eina_Bool                    elm_web_uri_set(Evas_Object *obj, const char *uri);
+   /**
+    * Gets the current URI for the object
+    *
+    * The returned string must not be freed and is guaranteed to be
+    * stringshared.
+    *
+    * @param obj The web object
+    * @return A stringshared internal string with the current URI, or NULL on
+    * failure
+    */
+   EAPI const char                  *elm_web_uri_get(const Evas_Object *obj);
+   /**
+    * Gets the current title
+    *
+    * The returned string must not be freed and is guaranteed to be
+    * stringshared.
+    *
+    * @param obj The web object
+    * @return A stringshared internal string with the current title, or NULL on
+    * failure
+    */
+   EAPI const char                  *elm_web_title_get(const Evas_Object *obj);
+   /**
+    * Sets the background color to be used by the web object
+    *
+    * This is the color that will be used by default when the loaded page
+    * does not set it's own. Color values are pre-multiplied.
+    *
+    * @param obj The web object
+    * @param r Red component
+    * @param g Green component
+    * @param b Blue component
+    * @param a Alpha component
+    */
+   EAPI void                         elm_web_bg_color_set(Evas_Object *obj, int r, int g, int b, int a);
+   /**
+    * Gets the background color to be used by the web object
+    *
+    * This is the color that will be used by default when the loaded page
+    * does not set it's own. Color values are pre-multiplied.
+    *
+    * @param obj The web object
+    * @param r Red component
+    * @param g Green component
+    * @param b Blue component
+    * @param a Alpha component
+    */
+   EAPI void                         elm_web_bg_color_get(const Evas_Object *obj, int *r, int *g, int *b, int *a);
+   /**
+    * Gets a copy of the currently selected text
+    *
+    * The string returned must be freed by the user when it's done with it.
+    *
+    * @param obj The web object
+    * @return A newly allocated string, or NULL if nothing is selected or an
+    * error occurred
+    */
+   EAPI char                        *elm_view_selection_get(const Evas_Object *obj);
+   /**
+    * Tells the web object which index in the currently open popup was selected
+    *
+    * When the user handles the popup creation from the "popup,created" signal,
+    * it needs to tell the web object which item was selected by calling this
+    * function with the index corresponding to the item.
+    *
+    * @param obj The web object
+    * @param index The index selected
+    *
+    * @see elm_web_popup_destroy()
+    */
+   EAPI void                         elm_web_popup_selected_set(Evas_Object *obj, int index);
+   /**
+    * Dismisses an open dropdown popup
+    *
+    * When the popup from a dropdown widget is to be dismissed, either after
+    * selecting an option or to cancel it, this function must be called, which
+    * will later emit an "popup,willdelete" signal to notify the user that
+    * any memory and objects related to this popup can be freed.
+    *
+    * @param obj The web object
+    * @return EINA_TRUE if the menu was successfully destroyed, or EINA_FALSE
+    * if there was no menu to destroy
+    */
+   EAPI Eina_Bool                    elm_web_popup_destroy(Evas_Object *obj);
+   /**
+    * Searches the given string in a document.
+    *
+    * @param obj The web object where to search the text
+    * @param string String to search
+    * @param case_sensitive If search should be case sensitive or not
+    * @param forward If search is from cursor and on or backwards
+    * @param wrap If search should wrap at the end
+    *
+    * @return @c EINA_TRUE if the given string was found, @c EINA_FALSE if not
+    * or failure
+    */
+   EAPI Eina_Bool                    elm_web_text_search(const Evas_Object *obj, const char *string, Eina_Bool case_sensitive, Eina_Bool forward, Eina_Bool wrap);
+   /**
+    * Marks matches of the given string in a document.
+    *
+    * @param obj The web object where to search text
+    * @param string String to match
+    * @param case_sensitive If match should be case sensitive or not
+    * @param highlight If matches should be highlighted
+    * @param limit Maximum amount of matches, or zero to unlimited
+    *
+    * @return number of matched @a string
+    */
+   EAPI unsigned int                 elm_web_text_matches_mark(Evas_Object *obj, const char *string, Eina_Bool case_sensitive, Eina_Bool highlight, unsigned int limit);
+   /**
+    * Clears all marked matches in the document
+    *
+    * @param obj The web object
+    *
+    * @return EINA_TRUE on success, EINA_FALSE otherwise
+    */
+   EAPI Eina_Bool                    elm_web_text_matches_unmark_all(Evas_Object *obj);
+   /**
+    * Sets whether to highlight the matched marks
+    *
+    * If enabled, marks set with elm_web_text_matches_mark() will be
+    * highlighted.
+    *
+    * @param obj The web object
+    * @param highlight Whether to highlight the marks or not
+    *
+    * @return EINA_TRUE on success, EINA_FALSE otherwise
+    */
+   EAPI Eina_Bool                    elm_web_text_matches_highlight_set(Evas_Object *obj, Eina_Bool highlight);
+   /**
+    * Gets whether highlighting marks is enabled
+    *
+    * @param The web object
+    *
+    * @return EINA_TRUE is marks are set to be highlighted, EINA_FALSE
+    * otherwise
+    */
+   EAPI Eina_Bool                    elm_web_text_matches_highlight_get(const Evas_Object *obj);
+   /**
+    * Gets the overall loading progress of the page
+    *
+    * Returns the estimated loading progress of the page, with a value between
+    * 0.0 and 1.0. This is an estimated progress accounting for all the frames
+    * included in the page.
+    *
+    * @param The web object
+    *
+    * @return A value between 0.0 and 1.0 indicating the progress, or -1.0 on
+    * failure
+    */
+   EAPI double                       elm_web_load_progress_get(const Evas_Object *obj);
+   /**
+    * Stops loading the current page
+    *
+    * Cancels the loading of the current page in the web object. This will
+    * cause a "load,error" signal to be emitted, with the is_cancellation
+    * flag set to EINA_TRUE.
+    *
+    * @param obj The web object
+    *
+    * @return EINA_TRUE if the cancel was successful, EINA_FALSE otherwise
+    */
+   EAPI Eina_Bool                    elm_web_stop(Evas_Object *obj);
+   /**
+    * Requests a reload of the current document in the object
+    *
+    * @param obj The web object
+    *
+    * @return EINA_TRUE on success, EINA_FALSE otherwise
+    */
+   EAPI Eina_Bool                    elm_web_reload(Evas_Object *obj);
+   /**
+    * Requests a reload of the current document, avoiding any existing caches
+    *
+    * @param obj The web object
+    *
+    * @return EINA_TRUE on success, EINA_FALSE otherwise
+    */
+   EAPI Eina_Bool                    elm_web_reload_full(Evas_Object *obj);
+   /**
+    * Goes back one step in the browsing history
+    *
+    * This is equivalent to calling elm_web_object_navigate(obj, -1);
+    *
+    * @param obj The web object
+    *
+    * @return EINA_TRUE on success, EINA_FALSE otherwise
+    *
+    * @see elm_web_history_enable_set()
+    * @see elm_web_back_possible()
+    * @see elm_web_forward()
+    * @see elm_web_navigate()
+    */
+   EAPI Eina_Bool                    elm_web_back(Evas_Object *obj);
+   /**
+    * Goes forward one step in the browsing history
+    *
+    * This is equivalent to calling elm_web_object_navigate(obj, 1);
+    *
+    * @param obj The web object
+    *
+    * @return EINA_TRUE on success, EINA_FALSE otherwise
+    *
+    * @see elm_web_history_enable_set()
+    * @see elm_web_forward_possible()
+    * @see elm_web_back()
+    * @see elm_web_navigate()
+    */
+   EAPI Eina_Bool                    elm_web_forward(Evas_Object *obj);
+   /**
+    * Jumps the given number of steps in the browsing history
+    *
+    * The @p steps value can be a negative integer to back in history, or a
+    * positive to move forward.
+    *
+    * @param obj The web object
+    * @param steps The number of steps to jump
+    *
+    * @return EINA_TRUE on success, EINA_FALSE on error or if not enough
+    * history exists to jump the given number of steps
+    *
+    * @see elm_web_history_enable_set()
+    * @see elm_web_navigate_possible()
+    * @see elm_web_back()
+    * @see elm_web_forward()
+    */
+   EAPI Eina_Bool                    elm_web_navigate(Evas_Object *obj, int steps);
+   /**
+    * Queries whether it's possible to go back in history
+    *
+    * @param obj The web object
+    *
+    * @return EINA_TRUE if it's possible to back in history, EINA_FALSE
+    * otherwise
+    */
+   EAPI Eina_Bool                    elm_web_back_possible(Evas_Object *obj);
+   /**
+    * Queries whether it's possible to go forward in history
+    *
+    * @param obj The web object
+    *
+    * @return EINA_TRUE if it's possible to forward in history, EINA_FALSE
+    * otherwise
+    */
+   EAPI Eina_Bool                    elm_web_forward_possible(Evas_Object *obj);
+   /**
+    * Queries whether it's possible to jump the given number of steps
+    *
+    * The @p steps value can be a negative integer to back in history, or a
+    * positive to move forward.
+    *
+    * @param obj The web object
+    * @param steps The number of steps to check for
+    *
+    * @return EINA_TRUE if enough history exists to perform the given jump,
+    * EINA_FALSE otherwise
+    */
+   EAPI Eina_Bool                    elm_web_navigate_possible(Evas_Object *obj, int steps);
+   /**
+    * Gets whether browsing history is enabled for the given object
+    *
+    * @param obj The web object
+    *
+    * @return EINA_TRUE if history is enabled, EINA_FALSE otherwise
+    */
+   EAPI Eina_Bool                    elm_web_history_enable_get(const Evas_Object *obj);
+   /**
+    * Enables or disables the browsing history
+    *
+    * @param obj The web object
+    * @param enable Whether to enable or disable the browsing history
+    */
+   EAPI void                         elm_web_history_enable_set(Evas_Object *obj, Eina_Bool enable);
+   /**
+    * Gets whether text-only zoom is set
+    *
+    * @param obj The web object
+    *
+    * @return EINA_TRUE if zoom is set to affect only text, EINA_FALSE
+    * otherwise
+    *
+    * @see elm_web_zoom_text_only_set()
+    */
+   EAPI Eina_Bool                    elm_web_zoom_text_only_get(const Evas_Object *obj);
+   /**
+    * Enables or disables zoom to affect only text
+    *
+    * If set, then the zoom level set to the page will only be applied on text,
+    * leaving other objects, such as images, at their original size.
+    *
+    * @param obj The web object
+    * @param setting EINA_TRUE to use text-only zoom, EINA_FALSE to have zoom
+    * affect the entire page
+    */
+   EAPI void                         elm_web_zoom_text_only_set(Evas_Object *obj, Eina_Bool setting);
+   /**
+    * Sets the default dialogs to use an Inwin instead of a normal window
+    *
+    * If set, then the default implementation for the JavaScript dialogs and
+    * file selector will be opened in an Inwin. Otherwise they will use a
+    * normal separated window.
+    *
+    * @param obj The web object
+    * @param value EINA_TRUE to use Inwin, EINA_FALSE to use a normal window
+    */
+   EAPI void                         elm_web_inwin_mode_set(Evas_Object *obj, Eina_Bool value);
+   /**
+    * Gets whether Inwin mode is set for the current object
+    *
+    * @param obj The web object
+    *
+    * @return EINA_TRUE if Inwin mode is set, EINA_FALSE otherwise
+    */
+   EAPI Eina_Bool                    elm_web_inwin_mode_get(const Evas_Object *obj);
+
+   EAPI void                         elm_web_window_features_ref(Elm_Web_Window_Features *wf);
+   EAPI void                         elm_web_window_features_unref(Elm_Web_Window_Features *wf);
+   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_visble, Eina_Bool *fullscreen);
+   EAPI void                         elm_web_window_features_int_property_get(const Elm_Web_Window_Features *wf, int *x, int *y, int *w, int *h);
+
+   /**
+    * @}
+    */
+
+   /**
     * @defgroup Hoversel Hoversel
     *
     * @image html img/widget/hoversel/preview-00.png
index 5a52be5..941ce64 100644 (file)
@@ -21,6 +21,7 @@ AM_CPPFLAGS = \
 @ELEMENTARY_EDBUS_CFLAGS@ \
 @ELEMENTARY_EFREET_CFLAGS@ \
 @ELEMENTARY_ETHUMB_CFLAGS@ \
+@ELEMENTARY_WEB_CFLAGS@ \
 @ELEMENTARY_EMAP_CFLAGS@ \
 @EVIL_CFLAGS@ \
 @EIO_CFLAGS@ \
@@ -112,6 +113,7 @@ elm_toolbar.c \
 elm_transit.c \
 elm_util.c \
 elm_video.c \
+elm_web.c \
 elm_widget.c \
 elm_win.c \
 els_box.c \
@@ -138,6 +140,7 @@ libelementary_la_LIBADD = \
 @ELEMENTARY_EDBUS_LIBS@ \
 @ELEMENTARY_EFREET_LIBS@ \
 @ELEMENTARY_ETHUMB_LIBS@ \
+@ELEMENTARY_WEB_LIBS@ \
 @ELEMENTARY_EMAP_LIBS@ \
 @EVIL_LIBS@ \
 @EIO_LIBS@ \
index db0ba7d..5f19d5d 100644 (file)
@@ -491,6 +491,7 @@ elm_quicklaunch_shutdown(void)
    _elm_unneed_efreet();
    _elm_unneed_e_dbus();
    _elm_unneed_ethumb();
+   _elm_unneed_web();
    ecore_file_shutdown();
 
 #ifdef HAVE_ELEMENTARY_EMAP
index 81ad807..6575ff0 100644 (file)
@@ -193,6 +193,7 @@ void                _elm_widget_top_win_focused_set(Evas_Object *obj, Eina_Bool
 Eina_Bool           _elm_widget_top_win_focused_get(const Evas_Object *obj);
 
 void                _elm_unneed_ethumb(void);
+void                _elm_unneed_web(void);
 
 void                _elm_rescale(void);
 void                _elm_widget_mirrored_reload(Evas_Object *obj);
diff --git a/src/lib/elm_web.c b/src/lib/elm_web.c
new file mode 100644 (file)
index 0000000..312d7ed
--- /dev/null
@@ -0,0 +1,1566 @@
+#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;
+   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(1.0, _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__, const char *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, const char *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 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
+_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_notify_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);
+     }
+}
+#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);
+
+   elm_widget_resize_object_set(obj, wd->ewk_view);
+
+   wd->tab_propagate = EINA_FALSE;
+   wd->inwin_mode = _elm_config->inwin_dialogs_enable;
+
+   _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 index)
+{
+   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, index);
+#else
+   (void)index;
+#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 Eina_Bool
+elm_web_zoom_text_only_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_zoom_text_only_get(wd->ewk_view);
+#else
+   return EINA_FALSE;
+#endif
+}
+
+EAPI void
+elm_web_zoom_text_only_set(Evas_Object *obj, Eina_Bool setting)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+#ifdef HAVE_ELEMENTARY_WEB
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   ewk_view_zoom_text_only_set(wd->ewk_view, setting);
+#else
+   (void)setting;
+#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!