| Index: Source/core/html/shadow/MediaControlElements.cpp
|
| diff --git a/Source/core/html/shadow/MediaControlElements.cpp b/Source/core/html/shadow/MediaControlElements.cpp
|
| index 3e2c7537ea26df6c70a25bb2dc7c27e768fc543f..c775ab4d55376b5d10388832ea2e58a6095979e0 100644
|
| --- a/Source/core/html/shadow/MediaControlElements.cpp
|
| +++ b/Source/core/html/shadow/MediaControlElements.cpp
|
| @@ -33,6 +33,9 @@
|
| #include "bindings/core/v8/ExceptionStatePlaceholder.h"
|
| #include "core/InputTypeNames.h"
|
| #include "core/dom/DOMTokenList.h"
|
| +#include "core/dom/Document.h"
|
| +#include "core/dom/Element.h"
|
| +#include "core/dom/Text.h"
|
| #include "core/dom/shadow/ShadowRoot.h"
|
| #include "core/events/MouseEvent.h"
|
| #include "core/frame/LocalFrame.h"
|
| @@ -40,11 +43,14 @@
|
| #include "core/html/MediaController.h"
|
| #include "core/html/TimeRanges.h"
|
| #include "core/html/shadow/MediaControls.h"
|
| +#include "core/html/track/TextTrackList.h"
|
| #include "core/layout/LayoutSlider.h"
|
| #include "core/layout/LayoutTheme.h"
|
| #include "core/layout/LayoutVideo.h"
|
| #include "core/page/EventHandler.h"
|
| +#include "platform/EventDispatchForbiddenScope.h"
|
| #include "platform/RuntimeEnabledFeatures.h"
|
| +#include "platform/text/PlatformLocale.h"
|
|
|
| namespace blink {
|
|
|
| @@ -53,6 +59,12 @@ using namespace HTMLNames;
|
| // This is the duration from mediaControls.css
|
| static const double fadeOutDuration = 0.3;
|
|
|
| +// track index attribute specifies trackIndex for text track list elements
|
| +static const char trackIndexAttr[] = "x-webkit-track-index";
|
| +
|
| +// when specified as trackIndex, disable text tracks
|
| +static const int trackIndexOffValue = -1;
|
| +
|
| static bool isUserInteractionEvent(Event* event)
|
| {
|
| const AtomicString& type = event->type();
|
| @@ -341,14 +353,12 @@ void MediaControlToggleClosedCaptionsButtonElement::updateDisplayType()
|
| {
|
| bool captionsVisible = mediaElement().closedCaptionsVisible();
|
| setDisplayType(captionsVisible ? MediaHideClosedCaptionsButton : MediaShowClosedCaptionsButton);
|
| - setChecked(captionsVisible);
|
| }
|
|
|
| void MediaControlToggleClosedCaptionsButtonElement::defaultEventHandler(Event* event)
|
| {
|
| if (event->type() == EventTypeNames::click) {
|
| - mediaElement().setClosedCaptionsVisible(!mediaElement().closedCaptionsVisible());
|
| - setChecked(mediaElement().closedCaptionsVisible());
|
| + mediaControls().toggleTextTrackList();
|
| updateDisplayType();
|
| event->setDefaultHandled();
|
| }
|
| @@ -358,6 +368,155 @@ void MediaControlToggleClosedCaptionsButtonElement::defaultEventHandler(Event* e
|
|
|
| // ----------------------------
|
|
|
| +MediaControlTextTrackListContainerElement::MediaControlTextTrackListContainerElement(MediaControls& mediaControls)
|
| + : MediaControlDivElement(mediaControls, MediaTextTrackListContainer)
|
| +{
|
| +}
|
| +
|
| +PassRefPtrWillBeRawPtr<MediaControlTextTrackListContainerElement>
|
| + MediaControlTextTrackListContainerElement::create(MediaControls& mediaControls)
|
| +{
|
| + RefPtrWillBeRawPtr<MediaControlTextTrackListContainerElement> element =
|
| + adoptRefWillBeNoop(new MediaControlTextTrackListContainerElement(mediaControls));
|
| + element->setShadowPseudoId(AtomicString("-webkit-media-controls-text-track-list-container",
|
| + AtomicString::ConstructFromLiteral));
|
| + element->hide();
|
| + return element.release();
|
| +}
|
| +
|
| +// ----------------------------
|
| +
|
| +MediaControlTextTrackListElement::MediaControlTextTrackListElement(MediaControls& mediaControls)
|
| + : MediaControlDivElement(mediaControls, MediaTextTrackList)
|
| +{
|
| +}
|
| +
|
| +PassRefPtrWillBeRawPtr<MediaControlTextTrackListElement> MediaControlTextTrackListElement::create(MediaControls& mediaControls)
|
| +{
|
| + RefPtrWillBeRawPtr<MediaControlTextTrackListElement> element =
|
| + adoptRefWillBeNoop(new MediaControlTextTrackListElement(mediaControls));
|
| + element->setShadowPseudoId(AtomicString("-webkit-media-controls-text-track-list",
|
| + AtomicString::ConstructFromLiteral));
|
| + return element.release();
|
| +}
|
| +
|
| +void MediaControlTextTrackListElement::defaultEventHandler(Event* event)
|
| +{
|
| + if (event->type() == EventTypeNames::change) {
|
| + // Identify which input element was selected and set track to showing
|
| + Node* target = event->target()->toNode();
|
| + if (!target || !target->isElementNode())
|
| + return;
|
| +
|
| + bool validIndex;
|
| + int trackIndex = toElement(target)->getAttribute(trackIndexAttr).toInt(&validIndex);
|
| + if (!validIndex)
|
| + return;
|
| + if (trackIndex != trackIndexOffValue) {
|
| + showTextTrackAtIndex(trackIndex);
|
| + mediaElement().setClosedCaptionsVisible(true);
|
| + } else {
|
| + mediaElement().setClosedCaptionsVisible(false);
|
| + }
|
| +
|
| + mediaControls().toggleTextTrackList();
|
| + event->setDefaultHandled();
|
| + }
|
| + HTMLDivElement::defaultEventHandler(event);
|
| +}
|
| +
|
| +void MediaControlTextTrackListElement::showTextTrackAtIndex(unsigned index)
|
| +{
|
| + TextTrackList* trackList = mediaElement().textTracks();
|
| + for (unsigned i = 0; i < trackList->length(); ++i) {
|
| + TextTrack* track = trackList->item(i);
|
| + if (track->mode() == TextTrack::showingKeyword())
|
| + track->setMode(TextTrack::disabledKeyword());
|
| + }
|
| +
|
| + if (index < trackList->length()) {
|
| + trackList->item(index)->setMode(TextTrack::showingKeyword());
|
| + mediaElement().setAutomaticTextTrackSelection(false);
|
| + }
|
| +}
|
| +
|
| +String MediaControlTextTrackListElement::getTextTrackLabel(TextTrack* track)
|
| +{
|
| + String trackLabel = track->label();
|
| +
|
| + if (trackLabel.isEmpty())
|
| + trackLabel = track->language();
|
| +
|
| + if (trackLabel.isEmpty())
|
| + trackLabel = String(mediaElement().locale().queryString(WebLocalizedString::TextTracksNoLabel));
|
| +
|
| + // When the track kind is captions, add a captions marker to distinguish between captions and subtitles.
|
| + if (track->kind() == track->captionsKeyword())
|
| + trackLabel.append(mediaElement().locale().queryString(WebLocalizedString::TextTracksCaptionsMarker));
|
| + return trackLabel;
|
| +}
|
| +
|
| +RefPtrWillBeRawPtr<Element> MediaControlTextTrackListElement::createTextTrackListItem(const String& trackDisplayText, int trackIndex, bool isShowing)
|
| +{
|
| + Document& document = this->document();
|
| + RefPtrWillBeRawPtr<Element> trackItem = document.createElement(labelTag, false);
|
| + trackItem->setShadowPseudoId(AtomicString("-webkit-media-controls-text-track-list-item",
|
| + AtomicString::ConstructFromLiteral));
|
| + RefPtrWillBeRawPtr<Element> trackItemInput = document.createElement(inputTag, false);
|
| + trackItemInput->setShadowPseudoId(AtomicString("-webkit-media-controls-text-track-list-item-input",
|
| + AtomicString::ConstructFromLiteral));
|
| + trackItemInput->setAttribute(typeAttr, InputTypeNames::radio);
|
| + trackItemInput->setAttribute(nameAttr, AtomicString("tracks", AtomicString::ConstructFromLiteral));
|
| + trackItemInput->setAttribute(trackIndexAttr, AtomicString::number(trackIndex), ASSERT_NO_EXCEPTION);
|
| + if (!mediaElement().closedCaptionsVisible()) {
|
| + if (trackIndex == trackIndexOffValue)
|
| + toHTMLInputElement(trackItemInput)->setChecked(true);
|
| + } else {
|
| + if (trackIndex >= 0 && isShowing)
|
| + toHTMLInputElement(trackItemInput)->setChecked(true);
|
| + }
|
| + trackItem->appendChild(trackItemInput);
|
| + trackItem->appendChild(document.createTextNode(trackDisplayText));
|
| + return trackItem;
|
| +}
|
| +
|
| +void MediaControlTextTrackListElement::refreshTextTrackListMenu()
|
| +{
|
| + DEFINE_STATIC_LOCAL(const AtomicString, tracksSectionId, ("tracks-header", AtomicString::ConstructFromLiteral));
|
| + if (!mediaElement().hasClosedCaptions() || !mediaElement().textTracksAreReady())
|
| + return;
|
| +
|
| + removeChildren();
|
| +
|
| + // Construct a menu for subtitles and captions
|
| + EventDispatchForbiddenScope::AllowUserAgentEvents allowEvents;
|
| + Document& document = this->document();
|
| + RefPtrWillBeRawPtr<Element> tracksHeader = document.createElement(h3Tag, false);
|
| + tracksHeader->setShadowPseudoId(AtomicString("-webkit-media-controls-text-track-list-header",
|
| + AtomicString::ConstructFromLiteral));
|
| + RefPtrWillBeRawPtr<Element> tracksSection = document.createElement(divTag, false);
|
| +
|
| + tracksHeader->appendChild(document.createTextNode(mediaElement().locale().queryString(WebLocalizedString::TextTracksSubtitlesCC)));
|
| + tracksHeader->setAttribute(idAttr, tracksSectionId);
|
| + tracksSection->setAttribute(roleAttr, radiogroupAttr.localName());
|
| + tracksSection->setAttribute(aria_labeledbyAttr, tracksSectionId);
|
| +
|
| + String textTracksOffLabel = mediaElement().locale().queryString(WebLocalizedString::TextTracksOff);
|
| + tracksSection->appendChild(createTextTrackListItem(textTracksOffLabel, trackIndexOffValue, false));
|
| +
|
| + TextTrackList* trackList = mediaElement().textTracks();
|
| + for (unsigned i = 0; i < trackList->length(); i++) {
|
| + TextTrack* track = trackList->item(i);
|
| + RefPtrWillBeRawPtr<Element> trackItem =
|
| + createTextTrackListItem(getTextTrackLabel(track), i, track->mode() == TextTrack::showingKeyword());
|
| + tracksSection->appendChild(trackItem);
|
| + }
|
| + appendChild(tracksHeader);
|
| + appendChild(tracksSection);
|
| +}
|
| +
|
| +// ----------------------------
|
| +
|
| MediaControlTimelineElement::MediaControlTimelineElement(MediaControls& mediaControls)
|
| : MediaControlInputElement(mediaControls, MediaSlider)
|
| {
|
|
|