efl/legacy/elementary/src/lib/elm_web.c

1945 lines
52 KiB
C

#include <Elementary.h>
#include "elm_priv.h"
// TODO:
// 1 - easy to use zoom like elm_photocam API
// 2 - review scrolling to match elm_scroller. Maybe in future use elm_scroller
#ifdef HAVE_ELEMENTARY_WEB
#include <EWebKit.h>
/* Similar to iPhone */
// TODO: switch between iPhone, iPad or Chrome/Safari based on some elm setting?
#define ELM_WEB_USER_AGENT "Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A543a Safari/419.3 " PACKAGE_NAME "/" PACKAGE_VERSION
static Ewk_View_Smart_Class _parent_sc = EWK_VIEW_SMART_CLASS_INIT_NULL;
typedef struct _View_Smart_Data View_Smart_Data;
struct _View_Smart_Data
{
Ewk_View_Smart_Data base;
struct
{
Evas_Event_Mouse_Down event;
Evas_Coord x, y;
unsigned int move_count;
Ecore_Timer *longpress_timer;
Ecore_Animator *pan_anim;
} mouse;
};
#endif
typedef struct _Widget_Data Widget_Data;
struct _Widget_Data
{
Evas_Object *self;
#ifdef HAVE_ELEMENTARY_WEB
Evas_Object *ewk_view;
struct
{
Elm_Web_Window_Open window_create;
void *window_create_data;
Elm_Web_Dialog_Alert alert;
void *alert_data;
Elm_Web_Dialog_Confirm confirm;
void *confirm_data;
Elm_Web_Dialog_Prompt prompt;
void *prompt_data;
Elm_Web_Dialog_File_Selector file_selector;
void *file_selector_data;
Elm_Web_Console_Message console_message;
void *console_message_data;
} hook;
Elm_Win_Keyboard_Mode input_method;
struct
{
Elm_Web_Zoom_Mode mode;
float current;
float min, max;
Eina_Bool no_anim;
Ecore_Timer *timer;
} zoom;
struct
{
struct
{
int x, y;
} start, end;
Ecore_Animator *animator;
} bring_in;
Eina_Bool tab_propagate : 1;
Eina_Bool inwin_mode : 1;
#else
Evas_Object *label;
#endif
};
enum Dialog_Type
{
DIALOG_ALERT,
DIALOG_CONFIRM,
DIALOG_PROMPT,
DIALOG_FILE_SELECTOR
};
typedef struct _Dialog_Data Dialog_Data;
struct _Dialog_Data
{
enum Dialog_Type type;
Evas_Object *dialog;
Evas_Object *box;
Evas_Object *bt_ok, *bt_cancel;
Evas_Object *entry;
Evas_Object *file_sel;
Eina_Bool *response;
char **entry_value;
Eina_List **selected_files;
};
struct _Elm_Web_Callback_Proxy_Context
{
const char *name;
Evas_Object *obj;
};
typedef struct _Elm_Web_Callback_Proxy_Context Elm_Web_Callback_Proxy_Context;
static const char *widtype = NULL;
static const Evas_Smart_Cb_Description _elm_web_callback_names[] = {
{ "download,request", "p" },
{ "editorclient,contents,changed", "" },
{ "editorclient,selection,changed", "" },
{ "frame,created", "p" },
{ "icon,received", "" },
{ "inputmethod,changed", "b" },
{ "js,windowobject,clear", "" },
{ "link,hover,in", "p" },
{ "link,hover,out", "" },
{ "load,document,finished", "p" },
{ "load,error", "p" },
{ "load,finished", "p" },
{ "load,newwindow,show", "" },
{ "load,progress", "d" },
{ "load,provisional", "" },
{ "load,started", "" },
{ "menubar,visible,get", "b" },
{ "menubar,visible,set", "b" },
{ "popup,created", "p" },
{ "popup,willdelete", "p" },
{ "ready", "" },
{ "scrollbars,visible,get", "b" },
{ "scrollbars,visible,set", "b" },
{ "statusbar,text,set", "s" },
{ "statusbar,visible,get", "b" },
{ "statusbar,visible,set", "b" },
{ "title,changed", "s" },
{ "toolbars,visible,get", "b" },
{ "toolbars,visible,set", "b" },
{ "tooltip,text,set", "s" },
{ "uri,changed", "s" },
{ "view,resized", "" },
{ "windows,close,request", ""},
{ "zoom,animated,end", "" },
{ NULL, NULL }
};
#ifdef HAVE_ELEMENTARY_WEB
static char *
_webkit_theme_find(const Eina_List *list)
{
const Eina_List *l;
const char *th;
EINA_LIST_FOREACH(list, l, th)
{
char *path = elm_theme_list_item_path_get(th, NULL);
if (!path) continue;
if (edje_file_group_exists(path, "webkit/base"))
return path;
free(path);
}
return NULL;
}
#endif
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;
char *view_theme = NULL;
themes = elm_theme_overlay_list_get(theme);
view_theme = _webkit_theme_find(themes);
if (view_theme) goto set;
themes = elm_theme_list_get(theme);
view_theme = _webkit_theme_find(themes);
if (view_theme) goto set;
themes = elm_theme_extension_list_get(theme);
view_theme = _webkit_theme_find(themes);
set:
if (view_theme)
{
ewk_view_theme_set(wd->ewk_view, view_theme);
free(view_theme);
}
else
ewk_view_theme_set(wd->ewk_view, WEBKIT_DATADIR"/themes/default.edj");
#else
(void)obj;
#endif
}
static void
_on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
{
#ifdef HAVE_ELEMENTARY_WEB
Widget_Data *wd = elm_widget_data_get(obj);
Evas_Object *top = elm_widget_top_get(obj);
if (!wd) return;
if (elm_object_focus_get(obj))
{
evas_object_focus_set(wd->ewk_view, EINA_TRUE);
if (top) elm_win_keyboard_mode_set(top, wd->input_method);
}
else
{
evas_object_focus_set(wd->ewk_view, EINA_FALSE);
if (top) elm_win_keyboard_mode_set(top, ELM_WIN_KEYBOARD_OFF);
}
#else
(void)obj;
#endif
}
static Eina_Bool
_event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
{
#ifdef HAVE_ELEMENTARY_WEB
Evas_Event_Key_Down *ev = event_info;
Widget_Data *wd = elm_widget_data_get(obj);
if (!wd) return EINA_FALSE;
if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
if (elm_widget_disabled_get(obj)) return EINA_FALSE;
if ((!strcmp(ev->keyname, "Tab")) && (!wd->tab_propagate))
{
ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
return EINA_TRUE;
}
else
return EINA_FALSE;
#else
return EINA_FALSE;
(void)obj;
(void)type;
(void)event_info;
#endif
}
#ifdef HAVE_ELEMENTARY_WEB
static Eina_Bool
_view_pan_animator(void *data)
{
View_Smart_Data *sd = data;
Evas_Coord x, y, dx, dy;
evas_pointer_canvas_xy_get(sd->base.base.evas, &x, &y);
dx = sd->mouse.x - x;
dy = sd->mouse.y - y;
if ((dx == 0) && (dy == 0))
goto end;
ewk_frame_scroll_add(sd->base.main_frame, dx, dy);
sd->mouse.x = x;
sd->mouse.y = y;
end:
return EINA_TRUE;
}
static void
_view_smart_add(Evas_Object *obj)
{
View_Smart_Data *sd;
sd = calloc(1, sizeof(View_Smart_Data));
evas_object_smart_data_set(obj, sd);
_parent_sc.sc.add(obj);
ewk_view_history_enable_set(obj, EINA_TRUE);
ewk_history_limit_set(ewk_view_history_get(obj), 100);
// TODO: auto toggle between smooth/nearest during bring-in animations
//ewk_view_zoom_weak_smooth_scale_set(obj, EINA_TRUE);
}
static void
_view_smart_del(Evas_Object *obj)
{
View_Smart_Data *sd;
sd = evas_object_smart_data_get(obj);
if (sd->mouse.pan_anim)
ecore_animator_del(sd->mouse.pan_anim);
_parent_sc.sc.del(obj);
}
static Eina_Bool
_view_longpress_timer(void *data)
{
View_Smart_Data *sd = data;
sd->mouse.move_count = 0;
sd->mouse.longpress_timer = NULL;
return ECORE_CALLBACK_CANCEL;
}
static Eina_Bool
_view_smart_mouse_down(Ewk_View_Smart_Data *esd, const Evas_Event_Mouse_Down *event)
{
// TODO: mimic elm_scroller and like
// TODO-minor: offer hook?
View_Smart_Data *sd = (View_Smart_Data *)esd;
if (event->button != 1)
return _parent_sc.mouse_down(esd, event);
sd->mouse.pan_anim = ecore_animator_add(_view_pan_animator, sd);
sd->mouse.longpress_timer = ecore_timer_add(_elm_config->longpress_timeout, _view_longpress_timer, sd);
sd->mouse.move_count = 1;
sd->mouse.x = event->canvas.x;
sd->mouse.y = event->canvas.y;
sd->mouse.event = *event;
return EINA_TRUE;
}
static Eina_Bool
_view_smart_mouse_up(Ewk_View_Smart_Data *esd, const Evas_Event_Mouse_Up *event)
{
// TODO: mimic elm_scroller and like
// TODO-minor: offer hook?
View_Smart_Data *sd = (View_Smart_Data *)esd;
if (sd->mouse.pan_anim)
{
ecore_animator_del(sd->mouse.pan_anim);
sd->mouse.pan_anim = NULL;
if (sd->mouse.longpress_timer)
_parent_sc.mouse_down(esd, &sd->mouse.event);
else
return EINA_TRUE;
}
if (sd->mouse.longpress_timer)
{
ecore_timer_del(sd->mouse.longpress_timer);
sd->mouse.longpress_timer = NULL;
}
sd->mouse.move_count = 0;
return _parent_sc.mouse_up(esd, event);
}
static Eina_Bool
_view_smart_mouse_move(Ewk_View_Smart_Data *esd, const Evas_Event_Mouse_Move *event)
{
// TODO: mimic elm_scroller and like
// TODO-minor: offer hook?
View_Smart_Data *sd = (View_Smart_Data *)esd;
sd->mouse.move_count++;
if (sd->mouse.longpress_timer &&
(((sd->mouse.x ^ sd->mouse.event.canvas.x) |
(sd->mouse.y ^ sd->mouse.event.canvas.y)) & (~0x07)))
{
ecore_timer_del(sd->mouse.longpress_timer);
sd->mouse.longpress_timer = NULL;
}
if (sd->mouse.pan_anim)
{
return EINA_FALSE;
}
return _parent_sc.mouse_move(esd, event);
}
static Evas_Object *
_view_smart_window_create(Ewk_View_Smart_Data *sd, Eina_Bool javascript, const Ewk_Window_Features *window_features)
{
Evas_Object *new;
Evas_Object *obj = evas_object_smart_parent_get(sd->self);
Widget_Data *wd = elm_widget_data_get(obj);
if (!wd->hook.window_create) return NULL;
new = wd->hook.window_create(wd->hook.window_create_data, obj, javascript,
(const Elm_Web_Window_Features *)window_features);
if (new) return elm_web_webkit_view_get(new);
return NULL;
}
static void
_view_smart_window_close(Ewk_View_Smart_Data *sd)
{
Evas_Object *obj = evas_object_smart_parent_get(sd->self);
evas_object_smart_callback_call(obj, "windows,close,request", NULL);
}
static void
_bt_close(void *data, Evas_Object *obj, void *event_info __UNUSED__)
{
Dialog_Data *d = data;
*d->response = (obj == d->bt_ok);
if ((d->type == DIALOG_PROMPT) && (*d->response == EINA_TRUE))
*d->entry_value = strdup(elm_entry_entry_get(d->entry));
evas_object_del(d->dialog);
}
static void
_file_sel_done(void *data, Evas_Object *obj __UNUSED__, void *event_info)
{
Dialog_Data *d = data;
if (event_info)
{
*d->selected_files = eina_list_append(NULL, strdup(event_info));
*d->response = EINA_TRUE;
}
else
*d->response = EINA_FALSE;
evas_object_del(d->dialog);
free(d);
}
static Dialog_Data *
_dialog_new(Evas_Object *parent)
{
Dialog_Data *d;
Widget_Data *wd = elm_widget_data_get(parent);
d = calloc(1, sizeof(Dialog_Data));
if (!d) return NULL;
if (!parent || wd->inwin_mode)
{
Evas_Object *bg;
d->dialog = elm_win_add(NULL, "elm-web-popup", ELM_WIN_DIALOG_BASIC);
evas_object_smart_callback_add(d->dialog, "delete,request",
_bt_close, d);
bg = elm_bg_add(d->dialog);
evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND,
EVAS_HINT_EXPAND);
elm_win_resize_object_add(d->dialog, bg);
evas_object_show(bg);
d->box = elm_box_add(d->dialog);
evas_object_size_hint_weight_set(d->box, EVAS_HINT_EXPAND,
EVAS_HINT_EXPAND);
elm_win_resize_object_add(d->dialog, d->box);
evas_object_show(d->box);
}
else
{
Evas_Object *win = elm_widget_top_get(parent);
d->dialog = elm_win_inwin_add(win);
elm_object_style_set(d->dialog, "minimal");
evas_object_size_hint_weight_set(d->dialog, EVAS_HINT_EXPAND,
EVAS_HINT_EXPAND);
d->box = elm_box_add(win);
evas_object_size_hint_weight_set(d->box, EVAS_HINT_EXPAND,
EVAS_HINT_EXPAND);
elm_win_inwin_content_set(d->dialog, d->box);
evas_object_show(d->box);
}
return d;
}
static Evas_Object *
_run_dialog(Evas_Object *parent, enum Dialog_Type type, const char *message, const char *default_entry_value, char **entry_value, Eina_Bool allows_multiple_files __UNUSED__, Eina_List *accept_types __UNUSED__, Eina_List **selected_filenames, Eina_Bool *response)
{
EINA_SAFETY_ON_TRUE_RETURN_VAL((type != DIALOG_PROMPT) && (!!default_entry_value), EINA_FALSE);
EINA_SAFETY_ON_TRUE_RETURN_VAL((type != DIALOG_PROMPT) && (!!entry_value), EINA_FALSE);
Dialog_Data *dialog_data = _dialog_new(evas_object_smart_parent_get(parent));
Evas_Object *lb;
if (type != DIALOG_FILE_SELECTOR)
{
lb = elm_label_add(dialog_data->box);
elm_object_text_set(lb, message);
elm_box_pack_end(dialog_data->box, lb);
evas_object_show(lb);
}
dialog_data->type = type;
dialog_data->response = response;
dialog_data->entry_value = entry_value;
dialog_data->selected_files = selected_filenames;
if (type == DIALOG_ALERT)
{
dialog_data->bt_ok = elm_button_add(dialog_data->box);
elm_object_text_set(dialog_data->bt_ok, "Close");
elm_box_pack_end(dialog_data->box, dialog_data->bt_ok);
evas_object_size_hint_align_set(dialog_data->bt_ok, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_smart_callback_add(dialog_data->bt_ok, "clicked", _bt_close, dialog_data);
evas_object_show(dialog_data->bt_ok);
}
else if (type == DIALOG_FILE_SELECTOR)
{
dialog_data->file_sel = elm_fileselector_add(dialog_data->dialog);
evas_object_size_hint_weight_set(dialog_data->file_sel,
EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(dialog_data->file_sel, EVAS_HINT_FILL,
EVAS_HINT_FILL);
elm_box_pack_end(dialog_data->box, dialog_data->file_sel);
evas_object_show(dialog_data->file_sel);
elm_fileselector_path_set(dialog_data->file_sel, ".");
elm_fileselector_is_save_set(dialog_data->file_sel, EINA_FALSE);
elm_fileselector_folder_only_set(dialog_data->file_sel, EINA_FALSE);
elm_fileselector_buttons_ok_cancel_set(dialog_data->file_sel,
EINA_TRUE);
elm_fileselector_expandable_set(dialog_data->file_sel, EINA_FALSE);
evas_object_smart_callback_add(dialog_data->file_sel, "done",
_file_sel_done, dialog_data);
// fileselector can't set it's minimum size correctly
evas_object_size_hint_min_set(dialog_data->file_sel, 300, 400);
}
else
{
if (type == DIALOG_PROMPT)
{
dialog_data->entry = elm_entry_add(dialog_data->box);
elm_entry_single_line_set(dialog_data->entry, EINA_TRUE);
elm_entry_scrollable_set(dialog_data->entry, EINA_TRUE);
elm_entry_entry_set(dialog_data->entry, default_entry_value);
evas_object_size_hint_align_set(dialog_data->entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_size_hint_weight_set(dialog_data->entry, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
elm_box_pack_end(dialog_data->box, dialog_data->entry);
evas_object_show(dialog_data->entry);
}
if (type == DIALOG_PROMPT || type == DIALOG_CONFIRM)
{
Evas_Object *bx_h = elm_box_add(dialog_data->box);
elm_box_horizontal_set(bx_h, 1);
elm_box_pack_end(dialog_data->box, bx_h);
evas_object_size_hint_weight_set(bx_h, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(bx_h, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_show(bx_h);
dialog_data->bt_cancel = elm_button_add(bx_h);
elm_object_text_set(dialog_data->bt_cancel, "Cancel");
elm_box_pack_end(bx_h, dialog_data->bt_cancel);
evas_object_size_hint_weight_set(dialog_data->bt_cancel, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(dialog_data->bt_cancel, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_smart_callback_add(dialog_data->bt_cancel, "clicked", _bt_close, dialog_data);
evas_object_show(dialog_data->bt_cancel);
dialog_data->bt_ok = elm_button_add(bx_h);
elm_object_text_set(dialog_data->bt_ok, "Ok");
elm_box_pack_end(bx_h, dialog_data->bt_ok);
evas_object_size_hint_weight_set(dialog_data->bt_ok, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(dialog_data->bt_ok, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_smart_callback_add(dialog_data->bt_ok, "clicked", _bt_close, dialog_data);
evas_object_show(dialog_data->bt_ok);
}
else
return EINA_FALSE;
}
evas_object_show(dialog_data->dialog);
return dialog_data->dialog;
}
static void
_dialog_del_cb(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
{
ecore_main_loop_quit();
}
static void
_exec_dialog(Evas_Object *dialog)
{
evas_object_event_callback_add(dialog, EVAS_CALLBACK_DEL, _dialog_del_cb,
NULL);
ecore_main_loop_begin();
}
/* called by ewk_view when javascript called alert()
*
*/
static void
_view_smart_run_javascript_alert(Ewk_View_Smart_Data *esd, Evas_Object *frame __UNUSED__, const char *message)
{
View_Smart_Data *sd = (View_Smart_Data *)esd;
Evas_Object *view = sd->base.self;
Evas_Object *obj = evas_object_smart_parent_get(view);
Evas_Object *diag = NULL;
Widget_Data *wd = elm_widget_data_get(obj);
Eina_Bool response = EINA_FALSE;
if (wd->hook.alert)
diag = wd->hook.alert(wd->hook.alert_data, obj, message);
else
diag = _run_dialog(view, DIALOG_ALERT, message, NULL, NULL, EINA_FALSE,
NULL, NULL, &response);
if (diag) _exec_dialog(diag);
}
/* called by ewk_view when javascript called confirm()
*
*/
static Eina_Bool
_view_smart_run_javascript_confirm(Ewk_View_Smart_Data *esd, Evas_Object *frame __UNUSED__, const char *message)
{
View_Smart_Data *sd = (View_Smart_Data *)esd;
Evas_Object *view = sd->base.self;
Evas_Object *obj = evas_object_smart_parent_get(view);
Evas_Object *diag = NULL;
Widget_Data *wd = elm_widget_data_get(obj);
Eina_Bool response = EINA_FALSE;
if (wd->hook.confirm)
diag = wd->hook.confirm(wd->hook.confirm_data, obj, message, &response);
else
diag = _run_dialog(view, DIALOG_CONFIRM, message, NULL, NULL, EINA_FALSE,
NULL, NULL, &response);
if (diag) _exec_dialog(diag);
return response;
}
/* called by ewk_view when javascript called confirm()
*
*/
static Eina_Bool
_view_smart_run_javascript_prompt(Ewk_View_Smart_Data *esd, Evas_Object *frame __UNUSED__, const char *message, const char *default_value, char **value)
{
View_Smart_Data *sd = (View_Smart_Data *)esd;
Evas_Object *view = sd->base.self;
Evas_Object *obj = evas_object_smart_parent_get(view);
Evas_Object *diag = NULL;
Widget_Data *wd = elm_widget_data_get(obj);
Eina_Bool response = EINA_FALSE;
if (wd->hook.prompt)
diag = wd->hook.prompt(wd->hook.prompt_data, obj, message, default_value,
value, &response);
else
diag = _run_dialog(view, DIALOG_PROMPT, message, default_value, value,
EINA_FALSE, NULL, NULL, &response);
if (diag) _exec_dialog(diag);
if (!response)
*value = NULL;
return EINA_TRUE;
}
static Eina_Bool
_view_smart_run_open_panel(Ewk_View_Smart_Data *esd, Evas_Object *frame __UNUSED__, Eina_Bool allows_multiple_files, Eina_List *accept_types, Eina_List **selected_filenames)
{
View_Smart_Data *sd = (View_Smart_Data *)esd;
Evas_Object *view = sd->base.self;
Evas_Object *obj = evas_object_smart_parent_get(view);
Evas_Object *diag = NULL;
Widget_Data *wd = elm_widget_data_get(obj);
Eina_Bool response = EINA_FALSE;
if (wd->hook.file_selector)
diag = wd->hook.file_selector(wd->hook.file_selector_data, obj,
allows_multiple_files, accept_types,
selected_filenames, &response);
else
diag = _run_dialog(view, DIALOG_FILE_SELECTOR, NULL, NULL, NULL,
allows_multiple_files, accept_types, selected_filenames,
&response);
if (diag) _exec_dialog(diag);
return response;
}
static void
_view_smart_add_console_message(Ewk_View_Smart_Data *esd, const char *message, unsigned int line_number, const char *source_id)
{
Evas_Object *obj = evas_object_smart_parent_get(esd->self);
Widget_Data *wd = elm_widget_data_get(obj);
if (wd->hook.console_message)
wd->hook.console_message(wd->hook.console_message_data, obj, message,
line_number, source_id);
}
static Eina_Bool
_view_smart_focus_can_cycle(Ewk_View_Smart_Data *sd, Ewk_Focus_Direction direction)
{
Evas_Object *obj = evas_object_smart_parent_get(sd->self);
Elm_Focus_Direction dir;
switch (direction)
{
case EWK_FOCUS_DIRECTION_FORWARD:
dir = ELM_FOCUS_NEXT;
break;
case EWK_FOCUS_DIRECTION_BACKWARD:
dir = ELM_FOCUS_PREVIOUS;
break;
default:
return EINA_FALSE;
}
elm_widget_focus_cycle(elm_widget_parent_get(obj), dir);
return EINA_TRUE;
}
/**
* Creates a new view object given the parent.
*
* @param parent object to use as parent.
*
* @return newly added Evas_Object or @c NULL on errors.
*/
Evas_Object *
_view_add(Evas_Object *parent)
{
static Evas_Smart *smart = NULL;
Evas *canvas = evas_object_evas_get(parent);
Evas_Object *view;
if (!smart)
{
static Ewk_View_Smart_Class api = EWK_VIEW_SMART_CLASS_INIT_NAME_VERSION("EWK_View_Elementary");
#ifndef TILED_BACKING_STORE
ewk_view_single_smart_set(&api);
#else
ewk_view_tiled_smart_set(&api);
#endif
_parent_sc = api;
// TODO: check every api method and provide overrides with hooks!
// TODO: hooks should provide extension points
// TODO: extension should have some kind of "default implementation",
// TODO: that can be replaced or controlled by hooks.
// TODO: ie: run_javascript_alert() should present an elm_win
// TODO: by default, but user could override it to show as inwin.
api.sc.add = _view_smart_add;
api.sc.del = _view_smart_del;
//api.sc.calculate = _view_smart_calculate;
api.mouse_down = _view_smart_mouse_down;
api.mouse_up = _view_smart_mouse_up;
api.mouse_move = _view_smart_mouse_move;
api.add_console_message = _view_smart_add_console_message;
api.window_create = _view_smart_window_create;
api.window_close = _view_smart_window_close;
api.run_javascript_alert = _view_smart_run_javascript_alert;
api.run_javascript_confirm = _view_smart_run_javascript_confirm;
api.run_javascript_prompt = _view_smart_run_javascript_prompt;
api.run_open_panel = _view_smart_run_open_panel;
api.focus_can_cycle = _view_smart_focus_can_cycle;
smart = evas_smart_class_new(&api.sc);
if (!smart)
{
CRITICAL("Could not create smart class");
return NULL;
}
}
view = evas_object_smart_add(canvas, smart);
if (!view)
{
ERR("Could not create smart object object for view");
return NULL;
}
return view;
}
static void
_ewk_view_inputmethod_change_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info)
{
Widget_Data *wd = data;
Evas_Object *top = elm_widget_top_get(wd->self);
if (!top) return;
if (event_info)
wd->input_method = ELM_WIN_KEYBOARD_ON;
else
wd->input_method = ELM_WIN_KEYBOARD_OFF;
elm_win_keyboard_mode_set(top, wd->input_method);
}
static void
_ewk_view_load_started_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__)
{
_ewk_view_inputmethod_change_cb(data, obj, (void *)(long)EINA_FALSE);
}
static void
_ewk_view_load_finished_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info)
{
Widget_Data *wd = data;
if (event_info)
return;
if (wd->zoom.mode != ELM_WEB_ZOOM_MODE_MANUAL)
{
float tz = wd->zoom.current;
wd->zoom.current = 0.0;
elm_web_zoom_set(wd->self, tz);
}
}
static void
_ewk_view_viewport_changed_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__)
{
Widget_Data *wd = data;
if (wd->zoom.mode != ELM_WEB_ZOOM_MODE_MANUAL)
{
ewk_view_zoom_set(obj, 1.0, 0, 0);
wd->zoom.no_anim = EINA_TRUE;
}
}
static Eina_Bool
_restore_zoom_mode_timer_cb(void *data)
{
Widget_Data *wd = data;
float tz = wd->zoom.current;
wd->zoom.timer = NULL;
wd->zoom.current = 0.0;
wd->zoom.no_anim = EINA_TRUE;
elm_web_zoom_set(wd->self, tz);
return EINA_FALSE;
}
static Eina_Bool
_reset_zoom_timer_cb(void *data)
{
Widget_Data *wd = data;
wd->zoom.timer = ecore_timer_add(0.0, _restore_zoom_mode_timer_cb, wd);
ewk_view_zoom_set(wd->ewk_view, 1.0, 0, 0);
return EINA_FALSE;
}
static void
_ewk_view_resized_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
{
Widget_Data *wd = data;
if (!(wd->zoom.mode != ELM_WEB_ZOOM_MODE_MANUAL))
return;
if (wd->zoom.timer)
ecore_timer_del(wd->zoom.timer);
wd->zoom.timer = ecore_timer_add(0.5, _reset_zoom_timer_cb, wd);
}
static void
_popup_del_job(void *data)
{
evas_object_del(data);
}
static void
_popup_will_delete(void *data, Evas_Object *obj, void *event_info __UNUSED__)
{
ecore_job_add(_popup_del_job, data);
evas_object_smart_callback_del(obj, "popup,willdelete", _popup_will_delete);
}
static void
_popup_item_selected(void *data, Evas_Object *obj, void *event_info __UNUSED__)
{
Evas_Object *view = data;
Elm_Object_Item *list_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 == list_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_allow_events_set(notify, EINA_FALSE);
elm_notify_orient_set(notify, ELM_NOTIFY_ORIENT_BOTTOM);
list = elm_list_add(obj);
elm_list_select_mode_set(data, ELM_OBJECT_SELECT_MODE_ALWAYS);
elm_list_bounce_set(list, EINA_FALSE, EINA_FALSE);
elm_list_mode_set(list, ELM_LIST_EXPAND);
evas_object_size_hint_weight_set(list, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(list, EVAS_HINT_FILL, EVAS_HINT_FILL);
elm_object_content_set(notify, list);
evas_object_show(list);
EINA_LIST_FOREACH(m->items, itr, it)
elm_list_item_append(list, it->text, NULL, NULL, _popup_item_selected,
obj);
elm_list_go(list);
evas_object_show(notify);
evas_object_smart_callback_add(obj, "popup,willdelete", _popup_will_delete,
notify);
evas_object_smart_callback_add(notify, "block,clicked", _popup_dismiss_cb,
obj);
}
static void
_view_smart_callback_proxy_free_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
{
free(data);
}
static void
_view_smart_callback_proxy_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info)
{
Elm_Web_Callback_Proxy_Context *ctxt = data;
evas_object_smart_callback_call(ctxt->obj, ctxt->name, event_info);
}
static void
_view_smart_callback_proxy(Evas_Object *view, Evas_Object *parent)
{
const Evas_Smart_Cb_Description **cls_descs, **inst_descs;
unsigned int cls_count, inst_count, total;
Elm_Web_Callback_Proxy_Context *ctxt;
evas_object_smart_callbacks_descriptions_get(view, &cls_descs, &cls_count,
&inst_descs, &inst_count);
total = cls_count + inst_count;
if (!total) return;
ctxt = malloc(sizeof(Elm_Web_Callback_Proxy_Context) * total);
if (!ctxt) return;
evas_object_event_callback_add(view, EVAS_CALLBACK_FREE,
_view_smart_callback_proxy_free_cb, ctxt);
for (; cls_count > 0; cls_count--, cls_descs++, ctxt++)
{
const Evas_Smart_Cb_Description *d = *cls_descs;
if (!strcmp(d->name, "popup,create"))
continue;
ctxt->name = d->name;
ctxt->obj = parent;
evas_object_smart_callback_add(view, d->name,
_view_smart_callback_proxy_cb, ctxt);
}
for (; inst_count > 0; inst_count--, inst_descs++, ctxt++)
{
const Evas_Smart_Cb_Description *d = *inst_descs;
ctxt->name = d->name;
ctxt->obj = parent;
evas_object_smart_callback_add(view, d->name,
_view_smart_callback_proxy_cb, ctxt);
}
}
static Eina_Bool
_bring_in_anim_cb(void *data, double pos)
{
Widget_Data *wd = data;
Evas_Object *frame = ewk_view_frame_main_get(wd->ewk_view);
int sx, sy, rx, ry;
sx = wd->bring_in.start.x;
sy = wd->bring_in.start.y;
rx = (wd->bring_in.end.x - sx) * pos;
ry = (wd->bring_in.end.y - sy) * pos;
ewk_frame_scroll_set(frame, rx + sx, ry + sy);
if (pos == 1.0)
{
wd->bring_in.end.x = wd->bring_in.end.y = wd->bring_in.start.x =
wd->bring_in.start.y = 0;
wd->bring_in.animator = NULL;
}
return EINA_TRUE;
}
#endif
#ifdef HAVE_ELEMENTARY_WEB
static int _elm_need_web = 0;
#endif
void
_elm_unneed_web(void)
{
#ifdef HAVE_ELEMENTARY_WEB
if (--_elm_need_web) return;
_elm_need_web = 0;
ewk_shutdown();
#endif
}
EAPI Eina_Bool
elm_need_web(void)
{
#ifdef HAVE_ELEMENTARY_WEB
if (_elm_need_web++) return EINA_TRUE;
ewk_init();
return EINA_TRUE;
#else
return EINA_FALSE;
#endif
}
EAPI Evas_Object *
elm_web_add(Evas_Object *parent)
{
Evas_Object *obj;
Widget_Data *wd;
Evas *e;
EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
wd = calloc(1, sizeof(Widget_Data));
e = evas_object_evas_get(parent);
if (!e)
return NULL;
obj = elm_widget_add(e);
wd->self = obj;
if (!widtype)
{
widtype = eina_stringshare_add("web");
elm_widget_type_register(&widtype);
}
elm_widget_type_set(obj, widtype);
elm_widget_sub_object_add(parent, obj);
elm_widget_theme_hook_set(obj, _theme_hook);
elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
elm_widget_event_hook_set(obj, _event_hook);
elm_widget_data_set(obj, wd);
elm_widget_can_focus_set(obj, EINA_TRUE);
#ifdef HAVE_ELEMENTARY_WEB
wd->ewk_view = _view_add(obj);
ewk_view_setting_user_agent_set(wd->ewk_view, ELM_WEB_USER_AGENT);
wd->input_method = ELM_WIN_KEYBOARD_OFF;
evas_object_smart_callback_add(wd->ewk_view, "inputmethod,changed",
_ewk_view_inputmethod_change_cb, wd);
evas_object_smart_callback_add(wd->ewk_view, "load,started",
_ewk_view_load_started_cb, wd);
evas_object_smart_callback_add(wd->ewk_view, "popup,create",
_ewk_view_popup_create_cb, wd);
evas_object_smart_callback_add(wd->ewk_view, "load,finished",
_ewk_view_load_finished_cb, wd);
evas_object_smart_callback_add(wd->ewk_view, "viewport,changed",
_ewk_view_viewport_changed_cb, wd);
evas_object_smart_callback_add(wd->ewk_view, "view,resized",
_ewk_view_resized_cb, wd);
elm_widget_resize_object_set(obj, wd->ewk_view);
wd->tab_propagate = EINA_FALSE;
wd->inwin_mode = _elm_config->inwin_dialogs_enable;
wd->zoom.min = ewk_view_zoom_range_min_get(wd->ewk_view);
wd->zoom.max = ewk_view_zoom_range_max_get(wd->ewk_view);
wd->zoom.current = 1.0;
_view_smart_callback_proxy(wd->ewk_view, wd->self);
evas_object_smart_callbacks_descriptions_set(obj, _elm_web_callback_names);
_theme_hook(obj);
#else
wd->label = elm_label_add(obj);
elm_object_text_set(wd->label, "WebKit not supported!");
evas_object_show(wd->label);
elm_widget_resize_object_set(obj, wd->label);
#endif
return obj;
}
EAPI Evas_Object *
elm_web_webkit_view_get(const Evas_Object *obj)
{
ELM_CHECK_WIDTYPE(obj, widtype) NULL;
#ifdef HAVE_ELEMENTARY_WEB
Widget_Data *wd = elm_widget_data_get(obj);
if (!wd) return NULL;
return wd->ewk_view;
#else
ERR("Elementary not compiled with EWebKit support.");
return NULL;
#endif
}
EAPI void
elm_web_window_create_hook_set(Evas_Object *obj, Elm_Web_Window_Open func, void *data)
{
ELM_CHECK_WIDTYPE(obj, widtype);
#ifdef HAVE_ELEMENTARY_WEB
Widget_Data *wd = elm_widget_data_get(obj);
if (!wd) return;
wd->hook.window_create = func;
wd->hook.window_create_data = data;
#else
(void)func;
(void)data;
#endif
}
EAPI void
elm_web_dialog_alert_hook_set(Evas_Object *obj, Elm_Web_Dialog_Alert func, void *data)
{
ELM_CHECK_WIDTYPE(obj, widtype);
#ifdef HAVE_ELEMENTARY_WEB
Widget_Data *wd = elm_widget_data_get(obj);
if (!wd) return;
wd->hook.alert = func;
wd->hook.alert_data = data;
#else
(void)func;
(void)data;
#endif
}
EAPI void
elm_web_dialog_confirm_hook_set(Evas_Object *obj, Elm_Web_Dialog_Confirm func, void *data)
{
ELM_CHECK_WIDTYPE(obj, widtype);
#ifdef HAVE_ELEMENTARY_WEB
Widget_Data *wd = elm_widget_data_get(obj);
if (!wd) return;
wd->hook.confirm = func;
wd->hook.confirm_data = data;
#else
(void)func;
(void)data;
#endif
}
EAPI void
elm_web_dialog_prompt_hook_set(Evas_Object *obj, Elm_Web_Dialog_Prompt func, void *data)
{
ELM_CHECK_WIDTYPE(obj, widtype);
#ifdef HAVE_ELEMENTARY_WEB
Widget_Data *wd = elm_widget_data_get(obj);
if (!wd) return;
wd->hook.prompt = func;
wd->hook.prompt_data = data;
#else
(void)func;
(void)data;
#endif
}
EAPI void
elm_web_dialog_file_selector_hook_set(Evas_Object *obj, Elm_Web_Dialog_File_Selector func, void *data)
{
ELM_CHECK_WIDTYPE(obj, widtype);
#ifdef HAVE_ELEMENTARY_WEB
Widget_Data *wd = elm_widget_data_get(obj);
if (!wd) return;
wd->hook.file_selector = func;
wd->hook.file_selector_data = data;
#else
(void)func;
(void)data;
#endif
}
EAPI void
elm_web_console_message_hook_set(Evas_Object *obj, Elm_Web_Console_Message func, void *data)
{
ELM_CHECK_WIDTYPE(obj, widtype);
#ifdef HAVE_ELEMENTARY_WEB
Widget_Data *wd = elm_widget_data_get(obj);
if (!wd) return;
wd->hook.console_message = func;
wd->hook.console_message_data = data;
#else
(void)func;
(void)data;
#endif
}
EAPI void
elm_web_useragent_set(Evas_Object *obj, const char *user_agent)
{
ELM_CHECK_WIDTYPE(obj, widtype);
#ifdef HAVE_ELEMENTARY_WEB
Widget_Data *wd = elm_widget_data_get(obj);
if (!wd) return;
ewk_view_setting_user_agent_set(wd->ewk_view, user_agent);
#else
(void)user_agent;
#endif
}
EAPI const char*
elm_web_useragent_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_setting_user_agent_get(wd->ewk_view);
#else
return NULL;
#endif
}
EAPI Eina_Bool
elm_web_tab_propagate_get(const Evas_Object *obj)
{
ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
#ifdef HAVE_ELEMENTARY_WEB
Widget_Data *wd = elm_widget_data_get(obj);
if (!wd) return EINA_FALSE;
return wd->tab_propagate;
#else
return EINA_FALSE;
#endif
}
EAPI void
elm_web_tab_propagate_set(Evas_Object *obj, Eina_Bool propagate)
{
ELM_CHECK_WIDTYPE(obj, widtype);
#ifdef HAVE_ELEMENTARY_WEB
Widget_Data *wd = elm_widget_data_get(obj);
if (!wd) return;
wd->tab_propagate = propagate;
#else
(void)propagate;
#endif
}
EAPI Eina_Bool
elm_web_uri_set(Evas_Object *obj, const char *uri)
{
ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
#ifdef HAVE_ELEMENTARY_WEB
Widget_Data *wd = elm_widget_data_get(obj);
if (!wd) return EINA_FALSE;
return ewk_view_uri_set(wd->ewk_view, uri);
#else
(void)uri;
return EINA_FALSE;
#endif
}
EAPI const char *
elm_web_uri_get(const Evas_Object *obj)
{
ELM_CHECK_WIDTYPE(obj, widtype) NULL;
#ifdef HAVE_ELEMENTARY_WEB
Widget_Data *wd = elm_widget_data_get(obj);
if (!wd) return NULL;
return ewk_view_uri_get(wd->ewk_view);
#else
return NULL;
#endif
}
EAPI const char *
elm_web_title_get(const Evas_Object *obj)
{
ELM_CHECK_WIDTYPE(obj, widtype) NULL;
#ifdef HAVE_ELEMENTARY_WEB
Widget_Data *wd = elm_widget_data_get(obj);
if (!wd) return NULL;
return ewk_view_title_get(wd->ewk_view);
#else
return NULL;
#endif
}
EAPI void
elm_web_bg_color_set(Evas_Object *obj, int r, int g, int b, int a)
{
ELM_CHECK_WIDTYPE(obj, widtype);
#ifdef HAVE_ELEMENTARY_WEB
Widget_Data *wd = elm_widget_data_get(obj);
if (!wd) return;
ewk_view_bg_color_set(wd->ewk_view, r, g, b, a);
#else
(void)r;
(void)g;
(void)b;
(void)a;
#endif
}
EAPI void
elm_web_bg_color_get(const Evas_Object *obj, int *r, int *g, int *b, int *a)
{
if (r) *r = 0;
if (g) *g = 0;
if (b) *b = 0;
if (a) *a = 0;
ELM_CHECK_WIDTYPE(obj, widtype);
#ifdef HAVE_ELEMENTARY_WEB
Widget_Data *wd = elm_widget_data_get(obj);
if (!wd) return;
return ewk_view_bg_color_get(wd->ewk_view, r, g, b, a);
#endif
}
EAPI char *
elm_web_selection_get(const Evas_Object *obj)
{
ELM_CHECK_WIDTYPE(obj, widtype) NULL;
#ifdef HAVE_ELEMENTARY_WEB
Widget_Data *wd = elm_widget_data_get(obj);
if (!wd) return NULL;
return ewk_view_selection_get(wd->ewk_view);
#else
return NULL;
#endif
}
EAPI void
elm_web_popup_selected_set(Evas_Object *obj, int idx)
{
ELM_CHECK_WIDTYPE(obj, widtype);
#ifdef HAVE_ELEMENTARY_WEB
Widget_Data *wd = elm_widget_data_get(obj);
ewk_view_popup_selected_set(wd->ewk_view, idx);
#else
(void)idx;
#endif
}
EAPI Eina_Bool
elm_web_popup_destroy(Evas_Object *obj)
{
ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
#ifdef HAVE_ELEMENTARY_WEB
Widget_Data *wd = elm_widget_data_get(obj);
return ewk_view_popup_destroy(wd->ewk_view);
#else
return EINA_FALSE;
#endif
}
EAPI Eina_Bool
elm_web_text_search(const Evas_Object *obj, const char *string, Eina_Bool case_sensitive, Eina_Bool forward, Eina_Bool wrap)
{
ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
#ifdef HAVE_ELEMENTARY_WEB
Widget_Data *wd = elm_widget_data_get(obj);
if (!wd) return EINA_FALSE;
return ewk_view_text_search
(wd->ewk_view, string, case_sensitive, forward, wrap);
#else
(void)string;
(void)case_sensitive;
(void)forward;
(void)wrap;
return EINA_FALSE;
#endif
}
EAPI unsigned int
elm_web_text_matches_mark(Evas_Object *obj, const char *string, Eina_Bool case_sensitive, Eina_Bool highlight, unsigned int limit)
{
ELM_CHECK_WIDTYPE(obj, widtype) 0;
#ifdef HAVE_ELEMENTARY_WEB
Widget_Data *wd = elm_widget_data_get(obj);
if (!wd) return 0;
return ewk_view_text_matches_mark
(wd->ewk_view, string, case_sensitive, highlight, limit);
#else
(void)string;
(void)case_sensitive;
(void)highlight;
(void)limit;
return 0;
#endif
}
EAPI Eina_Bool
elm_web_text_matches_unmark_all(Evas_Object *obj)
{
ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
#ifdef HAVE_ELEMENTARY_WEB
Widget_Data *wd = elm_widget_data_get(obj);
if (!wd) return EINA_FALSE;
return ewk_view_text_matches_unmark_all(wd->ewk_view);
#else
return EINA_FALSE;
#endif
}
EAPI Eina_Bool
elm_web_text_matches_highlight_set(Evas_Object *obj, Eina_Bool highlight)
{
ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
#ifdef HAVE_ELEMENTARY_WEB
Widget_Data *wd = elm_widget_data_get(obj);
if (!wd) return EINA_FALSE;
return ewk_view_text_matches_highlight_set(wd->ewk_view, highlight);
#else
(void)highlight;
return EINA_FALSE;
#endif
}
EAPI Eina_Bool
elm_web_text_matches_highlight_get(const Evas_Object *obj)
{
ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
#ifdef HAVE_ELEMENTARY_WEB
Widget_Data *wd = elm_widget_data_get(obj);
if (!wd) return EINA_FALSE;
return ewk_view_text_matches_highlight_get(wd->ewk_view);
#else
return EINA_FALSE;
#endif
}
EAPI double
elm_web_load_progress_get(const Evas_Object *obj)
{
ELM_CHECK_WIDTYPE(obj, widtype) -1.0;
#ifdef HAVE_ELEMENTARY_WEB
Widget_Data *wd = elm_widget_data_get(obj);
if (!wd) return -1.0;
return ewk_view_load_progress_get(wd->ewk_view);
#else
return EINA_FALSE;
#endif
}
EAPI Eina_Bool
elm_web_stop(Evas_Object *obj)
{
ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
#ifdef HAVE_ELEMENTARY_WEB
Widget_Data *wd = elm_widget_data_get(obj);
if (!wd) return EINA_FALSE;
return ewk_view_stop(wd->ewk_view);
#else
return EINA_FALSE;
#endif
}
EAPI Eina_Bool
elm_web_reload(Evas_Object *obj)
{
ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
#ifdef HAVE_ELEMENTARY_WEB
Widget_Data *wd = elm_widget_data_get(obj);
if (!wd) return EINA_FALSE;
return ewk_view_reload(wd->ewk_view);
#else
return EINA_FALSE;
#endif
}
EAPI Eina_Bool
elm_web_reload_full(Evas_Object *obj)
{
ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
#ifdef HAVE_ELEMENTARY_WEB
Widget_Data *wd = elm_widget_data_get(obj);
if (!wd) return EINA_FALSE;
return ewk_view_reload_full(wd->ewk_view);
#else
return EINA_FALSE;
#endif
}
EAPI Eina_Bool
elm_web_back(Evas_Object *obj)
{
ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
#ifdef HAVE_ELEMENTARY_WEB
Widget_Data *wd = elm_widget_data_get(obj);
if (!wd) return EINA_FALSE;
return ewk_view_back(wd->ewk_view);
#else
return EINA_FALSE;
#endif
}
EAPI Eina_Bool
elm_web_forward(Evas_Object *obj)
{
ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
#ifdef HAVE_ELEMENTARY_WEB
Widget_Data *wd = elm_widget_data_get(obj);
if (!wd) return EINA_FALSE;
return ewk_view_forward(wd->ewk_view);
#else
return EINA_FALSE;
#endif
}
EAPI Eina_Bool
elm_web_navigate(Evas_Object *obj, int steps)
{
ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
#ifdef HAVE_ELEMENTARY_WEB
Widget_Data *wd = elm_widget_data_get(obj);
if (!wd) return EINA_FALSE;
return ewk_view_navigate(wd->ewk_view, steps);
#else
return EINA_FALSE;
(void)steps;
#endif
}
EINA_DEPRECATED EAPI Eina_Bool
elm_web_back_possible(Evas_Object *obj)
{
return elm_web_back_possible_get(obj);
}
EAPI Eina_Bool
elm_web_back_possible_get(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_get(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_get(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_enabled_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_enabled_set(Evas_Object *obj, Eina_Bool enable)
{
ELM_CHECK_WIDTYPE(obj, widtype);
#ifdef HAVE_ELEMENTARY_WEB
Widget_Data *wd = elm_widget_data_get(obj);
if (!wd) return;
ewk_view_history_enable_set(wd->ewk_view, enable);
#else
(void)enable;
#endif
}
//EAPI Ewk_History *ewk_view_history_get(const Evas_Object *obj); // TODO:
EAPI void
elm_web_zoom_set(Evas_Object *obj, double zoom)
{
ELM_CHECK_WIDTYPE(obj, widtype);
#ifdef HAVE_ELEMENTARY_WEB
Widget_Data *wd = elm_widget_data_get(obj);
int vw, vh, cx, cy;
float z = 1.0;
evas_object_geometry_get(wd->ewk_view, NULL, NULL, &vw, &vh);
cx = vw / 2;
cy = vh / 2;
if (zoom > wd->zoom.max)
zoom = wd->zoom.max;
else if (zoom < wd->zoom.min)
zoom = wd->zoom.min;
if (zoom == wd->zoom.current) return;
wd->zoom.current = zoom;
if (wd->zoom.mode == ELM_WEB_ZOOM_MODE_MANUAL)
z = zoom;
else if (wd->zoom.mode == ELM_WEB_ZOOM_MODE_AUTO_FIT)
{
Evas_Object *frame = ewk_view_frame_main_get(wd->ewk_view);
Evas_Coord fw, fh, pw, ph;
if (!ewk_frame_contents_size_get(frame, &fw, &fh))
return;
z = ewk_frame_page_zoom_get(frame);
fw /= z;
fh /= z;
if ((fw > 0) && (fh > 0))
{
ph = (fh * vw) / fw;
if (ph > vh)
{
pw = (fw * vh) / fh;
ph = vh;
}
else
pw = vw;
if (fw > fh)
z = (float)pw / fw;
else
z = (float)ph / fh;
}
}
else if (wd->zoom.mode == ELM_WEB_ZOOM_MODE_AUTO_FILL)
{
Evas_Object *frame = ewk_view_frame_main_get(wd->ewk_view);
Evas_Coord fw, fh, pw, ph;
if (!ewk_frame_contents_size_get(frame, &fw, &fh))
return;
z = ewk_frame_page_zoom_get(frame);
fw /= z;
fh /= z;
if ((fw > 0) && (fh > 0))
{
ph = (fh * vw) / fw;
if (ph < vh)
{
pw = (fw * vh) / fh;
ph = vh;
}
else
pw = vw;
if (fw > fh)
z = (float)pw / fw;
else
z = (float)ph / fh;
}
}
if (wd->zoom.no_anim)
ewk_view_zoom_set(wd->ewk_view, z, cx, cy);
else
ewk_view_zoom_animated_set(wd->ewk_view, z, _elm_config->zoom_friction,
cx, cy);
wd->zoom.no_anim = EINA_FALSE;
#else
(void)zoom;
#endif
}
EAPI double
elm_web_zoom_get(const Evas_Object *obj)
{
ELM_CHECK_WIDTYPE(obj, widtype) -1.0;
#ifdef HAVE_ELEMENTARY_WEB
Widget_Data *wd = elm_widget_data_get(obj);
return wd->zoom.current;
#else
return -1.0;
#endif
}
EAPI void
elm_web_zoom_mode_set(Evas_Object *obj, Elm_Web_Zoom_Mode mode)
{
ELM_CHECK_WIDTYPE(obj, widtype);
#ifdef HAVE_ELEMENTARY_WEB
Widget_Data *wd = elm_widget_data_get(obj);
float tz;
if (mode >= ELM_WEB_ZOOM_MODE_LAST)
return;
if (mode == wd->zoom.mode)
return;
wd->zoom.mode = mode;
tz = wd->zoom.current;
wd->zoom.current = 0.0;
elm_web_zoom_set(obj, tz);
#else
(void)mode;
#endif
}
EAPI Elm_Web_Zoom_Mode
elm_web_zoom_mode_get(const Evas_Object *obj)
{
ELM_CHECK_WIDTYPE(obj, widtype) ELM_WEB_ZOOM_MODE_LAST;
#ifdef HAVE_ELEMENTARY_WEB
Widget_Data *wd = elm_widget_data_get(obj);
return wd->zoom.mode;
#else
return ELM_WEB_ZOOM_MODE_LAST;
#endif
}
EAPI void
elm_web_region_show(Evas_Object *obj, int x, int y, int w __UNUSED__, int h __UNUSED__)
{
ELM_CHECK_WIDTYPE(obj, widtype);
#ifdef HAVE_ELEMENTARY_WEB
Widget_Data *wd = elm_widget_data_get(obj);
Evas_Object *frame = ewk_view_frame_main_get(wd->ewk_view);
int fw, fh, zw, zh, rx, ry;
float zoom;
ewk_frame_contents_size_get(frame, &fw, &fh);
zoom = ewk_frame_page_zoom_get(frame);
zw = fw / zoom;
zh = fh / zoom;
rx = (x * fw) / zw;
ry = (y * fh) / zh;
if (wd->bring_in.animator)
{
ecore_animator_del(wd->bring_in.animator);
wd->bring_in.animator = NULL;
}
ewk_frame_scroll_set(frame, rx, ry);
#else
(void)x;
(void)y;
#endif
}
EAPI void
elm_web_region_bring_in(Evas_Object *obj, int x, int y, int w __UNUSED__, int h __UNUSED__)
{
ELM_CHECK_WIDTYPE(obj, widtype);
#ifdef HAVE_ELEMENTARY_WEB
Widget_Data *wd = elm_widget_data_get(obj);
Evas_Object *frame = ewk_view_frame_main_get(wd->ewk_view);
int fw, fh, zw, zh, rx, ry, sx, sy;
float zoom;
ewk_frame_contents_size_get(frame, &fw, &fh);
ewk_frame_scroll_pos_get(frame, &sx, &sy);
zoom = ewk_frame_page_zoom_get(frame);
zw = fw / zoom;
zh = fh / zoom;
rx = (x * fw) / zw;
ry = (y * fh) / zh;
if ((wd->bring_in.end.x == rx) && (wd->bring_in.end.y == ry))
return;
wd->bring_in.start.x = sx;
wd->bring_in.start.y = sy;
wd->bring_in.end.x = rx;
wd->bring_in.end.y = ry;
if (wd->bring_in.animator)
ecore_animator_del(wd->bring_in.animator);
wd->bring_in.animator = ecore_animator_timeline_add(
_elm_config->bring_in_scroll_friction, _bring_in_anim_cb, wd);
#else
(void)x;
(void)y;
#endif
}
EAPI void
elm_web_inwin_mode_set(Evas_Object *obj, Eina_Bool value)
{
ELM_CHECK_WIDTYPE(obj, widtype);
#ifdef HAVE_ELEMENTARY_WEB
Widget_Data *wd = elm_widget_data_get(obj);
wd->inwin_mode = value;
#else
(void)value;
#endif
}
EAPI Eina_Bool
elm_web_inwin_mode_get(const Evas_Object *obj)
{
ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
#ifdef HAVE_ELEMENTARY_WEB
Widget_Data *wd = elm_widget_data_get(obj);
return wd->inwin_mode;
#else
return EINA_FALSE;
#endif
}
EAPI void
elm_web_window_features_ref(Elm_Web_Window_Features *wf)
{
#ifdef HAVE_ELEMENTARY_WEB
ewk_window_features_ref((Ewk_Window_Features *)wf);
#else
(void)wf;
#endif
}
EAPI void
elm_web_window_features_unref(Elm_Web_Window_Features *wf)
{
#ifdef HAVE_ELEMENTARY_WEB
ewk_window_features_unref((Ewk_Window_Features *)wf);
#else
(void)wf;
#endif
}
EAPI Eina_Bool
elm_web_window_features_property_get(const Elm_Web_Window_Features *wf, Elm_Web_Window_Feature_Flag flag)
{
#ifdef HAVE_ELEMENTARY_WEB
Eina_Bool toolbar_visible, statusbar_visible;
Eina_Bool scrollbars_visible, menubar_visible;
Eina_Bool locationbar_visible, fullscreen;
ewk_window_features_bool_property_get((const Ewk_Window_Features *)wf,
&toolbar_visible, &statusbar_visible,
&scrollbars_visible, &menubar_visible,
&locationbar_visible, &fullscreen);
//TODO : Improve ewk API usage to get one value.
//
switch(flag)
{
case ELM_WEB_WINDOW_FEATURE_TOOLBAR:
return toolbar_visible;
break;
case ELM_WEB_WINDOW_FEATURE_STATUSBAR:
return statusbar_visible;
break;
case ELM_WEB_WINDOW_FEATURE_SCROLLBARS:
return scrollbars_visible;
break;
case ELM_WEB_WINDOW_FEATURE_MENUBAR:
return menubar_visible;
break;
case ELM_WEB_WINDOW_FEATURE_LOCATIONBAR:
return locationbar_visible;
break;
case ELM_WEB_WINDOW_FEATURE_FULLSCREEN:
return fullscreen;
break;
}
#else
if (!wf) return EINA_FALSE;
if (flag==ELM_WEB_WINDOW_FEATURE_TOOLBAR)
{
//TODO Handle unused variable warnings when
//ewk is not installed.
}
/* What to do with these ?
(void)wf;
(void)toolbar_visible;
(void)statusbar_visible;
(void)scrollbars_visible;
(void)menubar_visible;
(void)locationbar_visible;
(void)fullscreen;
*/
#endif
return EINA_FALSE;
}
EAPI void
elm_web_window_features_region_get(const Elm_Web_Window_Features *wf, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
{
#ifdef HAVE_ELEMENTARY_WEB
ewk_window_features_int_property_get((const Ewk_Window_Features *)wf,
x, y, w, h);
#else
if (!wf || !x || !y || !w || !h) return;
/* What to do with these ?
(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!