1/*
2 * Copyright (C) 2013 Intel Corporation. All rights reserved.
3 * Copyright (C) 2013 Samsung Electronics. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include "config.h"
28#if USE(COORDINATED_GRAPHICS)
29
30#include "WebView.h"
31
32#include "CoordinatedDrawingAreaProxy.h"
33#include "CoordinatedLayerTreeHostProxy.h"
34#include "NotImplemented.h"
35#include "ViewState.h"
36#include "WebContextMenuProxy.h"
37#include "WebPageProxy.h"
38#include <WebCore/CoordinatedGraphicsScene.h>
39
40#if ENABLE(FULLSCREEN_API)
41#include "WebFullScreenManagerProxy.h"
42#endif
43
44using namespace WebCore;
45
46namespace WebKit {
47
48WebView::WebView(WebContext* context, WebPageGroup* pageGroup)
49    : m_focused(false)
50    , m_visible(false)
51    , m_opacity(1.0)
52{
53    WebPageConfiguration webPageConfiguration;
54    webPageConfiguration.pageGroup = pageGroup;
55
56    // Need to call createWebPage after other data members, specifically m_visible, are initialized.
57    m_page = context->createWebPage(*this, WTF::move(webPageConfiguration));
58
59    m_page->pageGroup().preferences().setAcceleratedCompositingEnabled(true);
60    m_page->pageGroup().preferences().setForceCompositingMode(true);
61
62    char* debugVisualsEnvironment = getenv("WEBKIT_SHOW_COMPOSITING_DEBUG_VISUALS");
63    bool showDebugVisuals = debugVisualsEnvironment && !strcmp(debugVisualsEnvironment, "1");
64    m_page->pageGroup().preferences().setCompositingBordersVisible(showDebugVisuals);
65    m_page->pageGroup().preferences().setCompositingRepaintCountersVisible(showDebugVisuals);
66}
67
68WebView::~WebView()
69{
70    if (m_page->isClosed())
71        return;
72
73    m_page->close();
74}
75
76void WebView::initialize()
77{
78    m_page->initializeWebPage();
79    setActive(true);
80}
81
82void WebView::setContentScaleFactor(float scaleFactor)
83{
84    m_page->scalePage(scaleFactor, roundedIntPoint(contentPosition()));
85    updateViewportSize();
86}
87
88void WebView::setActive(bool active)
89{
90    CoordinatedGraphicsScene* scene = coordinatedGraphicsScene();
91    if (!scene || scene->isActive() == active)
92        return;
93
94    scene->setActive(active);
95    m_page->viewStateDidChange(ViewState::WindowIsActive);
96}
97
98void WebView::setSize(const WebCore::IntSize& size)
99{
100    if (m_size == size)
101        return;
102
103    m_size = size;
104
105    updateViewportSize();
106}
107
108void WebView::setFocused(bool focused)
109{
110    if (m_focused == focused)
111        return;
112
113    m_focused = focused;
114    m_page->viewStateDidChange(ViewState::IsFocused | ViewState::WindowIsActive);
115}
116
117void WebView::setVisible(bool visible)
118{
119    if (m_visible == visible)
120        return;
121
122    m_visible = visible;
123    m_page->viewStateDidChange(ViewState::IsVisible);
124
125    if (CoordinatedDrawingAreaProxy* drawingArea = static_cast<CoordinatedDrawingAreaProxy*>(page()->drawingArea()))
126        drawingArea->visibilityDidChange();
127}
128
129void WebView::setUserViewportTranslation(double tx, double ty)
130{
131    m_userViewportTransform = TransformationMatrix().translate(tx, ty);
132}
133
134IntPoint WebView::userViewportToContents(const IntPoint& point) const
135{
136    return transformFromScene().mapPoint(point);
137}
138
139IntPoint WebView::userViewportToScene(const WebCore::IntPoint& point) const
140{
141    return m_userViewportTransform.mapPoint(point);
142}
143
144IntPoint WebView::contentsToUserViewport(const IntPoint& point) const
145{
146    return transformToScene().mapPoint(point);
147}
148
149void WebView::paintToCurrentGLContext()
150{
151    CoordinatedGraphicsScene* scene = coordinatedGraphicsScene();
152    if (!scene)
153        return;
154
155    // FIXME: We need to clean up this code as it is split over CoordGfx and Page.
156    scene->setDrawsBackground(m_page->drawsBackground());
157    const FloatRect& viewport = m_userViewportTransform.mapRect(IntRect(IntPoint(), m_size));
158
159    scene->paintToCurrentGLContext(transformToScene().toTransformationMatrix(), m_opacity, viewport);
160}
161
162void WebView::setDrawsBackground(bool drawsBackground)
163{
164    m_page->setDrawsBackground(drawsBackground);
165}
166
167bool WebView::drawsBackground() const
168{
169    return m_page->drawsBackground();
170}
171
172void WebView::setDrawsTransparentBackground(bool transparentBackground)
173{
174    m_page->setDrawsTransparentBackground(transparentBackground);
175}
176
177bool WebView::drawsTransparentBackground() const
178{
179    return m_page->drawsTransparentBackground();
180}
181
182void WebView::suspendActiveDOMObjectsAndAnimations()
183{
184    m_page->suspendActiveDOMObjectsAndAnimations();
185}
186
187void WebView::resumeActiveDOMObjectsAndAnimations()
188{
189    m_page->resumeActiveDOMObjectsAndAnimations();
190}
191
192#if ENABLE(FULLSCREEN_API)
193WebFullScreenManagerProxyClient& WebView::fullScreenManagerProxyClient()
194{
195    return *this;
196}
197
198bool WebView::requestExitFullScreen()
199{
200    if (!isFullScreen())
201        return false;
202
203    m_page->fullScreenManager()->requestExitFullScreen();
204    return true;
205}
206#endif
207
208void WebView::initializeClient(const WKViewClientBase* client)
209{
210    m_client.initialize(client);
211}
212
213void WebView::didChangeContentSize(const WebCore::IntSize& size)
214{
215    if (m_contentsSize == size)
216        return;
217
218    m_contentsSize = size;
219    m_client.didChangeContentsSize(this, size);
220
221    updateViewportSize();
222}
223
224void WebView::didFindZoomableArea(const WebCore::IntPoint& target, const WebCore::IntRect& area)
225{
226    m_client.didFindZoomableArea(this, target, area);
227}
228
229AffineTransform WebView::transformFromScene() const
230{
231    return transformToScene().inverse();
232}
233
234AffineTransform WebView::transformToScene() const
235{
236    FloatPoint position = -m_contentPosition;
237    float effectiveScale = m_page->deviceScaleFactor();
238    if (m_page->useFixedLayout())
239        effectiveScale *= contentScaleFactor();
240    position.scale(effectiveScale, effectiveScale);
241
242    TransformationMatrix transform = m_userViewportTransform;
243    transform.translate(position.x(), position.y());
244    transform.scale(effectiveScale);
245
246    return transform.toAffineTransform();
247}
248
249CoordinatedGraphicsScene* WebView::coordinatedGraphicsScene()
250{
251    if (CoordinatedDrawingAreaProxy* drawingArea = static_cast<CoordinatedDrawingAreaProxy*>(page()->drawingArea()))
252        return drawingArea->coordinatedLayerTreeHostProxy().coordinatedGraphicsScene();
253
254    return nullptr;
255}
256
257void WebView::updateViewportSize()
258{
259    if (CoordinatedDrawingAreaProxy* drawingArea = static_cast<CoordinatedDrawingAreaProxy*>(page()->drawingArea())) {
260        // Web Process expects sizes in UI units, and not raw device units.
261        drawingArea->setSize(roundedIntSize(dipSize()), IntSize(), IntSize());
262        FloatRect visibleContentsRect(contentPosition(), visibleContentsSize());
263        visibleContentsRect.intersect(FloatRect(FloatPoint(), contentsSize()));
264        drawingArea->setVisibleContentsRect(visibleContentsRect, FloatPoint());
265    }
266}
267
268inline WebCore::FloatSize WebView::dipSize() const
269{
270    FloatSize dipSize(size());
271    dipSize.scale(1 / m_page->deviceScaleFactor());
272
273    return dipSize;
274}
275
276WebCore::FloatSize WebView::visibleContentsSize() const
277{
278    FloatSize visibleContentsSize(dipSize());
279    if (m_page->useFixedLayout())
280        visibleContentsSize.scale(1 / contentScaleFactor());
281
282    return visibleContentsSize;
283}
284
285// Page Client
286
287std::unique_ptr<DrawingAreaProxy> WebView::createDrawingAreaProxy()
288{
289    return std::make_unique<CoordinatedDrawingAreaProxy>(page());
290}
291
292void WebView::setViewNeedsDisplay(const WebCore::IntRect& area)
293{
294    m_client.viewNeedsDisplay(this, area);
295}
296
297void WebView::displayView()
298{
299    notImplemented();
300}
301
302void WebView::scrollView(const WebCore::IntRect& scrollRect, const WebCore::IntSize&)
303{
304    setViewNeedsDisplay(scrollRect);
305}
306
307void WebView::requestScroll(const WebCore::FloatPoint&, bool)
308{
309    notImplemented();
310}
311
312WebCore::IntSize WebView::viewSize()
313{
314    return roundedIntSize(dipSize());
315}
316
317bool WebView::isActive() const
318{
319    const CoordinatedGraphicsScene* scene = const_cast<WebView*>(this)->coordinatedGraphicsScene();
320    if (!scene)
321        return false;
322
323    return scene->isActive();
324}
325
326bool WebView::isViewWindowActive()
327{
328    notImplemented();
329    return true;
330}
331
332bool WebView::isViewFocused()
333{
334    return isFocused();
335}
336
337bool WebView::isViewVisible()
338{
339    return isVisible();
340}
341
342bool WebView::isViewInWindow()
343{
344    notImplemented();
345    return true;
346}
347
348void WebView::processDidExit()
349{
350    m_client.webProcessCrashed(this, m_page->urlAtProcessExit());
351}
352
353void WebView::didRelaunchProcess()
354{
355    m_client.webProcessDidRelaunch(this);
356}
357
358void WebView::pageClosed()
359{
360    notImplemented();
361}
362
363void WebView::preferencesDidChange()
364{
365    notImplemented();
366}
367
368void WebView::toolTipChanged(const String&, const String& newToolTip)
369{
370    m_client.didChangeTooltip(this, newToolTip);
371}
372
373void WebView::didCommitLoadForMainFrame(const String&, bool)
374{
375    setContentPosition(WebCore::FloatPoint());
376    m_contentsSize = IntSize();
377}
378
379void WebView::setCursor(const WebCore::Cursor&)
380{
381    notImplemented();
382}
383
384void WebView::setCursorHiddenUntilMouseMoves(bool)
385{
386    notImplemented();
387}
388
389void WebView::registerEditCommand(PassRefPtr<WebEditCommandProxy> command, WebPageProxy::UndoOrRedo undoOrRedo)
390{
391    m_undoController.registerEditCommand(command, undoOrRedo);
392}
393
394void WebView::clearAllEditCommands()
395{
396    m_undoController.clearAllEditCommands();
397}
398
399bool WebView::canUndoRedo(WebPageProxy::UndoOrRedo undoOrRedo)
400{
401    return m_undoController.canUndoRedo(undoOrRedo);
402}
403
404void WebView::executeUndoRedo(WebPageProxy::UndoOrRedo undoOrRedo)
405{
406    m_undoController.executeUndoRedo(undoOrRedo);
407}
408
409IntPoint WebView::screenToRootView(const IntPoint& point)
410{
411    notImplemented();
412    return point;
413}
414
415IntRect WebView::rootViewToScreen(const IntRect&)
416{
417    notImplemented();
418    return IntRect();
419}
420
421void WebView::doneWithKeyEvent(const NativeWebKeyboardEvent&, bool)
422{
423    notImplemented();
424}
425
426#if ENABLE(TOUCH_EVENTS)
427void WebView::doneWithTouchEvent(const NativeWebTouchEvent& event, bool wasEventHandled)
428{
429    m_client.doneWithTouchEvent(this, event, wasEventHandled);
430}
431#endif
432
433PassRefPtr<WebPopupMenuProxy> WebView::createPopupMenuProxy(WebPageProxy*)
434{
435    notImplemented();
436    return 0;
437}
438
439PassRefPtr<WebContextMenuProxy> WebView::createContextMenuProxy(WebPageProxy*)
440{
441    notImplemented();
442    return 0;
443}
444
445#if ENABLE(INPUT_TYPE_COLOR)
446PassRefPtr<WebColorPicker> WebView::createColorPicker(WebPageProxy*, const WebCore::Color&, const WebCore::IntRect&)
447{
448    notImplemented();
449    return 0;
450}
451#endif
452
453void WebView::setFindIndicator(PassRefPtr<FindIndicator>, bool, bool)
454{
455    notImplemented();
456}
457
458void WebView::enterAcceleratedCompositingMode(const LayerTreeContext&)
459{
460    setActive(true);
461}
462
463void WebView::exitAcceleratedCompositingMode()
464{
465    setActive(false);
466}
467
468void WebView::updateAcceleratedCompositingMode(const LayerTreeContext&)
469{
470    notImplemented();
471}
472
473void WebView::updateTextInputState()
474{
475    notImplemented();
476}
477
478void WebView::handleDownloadRequest(DownloadProxy*)
479{
480    notImplemented();
481}
482
483FloatRect WebView::convertToDeviceSpace(const FloatRect& userRect)
484{
485    if (m_page->useFixedLayout()) {
486        FloatRect result = userRect;
487        result.scale(m_page->deviceScaleFactor());
488        return result;
489    }
490    // Legacy mode.
491    notImplemented();
492    return userRect;
493}
494
495FloatRect WebView::convertToUserSpace(const FloatRect& deviceRect)
496{
497    if (m_page->useFixedLayout()) {
498        FloatRect result = deviceRect;
499        result.scale(1 / m_page->deviceScaleFactor());
500        return result;
501    }
502    // Legacy mode.
503    notImplemented();
504    return deviceRect;
505}
506
507void WebView::didChangeViewportProperties(const WebCore::ViewportAttributes& attr)
508{
509    m_client.didChangeViewportAttributes(this, attr);
510}
511
512void WebView::pageDidRequestScroll(const IntPoint& position)
513{
514    FloatPoint uiPosition(position);
515    setContentPosition(uiPosition);
516
517    m_client.didChangeContentsPosition(this, position);
518}
519
520void WebView::didRenderFrame(const WebCore::IntSize& contentsSize, const WebCore::IntRect& coveredRect)
521{
522    m_client.didRenderFrame(this, contentsSize, coveredRect);
523}
524
525void WebView::pageTransitionViewportReady()
526{
527    m_client.didCompletePageTransition(this);
528}
529
530void WebView::findZoomableAreaForPoint(const IntPoint& point, const IntSize& size)
531{
532    m_page->findZoomableAreaForPoint(transformFromScene().mapPoint(point), transformFromScene().mapSize(size));
533}
534
535} // namespace WebKit
536
537#endif // USE(COORDINATED_GRAPHICS)
538
539