[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.

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: http://svn.webkit.org/repository/webkit/trunk@155048 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 7d2a1ffb
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.
......@@ -796,15 +796,6 @@ Bug(GTK) media/progress-events-generated-correctly.html [ Failure Timeout ]
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 ]
......@@ -911,6 +902,11 @@ webkit.org/b/44478 fast/text/hyphen-min-preferred-width.html [ Skip ]
# 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>
......@@ -1220,6 +1216,7 @@ webkit.org/b/89663 editing/deleting/delete-3800834-fix.html [ Failure ]
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
......@@ -222,6 +222,69 @@ audio::-webkit-media-controls-toggle-closed-captions-button, video::-webkit-medi
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 {
......
......@@ -677,11 +677,11 @@ const AtomicString& MediaControlReturnToRealtimeButtonElement::shadowPseudoId()
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
}
......@@ -711,7 +711,7 @@ void MediaControlToggleClosedCaptionsButtonElement::defaultEventHandler(Event* e
// 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();
......
......@@ -280,7 +280,7 @@ private:
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
};
......
......@@ -31,12 +31,42 @@
#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)
{
}
......@@ -91,11 +121,24 @@ bool MediaControlsGtk::initializeControls(Document* document)
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);
......@@ -147,6 +190,10 @@ void MediaControlsGtk::setMediaController(MediaControllerInterface* controller)
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()
......@@ -159,6 +206,13 @@ 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();
}
......@@ -208,6 +262,8 @@ void MediaControlsGtk::makeTransparent()
if (m_volumeSliderContainer)
m_volumeSliderContainer->hide();
hideClosedCaptionTrackList();
}
void MediaControlsGtk::showVolumeSlider()
......@@ -236,6 +292,90 @@ void MediaControlsGtk::createTextTrackDisplay()
}
#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
......@@ -35,6 +35,8 @@
namespace WebCore {
class MediaControlsGtkEventListener;
class MediaControlsGtk : public MediaControls {
public:
// Called from port-specific parent create function to create custom controls.
......@@ -47,6 +49,9 @@ public:
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;
......@@ -54,13 +59,21 @@ public:
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;
};
}
......
......@@ -157,6 +157,11 @@ void CaptionUserPreferences::setPreferredLanguage(const String& language)
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())
......@@ -184,6 +189,8 @@ Vector<RefPtr<TextTrack> > CaptionUserPreferences::sortedTrackListForMenu(TextTr
tracksForMenu.append(trackList->item(i));
nonCopyingSort(tracksForMenu.begin(), tracksForMenu.end(), textTrackCompare);
tracksForMenu.insert(0, TextTrack::captionMenuOffItem());
tracksForMenu.insert(1, TextTrack::captionMenuAutomaticItem());
return tracksForMenu;
}
......
......@@ -795,12 +795,12 @@ String textTrackClosedCaptionsText()
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()
......@@ -810,7 +810,7 @@ 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
......
......@@ -87,6 +87,7 @@ public:
#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();
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment