https://bugs.webkit.org/show_bug.cgi?id=117008
By activating subtitles support on webkit2GTK, the video player
recognizes and use text <tracks> inside <video> elements.
Patch by Danilo Cesar Lemes de Paula <danilo.cesar@collabora.co.uk> on 2013-09-04
Reviewed by Martin Robinson.
Source/WebCore:
Layout tests (track-menu) should cover this change.
* css/mediaControlsGtk.css:
(audio::-webkit-media-controls-toggle-closed-captions-button, video::-webkit-media-controls-toggle-closed-captions-button):
(video::-webkit-media-controls-closed-captions-container):
(video::-webkit-media-controls-closed-captions-track-list):
(video::-webkit-media-controls-closed-captions-track-list h3):
(video::-webkit-media-controls-closed-captions-track-list ul):
(video::-webkit-media-controls-closed-captions-track-list li):
(video::-webkit-media-controls-closed-captions-track-list li.selected):
* html/shadow/MediaControlElements.cpp:
(WebCore::MediaControlToggleClosedCaptionsButtonElement::MediaControlToggleClosedCaptionsButtonElement):
(WebCore::MediaControlToggleClosedCaptionsButtonElement::defaultEventHandler):
* html/shadow/MediaControlElements.h:
* html/shadow/MediaControlsGtk.cpp:
(WebCore::MediaControlsGtkEventListener::create):
(WebCore::MediaControlsGtkEventListener::cast):
(WebCore::MediaControlsGtkEventListener::MediaControlsGtkEventListener):
(WebCore::MediaControlsGtk::MediaControlsGtk):
(WebCore::MediaControlsGtk::initializeControls):
(WebCore::MediaControlsGtk::setMediaController):
(WebCore::MediaControlsGtk::reset):
(WebCore::MediaControlsGtk::makeTransparent):
(WebCore::MediaControlsGtk::toggleClosedCaptionTrackList):
(WebCore::MediaControlsGtk::showClosedCaptionTrackList):
(WebCore::MediaControlsGtk::hideClosedCaptionTrackList):
(WebCore::MediaControlsGtk::handleClickEvent):
(WebCore::MediaControlsGtk::eventListener):
(WebCore::MediaControlsGtkEventListener::handleEvent):
(WebCore::MediaControlsGtkEventListener::operator==):
* html/shadow/MediaControlsGtk.h:
* page/CaptionUserPreferences.cpp:
(WebCore::trackDisplayName):
* platform/gtk/LocalizedStringsGtk.cpp:
(WebCore::textTrackSubtitlesText):
(WebCore::textTrackOffMenuItemText):
(WebCore::textTrackNoLabelText):
* platform/gtk/RenderThemeGtk.h:
LayoutTests:
* platform/gtk/TestExpectations:
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@155048
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2013-09-04 Danilo Cesar Lemes de Paula <danilo.cesar@collabora.co.uk>
+
+ [GTK] add support for subtitles on webkit2GTK
+ https://bugs.webkit.org/show_bug.cgi?id=117008
+
+ By activating subtitles support on webkit2GTK, the video player
+ recognizes and use text <tracks> inside <video> elements.
+
+ Reviewed by Martin Robinson.
+
+ * platform/gtk/TestExpectations:
+
2013-09-04 Zoltan Arvai <zarvai@inf.u-szeged.hu>
[Qt] Unreviewed bot greening.
webkit.org/b/102257 fast/dom/Window/open-window-min-size.html [ Timeout ]
-# GTK still has the CC toggle button, not the menu of tracks.
-webkit.org/b/101670 media/video-controls-captions-trackmenu.html [ Skip ]
-webkit.org/b/101670 media/video-controls-captions-trackmenu-sorted.html [ Skip ]
-webkit.org/b/101670 media/video-controls-captions-trackmenu-localized.html [ Skip ]
-webkit.org/b/101670 media/video-controls-captions-trackmenu-hide-on-click.html [ Skip ]
-webkit.org/b/101670 media/video-controls-captions-trackmenu-hide-on-click-outside.html [ Skip ]
-webkit.org/b/101670 media/track/track-user-preferences.html [ Skip ]
-webkit.org/b/101670 media/video-controls-captions-trackmenu-includes-enabled-track.html [ Skip ]
-
webkit.org/b/107194 storage/indexeddb/database-quota.html [ Timeout ]
webkit.org/b/107194 storage/indexeddb/pending-activity-workers.html [ Timeout ]
webkit.org/b/107194 storage/indexeddb/pending-version-change-on-exit.html [ Timeout ]
# LayoutTestController::applicationCacheDiskUsageForOrigin isn't implemented.
webkit.org/b/57127 http/tests/appcache/origin-usage.html [ Failure ]
+# GTK is moving from toggle button to a menu of tracks.
+webkit.org/b/101670 media/video-controls-captions-trackmenu.html [ Failure ]
+webkit.org/b/101670 media/track/track-user-preferences.html [ Failure ]
+webkit.org/b/101670 media/video-controls-captions-trackmenu-includes-enabled-track.html [ Failure ]
+
Bug(GTK) http/tests/loading/bad-scheme-subframe.html [ Failure ]
# Needed to cover the fix for <rdar://problem/6727495>
webkit.org/b/87355 canvas/philip/tests/2d.text.draw.fontface.notinpage.html [ Failure ]
+# GTK is moving from the simple toggle button to a menu of tracks
webkit.org/b/95428 media/video-controls-captions.html [ Failure ]
webkit.org/b/95429 svg/custom/clamped-masking-clipping.svg [ ImageOnlyFailure ]
+2013-09-04 Danilo Cesar Lemes de Paula <danilo.cesar@collabora.co.uk>
+
+ [GTK] add support for subtitles on webkit2GTK
+ https://bugs.webkit.org/show_bug.cgi?id=117008
+
+ By activating subtitles support on webkit2GTK, the video player
+ recognizes and use text <tracks> inside <video> elements.
+
+ Reviewed by Martin Robinson.
+
+ Layout tests (track-menu) should cover this change.
+
+ * css/mediaControlsGtk.css:
+ (audio::-webkit-media-controls-toggle-closed-captions-button, video::-webkit-media-controls-toggle-closed-captions-button):
+ (video::-webkit-media-controls-closed-captions-container):
+ (video::-webkit-media-controls-closed-captions-track-list):
+ (video::-webkit-media-controls-closed-captions-track-list h3):
+ (video::-webkit-media-controls-closed-captions-track-list ul):
+ (video::-webkit-media-controls-closed-captions-track-list li):
+ (video::-webkit-media-controls-closed-captions-track-list li.selected):
+ * html/shadow/MediaControlElements.cpp:
+ (WebCore::MediaControlToggleClosedCaptionsButtonElement::MediaControlToggleClosedCaptionsButtonElement):
+ (WebCore::MediaControlToggleClosedCaptionsButtonElement::defaultEventHandler):
+ * html/shadow/MediaControlElements.h:
+ * html/shadow/MediaControlsGtk.cpp:
+ (WebCore::MediaControlsGtkEventListener::create):
+ (WebCore::MediaControlsGtkEventListener::cast):
+ (WebCore::MediaControlsGtkEventListener::MediaControlsGtkEventListener):
+ (WebCore::MediaControlsGtk::MediaControlsGtk):
+ (WebCore::MediaControlsGtk::initializeControls):
+ (WebCore::MediaControlsGtk::setMediaController):
+ (WebCore::MediaControlsGtk::reset):
+ (WebCore::MediaControlsGtk::makeTransparent):
+ (WebCore::MediaControlsGtk::toggleClosedCaptionTrackList):
+ (WebCore::MediaControlsGtk::showClosedCaptionTrackList):
+ (WebCore::MediaControlsGtk::hideClosedCaptionTrackList):
+ (WebCore::MediaControlsGtk::handleClickEvent):
+ (WebCore::MediaControlsGtk::eventListener):
+ (WebCore::MediaControlsGtkEventListener::handleEvent):
+ (WebCore::MediaControlsGtkEventListener::operator==):
+ * html/shadow/MediaControlsGtk.h:
+ * page/CaptionUserPreferences.cpp:
+ (WebCore::trackDisplayName):
+ * platform/gtk/LocalizedStringsGtk.cpp:
+ (WebCore::textTrackSubtitlesText):
+ (WebCore::textTrackOffMenuItemText):
+ (WebCore::textTrackNoLabelText):
+ * platform/gtk/RenderThemeGtk.h:
+
2013-09-03 Darin Adler <darin@apple.com>
Use OwnPtr in the RenderLayerFilterInfo map
height: 30px;
line-height: 30px;
margin: 0 9px 0 -7px;
+ background-repeat:no-repeat;
+ background-position:center;
+ background-image: url('data:image/svg+xml,<svg id="svg7384" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/"><metadata id="metadata90"><rdf:RDF><cc:Work rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/><dc:title>Gnome Symbolic Icon Theme</dc:title></cc:Work></rdf:RDF></metadata><g id="layer9" transform="translate(-101,-357)"><path id="path12148" style="block-progression:tb;color:#bebebe;direction:ltr;text-indent:0;text-align:start;enable-background:accumulate;text-transform:none;" fill="#bebebe" d="m104.75,357.06c-2.0602,0-3.75,1.6898-3.75,3.75v4.4375c0,2.0602,1.6898,3.75,3.75,3.75h4.9375l3.75,2.6562,1.5938,1.125v-1.9688l-0.0313-2.5c1.1106-0.59715,1.9688-1.6526,1.9688-3.0625v-4.4375c0-2.0602-1.6898-3.75-3.75-3.75h-8.4688zm0,2,8.4688,0c0.9868,0,1.75,0.7632,1.75,1.75v4.4375c0,0.86273-0.63508,1.541-1.125,1.625l-0.84,0.12v0.84375,1.0312l-2.4062-1.6875-0.25-0.1875h-0.3125-5.2812c-0.9868,0-1.75-0.7632-1.75-1.75v-4.4375c0-0.9868,0.7632-1.75,1.75-1.75z"/></g></svg>');
+}
+
+video::-webkit-media-controls-closed-captions-container {
+ -webkit-appearance: media-closed-captions-container;
+ position: absolute;
+ display: block;
+ right: 38px;
+ bottom: 35px;
+ max-width: -webkit-calc(100% - 48px); /* right + 10px */
+ max-height: -webkit-calc(100% - 35px); /* bottom + 10px */
+ overflow-x: hidden;
+ overflow-y: auto;
+ background-color: rgba(20, 20, 20, 0.8);
+ border-radius: 10px;
+ cursor: default;
+ z-index: 2;
+}
+
+video::-webkit-media-controls-closed-captions-track-list {
+ display: block;
+ font-family: "Helvetica Bold", Helvetica;
+ font-size: 10pt;
+ -webkit-user-select: none;
+}
+
+video::-webkit-media-controls-closed-captions-track-list h3 {
+ margin: 1px 30px;
+ color: #757575;
+ text-shadow: 0 1px 0 black;
+ padding-top: 0px;
+ font-weight: bold;
+ font-size: 10pt;
+}
+
+video::-webkit-media-controls-closed-captions-track-list ul {
+ list-style-type: none;
+ margin: 0 0 4px 0;
+ padding: 0;
+ font-weight: bold;
+}
+
+video::-webkit-media-controls-closed-captions-track-list li {
+ position: relative;
+ color: white;
+ background-image: none;
+ text-shadow: 0 1px 0 black;
+ margin: 0;
+ padding-left: 37px;
+ padding-right: 35px;
+ padding-top: 0.15em;
+ padding-bottom: 0.2em;
+ box-sizing: border-box;
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ border-top: 1px solid rgba(0, 0, 0, 0);
+ border-bottom: 1px solid rgba(0, 0, 0, 0);
+}
+video::-webkit-media-controls-closed-captions-track-list li.selected {
+ background-color: rgba(230, 230, 230, 0.15);
}
audio::-webkit-media-controls-fullscreen-button, video::-webkit-media-controls-fullscreen-button {
MediaControlToggleClosedCaptionsButtonElement::MediaControlToggleClosedCaptionsButtonElement(Document* document, MediaControls* controls)
: MediaControlInputElement(document, MediaShowClosedCaptionsButton)
-#if PLATFORM(MAC) || PLATFORM(WIN)
+#if PLATFORM(MAC) || PLATFORM(WIN) || PLATFORM(GTK)
, m_controls(controls)
#endif
{
-#if !PLATFORM(MAC) && !PLATFORM(WIN)
+#if !PLATFORM(MAC) && !PLATFORM(WIN) || !PLATFORM(GTK)
UNUSED_PARAM(controls);
#endif
}
// UI. Not all ports may want the closed captions button to toggle a list of tracks, so
// we have to use #if.
// https://bugs.webkit.org/show_bug.cgi?id=101877
-#if !PLATFORM(MAC) && !PLATFORM(WIN)
+#if !PLATFORM(MAC) && !PLATFORM(WIN) && !PLATFORM(GTK)
mediaController()->setClosedCaptionsVisible(!mediaController()->closedCaptionsVisible());
setChecked(mediaController()->closedCaptionsVisible());
updateDisplayType();
virtual const AtomicString& shadowPseudoId() const OVERRIDE;
virtual void defaultEventHandler(Event*) OVERRIDE;
-#if PLATFORM(MAC) || PLATFORM(WIN)
+#if PLATFORM(MAC) || PLATFORM(WIN) || PLATFORM(GTK)
MediaControls* m_controls;
#endif
};
#if ENABLE(VIDEO)
#include "MediaControlsGtk.h"
+#include "Chrome.h"
+#include "MouseEvent.h"
+
namespace WebCore {
+class MediaControlsGtkEventListener : public EventListener {
+public:
+ static PassRefPtr<MediaControlsGtkEventListener> create(MediaControlsGtk* mediaControls) { return adoptRef(new MediaControlsGtkEventListener(mediaControls)); }
+ static const MediaControlsGtkEventListener* cast(const EventListener* listener)
+ {
+ return listener->type() == GObjectEventListenerType
+ ? static_cast<const MediaControlsGtkEventListener*>(listener)
+ : 0;
+ }
+
+ virtual bool operator==(const EventListener& other);
+
+private:
+ MediaControlsGtkEventListener(MediaControlsGtk* mediaControls)
+ : EventListener(GObjectEventListenerType)
+ , m_mediaControls(mediaControls)
+ {
+ }
+
+ virtual void handleEvent(ScriptExecutionContext*, Event*);
+
+ MediaControlsGtk* m_mediaControls;
+};
+
MediaControlsGtk::MediaControlsGtk(Document* document)
: MediaControls(document)
, m_durationDisplay(0)
, m_enclosure(0)
+ , m_eventListener(0)
+ , m_closedCaptionsTrackList(0)
+ , m_closedCaptionsContainer(0)
{
}
return false;
if (document->page()->theme()->supportsClosedCaptioning()) {
+ RefPtr<MediaControlClosedCaptionsContainerElement> closedCaptionsContainer = MediaControlClosedCaptionsContainerElement::create(document);
+
+ RefPtr<MediaControlClosedCaptionsTrackListElement> closedCaptionsTrackList = MediaControlClosedCaptionsTrackListElement::create(document, this);
+ m_closedCaptionsTrackList = closedCaptionsTrackList.get();
+ closedCaptionsContainer->appendChild(closedCaptionsTrackList.release(), exceptionCode, AttachLazily);
+ if (exceptionCode)
+ return false;
+
RefPtr<MediaControlToggleClosedCaptionsButtonElement> toggleClosedCaptionsButton = MediaControlToggleClosedCaptionsButtonElement::create(document, this);
m_toggleClosedCaptionsButton = toggleClosedCaptionsButton.get();
panel->appendChild(toggleClosedCaptionsButton.release(), exceptionCode, AttachLazily);
if (exceptionCode)
return false;
+
+ m_closedCaptionsContainer = closedCaptionsContainer.get();
+ appendChild(closedCaptionsContainer.release(), exceptionCode, AttachLazily);
+ if (exceptionCode)
+ return false;
}
RefPtr<MediaControlFullscreenButtonElement> fullscreenButton = MediaControlFullscreenButtonElement::create(document);
m_durationDisplay->setMediaController(controller);
if (m_enclosure)
m_enclosure->setMediaController(controller);
+ if (m_closedCaptionsContainer)
+ m_closedCaptionsContainer->setMediaController(controller);
+ if (m_closedCaptionsTrackList)
+ m_closedCaptionsTrackList->setMediaController(controller);
}
void MediaControlsGtk::reset()
m_durationDisplay->setInnerText(page->theme()->formatMediaControlsTime(duration), ASSERT_NO_EXCEPTION);
m_durationDisplay->setCurrentValue(duration);
+ if (m_toggleClosedCaptionsButton) {
+ if (m_mediaController->hasClosedCaptions())
+ m_toggleClosedCaptionsButton->show();
+ else
+ m_toggleClosedCaptionsButton->hide();
+ }
+
MediaControls::reset();
}
if (m_volumeSliderContainer)
m_volumeSliderContainer->hide();
+
+ hideClosedCaptionTrackList();
}
void MediaControlsGtk::showVolumeSlider()
}
#endif
+void MediaControlsGtk::toggleClosedCaptionTrackList()
+{
+ if (!m_mediaController->hasClosedCaptions())
+ return;
+
+ if (!m_closedCaptionsContainer || !m_closedCaptionsTrackList)
+ return;
+
+ if (m_closedCaptionsContainer->isShowing()) {
+ hideClosedCaptionTrackList();
+ return;
+ }
+
+ m_closedCaptionsTrackList->updateDisplay();
+ showClosedCaptionTrackList();
}
+void MediaControlsGtk::showClosedCaptionTrackList()
+{
+ m_volumeSliderContainer->hide();
+
+ if (!m_closedCaptionsContainer || m_closedCaptionsContainer->isShowing())
+ return;
+
+ m_closedCaptionsContainer->show();
+ m_panel->setInlineStyleProperty(CSSPropertyPointerEvents, CSSValueNone);
+
+ RefPtr<EventListener> listener = eventListener();
+
+ // Check for clicks outside the media-control
+ document().addEventListener(eventNames().clickEvent, listener, true);
+ // Check for clicks inside the media-control box
+ addEventListener(eventNames().clickEvent, listener, true);
+}
+
+void MediaControlsGtk::hideClosedCaptionTrackList()
+{
+ if (!m_closedCaptionsContainer || !m_closedCaptionsContainer->isShowing())
+ return;
+
+ m_closedCaptionsContainer->hide();
+ m_panel->removeInlineStyleProperty(CSSPropertyPointerEvents);
+
+ EventListener* listener = eventListener().get();
+
+ document().removeEventListener(eventNames().clickEvent, listener, true);
+ removeEventListener(eventNames().clickEvent, listener, true);
+}
+
+void MediaControlsGtk::handleClickEvent(Event *event)
+{
+ Node* currentTarget = event->currentTarget()->toNode();
+ Node* target = event->target()->toNode();
+
+ if ((currentTarget == &document() && !shadowHost()->contains(target))
+ || (currentTarget == this && !m_closedCaptionsContainer->contains(target))) {
+ hideClosedCaptionTrackList();
+ event->stopImmediatePropagation();
+ event->setDefaultHandled();
+ }
+}
+
+PassRefPtr<MediaControlsGtkEventListener> MediaControlsGtk::eventListener()
+{
+ if (!m_eventListener)
+ m_eventListener = MediaControlsGtkEventListener::create(this);
+
+ return m_eventListener;
+}
+
+void MediaControlsGtkEventListener::handleEvent(ScriptExecutionContext*, Event* event)
+{
+ if (event->type() == eventNames().clickEvent)
+ m_mediaControls->handleClickEvent(event);
+
+ return;
+}
+
+bool MediaControlsGtkEventListener::operator==(const EventListener& listener)
+{
+ if (const MediaControlsGtkEventListener* mediaControlsGtkEventListener = MediaControlsGtkEventListener::cast(&listener))
+ return m_mediaControls == mediaControlsGtkEventListener->m_mediaControls;
+ return false;
+}
+
+}
#endif
namespace WebCore {
+class MediaControlsGtkEventListener;
+
class MediaControlsGtk : public MediaControls {
public:
// Called from port-specific parent create function to create custom controls.
virtual void updateCurrentTimeDisplay() OVERRIDE;
virtual void showVolumeSlider() OVERRIDE;
virtual void makeTransparent() OVERRIDE;
+ virtual void toggleClosedCaptionTrackList() OVERRIDE;
+
+ void handleClickEvent(Event*);
#if ENABLE(VIDEO_TRACK)
void createTextTrackDisplay() OVERRIDE;
protected:
explicit MediaControlsGtk(Document*);
-
bool initializeControls(Document*);
private:
+ void showClosedCaptionTrackList();
+ void hideClosedCaptionTrackList();
+
+ PassRefPtr<MediaControlsGtkEventListener> eventListener();
+
MediaControlTimeRemainingDisplayElement* m_durationDisplay;
MediaControlPanelEnclosureElement* m_enclosure;
MediaControlVolumeSliderContainerElement* m_volumeSliderContainer;
+ MediaControlClosedCaptionsTrackListElement* m_closedCaptionsTrackList;
+ MediaControlClosedCaptionsContainerElement* m_closedCaptionsContainer;
+
+ RefPtr<MediaControlsGtkEventListener> m_eventListener;
};
}
static String trackDisplayName(TextTrack* track)
{
+ if (track == TextTrack::captionMenuOffItem())
+ return textTrackOffMenuItemText();
+ if (track == TextTrack::captionMenuAutomaticItem())
+ return textTrackAutomaticMenuItemText();
+
if (track->label().isEmpty() && track->language().isEmpty())
return textTrackNoLabelText();
if (!track->label().isEmpty())
tracksForMenu.append(trackList->item(i));
nonCopyingSort(tracksForMenu.begin(), tracksForMenu.end(), textTrackCompare);
+ tracksForMenu.insert(0, TextTrack::captionMenuOffItem());
+ tracksForMenu.insert(1, TextTrack::captionMenuAutomaticItem());
return tracksForMenu;
}
String textTrackSubtitlesText()
{
- return String::fromUTF8(C_("Subtitles", "Menu section heading for subtitles"));
+ return String::fromUTF8(C_("Menu section heading for subtitles", "Subtitles"));
}
String textTrackOffMenuItemText()
{
- return String::fromUTF8(C_("Off", "Menu item label for the track that represents disabling closed captions"));
+ return String::fromUTF8(C_("Menu item label for the track that represents disabling closed captions", "Off"));
}
String textTrackAutomaticMenuItemText()
String textTrackNoLabelText()
{
- return String::fromUTF8(C_("No label", "Menu item label for a closed captions track that has no other name"));
+ return String::fromUTF8(C_("Menu item label for a closed captions track that has no other name", "No label"));
}
#endif
#if ENABLE(VIDEO)
virtual String extraMediaControlsStyleSheet();
virtual String formatMediaControlsCurrentTime(float currentTime, float duration) const;
+ virtual bool supportsClosedCaptioning() const OVERRIDE { return true; }
#if ENABLE(FULLSCREEN_API)
virtual String extraFullScreenStyleSheet();