/* Copyright (C) 2011 Samsung Electronics Copyright (C) 2012 Intel Corporation. All rights reserved. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "config.h" #include "ewk_view.h" #include "NativeWebKeyboardEvent.h" #include "NativeWebMouseEvent.h" #include "NativeWebWheelEvent.h" #include "PageClientImpl.h" #include "WKAPICast.h" #include "WKColorPickerResultListener.h" #include "WKEinaSharedString.h" #include "WKFindOptions.h" #include "WKRetainPtr.h" #include "WKString.h" #include "WKURL.h" #include "WebContext.h" #include "WebPageGroup.h" #include "WebPopupItem.h" #include "WebPopupMenuProxyEfl.h" #include "WebPreferences.h" #include "ewk_back_forward_list_private.h" #include "ewk_context.h" #include "ewk_context_private.h" #include "ewk_intent_private.h" #include "ewk_popup_menu_item.h" #include "ewk_popup_menu_item_private.h" #include "ewk_private.h" #include "ewk_settings_private.h" #include "ewk_view_find_client_private.h" #include "ewk_view_form_client_private.h" #include "ewk_view_loader_client_private.h" #include "ewk_view_policy_client_private.h" #include "ewk_view_private.h" #include "ewk_view_resource_load_client_private.h" #include "ewk_view_ui_client_private.h" #include "ewk_web_resource.h" #include #include #include #include #include #include #if ENABLE(FULLSCREEN_API) #include "WebFullScreenManagerProxy.h" #endif #if USE(ACCELERATED_COMPOSITING) #include #endif #if USE(COORDINATED_GRAPHICS) #include "EflViewportHandler.h" #endif using namespace WebKit; using namespace WebCore; static const char EWK_VIEW_TYPE_STR[] = "EWK2_View"; static const int defaultCursorSize = 16; typedef HashMap LoadingResourcesMap; static void _ewk_view_priv_loading_resources_clear(LoadingResourcesMap& loadingResourcesMap); struct _Ewk_View_Private_Data { OwnPtr pageClient; #if USE(COORDINATED_GRAPHICS) OwnPtr viewportHandler; #endif RefPtr pageProxy; WKEinaSharedString uri; WKEinaSharedString title; WKEinaSharedString theme; WKEinaSharedString customEncoding; WKEinaSharedString cursorGroup; Evas_Object* cursorObject; LoadingResourcesMap loadingResourcesMap; Ewk_Back_Forward_List* backForwardList; OwnPtr settings; bool areMouseEventsEnabled; WKColorPickerResultListenerRef colorPickerResultListener; WebPopupMenuProxyEfl* popupMenuProxy; Eina_List* popupMenuItems; #ifdef HAVE_ECORE_X bool isUsingEcoreX; #endif #if USE(ACCELERATED_COMPOSITING) Evas_GL* evasGl; Evas_GL_Context* evasGlContext; Evas_GL_Surface* evasGlSurface; #endif _Ewk_View_Private_Data() : cursorObject(0) , backForwardList(0) , areMouseEventsEnabled(false) , colorPickerResultListener(0) , popupMenuProxy(0) , popupMenuItems(0) #ifdef HAVE_ECORE_X , isUsingEcoreX(false) #endif #if USE(ACCELERATED_COMPOSITING) , evasGl(0) , evasGlContext(0) , evasGlSurface(0) #endif { } ~_Ewk_View_Private_Data() { _ewk_view_priv_loading_resources_clear(loadingResourcesMap); if (cursorObject) evas_object_del(cursorObject); ewk_back_forward_list_free(backForwardList); void* item; EINA_LIST_FREE(popupMenuItems, item) ewk_popup_menu_item_free(static_cast(item)); } }; #define EWK_VIEW_TYPE_CHECK(ewkView, result) \ bool result = true; \ do { \ const char* _tmp_otype = evas_object_type_get(ewkView); \ const Evas_Smart* _tmp_s = evas_object_smart_smart_get(ewkView); \ if (EINA_UNLIKELY(!_tmp_s)) { \ EINA_LOG_CRIT \ ("%p (%s) is not a smart object!", \ ewkView, _tmp_otype ? _tmp_otype : "(null)"); \ result = false; \ } \ const Evas_Smart_Class* _tmp_sc = evas_smart_class_get(_tmp_s); \ if (EINA_UNLIKELY(!_tmp_sc)) { \ EINA_LOG_CRIT \ ("%p (%s) is not a smart object!", \ ewkView, _tmp_otype ? _tmp_otype : "(null)"); \ result = false; \ } \ if (EINA_UNLIKELY(_tmp_sc->data != EWK_VIEW_TYPE_STR)) { \ EINA_LOG_CRIT \ ("%p (%s) is not of an ewk_view (need %p, got %p)!", \ ewkView, _tmp_otype ? _tmp_otype : "(null)", \ EWK_VIEW_TYPE_STR, _tmp_sc->data); \ result = false; \ } \ } while (0) #define EWK_VIEW_SD_GET(ewkView, smartData) \ EWK_VIEW_TYPE_CHECK(ewkView, _tmp_result); \ Ewk_View_Smart_Data* smartData = 0; \ if (_tmp_result) \ smartData = (Ewk_View_Smart_Data*)evas_object_smart_data_get(ewkView) #define EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, ...) \ EWK_VIEW_SD_GET(ewkView, smartData); \ do { \ if (!smartData) { \ EINA_LOG_CRIT("no smart data for object %p (%s)", \ ewkView, evas_object_type_get(ewkView)); \ return __VA_ARGS__; \ } \ } while (0) #define EWK_VIEW_PRIV_GET(smartData, priv) \ Ewk_View_Private_Data* priv = smartData->priv #define EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, ...) \ if (!smartData) { \ EINA_LOG_CRIT("smart data is null"); \ return __VA_ARGS__; \ } \ EWK_VIEW_PRIV_GET(smartData, priv); \ do { \ if (!priv) { \ EINA_LOG_CRIT("no private data for object %p (%s)", \ smartData->self, evas_object_type_get(smartData->self)); \ return __VA_ARGS__; \ } \ } while (0) static void _ewk_view_smart_changed(Ewk_View_Smart_Data* smartData) { if (smartData->changed.any) return; smartData->changed.any = true; evas_object_smart_changed(smartData->self); } // Default Event Handling. static Eina_Bool _ewk_view_smart_focus_in(Ewk_View_Smart_Data* smartData) { EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); priv->pageProxy->viewStateDidChange(WebPageProxy::ViewIsFocused | WebPageProxy::ViewWindowIsActive); return true; } static Eina_Bool _ewk_view_smart_focus_out(Ewk_View_Smart_Data* smartData) { EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); priv->pageProxy->viewStateDidChange(WebPageProxy::ViewIsFocused | WebPageProxy::ViewWindowIsActive); return true; } static Eina_Bool _ewk_view_smart_mouse_wheel(Ewk_View_Smart_Data* smartData, const Evas_Event_Mouse_Wheel* wheelEvent) { EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); Evas_Point position = {smartData->view.x, smartData->view.y}; priv->pageProxy->handleWheelEvent(NativeWebWheelEvent(wheelEvent, &position)); return true; } static Eina_Bool _ewk_view_smart_mouse_down(Ewk_View_Smart_Data* smartData, const Evas_Event_Mouse_Down* downEvent) { EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); Evas_Point position = {smartData->view.x, smartData->view.y}; priv->pageProxy->handleMouseEvent(NativeWebMouseEvent(downEvent, &position)); return true; } static Eina_Bool _ewk_view_smart_mouse_up(Ewk_View_Smart_Data* smartData, const Evas_Event_Mouse_Up* upEvent) { EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); Evas_Point position = {smartData->view.x, smartData->view.y}; priv->pageProxy->handleMouseEvent(NativeWebMouseEvent(upEvent, &position)); return true; } static Eina_Bool _ewk_view_smart_mouse_move(Ewk_View_Smart_Data* smartData, const Evas_Event_Mouse_Move* moveEvent) { EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); Evas_Point position = {smartData->view.x, smartData->view.y}; priv->pageProxy->handleMouseEvent(NativeWebMouseEvent(moveEvent, &position)); return true; } static Eina_Bool _ewk_view_smart_key_down(Ewk_View_Smart_Data* smartData, const Evas_Event_Key_Down* downEvent) { EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); priv->pageProxy->handleKeyboardEvent(NativeWebKeyboardEvent(downEvent)); return true; } static Eina_Bool _ewk_view_smart_key_up(Ewk_View_Smart_Data* smartData, const Evas_Event_Key_Up* upEvent) { EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); priv->pageProxy->handleKeyboardEvent(NativeWebKeyboardEvent(upEvent)); return true; } // Event Handling. static void _ewk_view_on_focus_in(void* data, Evas*, Evas_Object*, void* /*eventInfo*/) { Ewk_View_Smart_Data* smartData = static_cast(data); EINA_SAFETY_ON_NULL_RETURN(smartData->api); EINA_SAFETY_ON_NULL_RETURN(smartData->api->focus_in); smartData->api->focus_in(smartData); } static void _ewk_view_on_focus_out(void* data, Evas*, Evas_Object*, void* /*eventInfo*/) { Ewk_View_Smart_Data* smartData = static_cast(data); EINA_SAFETY_ON_NULL_RETURN(smartData->api); EINA_SAFETY_ON_NULL_RETURN(smartData->api->focus_out); smartData->api->focus_out(smartData); } static void _ewk_view_on_mouse_wheel(void* data, Evas*, Evas_Object*, void* eventInfo) { Evas_Event_Mouse_Wheel* wheelEvent = static_cast(eventInfo); Ewk_View_Smart_Data* smartData = static_cast(data); EINA_SAFETY_ON_NULL_RETURN(smartData->api); EINA_SAFETY_ON_NULL_RETURN(smartData->api->mouse_wheel); smartData->api->mouse_wheel(smartData, wheelEvent); } static void _ewk_view_on_mouse_down(void* data, Evas*, Evas_Object*, void* eventInfo) { Evas_Event_Mouse_Down* downEvent = static_cast(eventInfo); Ewk_View_Smart_Data* smartData = static_cast(data); EINA_SAFETY_ON_NULL_RETURN(smartData->api); EINA_SAFETY_ON_NULL_RETURN(smartData->api->mouse_down); smartData->api->mouse_down(smartData, downEvent); } static void _ewk_view_on_mouse_up(void* data, Evas*, Evas_Object*, void* eventInfo) { Evas_Event_Mouse_Up* upEvent = static_cast(eventInfo); Ewk_View_Smart_Data* smartData = static_cast(data); EINA_SAFETY_ON_NULL_RETURN(smartData->api); EINA_SAFETY_ON_NULL_RETURN(smartData->api->mouse_up); smartData->api->mouse_up(smartData, upEvent); } static void _ewk_view_on_mouse_move(void* data, Evas*, Evas_Object*, void* eventInfo) { Evas_Event_Mouse_Move* moveEvent = static_cast(eventInfo); Ewk_View_Smart_Data* smartData = static_cast(data); EINA_SAFETY_ON_NULL_RETURN(smartData->api); EINA_SAFETY_ON_NULL_RETURN(smartData->api->mouse_move); smartData->api->mouse_move(smartData, moveEvent); } static void _ewk_view_on_key_down(void* data, Evas*, Evas_Object*, void* eventInfo) { Evas_Event_Key_Down* downEvent = static_cast(eventInfo); Ewk_View_Smart_Data* smartData = static_cast(data); EINA_SAFETY_ON_NULL_RETURN(smartData->api); EINA_SAFETY_ON_NULL_RETURN(smartData->api->key_down); smartData->api->key_down(smartData, downEvent); } static void _ewk_view_on_key_up(void* data, Evas*, Evas_Object*, void* eventInfo) { Evas_Event_Key_Up* upEvent = static_cast(eventInfo); Ewk_View_Smart_Data* smartData = static_cast(data); EINA_SAFETY_ON_NULL_RETURN(smartData->api); EINA_SAFETY_ON_NULL_RETURN(smartData->api->key_up); smartData->api->key_up(smartData, upEvent); } static Evas_Smart_Class g_parentSmartClass = EVAS_SMART_CLASS_INIT_NULL; static Ewk_View_Private_Data* _ewk_view_priv_new(Ewk_View_Smart_Data* smartData) { Ewk_View_Private_Data* priv = new Ewk_View_Private_Data; if (!priv) { EINA_LOG_CRIT("could not allocate Ewk_View_Private_Data"); return 0; } #ifdef HAVE_ECORE_X priv->isUsingEcoreX = WebCore::isUsingEcoreX(smartData->base.evas); #endif return priv; } static void _ewk_view_priv_loading_resources_clear(LoadingResourcesMap& loadingResourcesMap) { // Clear the loadingResources HashMap. LoadingResourcesMap::iterator it = loadingResourcesMap.begin(); LoadingResourcesMap::iterator end = loadingResourcesMap.end(); for ( ; it != end; ++it) ewk_web_resource_unref(it->second); loadingResourcesMap.clear(); } static void _ewk_view_priv_del(Ewk_View_Private_Data* priv) { delete priv; } static void _ewk_view_smart_add(Evas_Object* ewkView) { const Evas_Smart* smart = evas_object_smart_smart_get(ewkView); const Evas_Smart_Class* smartClass = evas_smart_class_get(smart); const Ewk_View_Smart_Class* api = reinterpret_cast(smartClass); EWK_VIEW_SD_GET(ewkView, smartData); if (!smartData) { smartData = static_cast(calloc(1, sizeof(Ewk_View_Smart_Data))); if (!smartData) { EINA_LOG_CRIT("could not allocate Ewk_View_Smart_Data"); return; } evas_object_smart_data_set(ewkView, smartData); } smartData->self = ewkView; smartData->api = api; g_parentSmartClass.add(ewkView); smartData->priv = _ewk_view_priv_new(smartData); if (!smartData->priv) { EINA_LOG_CRIT("could not allocate _Ewk_View_Private_Data"); evas_object_smart_data_set(ewkView, 0); free(smartData); return; } // Create evas_object_image to draw web contents. smartData->image = evas_object_image_add(smartData->base.evas); evas_object_image_alpha_set(smartData->image, false); evas_object_image_filled_set(smartData->image, true); evas_object_smart_member_add(smartData->image, ewkView); evas_object_show(smartData->image); ewk_view_mouse_events_enabled_set(ewkView, true); #define CONNECT(s, c) evas_object_event_callback_add(ewkView, s, c, smartData) CONNECT(EVAS_CALLBACK_FOCUS_IN, _ewk_view_on_focus_in); CONNECT(EVAS_CALLBACK_FOCUS_OUT, _ewk_view_on_focus_out); CONNECT(EVAS_CALLBACK_MOUSE_WHEEL, _ewk_view_on_mouse_wheel); CONNECT(EVAS_CALLBACK_KEY_DOWN, _ewk_view_on_key_down); CONNECT(EVAS_CALLBACK_KEY_UP, _ewk_view_on_key_up); #undef CONNECT } static void _ewk_view_smart_del(Evas_Object* ewkView) { EWK_VIEW_SD_GET(ewkView, smartData); if (smartData && smartData->priv) _ewk_view_priv_del(smartData->priv); g_parentSmartClass.del(ewkView); } static void _ewk_view_smart_resize(Evas_Object* ewkView, Evas_Coord width, Evas_Coord height) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData); evas_object_resize(smartData->image, width, height); evas_object_image_size_set(smartData->image, width, height); evas_object_image_fill_set(smartData->image, 0, 0, width, height); smartData->changed.size = true; _ewk_view_smart_changed(smartData); } static void _ewk_view_smart_move(Evas_Object* ewkView, Evas_Coord /*x*/, Evas_Coord /*y*/) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData); smartData->changed.position = true; _ewk_view_smart_changed(smartData); } IntSize ewk_view_size_get(const Evas_Object* ewkView) { int width, height; evas_object_geometry_get(ewkView, 0, 0, &width, &height); return IntSize(width, height); } #if USE(ACCELERATED_COMPOSITING) static bool ewk_view_create_gl_surface(const Evas_Object* ewkView, const IntSize& viewSize) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); Evas_GL_Config evasGlConfig = { EVAS_GL_RGBA_8888, EVAS_GL_DEPTH_BIT_8, EVAS_GL_STENCIL_NONE, EVAS_GL_OPTIONS_NONE, EVAS_GL_MULTISAMPLE_NONE }; ASSERT(!priv->evasGlSurface); priv->evasGlSurface = evas_gl_surface_create(priv->evasGl, &evasGlConfig, viewSize.width(), viewSize.height()); if (!priv->evasGlSurface) return false; Evas_Native_Surface nativeSurface; evas_gl_native_surface_get(priv->evasGl, priv->evasGlSurface, &nativeSurface); evas_object_image_native_surface_set(smartData->image, &nativeSurface); return true; } bool ewk_view_accelerated_compositing_mode_enter(const Evas_Object* ewkView) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); if (priv->evasGl) { EINA_LOG_DOM_WARN(_ewk_log_dom, "Accelerated compositing mode already entered."); return false; } Evas* evas = evas_object_evas_get(ewkView); priv->evasGl = evas_gl_new(evas); if (!priv->evasGl) return false; priv->evasGlContext = evas_gl_context_create(priv->evasGl, 0); if (!priv->evasGlContext) { evas_gl_free(priv->evasGl); priv->evasGl = 0; return false; } if (!ewk_view_create_gl_surface(ewkView, ewk_view_size_get(ewkView))) { evas_gl_context_destroy(priv->evasGl, priv->evasGlContext); priv->evasGlContext = 0; evas_gl_free(priv->evasGl); priv->evasGl = 0; return false; } return true; } bool ewk_view_accelerated_compositing_mode_exit(const Evas_Object* ewkView) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); EINA_SAFETY_ON_NULL_RETURN_VAL(priv->evasGl, false); if (priv->evasGlSurface) { evas_gl_surface_destroy(priv->evasGl, priv->evasGlSurface); priv->evasGlSurface = 0; } if (priv->evasGlContext) { evas_gl_context_destroy(priv->evasGl, priv->evasGlContext); priv->evasGlContext = 0; } evas_gl_free(priv->evasGl); priv->evasGl = 0; return true; } #endif static void _ewk_view_smart_calculate(Evas_Object* ewkView) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv); Evas_Coord x, y, width, height; smartData->changed.any = false; evas_object_geometry_get(ewkView, &x, &y, &width, &height); if (smartData->changed.size) { #if USE(COORDINATED_GRAPHICS) priv->viewportHandler->updateViewportSize(IntSize(width, height)); #endif if (priv->pageProxy->drawingArea()) priv->pageProxy->drawingArea()->setSize(IntSize(width, height), IntSize()); #if USE(ACCELERATED_COMPOSITING) if (!priv->evasGlSurface) return; evas_gl_surface_destroy(priv->evasGl, priv->evasGlSurface); priv->evasGlSurface = 0; ewk_view_create_gl_surface(ewkView, IntSize(width, height)); ewk_view_display(ewkView, IntRect(IntPoint(), IntSize(width, height))); #endif smartData->view.w = width; smartData->view.h = height; smartData->changed.size = false; } if (smartData->changed.position) { evas_object_move(smartData->image, x, y); smartData->view.x = x; smartData->view.y = y; smartData->changed.position = false; } } static void _ewk_view_smart_show(Evas_Object* ewkView) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData); if (evas_object_clipees_get(smartData->base.clipper)) evas_object_show(smartData->base.clipper); evas_object_show(smartData->image); } static void _ewk_view_smart_hide(Evas_Object* ewkView) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData); evas_object_hide(smartData->base.clipper); evas_object_hide(smartData->image); } static void _ewk_view_smart_color_set(Evas_Object* ewkView, int red, int green, int blue, int alpha) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv); if (alpha < 0) alpha = 0; else if (alpha > 255) alpha = 255; #define CHECK_COLOR(color, alpha) \ if (color < 0) \ color = 0; \ else if (color > alpha) \ color = alpha; CHECK_COLOR(red, alpha); CHECK_COLOR(green, alpha); CHECK_COLOR(blue, alpha); #undef CHECK_COLOR evas_object_image_alpha_set(smartData->image, alpha < 255); priv->pageProxy->setDrawsBackground(red || green || blue); priv->pageProxy->setDrawsTransparentBackground(alpha < 255); g_parentSmartClass.color_set(ewkView, red, green, blue, alpha); } Eina_Bool ewk_view_smart_class_set(Ewk_View_Smart_Class* api) { EINA_SAFETY_ON_NULL_RETURN_VAL(api, false); if (api->version != EWK_VIEW_SMART_CLASS_VERSION) { EINA_LOG_CRIT("Ewk_View_Smart_Class %p is version %lu while %lu was expected.", api, api->version, EWK_VIEW_SMART_CLASS_VERSION); return false; } if (EINA_UNLIKELY(!g_parentSmartClass.add)) evas_object_smart_clipped_smart_set(&g_parentSmartClass); evas_object_smart_clipped_smart_set(&api->sc); // Set Evas_Smart_Class functions. api->sc.add = _ewk_view_smart_add; api->sc.del = _ewk_view_smart_del; api->sc.move = _ewk_view_smart_move; api->sc.resize = _ewk_view_smart_resize; api->sc.show = _ewk_view_smart_show; api->sc.hide = _ewk_view_smart_hide; api->sc.color_set = _ewk_view_smart_color_set; api->sc.calculate = _ewk_view_smart_calculate; api->sc.data = EWK_VIEW_TYPE_STR; // It is used by type checking. // Set Ewk_View_Smart_Class functions. api->focus_in = _ewk_view_smart_focus_in; api->focus_out = _ewk_view_smart_focus_out; api->mouse_wheel = _ewk_view_smart_mouse_wheel; api->mouse_down = _ewk_view_smart_mouse_down; api->mouse_up = _ewk_view_smart_mouse_up; api->mouse_move = _ewk_view_smart_mouse_move; api->key_down = _ewk_view_smart_key_down; api->key_up = _ewk_view_smart_key_up; return true; } static inline Evas_Smart* _ewk_view_smart_class_new(void) { static Ewk_View_Smart_Class api = EWK_VIEW_SMART_CLASS_INIT_NAME_VERSION("Ewk_View"); static Evas_Smart* smart = 0; if (EINA_UNLIKELY(!smart)) { ewk_view_smart_class_set(&api); smart = evas_smart_class_new(&api.sc); } return smart; } static void _ewk_view_initialize(Evas_Object* ewkView, Ewk_Context* context, WKPageGroupRef pageGroupRef) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv); EINA_SAFETY_ON_NULL_RETURN(context); if (priv->pageClient) return; priv->pageClient = PageClientImpl::create(ewkView); if (pageGroupRef) priv->pageProxy = toImpl(ewk_context_WKContext_get(context))->createWebPage(priv->pageClient.get(), toImpl(pageGroupRef)); else priv->pageProxy = toImpl(ewk_context_WKContext_get(context))->createWebPage(priv->pageClient.get(), WebPageGroup::create().get()); #if USE(COORDINATED_GRAPHICS) priv->pageProxy->pageGroup()->preferences()->setAcceleratedCompositingEnabled(true); priv->pageProxy->pageGroup()->preferences()->setForceCompositingMode(true); priv->pageProxy->setUseFixedLayout(true); #endif priv->pageProxy->initializeWebPage(); priv->backForwardList = ewk_back_forward_list_new(toAPI(priv->pageProxy->backForwardList())); priv->settings = adoptPtr(new Ewk_Settings(WKPageGroupGetPreferences(WKPageGetPageGroup(toAPI(priv->pageProxy.get()))))); #if USE(COORDINATED_GRAPHICS) priv->viewportHandler = EflViewportHandler::create(ewkView); #endif WKPageRef wkPage = toAPI(priv->pageProxy.get()); ewk_view_find_client_attach(wkPage, ewkView); ewk_view_form_client_attach(wkPage, ewkView); ewk_view_loader_client_attach(wkPage, ewkView); ewk_view_policy_client_attach(wkPage, ewkView); ewk_view_resource_load_client_attach(wkPage, ewkView); ewk_view_ui_client_attach(wkPage, ewkView); #if ENABLE(FULLSCREEN_API) priv->pageProxy->fullScreenManager()->setWebView(ewkView); ewk_settings_fullscreen_enabled_set(priv->settings.get(), true); #endif } static Evas_Object* _ewk_view_add_with_smart(Evas* canvas, Evas_Smart* smart) { EINA_SAFETY_ON_NULL_RETURN_VAL(canvas, 0); EINA_SAFETY_ON_NULL_RETURN_VAL(smart, 0); Evas_Object* ewkView = evas_object_smart_add(canvas, smart); if (!ewkView) return 0; EWK_VIEW_SD_GET(ewkView, smartData); if (!smartData) { evas_object_del(ewkView); return 0; } EWK_VIEW_PRIV_GET(smartData, priv); if (!priv) { evas_object_del(ewkView); return 0; } return ewkView; } /** * @internal * Constructs a ewk_view Evas_Object with WKType parameters. */ Evas_Object* ewk_view_base_add(Evas* canvas, WKContextRef contextRef, WKPageGroupRef pageGroupRef) { EINA_SAFETY_ON_NULL_RETURN_VAL(canvas, 0); EINA_SAFETY_ON_NULL_RETURN_VAL(contextRef, 0); Evas_Object* ewkView = _ewk_view_add_with_smart(canvas, _ewk_view_smart_class_new()); if (!ewkView) return 0; _ewk_view_initialize(ewkView, ewk_context_new_from_WKContext(contextRef), pageGroupRef); return ewkView; } Evas_Object* ewk_view_smart_add(Evas* canvas, Evas_Smart* smart, Ewk_Context* context) { EINA_SAFETY_ON_NULL_RETURN_VAL(canvas, 0); EINA_SAFETY_ON_NULL_RETURN_VAL(smart, 0); EINA_SAFETY_ON_NULL_RETURN_VAL(context, 0); Evas_Object* ewkView = _ewk_view_add_with_smart(canvas, smart); if (!ewkView) return 0; _ewk_view_initialize(ewkView, context, 0); return ewkView; } Evas_Object* ewk_view_add_with_context(Evas* canvas, Ewk_Context* context) { return ewk_view_smart_add(canvas, _ewk_view_smart_class_new(), context); } Evas_Object* ewk_view_add(Evas* canvas) { return ewk_view_add_with_context(canvas, ewk_context_default_get()); } /** * @internal * The uri of view was changed by the frame loader. * * Emits signal: "uri,changed" with pointer to new uri string. */ void ewk_view_uri_update(Evas_Object* ewkView) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv); String activeURL = priv->pageProxy->activeURL(); if (activeURL.isEmpty()) return; if (priv->uri == activeURL.utf8().data()) return; priv->uri = activeURL.utf8().data(); const char* callbackArgument = static_cast(priv->uri); evas_object_smart_callback_call(ewkView, "uri,changed", const_cast(callbackArgument)); } Eina_Bool ewk_view_uri_set(Evas_Object* ewkView, const char* uri) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); EINA_SAFETY_ON_NULL_RETURN_VAL(uri, false); priv->pageProxy->loadURL(uri); ewk_view_uri_update(ewkView); return true; } const char* ewk_view_uri_get(const Evas_Object* ewkView) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, 0); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, 0); return priv->uri; } Eina_Bool ewk_view_reload(Evas_Object* ewkView) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); priv->pageProxy->reload(/*reloadFromOrigin*/ false); ewk_view_uri_update(ewkView); return true; } Eina_Bool ewk_view_reload_bypass_cache(Evas_Object* ewkView) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); priv->pageProxy->reload(/*reloadFromOrigin*/ true); ewk_view_uri_update(ewkView); return true; } Eina_Bool ewk_view_stop(Evas_Object* ewkView) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); priv->pageProxy->stopLoading(); return true; } Ewk_Settings* ewk_view_settings_get(const Evas_Object* ewkView) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, 0); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, 0); return priv->settings.get(); } /** * @internal * Load was initiated for a resource in the view. * * Emits signal: "resource,request,new" with pointer to resource request. */ void ewk_view_resource_load_initiated(Evas_Object* ewkView, uint64_t resourceIdentifier, Ewk_Web_Resource* resource, Ewk_Url_Request* request) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv); Ewk_Web_Resource_Request resourceRequest = {resource, request, 0}; // Keep the resource internally to reuse it later. priv->loadingResourcesMap.add(resourceIdentifier, ewk_web_resource_ref(resource)); evas_object_smart_callback_call(ewkView, "resource,request,new", &resourceRequest); } /** * @internal * Received a response to a resource load request in the view. * * Emits signal: "resource,request,response" with pointer to resource response. */ void ewk_view_resource_load_response(Evas_Object* ewkView, uint64_t resourceIdentifier, Ewk_Url_Response* response) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv); if (!priv->loadingResourcesMap.contains(resourceIdentifier)) return; Ewk_Web_Resource* resource = priv->loadingResourcesMap.get(resourceIdentifier); Ewk_Web_Resource_Load_Response resourceLoadResponse = {resource, response}; evas_object_smart_callback_call(ewkView, "resource,request,response", &resourceLoadResponse); } /** * @internal * Failed loading a resource in the view. * * Emits signal: "resource,request,finished" with pointer to the resource load error. */ void ewk_view_resource_load_failed(Evas_Object* ewkView, uint64_t resourceIdentifier, Ewk_Web_Error* error) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv); if (!priv->loadingResourcesMap.contains(resourceIdentifier)) return; Ewk_Web_Resource* resource = priv->loadingResourcesMap.get(resourceIdentifier); Ewk_Web_Resource_Load_Error resourceLoadError = {resource, error}; evas_object_smart_callback_call(ewkView, "resource,request,failed", &resourceLoadError); } /** * @internal * Finished loading a resource in the view. * * Emits signal: "resource,request,finished" with pointer to the resource. */ void ewk_view_resource_load_finished(Evas_Object* ewkView, uint64_t resourceIdentifier) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv); if (!priv->loadingResourcesMap.contains(resourceIdentifier)) return; Ewk_Web_Resource* resource = priv->loadingResourcesMap.take(resourceIdentifier); evas_object_smart_callback_call(ewkView, "resource,request,finished", resource); ewk_web_resource_unref(resource); } /** * @internal * Request was sent for a resource in the view. * * Emits signal: "resource,request,sent" with pointer to resource request and possible redirect response. */ void ewk_view_resource_request_sent(Evas_Object* ewkView, uint64_t resourceIdentifier, Ewk_Url_Request* request, Ewk_Url_Response* redirectResponse) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv); if (!priv->loadingResourcesMap.contains(resourceIdentifier)) return; Ewk_Web_Resource* resource = priv->loadingResourcesMap.get(resourceIdentifier); Ewk_Web_Resource_Request resourceRequest = {resource, request, redirectResponse}; evas_object_smart_callback_call(ewkView, "resource,request,sent", &resourceRequest); } const char* ewk_view_title_get(const Evas_Object* ewkView) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, 0); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, 0); CString title = priv->pageProxy->pageTitle().utf8(); priv->title = title.data(); return priv->title; } /** * @internal * Reports that the requested text was found. * * Emits signal: "text,found" with the number of matches. */ void ewk_view_text_found(Evas_Object* ewkView, unsigned int matchCount) { evas_object_smart_callback_call(ewkView, "text,found", &matchCount); } /** * @internal * The view title was changed by the frame loader. * * Emits signal: "title,changed" with pointer to new title string. */ void ewk_view_title_changed(Evas_Object* ewkView, const char* title) { evas_object_smart_callback_call(ewkView, "title,changed", const_cast(title)); } double ewk_view_load_progress_get(const Evas_Object* ewkView) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, -1.0); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, -1.0); return priv->pageProxy->estimatedProgress(); } Eina_Bool ewk_view_scale_set(Evas_Object* ewkView, double scaleFactor, int x, int y) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); priv->pageProxy->scalePage(scaleFactor, IntPoint(x, y)); return true; } double ewk_view_scale_get(const Evas_Object* ewkView) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, -1); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, -1); return priv->pageProxy->pageScaleFactor(); } Eina_Bool ewk_view_device_pixel_ratio_set(Evas_Object* ewkView, float ratio) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); priv->pageProxy->setCustomDeviceScaleFactor(ratio); return true; } float ewk_view_device_pixel_ratio_get(const Evas_Object* ewkView) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, -1.0); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, -1.0); return priv->pageProxy->deviceScaleFactor(); } /** * @internal * Reports load progress changed. * * Emits signal: "load,progress" with pointer to a double from 0.0 to 1.0. */ void ewk_view_load_progress_changed(Evas_Object* ewkView, double progress) { evas_object_smart_callback_call(ewkView, "load,progress", &progress); } /** * @internal * The view received a new intent request. * * Emits signal: "intent,request,new" with pointer to a Ewk_Intent. */ void ewk_view_intent_request_new(Evas_Object* ewkView, const Ewk_Intent* ewkIntent) { #if ENABLE(WEB_INTENTS) evas_object_smart_callback_call(ewkView, "intent,request,new", const_cast(ewkIntent)); #endif } void ewk_view_theme_set(Evas_Object* ewkView, const char* path) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv); if (priv->theme != path) { priv->theme = path; priv->pageProxy->setThemePath(path); } } const char* ewk_view_theme_get(const Evas_Object* ewkView) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, 0); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, 0); return priv->theme; } void ewk_view_cursor_set(Evas_Object* ewkView, const Cursor& cursor) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv); const char* group = cursor.platformCursor(); if (!group || group == priv->cursorGroup) return; priv->cursorGroup = group; if (priv->cursorObject) evas_object_del(priv->cursorObject); priv->cursorObject = edje_object_add(smartData->base.evas); Ecore_Evas* ecoreEvas = ecore_evas_ecore_evas_get(smartData->base.evas); if (!priv->theme || !edje_object_file_set(priv->cursorObject, priv->theme, group)) { evas_object_del(priv->cursorObject); priv->cursorObject = 0; ecore_evas_object_cursor_set(ecoreEvas, 0, 0, 0, 0); #ifdef HAVE_ECORE_X if (priv->isUsingEcoreX) WebCore::applyFallbackCursor(ecoreEvas, group); #endif return; } Evas_Coord width, height; edje_object_size_min_get(priv->cursorObject, &width, &height); if (width <= 0 || height <= 0) edje_object_size_min_calc(priv->cursorObject, &width, &height); if (width <= 0 || height <= 0) { width = defaultCursorSize; height = defaultCursorSize; } evas_object_resize(priv->cursorObject, width, height); const char* data; int hotspotX = 0; data = edje_object_data_get(priv->cursorObject, "hot.x"); if (data) hotspotX = atoi(data); int hotspotY = 0; data = edje_object_data_get(priv->cursorObject, "hot.y"); if (data) hotspotY = atoi(data); ecore_evas_object_cursor_set(ecoreEvas, priv->cursorObject, EVAS_LAYER_MAX, hotspotX, hotspotY); } void ewk_view_display(Evas_Object* ewkView, const IntRect& rect) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData); if (!smartData->image) return; #if USE(COORDINATED_GRAPHICS) EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv); evas_gl_make_current(priv->evasGl, priv->evasGlSurface, priv->evasGlContext); priv->viewportHandler->display(rect); #endif evas_object_image_data_update_add(smartData->image, rect.x(), rect.y(), rect.width(), rect.height()); } #if ENABLE(FULLSCREEN_API) /** * @internal * Calls fullscreen_enter callback or falls back to default behavior and enables fullscreen mode. */ void ewk_view_full_screen_enter(Evas_Object* ewkView) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData); if (!smartData->api->fullscreen_enter || !smartData->api->fullscreen_enter(smartData)) { Ecore_Evas* ecoreEvas = ecore_evas_ecore_evas_get(smartData->base.evas); ecore_evas_fullscreen_set(ecoreEvas, true); } } /** * @internal * Calls fullscreen_exit callback or falls back to default behavior and disables fullscreen mode. */ void ewk_view_full_screen_exit(Evas_Object* ewkView) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData); if (!smartData->api->fullscreen_exit || !smartData->api->fullscreen_exit(smartData)) { Ecore_Evas* ecoreEvas = ecore_evas_ecore_evas_get(smartData->base.evas); ecore_evas_fullscreen_set(ecoreEvas, false); } } #endif /** * @internal * A download for that view was cancelled. * * Emits signal: "download,cancelled" with pointer to a Ewk_Download_Job. */ void ewk_view_download_job_cancelled(Evas_Object* ewkView, Ewk_Download_Job* download) { evas_object_smart_callback_call(ewkView, "download,cancelled", download); } /** * @internal * A new download has been requested for that view. * * Emits signal: "download,request" with pointer to a Ewk_Download_Job. */ void ewk_view_download_job_requested(Evas_Object* ewkView, Ewk_Download_Job* download) { evas_object_smart_callback_call(ewkView, "download,request", download); } /** * @internal * A download for that view has failed. * * Emits signal: "download,failed" with pointer to a Ewk_Download_Job_Error. */ void ewk_view_download_job_failed(Evas_Object* ewkView, Ewk_Download_Job* download, Ewk_Web_Error* error) { Ewk_Download_Job_Error downloadError = { download, error }; evas_object_smart_callback_call(ewkView, "download,failed", &downloadError); } /** * @internal * A download for that view finished successfully. * * Emits signal: "download,finished" with pointer to a Ewk_Download_Job. */ void ewk_view_download_job_finished(Evas_Object* ewkView, Ewk_Download_Job* download) { evas_object_smart_callback_call(ewkView, "download,finished", download); } Eina_Bool ewk_view_back(Evas_Object* ewkView) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); WebPageProxy* page = priv->pageProxy.get(); if (page->canGoBack()) { page->goBack(); return true; } return false; } Eina_Bool ewk_view_forward(Evas_Object* ewkView) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); WebPageProxy* page = priv->pageProxy.get(); if (page->canGoForward()) { page->goForward(); return true; } return false; } Eina_Bool ewk_view_intent_deliver(Evas_Object* ewkView, Ewk_Intent* intent) { #if ENABLE(WEB_INTENTS) EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); EINA_SAFETY_ON_NULL_RETURN_VAL(intent, false); WebPageProxy* page = priv->pageProxy.get(); page->deliverIntentToFrame(page->mainFrame(), toImpl(ewk_intent_WKIntentDataRef_get(intent))); return true; #else return false; #endif } Eina_Bool ewk_view_back_possible(Evas_Object* ewkView) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); return priv->pageProxy->canGoBack(); } Eina_Bool ewk_view_forward_possible(Evas_Object* ewkView) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); return priv->pageProxy->canGoForward(); } Ewk_Back_Forward_List* ewk_view_back_forward_list_get(const Evas_Object* ewkView) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, 0); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, 0); return priv->backForwardList; } void ewk_view_image_data_set(Evas_Object* ewkView, void* imageData, const IntSize& size) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData); if (!imageData || !smartData->image) return; evas_object_resize(smartData->image, size.width(), size.height()); evas_object_image_size_set(smartData->image, size.width(), size.height()); evas_object_image_data_copy_set(smartData->image, imageData); } /** * @internal * Reports that a form request is about to be submitted. * * Emits signal: "form,submission,request" with pointer to Ewk_Form_Submission_Request. */ void ewk_view_form_submission_request_new(Evas_Object* ewkView, Ewk_Form_Submission_Request* request) { evas_object_smart_callback_call(ewkView, "form,submission,request", request); } /** * @internal * Reports load failed with error information. * * Emits signal: "load,error" with pointer to Ewk_Web_Error. */ void ewk_view_load_error(Evas_Object* ewkView, const Ewk_Web_Error* error) { evas_object_smart_callback_call(ewkView, "load,error", const_cast(error)); } /** * @internal * Reports load finished. * * Emits signal: "load,finished". */ void ewk_view_load_finished(Evas_Object* ewkView) { ewk_view_uri_update(ewkView); evas_object_smart_callback_call(ewkView, "load,finished", 0); } /** * @internal * Reports view provisional load failed with error information. * * Emits signal: "load,provisional,failed" with pointer to Ewk_Web_Error. */ void ewk_view_load_provisional_failed(Evas_Object* ewkView, const Ewk_Web_Error* error) { evas_object_smart_callback_call(ewkView, "load,provisional,failed", const_cast(error)); } /** * @internal * Reports view received redirect for provisional load. * * Emits signal: "load,provisional,redirect". */ void ewk_view_load_provisional_redirect(Evas_Object* ewkView) { ewk_view_uri_update(ewkView); evas_object_smart_callback_call(ewkView, "load,provisional,redirect", 0); } /** * @internal * Reports view provisional load started. * * Emits signal: "load,provisional,started". */ void ewk_view_load_provisional_started(Evas_Object* ewkView) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv); // The main frame started provisional load, we should clear // the loadingResources HashMap to start clean. _ewk_view_priv_loading_resources_clear(priv->loadingResourcesMap); ewk_view_uri_update(ewkView); evas_object_smart_callback_call(ewkView, "load,provisional,started", 0); } /** * @internal * Reports that a navigation policy decision should be taken. * * Emits signal: "policy,decision,navigation". */ void ewk_view_navigation_policy_decision(Evas_Object* ewkView, Ewk_Navigation_Policy_Decision* decision) { evas_object_smart_callback_call(ewkView, "policy,decision,navigation", decision); } /** * @internal * Reports that a new window policy decision should be taken. * * Emits signal: "policy,decision,new,window". */ void ewk_view_new_window_policy_decision(Evas_Object* ewkView, Ewk_Navigation_Policy_Decision* decision) { evas_object_smart_callback_call(ewkView, "policy,decision,new,window", decision); } Eina_Bool ewk_view_html_string_load(Evas_Object* ewkView, const char* html, const char* baseUrl, const char* unreachableUrl) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); EINA_SAFETY_ON_NULL_RETURN_VAL(html, false); if (unreachableUrl && *unreachableUrl) priv->pageProxy->loadAlternateHTMLString(String::fromUTF8(html), baseUrl ? String::fromUTF8(baseUrl) : "", String::fromUTF8(unreachableUrl)); else priv->pageProxy->loadHTMLString(String::fromUTF8(html), baseUrl ? String::fromUTF8(baseUrl) : ""); ewk_view_uri_update(ewkView); return true; } #if ENABLE(WEB_INTENTS_TAG) /** * @internal * The view received a new intent service registration. * * Emits signal: "intent,service,register" with pointer to a Ewk_Intent_Service. */ void ewk_view_intent_service_register(Evas_Object* ewkView, const Ewk_Intent_Service* ewkIntentService) { evas_object_smart_callback_call(ewkView, "intent,service,register", const_cast(ewkIntentService)); } #endif // ENABLE(WEB_INTENTS_TAG) WebPageProxy* ewk_view_page_get(const Evas_Object* ewkView) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, 0); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, 0); return priv->pageProxy.get(); } const char* ewk_view_setting_encoding_custom_get(const Evas_Object* ewkView) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, 0); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, 0); String customEncoding = priv->pageProxy->customTextEncodingName(); if (customEncoding.isEmpty()) return 0; priv->customEncoding = customEncoding.utf8().data(); return priv->customEncoding; } Eina_Bool ewk_view_setting_encoding_custom_set(Evas_Object* ewkView, const char* encoding) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); priv->customEncoding = encoding; priv->pageProxy->setCustomTextEncodingName(encoding ? encoding : String()); return true; } void ewk_view_page_close(Evas_Object* ewkView) { evas_object_smart_callback_call(ewkView, "close,window", 0); } WKPageRef ewk_view_page_create(Evas_Object* ewkView) { Evas_Object* newEwkView = 0; evas_object_smart_callback_call(ewkView, "create,window", &newEwkView); if (!newEwkView) return 0; return static_cast(WKRetain(ewk_view_page_get(newEwkView))); } // EwkFindOptions should be matched up orders with WkFindOptions. COMPILE_ASSERT_MATCHING_ENUM(EWK_FIND_OPTIONS_CASE_INSENSITIVE, kWKFindOptionsCaseInsensitive); COMPILE_ASSERT_MATCHING_ENUM(EWK_FIND_OPTIONS_AT_WORD_STARTS, kWKFindOptionsAtWordStarts); COMPILE_ASSERT_MATCHING_ENUM(EWK_FIND_OPTIONS_TREAT_MEDIAL_CAPITAL_AS_WORD_START, kWKFindOptionsTreatMedialCapitalAsWordStart); COMPILE_ASSERT_MATCHING_ENUM(EWK_FIND_OPTIONS_BACKWARDS, kWKFindOptionsBackwards); COMPILE_ASSERT_MATCHING_ENUM(EWK_FIND_OPTIONS_WRAP_AROUND, kWKFindOptionsWrapAround); COMPILE_ASSERT_MATCHING_ENUM(EWK_FIND_OPTIONS_SHOW_OVERLAY, kWKFindOptionsShowOverlay); COMPILE_ASSERT_MATCHING_ENUM(EWK_FIND_OPTIONS_SHOW_FIND_INDICATOR, kWKFindOptionsShowFindIndicator); COMPILE_ASSERT_MATCHING_ENUM(EWK_FIND_OPTIONS_SHOW_HIGHLIGHT, kWKFindOptionsShowHighlight); Eina_Bool ewk_view_text_find(Evas_Object* ewkView, const char* text, Ewk_Find_Options options, unsigned int maxMatchCount) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); EINA_SAFETY_ON_NULL_RETURN_VAL(text, false); WKRetainPtr findText(AdoptWK, WKStringCreateWithUTF8CString(text)); WKPageFindString(toAPI(priv->pageProxy.get()), findText.get(), static_cast(options), maxMatchCount); return true; } Eina_Bool ewk_view_text_find_highlight_clear(Evas_Object* ewkView) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); WKPageHideFindUI(toAPI(priv->pageProxy.get())); return true; } void ewk_view_contents_size_changed(const Evas_Object* ewkView, const IntSize& size) { #if USE(COORDINATED_GRAPHICS) EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv); priv->viewportHandler->didChangeContentsSize(size); #else UNUSED_PARAM(ewkView); UNUSED_PARAM(size); #endif } COMPILE_ASSERT_MATCHING_ENUM(EWK_TEXT_DIRECTION_RIGHT_TO_LEFT, RTL); COMPILE_ASSERT_MATCHING_ENUM(EWK_TEXT_DIRECTION_LEFT_TO_RIGHT, LTR); void ewk_view_popup_menu_request(Evas_Object* ewkView, WebPopupMenuProxyEfl* popupMenu, const IntRect& rect, TextDirection textDirection, double pageScaleFactor, const Vector& items, int32_t selectedIndex) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv); EINA_SAFETY_ON_NULL_RETURN(smartData->api); ASSERT(popupMenu); if (!smartData->api->popup_menu_show) return; if (priv->popupMenuProxy) ewk_view_popup_menu_close(ewkView); priv->popupMenuProxy = popupMenu; Eina_List* popupItems = 0; size_t size = items.size(); for (size_t i = 0; i < size; ++i) popupItems = eina_list_append(popupItems, ewk_popup_menu_item_new(items[i])); priv->popupMenuItems = popupItems; smartData->api->popup_menu_show(smartData, rect, static_cast(textDirection), pageScaleFactor, popupItems, selectedIndex); } Eina_Bool ewk_view_popup_menu_close(Evas_Object* ewkView) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->api, false); if (!priv->popupMenuProxy) return false; priv->popupMenuProxy = 0; if (smartData->api->popup_menu_hide) smartData->api->popup_menu_hide(smartData); void* item; EINA_LIST_FREE(priv->popupMenuItems, item) ewk_popup_menu_item_free(static_cast(item)); return true; } Eina_Bool ewk_view_popup_menu_select(Evas_Object* ewkView, unsigned int selectedIndex) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); EINA_SAFETY_ON_NULL_RETURN_VAL(priv->popupMenuProxy, false); if (selectedIndex >= eina_list_count(priv->popupMenuItems)) return false; priv->popupMenuProxy->valueChanged(selectedIndex); return true; } Eina_Bool ewk_view_mouse_events_enabled_set(Evas_Object* ewkView, Eina_Bool enabled) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); enabled = !!enabled; if (priv->areMouseEventsEnabled == enabled) return true; priv->areMouseEventsEnabled = enabled; if (enabled) { evas_object_event_callback_add(ewkView, EVAS_CALLBACK_MOUSE_DOWN, _ewk_view_on_mouse_down, smartData); evas_object_event_callback_add(ewkView, EVAS_CALLBACK_MOUSE_UP, _ewk_view_on_mouse_up, smartData); evas_object_event_callback_add(ewkView, EVAS_CALLBACK_MOUSE_MOVE, _ewk_view_on_mouse_move, smartData); } else { evas_object_event_callback_del(ewkView, EVAS_CALLBACK_MOUSE_DOWN, _ewk_view_on_mouse_down); evas_object_event_callback_del(ewkView, EVAS_CALLBACK_MOUSE_UP, _ewk_view_on_mouse_up); evas_object_event_callback_del(ewkView, EVAS_CALLBACK_MOUSE_MOVE, _ewk_view_on_mouse_move); } return true; } Eina_Bool ewk_view_mouse_events_enabled_get(const Evas_Object* ewkView) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); return priv->areMouseEventsEnabled; } /** * @internal * Web process has crashed. * * Emits signal: "webprocess,crashed" with pointer to crash handling boolean. */ void ewk_view_webprocess_crashed(Evas_Object* ewkView) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv); bool handled = false; evas_object_smart_callback_call(ewkView, "webprocess,crashed", &handled); if (!handled) { CString url = priv->pageProxy->urlAtProcessExit().utf8(); WARN("WARNING: The web process experienced a crash on '%s'.\n", url.data()); // Display an error page ewk_view_html_string_load(ewkView, "The web process has crashed.", 0, url.data()); } } /** * @internal * Calls a smart member function for javascript alert(). */ void ewk_view_run_javascript_alert(Evas_Object* ewkView, const WKEinaSharedString& message) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData); EINA_SAFETY_ON_NULL_RETURN(smartData->api); if (!smartData->api->run_javascript_alert) return; smartData->api->run_javascript_alert(smartData, message); } /** * @internal * Calls a smart member function for javascript confirm() and returns a value from the function. Returns false by default. */ bool ewk_view_run_javascript_confirm(Evas_Object* ewkView, const WKEinaSharedString& message) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false); EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->api, false); if (!smartData->api->run_javascript_confirm) return false; return smartData->api->run_javascript_confirm(smartData, message); } /** * @internal * Calls a smart member function for javascript prompt() and returns a value from the function. Returns null string by default. */ WKEinaSharedString ewk_view_run_javascript_prompt(Evas_Object* ewkView, const WKEinaSharedString& message, const WKEinaSharedString& defaultValue) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, WKEinaSharedString()); EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->api, WKEinaSharedString()); if (!smartData->api->run_javascript_prompt) return WKEinaSharedString(); return WKEinaSharedString::adopt(smartData->api->run_javascript_prompt(smartData, message, defaultValue)); } #if ENABLE(INPUT_TYPE_COLOR) /** * @internal * Reqeusts to show external color picker. */ void ewk_view_color_picker_request(Evas_Object* ewkView, int r, int g, int b, int a, WKColorPickerResultListenerRef listener) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv); EINA_SAFETY_ON_NULL_RETURN(smartData->api->input_picker_color_request); priv->colorPickerResultListener = listener; smartData->api->input_picker_color_request(smartData, r, g, b, a); } /** * @internal * Reqeusts to hide external color picker. */ void ewk_view_color_picker_dismiss(Evas_Object* ewkView) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv); EINA_SAFETY_ON_NULL_RETURN(smartData->api->input_picker_color_dismiss); priv->colorPickerResultListener = 0; smartData->api->input_picker_color_dismiss(smartData); } #endif Eina_Bool ewk_view_color_picker_color_set(Evas_Object* ewkView, int r, int g, int b, int a) { #if ENABLE(INPUT_TYPE_COLOR) EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); EINA_SAFETY_ON_NULL_RETURN_VAL(priv->colorPickerResultListener, false); WebCore::Color color = WebCore::Color(r, g, b, a); const WKStringRef colorString = WKStringCreateWithUTF8CString(color.serialized().utf8().data()); WKColorPickerResultListenerSetColor(priv->colorPickerResultListener, colorString); priv->colorPickerResultListener = 0; return true; #else return false; #endif }