Home | History | Annotate | Download | only in web
      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/frame/Frame.h"
     37 #include "core/frame/FrameView.h"
     38 #include "core/page/scrolling/ScrollingCoordinator.h"
     39 #include "core/rendering/RenderLayerCompositor.h"
     40 #include "platform/geometry/FloatSize.h"
     41 #include "platform/graphics/GraphicsLayer.h"
     42 #include "platform/scroll/Scrollbar.h"
     43 #include "public/platform/Platform.h"
     44 #include "public/platform/WebCompositorSupport.h"
     45 #include "public/platform/WebLayer.h"
     46 #include "public/platform/WebLayerTreeView.h"
     47 #include "public/platform/WebScrollbarLayer.h"
     48 
     49 using WebCore::GraphicsLayer;
     50 
     51 namespace blink {
     52 
     53 PassOwnPtr<PinchViewports> PinchViewports::create(WebViewImpl* owner)
     54 {
     55     return adoptPtr(new PinchViewports(owner));
     56 }
     57 
     58 PinchViewports::PinchViewports(WebViewImpl* owner)
     59     : m_owner(owner)
     60     , m_innerViewportContainerLayer(GraphicsLayer::create(m_owner->graphicsLayerFactory(), this))
     61     , m_pageScaleLayer(GraphicsLayer::create(m_owner->graphicsLayerFactory(), this))
     62     , m_innerViewportScrollLayer(GraphicsLayer::create(m_owner->graphicsLayerFactory(), this))
     63     , m_overlayScrollbarHorizontal(GraphicsLayer::create(m_owner->graphicsLayerFactory(), this))
     64     , m_overlayScrollbarVertical(GraphicsLayer::create(m_owner->graphicsLayerFactory(), this))
     65 {
     66     m_innerViewportContainerLayer->platformLayer()->setIsContainerForFixedPositionLayers(true);
     67     // No need for the inner viewport to clip, since the compositing
     68     // surface takes care of it -- and clipping here would interfere with
     69     // dynamically-sized viewports on Android.
     70     m_innerViewportContainerLayer->setMasksToBounds(false);
     71 
     72     m_innerViewportScrollLayer->platformLayer()->setScrollable(true);
     73     m_innerViewportScrollLayer->platformLayer()->setUserScrollable(true, true);
     74 
     75     m_innerViewportContainerLayer->addChild(m_pageScaleLayer.get());
     76     m_pageScaleLayer->addChild(m_innerViewportScrollLayer.get());
     77     m_innerViewportContainerLayer->addChild(m_overlayScrollbarHorizontal.get());
     78     m_innerViewportContainerLayer->addChild(m_overlayScrollbarVertical.get());
     79 
     80     // Setup the inner viewport overlay scrollbars.
     81     setupScrollbar(WebScrollbar::Horizontal);
     82     setupScrollbar(WebScrollbar::Vertical);
     83 }
     84 
     85 PinchViewports::~PinchViewports() { }
     86 
     87 void PinchViewports::setViewportSize(const WebCore::IntSize& newSize)
     88 {
     89     m_innerViewportContainerLayer->setSize(newSize);
     90 
     91     // Need to re-compute sizes for the overlay scrollbars.
     92     setupScrollbar(WebScrollbar::Horizontal);
     93     setupScrollbar(WebScrollbar::Vertical);
     94 }
     95 
     96 // Modifies the top of the graphics layer tree to add layers needed to support
     97 // the inner/outer viewport fixed-position model for pinch zoom. When finished,
     98 // the tree will look like this (with * denoting added layers):
     99 //
    100 // *innerViewportContainerLayer (fixed pos container)
    101 //  +- *pageScaleLayer
    102 //  |   +- *innerViewportScrollLayer
    103 //  |       +-- overflowControlsHostLayer (root layer)
    104 //  |           +-- outerViewportContainerLayer (fixed pos container) [frame container layer in RenderLayerCompositor]
    105 //  |           |   +-- outerViewportScrollLayer [frame scroll layer in RenderLayerCompositor]
    106 //  |           |       +-- content layers ...
    107 //  |           +-- horizontal ScrollbarLayer (non-overlay)
    108 //  |           +-- verticalScrollbarLayer (non-overlay)
    109 //  |           +-- scroll corner (non-overlay)
    110 //  +- *horizontalScrollbarLayer (overlay)
    111 //  +- *verticalScrollbarLayer (overlay)
    112 //
    113 void PinchViewports::setOverflowControlsHostLayer(GraphicsLayer* layer)
    114 {
    115     if (layer) {
    116         ASSERT(!m_innerViewportScrollLayer->children().size());
    117         m_innerViewportScrollLayer->addChild(layer);
    118     } else {
    119         m_innerViewportScrollLayer->removeAllChildren();
    120         return;
    121     }
    122 
    123     WebCore::Page* page = m_owner->page();
    124     if (!page)
    125         return;
    126 
    127     // We only need to disable the existing (outer viewport) scrollbars
    128     // if the existing ones are already overlay.
    129     // FIXME: If we knew in advance before the overflowControlsHostLayer goes
    130     // away, we would re-enable the drawing of these scrollbars.
    131     if (GraphicsLayer* scrollbar = m_owner->compositor()->layerForHorizontalScrollbar())
    132         scrollbar->setDrawsContent(!page->mainFrame()->view()->hasOverlayScrollbars());
    133     if (GraphicsLayer* scrollbar = m_owner->compositor()->layerForVerticalScrollbar())
    134         scrollbar->setDrawsContent(!page->mainFrame()->view()->hasOverlayScrollbars());
    135 }
    136 
    137 void PinchViewports::setupScrollbar(WebScrollbar::Orientation orientation)
    138 {
    139     bool isHorizontal = orientation == WebScrollbar::Horizontal;
    140     GraphicsLayer* scrollbarGraphicsLayer = isHorizontal ?
    141         m_overlayScrollbarHorizontal.get() : m_overlayScrollbarVertical.get();
    142     OwnPtr<WebScrollbarLayer>& webScrollbarLayer = isHorizontal ?
    143         m_webOverlayScrollbarHorizontal : m_webOverlayScrollbarVertical;
    144 
    145     const int overlayScrollbarThickness = m_owner->settingsImpl()->pinchOverlayScrollbarThickness();
    146 
    147     if (!webScrollbarLayer) {
    148         WebCore::ScrollingCoordinator* coordinator = m_owner->page()->scrollingCoordinator();
    149         ASSERT(coordinator);
    150         WebCore::ScrollbarOrientation webcoreOrientation = isHorizontal ? WebCore::HorizontalScrollbar : WebCore::VerticalScrollbar;
    151         webScrollbarLayer = coordinator->createSolidColorScrollbarLayer(webcoreOrientation, overlayScrollbarThickness, false);
    152 
    153         webScrollbarLayer->setScrollLayer(m_innerViewportScrollLayer->platformLayer());
    154         scrollbarGraphicsLayer->setContentsToPlatformLayer(webScrollbarLayer->layer());
    155         scrollbarGraphicsLayer->setDrawsContent(false);
    156     }
    157 
    158     int xPosition = isHorizontal ? 0 : m_innerViewportContainerLayer->size().width() - overlayScrollbarThickness;
    159     int yPosition = isHorizontal ? m_innerViewportContainerLayer->size().height() - overlayScrollbarThickness : 0;
    160     int width = isHorizontal ? m_innerViewportContainerLayer->size().width() - overlayScrollbarThickness : overlayScrollbarThickness;
    161     int height = isHorizontal ? overlayScrollbarThickness : m_innerViewportContainerLayer->size().height() - overlayScrollbarThickness;
    162 
    163     scrollbarGraphicsLayer->setPosition(WebCore::IntPoint(xPosition, yPosition));
    164     scrollbarGraphicsLayer->setSize(WebCore::IntSize(width, height));
    165 }
    166 
    167 void PinchViewports::registerViewportLayersWithTreeView(WebLayerTreeView* layerTreeView) const
    168 {
    169     ASSERT(layerTreeView);
    170 
    171     WebCore::RenderLayerCompositor* compositor = m_owner->compositor();
    172     GraphicsLayer* scrollLayer = compositor->scrollLayer();
    173 
    174     ASSERT(compositor);
    175     layerTreeView->registerViewportLayers(
    176         m_pageScaleLayer->platformLayer(),
    177         m_innerViewportScrollLayer->platformLayer(),
    178         scrollLayer->platformLayer());
    179 }
    180 
    181 void PinchViewports::clearViewportLayersForTreeView(WebLayerTreeView* layerTreeView) const
    182 {
    183     ASSERT(layerTreeView);
    184 
    185     layerTreeView->clearViewportLayers();
    186 }
    187 
    188 void PinchViewports::notifyAnimationStarted(const GraphicsLayer*, double wallClockTime, double monotonicTime)
    189 {
    190 }
    191 
    192 void PinchViewports::paintContents(const GraphicsLayer*, WebCore::GraphicsContext&, WebCore::GraphicsLayerPaintingPhase, const WebCore::IntRect& inClip)
    193 {
    194 }
    195 
    196 String PinchViewports::debugName(const GraphicsLayer* graphicsLayer)
    197 {
    198     String name;
    199     if (graphicsLayer == m_innerViewportContainerLayer.get()) {
    200         name = "Inner Viewport Container Layer";
    201     } else if (graphicsLayer == m_pageScaleLayer.get()) {
    202         name =  "Page Scale Layer";
    203     } else if (graphicsLayer == m_innerViewportScrollLayer.get()) {
    204         name =  "Inner Viewport Scroll Layer";
    205     } else if (graphicsLayer == m_overlayScrollbarHorizontal.get()) {
    206         name =  "Overlay Scrollbar Horizontal Layer";
    207     } else if (graphicsLayer == m_overlayScrollbarVertical.get()) {
    208         name =  "Overlay Scrollbar Vertical Layer";
    209     } else {
    210         ASSERT_NOT_REACHED();
    211     }
    212 
    213     return name;
    214 }
    215 
    216 } // namespace blink
    217