Source/WebCore: Remove Node::attached()
[WebKit-https.git] / Source / WebCore / html / shadow / MediaControlElementTypes.cpp
1 /*
2  * Copyright (C) 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
3  * Copyright (C) 2012 Google Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1.  Redistributions of source code must retain the above copyright
10  *     notice, this list of conditions and the following disclaimer.
11  * 2.  Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution.
14  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15  *     its contributors may be used to endorse or promote products derived
16  *     from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include "config.h"
31
32 #if ENABLE(VIDEO)
33 #include "MediaControlElementTypes.h"
34
35 #include "CSSValueKeywords.h"
36 #include "ExceptionCodePlaceholder.h"
37 #include "HTMLNames.h"
38 #include "MouseEvent.h"
39 #include "RenderMedia.h"
40 #include "RenderMediaControlElements.h"
41 #include "StyleProperties.h"
42
43 namespace WebCore {
44
45 using namespace HTMLNames;
46
47 class Event;
48
49 // FIXME: These constants may need to be tweaked to better match the seeking in the QuickTime plug-in.
50 static const double cSkipRepeatDelay = 0.1;
51 static const double cSkipTime = 0.2;
52 static const double cScanRepeatDelay = 1.5;
53 static const double cScanMaximumRate = 8;
54
55 HTMLMediaElement* parentMediaElement(Node* node)
56 {
57     if (!node)
58         return nullptr;
59     Node* mediaNode = node->shadowHost();
60     if (!mediaNode)
61         mediaNode = node;
62     if (!mediaNode->isElementNode() || !toElement(mediaNode)->isMediaElement())
63         return nullptr;
64     return toHTMLMediaElement(mediaNode);
65 }
66
67 MediaControlElementType mediaControlElementType(Node* node)
68 {
69     ASSERT_WITH_SECURITY_IMPLICATION(node->isMediaControlElement());
70     HTMLElement* element = toHTMLElement(node);
71     if (isHTMLInputElement(element))
72         return static_cast<MediaControlInputElement*>(element)->displayType();
73     return static_cast<MediaControlDivElement*>(element)->displayType();
74 }
75
76 MediaControlElement::MediaControlElement(MediaControlElementType displayType, HTMLElement* element)
77     : m_mediaController(0)
78     , m_displayType(displayType)
79     , m_element(element)
80 {
81 }
82
83 void MediaControlElement::hide()
84 {
85     m_element->setInlineStyleProperty(CSSPropertyDisplay, CSSValueNone);
86 }
87
88 void MediaControlElement::show()
89 {
90     m_element->removeInlineStyleProperty(CSSPropertyDisplay);
91 }
92
93 bool MediaControlElement::isShowing() const
94 {
95     const StyleProperties* propertySet = m_element->inlineStyle();
96     // Following the code from show() and hide() above, we only have
97     // to check for the presense of inline display.
98     return (!propertySet || !propertySet->getPropertyCSSValue(CSSPropertyDisplay));
99 }
100
101 void MediaControlElement::setDisplayType(MediaControlElementType displayType)
102 {
103     if (displayType == m_displayType)
104         return;
105
106     m_displayType = displayType;
107     if (auto object = m_element->renderer())
108         object->repaint();
109 }
110
111 // ----------------------------
112
113 MediaControlDivElement::MediaControlDivElement(Document& document, MediaControlElementType displayType)
114     : HTMLDivElement(divTag, document)
115     , MediaControlElement(displayType, this)
116 {
117 }
118
119 // ----------------------------
120
121 MediaControlInputElement::MediaControlInputElement(Document& document, MediaControlElementType displayType)
122     : HTMLInputElement(inputTag, document, 0, false)
123     , MediaControlElement(displayType, this)
124 {
125 }
126
127 // ----------------------------
128
129 MediaControlTimeDisplayElement::MediaControlTimeDisplayElement(Document& document, MediaControlElementType displayType)
130     : MediaControlDivElement(document, displayType)
131     , m_currentValue(0)
132 {
133 }
134
135 void MediaControlTimeDisplayElement::setCurrentValue(double time)
136 {
137     m_currentValue = time;
138 }
139
140 // ----------------------------
141
142 MediaControlMuteButtonElement::MediaControlMuteButtonElement(Document& document, MediaControlElementType displayType)
143     : MediaControlInputElement(document, displayType)
144 {
145 }
146
147 void MediaControlMuteButtonElement::defaultEventHandler(Event* event)
148 {
149     if (event->type() == eventNames().clickEvent) {
150         mediaController()->setMuted(!mediaController()->muted());
151         event->setDefaultHandled();
152     }
153
154     HTMLInputElement::defaultEventHandler(event);
155 }
156
157 void MediaControlMuteButtonElement::changedMute()
158 {
159     updateDisplayType();
160 }
161
162 void MediaControlMuteButtonElement::updateDisplayType()
163 {
164     setDisplayType(mediaController()->muted() ? MediaUnMuteButton : MediaMuteButton);
165 }
166
167 // ----------------------------
168
169 MediaControlSeekButtonElement::MediaControlSeekButtonElement(Document& document, MediaControlElementType displayType)
170     : MediaControlInputElement(document, displayType)
171     , m_actionOnStop(Nothing)
172     , m_seekType(Skip)
173     , m_seekTimer(this, &MediaControlSeekButtonElement::seekTimerFired)
174 {
175 }
176
177 void MediaControlSeekButtonElement::defaultEventHandler(Event* event)
178 {
179     // Set the mousedown and mouseup events as defaultHandled so they
180     // do not trigger drag start or end actions in MediaControlPanelElement.
181     if (event->type() == eventNames().mousedownEvent || event->type() == eventNames().mouseupEvent)
182         event->setDefaultHandled();
183 }
184
185 void MediaControlSeekButtonElement::setActive(bool flag, bool pause)
186 {
187     if (flag == active())
188         return;
189
190     if (flag)
191         startTimer();
192     else
193         stopTimer();
194
195     MediaControlInputElement::setActive(flag, pause);
196 }
197
198 void MediaControlSeekButtonElement::startTimer()
199 {
200     m_seekType = mediaController()->supportsScanning() ? Scan : Skip;
201
202     if (m_seekType == Skip) {
203         // Seeking by skipping requires the video to be paused during seeking.
204         m_actionOnStop = mediaController()->paused() ? Nothing : Play;
205         mediaController()->pause();
206     } else {
207         // Seeking by scanning requires the video to be playing during seeking.
208         m_actionOnStop = mediaController()->paused() ? Pause : Nothing;
209         mediaController()->play();
210         mediaController()->setPlaybackRate(nextRate());
211     }
212
213     m_seekTimer.start(0, m_seekType == Skip ? cSkipRepeatDelay : cScanRepeatDelay);
214 }
215
216 void MediaControlSeekButtonElement::stopTimer()
217 {
218     if (m_seekType == Scan)
219         mediaController()->setPlaybackRate(mediaController()->defaultPlaybackRate());
220
221     if (m_actionOnStop == Play)
222         mediaController()->play();
223     else if (m_actionOnStop == Pause)
224         mediaController()->pause();
225
226     if (m_seekTimer.isActive())
227         m_seekTimer.stop();
228 }
229
230 double MediaControlSeekButtonElement::nextRate() const
231 {
232     double rate = std::min(cScanMaximumRate, fabs(mediaController()->playbackRate() * 2));
233     if (!isForwardButton())
234         rate *= -1;
235     return rate;
236 }
237
238 void MediaControlSeekButtonElement::seekTimerFired(Timer<MediaControlSeekButtonElement>*)
239 {
240     if (m_seekType == Skip) {
241         double skipTime = isForwardButton() ? cSkipTime : -cSkipTime;
242         mediaController()->setCurrentTime(mediaController()->currentTime() + skipTime);
243     } else
244         mediaController()->setPlaybackRate(nextRate());
245 }
246
247 // ----------------------------
248
249 MediaControlVolumeSliderElement::MediaControlVolumeSliderElement(Document& document)
250     : MediaControlInputElement(document, MediaVolumeSlider)
251     , m_clearMutedOnUserInteraction(false)
252 {
253 }
254
255 void MediaControlVolumeSliderElement::defaultEventHandler(Event* event)
256 {
257     // Left button is 0. Rejects mouse events not from left button.
258     if (event->isMouseEvent() && static_cast<MouseEvent*>(event)->button())
259         return;
260
261     if (!renderer())
262         return;
263
264     MediaControlInputElement::defaultEventHandler(event);
265
266     if (event->type() == eventNames().mouseoverEvent || event->type() == eventNames().mouseoutEvent || event->type() == eventNames().mousemoveEvent)
267         return;
268
269     double volume = value().toDouble();
270     if (volume != mediaController()->volume())
271         mediaController()->setVolume(volume, ASSERT_NO_EXCEPTION);
272     if (m_clearMutedOnUserInteraction)
273         mediaController()->setMuted(false);
274     event->setDefaultHandled();
275 }
276
277 bool MediaControlVolumeSliderElement::willRespondToMouseMoveEvents()
278 {
279     if (!renderer())
280         return false;
281
282     return MediaControlInputElement::willRespondToMouseMoveEvents();
283 }
284
285 bool MediaControlVolumeSliderElement::willRespondToMouseClickEvents()
286 {
287     if (!renderer())
288         return false;
289
290     return MediaControlInputElement::willRespondToMouseClickEvents();
291 }
292
293 void MediaControlVolumeSliderElement::setVolume(double volume)
294 {
295     if (value().toDouble() != volume)
296         setValue(String::number(volume));
297 }
298
299 void MediaControlVolumeSliderElement::setClearMutedOnUserInteraction(bool clearMute)
300 {
301     m_clearMutedOnUserInteraction = clearMute;
302 }
303
304 } // namespace WebCore
305
306 #endif // ENABLE(VIDEO)