From 6011feea424c067dbe9f1176bfed6fc5b8920e33 Mon Sep 17 00:00:00 2001 From: sachiel Date: Thu, 29 Sep 2011 20:58:22 +0000 Subject: [PATCH] People from Earth: Welcome Elm_Web 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 --- configure.ac | 33 + doc/Makefile.am | 3 +- doc/index.doxy | 4 + doc/widgets/Makefile.am | 4 +- doc/widgets/widget_preview_web.c | 12 + src/bin/Makefile.am | 11 +- src/bin/test.c | 8 + src/bin/test_web.c | 370 +++++++++ src/lib/Elementary.h.in | 800 +++++++++++++++++++ src/lib/Makefile.am | 3 + src/lib/elm_main.c | 1 + src/lib/elm_priv.h | 1 + src/lib/elm_web.c | 1566 ++++++++++++++++++++++++++++++++++++++ 13 files changed, 2811 insertions(+), 5 deletions(-) create mode 100644 doc/widgets/widget_preview_web.c create mode 100644 src/bin/test_web.c create mode 100644 src/lib/elm_web.c diff --git a/configure.ac b/configure.ac index c06bdf5..7247235 100644 --- a/configure.ac +++ b/configure.ac @@ -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}" diff --git a/doc/Makefile.am b/doc/Makefile.am index f304a1f..e59ad9f 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -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 diff --git a/doc/index.doxy b/doc/index.doxy index caebcd7..0f73202 100644 --- a/doc/index.doxy +++ b/doc/index.doxy @@ -238,6 +238,10 @@ * @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 diff --git a/doc/widgets/Makefile.am b/doc/widgets/Makefile.am index 86343c8..33e02a0 100644 --- a/doc/widgets/Makefile.am +++ b/doc/widgets/Makefile.am @@ -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 index 0000000..1169074 --- /dev/null +++ b/doc/widgets/widget_preview_web.c @@ -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" diff --git a/src/bin/Makefile.am b/src/bin/Makefile.am index 43fa6c3..8833197 100644 --- a/src/bin/Makefile.am +++ b/src/bin/Makefile.am @@ -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 diff --git a/src/bin/test.c b/src/bin/test.c index 8bb1c42..3bf5f53 100644 --- a/src/bin/test.c +++ b/src/bin/test.c @@ -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 index 0000000..ebbf297 --- /dev/null +++ b/src/bin/test_web.c @@ -0,0 +1,370 @@ +#include +#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 diff --git a/src/lib/Elementary.h.in b/src/lib/Elementary.h.in index aa5cc0c..984e4a1 100644 --- a/src/lib/Elementary.h.in +++ b/src/lib/Elementary.h.in @@ -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 diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 5a52be5..941ce64 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -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@ \ diff --git a/src/lib/elm_main.c b/src/lib/elm_main.c index db0ba7d..5f19d5d 100644 --- a/src/lib/elm_main.c +++ b/src/lib/elm_main.c @@ -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 diff --git a/src/lib/elm_priv.h b/src/lib/elm_priv.h index 81ad807..6575ff0 100644 --- a/src/lib/elm_priv.h +++ b/src/lib/elm_priv.h @@ -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 index 0000000..312d7ed --- /dev/null +++ b/src/lib/elm_web.c @@ -0,0 +1,1566 @@ +#include +#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 + +/* 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! -- 2.7.4