PDFPlugin should take advantage of threaded scrolling
[WebKit-https.git] / Source / WebCore / page / PageOverlay.cpp
1 /*
2  * Copyright (C) 2010 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 "PageOverlay.h"
28
29 #include "FrameView.h"
30 #include "GraphicsContext.h"
31 #include "MainFrame.h"
32 #include "Page.h"
33 #include "PageOverlayController.h"
34 #include "PlatformMouseEvent.h"
35 #include "ScrollbarTheme.h"
36 #include <wtf/CurrentTime.h>
37
38 namespace WebCore {
39
40 static const double fadeAnimationDuration = 0.2;
41 static const double fadeAnimationFrameRate = 30;
42
43 static PageOverlay::PageOverlayID generatePageOverlayID()
44 {
45     static PageOverlay::PageOverlayID pageOverlayID;
46     return ++pageOverlayID;
47 }
48
49 Ref<PageOverlay> PageOverlay::create(Client& client, OverlayType overlayType)
50 {
51     return adoptRef(*new PageOverlay(client, overlayType));
52 }
53
54 PageOverlay::PageOverlay(Client& client, OverlayType overlayType)
55     : m_client(client)
56     , m_fadeAnimationTimer(*this, &PageOverlay::fadeAnimationTimerFired)
57     , m_fadeAnimationDuration(fadeAnimationDuration)
58     , m_needsSynchronousScrolling(overlayType == OverlayType::View)
59     , m_overlayType(overlayType)
60     , m_pageOverlayID(generatePageOverlayID())
61 {
62 }
63
64 PageOverlay::~PageOverlay()
65 {
66 }
67
68 PageOverlayController* PageOverlay::controller() const
69 {
70     if (!m_page)
71         return nullptr;
72     return &m_page->mainFrame().pageOverlayController();
73 }
74
75 IntRect PageOverlay::bounds() const
76 {
77     if (!m_overrideFrame.isEmpty())
78         return m_overrideFrame;
79
80     FrameView* frameView = m_page->mainFrame().view();
81
82     if (!frameView)
83         return IntRect();
84
85     switch (m_overlayType) {
86     case OverlayType::View: {
87         int width = frameView->width();
88         int height = frameView->height();
89
90         if (!ScrollbarTheme::theme().usesOverlayScrollbars()) {
91             if (frameView->verticalScrollbar())
92                 width -= frameView->verticalScrollbar()->width();
93             if (frameView->horizontalScrollbar())
94                 height -= frameView->horizontalScrollbar()->height();
95         }
96         return IntRect(0, 0, width, height);
97     }
98     case OverlayType::Document:
99         return IntRect(IntPoint(), frameView->contentsSize());
100     }
101
102     ASSERT_NOT_REACHED();
103     return IntRect(IntPoint(), frameView->contentsSize());
104 }
105
106 IntRect PageOverlay::frame() const
107 {
108     if (!m_overrideFrame.isEmpty())
109         return m_overrideFrame;
110
111     return bounds();
112 }
113
114 void PageOverlay::setFrame(IntRect frame)
115 {
116     if (m_overrideFrame == frame)
117         return;
118
119     m_overrideFrame = frame;
120
121     if (auto pageOverlayController = controller())
122         pageOverlayController->didChangeOverlayFrame(*this);
123 }
124
125 IntSize PageOverlay::viewToOverlayOffset() const
126 {
127     switch (m_overlayType) {
128     case OverlayType::View:
129         return IntSize();
130
131     case OverlayType::Document: {
132         FrameView* frameView = m_page->mainFrame().view();
133         return frameView ? toIntSize(frameView->viewToContents(IntPoint())) : IntSize();
134     }
135     }
136     return IntSize();
137 }
138
139 void PageOverlay::setBackgroundColor(RGBA32 backgroundColor)
140 {
141     if (m_backgroundColor == backgroundColor)
142         return;
143
144     m_backgroundColor = backgroundColor;
145
146     if (auto pageOverlayController = controller())
147         pageOverlayController->didChangeOverlayBackgroundColor(*this);
148 }
149
150 void PageOverlay::setPage(Page* page)
151 {
152     m_client.willMoveToPage(*this, page);
153     m_page = page;
154     m_client.didMoveToPage(*this, page);
155
156     m_fadeAnimationTimer.stop();
157 }
158
159 void PageOverlay::setNeedsDisplay(const IntRect& dirtyRect)
160 {
161     if (auto pageOverlayController = controller()) {
162         if (m_fadeAnimationType != FadeAnimationType::NoAnimation)
163             pageOverlayController->setPageOverlayOpacity(*this, m_fractionFadedIn);
164         pageOverlayController->setPageOverlayNeedsDisplay(*this, dirtyRect);
165     }
166 }
167
168 void PageOverlay::setNeedsDisplay()
169 {
170     setNeedsDisplay(bounds());
171 }
172
173 void PageOverlay::drawRect(GraphicsContext& graphicsContext, const IntRect& dirtyRect)
174 {
175     // If the dirty rect is outside the bounds, ignore it.
176     IntRect paintRect = intersection(dirtyRect, bounds());
177     if (paintRect.isEmpty())
178         return;
179
180     GraphicsContextStateSaver stateSaver(graphicsContext);
181     m_client.drawRect(*this, graphicsContext, paintRect);
182 }
183     
184 bool PageOverlay::mouseEvent(const PlatformMouseEvent& mouseEvent)
185 {
186     IntPoint mousePositionInOverlayCoordinates(mouseEvent.position());
187
188     if (m_overlayType == PageOverlay::OverlayType::Document)
189         mousePositionInOverlayCoordinates = m_page->mainFrame().view()->windowToContents(mousePositionInOverlayCoordinates);
190
191     // Ignore events outside the bounds.
192     if (m_shouldIgnoreMouseEventsOutsideBounds && !bounds().contains(mousePositionInOverlayCoordinates))
193         return false;
194
195     return m_client.mouseEvent(*this, mouseEvent);
196 }
197
198 void PageOverlay::didScrollFrame(Frame& frame)
199 {
200     m_client.didScrollFrame(*this, frame);
201 }
202
203 bool PageOverlay::copyAccessibilityAttributeStringValueForPoint(String attribute, FloatPoint parameter, String& value)
204 {
205     return m_client.copyAccessibilityAttributeStringValueForPoint(*this, attribute, parameter, value);
206 }
207
208 bool PageOverlay::copyAccessibilityAttributeBoolValueForPoint(String attribute, FloatPoint parameter, bool& value)
209 {
210     return m_client.copyAccessibilityAttributeBoolValueForPoint(*this, attribute, parameter, value);
211 }
212
213 Vector<String> PageOverlay::copyAccessibilityAttributeNames(bool parameterizedNames)
214 {
215     return m_client.copyAccessibilityAttributeNames(*this, parameterizedNames);
216 }
217
218 void PageOverlay::startFadeInAnimation()
219 {
220     m_fractionFadedIn = 0;
221     m_fadeAnimationType = FadeInAnimation;
222
223     startFadeAnimation();
224 }
225
226 void PageOverlay::startFadeOutAnimation()
227 {
228     m_fractionFadedIn = 1;
229     m_fadeAnimationType = FadeOutAnimation;
230
231     startFadeAnimation();
232 }
233
234 void PageOverlay::stopFadeOutAnimation()
235 {
236     m_fractionFadedIn = 1.0;
237     m_fadeAnimationTimer.stop();
238 }
239
240 void PageOverlay::startFadeAnimation()
241 {
242     m_fadeAnimationStartTime = currentTime();
243     m_fadeAnimationTimer.startRepeating(1 / fadeAnimationFrameRate);
244 }
245
246 void PageOverlay::fadeAnimationTimerFired()
247 {
248     float animationProgress = (currentTime() - m_fadeAnimationStartTime) / m_fadeAnimationDuration;
249
250     if (animationProgress >= 1.0)
251         animationProgress = 1.0;
252
253     double sine = sin(piOverTwoFloat * animationProgress);
254     float fadeAnimationValue = sine * sine;
255
256     m_fractionFadedIn = (m_fadeAnimationType == FadeInAnimation) ? fadeAnimationValue : 1 - fadeAnimationValue;
257     controller()->setPageOverlayOpacity(*this, m_fractionFadedIn);
258
259     if (animationProgress == 1.0) {
260         m_fadeAnimationTimer.stop();
261
262         bool wasFadingOut = m_fadeAnimationType == FadeOutAnimation;
263         m_fadeAnimationType = NoAnimation;
264
265         // If this was a fade out, uninstall the page overlay.
266         if (wasFadingOut)
267             controller()->uninstallPageOverlay(this, PageOverlay::FadeMode::DoNotFade);
268     }
269 }
270
271 void PageOverlay::clear()
272 {
273     if (auto pageOverlayController = controller())
274         pageOverlayController->clearPageOverlay(*this);
275 }
276
277 GraphicsLayer& PageOverlay::layer()
278 {
279     return controller()->layerForOverlay(*this);
280 }
281
282 } // namespace WebKit