1/*
2    Copyright (C) 2009-2010 ProFUSION embedded systems
3    Copyright (C) 2009-2011 Samsung Electronics
4
5    This library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Library General Public
7    License as published by the Free Software Foundation; either
8    version 2 of the License, or (at your option) any later version.
9
10    This library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Library General Public License for more details.
14
15    You should have received a copy of the GNU Library General Public License
16    along with this library; see the file COPYING.LIB.  If not, write to
17    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18    Boston, MA 02110-1301, USA.
19*/
20
21#define __STDC_FORMAT_MACROS
22#include "config.h"
23#include "ewk_view.h"
24
25#include "BackForwardListImpl.h"
26#include "Chrome.h"
27#include "ChromeClientEfl.h"
28#include "ContextMenuController.h"
29#include "DocumentLoader.h"
30#include "DragClientEfl.h"
31#include "EWebKit.h"
32#include "EditorClientEfl.h"
33#include "EventHandler.h"
34#include "FocusController.h"
35#include "FrameLoaderClientEfl.h"
36#include "FrameView.h"
37#include "GraphicsContext.h"
38#include "HTMLElement.h"
39#include "HTMLInputElement.h"
40#include "HTMLNames.h"
41#include "InspectorClientEfl.h"
42#include "IntSize.h"
43#include "PlatformMouseEvent.h"
44#include "PopupMenuClient.h"
45#include "ProgressTracker.h"
46#include "ewk_private.h"
47
48#include <Ecore.h>
49#include <Eina.h>
50#include <Evas.h>
51#include <eina_safety_checks.h>
52#include <inttypes.h>
53#include <sys/time.h>
54
55#ifdef HAVE_ECORE_X
56#include <Ecore_X.h>
57#endif
58
59#define ZOOM_MIN (0.05)
60#define ZOOM_MAX (4.0)
61
62#define DEVICE_PIXEL_RATIO (1.0)
63
64static const char EWK_VIEW_TYPE_STR[] = "EWK_View";
65
66static const size_t EWK_VIEW_REPAINTS_SIZE_INITIAL = 32;
67static const size_t EWK_VIEW_REPAINTS_SIZE_STEP = 8;
68static const size_t EWK_VIEW_REPAINTS_SIZE_MAX_FREE = 64;
69
70static const size_t EWK_VIEW_SCROLLS_SIZE_INITIAL = 8;
71static const size_t EWK_VIEW_SCROLLS_SIZE_STEP = 2;
72static const size_t EWK_VIEW_SCROLLS_SIZE_MAX_FREE = 32;
73
74struct _Ewk_View_Private_Data {
75    WebCore::Page* page;
76    WebCore::Settings* page_settings;
77    WebCore::Frame* main_frame;
78    WebCore::ViewportArguments viewport_arguments;
79    Ewk_History* history;
80    struct {
81        Ewk_Menu menu;
82        WebCore::PopupMenuClient* menu_client;
83    } popup;
84    struct {
85        Eina_Rectangle* array;
86        size_t count;
87        size_t allocated;
88    } repaints;
89    struct {
90        Ewk_Scroll_Request* array;
91        size_t count;
92        size_t allocated;
93    } scrolls;
94    unsigned int imh; /**< input method hints */
95    struct {
96        Eina_Bool view_cleared:1;
97        Eina_Bool need_touch_events:1;
98    } flags;
99    struct {
100        const char* user_agent;
101        const char* user_stylesheet;
102        const char* encoding_default;
103        const char* encoding_custom;
104        const char* theme;
105        const char* local_storage_database_path;
106        int font_minimum_size;
107        int font_minimum_logical_size;
108        int font_default_size;
109        int font_monospace_size;
110        const char* font_standard;
111        const char* font_cursive;
112        const char* font_monospace;
113        const char* font_fantasy;
114        const char* font_serif;
115        const char* font_sans_serif;
116        Eina_Bool auto_load_images:1;
117        Eina_Bool auto_shrink_images:1;
118        Eina_Bool enable_auto_resize_window:1;
119        Eina_Bool enable_scripts:1;
120        Eina_Bool enable_plugins:1;
121        Eina_Bool enable_frame_flattening:1;
122        Eina_Bool encoding_detector:1;
123        Eina_Bool scripts_window_open:1;
124        Eina_Bool resizable_textareas:1;
125        Eina_Bool private_browsing:1;
126        Eina_Bool caret_browsing:1;
127        Eina_Bool spatial_navigation:1;
128        Eina_Bool local_storage:1;
129        Eina_Bool offline_app_cache: 1;
130        Eina_Bool page_cache: 1;
131        struct {
132            float min_scale;
133            float max_scale;
134            Eina_Bool user_scalable:1;
135        } zoom_range;
136        float device_pixel_ratio;
137    } settings;
138    struct {
139        struct {
140            double start;
141            double end;
142            double duration;
143        } time;
144        struct {
145            float start;
146            float end;
147            float range;
148        } zoom;
149        struct {
150            Evas_Coord x, y;
151        } center;
152        Ecore_Animator* animator;
153    } animated_zoom;
154    struct {
155        Evas_Coord w, h;
156        Eina_Bool use:1;
157    } fixed_layout;
158};
159
160#ifndef EWK_TYPE_CHECK
161#define EWK_VIEW_TYPE_CHECK(o, ...) do { } while (0)
162#else
163#define EWK_VIEW_TYPE_CHECK(o, ...)                                     \
164    do {                                                                \
165        const char* _tmp_otype = evas_object_type_get(o);               \
166        const Evas_Smart* _tmp_s = evas_object_smart_smart_get(o);      \
167        if (EINA_UNLIKELY(!_tmp_s)) {                                   \
168            EINA_LOG_CRIT                                               \
169                ("%p (%s) is not a smart object!", o,                   \
170                 _tmp_otype ? _tmp_otype : "(null)");                   \
171            return __VA_ARGS__;                                         \
172        }                                                               \
173        const Evas_Smart_Class* _tmp_sc = evas_smart_class_get(_tmp_s); \
174        if (EINA_UNLIKELY(!_tmp_sc)) {                                  \
175            EINA_LOG_CRIT                                               \
176                ("%p (%s) is not a smart object!", o,                   \
177                 _tmp_otype ? _tmp_otype : "(null)");                   \
178            return __VA_ARGS__;                                         \
179        }                                                               \
180        if (EINA_UNLIKELY(_tmp_sc->data != EWK_VIEW_TYPE_STR)) {        \
181            EINA_LOG_CRIT                                               \
182                ("%p (%s) is not of an ewk_view (need %p, got %p)!",    \
183                 o, _tmp_otype ? _tmp_otype : "(null)",                 \
184                 EWK_VIEW_TYPE_STR, _tmp_sc->data);                     \
185            return __VA_ARGS__;                                         \
186        }                                                               \
187    } while (0)
188#endif
189
190#define EWK_VIEW_SD_GET(o, ptr)                                 \
191    Ewk_View_Smart_Data* ptr = (Ewk_View_Smart_Data*)evas_object_smart_data_get(o)
192
193#define EWK_VIEW_SD_GET_OR_RETURN(o, ptr, ...)          \
194    EWK_VIEW_TYPE_CHECK(o, __VA_ARGS__);                \
195    EWK_VIEW_SD_GET(o, ptr);                            \
196    if (!ptr) {                                         \
197        CRITICAL("no smart data for object %p (%s)",    \
198                 o, evas_object_type_get(o));           \
199        return __VA_ARGS__;                             \
200    }
201
202#define EWK_VIEW_PRIV_GET(sd, ptr)              \
203    Ewk_View_Private_Data* ptr = sd->_priv
204
205#define EWK_VIEW_PRIV_GET_OR_RETURN(sd, ptr, ...)               \
206    EWK_VIEW_PRIV_GET(sd, ptr);                                 \
207    if (!ptr) {                                                 \
208        CRITICAL("no private data for object %p (%s)",          \
209                 sd->self, evas_object_type_get(sd->self));     \
210        return __VA_ARGS__;                                     \
211    }
212
213static void _ewk_view_smart_changed(Ewk_View_Smart_Data* sd)
214{
215    if (sd->changed.any)
216        return;
217    sd->changed.any = EINA_TRUE;
218    evas_object_smart_changed(sd->self);
219}
220
221static Eina_Bool _ewk_view_repaints_resize(Ewk_View_Private_Data* priv, size_t size)
222{
223    void* tmp = realloc(priv->repaints.array, size * sizeof(Eina_Rectangle));
224    if (!tmp) {
225        CRITICAL("could not realloc repaints array to %zu elements.", size);
226        return EINA_FALSE;
227    }
228    priv->repaints.allocated = size;
229    priv->repaints.array = (Eina_Rectangle*)tmp;
230    return EINA_TRUE;
231}
232
233static void _ewk_view_repaint_add(Ewk_View_Private_Data* priv, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
234{
235    Eina_Rectangle* r;
236
237    // fprintf(stderr, ">>> repaint requested: %d,%d+%dx%d\n", x, y, w, h);
238    if (priv->repaints.allocated == priv->repaints.count) {
239        size_t size;
240        if (!priv->repaints.allocated)
241            size = EWK_VIEW_REPAINTS_SIZE_INITIAL;
242        else
243            size = priv->repaints.allocated + EWK_VIEW_REPAINTS_SIZE_STEP;
244        if (!_ewk_view_repaints_resize(priv, size))
245            return;
246    }
247
248    r = priv->repaints.array + priv->repaints.count;
249    priv->repaints.count++;
250
251    r->x = x;
252    r->y = y;
253    r->w = w;
254    r->h = h;
255
256    DBG("add repaint %d,%d+%dx%d", x, y, w, h);
257}
258
259static void _ewk_view_repaints_flush(Ewk_View_Private_Data* priv)
260{
261    priv->repaints.count = 0;
262    if (priv->repaints.allocated <= EWK_VIEW_REPAINTS_SIZE_MAX_FREE)
263        return;
264    _ewk_view_repaints_resize(priv, EWK_VIEW_REPAINTS_SIZE_MAX_FREE);
265}
266
267static Eina_Bool _ewk_view_scrolls_resize(Ewk_View_Private_Data* priv, size_t size)
268{
269    void* tmp = realloc(priv->scrolls.array, size * sizeof(Ewk_Scroll_Request));
270    if (!tmp) {
271        CRITICAL("could not realloc scrolls array to %zu elements.", size);
272        return EINA_FALSE;
273    }
274    priv->scrolls.allocated = size;
275    priv->scrolls.array = (Ewk_Scroll_Request*)tmp;
276    return EINA_TRUE;
277}
278
279static void _ewk_view_scroll_add(Ewk_View_Private_Data* priv, Evas_Coord dx, Evas_Coord dy, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h, Eina_Bool main_scroll)
280{
281    Ewk_Scroll_Request* r;
282    Ewk_Scroll_Request* r_end;
283    Evas_Coord x2 = x + w, y2 = y + h;
284
285    r = priv->scrolls.array;
286    r_end = r + priv->scrolls.count;
287    for (; r < r_end; r++) {
288        if (r->x == x && r->y == y && r->w == w && r->h == h) {
289            DBG("region already scrolled %d,%d+%dx%d %+03d,%+03d add "
290                "%+03d,%+03d",
291                r->x, r->y, r->w, r->h, r->dx, r->dy, dx, dy);
292            r->dx += dx;
293            r->dy += dy;
294            return;
295        }
296        if ((x <= r->x && x2 >= r->x2) && (y <= r->y && y2 >= r->y2)) {
297            DBG("old viewport (%d,%d+%dx%d %+03d,%+03d) was scrolled itself, "
298                "add %+03d,%+03d",
299                r->x, r->y, r->w, r->h, r->dx, r->dy, dx, dy);
300            r->x += dx;
301            r->y += dy;
302        }
303    }
304
305    if (priv->scrolls.allocated == priv->scrolls.count) {
306        size_t size;
307        if (!priv->scrolls.allocated)
308            size = EWK_VIEW_SCROLLS_SIZE_INITIAL;
309        else
310            size = priv->scrolls.allocated + EWK_VIEW_SCROLLS_SIZE_STEP;
311        if (!_ewk_view_scrolls_resize(priv, size))
312            return;
313    }
314
315    r = priv->scrolls.array + priv->scrolls.count;
316    priv->scrolls.count++;
317
318    r->x = x;
319    r->y = y;
320    r->w = w;
321    r->h = h;
322    r->x2 = x2;
323    r->y2 = y2;
324    r->dx = dx;
325    r->dy = dy;
326    r->main_scroll = main_scroll;
327    DBG("add scroll in region: %d,%d+%dx%d %+03d,%+03d", x, y, w, h, dx, dy);
328
329    Eina_Rectangle* pr;
330    Eina_Rectangle* pr_end;
331    size_t count;
332    pr = priv->repaints.array;
333    count = priv->repaints.count;
334    pr_end = pr + count;
335    for (; pr < pr_end; pr++) {
336        pr->x += dx;
337        pr->y += dy;
338    }
339}
340
341static void _ewk_view_scrolls_flush(Ewk_View_Private_Data* priv)
342{
343    priv->scrolls.count = 0;
344    if (priv->scrolls.allocated <= EWK_VIEW_SCROLLS_SIZE_MAX_FREE)
345        return;
346    _ewk_view_scrolls_resize(priv, EWK_VIEW_SCROLLS_SIZE_MAX_FREE);
347}
348
349// Default Event Handling //////////////////////////////////////////////
350static Eina_Bool _ewk_view_smart_focus_in(Ewk_View_Smart_Data* sd)
351{
352    EWK_VIEW_PRIV_GET(sd, priv);
353    WebCore::FocusController* fc = priv->page->focusController();
354    DBG("o=%p, fc=%p", sd->self, fc);
355    EINA_SAFETY_ON_NULL_RETURN_VAL(fc, EINA_FALSE);
356
357    fc->setActive(true);
358    fc->setFocused(true);
359    return EINA_TRUE;
360}
361
362static Eina_Bool _ewk_view_smart_focus_out(Ewk_View_Smart_Data* sd)
363{
364    EWK_VIEW_PRIV_GET(sd, priv);
365    WebCore::FocusController* fc = priv->page->focusController();
366    DBG("o=%p, fc=%p", sd->self, fc);
367    EINA_SAFETY_ON_NULL_RETURN_VAL(fc, EINA_FALSE);
368
369    fc->setActive(false);
370    fc->setFocused(false);
371    return EINA_TRUE;
372}
373
374static Eina_Bool _ewk_view_smart_mouse_wheel(Ewk_View_Smart_Data* sd, const Evas_Event_Mouse_Wheel* ev)
375{
376    return ewk_frame_feed_mouse_wheel(sd->main_frame, ev);
377}
378
379static Eina_Bool _ewk_view_smart_mouse_down(Ewk_View_Smart_Data* sd, const Evas_Event_Mouse_Down* ev)
380{
381    return ewk_frame_feed_mouse_down(sd->main_frame, ev);
382}
383
384static Eina_Bool _ewk_view_smart_mouse_up(Ewk_View_Smart_Data* sd, const Evas_Event_Mouse_Up* ev)
385{
386    return ewk_frame_feed_mouse_up(sd->main_frame, ev);
387}
388
389static Eina_Bool _ewk_view_smart_mouse_move(Ewk_View_Smart_Data* sd, const Evas_Event_Mouse_Move* ev)
390{
391    return ewk_frame_feed_mouse_move(sd->main_frame, ev);
392}
393
394static Eina_Bool _ewk_view_smart_key_down(Ewk_View_Smart_Data* sd, const Evas_Event_Key_Down* ev)
395{
396    Evas_Object* frame = ewk_view_frame_focused_get(sd->self);
397
398    if (!frame)
399        frame = sd->main_frame;
400
401    return ewk_frame_feed_key_down(frame, ev);
402}
403
404static Eina_Bool _ewk_view_smart_key_up(Ewk_View_Smart_Data* sd, const Evas_Event_Key_Up* ev)
405{
406    Evas_Object* frame = ewk_view_frame_focused_get(sd->self);
407
408    if (!frame)
409        frame = sd->main_frame;
410
411    return ewk_frame_feed_key_up(frame, ev);
412}
413
414static void _ewk_view_smart_add_console_message(Ewk_View_Smart_Data* sd, const char* message, unsigned int lineNumber, const char* sourceID)
415{
416    INF("console message: %s @%d: %s\n", sourceID, lineNumber, message);
417}
418
419static void _ewk_view_smart_run_javascript_alert(Ewk_View_Smart_Data* sd, Evas_Object* frame, const char* message)
420{
421    INF("javascript alert: %s\n", message);
422}
423
424static Eina_Bool _ewk_view_smart_run_javascript_confirm(Ewk_View_Smart_Data* sd, Evas_Object* frame, const char* message)
425{
426    INF("javascript confirm: %s", message);
427    INF("javascript confirm (HARD CODED)? YES");
428    return EINA_TRUE;
429}
430
431static Eina_Bool _ewk_view_smart_should_interrupt_javascript(Ewk_View_Smart_Data* sd)
432{
433    INF("should interrupt javascript?\n"
434            "\t(HARD CODED) NO");
435    return EINA_FALSE;
436}
437
438static Eina_Bool _ewk_view_smart_run_javascript_prompt(Ewk_View_Smart_Data* sd, Evas_Object* frame, const char* message, const char* defaultValue, char** value)
439{
440    *value = strdup("test");
441    Eina_Bool ret = EINA_TRUE;
442    INF("javascript prompt:\n"
443            "\t      message: %s\n"
444            "\tdefault value: %s\n"
445            "\tgiving answer: %s\n"
446            "\t       button: %s", message, defaultValue, *value, ret?"ok":"cancel");
447
448    return ret;
449}
450
451// Event Handling //////////////////////////////////////////////////////
452static void _ewk_view_on_focus_in(void* data, Evas* e, Evas_Object* o, void* event_info)
453{
454    Ewk_View_Smart_Data* sd = (Ewk_View_Smart_Data*)data;
455    EINA_SAFETY_ON_NULL_RETURN(sd->api);
456    EINA_SAFETY_ON_NULL_RETURN(sd->api->focus_in);
457    sd->api->focus_in(sd);
458}
459
460static void _ewk_view_on_focus_out(void* data, Evas* e, Evas_Object* o, void* event_info)
461{
462    Ewk_View_Smart_Data* sd = (Ewk_View_Smart_Data*)data;
463    EINA_SAFETY_ON_NULL_RETURN(sd->api);
464    EINA_SAFETY_ON_NULL_RETURN(sd->api->focus_out);
465    sd->api->focus_out(sd);
466}
467
468static void _ewk_view_on_mouse_wheel(void* data, Evas* e, Evas_Object* o, void* event_info)
469{
470    Evas_Event_Mouse_Wheel* ev = (Evas_Event_Mouse_Wheel*)event_info;
471    Ewk_View_Smart_Data* sd = (Ewk_View_Smart_Data*)data;
472    EINA_SAFETY_ON_NULL_RETURN(sd->api);
473    EINA_SAFETY_ON_NULL_RETURN(sd->api->mouse_wheel);
474    sd->api->mouse_wheel(sd, ev);
475}
476
477static void _ewk_view_on_mouse_down(void* data, Evas* e, Evas_Object* o, void* event_info)
478{
479    Evas_Event_Mouse_Down* ev = (Evas_Event_Mouse_Down*)event_info;
480    Ewk_View_Smart_Data* sd = (Ewk_View_Smart_Data*)data;
481    EINA_SAFETY_ON_NULL_RETURN(sd->api);
482    EINA_SAFETY_ON_NULL_RETURN(sd->api->mouse_down);
483    sd->api->mouse_down(sd, ev);
484}
485
486static void _ewk_view_on_mouse_up(void* data, Evas* e, Evas_Object* o, void* event_info)
487{
488    Evas_Event_Mouse_Up* ev = (Evas_Event_Mouse_Up*)event_info;
489    Ewk_View_Smart_Data* sd = (Ewk_View_Smart_Data*)data;
490    EINA_SAFETY_ON_NULL_RETURN(sd->api);
491    EINA_SAFETY_ON_NULL_RETURN(sd->api->mouse_up);
492    sd->api->mouse_up(sd, ev);
493}
494
495static void _ewk_view_on_mouse_move(void* data, Evas* e, Evas_Object* o, void* event_info)
496{
497    Evas_Event_Mouse_Move* ev = (Evas_Event_Mouse_Move*)event_info;
498    Ewk_View_Smart_Data* sd = (Ewk_View_Smart_Data*)data;
499    EINA_SAFETY_ON_NULL_RETURN(sd->api);
500    EINA_SAFETY_ON_NULL_RETURN(sd->api->mouse_move);
501    sd->api->mouse_move(sd, ev);
502}
503
504static void _ewk_view_on_key_down(void* data, Evas* e, Evas_Object* o, void* event_info)
505{
506    Evas_Event_Key_Down* ev = (Evas_Event_Key_Down*)event_info;
507    Ewk_View_Smart_Data* sd = (Ewk_View_Smart_Data*)data;
508    EINA_SAFETY_ON_NULL_RETURN(sd->api);
509    EINA_SAFETY_ON_NULL_RETURN(sd->api->key_down);
510    sd->api->key_down(sd, ev);
511}
512
513static void _ewk_view_on_key_up(void* data, Evas* e, Evas_Object* o, void* event_info)
514{
515    Evas_Event_Key_Up* ev = (Evas_Event_Key_Up*)event_info;
516    Ewk_View_Smart_Data* sd = (Ewk_View_Smart_Data*)data;
517    EINA_SAFETY_ON_NULL_RETURN(sd->api);
518    EINA_SAFETY_ON_NULL_RETURN(sd->api->key_up);
519    sd->api->key_up(sd, ev);
520}
521
522static WTF::PassRefPtr<WebCore::Frame> _ewk_view_core_frame_new(Ewk_View_Smart_Data* sd, Ewk_View_Private_Data* priv, WebCore::HTMLFrameOwnerElement* owner)
523{
524    WebCore::FrameLoaderClientEfl* flc = new WebCore::FrameLoaderClientEfl(sd->self);
525    if (!flc) {
526        CRITICAL("Could not create frame loader client.");
527        return 0;
528    }
529    flc->setCustomUserAgent(String::fromUTF8(priv->settings.user_agent));
530
531    return WebCore::Frame::create(priv->page, owner, flc);
532}
533
534static Evas_Smart_Class _parent_sc = EVAS_SMART_CLASS_INIT_NULL;
535
536static Ewk_View_Private_Data* _ewk_view_priv_new(Ewk_View_Smart_Data* sd)
537{
538    Ewk_View_Private_Data* priv =
539        (Ewk_View_Private_Data*)calloc(1, sizeof(Ewk_View_Private_Data));
540    AtomicString s;
541    WebCore::KURL url;
542
543    if (!priv) {
544        CRITICAL("could not allocate Ewk_View_Private_Data");
545        return 0;
546    }
547
548    WebCore::Page::PageClients pageClients;
549    pageClients.chromeClient = static_cast<WebCore::ChromeClient*>(new WebCore::ChromeClientEfl(sd->self));
550    pageClients.editorClient = static_cast<WebCore::EditorClient*>(new WebCore::EditorClientEfl(sd->self));
551    pageClients.dragClient = static_cast<WebCore::DragClient*>(new WebCore::DragClientEfl);
552    pageClients.inspectorClient = static_cast<WebCore::InspectorClient*>(new WebCore::InspectorClientEfl);
553    priv->page = new WebCore::Page(pageClients);
554    if (!priv->page) {
555        CRITICAL("Could not create WebKit Page");
556        goto error_page;
557    }
558
559    priv->page_settings = priv->page->settings();
560    if (!priv->page_settings) {
561        CRITICAL("Could not get page settings.");
562        goto error_settings;
563    }
564
565    priv->page_settings->setLoadsImagesAutomatically(true);
566    priv->page_settings->setDefaultFixedFontSize(12);
567    priv->page_settings->setDefaultFontSize(16);
568    priv->page_settings->setSerifFontFamily("serif");
569    priv->page_settings->setFixedFontFamily("monotype");
570    priv->page_settings->setSansSerifFontFamily("sans");
571    priv->page_settings->setStandardFontFamily("sans");
572    priv->page_settings->setJavaScriptEnabled(true);
573    priv->page_settings->setPluginsEnabled(true);
574    priv->page_settings->setLocalStorageEnabled(true);
575    priv->page_settings->setOfflineWebApplicationCacheEnabled(true);
576    priv->page_settings->setUsesPageCache(true);
577    priv->page_settings->setUsesEncodingDetector(true);
578
579    url = priv->page_settings->userStyleSheetLocation();
580    priv->settings.user_stylesheet = eina_stringshare_add(url.string().utf8().data());
581
582    priv->settings.encoding_default = eina_stringshare_add
583        (priv->page_settings->defaultTextEncodingName().utf8().data());
584    priv->settings.encoding_custom = 0;
585
586    s = priv->page_settings->localStorageDatabasePath();
587    priv->settings.local_storage_database_path = eina_stringshare_add(s.string().utf8().data());
588
589    priv->settings.font_minimum_size = priv->page_settings->minimumFontSize();
590    priv->settings.font_minimum_logical_size = priv->page_settings->minimumLogicalFontSize();
591    priv->settings.font_default_size = priv->page_settings->defaultFontSize();
592    priv->settings.font_monospace_size = priv->page_settings->defaultFixedFontSize();
593
594    s = priv->page_settings->standardFontFamily();
595    priv->settings.font_standard = eina_stringshare_add(s.string().utf8().data());
596    s = priv->page_settings->cursiveFontFamily();
597    priv->settings.font_cursive = eina_stringshare_add(s.string().utf8().data());
598    s = priv->page_settings->fixedFontFamily();
599    priv->settings.font_monospace = eina_stringshare_add(s.string().utf8().data());
600    s = priv->page_settings->fantasyFontFamily();
601    priv->settings.font_fantasy = eina_stringshare_add(s.string().utf8().data());
602    s = priv->page_settings->serifFontFamily();
603    priv->settings.font_serif = eina_stringshare_add(s.string().utf8().data());
604    s = priv->page_settings->sansSerifFontFamily();
605    priv->settings.font_sans_serif = eina_stringshare_add(s.string().utf8().data());
606
607    priv->settings.auto_load_images = priv->page_settings->loadsImagesAutomatically();
608    priv->settings.auto_shrink_images = priv->page_settings->shrinksStandaloneImagesToFit();
609    priv->settings.enable_auto_resize_window = EINA_TRUE;
610    priv->settings.enable_scripts = priv->page_settings->isJavaScriptEnabled();
611    priv->settings.enable_plugins = priv->page_settings->arePluginsEnabled();
612    priv->settings.enable_frame_flattening = priv->page_settings->frameFlatteningEnabled();
613    priv->settings.scripts_window_open = priv->page_settings->allowScriptsToCloseWindows();
614    priv->settings.resizable_textareas = priv->page_settings->textAreasAreResizable();
615    priv->settings.private_browsing = priv->page_settings->privateBrowsingEnabled();
616    priv->settings.caret_browsing = priv->page_settings->caretBrowsingEnabled();
617    priv->settings.spatial_navigation = priv->page_settings->isSpatialNavigationEnabled();
618    priv->settings.local_storage = priv->page_settings->localStorageEnabled();
619    priv->settings.offline_app_cache = true; // XXX no function to read setting; this keeps the original setting
620    priv->settings.page_cache = priv->page_settings->usesPageCache();
621    priv->settings.encoding_detector = priv->page_settings->usesEncodingDetector();
622
623    priv->settings.user_agent = ewk_settings_default_user_agent_get();
624
625    // Since there's no scale separated from zooming in webkit-efl, this functionality of
626    // viewport meta tag is implemented using zoom. When scale zoom is supported by webkit-efl,
627    // this functionality will be modified by the scale zoom patch.
628    priv->settings.zoom_range.min_scale = ZOOM_MIN;
629    priv->settings.zoom_range.max_scale = ZOOM_MAX;
630    priv->settings.zoom_range.user_scalable = EINA_TRUE;
631    priv->settings.device_pixel_ratio = DEVICE_PIXEL_RATIO;
632
633    priv->main_frame = _ewk_view_core_frame_new(sd, priv, 0).get();
634    if (!priv->main_frame) {
635        CRITICAL("Could not create main frame.");
636        goto error_main_frame;
637    }
638
639    priv->history = ewk_history_new(static_cast<WebCore::BackForwardListImpl*>(priv->page->backForwardList()));
640    if (!priv->history) {
641        CRITICAL("Could not create history instance for view.");
642        goto error_history;
643    }
644
645    return priv;
646
647error_history:
648    // delete priv->main_frame; /* do not delete priv->main_frame */
649error_main_frame:
650error_settings:
651    delete priv->page;
652error_page:
653    free(priv);
654    return 0;
655}
656
657static void _ewk_view_priv_del(Ewk_View_Private_Data* priv)
658{
659    if (!priv)
660        return;
661
662    /* do not delete priv->main_frame */
663
664    free(priv->repaints.array);
665    free(priv->scrolls.array);
666
667    eina_stringshare_del(priv->settings.user_agent);
668    eina_stringshare_del(priv->settings.user_stylesheet);
669    eina_stringshare_del(priv->settings.encoding_default);
670    eina_stringshare_del(priv->settings.encoding_custom);
671    eina_stringshare_del(priv->settings.font_standard);
672    eina_stringshare_del(priv->settings.font_cursive);
673    eina_stringshare_del(priv->settings.font_monospace);
674    eina_stringshare_del(priv->settings.font_fantasy);
675    eina_stringshare_del(priv->settings.font_serif);
676    eina_stringshare_del(priv->settings.font_sans_serif);
677    eina_stringshare_del(priv->settings.local_storage_database_path);
678
679    if (priv->animated_zoom.animator)
680        ecore_animator_del(priv->animated_zoom.animator);
681
682    ewk_history_free(priv->history);
683
684    delete priv->page;
685    free(priv);
686}
687
688static void _ewk_view_smart_add(Evas_Object* o)
689{
690    const Evas_Smart* smart = evas_object_smart_smart_get(o);
691    const Evas_Smart_Class* sc = evas_smart_class_get(smart);
692    const Ewk_View_Smart_Class* api = (const Ewk_View_Smart_Class*)sc;
693    EINA_SAFETY_ON_NULL_RETURN(api->backing_store_add);
694    EWK_VIEW_SD_GET(o, sd);
695
696    if (!sd) {
697        sd = (Ewk_View_Smart_Data*)calloc(1, sizeof(Ewk_View_Smart_Data));
698        if (!sd)
699            CRITICAL("could not allocate Ewk_View_Smart_Data");
700        else
701            evas_object_smart_data_set(o, sd);
702    }
703
704    sd->bg_color.r = 255;
705    sd->bg_color.g = 255;
706    sd->bg_color.b = 255;
707    sd->bg_color.a = 255;
708
709    sd->self = o;
710    sd->_priv = _ewk_view_priv_new(sd);
711    sd->api = api;
712
713    _parent_sc.add(o);
714
715    if (!sd->_priv)
716        return;
717
718    EWK_VIEW_PRIV_GET(sd, priv);
719
720    sd->backing_store = api->backing_store_add(sd);
721    if (!sd->backing_store) {
722        ERR("Could not create backing store object.");
723        return;
724    }
725
726    evas_object_smart_member_add(sd->backing_store, o);
727    evas_object_show(sd->backing_store);
728    evas_object_pass_events_set(sd->backing_store, EINA_TRUE);
729
730    sd->events_rect = evas_object_rectangle_add(sd->base.evas);
731    evas_object_color_set(sd->events_rect, 0, 0, 0, 0);
732    evas_object_smart_member_add(sd->events_rect, o);
733    evas_object_show(sd->events_rect);
734
735    sd->main_frame = ewk_frame_add(sd->base.evas);
736    if (!sd->main_frame) {
737        ERR("Could not create main frame object.");
738        return;
739    }
740
741    if (!ewk_frame_init(sd->main_frame, o, priv->main_frame)) {
742        ERR("Could not initialize main frme object.");
743        evas_object_del(sd->main_frame);
744        sd->main_frame = 0;
745
746        delete priv->main_frame;
747        priv->main_frame = 0;
748        return;
749    }
750
751    evas_object_name_set(sd->main_frame, "EWK_Frame:main");
752    evas_object_smart_member_add(sd->main_frame, o);
753    evas_object_show(sd->main_frame);
754
755#define CONNECT(s, c) evas_object_event_callback_add(o, s, c, sd)
756    CONNECT(EVAS_CALLBACK_FOCUS_IN, _ewk_view_on_focus_in);
757    CONNECT(EVAS_CALLBACK_FOCUS_OUT, _ewk_view_on_focus_out);
758    CONNECT(EVAS_CALLBACK_MOUSE_WHEEL, _ewk_view_on_mouse_wheel);
759    CONNECT(EVAS_CALLBACK_MOUSE_DOWN, _ewk_view_on_mouse_down);
760    CONNECT(EVAS_CALLBACK_MOUSE_UP, _ewk_view_on_mouse_up);
761    CONNECT(EVAS_CALLBACK_MOUSE_MOVE, _ewk_view_on_mouse_move);
762    CONNECT(EVAS_CALLBACK_KEY_DOWN, _ewk_view_on_key_down);
763    CONNECT(EVAS_CALLBACK_KEY_UP, _ewk_view_on_key_up);
764#undef CONNECT
765}
766
767static void _ewk_view_smart_del(Evas_Object* o)
768{
769    EWK_VIEW_SD_GET(o, sd);
770    Ewk_View_Private_Data* priv = sd ? sd->_priv : 0;
771
772    ewk_view_stop(o);
773    _parent_sc.del(o);
774    _ewk_view_priv_del(priv);
775}
776
777static void _ewk_view_smart_resize(Evas_Object* o, Evas_Coord w, Evas_Coord h)
778{
779    EWK_VIEW_SD_GET(o, sd);
780
781    // these should be queued and processed in calculate as well!
782    evas_object_resize(sd->backing_store, w, h);
783
784    sd->changed.size = EINA_TRUE;
785    _ewk_view_smart_changed(sd);
786}
787
788static void _ewk_view_smart_move(Evas_Object* o, Evas_Coord x, Evas_Coord y)
789{
790    EWK_VIEW_SD_GET(o, sd);
791    sd->changed.position = EINA_TRUE;
792    _ewk_view_smart_changed(sd);
793}
794
795static void _ewk_view_smart_calculate(Evas_Object* o)
796{
797    EWK_VIEW_SD_GET(o, sd);
798    EWK_VIEW_PRIV_GET(sd, priv);
799    EINA_SAFETY_ON_NULL_RETURN(sd->api->contents_resize);
800    EINA_SAFETY_ON_NULL_RETURN(sd->api->scrolls_process);
801    EINA_SAFETY_ON_NULL_RETURN(sd->api->repaints_process);
802    Evas_Coord x, y, w, h;
803
804    sd->changed.any = EINA_FALSE;
805
806    if (!sd->main_frame || !priv->main_frame)
807        return;
808
809    evas_object_geometry_get(o, &x, &y, &w, &h);
810
811    DBG("o=%p geo=[%d, %d + %dx%d], changed: size=%hhu, "
812        "scrolls=%zu, repaints=%zu",
813        o, x, y, w, h, sd->changed.size,
814        priv->scrolls.count, priv->repaints.count);
815
816    if (sd->changed.size && ((w != sd->view.w) || (h != sd->view.h))) {
817        WebCore::FrameView* view = priv->main_frame->view();
818        if (view) {
819            view->resize(w, h);
820            view->forceLayout();
821            view->adjustViewSize();
822        }
823        evas_object_resize(sd->main_frame, w, h);
824        evas_object_resize(sd->events_rect, w, h);
825        sd->changed.frame_rect = EINA_TRUE;
826        sd->view.w = w;
827        sd->view.h = h;
828
829        // This callback is a good place e.g. to change fixed layout size (ewk_view_fixed_layout_size_set).
830        evas_object_smart_callback_call(o, "view,resized", 0);
831    }
832    sd->changed.size = EINA_FALSE;
833
834    if (sd->changed.position && ((x != sd->view.x) || (y != sd->view.y))) {
835        evas_object_move(sd->main_frame, x, y);
836        evas_object_move(sd->backing_store, x, y);
837        evas_object_move(sd->events_rect, x, y);
838        sd->changed.frame_rect = EINA_TRUE;
839        sd->view.x = x;
840        sd->view.y = y;
841    }
842    sd->changed.position = EINA_FALSE;
843
844    ewk_view_layout_if_needed_recursive(sd->_priv);
845
846    if (!sd->api->scrolls_process(sd))
847        ERR("failed to process scrolls.");
848    _ewk_view_scrolls_flush(priv);
849
850    if (!sd->api->repaints_process(sd))
851        ERR("failed to process repaints.");
852    _ewk_view_repaints_flush(priv);
853
854    if (sd->changed.frame_rect) {
855        WebCore::FrameView* view = priv->main_frame->view();
856        view->frameRectsChanged(); /* force tree to get position from root */
857        sd->changed.frame_rect = EINA_FALSE;
858    }
859}
860
861static void _ewk_view_smart_show(Evas_Object *o)
862{
863    EWK_VIEW_SD_GET(o, sd);
864
865    if (evas_object_clipees_get(sd->base.clipper))
866        evas_object_show(sd->base.clipper);
867    evas_object_show(sd->backing_store);
868}
869
870static void _ewk_view_smart_hide(Evas_Object *o)
871{
872    EWK_VIEW_SD_GET(o, sd);
873
874    evas_object_hide(sd->base.clipper);
875    evas_object_hide(sd->backing_store);
876}
877
878static Eina_Bool _ewk_view_smart_contents_resize(Ewk_View_Smart_Data* sd, int w, int h)
879{
880    return EINA_TRUE;
881}
882
883static Eina_Bool _ewk_view_smart_zoom_set(Ewk_View_Smart_Data* sd, float zoom, Evas_Coord cx, Evas_Coord cy)
884{
885    double px, py;
886    Evas_Coord x, y, w, h;
887    Eina_Bool ret;
888
889    ewk_frame_scroll_size_get(sd->main_frame, &w, &h);
890    ewk_frame_scroll_pos_get(sd->main_frame, &x, &y);
891
892    if (w + sd->view.w > 0)
893        px = (double)(x + cx) / (w + sd->view.w);
894    else
895        px = 0.0;
896
897    if (h + sd->view.h > 0)
898        py = (double)(y + cy) / (h + sd->view.h);
899    else
900        py = 0.0;
901
902    ret = ewk_frame_zoom_set(sd->main_frame, zoom);
903
904    ewk_frame_scroll_size_get(sd->main_frame, &w, &h);
905    x = (w + sd->view.w) * px - cx;
906    y = (h + sd->view.h) * py - cy;
907    ewk_frame_scroll_set(sd->main_frame, x, y);
908    return ret;
909}
910
911static void _ewk_view_smart_flush(Ewk_View_Smart_Data* sd)
912{
913    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv);
914    _ewk_view_repaints_flush(priv);
915    _ewk_view_scrolls_flush(priv);
916}
917
918static Eina_Bool _ewk_view_smart_pre_render_region(Ewk_View_Smart_Data* sd, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h, float zoom)
919{
920    WRN("not supported by engine. sd=%p area=%d,%d+%dx%d, zoom=%f",
921        sd, x, y, w, h, zoom);
922    return EINA_FALSE;
923}
924
925static Eina_Bool _ewk_view_smart_pre_render_relative_radius(Ewk_View_Smart_Data* sd, unsigned int n, float zoom)
926{
927    WRN("not supported by engine. sd=%p, n=%u zoom=%f",
928        sd, n, zoom);
929    return EINA_FALSE;
930}
931
932static void _ewk_view_smart_pre_render_cancel(Ewk_View_Smart_Data* sd)
933{
934    WRN("not supported by engine. sd=%p", sd);
935}
936
937static void _ewk_view_zoom_animated_mark_stop(Ewk_View_Smart_Data* sd)
938{
939    sd->animated_zoom.zoom.start = 0.0;
940    sd->animated_zoom.zoom.end = 0.0;
941    sd->animated_zoom.zoom.current = 0.0;
942}
943
944static void _ewk_view_zoom_animated_finish(Ewk_View_Smart_Data* sd)
945{
946    EWK_VIEW_PRIV_GET(sd, priv);
947    ecore_animator_del(priv->animated_zoom.animator);
948    priv->animated_zoom.animator = 0;
949    _ewk_view_zoom_animated_mark_stop(sd);
950    evas_object_smart_callback_call(sd->self, "zoom,animated,end", 0);
951}
952
953static float _ewk_view_zoom_animated_current(Ewk_View_Private_Data* priv)
954{
955    double now = ecore_loop_time_get();
956    double delta = now - priv->animated_zoom.time.start;
957
958    if (delta > priv->animated_zoom.time.duration)
959        delta = priv->animated_zoom.time.duration;
960    if (delta < 0.0) // time went back, clock adjusted?
961        delta = 0.0;
962
963    delta /= priv->animated_zoom.time.duration;
964
965    return ((priv->animated_zoom.zoom.range * delta)
966            + priv->animated_zoom.zoom.start);
967}
968
969static Eina_Bool _ewk_view_zoom_animator_cb(void* data)
970{
971    Ewk_View_Smart_Data* sd = (Ewk_View_Smart_Data*)data;
972    Evas_Coord cx, cy;
973    EWK_VIEW_PRIV_GET(sd, priv);
974    double now = ecore_loop_time_get();
975
976    cx = priv->animated_zoom.center.x;
977    cy = priv->animated_zoom.center.y;
978
979    // TODO: progressively center (cx, cy) -> (view.x + view.h/2, view.y + view.h/2)
980    if (cx >= sd->view.w)
981        cx = sd->view.w - 1;
982    if (cy >= sd->view.h)
983        cy = sd->view.h - 1;
984
985    if ((now >= priv->animated_zoom.time.end)
986        || (now < priv->animated_zoom.time.start)) {
987        _ewk_view_zoom_animated_finish(sd);
988        ewk_view_zoom_set(sd->self, priv->animated_zoom.zoom.end, cx, cy);
989        sd->api->sc.calculate(sd->self);
990        return EINA_FALSE;
991    }
992
993    sd->animated_zoom.zoom.current = _ewk_view_zoom_animated_current(priv);
994    sd->api->zoom_weak_set(sd, sd->animated_zoom.zoom.current, cx, cy);
995    return EINA_TRUE;
996}
997
998static void _ewk_view_zoom_animation_start(Ewk_View_Smart_Data* sd)
999{
1000    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv);
1001    if (priv->animated_zoom.animator)
1002        return;
1003    priv->animated_zoom.animator = ecore_animator_add
1004        (_ewk_view_zoom_animator_cb, sd);
1005}
1006
1007static WebCore::ViewportAttributes _ewk_view_viewport_attributes_compute(Evas_Object* o)
1008{
1009    EWK_VIEW_SD_GET(o, sd);
1010    EWK_VIEW_PRIV_GET(sd, priv);
1011
1012    int desktop_width = 980;
1013    int device_dpi = ewk_view_dpi_get();
1014
1015    int available_width = (int) priv->page->chrome()->client()->pageRect().width();
1016    int available_height = (int) priv->page->chrome()->client()->pageRect().height();
1017
1018    int device_width = (int) priv->page->chrome()->client()->windowRect().width();
1019    int device_height = (int) priv->page->chrome()->client()->windowRect().height();
1020
1021    WebCore::IntSize available_size = WebCore::IntSize(available_width, available_height);
1022    WebCore::ViewportAttributes attributes = WebCore::computeViewportAttributes(priv->viewport_arguments, desktop_width, device_width, device_height, device_dpi, available_size);
1023
1024    return attributes;
1025}
1026
1027static Eina_Bool _ewk_view_smart_disable_render(Ewk_View_Smart_Data *sd)
1028{
1029    WRN("not supported by engine. sd=%p", sd);
1030    return EINA_FALSE;
1031}
1032
1033static Eina_Bool _ewk_view_smart_enable_render(Ewk_View_Smart_Data *sd)
1034{
1035    WRN("not supported by engine. sd=%p", sd);
1036    return EINA_FALSE;
1037}
1038
1039/**
1040 * Sets the smart class api without any backing store, enabling view
1041 * to be inherited.
1042 *
1043 * @param api class definition to be set, all members with the
1044 *        exception of Evas_Smart_Class->data may be overridden. Must
1045 *        @b not be @c 0.
1046 *
1047 * @note Evas_Smart_Class->data is used to implement type checking and
1048 *       is not supposed to be changed/overridden. If you need extra
1049 *       data for your smart class to work, just extend
1050 *       Ewk_View_Smart_Class instead.
1051 *
1052 * @return @c EINA_TRUE on success, @c EINA_FALSE on failure (probably
1053 *         version mismatch).
1054 *
1055 * @see ewk_view_single_smart_set()
1056 * @see ewk_view_tiled_smart_set()
1057 */
1058Eina_Bool ewk_view_base_smart_set(Ewk_View_Smart_Class* api)
1059{
1060    EINA_SAFETY_ON_NULL_RETURN_VAL(api, EINA_FALSE);
1061
1062    if (api->version != EWK_VIEW_SMART_CLASS_VERSION) {
1063        EINA_LOG_CRIT
1064            ("Ewk_View_Smart_Class %p is version %lu while %lu was expected.",
1065             api, api->version, EWK_VIEW_SMART_CLASS_VERSION);
1066        return EINA_FALSE;
1067    }
1068
1069    if (EINA_UNLIKELY(!_parent_sc.add))
1070        evas_object_smart_clipped_smart_set(&_parent_sc);
1071
1072    evas_object_smart_clipped_smart_set(&api->sc);
1073    api->sc.add = _ewk_view_smart_add;
1074    api->sc.del = _ewk_view_smart_del;
1075    api->sc.resize = _ewk_view_smart_resize;
1076    api->sc.move = _ewk_view_smart_move;
1077    api->sc.calculate = _ewk_view_smart_calculate;
1078    api->sc.show = _ewk_view_smart_show;
1079    api->sc.hide = _ewk_view_smart_hide;
1080    api->sc.data = EWK_VIEW_TYPE_STR; /* used by type checking */
1081
1082    api->contents_resize = _ewk_view_smart_contents_resize;
1083    api->zoom_set = _ewk_view_smart_zoom_set;
1084    api->flush = _ewk_view_smart_flush;
1085    api->pre_render_region = _ewk_view_smart_pre_render_region;
1086    api->pre_render_relative_radius = _ewk_view_smart_pre_render_relative_radius;
1087    api->pre_render_cancel = _ewk_view_smart_pre_render_cancel;
1088    api->disable_render = _ewk_view_smart_disable_render;
1089    api->enable_render = _ewk_view_smart_enable_render;
1090
1091    api->focus_in = _ewk_view_smart_focus_in;
1092    api->focus_out = _ewk_view_smart_focus_out;
1093    api->mouse_wheel = _ewk_view_smart_mouse_wheel;
1094    api->mouse_down = _ewk_view_smart_mouse_down;
1095    api->mouse_up = _ewk_view_smart_mouse_up;
1096    api->mouse_move = _ewk_view_smart_mouse_move;
1097    api->key_down = _ewk_view_smart_key_down;
1098    api->key_up = _ewk_view_smart_key_up;
1099
1100    api->add_console_message = _ewk_view_smart_add_console_message;
1101    api->run_javascript_alert = _ewk_view_smart_run_javascript_alert;
1102    api->run_javascript_confirm = _ewk_view_smart_run_javascript_confirm;
1103    api->run_javascript_prompt = _ewk_view_smart_run_javascript_prompt;
1104    api->should_interrupt_javascript = _ewk_view_smart_should_interrupt_javascript;
1105
1106    return EINA_TRUE;
1107}
1108
1109/**
1110 * Set a fixed layout size to be used, dissociating it from viewport size.
1111 *
1112 * Setting a width different than zero enables fixed layout on that
1113 * size. It's automatically scaled based on zoom, but will not change
1114 * if viewport changes.
1115 *
1116 * Setting both @a w and @a h to zero will disable fixed layout.
1117 *
1118 * @param o view object to change fixed layout.
1119 * @param w fixed width to use. This size will be automatically scaled
1120 *        based on zoom level.
1121 * @param h fixed height to use. This size will be automatically scaled
1122 *        based on zoom level.
1123 */
1124void ewk_view_fixed_layout_size_set(Evas_Object* o, Evas_Coord w, Evas_Coord h)
1125{
1126    EWK_VIEW_SD_GET_OR_RETURN(o, sd);
1127    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv);
1128
1129    WebCore::FrameView* view = sd->_priv->main_frame->view();
1130    if (w <= 0 && h <= 0) {
1131        if (!priv->fixed_layout.use)
1132            return;
1133        priv->fixed_layout.w = 0;
1134        priv->fixed_layout.h = 0;
1135        priv->fixed_layout.use = EINA_FALSE;
1136    } else {
1137        if (priv->fixed_layout.use
1138            && priv->fixed_layout.w == w && priv->fixed_layout.h == h)
1139            return;
1140        priv->fixed_layout.w = w;
1141        priv->fixed_layout.h = h;
1142        priv->fixed_layout.use = EINA_TRUE;
1143
1144        if (view)
1145            view->setFixedLayoutSize(WebCore::IntSize(w, h));
1146    }
1147
1148    if (!view)
1149        return;
1150    view->setUseFixedLayout(priv->fixed_layout.use);
1151    view->forceLayout();
1152}
1153
1154/**
1155 * Get fixed layout size in use.
1156 *
1157 * @param o view object to query fixed layout size.
1158 * @param w where to return width. Returns 0 on error or if no fixed
1159 *        layout in use.
1160 * @param h where to return height. Returns 0 on error or if no fixed
1161 *        layout in use.
1162 */
1163void ewk_view_fixed_layout_size_get(Evas_Object* o, Evas_Coord* w, Evas_Coord* h)
1164{
1165    if (w)
1166        *w = 0;
1167    if (h)
1168        *h = 0;
1169    EWK_VIEW_SD_GET_OR_RETURN(o, sd);
1170    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv);
1171    if (priv->fixed_layout.use) {
1172        if (w)
1173            *w = priv->fixed_layout.w;
1174        if (h)
1175            *h = priv->fixed_layout.h;
1176    }
1177}
1178
1179/**
1180 * Set the theme path to be used by this view.
1181 *
1182 * This also sets the theme on the main frame. As frames inherit theme
1183 * from their parent, this will have all frames with unset theme to
1184 * use this one.
1185 *
1186 * @param o view object to change theme.
1187 * @param path theme path, may be @c 0 to reset to default.
1188 */
1189void ewk_view_theme_set(Evas_Object* o, const char* path)
1190{
1191    EWK_VIEW_SD_GET_OR_RETURN(o, sd);
1192    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv);
1193    if (!eina_stringshare_replace(&priv->settings.theme, path))
1194        return;
1195    ewk_frame_theme_set(sd->main_frame, path);
1196}
1197
1198/**
1199 * Gets the theme set on this frame.
1200 *
1201 * This returns the value set by ewk_view_theme_set().
1202 *
1203 * @param o view object to get theme path.
1204 *
1205 * @return theme path, may be @c 0 if not set.
1206 */
1207const char* ewk_view_theme_get(Evas_Object* o)
1208{
1209    EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
1210    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
1211    return priv->settings.theme;
1212}
1213
1214/**
1215 * Get the object that represents the main frame.
1216 *
1217 * @param o view object to get main frame.
1218 *
1219 * @return ewk_frame object or @c 0 if none yet.
1220 */
1221Evas_Object* ewk_view_frame_main_get(const Evas_Object* o)
1222{
1223    EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
1224    return sd->main_frame;
1225}
1226
1227/**
1228 * Get the currently focused frame object.
1229 *
1230 * @param o view object to get focused frame.
1231 *
1232 * @return ewk_frame object or @c 0 if none yet.
1233 */
1234Evas_Object* ewk_view_frame_focused_get(const Evas_Object* o)
1235{
1236    EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
1237    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
1238
1239    WebCore::Frame* core = priv->page->focusController()->focusedFrame();
1240    if (!core)
1241        return 0;
1242
1243    WebCore::FrameLoaderClientEfl* client = static_cast<WebCore::FrameLoaderClientEfl*>(core->loader()->client());
1244    if (!client)
1245        return 0;
1246    return client->webFrame();
1247}
1248
1249/**
1250 * Ask main frame to load the given URI.
1251 *
1252 * @param o view object to load uri.
1253 * @param uri uniform resource identifier to load.
1254 *
1255 * @return @c EINA_TRUE on successful request, @c EINA_FALSE on failure.
1256 *         Note that it means the request was done, not that it was
1257 *         satisfied.
1258 */
1259Eina_Bool ewk_view_uri_set(Evas_Object* o, const char* uri)
1260{
1261    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1262    return ewk_frame_uri_set(sd->main_frame, uri);
1263}
1264
1265/**
1266 * Get the current uri loaded by main frame.
1267 *
1268 * @param o view object to get current uri.
1269 *
1270 * @return current uri reference or @c 0. It's internal, don't change.
1271 */
1272const char* ewk_view_uri_get(const Evas_Object* o)
1273{
1274    EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
1275    return ewk_frame_uri_get(sd->main_frame);
1276}
1277
1278/**
1279 * Get the current title of main frame.
1280 *
1281 * @param o view object to get current title.
1282 *
1283 * @return current title reference or @c 0. It's internal, don't change.
1284 */
1285const char* ewk_view_title_get(const Evas_Object* o)
1286{
1287    EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
1288    return ewk_frame_title_get(sd->main_frame);
1289}
1290
1291/**
1292 * Gets if main frame is editable.
1293 *
1294 * @param o view object to get editable state.
1295 *
1296 * @return @c EINA_TRUE if editable, @c EINA_FALSE otherwise.
1297 */
1298Eina_Bool ewk_view_editable_get(const Evas_Object* o)
1299{
1300    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1301    return ewk_frame_editable_get(sd->main_frame);
1302}
1303
1304/**
1305 * Set background color and transparency
1306 *
1307 * Just as in Evas, colors are pre-multiplied, so 50% red is
1308 * (128, 0, 0, 128) and not (255, 0, 0, 128)!
1309 *
1310 * @warning Watch out performance issues with transparency! Object
1311 *          will be handled as transparent image by evas even if the
1312 *          webpage specifies a background color. That mean you'll pay
1313 *          a price even if it's not really transparent, thus
1314 *          scrolling/panning and zooming will be likely slower than
1315 *          if transparency is off.
1316 *
1317 * @param o view object to change.
1318 * @param r red component.
1319 * @param g green component.
1320 * @param b blue component.
1321 * @param a transparency.
1322 */
1323void ewk_view_bg_color_set(Evas_Object* o, int r, int g, int b, int a)
1324{
1325    EWK_VIEW_SD_GET_OR_RETURN(o, sd);
1326    EINA_SAFETY_ON_NULL_RETURN(sd->api);
1327    EINA_SAFETY_ON_NULL_RETURN(sd->api->bg_color_set);
1328
1329    if (a < 0) {
1330        WRN("Alpha less than zero (%d).", a);
1331        a = 0;
1332    } else if (a > 255) {
1333        WRN("Alpha is larger than 255 (%d).", a);
1334        a = 255;
1335    }
1336
1337#define CHECK_PREMUL_COLOR(c, a)                                        \
1338    if (c < 0) {                                                        \
1339        WRN("Color component "#c" is less than zero (%d).", c);         \
1340        c = 0;                                                          \
1341    } else if (c > a) {                                                 \
1342        WRN("Color component "#c" is greater than alpha (%d, alpha=%d).", \
1343            c, a);                                                      \
1344        c = a;                                                          \
1345    }
1346    CHECK_PREMUL_COLOR(r, a);
1347    CHECK_PREMUL_COLOR(g, a);
1348    CHECK_PREMUL_COLOR(b, a);
1349#undef CHECK_PREMUL_COLOR
1350
1351    sd->bg_color.r = r;
1352    sd->bg_color.g = g;
1353    sd->bg_color.b = b;
1354    sd->bg_color.a = a;
1355
1356    sd->api->bg_color_set(sd, r, g, b, a);
1357
1358    WebCore::FrameView* view = sd->_priv->main_frame->view();
1359    if (view) {
1360        WebCore::Color color;
1361
1362        if (!a)
1363            color = WebCore::Color(0, 0, 0, 0);
1364        else if (a == 255)
1365            color = WebCore::Color(r, g, b, a);
1366        else
1367            color = WebCore::Color(r * 255 / a, g * 255 / a, b * 255 / a, a);
1368
1369        view->updateBackgroundRecursively(color, !a);
1370    }
1371}
1372
1373/**
1374 * Query if view object background color.
1375 *
1376 * Just as in Evas, colors are pre-multiplied, so 50% red is
1377 * (128, 0, 0, 128) and not (255, 0, 0, 128)!
1378 *
1379 * @param o view object to query.
1380 * @param r where to return red color component.
1381 * @param g where to return green color component.
1382 * @param b where to return blue color component.
1383 * @param a where to return alpha value.
1384 */
1385void ewk_view_bg_color_get(const Evas_Object* o, int* r, int* g, int* b, int* a)
1386{
1387    if (r)
1388        *r = 0;
1389    if (g)
1390        *g = 0;
1391    if (b)
1392        *b = 0;
1393    if (a)
1394        *a = 0;
1395    EWK_VIEW_SD_GET_OR_RETURN(o, sd);
1396    if (r)
1397        *r = sd->bg_color.r;
1398    if (g)
1399        *g = sd->bg_color.g;
1400    if (b)
1401        *b = sd->bg_color.b;
1402    if (a)
1403        *a = sd->bg_color.a;
1404}
1405
1406/**
1407 * Search the given text string in document.
1408 *
1409 * @param o view object where to search text.
1410 * @param string reference string to search.
1411 * @param case_sensitive if search should be case sensitive or not.
1412 * @param forward if search is from cursor and on or backwards.
1413 * @param wrap if search should wrap at end.
1414 *
1415 * @return @c EINA_TRUE if found, @c EINA_FALSE if not or failure.
1416 */
1417Eina_Bool ewk_view_text_search(const Evas_Object* o, const char* string, Eina_Bool case_sensitive, Eina_Bool forward, Eina_Bool wrap)
1418{
1419    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1420    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
1421    EINA_SAFETY_ON_NULL_RETURN_VAL(string, EINA_FALSE);
1422    WTF::TextCaseSensitivity sensitive;
1423    WebCore::FindDirection direction;
1424
1425    if (case_sensitive)
1426        sensitive = WTF::TextCaseSensitive;
1427    else
1428        sensitive = WTF::TextCaseInsensitive;
1429
1430    if (forward)
1431        direction = WebCore::FindDirectionForward;
1432    else
1433        direction = WebCore::FindDirectionBackward;
1434
1435    return priv->page->findString(String::fromUTF8(string), sensitive, direction, wrap);
1436}
1437
1438/**
1439 * Mark matches the given text string in document.
1440 *
1441 * @param o view object where to search text.
1442 * @param string reference string to match.
1443 * @param case_sensitive if match should be case sensitive or not.
1444 * @param highlight if matches should be highlighted.
1445 * @param limit maximum amount of matches, or zero to unlimited.
1446 *
1447 * @return number of matches.
1448 */
1449unsigned int ewk_view_text_matches_mark(Evas_Object* o, const char* string, Eina_Bool case_sensitive, Eina_Bool highlight, unsigned int limit)
1450{
1451    EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
1452    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
1453    EINA_SAFETY_ON_NULL_RETURN_VAL(string, 0);
1454    WTF::TextCaseSensitivity sensitive;
1455
1456    if (case_sensitive)
1457        sensitive = WTF::TextCaseSensitive;
1458    else
1459        sensitive = WTF::TextCaseInsensitive;
1460
1461    return priv->page->markAllMatchesForText(String::fromUTF8(string), sensitive, highlight, limit);
1462}
1463
1464/**
1465 * Reverses the effect of ewk_view_text_matches_mark()
1466 *
1467 * @param o view object where to search text.
1468 *
1469 * @return @c EINA_TRUE on success, @c EINA_FALSE for failure.
1470 */
1471Eina_Bool ewk_view_text_matches_unmark_all(Evas_Object* o)
1472{
1473    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1474    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
1475    priv->page->unmarkAllTextMatches();
1476    return EINA_TRUE;
1477}
1478
1479/**
1480 * Set if should highlight matches marked with ewk_view_text_matches_mark().
1481 *
1482 * @param o view object where to set if matches are highlighted or not.
1483 * @param highlight if @c EINA_TRUE, matches will be highlighted.
1484 *
1485 * @return @c EINA_TRUE on success, @c EINA_FALSE for failure.
1486 */
1487Eina_Bool ewk_view_text_matches_highlight_set(Evas_Object* o, Eina_Bool highlight)
1488{
1489    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1490    return ewk_frame_text_matches_highlight_set(sd->main_frame, highlight);
1491}
1492
1493/**
1494 * Get if should highlight matches marked with ewk_view_text_matches_mark().
1495 *
1496 * @param o view object to query if matches are highlighted or not.
1497 *
1498 * @return @c EINA_TRUE if they are highlighted, @c EINA_FALSE otherwise.
1499 */
1500Eina_Bool ewk_view_text_matches_highlight_get(const Evas_Object* o)
1501{
1502    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1503    return ewk_frame_text_matches_highlight_get(sd->main_frame);
1504}
1505
1506/**
1507 * Sets if main frame is editable.
1508 *
1509 * @param o view object to set editable state.
1510 * @param editable new state.
1511 *
1512 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1513 */
1514Eina_Bool ewk_view_editable_set(Evas_Object* o, Eina_Bool editable)
1515{
1516    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1517    return ewk_frame_editable_set(sd->main_frame, editable);
1518}
1519
1520/**
1521 * Get the copy of the selection text.
1522 *
1523 * @param o view object to get selection text.
1524 *
1525 * @return newly allocated string or @c 0 if nothing is selected or failure.
1526 */
1527char* ewk_view_selection_get(const Evas_Object* o)
1528{
1529    EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
1530    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
1531    CString s = priv->page->focusController()->focusedOrMainFrame()->editor()->selectedText().utf8();
1532    if (s.isNull())
1533        return 0;
1534    return strdup(s.data());
1535}
1536
1537static Eina_Bool _ewk_view_editor_command(Ewk_View_Private_Data* priv, const char* command)
1538{
1539    return priv->page->focusController()->focusedOrMainFrame()->editor()->command(String::fromUTF8(command)).execute();
1540}
1541
1542/**
1543 * Unselects whatever was selected.
1544 *
1545 * @return @c EINA_TRUE if operation was executed, @c EINA_FALSE otherwise.
1546 */
1547Eina_Bool ewk_view_select_none(Evas_Object* o)
1548{
1549    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1550    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
1551    return _ewk_view_editor_command(priv, "Unselect");
1552}
1553
1554/**
1555 * Selects everything.
1556 *
1557 * @return @c EINA_TRUE if operation was executed, @c EINA_FALSE otherwise.
1558 */
1559Eina_Bool ewk_view_select_all(Evas_Object* o)
1560{
1561    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1562    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
1563    return _ewk_view_editor_command(priv, "SelectAll");
1564}
1565
1566/**
1567 * Selects the current paragrah.
1568 *
1569 * @return @c EINA_TRUE if operation was executed, @c EINA_FALSE otherwise.
1570 */
1571Eina_Bool ewk_view_select_paragraph(Evas_Object* o)
1572{
1573    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1574    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
1575    return _ewk_view_editor_command(priv, "SelectParagraph");
1576}
1577
1578/**
1579 * Selects the current sentence.
1580 *
1581 * @return @c EINA_TRUE if operation was executed, @c EINA_FALSE otherwise.
1582 */
1583Eina_Bool ewk_view_select_sentence(Evas_Object* o)
1584{
1585    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1586    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
1587    return _ewk_view_editor_command(priv, "SelectSentence");
1588}
1589
1590/**
1591 * Selects the current line.
1592 *
1593 * @return @c EINA_TRUE if operation was executed, @c EINA_FALSE otherwise.
1594 */
1595Eina_Bool ewk_view_select_line(Evas_Object* o)
1596{
1597    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1598    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
1599    return _ewk_view_editor_command(priv, "SelectLine");
1600}
1601
1602/**
1603 * Selects the current word.
1604 *
1605 * @return @c EINA_TRUE if operation was executed, @c EINA_FALSE otherwise.
1606 */
1607Eina_Bool ewk_view_select_word(Evas_Object* o)
1608{
1609    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1610    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
1611    return _ewk_view_editor_command(priv, "SelectWord");
1612}
1613
1614#if ENABLE(CONTEXT_MENUS)
1615
1616/**
1617 * Forwards a request of new Context Menu to WebCore.
1618 *
1619 * @param o View.
1620 * @param ev Event data.
1621 *
1622 * @return @c EINA_TRUE if operation was executed, @c EINA_FALSE otherwise.
1623 */
1624Eina_Bool ewk_view_context_menu_forward_event(Evas_Object* o, const Evas_Event_Mouse_Down* ev)
1625{
1626    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1627    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
1628    Eina_Bool mouse_press_handled = EINA_FALSE;
1629
1630    priv->page->contextMenuController()->clearContextMenu();
1631    WebCore::Frame* main_frame = priv->page->mainFrame();
1632    Evas_Coord x, y;
1633    evas_object_geometry_get(sd->self, &x, &y, 0, 0);
1634
1635    WebCore::PlatformMouseEvent event(ev, WebCore::IntPoint(x, y));
1636
1637    if (main_frame->view()) {
1638        mouse_press_handled =
1639            main_frame->eventHandler()->handleMousePressEvent(event);
1640    }
1641
1642    if (main_frame->eventHandler()->sendContextMenuEvent(event))
1643        return EINA_FALSE;
1644
1645    WebCore::ContextMenu* coreMenu =
1646        priv->page->contextMenuController()->contextMenu();
1647    if (!coreMenu) {
1648        // WebCore decided not to create a context menu, return true if event
1649        // was handled by handleMouseReleaseEvent
1650        return mouse_press_handled;
1651    }
1652
1653    return EINA_TRUE;
1654}
1655
1656#endif
1657
1658/**
1659 * Get current load progress estimate from 0.0 to 1.0.
1660 *
1661 * @param o view object to get current progress.
1662 *
1663 * @return progres value from 0.0 to 1.0 or -1.0 on error.
1664 */
1665double ewk_view_load_progress_get(const Evas_Object* o)
1666{
1667    EWK_VIEW_SD_GET_OR_RETURN(o, sd, -1.0);
1668    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, -1.0);
1669    return priv->page->progress()->estimatedProgress();
1670}
1671
1672/**
1673 * Ask main frame to stop loading.
1674 *
1675 * @param o view object to stop loading.
1676 *
1677 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1678 *
1679 * @see ewk_frame_stop()
1680 */
1681Eina_Bool ewk_view_stop(Evas_Object* o)
1682{
1683    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1684    return ewk_frame_stop(sd->main_frame);
1685}
1686
1687/**
1688 * Ask main frame to reload current document.
1689 *
1690 * @param o view object to reload.
1691 *
1692 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1693 *
1694 * @see ewk_frame_reload()
1695 */
1696Eina_Bool ewk_view_reload(Evas_Object* o)
1697{
1698    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1699    return ewk_frame_reload(sd->main_frame);
1700}
1701
1702/**
1703 * Ask main frame to fully reload current document, using no caches.
1704 *
1705 * @param o view object to reload.
1706 *
1707 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1708 *
1709 * @see ewk_frame_reload_full()
1710 */
1711Eina_Bool ewk_view_reload_full(Evas_Object* o)
1712{
1713    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1714    return ewk_frame_reload_full(sd->main_frame);
1715}
1716
1717/**
1718 * Ask main frame to navigate back in history.
1719 *
1720 * @param o view object to navigate back.
1721 *
1722 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1723 *
1724 * @see ewk_frame_back()
1725 */
1726Eina_Bool ewk_view_back(Evas_Object* o)
1727{
1728    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1729    return ewk_frame_back(sd->main_frame);
1730}
1731
1732/**
1733 * Ask main frame to navigate forward in history.
1734 *
1735 * @param o view object to navigate forward.
1736 *
1737 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1738 *
1739 * @see ewk_frame_forward()
1740 */
1741Eina_Bool ewk_view_forward(Evas_Object* o)
1742{
1743    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1744    return ewk_frame_forward(sd->main_frame);
1745}
1746
1747/**
1748 * Navigate back or forward in history.
1749 *
1750 * @param o view object to navigate.
1751 * @param steps if positive navigates that amount forwards, if negative
1752 *        does backwards.
1753 *
1754 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1755 *
1756 * @see ewk_frame_navigate()
1757 */
1758Eina_Bool ewk_view_navigate(Evas_Object* o, int steps)
1759{
1760    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1761    return ewk_frame_navigate(sd->main_frame, steps);
1762}
1763
1764/**
1765 * Check if it is possible to navigate backwards one item in history.
1766 *
1767 * @param o view object to check if backward navigation is possible.
1768 *
1769 * @return @c EINA_TRUE if possible, @c EINA_FALSE otherwise.
1770 *
1771 * @see ewk_view_navigate_possible()
1772 */
1773Eina_Bool ewk_view_back_possible(Evas_Object* o)
1774{
1775    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1776    return ewk_frame_back_possible(sd->main_frame);
1777}
1778
1779/**
1780 * Check if it is possible to navigate forwards one item in history.
1781 *
1782 * @param o view object to check if forward navigation is possible.
1783 *
1784 * @return @c EINA_TRUE if possible, @c EINA_FALSE otherwise.
1785 *
1786 * @see ewk_view_navigate_possible()
1787 */
1788Eina_Bool ewk_view_forward_possible(Evas_Object* o)
1789{
1790    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1791    return ewk_frame_forward_possible(sd->main_frame);
1792}
1793
1794/**
1795 * Check if it is possible to navigate given @a steps in history.
1796 *
1797 * @param o view object to navigate.
1798 * @param steps if positive navigates that amount forwards, if negative
1799 *        does backwards.
1800 *
1801 * @return @c EINA_TRUE if possible, @c EINA_FALSE otherwise.
1802 */
1803Eina_Bool ewk_view_navigate_possible(Evas_Object* o, int steps)
1804{
1805    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1806    return ewk_frame_navigate_possible(sd->main_frame, steps);
1807}
1808
1809/**
1810 * Check if navigation history (back-forward lists) is enabled.
1811 *
1812 * @param o view object to check if navigation history is enabled.
1813 *
1814 * @return @c EINA_TRUE if view keeps history, @c EINA_FALSE otherwise.
1815 */
1816Eina_Bool ewk_view_history_enable_get(const Evas_Object* o)
1817{
1818    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1819    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
1820    return static_cast<WebCore::BackForwardListImpl*>(priv->page->backForwardList())->enabled();
1821}
1822
1823/**
1824 * Sets if navigation history (back-forward lists) is enabled.
1825 *
1826 * @param o view object to set if navigation history is enabled.
1827 * @param enable @c EINA_TRUE if we want to enable navigation history;
1828 * @c EINA_FALSE otherwise.
1829 *
1830 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1831 */
1832Eina_Bool ewk_view_history_enable_set(Evas_Object* o, Eina_Bool enable)
1833{
1834    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1835    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
1836    static_cast<WebCore::BackForwardListImpl*>(priv->page->backForwardList())->setEnabled(enable);
1837    return EINA_TRUE;
1838}
1839
1840/**
1841 * Gets the history (back-forward list) associated with this view.
1842 *
1843 * @param o view object to get navigation history from.
1844 *
1845 * @return returns the history instance handle associated with this
1846 *         view or @c 0 on errors (including when history is not
1847 *         enabled with ewk_view_history_enable_set()). This instance
1848 *         is unique for this view and thus multiple calls to this
1849 *         function with the same view as parameter returns the same
1850 *         handle. This handle is alive while view is alive, thus one
1851 *         might want to listen for EVAS_CALLBACK_DEL on given view
1852 *         (@a o) to know when to stop using returned handle.
1853 *
1854 * @see ewk_view_history_enable_set()
1855 */
1856Ewk_History* ewk_view_history_get(const Evas_Object* o)
1857{
1858    EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
1859    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
1860    if (!static_cast<WebCore::BackForwardListImpl*>(priv->page->backForwardList())->enabled()) {
1861        ERR("asked history, but it's disabled! Returning 0!");
1862        return 0;
1863    }
1864    return priv->history;
1865}
1866
1867/**
1868 * Get the current zoom level of main frame.
1869 *
1870 * @param o view object to query zoom level.
1871 *
1872 * @return current zoom level in use or -1.0 on error.
1873 */
1874float ewk_view_zoom_get(const Evas_Object* o)
1875{
1876    EWK_VIEW_SD_GET_OR_RETURN(o, sd, -1.0);
1877    return ewk_frame_zoom_get(sd->main_frame);
1878}
1879
1880/**
1881 * Set the current zoom level of main frame.
1882 *
1883 * @param o view object to set zoom level.
1884 * @param zoom new level to use.
1885 * @param cx x of center coordinate
1886 * @param cy y of center coordinate
1887 *
1888 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1889 */
1890Eina_Bool ewk_view_zoom_set(Evas_Object* o, float zoom, Evas_Coord cx, Evas_Coord cy)
1891{
1892    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1893    EWK_VIEW_PRIV_GET(sd, priv);
1894
1895    EINA_SAFETY_ON_NULL_RETURN_VAL(sd->api, EINA_FALSE);
1896    EINA_SAFETY_ON_NULL_RETURN_VAL(sd->api->zoom_set, EINA_FALSE);
1897
1898    if (!priv->settings.zoom_range.user_scalable) {
1899        WRN("userScalable is false");
1900        return EINA_FALSE;
1901    }
1902
1903    if (zoom < priv->settings.zoom_range.min_scale) {
1904        WRN("zoom level is < %f : %f", (double)priv->settings.zoom_range.min_scale, (double)zoom);
1905        return EINA_FALSE;
1906    }
1907    if (zoom > priv->settings.zoom_range.max_scale) {
1908        WRN("zoom level is > %f : %f", (double)priv->settings.zoom_range.max_scale, (double)zoom);
1909        return EINA_FALSE;
1910    }
1911
1912    if (cx >= sd->view.w)
1913        cx = sd->view.w - 1;
1914    if (cy >= sd->view.h)
1915        cy = sd->view.h - 1;
1916    if (cx < 0)
1917        cx = 0;
1918    if (cy < 0)
1919        cy = 0;
1920    _ewk_view_zoom_animated_mark_stop(sd);
1921    return sd->api->zoom_set(sd, zoom, cx, cy);
1922}
1923
1924Eina_Bool ewk_view_zoom_weak_smooth_scale_get(const Evas_Object* o)
1925{
1926    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1927    return sd->zoom_weak_smooth_scale;
1928}
1929
1930void ewk_view_zoom_weak_smooth_scale_set(Evas_Object* o, Eina_Bool smooth_scale)
1931{
1932    EWK_VIEW_SD_GET_OR_RETURN(o, sd);
1933    smooth_scale = !!smooth_scale;
1934    if (sd->zoom_weak_smooth_scale == smooth_scale)
1935        return;
1936    sd->zoom_weak_smooth_scale = smooth_scale;
1937    EINA_SAFETY_ON_NULL_RETURN(sd->api);
1938    EINA_SAFETY_ON_NULL_RETURN(sd->api->zoom_weak_smooth_scale_set);
1939    sd->api->zoom_weak_smooth_scale_set(sd, smooth_scale);
1940}
1941
1942/**
1943 * Set the current zoom level of backing store, centered at given point.
1944 *
1945 * Unlike ewk_view_zoom_set(), this call do not ask WebKit to render
1946 * at new size, but scale what is already rendered, being much faster
1947 * but worse quality.
1948 *
1949 * Often one should use ewk_view_zoom_animated_set(), it will call the
1950 * same machinery internally.
1951 *
1952 * @note this will set variables used by ewk_view_zoom_animated_set()
1953 *       so sub-classes will not reset internal state on their
1954 *       "calculate" phase. To unset those and enable sub-classes to
1955 *       reset their internal state, call
1956 *       ewk_view_zoom_animated_mark_stop(). Namely, this call will
1957 *       set ewk_view_zoom_animated_mark_start() to actual webkit zoom
1958 *       level, ewk_view_zoom_animated_mark_end() and
1959 *       ewk_view_zoom_animated_mark_current() to given zoom level.
1960 *
1961 * @param o view object to set weak zoom level.
1962 * @param zoom level to scale backing store.
1963 * @param cx horizontal center offset, relative to object (w/2 is middle).
1964 * @param cy vertical center offset, relative to object (h/2 is middle).
1965 *
1966 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1967 */
1968Eina_Bool ewk_view_zoom_weak_set(Evas_Object* o, float zoom, Evas_Coord cx, Evas_Coord cy)
1969{
1970    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1971    EWK_VIEW_PRIV_GET(sd, priv);
1972
1973    EINA_SAFETY_ON_NULL_RETURN_VAL(sd->api, EINA_FALSE);
1974    EINA_SAFETY_ON_NULL_RETURN_VAL(sd->api->zoom_weak_set, EINA_FALSE);
1975
1976    if (!priv->settings.zoom_range.user_scalable) {
1977        WRN("userScalable is false");
1978        return EINA_FALSE;
1979    }
1980
1981    if (zoom < priv->settings.zoom_range.min_scale) {
1982        WRN("zoom level is < %f : %f", (double)priv->settings.zoom_range.min_scale, (double)zoom);
1983        return EINA_FALSE;
1984    }
1985    if (zoom > priv->settings.zoom_range.max_scale) {
1986        WRN("zoom level is > %f : %f", (double)priv->settings.zoom_range.max_scale, (double)zoom);
1987        return EINA_FALSE;
1988    }
1989
1990    if (cx >= sd->view.w)
1991        cx = sd->view.w - 1;
1992    if (cy >= sd->view.h)
1993        cy = sd->view.h - 1;
1994    if (cx < 0)
1995        cx = 0;
1996    if (cy < 0)
1997        cy = 0;
1998
1999    sd->animated_zoom.zoom.start = ewk_frame_zoom_get(sd->main_frame);
2000    sd->animated_zoom.zoom.end = zoom;
2001    sd->animated_zoom.zoom.current = zoom;
2002    return sd->api->zoom_weak_set(sd, zoom, cx, cy);
2003}
2004
2005/**
2006 * Mark internal zoom animation state to given zoom.
2007 *
2008 * This does not modify any actual zoom in WebKit or backing store,
2009 * just set the Ewk_View_Smart_Data->animated_zoom.zoom.start so
2010 * sub-classes will know they should not reset their internal state.
2011 *
2012 * @param o view object to change value.
2013 * @param zoom new start value.
2014 *
2015 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
2016 *
2017 * @see ewk_view_zoom_animated_set()
2018 * @see ewk_view_zoom_weak_set()
2019 * @see ewk_view_zoom_animated_mark_stop()
2020 * @see ewk_view_zoom_animated_mark_end()
2021 * @see ewk_view_zoom_animated_mark_current()
2022 */
2023Eina_Bool ewk_view_zoom_animated_mark_start(Evas_Object* o, float zoom)
2024{
2025    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2026    sd->animated_zoom.zoom.start = zoom;
2027    return EINA_TRUE;
2028}
2029
2030/**
2031 * Mark internal zoom animation state to given zoom.
2032 *
2033 * This does not modify any actual zoom in WebKit or backing store,
2034 * just set the Ewk_View_Smart_Data->animated_zoom.zoom.end so
2035 * sub-classes will know they should not reset their internal state.
2036 *
2037 * @param o view object to change value.
2038 * @param zoom new end value.
2039 *
2040 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
2041 *
2042 * @see ewk_view_zoom_animated_set()
2043 * @see ewk_view_zoom_weak_set()
2044 * @see ewk_view_zoom_animated_mark_stop()
2045 * @see ewk_view_zoom_animated_mark_start()
2046 * @see ewk_view_zoom_animated_mark_current()
2047 */
2048Eina_Bool ewk_view_zoom_animated_mark_end(Evas_Object* o, float zoom)
2049{
2050    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2051    sd->animated_zoom.zoom.end = zoom;
2052    return EINA_TRUE;
2053}
2054
2055/**
2056 * Mark internal zoom animation state to given zoom.
2057 *
2058 * This does not modify any actual zoom in WebKit or backing store,
2059 * just set the Ewk_View_Smart_Data->animated_zoom.zoom.current so
2060 * sub-classes will know they should not reset their internal state.
2061 *
2062 * @param o view object to change value.
2063 * @param zoom new current value.
2064 *
2065 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
2066 *
2067 * @see ewk_view_zoom_animated_set()
2068 * @see ewk_view_zoom_weak_set()
2069 * @see ewk_view_zoom_animated_mark_stop()
2070 * @see ewk_view_zoom_animated_mark_start()
2071 * @see ewk_view_zoom_animated_mark_end()
2072 */
2073Eina_Bool ewk_view_zoom_animated_mark_current(Evas_Object* o, float zoom)
2074{
2075    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2076    sd->animated_zoom.zoom.current = zoom;
2077    return EINA_TRUE;
2078}
2079
2080/**
2081 * Unmark internal zoom animation state.
2082 *
2083 * This zero all start, end and current values.
2084 *
2085 * @param o view object to mark as animated is stopped.
2086 *
2087 * @see ewk_view_zoom_animated_mark_start()
2088 * @see ewk_view_zoom_animated_mark_end()
2089 * @see ewk_view_zoom_animated_mark_current()
2090 * @see ewk_view_zoom_weak_set()
2091 */
2092Eina_Bool ewk_view_zoom_animated_mark_stop(Evas_Object* o)
2093{
2094    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2095    _ewk_view_zoom_animated_mark_stop(sd);
2096    return EINA_TRUE;
2097}
2098
2099/**
2100 * Set the current zoom level while animating.
2101 *
2102 * If the view was already animating to another zoom, it will start
2103 * from current point to the next provided zoom (@a zoom parameter)
2104 * and duration (@a duration parameter).
2105 *
2106 * This is the recommended way to do transitions from one level to
2107 * another. However, one may wish to do those from outside, in that
2108 * case use ewk_view_zoom_weak_set() and later control intermediate
2109 * states with ewk_view_zoom_animated_mark_current(),
2110 * ewk_view_zoom_animated_mark_end() and
2111 * ewk_view_zoom_animated_mark_stop().
2112 *
2113 * @param o view object to animate.
2114 * @param zoom final zoom level to use.
2115 * @param duration time in seconds the animation should take.
2116 * @param cx offset inside object that defines zoom center. 0 is left side.
2117 * @param cy offset inside object that defines zoom center. 0 is top side.
2118 * @return @c EINA_TRUE if animation will be started, @c EINA_FALSE if not
2119 *            because zoom is too small/big.
2120 */
2121Eina_Bool ewk_view_zoom_animated_set(Evas_Object* o, float zoom, float duration, Evas_Coord cx, Evas_Coord cy)
2122{
2123    double now;
2124    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2125    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2126    EINA_SAFETY_ON_NULL_RETURN_VAL(sd->api, EINA_FALSE);
2127    EINA_SAFETY_ON_NULL_RETURN_VAL(sd->api->zoom_weak_set, EINA_FALSE);
2128
2129    if (!priv->settings.zoom_range.user_scalable) {
2130        WRN("userScalable is false");
2131        return EINA_FALSE;
2132    }
2133
2134    if (zoom < priv->settings.zoom_range.min_scale) {
2135        WRN("zoom level is < %f : %f", (double)priv->settings.zoom_range.min_scale, (double)zoom);
2136        return EINA_FALSE;
2137    }
2138    if (zoom > priv->settings.zoom_range.max_scale) {
2139        WRN("zoom level is > %f : %f", (double)priv->settings.zoom_range.max_scale, (double)zoom);
2140        return EINA_FALSE;
2141    }
2142
2143    if (priv->animated_zoom.animator)
2144        priv->animated_zoom.zoom.start = _ewk_view_zoom_animated_current(priv);
2145    else {
2146        priv->animated_zoom.zoom.start = ewk_frame_zoom_get(sd->main_frame);
2147        _ewk_view_zoom_animation_start(sd);
2148    }
2149
2150    if (cx < 0)
2151        cx = 0;
2152    if (cy < 0)
2153        cy = 0;
2154
2155    now = ecore_loop_time_get();
2156    priv->animated_zoom.time.start = now;
2157    priv->animated_zoom.time.end = now + duration;
2158    priv->animated_zoom.time.duration = duration;
2159    priv->animated_zoom.zoom.end = zoom;
2160    priv->animated_zoom.zoom.range = (priv->animated_zoom.zoom.end - priv->animated_zoom.zoom.start);
2161    priv->animated_zoom.center.x = cx;
2162    priv->animated_zoom.center.y = cy;
2163    sd->animated_zoom.zoom.current = priv->animated_zoom.zoom.start;
2164    sd->animated_zoom.zoom.start = priv->animated_zoom.zoom.start;
2165    sd->animated_zoom.zoom.end = priv->animated_zoom.zoom.end;
2166
2167    return EINA_TRUE;
2168}
2169
2170/**
2171 * Query if zoom level just applies to text and not other elements.
2172 *
2173 * @param o view to query setting.
2174 *
2175 * @return @c EINA_TRUE if just text are scaled, @c EINA_FALSE otherwise.
2176 */
2177Eina_Bool ewk_view_zoom_text_only_get(const Evas_Object* o)
2178{
2179    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2180    return ewk_frame_zoom_text_only_get(sd->main_frame);
2181}
2182
2183/**
2184 * Set if zoom level just applies to text and not other elements.
2185 *
2186 * @param o view to change setting.
2187 * @param setting @c EINA_TRUE if zoom should just be applied to text.
2188 *
2189 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
2190 */
2191Eina_Bool ewk_view_zoom_text_only_set(Evas_Object* o, Eina_Bool setting)
2192{
2193    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2194    return ewk_frame_zoom_text_only_set(sd->main_frame, setting);
2195}
2196
2197/**
2198 * Hint engine to pre-render region.
2199 *
2200 * Engines and backing store might be able to pre-render regions in
2201 * order to speed up zooming or scrolling to that region. Not all
2202 * engines might implement that and they will return @c EINA_FALSE
2203 * in that case.
2204 *
2205 * The given region is a hint. Engines might do bigger or smaller area
2206 * that covers that region. Pre-render might not be immediate, it may
2207 * be postponed to a thread, operated cooperatively in the main loop
2208 * and may be even ignored or cancelled afterwards.
2209 *
2210 * Multiple requests might be queued by engines. One can clear/forget
2211 * about them with ewk_view_pre_render_cancel().
2212 *
2213 * @param o view to ask pre-render of given region.
2214 * @param x absolute coordinate (0=left) to pre-render at zoom.
2215 * @param y absolute coordinate (0=top) to pre-render at zoom.
2216 * @param w width to pre-render starting from @a x at zoom.
2217 * @param h height to pre-render starting from @a y at zoom.
2218 * @param zoom desired zoom.
2219 *
2220 * @return @c EINA_TRUE if request was accepted, @c EINA_FALSE
2221 *         otherwise (errors, pre-render not supported, etc).
2222 *
2223 * @see ewk_view_pre_render_cancel()
2224 */
2225Eina_Bool ewk_view_pre_render_region(Evas_Object* o, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h, float zoom)
2226{
2227    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2228    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2229    EINA_SAFETY_ON_NULL_RETURN_VAL(sd->api->pre_render_region, EINA_FALSE);
2230    float cur_zoom;
2231    Evas_Coord cw, ch;
2232
2233    /* When doing animated zoom it's not possible to call pre-render since it
2234     * would screw up parameters that animation is currently using
2235     */
2236    if (priv->animated_zoom.animator)
2237        return EINA_FALSE;
2238
2239    cur_zoom = ewk_frame_zoom_get(sd->main_frame);
2240
2241    if (cur_zoom < 0.00001)
2242        return EINA_FALSE;
2243    if (!ewk_frame_contents_size_get(sd->main_frame, &cw, &ch))
2244        return EINA_FALSE;
2245
2246    cw *= zoom / cur_zoom;
2247    ch *= zoom / cur_zoom;
2248    DBG("region %d,%d+%dx%d @ %f contents=%dx%d", x, y, w, h, zoom, cw, ch);
2249
2250    if (x + w > cw)
2251        w = cw - x;
2252
2253    if (y + h > ch)
2254        h = ch - y;
2255
2256    if (x < 0) {
2257        w += x;
2258        x = 0;
2259    }
2260    if (y < 0) {
2261        h += y;
2262        y = 0;
2263    }
2264
2265    return sd->api->pre_render_region(sd, x, y, w, h, zoom);
2266}
2267
2268/**
2269 * Hint engine to pre-render region, given n extra cols/rows
2270 *
2271 * This is an alternative method to ewk_view_pre_render_region(). It does not
2272 * make sense in all engines and therefore it might not be implemented at all.
2273 *
2274 * It's only useful if engine divide the area being rendered in smaller tiles,
2275 * forming a grid. Then, browser could call this function to pre-render @param n
2276 * rows/cols involving the current viewport.
2277 *
2278 * @param o view to ask pre-render on.
2279 * @param n number of cols/rows that must be part of the region pre-rendered
2280 *
2281 * @see ewk_view_pre_render_region()
2282 */
2283Eina_Bool ewk_view_pre_render_relative_radius(Evas_Object* o, unsigned int n)
2284{
2285    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2286    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2287    EINA_SAFETY_ON_NULL_RETURN_VAL(sd->api->pre_render_relative_radius, EINA_FALSE);
2288    float cur_zoom;
2289
2290    if (priv->animated_zoom.animator)
2291        return EINA_FALSE;
2292
2293    cur_zoom = ewk_frame_zoom_get(sd->main_frame);
2294    return sd->api->pre_render_relative_radius(sd, n, cur_zoom);
2295}
2296
2297/**
2298 * Get input method hints
2299 *
2300 * @param o View.
2301 *
2302 * @return input method hints
2303 */
2304unsigned int ewk_view_imh_get(Evas_Object *o)
2305{
2306    EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
2307    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
2308    return priv->imh;
2309}
2310
2311/**
2312 * Cancel (clear) previous pre-render requests.
2313 *
2314 * @param o view to clear pre-render requests.
2315 */
2316void ewk_view_pre_render_cancel(Evas_Object* o)
2317{
2318    EWK_VIEW_SD_GET_OR_RETURN(o, sd);
2319    EINA_SAFETY_ON_NULL_RETURN(sd->api->pre_render_cancel);
2320    sd->api->pre_render_cancel(sd);
2321}
2322
2323/**
2324  * Enable processing of update requests.
2325  *
2326  * @param o view to enable rendering.
2327  *
2328  * @return @c EINA_TRUE if render was enabled, @c EINA_FALSE
2329            otherwise (errors, rendering suspension not supported).
2330  */
2331Eina_Bool ewk_view_enable_render(const Evas_Object *o)
2332{
2333    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2334    EINA_SAFETY_ON_NULL_RETURN_VAL(sd->api->enable_render, EINA_FALSE);
2335    return sd->api->enable_render(sd);
2336}
2337
2338/**
2339  * Disable processing of update requests.
2340  *
2341  * @param o view to disable rendering.
2342  *
2343  * @return @c EINA_TRUE if render was disabled, @c EINA_FALSE
2344            otherwise (errors, rendering suspension not supported).
2345  */
2346Eina_Bool ewk_view_disable_render(const Evas_Object *o)
2347{
2348    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2349    EINA_SAFETY_ON_NULL_RETURN_VAL(sd->api->disable_render, EINA_FALSE);
2350    return sd->api->disable_render(sd);
2351}
2352
2353const char* ewk_view_setting_user_agent_get(const Evas_Object* o)
2354{
2355    EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
2356    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
2357    return priv->settings.user_agent;
2358}
2359
2360Eina_Bool ewk_view_setting_user_agent_set(Evas_Object* o, const char* user_agent)
2361{
2362    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2363    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2364    if (eina_stringshare_replace(&priv->settings.user_agent, user_agent)) {
2365        WebCore::FrameLoaderClientEfl* client = static_cast<WebCore::FrameLoaderClientEfl*>(priv->main_frame->loader()->client());
2366        client->setCustomUserAgent(String::fromUTF8(user_agent));
2367    }
2368    return EINA_TRUE;
2369}
2370
2371const char* ewk_view_setting_user_stylesheet_get(const Evas_Object* o)
2372{
2373    EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
2374    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
2375    return priv->settings.user_stylesheet;
2376}
2377
2378Eina_Bool ewk_view_setting_user_stylesheet_set(Evas_Object* o, const char* uri)
2379{
2380    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2381    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2382    if (eina_stringshare_replace(&priv->settings.user_stylesheet, uri)) {
2383        WebCore::KURL kurl(WebCore::KURL(), String::fromUTF8(uri));
2384        priv->page_settings->setUserStyleSheetLocation(kurl);
2385    }
2386    return EINA_TRUE;
2387}
2388
2389Eina_Bool ewk_view_setting_auto_load_images_get(const Evas_Object* o)
2390{
2391    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2392    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2393    return priv->settings.auto_load_images;
2394}
2395
2396Eina_Bool ewk_view_setting_auto_load_images_set(Evas_Object* o, Eina_Bool automatic)
2397{
2398    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2399    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2400    automatic = !!automatic;
2401    if (priv->settings.auto_load_images != automatic) {
2402        priv->page_settings->setLoadsImagesAutomatically(automatic);
2403        priv->settings.auto_load_images = automatic;
2404    }
2405    return EINA_TRUE;
2406}
2407
2408Eina_Bool ewk_view_setting_auto_shrink_images_get(const Evas_Object* o)
2409{
2410    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2411    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2412    return priv->settings.auto_shrink_images;
2413}
2414
2415Eina_Bool ewk_view_setting_auto_shrink_images_set(Evas_Object* o, Eina_Bool automatic)
2416{
2417    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2418    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2419    automatic = !!automatic;
2420    if (priv->settings.auto_shrink_images != automatic) {
2421        priv->page_settings->setShrinksStandaloneImagesToFit(automatic);
2422        priv->settings.auto_shrink_images = automatic;
2423    }
2424    return EINA_TRUE;
2425}
2426
2427/**
2428 * Gets if view can be resized automatically.
2429 *
2430 * @param o view to check status
2431 *
2432 * @return EINA_TRUE if view can be resized, EINA_FALSE
2433 *         otherwise (errors, cannot be resized).
2434 */
2435Eina_Bool ewk_view_setting_enable_auto_resize_window_get(const Evas_Object* o)
2436{
2437    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2438    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2439    return priv->settings.enable_auto_resize_window;
2440}
2441
2442/**
2443 * Sets if view can be resized automatically.
2444 *
2445 * @param o View.
2446 * @param resizable @c EINA_TRUE if we want to resize automatically;
2447 * @c EINA_FALSE otherwise. It defaults to @c EINA_TRUE
2448 *
2449 * @return EINA_TRUE if auto_resize_window status set, EINA_FALSE
2450 *         otherwise (errors).
2451 */
2452Eina_Bool ewk_view_setting_enable_auto_resize_window_set(Evas_Object* o, Eina_Bool resizable)
2453{
2454    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2455    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2456    priv->settings.enable_auto_resize_window = resizable;
2457    return EINA_TRUE;
2458}
2459
2460Eina_Bool ewk_view_setting_enable_scripts_get(const Evas_Object* o)
2461{
2462    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2463    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2464    return priv->settings.enable_scripts;
2465}
2466
2467Eina_Bool ewk_view_setting_enable_scripts_set(Evas_Object* o, Eina_Bool enable)
2468{
2469    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2470    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2471    enable = !!enable;
2472    if (priv->settings.enable_scripts != enable) {
2473        priv->page_settings->setJavaScriptEnabled(enable);
2474        priv->settings.enable_scripts = enable;
2475    }
2476    return EINA_TRUE;
2477}
2478
2479Eina_Bool ewk_view_setting_enable_plugins_get(const Evas_Object* o)
2480{
2481    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2482    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2483    return priv->settings.enable_plugins;
2484}
2485
2486Eina_Bool ewk_view_setting_enable_plugins_set(Evas_Object* o, Eina_Bool enable)
2487{
2488    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2489    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2490    enable = !!enable;
2491    if (priv->settings.enable_plugins != enable) {
2492        priv->page_settings->setPluginsEnabled(enable);
2493        priv->settings.enable_plugins = enable;
2494    }
2495    return EINA_TRUE;
2496}
2497
2498/**
2499 * Get status of frame flattening.
2500 *
2501 * @param o view to check status
2502 *
2503 * @return EINA_TRUE if flattening is enabled, EINA_FALSE
2504 *         otherwise (errors, flattening disabled).
2505 */
2506Eina_Bool ewk_view_setting_enable_frame_flattening_get(const Evas_Object* o)
2507{
2508    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2509    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2510    return priv->settings.enable_frame_flattening;
2511}
2512
2513/**
2514 * Set frame flattening.
2515 *
2516 * @param o view to set flattening
2517 *
2518 * @return EINA_TRUE if flattening status set, EINA_FALSE
2519 *         otherwise (errors).
2520 */
2521Eina_Bool ewk_view_setting_enable_frame_flattening_set(Evas_Object* o, Eina_Bool enable)
2522{
2523    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2524    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2525    enable = !!enable;
2526    if (priv->settings.enable_frame_flattening != enable) {
2527        priv->page_settings->setFrameFlatteningEnabled(enable);
2528        priv->settings.enable_frame_flattening = enable;
2529    }
2530    return EINA_TRUE;
2531}
2532
2533Eina_Bool ewk_view_setting_scripts_window_open_get(const Evas_Object* o)
2534{
2535    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2536    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2537    return priv->settings.scripts_window_open;
2538}
2539
2540Eina_Bool ewk_view_setting_scripts_window_open_set(Evas_Object* o, Eina_Bool allow)
2541{
2542    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2543    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2544    allow = !!allow;
2545    if (priv->settings.scripts_window_open != allow) {
2546        priv->page_settings->setJavaScriptCanOpenWindowsAutomatically(allow);
2547        priv->settings.scripts_window_open = allow;
2548    }
2549    return EINA_TRUE;
2550}
2551
2552Eina_Bool ewk_view_setting_resizable_textareas_get(const Evas_Object* o)
2553{
2554    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2555    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2556    return priv->settings.resizable_textareas;
2557}
2558
2559Eina_Bool ewk_view_setting_resizable_textareas_set(Evas_Object* o, Eina_Bool enable)
2560{
2561    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2562    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2563    enable = !!enable;
2564    if (priv->settings.resizable_textareas != enable) {
2565        priv->page_settings->setTextAreasAreResizable(enable);
2566        priv->settings.resizable_textareas = enable;
2567    }
2568    return EINA_TRUE;
2569}
2570
2571Eina_Bool ewk_view_setting_private_browsing_get(const Evas_Object* o)
2572{
2573    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2574    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2575    return priv->settings.private_browsing;
2576}
2577
2578Eina_Bool ewk_view_setting_private_browsing_set(Evas_Object* o, Eina_Bool enable)
2579{
2580    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2581    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2582    enable = !!enable;
2583    if (priv->settings.private_browsing != enable) {
2584        priv->page_settings->setPrivateBrowsingEnabled(enable);
2585        priv->settings.private_browsing = enable;
2586    }
2587    return EINA_TRUE;
2588}
2589
2590Eina_Bool ewk_view_setting_offline_app_cache_get(const Evas_Object* o)
2591{
2592    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2593    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2594    return priv->settings.offline_app_cache;
2595}
2596
2597Eina_Bool ewk_view_setting_offline_app_cache_set(Evas_Object* o, Eina_Bool enable)
2598{
2599    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2600    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2601    enable = !!enable;
2602    if (priv->settings.offline_app_cache != enable) {
2603        priv->page_settings->setOfflineWebApplicationCacheEnabled(enable);
2604        priv->settings.offline_app_cache = enable;
2605    }
2606    return EINA_TRUE;
2607}
2608
2609
2610Eina_Bool ewk_view_setting_caret_browsing_get(const Evas_Object* o)
2611{
2612    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2613    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2614    return priv->settings.caret_browsing;
2615}
2616
2617Eina_Bool ewk_view_setting_caret_browsing_set(Evas_Object* o, Eina_Bool enable)
2618{
2619    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2620    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2621    enable = !!enable;
2622    if (priv->settings.caret_browsing != enable) {
2623        priv->page_settings->setCaretBrowsingEnabled(enable);
2624        priv->settings.caret_browsing = enable;
2625    }
2626    return EINA_TRUE;
2627}
2628
2629/**
2630 * Get current encoding of this View.
2631 *
2632 * @param o View.
2633 *
2634 * @return A pointer to an eina_strinshare containing the current custom
2635 * encoding for View object @param o, or @c 0 if it's not set.
2636 */
2637const char* ewk_view_setting_encoding_custom_get(const Evas_Object* o)
2638{
2639    EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
2640    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
2641    Evas_Object* main_frame = ewk_view_frame_main_get(o);
2642    WebCore::Frame* core_frame = ewk_frame_core_get(main_frame);
2643
2644    String overrideEncoding = core_frame->loader()->documentLoader()->overrideEncoding();
2645
2646    if (overrideEncoding.isEmpty())
2647        return 0;
2648
2649    eina_stringshare_replace(&priv->settings.encoding_custom, overrideEncoding.utf8().data());
2650    return priv->settings.encoding_custom;
2651}
2652
2653/**
2654 * Set encoding of this View and reload page.
2655 *
2656 * @param o View.
2657 * @param encoding The new encoding or @c 0 to restore the default encoding.
2658 *
2659 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
2660 */
2661Eina_Bool ewk_view_setting_encoding_custom_set(Evas_Object* o, const char *encoding)
2662{
2663    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2664    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2665    Evas_Object* main_frame = ewk_view_frame_main_get(o);
2666    WebCore::Frame* core_frame = ewk_frame_core_get(main_frame);
2667DBG("%s", encoding);
2668    eina_stringshare_replace(&priv->settings.encoding_custom, encoding);
2669    core_frame->loader()->reloadWithOverrideEncoding(String::fromUTF8(encoding));
2670
2671    return EINA_TRUE;
2672}
2673
2674const char* ewk_view_setting_encoding_default_get(const Evas_Object* o)
2675{
2676    EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
2677    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
2678    return priv->settings.encoding_default;
2679}
2680
2681Eina_Bool ewk_view_setting_encoding_default_set(Evas_Object* o, const char* encoding)
2682{
2683    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2684    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2685    if (eina_stringshare_replace(&priv->settings.encoding_default, encoding))
2686        priv->page_settings->setDefaultTextEncodingName(String::fromUTF8(encoding));
2687    return EINA_TRUE;
2688}
2689
2690/**
2691 * Sets the encoding detector.
2692 *
2693 * @param o view object to set if encoding detector is enabled.
2694 * @return @c EINA_TRUE on success and @c EINA_FALSE on failure
2695 */
2696Eina_Bool ewk_view_setting_encoding_detector_set(Evas_Object* o, Eina_Bool enable)
2697{
2698    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2699    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2700    enable = !!enable;
2701    if (priv->settings.encoding_detector != enable) {
2702        priv->page_settings->setUsesEncodingDetector(enable);
2703        priv->settings.encoding_detector = enable;
2704    }
2705    return EINA_TRUE;
2706}
2707
2708/**
2709 * Gets if the encoding detector is enabled.
2710 *
2711 * @param o view object to get if encoding detector is enabled.
2712 * @return @c EINA_TRUE if encoding detector is enabled, @c EINA_FALSE if not or on errors.
2713 */
2714Eina_Bool ewk_view_setting_encoding_detector_get(Evas_Object* o)
2715{
2716    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2717    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2718    return priv->settings.encoding_detector;
2719}
2720
2721int ewk_view_setting_font_minimum_size_get(const Evas_Object* o)
2722{
2723    EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
2724    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
2725    return priv->settings.font_minimum_size;
2726}
2727
2728Eina_Bool ewk_view_setting_font_minimum_size_set(Evas_Object* o, int size)
2729{
2730    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2731    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2732    if (priv->settings.font_minimum_size != size) {
2733        priv->page_settings->setMinimumFontSize(size);
2734        priv->settings.font_minimum_size = size;
2735    }
2736    return EINA_TRUE;
2737}
2738
2739int ewk_view_setting_font_minimum_logical_size_get(const Evas_Object* o)
2740{
2741    EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
2742    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
2743    return priv->settings.font_minimum_logical_size;
2744}
2745
2746Eina_Bool ewk_view_setting_font_minimum_logical_size_set(Evas_Object* o, int size)
2747{
2748    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2749    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2750    if (priv->settings.font_minimum_logical_size != size) {
2751        priv->page_settings->setMinimumLogicalFontSize(size);
2752        priv->settings.font_minimum_logical_size = size;
2753    }
2754    return EINA_TRUE;
2755}
2756
2757int ewk_view_setting_font_default_size_get(const Evas_Object* o)
2758{
2759    EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
2760    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
2761    return priv->settings.font_default_size;
2762}
2763
2764Eina_Bool ewk_view_setting_font_default_size_set(Evas_Object* o, int size)
2765{
2766    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2767    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2768    if (priv->settings.font_default_size != size) {
2769        priv->page_settings->setDefaultFontSize(size);
2770        priv->settings.font_default_size = size;
2771    }
2772    return EINA_TRUE;
2773}
2774
2775int ewk_view_setting_font_monospace_size_get(const Evas_Object* o)
2776{
2777    EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
2778    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
2779    return priv->settings.font_monospace_size;
2780}
2781
2782Eina_Bool ewk_view_setting_font_monospace_size_set(Evas_Object* o, int size)
2783{
2784    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2785    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2786    if (priv->settings.font_monospace_size != size) {
2787        priv->page_settings->setDefaultFixedFontSize(size);
2788        priv->settings.font_monospace_size = size;
2789    }
2790    return EINA_TRUE;
2791}
2792
2793const char* ewk_view_setting_font_standard_get(const Evas_Object* o)
2794{
2795    EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
2796    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
2797    return priv->settings.font_standard;
2798}
2799
2800Eina_Bool ewk_view_setting_font_standard_set(Evas_Object* o, const char* family)
2801{
2802    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2803    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2804    if (eina_stringshare_replace(&priv->settings.font_standard, family))
2805        priv->page_settings->setStandardFontFamily(AtomicString::fromUTF8(family));
2806    return EINA_TRUE;
2807}
2808
2809const char* ewk_view_setting_font_cursive_get(const Evas_Object* o)
2810{
2811    EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
2812    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
2813    return priv->settings.font_cursive;
2814}
2815
2816Eina_Bool ewk_view_setting_font_cursive_set(Evas_Object* o, const char* family)
2817{
2818    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2819    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2820    if (eina_stringshare_replace(&priv->settings.font_cursive, family))
2821        priv->page_settings->setCursiveFontFamily(AtomicString::fromUTF8(family));
2822    return EINA_TRUE;
2823}
2824
2825const char* ewk_view_setting_font_fantasy_get(const Evas_Object* o)
2826{
2827    EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
2828    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
2829    return priv->settings.font_fantasy;
2830}
2831
2832Eina_Bool ewk_view_setting_font_fantasy_set(Evas_Object* o, const char* family)
2833{
2834    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2835    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2836    if (eina_stringshare_replace(&priv->settings.font_fantasy, family))
2837        priv->page_settings->setFantasyFontFamily(AtomicString::fromUTF8(family));
2838    return EINA_TRUE;
2839}
2840
2841const char* ewk_view_setting_font_monospace_get(const Evas_Object* o)
2842{
2843    EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
2844    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
2845    return priv->settings.font_monospace;
2846}
2847
2848Eina_Bool ewk_view_setting_font_monospace_set(Evas_Object* o, const char* family)
2849{
2850    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2851    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2852    if (eina_stringshare_replace(&priv->settings.font_monospace, family))
2853        priv->page_settings->setFixedFontFamily(AtomicString::fromUTF8(family));
2854    return EINA_TRUE;
2855}
2856
2857const char* ewk_view_setting_font_serif_get(const Evas_Object* o)
2858{
2859    EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
2860    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
2861    return priv->settings.font_serif;
2862}
2863
2864Eina_Bool ewk_view_setting_font_serif_set(Evas_Object* o, const char* family)
2865{
2866    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2867    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2868    if (eina_stringshare_replace(&priv->settings.font_serif, family))
2869        priv->page_settings->setSerifFontFamily(AtomicString::fromUTF8(family));
2870    return EINA_TRUE;
2871}
2872
2873const char* ewk_view_setting_font_sans_serif_get(const Evas_Object* o)
2874{
2875    EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
2876    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
2877    return priv->settings.font_sans_serif;
2878}
2879
2880Eina_Bool ewk_view_setting_font_sans_serif_set(Evas_Object* o, const char* family)
2881{
2882    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2883    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2884    if (eina_stringshare_replace(&priv->settings.font_sans_serif, family))
2885        priv->page_settings->setSansSerifFontFamily(AtomicString::fromUTF8(family));
2886    return EINA_TRUE;
2887}
2888
2889/**
2890 * Gets if the spatial naviagtion is enabled.
2891 *
2892 * @param o view object to get spatial navigation setting.
2893 * @return @c EINA_TRUE if spatial navigation is enabled, @c EINA_FALSE if not or on errors.
2894 */
2895Eina_Bool ewk_view_setting_spatial_navigation_get(Evas_Object* o)
2896{
2897    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2898    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2899    return priv->settings.spatial_navigation;
2900}
2901
2902/**
2903 * Sets the spatial navigation.
2904 *
2905 * @param o view object to set spatial navigation setting.
2906 * @return @c EINA_TRUE on success and @c EINA_FALSE on failure
2907 */
2908Eina_Bool ewk_view_setting_spatial_navigation_set(Evas_Object* o, Eina_Bool enable)
2909{
2910    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2911    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2912    enable = !!enable;
2913    if (priv->settings.spatial_navigation != enable) {
2914        priv->page_settings->setSpatialNavigationEnabled(enable);
2915        priv->settings.spatial_navigation = enable;
2916    }
2917    return EINA_TRUE;
2918}
2919
2920/**
2921 * Gets if the local storage is enabled.
2922 *
2923 * @param o view object to get if local storage is enabled.
2924 * @return @c EINA_TRUE if local storage is enabled, @c EINA_FALSE if not or on errors.
2925 */
2926Eina_Bool ewk_view_setting_local_storage_get(Evas_Object* o)
2927{
2928    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2929    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2930    return priv->settings.local_storage;
2931}
2932
2933/**
2934 * Sets the local storage of HTML5.
2935 *
2936 * @param o view object to set if local storage is enabled.
2937 * @return @c EINA_TRUE on success and @c EINA_FALSE on failure
2938 */
2939Eina_Bool ewk_view_setting_local_storage_set(Evas_Object* o, Eina_Bool enable)
2940{
2941    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2942    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2943    enable = !!enable;
2944    if (priv->settings.local_storage != enable) {
2945        priv->page_settings->setLocalStorageEnabled(enable);
2946        priv->settings.local_storage = enable;
2947    }
2948    return EINA_TRUE;
2949}
2950
2951/**
2952 * Gets if the page cache is enabled.
2953 *
2954 * @param o view object to set if page cache is enabled.
2955 * @return @c EINA_TRUE if page cache is enabled, @c EINA_FALSE if not.
2956 */
2957Eina_Bool ewk_view_setting_page_cache_get(Evas_Object* o)
2958{
2959    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2960    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2961    return priv->settings.page_cache;
2962}
2963
2964/**
2965 * Sets the page cache.
2966 *
2967 * @param o view object to set if page cache is enabled.
2968 * @return @c EINA_TRUE on success and @c EINA_FALSE on failure
2969 */
2970Eina_Bool ewk_view_setting_page_cache_set(Evas_Object* o, Eina_Bool enable)
2971{
2972    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2973    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
2974    enable = !!enable;
2975    if (priv->settings.page_cache != enable) {
2976        priv->page_settings->setUsesPageCache(enable);
2977        priv->settings.page_cache = enable;
2978    }
2979    return EINA_TRUE;
2980}
2981
2982/*
2983 * Gets the local storage database path.
2984 *
2985 * @param o view object to get the local storage database path.
2986 * @return the local storage database path.
2987 */
2988const char* ewk_view_setting_local_storage_database_path_get(const Evas_Object* o)
2989{
2990    EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
2991    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
2992    return priv->settings.local_storage_database_path;
2993}
2994
2995/**
2996 * Sets the local storage database path.
2997 *
2998 * @param o view object to set the local storage database path.
2999 * @return @c EINA_TRUE on success and @c EINA_FALSE on failure
3000 */
3001Eina_Bool ewk_view_setting_local_storage_database_path_set(Evas_Object* o, const char* path)
3002{
3003    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
3004    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
3005    if (eina_stringshare_replace(&priv->settings.local_storage_database_path, path))
3006        priv->page_settings->setLocalStorageDatabasePath(String::fromUTF8(path));
3007    return EINA_TRUE;
3008}
3009
3010/**
3011 * Similar to evas_object_smart_data_get(), but does type checking.
3012 *
3013 * @param o view object to query internal data.
3014 * @return internal data or @c 0 on errors (ie: incorrect type of @a o).
3015 */
3016Ewk_View_Smart_Data* ewk_view_smart_data_get(const Evas_Object* o)
3017{
3018    EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
3019    return sd;
3020}
3021
3022/**
3023 * Gets the internal array of repaint requests.
3024 *
3025 * This array should not be modified anyhow. It should be processed
3026 * immediately as any further ewk_view call might change it, like
3027 * those that add repaints or flush them, so be sure that your code
3028 * does not call any of those while you process the repaints,
3029 * otherwise copy the array.
3030 *
3031 * @param priv private handle pointer of the view to get repaints.
3032 * @param count where to return the number of elements of returned array.
3033 *
3034 * @return reference to array of requested repaints.
3035 *
3036 * @note this is not for general use but just for subclasses that want
3037 *       to define their own backing store.
3038 */
3039const Eina_Rectangle* ewk_view_repaints_get(const Ewk_View_Private_Data* priv, size_t* count)
3040{
3041    EINA_SAFETY_ON_NULL_RETURN_VAL(count, 0);
3042    if (count)
3043        *count = 0;
3044    EINA_SAFETY_ON_NULL_RETURN_VAL(priv, 0);
3045    if (count)
3046        *count = priv->repaints.count;
3047    return priv->repaints.array;
3048}
3049
3050/**
3051 * Gets the internal array of scroll requests.
3052 *
3053 * This array should not be modified anyhow. It should be processed
3054 * immediately as any further ewk_view call might change it, like
3055 * those that add scrolls or flush them, so be sure that your code
3056 * does not call any of those while you process the scrolls,
3057 * otherwise copy the array.
3058 *
3059 * @param priv private handle pointer of the view to get scrolls.
3060 * @param count where to return the number of elements of returned array.
3061 *
3062 * @return reference to array of requested scrolls.
3063 *
3064 * @note this is not for general use but just for subclasses that want
3065 *       to define their own backing store.
3066 */
3067const Ewk_Scroll_Request* ewk_view_scroll_requests_get(const Ewk_View_Private_Data* priv, size_t* count)
3068{
3069    EINA_SAFETY_ON_NULL_RETURN_VAL(count, 0);
3070    if (count)
3071        *count = 0;
3072    EINA_SAFETY_ON_NULL_RETURN_VAL(priv, 0);
3073    if (count)
3074        *count = priv->scrolls.count;
3075    return priv->scrolls.array;
3076}
3077
3078/**
3079 * Add a new repaint request to queue.
3080 *
3081 * The repaints are assumed to be relative to current viewport.
3082 *
3083 * @param priv private handle pointer of the view to add repaint request.
3084 * @param x horizontal position relative to current view port (scrolled).
3085 * @param y vertical position relative to current view port (scrolled).
3086 * @param w width of area to be repainted
3087 * @param h height of area to be repainted
3088 *
3089 * @note this is not for general use but just for subclasses that want
3090 *       to define their own backing store.
3091 */
3092void ewk_view_repaint_add(Ewk_View_Private_Data* priv, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
3093{
3094    EINA_SAFETY_ON_NULL_RETURN(priv);
3095    _ewk_view_repaint_add(priv, x, y, w, h);
3096}
3097
3098/**
3099 * Do layout if required, applied recursively.
3100 *
3101 * @param priv private handle pointer of the view to layout.
3102 *
3103 * @note this is not for general use but just for subclasses that want
3104 *       to define their own backing store.
3105 */
3106void ewk_view_layout_if_needed_recursive(Ewk_View_Private_Data* priv)
3107{
3108    EINA_SAFETY_ON_NULL_RETURN(priv);
3109
3110    WebCore::FrameView* v = priv->main_frame->view();
3111    if (!v) {
3112        ERR("no main frame view");
3113        return;
3114    }
3115    v->updateLayoutAndStyleIfNeededRecursive();
3116}
3117
3118void ewk_view_scrolls_process(Ewk_View_Smart_Data* sd)
3119{
3120    EINA_SAFETY_ON_NULL_RETURN(sd);
3121    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv);
3122    if (!sd->api->scrolls_process(sd))
3123        ERR("failed to process scrolls.");
3124    _ewk_view_scrolls_flush(priv);
3125}
3126
3127struct _Ewk_View_Paint_Context {
3128    WebCore::GraphicsContext* gc;
3129    WebCore::FrameView* view;
3130    cairo_t* cr;
3131};
3132
3133/**
3134 * Create a new paint context using the view as source and cairo as output.
3135 *
3136 * @param priv private handle pointer of the view to use as paint source.
3137 * @param cr cairo context to use as paint destination. A new
3138 *        reference is taken, so it's safe to call cairo_destroy()
3139 *        after this function returns.
3140 *
3141 * @return newly allocated instance or @c 0 on errors.
3142 *
3143 * @note this is not for general use but just for subclasses that want
3144 *       to define their own backing store.
3145 */
3146Ewk_View_Paint_Context* ewk_view_paint_context_new(Ewk_View_Private_Data* priv, cairo_t* cr)
3147{
3148    EINA_SAFETY_ON_NULL_RETURN_VAL(priv, 0);
3149    EINA_SAFETY_ON_NULL_RETURN_VAL(cr, 0);
3150    EINA_SAFETY_ON_NULL_RETURN_VAL(priv->main_frame, 0);
3151    WebCore::FrameView* view = priv->main_frame->view();
3152    EINA_SAFETY_ON_NULL_RETURN_VAL(view, 0);
3153    Ewk_View_Paint_Context* ctxt = (Ewk_View_Paint_Context*)malloc(sizeof(*ctxt));
3154    EINA_SAFETY_ON_NULL_RETURN_VAL(ctxt, 0);
3155
3156    ctxt->gc = new WebCore::GraphicsContext(cr);
3157    if (!ctxt->gc) {
3158        free(ctxt);
3159        return 0;
3160    }
3161    ctxt->view = view;
3162    ctxt->cr = cairo_reference(cr);
3163    return ctxt;
3164}
3165
3166/**
3167 * Destroy previously created paint context.
3168 *
3169 * @param ctxt paint context to destroy. Must @b not be @c 0.
3170 *
3171 * @note this is not for general use but just for subclasses that want
3172 *       to define their own backing store.
3173 */
3174void ewk_view_paint_context_free(Ewk_View_Paint_Context* ctxt)
3175{
3176    EINA_SAFETY_ON_NULL_RETURN(ctxt);
3177    delete ctxt->gc;
3178    cairo_destroy(ctxt->cr);
3179    free(ctxt);
3180}
3181
3182/**
3183 * Save (push to stack) paint context status.
3184 *
3185 * @param ctxt paint context to save. Must @b not be @c 0.
3186 *
3187 * @see ewk_view_paint_context_restore()
3188 *
3189 * @note this is not for general use but just for subclasses that want
3190 *       to define their own backing store.
3191 */
3192void ewk_view_paint_context_save(Ewk_View_Paint_Context* ctxt)
3193{
3194    EINA_SAFETY_ON_NULL_RETURN(ctxt);
3195    cairo_save(ctxt->cr);
3196    ctxt->gc->save();
3197}
3198
3199/**
3200 * Restore (pop from stack) paint context status.
3201 *
3202 * @param ctxt paint context to restore. Must @b not be @c 0.
3203 *
3204 * @see ewk_view_paint_context_save()
3205 *
3206 * @note this is not for general use but just for subclasses that want
3207 *       to define their own backing store.
3208 */
3209void ewk_view_paint_context_restore(Ewk_View_Paint_Context* ctxt)
3210{
3211    EINA_SAFETY_ON_NULL_RETURN(ctxt);
3212    ctxt->gc->restore();
3213    cairo_restore(ctxt->cr);
3214}
3215
3216/**
3217 * Clip paint context drawings to given area.
3218 *
3219 * @param ctxt paint context to clip. Must @b not be @c 0.
3220 * @param area clip area to use.
3221 *
3222 * @see ewk_view_paint_context_save()
3223 * @see ewk_view_paint_context_restore()
3224 *
3225 * @note this is not for general use but just for subclasses that want
3226 *       to define their own backing store.
3227 */
3228void ewk_view_paint_context_clip(Ewk_View_Paint_Context* ctxt, const Eina_Rectangle* area)
3229{
3230    EINA_SAFETY_ON_NULL_RETURN(ctxt);
3231    EINA_SAFETY_ON_NULL_RETURN(area);
3232    ctxt->gc->clip(WebCore::IntRect(area->x, area->y, area->w, area->h));
3233}
3234
3235/**
3236 * Paint using context using given area.
3237 *
3238 * @param ctxt paint context to paint. Must @b not be @c 0.
3239 * @param area paint area to use. Coordinates are relative to current viewport,
3240 *        thus "scrolled".
3241 *
3242 * @note one may use cairo functions on the cairo context to
3243 *       translate, scale or any modification that may fit his desires.
3244 *
3245 * @see ewk_view_paint_context_clip()
3246 * @see ewk_view_paint_context_paint_contents()
3247 *
3248 * @note this is not for general use but just for subclasses that want
3249 *       to define their own backing store.
3250 */
3251void ewk_view_paint_context_paint(Ewk_View_Paint_Context* ctxt, const Eina_Rectangle* area)
3252{
3253    EINA_SAFETY_ON_NULL_RETURN(ctxt);
3254    EINA_SAFETY_ON_NULL_RETURN(area);
3255
3256    WebCore::IntRect rect(area->x, area->y, area->w, area->h);
3257
3258    if (ctxt->view->isTransparent())
3259        ctxt->gc->clearRect(rect);
3260    ctxt->view->paint(ctxt->gc, rect);
3261}
3262
3263/**
3264 * Paint just contents using context using given area.
3265 *
3266 * Unlike ewk_view_paint_context_paint(), this function paint just
3267 * bare contents and ignores any scrolling, scrollbars and extras. It
3268 * will walk the rendering tree and paint contents inside the given
3269 * area to the cairo context specified in @a ctxt.
3270 *
3271 * @param ctxt paint context to paint. Must @b not be @c 0.
3272 * @param area paint area to use. Coordinates are absolute to page.
3273 *
3274 * @note one may use cairo functions on the cairo context to
3275 *       translate, scale or any modification that may fit his desires.
3276 *
3277 * @see ewk_view_paint_context_clip()
3278 * @see ewk_view_paint_context_paint()
3279 *
3280 * @note this is not for general use but just for subclasses that want
3281 *       to define their own backing store.
3282 */
3283void ewk_view_paint_context_paint_contents(Ewk_View_Paint_Context* ctxt, const Eina_Rectangle* area)
3284{
3285    EINA_SAFETY_ON_NULL_RETURN(ctxt);
3286    EINA_SAFETY_ON_NULL_RETURN(area);
3287
3288    WebCore::IntRect rect(area->x, area->y, area->w, area->h);
3289
3290    if (ctxt->view->isTransparent())
3291        ctxt->gc->clearRect(rect);
3292
3293    ctxt->view->paintContents(ctxt->gc, rect);
3294}
3295
3296/**
3297 * Scale the contents by the given factors.
3298 *
3299 * This function applies a scaling transformation using Cairo.
3300 *
3301 * @param ctxt    paint context to paint. Must @b not be @c 0.
3302 * @param scale_x scale factor for the X dimension.
3303 * @param scale_y scale factor for the Y dimension.
3304 */
3305void ewk_view_paint_context_scale(Ewk_View_Paint_Context* ctxt, float scale_x, float scale_y)
3306{
3307    EINA_SAFETY_ON_NULL_RETURN(ctxt);
3308
3309    ctxt->gc->scale(WebCore::FloatSize(scale_x, scale_y));
3310}
3311
3312/**
3313 * Performs a translation of the origin coordinates.
3314 *
3315 * This function moves the origin coordinates by @p x and @p y pixels.
3316 *
3317 * @param ctxt paint context to paint. Must @b not be @c 0.
3318 * @param x    amount of pixels to translate in the X dimension.
3319 * @param y    amount of pixels to translate in the Y dimension.
3320 */
3321void ewk_view_paint_context_translate(Ewk_View_Paint_Context* ctxt, float x, float y)
3322{
3323    EINA_SAFETY_ON_NULL_RETURN(ctxt);
3324
3325    ctxt->gc->translate(x, y);
3326}
3327
3328/**
3329 * Paint using given graphics context the given area.
3330 *
3331 * This uses viewport relative area and will also handle scrollbars
3332 * and other extra elements. See ewk_view_paint_contents() for the
3333 * alternative function.
3334 *
3335 * @param priv private handle pointer of view to use as paint source.
3336 * @param cr cairo context to use as paint destination. Its state will
3337 *        be saved before operation and restored afterwards.
3338 * @param area viewport relative geometry to paint.
3339 *
3340 * @return @c EINA_TRUE on success and @c EINA_FALSE on failure, like
3341 *         incorrect parameters.
3342 *
3343 * @note this is an easy to use version, but internal structures are
3344 *       always created, then graphics context is clipped, then
3345 *       painted, restored and destroyed. This might not be optimum,
3346 *       so using #Ewk_View_Paint_Context may be a better solutions
3347 *       for large number of operations.
3348 *
3349 * @see ewk_view_paint_contents()
3350 * @see ewk_view_paint_context_paint()
3351 *
3352 * @note this is not for general use but just for subclasses that want
3353 *       to define their own backing store.
3354 */
3355Eina_Bool ewk_view_paint(Ewk_View_Private_Data* priv, cairo_t* cr, const Eina_Rectangle* area)
3356{
3357    EINA_SAFETY_ON_NULL_RETURN_VAL(priv, EINA_FALSE);
3358    EINA_SAFETY_ON_NULL_RETURN_VAL(cr, EINA_FALSE);
3359    EINA_SAFETY_ON_NULL_RETURN_VAL(area, EINA_FALSE);
3360    WebCore::FrameView* view = priv->main_frame->view();
3361    EINA_SAFETY_ON_NULL_RETURN_VAL(view, EINA_FALSE);
3362
3363    if (view->needsLayout())
3364        view->forceLayout();
3365    WebCore::GraphicsContext gc(cr);
3366    WebCore::IntRect rect(area->x, area->y, area->w, area->h);
3367
3368    cairo_save(cr);
3369    gc.save();
3370    gc.clip(rect);
3371    if (view->isTransparent())
3372        gc.clearRect(rect);
3373    view->paint(&gc,  rect);
3374    gc.restore();
3375    cairo_restore(cr);
3376
3377    return EINA_TRUE;
3378}
3379
3380/**
3381 * Paint just contents using given graphics context the given area.
3382 *
3383 * This uses absolute coordinates for area and will just handle
3384 * contents, no scrollbars or extras. See ewk_view_paint() for the
3385 * alternative solution.
3386 *
3387 * @param priv private handle pointer of view to use as paint source.
3388 * @param cr cairo context to use as paint destination. Its state will
3389 *        be saved before operation and restored afterwards.
3390 * @param area absolute geometry to paint.
3391 *
3392 * @return @c EINA_TRUE on success and @c EINA_FALSE on failure, like
3393 *         incorrect parameters.
3394 *
3395 * @note this is an easy to use version, but internal structures are
3396 *       always created, then graphics context is clipped, then
3397 *       painted, restored and destroyed. This might not be optimum,
3398 *       so using #Ewk_View_Paint_Context may be a better solutions
3399 *       for large number of operations.
3400 *
3401 * @see ewk_view_paint()
3402 * @see ewk_view_paint_context_paint_contents()
3403 *
3404 * @note this is not for general use but just for subclasses that want
3405 *       to define their own backing store.
3406 */
3407Eina_Bool ewk_view_paint_contents(Ewk_View_Private_Data* priv, cairo_t* cr, const Eina_Rectangle* area)
3408{
3409    EINA_SAFETY_ON_NULL_RETURN_VAL(priv, EINA_FALSE);
3410    EINA_SAFETY_ON_NULL_RETURN_VAL(cr, EINA_FALSE);
3411    EINA_SAFETY_ON_NULL_RETURN_VAL(area, EINA_FALSE);
3412    WebCore::FrameView* view = priv->main_frame->view();
3413    EINA_SAFETY_ON_NULL_RETURN_VAL(view, EINA_FALSE);
3414
3415    WebCore::GraphicsContext gc(cr);
3416    WebCore::IntRect rect(area->x, area->y, area->w, area->h);
3417
3418    cairo_save(cr);
3419    gc.save();
3420    gc.clip(rect);
3421    if (view->isTransparent())
3422        gc.clearRect(rect);
3423    view->paintContents(&gc,  rect);
3424    gc.restore();
3425    cairo_restore(cr);
3426
3427    return EINA_TRUE;
3428}
3429
3430
3431/* internal methods ****************************************************/
3432/**
3433 * @internal
3434 * Reports the view is ready to be displayed as all elements are aready.
3435 *
3436 * Emits signal: "ready" with no parameters.
3437 */
3438void ewk_view_ready(Evas_Object* o)
3439{
3440    DBG("o=%p", o);
3441    evas_object_smart_callback_call(o, "ready", 0);
3442}
3443
3444/**
3445 * @internal
3446 * Reports the state of input method changed. This is triggered, for example
3447 * when a input field received/lost focus
3448 *
3449 * Emits signal: "inputmethod,changed" with a boolean indicating whether it's
3450 * enabled or not.
3451 */
3452void ewk_view_input_method_state_set(Evas_Object* o, Eina_Bool active)
3453{
3454    EWK_VIEW_SD_GET_OR_RETURN(o, sd);
3455    EWK_VIEW_PRIV_GET(sd, priv);
3456    WebCore::Frame* focusedFrame = priv->page->focusController()->focusedOrMainFrame();
3457
3458    if (focusedFrame
3459        && focusedFrame->document()
3460        && focusedFrame->document()->focusedNode()
3461        && focusedFrame->document()->focusedNode()->hasTagName(WebCore::HTMLNames::inputTag)) {
3462        WebCore::HTMLInputElement* inputElement;
3463
3464        inputElement = static_cast<WebCore::HTMLInputElement*>(focusedFrame->document()->focusedNode());
3465        if (inputElement) {
3466            priv->imh = 0;
3467            // for password fields, active == false
3468            if (!active) {
3469                active = inputElement->isPasswordField();
3470                priv->imh = inputElement->isPasswordField() * EWK_IMH_PASSWORD;
3471            } else {
3472                // Set input method hints for "number", "tel", "email", and "url" input elements.
3473                priv->imh |= inputElement->isTelephoneField() * EWK_IMH_TELEPHONE;
3474                priv->imh |= inputElement->isNumberField() * EWK_IMH_NUMBER;
3475                priv->imh |= inputElement->isEmailField() * EWK_IMH_EMAIL;
3476                priv->imh |= inputElement->isURLField() * EWK_IMH_URL;
3477            }
3478        }
3479    }
3480
3481    evas_object_smart_callback_call(o, "inputmethod,changed", (void*)active);
3482}
3483
3484/**
3485 * @internal
3486 * The view title was changed by the frame loader.
3487 *
3488 * Emits signal: "title,changed" with pointer to new title string.
3489 */
3490void ewk_view_title_set(Evas_Object* o, const char* title)
3491{
3492    DBG("o=%p, title=%s", o, title ? title : "(null)");
3493    evas_object_smart_callback_call(o, "title,changed", (void*)title);
3494}
3495
3496/**
3497 * @internal
3498 * Reports that main frame's uri changed.
3499 *
3500 * Emits signal: "uri,changed" with pointer to the new uri string.
3501 */
3502void ewk_view_uri_changed(Evas_Object* o)
3503{
3504    EWK_VIEW_SD_GET_OR_RETURN(o, sd);
3505    const char* uri = ewk_frame_uri_get(sd->main_frame);
3506    DBG("o=%p, uri=%s", o, uri ? uri : "(null)");
3507    evas_object_smart_callback_call(o, "uri,changed", (void*)uri);
3508}
3509
3510/**
3511 * @internal
3512 * Reports the view started loading something.
3513 *
3514 * @param o View.
3515 *
3516 * Emits signal: "load,started" with no parameters.
3517 */
3518void ewk_view_load_started(Evas_Object* o)
3519{
3520    DBG("o=%p", o);
3521    evas_object_smart_callback_call(o, "load,started", 0);
3522}
3523
3524/**
3525 * Reports the frame started loading something.
3526 *
3527 * @param o View.
3528 *
3529 * Emits signal: "load,started" on main frame with no parameters.
3530 */
3531void ewk_view_frame_main_load_started(Evas_Object* o)
3532{
3533    DBG("o=%p", o);
3534    Evas_Object* frame = ewk_view_frame_main_get(o);
3535    evas_object_smart_callback_call(frame, "load,started", 0);
3536}
3537
3538/**
3539 * @internal
3540 * Reports the main frame started provisional load.
3541 *
3542 * @param o View.
3543 *
3544 * Emits signal: "load,provisional" on View with no parameters.
3545 */
3546void ewk_view_load_provisional(Evas_Object* o)
3547{
3548    DBG("o=%p", o);
3549    evas_object_smart_callback_call(o, "load,provisional", 0);
3550}
3551
3552/**
3553 * @internal
3554 * Reports view can be shown after a new window is created.
3555 *
3556 * @param o Frame.
3557 *
3558 * Emits signal: "load,newwindow,show" on view with no parameters.
3559 */
3560void ewk_view_load_show(Evas_Object* o)
3561{
3562    DBG("o=%p", o);
3563    evas_object_smart_callback_call(o, "load,newwindow,show", 0);
3564}
3565
3566
3567/**
3568 * @internal
3569 * Reports the main frame was cleared.
3570 *
3571 * @param o View.
3572 */
3573void ewk_view_frame_main_cleared(Evas_Object* o)
3574{
3575    DBG("o=%p", o);
3576    EWK_VIEW_SD_GET_OR_RETURN(o, sd);
3577    EINA_SAFETY_ON_NULL_RETURN(sd->api->flush);
3578    sd->api->flush(sd);
3579}
3580
3581/**
3582 * @internal
3583 * Reports the main frame received an icon.
3584 *
3585 * @param o View.
3586 *
3587 * Emits signal: "icon,received" with no parameters.
3588 */
3589void ewk_view_frame_main_icon_received(Evas_Object* o)
3590{
3591    DBG("o=%p", o);
3592    Evas_Object* frame = ewk_view_frame_main_get(o);
3593    evas_object_smart_callback_call(frame, "icon,received", 0);
3594}
3595
3596/**
3597 * @internal
3598 * Reports load finished, optionally with error information.
3599 *
3600 * Emits signal: "load,finished" with pointer to #Ewk_Frame_Load_Error
3601 * if any error, or @c 0 if successful load.
3602 *
3603 * @note there should not be any error stuff here, but trying to be
3604 *       compatible with previous WebKit.
3605 */
3606void ewk_view_load_finished(Evas_Object* o, const Ewk_Frame_Load_Error* error)
3607{
3608    DBG("o=%p, error=%p", o, error);
3609    evas_object_smart_callback_call(o, "load,finished", (void*)error);
3610}
3611
3612/**
3613 * @internal
3614 * Reports load failed with error information.
3615 *
3616 * Emits signal: "load,error" with pointer to Ewk_Frame_Load_Error.
3617 */
3618void ewk_view_load_error(Evas_Object* o, const Ewk_Frame_Load_Error* error)
3619{
3620    DBG("o=%p, error=%p", o, error);
3621    evas_object_smart_callback_call(o, "load,error", (void*)error);
3622}
3623
3624/**
3625 * @internal
3626 * Reports load progress changed.
3627 *
3628 * Emits signal: "load,progress" with pointer to a double from 0.0 to 1.0.
3629 */
3630void ewk_view_load_progress_changed(Evas_Object* o)
3631{
3632    EWK_VIEW_SD_GET_OR_RETURN(o, sd);
3633    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv);
3634
3635    // Evas_Coord w, h;
3636    double progress = priv->page->progress()->estimatedProgress();
3637
3638    DBG("o=%p (p=%0.3f)", o, progress);
3639
3640    evas_object_smart_callback_call(o, "load,progress", &progress);
3641}
3642
3643/**
3644 * @internal
3645 * Reports view @param o should be restored to default conditions
3646 *
3647 * @param o View.
3648 * @param frame Frame that originated restore.
3649 *
3650 * Emits signal: "restore" with frame.
3651 */
3652void ewk_view_restore_state(Evas_Object* o, Evas_Object* frame)
3653{
3654    evas_object_smart_callback_call(o, "restore", frame);
3655}
3656
3657/**
3658 * @internal
3659 * Delegates to browser the creation of a new window. If it is not implemented,
3660 * current view is returned, so navigation might continue in same window. If
3661 * browser supports the creation of new windows, a new Ewk_Window_Features is
3662 * created and passed to browser. If it intends to keep the request for opening
3663 * the window later it must increments the Ewk_Winwdow_Features ref count by
3664 * calling ewk_window_features_ref(window_features). Otherwise this struct will
3665 * be freed after returning to this function.
3666 *
3667 * @param o Current view.
3668 * @param javascript @c EINA_TRUE if the new window is originated from javascript,
3669 * @c EINA_FALSE otherwise
3670 * @param window_features Features of the new window being created. If it's @c
3671 * NULL, it will be created a window with default features.
3672 *
3673 * @return New view, in case smart class implements the creation of new windows;
3674 * else, current view @param o.
3675 *
3676 * @see ewk_window_features_ref().
3677 */
3678Evas_Object* ewk_view_window_create(Evas_Object* o, Eina_Bool javascript, const WebCore::WindowFeatures* coreFeatures)
3679{
3680    EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
3681
3682    if (!sd->api->window_create)
3683        return o;
3684
3685    Ewk_Window_Features* window_features = ewk_window_features_new_from_core(coreFeatures);
3686    Evas_Object* view = sd->api->window_create(sd, javascript, window_features);
3687    ewk_window_features_unref(window_features);
3688
3689    return view;
3690}
3691
3692/**
3693 * @internal
3694 * Reports a window should be closed. It's client responsibility to decide if
3695 * the window should in fact be closed. So, if only windows created by javascript
3696 * are allowed to be closed by this call, browser needs to save the javascript
3697 * flag when the window is created. Since a window can close itself (for example
3698 * with a 'self.close()' in Javascript) browser must postpone the deletion to an
3699 * idler.
3700 *
3701 * @param o View to be closed.
3702 */
3703void ewk_view_window_close(Evas_Object* o)
3704{
3705    EWK_VIEW_SD_GET_OR_RETURN(o, sd);
3706
3707    ewk_view_stop(o);
3708    if (!sd->api->window_close)
3709        return;
3710    sd->api->window_close(sd);
3711}
3712
3713/**
3714 * @internal
3715 * Reports mouse has moved over a link.
3716 *
3717 * Emits signal: "link,hover,in"
3718 */
3719void ewk_view_mouse_link_hover_in(Evas_Object* o, void* data)
3720{
3721    evas_object_smart_callback_call(o, "link,hover,in", data);
3722}
3723
3724/**
3725 * @internal
3726 * Reports mouse is not over a link anymore.
3727 *
3728 * Emits signal: "link,hover,out"
3729 */
3730void ewk_view_mouse_link_hover_out(Evas_Object* o)
3731{
3732    evas_object_smart_callback_call(o, "link,hover,out", 0);
3733}
3734
3735/**
3736 * @internal
3737 * Set toolbar visible.
3738 *
3739 * Emits signal: "toolbars,visible,set" with a pointer to a boolean.
3740 */
3741void ewk_view_toolbars_visible_set(Evas_Object* o, Eina_Bool visible)
3742{
3743    DBG("o=%p (visible=%d)", o, !!visible);
3744    evas_object_smart_callback_call(o, "toolbars,visible,set", &visible);
3745}
3746
3747/**
3748 * @internal
3749 * Get toolbar visibility.
3750 *
3751 * @param o View.
3752 * @param visible boolean pointer in which to save the result. It defaults
3753 * to @c FALSE, i.e. if browser does no listen to emitted signal, it means
3754 * there are no toolbars and therefore they are not visible.
3755 *
3756 * Emits signal: "toolbars,visible,get" with a pointer to a boolean.
3757 */
3758void ewk_view_toolbars_visible_get(Evas_Object* o, Eina_Bool* visible)
3759{
3760    DBG("%s, o=%p", __func__, o);
3761    *visible = EINA_FALSE;
3762    evas_object_smart_callback_call(o, "toolbars,visible,get", visible);
3763}
3764
3765/**
3766 * @internal
3767 * Set statusbar visible.
3768 *
3769 * @param o View.
3770 * @param visible @c TRUE if statusbar are visible, @c FALSE otherwise.
3771 *
3772 * Emits signal: "statusbar,visible,set" with a pointer to a boolean.
3773 */
3774void ewk_view_statusbar_visible_set(Evas_Object* o, Eina_Bool visible)
3775{
3776    DBG("o=%p (visible=%d)", o, !!visible);
3777    evas_object_smart_callback_call(o, "statusbar,visible,set", &visible);
3778}
3779
3780/**
3781 * @internal
3782 * Get statusbar visibility.
3783 *
3784 * @param o View.
3785 * @param visible boolean pointer in which to save the result. It defaults
3786 * to @c FALSE, i.e. if browser does no listen to emitted signal, it means
3787 * there is no statusbar and therefore it is not visible.
3788 *
3789 * Emits signal: "statusbar,visible,get" with a pointer to a boolean.
3790 */
3791void ewk_view_statusbar_visible_get(Evas_Object* o, Eina_Bool* visible)
3792{
3793    DBG("%s, o=%p", __func__, o);
3794    *visible = EINA_FALSE;
3795    evas_object_smart_callback_call(o, "statusbar,visible,get", visible);
3796}
3797
3798/**
3799 * @internal
3800 * Set text of statusbar
3801 *
3802 * @param o View.
3803 * @param text New text to put on statusbar.
3804 *
3805 * Emits signal: "statusbar,text,set" with a string.
3806 */
3807void ewk_view_statusbar_text_set(Evas_Object* o, const char* text)
3808{
3809    DBG("o=%p (text=%s)", o, text);
3810    INF("status bar text set: %s", text);
3811    evas_object_smart_callback_call(o, "statusbar,text,set", (void *)text);
3812}
3813
3814/**
3815 * @internal
3816 * Set scrollbars visible.
3817 *
3818 * @param o View.
3819 * @param visible @c TRUE if scrollbars are visible, @c FALSE otherwise.
3820 *
3821 * Emits signal: "scrollbars,visible,set" with a pointer to a boolean.
3822 */
3823void ewk_view_scrollbars_visible_set(Evas_Object* o, Eina_Bool visible)
3824{
3825    DBG("o=%p (visible=%d)", o, !!visible);
3826    evas_object_smart_callback_call(o, "scrollbars,visible,set", &visible);
3827}
3828
3829/**
3830 * @internal
3831 * Get scrollbars visibility.
3832 *
3833 * @param o View.
3834 * @param visible boolean pointer in which to save the result. It defaults
3835 * to @c FALSE, i.e. if browser does no listen to emitted signal, it means
3836 * there are no scrollbars and therefore they are not visible.
3837 *
3838 * Emits signal: "scrollbars,visible,get" with a pointer to a boolean.
3839 */
3840void ewk_view_scrollbars_visible_get(Evas_Object* o, Eina_Bool* visible)
3841{
3842    DBG("%s, o=%p", __func__, o);
3843    *visible = EINA_FALSE;
3844    evas_object_smart_callback_call(o, "scrollbars,visible,get", visible);
3845}
3846
3847/**
3848 * @internal
3849 * Set menubar visible.
3850 *
3851 * @param o View.
3852 * @param visible @c TRUE if menubar is visible, @c FALSE otherwise.
3853 *
3854 * Emits signal: "menubar,visible,set" with a pointer to a boolean.
3855 */
3856void ewk_view_menubar_visible_set(Evas_Object* o, Eina_Bool visible)
3857{
3858    DBG("o=%p (visible=%d)", o, !!visible);
3859    evas_object_smart_callback_call(o, "menubar,visible,set", &visible);
3860}
3861
3862/**
3863 * @internal
3864 * Get menubar visibility.
3865 *
3866 * @param o View.
3867 * @param visible boolean pointer in which to save the result. It defaults
3868 * to @c FALSE, i.e. if browser does no listen to emitted signal, it means
3869 * there is no menubar and therefore it is not visible.
3870 *
3871 * Emits signal: "menubar,visible,get" with a pointer to a boolean.
3872 */
3873void ewk_view_menubar_visible_get(Evas_Object* o, Eina_Bool* visible)
3874{
3875    DBG("%s, o=%p", __func__, o);
3876    *visible = EINA_FALSE;
3877    evas_object_smart_callback_call(o, "menubar,visible,get", visible);
3878}
3879
3880/**
3881 * @internal
3882 * Set tooltip text and display if it is currently hidden.
3883 *
3884 * @param o View.
3885 * @param text Text to set tooltip to.
3886 *
3887 * Emits signal: "tooltip,text,set" with a string. If tooltip must be actually
3888 * removed, text will be 0 or '\0'
3889 */
3890void ewk_view_tooltip_text_set(Evas_Object* o, const char* text)
3891{
3892    DBG("o=%p text=%s", o, text);
3893    evas_object_smart_callback_call(o, "tooltip,text,set", (void *)text);
3894}
3895
3896/**
3897 * @internal
3898 *
3899 * @param o View.
3900 * @param message String to show on console.
3901 * @param lineNumber Line number.
3902 * @sourceID Source id.
3903 *
3904 */
3905void ewk_view_add_console_message(Evas_Object* o, const char* message, unsigned int lineNumber, const char* sourceID)
3906{
3907    DBG("o=%p message=%s lineNumber=%u sourceID=%s", o, message, lineNumber, sourceID);
3908    EWK_VIEW_SD_GET_OR_RETURN(o, sd);
3909    EINA_SAFETY_ON_NULL_RETURN(sd->api);
3910    EINA_SAFETY_ON_NULL_RETURN(sd->api->add_console_message);
3911    sd->api->add_console_message(sd, message, lineNumber, sourceID);
3912}
3913
3914void ewk_view_run_javascript_alert(Evas_Object* o, Evas_Object* frame, const char* message)
3915{
3916    DBG("o=%p frame=%p message=%s", o, frame, message);
3917    EWK_VIEW_SD_GET_OR_RETURN(o, sd);
3918    EINA_SAFETY_ON_NULL_RETURN(sd->api);
3919
3920    if (!sd->api->run_javascript_alert)
3921        return;
3922
3923    sd->api->run_javascript_alert(sd, frame, message);
3924}
3925
3926Eina_Bool ewk_view_run_javascript_confirm(Evas_Object* o, Evas_Object* frame, const char* message)
3927{
3928    DBG("o=%p frame=%p message=%s", o, frame, message);
3929    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
3930    EINA_SAFETY_ON_NULL_RETURN_VAL(sd->api, EINA_FALSE);
3931
3932    if (!sd->api->run_javascript_confirm)
3933        return EINA_FALSE;
3934
3935    return sd->api->run_javascript_confirm(sd, frame, message);
3936}
3937
3938Eina_Bool ewk_view_run_javascript_prompt(Evas_Object* o, Evas_Object* frame, const char* message, const char* defaultValue, char** value)
3939{
3940    DBG("o=%p frame=%p message=%s", o, frame, message);
3941    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
3942    EINA_SAFETY_ON_NULL_RETURN_VAL(sd->api, EINA_FALSE);
3943
3944    if (!sd->api->run_javascript_prompt)
3945        return EINA_FALSE;
3946
3947    return sd->api->run_javascript_prompt(sd, frame, message, defaultValue, value);
3948}
3949
3950/**
3951 * @internal
3952 * Delegates to client to decide whether a script must be stopped because it's
3953 * running for too long. If client does not implement it, it goes to default
3954 * implementation, which logs and returns EINA_FALSE. Client may remove log by
3955 * setting this function 0, which will just return EINA_FALSE.
3956 *
3957 * @param o View.
3958 *
3959 * @return @c EINA_TRUE if script should be stopped; @c EINA_FALSE otherwise
3960 */
3961Eina_Bool ewk_view_should_interrupt_javascript(Evas_Object* o)
3962{
3963    DBG("o=%p", o);
3964    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
3965    EINA_SAFETY_ON_NULL_RETURN_VAL(sd->api, EINA_FALSE);
3966
3967    if (!sd->api->should_interrupt_javascript)
3968        return EINA_FALSE;
3969
3970    return sd->api->should_interrupt_javascript(sd);
3971}
3972
3973/**
3974 * @internal
3975 * This is called whenever the web site shown in @param frame is asking to store data
3976 * to the database @param databaseName and the quota allocated to that web site
3977 * is exceeded. Browser may use this to increase the size of quota before the
3978 * originating operationa fails.
3979 *
3980 * @param o View.
3981 * @param frame The frame whose web page exceeded its database quota.
3982 * @param databaseName Database name.
3983 * @param current_size Current size of this database
3984 * @param expected_size The expected size of this database in order to fulfill
3985 * site's requirement.
3986 */
3987uint64_t ewk_view_exceeded_database_quota(Evas_Object* o, Evas_Object* frame, const char* databaseName, uint64_t current_size, uint64_t expected_size)
3988{
3989    DBG("o=%p", o);
3990    EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
3991    EINA_SAFETY_ON_NULL_RETURN_VAL(sd->api, 0);
3992    if (!sd->api->exceeded_database_quota)
3993        return 0;
3994
3995    INF("current_size=%"PRIu64" expected_size=%"PRIu64, current_size, expected_size);
3996    return sd->api->exceeded_database_quota(sd, frame, databaseName, current_size, expected_size);
3997}
3998
3999/**
4000 * @internal
4001 * Open panel to choose a file.
4002 *
4003 * @param o View.
4004 * @param frame Frame in which operation is required.
4005 * @param allows_multiple_files @c EINA_TRUE when more than one file may be
4006 * selected, @c EINA_FALSE otherwise
4007 * @suggested_filenames List of suggested files to select. It's advisable to
4008 * just ignore this value, since it's a source of security flaw.
4009 * @selected_filenames List of files selected.
4010 *
4011 * @return @EINA_FALSE if user canceled file selection; @EINA_TRUE if confirmed.
4012 */
4013Eina_Bool ewk_view_run_open_panel(Evas_Object* o, Evas_Object* frame, Eina_Bool allows_multiple_files, const Eina_List* suggested_filenames, Eina_List** selected_filenames)
4014{
4015    DBG("o=%p frame=%p allows_multiple_files=%d", o, frame, allows_multiple_files);
4016    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
4017    EINA_SAFETY_ON_NULL_RETURN_VAL(sd->api, EINA_FALSE);
4018    Eina_Bool confirm;
4019
4020    if (!sd->api->run_open_panel)
4021        return EINA_FALSE;
4022
4023    *selected_filenames = 0;
4024
4025    confirm = sd->api->run_open_panel(sd, frame, allows_multiple_files, suggested_filenames, selected_filenames);
4026    if (!confirm && *selected_filenames)
4027        ERR("Canceled file selection, but selected filenames != 0. Free names before return.");
4028    return confirm;
4029}
4030
4031void ewk_view_repaint(Evas_Object* o, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
4032{
4033    DBG("o=%p, region=%d,%d + %dx%d", o, x, y, w, h);
4034    EWK_VIEW_SD_GET_OR_RETURN(o, sd);
4035    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv);
4036
4037    if (!priv->main_frame->contentRenderer()) {
4038        ERR("no main frame content renderer.");
4039        return;
4040    }
4041
4042    _ewk_view_repaint_add(priv, x, y, w, h);
4043    _ewk_view_smart_changed(sd);
4044}
4045
4046void ewk_view_scroll(Evas_Object* o, Evas_Coord dx, Evas_Coord dy, Evas_Coord sx, Evas_Coord sy, Evas_Coord sw, Evas_Coord sh, Evas_Coord cx, Evas_Coord cy, Evas_Coord cw, Evas_Coord ch, Eina_Bool main_frame)
4047{
4048    DBG("o=%p, delta: %d,%d, scroll: %d,%d+%dx%d, clip: %d,%d+%dx%d",
4049        o, dx, dy, sx, sy, sw, sh, cx, cy, cw, ch);
4050
4051    if ((sx != cx) || (sy != cy) || (sw != cw) || (sh != ch))
4052        WRN("scroll region and clip are different! %d,%d+%dx%d and %d,%d+%dx%d",
4053            sx, sy, sw, sh, cx, cy, cw, ch);
4054
4055    EWK_VIEW_SD_GET_OR_RETURN(o, sd);
4056    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv);
4057    EINA_SAFETY_ON_TRUE_RETURN(!dx && !dy);
4058
4059    _ewk_view_scroll_add(priv, dx, dy, sx, sy, sw, sh, main_frame);
4060
4061    _ewk_view_smart_changed(sd);
4062}
4063
4064WebCore::Page* ewk_view_core_page_get(const Evas_Object* o)
4065{
4066    EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
4067    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
4068    return priv->page;
4069}
4070
4071/**
4072 * Creates a new frame for given url and owner element.
4073 *
4074 * Emits "frame,created" with the new frame object on success.
4075 */
4076WTF::PassRefPtr<WebCore::Frame> ewk_view_frame_create(Evas_Object* o, Evas_Object* frame, const WTF::String& name, WebCore::HTMLFrameOwnerElement* ownerElement, const WebCore::KURL& url, const WTF::String& referrer)
4077{
4078    DBG("o=%p, frame=%p, name=%s, ownerElement=%p, url=%s, referrer=%s",
4079        o, frame, name.utf8().data(), ownerElement,
4080        url.string().utf8().data(), referrer.utf8().data());
4081
4082    EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
4083    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
4084
4085    WTF::RefPtr<WebCore::Frame> cf = _ewk_view_core_frame_new
4086        (sd, priv, ownerElement);
4087    if (!cf) {
4088        ERR("Could not create child core frame '%s'", name.utf8().data());
4089        return 0;
4090    }
4091
4092    if (!ewk_frame_child_add(frame, cf, name, url, referrer)) {
4093        ERR("Could not create child frame object '%s'", name.utf8().data());
4094        return 0;
4095    }
4096
4097    // The creation of the frame may have removed itself already.
4098    if (!cf->page() || !cf->tree() || !cf->tree()->parent())
4099        return 0;
4100
4101    sd->changed.frame_rect = EINA_TRUE;
4102    _ewk_view_smart_changed(sd);
4103
4104    evas_object_smart_callback_call(o, "frame,created", frame);
4105    return cf.release();
4106}
4107
4108WTF::PassRefPtr<WebCore::Widget> ewk_view_plugin_create(Evas_Object* o, Evas_Object* frame, const WebCore::IntSize& pluginSize, WebCore::HTMLPlugInElement* element, const WebCore::KURL& url, const WTF::Vector<WTF::String>& paramNames, const WTF::Vector<WTF::String>& paramValues, const WTF::String& mimeType, bool loadManually)
4109{
4110    DBG("o=%p, frame=%p, size=%dx%d, element=%p, url=%s, mimeType=%s",
4111        o, frame, pluginSize.width(), pluginSize.height(), element,
4112        url.string().utf8().data(), mimeType.utf8().data());
4113
4114    EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
4115    sd->changed.frame_rect = EINA_TRUE;
4116    _ewk_view_smart_changed(sd);
4117
4118    return ewk_frame_plugin_create
4119        (frame, pluginSize, element, url, paramNames, paramValues,
4120         mimeType, loadManually);
4121}
4122
4123
4124/**
4125 * @internal
4126 *
4127 * Creates a new popup with options when a select widget was clicked.
4128 *
4129 * @param client PopupMenuClient instance that allows communication with webkit.
4130 * @param selected Selected item.
4131 * @param rect Menu's position.
4132 *
4133 * Emits: "popup,create" with a list of Ewk_Menu containing each item's data
4134 */
4135void ewk_view_popup_new(Evas_Object* o, WebCore::PopupMenuClient* client, int selected, const WebCore::IntRect& rect)
4136{
4137    INF("o=%p", o);
4138    EWK_VIEW_SD_GET_OR_RETURN(o, sd);
4139    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv);
4140
4141    if (priv->popup.menu_client)
4142        ewk_view_popup_destroy(o);
4143
4144    priv->popup.menu_client = client;
4145
4146    // populate items
4147    const int size = client->listSize();
4148    for (int i = 0; i < size; ++i) {
4149        Ewk_Menu_Item* item = (Ewk_Menu_Item*) malloc(sizeof(*item));
4150        if (client->itemIsSeparator(i))
4151            item->type = EWK_MENU_SEPARATOR;
4152        else if (client->itemIsLabel(i))
4153            item->type = EWK_MENU_GROUP;
4154        else
4155            item->type = EWK_MENU_OPTION;
4156        item->text = eina_stringshare_add(client->itemText(i).utf8().data());
4157
4158        priv->popup.menu.items = eina_list_append(priv->popup.menu.items, item);
4159    }
4160
4161    priv->popup.menu.x = rect.x();
4162    priv->popup.menu.y = rect.y();
4163    priv->popup.menu.width = rect.width();
4164    priv->popup.menu.height = rect.height();
4165    evas_object_smart_callback_call(o, "popup,create", &priv->popup.menu);
4166}
4167
4168/**
4169 * Destroy a previously created menu.
4170 *
4171 * Before destroying, it informs client that menu's data is ready to be
4172 * destroyed by sending a "popup,willdelete" with a list of menu items. Then it
4173 * removes any reference to menu inside webkit. It's safe to call this
4174 * function either from inside webkit or from browser.
4175 *
4176 * @param o View.
4177 *
4178 * @returns EINA_TRUE in case menu was successfully destroyed or EINA_TRUE in
4179 * case there wasn't any menu to be destroyed.
4180 */
4181Eina_Bool ewk_view_popup_destroy(Evas_Object* o)
4182{
4183    INF("o=%p", o);
4184    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
4185    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
4186
4187    if (!priv->popup.menu_client)
4188        return EINA_FALSE;
4189
4190    evas_object_smart_callback_call(o, "popup,willdelete", &priv->popup.menu);
4191
4192    void* itemv;
4193    EINA_LIST_FREE(priv->popup.menu.items, itemv) {
4194        Ewk_Menu_Item* item = (Ewk_Menu_Item*)itemv;
4195        eina_stringshare_del(item->text);
4196        free(item);
4197    }
4198    priv->popup.menu_client->popupDidHide();
4199    priv->popup.menu_client = 0;
4200
4201    return EINA_TRUE;
4202}
4203
4204/**
4205 * Changes currently selected item.
4206 *
4207 * Changes the option selected in select widget. This is called by browser
4208 * whenever user has chosen a different item. Most likely after calling this, a
4209 * call to ewk_view_popup_destroy might be made in order to close the popup.
4210 *
4211 * @param o View.
4212 * @index Index of selected item.
4213 *
4214 */
4215void ewk_view_popup_selected_set(Evas_Object* o, int index)
4216{
4217    INF("o=%p", o);
4218    EWK_VIEW_SD_GET_OR_RETURN(o, sd);
4219    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv);
4220    EINA_SAFETY_ON_NULL_RETURN(priv->popup.menu_client);
4221
4222    priv->popup.menu_client->valueChanged(index);
4223}
4224
4225/**
4226 * @internal
4227 * Request a download to user.
4228 *
4229 * @param o View.
4230 * @oaram download Ewk_Download struct to be sent.
4231 *
4232 * Emits: "download,request" with an Ewk_Download containing the details of the
4233 * requested download. The download per se must be handled outside of webkit.
4234 */
4235void ewk_view_download_request(Evas_Object* o, Ewk_Download* download)
4236{
4237    DBG("view=%p", o);
4238    evas_object_smart_callback_call(o, "download,request", download);
4239}
4240
4241/**
4242 * @internal
4243 * Reports the viewport has changed.
4244 *
4245 * @param arguments viewport argument.
4246 *
4247 * Emits signal: "viewport,changed" with no parameters.
4248 */
4249void ewk_view_viewport_attributes_set(Evas_Object *o, const WebCore::ViewportArguments& arguments)
4250{
4251    EWK_VIEW_SD_GET(o, sd);
4252    EWK_VIEW_PRIV_GET(sd, priv);
4253
4254    priv->viewport_arguments = arguments;
4255    evas_object_smart_callback_call(o, "viewport,changed", 0);
4256}
4257
4258/**
4259 * Gets attributes of viewport meta tag.
4260 *
4261 * @param o view.
4262 * @param w width.
4263 * @param h height.
4264 * @param init_scale initial Scale value.
4265 * @param max_scale maximum Scale value.
4266 * @param min_scale minimum Scale value.
4267 * @param device_pixel_ratio value.
4268 * @param user_scalable user Scalable value.
4269 */
4270void ewk_view_viewport_attributes_get(Evas_Object *o, float* w, float* h, float* init_scale, float* max_scale, float* min_scale, float* device_pixel_ratio, Eina_Bool* user_scalable)
4271{
4272    WebCore::ViewportAttributes attributes = _ewk_view_viewport_attributes_compute(o);
4273
4274    if (w)
4275        *w = attributes.layoutSize.width();
4276    if (h)
4277        *h = attributes.layoutSize.height();
4278    if (init_scale)
4279        *init_scale = attributes.initialScale;
4280    if (max_scale)
4281        *max_scale = attributes.maximumScale;
4282    if (min_scale)
4283        *min_scale = attributes.minimumScale;
4284    if (device_pixel_ratio)
4285        *device_pixel_ratio = attributes.devicePixelRatio;
4286    if (user_scalable)
4287        *user_scalable = static_cast<bool>(attributes.userScalable);
4288}
4289
4290/**
4291 * Sets the zoom range.
4292 *
4293 * @param o view.
4294 * @param min_scale minimum value of zoom range.
4295 * @param max_scale maximum value of zoom range.
4296 *
4297 * @return @c EINA_TRUE if zoom range is changed, @c EINA_FALSE if not or failure.
4298 */
4299Eina_Bool ewk_view_zoom_range_set(Evas_Object* o, float min_scale, float max_scale)
4300{
4301    EWK_VIEW_SD_GET(o, sd);
4302    EWK_VIEW_PRIV_GET(sd, priv);
4303
4304    if (max_scale < min_scale) {
4305        WRN("min_scale is larger than max_scale");
4306        return EINA_FALSE;
4307    }
4308
4309    priv->settings.zoom_range.min_scale = min_scale;
4310    priv->settings.zoom_range.max_scale = max_scale;
4311
4312    return EINA_TRUE;
4313}
4314
4315/**
4316 * Gets the minimum value of zoom range.
4317 *
4318 * @param o view.
4319 *
4320 * @return minimum value of zoom range.
4321 */
4322float ewk_view_zoom_range_min_get(Evas_Object* o)
4323{
4324    EWK_VIEW_SD_GET(o, sd);
4325    EWK_VIEW_PRIV_GET(sd, priv);
4326
4327    return priv->settings.zoom_range.min_scale;
4328}
4329
4330/**
4331 * Gets the maximum value of zoom range.
4332 *
4333 * @param o view.
4334 *
4335 * @return maximum value of zoom range.
4336 */
4337float ewk_view_zoom_range_max_get(Evas_Object* o)
4338{
4339    EWK_VIEW_SD_GET(o, sd);
4340    EWK_VIEW_PRIV_GET(sd, priv);
4341
4342    return priv->settings.zoom_range.max_scale;
4343}
4344
4345/**
4346 * Sets if zoom is enabled.
4347 *
4348 * @param o view.
4349 * @param user_scalable boolean pointer in which to enable zoom. It defaults
4350 * to @c EINA_TRUE.
4351 */
4352void ewk_view_user_scalable_set(Evas_Object* o, Eina_Bool user_scalable)
4353{
4354    EWK_VIEW_SD_GET(o, sd);
4355    EWK_VIEW_PRIV_GET(sd, priv);
4356
4357    priv->settings.zoom_range.user_scalable = user_scalable;
4358}
4359
4360/**
4361 * Gets if zoom is enabled.
4362 *
4363 * @param o view.
4364 * @param user_scalable where to return the current user scalable value.
4365 *
4366 * @return @c EINA_TRUE if zoom is enabled, @c EINA_FALSE if not.
4367 */
4368Eina_Bool ewk_view_user_scalable_get(Evas_Object* o)
4369{
4370    EWK_VIEW_SD_GET(o, sd);
4371    EWK_VIEW_PRIV_GET(sd, priv);
4372
4373    return priv->settings.zoom_range.user_scalable;
4374}
4375
4376/**
4377 * Gets device pixel ratio value.
4378 *
4379 * @param o view.
4380 * @param user_scalable where to return the current user scalable value.
4381 *
4382 * @return @c EINA_TRUE if zoom is enabled, @c EINA_FALSE if not.
4383 */
4384float ewk_view_device_pixel_ratio_get(Evas_Object* o)
4385{
4386    EWK_VIEW_SD_GET(o, sd);
4387    EWK_VIEW_PRIV_GET(sd, priv);
4388
4389    return priv->settings.device_pixel_ratio;
4390}
4391
4392void ewk_view_did_first_visually_nonempty_layout(Evas_Object *o)
4393{
4394    EWK_VIEW_SD_GET_OR_RETURN(o, sd);
4395    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv);
4396    if (!priv->flags.view_cleared) {
4397        ewk_view_frame_main_cleared(o);
4398        ewk_view_enable_render(o);
4399        priv->flags.view_cleared = EINA_TRUE;
4400    }
4401}
4402
4403/**
4404 * @internal
4405 * Dispatch finished loading.
4406 *
4407 * @param o view.
4408 */
4409void ewk_view_dispatch_did_finish_loading(Evas_Object *o)
4410{
4411    /* If we reach this point and rendering is still disabled, WebCore will not
4412     * trigger the didFirstVisuallyNonEmptyLayout signal anymore. So, we
4413     * forcefully re-enable the rendering.
4414     */
4415    ewk_view_did_first_visually_nonempty_layout(o);
4416}
4417
4418void ewk_view_transition_to_commited_for_newpage(Evas_Object *o)
4419{
4420    EWK_VIEW_SD_GET_OR_RETURN(o, sd);
4421    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv);
4422
4423    ewk_view_disable_render(o);
4424    priv->flags.view_cleared = EINA_FALSE;
4425}
4426
4427
4428/**
4429 * @internal
4430 * Reports a requeset will be loaded. It's client responsibility to decide if
4431 * request would be used. If @return is true, loader will try to load. Else,
4432 * Loader ignore action of request.
4433 *
4434 * @param o View to load
4435 * @param request Request which contain url to navigate
4436 */
4437Eina_Bool ewk_view_navigation_policy_decision(Evas_Object* o, Ewk_Frame_Resource_Request* request)
4438{
4439    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_TRUE);
4440    EINA_SAFETY_ON_NULL_RETURN_VAL(sd->api, EINA_TRUE);
4441
4442    if (!sd->api->navigation_policy_decision)
4443        return EINA_TRUE;
4444
4445    return sd->api->navigation_policy_decision(sd, request);
4446}
4447
4448/**
4449 * @internal
4450 * Reports that the contents have resized. The ewk_view calls contents_resize,
4451 * which can be reimplemented as needed.
4452 *
4453 * @param o view.
4454 * @param w new content width.
4455 * @param h new content height.
4456 */
4457void ewk_view_contents_size_changed(Evas_Object *o, int w, int h)
4458{
4459    EWK_VIEW_SD_GET_OR_RETURN(o, sd);
4460    EINA_SAFETY_ON_NULL_RETURN(sd->api);
4461    EINA_SAFETY_ON_NULL_RETURN(sd->api->contents_resize);
4462
4463    if (!sd->api->contents_resize(sd, w, h))
4464        ERR("failed to resize contents to %dx%d", w, h);
4465}
4466
4467/**
4468 * @internal
4469 * Gets page size from frameview.
4470 *
4471 * @param o view.
4472 *
4473 * @return page size.
4474 */
4475WebCore::FloatRect ewk_view_page_rect_get(Evas_Object *o)
4476{
4477    EWK_VIEW_SD_GET(o, sd);
4478    EWK_VIEW_PRIV_GET(sd, priv);
4479
4480    WebCore::Frame* main_frame = priv->page->mainFrame();
4481    return main_frame->view()->frameRect();
4482}
4483
4484/**
4485 * @internal
4486 * Gets dpi value.
4487 *
4488 * @return device's dpi value.
4489 */
4490int ewk_view_dpi_get(void)
4491{
4492#ifdef HAVE_ECORE_X
4493     return ecore_x_dpi_get();
4494#else
4495     return 160;
4496#endif
4497}
4498
4499#if ENABLE(TOUCH_EVENTS)
4500void ewk_view_need_touch_events_set(Evas_Object* o, bool needed)
4501{
4502    EWK_VIEW_SD_GET(o, sd);
4503    EWK_VIEW_PRIV_GET(sd, priv);
4504
4505    priv->flags.need_touch_events = needed;
4506}
4507
4508Eina_Bool ewk_view_need_touch_events_get(Evas_Object* o)
4509{
4510    EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
4511    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
4512    return priv->flags.need_touch_events;
4513}
4514#endif
4515