summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@digia.com>2014-01-16 13:48:06 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-01-16 18:20:33 +0100
commit1ca1ca150c8a362980bb11123d416ff136da155c (patch)
treecc15d6f99ec5c62535c69bfa59a80a669267becc /Source
parentb38b96c88cd732f47940aed453f5cacf833ee1c2 (diff)
downloadqtwebkit-1ca1ca150c8a362980bb11123d416ff136da155c.tar.gz
Enable HTML5 video track support
This patch enables support for the HTML5 video track standard which defines subtitles and captions for HTML5 video. The HTML5 video controls will now have a popup button when captions are available that allows the user to select the preferred caption or turn them off. Change-Id: Id5b837d1a7b536935cd5038812594b11c48c3480 Reviewed-by: Jocelyn Turcotte <jocelyn.turcotte@digia.com>
Diffstat (limited to 'Source')
-rw-r--r--Source/WebCore/css/mediaControlsQt.css91
-rw-r--r--Source/WebCore/html/shadow/MediaControlElements.cpp6
-rw-r--r--Source/WebCore/html/shadow/MediaControlElements.h2
-rw-r--r--Source/WebCore/page/CaptionUserPreferences.cpp8
-rw-r--r--Source/WebCore/platform/qt/LocalizedStringsQt.cpp16
-rw-r--r--Source/WebCore/platform/qt/RenderThemeQt.cpp31
-rw-r--r--Source/WebCore/platform/qt/RenderThemeQt.h4
7 files changed, 144 insertions, 14 deletions
diff --git a/Source/WebCore/css/mediaControlsQt.css b/Source/WebCore/css/mediaControlsQt.css
index 715a37f66..5ed490f1b 100644
--- a/Source/WebCore/css/mediaControlsQt.css
+++ b/Source/WebCore/css/mediaControlsQt.css
@@ -23,7 +23,7 @@
* 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.
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* QtWebKit media controls. Extends mediaControls.css */
@@ -151,14 +151,99 @@ audio::-webkit-media-controls-return-to-realtime-button, video::-webkit-media-co
}
audio::-webkit-media-controls-toggle-closed-captions-button, video::-webkit-media-controls-toggle-closed-captions-button {
- display: none;
+ -webkit-appearance: media-toggle-closed-captions-button;
+ width: 12px;
+ height: 12px;
+ padding: 6px;
+ margin: 5px 5px 5px 3px;
+ -webkit-order: 3; /* between mute and fullscreen */
+ border: none !important;
+}
+
+video::-webkit-media-controls-closed-captions-container {
+ -webkit-appearance: media-closed-captions-container;
+ position: absolute;
+ display: block;
+ right: 38px;
+ bottom: 29px;
+ max-width: -webkit-calc(100% - 48px); /* right + 10px */
+ max-height: -webkit-calc(100% - 39px); /* bottom + 10px */
+ overflow-x: hidden;
+ overflow-y: auto;
+ background-color: rgba(0, 0, 0, 0.85);
+ border-radius: 10px;
+ cursor: default;
+ z-index: 2;
+}
+
+video::-webkit-media-controls-closed-captions-track-list {
+ display: block;
+ font-size: 10pt;
+}
+
+video::-webkit-media-controls-closed-captions-track-list h3 {
+ margin: 0;
+ color: #757575;
+ text-shadow: 0 1px 0 black;
+ -webkit-margin-start: 23px;
+ padding-top: 4px;
+ 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:hover {
+ background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #4f70f6), color-stop(1, #1a44f3));
+ border-top: 1px solid #4667ea;
+ border-bottom: 1px solid #0336e5;
+}
+
+video::-webkit-media-controls-closed-captions-track-list li.selected::before {
+ display: block;
+ content: "";
+ position: absolute;
+ top: 0.25em;
+ width: 1.1em;
+ height: 1.1em;
+ -webkit-margin-start: -20px;
+ background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300"><polygon fill="#a3a3a3" points="252.301,4.477 126.667,194.104 43.358,108.3 6.868,161.408 132.515,290.814 297.732,49.926"/></svg>');
+ background-repeat: no-repeat;
+}
+
+video::-webkit-media-controls-closed-captions-track-list li.selected:hover::before {
+ background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300"><polygon fill="white" points="252.301,4.477 126.667,194.104 43.358,108.3 6.868,161.408 132.515,290.814 297.732,49.926"/></svg>');
}
::-webkit-media-controls-mute-button,
::-webkit-media-controls-play-button,
::-webkit-media-controls-timeline,
::-webkit-media-controls-volume-slider,
-::-webkit-media-controls-fullscreen-button
+::-webkit-media-controls-fullscreen-button,
+::-webkit-media-controls-toggle-closed-captions-button
{
box-sizing: content-box !important;
}
diff --git a/Source/WebCore/html/shadow/MediaControlElements.cpp b/Source/WebCore/html/shadow/MediaControlElements.cpp
index 4f5bd4591..99a11150c 100644
--- a/Source/WebCore/html/shadow/MediaControlElements.cpp
+++ b/Source/WebCore/html/shadow/MediaControlElements.cpp
@@ -676,11 +676,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(QT)
, m_controls(controls)
#endif
{
-#if !PLATFORM(MAC) && !PLATFORM(WIN)
+#if !PLATFORM(MAC) && !PLATFORM(WIN) && !PLATFORM(QT)
UNUSED_PARAM(controls);
#endif
}
@@ -710,7 +710,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(QT)
mediaController()->setClosedCaptionsVisible(!mediaController()->closedCaptionsVisible());
setChecked(mediaController()->closedCaptionsVisible());
updateDisplayType();
diff --git a/Source/WebCore/html/shadow/MediaControlElements.h b/Source/WebCore/html/shadow/MediaControlElements.h
index 68262d377..06b19cd5c 100644
--- a/Source/WebCore/html/shadow/MediaControlElements.h
+++ b/Source/WebCore/html/shadow/MediaControlElements.h
@@ -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(QT)
MediaControls* m_controls;
#endif
};
diff --git a/Source/WebCore/page/CaptionUserPreferences.cpp b/Source/WebCore/page/CaptionUserPreferences.cpp
index 5b1590f6f..966fce3aa 100644
--- a/Source/WebCore/page/CaptionUserPreferences.cpp
+++ b/Source/WebCore/page/CaptionUserPreferences.cpp
@@ -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())
@@ -185,6 +190,9 @@ Vector<RefPtr<TextTrack> > CaptionUserPreferences::sortedTrackListForMenu(TextTr
nonCopyingSort(tracksForMenu.begin(), tracksForMenu.end(), textTrackCompare);
+ tracksForMenu.insert(0, TextTrack::captionMenuOffItem());
+ tracksForMenu.insert(1, TextTrack::captionMenuAutomaticItem());
+
return tracksForMenu;
}
diff --git a/Source/WebCore/platform/qt/LocalizedStringsQt.cpp b/Source/WebCore/platform/qt/LocalizedStringsQt.cpp
index def96e1e4..585544429 100644
--- a/Source/WebCore/platform/qt/LocalizedStringsQt.cpp
+++ b/Source/WebCore/platform/qt/LocalizedStringsQt.cpp
@@ -787,20 +787,22 @@ String validationMessageBadInputForNumberText()
#if ENABLE(VIDEO_TRACK)
String textTrackSubtitlesText()
{
- notImplemented();
- return String();
+ return QCoreApplication::translate("QWebPage", "Subtitles", "Menu section heading for subtitles");
}
-String textTrackOffText()
+String textTrackOffMenuItemText()
{
- notImplemented();
- return String();
+ return QCoreApplication::translate("QWebPage", "Off", "Menu item label for the track that represents disabling closed captions");
+}
+
+String textTrackAutomaticMenuItemText()
+{
+ return QCoreApplication::translate("QWebPage", "Auto", "Menu item label for the track that represents automatic closed captions selection");
}
String textTrackNoLabelText()
{
- notImplemented();
- return String();
+ return QCoreApplication::translate("QWebPage", "No label", "Menu item label for a closed captions track that has no other name");
}
#endif
diff --git a/Source/WebCore/platform/qt/RenderThemeQt.cpp b/Source/WebCore/platform/qt/RenderThemeQt.cpp
index a486ba2a8..208a492a5 100644
--- a/Source/WebCore/platform/qt/RenderThemeQt.cpp
+++ b/Source/WebCore/platform/qt/RenderThemeQt.cpp
@@ -678,6 +678,37 @@ bool RenderThemeQt::paintMediaPlayButton(RenderObject* o, const PaintInfo& paint
return false;
}
+bool RenderThemeQt::paintMediaToggleClosedCaptionsButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
+{
+ HTMLMediaElement* mediaElement = toParentMediaElement(o);
+ if (!mediaElement)
+ return false;
+
+ QSharedPointer<StylePainter> p = getStylePainter(paintInfo);
+ if (p.isNull() || !p->isValid())
+ return true;
+
+ p->painter->setRenderHint(QPainter::Antialiasing, true);
+
+ paintMediaBackground(p->painter, r);
+
+ WorldMatrixTransformer transformer(p->painter, o, r);
+ p->painter->setBrush(getMediaControlForegroundColor(o));
+
+ QPainterPath captionBubble;
+ captionBubble.moveTo(98.766, 43.244);
+ captionBubble.cubicTo(captionBubble.currentPosition() + QPointF(0, -23.163), captionBubble.currentPosition() + QPointF(-21.775, -41.94), captionBubble.currentPosition() + QPointF(-48.637, -41.94));
+ captionBubble.cubicTo(captionBubble.currentPosition() + QPointF(-26.859, 0), captionBubble.currentPosition() + QPointF(-48.635, 18.777), captionBubble.currentPosition() + QPointF(-48.635, 41.94));
+ captionBubble.cubicTo(captionBubble.currentPosition() + QPointF(0, 18.266), captionBubble.currentPosition() + QPointF(13.546, 33.796), captionBubble.currentPosition() + QPointF(32.444, 39.549));
+ captionBubble.cubicTo(captionBubble.currentPosition() + QPointF(1.131, 8.356), captionBubble.currentPosition() + QPointF(26.037, 24.255), captionBubble.currentPosition() + QPointF(22.864, 19.921));
+ captionBubble.cubicTo(captionBubble.currentPosition() + QPointF(-4.462, -6.096), captionBubble.currentPosition() + QPointF(-5.159, -13.183), captionBubble.currentPosition() + QPointF(-5.07, -17.566));
+ captionBubble.cubicTo(QPointF(77.85, 84.397), QPointF(98.766, 65.923), QPointF(98.766, 43.224));
+ captionBubble.closeSubpath();
+
+ p->painter->drawPath(captionBubble);
+ return false;
+}
+
bool RenderThemeQt::paintMediaSeekBackButton(RenderObject*, const PaintInfo&, const IntRect&)
{
// We don't want to paint this at the moment.
diff --git a/Source/WebCore/platform/qt/RenderThemeQt.h b/Source/WebCore/platform/qt/RenderThemeQt.h
index 0872b9486..1b137c9b6 100644
--- a/Source/WebCore/platform/qt/RenderThemeQt.h
+++ b/Source/WebCore/platform/qt/RenderThemeQt.h
@@ -146,6 +146,7 @@ protected:
virtual bool paintMediaMuteButton(RenderObject*, const PaintInfo&, const IntRect&);
virtual bool paintMediaSeekBackButton(RenderObject*, const PaintInfo&, const IntRect&);
virtual bool paintMediaSeekForwardButton(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual bool paintMediaToggleClosedCaptionsButton(RenderObject*, const PaintInfo&, const IntRect&);
virtual bool paintMediaSliderTrack(RenderObject*, const PaintInfo&, const IntRect&);
virtual bool paintMediaSliderThumb(RenderObject*, const PaintInfo&, const IntRect&);
virtual bool paintMediaCurrentTime(RenderObject*, const PaintInfo&, const IntRect&);
@@ -154,6 +155,9 @@ protected:
virtual String formatMediaControlsCurrentTime(float currentTime, float duration) const;
virtual String formatMediaControlsRemainingTime(float currentTime, float duration) const;
virtual bool hasOwnDisabledStateHandlingFor(ControlPart) const { return true; }
+#if ENABLE(VIDEO_TRACK)
+ virtual bool supportsClosedCaptioning() const { return true; }
+#endif
void paintMediaBackground(QPainter*, const IntRect&) const;
double mediaControlsBaselineOpacity() const;