diff options
Diffstat (limited to 'src/3rdparty/webkit/WebCore/rendering/MediaControlElements.cpp')
-rw-r--r-- | src/3rdparty/webkit/WebCore/rendering/MediaControlElements.cpp | 254 |
1 files changed, 254 insertions, 0 deletions
diff --git a/src/3rdparty/webkit/WebCore/rendering/MediaControlElements.cpp b/src/3rdparty/webkit/WebCore/rendering/MediaControlElements.cpp new file mode 100644 index 0000000..48ea3ab --- /dev/null +++ b/src/3rdparty/webkit/WebCore/rendering/MediaControlElements.cpp @@ -0,0 +1,254 @@ +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(VIDEO) + +#include "MediaControlElements.h" + +#include "Event.h" +#include "EventNames.h" +#include "EventHandler.h" +#include "FloatConversion.h" +#include "Frame.h" +#include "HTMLNames.h" +#include "RenderSlider.h" +#include "RenderTheme.h" + +namespace WebCore { + +using namespace HTMLNames; + +// FIXME: These constants may need to be tweaked to better match the seeking in the QT plugin +static const float cSeekRepeatDelay = 0.1f; +static const float cStepTime = 0.07f; +static const float cSeekTime = 0.2f; + +MediaControlShadowRootElement::MediaControlShadowRootElement(Document* doc, HTMLMediaElement* mediaElement) + : HTMLDivElement(divTag, doc) + , m_mediaElement(mediaElement) +{ + RefPtr<RenderStyle> rootStyle = RenderStyle::create(); + rootStyle->inheritFrom(mediaElement->renderer()->style()); + rootStyle->setDisplay(BLOCK); + rootStyle->setPosition(RelativePosition); + RenderMediaControlShadowRoot* renderer = new (mediaElement->renderer()->renderArena()) RenderMediaControlShadowRoot(this); + renderer->setParent(mediaElement->renderer()); + renderer->setStyle(rootStyle.release()); + setRenderer(renderer); + setAttached(); + setInDocument(true); +} + +// ---------------------------- + +MediaControlInputElement::MediaControlInputElement(Document* doc, RenderStyle::PseudoId pseudo, const String& type, HTMLMediaElement* mediaElement) + : HTMLInputElement(inputTag, doc) + , m_mediaElement(mediaElement) +{ + setInputType(type); + RenderStyle* style = m_mediaElement->renderer()->getCachedPseudoStyle(pseudo); + RenderObject* renderer = createRenderer(m_mediaElement->renderer()->renderArena(), style); + if (renderer) { + setRenderer(renderer); + renderer->setStyle(style); + } + setAttached(); + setInDocument(true); +} + +void MediaControlInputElement::attachToParent(Element* parent) +{ + parent->addChild(this); + parent->renderer()->addChild(renderer()); +} + +void MediaControlInputElement::update() +{ + if (renderer()) + renderer()->updateFromElement(); +} + +bool MediaControlInputElement::hitTest(const IntPoint& absPoint) +{ + if (renderer() && renderer()->style()->hasAppearance()) + return theme()->hitTestMediaControlPart(renderer(), absPoint); + + return false; +} + +// ---------------------------- + +MediaControlMuteButtonElement::MediaControlMuteButtonElement(Document* doc, HTMLMediaElement* element) + : MediaControlInputElement(doc, RenderStyle::MEDIA_CONTROLS_MUTE_BUTTON, "button", element) +{ +} + +void MediaControlMuteButtonElement::defaultEventHandler(Event* event) +{ + if (event->type() == eventNames().clickEvent) { + m_mediaElement->setMuted(!m_mediaElement->muted()); + event->setDefaultHandled(); + } + HTMLInputElement::defaultEventHandler(event); +} + +// ---------------------------- + +MediaControlPlayButtonElement::MediaControlPlayButtonElement(Document* doc, HTMLMediaElement* element) + : MediaControlInputElement(doc, RenderStyle::MEDIA_CONTROLS_PLAY_BUTTON, "button", element) +{ +} + +void MediaControlPlayButtonElement::defaultEventHandler(Event* event) +{ + if (event->type() == eventNames().clickEvent) { + ExceptionCode ec; + if (m_mediaElement->canPlay()) + m_mediaElement->play(ec); + else + m_mediaElement->pause(ec); + event->setDefaultHandled(); + } + HTMLInputElement::defaultEventHandler(event); +} + +// ---------------------------- + +MediaControlSeekButtonElement::MediaControlSeekButtonElement(Document* doc, HTMLMediaElement* element, bool forward) + : MediaControlInputElement(doc, forward ? RenderStyle::MEDIA_CONTROLS_SEEK_FORWARD_BUTTON : RenderStyle::MEDIA_CONTROLS_SEEK_BACK_BUTTON, "button", element) + , m_forward(forward) + , m_seeking(false) + , m_capturing(false) + , m_seekTimer(this, &MediaControlSeekButtonElement::seekTimerFired) +{ +} + +void MediaControlSeekButtonElement::defaultEventHandler(Event* event) +{ + if (event->type() == eventNames().mousedownEvent) { + if (Frame* frame = document()->frame()) { + m_capturing = true; + frame->eventHandler()->setCapturingMouseEventsNode(this); + } + ExceptionCode ec; + m_mediaElement->pause(ec); + m_seekTimer.startRepeating(cSeekRepeatDelay); + event->setDefaultHandled(); + } else if (event->type() == eventNames().mouseupEvent) { + if (m_capturing) + if (Frame* frame = document()->frame()) { + m_capturing = false; + frame->eventHandler()->setCapturingMouseEventsNode(0); + } + ExceptionCode ec; + if (m_seeking || m_seekTimer.isActive()) { + if (!m_seeking) { + float stepTime = m_forward ? cStepTime : -cStepTime; + m_mediaElement->setCurrentTime(m_mediaElement->currentTime() + stepTime, ec); + } + m_seekTimer.stop(); + m_seeking = false; + event->setDefaultHandled(); + } + } + HTMLInputElement::defaultEventHandler(event); +} + +void MediaControlSeekButtonElement::seekTimerFired(Timer<MediaControlSeekButtonElement>*) +{ + ExceptionCode ec; + m_seeking = true; + float seekTime = m_forward ? cSeekTime : -cSeekTime; + m_mediaElement->setCurrentTime(m_mediaElement->currentTime() + seekTime, ec); +} + +// ---------------------------- + +MediaControlTimelineElement::MediaControlTimelineElement(Document* doc, HTMLMediaElement* element) + : MediaControlInputElement(doc, RenderStyle::MEDIA_CONTROLS_TIMELINE, "range", element) +{ + setAttribute(precisionAttr, "float"); +} + +void MediaControlTimelineElement::defaultEventHandler(Event* event) +{ + RenderSlider* slider = static_cast<RenderSlider*>(renderer()); + bool oldInDragMode = slider && slider->inDragMode(); + float oldTime = narrowPrecisionToFloat(value().toDouble()); + bool oldEnded = m_mediaElement->ended(); + + HTMLInputElement::defaultEventHandler(event); + + float time = narrowPrecisionToFloat(value().toDouble()); + if (oldTime != time || event->type() == eventNames().inputEvent) { + ExceptionCode ec; + m_mediaElement->setCurrentTime(time, ec); + } + // Media element stays in non-paused state when it reaches end. If the slider is now dragged + // to some other position the playback resumes which does not match usual media player UIs. + // Get the expected behavior by pausing explicitly in this case. + if (oldEnded && !m_mediaElement->ended() && !m_mediaElement->paused()) { + ExceptionCode ec; + m_mediaElement->pause(ec); + } + // Pause playback during drag, but do it without using DOM API which would generate events + bool inDragMode = slider && slider->inDragMode(); + if (inDragMode != oldInDragMode) + m_mediaElement->setPausedInternal(inDragMode); +} + +void MediaControlTimelineElement::update(bool updateDuration) +{ + if (updateDuration) { + float dur = m_mediaElement->duration(); + setAttribute(maxAttr, String::number(isfinite(dur) ? dur : 0)); + } + setValue(String::number(m_mediaElement->currentTime())); +} + +// ---------------------------- + +MediaControlFullscreenButtonElement::MediaControlFullscreenButtonElement(Document* doc, HTMLMediaElement* element) + : MediaControlInputElement(doc, RenderStyle::MEDIA_CONTROLS_FULLSCREEN_BUTTON, "button", element) +{ +} + +void MediaControlFullscreenButtonElement::defaultEventHandler(Event* event) +{ + if (event->type() == eventNames().clickEvent) { + event->setDefaultHandled(); + } + HTMLInputElement::defaultEventHandler(event); +} + +// ---------------------------- + +} //namespace WebCore +#endif // enable(video) |