[EFL][WK2] Use C API inside ewk_window_features
[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 "CoordinatedLayerTreeHostProxy.h"
26 #include "EflScreenUtilities.h"
27 #include "FindClientEfl.h"
28 #include "FormClientEfl.h"
29 #include "InputMethodContextEfl.h"
30 #include "LayerTreeRenderer.h"
31 #include "PageClientBase.h"
32 #include "PageClientDefaultImpl.h"
33 #include "PageClientLegacyImpl.h"
34 #include "PageLoadClientEfl.h"
35 #include "PagePolicyClientEfl.h"
36 #include "PageUIClientEfl.h"
37 #include "SnapshotImageGL.h"
38 #include "WKDictionary.h"
39 #include "WKGeometry.h"
40 #include "WKNumber.h"
41 #include "WKString.h"
42 #include "WebContext.h"
43 #include "WebImage.h"
44 #include "WebPageGroup.h"
45 #include "WebPageProxy.h"
46 #include "WebPopupMenuProxyEfl.h"
47 #include "WebPreferences.h"
48 #include "ewk_back_forward_list_private.h"
49 #include "ewk_color_picker_private.h"
50 #include "ewk_context_menu_private.h"
51 #include "ewk_context_private.h"
52 #include "ewk_favicon_database_private.h"
53 #include "ewk_popup_menu_item_private.h"
54 #include "ewk_popup_menu_private.h"
55 #include "ewk_private.h"
56 #include "ewk_security_origin_private.h"
57 #include "ewk_settings_private.h"
58 #include "ewk_view.h"
59 #include "ewk_view_private.h"
60 #include "ewk_window_features_private.h"
61 #include <Ecore_Evas.h>
62 #include <Ecore_X.h>
63 #include <Edje.h>
64 #include <WebCore/CairoUtilitiesEfl.h>
65 #include <WebCore/Cursor.h>
66 #include <WebKit2/WKImageCairo.h>
67
68 #if ENABLE(VIBRATION)
69 #include "VibrationClientEfl.h"
70 #endif
71
72 #if ENABLE(FULLSCREEN_API)
73 #include "WebFullScreenManagerProxy.h"
74 #endif
75
76 #if USE(ACCELERATED_COMPOSITING)
77 #include <Evas_GL.h>
78 #endif
79
80 using namespace EwkViewCallbacks;
81 using namespace WebCore;
82 using namespace WebKit;
83
84 static const int defaultCursorSize = 16;
85
86 typedef HashMap<WKPageRef, Evas_Object*> PageViewMap;
87
88 static inline PageViewMap& pageViewMap()
89 {
90     DEFINE_STATIC_LOCAL(PageViewMap, map, ());
91     return map;
92 }
93
94 void EwkView::addToPageViewMap(EwkView* view)
95 {
96     PageViewMap::AddResult result = pageViewMap().add(view->wkPage(), view->view());
97     ASSERT_UNUSED(result, result.isNewEntry);
98 }
99
100 void EwkView::removeFromPageViewMap(EwkView* view)
101 {
102     ASSERT(pageViewMap().contains(view->wkPage()));
103     pageViewMap().remove(view->wkPage());
104 }
105
106 const Evas_Object* EwkView::viewFromPageViewMap(const WKPageRef page)
107 {
108     ASSERT(page);
109
110     return pageViewMap().get(page);
111 }
112
113 EwkView::EwkView(Evas_Object* evasObject, PassRefPtr<EwkContext> context, PassRefPtr<WebPageGroup> pageGroup, ViewBehavior behavior)
114     : m_evasObject(evasObject)
115     , m_context(context)
116 #if USE(ACCELERATED_COMPOSITING)
117     , m_pendingSurfaceResize(false)
118 #endif
119     , m_pageClient(behavior == DefaultBehavior ? PageClientDefaultImpl::create(this) : PageClientLegacyImpl::create(this))
120     , m_pageProxy(m_context->webContext()->createWebPage(m_pageClient.get(), pageGroup.get()))
121     , m_pageLoadClient(PageLoadClientEfl::create(this))
122     , m_pagePolicyClient(PagePolicyClientEfl::create(this))
123     , m_pageUIClient(PageUIClientEfl::create(this))
124     , m_contextMenuClient(ContextMenuClientEfl::create(this))
125     , m_findClient(FindClientEfl::create(this))
126     , m_formClient(FormClientEfl::create(this))
127 #if ENABLE(VIBRATION)
128     , m_vibrationClient(VibrationClientEfl::create(this))
129 #endif
130     , m_backForwardList(EwkBackForwardList::create(toAPI(m_pageProxy->backForwardList())))
131 #if USE(TILED_BACKING_STORE)
132     , m_pageScaleFactor(1)
133 #endif
134     , m_settings(EwkSettings::create(this))
135     , m_cursorIdentifier(0)
136     , m_mouseEventsEnabled(false)
137 #if ENABLE(TOUCH_EVENTS)
138     , m_touchEventsEnabled(false)
139 #endif
140     , m_displayTimer(this, &EwkView::displayTimerFired)
141     , m_inputMethodContext(InputMethodContextEfl::create(this, smartData()->base.evas))
142     , m_isHardwareAccelerated(true)
143     , m_setDrawsBackground(false)
144 {
145     ASSERT(m_evasObject);
146     ASSERT(m_context);
147     ASSERT(m_pageProxy);
148
149 #if USE(COORDINATED_GRAPHICS)
150     m_pageProxy->pageGroup()->preferences()->setAcceleratedCompositingEnabled(true);
151     m_pageProxy->pageGroup()->preferences()->setForceCompositingMode(true);
152     char* debugVisualsEnvironment = getenv("WEBKIT_SHOW_COMPOSITING_DEBUG_VISUALS");
153     bool showDebugVisuals = debugVisualsEnvironment && !strcmp(debugVisualsEnvironment, "1");
154     m_pageProxy->pageGroup()->preferences()->setCompositingBordersVisible(showDebugVisuals);
155     m_pageProxy->pageGroup()->preferences()->setCompositingRepaintCountersVisible(showDebugVisuals);
156 #if ENABLE(WEBGL)
157     m_pageProxy->pageGroup()->preferences()->setWebGLEnabled(true);
158 #endif
159     if (behavior == DefaultBehavior)
160         m_pageProxy->setUseFixedLayout(true);
161 #endif
162
163     m_pageProxy->initializeWebPage();
164
165 #if ENABLE(FULLSCREEN_API)
166     m_pageProxy->fullScreenManager()->setWebView(m_evasObject);
167     m_pageProxy->pageGroup()->preferences()->setFullScreenEnabled(true);
168 #endif
169 #if ENABLE(WEB_AUDIO)
170     m_pageProxy->pageGroup()->preferences()->setWebAudioEnabled(true);
171 #endif
172
173     m_pageProxy->pageGroup()->preferences()->setOfflineWebApplicationCacheEnabled(true);
174
175     // Enable mouse events by default
176     setMouseEventsEnabled(true);
177
178     // Listen for favicon changes.
179     EwkFaviconDatabase* iconDatabase = m_context->faviconDatabase();
180     ASSERT(iconDatabase);
181
182     iconDatabase->watchChanges(IconChangeCallbackData(EwkView::onFaviconChanged, this));
183
184     EwkView::addToPageViewMap(this);
185 }
186
187 EwkView::~EwkView()
188 {
189     m_pageProxy->close();
190
191     // Unregister icon change callback.
192     EwkFaviconDatabase* iconDatabase = m_context->faviconDatabase();
193     ASSERT(iconDatabase);
194
195     iconDatabase->unwatchChanges(EwkView::onFaviconChanged);
196
197     EwkView::removeFromPageViewMap(this);
198 }
199
200 Ewk_View_Smart_Data* EwkView::smartData() const
201 {
202     return static_cast<Ewk_View_Smart_Data*>(evas_object_smart_data_get(m_evasObject));
203 }
204
205 EwkView* EwkView::fromEvasObject(const Evas_Object* view)
206 {
207     ASSERT(view);
208     Ewk_View_Smart_Data* sd = static_cast<Ewk_View_Smart_Data*>(evas_object_smart_data_get(view));
209     ASSERT(sd);
210     ASSERT(sd->priv);
211     return sd->priv;
212 }
213
214 /**
215  * @internal
216  * Retrieves the internal WKPage for this view.
217  */
218 WKPageRef EwkView::wkPage()
219 {
220     return toAPI(m_pageProxy.get());
221 }
222
223 void EwkView::setCursor(const Cursor& cursor)
224 {
225     if (cursor.image()) {
226         // Custom cursor.
227         if (cursor.image() == m_cursorIdentifier)
228             return;
229
230         m_cursorIdentifier = cursor.image();
231
232         Ewk_View_Smart_Data* sd = smartData();
233         RefPtr<Evas_Object> cursorObject = adoptRef(cursor.image()->getEvasObject(sd->base.evas));
234         if (!cursorObject)
235             return;
236
237         // Resize cursor.
238         evas_object_resize(cursorObject.get(), cursor.image()->size().width(), cursor.image()->size().height());
239
240         // Get cursor hot spot.
241         IntPoint hotSpot;
242         cursor.image()->getHotSpot(hotSpot);
243
244         Ecore_Evas* ecoreEvas = ecore_evas_ecore_evas_get(sd->base.evas);
245         // ecore_evas takes care of freeing the cursor object.
246         ecore_evas_object_cursor_set(ecoreEvas, cursorObject.release().leakRef(), EVAS_LAYER_MAX, hotSpot.x(), hotSpot.y());
247
248         return;
249     }
250
251     // Standard cursor.
252     const char* group = cursor.platformCursor();
253     if (!group || group == m_cursorIdentifier)
254         return;
255
256     m_cursorIdentifier = group;
257     Ewk_View_Smart_Data* sd = smartData();
258     RefPtr<Evas_Object> cursorObject = adoptRef(edje_object_add(sd->base.evas));
259
260     Ecore_Evas* ecoreEvas = ecore_evas_ecore_evas_get(sd->base.evas);
261     if (!m_theme || !edje_object_file_set(cursorObject.get(), m_theme, group)) {
262         ecore_evas_object_cursor_set(ecoreEvas, 0, 0, 0, 0);
263 #ifdef HAVE_ECORE_X
264         if (WebCore::isUsingEcoreX(sd->base.evas))
265             WebCore::applyFallbackCursor(ecoreEvas, group);
266 #endif
267         return;
268     }
269
270     // Set cursor size.
271     Evas_Coord width, height;
272     edje_object_size_min_get(cursorObject.get(), &width, &height);
273     if (width <= 0 || height <= 0)
274         edje_object_size_min_calc(cursorObject.get(), &width, &height);
275     if (width <= 0 || height <= 0) {
276         width = defaultCursorSize;
277         height = defaultCursorSize;
278     }
279     evas_object_resize(cursorObject.get(), width, height);
280
281     // Get cursor hot spot.
282     const char* data;
283     int hotspotX = 0;
284     data = edje_object_data_get(cursorObject.get(), "hot.x");
285     if (data)
286         hotspotX = atoi(data);
287
288     int hotspotY = 0;
289     data = edje_object_data_get(cursorObject.get(), "hot.y");
290     if (data)
291         hotspotY = atoi(data);
292
293     // ecore_evas takes care of freeing the cursor object.
294     ecore_evas_object_cursor_set(ecoreEvas, cursorObject.release().leakRef(), EVAS_LAYER_MAX, hotspotX, hotspotY);
295 }
296
297 void EwkView::setDeviceScaleFactor(float scale)
298 {
299     page()->setIntrinsicDeviceScaleFactor(scale);
300 }
301
302 float EwkView::deviceScaleFactor() const
303 {
304     return m_pageProxy->deviceScaleFactor();
305 }
306
307 AffineTransform EwkView::transformFromScene() const
308 {
309     AffineTransform transform;
310
311 #if USE(TILED_BACKING_STORE)
312     // Note that we apply both page and device scale factors.
313     transform.scale(1 / pageScaleFactor());
314     transform.scale(1 / deviceScaleFactor());
315     transform.translate(pagePosition().x(), pagePosition().y());
316 #endif
317
318     Ewk_View_Smart_Data* sd = smartData();
319     transform.translate(-sd->view.x, -sd->view.y);
320
321     return transform;
322 }
323
324 AffineTransform EwkView::transformToScene() const
325 {
326     return transformFromScene().inverse();
327 }
328
329 AffineTransform EwkView::transformToScreen() const
330 {
331     AffineTransform transform;
332
333     int windowGlobalX = 0;
334     int windowGlobalY = 0;
335
336     Ewk_View_Smart_Data* sd = smartData();
337
338 #ifdef HAVE_ECORE_X
339     Ecore_Evas* ecoreEvas = ecore_evas_ecore_evas_get(sd->base.evas);
340
341     Ecore_X_Window window;
342 #if USE(ACCELERATED_COMPOSITING)
343     window = ecore_evas_gl_x11_window_get(ecoreEvas);
344     // Fallback to software mode if necessary.
345     if (!window)
346 #endif
347     window = ecore_evas_software_x11_window_get(ecoreEvas); // Returns 0 if none.
348
349     int x, y; // x, y are relative to parent (in a reparenting window manager).
350     while (window) {
351         ecore_x_window_geometry_get(window, &x, &y, 0, 0);
352         windowGlobalX += x;
353         windowGlobalY += y;
354         window = ecore_x_window_parent_get(window);
355     }
356 #endif
357
358     transform.translate(-sd->view.x, -sd->view.y);
359     transform.translate(windowGlobalX, windowGlobalY);
360
361     return transform;
362 }
363
364 #if USE(COORDINATED_GRAPHICS)
365 LayerTreeRenderer* EwkView::layerTreeRenderer()
366 {
367     DrawingAreaProxy* drawingArea = page()->drawingArea();
368     if (!drawingArea)
369         return 0;
370
371     WebKit::CoordinatedLayerTreeHostProxy* coordinatedLayerTreeHostProxy = drawingArea->coordinatedLayerTreeHostProxy();
372     if (!coordinatedLayerTreeHostProxy)
373         return 0;
374
375     return coordinatedLayerTreeHostProxy->layerTreeRenderer();
376 }
377 #endif
378
379 void EwkView::displayTimerFired(Timer<EwkView>*)
380 {
381 #if USE(COORDINATED_GRAPHICS)
382     Ewk_View_Smart_Data* sd = smartData();
383
384     if (m_pendingSurfaceResize) {
385         // Create a GL surface here so that Evas has no chance of painting to an empty GL surface.
386         if (!createGLSurface(IntSize(sd->view.w, sd->view.h)))
387             return;
388
389         m_pendingSurfaceResize = false;
390     }
391
392     evas_gl_make_current(m_evasGL.get(), m_evasGLSurface->surface(), m_evasGLContext->context());
393
394     // We are supposed to clip to the actual viewport, nothing less.
395     IntRect viewport(sd->view.x, sd->view.y, sd->view.w, sd->view.h);
396
397     LayerTreeRenderer* renderer = layerTreeRenderer();
398     if (!renderer)
399         return;
400
401     renderer->setActive(true);
402     renderer->setDrawsBackground(m_setDrawsBackground);
403     if (m_isHardwareAccelerated) {
404         renderer->paintToCurrentGLContext(transformToScene().toTransformationMatrix(), /* opacity */ 1, viewport);
405         // sd->image is tied to a native surface. The native surface is in the parent's coordinates,
406         // so we need to account for the viewport position when calling evas_object_image_data_update_add.
407         evas_object_image_data_update_add(sd->image, viewport.x(), viewport.y(), viewport.width(), viewport.height());
408     } else {
409         RefPtr<cairo_surface_t> surface = createSurfaceForImage(sd->image);
410         if (!surface)
411             return;
412
413         RefPtr<cairo_t> graphicsContext = adoptRef(cairo_create(surface.get()));
414         cairo_translate(graphicsContext.get(), - pagePosition().x(), - pagePosition().y());
415         cairo_scale(graphicsContext.get(), pageScaleFactor(), pageScaleFactor());
416         cairo_scale(graphicsContext.get(), deviceScaleFactor(), deviceScaleFactor());
417         renderer->paintToGraphicsContext(graphicsContext.get());
418         evas_object_image_data_update_add(sd->image, 0, 0, viewport.width(), viewport.height());
419     }
420 #endif
421 }
422
423 void EwkView::update(const IntRect& rect)
424 {
425     Ewk_View_Smart_Data* sd = smartData();
426 #if USE(COORDINATED_GRAPHICS)
427     // Coordinated graphices needs to schedule an full update, not
428     // repainting of a region. Update in the event loop.
429     UNUSED_PARAM(rect);
430
431     // Guard for zero sized viewport.
432     if (!(sd->view.w && sd->view.h))
433         return;
434
435     if (!m_displayTimer.isActive())
436         m_displayTimer.startOneShot(0);
437 #else
438     if (!sd->image)
439         return;
440
441     evas_object_image_data_update_add(sd->image, rect.x(), rect.y(), rect.width(), rect.height());
442 #endif
443 }
444
445 #if ENABLE(FULLSCREEN_API)
446 /**
447  * @internal
448  * Calls fullscreen_enter callback or falls back to default behavior and enables fullscreen mode.
449  */
450 void EwkView::enterFullScreen()
451 {
452     Ewk_View_Smart_Data* sd = smartData();
453
454     RefPtr<EwkSecurityOrigin> origin = EwkSecurityOrigin::create(KURL(ParsedURLString, String::fromUTF8(m_url)));
455
456     if (!sd->api->fullscreen_enter || !sd->api->fullscreen_enter(sd, origin.get())) {
457         Ecore_Evas* ecoreEvas = ecore_evas_ecore_evas_get(sd->base.evas);
458         ecore_evas_fullscreen_set(ecoreEvas, true);
459     }
460 }
461
462 /**
463  * @internal
464  * Calls fullscreen_exit callback or falls back to default behavior and disables fullscreen mode.
465  */
466 void EwkView::exitFullScreen()
467 {
468     Ewk_View_Smart_Data* sd = smartData();
469
470     if (!sd->api->fullscreen_exit || !sd->api->fullscreen_exit(sd)) {
471         Ecore_Evas* ecoreEvas = ecore_evas_ecore_evas_get(sd->base.evas);
472         ecore_evas_fullscreen_set(ecoreEvas, false);
473     }
474 }
475 #endif
476
477 WKRect EwkView::windowGeometry() const
478 {
479     Evas_Coord x, y, width, height;
480     Ewk_View_Smart_Data* sd = smartData();
481
482     if (!sd->api->window_geometry_get || !sd->api->window_geometry_get(sd, &x, &y, &width, &height)) {
483         Ecore_Evas* ee = ecore_evas_ecore_evas_get(sd->base.evas);
484         ecore_evas_request_geometry_get(ee, &x, &y, &width, &height);
485     }
486
487     return WKRectMake(x, y, width, height);
488 }
489
490 void EwkView::setWindowGeometry(const WKRect& rect)
491 {
492     Ewk_View_Smart_Data* sd = smartData();
493
494     if (!sd->api->window_geometry_set || !sd->api->window_geometry_set(sd, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height)) {
495         Ecore_Evas* ee = ecore_evas_ecore_evas_get(sd->base.evas);
496         ecore_evas_move_resize(ee, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
497     }
498 }
499
500 void EwkView::setImageData(void* imageData, const IntSize& size)
501 {
502     Ewk_View_Smart_Data* sd = smartData();
503     if (!imageData || !sd->image)
504         return;
505
506     evas_object_resize(sd->image, size.width(), size.height());
507     evas_object_image_size_set(sd->image, size.width(), size.height());
508     evas_object_image_data_copy_set(sd->image, imageData);
509 }
510
511 IntSize EwkView::size() const
512 {
513     int width, height;
514     evas_object_geometry_get(m_evasObject, 0, 0, &width, &height);
515     return IntSize(width, height);
516 }
517
518 bool EwkView::isFocused() const
519 {
520     return evas_object_focus_get(m_evasObject);
521 }
522
523 bool EwkView::isVisible() const
524 {
525     return evas_object_visible_get(m_evasObject);
526 }
527
528 const char* EwkView::title() const
529 {
530     m_title = m_pageProxy->pageTitle().utf8().data();
531
532     return m_title;
533 }
534
535 /**
536  * @internal
537  * This function may return @c NULL.
538  */
539 InputMethodContextEfl* EwkView::inputMethodContext()
540 {
541     return m_inputMethodContext.get();
542 }
543
544 const char* EwkView::themePath() const
545 {
546     return m_theme;
547 }
548
549 void EwkView::setThemePath(const char* theme)
550 {
551     if (m_theme != theme) {
552         m_theme = theme;
553         m_pageProxy->setThemePath(theme);
554     }
555 }
556
557 const char* EwkView::customTextEncodingName() const
558 {
559     String customEncoding = m_pageProxy->customTextEncodingName();
560     if (customEncoding.isEmpty())
561         return 0;
562
563     m_customEncoding = customEncoding.utf8().data();
564
565     return m_customEncoding;
566 }
567
568 void EwkView::setCustomTextEncodingName(const String& encoding)
569 {
570     m_pageProxy->setCustomTextEncodingName(encoding);
571 }
572
573 void EwkView::setMouseEventsEnabled(bool enabled)
574 {
575     if (m_mouseEventsEnabled == enabled)
576         return;
577
578     m_mouseEventsEnabled = enabled;
579     if (enabled) {
580         Ewk_View_Smart_Data* sd = smartData();
581         evas_object_event_callback_add(m_evasObject, EVAS_CALLBACK_MOUSE_DOWN, onMouseDown, sd);
582         evas_object_event_callback_add(m_evasObject, EVAS_CALLBACK_MOUSE_UP, onMouseUp, sd);
583         evas_object_event_callback_add(m_evasObject, EVAS_CALLBACK_MOUSE_MOVE, onMouseMove, sd);
584     } else {
585         evas_object_event_callback_del(m_evasObject, EVAS_CALLBACK_MOUSE_DOWN, onMouseDown);
586         evas_object_event_callback_del(m_evasObject, EVAS_CALLBACK_MOUSE_UP, onMouseUp);
587         evas_object_event_callback_del(m_evasObject, EVAS_CALLBACK_MOUSE_MOVE, onMouseMove);
588     }
589 }
590
591 #if ENABLE(TOUCH_EVENTS)
592 void EwkView::setTouchEventsEnabled(bool enabled)
593 {
594     if (m_touchEventsEnabled == enabled)
595         return;
596
597     m_touchEventsEnabled = enabled;
598
599     if (enabled) {
600         // FIXME: We have to connect touch callbacks with mouse and multi events
601         // because the Evas creates mouse events for first touch and multi events
602         // for second and third touches. Below codes should be fixed when the Evas
603         // supports the touch events.
604         // See https://bugs.webkit.org/show_bug.cgi?id=97785 for details.
605         Ewk_View_Smart_Data* sd = smartData();
606         evas_object_event_callback_add(m_evasObject, EVAS_CALLBACK_MOUSE_DOWN, onTouchDown, sd);
607         evas_object_event_callback_add(m_evasObject, EVAS_CALLBACK_MOUSE_UP, onTouchUp, sd);
608         evas_object_event_callback_add(m_evasObject, EVAS_CALLBACK_MOUSE_MOVE, onTouchMove, sd);
609         evas_object_event_callback_add(m_evasObject, EVAS_CALLBACK_MULTI_DOWN, onTouchDown, sd);
610         evas_object_event_callback_add(m_evasObject, EVAS_CALLBACK_MULTI_UP, onTouchUp, sd);
611         evas_object_event_callback_add(m_evasObject, EVAS_CALLBACK_MULTI_MOVE, onTouchMove, sd);
612     } else {
613         evas_object_event_callback_del(m_evasObject, EVAS_CALLBACK_MOUSE_DOWN, onTouchDown);
614         evas_object_event_callback_del(m_evasObject, EVAS_CALLBACK_MOUSE_UP, onTouchUp);
615         evas_object_event_callback_del(m_evasObject, EVAS_CALLBACK_MOUSE_MOVE, onTouchMove);
616         evas_object_event_callback_del(m_evasObject, EVAS_CALLBACK_MULTI_DOWN, onTouchDown);
617         evas_object_event_callback_del(m_evasObject, EVAS_CALLBACK_MULTI_UP, onTouchUp);
618         evas_object_event_callback_del(m_evasObject, EVAS_CALLBACK_MULTI_MOVE, onTouchMove);
619     }
620 }
621 #endif
622
623 /**
624  * @internal
625  * Update the view's favicon and emits a "icon,changed" signal if it has
626  * changed.
627  *
628  * This function is called whenever the URL has changed or when the icon for
629  * the current page URL has changed.
630  */
631 void EwkView::informIconChange()
632 {
633     EwkFaviconDatabase* iconDatabase = m_context->faviconDatabase();
634     ASSERT(iconDatabase);
635
636     m_faviconURL = ewk_favicon_database_icon_url_get(iconDatabase, m_url);
637     smartCallback<IconChanged>().call();
638 }
639
640 #if USE(ACCELERATED_COMPOSITING)
641 bool EwkView::createGLSurface(const IntSize& viewSize)
642 {
643     if (!m_isHardwareAccelerated)
644         return true;
645
646     if (!m_evasGL) {
647         Evas* evas = evas_object_evas_get(m_evasObject);
648         m_evasGL = adoptPtr(evas_gl_new(evas));
649         if (!m_evasGL) {
650             WARN("Failed to create Evas_GL, falling back to software mode.");
651             m_isHardwareAccelerated = false;
652 #if ENABLE(WEBGL)
653             m_pageProxy->pageGroup()->preferences()->setWebGLEnabled(false);
654 #endif
655             return false;
656         }
657     }
658
659     if (!m_evasGLContext) {
660         m_evasGLContext = EvasGLContext::create(m_evasGL.get());
661         if (!m_evasGLContext) {
662             WARN("Failed to create GLContext.");
663             return false;
664         }
665     }
666
667     Ewk_View_Smart_Data* sd = smartData();
668
669     Evas_GL_Config evasGLConfig = {
670         EVAS_GL_RGBA_8888,
671         EVAS_GL_DEPTH_BIT_8,
672         EVAS_GL_STENCIL_NONE,
673         EVAS_GL_OPTIONS_NONE,
674         EVAS_GL_MULTISAMPLE_NONE
675     };
676
677     // Replaces if non-null, and frees existing surface after (OwnPtr).
678     m_evasGLSurface = EvasGLSurface::create(m_evasGL.get(), &evasGLConfig, viewSize);
679     if (!m_evasGLSurface)
680         return false;
681
682     Evas_Native_Surface nativeSurface;
683     evas_gl_native_surface_get(m_evasGL.get(), m_evasGLSurface->surface(), &nativeSurface);
684     evas_object_image_native_surface_set(sd->image, &nativeSurface);
685
686     evas_gl_make_current(m_evasGL.get(), m_evasGLSurface->surface(), m_evasGLContext->context());
687
688     Evas_GL_API* gl = evas_gl_api_get(m_evasGL.get());
689     gl->glViewport(0, 0, viewSize.width() + sd->view.x, viewSize.height() + sd->view.y);
690     gl->glClearColor(1.0, 1.0, 1.0, 0);
691     gl->glClear(GL_COLOR_BUFFER_BIT);
692
693     return true;
694 }
695
696 bool EwkView::enterAcceleratedCompositingMode()
697 {
698     layerTreeRenderer()->setActive(true);
699
700     if (!m_isHardwareAccelerated)
701         return true;
702
703     if (!m_evasGLSurface) {
704         if (!createGLSurface(size())) {
705             WARN("Failed to create GLSurface.");
706             return false;
707         }
708     }
709
710     return true;
711 }
712
713 bool EwkView::exitAcceleratedCompositingMode()
714 {
715     return true;
716 }
717 #endif
718
719 #if ENABLE(INPUT_TYPE_COLOR)
720 /**
721  * @internal
722  * Requests to show external color picker.
723  */
724 void EwkView::requestColorPicker(WKColorPickerResultListenerRef listener, const WebCore::Color& color)
725 {
726     Ewk_View_Smart_Data* sd = smartData();
727     EINA_SAFETY_ON_NULL_RETURN(sd->api->input_picker_color_request);
728
729     if (!sd->api->input_picker_color_request)
730         return;
731
732     if (m_colorPicker)
733         dismissColorPicker();
734
735     m_colorPicker = EwkColorPicker::create(listener, color);
736
737     sd->api->input_picker_color_request(sd, m_colorPicker.get());
738 }
739
740 /**
741  * @internal
742  * Requests to hide external color picker.
743  */
744 void EwkView::dismissColorPicker()
745 {
746     if (!m_colorPicker)
747         return;
748
749     Ewk_View_Smart_Data* sd = smartData();
750     EINA_SAFETY_ON_NULL_RETURN(sd->api->input_picker_color_dismiss);
751
752     if (sd->api->input_picker_color_dismiss)
753         sd->api->input_picker_color_dismiss(sd);
754
755     m_colorPicker.clear();
756 }
757 #endif
758
759 COMPILE_ASSERT_MATCHING_ENUM(EWK_TEXT_DIRECTION_RIGHT_TO_LEFT, RTL);
760 COMPILE_ASSERT_MATCHING_ENUM(EWK_TEXT_DIRECTION_LEFT_TO_RIGHT, LTR);
761
762 void EwkView::showContextMenu(WebContextMenuProxyEfl* contextMenuProxy, const WebCore::IntPoint& position, const Vector<WebContextMenuItemData>& items)
763 {
764     Ewk_View_Smart_Data* sd = smartData();
765     ASSERT(sd->api);
766
767     ASSERT(contextMenuProxy);
768
769     if (!sd->api->context_menu_show)
770         return;
771
772     if (m_contextMenu)
773         hideContextMenu();
774
775     m_contextMenu = Ewk_Context_Menu::create(this, contextMenuProxy, items);
776
777     sd->api->context_menu_show(sd, position.x(), position.y(), m_contextMenu.get());
778 }
779
780 void EwkView::hideContextMenu()
781 {
782     if (!m_contextMenu)
783         return;
784
785     Ewk_View_Smart_Data* sd = smartData();
786     ASSERT(sd->api);
787
788     if (sd->api->context_menu_hide)
789         sd->api->context_menu_hide(sd);
790
791     m_contextMenu.clear();
792 }
793
794 void EwkView::requestPopupMenu(WebPopupMenuProxyEfl* popupMenuProxy, const IntRect& rect, TextDirection textDirection, double pageScaleFactor, const Vector<WebPopupItem>& items, int32_t selectedIndex)
795 {
796     Ewk_View_Smart_Data* sd = smartData();
797     ASSERT(sd->api);
798
799     ASSERT(popupMenuProxy);
800
801     if (!sd->api->popup_menu_show)
802         return;
803
804     if (m_popupMenu)
805         closePopupMenu();
806
807     m_popupMenu = EwkPopupMenu::create(this, popupMenuProxy, items, selectedIndex);
808
809     sd->api->popup_menu_show(sd, rect, static_cast<Ewk_Text_Direction>(textDirection), pageScaleFactor, m_popupMenu.get());
810 }
811
812 void EwkView::closePopupMenu()
813 {
814     if (!m_popupMenu)
815         return;
816
817     Ewk_View_Smart_Data* sd = smartData();
818     ASSERT(sd->api);
819
820     if (sd->api->popup_menu_hide)
821         sd->api->popup_menu_hide(sd);
822
823     m_popupMenu.clear();
824 }
825
826 /**
827  * @internal
828  * Calls a smart member function for javascript alert().
829  */
830 void EwkView::requestJSAlertPopup(const WKEinaSharedString& message)
831 {
832     Ewk_View_Smart_Data* sd = smartData();
833     ASSERT(sd->api);
834
835     if (!sd->api->run_javascript_alert)
836         return;
837
838     sd->api->run_javascript_alert(sd, message);
839 }
840
841 /**
842  * @internal
843  * Calls a smart member function for javascript confirm() and returns a value from the function. Returns false by default.
844  */
845 bool EwkView::requestJSConfirmPopup(const WKEinaSharedString& message)
846 {
847     Ewk_View_Smart_Data* sd = smartData();
848     ASSERT(sd->api);
849
850     if (!sd->api->run_javascript_confirm)
851         return false;
852
853     return sd->api->run_javascript_confirm(sd, message);
854 }
855
856 /**
857  * @internal
858  * Calls a smart member function for javascript prompt() and returns a value from the function. Returns null string by default.
859  */
860 WKEinaSharedString EwkView::requestJSPromptPopup(const WKEinaSharedString& message, const WKEinaSharedString& defaultValue)
861 {
862     Ewk_View_Smart_Data* sd = smartData();
863     ASSERT(sd->api);
864
865     if (!sd->api->run_javascript_prompt)
866         return WKEinaSharedString();
867
868     return WKEinaSharedString::adopt(sd->api->run_javascript_prompt(sd, message, defaultValue));
869 }
870
871 #if ENABLE(SQL_DATABASE)
872 /**
873  * @internal
874  * Calls exceeded_database_quota callback or falls back to default behavior returns default database quota.
875  */
876 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)
877 {
878     Ewk_View_Smart_Data* sd = smartData();
879     ASSERT(sd->api);
880
881     static const unsigned long long defaultQuota = 5 * 1024 * 1204; // 5 MB
882     if (sd->api->exceeded_database_quota)
883         return sd->api->exceeded_database_quota(sd, databaseName.utf8().data(), displayName.utf8().data(), currentQuota, currentOriginUsage, currentDatabaseUsage, expectedUsage);
884
885     return defaultQuota;
886 }
887 #endif
888
889 /**
890  * @internal
891  * The url of view was changed by the frame loader.
892  *
893  * Emits signal: "url,changed" with pointer to new url string.
894  */
895 void EwkView::informURLChange()
896 {
897     String activeURL = m_pageProxy->activeURL();
898     if (activeURL.isEmpty())
899         return;
900
901     CString rawActiveURL = activeURL.utf8();
902     if (m_url == rawActiveURL.data())
903         return;
904
905     m_url = rawActiveURL.data();
906     smartCallback<URLChanged>().call(m_url);
907
908     // Update the view's favicon.
909     informIconChange();
910 }
911
912 EwkWindowFeatures* EwkView::windowFeatures()
913 {
914     if (!m_windowFeatures)
915         m_windowFeatures = EwkWindowFeatures::create(0, this);
916
917     return m_windowFeatures.get();
918 }
919
920 WKPageRef EwkView::createNewPage(PassRefPtr<EwkUrlRequest> request, WKDictionaryRef windowFeatures)
921 {
922     Ewk_View_Smart_Data* sd = smartData();
923     ASSERT(sd->api);
924
925     if (!sd->api->window_create)
926         return 0;
927
928     RefPtr<EwkWindowFeatures> ewkWindowFeatures = EwkWindowFeatures::create(windowFeatures, this);
929
930     Evas_Object* newEwkView = sd->api->window_create(sd, request->url(), ewkWindowFeatures.get());
931     if (!newEwkView)
932         return 0;
933
934     EwkView* newViewImpl = EwkView::fromEvasObject(newEwkView);
935     ASSERT(newViewImpl);
936
937     newViewImpl->m_windowFeatures = ewkWindowFeatures;
938
939     return static_cast<WKPageRef>(WKRetain(newViewImpl->page()));
940 }
941
942 void EwkView::close()
943 {
944     Ewk_View_Smart_Data* sd = smartData();
945     ASSERT(sd->api);
946
947     if (!sd->api->window_close)
948         return;
949
950     sd->api->window_close(sd);
951 }
952
953 void EwkView::onMouseDown(void* data, Evas*, Evas_Object*, void* eventInfo)
954 {
955     Evas_Event_Mouse_Down* downEvent = static_cast<Evas_Event_Mouse_Down*>(eventInfo);
956     Ewk_View_Smart_Data* sd = static_cast<Ewk_View_Smart_Data*>(data);
957     EINA_SAFETY_ON_NULL_RETURN(sd->api);
958     EINA_SAFETY_ON_NULL_RETURN(sd->api->mouse_down);
959     sd->api->mouse_down(sd, downEvent);
960 }
961
962 void EwkView::onMouseUp(void* data, Evas*, Evas_Object*, void* eventInfo)
963 {
964     Evas_Event_Mouse_Up* upEvent = static_cast<Evas_Event_Mouse_Up*>(eventInfo);
965     Ewk_View_Smart_Data* sd = static_cast<Ewk_View_Smart_Data*>(data);
966     EINA_SAFETY_ON_NULL_RETURN(sd->api);
967     EINA_SAFETY_ON_NULL_RETURN(sd->api->mouse_up);
968     sd->api->mouse_up(sd, upEvent);
969 }
970
971 void EwkView::onMouseMove(void* data, Evas*, Evas_Object*, void* eventInfo)
972 {
973     Evas_Event_Mouse_Move* moveEvent = static_cast<Evas_Event_Mouse_Move*>(eventInfo);
974     Ewk_View_Smart_Data* sd = static_cast<Ewk_View_Smart_Data*>(data);
975     EINA_SAFETY_ON_NULL_RETURN(sd->api);
976     EINA_SAFETY_ON_NULL_RETURN(sd->api->mouse_move);
977     sd->api->mouse_move(sd, moveEvent);
978 }
979
980 #if ENABLE(TOUCH_EVENTS)
981 void EwkView::feedTouchEvents(Ewk_Touch_Event_Type type)
982 {
983     Ewk_View_Smart_Data* sd = smartData();
984
985     unsigned count = evas_touch_point_list_count(sd->base.evas);
986     if (!count)
987         return;
988
989     Eina_List* points = 0;
990     for (unsigned i = 0; i < count; ++i) {
991         Ewk_Touch_Point* point = new Ewk_Touch_Point;
992         point->id = evas_touch_point_list_nth_id_get(sd->base.evas, i);
993         evas_touch_point_list_nth_xy_get(sd->base.evas, i, &point->x, &point->y);
994         point->state = evas_touch_point_list_nth_state_get(sd->base.evas, i);
995         points = eina_list_append(points, point);
996     }
997
998     ewk_view_feed_touch_event(m_evasObject, type, points, evas_key_modifier_get(sd->base.evas));
999
1000     void* data;
1001     EINA_LIST_FREE(points, data)
1002         delete static_cast<Ewk_Touch_Point*>(data);
1003 }
1004
1005 void EwkView::onTouchDown(void* /* data */, Evas* /* canvas */, Evas_Object* ewkView, void* /* eventInfo */)
1006 {
1007     EwkView* view = EwkView::fromEvasObject(ewkView);
1008     view->feedTouchEvents(EWK_TOUCH_START);
1009 }
1010
1011 void EwkView::onTouchUp(void* /* data */, Evas* /* canvas */, Evas_Object* ewkView, void* /* eventInfo */)
1012 {
1013     EwkView* view = EwkView::fromEvasObject(ewkView);
1014     view->feedTouchEvents(EWK_TOUCH_END);
1015 }
1016
1017 void EwkView::onTouchMove(void* /* data */, Evas* /* canvas */, Evas_Object* ewkView, void* /* eventInfo */)
1018 {
1019     EwkView* view = EwkView::fromEvasObject(ewkView);
1020     view->feedTouchEvents(EWK_TOUCH_MOVE);
1021 }
1022 #endif
1023
1024 void EwkView::onFaviconChanged(const char* pageURL, void* eventInfo)
1025 {
1026     EwkView* view = static_cast<EwkView*>(eventInfo);
1027
1028     if (!view->url() || strcasecmp(view->url(), pageURL))
1029         return;
1030
1031     view->informIconChange();
1032 }
1033
1034 PassRefPtr<cairo_surface_t> EwkView::takeSnapshot()
1035 {
1036     // Suspend all animations before taking the snapshot.
1037     m_pageProxy->suspendActiveDOMObjectsAndAnimations();
1038
1039     // Wait for the pending repaint events to be processed.
1040     while (m_displayTimer.isActive())
1041         ecore_main_loop_iterate();
1042
1043     Ewk_View_Smart_Data* sd = smartData();
1044 #if USE(ACCELERATED_COMPOSITING)
1045     if (!m_isHardwareAccelerated) {
1046 #endif
1047         RefPtr<cairo_surface_t> snapshot = createSurfaceForImage(sd->image);
1048         // Resume all animations.
1049         m_pageProxy->resumeActiveDOMObjectsAndAnimations();
1050
1051         return snapshot.release();
1052 #if USE(ACCELERATED_COMPOSITING)
1053     }
1054
1055     RefPtr<cairo_surface_t> snapshot = getImageSurfaceFromFrameBuffer(0, 0, sd->view.w, sd->view.h);
1056     // Resume all animations.
1057     m_pageProxy->resumeActiveDOMObjectsAndAnimations();
1058
1059     return snapshot.release();
1060 #endif
1061 }