diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index f17a3b50424f..a7166673d6c8 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -255,7 +255,6 @@ struct ScrollReflowState { nsBoxLayoutState mBoxState; nsGfxScrollFrameInner::ScrollbarStyles mStyles; nsReflowReason mNewReason; - nsMargin mComputedBorder; // === Filled in when TryLayout succeeds === // The area of the scrollport, in coordinates relative to the scrollframe @@ -284,25 +283,20 @@ struct ScrollReflowState { }; static nsSize ComputeInsideBorderSize(ScrollReflowState* aState, - const nsSize& aDesiredInsideBorderSize) + const nsSize& aDesiredInsideBorderSize, + const nsMargin& aKidPadding) { - // aDesiredInsideBorderSize is the frame size; i.e., it includes - // borders and padding (but the scrolled child doesn't have - // borders). The scrolled child has the same padding as us. - nscoord contentWidth = aState->mReflowState.mComputedWidth; - if (contentWidth == NS_UNCONSTRAINEDSIZE) { - contentWidth = aDesiredInsideBorderSize.width - - aState->mReflowState.mComputedPadding.LeftRight(); + nscoord width = aState->mReflowState.mComputedWidth; + if (width == NS_UNCONSTRAINEDSIZE) { + width = aDesiredInsideBorderSize.width - aKidPadding.left - aKidPadding.right; } - nscoord contentHeight = aState->mReflowState.mComputedHeight; - if (contentHeight == NS_UNCONSTRAINEDSIZE) { - contentHeight = aDesiredInsideBorderSize.height - - aState->mReflowState.mComputedPadding.TopBottom(); + nscoord height = aState->mReflowState.mComputedHeight; + if (height == NS_UNCONSTRAINEDSIZE) { + height = aDesiredInsideBorderSize.height - aKidPadding.top - aKidPadding.bottom; } - - aState->mReflowState.ApplyMinMaxConstraints(&contentWidth, &contentHeight); - return nsSize(contentWidth + aState->mReflowState.mComputedPadding.LeftRight(), - contentHeight + aState->mReflowState.mComputedPadding.TopBottom()); + aState->mReflowState.ApplyMinMaxConstraints(&width, &height); + return nsSize(width + aKidPadding.left + aKidPadding.right, + height + aKidPadding.top + aKidPadding.bottom); } static void @@ -354,6 +348,7 @@ GetScrollbarMetrics(nsBoxLayoutState& aState, nsIBox* aBox, nsSize* aMin, PRBool PRBool nsHTMLScrollFrame::TryLayout(ScrollReflowState* aState, const nsHTMLReflowMetrics& aKidMetrics, + const nsMargin& aKidPadding, PRBool aAssumeVScroll, PRBool aAssumeHScroll, PRBool aForce) { @@ -386,7 +381,7 @@ nsHTMLScrollFrame::TryLayout(ScrollReflowState* aState, desiredInsideBorderSize.height = hScrollbarActualHeight + PR_MAX(aKidMetrics.height, vScrollbarRequiredHeight); aState->mInsideBorderSize = - ComputeInsideBorderSize(aState, desiredInsideBorderSize); + ComputeInsideBorderSize(aState, desiredInsideBorderSize, aKidPadding); nsSize scrollPortSize = nsSize(aState->mInsideBorderSize.width - vScrollbarActualWidth, aState->mInsideBorderSize.height - hScrollbarActualHeight); @@ -416,34 +411,21 @@ nsHTMLScrollFrame::TryLayout(ScrollReflowState* aState, aState->mShowHScrollbar = aAssumeHScroll; aState->mShowVScrollbar = aAssumeVScroll; - nsPoint scrollPortOrigin(aState->mComputedBorder.left, - aState->mComputedBorder.top); + nsPoint scrollPortOrigin(aState->mReflowState.mComputedBorderPadding.left, + aState->mReflowState.mComputedBorderPadding.top); if (!mInner.IsScrollbarOnRight()) { scrollPortOrigin.x += vScrollbarActualWidth; } aState->mScrollPortRect = nsRect(scrollPortOrigin, scrollPortSize); aState->mAscent = aKidMetrics.ascent; if (aKidMetrics.mComputeMEW) { - nscoord kidContentMEW = aKidMetrics.mMaxElementWidth - - aState->mReflowState.mComputedPadding.LeftRight(); - NS_ASSERTION(kidContentMEW >= 0, "MEW didn't include padding?"); - aState->mMaxElementWidth = vScrollbarActualWidth + - aState->mReflowState.mComputedPadding.LeftRight() + - aState->mReflowState.AdjustIntrinsicMinContentWidthForStyle(kidContentMEW); - // borders get added on the way out of Reflow() + aState->mMaxElementWidth = aKidMetrics.mMaxElementWidth + vScrollbarActualWidth; } if (aKidMetrics.mFlags & NS_REFLOW_CALC_MAX_WIDTH) { - nscoord kidMaxWidth = aKidMetrics.mMaximumWidth; - if (kidMaxWidth != NS_UNCONSTRAINEDSIZE) { - nscoord kidContentMaxWidth = kidMaxWidth - - aState->mReflowState.mComputedPadding.LeftRight(); - NS_ASSERTION(kidContentMaxWidth >= 0, "max-width didn't include padding?"); - kidMaxWidth = vScrollbarActualWidth + - aState->mReflowState.mComputedPadding.LeftRight() + - aState->mReflowState.AdjustIntrinsicContentWidthForStyle(kidContentMaxWidth); + aState->mMaximumWidth = aKidMetrics.mMaximumWidth; + if (aState->mMaximumWidth != NS_UNCONSTRAINEDSIZE) { + aState->mMaximumWidth += vScrollbarActualWidth; } - aState->mMaximumWidth = kidMaxWidth; - // borders get added on the way out of Reflow() } return PR_TRUE; } @@ -452,38 +434,24 @@ nsresult nsHTMLScrollFrame::ReflowScrolledFrame(const ScrollReflowState& aState, PRBool aAssumeVScroll, nsHTMLReflowMetrics* aMetrics, + nsMargin* aKidPadding, PRBool aFirstPass) { // these could be NS_UNCONSTRAINEDSIZE ... PR_MIN arithmetic should // be OK - nscoord paddingLR = aState.mReflowState.mComputedPadding.LeftRight(); - - nscoord availWidth = aState.mReflowState.availableWidth; - if (aState.mReflowState.mComputedWidth != NS_UNCONSTRAINEDSIZE) { - availWidth = aState.mReflowState.mComputedWidth + paddingLR; - } else { - if (aState.mReflowState.mComputedMaxWidth != NS_UNCONSTRAINEDSIZE) { - availWidth = PR_MIN(availWidth, - aState.mReflowState.mComputedMaxWidth + paddingLR); - } - if (aState.mReflowState.mComputedWidth != NS_UNCONSTRAINEDSIZE) { - availWidth = PR_MIN(availWidth, - aState.mReflowState.mComputedWidth + paddingLR); - } - } - + nscoord availWidth = PR_MIN(aState.mReflowState.mComputedMaxWidth, + PR_MIN(aState.mReflowState.mComputedWidth, + aState.mReflowState.availableWidth)); if (availWidth != NS_UNCONSTRAINEDSIZE && aAssumeVScroll) { nsSize vScrollbarMinSize; mInner.mVScrollbarBox->GetMinSize(NS_CONST_CAST(nsBoxLayoutState&, aState.mBoxState), vScrollbarMinSize); availWidth = PR_MAX(0, availWidth - vScrollbarMinSize.width); } - nsHTMLReflowState kidReflowState(GetPresContext(), aState.mReflowState, mInner.mScrolledFrame, nsSize(availWidth, NS_UNCONSTRAINEDSIZE), aFirstPass ? aState.mNewReason : eReflowReason_Resize); - if (IsRTLTextControl()) { kidReflowState.mRightEdge = mInner.GetScrolledSize().width; } @@ -494,6 +462,7 @@ nsHTMLScrollFrame::ReflowScrolledFrame(const ScrollReflowState& aState, FinishReflowChild(mInner.mScrolledFrame, GetPresContext(), &kidReflowState, *aMetrics, 0, 0, NS_FRAME_NO_MOVE_FRAME | NS_FRAME_NO_MOVE_VIEW); + *aKidPadding = kidReflowState.mComputedPadding; // XXX Some frames (e.g., nsObjectFrame, nsFrameFrame, nsTextFrame) don't bother // setting their mOverflowArea. This is wrong because every frame should @@ -538,8 +507,9 @@ nsHTMLScrollFrame::ReflowContents(ScrollReflowState* aState, currentlyUsingVScrollbar = PR_FALSE; nsHTMLReflowMetrics kidDesiredSize(aDesiredSize.mComputeMEW, aDesiredSize.mFlags); + nsMargin kidPadding; nsresult rv = ReflowScrolledFrame(*aState, currentlyUsingVScrollbar, - &kidDesiredSize, PR_TRUE); + &kidDesiredSize, &kidPadding, PR_TRUE); if (NS_FAILED(rv)) return rv; PRBool didUseScrollbar = currentlyUsingVScrollbar; @@ -564,14 +534,14 @@ nsHTMLScrollFrame::ReflowContents(ScrollReflowState* aState, aState->mStyles.mVertical != NS_STYLE_OVERFLOW_SCROLL && aState->mStyles.mHorizontal != NS_STYLE_OVERFLOW_SCROLL) { nsSize insideBorderSize = - ComputeInsideBorderSize(aState, - nsSize(kidDesiredSize.width, kidDesiredSize.height)); + ComputeInsideBorderSize(aState, nsSize(kidDesiredSize.width, kidDesiredSize.height), + kidPadding); if (kidDesiredSize.mOverflowArea.XMost() <= insideBorderSize.width && kidDesiredSize.mOverflowArea.YMost() <= insideBorderSize.height) { // Let's pretend we had no vertical scrollbar coming in here currentlyUsingVScrollbar = PR_FALSE; rv = ReflowScrolledFrame(*aState, currentlyUsingVScrollbar, - &kidDesiredSize, PR_FALSE); + &kidDesiredSize, &kidPadding, PR_FALSE); if (NS_FAILED(rv)) return rv; didUseScrollbar = PR_FALSE; @@ -579,9 +549,9 @@ nsHTMLScrollFrame::ReflowContents(ScrollReflowState* aState, } // First try a layout without a horizontal scrollbar, then with. - if (TryLayout(aState, kidDesiredSize, didUseScrollbar, PR_FALSE, PR_FALSE)) + if (TryLayout(aState, kidDesiredSize, kidPadding, didUseScrollbar, PR_FALSE, PR_FALSE)) return NS_OK; - if (TryLayout(aState, kidDesiredSize, didUseScrollbar, PR_TRUE, PR_FALSE)) + if (TryLayout(aState, kidDesiredSize, kidPadding, didUseScrollbar, PR_TRUE, PR_FALSE)) return NS_OK; // That didn't work. Try the other setting for the vertical scrollbar. @@ -589,13 +559,13 @@ nsHTMLScrollFrame::ReflowContents(ScrollReflowState* aState, if (currentlyUsingVScrollbar || canHaveVerticalScrollbar) { nsHTMLReflowMetrics kidRetrySize(aDesiredSize.mComputeMEW, aDesiredSize.mFlags); rv = ReflowScrolledFrame(*aState, !currentlyUsingVScrollbar, - &kidRetrySize, PR_FALSE); + &kidRetrySize, &kidPadding, PR_FALSE); if (NS_FAILED(rv)) return rv; didUseScrollbar = !currentlyUsingVScrollbar; - if (TryLayout(aState, kidRetrySize, didUseScrollbar, PR_FALSE, PR_FALSE)) + if (TryLayout(aState, kidRetrySize, kidPadding, didUseScrollbar, PR_FALSE, PR_FALSE)) return NS_OK; - if (TryLayout(aState, kidRetrySize, didUseScrollbar, PR_TRUE, PR_FALSE)) + if (TryLayout(aState, kidRetrySize, kidPadding, didUseScrollbar, PR_TRUE, PR_FALSE)) return NS_OK; NS_WARNING("Strange content ... we can't find logically consistent scrollbar settings"); @@ -606,11 +576,11 @@ nsHTMLScrollFrame::ReflowContents(ScrollReflowState* aState, // 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, &kidDesiredSize, PR_FALSE); + rv = ReflowScrolledFrame(*aState, PR_FALSE, &kidDesiredSize, &kidPadding, PR_FALSE); if (NS_FAILED(rv)) return rv; } - TryLayout(aState, kidDesiredSize, PR_FALSE, PR_FALSE, PR_TRUE); + TryLayout(aState, kidDesiredSize, kidPadding, PR_FALSE, PR_FALSE, PR_TRUE); return NS_OK; } @@ -723,8 +693,7 @@ nsHTMLScrollFrame::Reflow(nsPresContext* aPresContext, nsRect oldScrollAreaBounds = mInner.mScrollableView->View()->GetBounds(); nsRect oldScrolledAreaBounds = mInner.mScrolledFrame->GetView()->GetBounds(); - state.mComputedBorder = aReflowState.mComputedBorderPadding - - aReflowState.mComputedPadding; + const nsMargin& borderPadding = aReflowState.mComputedBorderPadding; nsresult rv = ReflowContents(&state, aDesiredSize); if (NS_FAILED(rv)) @@ -743,8 +712,9 @@ nsHTMLScrollFrame::Reflow(nsPresContext* aPresContext, // is deleted, because the XMost of the frame's overflow area is always // at least the right edge. But it looks like it has always worked this way. nsHTMLReflowMetrics kidDesiredSize(aDesiredSize.mComputeMEW, aDesiredSize.mFlags); + nsMargin kidPadding; rv = ReflowScrolledFrame(state, state.mShowVScrollbar, - &kidDesiredSize, PR_FALSE); + &kidDesiredSize, &kidPadding, PR_FALSE); if (NS_FAILED(rv)) return rv; } @@ -772,26 +742,25 @@ nsHTMLScrollFrame::Reflow(nsPresContext* aPresContext, mInner.SetScrollbarVisibility(mInner.mVScrollbarBox, state.mShowVScrollbar); // place and reflow scrollbars nsRect insideBorderArea = - nsRect(nsPoint(state.mComputedBorder.left, state.mComputedBorder.top), - state.mInsideBorderSize); + nsRect(nsPoint(borderPadding.left, borderPadding.top), state.mInsideBorderSize); mInner.LayoutScrollbars(state.mBoxState, insideBorderArea, oldScrollAreaBounds, state.mScrollPortRect); } ScrollToRestoredPosition(); aDesiredSize.width = state.mInsideBorderSize.width + - state.mComputedBorder.LeftRight(); + borderPadding.left + borderPadding.right; aDesiredSize.height = state.mInsideBorderSize.height + - state.mComputedBorder.TopBottom(); - aDesiredSize.ascent = state.mAscent + state.mComputedBorder.top; + borderPadding.top + borderPadding.bottom; + aDesiredSize.ascent = state.mAscent + borderPadding.top; if (aDesiredSize.mComputeMEW) { aDesiredSize.mMaxElementWidth = state.mMaxElementWidth + - state.mComputedBorder.LeftRight(); + borderPadding.left + borderPadding.right; } if (aDesiredSize.mFlags & NS_REFLOW_CALC_MAX_WIDTH) { aDesiredSize.mMaximumWidth = state.mMaximumWidth; if (aDesiredSize.mMaximumWidth != NS_UNCONSTRAINEDSIZE) { - aDesiredSize.mMaximumWidth += state.mComputedBorder.LeftRight(); + aDesiredSize.mMaximumWidth += borderPadding.left + borderPadding.right; } } diff --git a/layout/generic/nsGfxScrollFrame.h b/layout/generic/nsGfxScrollFrame.h index eed22d8ec41d..42e6968b0d28 100644 --- a/layout/generic/nsGfxScrollFrame.h +++ b/layout/generic/nsGfxScrollFrame.h @@ -183,11 +183,13 @@ public: PRBool TryLayout(ScrollReflowState* aState, const nsHTMLReflowMetrics& aKidMetrics, + const nsMargin& aKidPadding, PRBool aAssumeVScroll, PRBool aAssumeHScroll, PRBool aForce); nsresult ReflowScrolledFrame(const ScrollReflowState& aState, PRBool aAssumeVScroll, nsHTMLReflowMetrics* aMetrics, + nsMargin* aKidPadding, PRBool aFirstPass); nsresult ReflowContents(ScrollReflowState* aState, const nsHTMLReflowMetrics& aDesiredSize); diff --git a/layout/generic/nsHTMLReflowState.cpp b/layout/generic/nsHTMLReflowState.cpp index e29daea156f8..fe51e129a739 100644 --- a/layout/generic/nsHTMLReflowState.cpp +++ b/layout/generic/nsHTMLReflowState.cpp @@ -379,64 +379,6 @@ nsHTMLReflowState::GetContainingBlockContentWidth(const nsHTMLReflowState* aRefl return rs->mComputedWidth; } -nscoord -nsHTMLReflowState::AdjustIntrinsicMinContentWidthForStyle(nscoord aWidth) const -{ - nsStyleUnit widthUnit = mStylePosition->mWidth.GetUnit(); - if (eStyleUnit_Percent == widthUnit) { - aWidth = 0; - } else if (eStyleUnit_Coord == widthUnit) { - NS_ASSERTION(NS_UNCONSTRAINEDSIZE != mComputedWidth, - "Should be a computed width here"); - aWidth = mComputedWidth; - } - - nsStyleUnit maxWidthUnit = mStylePosition->mMaxWidth.GetUnit(); - if (eStyleUnit_Percent == maxWidthUnit) { - aWidth = 0; - } else if (eStyleUnit_Coord == maxWidthUnit) { - NS_ASSERTION(NS_UNCONSTRAINEDSIZE != mComputedMaxWidth, - "Should be a computed max-width here"); - aWidth = PR_MIN(aWidth, mComputedMaxWidth); - } - - nsStyleUnit minWidthUnit = mStylePosition->mMinWidth.GetUnit(); - if (eStyleUnit_Coord == minWidthUnit) { - NS_ASSERTION(NS_UNCONSTRAINEDSIZE != mComputedMinWidth, - "Should be a computed max-width here"); - aWidth = PR_MAX(aWidth, mComputedMinWidth); - } - - return aWidth; -} - -nscoord -nsHTMLReflowState::AdjustIntrinsicContentWidthForStyle(nscoord aWidth) const -{ - nsStyleUnit widthUnit = mStylePosition->mWidth.GetUnit(); - if (eStyleUnit_Coord == widthUnit) { - NS_ASSERTION(NS_UNCONSTRAINEDSIZE != mComputedWidth, - "Should be a computed width here"); - aWidth = mComputedWidth; - } - - nsStyleUnit maxWidthUnit = mStylePosition->mMaxWidth.GetUnit(); - if (eStyleUnit_Coord == maxWidthUnit) { - NS_ASSERTION(NS_UNCONSTRAINEDSIZE != mComputedMaxWidth, - "Should be a computed max-width here"); - aWidth = PR_MIN(aWidth, mComputedMaxWidth); - } - - nsStyleUnit minWidthUnit = mStylePosition->mMinWidth.GetUnit(); - if (eStyleUnit_Coord == minWidthUnit) { - NS_ASSERTION(NS_UNCONSTRAINEDSIZE != mComputedMinWidth, - "Should be a computed max-width here"); - aWidth = PR_MAX(aWidth, mComputedMinWidth); - } - - return aWidth; -} - /* static */ nsIFrame* nsHTMLReflowState::GetContainingBlockFor(const nsIFrame* aFrame) @@ -1766,7 +1708,11 @@ nsHTMLReflowState::InitConstraints(nsPresContext* aPresContext, mComputedPadding.left = aPadding->left; } else { - ComputePadding(aContainingBlockWidth, cbrs); + if (frame->GetType() == nsLayoutAtoms::scrollFrame) { + mComputedPadding.SizeTo(0, 0, 0, 0); + } else { + ComputePadding(aContainingBlockWidth, cbrs); + } } if (aBorder) { // border is an input arg mComputedBorderPadding = *aBorder;