diff --git a/mozilla/layout/generic/nsBlockFrame.cpp b/mozilla/layout/generic/nsBlockFrame.cpp index 68888f97c7c..815c3b17d2f 100644 --- a/mozilla/layout/generic/nsBlockFrame.cpp +++ b/mozilla/layout/generic/nsBlockFrame.cpp @@ -784,8 +784,12 @@ CalculateContainingBlockSizeForAbsolutes(const nsHTMLReflowState& aReflowState, // The issue here is that for a 'height' of 'auto' the reflow state // code won't know how to calculate the containing block height // because it's calculated bottom up. So we use our own computed - // size as the dimensions. + // size as the dimensions. We don't really want to do this for the + // initial containing block nsIFrame* frame = aReflowState.frame; + if (nsLayoutUtils::IsInitialContainingBlock(frame)) { + return nsSize(-1, -1); + } nsSize cbSize(aFrameSize); // Containing block is relative to the padding edge @@ -821,9 +825,13 @@ CalculateContainingBlockSizeForAbsolutes(const nsHTMLReflowState& aReflowState, nsBoxLayoutState dummyState(aLastRS->frame->PresContext(), aLastRS->rendContext); scrollbars = scrollFrame->GetDesiredScrollbarSizes(&dummyState); - if (!lastButOneRS->mFlags.mAssumingHScrollbar) { + // XXX We should account for the horizontal scrollbar too --- but currently + // nsGfxScrollFrame assumes nothing depends on the presence (or absence) of + // a horizontal scrollbar, so accounting for it would create incremental + // reflow bugs. + //if (!lastButOneRS->mFlags.mAssumingHScrollbar) { scrollbars.top = scrollbars.bottom = 0; - } + //} if (!lastButOneRS->mFlags.mAssumingVScrollbar) { scrollbars.left = scrollbars.right = 0; } diff --git a/mozilla/layout/generic/nsGfxScrollFrame.cpp b/mozilla/layout/generic/nsGfxScrollFrame.cpp index e6fa87beeb3..e7ab34c8975 100644 --- a/mozilla/layout/generic/nsGfxScrollFrame.cpp +++ b/mozilla/layout/generic/nsGfxScrollFrame.cpp @@ -420,19 +420,6 @@ nsHTMLScrollFrame::ReflowScrolledFrame(const ScrollReflowState& aState, nscoord availWidth = aState.mReflowState.ComputedWidth() + paddingLR; - nscoord computedHeight = aState.mReflowState.ComputedHeight(); - nscoord computedMinHeight = aState.mReflowState.mComputedMinHeight; - nscoord computedMaxHeight = aState.mReflowState.mComputedMaxHeight; - if (aAssumeHScroll) { - nsSize hScrollbarPrefSize = - mInner.mHScrollbarBox->GetPrefSize(const_cast(aState.mBoxState)); - if (computedHeight != NS_UNCONSTRAINEDSIZE) - computedHeight = PR_MAX(0, computedHeight - hScrollbarPrefSize.height); - computedMinHeight = PR_MAX(0, computedMinHeight - hScrollbarPrefSize.height); - if (computedMaxHeight != NS_UNCONSTRAINEDSIZE) - computedMaxHeight = PR_MAX(0, computedMaxHeight - hScrollbarPrefSize.height); - } - if (aAssumeVScroll) { nsSize vScrollbarPrefSize = mInner.mVScrollbarBox->GetPrefSize(const_cast(aState.mBoxState)); @@ -456,9 +443,6 @@ nsHTMLScrollFrame::ReflowScrolledFrame(const ScrollReflowState& aState, &aState.mReflowState.mComputedPadding); kidReflowState.mFlags.mAssumingHScrollbar = aAssumeHScroll; kidReflowState.mFlags.mAssumingVScrollbar = aAssumeVScroll; - kidReflowState.SetComputedHeight(computedHeight); - kidReflowState.mComputedMinHeight = computedMinHeight; - kidReflowState.mComputedMaxHeight = computedMaxHeight; nsReflowStatus status; nsresult rv = ReflowChild(mInner.mScrolledFrame, presContext, *aMetrics, @@ -542,14 +526,13 @@ nsresult nsHTMLScrollFrame::ReflowContents(ScrollReflowState* aState, const nsHTMLReflowMetrics& aDesiredSize) { - PRBool lastUsedVScrollbar = GuessVScrollbarNeeded(*aState); - PRBool lastUsedHScrollbar = mInner.mHasHorizontalScrollbar; // XXX is this good enough? + PRBool currentlyUsingVScrollbar = GuessVScrollbarNeeded(*aState); nsHTMLReflowMetrics kidDesiredSize(aDesiredSize.mFlags); - nsresult rv = ReflowScrolledFrame(*aState, lastUsedHScrollbar, lastUsedVScrollbar, + nsresult rv = ReflowScrolledFrame(*aState, PR_FALSE, currentlyUsingVScrollbar, &kidDesiredSize, PR_TRUE); - NS_ENSURE_SUCCESS(rv, rv); - - PRBool relativeHeight = (mInner.mScrolledFrame->GetStateBits() & NS_FRAME_CONTAINS_RELATIVE_HEIGHT) != 0; + if (NS_FAILED(rv)) + return rv; + PRBool didUseScrollbar = currentlyUsingVScrollbar; // There's an important special case ... if the child appears to fit // in the inside-border rect (but overflows the scrollport), we @@ -567,10 +550,7 @@ nsHTMLScrollFrame::ReflowContents(ScrollReflowState* aState, // Detecting when we enter this special case is important for when // people design layouts that exactly fit the container "most of the // time". - - // XXX Is this check really sufficient to catch all the incremental cases - // where the ideal case doesn't have a scrollbar? - if ((lastUsedVScrollbar || (lastUsedHScrollbar && relativeHeight)) && + if (currentlyUsingVScrollbar && aState->mStyles.mVertical != NS_STYLE_OVERFLOW_SCROLL && aState->mStyles.mHorizontal != NS_STYLE_OVERFLOW_SCROLL) { nsSize insideBorderSize = @@ -579,66 +559,56 @@ nsHTMLScrollFrame::ReflowContents(ScrollReflowState* aState, nsRect scrolledRect = mInner.GetScrolledRect(insideBorderSize); if (nsRect(nsPoint(0, 0), insideBorderSize).Contains(scrolledRect)) { // Let's pretend we had no vertical scrollbar coming in here - rv = ReflowScrolledFrame(*aState, PR_FALSE, PR_FALSE, + currentlyUsingVScrollbar = PR_FALSE; + rv = ReflowScrolledFrame(*aState, PR_FALSE, currentlyUsingVScrollbar, &kidDesiredSize, PR_FALSE); - NS_ENSURE_SUCCESS(rv, rv); - lastUsedVScrollbar = PR_FALSE; - lastUsedHScrollbar = PR_FALSE; + if (NS_FAILED(rv)) + return rv; + didUseScrollbar = PR_FALSE; } } // First try a layout without a horizontal scrollbar, then with. - if (!relativeHeight) { - if (TryLayout(aState, kidDesiredSize, lastUsedVScrollbar, PR_FALSE, PR_FALSE)) - return NS_OK; - - if (TryLayout(aState, kidDesiredSize, lastUsedVScrollbar, PR_TRUE, PR_FALSE)) - return NS_OK; - } else { - if (TryLayout(aState, kidDesiredSize, lastUsedVScrollbar, lastUsedHScrollbar, PR_FALSE)) - return NS_OK; - } + if (TryLayout(aState, kidDesiredSize, didUseScrollbar, PR_FALSE, PR_FALSE)) + return NS_OK; + // XXX Adding a horizontal scrollbar could cause absolute children positioned + // relative to the bottom padding-edge to need to be reflowed. But we don't, + // because that would be slow. + if (TryLayout(aState, kidDesiredSize, didUseScrollbar, PR_TRUE, PR_FALSE)) + return NS_OK; PRBool canHaveVerticalScrollbar = aState->mStyles.mVertical != NS_STYLE_OVERFLOW_HIDDEN; - PRBool canHaveHorizontalScrollbar = - aState->mStyles.mHorizontal != NS_STYLE_OVERFLOW_HIDDEN; - // That didn't work. Try the other setting for the vertical scrollbar. // But don't try to show a scrollbar if we know there can't be one. - if (lastUsedVScrollbar || canHaveVerticalScrollbar) { - rv = ReflowScrolledFrame(*aState, PR_FALSE, !lastUsedVScrollbar, - &kidDesiredSize, PR_FALSE); - NS_ENSURE_SUCCESS(rv, rv); - lastUsedHScrollbar = PR_FALSE; - lastUsedVScrollbar = !lastUsedVScrollbar; - if (!relativeHeight) { - if (TryLayout(aState, kidDesiredSize, lastUsedVScrollbar, PR_FALSE, PR_FALSE)) - return NS_OK; - if (TryLayout(aState, kidDesiredSize, lastUsedVScrollbar, PR_TRUE, PR_FALSE)) - return NS_OK; - } else { - if (TryLayout(aState, kidDesiredSize, lastUsedVScrollbar, lastUsedHScrollbar, PR_FALSE)) - return NS_OK; - } - } - - if ((lastUsedHScrollbar || canHaveHorizontalScrollbar) && relativeHeight) { - rv = ReflowScrolledFrame(*aState, PR_TRUE, PR_FALSE, - &kidDesiredSize, PR_FALSE); - lastUsedHScrollbar = PR_TRUE; - lastUsedVScrollbar = PR_FALSE; - NS_ENSURE_SUCCESS(rv, rv); - if (TryLayout(aState, kidDesiredSize, lastUsedVScrollbar, lastUsedHScrollbar, PR_FALSE)) + if (currentlyUsingVScrollbar || canHaveVerticalScrollbar) { + nsHTMLReflowMetrics kidRetrySize(aDesiredSize.mFlags); + rv = ReflowScrolledFrame(*aState, PR_FALSE, !currentlyUsingVScrollbar, + &kidRetrySize, PR_FALSE); + if (NS_FAILED(rv)) + return rv; + didUseScrollbar = !currentlyUsingVScrollbar; + // XXX Adding a horizontal scrollbar could cause absolute children positioned + // relative to the bottom padding-edge to need to be reflowed. But we don't, + // because that would be slow. + if (TryLayout(aState, kidRetrySize, didUseScrollbar, PR_FALSE, PR_FALSE)) return NS_OK; + if (TryLayout(aState, kidRetrySize, didUseScrollbar, PR_TRUE, PR_FALSE)) + return NS_OK; + + NS_WARNING("Strange content ... we can't find logically consistent scrollbar settings"); + } else { + NS_WARNING("Strange content ... we can't find logically consistent scrollbar settings"); } - rv = ReflowScrolledFrame(*aState, PR_TRUE, PR_TRUE, - &kidDesiredSize, PR_FALSE); - lastUsedHScrollbar = PR_TRUE; - lastUsedVScrollbar = PR_TRUE; - NS_ENSURE_SUCCESS(rv, rv); - TryLayout(aState, kidDesiredSize, lastUsedVScrollbar, lastUsedHScrollbar, PR_TRUE); + // Fall back to no scrollbars --- even if NS_STYLE_OVERFLOW_SCROLL is + // in effect. They might not fit anyway. + if (didUseScrollbar) { + rv = ReflowScrolledFrame(*aState, PR_FALSE, PR_FALSE, &kidDesiredSize, PR_FALSE); + if (NS_FAILED(rv)) + return rv; + } + TryLayout(aState, kidDesiredSize, PR_FALSE, PR_FALSE, PR_TRUE); return NS_OK; } diff --git a/mozilla/layout/generic/nsHTMLReflowState.cpp b/mozilla/layout/generic/nsHTMLReflowState.cpp index da7bc6b5109..427158890e2 100644 --- a/mozilla/layout/generic/nsHTMLReflowState.cpp +++ b/mozilla/layout/generic/nsHTMLReflowState.cpp @@ -362,7 +362,16 @@ IsQuirkContainingBlockHeight(const nsHTMLReflowState* rs) nsIAtom* frameType = rs->frame->GetType(); if (nsGkAtoms::blockFrame == frameType || nsGkAtoms::areaFrame == frameType || - nsGkAtoms::scrollFrame == frameType) { + nsGkAtoms::scrollFrame == frameType) { + + if (nsGkAtoms::areaFrame == frameType) { + // Skip over scrolled-content area frames + if (rs->frame->GetStyleContext()->GetPseudoType() == + nsCSSAnonBoxes::scrolledContent) { + return PR_FALSE; + } + } + // Note: This next condition could change due to a style change, // but that would cause a style reflow anyway, which means we're ok. if (NS_AUTOHEIGHT == rs->ComputedHeight()) { @@ -415,7 +424,7 @@ nsHTMLReflowState::InitResizeFlags(nsPresContext* aPresContext) mStylePosition->mMinHeight.GetUnit() == eStyleUnit_Percent || mStylePosition->mMaxHeight.GetUnit() == eStyleUnit_Percent || mStylePosition->mOffset.GetTopUnit() == eStyleUnit_Percent || - mStylePosition->mOffset.GetBottomUnit() != eStyleUnit_Auto || + mStylePosition->mOffset.GetBottomUnit() == eStyleUnit_Percent || frame->IsBoxFrame() || frame->GetIntrinsicSize().height.GetUnit() == eStyleUnit_Percent; @@ -1408,6 +1417,14 @@ CalcQuirkContainingBlockHeight(const nsHTMLReflowState* aCBReflowState) if (nsGkAtoms::blockFrame == frameType || nsGkAtoms::areaFrame == frameType || nsGkAtoms::scrollFrame == frameType) { + + if (nsGkAtoms::areaFrame == frameType) { + // Skip over scrolled-content area frames + if (rs->frame->GetStyleContext()->GetPseudoType() == + nsCSSAnonBoxes::scrolledContent) { + continue; + } + } secondAncestorRS = firstAncestorRS; firstAncestorRS = (nsHTMLReflowState*)rs; @@ -1425,7 +1442,12 @@ CalcQuirkContainingBlockHeight(const nsHTMLReflowState* aCBReflowState) } } else if (nsGkAtoms::canvasFrame == frameType) { - // Always continue on to the height calculation + // Use scroll frames' computed height if we have one, this will + // allow us to get viewport height for native scrollbars. + nsHTMLReflowState* scrollState = (nsHTMLReflowState *)rs->parentReflowState; + if (nsGkAtoms::scrollFrame == scrollState->frame->GetType()) { + rs = scrollState; + } } else if (nsGkAtoms::pageContentFrame == frameType) { nsIFrame* prevInFlow = rs->frame->GetPrevInFlow(); @@ -1646,14 +1668,24 @@ nsHTMLReflowState::InitConstraints(nsPresContext* aPresContext, // content nsIAtom* fType; if (NS_AUTOHEIGHT == aContainingBlockHeight) { - // See if the containing block is a cell frame which needs + // See if the containing block is (1) a scrolled frame, i.e. its + // parent is a scroll frame. The presence of the intervening + // frame (that the scroll frame scrolls) needs to be hidden from + // the containingBlockHeight calcuation, or (2) a cell frame which needs // to use the mComputedHeight of the cell instead of what the cell block passed in. - // XXX It seems like this could lead to bugs with min-height and friends if (cbrs->parentReflowState) { - fType = cbrs->frame->GetType(); - if (IS_TABLE_CELL(fType)) { - // use the cell's computed height - aContainingBlockHeight = cbrs->mComputedHeight; + nsIFrame* f = cbrs->parentReflowState->frame; + fType = f->GetType(); + if (nsGkAtoms::scrollFrame == fType) { + // Use the scroll frame's computed height instead + aContainingBlockHeight = cbrs->parentReflowState->mComputedHeight; + } + else { + fType = cbrs->frame->GetType(); + if (IS_TABLE_CELL(fType)) { + // use the cell's computed height + aContainingBlockHeight = cbrs->mComputedHeight; + } } } } diff --git a/mozilla/layout/reftests/reftest.list b/mozilla/layout/reftests/reftest.list index 098b307da4e..78687716026 100644 --- a/mozilla/layout/reftests/reftest.list +++ b/mozilla/layout/reftests/reftest.list @@ -80,7 +80,3 @@ include ib-split/reftest.list # line-breaking include line-breaking/reftest.list - -# percent-overflow-sizing -include percent-overflow-sizing/reftest.list -