• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008, 2009 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  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include "config.h"
30 
31 #if ENABLE(VIDEO)
32 
33 #include "MediaControlElements.h"
34 
35 #include "EventNames.h"
36 #include "FloatConversion.h"
37 #include "Frame.h"
38 #include "HTMLNames.h"
39 #include "LocalizedStrings.h"
40 #include "MouseEvent.h"
41 #include "Page.h"
42 #include "RenderMedia.h"
43 #include "RenderSlider.h"
44 #include "RenderTheme.h"
45 
46 namespace WebCore {
47 
48 using namespace HTMLNames;
49 
toParentMediaElement(RenderObject * o)50 HTMLMediaElement* toParentMediaElement(RenderObject* o)
51 {
52     Node* node = o->node();
53     Node* mediaNode = node ? node->shadowAncestorNode() : 0;
54     if (!mediaNode || (!mediaNode->hasTagName(HTMLNames::videoTag) && !mediaNode->hasTagName(HTMLNames::audioTag)))
55         return 0;
56 
57     return static_cast<HTMLMediaElement*>(mediaNode);
58 }
59 
60 // FIXME: These constants may need to be tweaked to better match the seeking in the QuickTime plug-in.
61 static const float cSeekRepeatDelay = 0.1f;
62 static const float cStepTime = 0.07f;
63 static const float cSeekTime = 0.2f;
64 
MediaControlShadowRootElement(Document * document,HTMLMediaElement * mediaElement)65 MediaControlShadowRootElement::MediaControlShadowRootElement(Document* document, HTMLMediaElement* mediaElement)
66     : HTMLDivElement(divTag, document)
67     , m_mediaElement(mediaElement)
68 {
69     RefPtr<RenderStyle> rootStyle = RenderStyle::create();
70     rootStyle->inheritFrom(mediaElement->renderer()->style());
71     rootStyle->setDisplay(BLOCK);
72     rootStyle->setPosition(RelativePosition);
73     RenderMediaControlShadowRoot* renderer = new (mediaElement->renderer()->renderArena()) RenderMediaControlShadowRoot(this);
74     renderer->setStyle(rootStyle.release());
75     setRenderer(renderer);
76     setAttached();
77     setInDocument(true);
78 }
79 
updateStyle()80 void MediaControlShadowRootElement::updateStyle()
81 {
82     if (renderer()) {
83         RenderStyle* timelineContainerStyle = m_mediaElement->renderer()->getCachedPseudoStyle(MEDIA_CONTROLS_TIMELINE_CONTAINER);
84         renderer()->setStyle(timelineContainerStyle);
85     }
86 }
87 
88 // ----------------------------
89 
MediaControlElement(Document * document,PseudoId pseudo,HTMLMediaElement * mediaElement)90 MediaControlElement::MediaControlElement(Document* document, PseudoId pseudo, HTMLMediaElement* mediaElement)
91     : HTMLDivElement(divTag, document)
92     , m_mediaElement(mediaElement)
93     , m_pseudoStyleId(pseudo)
94 {
95     setInDocument(true);
96     switch (pseudo) {
97     case MEDIA_CONTROLS_CURRENT_TIME_DISPLAY:
98         m_displayType = MediaCurrentTimeDisplay;
99         break;
100     case MEDIA_CONTROLS_TIME_REMAINING_DISPLAY:
101         m_displayType = MediaTimeRemainingDisplay;
102         break;
103     case MEDIA_CONTROLS_TIMELINE_CONTAINER:
104         m_displayType = MediaTimelineContainer;
105         break;
106     case MEDIA_CONTROLS_STATUS_DISPLAY:
107         m_displayType = MediaStatusDisplay;
108         break;
109     case MEDIA_CONTROLS_PANEL:
110         m_displayType = MediaControlsPanel;
111         break;
112     case MEDIA_CONTROLS_VOLUME_SLIDER_CONTAINER:
113         m_displayType = MediaVolumeSliderContainer;
114         break;
115     default:
116         ASSERT_NOT_REACHED();
117         break;
118     }
119 }
120 
attachToParent(Element * parent)121 void MediaControlElement::attachToParent(Element* parent)
122 {
123     parent->addChild(this);
124 }
125 
update()126 void MediaControlElement::update()
127 {
128     if (renderer())
129         renderer()->updateFromElement();
130     updateStyle();
131 }
132 
styleForElement()133 PassRefPtr<RenderStyle> MediaControlElement::styleForElement()
134 {
135     RenderStyle* style = m_mediaElement->renderer()->getCachedPseudoStyle(m_pseudoStyleId);
136     if (!style)
137         return 0;
138 
139     // text-decoration can't be overrided from CSS. So we do it here.
140     // See https://bugs.webkit.org/show_bug.cgi?id=27015
141     style->setTextDecoration(TDNONE);
142     style->setTextDecorationsInEffect(TDNONE);
143 
144     return style;
145 }
146 
rendererIsNeeded(RenderStyle * style)147 bool MediaControlElement::rendererIsNeeded(RenderStyle* style)
148 {
149     ASSERT(document()->page());
150 
151     return HTMLDivElement::rendererIsNeeded(style) && parent() && parent()->renderer()
152         && (!style->hasAppearance() || document()->page()->theme()->shouldRenderMediaControlPart(style->appearance(), m_mediaElement));
153 }
154 
attach()155 void MediaControlElement::attach()
156 {
157     RefPtr<RenderStyle> style = styleForElement();
158     if (!style)
159         return;
160     bool needsRenderer = rendererIsNeeded(style.get());
161     if (!needsRenderer)
162         return;
163     RenderObject* renderer = createRenderer(m_mediaElement->renderer()->renderArena(), style.get());
164     if (!renderer)
165         return;
166     renderer->setStyle(style.get());
167     setRenderer(renderer);
168     if (parent() && parent()->renderer()) {
169         // Find next sibling with a renderer to determine where to insert.
170         Node* sibling = nextSibling();
171         while (sibling && !sibling->renderer())
172             sibling = sibling->nextSibling();
173         parent()->renderer()->addChild(renderer, sibling ? sibling->renderer() : 0);
174     }
175     ContainerNode::attach();
176 }
177 
updateStyle()178 void MediaControlElement::updateStyle()
179 {
180     if (!m_mediaElement || !m_mediaElement->renderer())
181         return;
182 
183     RefPtr<RenderStyle> style = styleForElement();
184     if (!style)
185         return;
186 
187     bool needsRenderer = rendererIsNeeded(style.get()) && parent() && parent()->renderer();
188     if (renderer() && !needsRenderer)
189         detach();
190     else if (!renderer() && needsRenderer)
191         attach();
192     else if (renderer()) {
193         renderer()->setStyle(style.get());
194 
195         // Make sure that if there is any innerText renderer, it is updated as well.
196         if (firstChild() && firstChild()->renderer())
197             firstChild()->renderer()->setStyle(style.get());
198     }
199 }
200 
201 // ----------------------------
202 
MediaControlTimelineContainerElement(Document * document,HTMLMediaElement * element)203 MediaControlTimelineContainerElement::MediaControlTimelineContainerElement(Document* document, HTMLMediaElement* element)
204     : MediaControlElement(document, MEDIA_CONTROLS_TIMELINE_CONTAINER, element)
205 {
206 }
207 
rendererIsNeeded(RenderStyle * style)208 bool MediaControlTimelineContainerElement::rendererIsNeeded(RenderStyle* style)
209 {
210     if (!MediaControlElement::rendererIsNeeded(style))
211         return false;
212 
213     // This is for MediaControllerThemeClassic:
214     // If there is no style for MediaControlStatusDisplayElement style, don't hide
215     // the timeline.
216     if (!m_mediaElement->renderer()->getCachedPseudoStyle(MEDIA_CONTROLS_STATUS_DISPLAY))
217         return true;
218 
219     float duration = m_mediaElement->duration();
220     return !isnan(duration) && !isinf(duration);
221 }
222 
223 // ----------------------------
224 
MediaControlVolumeSliderContainerElement(Document * doc,HTMLMediaElement * element)225 MediaControlVolumeSliderContainerElement::MediaControlVolumeSliderContainerElement(Document* doc, HTMLMediaElement* element)
226     : MediaControlElement(doc, MEDIA_CONTROLS_VOLUME_SLIDER_CONTAINER, element)
227     , m_isVisible(false)
228     , m_x(0)
229     , m_y(0)
230 {
231 }
232 
styleForElement()233 PassRefPtr<RenderStyle> MediaControlVolumeSliderContainerElement::styleForElement()
234 {
235     RefPtr<RenderStyle> style = MediaControlElement::styleForElement();
236     style->setPosition(AbsolutePosition);
237     style->setLeft(Length(m_x, Fixed));
238     style->setTop(Length(m_y, Fixed));
239     style->setDisplay(m_isVisible ? BLOCK : NONE);
240     return style;
241 }
242 
setVisible(bool visible)243 void MediaControlVolumeSliderContainerElement::setVisible(bool visible)
244 {
245     if (visible == m_isVisible)
246         return;
247     m_isVisible = visible;
248 }
249 
setPosition(int x,int y)250 void MediaControlVolumeSliderContainerElement::setPosition(int x, int y)
251 {
252     if (x == m_x && y == m_y)
253         return;
254     m_x = x;
255     m_y = y;
256 }
257 
hitTest(const IntPoint & absPoint)258 bool MediaControlVolumeSliderContainerElement::hitTest(const IntPoint& absPoint)
259 {
260     if (renderer() && renderer()->style()->hasAppearance())
261         return renderer()->theme()->hitTestMediaControlPart(renderer(), absPoint);
262 
263     return false;
264 }
265 
266 // ----------------------------
267 
MediaControlStatusDisplayElement(Document * document,HTMLMediaElement * element)268 MediaControlStatusDisplayElement::MediaControlStatusDisplayElement(Document* document, HTMLMediaElement* element)
269     : MediaControlElement(document, MEDIA_CONTROLS_STATUS_DISPLAY, element)
270     , m_stateBeingDisplayed(Nothing)
271 {
272 }
273 
update()274 void MediaControlStatusDisplayElement::update()
275 {
276     MediaControlElement::update();
277 
278     // Get the new state that we'll have to display.
279     StateBeingDisplayed newStateToDisplay = Nothing;
280 
281     if (m_mediaElement->readyState() != HTMLMediaElement::HAVE_ENOUGH_DATA && !m_mediaElement->currentSrc().isEmpty())
282         newStateToDisplay = Loading;
283     else if (m_mediaElement->movieLoadType() == MediaPlayer::LiveStream)
284         newStateToDisplay = LiveBroadcast;
285 
286     // Propagate only if needed.
287     if (newStateToDisplay == m_stateBeingDisplayed)
288         return;
289     m_stateBeingDisplayed = newStateToDisplay;
290 
291     ExceptionCode e;
292     switch (m_stateBeingDisplayed) {
293     case Nothing:
294         setInnerText("", e);
295         break;
296     case Loading:
297         setInnerText(mediaElementLoadingStateText(), e);
298         break;
299     case LiveBroadcast:
300         setInnerText(mediaElementLiveBroadcastStateText(), e);
301         break;
302     }
303 }
304 
rendererIsNeeded(RenderStyle * style)305 bool MediaControlStatusDisplayElement::rendererIsNeeded(RenderStyle* style)
306 {
307     if (!MediaControlElement::rendererIsNeeded(style))
308         return false;
309     float duration = m_mediaElement->duration();
310     return (isnan(duration) || isinf(duration));
311 }
312 
313 // ----------------------------
314 
MediaControlInputElement(Document * document,PseudoId pseudo,const String & type,HTMLMediaElement * mediaElement)315 MediaControlInputElement::MediaControlInputElement(Document* document, PseudoId pseudo, const String& type, HTMLMediaElement* mediaElement)
316     : HTMLInputElement(inputTag, document)
317     , m_mediaElement(mediaElement)
318     , m_pseudoStyleId(pseudo)
319 {
320     setInputType(type);
321     setInDocument(true);
322 
323     switch (pseudo) {
324     case MEDIA_CONTROLS_MUTE_BUTTON:
325         m_displayType = MediaMuteButton;
326         break;
327     case MEDIA_CONTROLS_PLAY_BUTTON:
328         m_displayType = MediaPlayButton;
329         break;
330     case MEDIA_CONTROLS_SEEK_FORWARD_BUTTON:
331         m_displayType = MediaSeekForwardButton;
332         break;
333     case MEDIA_CONTROLS_SEEK_BACK_BUTTON:
334         m_displayType = MediaSeekBackButton;
335         break;
336     case MEDIA_CONTROLS_FULLSCREEN_BUTTON:
337         m_displayType = MediaFullscreenButton;
338         break;
339     case MEDIA_CONTROLS_TIMELINE:
340         m_displayType = MediaSlider;
341         break;
342     case MEDIA_CONTROLS_RETURN_TO_REALTIME_BUTTON:
343         m_displayType = MediaReturnToRealtimeButton;
344         break;
345     case MEDIA_CONTROLS_REWIND_BUTTON:
346         m_displayType = MediaRewindButton;
347         break;
348     case MEDIA_CONTROLS_VOLUME_SLIDER:
349         m_displayType = MediaVolumeSlider;
350         break;
351     case MEDIA_CONTROLS_TOGGLE_CLOSED_CAPTIONS_BUTTON:
352         m_displayType = MediaShowClosedCaptionsButton;
353         break;
354     default:
355         ASSERT_NOT_REACHED();
356         break;
357     }
358 }
359 
attachToParent(Element * parent)360 void MediaControlInputElement::attachToParent(Element* parent)
361 {
362     parent->addChild(this);
363 }
364 
update()365 void MediaControlInputElement::update()
366 {
367     updateDisplayType();
368     if (renderer())
369         renderer()->updateFromElement();
370     updateStyle();
371 }
372 
styleForElement()373 PassRefPtr<RenderStyle> MediaControlInputElement::styleForElement()
374 {
375     return m_mediaElement->renderer()->getCachedPseudoStyle(m_pseudoStyleId);
376 }
377 
rendererIsNeeded(RenderStyle * style)378 bool MediaControlInputElement::rendererIsNeeded(RenderStyle* style)
379 {
380     ASSERT(document()->page());
381 
382     return HTMLInputElement::rendererIsNeeded(style) && parent() && parent()->renderer()
383         && (!style->hasAppearance() || document()->page()->theme()->shouldRenderMediaControlPart(style->appearance(), m_mediaElement));
384 }
385 
attach()386 void MediaControlInputElement::attach()
387 {
388     RefPtr<RenderStyle> style = styleForElement();
389     if (!style)
390         return;
391 
392     bool needsRenderer = rendererIsNeeded(style.get());
393     if (!needsRenderer)
394         return;
395     RenderObject* renderer = createRenderer(m_mediaElement->renderer()->renderArena(), style.get());
396     if (!renderer)
397         return;
398     renderer->setStyle(style.get());
399     setRenderer(renderer);
400     if (parent() && parent()->renderer()) {
401         // Find next sibling with a renderer to determine where to insert.
402         Node* sibling = nextSibling();
403         while (sibling && !sibling->renderer())
404             sibling = sibling->nextSibling();
405         parent()->renderer()->addChild(renderer, sibling ? sibling->renderer() : 0);
406     }
407     ContainerNode::attach();
408 }
409 
updateStyle()410 void MediaControlInputElement::updateStyle()
411 {
412     if (!m_mediaElement || !m_mediaElement->renderer())
413         return;
414 
415     RefPtr<RenderStyle> style = styleForElement();
416     if (!style)
417         return;
418 
419     bool needsRenderer = rendererIsNeeded(style.get()) && parent() && parent()->renderer();
420     if (renderer() && !needsRenderer)
421         detach();
422     else if (!renderer() && needsRenderer)
423         attach();
424     else if (renderer())
425         renderer()->setStyle(style.get());
426 }
427 
hitTest(const IntPoint & absPoint)428 bool MediaControlInputElement::hitTest(const IntPoint& absPoint)
429 {
430     if (renderer() && renderer()->style()->hasAppearance())
431         return renderer()->theme()->hitTestMediaControlPart(renderer(), absPoint);
432 
433     return false;
434 }
435 
setDisplayType(MediaControlElementType displayType)436 void MediaControlInputElement::setDisplayType(MediaControlElementType displayType)
437 {
438     if (displayType == m_displayType)
439         return;
440 
441     m_displayType = displayType;
442     if (RenderObject* object = renderer())
443         object->repaint();
444 }
445 
446 // ----------------------------
447 
MediaControlMuteButtonElement(Document * document,HTMLMediaElement * element)448 MediaControlMuteButtonElement::MediaControlMuteButtonElement(Document* document, HTMLMediaElement* element)
449     : MediaControlInputElement(document, MEDIA_CONTROLS_MUTE_BUTTON, "button", element)
450 {
451 }
452 
defaultEventHandler(Event * event)453 void MediaControlMuteButtonElement::defaultEventHandler(Event* event)
454 {
455     if (event->type() == eventNames().clickEvent) {
456         m_mediaElement->setMuted(!m_mediaElement->muted());
457         event->setDefaultHandled();
458     }
459     HTMLInputElement::defaultEventHandler(event);
460 }
461 
updateDisplayType()462 void MediaControlMuteButtonElement::updateDisplayType()
463 {
464     setDisplayType(m_mediaElement->muted() ? MediaUnMuteButton : MediaMuteButton);
465 }
466 
467 // ----------------------------
468 
MediaControlPlayButtonElement(Document * document,HTMLMediaElement * element)469 MediaControlPlayButtonElement::MediaControlPlayButtonElement(Document* document, HTMLMediaElement* element)
470     : MediaControlInputElement(document, MEDIA_CONTROLS_PLAY_BUTTON, "button", element)
471 {
472 }
473 
defaultEventHandler(Event * event)474 void MediaControlPlayButtonElement::defaultEventHandler(Event* event)
475 {
476     if (event->type() == eventNames().clickEvent) {
477         m_mediaElement->togglePlayState();
478         event->setDefaultHandled();
479     }
480     HTMLInputElement::defaultEventHandler(event);
481 }
482 
updateDisplayType()483 void MediaControlPlayButtonElement::updateDisplayType()
484 {
485     setDisplayType(m_mediaElement->canPlay() ? MediaPlayButton : MediaPauseButton);
486 }
487 
488 // ----------------------------
489 
MediaControlSeekButtonElement(Document * document,HTMLMediaElement * element,bool forward)490 MediaControlSeekButtonElement::MediaControlSeekButtonElement(Document* document, HTMLMediaElement* element, bool forward)
491     : MediaControlInputElement(document, forward ? MEDIA_CONTROLS_SEEK_FORWARD_BUTTON : MEDIA_CONTROLS_SEEK_BACK_BUTTON,
492                                "button", element)
493     , m_forward(forward)
494     , m_seeking(false)
495     , m_capturing(false)
496     , m_seekTimer(this, &MediaControlSeekButtonElement::seekTimerFired)
497 {
498 }
499 
defaultEventHandler(Event * event)500 void MediaControlSeekButtonElement::defaultEventHandler(Event* event)
501 {
502     if (event->type() == eventNames().mousedownEvent) {
503         if (Frame* frame = document()->frame()) {
504             m_capturing = true;
505             frame->eventHandler()->setCapturingMouseEventsNode(this);
506         }
507         m_mediaElement->pause(event->fromUserGesture());
508         m_seekTimer.startRepeating(cSeekRepeatDelay);
509         event->setDefaultHandled();
510     } else if (event->type() == eventNames().mouseupEvent) {
511         if (m_capturing)
512             if (Frame* frame = document()->frame()) {
513                 m_capturing = false;
514                 frame->eventHandler()->setCapturingMouseEventsNode(0);
515             }
516         ExceptionCode ec;
517         if (m_seeking || m_seekTimer.isActive()) {
518             if (!m_seeking) {
519                 float stepTime = m_forward ? cStepTime : -cStepTime;
520                 m_mediaElement->setCurrentTime(m_mediaElement->currentTime() + stepTime, ec);
521             }
522             m_seekTimer.stop();
523             m_seeking = false;
524             event->setDefaultHandled();
525         }
526     }
527     HTMLInputElement::defaultEventHandler(event);
528 }
529 
seekTimerFired(Timer<MediaControlSeekButtonElement> *)530 void MediaControlSeekButtonElement::seekTimerFired(Timer<MediaControlSeekButtonElement>*)
531 {
532     ExceptionCode ec;
533     m_seeking = true;
534     float seekTime = m_forward ? cSeekTime : -cSeekTime;
535     m_mediaElement->setCurrentTime(m_mediaElement->currentTime() + seekTime, ec);
536 }
537 
detach()538 void MediaControlSeekButtonElement::detach()
539 {
540     if (m_capturing) {
541         if (Frame* frame = document()->frame())
542             frame->eventHandler()->setCapturingMouseEventsNode(0);
543     }
544     MediaControlInputElement::detach();
545 }
546 
547 
548 // ----------------------------
549 
MediaControlRewindButtonElement(Document * document,HTMLMediaElement * element)550 MediaControlRewindButtonElement::MediaControlRewindButtonElement(Document* document, HTMLMediaElement* element)
551     : MediaControlInputElement(document, MEDIA_CONTROLS_REWIND_BUTTON, "button", element)
552 {
553 }
554 
defaultEventHandler(Event * event)555 void MediaControlRewindButtonElement::defaultEventHandler(Event* event)
556 {
557     if (event->type() == eventNames().clickEvent) {
558         m_mediaElement->rewind(30);
559         event->setDefaultHandled();
560     }
561     HTMLInputElement::defaultEventHandler(event);
562 }
563 
564 
565 // ----------------------------
566 
MediaControlReturnToRealtimeButtonElement(Document * document,HTMLMediaElement * element)567 MediaControlReturnToRealtimeButtonElement::MediaControlReturnToRealtimeButtonElement(Document* document, HTMLMediaElement* element)
568     : MediaControlInputElement(document, MEDIA_CONTROLS_RETURN_TO_REALTIME_BUTTON, "button", element)
569 {
570 }
571 
defaultEventHandler(Event * event)572 void MediaControlReturnToRealtimeButtonElement::defaultEventHandler(Event* event)
573 {
574     if (event->type() == eventNames().clickEvent) {
575         m_mediaElement->returnToRealtime();
576         event->setDefaultHandled();
577     }
578     HTMLInputElement::defaultEventHandler(event);
579 }
580 
581 
582 // ----------------------------
583 
MediaControlToggleClosedCaptionsButtonElement(Document * doc,HTMLMediaElement * element)584 MediaControlToggleClosedCaptionsButtonElement::MediaControlToggleClosedCaptionsButtonElement(Document* doc, HTMLMediaElement* element)
585     : MediaControlInputElement(doc, MEDIA_CONTROLS_TOGGLE_CLOSED_CAPTIONS_BUTTON, "button", element)
586 {
587 }
588 
defaultEventHandler(Event * event)589 void MediaControlToggleClosedCaptionsButtonElement::defaultEventHandler(Event* event)
590 {
591     if (event->type() == eventNames().clickEvent) {
592         m_mediaElement->setClosedCaptionsVisible(!m_mediaElement->closedCaptionsVisible());
593         setChecked(m_mediaElement->closedCaptionsVisible());
594         event->setDefaultHandled();
595     }
596     HTMLInputElement::defaultEventHandler(event);
597 }
598 
updateDisplayType()599 void MediaControlToggleClosedCaptionsButtonElement::updateDisplayType()
600 {
601     setDisplayType(m_mediaElement->closedCaptionsVisible() ? MediaHideClosedCaptionsButton : MediaShowClosedCaptionsButton);
602 }
603 
604 
605 // ----------------------------
606 
MediaControlTimelineElement(Document * document,HTMLMediaElement * element)607 MediaControlTimelineElement::MediaControlTimelineElement(Document* document, HTMLMediaElement* element)
608     : MediaControlInputElement(document, MEDIA_CONTROLS_TIMELINE, "range", element)
609 {
610 }
611 
defaultEventHandler(Event * event)612 void MediaControlTimelineElement::defaultEventHandler(Event* event)
613 {
614     // Left button is 0. Rejects mouse events not from left button.
615     if (event->isMouseEvent() && static_cast<MouseEvent*>(event)->button())
616         return;
617 
618     if (event->type() == eventNames().mousedownEvent)
619         m_mediaElement->beginScrubbing();
620 
621     MediaControlInputElement::defaultEventHandler(event);
622 
623     if (event->type() == eventNames().mouseoverEvent || event->type() == eventNames().mouseoutEvent || event->type() == eventNames().mousemoveEvent)
624         return;
625 
626     float time = narrowPrecisionToFloat(value().toDouble());
627     if (time != m_mediaElement->currentTime()) {
628         ExceptionCode ec;
629         m_mediaElement->setCurrentTime(time, ec);
630     }
631 
632     RenderSlider* slider = toRenderSlider(renderer());
633     if (slider && slider->inDragMode())
634         toRenderMedia(m_mediaElement->renderer())->updateTimeDisplay();
635 
636     if (event->type() == eventNames().mouseupEvent)
637         m_mediaElement->endScrubbing();
638 }
639 
update(bool updateDuration)640 void MediaControlTimelineElement::update(bool updateDuration)
641 {
642     if (updateDuration) {
643         float dur = m_mediaElement->duration();
644         setAttribute(maxAttr, String::number(isfinite(dur) ? dur : 0));
645     }
646     setValue(String::number(m_mediaElement->currentTime()));
647     MediaControlInputElement::update();
648 }
649 
650 // ----------------------------
651 
MediaControlVolumeSliderElement(Document * document,HTMLMediaElement * element)652 MediaControlVolumeSliderElement::MediaControlVolumeSliderElement(Document* document, HTMLMediaElement* element)
653     : MediaControlInputElement(document, MEDIA_CONTROLS_VOLUME_SLIDER, "range", element)
654 {
655 }
656 
defaultEventHandler(Event * event)657 void MediaControlVolumeSliderElement::defaultEventHandler(Event* event)
658 {
659     // Left button is 0. Rejects mouse events not from left button.
660     if (event->isMouseEvent() && static_cast<MouseEvent*>(event)->button())
661         return;
662 
663     MediaControlInputElement::defaultEventHandler(event);
664 
665     if (event->type() == eventNames().mouseoverEvent || event->type() == eventNames().mouseoutEvent || event->type() == eventNames().mousemoveEvent)
666         return;
667 
668     float volume = narrowPrecisionToFloat(value().toDouble());
669     if (volume != m_mediaElement->volume()) {
670         ExceptionCode ec = 0;
671         m_mediaElement->setVolume(volume, ec);
672         ASSERT(!ec);
673     }
674 }
675 
update()676 void MediaControlVolumeSliderElement::update()
677 {
678     float volume = m_mediaElement->volume();
679     if (value().toFloat() != volume)
680         setValue(String::number(volume));
681     MediaControlInputElement::update();
682 }
683 
684 // ----------------------------
685 
MediaControlFullscreenButtonElement(Document * document,HTMLMediaElement * element)686 MediaControlFullscreenButtonElement::MediaControlFullscreenButtonElement(Document* document, HTMLMediaElement* element)
687     : MediaControlInputElement(document, MEDIA_CONTROLS_FULLSCREEN_BUTTON, "button", element)
688 {
689 }
690 
defaultEventHandler(Event * event)691 void MediaControlFullscreenButtonElement::defaultEventHandler(Event* event)
692 {
693     if (event->type() == eventNames().clickEvent) {
694         m_mediaElement->enterFullscreen();
695         event->setDefaultHandled();
696     }
697     HTMLInputElement::defaultEventHandler(event);
698 }
699 
700 // ----------------------------
701 
MediaControlTimeDisplayElement(Document * document,PseudoId pseudo,HTMLMediaElement * element)702 MediaControlTimeDisplayElement::MediaControlTimeDisplayElement(Document* document, PseudoId pseudo, HTMLMediaElement* element)
703     : MediaControlElement(document, pseudo, element)
704     , m_currentValue(0)
705     , m_isVisible(true)
706 {
707 }
708 
styleForElement()709 PassRefPtr<RenderStyle> MediaControlTimeDisplayElement::styleForElement()
710 {
711     RefPtr<RenderStyle> style = MediaControlElement::styleForElement();
712     if (!m_isVisible) {
713         style = RenderStyle::clone(style.get());
714         style->setWidth(Length(0, Fixed));
715     }
716     return style;
717 }
718 
setVisible(bool visible)719 void MediaControlTimeDisplayElement::setVisible(bool visible)
720 {
721     if (visible == m_isVisible)
722         return;
723     m_isVisible = visible;
724 
725     // This function is used during the RenderMedia::layout()
726     // call, where we cannot change the renderer at this time.
727     if (!renderer() || !renderer()->style())
728         return;
729 
730     RefPtr<RenderStyle> style = styleForElement();
731     renderer()->setStyle(style.get());
732 }
733 
setCurrentValue(float time)734 void MediaControlTimeDisplayElement::setCurrentValue(float time)
735 {
736     m_currentValue = time;
737 }
738 
739 
740 } //namespace WebCore
741 #endif // enable(video)
742