Bug 887934 - Part 2 - Reposition closed caption according to video control. r?rillian
MozReview-Commit-ID: HsHowVwkitM
--- a/dom/html/TextTrackManager.cpp
+++ b/dom/html/TextTrackManager.cpp
@@ -202,16 +202,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) {
@@ -219,17 +220,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::AddCue(TextTrackCue& aCue)
@@ -258,16 +259,20 @@ TextTrackManager::PopulatePendingList()
}
void
TextTrackManager::AddListeners()
{
if (mMediaElement) {
mMediaElement->AddEventListener(NS_LITERAL_STRING("resizevideocontrols"),
this, false, false);
+ mMediaElement->AddEventListener(NS_LITERAL_STRING("controlbarchange"),
+ this, false, true);
+ mMediaElement->AddEventListener(NS_LITERAL_STRING("texttrackchange"),
+ this, false, true);
}
}
void
TextTrackManager::HonorUserPreferencesForTrackSelection()
{
if (performedTrackSelection || !mTextTracks) {
return;
@@ -372,13 +377,26 @@ TextTrackManager::HandleEvent(nsIDOMEven
nsAutoString type;
aEvent->GetType(type);
if (type.EqualsLiteral("resizevideocontrols")) {
for (uint32_t i = 0; i< mTextTracks->Length(); i++) {
((*mTextTracks)[i])->SetCuesDirty();
}
}
+
+ if (type.EqualsLiteral("controlbarchange")) {
+ for (uint32_t i = 0; i< mTextTracks->Length(); i++) {
+ ((*mTextTracks)[i])->SetCuesDirty();
+ }
+
+ UpdateCueDisplay();
+ }
+
+ if (type.EqualsLiteral("texttrackchange")) {
+ UpdateCueDisplay();
+ }
+
return NS_OK;
}
} // namespace dom
} // namespace mozilla
--- 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 XBL Element that may 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
@@ -1143,26 +1143,37 @@ 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 XBL that controls playback. Cues' position will be
+ // affected and restyled 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, cueOffsetY;
+
+ if (controls) {
+ controlBar = controls.ownerDocument.getAnonymousElementByAttribute(
+ controls, "class", "controlBar");
+ }
+
+ cueOffsetY = controlBar ? controlBar.clientHeight : 0;
+
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);
@@ -1202,16 +1213,21 @@ this.EXPORTED_SYMBOLS = ["WebVTT"];
// 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.
moveBoxToLinePosition(window, styleBox, containerBox, boxPositions);
+ // Vertically move up only when cue overlapped with control bar
+ if (+styleBox.div.style.bottom.replace(/px$/, "") < cueOffsetY) {
+ styleBox.div.style.transform = `translateY(-${cueOffsetY}px)`;
+ }
+
// Remember the computed div so that we don't have to recompute it later
// if we don't have too.
cue.displayState = styleBox.div;
boxPositions.push(BoxPosition.getSimpleBoxPosition(styleBox));
}
})();
};
--- 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);