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