1 /*
2 Copyright (C) 2009-2010 ProFUSION embedded systems
3 Copyright (C) 2009-2010 Samsung Electronics
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19 */
20
21 // Uncomment to view frame regions and debug messages
22 // #define EWK_FRAME_DEBUG
23
24 #include "config.h"
25 #include "ewk_frame.h"
26
27 #include "DocumentMarkerController.h"
28 #include "EWebKit.h"
29 #include "EventHandler.h"
30 #include "FocusController.h"
31 #include "FrameLoaderClientEfl.h"
32 #include "FrameTree.h"
33 #include "FrameView.h"
34 #include "HTMLPlugInElement.h"
35 #include "HistoryItem.h"
36 #include "HitTestResult.h"
37 #include "IntSize.h"
38 #include "KURL.h"
39 #include "PlatformKeyboardEvent.h"
40 #include "PlatformMouseEvent.h"
41 #include "PlatformTouchEvent.h"
42 #include "PlatformWheelEvent.h"
43 #include "ProgressTracker.h"
44 #include "RefPtr.h"
45 #include "RenderTheme.h"
46 #include "ResourceRequest.h"
47 #include "ScriptValue.h"
48 #include "SharedBuffer.h"
49 #include "SubstituteData.h"
50 #include "WindowsKeyboardCodes.h"
51 #include "ewk_private.h"
52
53 #include <Eina.h>
54 #include <Evas.h>
55 #include <algorithm>
56 #include <eina_safety_checks.h>
57 #include <wtf/text/CString.h>
58
59 static const char EWK_FRAME_TYPE_STR[] = "EWK_Frame";
60
61 struct Ewk_Frame_Smart_Data {
62 Evas_Object_Smart_Clipped_Data base;
63 Evas_Object* self;
64 Evas_Object* view;
65 #ifdef EWK_FRAME_DEBUG
66 Evas_Object* region;
67 #endif
68 WebCore::Frame* frame;
69 const char* theme;
70 const char* title;
71 const char* uri;
72 const char* name;
73 struct {
74 Evas_Coord w, h;
75 } contents_size;
76 Eina_Bool textZoom:1;
77 Eina_Bool editable:1;
78 };
79
80 struct Eina_Iterator_Ewk_Frame {
81 Eina_Iterator base;
82 Evas_Object* obj;
83 WebCore::Frame* last;
84 };
85
86 #ifndef EWK_TYPE_CHECK
87 #define EWK_FRAME_TYPE_CHECK(o, ...) do { } while (0)
88 #else
89 #define EWK_FRAME_TYPE_CHECK(o, ...) \
90 do { \
91 const char* _tmp_otype = evas_object_type_get(o); \
92 if (EINA_UNLIKELY(_tmp_otype != EWK_FRAME_TYPE_STR)) { \
93 EINA_LOG_CRIT \
94 ("%p (%s) is not of an ewk_frame!", o, \
95 _tmp_otype ? _tmp_otype : "(null)"); \
96 return __VA_ARGS__; \
97 } \
98 } while (0)
99 #endif
100
101 #define EWK_FRAME_SD_GET(o, ptr) \
102 Ewk_Frame_Smart_Data* ptr = (Ewk_Frame_Smart_Data*)evas_object_smart_data_get(o)
103
104 #define EWK_FRAME_SD_GET_OR_RETURN(o, ptr, ...) \
105 EWK_FRAME_TYPE_CHECK(o, __VA_ARGS__); \
106 EWK_FRAME_SD_GET(o, ptr); \
107 if (!ptr) { \
108 CRITICAL("no smart data for object %p (%s)", \
109 o, evas_object_type_get(o)); \
110 return __VA_ARGS__; \
111 }
112
113 static Evas_Smart_Class _parent_sc = EVAS_SMART_CLASS_INIT_NULL;
114
115 #ifdef EWK_FRAME_DEBUG
_ewk_frame_debug(Evas_Object * o)116 static inline void _ewk_frame_debug(Evas_Object* o)
117 {
118 Evas_Object* clip, *parent;
119 Evas_Coord x, y, w, h, cx, cy, cw, ch;
120 int r, g, b, a, cr, cg, cb, ca;
121
122 evas_object_color_get(o, &r, &g, &b, &a);
123 evas_object_geometry_get(o, &x, &y, &w, &h);
124
125 clip = evas_object_clip_get(o);
126 evas_object_color_get(clip, &cr, &cg, &cb, &ca);
127 evas_object_geometry_get(clip, &cx, &cy, &cw, &ch);
128
129 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",
130 o, evas_object_type_get(o), evas_object_name_get(o), evas_object_visible_get(o),
131 r, g, b, a, x, y, w, h,
132 clip, evas_object_visible_get(clip), cr, cg, cb, ca, cx, cy, cw, ch);
133 parent = evas_object_smart_parent_get(o);
134 if (!parent)
135 fprintf(stderr, "\n");
136 else
137 _ewk_frame_debug(parent);
138 }
139 #endif
140
_ewk_frame_loader_efl_get(WebCore::Frame * frame)141 static WebCore::FrameLoaderClientEfl* _ewk_frame_loader_efl_get(WebCore::Frame* frame)
142 {
143 return static_cast<WebCore::FrameLoaderClientEfl*>(frame->loader()->client());
144 }
145
kit(WebCore::Frame * frame)146 static inline Evas_Object* kit(WebCore::Frame* frame)
147 {
148 if (!frame)
149 return 0;
150 WebCore::FrameLoaderClientEfl* fl = _ewk_frame_loader_efl_get(frame);
151 if (!fl)
152 return 0;
153 return fl->webFrame();
154 }
155
_ewk_frame_children_iterator_next(Eina_Iterator_Ewk_Frame * it,Evas_Object ** data)156 static Eina_Bool _ewk_frame_children_iterator_next(Eina_Iterator_Ewk_Frame* it, Evas_Object** data)
157 {
158 EWK_FRAME_SD_GET_OR_RETURN(it->obj, sd, EINA_FALSE);
159 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
160
161 WebCore::FrameTree* tree = sd->frame->tree(); // check if it's still valid
162 EINA_SAFETY_ON_NULL_RETURN_VAL(tree, EINA_FALSE);
163
164 WebCore::Frame* frame;
165 if (it->last)
166 frame = it->last->tree()->nextSibling();
167 else
168 frame = tree->firstChild();
169
170 if (!frame)
171 return EINA_FALSE;
172
173 *data = kit(frame);
174 return EINA_TRUE;
175 }
176
_ewk_frame_children_iterator_get_container(Eina_Iterator_Ewk_Frame * it)177 static Evas_Object* _ewk_frame_children_iterator_get_container(Eina_Iterator_Ewk_Frame* it)
178 {
179 return it->obj;
180 }
181
_ewk_frame_smart_add(Evas_Object * o)182 static void _ewk_frame_smart_add(Evas_Object* o)
183 {
184 EWK_FRAME_SD_GET(o, sd);
185
186 if (!sd) {
187 sd = (Ewk_Frame_Smart_Data*)calloc(1, sizeof(Ewk_Frame_Smart_Data));
188 if (!sd)
189 CRITICAL("could not allocate Ewk_Frame_Smart_Data");
190 else
191 evas_object_smart_data_set(o, sd);
192 }
193
194 sd->self = o;
195
196 _parent_sc.add(o);
197 evas_object_static_clip_set(sd->base.clipper, EINA_FALSE);
198 evas_object_move(sd->base.clipper, 0, 0);
199 evas_object_resize(sd->base.clipper, 0, 0);
200
201 #ifdef EWK_FRAME_DEBUG
202 sd->region = evas_object_rectangle_add(sd->base.evas);
203 static int i = 0;
204 switch (i) {
205 case 0:
206 evas_object_color_set(sd->region, 128, 0, 0, 128);
207 break;
208 case 1:
209 evas_object_color_set(sd->region, 0, 128, 0, 128);
210 break;
211 case 2:
212 evas_object_color_set(sd->region, 0, 0, 128, 128);
213 break;
214 case 3:
215 evas_object_color_set(sd->region, 128, 0, 0, 128);
216 break;
217 case 4:
218 evas_object_color_set(sd->region, 128, 128, 0, 128);
219 break;
220 case 5:
221 evas_object_color_set(sd->region, 128, 0, 128, 128);
222 break;
223 case 6:
224 evas_object_color_set(sd->region, 0, 128, 128, 128);
225 break;
226 default:
227 break;
228 }
229 i++;
230 if (i > 6)
231 i = 0;
232
233 evas_object_smart_member_add(sd->region, o);
234 evas_object_hide(sd->region);
235 #endif
236 }
237
_ewk_frame_smart_del(Evas_Object * o)238 static void _ewk_frame_smart_del(Evas_Object* o)
239 {
240 WRN("o=%p", o); // XXX REMOVE ME LATER
241 EWK_FRAME_SD_GET(o, sd);
242
243 if (sd) {
244 if (sd->frame) {
245 WebCore::FrameLoaderClientEfl* flc = _ewk_frame_loader_efl_get(sd->frame);
246 flc->setWebFrame(0);
247 sd->frame->loader()->cancelAndClear();
248 sd->frame = 0;
249 }
250
251 eina_stringshare_del(sd->title);
252 eina_stringshare_del(sd->uri);
253 eina_stringshare_del(sd->name);
254 }
255
256 _parent_sc.del(o);
257 }
258
_ewk_frame_smart_resize(Evas_Object * o,Evas_Coord w,Evas_Coord h)259 static void _ewk_frame_smart_resize(Evas_Object* o, Evas_Coord w, Evas_Coord h)
260 {
261 EWK_FRAME_SD_GET(o, sd);
262 evas_object_resize(sd->base.clipper, w, h);
263
264 #ifdef EWK_FRAME_DEBUG
265 evas_object_resize(sd->region, w, h);
266 Evas_Coord x, y;
267 evas_object_geometry_get(sd->region, &x, &y, &w, &h);
268 INF("region=%p, visible=%d, geo=%d,%d + %dx%d",
269 sd->region, evas_object_visible_get(sd->region), x, y, w, h);
270 _ewk_frame_debug(o);
271 #endif
272 }
273
_ewk_frame_smart_set(Evas_Smart_Class * api)274 static void _ewk_frame_smart_set(Evas_Smart_Class* api)
275 {
276 evas_object_smart_clipped_smart_set(api);
277 api->add = _ewk_frame_smart_add;
278 api->del = _ewk_frame_smart_del;
279 api->resize = _ewk_frame_smart_resize;
280 }
281
_ewk_frame_smart_class_new(void)282 static inline Evas_Smart* _ewk_frame_smart_class_new(void)
283 {
284 static Evas_Smart_Class sc = EVAS_SMART_CLASS_INIT_NAME_VERSION(EWK_FRAME_TYPE_STR);
285 static Evas_Smart* smart = 0;
286
287 if (EINA_UNLIKELY(!smart)) {
288 evas_object_smart_clipped_smart_set(&_parent_sc);
289 _ewk_frame_smart_set(&sc);
290 smart = evas_smart_class_new(&sc);
291 }
292
293 return smart;
294 }
295
296 /**
297 * @internal
298 *
299 * Creates a new EFL WebKit Frame object.
300 *
301 * Frames are low level entries contained in a page that is contained
302 * by a view. Usually one operates on the view and not directly on the
303 * frame.
304 *
305 * @param e canvas where to create the frame object.
306 *
307 * @return frame object or @c NULL if errors.
308 */
ewk_frame_add(Evas * e)309 Evas_Object* ewk_frame_add(Evas* e)
310 {
311 return evas_object_smart_add(e, _ewk_frame_smart_class_new());
312 }
313
314 /**
315 * Retrieves the ewk_view object that owns this frame.
316 *
317 * @param o frame object to get view from.
318 *
319 * @return view object or @c NULL if errors.
320 */
ewk_frame_view_get(const Evas_Object * o)321 Evas_Object* ewk_frame_view_get(const Evas_Object* o)
322 {
323 EWK_FRAME_SD_GET_OR_RETURN(o, sd, 0);
324 return sd->view;
325 }
326
327 /**
328 * Set the theme path to be used by this frame.
329 *
330 * Frames inherit theme from their parent, this will have all frames
331 * with unset theme to use this one.
332 *
333 * @param o frame object to change theme.
334 * @param path theme path, may be @c NULL to reset to default or inherit parent.
335 */
ewk_frame_theme_set(Evas_Object * o,const char * path)336 void ewk_frame_theme_set(Evas_Object* o, const char* path)
337 {
338 EWK_FRAME_SD_GET_OR_RETURN(o, sd);
339 if (!eina_stringshare_replace(&sd->theme, path))
340 return;
341 if (sd->frame && sd->frame->view()) {
342 sd->frame->view()->setEdjeTheme(WTF::String(path));
343 sd->frame->page()->theme()->themeChanged();
344 }
345 }
346
347 /**
348 * Gets the immediate theme set on this frame.
349 *
350 * This returns the value set by ewk_frame_theme_set(). Note that if
351 * it is @c NULL, the frame will inherit parent's theme.
352 *
353 * @param o frame object to get theme path.
354 *
355 * @return theme path, may be @c NULL if not set.
356 */
ewk_frame_theme_get(Evas_Object * o)357 const char* ewk_frame_theme_get(Evas_Object* o)
358 {
359 EWK_FRAME_SD_GET_OR_RETURN(o, sd, 0);
360 return sd->theme;
361 }
362
363 /**
364 * Returns a new iterator over all direct children frames.
365 *
366 * Keep frame object intact while iteration happens otherwise frame
367 * may be destroyed while iterated.
368 *
369 * Iteration results are Evas_Object*, so give eina_iterator_next() a
370 * pointer to it.
371 *
372 * @return a newly allocated iterator, free using
373 * eina_iterator_free(). If not possible to create the
374 * iterator, @c NULL is returned.
375 */
ewk_frame_children_iterator_new(Evas_Object * o)376 Eina_Iterator* ewk_frame_children_iterator_new(Evas_Object* o)
377 {
378 EWK_FRAME_SD_GET_OR_RETURN(o, sd, 0);
379 Eina_Iterator_Ewk_Frame* it = (Eina_Iterator_Ewk_Frame*)
380 calloc(1, sizeof(Eina_Iterator_Ewk_Frame));
381 if (!it)
382 return 0;
383
384 EINA_MAGIC_SET(&it->base, EINA_MAGIC_ITERATOR);
385 it->base.next = FUNC_ITERATOR_NEXT(_ewk_frame_children_iterator_next);
386 it->base.get_container = FUNC_ITERATOR_GET_CONTAINER(_ewk_frame_children_iterator_get_container);
387 it->base.free = FUNC_ITERATOR_FREE(free);
388 it->obj = o;
389 return &it->base;
390 }
391
392 /**
393 * Finds a child frame by its name, recursively.
394 *
395 * For pre-defined names, returns @a o if @a name is "_self" or
396 * "_current", returns @a o's parent frame if @a name is "_parent",
397 * and returns the main frame if @a name is "_top". Also returns @a o
398 * if it is the main frame and @a name is either "_parent" or
399 * "_top". For other names, this function returns the first frame that
400 * matches @a name. This function searches @a o and its descendents
401 * first, then @a o's parent and its children moving up the hierarchy
402 * until a match is found. If no match is found in @a o's hierarchy,
403 * this function will search for a matching frame in other main frame
404 * hierarchies.
405 *
406 * @return object if found, @c NULL if nothing with that name.
407 */
ewk_frame_child_find(Evas_Object * o,const char * name)408 Evas_Object* ewk_frame_child_find(Evas_Object* o, const char* name)
409 {
410 EWK_FRAME_SD_GET_OR_RETURN(o, sd, 0);
411 EINA_SAFETY_ON_NULL_RETURN_VAL(name, 0);
412 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, 0);
413 WTF::String s = WTF::String::fromUTF8(name);
414 return kit(sd->frame->tree()->find(WTF::AtomicString(s)));
415 }
416
417 /**
418 * Ask main frame to load the given URI.
419 *
420 * @param o frame object to load uri.
421 * @param uri uniform resource identifier to load.
422 */
ewk_frame_uri_set(Evas_Object * o,const char * uri)423 Eina_Bool ewk_frame_uri_set(Evas_Object* o, const char* uri)
424 {
425 EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
426 WebCore::KURL kurl(WebCore::KURL(), WTF::String::fromUTF8(uri));
427 WebCore::ResourceRequest req(kurl);
428 WebCore::FrameLoader* loader = sd->frame->loader();
429 loader->load(req, false);
430 return EINA_TRUE;
431 }
432
433 /**
434 * Gets the uri of this frame.
435 *
436 * @param o frame object to get uri.
437 *
438 * @return frame uri or @c NULL. It's a internal string and should
439 * not be modified. The string is guaranteed to be stringshared.
440 */
ewk_frame_uri_get(const Evas_Object * o)441 const char* ewk_frame_uri_get(const Evas_Object* o)
442 {
443 EWK_FRAME_SD_GET_OR_RETURN(o, sd, 0);
444 return sd->uri;
445 }
446
447 /**
448 * Gets the title of this frame.
449 *
450 * @param o frame object to get title.
451 *
452 * @return frame title or @c NULL. It's a internal string and should
453 * not be modified. The string is guaranteed to be stringshared.
454 */
ewk_frame_title_get(const Evas_Object * o)455 const char* ewk_frame_title_get(const Evas_Object* o)
456 {
457 EWK_FRAME_SD_GET_OR_RETURN(o, sd, 0);
458 return sd->title;
459 }
460
461 /**
462 * Gets the name of this frame.
463 *
464 * @param o frame object to get name.
465 *
466 * @return frame name or @c NULL. It's a internal string and should
467 * not be modified. The string is guaranteed to be stringshared.
468 */
ewk_frame_name_get(const Evas_Object * o)469 const char* ewk_frame_name_get(const Evas_Object* o)
470 {
471 EWK_FRAME_SD_GET_OR_RETURN(o, sd, 0);
472
473 if (sd->name)
474 return sd->name;
475
476 if (!sd->frame) {
477 ERR("could not get name of uninitialized frame.");
478 return 0;
479 }
480
481 WTF::String s = sd->frame->tree()->uniqueName();
482 WTF::CString cs = s.utf8();
483 sd->name = eina_stringshare_add_length(cs.data(), cs.length());
484 return sd->name;
485 }
486
487 /**
488 * Get last known contents size.
489 *
490 * @param o frame object to get contents size.
491 * @param w where to store contents size width. May be @c NULL.
492 * @param h where to store contents size height. May be @c NULL.
493 *
494 * @return @c EINA_TRUE on success or @c EINA_FALSE on failure and
495 * @a w and @a h will be zeroed.
496 */
ewk_frame_contents_size_get(const Evas_Object * o,Evas_Coord * w,Evas_Coord * h)497 Eina_Bool ewk_frame_contents_size_get(const Evas_Object* o, Evas_Coord* w, Evas_Coord* h)
498 {
499 if (w)
500 *w = 0;
501 if (h)
502 *h = 0;
503 EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
504 if (w)
505 *w = sd->contents_size.w;
506 if (h)
507 *h = sd->contents_size.h;
508 return EINA_TRUE;
509 }
510
_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)511 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)
512 {
513 size_t len = strlen(contents);
514 if (contents_size < 1 || contents_size > len)
515 contents_size = len;
516 if (!mime_type)
517 mime_type = "text/html";
518 if (!encoding)
519 encoding = "UTF-8";
520 if (!base_uri)
521 base_uri = "about:blank";
522
523 WebCore::KURL baseKURL(WebCore::KURL(), WTF::String::fromUTF8(base_uri));
524 WebCore::KURL unreachableKURL;
525 if (unreachable_uri)
526 unreachableKURL = WebCore::KURL(WebCore::KURL(), WTF::String::fromUTF8(unreachable_uri));
527 else
528 unreachableKURL = WebCore::KURL();
529
530 WTF::RefPtr<WebCore::SharedBuffer> buffer = WebCore::SharedBuffer::create(contents, contents_size);
531 WebCore::SubstituteData substituteData
532 (buffer.release(),
533 WTF::String::fromUTF8(mime_type),
534 WTF::String::fromUTF8(encoding),
535 baseKURL, unreachableKURL);
536 WebCore::ResourceRequest request(baseKURL);
537
538 sd->frame->loader()->load(request, substituteData, false);
539 return EINA_TRUE;
540 }
541
542 /**
543 * Requests loading the given contents in this frame.
544 *
545 * @param o frame object to load document.
546 * @param contents what to load into frame. Must not be @c NULL.
547 * @param contents_size byte size of data in @a contents.
548 * If zero, strlen() is used.
549 * @param mime_type type of @a contents data. If @c NULL "text/html" is assumed.
550 * @param encoding used for @a contents data. If @c NULL "UTF-8" is assumed.
551 * @param base_uri base uri to use for relative resources. May be @c NULL.
552 * If provided must be an absolute uri.
553 *
554 * @return @c EINA_TRUE on successful request, @c EINA_FALSE on errors.
555 */
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)556 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)
557 {
558 EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
559 EINA_SAFETY_ON_FALSE_RETURN_VAL(sd->frame, EINA_FALSE);
560 EINA_SAFETY_ON_NULL_RETURN_VAL(contents, EINA_FALSE);
561 return _ewk_frame_contents_set_internal
562 (sd, contents, contents_size, mime_type, encoding, base_uri, 0);
563 }
564
565 /**
566 * Requests loading alternative contents for unreachable URI in this frame.
567 *
568 * This is similar to ewk_frame_contents_set(), but is used when some
569 * URI failed to load, using the provided content instead. The main
570 * difference is that back-forward navigation list is not changed.
571 *
572 * @param o frame object to load document.
573 * @param contents what to load into frame. Must not be @c NULL.
574 * @param contents_size byte size of data in @a contents.
575 * If zero, strlen() is used.
576 * @param mime_type type of @a contents data. If @c NULL "text/html" is assumed.
577 * @param encoding used for @a contents data. If @c NULL "UTF-8" is assumed.
578 * @param base_uri base uri to use for relative resources. May be @c NULL.
579 * If provided must be an absolute uri.
580 * @param unreachable_uri the URI that failed to load and is getting the
581 * alternative representation.
582 *
583 * @return @c EINA_TRUE on successful request, @c EINA_FALSE on errors.
584 */
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)585 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)
586 {
587 EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
588 EINA_SAFETY_ON_FALSE_RETURN_VAL(sd->frame, EINA_FALSE);
589 EINA_SAFETY_ON_NULL_RETURN_VAL(contents, EINA_FALSE);
590 EINA_SAFETY_ON_NULL_RETURN_VAL(unreachable_uri, EINA_FALSE);
591 return _ewk_frame_contents_set_internal
592 (sd, contents, contents_size, mime_type, encoding, base_uri,
593 unreachable_uri);
594 }
595
596 /**
597 * Requests execution of given script.
598 *
599 * @param o frame object to execute script.
600 * @param script java script to execute.
601 *
602 * @return @c EINA_TRUE if request was done, @c EINA_FALSE on errors.
603 */
ewk_frame_script_execute(Evas_Object * o,const char * script)604 Eina_Bool ewk_frame_script_execute(Evas_Object* o, const char* script)
605 {
606 EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
607 EINA_SAFETY_ON_FALSE_RETURN_VAL(sd->frame, EINA_FALSE);
608 EINA_SAFETY_ON_NULL_RETURN_VAL(script, EINA_FALSE);
609 sd->frame->script()->executeScript(WTF::String::fromUTF8(script), true);
610 return EINA_TRUE;
611 }
612
613 /**
614 * Gets if frame is editable.
615 *
616 * @param o frame object to get editable state.
617 *
618 * @return @c EINA_TRUE if editable, @c EINA_FALSE otherwise.
619 */
ewk_frame_editable_get(const Evas_Object * o)620 Eina_Bool ewk_frame_editable_get(const Evas_Object* o)
621 {
622 EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
623 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
624 return sd->editable;
625 }
626
627 /**
628 * Sets if frame is editable.
629 *
630 * @param o frame object to set editable state.
631 * @param editable new state.
632 *
633 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
634 */
ewk_frame_editable_set(Evas_Object * o,Eina_Bool editable)635 Eina_Bool ewk_frame_editable_set(Evas_Object* o, Eina_Bool editable)
636 {
637 EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
638 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
639 editable = !!editable;
640 if (sd->editable == editable)
641 return EINA_TRUE;
642 if (editable)
643 sd->frame->editor()->applyEditingStyleToBodyElement();
644 return EINA_TRUE;
645 }
646
647 /**
648 * Get the copy of the selection text.
649 *
650 * @param o frame object to get selection text.
651 *
652 * @return newly allocated string or @c NULL if nothing is selected or failure.
653 */
ewk_frame_selection_get(const Evas_Object * o)654 char* ewk_frame_selection_get(const Evas_Object* o)
655 {
656 EWK_FRAME_SD_GET_OR_RETURN(o, sd, 0);
657 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, 0);
658 WTF::CString s = sd->frame->editor()->selectedText().utf8();
659 if (s.isNull())
660 return 0;
661 return strdup(s.data());
662 }
663
_ewk_frame_editor_command(Ewk_Frame_Smart_Data * sd,const char * command)664 static inline Eina_Bool _ewk_frame_editor_command(Ewk_Frame_Smart_Data* sd, const char* command)
665 {
666 return sd->frame->editor()->command(WTF::String::fromUTF8(command)).execute();
667 }
668
669 /**
670 * Unselects whatever was selected.
671 *
672 * @return @c EINA_TRUE if operation was executed, @c EINA_FALSE otherwise.
673 */
ewk_frame_select_none(Evas_Object * o)674 Eina_Bool ewk_frame_select_none(Evas_Object* o)
675 {
676 EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
677 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
678 return _ewk_frame_editor_command(sd, "Unselect");
679 }
680
681 /**
682 * Selects everything.
683 *
684 * @return @c EINA_TRUE if operation was executed, @c EINA_FALSE otherwise.
685 */
ewk_frame_select_all(Evas_Object * o)686 Eina_Bool ewk_frame_select_all(Evas_Object* o)
687 {
688 EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
689 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
690 return _ewk_frame_editor_command(sd, "SelectAll");
691 }
692
693 /**
694 * Selects the current paragrah.
695 *
696 * @return @c EINA_TRUE if operation was executed, @c EINA_FALSE otherwise.
697 */
ewk_frame_select_paragraph(Evas_Object * o)698 Eina_Bool ewk_frame_select_paragraph(Evas_Object* o)
699 {
700 EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
701 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
702 return _ewk_frame_editor_command(sd, "SelectParagraph");
703 }
704
705 /**
706 * Selects the current sentence.
707 *
708 * @return @c EINA_TRUE if operation was executed, @c EINA_FALSE otherwise.
709 */
ewk_frame_select_sentence(Evas_Object * o)710 Eina_Bool ewk_frame_select_sentence(Evas_Object* o)
711 {
712 EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
713 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
714 return _ewk_frame_editor_command(sd, "SelectSentence");
715 }
716
717 /**
718 * Selects the current line.
719 *
720 * @return @c EINA_TRUE if operation was executed, @c EINA_FALSE otherwise.
721 */
ewk_frame_select_line(Evas_Object * o)722 Eina_Bool ewk_frame_select_line(Evas_Object* o)
723 {
724 EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
725 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
726 return _ewk_frame_editor_command(sd, "SelectLine");
727 }
728
729 /**
730 * Selects the current word.
731 *
732 * @return @c EINA_TRUE if operation was executed, @c EINA_FALSE otherwise.
733 */
ewk_frame_select_word(Evas_Object * o)734 Eina_Bool ewk_frame_select_word(Evas_Object* o)
735 {
736 EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
737 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
738 return _ewk_frame_editor_command(sd, "SelectWord");
739 }
740
741 /**
742 * Search the given text string in document.
743 *
744 * @param o frame object where to search text.
745 * @param string reference string to search.
746 * @param case_sensitive if search should be case sensitive or not.
747 * @param forward if search is from cursor and on or backwards.
748 * @param wrap if search should wrap at end.
749 *
750 * @return @c EINA_TRUE if found, @c EINA_FALSE if not or failure.
751 */
ewk_frame_text_search(const Evas_Object * o,const char * string,Eina_Bool case_sensitive,Eina_Bool forward,Eina_Bool wrap)752 Eina_Bool ewk_frame_text_search(const Evas_Object* o, const char* string, Eina_Bool case_sensitive, Eina_Bool forward, Eina_Bool wrap)
753 {
754 EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
755 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
756 EINA_SAFETY_ON_NULL_RETURN_VAL(string, EINA_FALSE);
757
758 return sd->frame->editor()->findString(WTF::String::fromUTF8(string), forward, case_sensitive, wrap, true);
759 }
760
761 /**
762 * Mark matches the given text string in document.
763 *
764 * @param o frame object where to search text.
765 * @param string reference string to match.
766 * @param case_sensitive if match should be case sensitive or not.
767 * @param highlight if matches should be highlighted.
768 * @param limit maximum amount of matches, or zero to unlimited.
769 *
770 * @return number of matches.
771 */
ewk_frame_text_matches_mark(Evas_Object * o,const char * string,Eina_Bool case_sensitive,Eina_Bool highlight,unsigned int limit)772 unsigned int ewk_frame_text_matches_mark(Evas_Object* o, const char* string, Eina_Bool case_sensitive, Eina_Bool highlight, unsigned int limit)
773 {
774 EWK_FRAME_SD_GET_OR_RETURN(o, sd, 0);
775 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
776 EINA_SAFETY_ON_NULL_RETURN_VAL(string, 0);
777
778 sd->frame->editor()->setMarkedTextMatchesAreHighlighted(highlight);
779 return sd->frame->editor()->countMatchesForText(WTF::String::fromUTF8(string), case_sensitive, limit, true);
780 }
781
782 /**
783 * Reverses the effect of ewk_frame_text_matches_mark()
784 *
785 * @param o frame object where to search text.
786 *
787 * @return @c EINA_TRUE on success, @c EINA_FALSE for failure.
788 */
ewk_frame_text_matches_unmark_all(Evas_Object * o)789 Eina_Bool ewk_frame_text_matches_unmark_all(Evas_Object* o)
790 {
791 EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
792 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
793
794 sd->frame->document()->markers()->removeMarkers(WebCore::DocumentMarker::TextMatch);
795 return EINA_TRUE;
796 }
797
798 /**
799 * Set if should highlight matches marked with ewk_frame_text_matches_mark().
800 *
801 * @param o frame object where to set if matches are highlighted or not.
802 * @param highlight if @c EINA_TRUE, matches will be highlighted.
803 *
804 * @return @c EINA_TRUE on success, @c EINA_FALSE for failure.
805 */
ewk_frame_text_matches_highlight_set(Evas_Object * o,Eina_Bool highlight)806 Eina_Bool ewk_frame_text_matches_highlight_set(Evas_Object* o, Eina_Bool highlight)
807 {
808 EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
809 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
810 sd->frame->editor()->setMarkedTextMatchesAreHighlighted(highlight);
811 return EINA_TRUE;
812 }
813
814 /**
815 * Get if should highlight matches marked with ewk_frame_text_matches_mark().
816 *
817 * @param o frame object to query if matches are highlighted or not.
818 *
819 * @return @c EINA_TRUE if they are highlighted, @c EINA_FALSE otherwise.
820 */
ewk_frame_text_matches_highlight_get(const Evas_Object * o)821 Eina_Bool ewk_frame_text_matches_highlight_get(const Evas_Object* o)
822 {
823 EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
824 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
825 return sd->frame->editor()->markedTextMatchesAreHighlighted();
826 }
827
828 /**
829 * Comparison function used by ewk_frame_text_matches_nth_pos_get
830 */
_ewk_frame_rect_cmp_less_than(const WebCore::IntRect & i,const WebCore::IntRect & j)831 static bool _ewk_frame_rect_cmp_less_than(const WebCore::IntRect& i, const WebCore::IntRect& j)
832 {
833 return (i.y() < j.y() || (i.y() == j.y() && i.x() < j.x()));
834 }
835
836 /**
837 * Predicate used by ewk_frame_text_matches_nth_pos_get
838 */
_ewk_frame_rect_is_negative_value(const WebCore::IntRect & i)839 static bool _ewk_frame_rect_is_negative_value(const WebCore::IntRect& i)
840 {
841 return (i.x() < 0 || i.y() < 0);
842 }
843
844 /**
845 * Get x, y position of n-th text match in frame
846 *
847 * @param o frame object where matches are highlighted.
848 * @param n index of element
849 * @param x where to return x position. May be @c NULL.
850 * @param y where to return y position. May be @c NULL.
851 *
852 * @return @c EINA_TRUE on success, @c EINA_FALSE for failure - when no matches found or
853 * n bigger than search results.
854 */
ewk_frame_text_matches_nth_pos_get(Evas_Object * o,size_t n,int * x,int * y)855 Eina_Bool ewk_frame_text_matches_nth_pos_get(Evas_Object* o, size_t n, int* x, int* y)
856 {
857 EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
858 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
859
860 Vector<WebCore::IntRect> intRects = sd->frame->document()->markers()->renderedRectsForMarkers(WebCore::DocumentMarker::TextMatch);
861
862 /* remove useless values */
863 std::remove_if(intRects.begin(), intRects.end(), _ewk_frame_rect_is_negative_value);
864
865 if (intRects.isEmpty() || n > intRects.size())
866 return EINA_FALSE;
867
868 std::sort(intRects.begin(), intRects.end(), _ewk_frame_rect_cmp_less_than);
869
870 if (x)
871 *x = intRects[n - 1].x();
872 if (y)
873 *y = intRects[n - 1].y();
874 return EINA_TRUE;
875 }
876
877 /**
878 * Ask frame to stop loading.
879 *
880 * @param o frame object to stop loading.
881 *
882 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
883 */
ewk_frame_stop(Evas_Object * o)884 Eina_Bool ewk_frame_stop(Evas_Object* o)
885 {
886 EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
887 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
888 sd->frame->loader()->stopAllLoaders();
889 return EINA_TRUE;
890 }
891
892 /**
893 * Ask frame to reload current document.
894 *
895 * @param o frame object to reload.
896 *
897 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
898 *
899 * @see ewk_frame_reload_full()
900 */
ewk_frame_reload(Evas_Object * o)901 Eina_Bool ewk_frame_reload(Evas_Object* o)
902 {
903 EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
904 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
905 sd->frame->loader()->reload();
906 return EINA_TRUE;
907 }
908
909 /**
910 * Ask frame to fully reload current document, using no previous caches.
911 *
912 * @param o frame object to reload.
913 *
914 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
915 */
ewk_frame_reload_full(Evas_Object * o)916 Eina_Bool ewk_frame_reload_full(Evas_Object* o)
917 {
918 EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
919 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
920 sd->frame->loader()->reload(true);
921 return EINA_TRUE;
922 }
923
924 /**
925 * Ask frame to navigate back in history.
926 *
927 * @param o frame object to navigate back.
928 *
929 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
930 *
931 * @see ewk_frame_navigate()
932 */
ewk_frame_back(Evas_Object * o)933 Eina_Bool ewk_frame_back(Evas_Object* o)
934 {
935 return ewk_frame_navigate(o, -1);
936 }
937
938 /**
939 * Ask frame to navigate forward in history.
940 *
941 * @param o frame object to navigate forward.
942 *
943 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
944 *
945 * @see ewk_frame_navigate()
946 */
ewk_frame_forward(Evas_Object * o)947 Eina_Bool ewk_frame_forward(Evas_Object* o)
948 {
949 return ewk_frame_navigate(o, 1);
950 }
951
952 /**
953 * Navigate back or forward in history.
954 *
955 * @param o frame object to navigate.
956 * @param steps if positive navigates that amount forwards, if negative
957 * does backwards.
958 *
959 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
960 */
ewk_frame_navigate(Evas_Object * o,int steps)961 Eina_Bool ewk_frame_navigate(Evas_Object* o, int steps)
962 {
963 EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
964 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
965 WebCore::Page* page = sd->frame->page();
966 if (!page->canGoBackOrForward(steps))
967 return EINA_FALSE;
968 page->goBackOrForward(steps);
969 return EINA_TRUE;
970 }
971
972 /**
973 * Check if it is possible to navigate backwards one item in history.
974 *
975 * @param o frame object to check if backward navigation is possible.
976 *
977 * @return @c EINA_TRUE if possible, @c EINA_FALSE otherwise.
978 *
979 * @see ewk_frame_navigate_possible()
980 */
ewk_frame_back_possible(Evas_Object * o)981 Eina_Bool ewk_frame_back_possible(Evas_Object* o)
982 {
983 return ewk_frame_navigate_possible(o, -1);
984 }
985
986 /**
987 * Check if it is possible to navigate forwards one item in history.
988 *
989 * @param o frame object to check if forward navigation is possible.
990 *
991 * @return @c EINA_TRUE if possible, @c EINA_FALSE otherwise.
992 *
993 * @see ewk_frame_navigate_possible()
994 */
ewk_frame_forward_possible(Evas_Object * o)995 Eina_Bool ewk_frame_forward_possible(Evas_Object* o)
996 {
997 return ewk_frame_navigate_possible(o, 1);
998 }
999
1000 /**
1001 * Check if it is possible to navigate given @a steps in history.
1002 *
1003 * @param o frame object to navigate.
1004 * @param steps if positive navigates that amount forwards, if negative
1005 * does backwards.
1006 *
1007 * @return @c EINA_TRUE if possible, @c EINA_FALSE otherwise.
1008 */
ewk_frame_navigate_possible(Evas_Object * o,int steps)1009 Eina_Bool ewk_frame_navigate_possible(Evas_Object* o, int steps)
1010 {
1011 EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1012 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
1013 WebCore::Page* page = sd->frame->page();
1014 return page->canGoBackOrForward(steps);
1015 }
1016
1017 /**
1018 * Get current zoom level used by this frame.
1019 *
1020 * @param o frame object to query zoom level.
1021 *
1022 * @return zoom level or -1.0 on failure.
1023 */
ewk_frame_zoom_get(const Evas_Object * o)1024 float ewk_frame_zoom_get(const Evas_Object* o)
1025 {
1026 EWK_FRAME_SD_GET_OR_RETURN(o, sd, -1.0);
1027 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, -1.0);
1028
1029 if (sd->textZoom)
1030 return sd->frame->textZoomFactor();
1031 return sd->frame->pageZoomFactor();
1032 }
1033
1034 /**
1035 * Set current zoom level used by this frame.
1036 *
1037 * @param o frame object to change zoom level.
1038 * @param zoom new level.
1039 *
1040 * @return @c EINA_TRUE on success or @c EINA_FALSE on failure.
1041 *
1042 * @see ewk_frame_zoom_text_only_set()
1043 */
ewk_frame_zoom_set(Evas_Object * o,float zoom)1044 Eina_Bool ewk_frame_zoom_set(Evas_Object* o, float zoom)
1045 {
1046 EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1047 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
1048 if (sd->textZoom)
1049 sd->frame->setTextZoomFactor(zoom);
1050 else
1051 sd->frame->setPageZoomFactor(zoom);
1052 return EINA_TRUE;
1053 }
1054
1055 /**
1056 * Query if zoom level just applies to text and not other elements.
1057 *
1058 * @param o frame to query setting.
1059 *
1060 * @return @c EINA_TRUE if just text are scaled, @c EINA_FALSE otherwise.
1061 */
ewk_frame_zoom_text_only_get(const Evas_Object * o)1062 Eina_Bool ewk_frame_zoom_text_only_get(const Evas_Object* o)
1063 {
1064 EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1065 return sd->textZoom;
1066 }
1067
1068 /**
1069 * Set if zoom level just applies to text and not other elements.
1070 *
1071 * @param o frame to change setting.
1072 * @param setting @c EINA_TRUE if zoom should just be applied to text.
1073 *
1074 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1075 */
ewk_frame_zoom_text_only_set(Evas_Object * o,Eina_Bool setting)1076 Eina_Bool ewk_frame_zoom_text_only_set(Evas_Object* o, Eina_Bool setting)
1077 {
1078 EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1079 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
1080 if (sd->textZoom == setting)
1081 return EINA_TRUE;
1082
1083 float zoom_level = sd->textZoom ? sd->frame->textZoomFactor() : sd->frame->pageZoomFactor();
1084 sd->textZoom = setting;
1085 if (sd->textZoom)
1086 sd->frame->setPageAndTextZoomFactors(1, zoom_level);
1087 else
1088 sd->frame->setPageAndTextZoomFactors(zoom_level, 1);
1089 return EINA_TRUE;
1090 }
1091
1092 /**
1093 * Free hit test created with ewk_frame_hit_test_new().
1094 *
1095 * @param hit_test instance. Must @b not be @c NULL.
1096 */
ewk_frame_hit_test_free(Ewk_Hit_Test * hit_test)1097 void ewk_frame_hit_test_free(Ewk_Hit_Test* hit_test)
1098 {
1099 EINA_SAFETY_ON_NULL_RETURN(hit_test);
1100 eina_stringshare_del(hit_test->title);
1101 eina_stringshare_del(hit_test->alternate_text);
1102 eina_stringshare_del(hit_test->link.text);
1103 eina_stringshare_del(hit_test->link.url);
1104 eina_stringshare_del(hit_test->link.title);
1105 free(hit_test);
1106 }
1107
1108 /**
1109 * Creates a new hit test for given frame and point.
1110 *
1111 * @param o frame to do hit test on.
1112 * @param x horizontal position to query.
1113 * @param y vertical position to query.
1114 *
1115 * @return a newly allocated hit test on success, @c NULL otherwise.
1116 * Free memory with ewk_frame_hit_test_free()
1117 */
ewk_frame_hit_test_new(const Evas_Object * o,int x,int y)1118 Ewk_Hit_Test* ewk_frame_hit_test_new(const Evas_Object* o, int x, int y)
1119 {
1120 EWK_FRAME_SD_GET_OR_RETURN(o, sd, 0);
1121 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, 0);
1122
1123 WebCore::FrameView* view = sd->frame->view();
1124 EINA_SAFETY_ON_NULL_RETURN_VAL(view, 0);
1125 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame->contentRenderer(), 0);
1126
1127 WebCore::HitTestResult result = sd->frame->eventHandler()->hitTestResultAtPoint
1128 (view->windowToContents(WebCore::IntPoint(x, y)),
1129 /*allowShadowContent*/ false, /*ignoreClipping*/ true);
1130
1131 if (result.scrollbar())
1132 return 0;
1133 if (!result.innerNode())
1134 return 0;
1135
1136 Ewk_Hit_Test* hit_test = (Ewk_Hit_Test*)calloc(1, sizeof(Ewk_Hit_Test));
1137 if (!hit_test) {
1138 CRITICAL("Could not allocate memory for hit test.");
1139 return 0;
1140 }
1141
1142 hit_test->x = result.point().x();
1143 hit_test->y = result.point().y();
1144 #if 0
1145 // FIXME
1146 hit_test->bounding_box.x = result.boundingBox().x();
1147 hit_test->bounding_box.y = result.boundingBox().y();
1148 hit_test->bounding_box.w = result.boundingBox().width();
1149 hit_test->bounding_box.h = result.boundingBox().height();
1150 #else
1151 hit_test->bounding_box.x = 0;
1152 hit_test->bounding_box.y = 0;
1153 hit_test->bounding_box.w = 0;
1154 hit_test->bounding_box.h = 0;
1155 #endif
1156
1157 WebCore::TextDirection dir;
1158 hit_test->title = eina_stringshare_add(result.title(dir).utf8().data());
1159 hit_test->alternate_text = eina_stringshare_add(result.altDisplayString().utf8().data());
1160 if (result.innerNonSharedNode() && result.innerNonSharedNode()->document()
1161 && result.innerNonSharedNode()->document()->frame())
1162 hit_test->frame = kit(result.innerNonSharedNode()->document()->frame());
1163
1164 hit_test->link.text = eina_stringshare_add(result.textContent().utf8().data());
1165 hit_test->link.url = eina_stringshare_add(result.absoluteLinkURL().prettyURL().utf8().data());
1166 hit_test->link.title = eina_stringshare_add(result.titleDisplayString().utf8().data());
1167 hit_test->link.target_frame = kit(result.targetFrame());
1168
1169 hit_test->flags.editable = result.isContentEditable();
1170 hit_test->flags.selected = result.isSelected();
1171
1172 return hit_test;
1173 }
1174
1175 /**
1176 * Relative scroll of given frame.
1177 *
1178 * @param o frame object to scroll.
1179 * @param dx horizontal offset to scroll.
1180 * @param dy vertical offset to scroll.
1181 *
1182 * @return @c EINA_TRUE if possible, @c EINA_FALSE otherwise.
1183 */
1184 Eina_Bool
ewk_frame_scroll_add(Evas_Object * o,int dx,int dy)1185 ewk_frame_scroll_add(Evas_Object* o, int dx, int dy)
1186 {
1187 EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1188 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
1189 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame->view(), EINA_FALSE);
1190 sd->frame->view()->scrollBy(WebCore::IntSize(dx, dy));
1191 return EINA_TRUE;
1192 }
1193
1194 /**
1195 * Set absolute scroll of given frame.
1196 *
1197 * Both values are from zero to the contents size minus the viewport
1198 * size. See ewk_frame_scroll_size_get().
1199 *
1200 * @param o frame object to scroll.
1201 * @param x horizontal position to scroll.
1202 * @param y vertical position to scroll.
1203 *
1204 * @return @c EINA_TRUE if possible, @c EINA_FALSE otherwise.
1205 */
1206 Eina_Bool
ewk_frame_scroll_set(Evas_Object * o,int x,int y)1207 ewk_frame_scroll_set(Evas_Object* o, int x, int y)
1208 {
1209 EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1210 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
1211 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame->view(), EINA_FALSE);
1212 sd->frame->view()->setScrollPosition(WebCore::IntPoint(x, y));
1213 return EINA_TRUE;
1214 }
1215
1216 /**
1217 * Get the possible scroll size of given frame.
1218 *
1219 * Possible scroll size is contents size minus the viewport
1220 * size. It's the last allowed value for ewk_frame_scroll_set()
1221 *
1222 * @param o frame object to scroll.
1223 * @param w where to return horizontal size that is possible to
1224 * scroll. May be @c NULL.
1225 * @param h where to return vertical size that is possible to scroll.
1226 * May be @c NULL.
1227 *
1228 * @return @c EINA_TRUE if possible, @c EINA_FALSE otherwise and
1229 * values are zeroed.
1230 */
1231 Eina_Bool
ewk_frame_scroll_size_get(const Evas_Object * o,int * w,int * h)1232 ewk_frame_scroll_size_get(const Evas_Object* o, int* w, int* h)
1233 {
1234 if (w)
1235 *w = 0;
1236 if (h)
1237 *h = 0;
1238 EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1239 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
1240 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame->view(), EINA_FALSE);
1241 WebCore::IntPoint point = sd->frame->view()->maximumScrollPosition();
1242 if (w)
1243 *w = point.x();
1244 if (h)
1245 *h = point.y();
1246 return EINA_TRUE;
1247 }
1248
1249 /**
1250 * Get the current scroll position of given frame.
1251 *
1252 * @param o frame object to scroll.
1253 * @param x where to return horizontal position. May be @c NULL.
1254 * @param y where to return vertical position. May be @c NULL.
1255 *
1256 * @return @c EINA_TRUE if possible, @c EINA_FALSE otherwise and
1257 * values are zeroed.
1258 */
1259 Eina_Bool
ewk_frame_scroll_pos_get(const Evas_Object * o,int * x,int * y)1260 ewk_frame_scroll_pos_get(const Evas_Object* o, int* x, int* y)
1261 {
1262 if (x)
1263 *x = 0;
1264 if (y)
1265 *y = 0;
1266 EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1267 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
1268 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame->view(), EINA_FALSE);
1269 WebCore::IntPoint pos = sd->frame->view()->scrollPosition();
1270 if (x)
1271 *x = pos.x();
1272 if (y)
1273 *y = pos.y();
1274 return EINA_TRUE;
1275 }
1276
1277 /**
1278 * Get the current frame visible content geometry.
1279 *
1280 * @param o frame object to query visible content geometry.
1281 * @param include_scrollbars whenever to include scrollbars size.
1282 * @param x horizontal position. May be @c NULL.
1283 * @param y vertical position. May be @c NULL.
1284 * @param w width. May be @c NULL.
1285 * @param h height. May be @c NULL.
1286 *
1287 * @return @c EINA_TRUE if possible, @c EINA_FALSE otherwise and
1288 * values are zeroed.
1289 */
ewk_frame_visible_content_geometry_get(const Evas_Object * o,Eina_Bool include_scrollbars,int * x,int * y,int * w,int * h)1290 Eina_Bool ewk_frame_visible_content_geometry_get(const Evas_Object* o, Eina_Bool include_scrollbars, int* x, int* y, int* w, int* h)
1291 {
1292 if (x)
1293 *x = 0;
1294 if (y)
1295 *y = 0;
1296 if (w)
1297 *w = 0;
1298 if (h)
1299 *h = 0;
1300 EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1301 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
1302 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame->view(), EINA_FALSE);
1303 WebCore::IntRect rect = sd->frame->view()->visibleContentRect(include_scrollbars);
1304 if (x)
1305 *x = rect.x();
1306 if (y)
1307 *y = rect.y();
1308 if (w)
1309 *w = rect.width();
1310 if (h)
1311 *h = rect.height();
1312 return EINA_TRUE;
1313 }
1314
1315 /**
1316 * Get the current paintsEntireContents flag.
1317 *
1318 * This flag tells if dirty areas should be repainted even if they are
1319 * out of the screen.
1320 *
1321 * @param o frame object to query paintsEntireContents flag.
1322 *
1323 * @return @c EINA_TRUE if repainting any dirty area, @c EINA_FALSE
1324 * otherwise.
1325 */
ewk_frame_paint_full_get(const Evas_Object * o)1326 Eina_Bool ewk_frame_paint_full_get(const Evas_Object* o)
1327 {
1328 EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1329 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
1330 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame->view(), EINA_FALSE);
1331 return sd->frame->view()->paintsEntireContents();
1332 }
1333
1334 /**
1335 * Set the current paintsEntireContents flag.
1336 *
1337 * This flag tells if dirty areas should be repainted even if they are
1338 * out of the screen.
1339 *
1340 * @param o frame object to set paintsEntireContents flag.
1341 * @param flag @c EINA_TRUE if want to always repaint any dirty area,
1342 * @c EINA_FALSE otherwise.
1343 */
ewk_frame_paint_full_set(Evas_Object * o,Eina_Bool flag)1344 void ewk_frame_paint_full_set(Evas_Object* o, Eina_Bool flag)
1345 {
1346 EWK_FRAME_SD_GET_OR_RETURN(o, sd);
1347 EINA_SAFETY_ON_NULL_RETURN(sd->frame);
1348 EINA_SAFETY_ON_NULL_RETURN(sd->frame->view());
1349 sd->frame->view()->setPaintsEntireContents(flag);
1350 }
1351
1352 /**
1353 * Feed the focus in signal to this frame.
1354 *
1355 * @param o frame object to focus.
1356 *
1357 * @return @c EINA_TRUE if it was handled, @c EINA_FALSE otherwise.
1358 */
ewk_frame_feed_focus_in(Evas_Object * o)1359 Eina_Bool ewk_frame_feed_focus_in(Evas_Object* o)
1360 {
1361 EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1362 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
1363 WebCore::FocusController* c = sd->frame->page()->focusController();
1364 c->setFocusedFrame(sd->frame);
1365 return EINA_TRUE;
1366 }
1367
1368 /**
1369 * Feed the focus out signal to this frame.
1370 *
1371 * @param o frame object to remove focus.
1372 */
ewk_frame_feed_focus_out(Evas_Object * o)1373 Eina_Bool ewk_frame_feed_focus_out(Evas_Object* o)
1374 {
1375 // TODO: what to do on focus out?
1376 ERR("what to do?");
1377 return EINA_FALSE;
1378 }
1379
1380 /**
1381 * Feed the mouse wheel event to the frame.
1382 *
1383 * @param o frame object to feed event.
1384 * @param ev mouse wheel event.
1385 *
1386 * @return @c EINA_TRUE if it was handled, @c EINA_FALSE otherwise.
1387 */
ewk_frame_feed_mouse_wheel(Evas_Object * o,const Evas_Event_Mouse_Wheel * ev)1388 Eina_Bool ewk_frame_feed_mouse_wheel(Evas_Object* o, const Evas_Event_Mouse_Wheel* ev)
1389 {
1390 EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1391 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
1392 EINA_SAFETY_ON_NULL_RETURN_VAL(ev, EINA_FALSE);
1393
1394 WebCore::FrameView* view = sd->frame->view();
1395 DBG("o=%p, view=%p, direction=%d, z=%d, pos=%d,%d",
1396 o, view, ev->direction, ev->z, ev->canvas.x, ev->canvas.y);
1397 EINA_SAFETY_ON_NULL_RETURN_VAL(view, EINA_FALSE);
1398
1399 WebCore::PlatformWheelEvent event(ev);
1400 return sd->frame->eventHandler()->handleWheelEvent(event);
1401 }
1402
1403 /**
1404 * Feed the mouse down event to the frame.
1405 *
1406 * @param o frame object to feed event.
1407 * @param ev mouse down event.
1408 *
1409 * @return @c EINA_TRUE if it was handled, @c EINA_FALSE otherwise.
1410 */
ewk_frame_feed_mouse_down(Evas_Object * o,const Evas_Event_Mouse_Down * ev)1411 Eina_Bool ewk_frame_feed_mouse_down(Evas_Object* o, const Evas_Event_Mouse_Down* ev)
1412 {
1413 EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1414 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
1415 EINA_SAFETY_ON_NULL_RETURN_VAL(ev, EINA_FALSE);
1416
1417 WebCore::FrameView* view = sd->frame->view();
1418 DBG("o=%p, view=%p, button=%d, pos=%d,%d",
1419 o, view, ev->button, ev->canvas.x, ev->canvas.y);
1420 EINA_SAFETY_ON_NULL_RETURN_VAL(view, EINA_FALSE);
1421
1422 Evas_Coord x, y;
1423 evas_object_geometry_get(sd->view, &x, &y, 0, 0);
1424
1425 WebCore::PlatformMouseEvent event(ev, WebCore::IntPoint(x, y));
1426 return sd->frame->eventHandler()->handleMousePressEvent(event);
1427 }
1428
1429 /**
1430 * Feed the mouse up event to the frame.
1431 *
1432 * @param o frame object to feed event.
1433 * @param ev mouse up event.
1434 *
1435 * @return @c EINA_TRUE if it was handled, @c EINA_FALSE otherwise.
1436 */
ewk_frame_feed_mouse_up(Evas_Object * o,const Evas_Event_Mouse_Up * ev)1437 Eina_Bool ewk_frame_feed_mouse_up(Evas_Object* o, const Evas_Event_Mouse_Up* ev)
1438 {
1439 EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1440 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
1441 EINA_SAFETY_ON_NULL_RETURN_VAL(ev, EINA_FALSE);
1442
1443 WebCore::FrameView* view = sd->frame->view();
1444 DBG("o=%p, view=%p, button=%d, pos=%d,%d",
1445 o, view, ev->button, ev->canvas.x, ev->canvas.y);
1446 EINA_SAFETY_ON_NULL_RETURN_VAL(view, EINA_FALSE);
1447
1448 Evas_Coord x, y;
1449 evas_object_geometry_get(sd->view, &x, &y, 0, 0);
1450
1451 WebCore::PlatformMouseEvent event(ev, WebCore::IntPoint(x, y));
1452 return sd->frame->eventHandler()->handleMouseReleaseEvent(event);
1453 }
1454
1455 /**
1456 * Feed the mouse move event to the frame.
1457 *
1458 * @param o frame object to feed event.
1459 * @param ev mouse move event.
1460 *
1461 * @return @c EINA_TRUE if it was handled, @c EINA_FALSE otherwise.
1462 */
ewk_frame_feed_mouse_move(Evas_Object * o,const Evas_Event_Mouse_Move * ev)1463 Eina_Bool ewk_frame_feed_mouse_move(Evas_Object* o, const Evas_Event_Mouse_Move* ev)
1464 {
1465 EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1466 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
1467 EINA_SAFETY_ON_NULL_RETURN_VAL(ev, EINA_FALSE);
1468
1469 WebCore::FrameView* view = sd->frame->view();
1470 DBG("o=%p, view=%p, pos: old=%d,%d, new=%d,%d, buttons=%d",
1471 o, view, ev->cur.canvas.x, ev->cur.canvas.y,
1472 ev->prev.canvas.x, ev->prev.canvas.y, ev->buttons);
1473 EINA_SAFETY_ON_NULL_RETURN_VAL(view, EINA_FALSE);
1474
1475 Evas_Coord x, y;
1476 evas_object_geometry_get(sd->view, &x, &y, 0, 0);
1477
1478 WebCore::PlatformMouseEvent event(ev, WebCore::IntPoint(x, y));
1479 return sd->frame->eventHandler()->mouseMoved(event);
1480 }
1481
ewk_frame_feed_touch_event(Evas_Object * o,Ewk_Touch_Event_Type action,Eina_List * points,int metaState)1482 Eina_Bool ewk_frame_feed_touch_event(Evas_Object* o, Ewk_Touch_Event_Type action, Eina_List* points, int metaState)
1483 {
1484 Eina_Bool ret = EINA_FALSE;
1485
1486 #if ENABLE(TOUCH_EVENTS)
1487 EINA_SAFETY_ON_NULL_RETURN_VAL(points, EINA_FALSE);
1488 EWK_FRAME_SD_GET(o, sd);
1489
1490 if (!sd || !sd->frame || !ewk_view_need_touch_events_get(sd->view)) {
1491 void* point;
1492 EINA_LIST_FREE(points, point);
1493 return EINA_FALSE;
1494 }
1495
1496 Evas_Coord x, y;
1497 evas_object_geometry_get(sd->view, &x, &y, 0, 0);
1498
1499 WebCore::TouchEventType type = WebCore::TouchStart;
1500 switch (action) {
1501 case EWK_TOUCH_START:
1502 type = WebCore::TouchStart;
1503 break;
1504 case EWK_TOUCH_END:
1505 type = WebCore::TouchEnd;
1506 break;
1507 case EWK_TOUCH_MOVE:
1508 type = WebCore::TouchMove;
1509 break;
1510 case EWK_TOUCH_CANCEL:
1511 type = WebCore::TouchCancel;
1512 break;
1513 default:
1514 return EINA_FALSE;
1515 }
1516
1517 WebCore::PlatformTouchEvent te(points, WebCore::IntPoint(x, y), type, metaState);
1518 ret = sd->frame->eventHandler()->handleTouchEvent(te);
1519 #endif
1520 return ret;
1521 }
1522
_ewk_frame_handle_key_scrolling(WebCore::Frame * frame,const WebCore::PlatformKeyboardEvent & event)1523 static inline Eina_Bool _ewk_frame_handle_key_scrolling(WebCore::Frame* frame, const WebCore::PlatformKeyboardEvent &event)
1524 {
1525 WebCore::ScrollDirection direction;
1526 WebCore::ScrollGranularity granularity;
1527
1528 int keyCode = event.windowsVirtualKeyCode();
1529
1530 switch (keyCode) {
1531 case VK_SPACE:
1532 granularity = WebCore::ScrollByPage;
1533 if (event.shiftKey())
1534 direction = WebCore::ScrollUp;
1535 else
1536 direction = WebCore::ScrollDown;
1537 break;
1538 case VK_NEXT:
1539 granularity = WebCore::ScrollByPage;
1540 direction = WebCore::ScrollDown;
1541 break;
1542 case VK_PRIOR:
1543 granularity = WebCore::ScrollByPage;
1544 direction = WebCore::ScrollUp;
1545 break;
1546 case VK_HOME:
1547 granularity = WebCore::ScrollByDocument;
1548 direction = WebCore::ScrollUp;
1549 break;
1550 case VK_END:
1551 granularity = WebCore::ScrollByDocument;
1552 direction = WebCore::ScrollDown;
1553 break;
1554 case VK_LEFT:
1555 granularity = WebCore::ScrollByLine;
1556 direction = WebCore::ScrollLeft;
1557 break;
1558 case VK_RIGHT:
1559 granularity = WebCore::ScrollByLine;
1560 direction = WebCore::ScrollRight;
1561 break;
1562 case VK_UP:
1563 direction = WebCore::ScrollUp;
1564 if (event.ctrlKey())
1565 granularity = WebCore::ScrollByDocument;
1566 else
1567 granularity = WebCore::ScrollByLine;
1568 break;
1569 case VK_DOWN:
1570 direction = WebCore::ScrollDown;
1571 if (event.ctrlKey())
1572 granularity = WebCore::ScrollByDocument;
1573 else
1574 granularity = WebCore::ScrollByLine;
1575 break;
1576 default:
1577 return EINA_FALSE;
1578 }
1579
1580 if (frame->eventHandler()->scrollOverflow(direction, granularity))
1581 return EINA_FALSE;
1582
1583 frame->view()->scroll(direction, granularity);
1584 return EINA_TRUE;
1585 }
1586
1587 /**
1588 * Feed the keyboard key down event to the frame.
1589 *
1590 * @param o frame object to feed event.
1591 * @param ev keyboard key down event.
1592 *
1593 * @return @c EINA_TRUE if it was handled, @c EINA_FALSE otherwise.
1594 */
ewk_frame_feed_key_down(Evas_Object * o,const Evas_Event_Key_Down * ev)1595 Eina_Bool ewk_frame_feed_key_down(Evas_Object* o, const Evas_Event_Key_Down* ev)
1596 {
1597 EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1598 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
1599 EINA_SAFETY_ON_NULL_RETURN_VAL(ev, EINA_FALSE);
1600
1601 DBG("o=%p keyname=%s (key=%s, string=%s)",
1602 o, ev->keyname, ev->key ? ev->key : "", ev->string ? ev->string : "");
1603
1604 WebCore::PlatformKeyboardEvent event(ev);
1605 if (sd->frame->eventHandler()->keyEvent(event))
1606 return EINA_TRUE;
1607
1608 return _ewk_frame_handle_key_scrolling(sd->frame, event);
1609 }
1610
1611 /**
1612 * Feed the keyboard key up event to the frame.
1613 *
1614 * @param o frame object to feed event.
1615 * @param ev keyboard key up event.
1616 *
1617 * @return @c EINA_TRUE if it was handled, @c EINA_FALSE otherwise.
1618 */
ewk_frame_feed_key_up(Evas_Object * o,const Evas_Event_Key_Up * ev)1619 Eina_Bool ewk_frame_feed_key_up(Evas_Object* o, const Evas_Event_Key_Up* ev)
1620 {
1621 EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1622 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
1623 EINA_SAFETY_ON_NULL_RETURN_VAL(ev, EINA_FALSE);
1624
1625 DBG("o=%p keyname=%s (key=%s, string=%s)",
1626 o, ev->keyname, ev->key ? ev->key : "", ev->string ? ev->string : "");
1627
1628 WebCore::PlatformKeyboardEvent event(ev);
1629 return sd->frame->eventHandler()->keyEvent(event);
1630 }
1631
1632 /* internal methods ****************************************************/
1633
1634 /**
1635 * @internal
1636 *
1637 * Initialize frame based on actual WebKit frame.
1638 *
1639 * This is internal and should never be called by external users.
1640 */
ewk_frame_init(Evas_Object * o,Evas_Object * view,WebCore::Frame * frame)1641 Eina_Bool ewk_frame_init(Evas_Object* o, Evas_Object* view, WebCore::Frame* frame)
1642 {
1643 EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
1644 if (!sd->frame) {
1645 WebCore::FrameLoaderClientEfl* flc = _ewk_frame_loader_efl_get(frame);
1646 flc->setWebFrame(o);
1647 sd->frame = frame;
1648 sd->view = view;
1649 frame->init();
1650 return EINA_TRUE;
1651 }
1652
1653 ERR("frame %p already set for %p, ignored new %p",
1654 sd->frame, o, frame);
1655 return EINA_FALSE;
1656 }
1657
ewk_frame_child_add(Evas_Object * o,WTF::PassRefPtr<WebCore::Frame> child,const WTF::String & name,const WebCore::KURL & url,const WTF::String & referrer)1658 Evas_Object* ewk_frame_child_add(Evas_Object* o, WTF::PassRefPtr<WebCore::Frame> child, const WTF::String& name, const WebCore::KURL& url, const WTF::String& referrer)
1659 {
1660 EWK_FRAME_SD_GET_OR_RETURN(o, sd, 0);
1661 char buf[256];
1662 Evas_Object* frame;
1663 WebCore::Frame* cf;
1664
1665 frame = ewk_frame_add(sd->base.evas);
1666 if (!frame) {
1667 ERR("Could not create ewk_frame object.");
1668 return 0;
1669 }
1670
1671 cf = child.get();
1672 if (cf->tree())
1673 cf->tree()->setName(name);
1674 else
1675 ERR("no tree for child object");
1676 sd->frame->tree()->appendChild(child);
1677
1678 if (!ewk_frame_init(frame, sd->view, cf)) {
1679 evas_object_del(frame);
1680 return 0;
1681 }
1682 snprintf(buf, sizeof(buf), "EWK_Frame:child/%s", name.utf8().data());
1683 evas_object_name_set(frame, buf);
1684 evas_object_smart_member_add(frame, o);
1685 evas_object_show(frame);
1686
1687 if (!cf->page())
1688 goto died;
1689
1690 sd->frame->loader()->loadURLIntoChildFrame(url, referrer, cf);
1691 if (!cf->tree()->parent())
1692 goto died;
1693
1694 // TODO: announce frame was created?
1695 return frame;
1696
1697 died:
1698 CRITICAL("does this work: BEGIN");
1699 ewk_frame_core_gone(frame); // CONFIRM
1700 evas_object_del(frame); // CONFIRM
1701 CRITICAL("does this work: END");
1702 return 0;
1703 }
1704
1705 /**
1706 * @internal
1707 * Frame was destroyed by loader, remove internal reference.
1708 */
ewk_frame_core_gone(Evas_Object * o)1709 void ewk_frame_core_gone(Evas_Object* o)
1710 {
1711 DBG("o=%p", o);
1712 EWK_FRAME_SD_GET_OR_RETURN(o, sd);
1713 sd->frame = 0;
1714 }
1715
1716 /**
1717 * @internal
1718 * Retrieve WebCore::Frame associated with this object.
1719 *
1720 * Avoid using this call from outside, add specific ewk_frame_*
1721 * actions instead.
1722 */
ewk_frame_core_get(const Evas_Object * o)1723 WebCore::Frame* ewk_frame_core_get(const Evas_Object* o)
1724 {
1725 EWK_FRAME_SD_GET_OR_RETURN(o, sd, 0);
1726 return sd->frame;
1727 }
1728
1729
1730 /**
1731 * @internal
1732 * Reports a resource will be requested. User may override behavior of webkit by
1733 * changing values in @param request.
1734 *
1735 * @param o Frame.
1736 * @param request Request details that user may override. Whenever values on
1737 * this struct changes, it must be properly malloc'd as it will be freed
1738 * afterwards.
1739 *
1740 * Emits signal: "resource,request,willsend"
1741 */
ewk_frame_request_will_send(Evas_Object * o,Ewk_Frame_Resource_Request * request)1742 void ewk_frame_request_will_send(Evas_Object *o, Ewk_Frame_Resource_Request *request)
1743 {
1744 evas_object_smart_callback_call(o, "resource,request,willsend", request);
1745 }
1746
1747 /**
1748 * @internal
1749 * Reports that there's a new resource.
1750 *
1751 * @param o Frame.
1752 * @param request New request details. No changes are allowed to fields.
1753 *
1754 * Emits signal: "resource,request,new"
1755 */
ewk_frame_request_assign_identifier(Evas_Object * o,const Ewk_Frame_Resource_Request * request)1756 void ewk_frame_request_assign_identifier(Evas_Object *o, const Ewk_Frame_Resource_Request *request)
1757 {
1758 evas_object_smart_callback_call(o, "resource,request,new", (void *)request);
1759 }
1760
1761 /**
1762 * @internal
1763 * Reports that first navigation occurred
1764 *
1765 * @param o Frame.
1766 *
1767 * Emits signal: "navigation,first"
1768 */
ewk_frame_did_perform_first_navigation(Evas_Object * o)1769 void ewk_frame_did_perform_first_navigation(Evas_Object *o)
1770 {
1771 evas_object_smart_callback_call(o, "navigation,first", 0);
1772 }
1773
1774 /**
1775 * @internal
1776 * Reports frame will be saved to current state
1777 *
1778 * @param o Frame.
1779 * @param item History item to save details to.
1780 *
1781 * Emits signal: "state,save"
1782 */
ewk_frame_view_state_save(Evas_Object * o,WebCore::HistoryItem * item)1783 void ewk_frame_view_state_save(Evas_Object *o, WebCore::HistoryItem* item)
1784 {
1785 evas_object_smart_callback_call(o, "state,save", 0);
1786 }
1787
1788 /**
1789 * @internal
1790 * Reports the frame started loading something.
1791 *
1792 * Emits signal: "load,started" with no parameters.
1793 */
ewk_frame_load_started(Evas_Object * o)1794 void ewk_frame_load_started(Evas_Object* o)
1795 {
1796 Evas_Object* main_frame;
1797 DBG("o=%p", o);
1798 evas_object_smart_callback_call(o, "load,started", 0);
1799 EWK_FRAME_SD_GET_OR_RETURN(o, sd);
1800 ewk_view_load_started(sd->view);
1801
1802 main_frame = ewk_view_frame_main_get(sd->view);
1803 if (main_frame == o)
1804 ewk_view_frame_main_load_started(sd->view);
1805 }
1806
1807 /**
1808 * @internal
1809 * Reports the frame started provisional load.
1810 *
1811 * @param o Frame.
1812 *
1813 * Emits signal: "load,provisional" with no parameters.
1814 */
ewk_frame_load_provisional(Evas_Object * o)1815 void ewk_frame_load_provisional(Evas_Object* o)
1816 {
1817 evas_object_smart_callback_call(o, "load,provisional", 0);
1818 }
1819
1820 /**
1821 * @internal
1822 * Reports the frame finished first layout.
1823 *
1824 * @param o Frame.
1825 *
1826 * Emits signal: "load,firstlayout,finished" with no parameters.
1827 */
ewk_frame_load_firstlayout_finished(Evas_Object * o)1828 void ewk_frame_load_firstlayout_finished(Evas_Object *o)
1829 {
1830 evas_object_smart_callback_call(o, "load,firstlayout,finished", 0);
1831 }
1832
1833 /**
1834 * @internal
1835 * Reports the frame finished first non empty layout.
1836 *
1837 * @param o Frame.
1838 *
1839 * Emits signal: "load,nonemptylayout,finished" with no parameters.
1840 */
ewk_frame_load_firstlayout_nonempty_finished(Evas_Object * o)1841 void ewk_frame_load_firstlayout_nonempty_finished(Evas_Object *o)
1842 {
1843 evas_object_smart_callback_call(o, "load,nonemptylayout,finished", 0);
1844 }
1845
1846 /**
1847 * @internal
1848 * Reports the loading of a document has finished on frame.
1849 *
1850 * @param o Frame.
1851 *
1852 * Emits signal: "load,document,finished" with no parameters.
1853 */
ewk_frame_load_document_finished(Evas_Object * o)1854 void ewk_frame_load_document_finished(Evas_Object *o)
1855 {
1856 evas_object_smart_callback_call(o, "load,document,finished", 0);
1857 }
1858
1859 /**
1860 * @internal
1861 * Reports load finished, optionally with error information.
1862 *
1863 * Emits signal: "load,finished" with pointer to Ewk_Frame_Load_Error
1864 * if any error, or @c NULL if successful load.
1865 *
1866 * @note there should notbe any error stuff here, but trying to be
1867 * compatible with previous WebKit.
1868 */
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)1869 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)
1870 {
1871 Ewk_Frame_Load_Error buf, *error;
1872 if (!error_domain) {
1873 DBG("o=%p, success.", o);
1874 error = 0;
1875 } else {
1876 DBG("o=%p, error=%s (%d, cancellation=%hhu) \"%s\", url=%s",
1877 o, error_domain, error_code, is_cancellation,
1878 error_description, failing_url);
1879
1880 buf.domain = error_domain;
1881 buf.code = error_code;
1882 buf.is_cancellation = is_cancellation;
1883 buf.description = error_description;
1884 buf.failing_url = failing_url;
1885 buf.frame = o;
1886 error = &buf;
1887 }
1888 evas_object_smart_callback_call(o, "load,finished", error);
1889 EWK_FRAME_SD_GET_OR_RETURN(o, sd);
1890 ewk_view_load_finished(sd->view, error);
1891 }
1892
1893 /**
1894 * @internal
1895 * Reports load failed with error information.
1896 *
1897 * Emits signal: "load,error" with pointer to Ewk_Frame_Load_Error.
1898 */
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)1899 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)
1900 {
1901 Ewk_Frame_Load_Error error;
1902
1903 DBG("o=%p, error=%s (%d, cancellation=%hhu) \"%s\", url=%s",
1904 o, error_domain, error_code, is_cancellation,
1905 error_description, failing_url);
1906
1907 EINA_SAFETY_ON_NULL_RETURN(error_domain);
1908
1909 error.code = error_code;
1910 error.is_cancellation = is_cancellation;
1911 error.domain = error_domain;
1912 error.description = error_description;
1913 error.failing_url = failing_url;
1914 error.frame = o;
1915 evas_object_smart_callback_call(o, "load,error", &error);
1916 EWK_FRAME_SD_GET_OR_RETURN(o, sd);
1917 ewk_view_load_error(sd->view, &error);
1918 }
1919
1920 /**
1921 * @internal
1922 * Reports load progress changed.
1923 *
1924 * Emits signal: "load,progress" with pointer to a double from 0.0 to 1.0.
1925 */
ewk_frame_load_progress_changed(Evas_Object * o)1926 void ewk_frame_load_progress_changed(Evas_Object* o)
1927 {
1928 EWK_FRAME_SD_GET_OR_RETURN(o, sd);
1929 EINA_SAFETY_ON_NULL_RETURN(sd->frame);
1930
1931 // TODO: this is per page, there should be a way to have per-frame.
1932 double progress = sd->frame->page()->progress()->estimatedProgress();
1933
1934 DBG("o=%p (p=%0.3f)", o, progress);
1935
1936 evas_object_smart_callback_call(o, "load,progress", &progress);
1937 ewk_view_load_progress_changed(sd->view);
1938 }
1939
1940
1941 /**
1942 * @internal
1943 *
1944 * Reports contents size changed.
1945 */
ewk_frame_contents_size_changed(Evas_Object * o,Evas_Coord w,Evas_Coord h)1946 void ewk_frame_contents_size_changed(Evas_Object* o, Evas_Coord w, Evas_Coord h)
1947 {
1948 DBG("o=%p: %dx%d", o, w, h);
1949 EWK_FRAME_SD_GET_OR_RETURN(o, sd);
1950 if (sd->contents_size.w == w && sd->contents_size.h == h)
1951 return;
1952 sd->contents_size.w = w;
1953 sd->contents_size.h = h;
1954 // TODO: update something else internally?
1955
1956 Evas_Coord size[2] = {w, h};
1957 evas_object_smart_callback_call(o, "contents,size,changed", size);
1958 }
1959
1960 /**
1961 * @internal
1962 *
1963 * Reports title changed.
1964 */
ewk_frame_title_set(Evas_Object * o,const char * title)1965 void ewk_frame_title_set(Evas_Object* o, const char* title)
1966 {
1967 DBG("o=%p, title=%s", o, title ? title : "(null)");
1968 EWK_FRAME_SD_GET_OR_RETURN(o, sd);
1969 if (!eina_stringshare_replace(&sd->title, title))
1970 return;
1971 evas_object_smart_callback_call(o, "title,changed", (void*)sd->title);
1972 }
1973
ewk_frame_view_create_for_view(Evas_Object * o,Evas_Object * view)1974 void ewk_frame_view_create_for_view(Evas_Object* o, Evas_Object* view)
1975 {
1976 DBG("o=%p, view=%p", o, view);
1977 EWK_FRAME_SD_GET_OR_RETURN(o, sd);
1978 EINA_SAFETY_ON_NULL_RETURN(sd->frame);
1979 Evas_Coord w, h;
1980
1981 if (sd->frame->view())
1982 return;
1983
1984 evas_object_geometry_get(view, 0, 0, &w, &h);
1985
1986 WebCore::IntSize size(w, h);
1987 int r, g, b, a;
1988 WebCore::Color bg;
1989
1990 ewk_view_bg_color_get(view, &r, &g, &b, &a);
1991 if (!a)
1992 bg = WebCore::Color(0, 0, 0, 0);
1993 else if (a == 255)
1994 bg = WebCore::Color(r, g, b, a);
1995 else
1996 bg = WebCore::Color(r * 255 / a, g * 255 / a, b * 255 / a, a);
1997
1998 sd->frame->createView(size, bg, !a, WebCore::IntSize(), false);
1999 if (!sd->frame->view())
2000 return;
2001
2002 const char* theme = ewk_view_theme_get(view);
2003 sd->frame->view()->setEdjeTheme(theme);
2004 sd->frame->view()->setEvasObject(o);
2005 }
2006
2007 /**
2008 * @internal
2009 * Reports uri changed and swap internal string reference.
2010 *
2011 * Emits signal: "uri,changed" with new uri as parameter.
2012 */
ewk_frame_uri_changed(Evas_Object * o)2013 Eina_Bool ewk_frame_uri_changed(Evas_Object* o)
2014 {
2015 EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
2016 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
2017 WTF::CString uri(sd->frame->document()->url().prettyURL().utf8());
2018
2019 INF("uri=%s", uri.data());
2020 if (!uri.data()) {
2021 ERR("no uri");
2022 return EINA_FALSE;
2023 }
2024
2025 eina_stringshare_replace(&sd->uri, uri.data());
2026 evas_object_smart_callback_call(o, "uri,changed", (void*)sd->uri);
2027 return EINA_TRUE;
2028 }
2029
ewk_frame_force_layout(Evas_Object * o)2030 void ewk_frame_force_layout(Evas_Object* o)
2031 {
2032 DBG("o=%p", o);
2033 EWK_FRAME_SD_GET_OR_RETURN(o, sd);
2034 EINA_SAFETY_ON_NULL_RETURN(sd->frame);
2035 WebCore::FrameView* view = sd->frame->view();
2036 if (view)
2037 view->forceLayout(true);
2038 }
2039
ewk_frame_plugin_create(Evas_Object * o,const WebCore::IntSize & pluginSize,WebCore::HTMLPlugInElement * element,const WebCore::KURL & url,const WTF::Vector<WTF::String> & paramNames,const WTF::Vector<WTF::String> & paramValues,const WTF::String & mimeType,bool loadManually)2040 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<WTF::String>& paramNames, const WTF::Vector<WTF::String>& paramValues, const WTF::String& mimeType, bool loadManually)
2041 {
2042 return 0;
2043 }
2044