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