1/* 2 Copyright (C) 2011 Samsung Electronics 3 Copyright (C) 2012 Intel Corporation. All rights reserved. 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#include "config.h" 22#include "EwkView.h" 23 24#include "ContextMenuClientEfl.h" 25#include "EflScreenUtilities.h" 26#include "FindClientEfl.h" 27#include "FormClientEfl.h" 28#include "InputMethodContextEfl.h" 29#include "NativeWebKeyboardEvent.h" 30#include "NativeWebMouseEvent.h" 31#include "NativeWebWheelEvent.h" 32#include "PageLoadClientEfl.h" 33#include "PagePolicyClientEfl.h" 34#include "PageUIClientEfl.h" 35#include "PageViewportController.h" 36#include "PageViewportControllerClientEfl.h" 37#include "SnapshotImageGL.h" 38#include "ViewClientEfl.h" 39#include "WKDictionary.h" 40#include "WKGeometry.h" 41#include "WKNumber.h" 42#include "WKPageGroup.h" 43#include "WKPopupItem.h" 44#include "WKString.h" 45#include "WKView.h" 46#include "WKViewEfl.h" 47#include "WebContext.h" 48#include "WebImage.h" 49#include "WebPageGroup.h" 50#include "WebPageProxy.h" 51#include "WebPreferences.h" 52#include "ewk_back_forward_list_private.h" 53#include "ewk_color_picker_private.h" 54#include "ewk_context_menu_item_private.h" 55#include "ewk_context_menu_private.h" 56#include "ewk_context_private.h" 57#include "ewk_favicon_database_private.h" 58#include "ewk_page_group_private.h" 59#include "ewk_popup_menu_item_private.h" 60#include "ewk_popup_menu_private.h" 61#include "ewk_private.h" 62#include "ewk_security_origin_private.h" 63#include "ewk_settings_private.h" 64#include "ewk_view.h" 65#include "ewk_window_features_private.h" 66#include <Ecore_Evas.h> 67#include <Ecore_X.h> 68#include <Edje.h> 69#if USE(ACCELERATED_COMPOSITING) 70#include <Evas_GL.h> 71#endif 72#include <WebCore/CairoUtilitiesEfl.h> 73#include <WebCore/Cursor.h> 74#include <WebCore/PlatformContextCairo.h> 75#include <WebKit2/WKImageCairo.h> 76#include <wtf/MathExtras.h> 77 78#if ENABLE(VIBRATION) 79#include "VibrationClientEfl.h" 80#endif 81 82#if ENABLE(FULLSCREEN_API) 83#include "WebFullScreenManagerProxy.h" 84#endif 85 86using namespace EwkViewCallbacks; 87using namespace WebCore; 88using namespace WebKit; 89 90static const char smartClassName[] = "EWK2_View"; 91static const int defaultCursorSize = 16; 92 93// Auxiliary functions. 94 95static inline void smartDataChanged(Ewk_View_Smart_Data* smartData) 96{ 97 ASSERT(smartData); 98 99 if (smartData->changed.any) 100 return; 101 102 smartData->changed.any = true; 103 evas_object_smart_changed(smartData->self); 104} 105 106static Evas_Smart* defaultSmartClassInstance() 107{ 108 static Ewk_View_Smart_Class api = EWK_VIEW_SMART_CLASS_INIT_NAME_VERSION(smartClassName); 109 static Evas_Smart* smart = 0; 110 111 if (!smart) { 112 EwkView::initSmartClassInterface(api); 113 smart = evas_smart_class_new(&api.sc); 114 } 115 116 return smart; 117} 118 119static inline Ewk_View_Smart_Data* toSmartData(Evas_Object* evasObject) 120{ 121 ASSERT(evasObject); 122 ASSERT(isEwkViewEvasObject(evasObject)); 123 124 return static_cast<Ewk_View_Smart_Data*>(evas_object_smart_data_get(evasObject)); 125} 126 127static inline EwkView* toEwkView(const Ewk_View_Smart_Data* smartData) 128{ 129 ASSERT(smartData); 130 ASSERT(smartData->priv); 131 132 return smartData->priv; 133} 134 135static inline void showEvasObjectsIfNeeded(const Ewk_View_Smart_Data* smartData) 136{ 137 ASSERT(smartData); 138 139 if (evas_object_clipees_get(smartData->base.clipper)) 140 evas_object_show(smartData->base.clipper); 141 evas_object_show(smartData->image); 142} 143 144// EwkViewEventHandler implementation. 145 146template <Evas_Callback_Type EventType> 147class EwkViewEventHandler { 148public: 149 static void subscribe(Evas_Object* evasObject) 150 { 151 evas_object_event_callback_add(evasObject, EventType, handleEvent, toSmartData(evasObject)); 152 } 153 154 static void unsubscribe(Evas_Object* evasObject) 155 { 156 evas_object_event_callback_del(evasObject, EventType, handleEvent); 157 } 158 159 static void handleEvent(void* data, Evas*, Evas_Object*, void* eventInfo); 160}; 161 162template <> 163void EwkViewEventHandler<EVAS_CALLBACK_MOUSE_DOWN>::handleEvent(void* data, Evas*, Evas_Object*, void* eventInfo) 164{ 165 Ewk_View_Smart_Data* smartData = static_cast<Ewk_View_Smart_Data*>(data); 166 if (smartData->api->mouse_down) 167 smartData->api->mouse_down(smartData, static_cast<Evas_Event_Mouse_Down*>(eventInfo)); 168} 169 170template <> 171void EwkViewEventHandler<EVAS_CALLBACK_MOUSE_UP>::handleEvent(void* data, Evas*, Evas_Object*, void* eventInfo) 172{ 173 Ewk_View_Smart_Data* smartData = static_cast<Ewk_View_Smart_Data*>(data); 174 if (smartData->api->mouse_up) 175 smartData->api->mouse_up(smartData, static_cast<Evas_Event_Mouse_Up*>(eventInfo)); 176} 177 178template <> 179void EwkViewEventHandler<EVAS_CALLBACK_MOUSE_MOVE>::handleEvent(void* data, Evas*, Evas_Object*, void* eventInfo) 180{ 181 Ewk_View_Smart_Data* smartData = static_cast<Ewk_View_Smart_Data*>(data); 182 if (smartData->api->mouse_move) 183 smartData->api->mouse_move(smartData, static_cast<Evas_Event_Mouse_Move*>(eventInfo)); 184} 185 186template <> 187void EwkViewEventHandler<EVAS_CALLBACK_FOCUS_IN>::handleEvent(void* data, Evas*, Evas_Object*, void*) 188{ 189 Ewk_View_Smart_Data* smartData = static_cast<Ewk_View_Smart_Data*>(data); 190 if (smartData->api->focus_in) 191 smartData->api->focus_in(smartData); 192} 193 194template <> 195void EwkViewEventHandler<EVAS_CALLBACK_FOCUS_OUT>::handleEvent(void* data, Evas*, Evas_Object*, void*) 196{ 197 Ewk_View_Smart_Data* smartData = static_cast<Ewk_View_Smart_Data*>(data); 198 if (smartData->api->focus_out) 199 smartData->api->focus_out(smartData); 200} 201 202template <> 203void EwkViewEventHandler<EVAS_CALLBACK_MOUSE_WHEEL>::handleEvent(void* data, Evas*, Evas_Object*, void* eventInfo) 204{ 205 Ewk_View_Smart_Data* smartData = static_cast<Ewk_View_Smart_Data*>(data); 206 if (smartData->api->mouse_wheel) 207 smartData->api->mouse_wheel(smartData, static_cast<Evas_Event_Mouse_Wheel*>(eventInfo)); 208} 209 210template <> 211void EwkViewEventHandler<EVAS_CALLBACK_KEY_DOWN>::handleEvent(void* data, Evas*, Evas_Object*, void* eventInfo) 212{ 213 Ewk_View_Smart_Data* smartData = static_cast<Ewk_View_Smart_Data*>(data); 214 if (smartData->api->key_down) 215 smartData->api->key_down(smartData, static_cast<Evas_Event_Key_Down*>(eventInfo)); 216} 217 218template <> 219void EwkViewEventHandler<EVAS_CALLBACK_KEY_UP>::handleEvent(void* data, Evas*, Evas_Object*, void* eventInfo) 220{ 221 Ewk_View_Smart_Data* smartData = static_cast<Ewk_View_Smart_Data*>(data); 222 if (smartData->api->key_up) 223 smartData->api->key_up(smartData, static_cast<Evas_Event_Key_Up*>(eventInfo)); 224} 225 226template <> 227void EwkViewEventHandler<EVAS_CALLBACK_SHOW>::handleEvent(void* data, Evas*, Evas_Object*, void*) 228{ 229 Ewk_View_Smart_Data* smartData = static_cast<Ewk_View_Smart_Data*>(data); 230 WKViewSetIsVisible(toEwkView(smartData)->wkView(), true); 231} 232 233template <> 234void EwkViewEventHandler<EVAS_CALLBACK_HIDE>::handleEvent(void* data, Evas*, Evas_Object*, void*) 235{ 236 Ewk_View_Smart_Data* smartData = static_cast<Ewk_View_Smart_Data*>(data); 237 WKViewSetIsVisible(toEwkView(smartData)->wkView(), false); 238} 239 240typedef HashMap<WKPageRef, Evas_Object*> WKPageToEvasObjectMap; 241 242static inline WKPageToEvasObjectMap& wkPageToEvasObjectMap() 243{ 244 DEFINE_STATIC_LOCAL(WKPageToEvasObjectMap, map, ()); 245 return map; 246} 247 248// EwkView implementation. 249 250EwkView::EwkView(WKViewRef view, Evas_Object* evasObject) 251 : m_webView(view) 252 , m_evasObject(evasObject) 253 , m_context(EwkContext::findOrCreateWrapper(WKPageGetContext(wkPage()))) 254 , m_pageGroup(EwkPageGroup::findOrCreateWrapper(WKPageGetPageGroup(wkPage()))) 255#if USE(ACCELERATED_COMPOSITING) 256 , m_pendingSurfaceResize(false) 257#endif 258 , m_pageLoadClient(PageLoadClientEfl::create(this)) 259 , m_pagePolicyClient(PagePolicyClientEfl::create(this)) 260 , m_pageUIClient(PageUIClientEfl::create(this)) 261 , m_contextMenuClient(ContextMenuClientEfl::create(this)) 262 , m_findClient(FindClientEfl::create(this)) 263 , m_formClient(FormClientEfl::create(this)) 264 , m_viewClient(ViewClientEfl::create(this)) 265#if ENABLE(VIBRATION) 266 , m_vibrationClient(VibrationClientEfl::create(this)) 267#endif 268 , m_backForwardList(EwkBackForwardList::create(WKPageGetBackForwardList(wkPage()))) 269 , m_settings(EwkSettings::create(this)) 270 , m_cursorIdentifier(0) 271 , m_userAgent(WKEinaSharedString(AdoptWK, WKPageCopyUserAgent(wkPage()))) 272 , m_mouseEventsEnabled(false) 273#if ENABLE(TOUCH_EVENTS) 274 , m_touchEventsEnabled(false) 275#endif 276 , m_displayTimer(this, &EwkView::displayTimerFired) 277 , m_inputMethodContext(InputMethodContextEfl::create(this, smartData()->base.evas)) 278#if USE(ACCELERATED_COMPOSITING) 279 , m_pageViewportControllerClient(PageViewportControllerClientEfl::create(this)) 280 , m_pageViewportController(adoptPtr(new PageViewportController(page(), m_pageViewportControllerClient.get()))) 281#endif 282 , m_isAccelerated(true) 283{ 284 ASSERT(m_evasObject); 285 ASSERT(m_context); 286 287 // FIXME: Remove when possible. 288 static_cast<WebViewEfl*>(webView())->setEwkView(this); 289#if USE(ACCELERATED_COMPOSITING) 290 m_evasGL = adoptPtr(evas_gl_new(evas_object_evas_get(m_evasObject))); 291 if (m_evasGL) 292 m_evasGLContext = EvasGLContext::create(m_evasGL.get()); 293 294 if (!m_evasGLContext) { 295 WARN("Failed to create Evas_GL, falling back to software mode."); 296 m_isAccelerated = false; 297 } 298#endif 299 WKViewInitialize(wkView()); 300 301 WKPageGroupRef wkPageGroup = WKPageGetPageGroup(wkPage()); 302 WKPreferencesRef wkPreferences = WKPageGroupGetPreferences(wkPageGroup); 303#if USE(ACCELERATED_COMPOSITING) 304 WKPreferencesSetWebGLEnabled(wkPreferences, true); 305#endif 306 WKPreferencesSetFullScreenEnabled(wkPreferences, true); 307 WKPreferencesSetWebAudioEnabled(wkPreferences, true); 308 WKPreferencesSetOfflineWebApplicationCacheEnabled(wkPreferences, true); 309#if ENABLE(SPELLCHECK) 310 WKPreferencesSetAsynchronousSpellCheckingEnabled(wkPreferences, true); 311#endif 312 WKPreferencesSetInteractiveFormValidationEnabled(wkPreferences, true); 313 314 // Enable mouse events by default 315 setMouseEventsEnabled(true); 316 317 // Listen for favicon changes. 318 EwkFaviconDatabase* iconDatabase = m_context->faviconDatabase(); 319 ASSERT(iconDatabase); 320 321 iconDatabase->watchChanges(IconChangeCallbackData(EwkView::handleFaviconChanged, this)); 322 323 WKPageToEvasObjectMap::AddResult result = wkPageToEvasObjectMap().add(wkPage(), m_evasObject); 324 ASSERT_UNUSED(result, result.isNewEntry); 325} 326 327EwkView::~EwkView() 328{ 329 // Unregister icon change callback. 330 EwkFaviconDatabase* iconDatabase = m_context->faviconDatabase(); 331 ASSERT(iconDatabase); 332 333 iconDatabase->unwatchChanges(EwkView::handleFaviconChanged); 334 335 ASSERT(wkPageToEvasObjectMap().get(wkPage()) == m_evasObject); 336 wkPageToEvasObjectMap().remove(wkPage()); 337} 338 339EwkView* EwkView::create(WKViewRef webView, Evas* canvas, Evas_Smart* smart) 340{ 341 EINA_SAFETY_ON_NULL_RETURN_VAL(canvas, 0); 342 343 Evas_Object* evasObject = evas_object_smart_add(canvas, smart ? smart : defaultSmartClassInstance()); 344 EINA_SAFETY_ON_NULL_RETURN_VAL(evasObject, 0); 345 346 Ewk_View_Smart_Data* smartData = toSmartData(evasObject); 347 if (!smartData) { 348 evas_object_del(evasObject); 349 return 0; 350 } 351 352 ASSERT(!smartData->priv); 353 354 smartData->priv = new EwkView(webView, evasObject); 355 356 return smartData->priv; 357} 358 359bool EwkView::initSmartClassInterface(Ewk_View_Smart_Class& api) 360{ 361 if (api.version != EWK_VIEW_SMART_CLASS_VERSION) { 362 EINA_LOG_CRIT("Ewk_View_Smart_Class %p is version %lu while %lu was expected.", 363 &api, api.version, EWK_VIEW_SMART_CLASS_VERSION); 364 return false; 365 } 366 367 if (!parentSmartClass.add) 368 evas_object_smart_clipped_smart_set(&parentSmartClass); 369 370 evas_object_smart_clipped_smart_set(&api.sc); 371 372 // Set Evas_Smart_Class callbacks. 373 api.sc.add = handleEvasObjectAdd; 374 api.sc.del = handleEvasObjectDelete; 375 api.sc.move = handleEvasObjectMove; 376 api.sc.resize = handleEvasObjectResize; 377 api.sc.show = handleEvasObjectShow; 378 api.sc.hide = handleEvasObjectHide; 379 api.sc.color_set = handleEvasObjectColorSet; 380 api.sc.calculate = handleEvasObjectCalculate; 381 api.sc.data = smartClassName; // It is used for type checking. 382 383 // Set Ewk_View_Smart_Class callbacks. 384 api.focus_in = handleEwkViewFocusIn; 385 api.focus_out = handleEwkViewFocusOut; 386 api.mouse_wheel = handleEwkViewMouseWheel; 387 api.mouse_down = handleEwkViewMouseDown; 388 api.mouse_up = handleEwkViewMouseUp; 389 api.mouse_move = handleEwkViewMouseMove; 390 api.key_down = handleEwkViewKeyDown; 391 api.key_up = handleEwkViewKeyUp; 392 393 return true; 394} 395 396Evas_Object* EwkView::toEvasObject(WKPageRef page) 397{ 398 ASSERT(page); 399 return wkPageToEvasObjectMap().get(page); 400} 401 402WKPageRef EwkView::wkPage() const 403{ 404 return WKViewGetPage(wkView()); 405} 406 407void EwkView::setCursor(const Cursor& cursor) 408{ 409 if (cursor.image()) { 410 // Custom cursor. 411 if (cursor.image() == m_cursorIdentifier) 412 return; 413 414 m_cursorIdentifier = cursor.image(); 415 416 Ewk_View_Smart_Data* sd = smartData(); 417 RefPtr<Evas_Object> cursorObject = adoptRef(cursor.image()->getEvasObject(sd->base.evas)); 418 if (!cursorObject) 419 return; 420 421 // Resize cursor. 422 evas_object_resize(cursorObject.get(), cursor.image()->size().width(), cursor.image()->size().height()); 423 424 // Get cursor hot spot. 425 IntPoint hotSpot; 426 cursor.image()->getHotSpot(hotSpot); 427 428 Ecore_Evas* ecoreEvas = ecore_evas_ecore_evas_get(sd->base.evas); 429 // ecore_evas takes care of freeing the cursor object. 430 ecore_evas_object_cursor_set(ecoreEvas, cursorObject.release().leakRef(), EVAS_LAYER_MAX, hotSpot.x(), hotSpot.y()); 431 432 return; 433 } 434 435 // Standard cursor. 436 const char* group = cursor.platformCursor(); 437 if (!group || group == m_cursorIdentifier) 438 return; 439 440 m_cursorIdentifier = group; 441 Ewk_View_Smart_Data* sd = smartData(); 442 RefPtr<Evas_Object> cursorObject = adoptRef(edje_object_add(sd->base.evas)); 443 444 Ecore_Evas* ecoreEvas = ecore_evas_ecore_evas_get(sd->base.evas); 445 if (!m_theme || !edje_object_file_set(cursorObject.get(), m_theme, group)) { 446 ecore_evas_object_cursor_set(ecoreEvas, 0, 0, 0, 0); 447#ifdef HAVE_ECORE_X 448 if (WebCore::isUsingEcoreX(sd->base.evas)) 449 WebCore::applyFallbackCursor(ecoreEvas, group); 450#endif 451 return; 452 } 453 454 // Set cursor size. 455 Evas_Coord width, height; 456 edje_object_size_min_get(cursorObject.get(), &width, &height); 457 if (width <= 0 || height <= 0) 458 edje_object_size_min_calc(cursorObject.get(), &width, &height); 459 if (width <= 0 || height <= 0) { 460 width = defaultCursorSize; 461 height = defaultCursorSize; 462 } 463 evas_object_resize(cursorObject.get(), width, height); 464 465 // Get cursor hot spot. 466 const char* data; 467 int hotspotX = 0; 468 data = edje_object_data_get(cursorObject.get(), "hot.x"); 469 if (data) 470 hotspotX = atoi(data); 471 472 int hotspotY = 0; 473 data = edje_object_data_get(cursorObject.get(), "hot.y"); 474 if (data) 475 hotspotY = atoi(data); 476 477 // ecore_evas takes care of freeing the cursor object. 478 ecore_evas_object_cursor_set(ecoreEvas, cursorObject.release().leakRef(), EVAS_LAYER_MAX, hotspotX, hotspotY); 479} 480 481void EwkView::setDeviceScaleFactor(float scale) 482{ 483 const WKSize& deviceSize = WKViewGetSize(wkView()); 484 WKPageSetCustomBackingScaleFactor(wkPage(), scale); 485 486 // Update internal viewport size after device-scale change. 487 WKViewSetSize(wkView(), deviceSize); 488} 489 490float EwkView::deviceScaleFactor() const 491{ 492 return WKPageGetBackingScaleFactor(wkPage()); 493} 494 495AffineTransform EwkView::transformToScreen() const 496{ 497 AffineTransform transform; 498 499 int windowGlobalX = 0; 500 int windowGlobalY = 0; 501 502 Ewk_View_Smart_Data* sd = smartData(); 503 504#ifdef HAVE_ECORE_X 505 Ecore_Evas* ecoreEvas = ecore_evas_ecore_evas_get(sd->base.evas); 506 507 Ecore_X_Window window; 508 window = ecore_evas_gl_x11_window_get(ecoreEvas); 509 // Fallback to software mode if necessary. 510 if (!window) 511 window = ecore_evas_software_x11_window_get(ecoreEvas); // Returns 0 if none. 512 513 int x, y; // x, y are relative to parent (in a reparenting window manager). 514 while (window) { 515 ecore_x_window_geometry_get(window, &x, &y, 0, 0); 516 windowGlobalX += x; 517 windowGlobalY += y; 518 window = ecore_x_window_parent_get(window); 519 } 520#endif 521 522 transform.translate(-sd->view.x, -sd->view.y); 523 transform.translate(windowGlobalX, windowGlobalY); 524 525 return transform; 526} 527 528inline Ewk_View_Smart_Data* EwkView::smartData() const 529{ 530 return toSmartData(m_evasObject); 531} 532 533inline IntSize EwkView::size() const 534{ 535 // WebPage expects a size in UI units, and not raw device units. 536 FloatSize uiSize = deviceSize(); 537 uiSize.scale(1 / deviceScaleFactor()); 538 return roundedIntSize(uiSize); 539} 540 541inline IntSize EwkView::deviceSize() const 542{ 543 return toIntSize(WKViewGetSize(wkView())); 544} 545 546void EwkView::displayTimerFired(Timer<EwkView>*) 547{ 548 Ewk_View_Smart_Data* sd = smartData(); 549 550#if USE(ACCELERATED_COMPOSITING) 551 if (m_pendingSurfaceResize) { 552 // Create a GL surface here so that Evas has no chance of painting to an empty GL surface. 553 if (!createGLSurface()) 554 return; 555 // Make Evas objects visible here in order not to paint empty Evas objects with black color. 556 showEvasObjectsIfNeeded(sd); 557 558 m_pendingSurfaceResize = false; 559 } 560#endif 561 562 if (!m_isAccelerated) { 563 RefPtr<cairo_surface_t> surface = createSurfaceForImage(sd->image); 564 if (!surface) 565 return; 566 567 WKViewPaintToCairoSurface(wkView(), surface.get()); 568 evas_object_image_data_update_add(sd->image, 0, 0, sd->view.w, sd->view.h); 569 return; 570 } 571#if USE(ACCELERATED_COMPOSITING) 572 evas_gl_make_current(m_evasGL.get(), m_evasGLSurface->surface(), m_evasGLContext->context()); 573 574 WKViewPaintToCurrentGLContext(wkView()); 575#endif 576 // sd->image is tied to a native surface, which is in the parent's coordinates. 577 evas_object_image_data_update_add(sd->image, sd->view.x, sd->view.y, sd->view.w, sd->view.h); 578} 579 580void EwkView::scheduleUpdateDisplay() 581{ 582 if (deviceSize().isEmpty()) 583 return; 584 585 if (!m_displayTimer.isActive()) 586 m_displayTimer.startOneShot(0); 587} 588 589#if ENABLE(FULLSCREEN_API) 590/** 591 * @internal 592 * Calls fullscreen_enter callback or falls back to default behavior and enables fullscreen mode. 593 */ 594void EwkView::enterFullScreen() 595{ 596 Ewk_View_Smart_Data* sd = smartData(); 597 598 RefPtr<EwkSecurityOrigin> origin = EwkSecurityOrigin::create(m_url); 599 600 if (!sd->api->fullscreen_enter || !sd->api->fullscreen_enter(sd, origin.get())) { 601 Ecore_Evas* ecoreEvas = ecore_evas_ecore_evas_get(sd->base.evas); 602 ecore_evas_fullscreen_set(ecoreEvas, true); 603 } 604} 605 606/** 607 * @internal 608 * Calls fullscreen_exit callback or falls back to default behavior and disables fullscreen mode. 609 */ 610void EwkView::exitFullScreen() 611{ 612 Ewk_View_Smart_Data* sd = smartData(); 613 614 if (!sd->api->fullscreen_exit || !sd->api->fullscreen_exit(sd)) { 615 Ecore_Evas* ecoreEvas = ecore_evas_ecore_evas_get(sd->base.evas); 616 ecore_evas_fullscreen_set(ecoreEvas, false); 617 } 618} 619#endif 620 621WKRect EwkView::windowGeometry() const 622{ 623 Evas_Coord x, y, width, height; 624 Ewk_View_Smart_Data* sd = smartData(); 625 626 if (!sd->api->window_geometry_get || !sd->api->window_geometry_get(sd, &x, &y, &width, &height)) { 627 Ecore_Evas* ee = ecore_evas_ecore_evas_get(sd->base.evas); 628 ecore_evas_request_geometry_get(ee, &x, &y, &width, &height); 629 } 630 631 return WKRectMake(x, y, width, height); 632} 633 634void EwkView::setWindowGeometry(const WKRect& rect) 635{ 636 Ewk_View_Smart_Data* sd = smartData(); 637 638 if (!sd->api->window_geometry_set || !sd->api->window_geometry_set(sd, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height)) { 639 Ecore_Evas* ee = ecore_evas_ecore_evas_get(sd->base.evas); 640 ecore_evas_move_resize(ee, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height); 641 } 642} 643 644const char* EwkView::title() const 645{ 646 m_title = WKEinaSharedString(AdoptWK, WKPageCopyTitle(wkPage())); 647 648 return m_title; 649} 650 651/** 652 * @internal 653 * This function may return @c NULL. 654 */ 655InputMethodContextEfl* EwkView::inputMethodContext() 656{ 657 return m_inputMethodContext.get(); 658} 659 660const char* EwkView::themePath() const 661{ 662 return m_theme; 663} 664 665void EwkView::setThemePath(const char* theme) 666{ 667 if (m_theme != theme) { 668 m_theme = theme; 669 WKRetainPtr<WKStringRef> wkTheme = adoptWK(WKStringCreateWithUTF8CString(theme)); 670 WKViewSetThemePath(wkView(), wkTheme.get()); 671 } 672} 673 674void EwkView::setCustomTextEncodingName(const char* customEncoding) 675{ 676 if (m_customEncoding == customEncoding) 677 return; 678 679 m_customEncoding = customEncoding; 680 WKRetainPtr<WKStringRef> wkCustomEncoding = adoptWK(WKStringCreateWithUTF8CString(customEncoding)); 681 WKPageSetCustomTextEncodingName(wkPage(), wkCustomEncoding.get()); 682} 683 684void EwkView::setUserAgent(const char* userAgent) 685{ 686 if (m_userAgent == userAgent) 687 return; 688 689 WKRetainPtr<WKStringRef> wkUserAgent = adoptWK(WKStringCreateWithUTF8CString(userAgent)); 690 WKPageSetCustomUserAgent(wkPage(), wkUserAgent.get()); 691 692 // When 'userAgent' is 0, user agent is set as a standard user agent by WKPageSetCustomUserAgent() 693 // so m_userAgent needs to be updated using WKPageCopyUserAgent(). 694 m_userAgent = WKEinaSharedString(AdoptWK, WKPageCopyUserAgent(wkPage())); 695} 696 697void EwkView::setMouseEventsEnabled(bool enabled) 698{ 699 if (m_mouseEventsEnabled == enabled) 700 return; 701 702 m_mouseEventsEnabled = enabled; 703 if (enabled) { 704 EwkViewEventHandler<EVAS_CALLBACK_MOUSE_DOWN>::subscribe(m_evasObject); 705 EwkViewEventHandler<EVAS_CALLBACK_MOUSE_UP>::subscribe(m_evasObject); 706 EwkViewEventHandler<EVAS_CALLBACK_MOUSE_MOVE>::subscribe(m_evasObject); 707 } else { 708 EwkViewEventHandler<EVAS_CALLBACK_MOUSE_DOWN>::unsubscribe(m_evasObject); 709 EwkViewEventHandler<EVAS_CALLBACK_MOUSE_UP>::unsubscribe(m_evasObject); 710 EwkViewEventHandler<EVAS_CALLBACK_MOUSE_MOVE>::unsubscribe(m_evasObject); 711 } 712} 713 714#if ENABLE(TOUCH_EVENTS) 715void EwkView::feedTouchEvent(Ewk_Touch_Event_Type type, const Eina_List* points, const Evas_Modifier* modifiers) 716{ 717 page()->handleTouchEvent(NativeWebTouchEvent(type, points, modifiers, webView()->transformFromScene(), transformToScreen(), ecore_time_get())); 718} 719 720void EwkView::setTouchEventsEnabled(bool enabled) 721{ 722 if (m_touchEventsEnabled == enabled) 723 return; 724 725 m_touchEventsEnabled = enabled; 726 727 if (enabled) { 728 // FIXME: We have to connect touch callbacks with mouse and multi events 729 // because the Evas creates mouse events for first touch and multi events 730 // for second and third touches. Below codes should be fixed when the Evas 731 // supports the touch events. 732 // See https://bugs.webkit.org/show_bug.cgi?id=97785 for details. 733 Ewk_View_Smart_Data* sd = smartData(); 734 evas_object_event_callback_add(m_evasObject, EVAS_CALLBACK_MOUSE_DOWN, handleTouchDown, sd); 735 evas_object_event_callback_add(m_evasObject, EVAS_CALLBACK_MOUSE_UP, handleTouchUp, sd); 736 evas_object_event_callback_add(m_evasObject, EVAS_CALLBACK_MOUSE_MOVE, handleTouchMove, sd); 737 evas_object_event_callback_add(m_evasObject, EVAS_CALLBACK_MULTI_DOWN, handleTouchDown, sd); 738 evas_object_event_callback_add(m_evasObject, EVAS_CALLBACK_MULTI_UP, handleTouchUp, sd); 739 evas_object_event_callback_add(m_evasObject, EVAS_CALLBACK_MULTI_MOVE, handleTouchMove, sd); 740 } else { 741 evas_object_event_callback_del(m_evasObject, EVAS_CALLBACK_MOUSE_DOWN, handleTouchDown); 742 evas_object_event_callback_del(m_evasObject, EVAS_CALLBACK_MOUSE_UP, handleTouchUp); 743 evas_object_event_callback_del(m_evasObject, EVAS_CALLBACK_MOUSE_MOVE, handleTouchMove); 744 evas_object_event_callback_del(m_evasObject, EVAS_CALLBACK_MULTI_DOWN, handleTouchDown); 745 evas_object_event_callback_del(m_evasObject, EVAS_CALLBACK_MULTI_UP, handleTouchUp); 746 evas_object_event_callback_del(m_evasObject, EVAS_CALLBACK_MULTI_MOVE, handleTouchMove); 747 } 748} 749#endif 750 751#if USE(ACCELERATED_COMPOSITING) 752bool EwkView::createGLSurface() 753{ 754 if (!m_isAccelerated) 755 return true; 756 757 static Evas_GL_Config evasGLConfig = { 758 EVAS_GL_RGBA_8888, 759 EVAS_GL_DEPTH_BIT_8, 760 EVAS_GL_STENCIL_NONE, 761 EVAS_GL_OPTIONS_NONE, 762 EVAS_GL_MULTISAMPLE_NONE 763 }; 764 765 // Recreate to current size: Replaces if non-null, and frees existing surface after (OwnPtr). 766 m_evasGLSurface = EvasGLSurface::create(m_evasGL.get(), &evasGLConfig, deviceSize()); 767 if (!m_evasGLSurface) 768 return false; 769 770 Evas_Native_Surface nativeSurface; 771 evas_gl_native_surface_get(m_evasGL.get(), m_evasGLSurface->surface(), &nativeSurface); 772 evas_object_image_native_surface_set(smartData()->image, &nativeSurface); 773 774 evas_gl_make_current(m_evasGL.get(), m_evasGLSurface->surface(), m_evasGLContext->context()); 775 776 Evas_GL_API* gl = evas_gl_api_get(m_evasGL.get()); 777 778 WKPoint boundsEnd = WKViewUserViewportToScene(wkView(), WKPointMake(deviceSize().width(), deviceSize().height())); 779 gl->glViewport(0, 0, boundsEnd.x, boundsEnd.y); 780 gl->glClearColor(1.0, 1.0, 1.0, 0); 781 gl->glClear(GL_COLOR_BUFFER_BIT); 782 783 return true; 784} 785#endif 786 787#if ENABLE(INPUT_TYPE_COLOR) 788/** 789 * @internal 790 * Requests to show external color picker. 791 */ 792void EwkView::requestColorPicker(WKColorPickerResultListenerRef listener, const WebCore::Color& color) 793{ 794 Ewk_View_Smart_Data* sd = smartData(); 795 EINA_SAFETY_ON_NULL_RETURN(sd->api->input_picker_color_request); 796 797 if (!sd->api->input_picker_color_request) 798 return; 799 800 if (m_colorPicker) 801 dismissColorPicker(); 802 803 m_colorPicker = EwkColorPicker::create(listener, color); 804 805 sd->api->input_picker_color_request(sd, m_colorPicker.get()); 806} 807 808/** 809 * @internal 810 * Requests to hide external color picker. 811 */ 812void EwkView::dismissColorPicker() 813{ 814 if (!m_colorPicker) 815 return; 816 817 Ewk_View_Smart_Data* sd = smartData(); 818 EINA_SAFETY_ON_NULL_RETURN(sd->api->input_picker_color_dismiss); 819 820 if (sd->api->input_picker_color_dismiss) 821 sd->api->input_picker_color_dismiss(sd); 822 823 m_colorPicker.clear(); 824} 825#endif 826 827COMPILE_ASSERT_MATCHING_ENUM(EWK_TEXT_DIRECTION_RIGHT_TO_LEFT, RTL); 828COMPILE_ASSERT_MATCHING_ENUM(EWK_TEXT_DIRECTION_LEFT_TO_RIGHT, LTR); 829 830void EwkView::customContextMenuItemSelected(WKContextMenuItemRef contextMenuItem) 831{ 832 Ewk_View_Smart_Data* sd = smartData(); 833 ASSERT(sd->api); 834 835 if (!sd->api->custom_item_selected) 836 return; 837 838 OwnPtr<EwkContextMenuItem> item = EwkContextMenuItem::create(contextMenuItem, 0); 839 840 sd->api->custom_item_selected(sd, item.get()); 841} 842 843void EwkView::showContextMenu(WKPoint position, WKArrayRef items) 844{ 845 Ewk_View_Smart_Data* sd = smartData(); 846 ASSERT(sd->api); 847 848 if (!sd->api->context_menu_show) 849 return; 850 851 if (m_contextMenu) 852 hideContextMenu(); 853 854 m_contextMenu = EwkContextMenu::create(this, items); 855 856 position = WKViewContentsToUserViewport(wkView(), position); 857 858 sd->api->context_menu_show(sd, position.x, position.y, m_contextMenu.get()); 859} 860 861void EwkView::hideContextMenu() 862{ 863 if (!m_contextMenu) 864 return; 865 866 Ewk_View_Smart_Data* sd = smartData(); 867 ASSERT(sd->api); 868 869 if (sd->api->context_menu_hide) 870 sd->api->context_menu_hide(sd); 871 872 m_contextMenu.clear(); 873} 874 875COMPILE_ASSERT_MATCHING_ENUM(EWK_TEXT_DIRECTION_RIGHT_TO_LEFT, kWKPopupItemTextDirectionRTL); 876COMPILE_ASSERT_MATCHING_ENUM(EWK_TEXT_DIRECTION_LEFT_TO_RIGHT, kWKPopupItemTextDirectionLTR); 877 878void EwkView::requestPopupMenu(WKPopupMenuListenerRef popupMenuListener, const WKRect& rect, WKPopupItemTextDirection textDirection, double pageScaleFactor, WKArrayRef items, int32_t selectedIndex) 879{ 880 Ewk_View_Smart_Data* sd = smartData(); 881 ASSERT(sd->api); 882 883 ASSERT(popupMenuListener); 884 885 if (!sd->api->popup_menu_show) 886 return; 887 888 if (m_popupMenu) 889 closePopupMenu(); 890 891 m_popupMenu = EwkPopupMenu::create(this, popupMenuListener, items, selectedIndex); 892 893 WKPoint popupMenuPosition = WKViewContentsToUserViewport(wkView(), rect.origin); 894 895 Eina_Rectangle einaRect; 896 EINA_RECTANGLE_SET(&einaRect, popupMenuPosition.x, popupMenuPosition.y, rect.size.width, rect.size.height); 897 898 sd->api->popup_menu_show(sd, einaRect, static_cast<Ewk_Text_Direction>(textDirection), pageScaleFactor, m_popupMenu.get()); 899} 900 901void EwkView::closePopupMenu() 902{ 903 if (!m_popupMenu) 904 return; 905 906 Ewk_View_Smart_Data* sd = smartData(); 907 ASSERT(sd->api); 908 909 if (sd->api->popup_menu_hide) 910 sd->api->popup_menu_hide(sd); 911 912 m_popupMenu.clear(); 913} 914 915/** 916 * @internal 917 * Calls a smart member function for javascript alert(). 918 */ 919void EwkView::requestJSAlertPopup(const WKEinaSharedString& message) 920{ 921 Ewk_View_Smart_Data* sd = smartData(); 922 ASSERT(sd->api); 923 924 if (!sd->api->run_javascript_alert) 925 return; 926 927 sd->api->run_javascript_alert(sd, message); 928} 929 930/** 931 * @internal 932 * Calls a smart member function for javascript confirm() and returns a value from the function. Returns false by default. 933 */ 934bool EwkView::requestJSConfirmPopup(const WKEinaSharedString& message) 935{ 936 Ewk_View_Smart_Data* sd = smartData(); 937 ASSERT(sd->api); 938 939 if (!sd->api->run_javascript_confirm) 940 return false; 941 942 return sd->api->run_javascript_confirm(sd, message); 943} 944 945/** 946 * @internal 947 * Calls a smart member function for javascript prompt() and returns a value from the function. Returns null string by default. 948 */ 949WKEinaSharedString EwkView::requestJSPromptPopup(const WKEinaSharedString& message, const WKEinaSharedString& defaultValue) 950{ 951 Ewk_View_Smart_Data* sd = smartData(); 952 ASSERT(sd->api); 953 954 if (!sd->api->run_javascript_prompt) 955 return WKEinaSharedString(); 956 957 return WKEinaSharedString::adopt(sd->api->run_javascript_prompt(sd, message, defaultValue)); 958} 959 960#if ENABLE(SQL_DATABASE) 961/** 962 * @internal 963 * Calls exceeded_database_quota callback or falls back to default behavior returns default database quota. 964 */ 965unsigned long long EwkView::informDatabaseQuotaReached(const String& databaseName, const String& displayName, unsigned long long currentQuota, unsigned long long currentOriginUsage, unsigned long long currentDatabaseUsage, unsigned long long expectedUsage) 966{ 967 Ewk_View_Smart_Data* sd = smartData(); 968 ASSERT(sd->api); 969 970 static const unsigned long long defaultQuota = 5 * 1024 * 1204; // 5 MB 971 if (sd->api->exceeded_database_quota) 972 return sd->api->exceeded_database_quota(sd, databaseName.utf8().data(), displayName.utf8().data(), currentQuota, currentOriginUsage, currentDatabaseUsage, expectedUsage); 973 974 return defaultQuota; 975} 976#endif 977 978WebView* EwkView::webView() 979{ 980 return toImpl(m_webView.get()); 981} 982 983/** 984 * @internal 985 * The url of view was changed by the frame loader. 986 * 987 * Emits signal: "url,changed" with pointer to new url string. 988 */ 989void EwkView::informURLChange() 990{ 991 WKRetainPtr<WKURLRef> wkActiveURL = adoptWK(WKPageCopyActiveURL(wkPage())); 992 WKRetainPtr<WKStringRef> wkURLString = wkActiveURL ? adoptWK(WKURLCopyString(wkActiveURL.get())) : adoptWK(WKStringCreateWithUTF8CString("")); 993 994 if (WKStringIsEqualToUTF8CString(wkURLString.get(), m_url)) 995 return; 996 997 m_url = WKEinaSharedString(wkURLString.get()); 998 smartCallback<URLChanged>().call(m_url); 999 1000 // Update the view's favicon. 1001 smartCallback<FaviconChanged>().call(); 1002} 1003 1004Evas_Object* EwkView::createFavicon() const 1005{ 1006 EwkFaviconDatabase* iconDatabase = m_context->faviconDatabase(); 1007 ASSERT(iconDatabase); 1008 1009 return ewk_favicon_database_icon_get(iconDatabase, m_url, smartData()->base.evas); 1010} 1011 1012EwkWindowFeatures* EwkView::windowFeatures() 1013{ 1014 if (!m_windowFeatures) 1015 m_windowFeatures = EwkWindowFeatures::create(0, this); 1016 1017 return m_windowFeatures.get(); 1018} 1019 1020WKPageRef EwkView::createNewPage(PassRefPtr<EwkUrlRequest> request, WKDictionaryRef windowFeatures) 1021{ 1022 Ewk_View_Smart_Data* sd = smartData(); 1023 ASSERT(sd->api); 1024 1025 if (!sd->api->window_create) 1026 return 0; 1027 1028 RefPtr<EwkWindowFeatures> ewkWindowFeatures = EwkWindowFeatures::create(windowFeatures, this); 1029 1030 Evas_Object* newEwkView = sd->api->window_create(sd, request->url(), ewkWindowFeatures.get()); 1031 if (!newEwkView) 1032 return 0; 1033 1034 EwkView* newViewImpl = toEwkView(newEwkView); 1035 ASSERT(newViewImpl); 1036 1037 newViewImpl->m_windowFeatures = ewkWindowFeatures; 1038 1039 return static_cast<WKPageRef>(WKRetain(newViewImpl->page())); 1040} 1041 1042void EwkView::close() 1043{ 1044 Ewk_View_Smart_Data* sd = smartData(); 1045 ASSERT(sd->api); 1046 1047 if (!sd->api->window_close) 1048 return; 1049 1050 sd->api->window_close(sd); 1051} 1052 1053void EwkView::handleEvasObjectAdd(Evas_Object* evasObject) 1054{ 1055 const Evas_Smart* smart = evas_object_smart_smart_get(evasObject); 1056 const Evas_Smart_Class* smartClass = evas_smart_class_get(smart); 1057 const Ewk_View_Smart_Class* api = reinterpret_cast<const Ewk_View_Smart_Class*>(smartClass); 1058 ASSERT(api); 1059 1060 Ewk_View_Smart_Data* smartData = toSmartData(evasObject); 1061 1062 if (!smartData) { 1063 // Allocating with 'calloc' as the API contract is that it should be deleted with 'free()'. 1064 smartData = static_cast<Ewk_View_Smart_Data*>(calloc(1, sizeof(Ewk_View_Smart_Data))); 1065 evas_object_smart_data_set(evasObject, smartData); 1066 } 1067 1068 smartData->self = evasObject; 1069 smartData->api = api; 1070 1071 parentSmartClass.add(evasObject); 1072 1073 smartData->priv = 0; // Will be initialized further. 1074 1075 // Create evas_object_image to draw web contents. 1076 smartData->image = evas_object_image_add(smartData->base.evas); 1077 evas_object_image_alpha_set(smartData->image, false); 1078 evas_object_image_filled_set(smartData->image, true); 1079 evas_object_smart_member_add(smartData->image, evasObject); 1080 evas_object_show(smartData->image); 1081 1082 EwkViewEventHandler<EVAS_CALLBACK_FOCUS_IN>::subscribe(evasObject); 1083 EwkViewEventHandler<EVAS_CALLBACK_FOCUS_OUT>::subscribe(evasObject); 1084 EwkViewEventHandler<EVAS_CALLBACK_MOUSE_WHEEL>::subscribe(evasObject); 1085 EwkViewEventHandler<EVAS_CALLBACK_KEY_DOWN>::subscribe(evasObject); 1086 EwkViewEventHandler<EVAS_CALLBACK_KEY_UP>::subscribe(evasObject); 1087 EwkViewEventHandler<EVAS_CALLBACK_SHOW>::subscribe(evasObject); 1088 EwkViewEventHandler<EVAS_CALLBACK_HIDE>::subscribe(evasObject); 1089} 1090 1091void EwkView::handleEvasObjectDelete(Evas_Object* evasObject) 1092{ 1093 Ewk_View_Smart_Data* smartData = toSmartData(evasObject); 1094 if (smartData) { 1095 ASSERT(smartData->priv); // smartData->priv is EwkView instance. 1096 delete smartData->priv; 1097 } 1098 1099 parentSmartClass.del(evasObject); 1100} 1101 1102void EwkView::handleEvasObjectResize(Evas_Object* evasObject, Evas_Coord width, Evas_Coord height) 1103{ 1104 Ewk_View_Smart_Data* smartData = toSmartData(evasObject); 1105 ASSERT(smartData); 1106 1107 evas_object_resize(smartData->image, width, height); 1108 evas_object_image_size_set(smartData->image, width, height); 1109 evas_object_image_fill_set(smartData->image, 0, 0, width, height); 1110 1111 smartData->changed.size = true; 1112 smartDataChanged(smartData); 1113} 1114 1115void EwkView::handleEvasObjectMove(Evas_Object* evasObject, Evas_Coord /*x*/, Evas_Coord /*y*/) 1116{ 1117 Ewk_View_Smart_Data* smartData = toSmartData(evasObject); 1118 ASSERT(smartData); 1119 1120 smartData->changed.position = true; 1121 smartDataChanged(smartData); 1122} 1123 1124void EwkView::handleEvasObjectCalculate(Evas_Object* evasObject) 1125{ 1126 Ewk_View_Smart_Data* smartData = toSmartData(evasObject); 1127 ASSERT(smartData); 1128 1129 EwkView* self = toEwkView(smartData); 1130 1131 smartData->changed.any = false; 1132 1133 Evas_Coord x, y, width, height; 1134 evas_object_geometry_get(evasObject, &x, &y, &width, &height); 1135 1136 if (smartData->changed.position) { 1137 smartData->changed.position = false; 1138 smartData->view.x = x; 1139 smartData->view.y = y; 1140 evas_object_move(smartData->image, x, y); 1141 WKViewSetUserViewportTranslation(self->wkView(), x, y); 1142 } 1143 1144 if (smartData->changed.size) { 1145 smartData->changed.size = false; 1146 smartData->view.w = width; 1147 smartData->view.h = height; 1148 1149 WKViewSetSize(self->wkView(), WKSizeMake(width, height)); 1150#if USE(ACCELERATED_COMPOSITING) 1151 if (WKPageUseFixedLayout(self->wkPage())) 1152 self->pageViewportController()->didChangeViewportSize(self->size()); 1153 1154 self->setNeedsSurfaceResize(); 1155#endif 1156 } 1157} 1158 1159void EwkView::handleEvasObjectShow(Evas_Object* evasObject) 1160{ 1161 Ewk_View_Smart_Data* smartData = toSmartData(evasObject); 1162 ASSERT(smartData); 1163 1164 if (!toEwkView(smartData)->m_isAccelerated) 1165 showEvasObjectsIfNeeded(smartData); 1166} 1167 1168void EwkView::handleEvasObjectHide(Evas_Object* evasObject) 1169{ 1170 Ewk_View_Smart_Data* smartData = toSmartData(evasObject); 1171 ASSERT(smartData); 1172 1173 evas_object_hide(smartData->base.clipper); 1174 evas_object_hide(smartData->image); 1175} 1176 1177void EwkView::handleEvasObjectColorSet(Evas_Object* evasObject, int red, int green, int blue, int alpha) 1178{ 1179 Ewk_View_Smart_Data* smartData = toSmartData(evasObject); 1180 ASSERT(smartData); 1181 1182 EwkView* view = toEwkView(smartData); 1183 ASSERT(view); 1184 1185 alpha = clampTo(alpha, 0, 255); 1186 red = clampTo(red, 0, alpha); 1187 green = clampTo(green, 0, alpha); 1188 blue = clampTo(blue, 0, alpha); 1189 1190 evas_object_image_alpha_set(smartData->image, alpha < 255); 1191 WKViewSetDrawsBackground(view->wkView(), red || green || blue); 1192 WKViewSetDrawsTransparentBackground(view->wkView(), alpha < 255); 1193 1194 parentSmartClass.color_set(evasObject, red, green, blue, alpha); 1195} 1196 1197Eina_Bool EwkView::handleEwkViewFocusIn(Ewk_View_Smart_Data* smartData) 1198{ 1199 WKViewSetIsFocused(toEwkView(smartData)->wkView(), true); 1200 return true; 1201} 1202 1203Eina_Bool EwkView::handleEwkViewFocusOut(Ewk_View_Smart_Data* smartData) 1204{ 1205 WKViewSetIsFocused(toEwkView(smartData)->wkView(), false); 1206 return true; 1207} 1208 1209Eina_Bool EwkView::handleEwkViewMouseWheel(Ewk_View_Smart_Data* smartData, const Evas_Event_Mouse_Wheel* wheelEvent) 1210{ 1211 EwkView* self = toEwkView(smartData); 1212 self->page()->handleWheelEvent(NativeWebWheelEvent(wheelEvent, self->webView()->transformFromScene(), self->transformToScreen())); 1213 return true; 1214} 1215 1216Eina_Bool EwkView::handleEwkViewMouseDown(Ewk_View_Smart_Data* smartData, const Evas_Event_Mouse_Down* downEvent) 1217{ 1218 EwkView* self = toEwkView(smartData); 1219 self->page()->handleMouseEvent(NativeWebMouseEvent(downEvent, self->webView()->transformFromScene(), self->transformToScreen())); 1220 return true; 1221} 1222 1223Eina_Bool EwkView::handleEwkViewMouseUp(Ewk_View_Smart_Data* smartData, const Evas_Event_Mouse_Up* upEvent) 1224{ 1225 EwkView* self = toEwkView(smartData); 1226 self->page()->handleMouseEvent(NativeWebMouseEvent(upEvent, self->webView()->transformFromScene(), self->transformToScreen())); 1227 1228 if (InputMethodContextEfl* inputMethodContext = self->inputMethodContext()) 1229 inputMethodContext->handleMouseUpEvent(upEvent); 1230 1231 return true; 1232} 1233 1234Eina_Bool EwkView::handleEwkViewMouseMove(Ewk_View_Smart_Data* smartData, const Evas_Event_Mouse_Move* moveEvent) 1235{ 1236 EwkView* self = toEwkView(smartData); 1237 self->page()->handleMouseEvent(NativeWebMouseEvent(moveEvent, self->webView()->transformFromScene(), self->transformToScreen())); 1238 return true; 1239} 1240 1241Eina_Bool EwkView::handleEwkViewKeyDown(Ewk_View_Smart_Data* smartData, const Evas_Event_Key_Down* downEvent) 1242{ 1243 bool isFiltered = false; 1244 EwkView* self = toEwkView(smartData); 1245 if (InputMethodContextEfl* inputMethodContext = self->inputMethodContext()) 1246 inputMethodContext->handleKeyDownEvent(downEvent, &isFiltered); 1247 1248 self->page()->handleKeyboardEvent(NativeWebKeyboardEvent(downEvent, isFiltered)); 1249 return true; 1250} 1251 1252Eina_Bool EwkView::handleEwkViewKeyUp(Ewk_View_Smart_Data* smartData, const Evas_Event_Key_Up* upEvent) 1253{ 1254 toEwkView(smartData)->page()->handleKeyboardEvent(NativeWebKeyboardEvent(upEvent)); 1255 return true; 1256} 1257 1258#if ENABLE(TOUCH_EVENTS) 1259void EwkView::feedTouchEvents(Ewk_Touch_Event_Type type) 1260{ 1261 Ewk_View_Smart_Data* sd = smartData(); 1262 1263 unsigned count = evas_touch_point_list_count(sd->base.evas); 1264 if (!count) 1265 return; 1266 1267 Eina_List* points = 0; 1268 for (unsigned i = 0; i < count; ++i) { 1269 Ewk_Touch_Point* point = new Ewk_Touch_Point; 1270 point->id = evas_touch_point_list_nth_id_get(sd->base.evas, i); 1271 evas_touch_point_list_nth_xy_get(sd->base.evas, i, &point->x, &point->y); 1272 point->state = evas_touch_point_list_nth_state_get(sd->base.evas, i); 1273 points = eina_list_append(points, point); 1274 } 1275 1276 feedTouchEvent(type, points, evas_key_modifier_get(sd->base.evas)); 1277 1278 void* data; 1279 EINA_LIST_FREE(points, data) 1280 delete static_cast<Ewk_Touch_Point*>(data); 1281} 1282 1283void EwkView::handleTouchDown(void* /* data */, Evas* /* canvas */, Evas_Object* ewkView, void* /* eventInfo */) 1284{ 1285 toEwkView(ewkView)->feedTouchEvents(EWK_TOUCH_START); 1286} 1287 1288void EwkView::handleTouchUp(void* /* data */, Evas* /* canvas */, Evas_Object* ewkView, void* /* eventInfo */) 1289{ 1290 toEwkView(ewkView)->feedTouchEvents(EWK_TOUCH_END); 1291} 1292 1293void EwkView::handleTouchMove(void* /* data */, Evas* /* canvas */, Evas_Object* ewkView, void* /* eventInfo */) 1294{ 1295 toEwkView(ewkView)->feedTouchEvents(EWK_TOUCH_MOVE); 1296} 1297#endif 1298 1299void EwkView::handleFaviconChanged(const char* pageURL, void* eventInfo) 1300{ 1301 EwkView* view = static_cast<EwkView*>(eventInfo); 1302 1303 if (!view->url() || strcasecmp(view->url(), pageURL)) 1304 return; 1305 1306 view->smartCallback<FaviconChanged>().call(); 1307} 1308 1309PassRefPtr<cairo_surface_t> EwkView::takeSnapshot() 1310{ 1311 // Suspend all animations before taking the snapshot. 1312 WKViewSuspendActiveDOMObjectsAndAnimations(wkView()); 1313 1314 // Wait for the pending repaint events to be processed. 1315 while (m_displayTimer.isActive()) 1316 ecore_main_loop_iterate(); 1317 1318 Ewk_View_Smart_Data* sd = smartData(); 1319#if USE(ACCELERATED_COMPOSITING) 1320 if (m_isAccelerated) { 1321 RefPtr<cairo_surface_t> snapshot = getImageSurfaceFromFrameBuffer(0, 0, sd->view.w, sd->view.h); 1322 // Resume all animations. 1323 WKViewResumeActiveDOMObjectsAndAnimations(wkView()); 1324 1325 return snapshot.release(); 1326 } 1327#endif 1328 RefPtr<cairo_surface_t> snapshot = createSurfaceForImage(sd->image); 1329 // Resume all animations. 1330 WKViewResumeActiveDOMObjectsAndAnimations(wkView()); 1331 1332 return snapshot.release(); 1333} 1334 1335Evas_Smart_Class EwkView::parentSmartClass = EVAS_SMART_CLASS_INIT_NULL; 1336 1337// Free Ewk View functions. 1338 1339EwkView* toEwkView(const Evas_Object* evasObject) 1340{ 1341 ASSERT(evasObject); 1342 ASSERT(isEwkViewEvasObject(evasObject)); 1343 1344 return toEwkView(static_cast<Ewk_View_Smart_Data*>(evas_object_smart_data_get(evasObject))); 1345} 1346 1347bool isEwkViewEvasObject(const Evas_Object* evasObject) 1348{ 1349 ASSERT(evasObject); 1350 1351 const char* evasObjectType = evas_object_type_get(evasObject); 1352 const Evas_Smart* evasSmart = evas_object_smart_smart_get(evasObject); 1353 if (!evasSmart) { 1354 EINA_LOG_CRIT("%p (%s) is not a smart object!", evasObject, evasObjectType ? evasObjectType : "(null)"); 1355 return false; 1356 } 1357 1358 const Evas_Smart_Class* smartClass = evas_smart_class_get(evasSmart); 1359 if (!smartClass) { 1360 EINA_LOG_CRIT("%p (%s) is not a smart class object!", evasObject, evasObjectType ? evasObjectType : "(null)"); 1361 return false; 1362 } 1363 1364 if (smartClass->data != smartClassName) { 1365 EINA_LOG_CRIT("%p (%s) is not of an ewk_view (need %p, got %p)!", evasObject, evasObjectType ? evasObjectType : "(null)", 1366 smartClassName, smartClass->data); 1367 return false; 1368 } 1369 1370 return true; 1371} 1372