OSDN Git Service

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