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