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