1/* 2 * Copyright (C) 2014 Apple 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 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 23 * THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include "config.h" 27#include "PageOverlayController.h" 28 29#include "DrawingArea.h" 30#include "PageOverlay.h" 31#include "WebPage.h" 32#include <WebCore/Frame.h> 33#include <WebCore/FrameView.h> 34#include <WebCore/GraphicsContext.h> 35#include <WebCore/GraphicsLayer.h> 36#include <WebCore/MainFrame.h> 37#include <WebCore/ScrollingCoordinator.h> 38#include <WebCore/Settings.h> 39#include <WebCore/TiledBacking.h> 40 41using namespace WebCore; 42 43namespace WebKit { 44 45PageOverlayController::PageOverlayController(WebPage& webPage) 46 : m_webPage(webPage) 47{ 48} 49 50void PageOverlayController::initialize() 51{ 52 ASSERT(!m_documentOverlayRootLayer); 53 ASSERT(!m_viewOverlayRootLayer); 54 55 m_documentOverlayRootLayer = GraphicsLayer::create(m_webPage.drawingArea()->graphicsLayerFactory(), *this); 56 m_viewOverlayRootLayer = GraphicsLayer::create(m_webPage.drawingArea()->graphicsLayerFactory(), *this); 57#ifndef NDEBUG 58 m_documentOverlayRootLayer->setName("Page Overlay container (document-relative)"); 59 m_viewOverlayRootLayer->setName("Page Overlay container (view-relative)"); 60#endif 61} 62 63static void updateOverlayGeometry(PageOverlay& overlay, GraphicsLayer& graphicsLayer) 64{ 65 IntRect overlayFrame = overlay.frame(); 66 67 if (overlayFrame.location() == graphicsLayer.position() && overlayFrame.size() == graphicsLayer.size()) 68 return; 69 70 graphicsLayer.setPosition(overlayFrame.location()); 71 graphicsLayer.setSize(overlayFrame.size()); 72} 73 74void PageOverlayController::installPageOverlay(PassRefPtr<PageOverlay> pageOverlay, PageOverlay::FadeMode fadeMode) 75{ 76 ASSERT(m_documentOverlayRootLayer); 77 ASSERT(m_viewOverlayRootLayer); 78 79 RefPtr<PageOverlay> overlay = pageOverlay; 80 81 if (m_pageOverlays.contains(overlay)) 82 return; 83 84 m_pageOverlays.append(overlay); 85 overlay->setPage(&m_webPage); 86 87 if (fadeMode == PageOverlay::FadeMode::Fade) 88 overlay->startFadeInAnimation(); 89 90 std::unique_ptr<GraphicsLayer> layer = GraphicsLayer::create(m_webPage.drawingArea()->graphicsLayerFactory(), *this); 91 layer->setAnchorPoint(FloatPoint3D()); 92 layer->setBackgroundColor(overlay->backgroundColor()); 93 updateOverlayGeometry(*overlay, *layer); 94#ifndef NDEBUG 95 layer->setName("Page Overlay content"); 96#endif 97 98 updateSettingsForLayer(*layer); 99 100 switch (overlay->overlayType()) { 101 case PageOverlay::OverlayType::View: 102 m_viewOverlayRootLayer->addChild(layer.get()); 103 break; 104 case PageOverlay::OverlayType::Document: 105 m_documentOverlayRootLayer->addChild(layer.get()); 106 break; 107 } 108 109 m_overlayGraphicsLayers.set(overlay.get(), WTF::move(layer)); 110 111 updateForceSynchronousScrollLayerPositionUpdates(); 112} 113 114void PageOverlayController::uninstallPageOverlay(PageOverlay* overlay, PageOverlay::FadeMode fadeMode) 115{ 116 if (fadeMode == PageOverlay::FadeMode::Fade) { 117 overlay->startFadeOutAnimation(); 118 return; 119 } 120 121 overlay->setPage(nullptr); 122 123 m_overlayGraphicsLayers.take(overlay)->removeFromParent(); 124 125 size_t overlayIndex = m_pageOverlays.find(overlay); 126 ASSERT(overlayIndex != notFound); 127 m_pageOverlays.remove(overlayIndex); 128 129 updateForceSynchronousScrollLayerPositionUpdates(); 130} 131 132void PageOverlayController::updateForceSynchronousScrollLayerPositionUpdates() 133{ 134#if ENABLE(ASYNC_SCROLLING) 135 bool forceSynchronousScrollLayerPositionUpdates = false; 136 137 for (auto& overlay : m_pageOverlays) { 138 if (overlay->overlayType() == PageOverlay::OverlayType::View) 139 forceSynchronousScrollLayerPositionUpdates = true; 140 } 141 142 if (Page* page = m_webPage.corePage()) { 143 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator()) 144 scrollingCoordinator->setForceSynchronousScrollLayerPositionUpdates(forceSynchronousScrollLayerPositionUpdates); 145 } 146#endif 147} 148 149void PageOverlayController::setPageOverlayNeedsDisplay(PageOverlay& overlay, const WebCore::IntRect& dirtyRect) 150{ 151 ASSERT(m_pageOverlays.contains(&overlay)); 152 GraphicsLayer& graphicsLayer = *m_overlayGraphicsLayers.get(&overlay); 153 154 if (!graphicsLayer.drawsContent()) { 155 graphicsLayer.setDrawsContent(true); 156 updateOverlayGeometry(overlay, graphicsLayer); 157 } 158 159 graphicsLayer.setNeedsDisplayInRect(dirtyRect); 160} 161 162void PageOverlayController::setPageOverlayOpacity(PageOverlay& overlay, float opacity) 163{ 164 ASSERT(m_pageOverlays.contains(&overlay)); 165 m_overlayGraphicsLayers.get(&overlay)->setOpacity(opacity); 166} 167 168void PageOverlayController::clearPageOverlay(PageOverlay& overlay) 169{ 170 ASSERT(m_pageOverlays.contains(&overlay)); 171 m_overlayGraphicsLayers.get(&overlay)->setDrawsContent(false); 172} 173 174GraphicsLayer* PageOverlayController::layerForOverlay(PageOverlay& overlay) const 175{ 176 ASSERT(m_pageOverlays.contains(&overlay)); 177 return m_overlayGraphicsLayers.get(&overlay); 178} 179 180void PageOverlayController::didChangeViewSize() 181{ 182 for (auto& overlayAndLayer : m_overlayGraphicsLayers) { 183 if (overlayAndLayer.key->overlayType() == PageOverlay::OverlayType::View) 184 updateOverlayGeometry(*overlayAndLayer.key, *overlayAndLayer.value); 185 } 186} 187 188void PageOverlayController::didChangeDocumentSize() 189{ 190 for (auto& overlayAndLayer : m_overlayGraphicsLayers) { 191 if (overlayAndLayer.key->overlayType() == PageOverlay::OverlayType::Document) 192 updateOverlayGeometry(*overlayAndLayer.key, *overlayAndLayer.value); 193 } 194} 195 196void PageOverlayController::didChangePreferences() 197{ 198 for (auto& graphicsLayer : m_overlayGraphicsLayers.values()) 199 updateSettingsForLayer(*graphicsLayer); 200} 201 202void PageOverlayController::didChangeDeviceScaleFactor() 203{ 204 m_documentOverlayRootLayer->noteDeviceOrPageScaleFactorChangedIncludingDescendants(); 205 m_viewOverlayRootLayer->noteDeviceOrPageScaleFactorChangedIncludingDescendants(); 206 207 for (auto& graphicsLayer : m_overlayGraphicsLayers.values()) 208 graphicsLayer->setNeedsDisplay(); 209} 210 211void PageOverlayController::didChangeExposedRect() 212{ 213 m_webPage.drawingArea()->scheduleCompositingLayerFlush(); 214} 215 216void PageOverlayController::didScrollFrame(Frame* frame) 217{ 218 for (auto& overlayAndLayer : m_overlayGraphicsLayers) { 219 if (overlayAndLayer.key->overlayType() == PageOverlay::OverlayType::View || !frame->isMainFrame()) 220 overlayAndLayer.value->setNeedsDisplay(); 221 overlayAndLayer.key->didScrollFrame(frame); 222 } 223} 224 225void PageOverlayController::flushPageOverlayLayers(FloatRect visibleRect) 226{ 227 m_viewOverlayRootLayer->flushCompositingState(visibleRect); 228} 229 230void PageOverlayController::updateSettingsForLayer(GraphicsLayer& layer) 231{ 232 Settings& settings = m_webPage.corePage()->settings(); 233 layer.setAcceleratesDrawing(settings.acceleratedDrawingEnabled()); 234 layer.setShowDebugBorder(settings.showDebugBorders()); 235 layer.setShowRepaintCounter(settings.showRepaintCounter()); 236} 237 238bool PageOverlayController::handleMouseEvent(const WebMouseEvent& mouseEvent) 239{ 240 if (!m_pageOverlays.size()) 241 return false; 242 243 for (auto it = m_pageOverlays.rbegin(), end = m_pageOverlays.rend(); it != end; ++it) { 244 if ((*it)->mouseEvent(mouseEvent)) 245 return true; 246 } 247 248 return false; 249} 250 251WKTypeRef PageOverlayController::copyAccessibilityAttributeValue(WKStringRef attribute, WKTypeRef parameter) 252{ 253 if (!m_pageOverlays.size()) 254 return nullptr; 255 256 for (auto it = m_pageOverlays.rbegin(), end = m_pageOverlays.rend(); it != end; ++it) { 257 if (WKTypeRef value = (*it)->copyAccessibilityAttributeValue(attribute, parameter)) 258 return value; 259 } 260 261 return nullptr; 262} 263 264WKArrayRef PageOverlayController::copyAccessibilityAttributesNames(bool parameterizedNames) 265{ 266 if (!m_pageOverlays.size()) 267 return nullptr; 268 269 for (auto it = m_pageOverlays.rbegin(), end = m_pageOverlays.rend(); it != end; ++it) { 270 if (WKArrayRef value = (*it)->copyAccessibilityAttributeNames(parameterizedNames)) 271 return value; 272 } 273 274 return nullptr; 275} 276 277void PageOverlayController::paintContents(const WebCore::GraphicsLayer* graphicsLayer, WebCore::GraphicsContext& graphicsContext, WebCore::GraphicsLayerPaintingPhase, const WebCore::FloatRect& clipRect) 278{ 279 for (auto it = m_overlayGraphicsLayers.begin(), end = m_overlayGraphicsLayers.end(); it != end; ++it) { 280 if (it->value.get() != graphicsLayer) 281 continue; 282 283 GraphicsContextStateSaver stateSaver(graphicsContext); 284 graphicsContext.clip(clipRect); 285 it->key->drawRect(graphicsContext, enclosingIntRect(clipRect)); 286 287 return; 288 } 289} 290 291float PageOverlayController::deviceScaleFactor() const 292{ 293 return m_webPage.corePage()->deviceScaleFactor(); 294} 295 296void PageOverlayController::notifyFlushRequired(const WebCore::GraphicsLayer*) 297{ 298 if (m_webPage.drawingArea()) 299 m_webPage.drawingArea()->scheduleCompositingLayerFlush(); 300} 301 302void PageOverlayController::didChangeOverlayFrame(PageOverlay& overlay) 303{ 304 ASSERT(m_pageOverlays.contains(&overlay)); 305 updateOverlayGeometry(overlay, *m_overlayGraphicsLayers.get(&overlay)); 306} 307 308void PageOverlayController::didChangeOverlayBackgroundColor(PageOverlay& overlay) 309{ 310 ASSERT(m_pageOverlays.contains(&overlay)); 311 m_overlayGraphicsLayers.get(&overlay)->setBackgroundColor(overlay.backgroundColor()); 312} 313 314} // namespace WebKit 315