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 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 141 static WebCore::FrameLoaderClientEfl* _ewk_frame_loader_efl_get(WebCore::Frame* frame) 142 { 143 return static_cast<WebCore::FrameLoaderClientEfl*>(frame->loader()->client()); 144 } 145 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 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 177 static Evas_Object* _ewk_frame_children_iterator_get_container(Eina_Iterator_Ewk_Frame* it) 178 { 179 return it->obj; 180 } 181 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 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 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 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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().string().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 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 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 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 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 */ 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 */ 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 */ 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 */ 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().string().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 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 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