summaryrefslogtreecommitdiffstats
path: root/WebKit/efl/ewk
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2010-04-27 16:31:00 +0100
committerSteve Block <steveblock@google.com>2010-05-11 14:42:12 +0100
commitdcc8cf2e65d1aa555cce12431a16547e66b469ee (patch)
tree92a8d65cd5383bca9749f5327fb5e440563926e6 /WebKit/efl/ewk
parentccac38a6b48843126402088a309597e682f40fe6 (diff)
downloadexternal_webkit-dcc8cf2e65d1aa555cce12431a16547e66b469ee.zip
external_webkit-dcc8cf2e65d1aa555cce12431a16547e66b469ee.tar.gz
external_webkit-dcc8cf2e65d1aa555cce12431a16547e66b469ee.tar.bz2
Merge webkit.org at r58033 : Initial merge by git
Change-Id: If006c38561af287c50cd578d251629b51e4d8cd1
Diffstat (limited to 'WebKit/efl/ewk')
-rw-r--r--WebKit/efl/ewk/EWebKit.h34
-rw-r--r--WebKit/efl/ewk/ewk_eapi.h50
-rw-r--r--WebKit/efl/ewk/ewk_frame.cpp1844
-rw-r--r--WebKit/efl/ewk/ewk_frame.h184
-rw-r--r--WebKit/efl/ewk/ewk_history.cpp704
-rw-r--r--WebKit/efl/ewk/ewk_history.h96
-rw-r--r--WebKit/efl/ewk/ewk_logging.h31
-rw-r--r--WebKit/efl/ewk/ewk_main.cpp152
-rw-r--r--WebKit/efl/ewk/ewk_main.h36
-rw-r--r--WebKit/efl/ewk/ewk_private.h115
-rw-r--r--WebKit/efl/ewk/ewk_settings.cpp190
-rw-r--r--WebKit/efl/ewk/ewk_settings.h53
-rw-r--r--WebKit/efl/ewk/ewk_util.cpp98
-rw-r--r--WebKit/efl/ewk/ewk_util.h29
-rw-r--r--WebKit/efl/ewk/ewk_view.cpp3644
-rw-r--r--WebKit/efl/ewk/ewk_view.h455
-rw-r--r--WebKit/efl/ewk/ewk_view_single.c585
17 files changed, 8300 insertions, 0 deletions
diff --git a/WebKit/efl/ewk/EWebKit.h b/WebKit/efl/ewk/EWebKit.h
new file mode 100644
index 0000000..d87d204
--- /dev/null
+++ b/WebKit/efl/ewk/EWebKit.h
@@ -0,0 +1,34 @@
+/*
+ Copyright (C) 2008-2009 INdT - Instituto Nokia de Tecnologia
+ Copyright (C) 2009-2010 ProFUSION embedded systems
+ Copyright (C) 2009-2010 Samsung Electronics
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef EWebKit_h
+#define EWebKit_h
+
+#include "ewk_eapi.h"
+#include "ewk_frame.h"
+#include "ewk_history.h"
+#include "ewk_main.h"
+#include "ewk_settings.h"
+#include "ewk_view.h"
+
+#include <Evas.h>
+
+#endif // EWebKit_h
diff --git a/WebKit/efl/ewk/ewk_eapi.h b/WebKit/efl/ewk/ewk_eapi.h
new file mode 100644
index 0000000..adb8d7b
--- /dev/null
+++ b/WebKit/efl/ewk/ewk_eapi.h
@@ -0,0 +1,50 @@
+/*
+ Copyright (C) 2009-2010 ProFUSION embedded systems
+ Copyright (C) 2009-2010 Samsung Electronics
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef ewk_eapi_h
+#define ewk_eapi_h
+
+#ifdef EAPI
+# undef EAPI
+#endif
+
+#ifdef _WIN32
+# ifdef BUILDING_WEBKIT
+# ifdef DLL_EXPORT
+# define EAPI __declspec(dllexport)
+# else
+# define EAPI
+# endif /* ! DLL_EXPORT */
+# else
+# define EAPI __declspec(dllimport)
+# endif /* ! EFL_EINA_BUILD */
+#else
+# ifdef __GNUC__
+# if __GNUC__ >= 4
+# define EAPI __attribute__ ((visibility("default")))
+# else
+# define EAPI
+# endif
+# else
+# define EAPI
+# endif
+#endif
+
+#endif // ewk_eapi_h
diff --git a/WebKit/efl/ewk/ewk_frame.cpp b/WebKit/efl/ewk/ewk_frame.cpp
new file mode 100644
index 0000000..73d1d29
--- /dev/null
+++ b/WebKit/efl/ewk/ewk_frame.cpp
@@ -0,0 +1,1844 @@
+/*
+ Copyright (C) 2009-2010 ProFUSION embedded systems
+ Copyright (C) 2009-2010 Samsung Electronics
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+// Uncomment to view frame regions and debug messages
+// #define EWK_FRAME_DEBUG
+
+#include "config.h"
+#include "ewk_frame.h"
+
+#include "EWebKit.h"
+#include "EventHandler.h"
+#include "FocusController.h"
+#include "FrameLoaderClientEfl.h"
+#include "FrameTree.h"
+#include "FrameView.h"
+#include "HTMLPlugInElement.h"
+#include "HitTestResult.h"
+#include "KURL.h"
+#include "PlatformKeyboardEvent.h"
+#include "PlatformMouseEvent.h"
+#include "PlatformWheelEvent.h"
+#include "ProgressTracker.h"
+#include "RefPtr.h"
+#include "RenderTheme.h"
+#include "ResourceRequest.h"
+#include "ScriptValue.h"
+#include "SharedBuffer.h"
+#include "SubstituteData.h"
+#include "WindowsKeyboardCodes.h"
+#include "ewk_private.h"
+#include <wtf/text/CString.h>
+
+#include <Eina.h>
+#include <Evas.h>
+#include <eina_safety_checks.h>
+
+static const char EWK_FRAME_TYPE_STR[] = "EWK_Frame";
+
+struct Ewk_Frame_Smart_Data {
+ Evas_Object_Smart_Clipped_Data base;
+ Evas_Object* self;
+ Evas_Object* view;
+#ifdef EWK_FRAME_DEBUG
+ Evas_Object* region;
+#endif
+ WebCore::Frame* frame;
+ const char* theme;
+ const char* title;
+ const char* uri;
+ const char* name;
+ struct {
+ Evas_Coord w, h;
+ } contents_size;
+ Eina_Bool zoom_text_only:1;
+ Eina_Bool editable:1;
+};
+
+struct Eina_Iterator_Ewk_Frame {
+ Eina_Iterator base;
+ Evas_Object* obj;
+ WebCore::Frame* last;
+};
+
+#ifndef EWK_TYPE_CHECK
+#define EWK_FRAME_TYPE_CHECK(o, ...) do { } while (0)
+#else
+#define EWK_FRAME_TYPE_CHECK(o, ...) \
+ do { \
+ const char* _tmp_otype = evas_object_type_get(o); \
+ if (EINA_UNLIKELY(_tmp_otype != EWK_FRAME_TYPE_STR)) { \
+ EINA_LOG_CRIT \
+ ("%p (%s) is not of an ewk_frame!", o, \
+ _tmp_otype ? _tmp_otype : "(null)"); \
+ return __VA_ARGS__; \
+ } \
+ } while (0)
+#endif
+
+#define EWK_FRAME_SD_GET(o, ptr) \
+ Ewk_Frame_Smart_Data* ptr = (Ewk_Frame_Smart_Data*)evas_object_smart_data_get(o)
+
+#define EWK_FRAME_SD_GET_OR_RETURN(o, ptr, ...) \
+ EWK_FRAME_TYPE_CHECK(o, __VA_ARGS__); \
+ EWK_FRAME_SD_GET(o, ptr); \
+ if (!ptr) { \
+ CRITICAL("no smart data for object %p (%s)", \
+ o, evas_object_type_get(o)); \
+ return __VA_ARGS__; \
+ }
+
+static Evas_Smart_Class _parent_sc = EVAS_SMART_CLASS_INIT_NULL;
+
+#ifdef EWK_FRAME_DEBUG
+static inline void _ewk_frame_debug(Evas_Object* o)
+{
+ Evas_Object* clip, *parent;
+ Evas_Coord x, y, w, h, cx, cy, cw, ch;
+ int r, g, b, a, cr, cg, cb, ca;
+
+ evas_object_color_get(o, &r, &g, &b, &a);
+ evas_object_geometry_get(o, &x, &y, &w, &h);
+
+ clip = evas_object_clip_get(o);
+ evas_object_color_get(clip, &cr, &cg, &cb, &ca);
+ evas_object_geometry_get(clip, &cx, &cy, &cw, &ch);
+
+ fprintf(stderr, "%p: type=%s name=%s, visible=%d, color=%02x%02x%02x%02x, %d,%d+%dx%d, clipper=%p (%d, %02x%02x%02x%02x, %d,%d+%dx%d)\n",
+ o, evas_object_type_get(o), evas_object_name_get(o), evas_object_visible_get(o),
+ r, g, b, a, x, y, w, h,
+ clip, evas_object_visible_get(clip), cr, cg, cb, ca, cx, cy, cw, ch);
+ parent = evas_object_smart_parent_get(o);
+ if (!parent)
+ fprintf(stderr, "\n");
+ else
+ _ewk_frame_debug(parent);
+}
+#endif
+
+static WebCore::FrameLoaderClientEfl* _ewk_frame_loader_efl_get(WebCore::Frame* frame)
+{
+ return static_cast<WebCore::FrameLoaderClientEfl*>(frame->loader()->client());
+}
+
+static inline Evas_Object* kit(WebCore::Frame* frame)
+{
+ if (!frame)
+ return 0;
+ WebCore::FrameLoaderClientEfl* fl = _ewk_frame_loader_efl_get(frame);
+ if (!fl)
+ return 0;
+ return fl->webFrame();
+}
+
+static Eina_Bool _ewk_frame_children_iterator_next(Eina_Iterator_Ewk_Frame* it, Evas_Object** data)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(it->obj, sd, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
+
+ WebCore::FrameTree* tree = sd->frame->tree(); // check if it's still valid
+ EINA_SAFETY_ON_NULL_RETURN_VAL(tree, EINA_FALSE);
+
+ WebCore::Frame* frame;
+ if (it->last)
+ frame = it->last->tree()->nextSibling();
+ else
+ frame = tree->firstChild();
+
+ if (!frame)
+ return EINA_FALSE;
+
+ *data = kit(frame);
+ return EINA_TRUE;
+}
+
+static Evas_Object* _ewk_frame_children_iterator_get_container(Eina_Iterator_Ewk_Frame* it)
+{
+ return it->obj;
+}
+
+static void _ewk_frame_smart_add(Evas_Object* o)
+{
+ EWK_FRAME_SD_GET(o, sd);
+
+ if (!sd) {
+ sd = (Ewk_Frame_Smart_Data*)calloc(1, sizeof(Ewk_Frame_Smart_Data));
+ if (!sd)
+ CRITICAL("could not allocate Ewk_Frame_Smart_Data");
+ else
+ evas_object_smart_data_set(o, sd);
+ }
+
+ sd->self = o;
+
+ _parent_sc.add(o);
+ evas_object_move(sd->base.clipper, 0, 0);
+ evas_object_resize(sd->base.clipper, 0, 0);
+
+#ifdef EWK_FRAME_DEBUG
+ sd->region = evas_object_rectangle_add(sd->base.evas);
+ static int i = 0;
+ switch (i) {
+ case 0:
+ evas_object_color_set(sd->region, 128, 0, 0, 128);
+ break;
+ case 1:
+ evas_object_color_set(sd->region, 0, 128, 0, 128);
+ break;
+ case 2:
+ evas_object_color_set(sd->region, 0, 0, 128, 128);
+ break;
+ case 3:
+ evas_object_color_set(sd->region, 128, 0, 0, 128);
+ break;
+ case 4:
+ evas_object_color_set(sd->region, 128, 128, 0, 128);
+ break;
+ case 5:
+ evas_object_color_set(sd->region, 128, 0, 128, 128);
+ break;
+ case 6:
+ evas_object_color_set(sd->region, 0, 128, 128, 128);
+ break;
+ default:
+ break;
+ }
+ i++;
+ if (i > 6)
+ i = 0;
+
+ evas_object_smart_member_add(sd->region, o);
+ evas_object_hide(sd->region);
+#endif
+}
+
+static void _ewk_frame_smart_del(Evas_Object* o)
+{
+ WRN("o=%p", o); // XXX REMOVE ME LATER
+ EWK_FRAME_SD_GET(o, sd);
+
+ if (sd) {
+ if (sd->frame) {
+ WebCore::FrameLoaderClientEfl* flc = _ewk_frame_loader_efl_get(sd->frame);
+ flc->setWebFrame(0);
+ sd->frame->loader()->cancelAndClear();
+ sd->frame = 0;
+ }
+
+ eina_stringshare_del(sd->title);
+ eina_stringshare_del(sd->uri);
+ eina_stringshare_del(sd->name);
+ }
+
+ _parent_sc.del(o);
+}
+
+static void _ewk_frame_smart_resize(Evas_Object* o, Evas_Coord w, Evas_Coord h)
+{
+ EWK_FRAME_SD_GET(o, sd);
+ evas_object_resize(sd->base.clipper, w, h);
+
+#ifdef EWK_FRAME_DEBUG
+ evas_object_resize(sd->region, w, h);
+ Evas_Coord x, y;
+ evas_object_geometry_get(sd->region, &x, &y, &w, &h);
+ INF("region=%p, visible=%d, geo=%d,%d + %dx%d",
+ sd->region, evas_object_visible_get(sd->region), x, y, w, h);
+ _ewk_frame_debug(o);
+#endif
+}
+
+static void _ewk_frame_smart_set(Evas_Smart_Class* api)
+{
+ evas_object_smart_clipped_smart_set(api);
+ api->add = _ewk_frame_smart_add;
+ api->del = _ewk_frame_smart_del;
+ api->resize = _ewk_frame_smart_resize;
+}
+
+static inline Evas_Smart* _ewk_frame_smart_class_new(void)
+{
+ static Evas_Smart_Class sc = EVAS_SMART_CLASS_INIT_NAME_VERSION(EWK_FRAME_TYPE_STR);
+ static Evas_Smart* smart = 0;
+
+ if (EINA_UNLIKELY(!smart)) {
+ evas_object_smart_clipped_smart_set(&_parent_sc);
+ _ewk_frame_smart_set(&sc);
+ smart = evas_smart_class_new(&sc);
+ }
+
+ return smart;
+}
+
+/**
+ * @internal
+ *
+ * Creates a new EFL WebKit Frame object.
+ *
+ * Frames are low level entries contained in a page that is contained
+ * by a view. Usually one operates on the view and not directly on the
+ * frame.
+ *
+ * @param e canvas where to create the frame object.
+ *
+ * @return frame object or @c NULL if errors.
+ */
+Evas_Object* ewk_frame_add(Evas* e)
+{
+ return evas_object_smart_add(e, _ewk_frame_smart_class_new());
+}
+
+/**
+ * Retrieves the ewk_view object that owns this frame.
+ *
+ * @param o frame object to get view from.
+ *
+ * @return view object or @c NULL if errors.
+ */
+Evas_Object* ewk_frame_view_get(const Evas_Object* o)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, 0);
+ return sd->view;
+}
+
+/**
+ * Set the theme path to be used by this frame.
+ *
+ * Frames inherit theme from their parent, this will have all frames
+ * with unset theme to use this one.
+ *
+ * @param o frame object to change theme.
+ * @param path theme path, may be @c NULL to reset to default or inherit parent.
+ */
+void ewk_frame_theme_set(Evas_Object* o, const char* path)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd);
+ if (!eina_stringshare_replace(&sd->theme, path))
+ return;
+ if (sd->frame && sd->frame->view()) {
+ sd->frame->view()->setEdjeTheme(WebCore::String(path));
+ sd->frame->page()->theme()->themeChanged();
+ }
+}
+
+/**
+ * Gets the immediate theme set on this frame.
+ *
+ * This returns the value set by ewk_frame_theme_set(). Note that if
+ * it is @c NULL, the frame will inherit parent's theme.
+ *
+ * @param o frame object to get theme path.
+ *
+ * @return theme path, may be @c NULL if not set.
+ */
+const char* ewk_frame_theme_get(Evas_Object* o)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, 0);
+ return sd->theme;
+}
+
+/**
+ * Returns a new iterator over all direct children frames.
+ *
+ * Keep frame object intact while iteration happens otherwise frame
+ * may be destroyed while iterated.
+ *
+ * Iteration results are Evas_Object*, so give eina_iterator_next() a
+ * pointer to it.
+ *
+ * @return a newly allocated iterator, free using
+ * eina_iterator_free(). If not possible to create the
+ * iterator, @c NULL is returned.
+ */
+Eina_Iterator* ewk_frame_children_iterator_new(Evas_Object* o)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, 0);
+ Eina_Iterator_Ewk_Frame* it = (Eina_Iterator_Ewk_Frame*)
+ calloc(1, sizeof(Eina_Iterator_Ewk_Frame));
+ if (!it)
+ return 0;
+
+ EINA_MAGIC_SET(&it->base, EINA_MAGIC_ITERATOR);
+ it->base.next = FUNC_ITERATOR_NEXT(_ewk_frame_children_iterator_next);
+ it->base.get_container = FUNC_ITERATOR_GET_CONTAINER(_ewk_frame_children_iterator_get_container);
+ it->base.free = FUNC_ITERATOR_FREE(free);
+ it->obj = o;
+ return &it->base;
+}
+
+/**
+ * Finds a child frame by its name, recursively.
+ *
+ * For pre-defined names, returns @a o if @a name is "_self" or
+ * "_current", returns @a o's parent frame if @a name is "_parent",
+ * and returns the main frame if @a name is "_top". Also returns @a o
+ * if it is the main frame and @a name is either "_parent" or
+ * "_top". For other names, this function returns the first frame that
+ * matches @a name. This function searches @a o and its descendents
+ * first, then @a o's parent and its children moving up the hierarchy
+ * until a match is found. If no match is found in @a o's hierarchy,
+ * this function will search for a matching frame in other main frame
+ * hierarchies.
+ *
+ * @return object if found, @c NULL if nothing with that name.
+ */
+Evas_Object* ewk_frame_child_find(Evas_Object* o, const char* name)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, 0);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(name, 0);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, 0);
+ WebCore::String s = WebCore::String::fromUTF8(name);
+ return kit(sd->frame->tree()->find(WebCore::AtomicString(s)));
+}
+
+/**
+ * Ask main frame to load the given URI.
+ *
+ * @param o frame object to load uri.
+ * @param uri uniform resource identifier to load.
+ */
+Eina_Bool ewk_frame_uri_set(Evas_Object* o, const char* uri)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ WebCore::KURL kurl(WebCore::KURL(), WebCore::String::fromUTF8(uri));
+ WebCore::ResourceRequest req(kurl);
+ WebCore::FrameLoader* loader = sd->frame->loader();
+ loader->load(req, false);
+ return EINA_TRUE;
+}
+
+/**
+ * Gets the uri of this frame.
+ *
+ * @param o frame object to get uri.
+ *
+ * @return frame uri or @c NULL. It's a internal string and should
+ * not be modified. The string is guaranteed to be stringshared.
+ */
+const char* ewk_frame_uri_get(const Evas_Object* o)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, 0);
+ return sd->uri;
+}
+
+/**
+ * Gets the title of this frame.
+ *
+ * @param o frame object to get title.
+ *
+ * @return frame title or @c NULL. It's a internal string and should
+ * not be modified. The string is guaranteed to be stringshared.
+ */
+const char* ewk_frame_title_get(const Evas_Object* o)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, 0);
+ return sd->title;
+}
+
+/**
+ * Gets the name of this frame.
+ *
+ * @param o frame object to get name.
+ *
+ * @return frame name or @c NULL. It's a internal string and should
+ * not be modified. The string is guaranteed to be stringshared.
+ */
+const char* ewk_frame_name_get(const Evas_Object* o)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, 0);
+
+ if (sd->name)
+ return sd->name;
+
+ if (!sd->frame) {
+ ERR("could not get name of uninitialized frame.");
+ return 0;
+ }
+
+ WebCore::String s = sd->frame->tree()->name();
+ WTF::CString cs = s.utf8();
+ sd->name = eina_stringshare_add_length(cs.data(), cs.length());
+ return sd->name;
+}
+
+/**
+ * Get last known contents size.
+ *
+ * @param o frame object to get contents size.
+ * @param w where to store contents size width. May be @c NULL.
+ * @param h where to store contents size height. May be @c NULL.
+ *
+ * @return @c EINA_TRUE on success or @c EINA_FALSE on failure and
+ * @a w and @a h will be zeroed.
+ */
+Eina_Bool ewk_frame_contents_size_get(const Evas_Object* o, Evas_Coord* w, Evas_Coord* h)
+{
+ if (w)
+ *w = 0;
+ if (h)
+ *h = 0;
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ if (w)
+ *w = sd->contents_size.w;
+ if (h)
+ *h = sd->contents_size.h;
+ return EINA_TRUE;
+}
+
+static Eina_Bool _ewk_frame_contents_set_internal(Ewk_Frame_Smart_Data *sd, const char* contents, size_t contents_size, const char* mime_type, const char* encoding, const char* base_uri, const char* unreachable_uri)
+{
+ if (contents_size < 1)
+ contents_size = strlen(contents);
+ if (!mime_type)
+ mime_type = "text/html";
+ if (!encoding)
+ encoding = "UTF-8";
+ if (!base_uri)
+ base_uri = "about:blank";
+
+ WebCore::KURL baseKURL(WebCore::KURL(), WebCore::String::fromUTF8(base_uri));
+ WebCore::KURL unreachableKURL;
+ if (unreachable_uri)
+ unreachableKURL = WebCore::KURL(WebCore::KURL(), WebCore::String::fromUTF8(unreachable_uri));
+ else
+ unreachableKURL = WebCore::KURL();
+
+ WTF::RefPtr<WebCore::SharedBuffer> buffer = WebCore::SharedBuffer::create(contents, contents_size);
+ WebCore::SubstituteData substituteData
+ (buffer.release(),
+ WebCore::String::fromUTF8(mime_type),
+ WebCore::String::fromUTF8(encoding),
+ baseKURL, unreachableKURL);
+ WebCore::ResourceRequest request(baseKURL);
+
+ sd->frame->loader()->load(request, substituteData, false);
+ return EINA_TRUE;
+}
+
+/**
+ * Requests loading the given contents in this frame.
+ *
+ * @param o frame object to load document.
+ * @param contents what to load into frame. Must not be @c NULL.
+ * @param contents_size byte size of data in @a contents.
+ * If zero, strlen() is used.
+ * @param mime_type type of @a contents data. If @c NULL "text/html" is assumed.
+ * @param encoding used for @a contents data. If @c NULL "UTF-8" is assumed.
+ * @param base_uri base uri to use for relative resources. May be @c NULL.
+ * If provided must be an absolute uri.
+ *
+ * @return @c EINA_TRUE on successful request, @c EINA_FALSE on errors.
+ */
+Eina_Bool ewk_frame_contents_set(Evas_Object* o, const char* contents, size_t contents_size, const char* mime_type, const char* encoding, const char* base_uri)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_FALSE_RETURN_VAL(sd->frame, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(contents, EINA_FALSE);
+ return _ewk_frame_contents_set_internal
+ (sd, contents, contents_size, mime_type, encoding, base_uri, 0);
+}
+
+/**
+ * Requests loading alternative contents for unreachable URI in this frame.
+ *
+ * This is similar to ewk_frame_contents_set(), but is used when some
+ * URI failed to load, using the provided content instead. The main
+ * difference is that back-forward navigation list is not changed.
+ *
+ * @param o frame object to load document.
+ * @param contents what to load into frame. Must not be @c NULL.
+ * @param contents_size byte size of data in @a contents.
+ * If zero, strlen() is used.
+ * @param mime_type type of @a contents data. If @c NULL "text/html" is assumed.
+ * @param encoding used for @a contents data. If @c NULL "UTF-8" is assumed.
+ * @param base_uri base uri to use for relative resources. May be @c NULL.
+ * If provided must be an absolute uri.
+ * @param unreachable_uri the URI that failed to load and is getting the
+ * alternative representation.
+ *
+ * @return @c EINA_TRUE on successful request, @c EINA_FALSE on errors.
+ */
+Eina_Bool ewk_frame_contents_alternate_set(Evas_Object* o, const char* contents, size_t contents_size, const char* mime_type, const char* encoding, const char* base_uri, const char* unreachable_uri)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_FALSE_RETURN_VAL(sd->frame, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(contents, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(unreachable_uri, EINA_FALSE);
+ return _ewk_frame_contents_set_internal
+ (sd, contents, contents_size, mime_type, encoding, base_uri,
+ unreachable_uri);
+}
+
+/**
+ * Requests execution of given script.
+ *
+ * @param o frame object to execute script.
+ * @param script java script to execute.
+ *
+ * @return @c EINA_TRUE if request was done, @c EINA_FALSE on errors.
+ */
+Eina_Bool ewk_frame_script_execute(Evas_Object* o, const char* script)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_FALSE_RETURN_VAL(sd->frame, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(script, EINA_FALSE);
+ sd->frame->script()->executeScript(WebCore::String::fromUTF8(script), true);
+ return EINA_TRUE;
+}
+
+/**
+ * Gets if frame is editable.
+ *
+ * @param o frame object to get editable state.
+ *
+ * @return @c EINA_TRUE if editable, @c EINA_FALSE otherwise.
+ */
+Eina_Bool ewk_frame_editable_get(const Evas_Object* o)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
+ return sd->editable;
+}
+
+/**
+ * Sets if frame is editable.
+ *
+ * @param o frame object to set editable state.
+ * @param editable new state.
+ *
+ * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
+ */
+Eina_Bool ewk_frame_editable_set(Evas_Object* o, Eina_Bool editable)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
+ editable = !!editable;
+ if (sd->editable == editable)
+ return EINA_TRUE;
+ if (editable)
+ sd->frame->applyEditingStyleToBodyElement();
+ else
+ sd->frame->removeEditingStyleFromBodyElement();
+ return EINA_TRUE;
+}
+
+/**
+ * Get the copy of the selection text.
+ *
+ * @param o frame object to get selection text.
+ *
+ * @return newly allocated string or @c NULL if nothing is selected or failure.
+ */
+char* ewk_frame_selection_get(const Evas_Object* o)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, 0);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, 0);
+ WTF::CString s = sd->frame->selectedText().utf8();
+ if (s.isNull())
+ return 0;
+ return strdup(s.data());
+}
+
+static inline Eina_Bool _ewk_frame_editor_command(Ewk_Frame_Smart_Data* sd, const char* command)
+{
+ return sd->frame->editor()->command(WebCore::String::fromUTF8(command)).execute();
+}
+
+/**
+ * Unselects whatever was selected.
+ *
+ * @return @c EINA_TRUE if operation was executed, @c EINA_FALSE otherwise.
+ */
+Eina_Bool ewk_frame_select_none(Evas_Object* o)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
+ return _ewk_frame_editor_command(sd, "Unselect");
+}
+
+/**
+ * Selects everything.
+ *
+ * @return @c EINA_TRUE if operation was executed, @c EINA_FALSE otherwise.
+ */
+Eina_Bool ewk_frame_select_all(Evas_Object* o)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
+ return _ewk_frame_editor_command(sd, "SelectAll");
+}
+
+/**
+ * Selects the current paragrah.
+ *
+ * @return @c EINA_TRUE if operation was executed, @c EINA_FALSE otherwise.
+ */
+Eina_Bool ewk_frame_select_paragraph(Evas_Object* o)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
+ return _ewk_frame_editor_command(sd, "SelectParagraph");
+}
+
+/**
+ * Selects the current sentence.
+ *
+ * @return @c EINA_TRUE if operation was executed, @c EINA_FALSE otherwise.
+ */
+Eina_Bool ewk_frame_select_sentence(Evas_Object* o)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
+ return _ewk_frame_editor_command(sd, "SelectSentence");
+}
+
+/**
+ * Selects the current line.
+ *
+ * @return @c EINA_TRUE if operation was executed, @c EINA_FALSE otherwise.
+ */
+Eina_Bool ewk_frame_select_line(Evas_Object* o)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
+ return _ewk_frame_editor_command(sd, "SelectLine");
+}
+
+/**
+ * Selects the current word.
+ *
+ * @return @c EINA_TRUE if operation was executed, @c EINA_FALSE otherwise.
+ */
+Eina_Bool ewk_frame_select_word(Evas_Object* o)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
+ return _ewk_frame_editor_command(sd, "SelectWord");
+}
+
+/**
+ * Search the given text string in document.
+ *
+ * @param o frame object where to search text.
+ * @param string reference string to search.
+ * @param case_sensitive if search should be case sensitive or not.
+ * @param forward if search is from cursor and on or backwards.
+ * @param wrap if search should wrap at end.
+ *
+ * @return @c EINA_TRUE if found, @c EINA_FALSE if not or failure.
+ */
+Eina_Bool ewk_frame_text_search(const Evas_Object* o, const char* string, Eina_Bool case_sensitive, Eina_Bool forward, Eina_Bool wrap)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(string, EINA_FALSE);
+
+ return sd->frame->findString(WebCore::String::fromUTF8(string), forward, case_sensitive, wrap, true);
+}
+
+/**
+ * Mark matches the given text string in document.
+ *
+ * @param o frame object where to search text.
+ * @param string reference string to match.
+ * @param case_sensitive if match should be case sensitive or not.
+ * @param highlight if matches should be highlighted.
+ * @param limit maximum amount of matches, or zero to unlimited.
+ *
+ * @return number of matches.
+ */
+unsigned int ewk_frame_text_matches_mark(Evas_Object* o, const char* string, Eina_Bool case_sensitive, Eina_Bool highlight, unsigned int limit)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, 0);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(string, 0);
+
+ sd->frame->setMarkedTextMatchesAreHighlighted(highlight);
+ return sd->frame->markAllMatchesForText(WebCore::String::fromUTF8(string), case_sensitive, limit);
+}
+
+/**
+ * Reverses the effect of ewk_frame_text_matches_mark()
+ *
+ * @param o frame object where to search text.
+ *
+ * @return @c EINA_TRUE on success, @c EINA_FALSE for failure.
+ */
+Eina_Bool ewk_frame_text_matches_unmark_all(Evas_Object* o)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
+
+ sd->frame->document()->removeMarkers(WebCore::DocumentMarker::TextMatch);
+ return EINA_TRUE;
+}
+
+/**
+ * Set if should highlight matches marked with ewk_frame_text_matches_mark().
+ *
+ * @param o frame object where to set if matches are highlighted or not.
+ * @param highlight if @c EINA_TRUE, matches will be highlighted.
+ *
+ * @return @c EINA_TRUE on success, @c EINA_FALSE for failure.
+ */
+Eina_Bool ewk_frame_text_matches_highlight_set(Evas_Object* o, Eina_Bool highlight)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
+ sd->frame->setMarkedTextMatchesAreHighlighted(highlight);
+ return EINA_TRUE;
+}
+
+/**
+ * Get if should highlight matches marked with ewk_frame_text_matches_mark().
+ *
+ * @param o frame object to query if matches are highlighted or not.
+ *
+ * @return @c EINA_TRUE if they are highlighted, @c EINA_FALSE otherwise.
+ */
+Eina_Bool ewk_frame_text_matches_highlight_get(const Evas_Object* o)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
+ return sd->frame->markedTextMatchesAreHighlighted();
+}
+
+/**
+ * Ask frame to stop loading.
+ *
+ * @param o frame object to stop loading.
+ *
+ * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
+ */
+Eina_Bool ewk_frame_stop(Evas_Object* o)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
+ sd->frame->loader()->stopAllLoaders();
+ return EINA_TRUE;
+}
+
+/**
+ * Ask frame to reload current document.
+ *
+ * @param o frame object to reload.
+ *
+ * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
+ *
+ * @see ewk_frame_reload_full()
+ */
+Eina_Bool ewk_frame_reload(Evas_Object* o)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
+ sd->frame->loader()->reload();
+ return EINA_TRUE;
+}
+
+/**
+ * Ask frame to fully reload current document, using no previous caches.
+ *
+ * @param o frame object to reload.
+ *
+ * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
+ */
+Eina_Bool ewk_frame_reload_full(Evas_Object* o)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
+ sd->frame->loader()->reload(true);
+ return EINA_TRUE;
+}
+
+/**
+ * Ask frame to navigate back in history.
+ *
+ * @param o frame object to navigate back.
+ *
+ * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
+ *
+ * @see ewk_frame_navigate()
+ */
+Eina_Bool ewk_frame_back(Evas_Object* o)
+{
+ return ewk_frame_navigate(o, -1);
+}
+
+/**
+ * Ask frame to navigate forward in history.
+ *
+ * @param o frame object to navigate forward.
+ *
+ * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
+ *
+ * @see ewk_frame_navigate()
+ */
+Eina_Bool ewk_frame_forward(Evas_Object* o)
+{
+ return ewk_frame_navigate(o, 1);
+}
+
+/**
+ * Navigate back or forward in history.
+ *
+ * @param o frame object to navigate.
+ * @param steps if positive navigates that amount forwards, if negative
+ * does backwards.
+ *
+ * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
+ */
+Eina_Bool ewk_frame_navigate(Evas_Object* o, int steps)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
+ WebCore::Page* page = sd->frame->page();
+ if (!page->canGoBackOrForward(steps))
+ return EINA_FALSE;
+ page->goBackOrForward(steps);
+ return EINA_TRUE;
+}
+
+/**
+ * Check if it is possible to navigate backwards one item in history.
+ *
+ * @param o frame object to check if backward navigation is possible.
+ *
+ * @return @c EINA_TRUE if possible, @c EINA_FALSE otherwise.
+ *
+ * @see ewk_frame_navigate_possible()
+ */
+Eina_Bool ewk_frame_back_possible(Evas_Object* o)
+{
+ return ewk_frame_navigate_possible(o, -1);
+}
+
+/**
+ * Check if it is possible to navigate forwards one item in history.
+ *
+ * @param o frame object to check if forward navigation is possible.
+ *
+ * @return @c EINA_TRUE if possible, @c EINA_FALSE otherwise.
+ *
+ * @see ewk_frame_navigate_possible()
+ */
+Eina_Bool ewk_frame_forward_possible(Evas_Object* o)
+{
+ return ewk_frame_navigate_possible(o, 1);
+}
+
+/**
+ * Check if it is possible to navigate given @a steps in history.
+ *
+ * @param o frame object to navigate.
+ * @param steps if positive navigates that amount forwards, if negative
+ * does backwards.
+ *
+ * @return @c EINA_TRUE if possible, @c EINA_FALSE otherwise.
+ */
+Eina_Bool ewk_frame_navigate_possible(Evas_Object* o, int steps)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
+ WebCore::Page* page = sd->frame->page();
+ return page->canGoBackOrForward(steps);
+}
+
+/**
+ * Get current zoom level used by this frame.
+ *
+ * @param o frame object to query zoom level.
+ *
+ * @return zoom level or -1.0 on failure.
+ */
+float ewk_frame_zoom_get(const Evas_Object* o)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, -1.0);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, -1.0);
+ return sd->frame->zoomFactor();
+}
+
+/**
+ * Set current zoom level used by this frame.
+ *
+ * @param o frame object to change zoom level.
+ * @param zoom new level.
+ *
+ * @return @c EINA_TRUE on success or @c EINA_FALSE on failure.
+ *
+ * @see ewk_frame_zoom_text_only_set()
+ */
+Eina_Bool ewk_frame_zoom_set(Evas_Object* o, float zoom)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
+ sd->frame->setZoomFactor(zoom, sd->zoom_text_only);
+ return EINA_TRUE;
+}
+
+/**
+ * Query if zoom level just applies to text and not other elements.
+ *
+ * @param o frame to query setting.
+ *
+ * @return @c EINA_TRUE if just text are scaled, @c EINA_FALSE otherwise.
+ */
+Eina_Bool ewk_frame_zoom_text_only_get(const Evas_Object* o)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ return sd->zoom_text_only;
+}
+
+/**
+ * Set if zoom level just applies to text and not other elements.
+ *
+ * @param o frame to change setting.
+ * @param setting @c EINA_TRUE if zoom should just be applied to text.
+ *
+ * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
+ */
+Eina_Bool ewk_frame_zoom_text_only_set(Evas_Object* o, Eina_Bool setting)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
+ setting = !!setting;
+ if (sd->zoom_text_only == setting)
+ return EINA_TRUE;
+
+ sd->zoom_text_only = setting;
+ sd->frame->setZoomFactor(sd->frame->zoomFactor(), setting);
+ return EINA_TRUE;
+}
+
+/**
+ * Free hit test created with ewk_frame_hit_test_new().
+ *
+ * @param hit_test instance. Must @b not be @c NULL.
+ */
+void ewk_frame_hit_test_free(Ewk_Hit_Test* hit_test)
+{
+ EINA_SAFETY_ON_NULL_RETURN(hit_test);
+ eina_stringshare_del(hit_test->title);
+ eina_stringshare_del(hit_test->alternate_text);
+ eina_stringshare_del(hit_test->link.text);
+ eina_stringshare_del(hit_test->link.url);
+ eina_stringshare_del(hit_test->link.title);
+ free(hit_test);
+}
+
+/**
+ * Creates a new hit test for given frame and point.
+ *
+ * @param o frame to do hit test on.
+ * @param x horizontal position to query.
+ * @param y vertical position to query.
+ *
+ * @return a newly allocated hit test on success, @c NULL otherwise.
+ * Free memory with ewk_frame_hit_test_free()
+ */
+Ewk_Hit_Test* ewk_frame_hit_test_new(const Evas_Object* o, int x, int y)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, 0);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, 0);
+
+ WebCore::FrameView* view = sd->frame->view();
+ EINA_SAFETY_ON_NULL_RETURN_VAL(view, 0);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame->contentRenderer(), 0);
+
+ WebCore::HitTestResult result = sd->frame->eventHandler()->hitTestResultAtPoint
+ (view->windowToContents(WebCore::IntPoint(x, y)),
+ /*allowShadowContent*/ false, /*ignoreClipping*/ true);
+
+ if (result.scrollbar())
+ return 0;
+ if (!result.innerNode())
+ return 0;
+
+ Ewk_Hit_Test* hit_test = (Ewk_Hit_Test*)calloc(1, sizeof(Ewk_Hit_Test));
+ if (!hit_test) {
+ CRITICAL("Could not allocate memory for hit test.");
+ return 0;
+ }
+
+ hit_test->x = result.point().x();
+ hit_test->y = result.point().y();
+#if 0
+ // FIXME
+ hit_test->bounding_box.x = result.boundingBox().x();
+ hit_test->bounding_box.y = result.boundingBox().y();
+ hit_test->bounding_box.w = result.boundingBox().width();
+ hit_test->bounding_box.h = result.boundingBox().height();
+#else
+ hit_test->bounding_box.x = 0;
+ hit_test->bounding_box.y = 0;
+ hit_test->bounding_box.w = 0;
+ hit_test->bounding_box.h = 0;
+#endif
+
+ WebCore::TextDirection dir;
+ hit_test->title = eina_stringshare_add(result.title(dir).utf8().data());
+ hit_test->alternate_text = eina_stringshare_add(result.altDisplayString().utf8().data());
+ if (result.innerNonSharedNode() && result.innerNonSharedNode()->document()
+ && result.innerNonSharedNode()->document()->frame())
+ hit_test->frame = kit(result.innerNonSharedNode()->document()->frame());
+
+ hit_test->link.text = eina_stringshare_add(result.textContent().utf8().data());
+ hit_test->link.url = eina_stringshare_add(result.absoluteLinkURL().prettyURL().utf8().data());
+ hit_test->link.title = eina_stringshare_add(result.titleDisplayString().utf8().data());
+ hit_test->link.target_frame = kit(result.targetFrame());
+
+ hit_test->flags.editable = result.isContentEditable();
+ hit_test->flags.selected = result.isSelected();
+
+ return hit_test;
+}
+
+/**
+ * Relative scroll of given frame.
+ *
+ * @param o frame object to scroll.
+ * @param dx horizontal offset to scroll.
+ * @param dy vertical offset to scroll.
+ *
+ * @return @c EINA_TRUE if possible, @c EINA_FALSE otherwise.
+ */
+Eina_Bool
+ewk_frame_scroll_add(Evas_Object* o, int dx, int dy)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame->view(), EINA_FALSE);
+ sd->frame->view()->scrollBy(IntSize(dx, dy));
+ return EINA_TRUE;
+}
+
+/**
+ * Set absolute scroll of given frame.
+ *
+ * Both values are from zero to the contents size minus the viewport
+ * size. See ewk_frame_scroll_size_get().
+ *
+ * @param o frame object to scroll.
+ * @param x horizontal position to scroll.
+ * @param y vertical position to scroll.
+ *
+ * @return @c EINA_TRUE if possible, @c EINA_FALSE otherwise.
+ */
+Eina_Bool
+ewk_frame_scroll_set(Evas_Object* o, int x, int y)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame->view(), EINA_FALSE);
+ sd->frame->view()->setScrollPosition(WebCore::IntPoint(x, y));
+ return EINA_TRUE;
+}
+
+/**
+ * Get the possible scroll size of given frame.
+ *
+ * Possible scroll size is contents size minus the viewport
+ * size. It's the last allowed value for ewk_frame_scroll_set()
+ *
+ * @param o frame object to scroll.
+ * @param w where to return horizontal size that is possible to
+ * scroll. May be @c NULL.
+ * @param h where to return vertical size that is possible to scroll.
+ * May be @c NULL.
+ *
+ * @return @c EINA_TRUE if possible, @c EINA_FALSE otherwise and
+ * values are zeroed.
+ */
+Eina_Bool
+ewk_frame_scroll_size_get(const Evas_Object* o, int* w, int* h)
+{
+ if (w)
+ *w = 0;
+ if (h)
+ *h = 0;
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame->view(), EINA_FALSE);
+ WebCore::IntPoint point = sd->frame->view()->maximumScrollPosition();
+ if (w)
+ *w = point.x();
+ if (h)
+ *h = point.y();
+ return EINA_TRUE;
+}
+
+/**
+ * Get the current scroll position of given frame.
+ *
+ * @param o frame object to scroll.
+ * @param x where to return horizontal position. May be @c NULL.
+ * @param y where to return vertical position. May be @c NULL.
+ *
+ * @return @c EINA_TRUE if possible, @c EINA_FALSE otherwise and
+ * values are zeroed.
+ */
+Eina_Bool
+ewk_frame_scroll_pos_get(const Evas_Object* o, int* x, int* y)
+{
+ if (x)
+ *x = 0;
+ if (y)
+ *y = 0;
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame->view(), EINA_FALSE);
+ WebCore::IntPoint pos = sd->frame->view()->scrollPosition();
+ if (x)
+ *x = pos.x();
+ if (y)
+ *y = pos.y();
+ return EINA_TRUE;
+}
+
+/**
+ * Get the current frame visible content geometry.
+ *
+ * @param o frame object to query visible content geometry.
+ * @param include_scrollbars whenever to include scrollbars size.
+ * @param x horizontal position. May be @c NULL.
+ * @param y vertical position. May be @c NULL.
+ * @param w width. May be @c NULL.
+ * @param h height. May be @c NULL.
+ *
+ * @return @c EINA_TRUE if possible, @c EINA_FALSE otherwise and
+ * values are zeroed.
+ */
+Eina_Bool ewk_frame_visible_content_geometry_get(const Evas_Object* o, Eina_Bool include_scrollbars, int* x, int* y, int* w, int* h)
+{
+ if (x)
+ *x = 0;
+ if (y)
+ *y = 0;
+ if (w)
+ *w = 0;
+ if (h)
+ *h = 0;
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame->view(), EINA_FALSE);
+ WebCore::IntRect rect = sd->frame->view()->visibleContentRect(include_scrollbars);
+ if (x)
+ *x = rect.x();
+ if (y)
+ *y = rect.y();
+ if (w)
+ *w = rect.width();
+ if (h)
+ *h = rect.height();
+ return EINA_TRUE;
+}
+
+/**
+ * Get the current paintsEntireContents flag.
+ *
+ * This flag tells if dirty areas should be repainted even if they are
+ * out of the screen.
+ *
+ * @param o frame object to query paintsEntireContents flag.
+ *
+ * @return @c EINA_TRUE if repainting any dirty area, @c EINA_FALSE
+ * otherwise.
+ */
+Eina_Bool ewk_frame_paint_full_get(const Evas_Object* o)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame->view(), EINA_FALSE);
+ return sd->frame->view()->paintsEntireContents();
+}
+
+/**
+ * Set the current paintsEntireContents flag.
+ *
+ * This flag tells if dirty areas should be repainted even if they are
+ * out of the screen.
+ *
+ * @param o frame object to set paintsEntireContents flag.
+ * @param flag @c EINA_TRUE if want to always repaint any dirty area,
+ * @c EINA_FALSE otherwise.
+ */
+void ewk_frame_paint_full_set(Evas_Object* o, Eina_Bool flag)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd);
+ EINA_SAFETY_ON_NULL_RETURN(sd->frame);
+ EINA_SAFETY_ON_NULL_RETURN(sd->frame->view());
+ sd->frame->view()->setPaintsEntireContents(flag);
+}
+
+/**
+ * Feed the focus in signal to this frame.
+ *
+ * @param o frame object to focus.
+ *
+ * @return @c EINA_TRUE if it was handled, @c EINA_FALSE otherwise.
+ */
+Eina_Bool ewk_frame_feed_focus_in(Evas_Object* o)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
+ WebCore::FocusController* c = sd->frame->page()->focusController();
+ c->setFocusedFrame(sd->frame);
+ return EINA_TRUE;
+}
+
+/**
+ * Feed the focus out signal to this frame.
+ *
+ * @param o frame object to remove focus.
+ */
+Eina_Bool ewk_frame_feed_focus_out(Evas_Object* o)
+{
+ // TODO: what to do on focus out?
+ ERR("what to do?");
+ return EINA_FALSE;
+}
+
+/**
+ * Feed the mouse wheel event to the frame.
+ *
+ * @param o frame object to feed event.
+ * @param ev mouse wheel event.
+ *
+ * @return @c EINA_TRUE if it was handled, @c EINA_FALSE otherwise.
+ */
+Eina_Bool ewk_frame_feed_mouse_wheel(Evas_Object* o, const Evas_Event_Mouse_Wheel* ev)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(ev, EINA_FALSE);
+
+ WebCore::FrameView* view = sd->frame->view();
+ DBG("o=%p, view=%p, direction=%d, z=%d, pos=%d,%d",
+ o, view, ev->direction, ev->z, ev->canvas.x, ev->canvas.y);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(view, EINA_FALSE);
+
+ WebCore::PlatformWheelEvent event(ev);
+ return sd->frame->eventHandler()->handleWheelEvent(event);
+}
+
+/**
+ * Feed the mouse down event to the frame.
+ *
+ * @param o frame object to feed event.
+ * @param ev mouse down event.
+ *
+ * @return @c EINA_TRUE if it was handled, @c EINA_FALSE otherwise.
+ */
+Eina_Bool ewk_frame_feed_mouse_down(Evas_Object* o, const Evas_Event_Mouse_Down* ev)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(ev, EINA_FALSE);
+
+ WebCore::FrameView* view = sd->frame->view();
+ DBG("o=%p, view=%p, button=%d, pos=%d,%d",
+ o, view, ev->button, ev->canvas.x, ev->canvas.y);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(view, EINA_FALSE);
+
+ Evas_Coord x, y;
+ evas_object_geometry_get(sd->view, &x, &y, 0, 0);
+
+ WebCore::PlatformMouseEvent event(ev, WebCore::IntPoint(x, y));
+ return sd->frame->eventHandler()->handleMousePressEvent(event);
+}
+
+/**
+ * Feed the mouse up event to the frame.
+ *
+ * @param o frame object to feed event.
+ * @param ev mouse up event.
+ *
+ * @return @c EINA_TRUE if it was handled, @c EINA_FALSE otherwise.
+ */
+Eina_Bool ewk_frame_feed_mouse_up(Evas_Object* o, const Evas_Event_Mouse_Up* ev)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(ev, EINA_FALSE);
+
+ WebCore::FrameView* view = sd->frame->view();
+ DBG("o=%p, view=%p, button=%d, pos=%d,%d",
+ o, view, ev->button, ev->canvas.x, ev->canvas.y);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(view, EINA_FALSE);
+
+ Evas_Coord x, y;
+ evas_object_geometry_get(sd->view, &x, &y, 0, 0);
+
+ WebCore::PlatformMouseEvent event(ev, WebCore::IntPoint(x, y));
+ return sd->frame->eventHandler()->handleMouseReleaseEvent(event);
+}
+
+/**
+ * Feed the mouse move event to the frame.
+ *
+ * @param o frame object to feed event.
+ * @param ev mouse move event.
+ *
+ * @return @c EINA_TRUE if it was handled, @c EINA_FALSE otherwise.
+ */
+Eina_Bool ewk_frame_feed_mouse_move(Evas_Object* o, const Evas_Event_Mouse_Move* ev)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(ev, EINA_FALSE);
+
+ WebCore::FrameView* view = sd->frame->view();
+ DBG("o=%p, view=%p, pos: old=%d,%d, new=%d,%d, buttons=%d",
+ o, view, ev->cur.canvas.x, ev->cur.canvas.y,
+ ev->prev.canvas.x, ev->prev.canvas.y, ev->buttons);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(view, EINA_FALSE);
+
+ Evas_Coord x, y;
+ evas_object_geometry_get(sd->view, &x, &y, 0, 0);
+
+ WebCore::PlatformMouseEvent event(ev, WebCore::IntPoint(x, y));
+ return sd->frame->eventHandler()->mouseMoved(event);
+}
+
+static inline Eina_Bool _ewk_frame_handle_key_scrolling(WebCore::Frame* frame, const WebCore::PlatformKeyboardEvent &event)
+{
+ WebCore::ScrollDirection direction;
+ WebCore::ScrollGranularity granularity;
+
+ int keyCode = event.windowsVirtualKeyCode();
+
+ switch (keyCode) {
+ case WebCore::VK_SPACE:
+ granularity = WebCore::ScrollByPage;
+ if (event.shiftKey())
+ direction = WebCore::ScrollUp;
+ else
+ direction = WebCore::ScrollDown;
+ break;
+ case WebCore::VK_NEXT:
+ granularity = WebCore::ScrollByPage;
+ direction = WebCore::ScrollDown;
+ break;
+ case WebCore::VK_PRIOR:
+ granularity = WebCore::ScrollByPage;
+ direction = WebCore::ScrollUp;
+ break;
+ case WebCore::VK_HOME:
+ granularity = WebCore::ScrollByDocument;
+ direction = WebCore::ScrollUp;
+ break;
+ case WebCore::VK_END:
+ granularity = WebCore::ScrollByDocument;
+ direction = WebCore::ScrollDown;
+ break;
+ case WebCore::VK_LEFT:
+ granularity = WebCore::ScrollByLine;
+ direction = WebCore::ScrollLeft;
+ break;
+ case WebCore::VK_RIGHT:
+ granularity = WebCore::ScrollByLine;
+ direction = WebCore::ScrollRight;
+ break;
+ case WebCore::VK_UP:
+ direction = WebCore::ScrollUp;
+ if (event.ctrlKey())
+ granularity = WebCore::ScrollByDocument;
+ else
+ granularity = WebCore::ScrollByLine;
+ break;
+ case WebCore::VK_DOWN:
+ direction = WebCore::ScrollDown;
+ if (event.ctrlKey())
+ granularity = WebCore::ScrollByDocument;
+ else
+ granularity = WebCore::ScrollByLine;
+ break;
+ default:
+ return EINA_FALSE;
+ }
+
+ if (frame->eventHandler()->scrollOverflow(direction, granularity))
+ return EINA_FALSE;
+
+ frame->view()->scroll(direction, granularity);
+ return EINA_TRUE;
+}
+
+/**
+ * Feed the keyboard key down event to the frame.
+ *
+ * @param o frame object to feed event.
+ * @param ev keyboard key down event.
+ *
+ * @return @c EINA_TRUE if it was handled, @c EINA_FALSE otherwise.
+ */
+Eina_Bool ewk_frame_feed_key_down(Evas_Object* o, const Evas_Event_Key_Down* ev)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(ev, EINA_FALSE);
+
+ DBG("o=%p keyname=%s (key=%s, string=%s)",
+ o, ev->keyname, ev->key ? ev->key : "", ev->string ? ev->string : "");
+
+ WebCore::PlatformKeyboardEvent event(ev);
+ if (sd->frame->eventHandler()->keyEvent(event))
+ return EINA_TRUE;
+
+ return _ewk_frame_handle_key_scrolling(sd->frame, event);
+}
+
+/**
+ * Feed the keyboard key up event to the frame.
+ *
+ * @param o frame object to feed event.
+ * @param ev keyboard key up event.
+ *
+ * @return @c EINA_TRUE if it was handled, @c EINA_FALSE otherwise.
+ */
+Eina_Bool ewk_frame_feed_key_up(Evas_Object* o, const Evas_Event_Key_Up* ev)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(ev, EINA_FALSE);
+
+ DBG("o=%p keyname=%s (key=%s, string=%s)",
+ o, ev->keyname, ev->key ? ev->key : "", ev->string ? ev->string : "");
+
+ WebCore::PlatformKeyboardEvent event(ev);
+ return sd->frame->eventHandler()->keyEvent(event);
+}
+
+/* internal methods ****************************************************/
+
+/**
+ * @internal
+ *
+ * Initialize frame based on actual WebKit frame.
+ *
+ * This is internal and should never be called by external users.
+ */
+Eina_Bool ewk_frame_init(Evas_Object* o, Evas_Object* view, WebCore::Frame* frame)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ if (!sd->frame) {
+ WebCore::FrameLoaderClientEfl* flc = _ewk_frame_loader_efl_get(frame);
+ flc->setWebFrame(o);
+ sd->frame = frame;
+ sd->view = view;
+ frame->init();
+ return EINA_TRUE;
+ }
+
+ ERR("frame %p already set for %p, ignored new %p",
+ sd->frame, o, frame);
+ return EINA_FALSE;
+}
+
+Evas_Object* ewk_frame_child_add(Evas_Object* o, WTF::PassRefPtr<WebCore::Frame> child, const WebCore::String& name, const WebCore::KURL& url, const WebCore::String& referrer)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, 0);
+ char buf[256];
+ Evas_Object* frame;
+ WebCore::Frame* cf;
+
+ frame = ewk_frame_add(sd->base.evas);
+ if (!frame) {
+ ERR("Could not create ewk_frame object.");
+ return 0;
+ }
+
+ cf = child.get();
+ sd->frame->tree()->appendChild(child);
+ if (cf->tree())
+ cf->tree()->setName(name);
+ else
+ ERR("no tree for child object");
+
+ if (!ewk_frame_init(frame, sd->view, cf)) {
+ evas_object_del(frame);
+ return 0;
+ }
+ snprintf(buf, sizeof(buf), "EWK_Frame:child/%s", name.utf8().data());
+ evas_object_name_set(frame, buf);
+ evas_object_smart_member_add(frame, o);
+ evas_object_show(frame);
+
+ if (!cf->page())
+ goto died;
+
+ cf->loader()->loadURLIntoChildFrame(url, referrer, cf);
+ if (!cf->tree()->parent())
+ goto died;
+
+ // TODO: announce frame was created?
+ return frame;
+
+died:
+ CRITICAL("does this work: BEGIN");
+ ewk_frame_core_gone(frame); // CONFIRM
+ evas_object_del(frame); // CONFIRM
+ CRITICAL("does this work: END");
+ return 0;
+}
+
+/**
+ * @internal
+ * Frame was destroyed by loader, remove internal reference.
+ */
+void ewk_frame_core_gone(Evas_Object* o)
+{
+ DBG("o=%p", o);
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd);
+ sd->frame = 0;
+}
+
+/**
+ * @internal
+ * Retrieve WebCore::Frame associated with this object.
+ *
+ * Avoid using this call from outside, add specific ewk_frame_*
+ * actions instead.
+ */
+WebCore::Frame* ewk_frame_core_get(const Evas_Object* o)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, 0);
+ return sd->frame;
+}
+
+
+/**
+ * @internal
+ * Reports the frame started loading something.
+ *
+ * Emits signal: "load,started" with no parameters.
+ */
+void ewk_frame_load_started(Evas_Object* o)
+{
+ Evas_Object* main_frame;
+ DBG("o=%p", o);
+ evas_object_smart_callback_call(o, "load,started", 0);
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd);
+ ewk_view_load_started(sd->view);
+
+ main_frame = ewk_view_frame_main_get(sd->view);
+ if (main_frame == o)
+ ewk_view_frame_main_load_started(sd->view);
+}
+
+/**
+ * @internal
+ * Reports load finished, optionally with error information.
+ *
+ * Emits signal: "load,finished" with pointer to Ewk_Frame_Load_Error
+ * if any error, or @c NULL if successful load.
+ *
+ * @note there should notbe any error stuff here, but trying to be
+ * compatible with previous WebKit.
+ */
+void ewk_frame_load_finished(Evas_Object* o, const char* error_domain, int error_code, Eina_Bool is_cancellation, const char* error_description, const char* failing_url)
+{
+ Ewk_Frame_Load_Error buf, *error;
+ if (!error_domain) {
+ DBG("o=%p, success.", o);
+ error = 0;
+ } else {
+ DBG("o=%p, error=%s (%d, cancellation=%hhu) \"%s\", url=%s",
+ o, error_domain, error_code, is_cancellation,
+ error_description, failing_url);
+
+ buf.domain = error_domain;
+ buf.code = error_code;
+ buf.is_cancellation = is_cancellation;
+ buf.description = error_description;
+ buf.failing_url = failing_url;
+ buf.frame = o;
+ error = &buf;
+ }
+ evas_object_smart_callback_call(o, "load,finished", error);
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd);
+ ewk_view_load_finished(sd->view, error);
+}
+
+/**
+ * @internal
+ * Reports load failed with error information.
+ *
+ * Emits signal: "load,error" with pointer to Ewk_Frame_Load_Error.
+ */
+void ewk_frame_load_error(Evas_Object* o, const char* error_domain, int error_code, Eina_Bool is_cancellation, const char* error_description, const char* failing_url)
+{
+ Ewk_Frame_Load_Error error;
+
+ DBG("o=%p, error=%s (%d, cancellation=%hhu) \"%s\", url=%s",
+ o, error_domain, error_code, is_cancellation,
+ error_description, failing_url);
+
+ EINA_SAFETY_ON_NULL_RETURN(error_domain);
+
+ error.code = error_code;
+ error.is_cancellation = is_cancellation;
+ error.domain = error_domain;
+ error.description = error_description;
+ error.failing_url = failing_url;
+ error.frame = o;
+ evas_object_smart_callback_call(o, "load,error", &error);
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd);
+ ewk_view_load_error(sd->view, &error);
+}
+
+/**
+ * @internal
+ * Reports load progress changed.
+ *
+ * Emits signal: "load,progress" with pointer to a double from 0.0 to 1.0.
+ */
+void ewk_frame_load_progress_changed(Evas_Object* o)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd);
+ EINA_SAFETY_ON_NULL_RETURN(sd->frame);
+
+ // TODO: this is per page, there should be a way to have per-frame.
+ double progress = sd->frame->page()->progress()->estimatedProgress();
+
+ DBG("o=%p (p=%0.3f)", o, progress);
+
+ evas_object_smart_callback_call(o, "load,progress", &progress);
+ ewk_view_load_progress_changed(sd->view);
+}
+
+
+/**
+ * @internal
+ *
+ * Reports contents size changed.
+ */
+void ewk_frame_contents_size_changed(Evas_Object* o, Evas_Coord w, Evas_Coord h)
+{
+ DBG("o=%p: %dx%d", o, w, h);
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd);
+ if (sd->contents_size.w == w && sd->contents_size.h == h)
+ return;
+ sd->contents_size.w = w;
+ sd->contents_size.h = h;
+ // TODO: update something else internally?
+
+ Evas_Coord size[2] = {w, h};
+ evas_object_smart_callback_call(o, "contents,size,changed", size);
+}
+
+/**
+ * @internal
+ *
+ * Reports title changed.
+ */
+void ewk_frame_title_set(Evas_Object* o, const char* title)
+{
+ DBG("o=%p, title=%s", o, title ? title : "(null)");
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd);
+ if (!eina_stringshare_replace(&sd->title, title))
+ return;
+ evas_object_smart_callback_call(o, "title,changed", (void*)sd->title);
+}
+
+void ewk_frame_view_create_for_view(Evas_Object* o, Evas_Object* view)
+{
+ DBG("o=%p, view=%p", o, view);
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd);
+ EINA_SAFETY_ON_NULL_RETURN(sd->frame);
+ Evas_Coord w, h;
+
+ if (sd->frame->view())
+ return;
+
+ evas_object_geometry_get(view, 0, 0, &w, &h);
+
+ WebCore::IntSize size(w, h);
+ int r, g, b, a;
+ WebCore::Color bg;
+
+ ewk_view_bg_color_get(view, &r, &g, &b, &a);
+ if (!a)
+ bg = WebCore::Color(0, 0, 0, 0);
+ else if (a == 255)
+ bg = WebCore::Color(r, g, b, a);
+ else
+ bg = WebCore::Color(r * 255 / a, g * 255 / a, b * 255 / a, a);
+
+ sd->frame->createView(size, bg, !a, WebCore::IntSize(), false);
+ if (!sd->frame->view())
+ return;
+ sd->frame->view()->setEdjeTheme(sd->theme);
+ sd->frame->view()->setEvasObject(o);
+}
+
+/**
+ * @internal
+ * Reports uri changed and swap internal string reference.
+ *
+ * Emits signal: "uri,changed" with new uri as parameter.
+ */
+Eina_Bool ewk_frame_uri_changed(Evas_Object* o)
+{
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
+ WTF::CString uri(sd->frame->loader()->url().prettyURL().utf8());
+
+ INF("uri=%s", uri.data());
+ if (!uri.data()) {
+ ERR("no uri");
+ return EINA_FALSE;
+ }
+
+ eina_stringshare_replace(&sd->uri, uri.data());
+ evas_object_smart_callback_call(o, "uri,changed", (void*)sd->uri);
+ return EINA_TRUE;
+}
+
+void ewk_frame_force_layout(Evas_Object* o)
+{
+ DBG("o=%p", o);
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd);
+ EINA_SAFETY_ON_NULL_RETURN(sd->frame);
+ WebCore::FrameView* view = sd->frame->view();
+ if (view)
+ view->forceLayout(true);
+}
+
+WTF::PassRefPtr<WebCore::Widget> ewk_frame_plugin_create(Evas_Object* o, const WebCore::IntSize& pluginSize, WebCore::HTMLPlugInElement* element, const WebCore::KURL& url, const WTF::Vector<WebCore::String>& paramNames, const WTF::Vector<WebCore::String>& paramValues, const WebCore::String& mimeType, bool loadManually)
+{
+ DBG("o=%p, size=%dx%d, element=%p, url=%s, mimeType=%s",
+ o, pluginSize.width(), pluginSize.height(), element,
+ url.prettyURL().utf8().data(), mimeType.utf8().data());
+
+ EWK_FRAME_SD_GET_OR_RETURN(o, sd, 0);
+
+ // TODO: emit signal and ask webkit users if something else should be done.
+ // like creating another x window (see gtk, it allows users to create
+ // GtkPluginWidget.
+
+ WTF::RefPtr<WebCore::PluginView> pluginView = WebCore::PluginView::create
+ (sd->frame, pluginSize, element, url, paramNames, paramValues,
+ mimeType, loadManually);
+
+ if (pluginView->status() == WebCore::PluginStatusLoadedSuccessfully)
+ return pluginView;
+
+ return 0;
+}
diff --git a/WebKit/efl/ewk/ewk_frame.h b/WebKit/efl/ewk/ewk_frame.h
new file mode 100644
index 0000000..c71269b
--- /dev/null
+++ b/WebKit/efl/ewk/ewk_frame.h
@@ -0,0 +1,184 @@
+/*
+ Copyright (C) 2009-2010 ProFUSION embedded systems
+ Copyright (C) 2009-2010 Samsung Electronics
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef ewk_frame_h
+#define ewk_frame_h
+
+#include "ewk_eapi.h"
+#include <Evas.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @file
+ *
+ * WebKit frame smart object.
+ *
+ * This object is the low level access to WebKit-EFL browser
+ * component. It represents both the main and internal frames that
+ * HTML pages contain.
+ *
+ * Every ewk_view has at least one frame, called "main frame" and
+ * retrieved with ewk_view_frame_main_get(). One can retrieve frame's
+ * owner view with ewk_frame_view_get(). Parent frame can be retrieved
+ * with standard smart object's evas_object_smart_parent_get().
+ * Children can be accessed with ewk_frame_children_iterator_new() or
+ * ewk_frame_child_find().
+ *
+ * The following signals (see evas_object_smart_callback_add()) are emitted:
+ *
+ * - "title,changed", const char*: title of the main frame changed.
+ * - "uri,changed", const char*: uri of the main frame changed.
+ * - "load,started", void: frame started loading.
+ * - "load,progress", double*: load progress changed (overall value
+ * from 0.0 to 1.0, connect to individual frames for fine grained).
+ * - "load,finished", const Ewk_Frame_Load_Error*: reports load
+ * finished and as argument @c NULL if successfully or pointer to
+ * structure defining the error.
+ * - "load,error", const Ewk_Frame_Load_Error*: reports load failed
+ * and as argument a pointer to structure defining the error.
+ * - "contents,size,changed", Evas_Coord[2]: reports contents size
+ * changed due new layout, script actions or any other events.
+ */
+
+
+/**
+ * Structure used to report load errors.
+ *
+ * Load errors are reported as signal by ewk_view. All the strings are
+ * temporary references and should @b not be used after the signal
+ * callback returns. If required, make copies with strdup() or
+ * eina_stringshare_add() (they are not even guaranteed to be
+ * stringshared, so must use eina_stringshare_add() and not
+ * eina_stringshare_ref()).
+ */
+typedef struct _Ewk_Frame_Load_Error Ewk_Frame_Load_Error;
+struct _Ewk_Frame_Load_Error {
+ int code; /**< numeric error code */
+ Eina_Bool is_cancellation; /**< if load failed because it was canceled */
+ const char *domain; /**< error domain name */
+ const char *description; /**< error description already localized */
+ const char *failing_url; /**< the url that failed to load */
+ Evas_Object *frame; /**< frame where the failure happened */
+};
+
+/**
+ * Structure used to report hit test results.
+ */
+typedef struct _Ewk_Hit_Test Ewk_Hit_Test;
+struct _Ewk_Hit_Test {
+ int x, y;
+ struct {
+ int x, y, w, h;
+ } bounding_box;
+ const char *title;
+ const char *alternate_text; /**< for image, area, input and applet */
+ Evas_Object *frame;
+ struct {
+ const char *text;
+ const char *url;
+ const char *title;
+ Evas_Object *target_frame;
+ } link;
+ struct {
+ Eina_Bool editable:1;
+ Eina_Bool selected:1;
+ } flags;
+};
+
+
+EAPI Evas_Object *ewk_frame_view_get(const Evas_Object *o);
+EAPI void ewk_frame_theme_set(Evas_Object *o, const char *path);
+EAPI const char *ewk_frame_theme_get(Evas_Object *o);
+
+EAPI Eina_Iterator *ewk_frame_children_iterator_new(Evas_Object *o);
+EAPI Evas_Object *ewk_frame_child_find(Evas_Object *o, const char *name);
+
+EAPI Eina_Bool ewk_frame_uri_set(Evas_Object *o, const char *uri);
+EAPI const char *ewk_frame_uri_get(const Evas_Object *o);
+EAPI const char *ewk_frame_title_get(const Evas_Object *o);
+EAPI const char *ewk_frame_name_get(const Evas_Object *o);
+EAPI Eina_Bool ewk_frame_contents_size_get(const Evas_Object *o, Evas_Coord *w, Evas_Coord *h);
+
+EAPI Eina_Bool ewk_frame_contents_set(Evas_Object *o, const char *contents, size_t contents_size, const char *mime_type, const char *encoding, const char *base_uri);
+EAPI Eina_Bool ewk_frame_contents_alternate_set(Evas_Object *o, const char *contents, size_t contents_size, const char *mime_type, const char *encoding, const char *base_uri, const char *unreachable_uri);
+
+EAPI Eina_Bool ewk_frame_script_execute(Evas_Object *o, const char *script);
+
+EAPI Eina_Bool ewk_frame_editable_get(const Evas_Object *o);
+EAPI Eina_Bool ewk_frame_editable_set(Evas_Object *o, Eina_Bool editable);
+
+EAPI char *ewk_frame_selection_get(const Evas_Object *o);
+
+EAPI Eina_Bool ewk_frame_text_search(const Evas_Object *o, const char *string, Eina_Bool case_sensitive, Eina_Bool forward, Eina_Bool wrap);
+
+EAPI unsigned int ewk_frame_text_matches_mark(Evas_Object *o, const char *string, Eina_Bool case_sensitive, Eina_Bool highlight, unsigned int limit);
+EAPI Eina_Bool ewk_frame_text_matches_unmark_all(Evas_Object *o);
+EAPI Eina_Bool ewk_frame_text_matches_highlight_set(Evas_Object *o, Eina_Bool highlight);
+EAPI Eina_Bool ewk_frame_text_matches_highlight_get(const Evas_Object *o);
+
+EAPI Eina_Bool ewk_frame_stop(Evas_Object *o);
+EAPI Eina_Bool ewk_frame_reload(Evas_Object *o);
+EAPI Eina_Bool ewk_frame_reload_full(Evas_Object *o);
+
+EAPI Eina_Bool ewk_frame_back(Evas_Object *o);
+EAPI Eina_Bool ewk_frame_forward(Evas_Object *o);
+EAPI Eina_Bool ewk_frame_navigate(Evas_Object *o, int steps);
+
+EAPI Eina_Bool ewk_frame_back_possible(Evas_Object *o);
+EAPI Eina_Bool ewk_frame_forward_possible(Evas_Object *o);
+EAPI Eina_Bool ewk_frame_navigate_possible(Evas_Object *o, int steps);
+
+EAPI float ewk_frame_zoom_get(const Evas_Object *o);
+EAPI Eina_Bool ewk_frame_zoom_set(Evas_Object *o, float zoom);
+EAPI Eina_Bool ewk_frame_zoom_text_only_get(const Evas_Object *o);
+EAPI Eina_Bool ewk_frame_zoom_text_only_set(Evas_Object *o, Eina_Bool setting);
+
+EAPI void ewk_frame_hit_test_free(Ewk_Hit_Test *hit_test);
+EAPI Ewk_Hit_Test *ewk_frame_hit_test_new(const Evas_Object *o, int x, int y);
+
+EAPI Eina_Bool ewk_frame_scroll_add(Evas_Object *o, int dx, int dy);
+EAPI Eina_Bool ewk_frame_scroll_set(Evas_Object *o, int x, int y);
+
+EAPI Eina_Bool ewk_frame_scroll_size_get(const Evas_Object *o, int *w, int *h);
+EAPI Eina_Bool ewk_frame_scroll_pos_get(const Evas_Object *o, int *x, int *y);
+
+EAPI Eina_Bool ewk_frame_visible_content_geometry_get(const Evas_Object *o, Eina_Bool include_scrollbars, int *x, int *y, int *w, int *h);
+
+EAPI Eina_Bool ewk_frame_paint_full_get(const Evas_Object *o);
+EAPI void ewk_frame_paint_full_set(Evas_Object *o, Eina_Bool flag);
+
+EAPI Eina_Bool ewk_frame_feed_focus_in(Evas_Object *o);
+EAPI Eina_Bool ewk_frame_feed_focus_out(Evas_Object *o);
+
+EAPI Eina_Bool ewk_frame_feed_mouse_wheel(Evas_Object *o, const Evas_Event_Mouse_Wheel *ev);
+EAPI Eina_Bool ewk_frame_feed_mouse_down(Evas_Object *o, const Evas_Event_Mouse_Down *ev);
+EAPI Eina_Bool ewk_frame_feed_mouse_up(Evas_Object *o, const Evas_Event_Mouse_Up *ev);
+EAPI Eina_Bool ewk_frame_feed_mouse_move(Evas_Object *o, const Evas_Event_Mouse_Move *ev);
+EAPI Eina_Bool ewk_frame_feed_key_down(Evas_Object *o, const Evas_Event_Key_Down *ev);
+EAPI Eina_Bool ewk_frame_feed_key_up(Evas_Object *o, const Evas_Event_Key_Up *ev);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif // ewk_frame_h
diff --git a/WebKit/efl/ewk/ewk_history.cpp b/WebKit/efl/ewk/ewk_history.cpp
new file mode 100644
index 0000000..da48c33
--- /dev/null
+++ b/WebKit/efl/ewk/ewk_history.cpp
@@ -0,0 +1,704 @@
+/*
+ Copyright (C) 2009-2010 ProFUSION embedded systems
+ Copyright (C) 2009-2010 Samsung Electronics
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+#include "ewk_history.h"
+
+#include "BackForwardList.h"
+#include "EWebKit.h"
+#include "HistoryItem.h"
+#include "Image.h"
+#include "ewk_private.h"
+#include <wtf/text/CString.h>
+
+#include <Eina.h>
+#include <eina_safety_checks.h>
+
+struct _Ewk_History {
+ WebCore::BackForwardList *core;
+};
+
+#define EWK_HISTORY_CORE_GET_OR_RETURN(history, core_, ...) \
+ if (!(history)) { \
+ CRITICAL("history is NULL."); \
+ return __VA_ARGS__; \
+ } \
+ if (!(history)->core) { \
+ CRITICAL("history->core is NULL."); \
+ return __VA_ARGS__; \
+ } \
+ if (!(history)->core->enabled()) { \
+ ERR("history->core is disabled!."); \
+ return __VA_ARGS__; \
+ } \
+ WebCore::BackForwardList *core_ = (history)->core
+
+
+struct _Ewk_History_Item {
+ WebCore::HistoryItem *core;
+
+ const char *title;
+ const char *alternate_title;
+ const char *uri;
+ const char *original_uri;
+};
+
+#define EWK_HISTORY_ITEM_CORE_GET_OR_RETURN(item, core_, ...) \
+ if (!(item)) { \
+ CRITICAL("item is NULL."); \
+ return __VA_ARGS__; \
+ } \
+ if (!(item)->core) { \
+ CRITICAL("item->core is NULL."); \
+ return __VA_ARGS__; \
+ } \
+ WebCore::HistoryItem *core_ = (item)->core
+
+
+static inline Ewk_History_Item *_ewk_history_item_new(WebCore::HistoryItem *core)
+{
+ Ewk_History_Item* item;
+
+ if (!core) {
+ ERR("WebCore::HistoryItem is NULL.");
+ return 0;
+ }
+
+ item = (Ewk_History_Item *)calloc(1, sizeof(Ewk_History_Item));
+ if (!item) {
+ CRITICAL("Could not allocate item memory.");
+ return 0;
+ }
+
+ core->ref();
+ item->core = core;
+
+ return item;
+}
+
+static inline Eina_List *_ewk_history_item_list_get(const WebCore::HistoryItemVector &core_items)
+{
+ Eina_List* ret = 0;
+ unsigned int i, size;
+
+ size = core_items.size();
+ for (i = 0; i < size; i++) {
+ Ewk_History_Item* item = _ewk_history_item_new(core_items[i].get());
+ if (item)
+ ret = eina_list_append(ret, item);
+ }
+
+ return ret;
+}
+
+/**
+ * Go forward in history one item, if possible.
+ *
+ * @param history which history instance to modify.
+ *
+ * @return @c EINA_TRUE on success, @c EINA_FALSE on failure.
+ */
+Eina_Bool ewk_history_forward(Ewk_History* history)
+{
+ EWK_HISTORY_CORE_GET_OR_RETURN(history, core, EINA_FALSE);
+ if (core->forwardListCount() < 1)
+ return EINA_FALSE;
+ core->goForward();
+ return EINA_TRUE;
+}
+
+/**
+ * Go back in history one item, if possible.
+ *
+ * @param history which history instance to modify.
+ *
+ * @return @c EINA_TRUE on success, @c EINA_FALSE on failure.
+ */
+Eina_Bool ewk_history_back(Ewk_History* history)
+{
+ EWK_HISTORY_CORE_GET_OR_RETURN(history, core, EINA_FALSE);
+ if (core->backListCount() < 1)
+ return EINA_FALSE;
+ core->goBack();
+ return EINA_TRUE;
+}
+
+/**
+ * Adds the given item to history.
+ *
+ * Memory handling: This will not modify or even take references to
+ * given item (Ewk_History_Item), so you should still handle it with
+ * ewk_history_item_free().
+ *
+ * @param history which history instance to modify.
+ * @param item reference to add to history. Unmodified. Must @b not be @c NULL.
+ *
+ * @return @c EINA_TRUE on success, @c EINA_FALSE on failure.
+ */
+Eina_Bool ewk_history_history_item_add(Ewk_History* history, const Ewk_History_Item* item)
+{
+ EWK_HISTORY_CORE_GET_OR_RETURN(history, history_core, EINA_FALSE);
+ EWK_HISTORY_ITEM_CORE_GET_OR_RETURN(item, item_core, EINA_FALSE);
+ history_core->addItem(item_core);
+ return EINA_TRUE;
+}
+
+/**
+ * Sets the given item as current in history (go to item).
+ *
+ * Memory handling: This will not modify or even take references to
+ * given item (Ewk_History_Item), so you should still handle it with
+ * ewk_history_item_free().
+ *
+ * @param history which history instance to modify.
+ * @param item reference to go to history. Unmodified. Must @b not be @c NULL.
+ *
+ * @return @c EINA_TRUE on success, @c EINA_FALSE on failure.
+ */
+Eina_Bool ewk_history_history_item_set(Ewk_History* history, const Ewk_History_Item* item)
+{
+ EWK_HISTORY_CORE_GET_OR_RETURN(history, history_core, EINA_FALSE);
+ EWK_HISTORY_ITEM_CORE_GET_OR_RETURN(item, item_core, EINA_FALSE);
+ history_core->goToItem(item_core);
+ return EINA_TRUE;
+}
+
+/**
+ * Get the first item from back list, if any.
+ *
+ * @param history which history instance to query.
+ *
+ * @return the @b newly allocated item instance. This memory must be
+ * released with ewk_history_item_free() after use.
+ */
+Ewk_History_Item* ewk_history_history_item_back_get(const Ewk_History* history)
+{
+ EWK_HISTORY_CORE_GET_OR_RETURN(history, core, 0);
+ return _ewk_history_item_new(core->backItem());
+}
+
+/**
+ * Get the current item in history, if any.
+ *
+ * @param history which history instance to query.
+ *
+ * @return the @b newly allocated item instance. This memory must be
+ * released with ewk_history_item_free() after use.
+ */
+Ewk_History_Item* ewk_history_history_item_current_get(const Ewk_History* history)
+{
+ EWK_HISTORY_CORE_GET_OR_RETURN(history, core, 0);
+ return _ewk_history_item_new(core->currentItem());
+}
+
+/**
+ * Get the first item from forward list, if any.
+ *
+ * @param history which history instance to query.
+ *
+ * @return the @b newly allocated item instance. This memory must be
+ * released with ewk_history_item_free() after use.
+ */
+Ewk_History_Item* ewk_history_history_item_forward_get(const Ewk_History* history)
+{
+ EWK_HISTORY_CORE_GET_OR_RETURN(history, core, 0);
+ return _ewk_history_item_new(core->forwardItem());
+}
+
+/**
+ * Get item at given position, if any at that index.
+ *
+ * @param history which history instance to query.
+ * @param index position of item to get.
+ *
+ * @return the @b newly allocated item instance. This memory must be
+ * released with ewk_history_item_free() after use.
+ */
+Ewk_History_Item* ewk_history_history_item_nth_get(const Ewk_History* history, int index)
+{
+ EWK_HISTORY_CORE_GET_OR_RETURN(history, core, 0);
+ return _ewk_history_item_new(core->itemAtIndex(index));
+}
+
+/**
+ * Queries if given item is in history.
+ *
+ * Memory handling: This will not modify or even take references to
+ * given item (Ewk_History_Item), so you should still handle it with
+ * ewk_history_item_free().
+ *
+ * @param history which history instance to modify.
+ * @param item reference to check in history. Must @b not be @c NULL.
+ *
+ * @return @c EINA_TRUE if in history, @c EINA_FALSE if not or failure.
+ */
+Eina_Bool ewk_history_history_item_contains(const Ewk_History* history, const Ewk_History_Item* item)
+{
+ EWK_HISTORY_CORE_GET_OR_RETURN(history, history_core, EINA_FALSE);
+ EWK_HISTORY_ITEM_CORE_GET_OR_RETURN(item, item_core, EINA_FALSE);
+ return history_core->containsItem(item_core);
+}
+
+/**
+ * Get the whole forward list.
+ *
+ * @param history which history instance to query.
+ *
+ * @return a newly allocated list of @b newly allocated item
+ * instance. This memory of each item must be released with
+ * ewk_history_item_free() after use. use
+ * ewk_history_item_list_free() for convenience.
+ *
+ * @see ewk_history_item_list_free()
+ * @see ewk_history_forward_list_get_with_limit()
+ */
+Eina_List* ewk_history_forward_list_get(const Ewk_History* history)
+{
+ EWK_HISTORY_CORE_GET_OR_RETURN(history, core, 0);
+ WebCore::HistoryItemVector items;
+ int limit = core->forwardListCount();
+ core->forwardListWithLimit(limit, items);
+ return _ewk_history_item_list_get(items);
+}
+
+/**
+ * Get the forward list within the given limit.
+ *
+ * @param history which history instance to query.
+ * @param limit the maximum number of items to return.
+ *
+ * @return a newly allocated list of @b newly allocated item
+ * instance. This memory of each item must be released with
+ * ewk_history_item_free() after use. use
+ * ewk_history_item_list_free() for convenience.
+ *
+ * @see ewk_history_item_list_free()
+ * @see ewk_history_forward_list_length()
+ * @see ewk_history_forward_list_get()
+ */
+Eina_List* ewk_history_forward_list_get_with_limit(const Ewk_History* history, int limit)
+{
+ EWK_HISTORY_CORE_GET_OR_RETURN(history, core, 0);
+ WebCore::HistoryItemVector items;
+ core->forwardListWithLimit(limit, items);
+ return _ewk_history_item_list_get(items);
+}
+
+/**
+ * Get the whole size of forward list.
+ *
+ * @param history which history instance to query.
+ *
+ * @return number of elements in whole list.
+ *
+ * @see ewk_history_forward_list_get_with_limit()
+ */
+int ewk_history_forward_list_length(const Ewk_History* history)
+{
+ EWK_HISTORY_CORE_GET_OR_RETURN(history, core, 0);
+ return core->forwardListCount();
+}
+
+/**
+ * Get the whole back list.
+ *
+ * @param history which history instance to query.
+ *
+ * @return a newly allocated list of @b newly allocated item
+ * instance. This memory of each item must be released with
+ * ewk_history_item_free() after use. use
+ * ewk_history_item_list_free() for convenience.
+ *
+ * @see ewk_history_item_list_free()
+ * @see ewk_history_back_list_get_with_limit()
+ */
+Eina_List* ewk_history_back_list_get(const Ewk_History* history)
+{
+ EWK_HISTORY_CORE_GET_OR_RETURN(history, core, 0);
+ WebCore::HistoryItemVector items;
+ int limit = core->backListCount();
+ core->backListWithLimit(limit, items);
+ return _ewk_history_item_list_get(items);
+}
+
+/**
+ * Get the back list within the given limit.
+ *
+ * @param history which history instance to query.
+ * @param limit the maximum number of items to return.
+ *
+ * @return a newly allocated list of @b newly allocated item
+ * instance. This memory of each item must be released with
+ * ewk_history_item_free() after use. use
+ * ewk_history_item_list_free() for convenience.
+ *
+ * @see ewk_history_item_list_free()
+ * @see ewk_history_back_list_length()
+ * @see ewk_history_back_list_get()
+ */
+Eina_List* ewk_history_back_list_get_with_limit(const Ewk_History* history, int limit)
+{
+ EWK_HISTORY_CORE_GET_OR_RETURN(history, core, 0);
+ WebCore::HistoryItemVector items;
+ core->backListWithLimit(limit, items);
+ return _ewk_history_item_list_get(items);
+}
+
+/**
+ * Get the whole size of back list.
+ *
+ * @param history which history instance to query.
+ *
+ * @return number of elements in whole list.
+ *
+ * @see ewk_history_back_list_get_with_limit()
+ */
+int ewk_history_back_list_length(const Ewk_History* history)
+{
+ EWK_HISTORY_CORE_GET_OR_RETURN(history, core, 0);
+ return core->backListCount();
+}
+
+/**
+ * Get maximum capacity of given history.
+ *
+ * @param history which history instance to query.
+ *
+ * @return maximum number of entries this history will hold.
+ */
+int ewk_history_limit_get(Ewk_History* history)
+{
+ EWK_HISTORY_CORE_GET_OR_RETURN(history, core, 0);
+ return core->capacity();
+}
+
+/**
+ * Set maximum capacity of given history.
+ *
+ * @param history which history instance to modify.
+ * @param limit maximum size to allow.
+ *
+ * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
+ */
+Eina_Bool ewk_history_limit_set(const Ewk_History* history, int limit)
+{
+ EWK_HISTORY_CORE_GET_OR_RETURN(history, core, EINA_FALSE);
+ core->setCapacity(limit);
+ return EINA_TRUE;
+}
+
+/**
+ * Create a new history item with given URI and title.
+ *
+ * @param uri where this resource is located.
+ * @param title resource title.
+ *
+ * @return newly allocated history item or @c NULL on errors. You must
+ * free this item with ewk_history_item_free().
+ */
+Ewk_History_Item* ewk_history_item_new(const char* uri, const char* title)
+{
+ WebCore::String u = WebCore::String::fromUTF8(uri);
+ WebCore::String t = WebCore::String::fromUTF8(title);
+ WTF::RefPtr<WebCore::HistoryItem> core = WebCore::HistoryItem::create(u, t, 0);
+ Ewk_History_Item* item = _ewk_history_item_new(core.release().releaseRef());
+ return item;
+}
+
+static inline void _ewk_history_item_free(Ewk_History_Item* item, WebCore::HistoryItem* core)
+{
+ core->deref();
+ free(item);
+}
+
+/**
+ * Free given history item instance.
+ *
+ * @param item what to free.
+ */
+void ewk_history_item_free(Ewk_History_Item* item)
+{
+ EWK_HISTORY_ITEM_CORE_GET_OR_RETURN(item, core);
+ _ewk_history_item_free(item, core);
+}
+
+/**
+ * Free given list and associated history items instances.
+ *
+ * @param history_items list of items to free (both list nodes and
+ * item instances).
+ */
+void ewk_history_item_list_free(Eina_List* history_items)
+{
+ void* d;
+ EINA_LIST_FREE(history_items, d) {
+ Ewk_History_Item* item = (Ewk_History_Item*)d;
+ _ewk_history_item_free(item, item->core);
+ }
+}
+
+/**
+ * Query title for given history item.
+ *
+ * @param item history item to query.
+ *
+ * @return the title pointer, that may be @c NULL. This pointer is
+ * guaranteed to be eina_stringshare, so whenever possible
+ * save yourself some cpu cycles and use
+ * eina_stringshare_ref() instead of eina_stringshare_add() or
+ * strdup().
+ */
+const char* ewk_history_item_title_get(const Ewk_History_Item* item)
+{
+ EWK_HISTORY_ITEM_CORE_GET_OR_RETURN(item, core, 0);
+ // hide the following optimzation from outside
+ Ewk_History_Item* i = (Ewk_History_Item*)item;
+ eina_stringshare_replace(&i->title, core->title().utf8().data());
+ return i->title;
+}
+
+/**
+ * Query alternate title for given history item.
+ *
+ * @param item history item to query.
+ *
+ * @return the alternate title pointer, that may be @c NULL. This
+ * pointer is guaranteed to be eina_stringshare, so whenever
+ * possible save yourself some cpu cycles and use
+ * eina_stringshare_ref() instead of eina_stringshare_add() or
+ * strdup().
+ */
+const char* ewk_history_item_title_alternate_get(const Ewk_History_Item* item)
+{
+ EWK_HISTORY_ITEM_CORE_GET_OR_RETURN(item, core, 0);
+ // hide the following optimzation from outside
+ Ewk_History_Item* i = (Ewk_History_Item*)item;
+ eina_stringshare_replace(&i->alternate_title,
+ core->alternateTitle().utf8().data());
+ return i->alternate_title;
+}
+
+/**
+ * Set alternate title for given history item.
+ *
+ * @param item history item to query.
+ * @param title new alternate title to use for given item. No
+ * references are kept after this function returns.
+ */
+void ewk_history_item_title_alternate_set(Ewk_History_Item* item, const char* title)
+{
+ EWK_HISTORY_ITEM_CORE_GET_OR_RETURN(item, core);
+ if (!eina_stringshare_replace(&item->alternate_title, title))
+ return;
+ core->setAlternateTitle(WebCore::String::fromUTF8(title));
+}
+
+/**
+ * Query URI for given history item.
+ *
+ * @param item history item to query.
+ *
+ * @return the URI pointer, that may be @c NULL. This pointer is
+ * guaranteed to be eina_stringshare, so whenever possible
+ * save yourself some cpu cycles and use
+ * eina_stringshare_ref() instead of eina_stringshare_add() or
+ * strdup().
+ */
+const char* ewk_history_item_uri_get(const Ewk_History_Item* item)
+{
+ EWK_HISTORY_ITEM_CORE_GET_OR_RETURN(item, core, 0);
+ // hide the following optimzation from outside
+ Ewk_History_Item* i = (Ewk_History_Item*)item;
+ eina_stringshare_replace(&i->uri, core->urlString().utf8().data());
+ return i->uri;
+}
+
+/**
+ * Query original URI for given history item.
+ *
+ * @param item history item to query.
+ *
+ * @return the original URI pointer, that may be @c NULL. This pointer
+ * is guaranteed to be eina_stringshare, so whenever possible
+ * save yourself some cpu cycles and use
+ * eina_stringshare_ref() instead of eina_stringshare_add() or
+ * strdup().
+ */
+const char* ewk_history_item_uri_original_get(const Ewk_History_Item* item)
+{
+ EWK_HISTORY_ITEM_CORE_GET_OR_RETURN(item, core, 0);
+ // hide the following optimzation from outside
+ Ewk_History_Item* i = (Ewk_History_Item*)item;
+ eina_stringshare_replace(&i->original_uri,
+ core->originalURLString().utf8().data());
+ return i->original_uri;
+}
+
+/**
+ * Query last visited time for given history item.
+ *
+ * @param item history item to query.
+ *
+ * @return the time in seconds this item was visited.
+ */
+double ewk_history_item_time_last_visited_get(const Ewk_History_Item* item)
+{
+ EWK_HISTORY_ITEM_CORE_GET_OR_RETURN(item, core, 0.0);
+ return core->lastVisitedTime();
+}
+
+/**
+ * Get the icon (aka favicon) associated with this history item.
+ *
+ * @note in order to have this working, one must open icon database
+ * with ewk_settings_icon_database_path_set().
+ *
+ * @param item history item to query.
+ *
+ * @return the surface reference or @c NULL on errors. Note that the
+ * reference may be to a standard fallback icon.
+ */
+cairo_surface_t* ewk_history_item_icon_surface_get(const Ewk_History_Item* item)
+{
+ EWK_HISTORY_ITEM_CORE_GET_OR_RETURN(item, core, 0);
+ WebCore::Image* icon = core->icon();
+ if (!icon) {
+ ERR("icon is NULL.");
+ return 0;
+ }
+ return icon->nativeImageForCurrentFrame();
+}
+
+/**
+ * Add an Evas_Object of type 'image' to given canvas with history item icon.
+ *
+ * This is an utility function that creates an Evas_Object of type
+ * image set to have fill always match object size
+ * (evas_object_image_filled_add()), saving some code to use it from Evas.
+ *
+ * @note in order to have this working, one must open icon database
+ * with ewk_settings_icon_database_path_set().
+ *
+ * @param item history item to query.
+ * @param canvas evas instance where to add resulting object.
+ *
+ * @return newly allocated Evas_Object instance or @c NULL on
+ * errors. Delete the object with evas_object_del().
+ */
+Evas_Object* ewk_history_item_icon_object_add(const Ewk_History_Item* item, Evas* canvas)
+{
+ EWK_HISTORY_ITEM_CORE_GET_OR_RETURN(item, core, 0);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(canvas, 0);
+ WebCore::Image* icon = core->icon();
+ cairo_surface_t* surface;
+
+ if (!icon) {
+ ERR("icon is NULL.");
+ return 0;
+ }
+
+ surface = icon->nativeImageForCurrentFrame();
+ return ewk_util_image_from_cairo_surface_add(canvas, surface);
+}
+
+/**
+ * Query if given item is still in page cache.
+ *
+ * @param item history item to query.
+ *
+ * @return @c EINA_TRUE if in cache, @c EINA_FALSE otherwise.
+ */
+Eina_Bool ewk_history_item_page_cache_exists(const Ewk_History_Item* item)
+{
+ EWK_HISTORY_ITEM_CORE_GET_OR_RETURN(item, core, EINA_FALSE);
+ return core->isInPageCache();
+}
+
+/**
+ * Query number of times item was visited.
+ *
+ * @param item history item to query.
+ *
+ * @return number of visits.
+ */
+int ewk_history_item_visit_count(const Ewk_History_Item* item)
+{
+ EWK_HISTORY_ITEM_CORE_GET_OR_RETURN(item, core, 0);
+ return core->visitCount();
+}
+
+/**
+ * Query if last visit to item was failure or not.
+ *
+ * @param item history item to query.
+ *
+ * @return @c EINA_TRUE if last visit was failure, @c EINA_FALSE if it
+ * was fine.
+ */
+Eina_Bool ewk_history_item_visit_last_failed(const Ewk_History_Item* item)
+{
+ EWK_HISTORY_ITEM_CORE_GET_OR_RETURN(item, core, EINA_TRUE);
+ return core->lastVisitWasFailure();
+}
+
+
+/* internal methods ****************************************************/
+/**
+ * @internal
+ *
+ * Creates history for given view. Called internally by ewk_view and
+ * should never be called from outside.
+ *
+ * @param core WebCore::BackForwardList instance to use internally.
+ *
+ * @return newly allocated history instance or @c NULL on errors.
+ */
+Ewk_History* ewk_history_new(WebCore::BackForwardList* core)
+{
+ Ewk_History* history;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(core, 0);
+ DBG("core=%p", core);
+
+ history = (Ewk_History*)malloc(sizeof(Ewk_History));
+ if (!history) {
+ CRITICAL("Could not allocate history memory.");
+ return 0;
+ }
+
+ core->ref();
+ history->core = core;
+
+ return history;
+}
+
+/**
+ * @internal
+ *
+ * Destroys previously allocated history instance. This is called
+ * automatically by ewk_view and should never be called from outside.
+ *
+ * @param history instance to free
+ */
+void ewk_history_free(Ewk_History* history)
+{
+ DBG("history=%p", history);
+ history->core->deref();
+ free(history);
+}
diff --git a/WebKit/efl/ewk/ewk_history.h b/WebKit/efl/ewk/ewk_history.h
new file mode 100644
index 0000000..3943d7e
--- /dev/null
+++ b/WebKit/efl/ewk/ewk_history.h
@@ -0,0 +1,96 @@
+/*
+ Copyright (C) 2009-2010 ProFUSION embedded systems
+ Copyright (C) 2009-2010 Samsung Electronics
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef ewk_history_h
+#define ewk_history_h
+
+#include "ewk_eapi.h"
+
+#include <Eina.h>
+#include <Evas.h>
+#include <cairo.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * The history (back-forward list) associated with a given ewk_view.
+ *
+ * Changing the history affects immediately the view, changing the
+ * current uri, for example.
+ *
+ * When ewk_view is navigated or uris are set, history automatically
+ * updates. That's why no direct access to history structure is
+ * allowed.
+ */
+typedef struct _Ewk_History Ewk_History;
+
+/**
+ * Represents one item from Ewk_History.
+ */
+typedef struct _Ewk_History_Item Ewk_History_Item;
+
+
+
+EAPI Eina_Bool ewk_history_forward(Ewk_History *history);
+EAPI Eina_Bool ewk_history_back(Ewk_History *history);
+
+EAPI Eina_Bool ewk_history_history_item_add(Ewk_History *history, const Ewk_History_Item *item);
+EAPI Eina_Bool ewk_history_history_item_set(Ewk_History *history, const Ewk_History_Item *item);
+EAPI Ewk_History_Item *ewk_history_history_item_back_get(const Ewk_History *history);
+EAPI Ewk_History_Item *ewk_history_history_item_current_get(const Ewk_History *history);
+EAPI Ewk_History_Item *ewk_history_history_item_forward_get(const Ewk_History *history);
+EAPI Ewk_History_Item *ewk_history_history_item_nth_get(const Ewk_History *history, int index);
+EAPI Eina_Bool ewk_history_history_item_contains(const Ewk_History *history, const Ewk_History_Item *item);
+
+EAPI Eina_List *ewk_history_forward_list_get(const Ewk_History *history);
+EAPI Eina_List *ewk_history_forward_list_get_with_limit(const Ewk_History *history, int limit);
+EAPI int ewk_history_forward_list_length(const Ewk_History *history);
+
+EAPI Eina_List *ewk_history_back_list_get(const Ewk_History *history);
+EAPI Eina_List *ewk_history_back_list_get_with_limit(const Ewk_History *history, int limit);
+EAPI int ewk_history_back_list_length(const Ewk_History *history);
+
+EAPI int ewk_history_limit_get(Ewk_History *history);
+EAPI Eina_Bool ewk_history_limit_set(const Ewk_History *history, int limit);
+
+EAPI Ewk_History_Item *ewk_history_item_new(const char *uri, const char *title);
+EAPI void ewk_history_item_free(Ewk_History_Item *item);
+EAPI void ewk_history_item_list_free(Eina_List *history_items);
+
+EAPI const char *ewk_history_item_title_get(const Ewk_History_Item *item);
+EAPI const char *ewk_history_item_title_alternate_get(const Ewk_History_Item *item);
+EAPI void ewk_history_item_title_alternate_set(Ewk_History_Item *item, const char *title);
+EAPI const char *ewk_history_item_uri_get(const Ewk_History_Item *item);
+EAPI const char *ewk_history_item_uri_original_get(const Ewk_History_Item *item);
+EAPI double ewk_history_item_time_last_visited_get(const Ewk_History_Item *item);
+
+EAPI cairo_surface_t *ewk_history_item_icon_surface_get(const Ewk_History_Item *item);
+EAPI Evas_Object *ewk_history_item_icon_object_add(const Ewk_History_Item *item, Evas *canvas);
+
+EAPI Eina_Bool ewk_history_item_page_cache_exists(const Ewk_History_Item *item);
+EAPI int ewk_history_item_visit_count(const Ewk_History_Item *item);
+EAPI Eina_Bool ewk_history_item_visit_last_failed(const Ewk_History_Item *item);
+
+#ifdef __cplusplus
+}
+#endif
+#endif // ewk_history_h
diff --git a/WebKit/efl/ewk/ewk_logging.h b/WebKit/efl/ewk/ewk_logging.h
new file mode 100644
index 0000000..045bd9c
--- /dev/null
+++ b/WebKit/efl/ewk/ewk_logging.h
@@ -0,0 +1,31 @@
+/*
+ Copyright (C) 2009-2010 ProFUSION embedded systems
+ Copyright (C) 2009-2010 Samsung Electronics
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef ewk_logging_h
+#define ewk_logging_h
+
+extern int _ewk_log_dom;
+#define CRITICAL(...) EINA_LOG_DOM_CRIT(_ewk_log_dom, __VA_ARGS__)
+#define ERR(...) EINA_LOG_DOM_ERR(_ewk_log_dom, __VA_ARGS__)
+#define WRN(...) EINA_LOG_DOM_WARN(_ewk_log_dom, __VA_ARGS__)
+#define INF(...) EINA_LOG_DOM_INFO(_ewk_log_dom, __VA_ARGS__)
+#define DBG(...) EINA_LOG_DOM_DBG(_ewk_log_dom, __VA_ARGS__)
+
+#endif // ewk_logging_h
diff --git a/WebKit/efl/ewk/ewk_main.cpp b/WebKit/efl/ewk/ewk_main.cpp
new file mode 100644
index 0000000..2c69b36
--- /dev/null
+++ b/WebKit/efl/ewk/ewk_main.cpp
@@ -0,0 +1,152 @@
+/*
+ Copyright (C) 2009-2010 ProFUSION embedded systems
+ Copyright (C) 2009-2010 Samsung Electronics
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+#include "ewk_main.h"
+
+#include "EWebKit.h"
+#include "Logging.h"
+#include "PageCache.h"
+#include "PageGroup.h"
+#include "ewk_private.h"
+#include "runtime/InitializeThreading.h"
+
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Edje.h>
+#include <Eina.h>
+#include <Evas.h>
+
+#ifdef ENABLE_GLIB_SUPPORT
+#include <glib-object.h>
+#include <glib.h>
+
+#ifdef ENABLE_GTK_PLUGINS_SUPPORT
+#include <gtk/gtk.h>
+#endif
+
+#endif
+
+// REMOVE-ME: see todo below
+#include "ResourceHandle.h"
+#include <libsoup/soup.h>
+
+static int _ewk_init_count = 0;
+int _ewk_log_dom = -1;
+
+int ewk_init(void)
+{
+ if (_ewk_init_count)
+ return ++_ewk_init_count;
+
+ if (!eina_init())
+ goto error_eina;
+
+ _ewk_log_dom = eina_log_domain_register("ewebkit", EINA_COLOR_ORANGE);
+ if (_ewk_log_dom < 0) {
+ EINA_LOG_CRIT("could not register log domain 'ewebkit'");
+ goto error_log_domain;
+ }
+
+ if (!evas_init()) {
+ CRITICAL("could not init evas.");
+ goto error_evas;
+ }
+
+ if (!ecore_init()) {
+ CRITICAL("could not init ecore.");
+ goto error_ecore;
+ }
+
+ if (!ecore_evas_init()) {
+ CRITICAL("could not init ecore_evas.");
+ goto error_ecore_evas;
+ }
+
+ if (!edje_init()) {
+ CRITICAL("could not init edje.");
+ goto error_edje;
+ }
+
+#ifdef ENABLE_GLIB_SUPPORT
+ g_type_init();
+
+ if (!g_thread_supported())
+ g_thread_init(0);
+
+#ifdef ENABLE_GTK_PLUGINS_SUPPORT
+ gdk_threads_init();
+ if (!gtk_init_check(0, 0))
+ WRN("Could not initialize GTK support.");
+#endif
+
+ if (!ecore_main_loop_glib_integrate())
+ WRN("Ecore was not compiled with GLib support, some plugins will not "
+ "work (ie: Adobe Flash)");
+#endif
+
+ JSC::initializeThreading();
+ WebCore::InitializeLoggingChannelsIfNecessary();
+
+ // Page cache capacity (in pages). Comment from Mac port:
+ // (Research indicates that value / page drops substantially after 3 pages.)
+ // FIXME: Expose this with an API and/or calculate based on available resources
+ WebCore::pageCache()->setCapacity(3);
+ WebCore::PageGroup::setShouldTrackVisitedLinks(true);
+
+ // TODO: this should move to WebCore, already reported to webkit-gtk folks:
+ if (1) {
+ SoupSession* session = WebCore::ResourceHandle::defaultSession();
+ soup_session_add_feature_by_type(session, SOUP_TYPE_CONTENT_SNIFFER);
+ }
+
+ return ++_ewk_init_count;
+
+error_edje:
+ ecore_evas_shutdown();
+error_ecore_evas:
+ ecore_shutdown();
+error_ecore:
+ evas_shutdown();
+error_evas:
+ eina_log_domain_unregister(_ewk_log_dom);
+ _ewk_log_dom = -1;
+error_log_domain:
+ eina_shutdown();
+error_eina:
+ return 0;
+}
+
+int ewk_shutdown(void)
+{
+ _ewk_init_count--;
+ if (_ewk_init_count)
+ return _ewk_init_count;
+
+ ecore_evas_shutdown();
+ ecore_shutdown();
+ evas_shutdown();
+ eina_log_domain_unregister(_ewk_log_dom);
+ _ewk_log_dom = -1;
+ eina_shutdown();
+
+ return 0;
+}
+
diff --git a/WebKit/efl/ewk/ewk_main.h b/WebKit/efl/ewk/ewk_main.h
new file mode 100644
index 0000000..3730e88
--- /dev/null
+++ b/WebKit/efl/ewk/ewk_main.h
@@ -0,0 +1,36 @@
+/*
+ Copyright (C) 2009-2010 ProFUSION embedded systems
+ Copyright (C) 2009-2010 Samsung Electronics
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef ewk_main_h
+#define ewk_main_h
+
+#include "ewk_eapi.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EAPI int ewk_init(void);
+EAPI int ewk_shutdown(void);
+
+#ifdef __cplusplus
+}
+#endif
+#endif // ewk_main_h
diff --git a/WebKit/efl/ewk/ewk_private.h b/WebKit/efl/ewk/ewk_private.h
new file mode 100644
index 0000000..947bd79
--- /dev/null
+++ b/WebKit/efl/ewk/ewk_private.h
@@ -0,0 +1,115 @@
+/*
+ Copyright (C) 2009-2010 ProFUSION embedded systems
+ Copyright (C) 2009-2010 Samsung Electronics
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef ewk_private_h
+#define ewk_private_h
+
+#include "BackForwardList.h"
+#include "EWebKit.h"
+#include "Frame.h"
+#include "Page.h"
+#include "Settings.h"
+#include "Widget.h"
+#include "ewk_logging.h"
+#include "ewk_util.h"
+
+#include <cairo.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/Vector.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// If defined, ewk will do type checking to ensure objects are of correct type
+#define EWK_TYPE_CHECK 1
+
+void ewk_view_ready(Evas_Object *o);
+void ewk_view_title_set(Evas_Object *o, const char *title);
+void ewk_view_uri_changed(Evas_Object *o);
+void ewk_view_load_started(Evas_Object *o);
+void ewk_view_frame_main_load_started(Evas_Object *o);
+void ewk_view_load_finished(Evas_Object *o, const Ewk_Frame_Load_Error *error);
+void ewk_view_load_error(Evas_Object *o, const Ewk_Frame_Load_Error *error);
+void ewk_view_load_progress_changed(Evas_Object *o);
+
+void ewk_view_mouse_link_hover_in(Evas_Object *o, void *data);
+void ewk_view_mouse_link_hover_out(Evas_Object *o);
+
+void ewk_view_toolbars_visible_set(Evas_Object *o, Eina_Bool visible);
+void ewk_view_toolbars_visible_get(Evas_Object *o, Eina_Bool *visible);
+
+void ewk_view_statusbar_visible_set(Evas_Object *o, Eina_Bool visible);
+void ewk_view_statusbar_visible_get(Evas_Object *o, Eina_Bool *visible);
+void ewk_view_statusbar_text_set(Evas_Object *o, const char *text);
+
+void ewk_view_scrollbars_visible_set(Evas_Object *o, Eina_Bool visible);
+void ewk_view_scrollbars_visible_get(Evas_Object *o, Eina_Bool *visible);
+
+void ewk_view_menubar_visible_set(Evas_Object *o, Eina_Bool visible);
+void ewk_view_menubar_visible_get(Evas_Object *o, Eina_Bool *visible);
+
+void ewk_view_tooltip_text_set(Evas_Object *o, const char *text);
+
+void ewk_view_add_console_message(Evas_Object *o, const char *message, unsigned int lineNumber, const char *sourceID);
+
+void ewk_view_run_javascript_alert(Evas_Object *o, Evas_Object *frame, const char *message);
+Eina_Bool ewk_view_run_javascript_confirm(Evas_Object *o, Evas_Object *frame, const char *message);
+Eina_Bool ewk_view_run_javascript_prompt(Evas_Object *o, Evas_Object *frame, const char *message, const char *defaultValue, char **value);
+Eina_Bool ewk_view_should_interrupt_javascript(Evas_Object *o);
+void ewk_view_exceeded_database_quota(Evas_Object *o, Evas_Object *frame, const char *databaseName);
+
+void ewk_view_repaint(Evas_Object *o, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h);
+void 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);
+WebCore::Page *ewk_view_core_page_get(const Evas_Object *o);
+
+WTF::PassRefPtr<WebCore::Frame> ewk_view_frame_create(Evas_Object *o, Evas_Object *frame, const WebCore::String& name, WebCore::HTMLFrameOwnerElement* ownerElement, const WebCore::KURL& url, const WebCore::String& referrer);
+
+WTF::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<WebCore::String>& paramNames, const WTF::Vector<WebCore::String>& paramValues, const WebCore::String& mimeType, bool loadManually);
+
+Ewk_History *ewk_history_new(WebCore::BackForwardList *history);
+void ewk_history_free(Ewk_History *history);
+
+Evas_Object *ewk_frame_add(Evas *e);
+Eina_Bool ewk_frame_init(Evas_Object *o, Evas_Object *view, WebCore::Frame *frame);
+Evas_Object *ewk_frame_child_add(Evas_Object *o, WTF::PassRefPtr<WebCore::Frame> child, const WebCore::String& name, const WebCore::KURL& url, const WebCore::String& referrer);
+
+WebCore::Frame *ewk_frame_core_get(const Evas_Object *o);
+void ewk_frame_core_gone(Evas_Object *o);
+
+void ewk_frame_load_started(Evas_Object *o);
+void ewk_frame_load_finished(Evas_Object *o, const char *error_domain, int error_code, Eina_Bool is_cancellation, const char *error_description, const char *failing_url);
+void ewk_frame_load_error(Evas_Object *o, const char *error_domain, int error_code, Eina_Bool is_cancellation, const char *error_description, const char *failing_url);
+void ewk_frame_load_progress_changed(Evas_Object *o);
+
+void ewk_frame_contents_size_changed(Evas_Object *o, Evas_Coord w, Evas_Coord h);
+void ewk_frame_title_set(Evas_Object *o, const char *title);
+
+void ewk_frame_view_create_for_view(Evas_Object *o, Evas_Object *view);
+Eina_Bool ewk_frame_uri_changed(Evas_Object *o);
+void ewk_frame_force_layout(Evas_Object *o);
+
+WTF::PassRefPtr<WebCore::Widget> ewk_frame_plugin_create(Evas_Object* o, const WebCore::IntSize& pluginSize, WebCore::HTMLPlugInElement* element, const WebCore::KURL& url, const WTF::Vector<WebCore::String>& paramNames, const WTF::Vector<WebCore::String>& paramValues, const WebCore::String& mimeType, bool loadManually);
+
+#ifdef __cplusplus
+
+}
+#endif
+#endif // ewk_private_h
diff --git a/WebKit/efl/ewk/ewk_settings.cpp b/WebKit/efl/ewk/ewk_settings.cpp
new file mode 100644
index 0000000..0822dc2
--- /dev/null
+++ b/WebKit/efl/ewk/ewk_settings.cpp
@@ -0,0 +1,190 @@
+/*
+ Copyright (C) 2009-2010 ProFUSION embedded systems
+ Copyright (C) 2009-2010 Samsung Electronics
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+#include "ewk_settings.h"
+
+#include "EWebKit.h"
+#include "IconDatabase.h"
+#include "Image.h"
+#include "IntSize.h"
+#include "KURL.h"
+#include "ewk_private.h"
+#include <wtf/text/CString.h>
+
+#include <eina_safety_checks.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+static uint64_t _ewk_default_web_database_quota = 1 * 1024;
+
+/**
+ * Returns the default quota for Web Database databases. By default
+ * this value is 1MB.
+ *
+ * @return the current default database quota in bytes
+ **/
+uint64_t ewk_settings_web_database_default_quota_get()
+{
+ return _ewk_default_web_database_quota;
+}
+
+/**
+ * Sets directory where to store icon database, opening database.
+ *
+ * @param directory where to store icon database, must be
+ * write-able. If @c NULL is given, then database is closed.
+ *
+ * @return @c EINA_TRUE on success, @c EINA_FALSE on errors.
+ */
+Eina_Bool ewk_settings_icon_database_path_set(const char *directory)
+{
+ WebCore::iconDatabase()->delayDatabaseCleanup();
+
+ if (directory) {
+ struct stat st;
+
+ if (stat(directory, &st)) {
+ ERR("could not stat(%s): %s", directory, strerror(errno));
+ return EINA_FALSE;
+ }
+
+ if (!S_ISDIR(st.st_mode)) {
+ ERR("not a directory: %s", directory);
+ return EINA_FALSE;
+ }
+
+ if (access(directory, R_OK | W_OK)) {
+ ERR("could not access directory '%s' for read and write: %s",
+ directory, strerror(errno));
+ return EINA_FALSE;
+ }
+
+ WebCore::iconDatabase()->setEnabled(true);
+ WebCore::iconDatabase()->open(WebCore::String::fromUTF8(directory));
+ } else {
+ WebCore::iconDatabase()->setEnabled(false);
+ WebCore::iconDatabase()->close();
+ }
+ return EINA_TRUE;
+}
+
+/**
+ * Return directory path where icon database is stored.
+ *
+ * @return newly allocated string with database path or @c NULL if
+ * none is set or database is closed. Note that return must be
+ * freed with free() as it's a strdup()ed copy of the string
+ * due reference counting.
+ */
+char* ewk_settings_icon_database_path_get(void)
+{
+ if (!WebCore::iconDatabase()->isEnabled())
+ return 0;
+ if (!WebCore::iconDatabase()->isOpen())
+ return 0;
+
+ WebCore::String path = WebCore::iconDatabase()->databasePath();
+ if (path.isEmpty())
+ return 0;
+ return strdup(path.utf8().data());
+}
+
+/**
+ * Remove all known icons from database.
+ *
+ * Database must be opened with ewk_settings_icon_database_path_set()
+ * in order to work.
+ *
+ * @return @c EINA_TRUE on success or @c EINA_FALSE otherwise, like
+ * closed database.
+ */
+Eina_Bool ewk_settings_icon_database_clear(void)
+{
+ if (!WebCore::iconDatabase()->isEnabled())
+ return EINA_FALSE;
+ if (!WebCore::iconDatabase()->isOpen())
+ return EINA_FALSE;
+
+ WebCore::iconDatabase()->removeAllIcons();
+ return EINA_TRUE;
+}
+
+/**
+ * Query icon for given URL, returning associated cairo surface.
+ *
+ * @note in order to have this working, one must open icon database
+ * with ewk_settings_icon_database_path_set().
+ *
+ * @param url which url to query icon.
+ *
+ * @return cairo surface if any, or NULL on failure.
+ */
+cairo_surface_t* ewk_settings_icon_database_icon_surface_get(const char *url)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(url, 0);
+
+ WebCore::KURL kurl(WebCore::KURL(), WebCore::String::fromUTF8(url));
+ WebCore::Image *icon = WebCore::iconDatabase()->iconForPageURL(kurl.string(), WebCore::IntSize(16, 16));
+
+ if (!icon) {
+ ERR("no icon for url %s", url);
+ return 0;
+ }
+
+ return icon->nativeImageForCurrentFrame();
+}
+
+/**
+ * Create Evas_Object of type image representing the given URL.
+ *
+ * This is an utility function that creates an Evas_Object of type
+ * image set to have fill always match object size
+ * (evas_object_image_filled_add()), saving some code to use it from Evas.
+ *
+ * @note in order to have this working, one must open icon database
+ * with ewk_settings_icon_database_path_set().
+ *
+ * @param url which url to query icon.
+ * @param canvas evas instance where to add resulting object.
+ *
+ * @return newly allocated Evas_Object instance or @c NULL on
+ * errors. Delete the object with evas_object_del().
+ */
+Evas_Object* ewk_settings_icon_database_icon_object_add(const char* url, Evas* canvas)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(url, 0);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(canvas, 0);
+
+ WebCore::KURL kurl(WebCore::KURL(), WebCore::String::fromUTF8(url));
+ WebCore::Image* icon = WebCore::iconDatabase()->iconForPageURL(kurl.string(), WebCore::IntSize(16, 16));
+ cairo_surface_t* surface;
+
+ if (!icon) {
+ ERR("no icon for url %s", url);
+ return 0;
+ }
+
+ surface = icon->nativeImageForCurrentFrame();
+ return ewk_util_image_from_cairo_surface_add(canvas, surface);
+}
diff --git a/WebKit/efl/ewk/ewk_settings.h b/WebKit/efl/ewk/ewk_settings.h
new file mode 100644
index 0000000..e843fd1
--- /dev/null
+++ b/WebKit/efl/ewk/ewk_settings.h
@@ -0,0 +1,53 @@
+/*
+ Copyright (C) 2009-2010 ProFUSION embedded systems
+ Copyright (C) 2009-2010 Samsung Electronics
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef ewk_settings_h
+#define ewk_settings_h
+
+#include "ewk_eapi.h"
+
+#include <Eina.h>
+#include <Evas.h>
+#include <cairo.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @file
+ *
+ * General purpose settings, not tied to any view object.
+ */
+
+EAPI uint64_t ewk_settings_web_database_default_quota_get();
+
+EAPI Eina_Bool ewk_settings_icon_database_path_set(const char *path);
+EAPI char *ewk_settings_icon_database_path_get(void);
+EAPI Eina_Bool ewk_settings_icon_database_clear(void);
+
+EAPI cairo_surface_t *ewk_settings_icon_database_icon_surface_get(const char *url);
+EAPI Evas_Object *ewk_settings_icon_database_icon_object_add(const char *url, Evas *canvas);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif // ewk_settings_h
diff --git a/WebKit/efl/ewk/ewk_util.cpp b/WebKit/efl/ewk/ewk_util.cpp
new file mode 100644
index 0000000..bf82695
--- /dev/null
+++ b/WebKit/efl/ewk/ewk_util.cpp
@@ -0,0 +1,98 @@
+/*
+ Copyright (C) 2009-2010 ProFUSION embedded systems
+ Copyright (C) 2009-2010 Samsung Electronics
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+#include "ewk_util.h"
+
+#include "ewk_private.h"
+#include <eina_safety_checks.h>
+
+Evas_Object* ewk_util_image_from_cairo_surface_add(Evas* canvas, cairo_surface_t* surface)
+{
+ cairo_status_t status;
+ cairo_surface_type_t type;
+ cairo_format_t format;
+ int w, h, stride;
+ Evas_Object* image;
+ const void* src;
+ void* dst;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(canvas, 0);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(surface, 0);
+
+ status = cairo_surface_status(surface);
+ if (status != CAIRO_STATUS_SUCCESS) {
+ ERR("cairo surface is invalid: %s", cairo_status_to_string(status));
+ return 0;
+ }
+
+ type = cairo_surface_get_type(surface);
+ if (type != CAIRO_SURFACE_TYPE_IMAGE) {
+ ERR("unknown surface type %d, required %d (CAIRO_SURFACE_TYPE_IMAGE).",
+ type, CAIRO_SURFACE_TYPE_IMAGE);
+ return 0;
+ }
+
+ format = cairo_image_surface_get_format(surface);
+ if (format != CAIRO_FORMAT_ARGB32 && format != CAIRO_FORMAT_RGB24) {
+ ERR("unknown surface format %d, expected %d or %d.",
+ format, CAIRO_FORMAT_ARGB32, CAIRO_FORMAT_RGB24);
+ return 0;
+ }
+
+ w = cairo_image_surface_get_width(surface);
+ h = cairo_image_surface_get_height(surface);
+ stride = cairo_image_surface_get_stride(surface);
+ if (w <= 0 || h <= 0 || stride <= 0) {
+ ERR("invalid image size %dx%d, stride=%d", w, h, stride);
+ return 0;
+ }
+
+ src = cairo_image_surface_get_data(surface);
+ if (!src) {
+ ERR("could not get source data.");
+ return 0;
+ }
+
+ image = evas_object_image_filled_add(canvas);
+ if (!image) {
+ ERR("could not add image to canvas.");
+ return 0;
+ }
+
+ evas_object_image_colorspace_set(image, EVAS_COLORSPACE_ARGB8888);
+ evas_object_image_size_set(image, w, h);
+ evas_object_image_alpha_set(image, format == CAIRO_FORMAT_ARGB32);
+
+ if (evas_object_image_stride_get(image) * 4 != stride) {
+ ERR("evas' stride %d diverges from cairo's %d.",
+ evas_object_image_stride_get(image) * 4, stride);
+ evas_object_del(image);
+ return 0;
+ }
+
+ dst = evas_object_image_data_get(image, EINA_TRUE);
+ memcpy(dst, src, h * stride);
+ evas_object_image_data_set(image, dst);
+
+ evas_object_resize(image, w, h); // helpful but not really required
+
+ return image;
+}
diff --git a/WebKit/efl/ewk/ewk_util.h b/WebKit/efl/ewk/ewk_util.h
new file mode 100644
index 0000000..d9c8f9c
--- /dev/null
+++ b/WebKit/efl/ewk/ewk_util.h
@@ -0,0 +1,29 @@
+/*
+ Copyright (C) 2009-2010 ProFUSION embedded systems
+ Copyright (C) 2009-2010 Samsung Electronics
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef ewk_util_h
+#define ewk_util_h
+
+#include <Evas.h>
+#include <cairo.h>
+
+Evas_Object* ewk_util_image_from_cairo_surface_add(Evas* canvas, cairo_surface_t* surface);
+
+#endif // ewk_util_h
diff --git a/WebKit/efl/ewk/ewk_view.cpp b/WebKit/efl/ewk/ewk_view.cpp
new file mode 100644
index 0000000..eeb6535
--- /dev/null
+++ b/WebKit/efl/ewk/ewk_view.cpp
@@ -0,0 +1,3644 @@
+/*
+ Copyright (C) 2009-2010 ProFUSION embedded systems
+ Copyright (C) 2009-2010 Samsung Electronics
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+#include "ewk_view.h"
+
+#include "ChromeClientEfl.h"
+#include "ContextMenuClientEfl.h"
+#include "DocumentLoader.h"
+#include "DragClientEfl.h"
+#include "EWebKit.h"
+#include "EditorClientEfl.h"
+#include "FocusController.h"
+#include "FrameLoaderClientEfl.h"
+#include "FrameView.h"
+#include "GraphicsContext.h"
+#include "InspectorClientEfl.h"
+#include "PopupMenuClient.h"
+#include "ProgressTracker.h"
+#include "ewk_private.h"
+
+#include <Ecore.h>
+#include <Eina.h>
+#include <Evas.h>
+#include <eina_safety_checks.h>
+#include <sys/time.h>
+
+#define ZOOM_MIN (0.05)
+#define ZOOM_MAX (4.0)
+
+static const char EWK_VIEW_TYPE_STR[] = "EWK_View";
+
+static const size_t EWK_VIEW_REPAINTS_SIZE_INITIAL = 32;
+static const size_t EWK_VIEW_REPAINTS_SIZE_STEP = 8;
+static const size_t EWK_VIEW_REPAINTS_SIZE_MAX_FREE = 64;
+
+static const size_t EWK_VIEW_SCROLLS_SIZE_INITIAL = 8;
+static const size_t EWK_VIEW_SCROLLS_SIZE_STEP = 2;
+static const size_t EWK_VIEW_SCROLLS_SIZE_MAX_FREE = 32;
+
+struct _Ewk_View_Private_Data {
+ WebCore::Page* page;
+ WebCore::Settings* page_settings;
+ WebCore::Frame* main_frame;
+ Ewk_History* history;
+ struct {
+ Ewk_Menu menu;
+ WebCore::PopupMenuClient* menu_client;
+ } popup;
+ struct {
+ Eina_Rectangle* array;
+ size_t count;
+ size_t allocated;
+ } repaints;
+ struct {
+ Ewk_Scroll_Request* array;
+ size_t count;
+ size_t allocated;
+ } scrolls;
+ struct {
+ const char* user_agent;
+ const char* user_stylesheet;
+ const char* encoding_default;
+ const char* encoding_custom;
+ int font_minimum_size;
+ int font_minimum_logical_size;
+ int font_default_size;
+ int font_monospace_size;
+ const char* font_standard;
+ const char* font_cursive;
+ const char* font_monospace;
+ const char* font_fantasy;
+ const char* font_serif;
+ const char* font_sans_serif;
+ Eina_Bool auto_load_images:1;
+ Eina_Bool auto_shrink_images:1;
+ Eina_Bool enable_scripts:1;
+ Eina_Bool enable_plugins:1;
+ Eina_Bool scripts_window_open:1;
+ Eina_Bool resizable_textareas:1;
+ Eina_Bool private_browsing:1;
+ Eina_Bool caret_browsing:1;
+ } settings;
+ struct {
+ struct {
+ double start;
+ double end;
+ double duration;
+ } time;
+ struct {
+ float start;
+ float end;
+ float range;
+ } zoom;
+ struct {
+ Evas_Coord x, y;
+ } center;
+ Ecore_Animator* animator;
+ } animated_zoom;
+ struct {
+ Evas_Coord w, h;
+ Eina_Bool use:1;
+ } fixed_layout;
+};
+
+#ifndef EWK_TYPE_CHECK
+#define EWK_VIEW_TYPE_CHECK(o, ...) do { } while (0)
+#else
+#define EWK_VIEW_TYPE_CHECK(o, ...) \
+ do { \
+ const char* _tmp_otype = evas_object_type_get(o); \
+ const Evas_Smart* _tmp_s = evas_object_smart_smart_get(o); \
+ if (EINA_UNLIKELY(!_tmp_s)) { \
+ EINA_LOG_CRIT \
+ ("%p (%s) is not a smart object!", o, \
+ _tmp_otype ? _tmp_otype : "(null)"); \
+ return __VA_ARGS__; \
+ } \
+ const Evas_Smart_Class* _tmp_sc = evas_smart_class_get(_tmp_s); \
+ if (EINA_UNLIKELY(!_tmp_sc)) { \
+ EINA_LOG_CRIT \
+ ("%p (%s) is not a smart object!", o, \
+ _tmp_otype ? _tmp_otype : "(null)"); \
+ return __VA_ARGS__; \
+ } \
+ if (EINA_UNLIKELY(_tmp_sc->data != EWK_VIEW_TYPE_STR)) { \
+ EINA_LOG_CRIT \
+ ("%p (%s) is not of an ewk_view (need %p, got %p)!", \
+ o, _tmp_otype ? _tmp_otype : "(null)", \
+ EWK_VIEW_TYPE_STR, _tmp_sc->data); \
+ return __VA_ARGS__; \
+ } \
+ } while (0)
+#endif
+
+#define EWK_VIEW_SD_GET(o, ptr) \
+ Ewk_View_Smart_Data* ptr = (Ewk_View_Smart_Data*)evas_object_smart_data_get(o)
+
+#define EWK_VIEW_SD_GET_OR_RETURN(o, ptr, ...) \
+ EWK_VIEW_TYPE_CHECK(o, __VA_ARGS__); \
+ EWK_VIEW_SD_GET(o, ptr); \
+ if (!ptr) { \
+ CRITICAL("no smart data for object %p (%s)", \
+ o, evas_object_type_get(o)); \
+ return __VA_ARGS__; \
+ }
+
+#define EWK_VIEW_PRIV_GET(sd, ptr) \
+ Ewk_View_Private_Data* ptr = sd->_priv
+
+#define EWK_VIEW_PRIV_GET_OR_RETURN(sd, ptr, ...) \
+ EWK_VIEW_PRIV_GET(sd, ptr); \
+ if (!ptr) { \
+ CRITICAL("no private data for object %p (%s)", \
+ sd->self, evas_object_type_get(sd->self)); \
+ return __VA_ARGS__; \
+ }
+
+static void _ewk_view_smart_changed(Ewk_View_Smart_Data* sd)
+{
+ if (sd->changed.any)
+ return;
+ sd->changed.any = EINA_TRUE;
+ evas_object_smart_changed(sd->self);
+}
+
+static Eina_Bool _ewk_view_repaints_resize(Ewk_View_Private_Data* priv, size_t size)
+{
+ void* tmp = realloc(priv->repaints.array, size * sizeof(Eina_Rectangle));
+ if (!tmp) {
+ CRITICAL("could not realloc repaints array to %zu elements.", size);
+ return EINA_FALSE;
+ }
+ priv->repaints.allocated = size;
+ priv->repaints.array = (Eina_Rectangle*)tmp;
+ return EINA_TRUE;
+}
+
+static void _ewk_view_repaint_add(Ewk_View_Private_Data* priv, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
+{
+ Eina_Rectangle* r;
+
+ // fprintf(stderr, ">>> repaint requested: %d,%d+%dx%d\n", x, y, w, h);
+ if (priv->repaints.allocated == priv->repaints.count) {
+ size_t size;
+ if (!priv->repaints.allocated)
+ size = EWK_VIEW_REPAINTS_SIZE_INITIAL;
+ else
+ size = priv->repaints.allocated + EWK_VIEW_REPAINTS_SIZE_STEP;
+ if (!_ewk_view_repaints_resize(priv, size))
+ return;
+ }
+
+ r = priv->repaints.array + priv->repaints.count;
+ priv->repaints.count++;
+
+ r->x = x;
+ r->y = y;
+ r->w = w;
+ r->h = h;
+
+ DBG("add repaint %d,%d+%dx%d", x, y, w, h);
+}
+
+static void _ewk_view_repaints_flush(Ewk_View_Private_Data* priv)
+{
+ priv->repaints.count = 0;
+ if (priv->repaints.allocated <= EWK_VIEW_REPAINTS_SIZE_MAX_FREE)
+ return;
+ _ewk_view_repaints_resize(priv, EWK_VIEW_REPAINTS_SIZE_MAX_FREE);
+}
+
+static Eina_Bool _ewk_view_scrolls_resize(Ewk_View_Private_Data* priv, size_t size)
+{
+ void* tmp = realloc(priv->scrolls.array, size * sizeof(Ewk_Scroll_Request));
+ if (!tmp) {
+ CRITICAL("could not realloc scrolls array to %zu elements.", size);
+ return EINA_FALSE;
+ }
+ priv->scrolls.allocated = size;
+ priv->scrolls.array = (Ewk_Scroll_Request*)tmp;
+ return EINA_TRUE;
+}
+
+static 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)
+{
+ Ewk_Scroll_Request* r;
+ Ewk_Scroll_Request* r_end;
+ Evas_Coord x2 = x + w, y2 = y + h;
+
+ r = priv->scrolls.array;
+ r_end = r + priv->scrolls.count;
+ for (; r < r_end; r++) {
+ if (r->x == x && r->y == y && r->w == w && r->h == h) {
+ DBG("region already scrolled %d,%d+%dx%d %+03d,%+03d add "
+ "%+03d,%+03d",
+ r->x, r->y, r->w, r->h, r->dx, r->dy, dx, dy);
+ r->dx += dx;
+ r->dy += dy;
+ return;
+ }
+ if ((x <= r->x && x2 >= r->x2) && (y <= r->y && y2 >= r->y2)) {
+ DBG("old viewport (%d,%d+%dx%d %+03d,%+03d) was scrolled itself, "
+ "add %+03d,%+03d",
+ r->x, r->y, r->w, r->h, r->dx, r->dy, dx, dy);
+ r->x += dx;
+ r->y += dy;
+ }
+ }
+
+ if (priv->scrolls.allocated == priv->scrolls.count) {
+ size_t size;
+ if (!priv->scrolls.allocated)
+ size = EWK_VIEW_SCROLLS_SIZE_INITIAL;
+ else
+ size = priv->scrolls.allocated + EWK_VIEW_SCROLLS_SIZE_STEP;
+ if (!_ewk_view_scrolls_resize(priv, size))
+ return;
+ }
+
+ r = priv->scrolls.array + priv->scrolls.count;
+ priv->scrolls.count++;
+
+ r->x = x;
+ r->y = y;
+ r->w = w;
+ r->h = h;
+ r->x2 = x2;
+ r->y2 = y2;
+ r->dx = dx;
+ r->dy = dy;
+ r->main_scroll = main_scroll;
+ DBG("add scroll in region: %d,%d+%dx%d %+03d,%+03d", x, y, w, h, dx, dy);
+
+ Eina_Rectangle* pr;
+ Eina_Rectangle* pr_end;
+ size_t count;
+ pr = priv->repaints.array;
+ count = priv->repaints.count;
+ pr_end = pr + count;
+ for (; pr < pr_end; pr++) {
+ pr->x += dx;
+ pr->y += dy;
+ }
+}
+
+static void _ewk_view_scrolls_flush(Ewk_View_Private_Data* priv)
+{
+ priv->scrolls.count = 0;
+ if (priv->scrolls.allocated <= EWK_VIEW_SCROLLS_SIZE_MAX_FREE)
+ return;
+ _ewk_view_scrolls_resize(priv, EWK_VIEW_SCROLLS_SIZE_MAX_FREE);
+}
+
+// Default Event Handling //////////////////////////////////////////////
+static Eina_Bool _ewk_view_smart_focus_in(Ewk_View_Smart_Data* sd)
+{
+ EWK_VIEW_PRIV_GET(sd, priv);
+ WebCore::FocusController* fc = priv->page->focusController();
+ DBG("o=%p, fc=%p", sd->self, fc);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(fc, EINA_FALSE);
+
+ fc->setActive(true);
+ fc->setFocused(true);
+ return EINA_TRUE;
+}
+
+static Eina_Bool _ewk_view_smart_focus_out(Ewk_View_Smart_Data* sd)
+{
+ EWK_VIEW_PRIV_GET(sd, priv);
+ WebCore::FocusController* fc = priv->page->focusController();
+ DBG("o=%p, fc=%p", sd->self, fc);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(fc, EINA_FALSE);
+
+ fc->setActive(false);
+ fc->setFocused(false);
+ return EINA_TRUE;
+}
+
+static Eina_Bool _ewk_view_smart_mouse_wheel(Ewk_View_Smart_Data* sd, const Evas_Event_Mouse_Wheel* ev)
+{
+ return ewk_frame_feed_mouse_wheel(sd->main_frame, ev);
+}
+
+static Eina_Bool _ewk_view_smart_mouse_down(Ewk_View_Smart_Data* sd, const Evas_Event_Mouse_Down* ev)
+{
+ return ewk_frame_feed_mouse_down(sd->main_frame, ev);
+}
+
+static Eina_Bool _ewk_view_smart_mouse_up(Ewk_View_Smart_Data* sd, const Evas_Event_Mouse_Up* ev)
+{
+ return ewk_frame_feed_mouse_up(sd->main_frame, ev);
+}
+
+static Eina_Bool _ewk_view_smart_mouse_move(Ewk_View_Smart_Data* sd, const Evas_Event_Mouse_Move* ev)
+{
+ return ewk_frame_feed_mouse_move(sd->main_frame, ev);
+}
+
+static Eina_Bool _ewk_view_smart_key_down(Ewk_View_Smart_Data* sd, const Evas_Event_Key_Down* ev)
+{
+ Evas_Object* frame = ewk_view_frame_focused_get(sd->self);
+
+ if (!frame)
+ frame = sd->main_frame;
+
+ return ewk_frame_feed_key_down(frame, ev);
+}
+
+static Eina_Bool _ewk_view_smart_key_up(Ewk_View_Smart_Data* sd, const Evas_Event_Key_Up* ev)
+{
+ Evas_Object* frame = ewk_view_frame_focused_get(sd->self);
+
+ if (!frame)
+ frame = sd->main_frame;
+
+ return ewk_frame_feed_key_up(frame, ev);
+}
+
+static void _ewk_view_smart_add_console_message(Ewk_View_Smart_Data* sd, const char* message, unsigned int lineNumber, const char* sourceID)
+{
+ INF("console message: %s @%d: %s\n", sourceID, lineNumber, message);
+}
+
+static void _ewk_view_smart_run_javascript_alert(Ewk_View_Smart_Data* sd, Evas_Object* frame, const char* message)
+{
+ INF("javascript alert: %s\n", message);
+}
+
+static Eina_Bool _ewk_view_smart_run_javascript_confirm(Ewk_View_Smart_Data* sd, Evas_Object* frame, const char* message)
+{
+ INF("javascript confirm: %s", message);
+ INF("javascript confirm (HARD CODED)? YES");
+ return EINA_TRUE;
+}
+
+static Eina_Bool _ewk_view_smart_should_interrupt_javascript(Ewk_View_Smart_Data* sd)
+{
+ INF("should interrupt javascript?\n"
+ "\t(HARD CODED) NO");
+ return EINA_FALSE;
+}
+
+static Eina_Bool _ewk_view_smart_run_javascript_prompt(Ewk_View_Smart_Data* sd, Evas_Object* frame, const char* message, const char* defaultValue, char** value)
+{
+ *value = strdup("test");
+ Eina_Bool ret = EINA_TRUE;
+ INF("javascript prompt:\n"
+ "\t message: %s\n"
+ "\tdefault value: %s\n"
+ "\tgiving answer: %s\n"
+ "\t button: %s", message, defaultValue, *value, ret?"ok":"cancel");
+
+ return ret;
+}
+
+// Event Handling //////////////////////////////////////////////////////
+static void _ewk_view_on_focus_in(void* data, Evas* e, Evas_Object* o, void* event_info)
+{
+ Ewk_View_Smart_Data* sd = (Ewk_View_Smart_Data*)data;
+ EINA_SAFETY_ON_NULL_RETURN(sd->api);
+ EINA_SAFETY_ON_NULL_RETURN(sd->api->focus_in);
+ sd->api->focus_in(sd);
+}
+
+static void _ewk_view_on_focus_out(void* data, Evas* e, Evas_Object* o, void* event_info)
+{
+ Ewk_View_Smart_Data* sd = (Ewk_View_Smart_Data*)data;
+ EINA_SAFETY_ON_NULL_RETURN(sd->api);
+ EINA_SAFETY_ON_NULL_RETURN(sd->api->focus_out);
+ sd->api->focus_out(sd);
+}
+
+static void _ewk_view_on_mouse_wheel(void* data, Evas* e, Evas_Object* o, void* event_info)
+{
+ Evas_Event_Mouse_Wheel* ev = (Evas_Event_Mouse_Wheel*)event_info;
+ Ewk_View_Smart_Data* sd = (Ewk_View_Smart_Data*)data;
+ EINA_SAFETY_ON_NULL_RETURN(sd->api);
+ EINA_SAFETY_ON_NULL_RETURN(sd->api->mouse_wheel);
+ sd->api->mouse_wheel(sd, ev);
+}
+
+static void _ewk_view_on_mouse_down(void* data, Evas* e, Evas_Object* o, void* event_info)
+{
+ Evas_Event_Mouse_Down* ev = (Evas_Event_Mouse_Down*)event_info;
+ Ewk_View_Smart_Data* sd = (Ewk_View_Smart_Data*)data;
+ EINA_SAFETY_ON_NULL_RETURN(sd->api);
+ EINA_SAFETY_ON_NULL_RETURN(sd->api->mouse_down);
+ sd->api->mouse_down(sd, ev);
+}
+
+static void _ewk_view_on_mouse_up(void* data, Evas* e, Evas_Object* o, void* event_info)
+{
+ Evas_Event_Mouse_Up* ev = (Evas_Event_Mouse_Up*)event_info;
+ Ewk_View_Smart_Data* sd = (Ewk_View_Smart_Data*)data;
+ EINA_SAFETY_ON_NULL_RETURN(sd->api);
+ EINA_SAFETY_ON_NULL_RETURN(sd->api->mouse_up);
+ sd->api->mouse_up(sd, ev);
+}
+
+static void _ewk_view_on_mouse_move(void* data, Evas* e, Evas_Object* o, void* event_info)
+{
+ Evas_Event_Mouse_Move* ev = (Evas_Event_Mouse_Move*)event_info;
+ Ewk_View_Smart_Data* sd = (Ewk_View_Smart_Data*)data;
+ EINA_SAFETY_ON_NULL_RETURN(sd->api);
+ EINA_SAFETY_ON_NULL_RETURN(sd->api->mouse_move);
+ sd->api->mouse_move(sd, ev);
+}
+
+static void _ewk_view_on_key_down(void* data, Evas* e, Evas_Object* o, void* event_info)
+{
+ Evas_Event_Key_Down* ev = (Evas_Event_Key_Down*)event_info;
+ Ewk_View_Smart_Data* sd = (Ewk_View_Smart_Data*)data;
+ EINA_SAFETY_ON_NULL_RETURN(sd->api);
+ EINA_SAFETY_ON_NULL_RETURN(sd->api->key_down);
+ sd->api->key_down(sd, ev);
+}
+
+static void _ewk_view_on_key_up(void* data, Evas* e, Evas_Object* o, void* event_info)
+{
+ Evas_Event_Key_Up* ev = (Evas_Event_Key_Up*)event_info;
+ Ewk_View_Smart_Data* sd = (Ewk_View_Smart_Data*)data;
+ EINA_SAFETY_ON_NULL_RETURN(sd->api);
+ EINA_SAFETY_ON_NULL_RETURN(sd->api->key_up);
+ sd->api->key_up(sd, ev);
+}
+
+static WTF::PassRefPtr<WebCore::Frame> _ewk_view_core_frame_new(Ewk_View_Smart_Data* sd, Ewk_View_Private_Data* priv, WebCore::HTMLFrameOwnerElement* owner)
+{
+ WebCore::FrameLoaderClientEfl* flc = new WebCore::FrameLoaderClientEfl(sd->self);
+ if (!flc) {
+ CRITICAL("Could not create frame loader client.");
+ return 0;
+ }
+ flc->setCustomUserAgent(WebCore::String::fromUTF8(priv->settings.user_agent));
+
+ return WebCore::Frame::create(priv->page, owner, flc);
+}
+
+static Evas_Smart_Class _parent_sc = EVAS_SMART_CLASS_INIT_0;
+
+static Ewk_View_Private_Data* _ewk_view_priv_new(Ewk_View_Smart_Data* sd)
+{
+ Ewk_View_Private_Data* priv =
+ (Ewk_View_Private_Data*)calloc(1, sizeof(Ewk_View_Private_Data));
+ WebCore::AtomicString s;
+ WebCore::KURL url;
+
+ if (!priv) {
+ CRITICAL("could not allocate Ewk_View_Private_Data");
+ return 0;
+ }
+ priv->page = new WebCore::Page(
+ static_cast<WebCore::ChromeClient*>(new WebCore::ChromeClientEfl(sd->self)),
+ static_cast<WebCore::ContextMenuClient*>(new WebCore::ContextMenuClientEfl(sd->self)),
+ static_cast<WebCore::EditorClient*>(new WebCore::EditorClientEfl(sd->self)),
+ static_cast<WebCore::DragClient*>(new WebCore::DragClientEfl),
+ static_cast<WebCore::InspectorClient*>(new WebCore::InspectorClientEfl),
+ 0,
+ 0);
+ if (!priv->page) {
+ CRITICAL("Could not create WebKit Page");
+ goto error_page;
+ }
+
+ priv->page_settings = priv->page->settings();
+ if (!priv->page_settings) {
+ CRITICAL("Could not get page settings.");
+ goto error_settings;
+ }
+
+ priv->page_settings->setLoadsImagesAutomatically(true);
+ priv->page_settings->setDefaultFixedFontSize(12);
+ priv->page_settings->setDefaultFontSize(16);
+ priv->page_settings->setSerifFontFamily("serif");
+ priv->page_settings->setFixedFontFamily("monotype");
+ priv->page_settings->setSansSerifFontFamily("sans");
+ priv->page_settings->setStandardFontFamily("sans");
+ priv->page_settings->setJavaScriptEnabled(true);
+ priv->page_settings->setPluginsEnabled(true);
+
+ url = priv->page_settings->userStyleSheetLocation();
+ priv->settings.user_stylesheet = eina_stringshare_add(url.prettyURL().utf8().data());
+
+ priv->settings.encoding_default = eina_stringshare_add
+ (priv->page_settings->defaultTextEncodingName().utf8().data());
+ priv->settings.encoding_custom = 0;
+
+ priv->settings.font_minimum_size = priv->page_settings->minimumFontSize();
+ priv->settings.font_minimum_logical_size = priv->page_settings->minimumLogicalFontSize();
+ priv->settings.font_default_size = priv->page_settings->defaultFontSize();
+ priv->settings.font_monospace_size = priv->page_settings->defaultFixedFontSize();
+
+ s = priv->page_settings->standardFontFamily();
+ priv->settings.font_standard = eina_stringshare_add(s.string().utf8().data());
+ s = priv->page_settings->cursiveFontFamily();
+ priv->settings.font_cursive = eina_stringshare_add(s.string().utf8().data());
+ s = priv->page_settings->fixedFontFamily();
+ priv->settings.font_monospace = eina_stringshare_add(s.string().utf8().data());
+ s = priv->page_settings->fantasyFontFamily();
+ priv->settings.font_fantasy = eina_stringshare_add(s.string().utf8().data());
+ s = priv->page_settings->serifFontFamily();
+ priv->settings.font_serif = eina_stringshare_add(s.string().utf8().data());
+ s = priv->page_settings->sansSerifFontFamily();
+ priv->settings.font_sans_serif = eina_stringshare_add(s.string().utf8().data());
+
+ priv->settings.auto_load_images = priv->page_settings->loadsImagesAutomatically();
+ priv->settings.auto_shrink_images = priv->page_settings->shrinksStandaloneImagesToFit();
+ priv->settings.enable_scripts = priv->page_settings->isJavaScriptEnabled();
+ priv->settings.enable_plugins = priv->page_settings->arePluginsEnabled();
+ priv->settings.scripts_window_open = priv->page_settings->allowScriptsToCloseWindows();
+ priv->settings.resizable_textareas = priv->page_settings->textAreasAreResizable();
+ priv->settings.private_browsing = priv->page_settings->privateBrowsingEnabled();
+ priv->settings.caret_browsing = priv->page_settings->caretBrowsingEnabled();
+
+ priv->main_frame = _ewk_view_core_frame_new(sd, priv, 0).get();
+ if (!priv->main_frame) {
+ CRITICAL("Could not create main frame.");
+ goto error_main_frame;
+ }
+
+ priv->history = ewk_history_new(priv->page->backForwardList());
+ if (!priv->history) {
+ CRITICAL("Could not create history instance for view.");
+ goto error_history;
+ }
+
+ return priv;
+
+error_history:
+ // delete priv->main_frame; /* do not delete priv->main_frame */
+error_main_frame:
+error_settings:
+ delete priv->page;
+error_page:
+ free(priv);
+ return 0;
+}
+
+static void _ewk_view_priv_del(Ewk_View_Private_Data* priv)
+{
+ if (!priv)
+ return;
+
+ /* do not delete priv->main_frame */
+
+ free(priv->repaints.array);
+ free(priv->scrolls.array);
+
+ eina_stringshare_del(priv->settings.user_agent);
+ eina_stringshare_del(priv->settings.user_stylesheet);
+ eina_stringshare_del(priv->settings.encoding_default);
+ eina_stringshare_del(priv->settings.encoding_custom);
+ eina_stringshare_del(priv->settings.font_standard);
+ eina_stringshare_del(priv->settings.font_cursive);
+ eina_stringshare_del(priv->settings.font_monospace);
+ eina_stringshare_del(priv->settings.font_fantasy);
+ eina_stringshare_del(priv->settings.font_serif);
+ eina_stringshare_del(priv->settings.font_sans_serif);
+
+ if (priv->animated_zoom.animator)
+ ecore_animator_del(priv->animated_zoom.animator);
+
+ ewk_history_free(priv->history);
+
+ delete priv->page;
+ free(priv);
+}
+
+static void _ewk_view_smart_add(Evas_Object* o)
+{
+ const Evas_Smart* smart = evas_object_smart_smart_get(o);
+ const Evas_Smart_Class* sc = evas_smart_class_get(smart);
+ const Ewk_View_Smart_Class* api = (const Ewk_View_Smart_Class*)sc;
+ EINA_SAFETY_ON_NULL_RETURN(api->backing_store_add);
+ EWK_VIEW_SD_GET(o, sd);
+
+ if (!sd) {
+ sd = (Ewk_View_Smart_Data*)calloc(1, sizeof(Ewk_View_Smart_Data));
+ if (!sd)
+ CRITICAL("could not allocate Ewk_View_Smart_Data");
+ else
+ evas_object_smart_data_set(o, sd);
+ }
+
+ sd->bg_color.r = 255;
+ sd->bg_color.g = 255;
+ sd->bg_color.b = 255;
+ sd->bg_color.a = 255;
+
+ sd->self = o;
+ sd->_priv = _ewk_view_priv_new(sd);
+ sd->api = api;
+
+ _parent_sc.add(o);
+
+ if (!sd->_priv)
+ return;
+
+ EWK_VIEW_PRIV_GET(sd, priv);
+
+ sd->backing_store = api->backing_store_add(sd);
+ if (!sd->backing_store) {
+ ERR("Could not create backing store object.");
+ return;
+ }
+
+ evas_object_smart_member_add(sd->backing_store, o);
+ evas_object_show(sd->backing_store);
+
+ sd->main_frame = ewk_frame_add(sd->base.evas);
+ if (!sd->main_frame) {
+ ERR("Could not create main frame object.");
+ return;
+ }
+
+ if (!ewk_frame_init(sd->main_frame, o, priv->main_frame)) {
+ ERR("Could not initialize main frme object.");
+ evas_object_del(sd->main_frame);
+ sd->main_frame = 0;
+
+ delete priv->main_frame;
+ priv->main_frame = 0;
+ return;
+ }
+
+ evas_object_name_set(sd->main_frame, "EWK_Frame:main");
+ evas_object_smart_member_add(sd->main_frame, o);
+ evas_object_show(sd->main_frame);
+
+#define CONNECT(s, c) evas_object_event_callback_add(o, s, c, sd)
+ CONNECT(EVAS_CALLBACK_FOCUS_IN, _ewk_view_on_focus_in);
+ CONNECT(EVAS_CALLBACK_FOCUS_OUT, _ewk_view_on_focus_out);
+ CONNECT(EVAS_CALLBACK_MOUSE_WHEEL, _ewk_view_on_mouse_wheel);
+ CONNECT(EVAS_CALLBACK_MOUSE_DOWN, _ewk_view_on_mouse_down);
+ CONNECT(EVAS_CALLBACK_MOUSE_UP, _ewk_view_on_mouse_up);
+ CONNECT(EVAS_CALLBACK_MOUSE_MOVE, _ewk_view_on_mouse_move);
+ CONNECT(EVAS_CALLBACK_KEY_DOWN, _ewk_view_on_key_down);
+ CONNECT(EVAS_CALLBACK_KEY_UP, _ewk_view_on_key_up);
+#undef CONNECT
+}
+
+static void _ewk_view_smart_del(Evas_Object* o)
+{
+ EWK_VIEW_SD_GET(o, sd);
+ Ewk_View_Private_Data* priv = sd ? sd->_priv : 0;
+
+ _parent_sc.del(o);
+ _ewk_view_priv_del(priv);
+}
+
+static void _ewk_view_smart_resize(Evas_Object* o, Evas_Coord w, Evas_Coord h)
+{
+ EWK_VIEW_SD_GET(o, sd);
+
+ // these should be queued and processed in calculate as well!
+ evas_object_resize(sd->backing_store, w, h);
+
+ sd->changed.size = EINA_TRUE;
+ _ewk_view_smart_changed(sd);
+}
+
+static void _ewk_view_smart_move(Evas_Object* o, Evas_Coord x, Evas_Coord y)
+{
+ EWK_VIEW_SD_GET(o, sd);
+ sd->changed.position = EINA_TRUE;
+ _ewk_view_smart_changed(sd);
+}
+
+static void _ewk_view_smart_calculate(Evas_Object* o)
+{
+ EWK_VIEW_SD_GET(o, sd);
+ EWK_VIEW_PRIV_GET(sd, priv);
+ EINA_SAFETY_ON_NULL_RETURN(sd->api->contents_resize);
+ EINA_SAFETY_ON_NULL_RETURN(sd->api->scrolls_process);
+ EINA_SAFETY_ON_NULL_RETURN(sd->api->repaints_process);
+ Evas_Coord x, y, w, h;
+
+ sd->changed.any = EINA_FALSE;
+
+ if (!sd->main_frame || !priv->main_frame)
+ return;
+
+ evas_object_geometry_get(o, &x, &y, &w, &h);
+
+ DBG("o=%p geo=[%d, %d + %dx%d], changed: size=%hhu, "
+ "scrolls=%zu, repaints=%zu",
+ o, x, y, w, h, sd->changed.size,
+ priv->scrolls.count, priv->repaints.count);
+
+ if (sd->changed.size && ((w != sd->view.w) || (h != sd->view.h))) {
+ WebCore::FrameView* view = priv->main_frame->view();
+ if (view) {
+ view->resize(w, h);
+ view->forceLayout();
+ view->adjustViewSize();
+ IntSize size = view->contentsSize();
+ if (!sd->api->contents_resize(sd, size.width(), size.height()))
+ ERR("failed to resize contents to %dx%d",
+ size.width(), size.height());
+ }
+ evas_object_resize(sd->main_frame, w, h);
+ sd->changed.frame_rect = EINA_TRUE;
+ sd->view.w = w;
+ sd->view.h = h;
+ }
+ sd->changed.size = EINA_FALSE;
+
+ if (sd->changed.position && ((x != sd->view.x) || (y != sd->view.y))) {
+ evas_object_move(sd->main_frame, x, y);
+ evas_object_move(sd->backing_store, x, y);
+ sd->changed.frame_rect = EINA_TRUE;
+ sd->view.x = x;
+ sd->view.y = y;
+ }
+ sd->changed.position = EINA_FALSE;
+
+ ewk_view_layout_if_needed_recursive(sd->_priv);
+
+ if (!sd->api->scrolls_process(sd))
+ ERR("failed to process scrolls.");
+ _ewk_view_scrolls_flush(priv);
+
+ if (!sd->api->repaints_process(sd))
+ ERR("failed to process repaints.");
+ _ewk_view_repaints_flush(priv);
+
+ if (sd->changed.frame_rect) {
+ WebCore::FrameView* view = priv->main_frame->view();
+ view->frameRectsChanged(); /* force tree to get position from root */
+ sd->changed.frame_rect = EINA_FALSE;
+ }
+}
+
+static Eina_Bool _ewk_view_smart_contents_resize(Ewk_View_Smart_Data* sd, int w, int h)
+{
+ return EINA_TRUE;
+}
+
+static Eina_Bool _ewk_view_smart_zoom_set(Ewk_View_Smart_Data* sd, float zoom, Evas_Coord cx, Evas_Coord cy)
+{
+ double px, py;
+ Evas_Coord x, y, w, h;
+ Eina_Bool ret;
+
+ ewk_frame_scroll_size_get(sd->main_frame, &w, &h);
+ ewk_frame_scroll_pos_get(sd->main_frame, &x, &y);
+
+ if (w + sd->view.w > 0)
+ px = (double)(x + cx) / (w + sd->view.w);
+ else
+ px = 0.0;
+
+ if (h + sd->view.h > 0)
+ py = (double)(y + cy) / (h + sd->view.h);
+ else
+ py = 0.0;
+
+ ret = ewk_frame_zoom_set(sd->main_frame, zoom);
+
+ ewk_frame_scroll_size_get(sd->main_frame, &w, &h);
+ x = (w + sd->view.w) * px - cx;
+ y = (h + sd->view.h) * py - cy;
+ ewk_frame_scroll_set(sd->main_frame, x, y);
+ return ret;
+}
+
+static void _ewk_view_smart_flush(Ewk_View_Smart_Data* sd)
+{
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv);
+ _ewk_view_repaints_flush(priv);
+ _ewk_view_scrolls_flush(priv);
+}
+
+static 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)
+{
+ WRN("not supported by engine. sd=%p area=%d,%d+%dx%d, zoom=%f",
+ sd, x, y, w, h, zoom);
+ return EINA_FALSE;
+}
+
+static void _ewk_view_smart_pre_render_cancel(Ewk_View_Smart_Data* sd)
+{
+ WRN("not supported by engine. sd=%p", sd);
+}
+
+static void _ewk_view_zoom_animated_mark_stop(Ewk_View_Smart_Data* sd)
+{
+ sd->animated_zoom.zoom.start = 0.0;
+ sd->animated_zoom.zoom.end = 0.0;
+ sd->animated_zoom.zoom.current = 0.0;
+}
+
+static void _ewk_view_zoom_animated_finish(Ewk_View_Smart_Data* sd)
+{
+ EWK_VIEW_PRIV_GET(sd, priv);
+ ecore_animator_del(priv->animated_zoom.animator);
+ priv->animated_zoom.animator = 0;
+ _ewk_view_zoom_animated_mark_stop(sd);
+ evas_object_smart_callback_call(sd->self, "zoom,animated,end", 0);
+}
+
+static float _ewk_view_zoom_animated_current(Ewk_View_Private_Data* priv)
+{
+ double now = ecore_loop_time_get();
+ double delta = now - priv->animated_zoom.time.start;
+
+ if (delta > priv->animated_zoom.time.duration)
+ delta = priv->animated_zoom.time.duration;
+ if (delta < 0.0) // time went back, clock adjusted?
+ delta = 0.0;
+
+ delta /= priv->animated_zoom.time.duration;
+
+ return ((priv->animated_zoom.zoom.range * delta)
+ + priv->animated_zoom.zoom.start);
+}
+
+static int _ewk_view_zoom_animator_cb(void* data)
+{
+ Ewk_View_Smart_Data* sd = (Ewk_View_Smart_Data*)data;
+ Evas_Coord cx, cy;
+ EWK_VIEW_PRIV_GET(sd, priv);
+ double now = ecore_loop_time_get();
+
+ cx = priv->animated_zoom.center.x;
+ cy = priv->animated_zoom.center.y;
+
+ // TODO: progressively center (cx, cy) -> (view.x + view.h/2, view.y + view.h/2)
+ if (cx >= sd->view.w)
+ cx = sd->view.w - 1;
+ if (cy >= sd->view.h)
+ cy = sd->view.h - 1;
+
+ if ((now >= priv->animated_zoom.time.end)
+ || (now < priv->animated_zoom.time.start)) {
+ _ewk_view_zoom_animated_finish(sd);
+ ewk_view_zoom_set(sd->self, priv->animated_zoom.zoom.end, cx, cy);
+ return 0;
+ }
+
+ sd->animated_zoom.zoom.current = _ewk_view_zoom_animated_current(priv);
+ sd->api->zoom_weak_set(sd, sd->animated_zoom.zoom.current, cx, cy);
+ return 1;
+}
+
+static void _ewk_view_zoom_animation_start(Ewk_View_Smart_Data* sd)
+{
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv);
+ if (priv->animated_zoom.animator)
+ return;
+ priv->animated_zoom.animator = ecore_animator_add
+ (_ewk_view_zoom_animator_cb, sd);
+}
+
+/**
+ * Sets the smart class api without any backing store, enabling view
+ * to be inherited.
+ *
+ * @param api class definition to be set, all members with the
+ * exception of Evas_Smart_Class->data may be overridden. Must
+ * @b not be @c 0.
+ *
+ * @note Evas_Smart_Class->data is used to implement type checking and
+ * is not supposed to be changed/overridden. If you need extra
+ * data for your smart class to work, just extend
+ * Ewk_View_Smart_Class instead.
+ *
+ * @return @c EINA_TRUE on success, @c EINA_FALSE on failure (probably
+ * version mismatch).
+ *
+ * @see ewk_view_single_smart_set()
+ * @see ewk_view_tiled_smart_set()
+ */
+Eina_Bool ewk_view_base_smart_set(Ewk_View_Smart_Class* api)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(api, EINA_FALSE);
+
+ if (api->version != EWK_VIEW_SMART_CLASS_VERSION) {
+ EINA_LOG_CRIT
+ ("Ewk_View_Smart_Class %p is version %lu while %lu was expected.",
+ api, api->version, EWK_VIEW_SMART_CLASS_VERSION);
+ return EINA_FALSE;
+ }
+
+ if (EINA_UNLIKELY(!_parent_sc.add))
+ evas_object_smart_clipped_smart_set(&_parent_sc);
+
+ evas_object_smart_clipped_smart_set(&api->sc);
+ api->sc.add = _ewk_view_smart_add;
+ api->sc.del = _ewk_view_smart_del;
+ api->sc.resize = _ewk_view_smart_resize;
+ api->sc.move = _ewk_view_smart_move;
+ api->sc.calculate = _ewk_view_smart_calculate;
+ api->sc.data = EWK_VIEW_TYPE_STR; /* used by type checking */
+
+ api->contents_resize = _ewk_view_smart_contents_resize;
+ api->zoom_set = _ewk_view_smart_zoom_set;
+ api->flush = _ewk_view_smart_flush;
+ api->pre_render_region = _ewk_view_smart_pre_render_region;
+ api->pre_render_cancel = _ewk_view_smart_pre_render_cancel;
+
+ api->focus_in = _ewk_view_smart_focus_in;
+ api->focus_out = _ewk_view_smart_focus_out;
+ api->mouse_wheel = _ewk_view_smart_mouse_wheel;
+ api->mouse_down = _ewk_view_smart_mouse_down;
+ api->mouse_up = _ewk_view_smart_mouse_up;
+ api->mouse_move = _ewk_view_smart_mouse_move;
+ api->key_down = _ewk_view_smart_key_down;
+ api->key_up = _ewk_view_smart_key_up;
+
+ api->add_console_message = _ewk_view_smart_add_console_message;
+ api->run_javascript_alert = _ewk_view_smart_run_javascript_alert;
+ api->run_javascript_confirm = _ewk_view_smart_run_javascript_confirm;
+ api->run_javascript_prompt = _ewk_view_smart_run_javascript_prompt;
+ api->should_interrupt_javascript = _ewk_view_smart_should_interrupt_javascript;
+
+ return EINA_TRUE;
+}
+
+/**
+ * Set a fixed layout size to be used, dissociating it from viewport size.
+ *
+ * Setting a width different than zero enables fixed layout on that
+ * size. It's automatically scaled based on zoom, but will not change
+ * if viewport changes.
+ *
+ * Setting both @a w and @a h to zero will disable fixed layout.
+ *
+ * @param o view object to change fixed layout.
+ * @param w fixed width to use. This size will be automatically scaled
+ * based on zoom level.
+ * @param h fixed height to use. This size will be automatically scaled
+ * based on zoom level.
+ */
+void ewk_view_fixed_layout_size_set(Evas_Object* o, Evas_Coord w, Evas_Coord h)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv);
+ WebCore::FrameView* view = sd->_priv->main_frame->view();
+ if (w <= 0 && h <= 0) {
+ if (!priv->fixed_layout.use)
+ return;
+ priv->fixed_layout.w = 0;
+ priv->fixed_layout.h = 0;
+ priv->fixed_layout.use = EINA_FALSE;
+ } else {
+ if (priv->fixed_layout.use
+ && priv->fixed_layout.w == w && priv->fixed_layout.h == h)
+ return;
+ priv->fixed_layout.w = w;
+ priv->fixed_layout.h = h;
+ priv->fixed_layout.use = EINA_TRUE;
+
+ if (view)
+ view->setFixedLayoutSize(WebCore::IntSize(w, h));
+ }
+
+ if (!view)
+ return;
+ view->setUseFixedLayout(priv->fixed_layout.use);
+ view->forceLayout();
+}
+
+/**
+ * Get fixed layout size in use.
+ *
+ * @param o view object to query fixed layout size.
+ * @param w where to return width. Returns 0 on error or if no fixed
+ * layout in use.
+ * @param h where to return height. Returns 0 on error or if no fixed
+ * layout in use.
+ */
+void ewk_view_fixed_layout_size_get(Evas_Object* o, Evas_Coord* w, Evas_Coord* h)
+{
+ if (w)
+ *w = 0;
+ if (h)
+ *h = 0;
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv);
+ if (priv->fixed_layout.use) {
+ if (w)
+ *w = priv->fixed_layout.w;
+ if (h)
+ *h = priv->fixed_layout.h;
+ }
+}
+
+/**
+ * Set the theme path to be used by this view.
+ *
+ * This also sets the theme on the main frame. As frames inherit theme
+ * from their parent, this will have all frames with unset theme to
+ * use this one.
+ *
+ * @param o view object to change theme.
+ * @param path theme path, may be @c 0 to reset to default.
+ */
+void ewk_view_theme_set(Evas_Object* o, const char* path)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd);
+ ewk_frame_theme_set(sd->main_frame, path);
+}
+
+/**
+ * Gets the theme set on this frame.
+ *
+ * This returns the value set by ewk_view_theme_set().
+ *
+ * @param o view object to get theme path.
+ *
+ * @return theme path, may be @c 0 if not set.
+ */
+const char* ewk_view_theme_get(Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
+ return ewk_frame_theme_get(sd->main_frame);
+}
+
+/**
+ * Get the object that represents the main frame.
+ *
+ * @param o view object to get main frame.
+ *
+ * @return ewk_frame object or @c 0 if none yet.
+ */
+Evas_Object* ewk_view_frame_main_get(const Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
+ return sd->main_frame;
+}
+
+/**
+ * Get the currently focused frame object.
+ *
+ * @param o view object to get focused frame.
+ *
+ * @return ewk_frame object or @c 0 if none yet.
+ */
+Evas_Object* ewk_view_frame_focused_get(const Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
+
+ WebCore::Frame* core = priv->page->focusController()->focusedFrame();
+ if (!core)
+ return 0;
+
+ WebCore::FrameLoaderClientEfl* client = static_cast<WebCore::FrameLoaderClientEfl*>(core->loader()->client());
+ if (!client)
+ return 0;
+ return client->webFrame();
+}
+
+/**
+ * Ask main frame to load the given URI.
+ *
+ * @param o view object to load uri.
+ * @param uri uniform resource identifier to load.
+ *
+ * @return @c EINA_TRUE on successful request, @c EINA_FALSE on failure.
+ * Note that it means the request was done, not that it was
+ * satisfied.
+ */
+Eina_Bool ewk_view_uri_set(Evas_Object* o, const char* uri)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ return ewk_frame_uri_set(sd->main_frame, uri);
+}
+
+/**
+ * Get the current uri loaded by main frame.
+ *
+ * @param o view object to get current uri.
+ *
+ * @return current uri reference or @c 0. It's internal, don't change.
+ */
+const char* ewk_view_uri_get(const Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
+ return ewk_frame_uri_get(sd->main_frame);
+}
+
+/**
+ * Get the current title of main frame.
+ *
+ * @param o view object to get current title.
+ *
+ * @return current title reference or @c 0. It's internal, don't change.
+ */
+const char* ewk_view_title_get(const Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
+ return ewk_frame_title_get(sd->main_frame);
+}
+
+/**
+ * Gets if main frame is editable.
+ *
+ * @param o view object to get editable state.
+ *
+ * @return @c EINA_TRUE if editable, @c EINA_FALSE otherwise.
+ */
+Eina_Bool ewk_view_editable_get(const Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ return ewk_frame_editable_get(sd->main_frame);
+}
+
+/**
+ * Set background color and transparency
+ *
+ * Just as in Evas, colors are pre-multiplied, so 50% red is
+ * (128, 0, 0, 128) and not (255, 0, 0, 128)!
+ *
+ * @warning Watch out performance issues with transparency! Object
+ * will be handled as transparent image by evas even if the
+ * webpage specifies a background color. That mean you'll pay
+ * a price even if it's not really transparent, thus
+ * scrolling/panning and zooming will be likely slower than
+ * if transparency is off.
+ *
+ * @param o view object to change.
+ * @param r red component.
+ * @param g green component.
+ * @param b blue component.
+ * @param a transparency.
+ */
+void ewk_view_bg_color_set(Evas_Object* o, int r, int g, int b, int a)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd);
+ EINA_SAFETY_ON_NULL_RETURN(sd->api);
+ EINA_SAFETY_ON_NULL_RETURN(sd->api->bg_color_set);
+
+ if (a < 0) {
+ WRN("Alpha less than zero (%d).", a);
+ a = 0;
+ } else if (a > 255) {
+ WRN("Alpha is larger than 255 (%d).", a);
+ a = 255;
+ }
+
+#define CHECK_PREMUL_COLOR(c, a) \
+ if (c < 0) { \
+ WRN("Color component "#c" is less than zero (%d).", c); \
+ c = 0; \
+ } else if (c > a) { \
+ WRN("Color component "#c" is greater than alpha (%d, alpha=%d).", \
+ c, a); \
+ c = a; \
+ }
+ CHECK_PREMUL_COLOR(r, a);
+ CHECK_PREMUL_COLOR(g, a);
+ CHECK_PREMUL_COLOR(b, a);
+#undef CHECK_PREMUL_COLOR
+
+ sd->bg_color.r = r;
+ sd->bg_color.g = g;
+ sd->bg_color.b = b;
+ sd->bg_color.a = a;
+
+ sd->api->bg_color_set(sd, r, g, b, a);
+
+ WebCore::FrameView* view = sd->_priv->main_frame->view();
+ if (view) {
+ WebCore::Color color;
+
+ if (!a)
+ color = WebCore::Color(0, 0, 0, 0);
+ else if (a == 255)
+ color = WebCore::Color(r, g, b, a);
+ else
+ color = WebCore::Color(r * 255 / a, g * 255 / a, b * 255 / a, a);
+
+ view->updateBackgroundRecursively(color, !a);
+ }
+}
+
+/**
+ * Query if view object background color.
+ *
+ * Just as in Evas, colors are pre-multiplied, so 50% red is
+ * (128, 0, 0, 128) and not (255, 0, 0, 128)!
+ *
+ * @param o view object to query.
+ * @param r where to return red color component.
+ * @param g where to return green color component.
+ * @param b where to return blue color component.
+ * @param a where to return alpha value.
+ */
+void ewk_view_bg_color_get(const Evas_Object* o, int* r, int* g, int* b, int* a)
+{
+ if (r)
+ *r = 0;
+ if (g)
+ *g = 0;
+ if (b)
+ *b = 0;
+ if (a)
+ *a = 0;
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd);
+ if (r)
+ *r = sd->bg_color.r;
+ if (g)
+ *g = sd->bg_color.g;
+ if (b)
+ *b = sd->bg_color.b;
+ if (a)
+ *a = sd->bg_color.a;
+}
+
+/**
+ * Search the given text string in document.
+ *
+ * @param o view object where to search text.
+ * @param string reference string to search.
+ * @param case_sensitive if search should be case sensitive or not.
+ * @param forward if search is from cursor and on or backwards.
+ * @param wrap if search should wrap at end.
+ *
+ * @return @c EINA_TRUE if found, @c EINA_FALSE if not or failure.
+ */
+Eina_Bool ewk_view_text_search(const Evas_Object* o, const char* string, Eina_Bool case_sensitive, Eina_Bool forward, Eina_Bool wrap)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(string, EINA_FALSE);
+ WebCore::TextCaseSensitivity sensitive;
+ WebCore::FindDirection direction;
+
+ if (case_sensitive)
+ sensitive = WebCore::TextCaseSensitive;
+ else
+ sensitive = WebCore::TextCaseInsensitive;
+
+ if (forward)
+ direction = WebCore::FindDirectionForward;
+ else
+ direction = WebCore::FindDirectionBackward;
+
+ return priv->page->findString(WebCore::String::fromUTF8(string), sensitive, direction, wrap);
+}
+
+/**
+ * Mark matches the given text string in document.
+ *
+ * @param o view object where to search text.
+ * @param string reference string to match.
+ * @param case_sensitive if match should be case sensitive or not.
+ * @param highlight if matches should be highlighted.
+ * @param limit maximum amount of matches, or zero to unlimited.
+ *
+ * @return number of matches.
+ */
+unsigned int ewk_view_text_matches_mark(Evas_Object* o, const char* string, Eina_Bool case_sensitive, Eina_Bool highlight, unsigned int limit)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(string, 0);
+ WebCore::TextCaseSensitivity sensitive;
+
+ if (case_sensitive)
+ sensitive = WebCore::TextCaseSensitive;
+ else
+ sensitive = WebCore::TextCaseInsensitive;
+
+ return priv->page->markAllMatchesForText(WebCore::String::fromUTF8(string), sensitive, highlight, limit);
+}
+
+/**
+ * Reverses the effect of ewk_view_text_matches_mark()
+ *
+ * @param o view object where to search text.
+ *
+ * @return @c EINA_TRUE on success, @c EINA_FALSE for failure.
+ */
+Eina_Bool ewk_view_text_matches_unmark_all(Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
+ priv->page->unmarkAllTextMatches();
+ return EINA_TRUE;
+}
+
+/**
+ * Set if should highlight matches marked with ewk_view_text_matches_mark().
+ *
+ * @param o view object where to set if matches are highlighted or not.
+ * @param highlight if @c EINA_TRUE, matches will be highlighted.
+ *
+ * @return @c EINA_TRUE on success, @c EINA_FALSE for failure.
+ */
+Eina_Bool ewk_view_text_matches_highlight_set(Evas_Object* o, Eina_Bool highlight)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ return ewk_frame_text_matches_highlight_set(sd->main_frame, highlight);
+}
+
+/**
+ * Get if should highlight matches marked with ewk_view_text_matches_mark().
+ *
+ * @param o view object to query if matches are highlighted or not.
+ *
+ * @return @c EINA_TRUE if they are highlighted, @c EINA_FALSE otherwise.
+ */
+Eina_Bool ewk_view_text_matches_highlight_get(const Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ return ewk_frame_text_matches_highlight_get(sd->main_frame);
+}
+
+/**
+ * Sets if main frame is editable.
+ *
+ * @param o view object to set editable state.
+ * @param editable new state.
+ *
+ * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
+ */
+Eina_Bool ewk_view_editable_set(Evas_Object* o, Eina_Bool editable)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ return ewk_frame_editable_set(sd->main_frame, editable);
+}
+
+/**
+ * Get the copy of the selection text.
+ *
+ * @param o view object to get selection text.
+ *
+ * @return newly allocated string or @c 0 if nothing is selected or failure.
+ */
+char* ewk_view_selection_get(const Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
+ WebCore::CString s = priv->page->focusController()->focusedOrMainFrame()->selectedText().utf8();
+ if (s.isNull())
+ return 0;
+ return strdup(s.data());
+}
+
+static Eina_Bool _ewk_view_editor_command(Ewk_View_Private_Data* priv, const char* command)
+{
+ return priv->page->focusController()->focusedOrMainFrame()->editor()->command(WebCore::String::fromUTF8(command)).execute();
+}
+
+/**
+ * Unselects whatever was selected.
+ *
+ * @return @c EINA_TRUE if operation was executed, @c EINA_FALSE otherwise.
+ */
+Eina_Bool ewk_view_select_none(Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
+ return _ewk_view_editor_command(priv, "Unselect");
+}
+
+/**
+ * Selects everything.
+ *
+ * @return @c EINA_TRUE if operation was executed, @c EINA_FALSE otherwise.
+ */
+Eina_Bool ewk_view_select_all(Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
+ return _ewk_view_editor_command(priv, "SelectAll");
+}
+
+/**
+ * Selects the current paragrah.
+ *
+ * @return @c EINA_TRUE if operation was executed, @c EINA_FALSE otherwise.
+ */
+Eina_Bool ewk_view_select_paragraph(Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
+ return _ewk_view_editor_command(priv, "SelectParagraph");
+}
+
+/**
+ * Selects the current sentence.
+ *
+ * @return @c EINA_TRUE if operation was executed, @c EINA_FALSE otherwise.
+ */
+Eina_Bool ewk_view_select_sentence(Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
+ return _ewk_view_editor_command(priv, "SelectSentence");
+}
+
+/**
+ * Selects the current line.
+ *
+ * @return @c EINA_TRUE if operation was executed, @c EINA_FALSE otherwise.
+ */
+Eina_Bool ewk_view_select_line(Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
+ return _ewk_view_editor_command(priv, "SelectLine");
+}
+
+/**
+ * Selects the current word.
+ *
+ * @return @c EINA_TRUE if operation was executed, @c EINA_FALSE otherwise.
+ */
+Eina_Bool ewk_view_select_word(Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
+ return _ewk_view_editor_command(priv, "SelectWord");
+}
+
+/**
+ * Get current load progress estimate from 0.0 to 1.0.
+ *
+ * @param o view object to get current progress.
+ *
+ * @return progres value from 0.0 to 1.0 or -1.0 on error.
+ */
+double ewk_view_load_progress_get(const Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, -1.0);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, -1.0);
+ return priv->page->progress()->estimatedProgress();
+}
+
+/**
+ * Ask main frame to stop loading.
+ *
+ * @param o view object to stop loading.
+ *
+ * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
+ *
+ * @see ewk_frame_stop()
+ */
+Eina_Bool ewk_view_stop(Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ return ewk_frame_stop(sd->main_frame);
+}
+
+/**
+ * Ask main frame to reload current document.
+ *
+ * @param o view object to reload.
+ *
+ * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
+ *
+ * @see ewk_frame_reload()
+ */
+Eina_Bool ewk_view_reload(Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ return ewk_frame_reload(sd->main_frame);
+}
+
+/**
+ * Ask main frame to fully reload current document, using no caches.
+ *
+ * @param o view object to reload.
+ *
+ * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
+ *
+ * @see ewk_frame_reload_full()
+ */
+Eina_Bool ewk_view_reload_full(Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ return ewk_frame_reload_full(sd->main_frame);
+}
+
+/**
+ * Ask main frame to navigate back in history.
+ *
+ * @param o view object to navigate back.
+ *
+ * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
+ *
+ * @see ewk_frame_back()
+ */
+Eina_Bool ewk_view_back(Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ return ewk_frame_back(sd->main_frame);
+}
+
+/**
+ * Ask main frame to navigate forward in history.
+ *
+ * @param o view object to navigate forward.
+ *
+ * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
+ *
+ * @see ewk_frame_forward()
+ */
+Eina_Bool ewk_view_forward(Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ return ewk_frame_forward(sd->main_frame);
+}
+
+/**
+ * Navigate back or forward in history.
+ *
+ * @param o view object to navigate.
+ * @param steps if positive navigates that amount forwards, if negative
+ * does backwards.
+ *
+ * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
+ *
+ * @see ewk_frame_navigate()
+ */
+Eina_Bool ewk_view_navigate(Evas_Object* o, int steps)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ return ewk_frame_navigate(sd->main_frame, steps);
+}
+
+/**
+ * Check if it is possible to navigate backwards one item in history.
+ *
+ * @param o view object to check if backward navigation is possible.
+ *
+ * @return @c EINA_TRUE if possible, @c EINA_FALSE otherwise.
+ *
+ * @see ewk_view_navigate_possible()
+ */
+Eina_Bool ewk_view_back_possible(Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ return ewk_frame_back_possible(sd->main_frame);
+}
+
+/**
+ * Check if it is possible to navigate forwards one item in history.
+ *
+ * @param o view object to check if forward navigation is possible.
+ *
+ * @return @c EINA_TRUE if possible, @c EINA_FALSE otherwise.
+ *
+ * @see ewk_view_navigate_possible()
+ */
+Eina_Bool ewk_view_forward_possible(Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ return ewk_frame_forward_possible(sd->main_frame);
+}
+
+/**
+ * Check if it is possible to navigate given @a steps in history.
+ *
+ * @param o view object to navigate.
+ * @param steps if positive navigates that amount forwards, if negative
+ * does backwards.
+ *
+ * @return @c EINA_TRUE if possible, @c EINA_FALSE otherwise.
+ */
+Eina_Bool ewk_view_navigate_possible(Evas_Object* o, int steps)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ return ewk_frame_navigate_possible(sd->main_frame, steps);
+}
+
+/**
+ * Check if navigation history (back-forward lists) is enabled.
+ *
+ * @param o view object to check if navigation history is enabled.
+ *
+ * @return @c EINA_TRUE if view keeps history, @c EINA_FALSE otherwise.
+ */
+Eina_Bool ewk_view_history_enable_get(const Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
+ return priv->page->backForwardList()->enabled();
+}
+
+/**
+ * Sets if navigation history (back-forward lists) is enabled.
+ *
+ * @param o view object to set if navigation history is enabled.
+ * @param enable @c EINA_TRUE if we want to enable navigation history;
+ * @c EINA_FALSE otherwise.
+ *
+ * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
+ */
+Eina_Bool ewk_view_history_enable_set(Evas_Object* o, Eina_Bool enable)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
+ priv->page->backForwardList()->setEnabled(enable);
+ return EINA_TRUE;
+}
+
+/**
+ * Gets the history (back-forward list) associated with this view.
+ *
+ * @param o view object to get navigation history from.
+ *
+ * @return returns the history instance handle associated with this
+ * view or @c 0 on errors (including when history is not
+ * enabled with ewk_view_history_enable_set()). This instance
+ * is unique for this view and thus multiple calls to this
+ * function with the same view as parameter returns the same
+ * handle. This handle is alive while view is alive, thus one
+ * might want to listen for EVAS_CALLBACK_DEL on given view
+ * (@a o) to know when to stop using returned handle.
+ *
+ * @see ewk_view_history_enable_set()
+ */
+Ewk_History* ewk_view_history_get(const Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
+ if (!priv->page->backForwardList()->enabled()) {
+ ERR("asked history, but it's disabled! Returning 0!");
+ return 0;
+ }
+ return priv->history;
+}
+
+/**
+ * Get the current zoom level of main frame.
+ *
+ * @param o view object to query zoom level.
+ *
+ * @return current zoom level in use or -1.0 on error.
+ */
+float ewk_view_zoom_get(const Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, -1.0);
+ return ewk_frame_zoom_get(sd->main_frame);
+}
+
+/**
+ * Set the current zoom level of main frame.
+ *
+ * @param o view object to set zoom level.
+ * @param zoom new level to use.
+ * @param cx x of center coordinate
+ * @param cy y of center coordinate
+ *
+ * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
+ */
+Eina_Bool ewk_view_zoom_set(Evas_Object* o, float zoom, Evas_Coord cx, Evas_Coord cy)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->api, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->api->zoom_set, EINA_FALSE);
+ if (zoom < ZOOM_MIN) {
+ WRN("zoom level is < %f : %f", (double)ZOOM_MIN, (double)zoom);
+ return EINA_FALSE;
+ }
+ if (zoom > ZOOM_MAX) {
+ WRN("zoom level is > %f : %f", (double)ZOOM_MAX, (double)zoom);
+ return EINA_FALSE;
+ }
+
+ if (cx >= sd->view.w)
+ cx = sd->view.w - 1;
+ if (cy >= sd->view.h)
+ cy = sd->view.h - 1;
+ if (cx < 0)
+ cx = 0;
+ if (cy < 0)
+ cy = 0;
+ _ewk_view_zoom_animated_mark_stop(sd);
+ return sd->api->zoom_set(sd, zoom, cx, cy);
+}
+
+Eina_Bool ewk_view_zoom_weak_smooth_scale_get(const Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ return sd->zoom_weak_smooth_scale;
+}
+
+void ewk_view_zoom_weak_smooth_scale_set(Evas_Object* o, Eina_Bool smooth_scale)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd);
+ smooth_scale = !!smooth_scale;
+ if (sd->zoom_weak_smooth_scale == smooth_scale)
+ return;
+ sd->zoom_weak_smooth_scale = smooth_scale;
+ EINA_SAFETY_ON_NULL_RETURN(sd->api);
+ EINA_SAFETY_ON_NULL_RETURN(sd->api->zoom_weak_smooth_scale_set);
+ sd->api->zoom_weak_smooth_scale_set(sd, smooth_scale);
+}
+
+/**
+ * Set the current zoom level of backing store, centered at given point.
+ *
+ * Unlike ewk_view_zoom_set(), this call do not ask WebKit to render
+ * at new size, but scale what is already rendered, being much faster
+ * but worse quality.
+ *
+ * Often one should use ewk_view_zoom_animated_set(), it will call the
+ * same machinery internally.
+ *
+ * @note this will set variables used by ewk_view_zoom_animated_set()
+ * so sub-classes will not reset internal state on their
+ * "calculate" phase. To unset those and enable sub-classes to
+ * reset their internal state, call
+ * ewk_view_zoom_animated_mark_stop(). Namely, this call will
+ * set ewk_view_zoom_animated_mark_start() to actual webkit zoom
+ * level, ewk_view_zoom_animated_mark_end() and
+ * ewk_view_zoom_animated_mark_current() to given zoom level.
+ *
+ * @param o view object to set weak zoom level.
+ * @param zoom level to scale backing store.
+ * @param cx horizontal center offset, relative to object (w/2 is middle).
+ * @param cy vertical center offset, relative to object (h/2 is middle).
+ *
+ * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
+ */
+Eina_Bool ewk_view_zoom_weak_set(Evas_Object* o, float zoom, Evas_Coord cx, Evas_Coord cy)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->api, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->api->zoom_weak_set, EINA_FALSE);
+ if (zoom < ZOOM_MIN) {
+ WRN("zoom level is < %f : %f", (double)ZOOM_MIN, (double)zoom);
+ return EINA_FALSE;
+ }
+ if (zoom > ZOOM_MAX) {
+ WRN("zoom level is > %f : %f", (double)ZOOM_MAX, (double)zoom);
+ return EINA_FALSE;
+ }
+
+ if (cx >= sd->view.w)
+ cx = sd->view.w - 1;
+ if (cy >= sd->view.h)
+ cy = sd->view.h - 1;
+ if (cx < 0)
+ cx = 0;
+ if (cy < 0)
+ cy = 0;
+
+ sd->animated_zoom.zoom.start = ewk_frame_zoom_get(sd->main_frame);
+ sd->animated_zoom.zoom.end = zoom;
+ sd->animated_zoom.zoom.current = zoom;
+ return sd->api->zoom_weak_set(sd, zoom, cx, cy);
+}
+
+/**
+ * Mark internal zoom animation state to given zoom.
+ *
+ * This does not modify any actual zoom in WebKit or backing store,
+ * just set the Ewk_View_Smart_Data->animated_zoom.zoom.start so
+ * sub-classes will know they should not reset their internal state.
+ *
+ * @param o view object to change value.
+ * @param zoom new start value.
+ *
+ * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
+ *
+ * @see ewk_view_zoom_animated_set()
+ * @see ewk_view_zoom_weak_set()
+ * @see ewk_view_zoom_animated_mark_stop()
+ * @see ewk_view_zoom_animated_mark_end()
+ * @see ewk_view_zoom_animated_mark_current()
+ */
+Eina_Bool ewk_view_zoom_animated_mark_start(Evas_Object* o, float zoom)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ sd->animated_zoom.zoom.start = zoom;
+ return EINA_TRUE;
+}
+
+/**
+ * Mark internal zoom animation state to given zoom.
+ *
+ * This does not modify any actual zoom in WebKit or backing store,
+ * just set the Ewk_View_Smart_Data->animated_zoom.zoom.end so
+ * sub-classes will know they should not reset their internal state.
+ *
+ * @param o view object to change value.
+ * @param zoom new end value.
+ *
+ * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
+ *
+ * @see ewk_view_zoom_animated_set()
+ * @see ewk_view_zoom_weak_set()
+ * @see ewk_view_zoom_animated_mark_stop()
+ * @see ewk_view_zoom_animated_mark_start()
+ * @see ewk_view_zoom_animated_mark_current()
+ */
+Eina_Bool ewk_view_zoom_animated_mark_end(Evas_Object* o, float zoom)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ sd->animated_zoom.zoom.end = zoom;
+ return EINA_TRUE;
+}
+
+/**
+ * Mark internal zoom animation state to given zoom.
+ *
+ * This does not modify any actual zoom in WebKit or backing store,
+ * just set the Ewk_View_Smart_Data->animated_zoom.zoom.current so
+ * sub-classes will know they should not reset their internal state.
+ *
+ * @param o view object to change value.
+ * @param zoom new current value.
+ *
+ * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
+ *
+ * @see ewk_view_zoom_animated_set()
+ * @see ewk_view_zoom_weak_set()
+ * @see ewk_view_zoom_animated_mark_stop()
+ * @see ewk_view_zoom_animated_mark_start()
+ * @see ewk_view_zoom_animated_mark_end()
+ */
+Eina_Bool ewk_view_zoom_animated_mark_current(Evas_Object* o, float zoom)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ sd->animated_zoom.zoom.current = zoom;
+ return EINA_TRUE;
+}
+
+/**
+ * Unmark internal zoom animation state.
+ *
+ * This zero all start, end and current values.
+ *
+ * @param o view object to mark as animated is stopped.
+ *
+ * @see ewk_view_zoom_animated_mark_start()
+ * @see ewk_view_zoom_animated_mark_end()
+ * @see ewk_view_zoom_animated_mark_current()
+ * @see ewk_view_zoom_weak_set()
+ */
+Eina_Bool ewk_view_zoom_animated_mark_stop(Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ _ewk_view_zoom_animated_mark_stop(sd);
+ return EINA_TRUE;
+}
+
+/**
+ * Set the current zoom level while animating.
+ *
+ * If the view was already animating to another zoom, it will start
+ * from current point to the next provided zoom (@a zoom parameter)
+ * and duration (@a duration parameter).
+ *
+ * This is the recommended way to do transitions from one level to
+ * another. However, one may wish to do those from outside, in that
+ * case use ewk_view_zoom_weak_set() and later control intermediate
+ * states with ewk_view_zoom_animated_mark_current(),
+ * ewk_view_zoom_animated_mark_end() and
+ * ewk_view_zoom_animated_mark_stop().
+ *
+ * @param o view object to animate.
+ * @param zoom final zoom level to use.
+ * @param duration time in seconds the animation should take.
+ * @param cx offset inside object that defines zoom center. 0 is left side.
+ * @param cy offset inside object that defines zoom center. 0 is top side.
+ * @return @c EINA_TRUE if animation will be started, @c EINA_FALSE if not
+ * because zoom is too small/big.
+ */
+Eina_Bool ewk_view_zoom_animated_set(Evas_Object* o, float zoom, float duration, Evas_Coord cx, Evas_Coord cy)
+{
+ double now;
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->api, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->api->zoom_weak_set, EINA_FALSE);
+
+ if (zoom < ZOOM_MIN) {
+ WRN("zoom level is < %f : %f", (double)ZOOM_MIN, (double)zoom);
+ return EINA_FALSE;
+ }
+ if (zoom > ZOOM_MAX) {
+ WRN("zoom level is > %f : %f", (double)ZOOM_MAX, (double)zoom);
+ return EINA_FALSE;
+ }
+
+ if (priv->animated_zoom.animator)
+ priv->animated_zoom.zoom.start = _ewk_view_zoom_animated_current(priv);
+ else {
+ priv->animated_zoom.zoom.start = ewk_frame_zoom_get(sd->main_frame);
+ _ewk_view_zoom_animation_start(sd);
+ }
+
+ if (cx < 0)
+ cx = 0;
+ if (cy < 0)
+ cy = 0;
+
+ now = ecore_loop_time_get();
+ priv->animated_zoom.time.start = now;
+ priv->animated_zoom.time.end = now + duration;
+ priv->animated_zoom.time.duration = duration;
+ priv->animated_zoom.zoom.end = zoom;
+ priv->animated_zoom.zoom.range = (priv->animated_zoom.zoom.end - priv->animated_zoom.zoom.start);
+ priv->animated_zoom.center.x = cx;
+ priv->animated_zoom.center.y = cy;
+ sd->animated_zoom.zoom.current = priv->animated_zoom.zoom.start;
+ sd->animated_zoom.zoom.start = priv->animated_zoom.zoom.start;
+ sd->animated_zoom.zoom.end = priv->animated_zoom.zoom.end;
+
+ return EINA_TRUE;
+}
+
+/**
+ * Query if zoom level just applies to text and not other elements.
+ *
+ * @param o view to query setting.
+ *
+ * @return @c EINA_TRUE if just text are scaled, @c EINA_FALSE otherwise.
+ */
+Eina_Bool ewk_view_zoom_text_only_get(const Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ return ewk_frame_zoom_text_only_get(sd->main_frame);
+}
+
+/**
+ * Set if zoom level just applies to text and not other elements.
+ *
+ * @param o view to change setting.
+ * @param setting @c EINA_TRUE if zoom should just be applied to text.
+ *
+ * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
+ */
+Eina_Bool ewk_view_zoom_text_only_set(Evas_Object* o, Eina_Bool setting)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ return ewk_frame_zoom_text_only_set(sd->main_frame, setting);
+}
+
+/**
+ * Hint engine to pre-render region.
+ *
+ * Engines and backing store might be able to pre-render regions in
+ * order to speed up zooming or scrolling to that region. Not all
+ * engines might implement that and they will return @c EINA_FALSE
+ * in that case.
+ *
+ * The given region is a hint. Engines might do bigger or smaller area
+ * that covers that region. Pre-render might not be immediate, it may
+ * be postponed to a thread, operated cooperatively in the main loop
+ * and may be even ignored or cancelled afterwards.
+ *
+ * Multiple requests might be queued by engines. One can clear/forget
+ * about them with ewk_view_pre_render_cancel().
+ *
+ * @param o view to ask pre-render of given region.
+ * @param x absolute coordinate (0=left) to pre-render at zoom.
+ * @param y absolute coordinate (0=top) to pre-render at zoom.
+ * @param w width to pre-render starting from @a x at zoom.
+ * @param h height to pre-render starting from @a y at zoom.
+ * @param zoom desired zoom.
+ *
+ * @return @c EINA_TRUE if request was accepted, @c EINA_FALSE
+ * otherwise (errors, pre-render not supported, etc).
+ *
+ * @see ewk_view_pre_render_cancel()
+ */
+Eina_Bool ewk_view_pre_render_region(Evas_Object* o, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h, float zoom)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->api->pre_render_region, EINA_FALSE);
+ float cur_zoom = ewk_frame_zoom_get(sd->main_frame);
+ Evas_Coord cw, ch;
+
+ if (cur_zoom < 0.00001)
+ return EINA_FALSE;
+ if (!ewk_frame_contents_size_get(sd->main_frame, &cw, &ch))
+ return EINA_FALSE;
+
+ cw *= zoom / cur_zoom;
+ ch *= zoom / cur_zoom;
+ DBG("region %d,%d+%dx%d @ %f contents=%dx%d", x, y, w, h, zoom, cw, ch);
+
+ if (x + w > cw)
+ w = cw - x;
+
+ if (y + h > ch)
+ h = ch - y;
+
+ if (x < 0) {
+ w += x;
+ x = 0;
+ }
+ if (y < 0) {
+ h += y;
+ y = 0;
+ }
+
+ return sd->api->pre_render_region(sd, x, y, w, h, zoom);
+}
+
+/**
+ * Cancel (clear) previous pre-render requests.
+ *
+ * @param o view to clear pre-render requests.
+ */
+void ewk_view_pre_render_cancel(Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd);
+ EINA_SAFETY_ON_NULL_RETURN(sd->api->pre_render_cancel);
+ sd->api->pre_render_cancel(sd);
+}
+
+const char* ewk_view_setting_user_agent_get(const Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
+ return priv->settings.user_agent;
+}
+
+Eina_Bool ewk_view_setting_user_agent_set(Evas_Object* o, const char* user_agent)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
+ if (eina_stringshare_replace(&priv->settings.user_agent, user_agent)) {
+ WebCore::FrameLoaderClientEfl* client = static_cast<WebCore::FrameLoaderClientEfl*>(priv->main_frame->loader()->client());
+ client->setCustomUserAgent(WebCore::String::fromUTF8(user_agent));
+ }
+ return EINA_TRUE;
+}
+
+const char* ewk_view_setting_user_stylesheet_get(const Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
+ return priv->settings.user_stylesheet;
+}
+
+Eina_Bool ewk_view_setting_user_stylesheet_set(Evas_Object* o, const char* uri)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
+ if (eina_stringshare_replace(&priv->settings.user_stylesheet, uri)) {
+ WebCore::KURL kurl(WebCore::KURL(), WebCore::String::fromUTF8(uri));
+ priv->page_settings->setUserStyleSheetLocation(kurl);
+ }
+ return EINA_TRUE;
+}
+
+Eina_Bool ewk_view_setting_auto_load_images_get(const Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
+ return priv->settings.auto_load_images;
+}
+
+Eina_Bool ewk_view_setting_auto_load_images_set(Evas_Object* o, Eina_Bool automatic)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
+ automatic = !!automatic;
+ if (priv->settings.auto_load_images != automatic) {
+ priv->page_settings->setLoadsImagesAutomatically(automatic);
+ priv->settings.auto_load_images = automatic;
+ }
+ return EINA_TRUE;
+}
+
+Eina_Bool ewk_view_setting_auto_shrink_images_get(const Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
+ return priv->settings.auto_shrink_images;
+}
+
+Eina_Bool ewk_view_setting_auto_shrink_images_set(Evas_Object* o, Eina_Bool automatic)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
+ automatic = !!automatic;
+ if (priv->settings.auto_shrink_images != automatic) {
+ priv->page_settings->setShrinksStandaloneImagesToFit(automatic);
+ priv->settings.auto_shrink_images = automatic;
+ }
+ return EINA_TRUE;
+}
+
+Eina_Bool ewk_view_setting_enable_scripts_get(const Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
+ return priv->settings.enable_scripts;
+}
+
+Eina_Bool ewk_view_setting_enable_scripts_set(Evas_Object* o, Eina_Bool enable)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
+ enable = !!enable;
+ if (priv->settings.enable_scripts != enable) {
+ priv->page_settings->setJavaScriptEnabled(enable);
+ priv->settings.enable_scripts = enable;
+ }
+ return EINA_TRUE;
+}
+
+Eina_Bool ewk_view_setting_enable_plugins_get(const Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
+ return priv->settings.enable_plugins;
+}
+
+Eina_Bool ewk_view_setting_enable_plugins_set(Evas_Object* o, Eina_Bool enable)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
+ enable = !!enable;
+ if (priv->settings.enable_plugins != enable) {
+ priv->page_settings->setPluginsEnabled(enable);
+ priv->settings.enable_plugins = enable;
+ }
+ return EINA_TRUE;
+}
+
+Eina_Bool ewk_view_setting_scripts_window_open_get(const Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
+ return priv->settings.scripts_window_open;
+}
+
+Eina_Bool ewk_view_setting_scripts_window_open_set(Evas_Object* o, Eina_Bool allow)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
+ allow = !!allow;
+ if (priv->settings.scripts_window_open != allow) {
+ priv->page_settings->setJavaScriptCanOpenWindowsAutomatically(allow);
+ priv->settings.scripts_window_open = allow;
+ }
+ return EINA_TRUE;
+}
+
+Eina_Bool ewk_view_setting_resizable_textareas_get(const Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
+ return priv->settings.resizable_textareas;
+}
+
+Eina_Bool ewk_view_setting_resizable_textareas_set(Evas_Object* o, Eina_Bool enable)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
+ enable = !!enable;
+ if (priv->settings.resizable_textareas != enable) {
+ priv->page_settings->setTextAreasAreResizable(enable);
+ priv->settings.resizable_textareas = enable;
+ }
+ return EINA_TRUE;
+}
+
+Eina_Bool ewk_view_setting_private_browsing_get(const Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
+ return priv->settings.private_browsing;
+}
+
+Eina_Bool ewk_view_setting_private_browsing_set(Evas_Object* o, Eina_Bool enable)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
+ enable = !!enable;
+ if (priv->settings.private_browsing != enable) {
+ priv->page_settings->setPrivateBrowsingEnabled(enable);
+ priv->settings.private_browsing = enable;
+ }
+ return EINA_TRUE;
+}
+
+Eina_Bool ewk_view_setting_caret_browsing_get(const Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
+ return priv->settings.caret_browsing;
+}
+
+Eina_Bool ewk_view_setting_caret_browsing_set(Evas_Object* o, Eina_Bool enable)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
+ enable = !!enable;
+ if (priv->settings.caret_browsing != enable) {
+ priv->page_settings->setCaretBrowsingEnabled(enable);
+ priv->settings.caret_browsing = enable;
+ }
+ return EINA_TRUE;
+}
+
+/**
+ * Get current encoding of this View.
+ *
+ * @param o View.
+ *
+ * @return A pointer to an eina_strinshare containing the current custom
+ * encoding for View object @param o, or @c 0 if it's not set.
+ */
+const char* ewk_view_setting_encoding_custom_get(const Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
+ Evas_Object* main_frame = ewk_view_frame_main_get(o);
+ WebCore::Frame* core_frame = ewk_frame_core_get(main_frame);
+
+ WebCore::String overrideEncoding = core_frame->loader()->documentLoader()->overrideEncoding();
+
+ if (overrideEncoding.isEmpty())
+ return 0;
+
+ eina_stringshare_replace(&priv->settings.encoding_custom, overrideEncoding.utf8().data());
+ return priv->settings.encoding_custom;
+}
+
+/**
+ * Set encoding of this View and reload page.
+ *
+ * @param o View.
+ * @param encoding The new encoding or @c 0 to restore the default encoding.
+ *
+ * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
+ */
+Eina_Bool ewk_view_setting_encoding_custom_set(Evas_Object* o, const char *encoding)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
+ Evas_Object* main_frame = ewk_view_frame_main_get(o);
+ WebCore::Frame* core_frame = ewk_frame_core_get(main_frame);
+DBG("%s", encoding);
+ eina_stringshare_replace(&priv->settings.encoding_custom, encoding);
+ core_frame->loader()->reloadWithOverrideEncoding(WebCore::String::fromUTF8(encoding));
+
+ return EINA_TRUE;
+}
+
+const char* ewk_view_setting_encoding_default_get(const Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
+ return priv->settings.encoding_default;
+}
+
+Eina_Bool ewk_view_setting_encoding_default_set(Evas_Object* o, const char* encoding)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
+ if (eina_stringshare_replace(&priv->settings.encoding_default, encoding))
+ priv->page_settings->setDefaultTextEncodingName(WebCore::String::fromUTF8(encoding));
+ return EINA_TRUE;
+}
+
+int ewk_view_setting_font_minimum_size_get(const Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
+ return priv->settings.font_minimum_size;
+}
+
+Eina_Bool ewk_view_setting_font_minimum_size_set(Evas_Object* o, int size)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
+ if (priv->settings.font_minimum_size != size) {
+ priv->page_settings->setMinimumFontSize(size);
+ priv->settings.font_minimum_size = size;
+ }
+ return EINA_TRUE;
+}
+
+int ewk_view_setting_font_minimum_logical_size_get(const Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
+ return priv->settings.font_minimum_logical_size;
+}
+
+Eina_Bool ewk_view_setting_font_minimum_logical_size_set(Evas_Object* o, int size)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
+ if (priv->settings.font_minimum_logical_size != size) {
+ priv->page_settings->setMinimumLogicalFontSize(size);
+ priv->settings.font_minimum_logical_size = size;
+ }
+ return EINA_TRUE;
+}
+
+int ewk_view_setting_font_default_size_get(const Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
+ return priv->settings.font_default_size;
+}
+
+Eina_Bool ewk_view_setting_font_default_size_set(Evas_Object* o, int size)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
+ if (priv->settings.font_default_size != size) {
+ priv->page_settings->setDefaultFontSize(size);
+ priv->settings.font_default_size = size;
+ }
+ return EINA_TRUE;
+}
+
+int ewk_view_setting_font_monospace_size_get(const Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
+ return priv->settings.font_monospace_size;
+}
+
+Eina_Bool ewk_view_setting_font_monospace_size_set(Evas_Object* o, int size)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
+ if (priv->settings.font_monospace_size != size) {
+ priv->page_settings->setDefaultFixedFontSize(size);
+ priv->settings.font_monospace_size = size;
+ }
+ return EINA_TRUE;
+}
+
+const char* ewk_view_setting_font_standard_get(const Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
+ return priv->settings.font_standard;
+}
+
+Eina_Bool ewk_view_setting_font_standard_set(Evas_Object* o, const char* family)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
+ if (eina_stringshare_replace(&priv->settings.font_standard, family)) {
+ WebCore::AtomicString s = WebCore::String::fromUTF8(family);
+ priv->page_settings->setStandardFontFamily(s);
+ }
+ return EINA_TRUE;
+}
+
+const char* ewk_view_setting_font_cursive_get(const Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
+ return priv->settings.font_cursive;
+}
+
+Eina_Bool ewk_view_setting_font_cursive_set(Evas_Object* o, const char* family)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
+ if (eina_stringshare_replace(&priv->settings.font_cursive, family)) {
+ WebCore::AtomicString s = WebCore::String::fromUTF8(family);
+ priv->page_settings->setCursiveFontFamily(s);
+ }
+ return EINA_TRUE;
+}
+
+const char* ewk_view_setting_font_fantasy_get(const Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
+ return priv->settings.font_fantasy;
+}
+
+Eina_Bool ewk_view_setting_font_fantasy_set(Evas_Object* o, const char* family)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
+ if (eina_stringshare_replace(&priv->settings.font_fantasy, family)) {
+ WebCore::AtomicString s = WebCore::String::fromUTF8(family);
+ priv->page_settings->setFantasyFontFamily(s);
+ }
+ return EINA_TRUE;
+}
+
+const char* ewk_view_setting_font_monospace_get(const Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
+ return priv->settings.font_monospace;
+}
+
+Eina_Bool ewk_view_setting_font_monospace_set(Evas_Object* o, const char* family)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
+ if (eina_stringshare_replace(&priv->settings.font_monospace, family)) {
+ WebCore::AtomicString s = WebCore::String::fromUTF8(family);
+ priv->page_settings->setFixedFontFamily(s);
+ }
+ return EINA_TRUE;
+}
+
+const char* ewk_view_setting_font_serif_get(const Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
+ return priv->settings.font_serif;
+}
+
+Eina_Bool ewk_view_setting_font_serif_set(Evas_Object* o, const char* family)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
+ if (eina_stringshare_replace(&priv->settings.font_serif, family)) {
+ WebCore::AtomicString s = WebCore::String::fromUTF8(family);
+ priv->page_settings->setSerifFontFamily(s);
+ }
+ return EINA_TRUE;
+}
+
+const char* ewk_view_setting_font_sans_serif_get(const Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
+ return priv->settings.font_sans_serif;
+}
+
+Eina_Bool ewk_view_setting_font_sans_serif_set(Evas_Object* o, const char* family)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
+ if (eina_stringshare_replace(&priv->settings.font_sans_serif, family)) {
+ WebCore::AtomicString s = WebCore::String::fromUTF8(family);
+ priv->page_settings->setSansSerifFontFamily(s);
+ }
+ return EINA_TRUE;
+}
+
+/**
+ * Similar to evas_object_smart_data_get(), but does type checking.
+ *
+ * @param o view object to query internal data.
+ * @return internal data or @c 0 on errors (ie: incorrect type of @a o).
+ */
+Ewk_View_Smart_Data* ewk_view_smart_data_get(const Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
+ return sd;
+}
+
+/**
+ * Gets the internal array of repaint requests.
+ *
+ * This array should not be modified anyhow. It should be processed
+ * immediately as any further ewk_view call might change it, like
+ * those that add repaints or flush them, so be sure that your code
+ * does not call any of those while you process the repaints,
+ * otherwise copy the array.
+ *
+ * @param priv private handle pointer of the view to get repaints.
+ * @param count where to return the number of elements of returned array.
+ *
+ * @return reference to array of requested repaints.
+ *
+ * @note this is not for general use but just for subclasses that want
+ * to define their own backing store.
+ */
+const Eina_Rectangle* ewk_view_repaints_get(const Ewk_View_Private_Data* priv, size_t* count)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(count, 0);
+ if (count)
+ *count = 0;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(priv, 0);
+ if (count)
+ *count = priv->repaints.count;
+ return priv->repaints.array;
+}
+
+/**
+ * Gets the internal array of scroll requests.
+ *
+ * This array should not be modified anyhow. It should be processed
+ * immediately as any further ewk_view call might change it, like
+ * those that add scrolls or flush them, so be sure that your code
+ * does not call any of those while you process the scrolls,
+ * otherwise copy the array.
+ *
+ * @param priv private handle pointer of the view to get scrolls.
+ * @param count where to return the number of elements of returned array.
+ *
+ * @return reference to array of requested scrolls.
+ *
+ * @note this is not for general use but just for subclasses that want
+ * to define their own backing store.
+ */
+const Ewk_Scroll_Request* ewk_view_scroll_requests_get(const Ewk_View_Private_Data* priv, size_t* count)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(count, 0);
+ if (count)
+ *count = 0;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(priv, 0);
+ if (count)
+ *count = priv->scrolls.count;
+ return priv->scrolls.array;
+}
+
+/**
+ * Add a new repaint request to queue.
+ *
+ * The repaints are assumed to be relative to current viewport.
+ *
+ * @param priv private handle pointer of the view to add repaint request.
+ * @param x horizontal position relative to current view port (scrolled).
+ * @param y vertical position relative to current view port (scrolled).
+ * @param w width of area to be repainted
+ * @param h height of area to be repainted
+ *
+ * @note this is not for general use but just for subclasses that want
+ * to define their own backing store.
+ */
+void ewk_view_repaint_add(Ewk_View_Private_Data* priv, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
+{
+ EINA_SAFETY_ON_NULL_RETURN(priv);
+ _ewk_view_repaint_add(priv, x, y, w, h);
+}
+
+/**
+ * Do layout if required, applied recursively.
+ *
+ * @param priv private handle pointer of the view to layout.
+ *
+ * @note this is not for general use but just for subclasses that want
+ * to define their own backing store.
+ */
+void ewk_view_layout_if_needed_recursive(Ewk_View_Private_Data* priv)
+{
+ EINA_SAFETY_ON_NULL_RETURN(priv);
+
+ WebCore::FrameView* v = priv->main_frame->view();
+ if (!v) {
+ ERR("no main frame view");
+ return;
+ }
+ v->layoutIfNeededRecursive();
+}
+
+void ewk_view_scrolls_process(Ewk_View_Smart_Data* sd)
+{
+ EINA_SAFETY_ON_NULL_RETURN(sd);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv);
+ if (!sd->api->scrolls_process(sd))
+ ERR("failed to process scrolls.");
+ _ewk_view_scrolls_flush(priv);
+}
+
+struct _Ewk_View_Paint_Context {
+ WebCore::GraphicsContext* gc;
+ WebCore::FrameView* view;
+ cairo_t* cr;
+};
+
+/**
+ * Create a new paint context using the view as source and cairo as output.
+ *
+ * @param priv private handle pointer of the view to use as paint source.
+ * @param cr cairo context to use as paint destination. A new
+ * reference is taken, so it's safe to call cairo_destroy()
+ * after this function returns.
+ *
+ * @return newly allocated instance or @c 0 on errors.
+ *
+ * @note this is not for general use but just for subclasses that want
+ * to define their own backing store.
+ */
+Ewk_View_Paint_Context* ewk_view_paint_context_new(Ewk_View_Private_Data* priv, cairo_t* cr)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(priv, 0);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(cr, 0);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(priv->main_frame, 0);
+ WebCore::FrameView* view = priv->main_frame->view();
+ EINA_SAFETY_ON_NULL_RETURN_VAL(view, 0);
+ Ewk_View_Paint_Context* ctxt = (Ewk_View_Paint_Context*)malloc(sizeof(*ctxt));
+ EINA_SAFETY_ON_NULL_RETURN_VAL(ctxt, 0);
+
+ ctxt->gc = new WebCore::GraphicsContext(cr);
+ if (!ctxt->gc) {
+ free(ctxt);
+ return 0;
+ }
+ ctxt->view = view;
+ ctxt->cr = cairo_reference(cr);
+ return ctxt;
+}
+
+/**
+ * Destroy previously created paint context.
+ *
+ * @param ctxt paint context to destroy. Must @b not be @c 0.
+ *
+ * @note this is not for general use but just for subclasses that want
+ * to define their own backing store.
+ */
+void ewk_view_paint_context_free(Ewk_View_Paint_Context* ctxt)
+{
+ EINA_SAFETY_ON_NULL_RETURN(ctxt);
+ delete ctxt->gc;
+ cairo_destroy(ctxt->cr);
+ free(ctxt);
+}
+
+/**
+ * Save (push to stack) paint context status.
+ *
+ * @param ctxt paint context to save. Must @b not be @c 0.
+ *
+ * @see ewk_view_paint_context_restore()
+ *
+ * @note this is not for general use but just for subclasses that want
+ * to define their own backing store.
+ */
+void ewk_view_paint_context_save(Ewk_View_Paint_Context* ctxt)
+{
+ EINA_SAFETY_ON_NULL_RETURN(ctxt);
+ cairo_save(ctxt->cr);
+ ctxt->gc->save();
+}
+
+/**
+ * Restore (pop from stack) paint context status.
+ *
+ * @param ctxt paint context to restore. Must @b not be @c 0.
+ *
+ * @see ewk_view_paint_context_save()
+ *
+ * @note this is not for general use but just for subclasses that want
+ * to define their own backing store.
+ */
+void ewk_view_paint_context_restore(Ewk_View_Paint_Context* ctxt)
+{
+ EINA_SAFETY_ON_NULL_RETURN(ctxt);
+ ctxt->gc->restore();
+ cairo_restore(ctxt->cr);
+}
+
+/**
+ * Clip paint context drawings to given area.
+ *
+ * @param ctxt paint context to clip. Must @b not be @c 0.
+ * @param area clip area to use.
+ *
+ * @see ewk_view_paint_context_save()
+ * @see ewk_view_paint_context_restore()
+ *
+ * @note this is not for general use but just for subclasses that want
+ * to define their own backing store.
+ */
+void ewk_view_paint_context_clip(Ewk_View_Paint_Context* ctxt, const Eina_Rectangle* area)
+{
+ EINA_SAFETY_ON_NULL_RETURN(ctxt);
+ EINA_SAFETY_ON_NULL_RETURN(area);
+ ctxt->gc->clip(WebCore::IntRect(area->x, area->y, area->w, area->h));
+}
+
+/**
+ * Paint using context using given area.
+ *
+ * @param ctxt paint context to paint. Must @b not be @c 0.
+ * @param area paint area to use. Coordinates are relative to current viewport,
+ * thus "scrolled".
+ *
+ * @note one may use cairo functions on the cairo context to
+ * translate, scale or any modification that may fit his desires.
+ *
+ * @see ewk_view_paint_context_clip()
+ * @see ewk_view_paint_context_paint_contents()
+ *
+ * @note this is not for general use but just for subclasses that want
+ * to define their own backing store.
+ */
+void ewk_view_paint_context_paint(Ewk_View_Paint_Context* ctxt, const Eina_Rectangle* area)
+{
+ EINA_SAFETY_ON_NULL_RETURN(ctxt);
+ EINA_SAFETY_ON_NULL_RETURN(area);
+
+ WebCore::IntRect rect(area->x, area->y, area->w, area->h);
+
+ if (ctxt->view->isTransparent())
+ ctxt->gc->clearRect(rect);
+ ctxt->view->paint(ctxt->gc, rect);
+}
+
+/**
+ * Paint just contents using context using given area.
+ *
+ * Unlike ewk_view_paint_context_paint(), this function paint just
+ * bare contents and ignores any scrolling, scrollbars and extras. It
+ * will walk the rendering tree and paint contents inside the given
+ * area to the cairo context specified in @a ctxt.
+ *
+ * @param ctxt paint context to paint. Must @b not be @c 0.
+ * @param area paint area to use. Coordinates are absolute to page.
+ *
+ * @note one may use cairo functions on the cairo context to
+ * translate, scale or any modification that may fit his desires.
+ *
+ * @see ewk_view_paint_context_clip()
+ * @see ewk_view_paint_context_paint()
+ *
+ * @note this is not for general use but just for subclasses that want
+ * to define their own backing store.
+ */
+void ewk_view_paint_context_paint_contents(Ewk_View_Paint_Context* ctxt, const Eina_Rectangle* area)
+{
+ EINA_SAFETY_ON_NULL_RETURN(ctxt);
+ EINA_SAFETY_ON_NULL_RETURN(area);
+
+ WebCore::IntRect rect(area->x, area->y, area->w, area->h);
+
+ if (ctxt->view->isTransparent())
+ ctxt->gc->clearRect(rect);
+
+ ctxt->view->paintContents(ctxt->gc, rect);
+}
+
+/**
+ * Scale the contents by the given factors.
+ *
+ * This function applies a scaling transformation using Cairo.
+ *
+ * @param ctxt paint context to paint. Must @b not be @c 0.
+ * @param scale_x scale factor for the X dimension.
+ * @param scale_y scale factor for the Y dimension.
+ */
+void ewk_view_paint_context_scale(Ewk_View_Paint_Context* ctxt, float scale_x, float scale_y)
+{
+ EINA_SAFETY_ON_NULL_RETURN(ctxt);
+
+ ctxt->gc->scale(WebCore::FloatSize(scale_x, scale_y));
+}
+
+/**
+ * Performs a translation of the origin coordinates.
+ *
+ * This function moves the origin coordinates by @p x and @p y pixels.
+ *
+ * @param ctxt paint context to paint. Must @b not be @c 0.
+ * @param x amount of pixels to translate in the X dimension.
+ * @param y amount of pixels to translate in the Y dimension.
+ */
+void ewk_view_paint_context_translate(Ewk_View_Paint_Context* ctxt, float x, float y)
+{
+ EINA_SAFETY_ON_NULL_RETURN(ctxt);
+
+ ctxt->gc->translate(x, y);
+}
+
+/**
+ * Paint using given graphics context the given area.
+ *
+ * This uses viewport relative area and will also handle scrollbars
+ * and other extra elements. See ewk_view_paint_contents() for the
+ * alternative function.
+ *
+ * @param priv private handle pointer of view to use as paint source.
+ * @param cr cairo context to use as paint destination. Its state will
+ * be saved before operation and restored afterwards.
+ * @param area viewport relative geometry to paint.
+ *
+ * @return @c EINA_TRUE on success and @c EINA_FALSE on failure, like
+ * incorrect parameters.
+ *
+ * @note this is an easy to use version, but internal structures are
+ * always created, then graphics context is clipped, then
+ * painted, restored and destroyed. This might not be optimum,
+ * so using #Ewk_View_Paint_Context may be a better solutions
+ * for large number of operations.
+ *
+ * @see ewk_view_paint_contents()
+ * @see ewk_view_paint_context_paint()
+ *
+ * @note this is not for general use but just for subclasses that want
+ * to define their own backing store.
+ */
+Eina_Bool ewk_view_paint(Ewk_View_Private_Data* priv, cairo_t* cr, const Eina_Rectangle* area)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(priv, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(cr, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(area, EINA_FALSE);
+ WebCore::FrameView* view = priv->main_frame->view();
+ EINA_SAFETY_ON_NULL_RETURN_VAL(view, EINA_FALSE);
+
+ if (view->needsLayout())
+ view->forceLayout();
+ WebCore::GraphicsContext gc(cr);
+ WebCore::IntRect rect(area->x, area->y, area->w, area->h);
+
+ cairo_save(cr);
+ gc.save();
+ gc.clip(rect);
+ if (view->isTransparent())
+ gc.clearRect(rect);
+ view->paint(&gc, rect);
+ gc.restore();
+ cairo_restore(cr);
+
+ return EINA_TRUE;
+}
+
+/**
+ * Paint just contents using given graphics context the given area.
+ *
+ * This uses absolute coordinates for area and will just handle
+ * contents, no scrollbars or extras. See ewk_view_paint() for the
+ * alternative solution.
+ *
+ * @param priv private handle pointer of view to use as paint source.
+ * @param cr cairo context to use as paint destination. Its state will
+ * be saved before operation and restored afterwards.
+ * @param area absolute geometry to paint.
+ *
+ * @return @c EINA_TRUE on success and @c EINA_FALSE on failure, like
+ * incorrect parameters.
+ *
+ * @note this is an easy to use version, but internal structures are
+ * always created, then graphics context is clipped, then
+ * painted, restored and destroyed. This might not be optimum,
+ * so using #Ewk_View_Paint_Context may be a better solutions
+ * for large number of operations.
+ *
+ * @see ewk_view_paint()
+ * @see ewk_view_paint_context_paint_contents()
+ *
+ * @note this is not for general use but just for subclasses that want
+ * to define their own backing store.
+ */
+Eina_Bool ewk_view_paint_contents(Ewk_View_Private_Data* priv, cairo_t* cr, const Eina_Rectangle* area)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(priv, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(cr, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(area, EINA_FALSE);
+ WebCore::FrameView* view = priv->main_frame->view();
+ EINA_SAFETY_ON_NULL_RETURN_VAL(view, EINA_FALSE);
+
+ WebCore::GraphicsContext gc(cr);
+ WebCore::IntRect rect(area->x, area->y, area->w, area->h);
+
+ cairo_save(cr);
+ gc.save();
+ gc.clip(rect);
+ if (view->isTransparent())
+ gc.clearRect(rect);
+ view->paintContents(&gc, rect);
+ gc.restore();
+ cairo_restore(cr);
+
+ return EINA_TRUE;
+}
+
+
+/* internal methods ****************************************************/
+/**
+ * @internal
+ * Reports the view is ready to be displayed as all elements are aready.
+ *
+ * Emits signal: "ready" with no parameters.
+ */
+void ewk_view_ready(Evas_Object* o)
+{
+ DBG("o=%p", o);
+ evas_object_smart_callback_call(o, "ready", 0);
+}
+
+/**
+ * @internal
+ * The view title was changed by the frame loader.
+ *
+ * Emits signal: "title,changed" with pointer to new title string.
+ */
+void ewk_view_title_set(Evas_Object* o, const char* title)
+{
+ DBG("o=%p, title=%s", o, title ? title : "(null)");
+ evas_object_smart_callback_call(o, "title,changed", (void*)title);
+}
+
+/**
+ * @internal
+ * Reports that main frame's uri changed.
+ *
+ * Emits signal: "uri,changed" with pointer to the new uri string.
+ */
+void ewk_view_uri_changed(Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd);
+ const char* uri = ewk_frame_uri_get(sd->main_frame);
+ DBG("o=%p, uri=%s", o, uri ? uri : "(null)");
+ evas_object_smart_callback_call(o, "uri,changed", (void*)uri);
+}
+
+/**
+ * @internal
+ * Reports the view started loading something.
+ *
+ * @param o View.
+ *
+ * Emits signal: "load,started" with no parameters.
+ */
+void ewk_view_load_started(Evas_Object* o)
+{
+ DBG("o=%p", o);
+ evas_object_smart_callback_call(o, "load,started", 0);
+}
+
+/**
+ * Reports the frame started loading something.
+ *
+ * @param o View.
+ *
+ * Emits signal: "load,started" on main frame with no parameters.
+ */
+void ewk_view_frame_main_load_started(Evas_Object* o)
+{
+ DBG("o=%p", o);
+ Evas_Object* frame = ewk_view_frame_main_get(o);
+ evas_object_smart_callback_call(frame, "load,started", 0);
+}
+
+/**
+ * @internal
+ * Reports the main frame started provisional load.
+ *
+ * @param o View.
+ *
+ * Emits signal: "load,provisional" on View with no parameters.
+ */
+void ewk_view_load_provisional(Evas_Object* o)
+{
+ DBG("o=%p", o);
+ evas_object_smart_callback_call(o, "load,provisional", 0);
+}
+
+/**
+ * @internal
+ * Reports view can be shown after a new window is created.
+ *
+ * @param o Frame.
+ *
+ * Emits signal: "load,newwindow,show" on view with no parameters.
+ */
+void ewk_view_load_show(Evas_Object* o)
+{
+ DBG("o=%p", o);
+ evas_object_smart_callback_call(o, "load,newwindow,show", 0);
+}
+
+
+/**
+ * @internal
+ * Reports the main frame was cleared.
+ *
+ * @param o View.
+ */
+void ewk_view_frame_main_cleared(Evas_Object* o)
+{
+ DBG("o=%p", o);
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd);
+ EINA_SAFETY_ON_NULL_RETURN(sd->api->flush);
+ sd->api->flush(sd);
+}
+
+/**
+ * @internal
+ * Reports the main frame received an icon.
+ *
+ * @param o View.
+ *
+ * Emits signal: "icon,received" with no parameters.
+ */
+void ewk_view_frame_main_icon_received(Evas_Object* o)
+{
+ DBG("o=%p", o);
+ Evas_Object* frame = ewk_view_frame_main_get(o);
+ evas_object_smart_callback_call(frame, "icon,received", 0);
+}
+
+/**
+ * @internal
+ * Reports load finished, optionally with error information.
+ *
+ * Emits signal: "load,finished" with pointer to #Ewk_Frame_Load_Error
+ * if any error, or @c 0 if successful load.
+ *
+ * @note there should not be any error stuff here, but trying to be
+ * compatible with previous WebKit.
+ */
+void ewk_view_load_finished(Evas_Object* o, const Ewk_Frame_Load_Error* error)
+{
+ DBG("o=%p, error=%p", o, error);
+ evas_object_smart_callback_call(o, "load,finished", (void*)error);
+}
+
+/**
+ * @internal
+ * Reports load failed with error information.
+ *
+ * Emits signal: "load,error" with pointer to Ewk_Frame_Load_Error.
+ */
+void ewk_view_load_error(Evas_Object* o, const Ewk_Frame_Load_Error* error)
+{
+ DBG("o=%p, error=%p", o, error);
+ evas_object_smart_callback_call(o, "load,error", (void*)error);
+}
+
+/**
+ * @internal
+ * Reports load progress changed.
+ *
+ * Emits signal: "load,progress" with pointer to a double from 0.0 to 1.0.
+ */
+void ewk_view_load_progress_changed(Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv);
+
+ // Evas_Coord w, h;
+ double progress = priv->page->progress()->estimatedProgress();
+
+ DBG("o=%p (p=%0.3f)", o, progress);
+
+ evas_object_smart_callback_call(o, "load,progress", &progress);
+}
+
+/**
+ * @internal
+ * Reports view @param o should be restored to default conditions
+ *
+ * @param o View.
+ * @param frame Frame that originated restore.
+ *
+ * Emits signal: "restore" with frame.
+ */
+void ewk_view_restore_state(Evas_Object* o, Evas_Object* frame)
+{
+ evas_object_smart_callback_call(o, "restore", frame);
+}
+
+/**
+ * @internal
+ * Delegates to browser the creation of a new window. If it is not implemented,
+ * current view is returned, so navigation might continue in same window.
+ *
+ * @param o Current view.
+ *
+ * @return New view, in case smart class implements the creation of new windows;
+ * else, current view @param o.
+ */
+Evas_Object* ewk_view_window_create(Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
+
+ if (!sd->api->window_create)
+ return o;
+
+ return sd->api->window_create(sd);
+}
+
+/**
+ * @internal
+ * Reports mouse has moved over a link.
+ *
+ * Emits signal: "link,hover,in"
+ */
+void ewk_view_mouse_link_hover_in(Evas_Object* o, void* data)
+{
+ evas_object_smart_callback_call(o, "link,hover,in", data);
+}
+
+/**
+ * @internal
+ * Reports mouse is not over a link anymore.
+ *
+ * Emits signal: "link,hover,out"
+ */
+void ewk_view_mouse_link_hover_out(Evas_Object* o)
+{
+ evas_object_smart_callback_call(o, "link,hover,out", 0);
+}
+
+/**
+ * @internal
+ * Set toolbar visible.
+ *
+ * Emits signal: "toolbars,visible,set" with a pointer to a boolean.
+ */
+void ewk_view_toolbars_visible_set(Evas_Object* o, Eina_Bool visible)
+{
+ DBG("o=%p (visible=%d)", o, !!visible);
+ evas_object_smart_callback_call(o, "toolbars,visible,set", &visible);
+}
+
+/**
+ * @internal
+ * Get toolbar visibility.
+ *
+ * @param o View.
+ * @param visible boolean pointer in which to save the result. It defaults
+ * to @c FALSE, i.e. if browser does no listen to emitted signal, it means
+ * there are no toolbars and therefore they are not visible.
+ *
+ * Emits signal: "toolbars,visible,get" with a pointer to a boolean.
+ */
+void ewk_view_toolbars_visible_get(Evas_Object* o, Eina_Bool* visible)
+{
+ DBG("%s, o=%p", __func__, o);
+ *visible = EINA_FALSE;
+ evas_object_smart_callback_call(o, "toolbars,visible,get", visible);
+}
+
+/**
+ * @internal
+ * Set statusbar visible.
+ *
+ * @param o View.
+ * @param visible @c TRUE if statusbar are visible, @c FALSE otherwise.
+ *
+ * Emits signal: "statusbar,visible,set" with a pointer to a boolean.
+ */
+void ewk_view_statusbar_visible_set(Evas_Object* o, Eina_Bool visible)
+{
+ DBG("o=%p (visible=%d)", o, !!visible);
+ evas_object_smart_callback_call(o, "statusbar,visible,set", &visible);
+}
+
+/**
+ * @internal
+ * Get statusbar visibility.
+ *
+ * @param o View.
+ * @param visible boolean pointer in which to save the result. It defaults
+ * to @c FALSE, i.e. if browser does no listen to emitted signal, it means
+ * there is no statusbar and therefore it is not visible.
+ *
+ * Emits signal: "statusbar,visible,get" with a pointer to a boolean.
+ */
+void ewk_view_statusbar_visible_get(Evas_Object* o, Eina_Bool* visible)
+{
+ DBG("%s, o=%p", __func__, o);
+ *visible = EINA_FALSE;
+ evas_object_smart_callback_call(o, "statusbar,visible,get", visible);
+}
+
+/**
+ * @internal
+ * Set text of statusbar
+ *
+ * @param o View.
+ * @param text New text to put on statusbar.
+ *
+ * Emits signal: "statusbar,text,set" with a string.
+ */
+void ewk_view_statusbar_text_set(Evas_Object* o, const char* text)
+{
+ DBG("o=%p (text=%s)", o, text);
+ INF("status bar text set: %s", text);
+ evas_object_smart_callback_call(o, "statusbar,text,set", (void *)text);
+}
+
+/**
+ * @internal
+ * Set scrollbars visible.
+ *
+ * @param o View.
+ * @param visible @c TRUE if scrollbars are visible, @c FALSE otherwise.
+ *
+ * Emits signal: "scrollbars,visible,set" with a pointer to a boolean.
+ */
+void ewk_view_scrollbars_visible_set(Evas_Object* o, Eina_Bool visible)
+{
+ DBG("o=%p (visible=%d)", o, !!visible);
+ evas_object_smart_callback_call(o, "scrollbars,visible,set", &visible);
+}
+
+/**
+ * @internal
+ * Get scrollbars visibility.
+ *
+ * @param o View.
+ * @param visible boolean pointer in which to save the result. It defaults
+ * to @c FALSE, i.e. if browser does no listen to emitted signal, it means
+ * there are no scrollbars and therefore they are not visible.
+ *
+ * Emits signal: "scrollbars,visible,get" with a pointer to a boolean.
+ */
+void ewk_view_scrollbars_visible_get(Evas_Object* o, Eina_Bool* visible)
+{
+ DBG("%s, o=%p", __func__, o);
+ *visible = EINA_FALSE;
+ evas_object_smart_callback_call(o, "scrollbars,visible,get", visible);
+}
+
+/**
+ * @internal
+ * Set menubar visible.
+ *
+ * @param o View.
+ * @param visible @c TRUE if menubar is visible, @c FALSE otherwise.
+ *
+ * Emits signal: "menubar,visible,set" with a pointer to a boolean.
+ */
+void ewk_view_menubar_visible_set(Evas_Object* o, Eina_Bool visible)
+{
+ DBG("o=%p (visible=%d)", o, !!visible);
+ evas_object_smart_callback_call(o, "menubar,visible,set", &visible);
+}
+
+/**
+ * @internal
+ * Get menubar visibility.
+ *
+ * @param o View.
+ * @param visible boolean pointer in which to save the result. It defaults
+ * to @c FALSE, i.e. if browser does no listen to emitted signal, it means
+ * there is no menubar and therefore it is not visible.
+ *
+ * Emits signal: "menubar,visible,get" with a pointer to a boolean.
+ */
+void ewk_view_menubar_visible_get(Evas_Object* o, Eina_Bool* visible)
+{
+ DBG("%s, o=%p", __func__, o);
+ *visible = EINA_FALSE;
+ evas_object_smart_callback_call(o, "menubar,visible,get", visible);
+}
+
+/**
+ * @internal
+ * Set tooltip text and display if it is currently hidden.
+ *
+ * @param o View.
+ * @param text Text to set tooltip to.
+ *
+ * Emits signal: "tooltip,text,set" with a string. If tooltip must be actually
+ * removed, text will be 0 or '\0'
+ */
+void ewk_view_tooltip_text_set(Evas_Object* o, const char* text)
+{
+ DBG("o=%p text=%s", o, text);
+ evas_object_smart_callback_call(o, "tooltip,text,set", (void *)text);
+}
+
+/**
+ * @internal
+ *
+ * @param o View.
+ * @param message String to show on console.
+ * @param lineNumber Line number.
+ * @sourceID Source id.
+ *
+ */
+void ewk_view_add_console_message(Evas_Object* o, const char* message, unsigned int lineNumber, const char* sourceID)
+{
+ DBG("o=%p message=%s lineNumber=%u sourceID=%s", o, message, lineNumber, sourceID);
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd);
+ EINA_SAFETY_ON_NULL_RETURN(sd->api);
+ EINA_SAFETY_ON_NULL_RETURN(sd->api->add_console_message);
+ sd->api->add_console_message(sd, message, lineNumber, sourceID);
+}
+
+void ewk_view_run_javascript_alert(Evas_Object* o, Evas_Object* frame, const char* message)
+{
+ DBG("o=%p frame=%p message=%s", o, frame, message);
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd);
+ EINA_SAFETY_ON_NULL_RETURN(sd->api);
+
+ if (!sd->api->run_javascript_alert)
+ return;
+
+ sd->api->run_javascript_alert(sd, frame, message);
+}
+
+Eina_Bool ewk_view_run_javascript_confirm(Evas_Object* o, Evas_Object* frame, const char* message)
+{
+ DBG("o=%p frame=%p message=%s", o, frame, message);
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->api, EINA_FALSE);
+
+ if (!sd->api->run_javascript_confirm)
+ return EINA_FALSE;
+
+ return sd->api->run_javascript_confirm(sd, frame, message);
+}
+
+Eina_Bool ewk_view_run_javascript_prompt(Evas_Object* o, Evas_Object* frame, const char* message, const char* defaultValue, char** value)
+{
+ DBG("o=%p frame=%p message=%s", o, frame, message);
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->api, EINA_FALSE);
+
+ if (!sd->api->run_javascript_prompt)
+ return EINA_FALSE;
+
+ return sd->api->run_javascript_prompt(sd, frame, message, defaultValue, value);
+}
+
+/**
+ * @internal
+ * Delegates to client to decide whether a script must be stopped because it's
+ * running for too long. If client does not implement it, it goes to default
+ * implementation, which logs and returns EINA_FALSE. Client may remove log by
+ * setting this function 0, which will just return EINA_FALSE.
+ *
+ * @param o View.
+ *
+ * @return @c EINA_TRUE if script should be stopped; @c EINA_FALSE otherwise
+ */
+Eina_Bool ewk_view_should_interrupt_javascript(Evas_Object* o)
+{
+ DBG("o=%p", o);
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->api, EINA_FALSE);
+
+ if (!sd->api->should_interrupt_javascript)
+ return EINA_FALSE;
+
+ return sd->api->should_interrupt_javascript(sd);
+}
+
+/**
+ * @internal
+ * This is called whenever the web site shown in @param frame is asking to store data
+ * to the database @param databaseName and the quota allocated to that web site
+ * is exceeded. Browser may use this to increase the size of quota before the
+ * originating operationa fails.
+ *
+ * @param o View.
+ * @param frame The frame whose web page exceeded its database quota.
+ * @param databaseName Database name.
+ */
+void ewk_view_exceeded_database_quota(Evas_Object* o, Evas_Object* frame, const char* databaseName)
+{
+ DBG("o=%p", o);
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd);
+ EINA_SAFETY_ON_NULL_RETURN(sd->api);
+ EINA_SAFETY_ON_NULL_RETURN(sd->api->exceeded_database_quota);
+ sd->api->exceeded_database_quota(sd, frame, databaseName);
+}
+
+/**
+ * @internal
+ * Open panel to choose a file.
+ *
+ * @param o View.
+ * @param frame Frame in which operation is required.
+ * @param allows_multiple_files @c EINA_TRUE when more than one file may be
+ * selected, @c EINA_FALSE otherwise
+ * @suggested_filenames List of suggested files to select. It's advisable to
+ * just ignore this value, since it's a source of security flaw.
+ * @selected_filenames List of files selected.
+ *
+ * @return @EINA_FALSE if user canceled file selection; @EINA_TRUE if confirmed.
+ */
+Eina_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)
+{
+ DBG("o=%p frame=%p allows_multiple_files=%d", o, frame, allows_multiple_files);
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(sd->api, EINA_FALSE);
+ Eina_Bool confirm;
+
+ if (!sd->api->run_open_panel)
+ return EINA_FALSE;
+
+ *selected_filenames = 0;
+
+ confirm = sd->api->run_open_panel(sd, frame, allows_multiple_files, suggested_filenames, selected_filenames);
+ if (!confirm && *selected_filenames)
+ ERR("Canceled file selection, but selected filenames != 0. Free names before return.");
+ return confirm;
+}
+
+void ewk_view_repaint(Evas_Object* o, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
+{
+ DBG("o=%p, region=%d,%d + %dx%d", o, x, y, w, h);
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv);
+
+ if (!priv->main_frame->contentRenderer()) {
+ ERR("no main frame content renderer.");
+ return;
+ }
+
+ _ewk_view_repaint_add(priv, x, y, w, h);
+ _ewk_view_smart_changed(sd);
+}
+
+void 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)
+{
+ DBG("o=%p, delta: %d,%d, scroll: %d,%d+%dx%d, clip: %d,%d+%dx%d",
+ o, dx, dy, sx, sy, sw, sh, cx, cy, cw, ch);
+
+ if ((sx != cx) || (sy != cy) || (sw != cw) || (sh != ch))
+ WRN("scroll region and clip are different! %d,%d+%dx%d and %d,%d+%dx%d",
+ sx, sy, sw, sh, cx, cy, cw, ch);
+
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv);
+ EINA_SAFETY_ON_TRUE_RETURN(!dx && !dy);
+
+ _ewk_view_scroll_add(priv, dx, dy, sx, sy, sw, sh, main_frame);
+ _ewk_view_smart_changed(sd);
+}
+
+WebCore::Page* ewk_view_core_page_get(const Evas_Object* o)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
+ return priv->page;
+}
+
+/**
+ * Creates a new frame for given url and owner element.
+ *
+ * Emits "frame,created" with the new frame object on success.
+ */
+WTF::PassRefPtr<WebCore::Frame> ewk_view_frame_create(Evas_Object* o, Evas_Object* frame, const WebCore::String& name, WebCore::HTMLFrameOwnerElement* ownerElement, const WebCore::KURL& url, const WebCore::String& referrer)
+{
+ DBG("o=%p, frame=%p, name=%s, ownerElement=%p, url=%s, referrer=%s",
+ o, frame, name.utf8().data(), ownerElement,
+ url.prettyURL().utf8().data(), referrer.utf8().data());
+
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
+
+ WTF::RefPtr<WebCore::Frame> cf = _ewk_view_core_frame_new
+ (sd, priv, ownerElement);
+ if (!cf) {
+ ERR("Could not create child core frame '%s'", name.utf8().data());
+ return 0;
+ }
+
+ if (!ewk_frame_child_add(frame, cf, name, url, referrer)) {
+ ERR("Could not create child frame object '%s'", name.utf8().data());
+ return 0;
+ }
+
+ // The creation of the frame may have removed itself already.
+ if (!cf->page() || !cf->tree() || !cf->tree()->parent())
+ return 0;
+
+ sd->changed.frame_rect = EINA_TRUE;
+ _ewk_view_smart_changed(sd);
+
+ evas_object_smart_callback_call(o, "frame,created", frame);
+ return cf.release();
+}
+
+WTF::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<WebCore::String>& paramNames, const WTF::Vector<WebCore::String>& paramValues, const WebCore::String& mimeType, bool loadManually)
+{
+ DBG("o=%p, frame=%p, size=%dx%d, element=%p, url=%s, mimeType=%s",
+ o, frame, pluginSize.width(), pluginSize.height(), element,
+ url.prettyURL().utf8().data(), mimeType.utf8().data());
+
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
+ sd->changed.frame_rect = EINA_TRUE;
+ _ewk_view_smart_changed(sd);
+
+ return ewk_frame_plugin_create
+ (frame, pluginSize, element, url, paramNames, paramValues,
+ mimeType, loadManually);
+}
+
+
+/**
+ * @internal
+ *
+ * Creates a new popup with options when a select widget was clicked.
+ *
+ * @param client PopupMenuClient instance that allows communication with webkit.
+ * @param selected Selected item.
+ * @param rect Menu's position.
+ *
+ * Emits: "popup,create" with a list of Ewk_Menu containing each item's data
+ */
+void ewk_view_popup_new(Evas_Object* o, WebCore::PopupMenuClient* client, int selected, const WebCore::IntRect& rect)
+{
+ INF("o=%p", o);
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv);
+
+ if (priv->popup.menu_client)
+ ewk_view_popup_destroy(o);
+
+ priv->popup.menu_client = client;
+
+ // populate items
+ const int size = client->listSize();
+ for (int i = 0; i < size; ++i) {
+ Ewk_Menu_Item* item = (Ewk_Menu_Item*) malloc(sizeof(*item));
+ if (client->itemIsSeparator(i))
+ item->type = EWK_MENU_SEPARATOR;
+ else if (client->itemIsLabel(i))
+ item->type = EWK_MENU_GROUP;
+ else
+ item->type = EWK_MENU_OPTION;
+ item->text = eina_stringshare_add(client->itemText(i).utf8().data());
+
+ priv->popup.menu.items = eina_list_append(priv->popup.menu.items, item);
+ }
+
+ priv->popup.menu.x = rect.x();
+ priv->popup.menu.y = rect.y();
+ priv->popup.menu.width = rect.width();
+ priv->popup.menu.height = rect.height();
+ evas_object_smart_callback_call(o, "popup,create", &priv->popup.menu);
+}
+
+/**
+ * Destroy a previously created menu.
+ *
+ * Before destroying, it informs client that menu's data is ready to be
+ * destroyed by sending a "popup,willdelete" with a list of menu items. Then it
+ * removes any reference to menu inside webkit. It's safe to call this
+ * function either from inside webkit or from browser.
+ *
+ * @param o View.
+ *
+ * @returns EINA_TRUE in case menu was successfully destroyed or EINA_TRUE in
+ * case there wasn't any menu to be destroyed.
+ */
+Eina_Bool ewk_view_popup_destroy(Evas_Object* o)
+{
+ INF("o=%p", o);
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, EINA_FALSE);
+
+ if (!priv->popup.menu_client)
+ return EINA_FALSE;
+
+ evas_object_smart_callback_call(o, "popup,willdelete", &priv->popup.menu);
+
+ void* itemv;
+ EINA_LIST_FREE(priv->popup.menu.items, itemv) {
+ Ewk_Menu_Item* item = (Ewk_Menu_Item*)itemv;
+ eina_stringshare_del(item->text);
+ free(item);
+ }
+ priv->popup.menu_client->popupDidHide();
+ priv->popup.menu_client = 0;
+
+ return EINA_TRUE;
+}
+
+/**
+ * Changes currently selected item.
+ *
+ * Changes the option selected in select widget. This is called by browser
+ * whenever user has chosen a different item. Most likely after calling this, a
+ * call to ewk_view_popup_destroy might be made in order to close the popup.
+ *
+ * @param o View.
+ * @index Index of selected item.
+ *
+ */
+void ewk_view_popup_selected_set(Evas_Object* o, int index)
+{
+ INF("o=%p", o);
+ EWK_VIEW_SD_GET_OR_RETURN(o, sd);
+ EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv);
+
+ priv->popup.menu_client->valueChanged(index);
+}
+
+/**
+ * @internal
+ * Request a download to user.
+ *
+ * @param o View.
+ * @oaram download Ewk_Download struct to be sent.
+ *
+ * Emits: "download,request" with an Ewk_Download containing the details of the
+ * requested download. The download per se must be handled outside of webkit.
+ */
+void ewk_view_download_request(Evas_Object* o, Ewk_Download* download)
+{
+ DBG("view=%p", o);
+ evas_object_smart_callback_call(o, "download,request", download);
+}
diff --git a/WebKit/efl/ewk/ewk_view.h b/WebKit/efl/ewk/ewk_view.h
new file mode 100644
index 0000000..20df601
--- /dev/null
+++ b/WebKit/efl/ewk/ewk_view.h
@@ -0,0 +1,455 @@
+/*
+ Copyright (C) 2009-2010 ProFUSION embedded systems
+ Copyright (C) 2009-2010 Samsung Electronics
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef ewk_view_h
+#define ewk_view_h
+
+#include <Evas.h>
+#include <cairo.h>
+#include <ewk_history.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief WebKit main smart object.
+ *
+ * This object is the high level access to WebKit-EFL browser
+ * component. It is responsible for managing the main frame and other
+ * critical resources.
+ *
+ * Every ewk_view has at least one frame, called "main frame" and
+ * retrieved with ewk_view_frame_main_get(). Direct frame access is
+ * often discouraged, it is recommended to use ewk_view functions
+ * instead.
+ *
+ * The following signals (see evas_object_smart_callback_add()) are emitted:
+ *
+ * - "ready", void: page is fully loaded.
+ * - "title,changed", const char*: title of the main frame changed.
+ * - "uri,changed", const char*: uri of the main frame changed.
+ * - "load,started", void: frame started loading.
+ * - "load,progress", double*: load progress changed (overall value
+ * from 0.0 to 1.0, connect to individual frames for fine grained).
+ * - "load,finished", const Ewk_Frame_Load_Error*: reports load
+ * finished and as argument @c NULL if successfully or pointer to
+ * structure defining the error.
+ * - "load,provisional", void: view started provisional load.
+ * - "load,error", const Ewk_Frame_Load_Error*: reports load failed
+ * and as argument a pointer to structure defining the error.
+ * - "frame,created", Evas_Object*: when frames are created, they are
+ * emitted in this signal.
+ * - "zoom,animated,end", void: requested animated zoom is finished.
+ * - "menubar,visible,set", Eina_Bool: set menubar visibility.
+ * - "menubar,visible,get", Eina_Bool *: expects a @c EINA_TRUE if menubar is
+ * visible; otherwise, @c EINA_FALSE.
+ * - "menubar,visible,set", Eina_Bool: set menubar visibility.
+ * - "menubar,visible,get", Eina_Bool *: expects a @c EINA_TRUE if menubar is
+ * visible; @c EINA_FALSE, otherwise.
+ * - "scrollbars,visible,set", Eina_Bool: set scrollbars visibility.
+ * - "scrollbars,visible,get", Eina_Bool *: expects a @c EINA_TRUE if scrollbars
+ * are visible; @c EINA_FALSE, otherwise.
+ * - "statusbar,visible,set", Eina_Bool: set statusbar visibility.
+ * - "statusbar,visible,get", Eina_Bool *: expects a @c EINA_TRUE if statusbar is
+ * visible; @c EINA_FALSE, otherwise.
+ * - "toolbar,visible,set", Eina_Bool: set toolbar visibility.
+ * - "toolbar,visible,get", Eina_Bool *: expects a @c EINA_TRUE if toolbar
+ * is visible; @c EINA_FALSE, otherwise.
+ * - "link,hover,in", const char *link[2]: reports mouse is over a link and as
+ * argument gives the url in link[0] and link's title in link[1].
+ * - "link,hover,out", const char *link[2]: reports mouse moved out from a link
+ * and as argument gives the url in link[0] and link's title in link[1].
+ * - "popup,create", Ewk_Menu: reports that a new menu was created.
+ * - "popup,willdeleted", Ewk_Menu: reports that a previously created menu is
+ * about to be deleted.
+ * - "download,request", Ewk_Download: reports a download is being requested
+ * and as arguments gives its details.
+ * - "icon,received", void: main frame received an icon.
+ */
+
+typedef struct _Ewk_View_Smart_Data Ewk_View_Smart_Data;
+
+/**
+ * Ewk view's class, to be overridden by sub-classes.
+ */
+typedef struct _Ewk_View_Smart_Class Ewk_View_Smart_Class;
+struct _Ewk_View_Smart_Class {
+ Evas_Smart_Class sc; /**< all but 'data' is free to be changed. */
+ unsigned long version;
+
+ Evas_Object *(*window_create)(Ewk_View_Smart_Data *sd); /**< creates a new window, requested by webkit */
+ // hooks to allow different backing stores
+ Evas_Object *(*backing_store_add)(Ewk_View_Smart_Data *sd); /**< must be defined */
+ Eina_Bool (*scrolls_process)(Ewk_View_Smart_Data *sd); /**< must be defined */
+ Eina_Bool (*repaints_process)(Ewk_View_Smart_Data *sd); /**< must be defined */
+ Eina_Bool (*contents_resize)(Ewk_View_Smart_Data *sd, int w, int h);
+ Eina_Bool (*zoom_set)(Ewk_View_Smart_Data *sd, float zoom, Evas_Coord cx, Evas_Coord cy);
+ Eina_Bool (*zoom_weak_set)(Ewk_View_Smart_Data *sd, float zoom, Evas_Coord cx, Evas_Coord cy);
+ void (*zoom_weak_smooth_scale_set)(Ewk_View_Smart_Data *sd, Eina_Bool smooth_scale);
+ void (*bg_color_set)(Ewk_View_Smart_Data *sd, unsigned char r, unsigned char g, unsigned char b, unsigned char a);
+ void (*flush)(Ewk_View_Smart_Data *sd);
+ Eina_Bool (*pre_render_region)(Ewk_View_Smart_Data *sd, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h, float zoom);
+ void (*pre_render_cancel)(Ewk_View_Smart_Data *sd);
+ // event handling:
+ // - returns true if handled
+ // - if overridden, have to call parent method if desired
+ Eina_Bool (*focus_in)(Ewk_View_Smart_Data *sd);
+ Eina_Bool (*focus_out)(Ewk_View_Smart_Data *sd);
+ Eina_Bool (*mouse_wheel)(Ewk_View_Smart_Data *sd, const Evas_Event_Mouse_Wheel *ev);
+ Eina_Bool (*mouse_down)(Ewk_View_Smart_Data *sd, const Evas_Event_Mouse_Down *ev);
+ Eina_Bool (*mouse_up)(Ewk_View_Smart_Data *sd, const Evas_Event_Mouse_Up *ev);
+ Eina_Bool (*mouse_move)(Ewk_View_Smart_Data *sd, const Evas_Event_Mouse_Move *ev);
+ Eina_Bool (*key_down)(Ewk_View_Smart_Data *sd, const Evas_Event_Key_Down *ev);
+ Eina_Bool (*key_up)(Ewk_View_Smart_Data *sd, const Evas_Event_Key_Up *ev);
+
+ void (*add_console_message)(Ewk_View_Smart_Data *sd, const char *message, unsigned int lineNumber, const char *sourceID);
+ void (*run_javascript_alert)(Ewk_View_Smart_Data *sd, Evas_Object *frame, const char *message);
+ Eina_Bool (*run_javascript_confirm)(Ewk_View_Smart_Data *sd, Evas_Object *frame, const char *message);
+ Eina_Bool (*run_javascript_prompt)(Ewk_View_Smart_Data *sd, Evas_Object *frame, const char *message, const char *defaultValue, char **value);
+ Eina_Bool (*should_interrupt_javascript)(Ewk_View_Smart_Data *sd);
+ void (*exceeded_database_quota)(Ewk_View_Smart_Data *sd, Evas_Object *frame, const char *databaseName);
+
+ Eina_Bool (*run_open_panel)(Ewk_View_Smart_Data *sd, Evas_Object *frame, Eina_Bool allows_multiple_files, const Eina_List *suggested_filenames, Eina_List **selected_filenames);
+};
+
+#define EWK_VIEW_SMART_CLASS_VERSION 1UL /** the version you have to put into the version field in the Ewk_View_Smart_Class structure */
+
+/**
+ * Initializer for whole Ewk_View_Smart_Class structure.
+ *
+ * @param smart_class_init initializer to use for the "base" field
+ * (Evas_Smart_Class).
+ *
+ * @see EWK_VIEW_SMART_CLASS_INIT_NULL
+ * @see EWK_VIEW_SMART_CLASS_INIT_VERSION
+ * @see EWK_VIEW_SMART_CLASS_INIT_NAME_VERSION
+ */
+#define EWK_VIEW_SMART_CLASS_INIT(smart_class_init) {smart_class_init, EWK_VIEW_SMART_CLASS_VERSION, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+
+/**
+ * Initializer to zero a whole Ewk_View_Smart_Class structure.
+ *
+ * @see EWK_VIEW_SMART_CLASS_INIT_VERSION
+ * @see EWK_VIEW_SMART_CLASS_INIT_NAME_VERSION
+ * @see EWK_VIEW_SMART_CLASS_INIT
+ */
+#define EWK_VIEW_SMART_CLASS_INIT_NULL EWK_VIEW_SMART_CLASS_INIT(EVAS_SMART_CLASS_INIT_NULL)
+
+/**
+ * Initializer to zero a whole Ewk_View_Smart_Class structure and set version.
+ *
+ * Similar to EWK_VIEW_SMART_CLASS_INIT_NULL, but will set version field of
+ * Evas_Smart_Class (base field) to latest EVAS_SMART_CLASS_VERSION
+ *
+ * @see EWK_VIEW_SMART_CLASS_INIT_NULL
+ * @see EWK_VIEW_SMART_CLASS_INIT_NAME_VERSION
+ * @see EWK_VIEW_SMART_CLASS_INIT
+ */
+#define EWK_VIEW_SMART_CLASS_INIT_VERSION EWK_VIEW_SMART_CLASS_INIT(EVAS_SMART_CLASS_INIT_VERSION)
+
+/**
+ * Initializer to zero a whole Ewk_View_Smart_Class structure and set
+ * name and version.
+ *
+ * Similar to EWK_VIEW_SMART_CLASS_INIT_NULL, but will set version field of
+ * Evas_Smart_Class (base field) to latest EVAS_SMART_CLASS_VERSION and name
+ * to the specific value.
+ *
+ * It will keep a reference to name field as a "const char *", that is,
+ * name must be available while the structure is used (hint: static or global!)
+ * and will not be modified.
+ *
+ * @see EWK_VIEW_SMART_CLASS_INIT_NULL
+ * @see EWK_VIEW_SMART_CLASS_INIT_VERSION
+ * @see EWK_VIEW_SMART_CLASS_INIT
+ */
+#define EWK_VIEW_SMART_CLASS_INIT_NAME_VERSION(name) EWK_VIEW_SMART_CLASS_INIT(EVAS_SMART_CLASS_INIT_NAME_VERSION(name))
+
+/**
+ * @internal
+ *
+ * private data that is used internally by EFL WebKit and should never
+ * be modified from outside.
+ */
+typedef struct _Ewk_View_Private_Data Ewk_View_Private_Data;
+
+enum _Ewk_Menu_Item_Type {
+ EWK_MENU_SEPARATOR,
+ EWK_MENU_GROUP,
+ EWK_MENU_OPTION
+};
+typedef enum _Ewk_Menu_Item_Type Ewk_Menu_Item_Type;
+
+
+/**
+ * Structure do contain data of each menu item
+ */
+typedef struct _Ewk_Menu_Item Ewk_Menu_Item;
+struct _Ewk_Menu_Item {
+ const char *text; /**< Item's text */
+ Ewk_Menu_Item_Type type; /** Item's type */
+};
+
+/**
+ * Structure to contain Popup menu data.
+ */
+typedef struct _Ewk_Menu Ewk_Menu;
+struct _Ewk_Menu {
+ Eina_List* items;
+ int x;
+ int y;
+ int width;
+ int height;
+};
+
+/**
+ * Structure to contain Download data
+ */
+typedef struct _Ewk_Download Ewk_Download;
+struct _Ewk_Download {
+ const char* url;
+ /* to be extended */
+};
+
+/**
+ * Scroll request that should be processed by subclass implementations.
+ */
+typedef struct _Ewk_Scroll_Request Ewk_Scroll_Request;
+struct _Ewk_Scroll_Request {
+ Evas_Coord dx, dy;
+ Evas_Coord x, y, w, h, x2, y2;
+ Eina_Bool main_scroll;
+};
+
+/**
+ * Structure to contain internal View data, it is to be considered
+ * private by users, but may be extended or changed by sub-classes
+ * (that's why it's in public header file).
+ */
+struct _Ewk_View_Smart_Data {
+ Evas_Object_Smart_Clipped_Data base;
+ const Ewk_View_Smart_Class *api; /**< reference to casted class instance */
+ Evas_Object *self; /**< reference to owner object */
+ Evas_Object *main_frame; /**< reference to main frame object */
+ Evas_Object *backing_store; /**< reference to backing store */
+ Ewk_View_Private_Data *_priv; /**< should never be accessed, c++ stuff */
+ struct {
+ Evas_Coord x, y, w, h; /**< last used viewport */
+ } view;
+ struct {
+ struct {
+ float start;
+ float end;
+ float current; /**< if > 0.0, then doing animated zoom. */
+ } zoom;
+ } animated_zoom;
+ struct {
+ unsigned char r, g, b, a;
+ } bg_color;
+ Eina_Bool zoom_weak_smooth_scale:1;
+ struct { /**< what changed since last smart_calculate */
+ Eina_Bool any:1;
+ Eina_Bool size:1;
+ Eina_Bool position:1;
+ Eina_Bool frame_rect:1;
+ } changed;
+};
+
+EAPI Eina_Bool ewk_view_base_smart_set(Ewk_View_Smart_Class *api);
+EAPI Eina_Bool ewk_view_single_smart_set(Ewk_View_Smart_Class *api);
+
+EAPI Evas_Object *ewk_view_single_add(Evas *e);
+
+EAPI void ewk_view_fixed_layout_size_set(Evas_Object *o, Evas_Coord w, Evas_Coord h);
+EAPI void ewk_view_fixed_layout_size_get(Evas_Object *o, Evas_Coord *w, Evas_Coord *h);
+
+EAPI void ewk_view_theme_set(Evas_Object *o, const char *path);
+EAPI const char *ewk_view_theme_get(Evas_Object *o);
+
+EAPI Evas_Object *ewk_view_frame_main_get(const Evas_Object *o);
+EAPI Evas_Object *ewk_view_frame_focused_get(const Evas_Object *o);
+
+EAPI Eina_Bool ewk_view_uri_set(Evas_Object *o, const char *uri);
+EAPI const char *ewk_view_uri_get(const Evas_Object *o);
+EAPI const char *ewk_view_title_get(const Evas_Object *o);
+
+EAPI Eina_Bool ewk_view_editable_get(const Evas_Object *o);
+EAPI Eina_Bool ewk_view_editable_set(Evas_Object *o, Eina_Bool editable);
+
+EAPI void ewk_view_bg_color_set(Evas_Object *o, int r, int g, int b, int a);
+EAPI void ewk_view_bg_color_get(const Evas_Object *o, int *r, int *g, int *b, int *a);
+
+EAPI char *ewk_view_selection_get(const Evas_Object *o);
+EAPI Eina_Bool ewk_view_select_none(Evas_Object *o);
+EAPI Eina_Bool ewk_view_select_all(Evas_Object *o);
+EAPI Eina_Bool ewk_view_select_paragraph(Evas_Object *o);
+EAPI Eina_Bool ewk_view_select_sentence(Evas_Object *o);
+EAPI Eina_Bool ewk_view_select_line(Evas_Object *o);
+EAPI Eina_Bool ewk_view_select_word(Evas_Object *o);
+
+EAPI void ewk_view_popup_selected_set(Evas_Object *o, int index);
+EAPI Eina_Bool ewk_view_popup_destroy(Evas_Object *o);
+
+EAPI Eina_Bool ewk_view_text_search(const Evas_Object *o, const char *string, Eina_Bool case_sensitive, Eina_Bool forward, Eina_Bool wrap);
+
+EAPI unsigned int ewk_view_text_matches_mark(Evas_Object *o, const char *string, Eina_Bool case_sensitive, Eina_Bool highlight, unsigned int limit);
+EAPI Eina_Bool ewk_view_text_matches_unmark_all(Evas_Object *o);
+EAPI Eina_Bool ewk_view_text_matches_highlight_set(Evas_Object *o, Eina_Bool highlight);
+EAPI Eina_Bool ewk_view_text_matches_highlight_get(const Evas_Object *o);
+
+EAPI double ewk_view_load_progress_get(const Evas_Object *o);
+
+EAPI Eina_Bool ewk_view_stop(Evas_Object *o);
+EAPI Eina_Bool ewk_view_reload(Evas_Object *o);
+EAPI Eina_Bool ewk_view_reload_full(Evas_Object *o);
+
+EAPI Eina_Bool ewk_view_back(Evas_Object *o);
+EAPI Eina_Bool ewk_view_forward(Evas_Object *o);
+EAPI Eina_Bool ewk_view_navigate(Evas_Object *o, int steps);
+
+EAPI Eina_Bool ewk_view_back_possible(Evas_Object *o);
+EAPI Eina_Bool ewk_view_forward_possible(Evas_Object *o);
+EAPI Eina_Bool ewk_view_navigate_possible(Evas_Object *o, int steps);
+
+EAPI Eina_Bool ewk_view_history_enable_get(const Evas_Object *o);
+EAPI Eina_Bool ewk_view_history_enable_set(Evas_Object *o, Eina_Bool enable);
+EAPI Ewk_History *ewk_view_history_get(const Evas_Object *o);
+
+EAPI float ewk_view_zoom_get(const Evas_Object *o);
+EAPI Eina_Bool ewk_view_zoom_set(Evas_Object *o, float zoom, Evas_Coord cx, Evas_Coord cy);
+
+EAPI Eina_Bool ewk_view_zoom_weak_smooth_scale_get(const Evas_Object *o);
+EAPI void ewk_view_zoom_weak_smooth_scale_set(Evas_Object *o, Eina_Bool smooth_scale);
+
+EAPI Eina_Bool ewk_view_zoom_weak_set(Evas_Object *o, float zoom, Evas_Coord cx, Evas_Coord cy);
+EAPI Eina_Bool ewk_view_zoom_animated_mark_start(Evas_Object *o, float zoom);
+EAPI Eina_Bool ewk_view_zoom_animated_mark_end(Evas_Object *o, float zoom);
+EAPI Eina_Bool ewk_view_zoom_animated_mark_current(Evas_Object *o, float zoom);
+EAPI Eina_Bool ewk_view_zoom_animated_mark_stop(Evas_Object *o);
+
+EAPI Eina_Bool ewk_view_zoom_animated_set(Evas_Object *o, float zoom, float duration, Evas_Coord cx, Evas_Coord cy);
+EAPI Eina_Bool ewk_view_zoom_text_only_get(const Evas_Object *o);
+EAPI Eina_Bool ewk_view_zoom_text_only_set(Evas_Object *o, Eina_Bool setting);
+
+EAPI Eina_Bool ewk_view_pre_render_region(Evas_Object *o, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h, float zoom);
+EAPI void ewk_view_pre_render_cancel(Evas_Object *o);
+
+/* settings */
+EAPI const char *ewk_view_setting_user_agent_get(const Evas_Object *o);
+EAPI Eina_Bool ewk_view_setting_user_agent_set(Evas_Object *o, const char *user_agent);
+
+EAPI Eina_Bool ewk_view_setting_auto_load_images_get(const Evas_Object *o);
+EAPI Eina_Bool ewk_view_setting_auto_load_images_set(Evas_Object *o, Eina_Bool automatic);
+
+EAPI Eina_Bool ewk_view_setting_auto_shrink_images_get(const Evas_Object *o);
+EAPI Eina_Bool ewk_view_setting_auto_shrink_images_set(Evas_Object *o, Eina_Bool automatic);
+
+EAPI Eina_Bool ewk_view_setting_enable_scripts_get(const Evas_Object *o);
+EAPI Eina_Bool ewk_view_setting_enable_scripts_set(Evas_Object *o, Eina_Bool enable);
+
+EAPI Eina_Bool ewk_view_setting_enable_plugins_get(const Evas_Object *o);
+EAPI Eina_Bool ewk_view_setting_enable_plugins_set(Evas_Object *o, Eina_Bool enable);
+
+EAPI Eina_Bool ewk_view_setting_scripts_window_open_get(const Evas_Object *o);
+EAPI Eina_Bool ewk_view_setting_scripts_window_open_set(Evas_Object *o, Eina_Bool allow);
+
+EAPI Eina_Bool ewk_view_setting_resizable_textareas_get(const Evas_Object *o);
+EAPI Eina_Bool ewk_view_setting_resizable_textareas_set(Evas_Object *o, Eina_Bool enable);
+
+EAPI const char *ewk_view_setting_user_stylesheet_get(const Evas_Object *o);
+EAPI Eina_Bool ewk_view_setting_user_stylesheet_set(Evas_Object *o, const char *uri);
+
+EAPI Eina_Bool ewk_view_setting_private_browsing_get(const Evas_Object *o);
+EAPI Eina_Bool ewk_view_setting_private_browsing_set(Evas_Object *o, Eina_Bool enable);
+
+EAPI Eina_Bool ewk_view_setting_caret_browsing_get(const Evas_Object *o);
+EAPI Eina_Bool ewk_view_setting_caret_browsing_set(Evas_Object *o, Eina_Bool enable);
+
+EAPI const char *ewk_view_setting_encoding_custom_get(const Evas_Object *o);
+EAPI Eina_Bool ewk_view_setting_encoding_custom_set(Evas_Object *o, const char *encoding);
+EAPI const char *ewk_view_setting_encoding_default_get(const Evas_Object *o);
+EAPI Eina_Bool ewk_view_setting_encoding_default_set(Evas_Object *o, const char *encoding);
+
+EAPI int ewk_view_setting_font_minimum_size_get(const Evas_Object *o);
+EAPI Eina_Bool ewk_view_setting_font_minimum_size_set(Evas_Object *o, int size);
+EAPI int ewk_view_setting_font_minimum_logical_size_get(const Evas_Object *o);
+EAPI Eina_Bool ewk_view_setting_font_minimum_logical_size_set(Evas_Object *o, int size);
+EAPI int ewk_view_setting_font_default_size_get(const Evas_Object *o);
+EAPI Eina_Bool ewk_view_setting_font_default_size_set(Evas_Object *o, int size);
+EAPI int ewk_view_setting_font_monospace_size_get(const Evas_Object *o);
+EAPI Eina_Bool ewk_view_setting_font_monospace_size_set(Evas_Object *o, int size);
+
+EAPI const char *ewk_view_setting_font_standard_get(const Evas_Object *o);
+EAPI Eina_Bool ewk_view_setting_font_standard_set(Evas_Object *o, const char *family);
+
+EAPI const char *ewk_view_setting_font_cursive_get(const Evas_Object *o);
+EAPI Eina_Bool ewk_view_setting_font_cursive_set(Evas_Object *o, const char *family);
+
+EAPI const char *ewk_view_setting_font_monospace_get(const Evas_Object *o);
+EAPI Eina_Bool ewk_view_setting_font_monospace_set(Evas_Object *o, const char *family);
+
+EAPI const char *ewk_view_setting_font_fantasy_get(const Evas_Object *o);
+EAPI Eina_Bool ewk_view_setting_font_fantasy_set(Evas_Object *o, const char *family);
+
+EAPI const char *ewk_view_setting_font_serif_get(const Evas_Object *o);
+EAPI Eina_Bool ewk_view_setting_font_serif_set(Evas_Object *o, const char *family);
+
+EAPI const char *ewk_view_setting_font_sans_serif_get(const Evas_Object *o);
+EAPI Eina_Bool ewk_view_setting_font_sans_serif_set(Evas_Object *o, const char *family);
+
+/* to be used by subclass implementations */
+EAPI Ewk_View_Smart_Data *ewk_view_smart_data_get(const Evas_Object *o);
+
+EAPI const Eina_Rectangle *ewk_view_repaints_get(const Ewk_View_Private_Data *priv, size_t *count);
+EAPI const Ewk_Scroll_Request *ewk_view_scroll_requests_get(const Ewk_View_Private_Data *priv, size_t *count);
+
+EAPI void ewk_view_repaint_add(Ewk_View_Private_Data *priv, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h);
+
+EAPI void ewk_view_layout_if_needed_recursive(Ewk_View_Private_Data *priv);
+
+EAPI void ewk_view_scrolls_process(Ewk_View_Smart_Data *sd);
+
+/**
+ * Structure that keeps paint context.
+ *
+ * @note this is not for general use but just for subclasses that want
+ * to define their own backing store.
+ */
+typedef struct _Ewk_View_Paint_Context Ewk_View_Paint_Context;
+
+EAPI Ewk_View_Paint_Context *ewk_view_paint_context_new(Ewk_View_Private_Data *priv, cairo_t *cr);
+EAPI void ewk_view_paint_context_free(Ewk_View_Paint_Context *ctxt);
+
+EAPI void ewk_view_paint_context_save(Ewk_View_Paint_Context *ctxt);
+EAPI void ewk_view_paint_context_restore(Ewk_View_Paint_Context *ctxt);
+EAPI void ewk_view_paint_context_clip(Ewk_View_Paint_Context *ctxt, const Eina_Rectangle *area);
+EAPI void ewk_view_paint_context_paint(Ewk_View_Paint_Context *ctxt, const Eina_Rectangle *area);
+EAPI void ewk_view_paint_context_paint_contents(Ewk_View_Paint_Context *ctxt, const Eina_Rectangle *area);
+EAPI void ewk_view_paint_context_scale(Ewk_View_Paint_Context *ctxt, float scale_x, float scale_y);
+EAPI void ewk_view_paint_context_translate(Ewk_View_Paint_Context *ctxt, float x, float y);
+
+EAPI Eina_Bool ewk_view_paint(Ewk_View_Private_Data *priv, cairo_t *cr, const Eina_Rectangle *area);
+EAPI Eina_Bool ewk_view_paint_contents(Ewk_View_Private_Data *priv, cairo_t *cr, const Eina_Rectangle *area);
+
+#ifdef __cplusplus
+}
+#endif
+#endif // ewk_view_h
diff --git a/WebKit/efl/ewk/ewk_view_single.c b/WebKit/efl/ewk/ewk_view_single.c
new file mode 100644
index 0000000..4111370
--- /dev/null
+++ b/WebKit/efl/ewk/ewk_view_single.c
@@ -0,0 +1,585 @@
+/*
+ Copyright (C) 2009-2010 ProFUSION embedded systems
+ Copyright (C) 2009-2010 Samsung Electronics
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+#include "ewk_view.h"
+
+#include "ewk_frame.h"
+#include "ewk_logging.h"
+
+#include <Evas.h>
+#include <eina_safety_checks.h>
+#include <string.h>
+
+static Ewk_View_Smart_Class _parent_sc = EWK_VIEW_SMART_CLASS_INIT_NULL;
+
+static void _ewk_view_single_on_del(void *data, Evas *e, Evas_Object *o, void *event_info)
+{
+ Evas_Object *clip = (Evas_Object*)data;
+ evas_object_del(clip);
+}
+
+static Evas_Object *_ewk_view_single_smart_backing_store_add(Ewk_View_Smart_Data *sd)
+{
+ Evas_Object *bs = evas_object_image_add(sd->base.evas);
+ Evas_Object *clip = evas_object_rectangle_add(sd->base.evas);
+ evas_object_image_alpha_set(bs, EINA_FALSE);
+ evas_object_image_smooth_scale_set(bs, sd->zoom_weak_smooth_scale);
+ evas_object_clip_set(bs, clip);
+ evas_object_show(clip);
+
+ evas_object_event_callback_add
+ (bs, EVAS_CALLBACK_DEL, _ewk_view_single_on_del, clip);
+
+ return bs;
+}
+
+static void _ewk_view_single_smart_resize(Evas_Object *o, Evas_Coord w, Evas_Coord h)
+{
+ Ewk_View_Smart_Data *sd = (Ewk_View_Smart_Data*)evas_object_smart_data_get(o);
+ _parent_sc.sc.resize(o, w, h);
+
+ // these should be queued and processed in calculate as well!
+ evas_object_image_size_set(sd->backing_store, w, h);
+ if (sd->animated_zoom.zoom.current < 0.00001) {
+ Evas_Object *clip = evas_object_clip_get(sd->backing_store);
+ Evas_Coord x, y, cw, ch;
+ evas_object_image_fill_set(sd->backing_store, 0, 0, w, h);
+ evas_object_geometry_get(sd->backing_store, &x, &y, 0, 0);
+ evas_object_move(clip, x, y);
+ ewk_frame_contents_size_get(sd->main_frame, &cw, &ch);
+ if (w > cw)
+ w = cw;
+ if (h > ch)
+ h = ch;
+ evas_object_resize(clip, w, h);
+ }
+}
+
+static inline void _ewk_view_4b_move_region_up(uint32_t *image, size_t rows, size_t x, size_t y, size_t w, size_t h, size_t rowsize)
+{
+ uint32_t *src;
+ uint32_t *dst;
+
+ dst = image + x + y * rowsize;
+ src = dst + rows * rowsize;
+ h -= rows;
+
+ for (; h > 0; h--, dst += rowsize, src += rowsize)
+ memcpy(dst, src, w * 4);
+}
+
+static inline void _ewk_view_4b_move_region_down(uint32_t *image, size_t rows, size_t x, size_t y, size_t w, size_t h, size_t rowsize)
+{
+ uint32_t *src;
+ uint32_t *dst;
+
+ h -= rows;
+ src = image + x + (y + h - 1) * rowsize;
+ dst = src + rows * rowsize;
+
+ for (; h > 0; h--, dst -= rowsize, src -= rowsize)
+ memcpy(dst, src, w * 4);
+}
+
+static inline void _ewk_view_4b_move_line_left(uint32_t *dst, const uint32_t *src, size_t count)
+{
+ uint32_t *dst_end = dst + count;
+ /* no memcpy() as it does not allow overlapping regions */
+ /* no memmove() as it will copy to a temporary buffer */
+ /* TODO: loop unrolling, copying up to quad-words would help */
+ for (; dst < dst_end; dst++, src++)
+ *dst = *src;
+}
+
+static inline void _ewk_view_4b_move_line_right(uint32_t *dst, uint32_t *src, size_t count)
+{
+ uint32_t *dst_end = dst - count;
+ /* no memcpy() as it does not allow overlapping regions */
+ /* no memmove() as it will copy to a temporary buffer */
+ /* TODO: loop unrolling, copying up to quad-words would help */
+ for (; dst > dst_end; dst--, src--)
+ *dst = *src;
+}
+
+static inline void _ewk_view_4b_move_region_left(uint32_t *image, size_t cols, size_t x, size_t y, size_t w, size_t h, size_t rowsize)
+{
+ uint32_t *src;
+ uint32_t *dst;
+
+ dst = image + x + y * rowsize;
+ src = dst + cols;
+ w -= cols;
+
+ for (; h > 0; h--, dst += rowsize, src += rowsize)
+ _ewk_view_4b_move_line_left(dst, src, w);
+}
+
+static inline void _ewk_view_4b_move_region_right(uint32_t *image, size_t cols, size_t x, size_t y, size_t w, size_t h, size_t rowsize)
+{
+ uint32_t *src;
+ uint32_t *dst;
+
+ w -= cols;
+ src = image + (x + w - 1) + y * rowsize;
+ dst = src + cols;
+
+ for (; h > 0; h--, dst += rowsize, src += rowsize)
+ _ewk_view_4b_move_line_right(dst, src, w);
+}
+
+/* catch-all function, not as optimized as the others, but does the work. */
+static inline void _ewk_view_4b_move_region(uint32_t *image, int dx, int dy, size_t x, size_t y, size_t w, size_t h, size_t rowsize)
+{
+ uint32_t *src;
+ uint32_t *dst;
+
+ if (dy < 0) {
+ h += dy;
+ dst = image + x + y * rowsize;
+ src = dst - dy * rowsize;
+ if (dx <= 0) {
+ w += dx;
+ src -= dx;
+ for (; h > 0; h--, dst += rowsize, src += rowsize)
+ _ewk_view_4b_move_line_left(dst, src, w);
+ } else {
+ w -= dx;
+ src += w - 1;
+ dst += w + dx -1;
+ for (; h > 0; h--, dst += rowsize, src += rowsize)
+ _ewk_view_4b_move_line_right(dst, src, w);
+ }
+ } else {
+ h -= dy;
+ src = image + x + (y + h - 1) * rowsize;
+ dst = src + dy * rowsize;
+ if (dx <= 0) {
+ w += dx;
+ src -= dx;
+ for (; h > 0; h--, dst -= rowsize, src -= rowsize)
+ _ewk_view_4b_move_line_left(dst, src, w);
+ } else {
+ w -= dx;
+ src += w - 1;
+ dst += w + dx - 1;
+ for (; h > 0; h--, dst -= rowsize, src -= rowsize)
+ _ewk_view_4b_move_line_right(dst, src, w);
+ }
+ }
+}
+
+static inline void _ewk_view_single_scroll_process_single(Ewk_View_Smart_Data *sd, void *pixels, Evas_Coord ow, Evas_Coord oh, const Ewk_Scroll_Request *sr)
+{
+ Evas_Coord sx, sy, sw, sh;
+
+ DBG("%d,%d + %d,%d %+03d,%+03d, store: %p %dx%d",
+ sr->x, sr->y, sr->w, sr->h, sr->dx, sr->dy, pixels, ow, oh);
+
+ sx = sr->x;
+ sy = sr->y;
+ sw = sr->w;
+ sh = sr->h;
+
+ if (abs(sr->dx) >= sw || abs(sr->dy) >= sh) {
+ /* doubt webkit would be so stupid... */
+ DBG("full page scroll %+03d,%+03d. convert to repaint %d,%d + %dx%d",
+ sr->dx, sr->dy, sx, sy, sw, sh);
+ ewk_view_repaint_add(sd->_priv, sx, sy, sw, sh);
+ return;
+ }
+
+ if (sx < 0) {
+ sw += sx;
+ sx = 0;
+ }
+ if (sy < 0) {
+ sh += sy;
+ sy = 0;
+ }
+
+ if (sx + sw > ow)
+ sw = ow - sx;
+ if (sy + sh > oh)
+ sh = oh - sy;
+
+ if (sw < 0)
+ sw = 0;
+ if (sh < 0)
+ sh = 0;
+
+ EINA_SAFETY_ON_TRUE_RETURN(!sw || !sh);
+ if (!sr->dx) {
+ if (sr->dy < 0) {
+ DBG("scroll up: %+03d,%+03d update=%d,%d+%dx%d, "
+ "repaint=%d,%d+%dx%d",
+ sr->dx, sr->dy, sx, sy, sw, sh + sr->dy,
+ sx, sy + sh + sr->dy, sw, -sr->dy);
+
+ _ewk_view_4b_move_region_up
+ ((uint32_t*)pixels, -sr->dy, sx, sy, sw, sh, ow);
+ evas_object_image_data_update_add
+ (sd->backing_store, sx, sy, sw, sh + sr->dy);
+
+ ewk_view_repaint_add(sd->_priv, sx, sy + sh + sr->dy, sw, -sr->dy);
+ } else if (sr->dy > 0) {
+ DBG("scroll down: %+03d,%+03d update=%d,%d+%dx%d, "
+ "repaint=%d,%d+%dx%d",
+ sr->dx, sr->dy, sx, sy + sr->dy, sw, sh - sr->dy,
+ sx, sy, sw, sr->dy);
+
+ _ewk_view_4b_move_region_down
+ ((uint32_t*)pixels, sr->dy, sx, sy, sw, sh, ow);
+ evas_object_image_data_update_add
+ (sd->backing_store, sx, sy + sr->dy, sw, sh - sr->dy);
+
+ ewk_view_repaint_add(sd->_priv, sx, sy, sw, sr->dy);
+ }
+ } else if (!sr->dy) {
+ if (sr->dx < 0) {
+ DBG("scroll left: %+03d,%+03d update=%d,%d+%dx%d, "
+ "repaint=%d,%d+%dx%d",
+ sr->dx, sr->dy, sx, sy, sw + sr->dx, sh,
+ sx + sw + sr->dx, sy, -sr->dx, sh);
+
+ _ewk_view_4b_move_region_left
+ ((uint32_t*)pixels, -sr->dx, sx, sy, sw, sh, ow);
+ evas_object_image_data_update_add
+ (sd->backing_store, sx, sy, sw + sr->dx, sh);
+
+ ewk_view_repaint_add(sd->_priv, sx + sw + sr->dx, sy, -sr->dx, sh);
+ } else if (sr->dx > 0) {
+ DBG("scroll up: %+03d,%+03d update=%d,%d+%dx%d, "
+ "repaint=%d,%d+%dx%d",
+ sr->dx, sr->dy, sx + sr->dx, sy, sw - sr->dx, sh,
+ sx, sy, sr->dx, sh);
+
+ _ewk_view_4b_move_region_right
+ ((uint32_t*)pixels, sr->dx, sx, sy, sw, sh, ow);
+ evas_object_image_data_update_add
+ (sd->backing_store, sx + sr->dx, sy, sw - sr->dx, sh);
+
+ ewk_view_repaint_add(sd->_priv, sx, sy, sr->dx, sh);
+ }
+ } else {
+ Evas_Coord mx, my, mw, mh, ax, ay, aw, ah, bx, by, bw, bh;
+
+ if (sr->dx < 0) {
+ mx = sx;
+ mw = sw + sr->dx;
+ ax = mx + mw;
+ aw = -sr->dx;
+ } else {
+ ax = sx;
+ aw = sr->dx;
+ mx = ax + aw;
+ mw = sw - sr->dx;
+ }
+
+ if (sr->dy < 0) {
+ my = sy;
+ mh = sh + sr->dy;
+ by = my + mh;
+ bh = -sr->dy;
+ } else {
+ by = sy;
+ bh = sr->dy;
+ my = by + bh;
+ mh = sh - sr->dy;
+ }
+
+ ay = my;
+ ah = mh;
+ bx = sx;
+ bw = sw;
+
+ DBG("scroll diagonal: %+03d,%+03d update=%d,%d+%dx%d, "
+ "repaints: h=%d,%d+%dx%d v=%d,%d+%dx%d",
+ sr->dx, sr->dy, mx, my, mw, mh, ax, ay, aw, ah, bx, by, bw, bh);
+
+ _ewk_view_4b_move_region
+ ((uint32_t*)pixels, sr->dx, sr->dy, sx, sy, sw, sh, ow);
+
+ evas_object_image_data_update_add(sd->backing_store, mx, my, mw, mh);
+ ewk_view_repaint_add(sd->_priv, ax, ay, aw, ah);
+ ewk_view_repaint_add(sd->_priv, bx, by, bw, bh);
+ }
+}
+
+static Eina_Bool _ewk_view_single_smart_scrolls_process(Ewk_View_Smart_Data *sd)
+{
+ const Ewk_Scroll_Request *sr;
+ const Ewk_Scroll_Request *sr_end;
+ Evas_Coord ow, oh;
+ size_t count;
+ void *pixels = evas_object_image_data_get(sd->backing_store, 1);
+ evas_object_image_size_get(sd->backing_store, &ow, &oh);
+
+ sr = ewk_view_scroll_requests_get(sd->_priv, &count);
+ sr_end = sr + count;
+ for (; sr < sr_end; sr++)
+ _ewk_view_single_scroll_process_single(sd, pixels, ow, oh, sr);
+
+ return EINA_TRUE;
+}
+
+static Eina_Bool _ewk_view_single_smart_repaints_process(Ewk_View_Smart_Data *sd)
+{
+ Ewk_View_Paint_Context *ctxt;
+ Evas_Coord ow, oh;
+ void *pixels;
+ Eina_Rectangle r = {0, 0, 0, 0};
+ const Eina_Rectangle *pr;
+ const Eina_Rectangle *pr_end;
+ Eina_Tiler *tiler;
+ Eina_Iterator *itr;
+ cairo_status_t status;
+ cairo_surface_t *surface;
+ cairo_format_t format;
+ cairo_t *cairo;
+ size_t count;
+ Eina_Bool ret = EINA_TRUE;
+
+ if (sd->animated_zoom.zoom.current < 0.00001) {
+ Evas_Object *clip = evas_object_clip_get(sd->backing_store);
+ Evas_Coord w, h, cw, ch;
+ // reset effects of zoom_weak_set()
+ evas_object_image_fill_set
+ (sd->backing_store, 0, 0, sd->view.w, sd->view.h);
+ evas_object_move(clip, sd->view.x, sd->view.y);
+
+ w = sd->view.w;
+ h = sd->view.h;
+
+ ewk_frame_contents_size_get(sd->main_frame, &cw, &ch);
+ if (w > cw)
+ w = cw;
+ if (h > ch)
+ h = ch;
+ evas_object_resize(clip, w, h);
+ }
+
+ pixels = evas_object_image_data_get(sd->backing_store, 1);
+ evas_object_image_size_get(sd->backing_store, &ow, &oh);
+
+ if (sd->bg_color.a < 255)
+ format = CAIRO_FORMAT_ARGB32;
+ else
+ format = CAIRO_FORMAT_RGB24;
+
+ surface = cairo_image_surface_create_for_data
+ ((unsigned char*)pixels, format, ow, oh, ow * 4);
+ status = cairo_surface_status(surface);
+ if (status != CAIRO_STATUS_SUCCESS) {
+ ERR("could not create surface from data %dx%d: %s",
+ ow, oh, cairo_status_to_string(status));
+ ret = EINA_FALSE;
+ goto error_cairo_surface;
+ }
+ cairo = cairo_create(surface);
+ status = cairo_status(cairo);
+ if (status != CAIRO_STATUS_SUCCESS) {
+ ERR("could not create cairo from surface %dx%d: %s",
+ ow, oh, cairo_status_to_string(status));
+ ret = EINA_FALSE;
+ goto error_cairo;
+ }
+
+ ctxt = ewk_view_paint_context_new(sd->_priv, cairo);
+ if (!ctxt) {
+ ERR("could not create paint context");
+ ret = EINA_FALSE;
+ goto error_paint_context;
+ }
+
+ tiler = eina_tiler_new(ow, oh);
+ if (!tiler) {
+ ERR("could not create tiler %dx%d", ow, oh);
+ ret = EINA_FALSE;
+ goto error_tiler;
+ }
+
+ pr = ewk_view_repaints_get(sd->_priv, &count);
+ pr_end = pr + count;
+ for (; pr < pr_end; pr++)
+ eina_tiler_rect_add(tiler, pr);
+
+ itr = eina_tiler_iterator_new(tiler);
+ if (!itr) {
+ ERR("could not get iterator for tiler");
+ ret = EINA_FALSE;
+ goto error_iterator;
+ }
+
+ int sx, sy;
+ ewk_frame_scroll_pos_get(sd->main_frame, &sx, &sy);
+
+ EINA_ITERATOR_FOREACH(itr, r) {
+ Eina_Rectangle scrolled_rect = {
+ r.x + sx, r.y + sy,
+ r.w, r.h
+ };
+
+ ewk_view_paint_context_save(ctxt);
+
+ if ((sx) || (sy))
+ ewk_view_paint_context_translate(ctxt, -sx, -sy);
+
+ ewk_view_paint_context_clip(ctxt, &scrolled_rect);
+ ewk_view_paint_context_paint_contents(ctxt, &scrolled_rect);
+
+ ewk_view_paint_context_restore(ctxt);
+ evas_object_image_data_update_add
+ (sd->backing_store, r.x, r.y, r.w, r.h);
+ }
+ eina_iterator_free(itr);
+
+error_iterator:
+ eina_tiler_free(tiler);
+error_tiler:
+ ewk_view_paint_context_free(ctxt);
+error_paint_context:
+ cairo_destroy(cairo);
+error_cairo:
+ cairo_surface_destroy(surface);
+error_cairo_surface:
+ evas_object_image_data_set(sd->backing_store, pixels); /* dec refcount */
+
+ return ret;
+}
+
+static Eina_Bool _ewk_view_single_smart_zoom_weak_set(Ewk_View_Smart_Data *sd, float zoom, Evas_Coord cx, Evas_Coord cy)
+{
+ // TODO: review
+ float scale = zoom / sd->animated_zoom.zoom.start;
+ Evas_Coord w = sd->view.w * scale;
+ Evas_Coord h = sd->view.h * scale;
+ Evas_Coord dx, dy, cw, ch;
+ Evas_Object *clip = evas_object_clip_get(sd->backing_store);
+
+ ewk_frame_contents_size_get(sd->main_frame, &cw, &ch);
+ if (sd->view.w > 0 && sd->view.h > 0) {
+ dx = (w * (sd->view.w - cx)) / sd->view.w;
+ dy = (h * (sd->view.h - cy)) / sd->view.h;
+ } else {
+ dx = 0;
+ dy = 0;
+ }
+
+ evas_object_image_fill_set(sd->backing_store, cx + dx, cy + dy, w, h);
+
+ if (sd->view.w > 0 && sd->view.h > 0) {
+ dx = ((sd->view.w - w) * cx) / sd->view.w;
+ dy = ((sd->view.h - h) * cy) / sd->view.h;
+ } else {
+ dx = 0;
+ dy = 0;
+ }
+ evas_object_move(clip, sd->view.x + dx, sd->view.y + dy);
+
+ if (cw < sd->view.w)
+ w = cw * scale;
+ if (ch < sd->view.h)
+ h = ch * scale;
+ evas_object_resize(clip, w, h);
+ return EINA_TRUE;
+}
+
+static void _ewk_view_single_smart_zoom_weak_smooth_scale_set(Ewk_View_Smart_Data *sd, Eina_Bool smooth_scale)
+{
+ evas_object_image_smooth_scale_set(sd->backing_store, smooth_scale);
+}
+
+static void _ewk_view_single_smart_bg_color_set(Ewk_View_Smart_Data *sd, unsigned char r, unsigned char g, unsigned char b, unsigned char a)
+{
+ evas_object_image_alpha_set(sd->backing_store, a < 255);
+}
+
+/**
+ * Sets the smart class api using single backing store, enabling view
+ * to be inherited.
+ *
+ * @param api class definition to be set, all members with the
+ * exception of Evas_Smart_Class->data may be overridden. Must
+ * @b not be @c NULL.
+ *
+ * @note Evas_Smart_Class->data is used to implement type checking and
+ * is not supposed to be changed/overridden. If you need extra
+ * data for your smart class to work, just extend
+ * Ewk_View_Smart_Class instead.
+ *
+ * @return @c EINA_TRUE on success, @c EINA_FALSE on failure (probably
+ * version mismatch).
+ *
+ * @see ewk_view_base_smart_set()
+ */
+Eina_Bool ewk_view_single_smart_set(Ewk_View_Smart_Class *api)
+{
+ if (!ewk_view_base_smart_set(api))
+ return EINA_FALSE;
+
+ if (EINA_UNLIKELY(!_parent_sc.sc.add))
+ ewk_view_base_smart_set(&_parent_sc);
+
+ api->sc.resize = _ewk_view_single_smart_resize;
+
+ api->backing_store_add = _ewk_view_single_smart_backing_store_add;
+ api->scrolls_process = _ewk_view_single_smart_scrolls_process;
+ api->repaints_process = _ewk_view_single_smart_repaints_process;
+ api->zoom_weak_set = _ewk_view_single_smart_zoom_weak_set;
+ api->zoom_weak_smooth_scale_set = _ewk_view_single_smart_zoom_weak_smooth_scale_set;
+ api->bg_color_set = _ewk_view_single_smart_bg_color_set;
+
+ return EINA_TRUE;
+}
+
+static inline Evas_Smart *_ewk_view_single_smart_class_new(void)
+{
+ static Ewk_View_Smart_Class api = EWK_VIEW_SMART_CLASS_INIT_NAME_VERSION("Ewk_View_Single");
+ static Evas_Smart *smart = 0;
+
+ if (EINA_UNLIKELY(!smart)) {
+ ewk_view_single_smart_set(&api);
+ smart = evas_smart_class_new(&api.sc);
+ }
+
+ return smart;
+}
+
+/**
+ * Creates a new EFL WebKit View object.
+ *
+ * View objects are the recommended way to deal with EFL WebKit as it
+ * abstracts the complex pieces of the process.
+ *
+ * Each view is composed by a set of frames. The set has at least one
+ * frame, called 'main_frame'. See ewk_view_frame_main_get() and
+ * ewk_view_frame_focused_get().
+ *
+ * @param e canvas where to create the view object.
+ *
+ * @return view object or @c NULL if errors.
+ *
+ * @see ewk_view_uri_set()
+ */
+Evas_Object *ewk_view_single_add(Evas *e)
+{
+ return evas_object_smart_add(e, _ewk_view_single_smart_class_new());
+}