1 #include <Elementary.h>
5 // 1 - easy to use zoom like elm_photocam API
6 // 2 - review scrolling to match elm_scroller. Maybe in future use elm_scroller
8 #ifdef HAVE_ELEMENTARY_WEB
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
15 static Ewk_View_Smart_Class _parent_sc = EWK_VIEW_SMART_CLASS_INIT_NULL;
17 typedef struct _View_Smart_Data View_Smart_Data;
18 struct _View_Smart_Data
20 Ewk_View_Smart_Data base;
22 Evas_Event_Mouse_Down event;
24 unsigned int move_count;
25 Ecore_Timer *longpress_timer;
26 Ecore_Animator *pan_anim;
31 typedef struct _Widget_Data Widget_Data;
35 #ifdef HAVE_ELEMENTARY_WEB
36 Evas_Object *ewk_view;
38 Elm_Web_Window_Open window_create;
39 void *window_create_data;
40 Elm_Web_Dialog_Alert alert;
42 Elm_Web_Dialog_Confirm confirm;
44 Elm_Web_Dialog_Prompt prompt;
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;
51 Elm_Win_Keyboard_Mode input_method;
52 Eina_Bool tab_propagate : 1;
53 Eina_Bool inwin_mode : 1;
67 typedef struct _Dialog_Data Dialog_Data;
70 enum Dialog_Type type;
73 Evas_Object *bt_ok, *bt_cancel;
75 Evas_Object *file_sel;
79 Eina_List **selected_files;
82 struct _Elm_Web_Callback_Proxy_Context
87 typedef struct _Elm_Web_Callback_Proxy_Context Elm_Web_Callback_Proxy_Context;
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" },
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", "" },
129 _theme_hook(Evas_Object *obj)
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;
136 char *view_theme = NULL;
138 themes = elm_theme_list_get(theme);
139 EINA_LIST_FOREACH(themes, l, th)
141 char *path = elm_theme_list_item_path_get(th, NULL);
143 if (edje_file_group_exists(path, "webkit/base"))
153 ewk_view_theme_set(wd->ewk_view, view_theme);
157 ewk_view_theme_set(wd->ewk_view, WEBKIT_DATADIR"/themes/default.edj");
164 _on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
166 #ifdef HAVE_ELEMENTARY_WEB
167 Widget_Data *wd = elm_widget_data_get(obj);
168 Evas_Object *top = elm_widget_top_get(obj);
172 if (elm_object_focus_get(obj))
174 evas_object_focus_set(wd->ewk_view, EINA_TRUE);
175 if (top) elm_win_keyboard_mode_set(top, wd->input_method);
179 evas_object_focus_set(wd->ewk_view, EINA_FALSE);
180 if (top) elm_win_keyboard_mode_set(top, ELM_WIN_KEYBOARD_OFF);
188 _event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
190 #ifdef HAVE_ELEMENTARY_WEB
191 Evas_Event_Key_Down *ev = event_info;
192 Widget_Data *wd = elm_widget_data_get(obj);
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;
199 if ((!strcmp(ev->keyname, "Tab")) && (!wd->tab_propagate))
201 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
214 #ifdef HAVE_ELEMENTARY_WEB
216 _view_pan_animator(void *data)
218 View_Smart_Data *sd = data;
219 Evas_Coord x, y, dx, dy;
221 evas_pointer_canvas_xy_get(sd->base.base.evas, &x, &y);
223 dx = sd->mouse.x - x;
224 dy = sd->mouse.y - y;
226 if ((dx == 0) && (dy == 0))
229 ewk_frame_scroll_add(sd->base.main_frame, dx, dy);
239 _view_smart_add(Evas_Object *obj)
243 sd = calloc(1, sizeof(View_Smart_Data));
244 evas_object_smart_data_set(obj, sd);
246 _parent_sc.sc.add(obj);
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);
255 _view_smart_del(Evas_Object *obj)
259 sd = evas_object_smart_data_get(obj);
261 if (sd->mouse.pan_anim)
262 ecore_animator_del(sd->mouse.pan_anim);
264 _parent_sc.sc.del(obj);
268 _view_longpress_timer(void *data)
270 View_Smart_Data *sd = data;
272 sd->mouse.move_count = 0;
273 sd->mouse.longpress_timer = NULL;
274 return ECORE_CALLBACK_CANCEL;
278 _view_smart_mouse_down(Ewk_View_Smart_Data *esd, const Evas_Event_Mouse_Down *event)
280 // TODO: mimic elm_scroller and like
281 // TODO-minor: offer hook?
282 View_Smart_Data *sd = (View_Smart_Data *)esd;
284 if (event->button != 1)
285 return _parent_sc.mouse_down(esd, event);
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;
298 _view_smart_mouse_up(Ewk_View_Smart_Data *esd, const Evas_Event_Mouse_Up *event)
300 // TODO: mimic elm_scroller and like
301 // TODO-minor: offer hook?
302 View_Smart_Data *sd = (View_Smart_Data *)esd;
304 if (sd->mouse.pan_anim)
306 ecore_animator_del(sd->mouse.pan_anim);
307 sd->mouse.pan_anim = NULL;
309 if (sd->mouse.longpress_timer)
310 _parent_sc.mouse_down(esd, &sd->mouse.event);
315 if (sd->mouse.longpress_timer)
317 ecore_timer_del(sd->mouse.longpress_timer);
318 sd->mouse.longpress_timer = NULL;
321 sd->mouse.move_count = 0;
322 return _parent_sc.mouse_up(esd, event);
326 _view_smart_mouse_move(Ewk_View_Smart_Data *esd, const Evas_Event_Mouse_Move *event)
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++;
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)))
337 ecore_timer_del(sd->mouse.longpress_timer);
338 sd->mouse.longpress_timer = NULL;
341 if (sd->mouse.pan_anim)
346 return _parent_sc.mouse_move(esd, event);
350 _view_smart_window_create(Ewk_View_Smart_Data *sd, Eina_Bool javascript, const Ewk_Window_Features *window_features)
353 Evas_Object *obj = evas_object_smart_parent_get(sd->self);
354 Widget_Data *wd = elm_widget_data_get(obj);
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);
365 _view_smart_window_close(Ewk_View_Smart_Data *sd)
367 Evas_Object *obj = evas_object_smart_parent_get(sd->self);
368 evas_object_smart_callback_call(obj, "windows,close,request", NULL);
372 _bt_close(void *data, Evas_Object *obj, void *event_info __UNUSED__)
374 Dialog_Data *d = data;
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);
383 _file_sel_done(void *data, Evas_Object *obj __UNUSED__, void *event_info)
385 Dialog_Data *d = data;
388 *d->selected_files = eina_list_append(NULL, strdup(event_info));
389 *d->response = EINA_TRUE;
392 *d->response = EINA_FALSE;
393 evas_object_del(d->dialog);
398 _dialog_new(Evas_Object *parent)
401 Widget_Data *wd = elm_widget_data_get(parent);
403 d = calloc(1, sizeof(Dialog_Data));
406 if (!parent || wd->inwin_mode)
410 d->dialog = elm_win_add(NULL, "elm-web-popup", ELM_WIN_DIALOG_BASIC);
411 evas_object_smart_callback_add(d->dialog, "delete,request",
414 bg = elm_bg_add(d->dialog);
415 evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND,
417 elm_win_resize_object_add(d->dialog, bg);
418 evas_object_show(bg);
420 d->box = elm_box_add(d->dialog);
421 evas_object_size_hint_weight_set(d->box, EVAS_HINT_EXPAND,
423 elm_win_resize_object_add(d->dialog, d->box);
424 evas_object_show(d->box);
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,
434 d->box = elm_box_add(win);
435 evas_object_size_hint_weight_set(d->box, EVAS_HINT_EXPAND,
437 elm_win_inwin_content_set(d->dialog, d->box);
438 evas_object_show(d->box);
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)
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);
450 Dialog_Data *dialog_data = _dialog_new(evas_object_smart_parent_get(parent));
453 if (type != DIALOG_FILE_SELECTOR)
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);
461 dialog_data->type = type;
462 dialog_data->response = response;
463 dialog_data->entry_value = entry_value;
464 dialog_data->selected_files = selected_filenames;
466 if (type == DIALOG_ALERT)
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);
475 else if (type == DIALOG_FILE_SELECTOR)
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,
482 elm_box_pack_end(dialog_data->box, dialog_data->file_sel);
483 evas_object_show(dialog_data->file_sel);
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,
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);
498 if (type == DIALOG_PROMPT)
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);
510 if (type == DIALOG_PROMPT || type == DIALOG_CONFIRM)
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);
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);
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);
539 evas_object_show(dialog_data->dialog);
541 return dialog_data->dialog;
545 _dialog_del_cb(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
547 ecore_main_loop_quit();
551 _exec_dialog(Evas_Object *dialog)
553 evas_object_event_callback_add(dialog, EVAS_CALLBACK_DEL, _dialog_del_cb,
555 ecore_main_loop_begin();
558 /* called by ewk_view when javascript called alert()
562 _view_smart_run_javascript_alert(Ewk_View_Smart_Data *esd, Evas_Object *frame __UNUSED__, const char *message)
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;
572 diag = wd->hook.alert(wd->hook.alert_data, obj, message);
574 diag = _run_dialog(view, DIALOG_ALERT, message, NULL, NULL, EINA_FALSE,
575 NULL, NULL, &response);
576 if (diag) _exec_dialog(diag);
579 /* called by ewk_view when javascript called confirm()
583 _view_smart_run_javascript_confirm(Ewk_View_Smart_Data *esd, Evas_Object *frame __UNUSED__, const char *message)
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;
592 if (wd->hook.confirm)
593 diag = wd->hook.confirm(wd->hook.confirm_data, obj, message, &response);
595 diag = _run_dialog(view, DIALOG_CONFIRM, message, NULL, NULL, EINA_FALSE,
596 NULL, NULL, &response);
597 if (diag) _exec_dialog(diag);
601 /* called by ewk_view when javascript called confirm()
605 _view_smart_run_javascript_prompt(Ewk_View_Smart_Data *esd, Evas_Object *frame __UNUSED__, const char *message, const char *default_value, char **value)
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;
615 diag = wd->hook.prompt(wd->hook.prompt_data, obj, message, default_value,
618 diag = _run_dialog(view, DIALOG_PROMPT, message, default_value, value,
619 EINA_FALSE, NULL, NULL, &response);
620 if (diag) _exec_dialog(diag);
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)
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;
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);
642 diag = _run_dialog(view, DIALOG_FILE_SELECTOR, NULL, NULL, NULL,
643 allows_multiple_files, accept_types, selected_filenames,
645 if (diag) _exec_dialog(diag);
651 _view_smart_focus_can_cycle(Ewk_View_Smart_Data *sd, Ewk_Focus_Direction direction)
653 Evas_Object *obj = evas_object_smart_parent_get(sd->self);
654 Elm_Focus_Direction dir;
658 case EWK_FOCUS_DIRECTION_FORWARD:
659 dir = ELM_FOCUS_NEXT;
661 case EWK_FOCUS_DIRECTION_BACKWARD:
662 dir = ELM_FOCUS_PREVIOUS;
668 elm_widget_focus_cycle(elm_widget_parent_get(obj), dir);
674 * Creates a new view object given the parent.
676 * @param parent object to use as parent.
678 * @return newly added Evas_Object or @c NULL on errors.
681 _view_add(Evas_Object *parent)
683 static Evas_Smart *smart = NULL;
684 Evas *canvas = evas_object_evas_get(parent);
689 static Ewk_View_Smart_Class api = EWK_VIEW_SMART_CLASS_INIT_NAME_VERSION("EWK_View_Elementary");
691 #ifndef TILED_BACKING_STORE
692 ewk_view_single_smart_set(&api);
694 ewk_view_tiled_smart_set(&api);
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;
720 smart = evas_smart_class_new(&api.sc);
723 CRITICAL("Could not create smart class");
728 view = evas_object_smart_add(canvas, smart);
731 ERR("Could not create smart object object for view");
739 _ewk_view_inputmethod_change_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info)
741 Widget_Data *wd = data;
742 Evas_Object *top = elm_widget_top_get(wd->self);
746 wd->input_method = ELM_WIN_KEYBOARD_ON;
748 wd->input_method = ELM_WIN_KEYBOARD_OFF;
749 elm_win_keyboard_mode_set(top, wd->input_method);
753 _ewk_view_load_started_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__)
755 _ewk_view_inputmethod_change_cb(data, obj, (void *)(long)EINA_FALSE);
759 _popup_del_job(void *data)
761 evas_object_del(data);
765 _popup_will_delete(void *data, Evas_Object *obj, void *event_info __UNUSED__)
767 ecore_job_add(_popup_del_job, data);
768 evas_object_smart_callback_del(obj, "popup,willdelete", _popup_will_delete);
772 _popup_item_selected(void *data, Evas_Object *obj, void *event_info __UNUSED__)
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);
780 EINA_LIST_FOREACH(list, itr, d)
788 ewk_view_popup_selected_set(view, i);
789 ewk_view_popup_destroy(view);
793 _popup_dismiss_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
795 ewk_view_popup_destroy(data);
799 _ewk_view_popup_create_cb(void *data, Evas_Object *obj, void *event_info)
801 Widget_Data *wd = data;
802 Ewk_Menu *m = event_info;
806 Evas_Object *notify, *list;
812 m2.height = m->height;
813 m2.handled = EINA_FALSE;
814 evas_object_smart_callback_call(wd->self, "popup,create", &m2);
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);
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);
831 EINA_LIST_FOREACH(m->items, itr, it)
832 elm_list_item_append(list, it->text, NULL, NULL, _popup_item_selected,
836 evas_object_show(notify);
838 evas_object_smart_callback_add(obj, "popup,willdelete", _popup_will_delete,
840 evas_object_smart_callback_add(notify, "block,clicked", _popup_dismiss_cb,
845 _view_smart_callback_proxy_free_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
851 _view_smart_callback_proxy_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info)
853 Elm_Web_Callback_Proxy_Context *ctxt = data;
855 evas_object_smart_callback_call(ctxt->obj, ctxt->name, event_info);
859 _view_smart_callback_proxy(Evas_Object *view, Evas_Object *parent)
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;
865 evas_object_smart_callbacks_descriptions_get(view, &cls_descs, &cls_count,
866 &inst_descs, &inst_count);
867 total = cls_count + inst_count;
869 ctxt = malloc(sizeof(Elm_Web_Callback_Proxy_Context) * total);
871 evas_object_event_callback_add(view, EVAS_CALLBACK_FREE,
872 _view_smart_callback_proxy_free_cb, ctxt);
874 for (; cls_count > 0; cls_count--, cls_descs++, ctxt++)
876 const Evas_Smart_Cb_Description *d = *cls_descs;
877 if (!strcmp(d->name, "popup,create"))
879 ctxt->name = d->name;
881 evas_object_smart_callback_add(view, d->name,
882 _view_smart_callback_proxy_cb, ctxt);
885 for (; inst_count > 0; inst_count--, inst_descs++, ctxt++)
887 const Evas_Smart_Cb_Description *d = *inst_descs;
888 ctxt->name = d->name;
890 evas_object_smart_callback_add(view, d->name,
891 _view_smart_callback_proxy_cb, ctxt);
896 #ifdef HAVE_ELEMENTARY_WEB
897 static int _elm_need_web = 0;
901 _elm_unneed_web(void)
903 #ifdef HAVE_ELEMENTARY_WEB
904 if (--_elm_need_web) return;
914 #ifdef HAVE_ELEMENTARY_WEB
915 if (_elm_need_web++) return EINA_TRUE;
924 elm_web_add(Evas_Object *parent)
930 EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
932 wd = calloc(1, sizeof(Widget_Data));
933 e = evas_object_evas_get(parent);
936 obj = elm_widget_add(e);
941 widtype = eina_stringshare_add("web");
942 elm_widget_type_register(&widtype);
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);
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);
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);
965 elm_widget_resize_object_set(obj, wd->ewk_view);
967 wd->tab_propagate = EINA_FALSE;
968 wd->inwin_mode = _elm_config->inwin_dialogs_enable;
970 _view_smart_callback_proxy(wd->ewk_view, wd->self);
971 evas_object_smart_callbacks_descriptions_set(obj, _elm_web_callback_names);
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);
986 elm_web_webkit_view_get(const Evas_Object *obj)
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;
994 ERR("Elementary not compiled with EWebKit support.");
1000 elm_web_window_create_hook_set(Evas_Object *obj, Elm_Web_Window_Open func, void *data)
1002 ELM_CHECK_WIDTYPE(obj, widtype);
1003 #ifdef HAVE_ELEMENTARY_WEB
1004 Widget_Data *wd = elm_widget_data_get(obj);
1006 wd->hook.window_create = func;
1007 wd->hook.window_create_data = data;
1015 elm_web_dialog_alert_hook_set(Evas_Object *obj, Elm_Web_Dialog_Alert func, void *data)
1017 ELM_CHECK_WIDTYPE(obj, widtype);
1018 #ifdef HAVE_ELEMENTARY_WEB
1019 Widget_Data *wd = elm_widget_data_get(obj);
1021 wd->hook.alert = func;
1022 wd->hook.alert_data = data;
1030 elm_web_dialog_confirm_hook_set(Evas_Object *obj, Elm_Web_Dialog_Confirm func, void *data)
1032 ELM_CHECK_WIDTYPE(obj, widtype);
1033 #ifdef HAVE_ELEMENTARY_WEB
1034 Widget_Data *wd = elm_widget_data_get(obj);
1036 wd->hook.confirm = func;
1037 wd->hook.confirm_data = data;
1045 elm_web_dialog_prompt_hook_set(Evas_Object *obj, Elm_Web_Dialog_Prompt func, void *data)
1047 ELM_CHECK_WIDTYPE(obj, widtype);
1048 #ifdef HAVE_ELEMENTARY_WEB
1049 Widget_Data *wd = elm_widget_data_get(obj);
1051 wd->hook.prompt = func;
1052 wd->hook.prompt_data = data;
1060 elm_web_dialog_file_selector_hook_set(Evas_Object *obj, Elm_Web_Dialog_File_Selector func, void *data)
1062 ELM_CHECK_WIDTYPE(obj, widtype);
1063 #ifdef HAVE_ELEMENTARY_WEB
1064 Widget_Data *wd = elm_widget_data_get(obj);
1066 wd->hook.file_selector = func;
1067 wd->hook.file_selector_data = data;
1075 elm_web_console_message_hook_set(Evas_Object *obj, Elm_Web_Console_Message func, void *data)
1077 ELM_CHECK_WIDTYPE(obj, widtype);
1078 #ifdef HAVE_ELEMENTARY_WEB
1079 Widget_Data *wd = elm_widget_data_get(obj);
1081 wd->hook.console_message = func;
1082 wd->hook.console_message_data = data;
1090 elm_web_tab_propagate_get(const Evas_Object *obj)
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;
1103 elm_web_tab_propagate_set(Evas_Object *obj, Eina_Bool propagate)
1105 ELM_CHECK_WIDTYPE(obj, widtype);
1106 #ifdef HAVE_ELEMENTARY_WEB
1107 Widget_Data *wd = elm_widget_data_get(obj);
1109 wd->tab_propagate = propagate;
1116 elm_web_uri_set(Evas_Object *obj, const char *uri)
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);
1130 elm_web_uri_get(const Evas_Object *obj)
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);
1143 elm_web_title_get(const Evas_Object *obj)
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);
1156 elm_web_bg_color_set(Evas_Object *obj, int r, int g, int b, int a)
1158 ELM_CHECK_WIDTYPE(obj, widtype);
1159 #ifdef HAVE_ELEMENTARY_WEB
1160 Widget_Data *wd = elm_widget_data_get(obj);
1162 ewk_view_bg_color_set(wd->ewk_view, r, g, b, a);
1172 elm_web_bg_color_get(const Evas_Object *obj, int *r, int *g, int *b, int *a)
1178 ELM_CHECK_WIDTYPE(obj, widtype);
1179 #ifdef HAVE_ELEMENTARY_WEB
1180 Widget_Data *wd = elm_widget_data_get(obj);
1182 return ewk_view_bg_color_get(wd->ewk_view, r, g, b, a);
1187 elm_web_selection_get(const Evas_Object *obj)
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);
1200 elm_web_popup_selected_set(Evas_Object *obj, int index)
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);
1212 elm_web_popup_destroy(Evas_Object *obj)
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);
1224 elm_web_text_search(const Evas_Object *obj, const char *string, Eina_Bool case_sensitive, Eina_Bool forward, Eina_Bool wrap)
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);
1234 (void)case_sensitive;
1242 elm_web_text_matches_mark(Evas_Object *obj, const char *string, Eina_Bool case_sensitive, Eina_Bool highlight, unsigned int limit)
1244 ELM_CHECK_WIDTYPE(obj, widtype) 0;
1245 #ifdef HAVE_ELEMENTARY_WEB
1246 Widget_Data *wd = elm_widget_data_get(obj);
1248 return ewk_view_text_matches_mark
1249 (wd->ewk_view, string, case_sensitive, highlight, limit);
1252 (void)case_sensitive;
1260 elm_web_text_matches_unmark_all(Evas_Object *obj)
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);
1273 elm_web_text_matches_highlight_set(Evas_Object *obj, Eina_Bool highlight)
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);
1287 elm_web_text_matches_highlight_get(const Evas_Object *obj)
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);
1300 elm_web_load_progress_get(const Evas_Object *obj)
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);
1313 elm_web_stop(Evas_Object *obj)
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);
1326 elm_web_reload(Evas_Object *obj)
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);
1339 elm_web_reload_full(Evas_Object *obj)
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);
1353 elm_web_back(Evas_Object *obj)
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);
1366 elm_web_forward(Evas_Object *obj)
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);
1379 elm_web_navigate(Evas_Object *obj, int steps)
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);
1393 elm_web_back_possible(Evas_Object *obj)
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);
1406 elm_web_forward_possible(Evas_Object *obj)
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);
1419 elm_web_navigate_possible(Evas_Object *obj, int steps)
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);
1433 elm_web_history_enable_get(const Evas_Object *obj)
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);
1446 elm_web_history_enable_set(Evas_Object *obj, Eina_Bool enable)
1448 ELM_CHECK_WIDTYPE(obj, widtype);
1449 #ifdef HAVE_ELEMENTARY_WEB
1450 Widget_Data *wd = elm_widget_data_get(obj);
1452 ewk_view_history_enable_set(wd->ewk_view, enable);
1458 //EAPI Ewk_History *ewk_view_history_get(const Evas_Object *obj); // TODO:
1461 elm_web_zoom_text_only_get(const Evas_Object *obj)
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);
1474 elm_web_zoom_text_only_set(Evas_Object *obj, Eina_Bool setting)
1476 ELM_CHECK_WIDTYPE(obj, widtype);
1477 #ifdef HAVE_ELEMENTARY_WEB
1478 Widget_Data *wd = elm_widget_data_get(obj);
1480 ewk_view_zoom_text_only_set(wd->ewk_view, setting);
1487 elm_web_inwin_mode_set(Evas_Object *obj, Eina_Bool value)
1489 ELM_CHECK_WIDTYPE(obj, widtype);
1490 #ifdef HAVE_ELEMENTARY_WEB
1491 Widget_Data *wd = elm_widget_data_get(obj);
1493 wd->inwin_mode = value;
1500 elm_web_inwin_mode_get(const Evas_Object *obj)
1502 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1503 #ifdef HAVE_ELEMENTARY_WEB
1504 Widget_Data *wd = elm_widget_data_get(obj);
1506 return wd->inwin_mode;
1513 elm_web_window_features_ref(Elm_Web_Window_Features *wf)
1515 #ifdef HAVE_ELEMENTARY_WEB
1516 ewk_window_features_ref((Ewk_Window_Features *)wf);
1523 elm_web_window_features_unref(Elm_Web_Window_Features *wf)
1525 #ifdef HAVE_ELEMENTARY_WEB
1526 ewk_window_features_unref((Ewk_Window_Features *)wf);
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)
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);
1542 (void)toolbar_visible;
1543 (void)statusbar_visible;
1544 (void)scrollbars_visible;
1545 (void)menubar_visible;
1546 (void)locationbar_visible;
1552 elm_web_window_features_int_property_get(const Elm_Web_Window_Features *wf, int *x, int *y, int *w, int *h)
1554 #ifdef HAVE_ELEMENTARY_WEB
1555 ewk_window_features_int_property_get((const Ewk_Window_Features *)wf,
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!