1/*
2 * Copyright (C) 2013 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 *     * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *     * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 *     * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include "config.h"
32#include "PinchViewports.h"
33
34#include "WebSettingsImpl.h"
35#include "WebViewImpl.h"
36#include "core/page/FrameView.h"
37#include "core/platform/graphics/FloatSize.h"
38#include "core/platform/graphics/GraphicsLayer.h"
39#include "core/rendering/RenderLayerCompositor.h"
40#include "public/platform/Platform.h"
41#include "public/platform/WebCompositorSupport.h"
42#include "public/platform/WebLayerTreeView.h"
43#include "public/platform/WebScrollbarLayer.h"
44
45using WebCore::GraphicsLayer;
46
47namespace WebKit {
48
49PassOwnPtr<PinchViewports> PinchViewports::create(WebViewImpl* owner)
50{
51    return adoptPtr(new PinchViewports(owner));
52}
53
54PinchViewports::PinchViewports(WebViewImpl* owner)
55    : m_owner(owner)
56    , m_innerViewportContainerLayer(GraphicsLayer::create(m_owner->graphicsLayerFactory(), this))
57    , m_pageScaleLayer(GraphicsLayer::create(m_owner->graphicsLayerFactory(), this))
58    , m_innerViewportScrollLayer(GraphicsLayer::create(m_owner->graphicsLayerFactory(), this))
59    , m_overlayScrollbarHorizontal(GraphicsLayer::create(m_owner->graphicsLayerFactory(), this))
60    , m_overlayScrollbarVertical(GraphicsLayer::create(m_owner->graphicsLayerFactory(), this))
61{
62    m_innerViewportContainerLayer->platformLayer()->setIsContainerForFixedPositionLayers(true);
63    // No need for the inner viewport to clip, since the compositing
64    // surface takes care of it -- and clipping here would interfere with
65    // dynamically-sized viewports on Android.
66    m_innerViewportContainerLayer->setMasksToBounds(false);
67
68    m_innerViewportScrollLayer->platformLayer()->setScrollable(true);
69
70#ifndef NDEBUG
71    m_innerViewportContainerLayer->setName("inner viewport container layer");
72    m_pageScaleLayer->setName("page scale layer");
73    m_innerViewportScrollLayer->setName("inner viewport scroll layer");
74    m_overlayScrollbarHorizontal->setName("overlay scrollbar horizontal");
75    m_overlayScrollbarVertical->setName("overlay scrollbar vertical");
76#endif
77
78    m_innerViewportContainerLayer->addChild(m_pageScaleLayer.get());
79    m_pageScaleLayer->addChild(m_innerViewportScrollLayer.get());
80    m_innerViewportContainerLayer->addChild(m_overlayScrollbarHorizontal.get());
81    m_innerViewportContainerLayer->addChild(m_overlayScrollbarVertical.get());
82
83    // Setup the inner viewport overlay scrollbars.
84    setupScrollbar(WebScrollbar::Horizontal);
85    setupScrollbar(WebScrollbar::Vertical);
86}
87
88PinchViewports::~PinchViewports() { }
89
90void PinchViewports::setViewportSize(const WebCore::IntSize& newSize)
91{
92    m_innerViewportContainerLayer->setSize(newSize);
93
94    // Need to re-compute sizes for the overlay scrollbars.
95    setupScrollbar(WebScrollbar::Horizontal);
96    setupScrollbar(WebScrollbar::Vertical);
97}
98
99// Modifies the top of the graphics layer tree to add layers needed to support
100// the inner/outer viewport fixed-position model for pinch zoom. When finished,
101// the tree will look like this (with * denoting added layers):
102//
103// *innerViewportContainerLayer (fixed pos container)
104//  +- *pageScaleLayer
105//  |   +- *innerViewportScrollLayer
106//  |       +-- overflowControlsHostLayer (root layer)
107//  |           +-- outerViewportContainerLayer (fixed pos container) [frame container layer in RenderLayerCompositor]
108//  |           |   +-- outerViewportScrollLayer [frame scroll layer in RenderLayerCompositor]
109//  |           |       +-- content layers ...
110//  |           +-- horizontal ScrollbarLayer (non-overlay)
111//  |           +-- verticalScrollbarLayer (non-overlay)
112//  |           +-- scroll corner (non-overlay)
113//  +- *horizontalScrollbarLayer (overlay)
114//  +- *verticalScrollbarLayer (overlay)
115//
116void PinchViewports::setOverflowControlsHostLayer(GraphicsLayer* layer)
117{
118    if (layer) {
119        ASSERT(!m_innerViewportScrollLayer->children().size());
120        m_innerViewportScrollLayer->addChild(layer);
121    } else {
122        m_innerViewportScrollLayer->removeAllChildren();
123        return;
124    }
125
126    WebCore::Page* page = m_owner->page();
127    if (!page)
128        return;
129
130    // We only need to disable the existing (outer viewport) scrollbars
131    // if the existing ones are already overlay.
132    // FIXME: If we knew in advance before the overflowControlsHostLayer goes
133    // away, we would re-enable the drawing of these scrollbars.
134    if (GraphicsLayer* scrollbar = m_owner->compositor()->layerForHorizontalScrollbar())
135        scrollbar->setDrawsContent(!page->mainFrame()->view()->hasOverlayScrollbars());
136    if (GraphicsLayer* scrollbar = m_owner->compositor()->layerForVerticalScrollbar())
137        scrollbar->setDrawsContent(!page->mainFrame()->view()->hasOverlayScrollbars());
138}
139
140void PinchViewports::setupScrollbar(WebScrollbar::Orientation orientation)
141{
142    bool isHorizontal = orientation == WebScrollbar::Horizontal;
143    GraphicsLayer* scrollbarGraphicsLayer = isHorizontal ?
144        m_overlayScrollbarHorizontal.get() : m_overlayScrollbarVertical.get();
145
146    const int overlayScrollbarThickness = m_owner->settingsImpl()->pinchOverlayScrollbarThickness();
147
148    int xPosition = isHorizontal ? 0 : m_innerViewportContainerLayer->size().width() - overlayScrollbarThickness;
149    int yPosition = isHorizontal ? m_innerViewportContainerLayer->size().height() - overlayScrollbarThickness : 0;
150    int width = isHorizontal ? m_innerViewportContainerLayer->size().width() - overlayScrollbarThickness : overlayScrollbarThickness;
151    int height = isHorizontal ? overlayScrollbarThickness : m_innerViewportContainerLayer->size().height() - overlayScrollbarThickness;
152
153    scrollbarGraphicsLayer->setPosition(WebCore::IntPoint(xPosition, yPosition));
154    scrollbarGraphicsLayer->setSize(WebCore::IntSize(width, height));
155}
156
157void PinchViewports::registerViewportLayersWithTreeView(WebLayerTreeView* layerTreeView) const
158{
159    if (!layerTreeView)
160        return;
161
162    WebCore::RenderLayerCompositor* compositor = m_owner->compositor();
163    ASSERT(compositor);
164    layerTreeView->registerPinchViewportLayers(
165        m_innerViewportContainerLayer->platformLayer(),
166        m_pageScaleLayer->platformLayer(),
167        m_innerViewportScrollLayer->platformLayer(),
168        compositor->scrollLayer()->platformLayer(),
169        m_overlayScrollbarHorizontal->platformLayer(),
170        m_overlayScrollbarVertical->platformLayer());
171}
172
173void PinchViewports::clearViewportLayersForTreeView(WebLayerTreeView* layerTreeView) const
174{
175    if (!layerTreeView)
176        return;
177
178    layerTreeView->clearPinchViewportLayers();
179}
180
181void PinchViewports::notifyAnimationStarted(const GraphicsLayer*, double time)
182{
183}
184
185void PinchViewports::paintContents(const GraphicsLayer*, WebCore::GraphicsContext&, WebCore::GraphicsLayerPaintingPhase, const WebCore::IntRect& inClip)
186{
187}
188
189} // namespace WebKit
190