WebCore/rendering/RenderMedia.cpp
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2  * Copyright (C) 2007, 2008, 2009, 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 COMPUTER, INC. ``AS IS'' AND ANY
       
    14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
       
    15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
       
    16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
       
    17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
       
    18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
       
    19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
       
    20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
       
    21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
       
    22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
       
    23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
       
    24  */
       
    25 
       
    26 #include "config.h"
       
    27 
       
    28 #if ENABLE(VIDEO)
       
    29 #include "RenderMedia.h"
       
    30 
       
    31 #include "EventNames.h"
       
    32 #include "FloatConversion.h"
       
    33 #include "HTMLNames.h"
       
    34 #include "MediaControlElements.h"
       
    35 #include "MouseEvent.h"
       
    36 #include "Page.h"
       
    37 #include "RenderTheme.h"
       
    38 #include <wtf/CurrentTime.h>
       
    39 #include <wtf/MathExtras.h>
       
    40 
       
    41 using namespace std;
       
    42 
       
    43 namespace WebCore {
       
    44 
       
    45 using namespace HTMLNames;
       
    46 
       
    47 static const double cTimeUpdateRepeatDelay = 0.2;
       
    48 static const double cOpacityAnimationRepeatDelay = 0.05;
       
    49 
       
    50 RenderMedia::RenderMedia(HTMLMediaElement* video)
       
    51     : RenderImage(video)
       
    52     , m_timeUpdateTimer(this, &RenderMedia::timeUpdateTimerFired)
       
    53     , m_opacityAnimationTimer(this, &RenderMedia::opacityAnimationTimerFired)
       
    54     , m_mouseOver(false)
       
    55     , m_opacityAnimationStartTime(0)
       
    56     , m_opacityAnimationDuration(0)
       
    57     , m_opacityAnimationFrom(0)
       
    58     , m_opacityAnimationTo(1.0f)
       
    59 {
       
    60 }
       
    61 
       
    62 RenderMedia::RenderMedia(HTMLMediaElement* video, const IntSize& intrinsicSize)
       
    63     : RenderImage(video)
       
    64     , m_timeUpdateTimer(this, &RenderMedia::timeUpdateTimerFired)
       
    65     , m_opacityAnimationTimer(this, &RenderMedia::opacityAnimationTimerFired)
       
    66     , m_mouseOver(false)
       
    67     , m_opacityAnimationStartTime(0)
       
    68     , m_opacityAnimationDuration(0)
       
    69     , m_opacityAnimationFrom(0)
       
    70     , m_opacityAnimationTo(1.0f)
       
    71 {
       
    72     setIntrinsicSize(intrinsicSize);
       
    73 }
       
    74 
       
    75 RenderMedia::~RenderMedia()
       
    76 {
       
    77 }
       
    78 
       
    79 void RenderMedia::destroy()
       
    80 {
       
    81     if (m_controlsShadowRoot && m_controlsShadowRoot->renderer()) {
       
    82 
       
    83         // detach the panel before removing the shadow renderer to prevent a crash in m_controlsShadowRoot->detach() 
       
    84         //  when display: style changes
       
    85         m_panel->detach();
       
    86 
       
    87         removeChild(m_controlsShadowRoot->renderer());
       
    88         m_controlsShadowRoot->detach();
       
    89         m_controlsShadowRoot = 0;
       
    90     }
       
    91     RenderImage::destroy();
       
    92 }
       
    93 
       
    94 HTMLMediaElement* RenderMedia::mediaElement() const
       
    95 { 
       
    96     return static_cast<HTMLMediaElement*>(node()); 
       
    97 }
       
    98 
       
    99 MediaPlayer* RenderMedia::player() const
       
   100 {
       
   101     return mediaElement()->player();
       
   102 }
       
   103 
       
   104 void RenderMedia::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
       
   105 {
       
   106     RenderImage::styleDidChange(diff, oldStyle);
       
   107 
       
   108     if (m_controlsShadowRoot) {
       
   109         if (m_panel)
       
   110             m_panel->updateStyle();
       
   111         if (m_muteButton)
       
   112             m_muteButton->updateStyle();
       
   113         if (m_playButton)
       
   114             m_playButton->updateStyle();
       
   115         if (m_seekBackButton)
       
   116             m_seekBackButton->updateStyle();
       
   117         if (m_seekForwardButton)
       
   118             m_seekForwardButton->updateStyle();
       
   119         if (m_rewindButton)
       
   120             m_rewindButton->updateStyle();
       
   121         if (m_returnToRealtimeButton)
       
   122             m_returnToRealtimeButton->updateStyle();
       
   123         if (m_toggleClosedCaptionsButton)
       
   124             m_toggleClosedCaptionsButton->updateStyle();
       
   125         if (m_statusDisplay)
       
   126             m_statusDisplay->updateStyle();
       
   127         if (m_timelineContainer)
       
   128             m_timelineContainer->updateStyle();
       
   129         if (m_timeline)
       
   130             m_timeline->updateStyle();
       
   131         if (m_fullscreenButton)
       
   132             m_fullscreenButton->updateStyle();
       
   133         if (m_currentTimeDisplay)
       
   134             m_currentTimeDisplay->updateStyle();
       
   135         if (m_timeRemainingDisplay)
       
   136             m_timeRemainingDisplay->updateStyle();
       
   137         if (m_volumeSliderContainer)
       
   138             m_volumeSliderContainer->updateStyle();
       
   139         if (m_volumeSliderMuteButton)
       
   140             m_volumeSliderMuteButton->updateStyle();
       
   141         if (m_volumeSlider)
       
   142             m_volumeSlider->updateStyle();
       
   143     }
       
   144 }
       
   145 
       
   146 void RenderMedia::layout()
       
   147 {
       
   148     IntSize oldSize = contentBoxRect().size();
       
   149 
       
   150     RenderImage::layout();
       
   151 
       
   152     RenderBox* controlsRenderer = m_controlsShadowRoot ? m_controlsShadowRoot->renderBox() : 0;
       
   153     if (!controlsRenderer)
       
   154         return;
       
   155     IntSize newSize = contentBoxRect().size();
       
   156     if (newSize != oldSize || controlsRenderer->needsLayout()) {
       
   157 
       
   158         if (m_currentTimeDisplay && m_timeRemainingDisplay) {
       
   159             bool shouldShowTimeDisplays = shouldShowTimeDisplayControls();
       
   160             m_currentTimeDisplay->setVisible(shouldShowTimeDisplays);
       
   161             m_timeRemainingDisplay->setVisible(shouldShowTimeDisplays);
       
   162         }
       
   163 
       
   164         controlsRenderer->setLocation(borderLeft() + paddingLeft(), borderTop() + paddingTop());
       
   165         controlsRenderer->style()->setHeight(Length(newSize.height(), Fixed));
       
   166         controlsRenderer->style()->setWidth(Length(newSize.width(), Fixed));
       
   167         controlsRenderer->setNeedsLayout(true, false);
       
   168         controlsRenderer->layout();
       
   169         setChildNeedsLayout(false);
       
   170     }
       
   171 }
       
   172 
       
   173 void RenderMedia::createControlsShadowRoot()
       
   174 {
       
   175     ASSERT(!m_controlsShadowRoot);
       
   176     m_controlsShadowRoot = MediaControlShadowRootElement::create(mediaElement());
       
   177     addChild(m_controlsShadowRoot->renderer());
       
   178 }
       
   179 
       
   180 void RenderMedia::createPanel()
       
   181 {
       
   182     ASSERT(!m_panel);
       
   183     m_panel = MediaControlElement::create(mediaElement(), MEDIA_CONTROLS_PANEL);
       
   184     m_panel->attachToParent(m_controlsShadowRoot.get());
       
   185 }
       
   186 
       
   187 void RenderMedia::createMuteButton()
       
   188 {
       
   189     ASSERT(!m_muteButton);
       
   190     m_muteButton = MediaControlMuteButtonElement::create(mediaElement(), MediaControlMuteButtonElement::Controller);
       
   191     m_muteButton->attachToParent(m_panel.get());
       
   192 }
       
   193 
       
   194 void RenderMedia::createPlayButton()
       
   195 {
       
   196     ASSERT(!m_playButton);
       
   197     m_playButton = MediaControlPlayButtonElement::create(mediaElement());
       
   198     m_playButton->attachToParent(m_panel.get());
       
   199 }
       
   200 
       
   201 void RenderMedia::createSeekBackButton()
       
   202 {
       
   203     ASSERT(!m_seekBackButton);
       
   204     m_seekBackButton = MediaControlSeekButtonElement::create(mediaElement(), MEDIA_CONTROLS_SEEK_BACK_BUTTON);
       
   205     m_seekBackButton->attachToParent(m_panel.get());
       
   206 }
       
   207 
       
   208 void RenderMedia::createSeekForwardButton()
       
   209 {
       
   210     ASSERT(!m_seekForwardButton);
       
   211     m_seekForwardButton = MediaControlSeekButtonElement::create(mediaElement(), MEDIA_CONTROLS_SEEK_FORWARD_BUTTON);
       
   212     m_seekForwardButton->attachToParent(m_panel.get());
       
   213 }
       
   214 
       
   215 void RenderMedia::createRewindButton()
       
   216 {
       
   217     ASSERT(!m_rewindButton);
       
   218     m_rewindButton = MediaControlRewindButtonElement::create(mediaElement());
       
   219     m_rewindButton->attachToParent(m_panel.get());
       
   220 }
       
   221 
       
   222 void RenderMedia::createReturnToRealtimeButton()
       
   223 {
       
   224     ASSERT(!m_returnToRealtimeButton);
       
   225     m_returnToRealtimeButton = MediaControlReturnToRealtimeButtonElement::create(mediaElement());
       
   226     m_returnToRealtimeButton->attachToParent(m_panel.get());
       
   227 }
       
   228 
       
   229 void RenderMedia::createToggleClosedCaptionsButton()
       
   230 {
       
   231     ASSERT(!m_toggleClosedCaptionsButton);
       
   232     m_toggleClosedCaptionsButton = MediaControlToggleClosedCaptionsButtonElement::create(mediaElement());
       
   233     m_toggleClosedCaptionsButton->attachToParent(m_panel.get());
       
   234 }
       
   235 
       
   236 void RenderMedia::createStatusDisplay()
       
   237 {
       
   238     ASSERT(!m_statusDisplay);
       
   239     m_statusDisplay = MediaControlStatusDisplayElement::create(mediaElement());
       
   240     m_statusDisplay->attachToParent(m_panel.get());
       
   241 }
       
   242 
       
   243 void RenderMedia::createTimelineContainer()
       
   244 {
       
   245     ASSERT(!m_timelineContainer);
       
   246     m_timelineContainer = MediaControlTimelineContainerElement::create(mediaElement());
       
   247     m_timelineContainer->attachToParent(m_panel.get());
       
   248 }
       
   249 
       
   250 void RenderMedia::createTimeline()
       
   251 {
       
   252     ASSERT(!m_timeline);
       
   253     m_timeline = MediaControlTimelineElement::create(mediaElement());
       
   254     m_timeline->setAttribute(precisionAttr, "float");
       
   255     m_timeline->attachToParent(m_timelineContainer.get());
       
   256 }
       
   257 
       
   258 void RenderMedia::createVolumeSliderContainer()
       
   259 {
       
   260     ASSERT(!m_volumeSliderContainer);
       
   261     m_volumeSliderContainer = MediaControlVolumeSliderContainerElement::create(mediaElement());
       
   262     m_volumeSliderContainer->attachToParent(m_panel.get());
       
   263 }
       
   264 
       
   265 void RenderMedia::createVolumeSlider()
       
   266 {
       
   267     ASSERT(!m_volumeSlider);
       
   268     m_volumeSlider = MediaControlVolumeSliderElement::create(mediaElement());
       
   269     m_volumeSlider->setAttribute(precisionAttr, "float");
       
   270     m_volumeSlider->setAttribute(maxAttr, "1");
       
   271     m_volumeSlider->setAttribute(valueAttr, String::number(mediaElement()->volume()));
       
   272     m_volumeSlider->attachToParent(m_volumeSliderContainer.get());
       
   273 }
       
   274 
       
   275 void RenderMedia::createVolumeSliderMuteButton()
       
   276 {
       
   277     ASSERT(!m_volumeSliderMuteButton);
       
   278     m_volumeSliderMuteButton = MediaControlMuteButtonElement::create(mediaElement(), MediaControlMuteButtonElement::VolumeSlider);
       
   279     m_volumeSliderMuteButton->attachToParent(m_volumeSliderContainer.get());
       
   280     
       
   281 }
       
   282 
       
   283 void RenderMedia::createCurrentTimeDisplay()
       
   284 {
       
   285     ASSERT(!m_currentTimeDisplay);
       
   286     m_currentTimeDisplay = MediaControlTimeDisplayElement::create(mediaElement(), MEDIA_CONTROLS_CURRENT_TIME_DISPLAY);
       
   287     m_currentTimeDisplay->attachToParent(m_timelineContainer.get());
       
   288 }
       
   289 
       
   290 void RenderMedia::createTimeRemainingDisplay()
       
   291 {
       
   292     ASSERT(!m_timeRemainingDisplay);
       
   293     m_timeRemainingDisplay = MediaControlTimeDisplayElement::create(mediaElement(), MEDIA_CONTROLS_TIME_REMAINING_DISPLAY);
       
   294     m_timeRemainingDisplay->attachToParent(m_timelineContainer.get());
       
   295 }
       
   296 
       
   297 void RenderMedia::createFullscreenButton()
       
   298 {
       
   299     ASSERT(!m_fullscreenButton);
       
   300     m_fullscreenButton = MediaControlFullscreenButtonElement::create(mediaElement());
       
   301     m_fullscreenButton->attachToParent(m_panel.get());
       
   302 }
       
   303     
       
   304 void RenderMedia::updateFromElement()
       
   305 {
       
   306     updateControls();
       
   307 }
       
   308             
       
   309 void RenderMedia::updateControls()
       
   310 {
       
   311     HTMLMediaElement* media = mediaElement();
       
   312     if (!media->controls() || !media->inActiveDocument()) {
       
   313         if (m_controlsShadowRoot) {
       
   314             m_controlsShadowRoot->detach();
       
   315             m_panel = 0;
       
   316             m_muteButton = 0;
       
   317             m_playButton = 0;
       
   318             m_statusDisplay = 0;
       
   319             m_timelineContainer = 0;
       
   320             m_timeline = 0;
       
   321             m_seekBackButton = 0;
       
   322             m_seekForwardButton = 0;
       
   323             m_rewindButton = 0;
       
   324             m_returnToRealtimeButton = 0;
       
   325             m_currentTimeDisplay = 0;
       
   326             m_timeRemainingDisplay = 0;
       
   327             m_fullscreenButton = 0;
       
   328             m_volumeSliderContainer = 0;
       
   329             m_volumeSlider = 0;
       
   330             m_volumeSliderMuteButton = 0;
       
   331             m_controlsShadowRoot = 0;
       
   332             m_toggleClosedCaptionsButton = 0;
       
   333         }
       
   334         m_opacityAnimationTo = 1.0f;
       
   335         m_opacityAnimationTimer.stop();
       
   336         m_timeUpdateTimer.stop();
       
   337         return;
       
   338     }
       
   339     
       
   340     if (!m_controlsShadowRoot) {
       
   341         createControlsShadowRoot();
       
   342         createPanel();
       
   343         if (m_panel) {
       
   344             createRewindButton();
       
   345             createPlayButton();
       
   346             createReturnToRealtimeButton();
       
   347             createStatusDisplay();
       
   348             createTimelineContainer();
       
   349             if (m_timelineContainer) {
       
   350                 createCurrentTimeDisplay();
       
   351                 createTimeline();
       
   352                 createTimeRemainingDisplay();
       
   353             }
       
   354             createSeekBackButton();
       
   355             createSeekForwardButton();
       
   356             createToggleClosedCaptionsButton();
       
   357             createFullscreenButton();
       
   358             createMuteButton();
       
   359             createVolumeSliderContainer();
       
   360             if (m_volumeSliderContainer) {
       
   361                 createVolumeSlider();
       
   362                 createVolumeSliderMuteButton();
       
   363             }
       
   364             m_panel->attach();
       
   365         }
       
   366     }
       
   367 
       
   368     if (media->canPlay()) {
       
   369         if (m_timeUpdateTimer.isActive())
       
   370             m_timeUpdateTimer.stop();
       
   371     } else if (style()->visibility() == VISIBLE && m_timeline && m_timeline->renderer() && m_timeline->renderer()->style()->display() != NONE) {
       
   372         m_timeUpdateTimer.startRepeating(cTimeUpdateRepeatDelay);
       
   373     }
       
   374 
       
   375     
       
   376     if (m_panel) {
       
   377         // update() might alter the opacity of the element, especially if we are in the middle
       
   378         // of an animation. This is the only element concerned as we animate only this element.
       
   379         float opacityBeforeChangingStyle = m_panel->renderer() ? m_panel->renderer()->style()->opacity() : 0;
       
   380         m_panel->update();
       
   381         changeOpacity(m_panel.get(), opacityBeforeChangingStyle);
       
   382     }
       
   383     if (m_muteButton)
       
   384         m_muteButton->update();
       
   385     if (m_playButton)
       
   386         m_playButton->update();
       
   387     if (m_timelineContainer)
       
   388         m_timelineContainer->update();
       
   389     if (m_volumeSliderContainer)
       
   390         m_volumeSliderContainer->update();
       
   391     if (m_timeline)
       
   392         m_timeline->update();
       
   393     if (m_currentTimeDisplay)
       
   394         m_currentTimeDisplay->update();
       
   395     if (m_timeRemainingDisplay)
       
   396         m_timeRemainingDisplay->update();
       
   397     if (m_seekBackButton)
       
   398         m_seekBackButton->update();
       
   399     if (m_seekForwardButton)
       
   400         m_seekForwardButton->update();
       
   401     if (m_rewindButton)
       
   402         m_rewindButton->update();
       
   403     if (m_returnToRealtimeButton)
       
   404         m_returnToRealtimeButton->update();
       
   405     if (m_toggleClosedCaptionsButton)
       
   406         m_toggleClosedCaptionsButton->update();
       
   407     if (m_statusDisplay)
       
   408         m_statusDisplay->update();
       
   409     if (m_fullscreenButton)
       
   410         m_fullscreenButton->update();
       
   411     if (m_volumeSlider)
       
   412         m_volumeSlider->update();
       
   413     if (m_volumeSliderMuteButton)
       
   414         m_volumeSliderMuteButton->update();
       
   415 
       
   416     updateTimeDisplay();
       
   417     updateControlVisibility();
       
   418 }
       
   419 
       
   420 void RenderMedia::timeUpdateTimerFired(Timer<RenderMedia>*)
       
   421 {
       
   422     if (m_timeline)
       
   423         m_timeline->update(false);
       
   424     updateTimeDisplay();
       
   425 }
       
   426     
       
   427 void RenderMedia::updateTimeDisplay()
       
   428 {
       
   429     if (!m_currentTimeDisplay || !m_currentTimeDisplay->renderer() || m_currentTimeDisplay->renderer()->style()->display() == NONE || style()->visibility() != VISIBLE)
       
   430         return;
       
   431 
       
   432     float now = mediaElement()->currentTime();
       
   433     float duration = mediaElement()->duration();
       
   434 
       
   435     // Allow the theme to format the time
       
   436     ExceptionCode ec;
       
   437     m_currentTimeDisplay->setInnerText(theme()->formatMediaControlsCurrentTime(now, duration), ec);
       
   438     m_currentTimeDisplay->setCurrentValue(now);
       
   439     m_timeRemainingDisplay->setInnerText(theme()->formatMediaControlsRemainingTime(now, duration), ec);
       
   440     m_timeRemainingDisplay->setCurrentValue(now - duration);
       
   441 }
       
   442 
       
   443 void RenderMedia::updateControlVisibility() 
       
   444 {
       
   445     if (!m_panel || !m_panel->renderer())
       
   446         return;
       
   447 
       
   448     // Don't fade for audio controls.
       
   449     HTMLMediaElement* media = mediaElement();
       
   450     if (!media->hasVideo())
       
   451         return;
       
   452 
       
   453     // Don't fade if the media element is not visible
       
   454     if (style()->visibility() != VISIBLE)
       
   455         return;
       
   456     
       
   457     bool shouldHideController = !m_mouseOver && !media->canPlay();
       
   458 
       
   459     // Do fading manually, css animations don't work with shadow trees
       
   460 
       
   461     float animateFrom = m_panel->renderer()->style()->opacity();
       
   462     float animateTo = shouldHideController ? 0.0f : 1.0f;
       
   463 
       
   464     if (animateFrom == animateTo)
       
   465         return;
       
   466 
       
   467     if (m_opacityAnimationTimer.isActive()) {
       
   468         if (m_opacityAnimationTo == animateTo)
       
   469             return;
       
   470         m_opacityAnimationTimer.stop();
       
   471     }
       
   472 
       
   473     if (animateFrom < animateTo)
       
   474         m_opacityAnimationDuration = m_panel->renderer()->theme()->mediaControlsFadeInDuration();
       
   475     else
       
   476         m_opacityAnimationDuration = m_panel->renderer()->theme()->mediaControlsFadeOutDuration();
       
   477 
       
   478     m_opacityAnimationFrom = animateFrom;
       
   479     m_opacityAnimationTo = animateTo;
       
   480 
       
   481     m_opacityAnimationStartTime = currentTime();
       
   482     m_opacityAnimationTimer.startRepeating(cOpacityAnimationRepeatDelay);
       
   483 }
       
   484     
       
   485 void RenderMedia::changeOpacity(HTMLElement* e, float opacity) 
       
   486 {
       
   487     if (!e || !e->renderer() || !e->renderer()->style())
       
   488         return;
       
   489     RefPtr<RenderStyle> s = RenderStyle::clone(e->renderer()->style());
       
   490     s->setOpacity(opacity);
       
   491     // z-index can't be auto if opacity is used
       
   492     s->setZIndex(0);
       
   493     e->renderer()->setStyle(s.release());
       
   494 }
       
   495     
       
   496 void RenderMedia::opacityAnimationTimerFired(Timer<RenderMedia>*)
       
   497 {
       
   498     double time = currentTime() - m_opacityAnimationStartTime;
       
   499     if (time >= m_opacityAnimationDuration) {
       
   500         time = m_opacityAnimationDuration;
       
   501         m_opacityAnimationTimer.stop();
       
   502     }
       
   503     float opacity = narrowPrecisionToFloat(m_opacityAnimationFrom + (m_opacityAnimationTo - m_opacityAnimationFrom) * time / m_opacityAnimationDuration);
       
   504     changeOpacity(m_panel.get(), opacity);
       
   505 }
       
   506 
       
   507 void RenderMedia::updateVolumeSliderContainer(bool visible)
       
   508 {
       
   509     if (!mediaElement()->hasAudio() || !m_volumeSliderContainer || !m_volumeSlider)
       
   510         return;
       
   511 
       
   512     if (visible && !m_volumeSliderContainer->isVisible()) {
       
   513         if (!m_muteButton || !m_muteButton->renderer() || !m_muteButton->renderBox())
       
   514             return;
       
   515 
       
   516         RefPtr<RenderStyle> s = m_volumeSliderContainer->styleForElement();
       
   517         int height = s->height().isPercent() ? 0 : s->height().value();
       
   518         int width = s->width().isPercent() ? 0 : s->width().value();
       
   519         IntPoint offset = document()->page()->theme()->volumeSliderOffsetFromMuteButton(m_muteButton->renderer()->node(), IntSize(width, height));
       
   520         int x = offset.x() + m_muteButton->renderBox()->offsetLeft();
       
   521         int y = offset.y() + m_muteButton->renderBox()->offsetTop();
       
   522 
       
   523         m_volumeSliderContainer->setPosition(x, y);
       
   524         m_volumeSliderContainer->setVisible(true);
       
   525         m_volumeSliderContainer->update();
       
   526         m_volumeSlider->update();
       
   527     } else if (!visible && m_volumeSliderContainer->isVisible()) {
       
   528         m_volumeSliderContainer->setVisible(false);
       
   529         m_volumeSliderContainer->updateStyle();
       
   530     }
       
   531 }
       
   532 
       
   533 void RenderMedia::forwardEvent(Event* event)
       
   534 {
       
   535     if (event->isMouseEvent() && m_controlsShadowRoot) {
       
   536         MouseEvent* mouseEvent = static_cast<MouseEvent*>(event);
       
   537         IntPoint point(mouseEvent->absoluteLocation());
       
   538 
       
   539         bool defaultHandled = false;
       
   540         if (m_volumeSliderMuteButton && m_volumeSliderMuteButton->hitTest(point)) {
       
   541             m_volumeSliderMuteButton->defaultEventHandler(event);
       
   542             defaultHandled = event->defaultHandled();
       
   543         }
       
   544 
       
   545         bool showVolumeSlider = false;
       
   546         if (!defaultHandled && m_muteButton && m_muteButton->hitTest(point)) {
       
   547             m_muteButton->defaultEventHandler(event);
       
   548             if (event->type() != eventNames().mouseoutEvent)
       
   549                 showVolumeSlider = true;
       
   550         }
       
   551 
       
   552         if (m_volumeSliderContainer && m_volumeSliderContainer->hitTest(point))
       
   553             showVolumeSlider = true;
       
   554 
       
   555         if (m_volumeSlider && m_volumeSlider->hitTest(point)) {
       
   556             m_volumeSlider->defaultEventHandler(event);
       
   557             showVolumeSlider = true;
       
   558         }
       
   559 
       
   560         updateVolumeSliderContainer(showVolumeSlider);
       
   561 
       
   562         if (m_playButton && m_playButton->hitTest(point))
       
   563             m_playButton->defaultEventHandler(event);
       
   564 
       
   565         if (m_seekBackButton && m_seekBackButton->hitTest(point))
       
   566             m_seekBackButton->defaultEventHandler(event);
       
   567 
       
   568         if (m_seekForwardButton && m_seekForwardButton->hitTest(point))
       
   569             m_seekForwardButton->defaultEventHandler(event);
       
   570 
       
   571         if (m_rewindButton && m_rewindButton->hitTest(point))
       
   572             m_rewindButton->defaultEventHandler(event);
       
   573 
       
   574         if (m_returnToRealtimeButton && m_returnToRealtimeButton->hitTest(point))
       
   575             m_returnToRealtimeButton->defaultEventHandler(event);
       
   576 
       
   577        if (m_toggleClosedCaptionsButton && m_toggleClosedCaptionsButton->hitTest(point))
       
   578             m_toggleClosedCaptionsButton->defaultEventHandler(event);
       
   579 
       
   580         if (m_timeline && m_timeline->hitTest(point))
       
   581             m_timeline->defaultEventHandler(event);
       
   582 
       
   583         if (m_fullscreenButton && m_fullscreenButton->hitTest(point))
       
   584             m_fullscreenButton->defaultEventHandler(event);
       
   585         
       
   586         if (event->type() == eventNames().mouseoverEvent) {
       
   587             m_mouseOver = true;
       
   588             updateControlVisibility();
       
   589         }
       
   590         if (event->type() == eventNames().mouseoutEvent) {
       
   591             // When the scrollbar thumb captures mouse events, we should treat the mouse as still being over our renderer if the new target is a descendant
       
   592             Node* mouseOverNode = mouseEvent->relatedTarget() ? mouseEvent->relatedTarget()->toNode() : 0;
       
   593             RenderObject* mouseOverRenderer = mouseOverNode ? mouseOverNode->renderer() : 0;
       
   594             m_mouseOver = mouseOverRenderer && mouseOverRenderer->isDescendantOf(this);
       
   595             updateControlVisibility();
       
   596         }
       
   597     }
       
   598 }
       
   599 
       
   600 int RenderMedia::lowestPosition(bool includeOverflowInterior, bool includeSelf) const
       
   601 {
       
   602     int bottom = RenderImage::lowestPosition(includeOverflowInterior, includeSelf);
       
   603     if (!m_controlsShadowRoot || !m_controlsShadowRoot->renderer())
       
   604         return bottom;
       
   605     
       
   606     return max(bottom,  m_controlsShadowRoot->renderBox()->y() + m_controlsShadowRoot->renderBox()->lowestPosition(includeOverflowInterior, includeSelf));
       
   607 }
       
   608 
       
   609 int RenderMedia::rightmostPosition(bool includeOverflowInterior, bool includeSelf) const
       
   610 {
       
   611     int right = RenderImage::rightmostPosition(includeOverflowInterior, includeSelf);
       
   612     if (!m_controlsShadowRoot || !m_controlsShadowRoot->renderer())
       
   613         return right;
       
   614     
       
   615     return max(right, m_controlsShadowRoot->renderBox()->x() + m_controlsShadowRoot->renderBox()->rightmostPosition(includeOverflowInterior, includeSelf));
       
   616 }
       
   617 
       
   618 int RenderMedia::leftmostPosition(bool includeOverflowInterior, bool includeSelf) const
       
   619 {
       
   620     int left = RenderImage::leftmostPosition(includeOverflowInterior, includeSelf);
       
   621     if (!m_controlsShadowRoot || !m_controlsShadowRoot->renderer())
       
   622         return left;
       
   623     
       
   624     return min(left, m_controlsShadowRoot->renderBox()->x() +  m_controlsShadowRoot->renderBox()->leftmostPosition(includeOverflowInterior, includeSelf));
       
   625 }
       
   626 
       
   627 
       
   628 // We want the timeline slider to be at least 100 pixels wide.
       
   629 static const int minWidthToDisplayTimeDisplays = 16 + 16 + 45 + 100 + 45 + 16 + 1;
       
   630 
       
   631 bool RenderMedia::shouldShowTimeDisplayControls() const
       
   632 {
       
   633     if (!m_currentTimeDisplay && !m_timeRemainingDisplay)
       
   634         return false;
       
   635 
       
   636     int width = mediaElement()->renderBox()->width();
       
   637     return width >= minWidthToDisplayTimeDisplays * style()->effectiveZoom();
       
   638 }
       
   639 
       
   640 } // namespace WebCore
       
   641 
       
   642 #endif