Use "= default" to denote default constructor or destructor
[WebKit-https.git] / Source / WebCore / page / PageOverlayController.cpp
1 /*
2  * Copyright (C) 2014-2017 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 "Chrome.h"
30 #include "ChromeClient.h"
31 #include "Frame.h"
32 #include "FrameView.h"
33 #include "GraphicsContext.h"
34 #include "GraphicsLayer.h"
35 #include "MainFrame.h"
36 #include "Page.h"
37 #include "PageOverlay.h"
38 #include "ScrollingCoordinator.h"
39 #include "Settings.h"
40 #include "TiledBacking.h"
41
42 // FIXME: Someone needs to call didChangeSettings() if we want dynamic updates of layer border/repaint counter settings.
43
44 namespace WebCore {
45
46 PageOverlayController::PageOverlayController(MainFrame& mainFrame)
47     : m_initialized(false)
48     , m_mainFrame(mainFrame)
49 {
50 }
51
52 PageOverlayController::~PageOverlayController() = default;
53
54 void PageOverlayController::createRootLayersIfNeeded()
55 {
56     if (m_initialized)
57         return;
58
59     m_initialized = true;
60
61     ASSERT(!m_documentOverlayRootLayer);
62     ASSERT(!m_viewOverlayRootLayer);
63
64     m_documentOverlayRootLayer = GraphicsLayer::create(m_mainFrame.page()->chrome().client().graphicsLayerFactory(), *this);
65     m_viewOverlayRootLayer = GraphicsLayer::create(m_mainFrame.page()->chrome().client().graphicsLayerFactory(), *this);
66     m_documentOverlayRootLayer->setName("Document overlay Container");
67     m_viewOverlayRootLayer->setName("View overlay container");
68 }
69
70 GraphicsLayer* PageOverlayController::documentOverlayRootLayer() const
71 {
72     return m_documentOverlayRootLayer.get();
73 }
74
75 GraphicsLayer* PageOverlayController::viewOverlayRootLayer() const
76 {
77     return m_viewOverlayRootLayer.get();
78 }
79
80 static void updateOverlayGeometry(PageOverlay& overlay, GraphicsLayer& graphicsLayer)
81 {
82     IntRect overlayFrame = overlay.frame();
83
84     if (overlayFrame.location() == graphicsLayer.position() && overlayFrame.size() == graphicsLayer.size())
85         return;
86
87     graphicsLayer.setPosition(overlayFrame.location());
88     graphicsLayer.setSize(overlayFrame.size());
89 }
90
91 GraphicsLayer& PageOverlayController::layerWithDocumentOverlays()
92 {
93     createRootLayersIfNeeded();
94
95     bool inWindow = m_mainFrame.page() ? m_mainFrame.page()->isInWindow() : false;
96
97     for (auto& overlayAndLayer : m_overlayGraphicsLayers) {
98         PageOverlay& overlay = *overlayAndLayer.key;
99         if (overlay.overlayType() != PageOverlay::OverlayType::Document)
100             continue;
101
102         GraphicsLayer& layer = *overlayAndLayer.value;
103         GraphicsLayer::traverse(layer, [inWindow](GraphicsLayer& layer) {
104             layer.setIsInWindow(inWindow);
105         });
106         updateOverlayGeometry(overlay, layer);
107         
108         if (!layer.parent())
109             m_documentOverlayRootLayer->addChild(&layer);
110     }
111
112     return *m_documentOverlayRootLayer;
113 }
114
115 GraphicsLayer& PageOverlayController::layerWithViewOverlays()
116 {
117     createRootLayersIfNeeded();
118
119     bool inWindow = m_mainFrame.page() ? m_mainFrame.page()->isInWindow() : false;
120
121     for (auto& overlayAndLayer : m_overlayGraphicsLayers) {
122         PageOverlay& overlay = *overlayAndLayer.key;
123         if (overlay.overlayType() != PageOverlay::OverlayType::View)
124             continue;
125
126         GraphicsLayer& layer = *overlayAndLayer.value;
127         GraphicsLayer::traverse(layer, [inWindow](GraphicsLayer& layer) {
128             layer.setIsInWindow(inWindow);
129         });
130         updateOverlayGeometry(overlay, layer);
131         
132         if (!layer.parent())
133             m_viewOverlayRootLayer->addChild(&layer);
134     }
135
136     return *m_viewOverlayRootLayer;
137 }
138
139 void PageOverlayController::installPageOverlay(PageOverlay& overlay, PageOverlay::FadeMode fadeMode)
140 {
141     createRootLayersIfNeeded();
142
143     if (m_pageOverlays.contains(&overlay))
144         return;
145
146     m_pageOverlays.append(&overlay);
147
148     std::unique_ptr<GraphicsLayer> layer = GraphicsLayer::create(m_mainFrame.page()->chrome().client().graphicsLayerFactory(), *this);
149     layer->setAnchorPoint(FloatPoint3D());
150     layer->setBackgroundColor(overlay.backgroundColor());
151     layer->setName("Overlay content");
152
153     updateSettingsForLayer(*layer);
154
155     switch (overlay.overlayType()) {
156     case PageOverlay::OverlayType::View:
157         m_viewOverlayRootLayer->addChild(layer.get());
158         break;
159     case PageOverlay::OverlayType::Document:
160         m_documentOverlayRootLayer->addChild(layer.get());
161         break;
162     }
163
164     GraphicsLayer& rawLayer = *layer;
165     m_overlayGraphicsLayers.set(&overlay, WTFMove(layer));
166
167     updateForceSynchronousScrollLayerPositionUpdates();
168
169     overlay.setPage(m_mainFrame.page());
170
171     if (FrameView* frameView = m_mainFrame.view())
172         frameView->enterCompositingMode();
173
174     updateOverlayGeometry(overlay, rawLayer);
175
176     if (fadeMode == PageOverlay::FadeMode::Fade)
177         overlay.startFadeInAnimation();
178 }
179
180 void PageOverlayController::uninstallPageOverlay(PageOverlay& overlay, PageOverlay::FadeMode fadeMode)
181 {
182     if (fadeMode == PageOverlay::FadeMode::Fade) {
183         overlay.startFadeOutAnimation();
184         return;
185     }
186
187     overlay.setPage(nullptr);
188
189     m_overlayGraphicsLayers.take(&overlay)->removeFromParent();
190
191     bool removed = m_pageOverlays.removeFirst(&overlay);
192     ASSERT_UNUSED(removed, removed);
193
194     updateForceSynchronousScrollLayerPositionUpdates();
195 }
196
197 void PageOverlayController::updateForceSynchronousScrollLayerPositionUpdates()
198 {
199 #if ENABLE(ASYNC_SCROLLING)
200     bool forceSynchronousScrollLayerPositionUpdates = false;
201
202     for (auto& overlay : m_pageOverlays) {
203         if (overlay->needsSynchronousScrolling())
204             forceSynchronousScrollLayerPositionUpdates = true;
205     }
206
207     if (ScrollingCoordinator* scrollingCoordinator = m_mainFrame.page()->scrollingCoordinator())
208         scrollingCoordinator->setForceSynchronousScrollLayerPositionUpdates(forceSynchronousScrollLayerPositionUpdates);
209 #endif
210 }
211
212 void PageOverlayController::setPageOverlayNeedsDisplay(PageOverlay& overlay, const WebCore::IntRect& dirtyRect)
213 {
214     ASSERT(m_pageOverlays.contains(&overlay));
215     GraphicsLayer& graphicsLayer = *m_overlayGraphicsLayers.get(&overlay);
216
217     if (!graphicsLayer.drawsContent()) {
218         graphicsLayer.setDrawsContent(true);
219         updateOverlayGeometry(overlay, graphicsLayer);
220     }
221
222     graphicsLayer.setNeedsDisplayInRect(dirtyRect);
223 }
224
225 void PageOverlayController::setPageOverlayOpacity(PageOverlay& overlay, float opacity)
226 {
227     ASSERT(m_pageOverlays.contains(&overlay));
228     m_overlayGraphicsLayers.get(&overlay)->setOpacity(opacity);
229 }
230
231 void PageOverlayController::clearPageOverlay(PageOverlay& overlay)
232 {
233     ASSERT(m_pageOverlays.contains(&overlay));
234     m_overlayGraphicsLayers.get(&overlay)->setDrawsContent(false);
235 }
236
237 GraphicsLayer& PageOverlayController::layerForOverlay(PageOverlay& overlay) const
238 {
239     ASSERT(m_pageOverlays.contains(&overlay));
240     return *m_overlayGraphicsLayers.get(&overlay);
241 }
242
243 void PageOverlayController::willDetachRootLayer()
244 {
245     m_documentOverlayRootLayer = nullptr;
246     m_viewOverlayRootLayer = nullptr;
247     m_initialized = false;
248 }
249
250 void PageOverlayController::didChangeViewSize()
251 {
252     for (auto& overlayAndLayer : m_overlayGraphicsLayers) {
253         if (overlayAndLayer.key->overlayType() == PageOverlay::OverlayType::View)
254             updateOverlayGeometry(*overlayAndLayer.key, *overlayAndLayer.value);
255     }
256 }
257
258 void PageOverlayController::didChangeDocumentSize()
259 {
260     for (auto& overlayAndLayer : m_overlayGraphicsLayers) {
261         if (overlayAndLayer.key->overlayType() == PageOverlay::OverlayType::Document)
262             updateOverlayGeometry(*overlayAndLayer.key, *overlayAndLayer.value);
263     }
264 }
265
266 void PageOverlayController::didChangeSettings()
267 {
268     // FIXME: We should apply these settings to all overlay sublayers recursively.
269     for (auto& graphicsLayer : m_overlayGraphicsLayers.values())
270         updateSettingsForLayer(*graphicsLayer);
271 }
272
273 void PageOverlayController::didChangeDeviceScaleFactor()
274 {
275     if (!m_initialized)
276         return;
277
278     m_documentOverlayRootLayer->noteDeviceOrPageScaleFactorChangedIncludingDescendants();
279     m_viewOverlayRootLayer->noteDeviceOrPageScaleFactorChangedIncludingDescendants();
280
281     for (auto& graphicsLayer : m_overlayGraphicsLayers.values())
282         graphicsLayer->setNeedsDisplay();
283 }
284
285 void PageOverlayController::didChangeViewExposedRect()
286 {
287     m_mainFrame.page()->chrome().client().scheduleCompositingLayerFlush();
288 }
289
290 void PageOverlayController::didScrollFrame(Frame& frame)
291 {
292     for (auto& overlayAndLayer : m_overlayGraphicsLayers) {
293         if (overlayAndLayer.key->overlayType() == PageOverlay::OverlayType::View || !frame.isMainFrame())
294             overlayAndLayer.value->setNeedsDisplay();
295         overlayAndLayer.key->didScrollFrame(frame);
296     }
297 }
298
299 void PageOverlayController::updateSettingsForLayer(GraphicsLayer& layer)
300 {
301     Settings& settings = m_mainFrame.settings();
302     layer.setAcceleratesDrawing(settings.acceleratedDrawingEnabled());
303     layer.setShowDebugBorder(settings.showDebugBorders());
304     layer.setShowRepaintCounter(settings.showRepaintCounter());
305 }
306
307 bool PageOverlayController::handleMouseEvent(const PlatformMouseEvent& mouseEvent)
308 {
309     if (m_pageOverlays.isEmpty())
310         return false;
311
312     for (auto it = m_pageOverlays.rbegin(), end = m_pageOverlays.rend(); it != end; ++it) {
313         if ((*it)->mouseEvent(mouseEvent))
314             return true;
315     }
316
317     return false;
318 }
319
320 bool PageOverlayController::copyAccessibilityAttributeStringValueForPoint(String attribute, FloatPoint parameter, String& value)
321 {
322     if (m_pageOverlays.isEmpty())
323         return false;
324
325     for (auto it = m_pageOverlays.rbegin(), end = m_pageOverlays.rend(); it != end; ++it) {
326         if ((*it)->copyAccessibilityAttributeStringValueForPoint(attribute, parameter, value))
327             return true;
328     }
329
330     return false;
331 }
332
333 bool PageOverlayController::copyAccessibilityAttributeBoolValueForPoint(String attribute, FloatPoint parameter, bool& value)
334 {
335     if (m_pageOverlays.isEmpty())
336         return false;
337
338     for (auto it = m_pageOverlays.rbegin(), end = m_pageOverlays.rend(); it != end; ++it) {
339         if ((*it)->copyAccessibilityAttributeBoolValueForPoint(attribute, parameter, value))
340             return true;
341     }
342     
343     return false;
344 }
345
346 Vector<String> PageOverlayController::copyAccessibilityAttributesNames(bool parameterizedNames)
347 {
348     if (m_pageOverlays.isEmpty())
349         return { };
350
351     for (auto it = m_pageOverlays.rbegin(), end = m_pageOverlays.rend(); it != end; ++it) {
352         Vector<String> names = (*it)->copyAccessibilityAttributeNames(parameterizedNames);
353         if (!names.isEmpty())
354             return names;
355     }
356
357     return { };
358 }
359
360 void PageOverlayController::paintContents(const WebCore::GraphicsLayer* graphicsLayer, WebCore::GraphicsContext& graphicsContext, WebCore::GraphicsLayerPaintingPhase, const WebCore::FloatRect& clipRect, GraphicsLayerPaintBehavior)
361 {
362     for (auto& overlayAndGraphicsLayer : m_overlayGraphicsLayers) {
363         if (overlayAndGraphicsLayer.value.get() != graphicsLayer)
364             continue;
365
366         GraphicsContextStateSaver stateSaver(graphicsContext);
367         graphicsContext.clip(clipRect);
368         overlayAndGraphicsLayer.key->drawRect(graphicsContext, enclosingIntRect(clipRect));
369
370         return;
371     }
372 }
373
374 float PageOverlayController::deviceScaleFactor() const
375 {
376     if (Page* page = m_mainFrame.page())
377         return page->deviceScaleFactor();
378     return 1;
379 }
380
381 void PageOverlayController::notifyFlushRequired(const WebCore::GraphicsLayer*)
382 {
383     if (Page* page = m_mainFrame.page())
384         page->chrome().client().scheduleCompositingLayerFlush();
385 }
386
387 void PageOverlayController::didChangeOverlayFrame(PageOverlay& overlay)
388 {
389     ASSERT(m_pageOverlays.contains(&overlay));
390     updateOverlayGeometry(overlay, *m_overlayGraphicsLayers.get(&overlay));
391 }
392
393 void PageOverlayController::didChangeOverlayBackgroundColor(PageOverlay& overlay)
394 {
395     ASSERT(m_pageOverlays.contains(&overlay));
396     m_overlayGraphicsLayers.get(&overlay)->setBackgroundColor(overlay.backgroundColor());
397 }
398
399 bool PageOverlayController::shouldSkipLayerInDump(const GraphicsLayer*, LayerTreeAsTextBehavior behavior) const
400 {
401     return !(behavior & LayerTreeAsTextIncludePageOverlayLayers);
402 }
403
404 void PageOverlayController::tiledBackingUsageChanged(const GraphicsLayer* graphicsLayer, bool usingTiledBacking)
405 {
406     if (usingTiledBacking)
407         graphicsLayer->tiledBacking()->setIsInWindow(m_mainFrame.page()->isInWindow());
408 }
409
410 } // namespace WebKit