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