Service overlays stay fixed when <iframe> scrolls
[WebKit-https.git] / Source / WebKit2 / WebProcess / WebPage / PageOverlayController.cpp
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
41 using namespace WebCore;
42
43 namespace WebKit {
44
45 PageOverlayController::PageOverlayController(WebPage& webPage)
46     : m_webPage(webPage)
47 {
48 }
49
50 void 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
63 static 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
74 void 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
114 void 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
132 void 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
149 void 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
162 void PageOverlayController::setPageOverlayOpacity(PageOverlay& overlay, float opacity)
163 {
164     ASSERT(m_pageOverlays.contains(&overlay));
165     m_overlayGraphicsLayers.get(&overlay)->setOpacity(opacity);
166 }
167
168 void PageOverlayController::clearPageOverlay(PageOverlay& overlay)
169 {
170     ASSERT(m_pageOverlays.contains(&overlay));
171     m_overlayGraphicsLayers.get(&overlay)->setDrawsContent(false);
172 }
173
174 GraphicsLayer* PageOverlayController::layerForOverlay(PageOverlay& overlay) const
175 {
176     ASSERT(m_pageOverlays.contains(&overlay));
177     return m_overlayGraphicsLayers.get(&overlay);
178 }
179
180 void 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
188 void 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
196 void PageOverlayController::didChangePreferences()
197 {
198     for (auto& graphicsLayer : m_overlayGraphicsLayers.values())
199         updateSettingsForLayer(*graphicsLayer);
200 }
201
202 void PageOverlayController::didChangeDeviceScaleFactor()
203 {
204     m_documentOverlayRootLayer->noteDeviceOrPageScaleFactorChangedIncludingDescendants();
205     m_viewOverlayRootLayer->noteDeviceOrPageScaleFactorChangedIncludingDescendants();
206
207     for (auto& graphicsLayer : m_overlayGraphicsLayers.values())
208         graphicsLayer->setNeedsDisplay();
209 }
210
211 void PageOverlayController::didChangeExposedRect()
212 {
213     m_webPage.drawingArea()->scheduleCompositingLayerFlush();
214 }
215
216 void 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
225 void PageOverlayController::flushPageOverlayLayers(FloatRect visibleRect)
226 {
227     m_viewOverlayRootLayer->flushCompositingState(visibleRect);
228 }
229
230 void 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
238 bool 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
251 WKTypeRef 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
264 WKArrayRef 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
277 void 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
291 float PageOverlayController::deviceScaleFactor() const
292 {
293     return m_webPage.corePage()->deviceScaleFactor();
294 }
295
296 void PageOverlayController::notifyFlushRequired(const WebCore::GraphicsLayer*)
297 {
298     if (m_webPage.drawingArea())
299         m_webPage.drawingArea()->scheduleCompositingLayerFlush();
300 }
301
302 void PageOverlayController::didChangeOverlayFrame(PageOverlay& overlay)
303 {
304     ASSERT(m_pageOverlays.contains(&overlay));
305     updateOverlayGeometry(overlay, *m_overlayGraphicsLayers.get(&overlay));
306 }
307
308 void PageOverlayController::didChangeOverlayBackgroundColor(PageOverlay& overlay)
309 {
310     ASSERT(m_pageOverlays.contains(&overlay));
311     m_overlayGraphicsLayers.get(&overlay)->setBackgroundColor(overlay.backgroundColor());
312 }
313
314 } // namespace WebKit