Replace WTF::move with WTFMove
[WebKit-https.git] / Source / WebCore / page / DebugPageOverlays.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 "DebugPageOverlays.h"
28
29 #include "ElementIterator.h"
30 #include "FrameView.h"
31 #include "GraphicsContext.h"
32 #include "MainFrame.h"
33 #include "Page.h"
34 #include "PageOverlay.h"
35 #include "PageOverlayController.h"
36 #include "Region.h"
37 #include "ScrollingCoordinator.h"
38 #include "Settings.h"
39 #include <wtf/RefPtr.h>
40
41 namespace WebCore {
42
43 DebugPageOverlays* DebugPageOverlays::sharedDebugOverlays;
44
45 class RegionOverlay : public RefCounted<RegionOverlay>, public PageOverlay::Client {
46 public:
47     static PassRefPtr<RegionOverlay> create(MainFrame&, DebugPageOverlays::RegionType);
48     virtual ~RegionOverlay();
49
50     void recomputeRegion();
51     PageOverlay& overlay() { return *m_overlay; }
52
53 protected:
54     RegionOverlay(MainFrame&, Color);
55
56 private:
57     virtual void pageOverlayDestroyed(PageOverlay&) final;
58     virtual void willMoveToPage(PageOverlay&, Page*) final;
59     virtual void didMoveToPage(PageOverlay&, Page*) final;
60     virtual void drawRect(PageOverlay&, GraphicsContext&, const IntRect& dirtyRect) final;
61     virtual bool mouseEvent(PageOverlay&, const PlatformMouseEvent&) final;
62     virtual void didScrollFrame(PageOverlay&, Frame&) final;
63
64 protected:
65     // Returns true if the region changed.
66     virtual bool updateRegion() = 0;
67     
68     MainFrame& m_frame;
69     RefPtr<PageOverlay> m_overlay;
70     std::unique_ptr<Region> m_region;
71     Color m_color;
72 };
73
74
75 class MouseWheelRegionOverlay final : public RegionOverlay {
76 public:
77     static Ref<MouseWheelRegionOverlay> create(MainFrame& frame)
78     {
79         return adoptRef(*new MouseWheelRegionOverlay(frame));
80     }
81
82 private:
83     explicit MouseWheelRegionOverlay(MainFrame& frame)
84         : RegionOverlay(frame, Color(0.5f, 0.0f, 0.0f, 0.4f))
85     {
86     }
87
88     virtual bool updateRegion() override;
89 };
90
91 bool MouseWheelRegionOverlay::updateRegion()
92 {
93     std::unique_ptr<Region> region = std::make_unique<Region>();
94     
95     for (const Frame* frame = &m_frame; frame; frame = frame->tree().traverseNext()) {
96         if (!frame->view() || !frame->document())
97             continue;
98
99         Document::RegionFixedPair frameRegion = frame->document()->absoluteRegionForEventTargets(frame->document()->wheelEventTargets());
100     
101         IntPoint frameOffset = frame->view()->contentsToRootView(IntPoint());
102         frameRegion.first.translate(toIntSize(frameOffset));
103         
104         region->unite(frameRegion.first);
105     }
106     
107     region->translate(m_overlay->viewToOverlayOffset());
108
109     bool regionChanged = !m_region || !(*m_region == *region);
110     m_region = WTFMove(region);
111     return regionChanged;
112 }
113
114 class NonFastScrollableRegionOverlay final : public RegionOverlay {
115 public:
116     static Ref<NonFastScrollableRegionOverlay> create(MainFrame& frame)
117     {
118         return adoptRef(*new NonFastScrollableRegionOverlay(frame));
119     }
120
121 private:
122     explicit NonFastScrollableRegionOverlay(MainFrame& frame)
123         : RegionOverlay(frame, Color(1.0f, 0.5f, 0.0f, 0.4f))
124     {
125     }
126
127     virtual bool updateRegion() override;
128 };
129
130 bool NonFastScrollableRegionOverlay::updateRegion()
131 {
132     std::unique_ptr<Region> region = std::make_unique<Region>();
133
134     if (Page* page = m_frame.page()) {
135         if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
136             *region = scrollingCoordinator->absoluteNonFastScrollableRegion();
137     }
138
139     bool regionChanged = !m_region || !(*m_region == *region);
140     m_region = WTFMove(region);
141     return regionChanged;
142 }
143
144 PassRefPtr<RegionOverlay> RegionOverlay::create(MainFrame& frame, DebugPageOverlays::RegionType regionType)
145 {
146     switch (regionType) {
147     case DebugPageOverlays::RegionType::WheelEventHandlers:
148         return MouseWheelRegionOverlay::create(frame);
149
150     case DebugPageOverlays::RegionType::NonFastScrollableRegion:
151         return NonFastScrollableRegionOverlay::create(frame);
152     }
153     return nullptr;
154 }
155
156 RegionOverlay::RegionOverlay(MainFrame& frame, Color regionColor)
157     : m_frame(frame)
158     , m_overlay(PageOverlay::create(*this, PageOverlay::OverlayType::Document))
159     , m_color(regionColor)
160 {
161 }
162
163 RegionOverlay::~RegionOverlay()
164 {
165     if (m_overlay)
166         m_frame.pageOverlayController().uninstallPageOverlay(m_overlay.get(), PageOverlay::FadeMode::DoNotFade);
167 }
168
169 void RegionOverlay::pageOverlayDestroyed(PageOverlay&)
170 {
171 }
172
173 void RegionOverlay::willMoveToPage(PageOverlay&, Page* page)
174 {
175     if (!page)
176         m_overlay = nullptr;
177 }
178
179 void RegionOverlay::didMoveToPage(PageOverlay&, Page* page)
180 {
181     if (page)
182         recomputeRegion();
183 }
184
185 void RegionOverlay::drawRect(PageOverlay&, GraphicsContext& context, const IntRect& dirtyRect)
186 {
187     context.clearRect(dirtyRect);
188
189     if (!m_region)
190         return;
191     
192     GraphicsContextStateSaver saver(context);
193     context.setFillColor(m_color);
194     for (auto rect : m_region->rects()) {
195     
196         if (rect.intersects(dirtyRect))
197             context.fillRect(rect);
198     }
199 }
200
201 bool RegionOverlay::mouseEvent(PageOverlay&, const PlatformMouseEvent&)
202 {
203     return false;
204 }
205
206 void RegionOverlay::didScrollFrame(PageOverlay&, Frame&)
207 {
208 }
209
210 void RegionOverlay::recomputeRegion()
211 {
212     if (updateRegion())
213         m_overlay->setNeedsDisplay();
214 }
215
216 DebugPageOverlays& DebugPageOverlays::singleton()
217 {
218     if (!sharedDebugOverlays)
219         sharedDebugOverlays = new DebugPageOverlays;
220
221     return *sharedDebugOverlays;
222 }
223
224 static inline size_t indexOf(DebugPageOverlays::RegionType regionType)
225 {
226     return static_cast<size_t>(regionType);
227 }
228
229 RegionOverlay& DebugPageOverlays::ensureRegionOverlayForFrame(MainFrame& frame, RegionType regionType)
230 {
231     auto it = m_frameRegionOverlays.find(&frame);
232     if (it != m_frameRegionOverlays.end()) {
233         auto& visualizers = it->value;
234         
235         if (!visualizers[indexOf(regionType)])
236             visualizers[indexOf(regionType)] = RegionOverlay::create(frame, regionType);
237
238         return *visualizers[indexOf(regionType)];
239     }
240
241     Vector<RefPtr<RegionOverlay>> visualizers(NumberOfRegionTypes);
242     
243     RefPtr<RegionOverlay> visualizer = RegionOverlay::create(frame, regionType);
244     visualizers[indexOf(regionType)] = visualizer;
245
246     m_frameRegionOverlays.add(&frame, WTFMove(visualizers));
247     return *visualizer;
248 }
249
250 void DebugPageOverlays::showRegionOverlay(MainFrame& frame, RegionType regionType)
251 {
252     RegionOverlay& visualizer = ensureRegionOverlayForFrame(frame, regionType);
253     frame.pageOverlayController().installPageOverlay(&visualizer.overlay(), PageOverlay::FadeMode::DoNotFade);
254 }
255
256 void DebugPageOverlays::hideRegionOverlay(MainFrame& frame, RegionType regionType)
257 {
258     auto it = m_frameRegionOverlays.find(&frame);
259     if (it != m_frameRegionOverlays.end()) {
260         auto& visualizers = it->value;
261         if (RegionOverlay* visualizer = visualizers[indexOf(regionType)].get()) {
262             frame.pageOverlayController().uninstallPageOverlay(&visualizer->overlay(), PageOverlay::FadeMode::DoNotFade);
263             visualizers[indexOf(regionType)] = nullptr;
264         }
265     }
266 }
267
268 void DebugPageOverlays::regionChanged(Frame& frame, RegionType regionType)
269 {
270     if (RegionOverlay* visualizer = regionOverlayForFrame(frame.mainFrame(), regionType))
271         visualizer->recomputeRegion();
272 }
273
274 RegionOverlay* DebugPageOverlays::regionOverlayForFrame(MainFrame& frame, RegionType regionType) const
275 {
276     auto it = m_frameRegionOverlays.find(&frame);
277     if (it != m_frameRegionOverlays.end())
278         return it->value.at(indexOf(regionType)).get();
279
280     return nullptr;
281 }
282
283 void DebugPageOverlays::updateOverlayRegionVisibility(MainFrame& frame, DebugOverlayRegions visibleRegions)
284 {
285     if (visibleRegions & NonFastScrollableRegion)
286         showRegionOverlay(frame, RegionType::NonFastScrollableRegion);
287     else
288         hideRegionOverlay(frame, RegionType::NonFastScrollableRegion);
289
290     if (visibleRegions & WheelEventHandlerRegion)
291         showRegionOverlay(frame, RegionType::WheelEventHandlers);
292     else
293         hideRegionOverlay(frame, RegionType::WheelEventHandlers);
294 }
295
296 void DebugPageOverlays::settingsChanged(MainFrame& frame)
297 {
298     DebugOverlayRegions activeOverlayRegions = frame.settings().visibleDebugOverlayRegions();
299     if (!activeOverlayRegions && !hasOverlays(frame))
300         return;
301
302     DebugPageOverlays::singleton().updateOverlayRegionVisibility(frame, activeOverlayRegions);
303 }
304
305 }