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