People from Earth: Welcome Elm_Web
[framework/uifw/elementary.git] / src / lib / elm_web.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 // TODO:
5 //  1 - easy to use zoom like elm_photocam API
6 //  2 - review scrolling to match elm_scroller. Maybe in future use elm_scroller
7
8 #ifdef HAVE_ELEMENTARY_WEB
9 #include <EWebKit.h>
10
11 /* Similar to iPhone */
12 // TODO: switch between iPhone, iPad or Chrome/Safari based on some elm setting?
13 #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
14
15 static Ewk_View_Smart_Class _parent_sc = EWK_VIEW_SMART_CLASS_INIT_NULL;
16
17 typedef struct _View_Smart_Data View_Smart_Data;
18 struct _View_Smart_Data
19 {
20    Ewk_View_Smart_Data base;
21    struct {
22       Evas_Event_Mouse_Down event;
23       Evas_Coord x, y;
24       unsigned int move_count;
25       Ecore_Timer *longpress_timer;
26       Ecore_Animator *pan_anim;
27    } mouse;
28 };
29 #endif
30
31 typedef struct _Widget_Data Widget_Data;
32 struct _Widget_Data
33 {
34    Evas_Object *self;
35 #ifdef HAVE_ELEMENTARY_WEB
36    Evas_Object *ewk_view;
37    struct {
38       Elm_Web_Window_Open window_create;
39       void *window_create_data;
40       Elm_Web_Dialog_Alert alert;
41       void *alert_data;
42       Elm_Web_Dialog_Confirm confirm;
43       void *confirm_data;
44       Elm_Web_Dialog_Prompt prompt;
45       void *prompt_data;
46       Elm_Web_Dialog_File_Selector file_selector;
47       void *file_selector_data;
48       Elm_Web_Console_Message console_message;
49       void *console_message_data;
50    } hook;
51    Elm_Win_Keyboard_Mode input_method;
52    Eina_Bool tab_propagate : 1;
53    Eina_Bool inwin_mode : 1;
54 #else
55    Evas_Object *label;
56 #endif
57 };
58
59 enum Dialog_Type
60 {
61    DIALOG_ALERT,
62    DIALOG_CONFIRM,
63    DIALOG_PROMPT,
64    DIALOG_FILE_SELECTOR
65 };
66
67 typedef struct _Dialog_Data Dialog_Data;
68 struct _Dialog_Data
69 {
70    enum Dialog_Type type;
71    Evas_Object *dialog;
72    Evas_Object *box;
73    Evas_Object *bt_ok, *bt_cancel;
74    Evas_Object *entry;
75    Evas_Object *file_sel;
76
77    Eina_Bool   *response;
78    char       **entry_value;
79    Eina_List  **selected_files;
80 };
81
82 struct _Elm_Web_Callback_Proxy_Context
83 {
84    const char *name;
85    Evas_Object *obj;
86 };
87 typedef struct _Elm_Web_Callback_Proxy_Context Elm_Web_Callback_Proxy_Context;
88
89 static const char *widtype = NULL;
90 static const Evas_Smart_Cb_Description _elm_web_callback_names[] = {
91    { "download,request", "p" },
92    { "editorclient,contents,changed", "" },
93    { "editorclient,selection,changed", "" },
94    { "frame,created", "p" },
95    { "icon,received", "" },
96    { "inputmethod,changed", "b" },
97    { "js,windowobject,clear", "" },
98    { "link,hover,in", "p" },
99    { "link,hover,out", "" },
100    { "load,document,finished", "p" },
101    { "load,error", "p" },
102    { "load,finished", "p" },
103    { "load,newwindow,show", "" },
104    { "load,progress", "d" },
105    { "load,provisional", "" },
106    { "load,started", "" },
107    { "menubar,visible,get", "b" },
108    { "menubar,visible,set", "b" },
109    { "popup,created", "p" },
110    { "popup,willdelete", "p" },
111    { "ready", "" },
112    { "scrollbars,visible,get", "b" },
113    { "scrollbars,visible,set", "b" },
114    { "statusbar,text,set", "s" },
115    { "statusbar,visible,get", "b" },
116    { "statusbar,visible,set", "b" },
117    { "title,changed", "s" },
118    { "toolbars,visible,get", "b" },
119    { "toolbars,visible,set", "b" },
120    { "tooltip,text,set", "s" },
121    { "uri,changed", "s" },
122    { "view,resized", "" },
123    { "windows,close,request", ""},
124    { "zoom,animated,end", "" },
125    { NULL, NULL }
126 };
127
128 static void
129 _theme_hook(Evas_Object *obj)
130 {
131 #ifdef HAVE_ELEMENTARY_WEB
132    Elm_Theme *theme = elm_object_theme_get(obj);
133    Widget_Data *wd = elm_widget_data_get(obj);
134    const Eina_List *themes, *l;
135    const char *th;
136    char *view_theme = NULL;
137
138    themes = elm_theme_list_get(theme);
139    EINA_LIST_FOREACH(themes, l, th)
140      {
141         char *path = elm_theme_list_item_path_get(th, NULL);
142         if (!path) continue;
143         if (edje_file_group_exists(path, "webkit/base"))
144           {
145              view_theme = path;
146              break;
147           }
148         free(path);
149      }
150
151    if (view_theme)
152      {
153         ewk_view_theme_set(wd->ewk_view, view_theme);
154         free(view_theme);
155      }
156    else
157      ewk_view_theme_set(wd->ewk_view, WEBKIT_DATADIR"/themes/default.edj");
158 #else
159    (void)obj;
160 #endif
161 }
162
163 static void
164 _on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
165 {
166 #ifdef HAVE_ELEMENTARY_WEB
167    Widget_Data *wd = elm_widget_data_get(obj);
168    Evas_Object *top = elm_widget_top_get(obj);
169
170    if (!wd) return;
171
172    if (elm_object_focus_get(obj))
173      {
174         evas_object_focus_set(wd->ewk_view, EINA_TRUE);
175         if (top) elm_win_keyboard_mode_set(top, wd->input_method);
176      }
177    else
178      {
179         evas_object_focus_set(wd->ewk_view, EINA_FALSE);
180         if (top) elm_win_keyboard_mode_set(top, ELM_WIN_KEYBOARD_OFF);
181      }
182 #else
183    (void)obj;
184 #endif
185 }
186
187 static Eina_Bool
188 _event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
189 {
190 #ifdef HAVE_ELEMENTARY_WEB
191    Evas_Event_Key_Down *ev = event_info;
192    Widget_Data *wd = elm_widget_data_get(obj);
193
194    if (!wd) return EINA_FALSE;
195    if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
196    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
197    if (elm_widget_disabled_get(obj)) return EINA_FALSE;
198
199    if ((!strcmp(ev->keyname, "Tab")) && (!wd->tab_propagate))
200      {
201         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
202         return EINA_TRUE;
203      }
204    else
205      return EINA_FALSE;
206 #else
207    return EINA_FALSE;
208    (void)obj;
209    (void)type;
210    (void)event_info;
211 #endif
212 }
213
214 #ifdef HAVE_ELEMENTARY_WEB
215 static Eina_Bool
216 _view_pan_animator(void *data)
217 {
218    View_Smart_Data *sd = data;
219    Evas_Coord x, y, dx, dy;
220
221    evas_pointer_canvas_xy_get(sd->base.base.evas, &x, &y);
222
223    dx = sd->mouse.x - x;
224    dy = sd->mouse.y - y;
225
226    if ((dx == 0) && (dy == 0))
227      goto end;
228
229    ewk_frame_scroll_add(sd->base.main_frame, dx, dy);
230
231    sd->mouse.x = x;
232    sd->mouse.y = y;
233
234  end:
235    return EINA_TRUE;
236 }
237
238 static void
239 _view_smart_add(Evas_Object *obj)
240 {
241    View_Smart_Data *sd;
242
243    sd = calloc(1, sizeof(View_Smart_Data));
244    evas_object_smart_data_set(obj, sd);
245
246    _parent_sc.sc.add(obj);
247
248    ewk_view_history_enable_set(obj, EINA_TRUE);
249    ewk_history_limit_set(ewk_view_history_get(obj), 100);
250    // TODO: auto toggle between smooth/nearest during bring-in animations
251    //ewk_view_zoom_weak_smooth_scale_set(obj, EINA_TRUE);
252 }
253
254 static void
255 _view_smart_del(Evas_Object *obj)
256 {
257    View_Smart_Data *sd;
258
259    sd = evas_object_smart_data_get(obj);
260
261    if (sd->mouse.pan_anim)
262      ecore_animator_del(sd->mouse.pan_anim);
263
264    _parent_sc.sc.del(obj);
265 }
266
267 static Eina_Bool
268 _view_longpress_timer(void *data)
269 {
270    View_Smart_Data *sd = data;
271
272    sd->mouse.move_count = 0;
273    sd->mouse.longpress_timer = NULL;
274    return ECORE_CALLBACK_CANCEL;
275 }
276
277 static Eina_Bool
278 _view_smart_mouse_down(Ewk_View_Smart_Data *esd, const Evas_Event_Mouse_Down *event)
279 {
280    // TODO: mimic elm_scroller and like
281    // TODO-minor: offer hook?
282    View_Smart_Data *sd = (View_Smart_Data *)esd;
283
284    if (event->button != 1)
285      return _parent_sc.mouse_down(esd, event);
286
287    sd->mouse.pan_anim = ecore_animator_add(_view_pan_animator, sd);
288    sd->mouse.longpress_timer = ecore_timer_add(1.0, _view_longpress_timer, sd);
289    sd->mouse.move_count = 1;
290    sd->mouse.x = event->canvas.x;
291    sd->mouse.y = event->canvas.y;
292    sd->mouse.event = *event;
293
294    return EINA_TRUE;
295 }
296
297 static Eina_Bool
298 _view_smart_mouse_up(Ewk_View_Smart_Data *esd, const Evas_Event_Mouse_Up *event)
299 {
300    // TODO: mimic elm_scroller and like
301    // TODO-minor: offer hook?
302    View_Smart_Data *sd = (View_Smart_Data *)esd;
303
304    if (sd->mouse.pan_anim)
305      {
306         ecore_animator_del(sd->mouse.pan_anim);
307         sd->mouse.pan_anim = NULL;
308
309         if (sd->mouse.longpress_timer)
310           _parent_sc.mouse_down(esd, &sd->mouse.event);
311         else
312           return EINA_TRUE;
313      }
314
315    if (sd->mouse.longpress_timer)
316      {
317         ecore_timer_del(sd->mouse.longpress_timer);
318         sd->mouse.longpress_timer = NULL;
319      }
320
321    sd->mouse.move_count = 0;
322    return _parent_sc.mouse_up(esd, event);
323 }
324
325 static Eina_Bool
326 _view_smart_mouse_move(Ewk_View_Smart_Data *esd, const Evas_Event_Mouse_Move *event)
327 {
328    // TODO: mimic elm_scroller and like
329    // TODO-minor: offer hook?
330    View_Smart_Data *sd = (View_Smart_Data *)esd;
331    sd->mouse.move_count++;
332
333    if (sd->mouse.longpress_timer &&
334        (((sd->mouse.x ^ sd->mouse.event.canvas.x) |
335          (sd->mouse.y ^ sd->mouse.event.canvas.y)) & (~0x07)))
336      {
337         ecore_timer_del(sd->mouse.longpress_timer);
338         sd->mouse.longpress_timer = NULL;
339      }
340
341    if (sd->mouse.pan_anim)
342      {
343         return EINA_FALSE;
344      }
345
346    return _parent_sc.mouse_move(esd, event);
347 }
348
349 static Evas_Object *
350 _view_smart_window_create(Ewk_View_Smart_Data *sd, Eina_Bool javascript, const Ewk_Window_Features *window_features)
351 {
352    Evas_Object *new;
353    Evas_Object *obj = evas_object_smart_parent_get(sd->self);
354    Widget_Data *wd = elm_widget_data_get(obj);
355
356    if (!wd->hook.window_create) return NULL;
357    new = wd->hook.window_create(wd->hook.window_create_data, obj, javascript,
358                         (const Elm_Web_Window_Features *)window_features);
359    if (new) return elm_web_webkit_view_get(new);
360
361    return NULL;
362 }
363
364 static void
365 _view_smart_window_close(Ewk_View_Smart_Data *sd)
366 {
367    Evas_Object *obj = evas_object_smart_parent_get(sd->self);
368    evas_object_smart_callback_call(obj, "windows,close,request", NULL);
369 }
370
371 static void
372 _bt_close(void *data, Evas_Object *obj, void *event_info __UNUSED__)
373 {
374    Dialog_Data *d = data;
375
376    *d->response = (obj == d->bt_ok);
377    if ((d->type == DIALOG_PROMPT) && (*d->response == EINA_TRUE))
378      *d->entry_value = strdup(elm_entry_entry_get(d->entry));
379    evas_object_del(d->dialog);
380 }
381
382 static void
383 _file_sel_done(void *data, Evas_Object *obj __UNUSED__, void *event_info)
384 {
385    Dialog_Data *d = data;
386    if (event_info)
387      {
388         *d->selected_files = eina_list_append(NULL, strdup(event_info));
389         *d->response = EINA_TRUE;
390      }
391    else
392      *d->response = EINA_FALSE;
393    evas_object_del(d->dialog);
394    free(d);
395 }
396
397 static Dialog_Data *
398 _dialog_new(Evas_Object *parent)
399 {
400    Dialog_Data *d;
401    Widget_Data *wd = elm_widget_data_get(parent);
402
403    d = calloc(1, sizeof(Dialog_Data));
404    if (!d) return NULL;
405
406    if (!parent || wd->inwin_mode)
407      {
408         Evas_Object *bg;
409
410         d->dialog = elm_win_add(NULL, "elm-web-popup", ELM_WIN_DIALOG_BASIC);
411         evas_object_smart_callback_add(d->dialog, "delete,request",
412                                        _bt_close, d);
413
414         bg = elm_bg_add(d->dialog);
415         evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND,
416                                          EVAS_HINT_EXPAND);
417         elm_win_resize_object_add(d->dialog, bg);
418         evas_object_show(bg);
419
420         d->box = elm_box_add(d->dialog);
421         evas_object_size_hint_weight_set(d->box, EVAS_HINT_EXPAND,
422                                          EVAS_HINT_EXPAND);
423         elm_win_resize_object_add(d->dialog, d->box);
424         evas_object_show(d->box);
425      }
426    else
427      {
428         Evas_Object *win = elm_widget_top_get(parent);
429         d->dialog = elm_win_inwin_add(win);
430         elm_object_style_set(d->dialog, "minimal");
431         evas_object_size_hint_weight_set(d->dialog, EVAS_HINT_EXPAND,
432                                          EVAS_HINT_EXPAND);
433
434         d->box = elm_box_add(win);
435         evas_object_size_hint_weight_set(d->box, EVAS_HINT_EXPAND,
436                                          EVAS_HINT_EXPAND);
437         elm_win_inwin_content_set(d->dialog, d->box);
438         evas_object_show(d->box);
439      }
440
441    return d;
442 }
443
444 static Evas_Object *
445 _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)
446 {
447    EINA_SAFETY_ON_TRUE_RETURN_VAL((type != DIALOG_PROMPT) && (!!default_entry_value), EINA_FALSE);
448    EINA_SAFETY_ON_TRUE_RETURN_VAL((type != DIALOG_PROMPT) && (!!entry_value), EINA_FALSE);
449
450    Dialog_Data *dialog_data = _dialog_new(evas_object_smart_parent_get(parent));
451    Evas_Object *lb;
452
453    if (type != DIALOG_FILE_SELECTOR)
454      {
455         lb = elm_label_add(dialog_data->box);
456         elm_object_text_set(lb, message);
457         elm_box_pack_end(dialog_data->box, lb);
458         evas_object_show(lb);
459      }
460
461    dialog_data->type = type;
462    dialog_data->response = response;
463    dialog_data->entry_value = entry_value;
464    dialog_data->selected_files = selected_filenames;
465
466    if (type == DIALOG_ALERT)
467      {
468         dialog_data->bt_ok = elm_button_add(dialog_data->box);
469         elm_object_text_set(dialog_data->bt_ok, "Close");
470         elm_box_pack_end(dialog_data->box, dialog_data->bt_ok);
471         evas_object_size_hint_align_set(dialog_data->bt_ok, EVAS_HINT_FILL, EVAS_HINT_FILL);
472         evas_object_smart_callback_add(dialog_data->bt_ok, "clicked", _bt_close, dialog_data);
473         evas_object_show(dialog_data->bt_ok);
474      }
475    else if (type == DIALOG_FILE_SELECTOR)
476      {
477         dialog_data->file_sel = elm_fileselector_add(dialog_data->dialog);
478         evas_object_size_hint_weight_set(dialog_data->file_sel,
479                                          EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
480         evas_object_size_hint_align_set(dialog_data->file_sel, EVAS_HINT_FILL,
481                                         EVAS_HINT_FILL);
482         elm_box_pack_end(dialog_data->box, dialog_data->file_sel);
483         evas_object_show(dialog_data->file_sel);
484
485         elm_fileselector_path_set(dialog_data->file_sel, ".");
486         elm_fileselector_is_save_set(dialog_data->file_sel, EINA_FALSE);
487         elm_fileselector_folder_only_set(dialog_data->file_sel, EINA_FALSE);
488         elm_fileselector_buttons_ok_cancel_set(dialog_data->file_sel,
489                                                EINA_TRUE);
490         elm_fileselector_expandable_set(dialog_data->file_sel, EINA_FALSE);
491         evas_object_smart_callback_add(dialog_data->file_sel, "done",
492                                        _file_sel_done, dialog_data);
493         // fileselector can't set it's minimum size correctly
494         evas_object_size_hint_min_set(dialog_data->file_sel, 300, 400);
495      }
496    else
497      {
498         if (type == DIALOG_PROMPT)
499           {
500              dialog_data->entry = elm_entry_add(dialog_data->box);
501              elm_entry_single_line_set(dialog_data->entry, EINA_TRUE);
502              elm_entry_scrollable_set(dialog_data->entry, EINA_TRUE);
503              elm_entry_entry_set(dialog_data->entry, default_entry_value);
504              evas_object_size_hint_align_set(dialog_data->entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
505              evas_object_size_hint_weight_set(dialog_data->entry, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
506              elm_box_pack_end(dialog_data->box, dialog_data->entry);
507              evas_object_show(dialog_data->entry);
508           }
509
510         if (type == DIALOG_PROMPT || type == DIALOG_CONFIRM)
511           {
512              Evas_Object *bx_h = elm_box_add(dialog_data->box);
513              elm_box_horizontal_set(bx_h, 1);
514              elm_box_pack_end(dialog_data->box, bx_h);
515              evas_object_size_hint_weight_set(bx_h, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
516              evas_object_size_hint_align_set(bx_h, EVAS_HINT_FILL, EVAS_HINT_FILL);
517              evas_object_show(bx_h);
518
519              dialog_data->bt_cancel = elm_button_add(bx_h);
520              elm_object_text_set(dialog_data->bt_cancel, "Cancel");
521              elm_box_pack_end(bx_h, dialog_data->bt_cancel);
522              evas_object_size_hint_weight_set(dialog_data->bt_cancel, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
523              evas_object_size_hint_align_set(dialog_data->bt_cancel, EVAS_HINT_FILL, EVAS_HINT_FILL);
524              evas_object_smart_callback_add(dialog_data->bt_cancel, "clicked", _bt_close, dialog_data);
525              evas_object_show(dialog_data->bt_cancel);
526
527              dialog_data->bt_ok = elm_button_add(bx_h);
528              elm_object_text_set(dialog_data->bt_ok, "Ok");
529              elm_box_pack_end(bx_h, dialog_data->bt_ok);
530              evas_object_size_hint_weight_set(dialog_data->bt_ok, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
531              evas_object_size_hint_align_set(dialog_data->bt_ok, EVAS_HINT_FILL, EVAS_HINT_FILL);
532              evas_object_smart_callback_add(dialog_data->bt_ok, "clicked", _bt_close, dialog_data);
533              evas_object_show(dialog_data->bt_ok);
534           }
535         else
536            return EINA_FALSE;
537      }
538
539    evas_object_show(dialog_data->dialog);
540
541    return dialog_data->dialog;
542 }
543
544 static void
545 _dialog_del_cb(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
546 {
547    ecore_main_loop_quit();
548 }
549
550 static void
551 _exec_dialog(Evas_Object *dialog)
552 {
553    evas_object_event_callback_add(dialog, EVAS_CALLBACK_DEL, _dialog_del_cb,
554                                   NULL);
555    ecore_main_loop_begin();
556 }
557
558 /* called by ewk_view when javascript called alert()
559  *
560  */
561 static void
562 _view_smart_run_javascript_alert(Ewk_View_Smart_Data *esd, Evas_Object *frame __UNUSED__, const char *message)
563 {
564    View_Smart_Data *sd = (View_Smart_Data *)esd;
565    Evas_Object *view = sd->base.self;
566    Evas_Object *obj = evas_object_smart_parent_get(view);
567    Evas_Object *diag = NULL;
568    Widget_Data *wd = elm_widget_data_get(obj);
569    Eina_Bool response = EINA_FALSE;
570
571    if (wd->hook.alert)
572      diag = wd->hook.alert(wd->hook.alert_data, obj, message);
573    else
574      diag = _run_dialog(view, DIALOG_ALERT, message, NULL, NULL, EINA_FALSE,
575                         NULL, NULL, &response);
576    if (diag) _exec_dialog(diag);
577 }
578
579 /* called by ewk_view when javascript called confirm()
580  *
581  */
582 static Eina_Bool
583 _view_smart_run_javascript_confirm(Ewk_View_Smart_Data *esd, Evas_Object *frame __UNUSED__, const char *message)
584 {
585    View_Smart_Data *sd = (View_Smart_Data *)esd;
586    Evas_Object *view = sd->base.self;
587    Evas_Object *obj = evas_object_smart_parent_get(view);
588    Evas_Object *diag = NULL;
589    Widget_Data *wd = elm_widget_data_get(obj);
590    Eina_Bool response = EINA_FALSE;
591
592    if (wd->hook.confirm)
593      diag = wd->hook.confirm(wd->hook.confirm_data, obj, message, &response);
594    else
595     diag = _run_dialog(view, DIALOG_CONFIRM, message, NULL, NULL, EINA_FALSE,
596                        NULL, NULL, &response);
597    if (diag) _exec_dialog(diag);
598    return response;
599 }
600
601 /* called by ewk_view when javascript called confirm()
602  *
603  */
604 static Eina_Bool
605 _view_smart_run_javascript_prompt(Ewk_View_Smart_Data *esd, Evas_Object *frame __UNUSED__, const char *message, const char *default_value, char **value)
606 {
607    View_Smart_Data *sd = (View_Smart_Data *)esd;
608    Evas_Object *view = sd->base.self;
609    Evas_Object *obj = evas_object_smart_parent_get(view);
610    Evas_Object *diag = NULL;
611    Widget_Data *wd = elm_widget_data_get(obj);
612    Eina_Bool response = EINA_FALSE;
613
614    if (wd->hook.prompt)
615      diag = wd->hook.prompt(wd->hook.prompt_data, obj, message, default_value,
616                             value, &response);
617    else
618      diag = _run_dialog(view, DIALOG_PROMPT, message, default_value, value,
619                         EINA_FALSE, NULL, NULL, &response);
620    if (diag) _exec_dialog(diag);
621    if (!response)
622       *value = NULL;
623
624    return EINA_TRUE;
625 }
626
627 static Eina_Bool
628 _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)
629 {
630    View_Smart_Data *sd = (View_Smart_Data *)esd;
631    Evas_Object *view = sd->base.self;
632    Evas_Object *obj = evas_object_smart_parent_get(view);
633    Evas_Object *diag = NULL;
634    Widget_Data *wd = elm_widget_data_get(obj);
635    Eina_Bool response = EINA_FALSE;
636
637    if (wd->hook.file_selector)
638      diag = wd->hook.file_selector(wd->hook.file_selector_data, obj,
639                                    allows_multiple_files, accept_types,
640                                    selected_filenames, &response);
641    else
642      diag = _run_dialog(view, DIALOG_FILE_SELECTOR, NULL, NULL, NULL,
643                         allows_multiple_files, accept_types, selected_filenames,
644                         &response);
645    if (diag) _exec_dialog(diag);
646
647    return response;
648 }
649
650 static Eina_Bool
651 _view_smart_focus_can_cycle(Ewk_View_Smart_Data *sd, Ewk_Focus_Direction direction)
652 {
653    Evas_Object *obj = evas_object_smart_parent_get(sd->self);
654    Elm_Focus_Direction dir;
655
656    switch (direction)
657      {
658       case EWK_FOCUS_DIRECTION_FORWARD:
659          dir = ELM_FOCUS_NEXT;
660          break;
661       case EWK_FOCUS_DIRECTION_BACKWARD:
662          dir = ELM_FOCUS_PREVIOUS;
663          break;
664       default:
665          return EINA_FALSE;
666      }
667
668    elm_widget_focus_cycle(elm_widget_parent_get(obj), dir);
669
670    return EINA_TRUE;
671 }
672
673 /**
674  * Creates a new view object given the parent.
675  *
676  * @param parent object to use as parent.
677  *
678  * @return newly added Evas_Object or @c NULL on errors.
679  */
680 Evas_Object *
681 _view_add(Evas_Object *parent)
682 {
683    static Evas_Smart *smart = NULL;
684    Evas *canvas = evas_object_evas_get(parent);
685    Evas_Object *view;
686
687    if (!smart)
688      {
689         static Ewk_View_Smart_Class api = EWK_VIEW_SMART_CLASS_INIT_NAME_VERSION("EWK_View_Elementary");
690
691 #ifndef TILED_BACKING_STORE
692         ewk_view_single_smart_set(&api);
693 #else
694         ewk_view_tiled_smart_set(&api);
695 #endif
696
697         _parent_sc = api;
698
699         // TODO: check every api method and provide overrides with hooks!
700         // TODO: hooks should provide extension points
701         // TODO: extension should have some kind of "default implementation",
702         // TODO: that can be replaced or controlled by hooks.
703         // TODO: ie: run_javascript_alert() should present an elm_win
704         // TODO: by default, but user could override it to show as inwin.
705         api.sc.add = _view_smart_add;
706         api.sc.del = _view_smart_del;
707         //api.sc.calculate = _view_smart_calculate;
708         api.mouse_down = _view_smart_mouse_down;
709         api.mouse_up = _view_smart_mouse_up;
710         api.mouse_move = _view_smart_mouse_move;
711         //api.add_console_message = _view_smart_add_console_message;
712         api.window_create = _view_smart_window_create;
713         api.window_close = _view_smart_window_close;
714         api.run_javascript_alert = _view_smart_run_javascript_alert;
715         api.run_javascript_confirm = _view_smart_run_javascript_confirm;
716         api.run_javascript_prompt = _view_smart_run_javascript_prompt;
717         api.run_open_panel = _view_smart_run_open_panel;
718         api.focus_can_cycle = _view_smart_focus_can_cycle;
719
720         smart = evas_smart_class_new(&api.sc);
721         if (!smart)
722           {
723              CRITICAL("Could not create smart class");
724              return NULL;
725           }
726      }
727
728    view = evas_object_smart_add(canvas, smart);
729    if (!view)
730      {
731         ERR("Could not create smart object object for view");
732         return NULL;
733      }
734
735    return view;
736 }
737
738 static void
739 _ewk_view_inputmethod_change_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info)
740 {
741    Widget_Data *wd = data;
742    Evas_Object *top = elm_widget_top_get(wd->self);
743    if (!top) return;
744
745    if (event_info)
746      wd->input_method = ELM_WIN_KEYBOARD_ON;
747    else
748      wd->input_method = ELM_WIN_KEYBOARD_OFF;
749    elm_win_keyboard_mode_set(top, wd->input_method);
750 }
751
752 static void
753 _ewk_view_load_started_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__)
754 {
755    _ewk_view_inputmethod_change_cb(data, obj, (void *)(long)EINA_FALSE);
756 }
757
758 static void
759 _popup_del_job(void *data)
760 {
761    evas_object_del(data);
762 }
763
764 static void
765 _popup_will_delete(void *data, Evas_Object *obj, void *event_info __UNUSED__)
766 {
767    ecore_job_add(_popup_del_job, data);
768    evas_object_smart_callback_del(obj, "popup,willdelete", _popup_will_delete);
769 }
770
771 static void
772 _popup_item_selected(void *data, Evas_Object *obj, void *event_info __UNUSED__)
773 {
774    Evas_Object *view = data;
775    Elm_List_Item *it = elm_list_selected_item_get(obj);
776    const Eina_List *itr, *list = elm_list_items_get(obj);
777    void *d;
778    int i = 0;
779
780    EINA_LIST_FOREACH(list, itr, d)
781    {
782       if (d == it)
783          break;
784
785       i++;
786    }
787
788    ewk_view_popup_selected_set(view, i);
789    ewk_view_popup_destroy(view);
790 }
791
792 static void
793 _popup_dismiss_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
794 {
795    ewk_view_popup_destroy(data);
796 }
797
798 static void
799 _ewk_view_popup_create_cb(void *data, Evas_Object *obj, void *event_info)
800 {
801    Widget_Data *wd = data;
802    Ewk_Menu *m = event_info;
803    Elm_Web_Menu m2;
804    Ewk_Menu_Item *it;
805    Eina_List *itr;
806    Evas_Object *notify, *list;
807
808    m2.items = m->items;
809    m2.x = m->x;
810    m2.y = m->y;
811    m2.width = m->width;
812    m2.height = m->height;
813    m2.handled = EINA_FALSE;
814    evas_object_smart_callback_call(wd->self, "popup,create", &m2);
815    if (m2.handled)
816      return;
817
818    notify = elm_notify_add(obj);
819    elm_notify_repeat_events_set(notify, EINA_FALSE);
820    elm_notify_orient_set(notify, ELM_NOTIFY_ORIENT_BOTTOM);
821
822    list = elm_list_add(obj);
823    elm_list_always_select_mode_set(list, EINA_TRUE);
824    elm_list_bounce_set(list, EINA_FALSE, EINA_FALSE);
825    elm_list_mode_set(list, ELM_LIST_EXPAND);
826    evas_object_size_hint_weight_set(list, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
827    evas_object_size_hint_align_set(list, EVAS_HINT_FILL, EVAS_HINT_FILL);
828    elm_notify_content_set(notify, list);
829    evas_object_show(list);
830
831    EINA_LIST_FOREACH(m->items, itr, it)
832       elm_list_item_append(list, it->text, NULL, NULL, _popup_item_selected,
833                            obj);
834    elm_list_go(list);
835
836    evas_object_show(notify);
837
838    evas_object_smart_callback_add(obj, "popup,willdelete", _popup_will_delete,
839                                   notify);
840    evas_object_smart_callback_add(notify, "block,clicked", _popup_dismiss_cb,
841                                   obj);
842 }
843
844 static void
845 _view_smart_callback_proxy_free_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
846 {
847    free(data);
848 }
849
850 static void
851 _view_smart_callback_proxy_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info)
852 {
853    Elm_Web_Callback_Proxy_Context *ctxt = data;
854
855    evas_object_smart_callback_call(ctxt->obj, ctxt->name, event_info);
856 }
857
858 static void
859 _view_smart_callback_proxy(Evas_Object *view, Evas_Object *parent)
860 {
861    const Evas_Smart_Cb_Description **cls_descs, **inst_descs;
862    unsigned int cls_count, inst_count, total;
863    Elm_Web_Callback_Proxy_Context *ctxt;
864
865    evas_object_smart_callbacks_descriptions_get(view, &cls_descs, &cls_count,
866                                                 &inst_descs, &inst_count);
867    total = cls_count + inst_count;
868    if (!total) return;
869    ctxt = malloc(sizeof(Elm_Web_Callback_Proxy_Context) * total);
870    if (!ctxt) return;
871    evas_object_event_callback_add(view, EVAS_CALLBACK_FREE,
872                                   _view_smart_callback_proxy_free_cb, ctxt);
873
874    for (; cls_count > 0; cls_count--, cls_descs++, ctxt++)
875      {
876         const Evas_Smart_Cb_Description *d = *cls_descs;
877         if (!strcmp(d->name, "popup,create"))
878           continue;
879         ctxt->name = d->name;
880         ctxt->obj = parent;
881         evas_object_smart_callback_add(view, d->name,
882                                        _view_smart_callback_proxy_cb, ctxt);
883      }
884
885    for (; inst_count > 0; inst_count--, inst_descs++, ctxt++)
886      {
887         const Evas_Smart_Cb_Description *d = *inst_descs;
888         ctxt->name = d->name;
889         ctxt->obj = parent;
890         evas_object_smart_callback_add(view, d->name,
891                                        _view_smart_callback_proxy_cb, ctxt);
892      }
893 }
894 #endif
895
896 #ifdef HAVE_ELEMENTARY_WEB
897 static int _elm_need_web = 0;
898 #endif
899
900 void
901 _elm_unneed_web(void)
902 {
903 #ifdef HAVE_ELEMENTARY_WEB
904    if (--_elm_need_web) return;
905
906    _elm_need_web = 0;
907    ewk_shutdown();
908 #endif
909 }
910
911 EAPI Eina_Bool
912 elm_need_web(void)
913 {
914 #ifdef HAVE_ELEMENTARY_WEB
915    if (_elm_need_web++) return EINA_TRUE;
916    ewk_init();
917    return EINA_TRUE;
918 #else
919    return EINA_FALSE;
920 #endif
921 }
922
923 EAPI Evas_Object *
924 elm_web_add(Evas_Object *parent)
925 {
926    Evas_Object *obj;
927    Widget_Data *wd;
928    Evas *e;
929
930    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
931
932    wd = calloc(1, sizeof(Widget_Data));
933    e = evas_object_evas_get(parent);
934    if (!e)
935      return NULL;
936    obj = elm_widget_add(e);
937    wd->self = obj;
938
939    if (!widtype)
940      {
941         widtype = eina_stringshare_add("web");
942         elm_widget_type_register(&widtype);
943      }
944
945    elm_widget_type_set(obj, widtype);
946    elm_widget_sub_object_add(parent, obj);
947    elm_widget_theme_hook_set(obj, _theme_hook);
948    elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
949    elm_widget_event_hook_set(obj, _event_hook);
950    elm_widget_data_set(obj, wd);
951    elm_widget_can_focus_set(obj, EINA_TRUE);
952
953 #ifdef HAVE_ELEMENTARY_WEB
954    wd->ewk_view = _view_add(obj);
955    ewk_view_setting_user_agent_set(wd->ewk_view, ELM_WEB_USER_AGENT);
956
957    wd->input_method = ELM_WIN_KEYBOARD_OFF;
958    evas_object_smart_callback_add(wd->ewk_view, "inputmethod,changed",
959                                   _ewk_view_inputmethod_change_cb, wd);
960    evas_object_smart_callback_add(wd->ewk_view, "load,started",
961                                   _ewk_view_load_started_cb, wd);
962    evas_object_smart_callback_add(wd->ewk_view, "popup,create",
963                                   _ewk_view_popup_create_cb, wd);
964
965    elm_widget_resize_object_set(obj, wd->ewk_view);
966
967    wd->tab_propagate = EINA_FALSE;
968    wd->inwin_mode = _elm_config->inwin_dialogs_enable;
969
970    _view_smart_callback_proxy(wd->ewk_view, wd->self);
971    evas_object_smart_callbacks_descriptions_set(obj, _elm_web_callback_names);
972
973    _theme_hook(obj);
974
975 #else
976    wd->label = elm_label_add(obj);
977    elm_object_text_set(wd->label, "WebKit not supported!");
978    evas_object_show(wd->label);
979    elm_widget_resize_object_set(obj, wd->label);
980 #endif
981
982    return obj;
983 }
984
985 EAPI Evas_Object *
986 elm_web_webkit_view_get(const Evas_Object *obj)
987 {
988    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
989 #ifdef HAVE_ELEMENTARY_WEB
990    Widget_Data *wd = elm_widget_data_get(obj);
991    if (!wd) return NULL;
992    return wd->ewk_view;
993 #else
994    ERR("Elementary not compiled with EWebKit support.");
995    return NULL;
996 #endif
997 }
998
999 EAPI void
1000 elm_web_window_create_hook_set(Evas_Object *obj, Elm_Web_Window_Open func, void *data)
1001 {
1002    ELM_CHECK_WIDTYPE(obj, widtype);
1003 #ifdef HAVE_ELEMENTARY_WEB
1004    Widget_Data *wd = elm_widget_data_get(obj);
1005    if (!wd) return;
1006    wd->hook.window_create = func;
1007    wd->hook.window_create_data = data;
1008 #else
1009    (void)func;
1010    (void)data;
1011 #endif
1012 }
1013
1014 EAPI void
1015 elm_web_dialog_alert_hook_set(Evas_Object *obj, Elm_Web_Dialog_Alert func, void *data)
1016 {
1017    ELM_CHECK_WIDTYPE(obj, widtype);
1018 #ifdef HAVE_ELEMENTARY_WEB
1019    Widget_Data *wd = elm_widget_data_get(obj);
1020    if (!wd) return;
1021    wd->hook.alert = func;
1022    wd->hook.alert_data = data;
1023 #else
1024    (void)func;
1025    (void)data;
1026 #endif
1027 }
1028
1029 EAPI void
1030 elm_web_dialog_confirm_hook_set(Evas_Object *obj, Elm_Web_Dialog_Confirm func, void *data)
1031 {
1032    ELM_CHECK_WIDTYPE(obj, widtype);
1033 #ifdef HAVE_ELEMENTARY_WEB
1034    Widget_Data *wd = elm_widget_data_get(obj);
1035    if (!wd) return;
1036    wd->hook.confirm = func;
1037    wd->hook.confirm_data = data;
1038 #else
1039    (void)func;
1040    (void)data;
1041 #endif
1042 }
1043
1044 EAPI void
1045 elm_web_dialog_prompt_hook_set(Evas_Object *obj, Elm_Web_Dialog_Prompt func, void *data)
1046 {
1047    ELM_CHECK_WIDTYPE(obj, widtype);
1048 #ifdef HAVE_ELEMENTARY_WEB
1049    Widget_Data *wd = elm_widget_data_get(obj);
1050    if (!wd) return;
1051    wd->hook.prompt = func;
1052    wd->hook.prompt_data = data;
1053 #else
1054    (void)func;
1055    (void)data;
1056 #endif
1057 }
1058
1059 EAPI void
1060 elm_web_dialog_file_selector_hook_set(Evas_Object *obj, Elm_Web_Dialog_File_Selector func, void *data)
1061 {
1062    ELM_CHECK_WIDTYPE(obj, widtype);
1063 #ifdef HAVE_ELEMENTARY_WEB
1064    Widget_Data *wd = elm_widget_data_get(obj);
1065    if (!wd) return;
1066    wd->hook.file_selector = func;
1067    wd->hook.file_selector_data = data;
1068 #else
1069    (void)func;
1070    (void)data;
1071 #endif
1072 }
1073
1074 EAPI void
1075 elm_web_console_message_hook_set(Evas_Object *obj, Elm_Web_Console_Message func, void *data)
1076 {
1077    ELM_CHECK_WIDTYPE(obj, widtype);
1078 #ifdef HAVE_ELEMENTARY_WEB
1079    Widget_Data *wd = elm_widget_data_get(obj);
1080    if (!wd) return;
1081    wd->hook.console_message = func;
1082    wd->hook.console_message_data = data;
1083 #else
1084    (void)func;
1085    (void)data;
1086 #endif
1087 }
1088
1089 EAPI Eina_Bool
1090 elm_web_tab_propagate_get(const Evas_Object *obj)
1091 {
1092    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1093 #ifdef HAVE_ELEMENTARY_WEB
1094    Widget_Data *wd = elm_widget_data_get(obj);
1095    if (!wd) return EINA_FALSE;
1096    return wd->tab_propagate;
1097 #else
1098    return EINA_FALSE;
1099 #endif
1100 }
1101
1102 EAPI void
1103 elm_web_tab_propagate_set(Evas_Object *obj, Eina_Bool propagate)
1104 {
1105    ELM_CHECK_WIDTYPE(obj, widtype);
1106 #ifdef HAVE_ELEMENTARY_WEB
1107    Widget_Data *wd = elm_widget_data_get(obj);
1108    if (!wd) return;
1109    wd->tab_propagate = propagate;
1110 #else
1111    (void)propagate;
1112 #endif
1113 }
1114
1115 EAPI Eina_Bool
1116 elm_web_uri_set(Evas_Object *obj, const char *uri)
1117 {
1118    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1119 #ifdef HAVE_ELEMENTARY_WEB
1120    Widget_Data *wd = elm_widget_data_get(obj);
1121    if (!wd) return EINA_FALSE;
1122    return ewk_view_uri_set(wd->ewk_view, uri);
1123 #else
1124    (void)uri;
1125    return EINA_FALSE;
1126 #endif
1127 }
1128
1129 EAPI const char *
1130 elm_web_uri_get(const Evas_Object *obj)
1131 {
1132    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1133 #ifdef HAVE_ELEMENTARY_WEB
1134    Widget_Data *wd = elm_widget_data_get(obj);
1135    if (!wd) return NULL;
1136    return ewk_view_uri_get(wd->ewk_view);
1137 #else
1138    return NULL;
1139 #endif
1140 }
1141
1142 EAPI const char *
1143 elm_web_title_get(const Evas_Object *obj)
1144 {
1145    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1146 #ifdef HAVE_ELEMENTARY_WEB
1147    Widget_Data *wd = elm_widget_data_get(obj);
1148    if (!wd) return NULL;
1149    return ewk_view_title_get(wd->ewk_view);
1150 #else
1151    return NULL;
1152 #endif
1153 }
1154
1155 EAPI void
1156 elm_web_bg_color_set(Evas_Object *obj, int r, int g, int b, int a)
1157 {
1158    ELM_CHECK_WIDTYPE(obj, widtype);
1159 #ifdef HAVE_ELEMENTARY_WEB
1160    Widget_Data *wd = elm_widget_data_get(obj);
1161    if (!wd) return;
1162    ewk_view_bg_color_set(wd->ewk_view, r, g, b, a);
1163 #else
1164    (void)r;
1165    (void)g;
1166    (void)b;
1167    (void)a;
1168 #endif
1169 }
1170
1171 EAPI void
1172 elm_web_bg_color_get(const Evas_Object *obj, int *r, int *g, int *b, int *a)
1173 {
1174    if (r) *r = 0;
1175    if (g) *g = 0;
1176    if (b) *b = 0;
1177    if (a) *a = 0;
1178    ELM_CHECK_WIDTYPE(obj, widtype);
1179 #ifdef HAVE_ELEMENTARY_WEB
1180    Widget_Data *wd = elm_widget_data_get(obj);
1181    if (!wd) return;
1182    return ewk_view_bg_color_get(wd->ewk_view, r, g, b, a);
1183 #endif
1184 }
1185
1186 EAPI char *
1187 elm_web_selection_get(const Evas_Object *obj)
1188 {
1189    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1190 #ifdef HAVE_ELEMENTARY_WEB
1191    Widget_Data *wd = elm_widget_data_get(obj);
1192    if (!wd) return NULL;
1193    return ewk_view_selection_get(wd->ewk_view);
1194 #else
1195    return NULL;
1196 #endif
1197 }
1198
1199 EAPI void
1200 elm_web_popup_selected_set(Evas_Object *obj, int index)
1201 {
1202    ELM_CHECK_WIDTYPE(obj, widtype);
1203 #ifdef HAVE_ELEMENTARY_WEB
1204    Widget_Data *wd = elm_widget_data_get(obj);
1205    ewk_view_popup_selected_set(wd->ewk_view, index);
1206 #else
1207    (void)index;
1208 #endif
1209 }
1210
1211 EAPI Eina_Bool
1212 elm_web_popup_destroy(Evas_Object *obj)
1213 {
1214    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1215 #ifdef HAVE_ELEMENTARY_WEB
1216    Widget_Data *wd = elm_widget_data_get(obj);
1217    return ewk_view_popup_destroy(wd->ewk_view);
1218 #else
1219    return EINA_FALSE;
1220 #endif
1221 }
1222
1223 EAPI Eina_Bool
1224 elm_web_text_search(const Evas_Object *obj, const char *string, Eina_Bool case_sensitive, Eina_Bool forward, Eina_Bool wrap)
1225 {
1226    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1227 #ifdef HAVE_ELEMENTARY_WEB
1228    Widget_Data *wd = elm_widget_data_get(obj);
1229    if (!wd) return EINA_FALSE;
1230    return ewk_view_text_search
1231      (wd->ewk_view, string, case_sensitive, forward, wrap);
1232 #else
1233    (void)string;
1234    (void)case_sensitive;
1235    (void)forward;
1236    (void)wrap;
1237    return EINA_FALSE;
1238 #endif
1239 }
1240
1241 EAPI unsigned int
1242 elm_web_text_matches_mark(Evas_Object *obj, const char *string, Eina_Bool case_sensitive, Eina_Bool highlight, unsigned int limit)
1243 {
1244    ELM_CHECK_WIDTYPE(obj, widtype) 0;
1245 #ifdef HAVE_ELEMENTARY_WEB
1246    Widget_Data *wd = elm_widget_data_get(obj);
1247    if (!wd) return 0;
1248    return ewk_view_text_matches_mark
1249      (wd->ewk_view, string, case_sensitive, highlight, limit);
1250 #else
1251    (void)string;
1252    (void)case_sensitive;
1253    (void)highlight;
1254    (void)limit;
1255    return 0;
1256 #endif
1257 }
1258
1259 EAPI Eina_Bool
1260 elm_web_text_matches_unmark_all(Evas_Object *obj)
1261 {
1262    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1263 #ifdef HAVE_ELEMENTARY_WEB
1264    Widget_Data *wd = elm_widget_data_get(obj);
1265    if (!wd) return EINA_FALSE;
1266    return ewk_view_text_matches_unmark_all(wd->ewk_view);
1267 #else
1268    return EINA_FALSE;
1269 #endif
1270 }
1271
1272 EAPI Eina_Bool
1273 elm_web_text_matches_highlight_set(Evas_Object *obj, Eina_Bool highlight)
1274 {
1275    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1276 #ifdef HAVE_ELEMENTARY_WEB
1277    Widget_Data *wd = elm_widget_data_get(obj);
1278    if (!wd) return EINA_FALSE;
1279    return ewk_view_text_matches_highlight_set(wd->ewk_view, highlight);
1280 #else
1281    (void)highlight;
1282    return EINA_FALSE;
1283 #endif
1284 }
1285
1286 EAPI Eina_Bool
1287 elm_web_text_matches_highlight_get(const Evas_Object *obj)
1288 {
1289    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1290 #ifdef HAVE_ELEMENTARY_WEB
1291    Widget_Data *wd = elm_widget_data_get(obj);
1292    if (!wd) return EINA_FALSE;
1293    return ewk_view_text_matches_highlight_get(wd->ewk_view);
1294 #else
1295    return EINA_FALSE;
1296 #endif
1297 }
1298
1299 EAPI double
1300 elm_web_load_progress_get(const Evas_Object *obj)
1301 {
1302    ELM_CHECK_WIDTYPE(obj, widtype) -1.0;
1303 #ifdef HAVE_ELEMENTARY_WEB
1304    Widget_Data *wd = elm_widget_data_get(obj);
1305    if (!wd) return -1.0;
1306    return ewk_view_load_progress_get(wd->ewk_view);
1307 #else
1308    return EINA_FALSE;
1309 #endif
1310 }
1311
1312 EAPI Eina_Bool
1313 elm_web_stop(Evas_Object *obj)
1314 {
1315    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1316 #ifdef HAVE_ELEMENTARY_WEB
1317    Widget_Data *wd = elm_widget_data_get(obj);
1318    if (!wd) return EINA_FALSE;
1319    return ewk_view_stop(wd->ewk_view);
1320 #else
1321    return EINA_FALSE;
1322 #endif
1323 }
1324
1325 EAPI Eina_Bool
1326 elm_web_reload(Evas_Object *obj)
1327 {
1328    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1329 #ifdef HAVE_ELEMENTARY_WEB
1330    Widget_Data *wd = elm_widget_data_get(obj);
1331    if (!wd) return EINA_FALSE;
1332    return ewk_view_reload(wd->ewk_view);
1333 #else
1334    return EINA_FALSE;
1335 #endif
1336 }
1337
1338 EAPI Eina_Bool
1339 elm_web_reload_full(Evas_Object *obj)
1340 {
1341    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1342 #ifdef HAVE_ELEMENTARY_WEB
1343    Widget_Data *wd = elm_widget_data_get(obj);
1344    if (!wd) return EINA_FALSE;
1345    return ewk_view_reload_full(wd->ewk_view);
1346 #else
1347    return EINA_FALSE;
1348 #endif
1349 }
1350
1351
1352 EAPI Eina_Bool
1353 elm_web_back(Evas_Object *obj)
1354 {
1355    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1356 #ifdef HAVE_ELEMENTARY_WEB
1357    Widget_Data *wd = elm_widget_data_get(obj);
1358    if (!wd) return EINA_FALSE;
1359    return ewk_view_back(wd->ewk_view);
1360 #else
1361    return EINA_FALSE;
1362 #endif
1363 }
1364
1365 EAPI Eina_Bool
1366 elm_web_forward(Evas_Object *obj)
1367 {
1368    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1369 #ifdef HAVE_ELEMENTARY_WEB
1370    Widget_Data *wd = elm_widget_data_get(obj);
1371    if (!wd) return EINA_FALSE;
1372    return ewk_view_forward(wd->ewk_view);
1373 #else
1374    return EINA_FALSE;
1375 #endif
1376 }
1377
1378 EAPI Eina_Bool
1379 elm_web_navigate(Evas_Object *obj, int steps)
1380 {
1381    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1382 #ifdef HAVE_ELEMENTARY_WEB
1383    Widget_Data *wd = elm_widget_data_get(obj);
1384    if (!wd) return EINA_FALSE;
1385    return ewk_view_navigate(wd->ewk_view, steps);
1386 #else
1387    return EINA_FALSE;
1388    (void)steps;
1389 #endif
1390 }
1391
1392 EAPI Eina_Bool
1393 elm_web_back_possible(Evas_Object *obj)
1394 {
1395    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1396 #ifdef HAVE_ELEMENTARY_WEB
1397    Widget_Data *wd = elm_widget_data_get(obj);
1398    if (!wd) return EINA_FALSE;
1399    return ewk_view_back_possible(wd->ewk_view);
1400 #else
1401    return EINA_FALSE;
1402 #endif
1403 }
1404
1405 EAPI Eina_Bool
1406 elm_web_forward_possible(Evas_Object *obj)
1407 {
1408    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1409 #ifdef HAVE_ELEMENTARY_WEB
1410    Widget_Data *wd = elm_widget_data_get(obj);
1411    if (!wd) return EINA_FALSE;
1412    return ewk_view_forward_possible(wd->ewk_view);
1413 #else
1414    return EINA_FALSE;
1415 #endif
1416 }
1417
1418 EAPI Eina_Bool
1419 elm_web_navigate_possible(Evas_Object *obj, int steps)
1420 {
1421    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1422 #ifdef HAVE_ELEMENTARY_WEB
1423    Widget_Data *wd = elm_widget_data_get(obj);
1424    if (!wd) return EINA_FALSE;
1425    return ewk_view_navigate_possible(wd->ewk_view, steps);
1426 #else
1427    return EINA_FALSE;
1428    (void)steps;
1429 #endif
1430 }
1431
1432 EAPI Eina_Bool
1433 elm_web_history_enable_get(const Evas_Object *obj)
1434 {
1435    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1436 #ifdef HAVE_ELEMENTARY_WEB
1437    Widget_Data *wd = elm_widget_data_get(obj);
1438    if (!wd) return EINA_FALSE;
1439    return ewk_view_history_enable_get(wd->ewk_view);
1440 #else
1441    return EINA_FALSE;
1442 #endif
1443 }
1444
1445 EAPI void
1446 elm_web_history_enable_set(Evas_Object *obj, Eina_Bool enable)
1447 {
1448    ELM_CHECK_WIDTYPE(obj, widtype);
1449 #ifdef HAVE_ELEMENTARY_WEB
1450    Widget_Data *wd = elm_widget_data_get(obj);
1451    if (!wd) return;
1452    ewk_view_history_enable_set(wd->ewk_view, enable);
1453 #else
1454    (void)enable;
1455 #endif
1456 }
1457
1458 //EAPI Ewk_History *ewk_view_history_get(const Evas_Object *obj); // TODO:
1459
1460 EAPI Eina_Bool
1461 elm_web_zoom_text_only_get(const Evas_Object *obj)
1462 {
1463    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1464 #ifdef HAVE_ELEMENTARY_WEB
1465    Widget_Data *wd = elm_widget_data_get(obj);
1466    if (!wd) return EINA_FALSE;
1467    return ewk_view_zoom_text_only_get(wd->ewk_view);
1468 #else
1469    return EINA_FALSE;
1470 #endif
1471 }
1472
1473 EAPI void
1474 elm_web_zoom_text_only_set(Evas_Object *obj, Eina_Bool setting)
1475 {
1476    ELM_CHECK_WIDTYPE(obj, widtype);
1477 #ifdef HAVE_ELEMENTARY_WEB
1478    Widget_Data *wd = elm_widget_data_get(obj);
1479    if (!wd) return;
1480    ewk_view_zoom_text_only_set(wd->ewk_view, setting);
1481 #else
1482    (void)setting;
1483 #endif
1484 }
1485
1486 EAPI void
1487 elm_web_inwin_mode_set(Evas_Object *obj, Eina_Bool value)
1488 {
1489    ELM_CHECK_WIDTYPE(obj, widtype);
1490 #ifdef HAVE_ELEMENTARY_WEB
1491    Widget_Data *wd = elm_widget_data_get(obj);
1492
1493    wd->inwin_mode = value;
1494 #else
1495    (void)value;
1496 #endif
1497 }
1498
1499 EAPI Eina_Bool
1500 elm_web_inwin_mode_get(const Evas_Object *obj)
1501 {
1502    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1503 #ifdef HAVE_ELEMENTARY_WEB
1504    Widget_Data *wd = elm_widget_data_get(obj);
1505
1506    return wd->inwin_mode;
1507 #else
1508    return EINA_FALSE;
1509 #endif
1510 }
1511
1512 EAPI void
1513 elm_web_window_features_ref(Elm_Web_Window_Features *wf)
1514 {
1515 #ifdef HAVE_ELEMENTARY_WEB
1516    ewk_window_features_ref((Ewk_Window_Features *)wf);
1517 #else
1518    (void)wf;
1519 #endif
1520 }
1521
1522 EAPI void
1523 elm_web_window_features_unref(Elm_Web_Window_Features *wf)
1524 {
1525 #ifdef HAVE_ELEMENTARY_WEB
1526    ewk_window_features_unref((Ewk_Window_Features *)wf);
1527 #else
1528    (void)wf;
1529 #endif
1530 }
1531
1532 EAPI void
1533 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)
1534 {
1535 #ifdef HAVE_ELEMENTARY_WEB
1536    ewk_window_features_bool_property_get((const Ewk_Window_Features *)wf,
1537                                          toolbar_visible, statusbar_visible,
1538                                          scrollbars_visible, menubar_visible,
1539                                          locationbar_visible, fullscreen);
1540 #else
1541    (void)wf;
1542    (void)toolbar_visible;
1543    (void)statusbar_visible;
1544    (void)scrollbars_visible;
1545    (void)menubar_visible;
1546    (void)locationbar_visible;
1547    (void)fullscreen;
1548 #endif
1549 }
1550
1551 EAPI void
1552 elm_web_window_features_int_property_get(const Elm_Web_Window_Features *wf, int *x, int *y, int *w, int *h)
1553 {
1554 #ifdef HAVE_ELEMENTARY_WEB
1555    ewk_window_features_int_property_get((const Ewk_Window_Features *)wf,
1556                                         x, y, w, h);
1557 #else
1558    (void)wf;
1559    (void)x;
1560    (void)y;
1561    (void)w;
1562    (void)h;
1563 #endif
1564 }
1565
1566 // 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!