--- a/layout/generic/nsVideoFrame.cpp
+++ b/layout/generic/nsVideoFrame.cpp
@@ -293,28 +293,36 @@ nsVideoFrame::Reflow(nsPresContext* aPre
("enter nsVideoFrame::Reflow: availSize=%d,%d",
aReflowInput.AvailableWidth(),
aReflowInput.AvailableHeight()));
NS_PRECONDITION(mState & NS_FRAME_IN_REFLOW, "frame is not in reflow");
aStatus = NS_FRAME_COMPLETE;
- aMetrics.Width() = aReflowInput.ComputedWidth();
- aMetrics.Height() = aReflowInput.ComputedHeight();
+ const WritingMode myWM = aReflowInput.GetWritingMode();
+ nscoord contentBoxBSize = aReflowInput.ComputedBSize();
+ const nscoord borderBoxISize = aReflowInput.ComputedISize() +
+ aReflowInput.ComputedLogicalBorderPadding().IStartEnd(myWM);
+ const bool isBSizeShrinkWrapping = (contentBoxBSize == NS_INTRINSICSIZE);
- // stash this away so we can compute our inner area later
+ nscoord borderBoxBSize;
+ if (!isBSizeShrinkWrapping) {
+ borderBoxBSize = contentBoxBSize +
+ aReflowInput.ComputedLogicalBorderPadding().BStartEnd(myWM);
+ }
+
mBorderPadding = aReflowInput.ComputedPhysicalBorderPadding();
- aMetrics.Width() += mBorderPadding.left + mBorderPadding.right;
- aMetrics.Height() += mBorderPadding.top + mBorderPadding.bottom;
+ // Reflow the child frames. We may have up to three: an image
+ // frame (for the poster image), a container frame for the controls,
+ // and a container frame for the caption.
+ for (nsIFrame* child : mFrames) {
+ nsSize oldChildSize = child->GetSize();
- // Reflow the child frames. We may have up to two, an image frame
- // which is the poster, and a box frame, which is the video controls.
- for (nsIFrame* child : mFrames) {
if (child->GetContent() == mPosterImage) {
// Reflow the poster frame.
nsImageFrame* imageFrame = static_cast<nsImageFrame*>(child);
ReflowOutput kidDesiredSize(aReflowInput);
WritingMode wm = imageFrame->GetWritingMode();
LogicalSize availableSize = aReflowInput.AvailableSize(wm);
LogicalSize cbSize = aMetrics.Size(aMetrics.GetWritingMode()).
ConvertTo(wm, aMetrics.GetWritingMode());
@@ -333,56 +341,77 @@ nsVideoFrame::Reflow(nsPresContext* aPre
}
kidReflowInput.SetComputedWidth(posterRenderRect.width);
kidReflowInput.SetComputedHeight(posterRenderRect.height);
ReflowChild(imageFrame, aPresContext, kidDesiredSize, kidReflowInput,
posterRenderRect.x, posterRenderRect.y, 0, aStatus);
FinishReflowChild(imageFrame, aPresContext,
kidDesiredSize, &kidReflowInput,
posterRenderRect.x, posterRenderRect.y, 0);
+
+// Android still uses XUL media controls & hence needs this XUL-friendly
+// custom reflow code. This will go away in bug 1310907.
+#ifdef ANDROID
} else if (child->GetContent() == mVideoControls) {
// Reflow the video controls frame.
nsBoxLayoutState boxState(PresContext(), aReflowInput.mRenderingContext);
- nsSize size = child->GetSize();
nsBoxFrame::LayoutChildAt(boxState,
child,
nsRect(mBorderPadding.left,
mBorderPadding.top,
aReflowInput.ComputedWidth(),
aReflowInput.ComputedHeight()));
- if (child->GetSize() != size) {
- RefPtr<Runnable> event = new DispatchResizeToControls(child->GetContent());
- nsContentUtils::AddScriptRunner(event);
- }
- } else if (child->GetContent() == mCaptionDiv) {
- // Reflow to caption div
- ReflowOutput kidDesiredSize(aReflowInput);
+
+#endif // ANDROID
+ } else if (child->GetContent() == mCaptionDiv ||
+ child->GetContent() == mVideoControls) {
+ // Reflow the caption and control bar frames.
WritingMode wm = child->GetWritingMode();
- LogicalSize availableSize = aReflowInput.AvailableSize(wm);
- LogicalSize cbSize = aMetrics.Size(aMetrics.GetWritingMode()).
- ConvertTo(wm, aMetrics.GetWritingMode());
+ LogicalSize availableSize = aReflowInput.ComputedSize(wm);
+ availableSize.BSize(wm) = NS_UNCONSTRAINEDSIZE;
+
ReflowInput kidReflowInput(aPresContext,
aReflowInput,
child,
- availableSize,
- &cbSize);
- nsSize size(aReflowInput.ComputedWidth(), aReflowInput.ComputedHeight());
- size.width -= kidReflowInput.ComputedPhysicalBorderPadding().LeftRight();
- size.height -= kidReflowInput.ComputedPhysicalBorderPadding().TopBottom();
-
- kidReflowInput.SetComputedWidth(std::max(size.width, 0));
- kidReflowInput.SetComputedHeight(std::max(size.height, 0));
-
+ availableSize);
+ ReflowOutput kidDesiredSize(kidReflowInput);
ReflowChild(child, aPresContext, kidDesiredSize, kidReflowInput,
mBorderPadding.left, mBorderPadding.top, 0, aStatus);
+
+ if (child->GetContent() == mVideoControls && isBSizeShrinkWrapping) {
+ contentBoxBSize = kidDesiredSize.BSize(myWM);
+ }
+
FinishReflowChild(child, aPresContext,
kidDesiredSize, &kidReflowInput,
mBorderPadding.left, mBorderPadding.top, 0);
}
+
+ if (child->GetContent() == mVideoControls && child->GetSize() != oldChildSize) {
+ RefPtr<Runnable> event = new DispatchResizeToControls(child->GetContent());
+ nsContentUtils::AddScriptRunner(event);
+ }
}
+
+ if (isBSizeShrinkWrapping) {
+ if (contentBoxBSize == NS_INTRINSICSIZE) {
+ // We didn't get a BSize from our intrinsic size/ratio, nor did we
+ // get one from our controls. Just use BSize of 0.
+ contentBoxBSize = 0;
+ }
+ contentBoxBSize = NS_CSS_MINMAX(contentBoxBSize,
+ aReflowInput.ComputedMinBSize(),
+ aReflowInput.ComputedMaxBSize());
+ borderBoxBSize = contentBoxBSize +
+ aReflowInput.ComputedLogicalBorderPadding().BStartEnd(myWM);
+ }
+
+ LogicalSize logicalDesiredSize(myWM, borderBoxISize, borderBoxBSize);
+ aMetrics.SetSize(myWM, logicalDesiredSize);
+
aMetrics.SetOverflowAreasToDesiredBounds();
FinishAndStoreOverflow(&aMetrics);
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
("exit nsVideoFrame::Reflow: size=%d,%d",
aMetrics.Width(), aMetrics.Height()));
NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aMetrics);
@@ -521,16 +550,32 @@ nsVideoFrame::ComputeSize(nsRenderingCon
WritingMode aWM,
const LogicalSize& aCBSize,
nscoord aAvailableISize,
const LogicalSize& aMargin,
const LogicalSize& aBorder,
const LogicalSize& aPadding,
ComputeSizeFlags aFlags)
{
+// When in no video scenario, it should fall back to inherited method.
+// We keep old codepath here since Android still uses XUL media controls.
+// This will go away in bug 1310907.
+#ifndef ANDROID
+ if (!HasVideoElement()) {
+ return nsContainerFrame::ComputeSize(aRenderingContext,
+ aWM,
+ aCBSize,
+ aAvailableISize,
+ aMargin,
+ aBorder,
+ aPadding,
+ aFlags);
+ }
+#endif // ANDROID
+
nsSize size = GetVideoIntrinsicSize(aRenderingContext);
IntrinsicSize intrinsicSize;
intrinsicSize.width.SetCoordValue(size.width);
intrinsicSize.height.SetCoordValue(size.height);
// Only video elements have an intrinsic ratio.
nsSize intrinsicRatio = HasVideoElement() ? size : nsSize(0, 0);
@@ -538,27 +583,59 @@ nsVideoFrame::ComputeSize(nsRenderingCon
return ComputeSizeWithIntrinsicDimensions(aRenderingContext, aWM,
intrinsicSize, intrinsicRatio,
aCBSize, aMargin, aBorder, aPadding,
aFlags);
}
nscoord nsVideoFrame::GetMinISize(nsRenderingContext *aRenderingContext)
{
- nsSize size = GetVideoIntrinsicSize(aRenderingContext);
- nscoord result = GetWritingMode().IsVertical() ? size.height : size.width;
+ nscoord result;
DISPLAY_MIN_WIDTH(this, result);
+
+ if (HasVideoElement()) {
+ nsSize size = GetVideoIntrinsicSize(aRenderingContext);
+ result = GetWritingMode().IsVertical() ? size.height : size.width;
+ } else {
+ // We expect last and only child of audio elements to be control if
+ // "controls" attribute is present.
+ nsIFrame* kid = mFrames.LastChild();
+ if (kid) {
+ result = nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
+ kid,
+ nsLayoutUtils::MIN_ISIZE);
+ } else {
+ result = 0;
+ }
+ }
+
return result;
}
nscoord nsVideoFrame::GetPrefISize(nsRenderingContext *aRenderingContext)
{
- nsSize size = GetVideoIntrinsicSize(aRenderingContext);
- nscoord result = GetWritingMode().IsVertical() ? size.height : size.width;
+ nscoord result;
DISPLAY_PREF_WIDTH(this, result);
+
+ if (HasVideoElement()) {
+ nsSize size = GetVideoIntrinsicSize(aRenderingContext);
+ result = GetWritingMode().IsVertical() ? size.height : size.width;
+ } else {
+ // We expect last and only child of audio elements to be control if
+ // "controls" attribute is present.
+ nsIFrame* kid = mFrames.LastChild();
+ if (kid) {
+ result = nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
+ kid,
+ nsLayoutUtils::PREF_ISIZE);
+ } else {
+ result = 0;
+ }
+ }
+
return result;
}
nsSize nsVideoFrame::GetIntrinsicRatio()
{
if (!HasVideoElement()) {
// Audio elements have no intrinsic ratio.
return nsSize(0, 0);
@@ -595,26 +672,30 @@ bool nsVideoFrame::ShouldDisplayPoster()
}
nsSize
nsVideoFrame::GetVideoIntrinsicSize(nsRenderingContext *aRenderingContext)
{
// Defaulting size to 300x150 if no size given.
nsIntSize size(300, 150);
+// All media controls have been converted to HTML except Android. Hence
+// we keep this codepath for Android until removal in bug 1310907.
+#ifdef ANDROID
if (!HasVideoElement()) {
if (!mFrames.FirstChild()) {
return nsSize(0, 0);
}
// Ask the controls frame what its preferred height is
nsBoxLayoutState boxState(PresContext(), aRenderingContext, 0);
nscoord prefHeight = mFrames.LastChild()->GetXULPrefSize(boxState).height;
return nsSize(nsPresContext::CSSPixelsToAppUnits(size.width), prefHeight);
}
+#endif // ANDROID
HTMLVideoElement* element = static_cast<HTMLVideoElement*>(GetContent());
if (NS_FAILED(element->GetVideoSize(&size)) && ShouldDisplayPoster()) {
// Use the poster image frame's size.
nsIFrame *child = mPosterImage->GetPrimaryFrame();
nsImageFrame* imageFrame = do_QueryFrame(child);
nsSize imgsize;
if (NS_SUCCEEDED(imageFrame->GetIntrinsicImageSize(imgsize))) {