Bug 985915 - Vertically move up closed caption to not overlap control bar. r?rillian
MozReview-Commit-ID: HzJ3ppbmQnk
--- a/dom/html/TextTrackManager.cpp
+++ b/dom/html/TextTrackManager.cpp
@@ -225,16 +225,17 @@ TextTrackManager::UpdateCueDisplay()
nsIFrame* frame = mMediaElement->GetPrimaryFrame();
nsVideoFrame* videoFrame = do_QueryFrame(frame);
if (!videoFrame) {
return;
}
nsCOMPtr<nsIContent> overlay = videoFrame->GetCaptionOverlay();
+ nsCOMPtr<nsIContent> controls = videoFrame->GetVideoControls();
if (!overlay) {
return;
}
nsTArray<RefPtr<TextTrackCue> > activeCues;
mTextTracks->UpdateAndGetShowingCues(activeCues);
if (activeCues.Length() > 0) {
@@ -242,17 +243,17 @@ TextTrackManager::UpdateCueDisplay()
jsCues->SetAsArray(nsIDataType::VTYPE_INTERFACE,
&NS_GET_IID(nsIDOMEventTarget),
activeCues.Length(),
static_cast<void*>(activeCues.Elements()));
nsPIDOMWindowInner* window = mMediaElement->OwnerDoc()->GetInnerWindow();
if (window) {
- sParserWrapper->ProcessCues(window, jsCues, overlay);
+ sParserWrapper->ProcessCues(window, jsCues, overlay, controls);
}
} else if (overlay->Length() > 0) {
nsContentUtils::SetNodeTextContent(overlay, EmptyString(), true);
}
}
void
TextTrackManager::NotifyCueAdded(TextTrackCue& aCue)
@@ -291,16 +292,20 @@ TextTrackManager::PopulatePendingList()
}
void
TextTrackManager::AddListeners()
{
if (mMediaElement) {
mMediaElement->AddEventListener(NS_LITERAL_STRING("resizevideocontrols"),
this, false, false);
+ mMediaElement->AddEventListener(NS_LITERAL_STRING("seeked"),
+ this, false, false);
+ mMediaElement->AddEventListener(NS_LITERAL_STRING("controlbarchange"),
+ this, false, true);
}
}
void
TextTrackManager::HonorUserPreferencesForTrackSelection()
{
if (performedTrackSelection || !mTextTracks) {
return;
@@ -400,21 +405,27 @@ NS_IMETHODIMP
TextTrackManager::HandleEvent(nsIDOMEvent* aEvent)
{
if (!mTextTracks) {
return NS_OK;
}
nsAutoString type;
aEvent->GetType(type);
- if (type.EqualsLiteral("resizevideocontrols")) {
+ if (type.EqualsLiteral("resizevideocontrols") ||
+ type.EqualsLiteral("seeked")) {
for (uint32_t i = 0; i< mTextTracks->Length(); i++) {
((*mTextTracks)[i])->SetCuesDirty();
}
}
+
+ if (type.EqualsLiteral("controlbarchange")) {
+ UpdateCueDisplay();
+ }
+
return NS_OK;
}
class SimpleTextTrackEvent : public Runnable
{
public:
friend class CompareSimpleTextTrackEvents;
--- a/dom/media/webvtt/WebVTTParserWrapper.js
+++ b/dom/media/webvtt/WebVTTParserWrapper.js
@@ -49,19 +49,19 @@ WebVTTParserWrapper.prototype =
};
},
convertCueToDOMTree: function(window, cue)
{
return WebVTT.convertCueToDOMTree(window, cue.text);
},
- processCues: function(window, cues, overlay)
+ processCues: function(window, cues, overlay, controls)
{
- WebVTT.processCues(window, cues, overlay);
+ WebVTT.processCues(window, cues, overlay, controls);
},
classDescription: "Wrapper for the JS WebVTT implementation (vtt.js)",
classID: Components.ID(WEBVTTPARSERWRAPPER_CID),
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebVTTParserWrapper]),
classInfo: XPCOMUtils.generateCI({
classID: WEBVTTPARSERWRAPPER_CID,
contractID: WEBVTTPARSERWRAPPER_CONTRACTID,
--- a/dom/media/webvtt/nsIWebVTTParserWrapper.idl
+++ b/dom/media/webvtt/nsIWebVTTParserWrapper.idl
@@ -72,16 +72,17 @@ interface nsIWebVTTParserWrapper : nsISu
* overlap avoidance using the dimensions of 'overlay'. Finally, it adds the
* computed divs to the VTTCues display state property for use later.
*
* @param window A window object with which it will create the DOM tree
* and containing div element.
* @param cues An array of VTTCues who need there display state to be
* computed.
* @param overlay The HTMLElement that the cues will be displayed within.
+ * @param controls The video control element that will affect cues position.
*/
void processCues(in mozIDOMWindow window, in nsIVariant cues,
- in nsISupports overlay);
+ in nsISupports overlay, in nsISupports controls);
};
%{C++
#define NS_WEBVTTPARSERWRAPPER_CONTRACTID "@mozilla.org/webvttParserWrapper;1"
%}
--- a/dom/media/webvtt/vtt.jsm
+++ b/dom/media/webvtt/vtt.jsm
@@ -1115,39 +1115,54 @@ this.EXPORTED_SYMBOLS = ["WebVTT"];
var FONT_SIZE_PERCENT = 0.05;
var FONT_STYLE = "sans-serif";
var CUE_BACKGROUND_PADDING = "1.5%";
// Runs the processing model over the cues and regions passed to it.
// @param overlay A block level element (usually a div) that the computed cues
// and regions will be placed into.
- WebVTT.processCues = function(window, cues, overlay) {
+ // @param controls A Control bar element. Cues' position will be
+ // affected and repositioned according to it.
+ WebVTT.processCues = function(window, cues, overlay, controls) {
if (!window || !cues || !overlay) {
return null;
}
// Remove all previous children.
while (overlay.firstChild) {
overlay.removeChild(overlay.firstChild);
}
+ var controlBar;
+ var controlBarShown;
+
+ if (controls) {
+ controlBar = controls.ownerDocument.getAnonymousElementByAttribute(
+ controls, "class", "controlBar");
+ controlBarShown = controlBar ? !!controlBar.clientHeight : false;
+ }
+
var paddedOverlay = window.document.createElement("div");
paddedOverlay.style.position = "absolute";
paddedOverlay.style.left = "0";
paddedOverlay.style.right = "0";
paddedOverlay.style.top = "0";
paddedOverlay.style.bottom = "0";
paddedOverlay.style.margin = CUE_BACKGROUND_PADDING;
overlay.appendChild(paddedOverlay);
// Determine if we need to compute the display states of the cues. This could
// be the case if a cue's state has been changed since the last computation or
// if it has not been computed yet.
function shouldCompute(cues) {
+ if (controlBarShown) {
+ return true;
+ }
+
for (var i = 0; i < cues.length; i++) {
if (cues[i].hasBeenReset || !cues[i].displayState) {
return true;
}
}
return false;
}
@@ -1164,16 +1179,21 @@ this.EXPORTED_SYMBOLS = ["WebVTT"];
fontSize = Math.round(containerBox.height * FONT_SIZE_PERCENT * 100) / 100;
var styleOptions = {
font: fontSize + "px " + FONT_STYLE
};
(function() {
var styleBox, cue;
+ if (controlBarShown) {
+ // Add an empty output box that cover the same region as video control bar.
+ boxPositions.push(BoxPosition.getSimpleBoxPosition(controlBar));
+ }
+
for (var i = 0; i < cues.length; i++) {
cue = cues[i];
// Compute the intial position and styles of the cue div.
styleBox = new CueStyleBox(window, cue, styleOptions);
paddedOverlay.appendChild(styleBox.div);
// Move the cue div to it's correct line position.
--- a/layout/generic/nsVideoFrame.h
+++ b/layout/generic/nsVideoFrame.h
@@ -97,16 +97,18 @@ public:
nsIContent* GetPosterImage() { return mPosterImage; }
// Returns true if we should display the poster. Note that once we show
// a video frame, the poster will never be displayed again.
bool ShouldDisplayPoster();
nsIContent *GetCaptionOverlay() { return mCaptionDiv; }
+ nsIContent *GetVideoControls() { return mVideoControls; }
+
#ifdef DEBUG_FRAME_DUMP
virtual nsresult GetFrameName(nsAString& aResult) const override;
#endif
already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
nsDisplayItem* aItem,
const ContainerLayerParameters& aContainerParameters);
--- a/toolkit/content/widgets/videocontrols.xml
+++ b/toolkit/content/widgets/videocontrols.xml
@@ -1318,16 +1318,17 @@
}
this.textTrackList.setAttribute("hidden", "true");
this.setClosedCaptionButtonState();
},
onControlBarTransitioned : function () {
this.textTrackList.setAttribute("hidden", "true");
+ this.video.dispatchEvent(new CustomEvent("controlbarchange"));
},
toggleClosedCaption : function () {
if (this.overlayableTextTracks.length === 1) {
const lastTTIdx = this.overlayableTextTracks[0].index;
return this.changeTextTrack(this.isClosedCaptionOn() ? 0 : lastTTIdx);
}