diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index 947a0559e894..d91684eb48e0 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -992,10 +992,21 @@ PresShell::InitialReflow(nscoord aWidth, nscoord aHeight) nsHTMLReflowState reflowState(*mPresContext, rootFrame, eReflowReason_Initial, rcx, maxSize); + nsIView* view; + rootFrame->WillReflow(*mPresContext); + rootFrame->GetView(mPresContext, &view); + if (view) { + nsContainerFrame::PositionFrameView(mPresContext, rootFrame, view); + } rootFrame->Reflow(*mPresContext, desiredSize, reflowState, status); rootFrame->SizeTo(mPresContext, desiredSize.width, desiredSize.height); mPresContext->SetVisibleArea(nsRect(0,0,desiredSize.width,desiredSize.height)); + if (view) { + nsContainerFrame::SyncFrameViewAfterReflow(mPresContext, rootFrame, view, + nsnull); + } + rootFrame->DidReflow(*mPresContext, NS_FRAME_REFLOW_FINISHED); #ifdef NS_DEBUG if (nsIFrameDebug::GetVerifyTreeEnable()) { @@ -1077,9 +1088,20 @@ PresShell::ResizeReflow(nscoord aWidth, nscoord aHeight) nsHTMLReflowState reflowState(*mPresContext, rootFrame, eReflowReason_Resize, rcx, maxSize); + nsIView* view; + rootFrame->WillReflow(*mPresContext); + rootFrame->GetView(mPresContext, &view); + if (view) { + nsContainerFrame::PositionFrameView(mPresContext, rootFrame, view); + } rootFrame->Reflow(*mPresContext, desiredSize, reflowState, status); rootFrame->SizeTo(mPresContext, desiredSize.width, desiredSize.height); + if (view) { + nsContainerFrame::SyncFrameViewAfterReflow(mPresContext, rootFrame, view, + nsnull); + } + rootFrame->DidReflow(*mPresContext, NS_FRAME_REFLOW_FINISHED); #ifdef NS_DEBUG if (nsIFrameDebug::GetVerifyTreeEnable()) { nsIFrameDebug* frameDebug; @@ -1262,9 +1284,21 @@ PresShell::StyleChangeReflow() // XXX We should be using eReflowReason_StyleChange nsHTMLReflowState reflowState(*mPresContext, rootFrame, eReflowReason_Resize, rcx, maxSize); + nsIView* view; + rootFrame->WillReflow(*mPresContext); + rootFrame->GetView(mPresContext, &view); + if (view) { + nsContainerFrame::PositionFrameView(mPresContext, rootFrame, view); + } rootFrame->Reflow(*mPresContext, desiredSize, reflowState, status); rootFrame->SizeTo(mPresContext, desiredSize.width, desiredSize.height); + mPresContext->SetVisibleArea(nsRect(0,0,desiredSize.width,desiredSize.height)); + if (view) { + nsContainerFrame::SyncFrameViewAfterReflow(mPresContext, rootFrame, view, + nsnull); + } + rootFrame->DidReflow(*mPresContext, NS_FRAME_REFLOW_FINISHED); #ifdef NS_DEBUG if (nsIFrameDebug::GetVerifyTreeEnable()) { nsIFrameDebug* frameDebug; diff --git a/layout/base/public/nsIFrame.h b/layout/base/public/nsIFrame.h index 855abcaf3039..e273b3ae028f 100644 --- a/layout/base/public/nsIFrame.h +++ b/layout/base/public/nsIFrame.h @@ -32,6 +32,23 @@ #include "nsStyleCoord.h" #include "nsHTMLReflowState.h" +/** + * New rules of reflow: + * 1. you get a WillReflow() followed by a Reflow() followed by a DidReflow() in order + * (no separate pass over the tree) + * 2. it's the parent frame's responsibility to size/position the child's view (not + * the child frame's responsibility as it is today) during reflow (and before + * sending the DidReflow() notification) + * 3. positioning of child frames (and their views) is done on the way down the tree, + * and sizing of child frames (and their views) on the way back up + * 4. if you move a frame (outside of the reflow process, or after reflowing it), + * then you must make sure that its view (or its child frame's views) are re-positioned + * as well. It's reasonable to not position the view until after all reflowing the + * entire line, for example, but the frame should still be positioned and sized (and + * the view sized) during the reflow (i.e., before sending the DidReflow() notification) + * 5. the view system handles moving of widgets, i.e., it's not our problem + */ + class nsIAtom; class nsIContent; class nsIPresContext; @@ -545,6 +562,9 @@ public: * Bounding rect of the frame. The values are in twips, and the origin is * relative to the upper-left of the geometric parent. The size includes the * content area, borders, and padding. + * + * Note: moving or sizing the frame does not affect the view's size or + * position. */ NS_IMETHOD GetRect(nsRect& aRect) const = 0; NS_IMETHOD GetOrigin(nsPoint& aPoint) const = 0; diff --git a/layout/forms/nsComboboxControlFrame.cpp b/layout/forms/nsComboboxControlFrame.cpp index fbbca2a812ae..e2ab094b966b 100644 --- a/layout/forms/nsComboboxControlFrame.cpp +++ b/layout/forms/nsComboboxControlFrame.cpp @@ -424,14 +424,13 @@ nsComboboxControlFrame::ReflowComboChildFrame(nsIFrame* aFrame, kidReflowState.mComputedHeight = aAvailableHeight; // Reflow child - nsresult rv = ReflowChild(aFrame, aPresContext, aDesiredSize, kidReflowState, aStatus); - - // Set the child's width and height to it's desired size nsRect rect; aFrame->GetRect(rect); - rect.width = aDesiredSize.width; - rect.height = aDesiredSize.height; - aFrame->SetRect(&aPresContext, rect); + nsresult rv = ReflowChild(aFrame, aPresContext, aDesiredSize, kidReflowState, + rect.x, rect.y, 0, aStatus); + + // Set the child's width and height to it's desired size + FinishReflowChild(aFrame, aPresContext, aDesiredSize, rect.x, rect.y, 0); return rv; } diff --git a/layout/forms/nsFieldSetFrame.cpp b/layout/forms/nsFieldSetFrame.cpp index 80b331de9a57..74747f03dd34 100644 --- a/layout/forms/nsFieldSetFrame.cpp +++ b/layout/forms/nsFieldSetFrame.cpp @@ -318,7 +318,8 @@ nsFieldSetFrame::Reflow(nsIPresContext& aPresContext, legendReflowState.mComputedWidth = NS_INTRINSICSIZE; legendReflowState.mComputedHeight = NS_INTRINSICSIZE; - ReflowChild(mLegendFrame, aPresContext, aDesiredSize, legendReflowState, aStatus); + ReflowChild(mLegendFrame, aPresContext, aDesiredSize, legendReflowState, + 0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus); // get the legend's margin nsIStyleContext* legendSC = nsnull; @@ -354,20 +355,23 @@ nsFieldSetFrame::Reflow(nsIPresContext& aPresContext, if (availSize.width < mLegendRect.width) availSize.width = mLegendRect.width; } - + + // Tell the legend we're done with the reflow. We'll size and place it later on + mLegendFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); } // Try to reflow the area frame into the available space. nsHTMLReflowState contentReflowState(aPresContext, aReflowState, mContentFrame, availSize); - ReflowChild(mContentFrame, aPresContext, aDesiredSize, contentReflowState, aStatus); + ReflowChild(mContentFrame, aPresContext, aDesiredSize, contentReflowState, + borderPadding.left, borderPadding.top + mLegendSpace, 0, aStatus); // set the rect. make sure we add the margin back in. nsRect contentRect(borderPadding.left,borderPadding.top + mLegendSpace,aDesiredSize.width ,aDesiredSize.height); // Place the content area frame. - mContentFrame->SetRect(&aPresContext, contentRect); + FinishReflowChild(mContentFrame, aPresContext, aDesiredSize, contentRect.x, contentRect.y, 0); if (mLegendFrame) { diff --git a/layout/forms/nsHTMLButtonControlFrame.cpp b/layout/forms/nsHTMLButtonControlFrame.cpp index c1b97cc7d9b0..8e8ec5684226 100644 --- a/layout/forms/nsHTMLButtonControlFrame.cpp +++ b/layout/forms/nsHTMLButtonControlFrame.cpp @@ -516,6 +516,9 @@ nsHTMLButtonControlFrame::Reflow(nsIPresContext& aPresContext, // the view also breaks the outline code. For some reason you can not reset // the clip rect to draw outside you bounds if you have a view. And you need to // because the outline must be drawn outside of our bounds according to CSS. -EDV + + // XXX If you do decide you need a view, then create it in the Init() function + // and not here... #if 0 if (!mDidInit) { // create our view, we need a view to grab the mouse @@ -596,11 +599,15 @@ nsHTMLButtonControlFrame::Reflow(nsIPresContext& aPresContext, } } - ReflowChild(firstKid, aPresContext, aDesiredSize, reflowState, aStatus); + ReflowChild(firstKid, aPresContext, aDesiredSize, reflowState, + focusPadding.left + aReflowState.mComputedBorderPadding.left, + focusPadding.top + aReflowState.mComputedBorderPadding.top, + 0, aStatus); // Place the child - nsRect rect = nsRect(focusPadding.left + aReflowState.mComputedBorderPadding.left, focusPadding.top + aReflowState.mComputedBorderPadding.top, aDesiredSize.width, aDesiredSize.height); - firstKid->SetRect(&aPresContext, rect); + FinishReflowChild(firstKid, aPresContext, aDesiredSize, + focusPadding.left + aReflowState.mComputedBorderPadding.left, + focusPadding.top + aReflowState.mComputedBorderPadding.top, 0); #if 0 // old way // if computed use the computed values. diff --git a/layout/forms/nsImageControlFrame.cpp b/layout/forms/nsImageControlFrame.cpp index 914ecec0f81c..e7836ef7a88d 100644 --- a/layout/forms/nsImageControlFrame.cpp +++ b/layout/forms/nsImageControlFrame.cpp @@ -70,6 +70,12 @@ public: NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); + NS_IMETHOD Init(nsIPresContext& aPresContext, + nsIContent* aContent, + nsIFrame* aParent, + nsIStyleContext* aContext, + nsIFrame* aPrevInFlow); + NS_IMETHOD Reflow(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, @@ -202,6 +208,46 @@ nsrefcnt nsImageControlFrame::Release(void) return 1; } +NS_IMETHODIMP +nsImageControlFrame::Init(nsIPresContext& aPresContext, + nsIContent* aContent, + nsIFrame* aParent, + nsIStyleContext* aContext, + nsIFrame* aPrevInFlow) +{ + // call our base class + nsresult rv = nsImageControlFrameSuper::Init(aPresContext, aContent, aParent, + aContext, aPrevInFlow); + + // create our view, we need a view to grab the mouse + nsIView* view; + GetView(&aPresContext, &view); + if (!view) { + nsresult result = nsComponentManager::CreateInstance(kViewCID, nsnull, kIViewIID, (void **)&view); + nsCOMPtr presShell; + aPresContext.GetShell(getter_AddRefs(presShell)); + nsCOMPtr viewMan; + presShell->GetViewManager(getter_AddRefs(viewMan)); + + nsIFrame* parWithView; + nsIView *parView; + GetParentWithView(&aPresContext, &parWithView); + parWithView->GetView(&aPresContext, &parView); + // the view's size is not know yet, but its size will be kept in synch with our frame. + nsRect boundBox(0, 0, 0, 0); + result = view->Init(viewMan, boundBox, parView, nsnull); + view->SetContentTransparency(PR_TRUE); + viewMan->InsertChild(parView, view, 0); + SetView(&aPresContext, view); + + const nsStyleColor* color = (const nsStyleColor*) mStyleContext->GetStyleData(eStyleStruct_Color); + // set the opacity + viewMan->SetViewOpacity(view, color->mOpacity); + } + + return NS_OK; +} + NS_METHOD nsImageControlFrame::Reflow(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, @@ -211,32 +257,6 @@ nsImageControlFrame::Reflow(nsIPresContext& aPresContext, if (!mFormFrame && (eReflowReason_Initial == aReflowState.reason)) { // add ourself as an nsIFormControlFrame nsFormFrame::AddFormControlFrame(aPresContext, *this); - - // create our view, we need a view to grab the mouse - nsIView* view; - GetView(&aPresContext, &view); - if (!view) { - nsresult result = nsComponentManager::CreateInstance(kViewCID, nsnull, kIViewIID, (void **)&view); - nsCOMPtr presShell; - aPresContext.GetShell(getter_AddRefs(presShell)); - nsCOMPtr viewMan; - presShell->GetViewManager(getter_AddRefs(viewMan)); - - nsIFrame* parWithView; - nsIView *parView; - GetParentWithView(&aPresContext, &parWithView); - parWithView->GetView(&aPresContext, &parView); - // the view's size is not know yet, but its size will be kept in synch with our frame. - nsRect boundBox(0, 0, 500, 500); - result = view->Init(viewMan, boundBox, parView, nsnull); - view->SetContentTransparency(PR_TRUE); - viewMan->InsertChild(parView, view, 0); - SetView(&aPresContext, view); - - const nsStyleColor* color = (const nsStyleColor*) mStyleContext->GetStyleData(eStyleStruct_Color); - // set the opacity - viewMan->SetViewOpacity(view, color->mOpacity); - } } return nsImageControlFrameSuper::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); } diff --git a/layout/generic/nsAbsoluteContainingBlock.cpp b/layout/generic/nsAbsoluteContainingBlock.cpp index 95d422450058..b14fe19f6e6d 100644 --- a/layout/generic/nsAbsoluteContainingBlock.cpp +++ b/layout/generic/nsAbsoluteContainingBlock.cpp @@ -260,8 +260,6 @@ nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegat NS_NOTYETIMPLEMENTED("percentage border"); } - aKidFrame->WillReflow(aPresContext); - nsSize availSize(aReflowState.mComputedWidth, NS_UNCONSTRAINEDSIZE); nsHTMLReflowMetrics kidDesiredSize(nsnull); nsHTMLReflowState kidReflowState(aPresContext, aReflowState, aKidFrame, @@ -274,6 +272,19 @@ nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegat kidReflowState.reason = eReflowReason_Initial; } + // XXX TROY + // Send the WillReflow() notification and position the frame + aKidFrame->WillReflow(aPresContext); + aKidFrame->MoveTo(&aPresContext, + border.left + kidReflowState.mComputedOffsets.left + kidReflowState.mComputedMargin.left, + border.top + kidReflowState.mComputedOffsets.top + kidReflowState.mComputedMargin.top); + + // Position its view + nsIView* kidView; + aKidFrame->GetView(&aPresContext, &kidView); + nsContainerFrame::PositionFrameView(&aPresContext, aKidFrame, kidView); + + // Do the reflow rv = aKidFrame->Reflow(aPresContext, kidDesiredSize, kidReflowState, aStatus); // Because we don't know the size of a replaced element until after we reflow @@ -368,6 +379,11 @@ nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegat kidDesiredSize.width, kidDesiredSize.height); aKidFrame->SetRect(&aPresContext, rect); + // Size and position the view and set its opacity, visibility, content + // transparency, and clip + nsContainerFrame::SyncFrameViewAfterReflow(&aPresContext, aKidFrame, kidView, + &kidDesiredSize.mCombinedArea); + aKidFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); return rv; } diff --git a/layout/generic/nsAreaFrame.cpp b/layout/generic/nsAreaFrame.cpp index ce00705f1c0f..4a8d22af98f8 100644 --- a/layout/generic/nsAreaFrame.cpp +++ b/layout/generic/nsAreaFrame.cpp @@ -328,57 +328,6 @@ nsAreaFrame::GetFrameType(nsIAtom** aType) const return NS_OK; } -NS_IMETHODIMP -nsAreaFrame::DidReflow(nsIPresContext& aPresContext, - nsDidReflowStatus aStatus) -{ - if (NS_FRAME_REFLOW_FINISHED == aStatus) { - // If we should position our view, and we have child frames that stick - // outside our box, then we need to size our view large enough to include - // those child frames - if ((mState & NS_FRAME_SYNC_FRAME_AND_VIEW) && - (mState & NS_FRAME_OUTSIDE_CHILDREN)) { - - nsIView* view; - const nsStyleDisplay* display = (const nsStyleDisplay*) - mStyleContext->GetStyleData(eStyleStruct_Display); - - GetView(&aPresContext, &view); - if (view && (NS_STYLE_OVERFLOW_VISIBLE == display->mOverflow)) { - // Don't let our base class position the view since we're doing it - mState &= ~NS_FRAME_SYNC_FRAME_AND_VIEW; - - // Set the view's bit that indicates that it has transparent content - nsIViewManager* vm; - - view->GetViewManager(vm); - vm->SetViewContentTransparency(view, PR_TRUE); - - // Position and size view relative to its parent, not relative to our - // parent frame (our parent frame may not have a view). - nsIView* parentWithView; - nsPoint origin; - - // XXX We need to handle the case where child frames stick out on the - // left and top edges as well... - GetOffsetFromView(&aPresContext, origin, &parentWithView); - vm->ResizeView(view, mCombinedArea.XMost(), mCombinedArea.YMost()); - vm->MoveViewTo(view, origin.x, origin.y); - NS_RELEASE(vm); - - // Call our base class - nsresult rv = nsBlockFrame::DidReflow(aPresContext, aStatus); - - // Set the flag again... - mState |= NS_FRAME_SYNC_FRAME_AND_VIEW; - return rv; - } - } - } - - return nsBlockFrame::DidReflow(aPresContext, aStatus); -} - ///////////////////////////////////////////////////////////////////////////// // Diagnostics diff --git a/layout/generic/nsAreaFrame.h b/layout/generic/nsAreaFrame.h index b5f056abb85c..5cd9ddda2123 100644 --- a/layout/generic/nsAreaFrame.h +++ b/layout/generic/nsAreaFrame.h @@ -82,9 +82,6 @@ public: const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus); - NS_IMETHOD DidReflow(nsIPresContext& aPresContext, - nsDidReflowStatus aStatus); - /** * Get the "type" of the frame * diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index 32bf803e5edb..8c6b7aad71c0 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -2809,6 +2809,20 @@ nsBlockFrame::PullFrame(nsBlockReflowState& aState, return NS_OK; } +static void +PlaceFrameView(nsIPresContext* aPresContext, + nsIFrame* aFrame) +{ + nsIView* view; + aFrame->GetView(aPresContext, &view); + if (view) { + nsContainerFrame::SyncFrameViewAfterReflow(aPresContext, aFrame, view, nsnull); + + } else { + nsContainerFrame::PositionChildViews(aPresContext, aFrame); + } +} + void nsBlockFrame::SlideLine(nsBlockReflowState& aState, nsLineBox* aLine, nscoord aDY) @@ -2830,6 +2844,9 @@ nsBlockFrame::SlideLine(nsBlockReflowState& aState, kid->SetRect(aState.mPresContext, r); } + // Make sure the frame's view and any child views are updated + ::PlaceFrameView(aState.mPresContext, kid); + // If the child has any floaters that impact the space-manager, // place them now so that they are present in the space-manager // again (they were removed by the space-manager's frame when @@ -2851,16 +2868,21 @@ nsBlockFrame::SlideLine(nsBlockReflowState& aState, } } else { - if (aDY) { - // Adjust the Y coordinate of the frames in the line - nsRect r; - PRInt32 n = aLine->GetChildCount(); - while (--n >= 0) { + // Adjust the Y coordinate of the frames in the line. + // Note: we need to re-position views even if aDY is 0, because + // one of our parent frames may have moved and so the view's position + // relative to its parent may have changed + nsRect r; + PRInt32 n = aLine->GetChildCount(); + while (--n >= 0) { + if (aDY) { kid->GetRect(r); r.y += aDY; kid->SetRect(aState.mPresContext, r); - kid->GetNextSibling(&kid); } + // Make sure the frame's view and any child views are updated + ::PlaceFrameView(aState.mPresContext, kid); + kid->GetNextSibling(&kid); } } } @@ -4161,6 +4183,16 @@ nsBlockFrame::PostPlaceLine(nsBlockReflowState& aState, nsLineBox* aLine, const nsSize& aMaxElementSize) { + // If it's inline elements, then make sure the views are correctly + // positioned and sized + if (aLine->IsInline()) { + nsIFrame* frame = aLine->mFirstChild; + for (PRInt32 i = 0; i < aLine->GetChildCount(); i++) { + ::PlaceFrameView(aState.mPresContext, frame); + frame->GetNextSibling(&frame); + } + } + // Update max-element-size if (aState.mComputeMaxElementSize) { aState.UpdateMaxElementSize(aMaxElementSize); @@ -6087,7 +6119,6 @@ nsBlockFrame::ReflowBullet(nsBlockReflowState& aState, nsReflowStatus status; mBullet->WillReflow(*aState.mPresContext); mBullet->Reflow(*aState.mPresContext, aMetrics, reflowState, status); - mBullet->DidReflow(*aState.mPresContext, NS_FRAME_REFLOW_FINISHED); // Place the bullet now; use its right margin to distance it // from the rest of the frames in the line @@ -6098,6 +6129,7 @@ nsBlockFrame::ReflowBullet(nsBlockReflowState& aState, const nsMargin& bp = aState.BorderPadding(); nscoord y = bp.top; mBullet->SetRect(aState.mPresContext, nsRect(x, y, aMetrics.width, aMetrics.height)); + mBullet->DidReflow(*aState.mPresContext, NS_FRAME_REFLOW_FINISHED); } //XXX get rid of this -- its slow diff --git a/layout/generic/nsBlockReflowContext.cpp b/layout/generic/nsBlockReflowContext.cpp index 1b6d61922bd3..ecce17d09d3e 100644 --- a/layout/generic/nsBlockReflowContext.cpp +++ b/layout/generic/nsBlockReflowContext.cpp @@ -226,6 +226,14 @@ nsBlockReflowContext::ReflowBlock(nsIFrame* aFrame, // Let frame know that we are reflowing it aFrame->WillReflow(*mPresContext); + // Position it and its view (if it has one) + aFrame->MoveTo(mPresContext, mX, mY); + nsIView* view; + aFrame->GetView(mPresContext, &view); + if (view) { + nsContainerFrame::PositionFrameView(mPresContext, aFrame, view); + } + #ifdef DEBUG mMetrics.width = nscoord(0xdeadbeef); mMetrics.height = nscoord(0xdeadbeef); @@ -417,7 +425,9 @@ nsBlockReflowContext::PlaceBlock(PRBool aForceFit, // Empty blocks do not have anything special done to them and they // always fit. Note: don't force the width to 0 nsRect r(x, y, mMetrics.width, 0); - mFrame->SetRect(mPresContext, r); + + // Now place the frame and complete the reflow process + nsContainerFrame::FinishReflowChild(mFrame, *mPresContext, mMetrics, x, y, 0); aInFlowBounds = r; // Retain combined area information in case we contain a floater @@ -544,8 +554,8 @@ nsBlockReflowContext::PlaceBlock(PRBool aForceFit, aCombinedRect.width = mMetrics.mCombinedArea.width; aCombinedRect.height = mMetrics.mCombinedArea.height; - // Now place the frame - mFrame->SetRect(mPresContext, nsRect(x, y, mMetrics.width, mMetrics.height)); + // Now place the frame and complete the reflow process + nsContainerFrame::FinishReflowChild(mFrame, *mPresContext, mMetrics, x, y, 0); // XXX obsolete, i believe... #if 0 @@ -591,6 +601,9 @@ nsBlockReflowContext::PlaceBlock(PRBool aForceFit, } } else { + // Send the DidReflow() notification, but don't bother placing + // the frame + mFrame->DidReflow(*mPresContext, NS_FRAME_REFLOW_FINISHED); fits = PR_FALSE; } } diff --git a/layout/generic/nsBlockReflowState.cpp b/layout/generic/nsBlockReflowState.cpp index 32bf803e5edb..8c6b7aad71c0 100644 --- a/layout/generic/nsBlockReflowState.cpp +++ b/layout/generic/nsBlockReflowState.cpp @@ -2809,6 +2809,20 @@ nsBlockFrame::PullFrame(nsBlockReflowState& aState, return NS_OK; } +static void +PlaceFrameView(nsIPresContext* aPresContext, + nsIFrame* aFrame) +{ + nsIView* view; + aFrame->GetView(aPresContext, &view); + if (view) { + nsContainerFrame::SyncFrameViewAfterReflow(aPresContext, aFrame, view, nsnull); + + } else { + nsContainerFrame::PositionChildViews(aPresContext, aFrame); + } +} + void nsBlockFrame::SlideLine(nsBlockReflowState& aState, nsLineBox* aLine, nscoord aDY) @@ -2830,6 +2844,9 @@ nsBlockFrame::SlideLine(nsBlockReflowState& aState, kid->SetRect(aState.mPresContext, r); } + // Make sure the frame's view and any child views are updated + ::PlaceFrameView(aState.mPresContext, kid); + // If the child has any floaters that impact the space-manager, // place them now so that they are present in the space-manager // again (they were removed by the space-manager's frame when @@ -2851,16 +2868,21 @@ nsBlockFrame::SlideLine(nsBlockReflowState& aState, } } else { - if (aDY) { - // Adjust the Y coordinate of the frames in the line - nsRect r; - PRInt32 n = aLine->GetChildCount(); - while (--n >= 0) { + // Adjust the Y coordinate of the frames in the line. + // Note: we need to re-position views even if aDY is 0, because + // one of our parent frames may have moved and so the view's position + // relative to its parent may have changed + nsRect r; + PRInt32 n = aLine->GetChildCount(); + while (--n >= 0) { + if (aDY) { kid->GetRect(r); r.y += aDY; kid->SetRect(aState.mPresContext, r); - kid->GetNextSibling(&kid); } + // Make sure the frame's view and any child views are updated + ::PlaceFrameView(aState.mPresContext, kid); + kid->GetNextSibling(&kid); } } } @@ -4161,6 +4183,16 @@ nsBlockFrame::PostPlaceLine(nsBlockReflowState& aState, nsLineBox* aLine, const nsSize& aMaxElementSize) { + // If it's inline elements, then make sure the views are correctly + // positioned and sized + if (aLine->IsInline()) { + nsIFrame* frame = aLine->mFirstChild; + for (PRInt32 i = 0; i < aLine->GetChildCount(); i++) { + ::PlaceFrameView(aState.mPresContext, frame); + frame->GetNextSibling(&frame); + } + } + // Update max-element-size if (aState.mComputeMaxElementSize) { aState.UpdateMaxElementSize(aMaxElementSize); @@ -6087,7 +6119,6 @@ nsBlockFrame::ReflowBullet(nsBlockReflowState& aState, nsReflowStatus status; mBullet->WillReflow(*aState.mPresContext); mBullet->Reflow(*aState.mPresContext, aMetrics, reflowState, status); - mBullet->DidReflow(*aState.mPresContext, NS_FRAME_REFLOW_FINISHED); // Place the bullet now; use its right margin to distance it // from the rest of the frames in the line @@ -6098,6 +6129,7 @@ nsBlockFrame::ReflowBullet(nsBlockReflowState& aState, const nsMargin& bp = aState.BorderPadding(); nscoord y = bp.top; mBullet->SetRect(aState.mPresContext, nsRect(x, y, aMetrics.width, aMetrics.height)); + mBullet->DidReflow(*aState.mPresContext, NS_FRAME_REFLOW_FINISHED); } //XXX get rid of this -- its slow diff --git a/layout/generic/nsBlockReflowState.h b/layout/generic/nsBlockReflowState.h index 32bf803e5edb..8c6b7aad71c0 100644 --- a/layout/generic/nsBlockReflowState.h +++ b/layout/generic/nsBlockReflowState.h @@ -2809,6 +2809,20 @@ nsBlockFrame::PullFrame(nsBlockReflowState& aState, return NS_OK; } +static void +PlaceFrameView(nsIPresContext* aPresContext, + nsIFrame* aFrame) +{ + nsIView* view; + aFrame->GetView(aPresContext, &view); + if (view) { + nsContainerFrame::SyncFrameViewAfterReflow(aPresContext, aFrame, view, nsnull); + + } else { + nsContainerFrame::PositionChildViews(aPresContext, aFrame); + } +} + void nsBlockFrame::SlideLine(nsBlockReflowState& aState, nsLineBox* aLine, nscoord aDY) @@ -2830,6 +2844,9 @@ nsBlockFrame::SlideLine(nsBlockReflowState& aState, kid->SetRect(aState.mPresContext, r); } + // Make sure the frame's view and any child views are updated + ::PlaceFrameView(aState.mPresContext, kid); + // If the child has any floaters that impact the space-manager, // place them now so that they are present in the space-manager // again (they were removed by the space-manager's frame when @@ -2851,16 +2868,21 @@ nsBlockFrame::SlideLine(nsBlockReflowState& aState, } } else { - if (aDY) { - // Adjust the Y coordinate of the frames in the line - nsRect r; - PRInt32 n = aLine->GetChildCount(); - while (--n >= 0) { + // Adjust the Y coordinate of the frames in the line. + // Note: we need to re-position views even if aDY is 0, because + // one of our parent frames may have moved and so the view's position + // relative to its parent may have changed + nsRect r; + PRInt32 n = aLine->GetChildCount(); + while (--n >= 0) { + if (aDY) { kid->GetRect(r); r.y += aDY; kid->SetRect(aState.mPresContext, r); - kid->GetNextSibling(&kid); } + // Make sure the frame's view and any child views are updated + ::PlaceFrameView(aState.mPresContext, kid); + kid->GetNextSibling(&kid); } } } @@ -4161,6 +4183,16 @@ nsBlockFrame::PostPlaceLine(nsBlockReflowState& aState, nsLineBox* aLine, const nsSize& aMaxElementSize) { + // If it's inline elements, then make sure the views are correctly + // positioned and sized + if (aLine->IsInline()) { + nsIFrame* frame = aLine->mFirstChild; + for (PRInt32 i = 0; i < aLine->GetChildCount(); i++) { + ::PlaceFrameView(aState.mPresContext, frame); + frame->GetNextSibling(&frame); + } + } + // Update max-element-size if (aState.mComputeMaxElementSize) { aState.UpdateMaxElementSize(aMaxElementSize); @@ -6087,7 +6119,6 @@ nsBlockFrame::ReflowBullet(nsBlockReflowState& aState, nsReflowStatus status; mBullet->WillReflow(*aState.mPresContext); mBullet->Reflow(*aState.mPresContext, aMetrics, reflowState, status); - mBullet->DidReflow(*aState.mPresContext, NS_FRAME_REFLOW_FINISHED); // Place the bullet now; use its right margin to distance it // from the rest of the frames in the line @@ -6098,6 +6129,7 @@ nsBlockFrame::ReflowBullet(nsBlockReflowState& aState, const nsMargin& bp = aState.BorderPadding(); nscoord y = bp.top; mBullet->SetRect(aState.mPresContext, nsRect(x, y, aMetrics.width, aMetrics.height)); + mBullet->DidReflow(*aState.mPresContext, NS_FRAME_REFLOW_FINISHED); } //XXX get rid of this -- its slow diff --git a/layout/generic/nsContainerFrame.cpp b/layout/generic/nsContainerFrame.cpp index d6b960d6c95b..a6f3d9fb37e3 100644 --- a/layout/generic/nsContainerFrame.cpp +++ b/layout/generic/nsContainerFrame.cpp @@ -39,6 +39,7 @@ #include "nsIPresShell.h" #include "nsCOMPtr.h" #include "nsLayoutAtoms.h" +#include "nsIViewManager.h" #ifdef NS_DEBUG #undef NOISY @@ -107,6 +108,8 @@ nsContainerFrame::DidReflow(nsIPresContext& aPresContext, // the NS_FRAME_IN_REFLOW bit nsresult result = nsFrame::DidReflow(aPresContext, aStatus); + // XXX TROY +#if 0 if (NS_FRAME_REFLOW_FINISHED == aStatus) { // Apply DidReflow to each and every list that this frame implements nsIAtom* listName = nsnull; @@ -122,6 +125,7 @@ nsContainerFrame::DidReflow(nsIPresContext& aPresContext, GetAdditionalChildListName(listIndex++, &listName); } while(nsnull != listName); } +#endif NS_FRAME_TRACE_OUT("nsContainerFrame::DidReflow"); return result; @@ -372,17 +376,194 @@ nsContainerFrame::ReplaceFrame(nsIPresContext& aPresContext, ///////////////////////////////////////////////////////////////////////////// // Helper member functions +void +nsContainerFrame::PositionFrameView(nsIPresContext* aPresContext, + nsIFrame* aKidFrame, + nsIView* aView) +{ + if (aView) { + // Position view relative to its parent, not relative to aKidFrame's + // frame which may not have a view + nsIView* containingView; + nsPoint origin; + nsIView* parentView; + + aView->GetParent(parentView); + aKidFrame->GetOffsetFromView(aPresContext, origin, &containingView); + + if (containingView == parentView) { + nsIViewManager *vm; + aView->GetViewManager(vm); + vm->MoveViewTo(aView, origin.x, origin.y); + NS_RELEASE(vm); + } + } +} + +void +nsContainerFrame::SyncFrameViewAfterReflow(nsIPresContext* aPresContext, + nsIFrame* aFrame, + nsIView* aView, + nsRect* aCombinedArea, + PRUint32 aFlags) +{ + if (aView) { + nsIViewManager *vm; + nsFrameState kidState; + nsSize frameSize; + + aView->GetViewManager(vm); + aFrame->GetFrameState(&kidState); + aFrame->GetSize(frameSize); + + // Make sure the view is sized and positioned correctly + if (0 == (aFlags & NS_FRAME_NO_MOVE_VIEW)) { + nsIView* containingView; + nsPoint origin; + nsIView* parentView; + + aView->GetParent(parentView); + aFrame->GetOffsetFromView(aPresContext, origin, &containingView); + + if (containingView == parentView) { + vm->MoveViewTo(aView, origin.x, origin.y); + } + } + + if (0 == (aFlags & NS_FRAME_NO_SIZE_VIEW)) { + // If the frame has child frames that stick outside the content + // area, then size the view large enough to include those child + // frames + if ((kidState & NS_FRAME_OUTSIDE_CHILDREN) && aCombinedArea) { + vm->ResizeView(aView, aCombinedArea->XMost(), aCombinedArea->YMost()); + + } else { + vm->ResizeView(aView, frameSize.width, frameSize.height); + } + } + + const nsStyleColor* color; + const nsStyleDisplay* display; + aFrame->GetStyleData(eStyleStruct_Color, (const nsStyleStruct*&)color); + aFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display); + + // Set the view's opacity + vm->SetViewOpacity(aView, color->mOpacity); + + // See if the view should be hidden or visible + PRBool viewIsVisible = PR_TRUE; + PRBool viewHasTransparentContent = (color->mBackgroundFlags & + NS_STYLE_BG_COLOR_TRANSPARENT) == NS_STYLE_BG_COLOR_TRANSPARENT; + + if (NS_STYLE_VISIBILITY_COLLAPSE == display->mVisible) { + viewIsVisible = PR_FALSE; + } + else if (NS_STYLE_VISIBILITY_HIDDEN == display->mVisible) { + // If it has a widget, hide the view because the widget can't deal with it + nsIWidget* widget = nsnull; + aView->GetWidget(widget); + if (widget) { + viewIsVisible = PR_FALSE; + NS_RELEASE(widget); + } + else { + // If it's a scroll frame, then hide the view. This means that + // child elements can't override their parent's visibility, but + // it's not practical to leave it visible in all cases because + // the scrollbars will be showing + nsIAtom* frameType; + aFrame->GetFrameType(&frameType); + + if (frameType == nsLayoutAtoms::scrollFrame) { + viewIsVisible = PR_FALSE; + + } else { + // If we're a container element, then leave the view visible, but + // mark it as having transparent content. The reason we need to + // do this is that child elements can override their parent's + // hidden visibility and be visible anyway + nsIFrame* firstChild; + + aFrame->FirstChild(nsnull, &firstChild); + if (firstChild) { + // Not a left frame, so the view needs to be visible, but marked + // as having transparent content + viewHasTransparentContent = PR_TRUE; + } else { + // Leaf frame so go ahead and hide the view + viewIsVisible = PR_FALSE; + } + } + NS_IF_RELEASE(frameType); + } + } + + // If the frame has visible content that overflows the content area, then we + // need the view marked as having transparent content + if (NS_STYLE_OVERFLOW_VISIBLE == display->mOverflow) { + if (kidState & NS_FRAME_OUTSIDE_CHILDREN) { + viewHasTransparentContent = PR_TRUE; + } + } + + // Make sure visibility is correct + vm->SetViewVisibility(aView, viewIsVisible ? nsViewVisibility_kShow : + nsViewVisibility_kHide); + + // Make sure content transparency is correct + if (viewIsVisible) { + vm->SetViewContentTransparency(aView, viewHasTransparentContent); + } + + // Clip applies to block-level and replaced elements with overflow + // set to other than 'visible' + if (display->IsBlockLevel()) { + if (display->mOverflow == NS_STYLE_OVERFLOW_HIDDEN) { + nscoord left, top, right, bottom; + + // Start with the 'auto' values and then factor in user + // specified values + left = top = 0; + right = frameSize.width; + bottom = frameSize.height; + + if (0 == (NS_STYLE_CLIP_TOP_AUTO & display->mClipFlags)) { + top += display->mClip.top; + } + if (0 == (NS_STYLE_CLIP_RIGHT_AUTO & display->mClipFlags)) { + right -= display->mClip.right; + } + if (0 == (NS_STYLE_CLIP_BOTTOM_AUTO & display->mClipFlags)) { + bottom -= display->mClip.bottom; + } + if (0 == (NS_STYLE_CLIP_LEFT_AUTO & display->mClipFlags)) { + left += display->mClip.left; + } + aView->SetClip(left, top, right, bottom); + + } else { + // Make sure no clip is set + aView->SetClip(0, 0, 0, 0); + } + } + + NS_RELEASE(vm); + } +} + /** - * Queries the child frame for the nsIHTMLReflow interface and if it's - * supported invokes the WillReflow() and Reflow() member functions. If - * the reflow succeeds and the child frame is complete, deletes any - * next-in-flows using DeleteChildsNextInFlow() + * Invokes the WillReflow() function, positions the frame and its view (if + * requested), and then calls Reflow(). If the reflow succeeds and the child + * frame is complete, deletes any next-in-flows using DeleteChildsNextInFlow() */ nsresult nsContainerFrame::ReflowChild(nsIFrame* aKidFrame, nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, + nscoord aX, + nscoord aY, + PRUint32 aFlags, nsReflowStatus& aStatus) { NS_PRECONDITION(aReflowState.frame == aKidFrame, "bad reflow state"); @@ -399,8 +580,23 @@ nsContainerFrame::ReflowChild(nsIFrame* aKidFrame, #endif #endif - // Send the WillReflow notification, and reflow the child frame + // Send the WillReflow() notification, and position the child frame + // and its view if requested aKidFrame->WillReflow(aPresContext); + + if (0 == (aFlags & NS_FRAME_NO_MOVE_FRAME)) { + aKidFrame->MoveTo(&aPresContext, aX, aY); + } + + if (0 == (aFlags & NS_FRAME_NO_MOVE_VIEW)) { + nsIView* view; + aKidFrame->GetView(&aPresContext, &view); + if (view) { + PositionFrameView(&aPresContext, aKidFrame, view); + } + } + + // Reflow the child frame result = aKidFrame->Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); @@ -441,6 +637,97 @@ nsContainerFrame::ReflowChild(nsIFrame* aKidFrame, return result; } +void +nsContainerFrame::PositionChildViews(nsIPresContext* aPresContext, + nsIFrame* aFrame) +{ + nsIAtom* childListName = nsnull; + PRInt32 childListIndex = 0; + + do { + // Recursively walk aFrame's child frames + nsIFrame* childFrame; + aFrame->FirstChild(childListName, &childFrame); + while (childFrame) { + nsIView* view; + + // See if the child frame has a view + childFrame->GetView(aPresContext, &view); + + if (view) { + // Position the view. Because any child views are relative to their + // parent, there's no need to recurse + PositionFrameView(aPresContext, childFrame, view); + + } else { + // Recursively examine its child frames + PositionChildViews(aPresContext, childFrame); + } + + // Get the next sibling child frame + childFrame->GetNextSibling(&childFrame); + } + + NS_IF_RELEASE(childListName); + aFrame->GetAdditionalChildListName(childListIndex++, &childListName); + } while (childListName); +} + +/** + * The second half of frame reflow. Does the following: + * - sets the frame's bounds + * - sizes and positions (if requested) the frame's view. If the frame's final + * position differs from the current position and the frame itself does not + * have a view, then any child frames with views are positioned so they stay + * in sync + * - sets the view's visibility, opacity, content transparency, and clip + * - invoked the DidReflow() function + * + * Flags: + * NS_FRAME_NO_MOVE_FRAME - don't move the frame. aX and aY are ignored in this + * case. Also implies NS_FRAME_NO_MOVE_VIEW + * NS_FRAME_NO_MOVE_VIEW - don't position the frame's view. Set this if you + * don't want to automatically sync the frame and view + * NS_FRAME_NO_SIZE_VIEW - don't size the frame's view + * NS_FRAME_NO_MOVE_CHILD_VIEWS - don't move child views. This is for the case + * where the frame's new position differs from its current position and the + * frame itself doesn't have a view, so moving the frame would cause any child + * views to be out of sync +*/ +nsresult +nsContainerFrame::FinishReflowChild(nsIFrame* aKidFrame, + nsIPresContext& aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + nscoord aX, + nscoord aY, + PRUint32 aFlags) +{ + nsPoint curOrigin; + nsRect bounds(aX, aY, aDesiredSize.width, aDesiredSize.height); + + aKidFrame->GetOrigin(curOrigin); + aKidFrame->SetRect(&aPresContext, bounds); + + nsIView* view; + aKidFrame->GetView(&aPresContext, &view); + if (view) { + // Make sure the frame's view is properly sized and positioned and has + // things like opacity correct + SyncFrameViewAfterReflow(&aPresContext, aKidFrame, view, + &aDesiredSize.mCombinedArea, + aFlags); + + } else if (0 == (aFlags & NS_FRAME_NO_MOVE_CHILD_VIEWS)) { + // If the frame has moved, then we need to make sure any child views are + // correctly positioned + if ((curOrigin.x != aX) || (curOrigin.y != aY)) { + PositionChildViews(&aPresContext, aKidFrame); + } + } + + return aKidFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); +} + /** * Remove and delete aChild's next-in-flow(s). Updates the sibling and flow * pointers diff --git a/layout/generic/nsContainerFrame.h b/layout/generic/nsContainerFrame.h index 5fd59b6c5930..6a0c6f6e0496 100644 --- a/layout/generic/nsContainerFrame.h +++ b/layout/generic/nsContainerFrame.h @@ -25,6 +25,13 @@ #include "nsSplittableFrame.h" #include "nsFrameList.h" +// Option flags for ReflowChild() and FinishReflowChild() +// member functions +#define NS_FRAME_NO_MOVE_VIEW 0x0001 +#define NS_FRAME_NO_MOVE_FRAME (0x0002 | NS_FRAME_NO_MOVE_VIEW) +#define NS_FRAME_NO_SIZE_VIEW 0x0004 +#define NS_FRAME_NO_MOVE_CHILD_VIEWS 0x0008 + /** * Implementation of a container frame. */ @@ -67,6 +74,82 @@ public: return tmp.GetLength(); } + // Positions the frame's view based on the frame's origin + static void PositionFrameView(nsIPresContext* aPresContext, + nsIFrame* aKidFrame, + nsIView* aView); + + // Sets several view attributes: + // - if requested sizes the frame's view based on the current size and origin. + // Takes into account the combined area and (if overflow is visible) whether + // the frame has children that extend outside + // - opacity + // - visibility + // - content transparency + // - clip + // + // Flags: + // NS_FRAME_NO_MOVE_VIEW - don't position the frame's view. Set this if you + // don't want to automatically sync the frame and view + // NS_FRAME_NO_MOVE_VIEW - don't move the frame. aX and aY are ignored in this + // case. Also implies NS_FRAME_NO_MOVE_VIEW + static void SyncFrameViewAfterReflow(nsIPresContext* aPresContext, + nsIFrame* aFrame, + nsIView* aView, + nsRect* aCombinedArea, + PRUint32 aFlags = 0); + + /** + * Invokes the WillReflow() function, positions the frame and its view (if + * requested), and then calls Reflow(). If the reflow succeeds and the child + * frame is complete, deletes any next-in-flows using DeleteChildsNextInFlow() + * + * Flags: + * NS_FRAME_NO_MOVE_VIEW - don't position the frame's view. Set this if you + * don't want to automatically sync the frame and view + * NS_FRAME_NO_MOVE_VIEW - don't move the frame. aX and aY are ignored in this + * case. Also implies NS_FRAME_NO_MOVE_VIEW + */ + nsresult ReflowChild(nsIFrame* aKidFrame, + nsIPresContext& aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nscoord aX, + nscoord aY, + PRUint32 aFlags, + nsReflowStatus& aStatus); + + /** + * The second half of frame reflow. Does the following: + * - sets the frame's bounds + * - sizes and positions (if requested) the frame's view. If the frame's final + * position differs from the current position and the frame itself does not + * have a view, then any child frames with views are positioned so they stay + * in sync + * - sets the view's visibility, opacity, content transparency, and clip + * - invoked the DidReflow() function + * + * Flags: + * NS_FRAME_NO_MOVE_FRAME - don't move the frame. aX and aY are ignored in this + * case. Also implies NS_FRAME_NO_MOVE_VIEW + * NS_FRAME_NO_MOVE_VIEW - don't position the frame's view. Set this if you + * don't want to automatically sync the frame and view + * NS_FRAME_NO_SIZE_VIEW - don't size the frame's view + * NS_FRAME_NO_MOVE_CHILD_VIEWS - don't move child views. This is for the case + * where the frame's new position differs from its current position and the + * frame itself doesn't have a view, so moving the frame would cause any child + * views to be out of sync + */ + static nsresult FinishReflowChild(nsIFrame* aKidFrame, + nsIPresContext& aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + nscoord aX, + nscoord aY, + PRUint32 aFlags); + + static void PositionChildViews(nsIPresContext* aPresContext, + nsIFrame* aFrame); + protected: nsContainerFrame(); ~nsContainerFrame(); @@ -87,18 +170,6 @@ protected: nsIFrame* aFrame, nsFramePaintLayer aWhichLayer); - /** - * Queries the child frame for the nsIHTMLReflow interface and if it's - * supported invokes the WillReflow() and Reflow() member functions. If - * the reflow succeeds and the child frame is complete, deletes any - * next-in-flows using DeleteChildsNextInFlow() - */ - nsresult ReflowChild(nsIFrame* aKidFrame, - nsIPresContext& aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus); - /** * Get the frames on the overflow list */ diff --git a/layout/generic/nsFirstLetterFrame.cpp b/layout/generic/nsFirstLetterFrame.cpp index 90c1a7cb3905..ca02fef22a9f 100644 --- a/layout/generic/nsFirstLetterFrame.cpp +++ b/layout/generic/nsFirstLetterFrame.cpp @@ -247,6 +247,7 @@ nsFirstLetterFrame::Reflow(nsIPresContext& aPresContext, // Place and size the child and update the output metrics kid->MoveTo(&aPresContext, bp.left, bp.top); kid->SizeTo(&aPresContext, aMetrics.width, aMetrics.height); + kid->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); aMetrics.width += lr; aMetrics.height += tb; aMetrics.ascent += bp.top; diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 5ef77927479c..103d35d81e70 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -507,6 +507,8 @@ NS_IMETHODIMP nsFrame::MoveTo(nsIPresContext* aPresContext, nscoord aX, nscoord mRect.x = aX; mRect.y = aY; + // XXX TROY +#if 0 nsIView* view; GetView(aPresContext, &view); if (view) { @@ -526,6 +528,7 @@ NS_IMETHODIMP nsFrame::MoveTo(nsIPresContext* aPresContext, nscoord aX, nscoord NS_RELEASE(vm); } } +#endif return NS_OK; } @@ -535,6 +538,8 @@ NS_IMETHODIMP nsFrame::SizeTo(nsIPresContext* aPresContext, nscoord aWidth, nsco mRect.width = aWidth; mRect.height = aHeight; + // XXX TROY +#if 0 // Let the view know nsIView* view; GetView(aPresContext, &view); @@ -551,6 +556,7 @@ NS_IMETHODIMP nsFrame::SizeTo(nsIPresContext* aPresContext, nscoord aWidth, nsco NS_RELEASE(vm); } } +#endif return NS_OK; } @@ -1266,6 +1272,8 @@ nsFrame::DidReflow(nsIPresContext& aPresContext, if (NS_FRAME_REFLOW_FINISHED == aStatus) { mState &= ~(NS_FRAME_IN_REFLOW | NS_FRAME_FIRST_REFLOW | NS_FRAME_IS_DIRTY); + // XXX TROY +#if 0 // Make sure the view is sized and positioned correctly and it's // visibility, opacity, content transparency, and clip are correct nsIView* view; @@ -1390,6 +1398,7 @@ nsFrame::DidReflow(nsIPresContext& aPresContext, } NS_RELEASE(vm); } +#endif } return NS_OK; } diff --git a/layout/generic/nsFrameFrame.cpp b/layout/generic/nsFrameFrame.cpp index 7f8a070b16ba..7ed495115b34 100644 --- a/layout/generic/nsFrameFrame.cpp +++ b/layout/generic/nsFrameFrame.cpp @@ -360,12 +360,12 @@ nsHTMLFrameOuterFrame::Reflow(nsIPresContext& aPresContext, nsHTMLReflowMetrics kidMetrics(aDesiredSize.maxElementSize); nsHTMLReflowState kidReflowState(aPresContext, aReflowState, firstChild, innerSize); - ReflowChild(firstChild, aPresContext, kidMetrics, kidReflowState, aStatus); + ReflowChild(firstChild, aPresContext, kidMetrics, kidReflowState, + offset.x, offset.y, 0, aStatus); NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status"); // Place and size the child - nsRect rect(offset.x, offset.y, innerSize.width, innerSize.height); - firstChild->SetRect(&aPresContext, rect); + FinishReflowChild(firstChild, aPresContext, kidMetrics, offset.x, offset.y, 0); // XXX what should the max-element-size of an iframe be? Shouldn't // iframe's normally shrink wrap around their content when they diff --git a/layout/generic/nsFrameSetFrame.cpp b/layout/generic/nsFrameSetFrame.cpp index 380bad672c0d..81a64d3b0026 100644 --- a/layout/generic/nsFrameSetFrame.cpp +++ b/layout/generic/nsFrameSetFrame.cpp @@ -234,6 +234,9 @@ nsresult nsHTMLFramesetFrame::QueryInterface(const nsIID& aIID, return nsHTMLContainerFrame::QueryInterface(aIID, aInstancePtr); } +static NS_DEFINE_IID(kViewCID, NS_VIEW_CID); +static NS_DEFINE_IID(kIViewIID, NS_IVIEW_IID); + NS_IMETHODIMP nsHTMLFramesetFrame::Init(nsIPresContext& aPresContext, nsIContent* aContent, @@ -258,6 +261,25 @@ nsHTMLFramesetFrame::Init(nsIPresContext& aPresContext, break; } } + + // create the view. a view is needed since it needs to be a mouse grabber + nsIView* view; + nsresult result = nsComponentManager::CreateInstance(kViewCID, nsnull, kIViewIID, + (void **)&view); + nsCOMPtr presShell; + aPresContext.GetShell(getter_AddRefs(presShell)); + nsCOMPtr viewMan; + presShell->GetViewManager(getter_AddRefs(viewMan)); + + nsIFrame* parWithView; + nsIView *parView; + GetParentWithView(&aPresContext, &parWithView); + parWithView->GetView(&aPresContext, &parView); + nsRect boundBox(0, 0, 0, 0); + result = view->Init(viewMan, boundBox, parView, nsnull); + viewMan->InsertChild(parView, view, 0); + SetView(&aPresContext, view); + return rv; } @@ -785,13 +807,14 @@ nsHTMLFramesetFrame::ReflowPlaceChild(nsIFrame* aChild, metrics.height= aSize.height; nsReflowStatus status; - ReflowChild(aChild, aPresContext, metrics, reflowState, status); + ReflowChild(aChild, aPresContext, metrics, reflowState, aOffset.x, + aOffset.y, 0, status); NS_ASSERTION(NS_FRAME_IS_COMPLETE(status), "bad status"); // Place and size the child - nsRect rect(aOffset.x, aOffset.y, aSize.width, aSize.height); - aChild->SetRect(&aPresContext, rect); - aChild->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); // this call is needed + metrics.width = aSize.width; + metrics.height = aSize.height; + FinishReflowChild(aChild, aPresContext, metrics, aOffset.x, aOffset.y, 0); } static @@ -902,10 +925,6 @@ nscolor nsHTMLFramesetFrame::GetBorderColor(nsIContent* aContent) #define FRAME 1 #define BLANK 2 - -static NS_DEFINE_IID(kViewCID, NS_VIEW_CID); -static NS_DEFINE_IID(kIViewIID, NS_IVIEW_IID); - NS_IMETHODIMP nsHTMLFramesetFrame::Reflow(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, @@ -918,25 +937,6 @@ nsHTMLFramesetFrame::Reflow(nsIPresContext& aPresContext, PRBool firstTime = (0 == mNumRows); if (firstTime) { - // create the view. a view is needed since it needs to be a mouse grabber - - nsIView* view; - nsresult result = nsComponentManager::CreateInstance(kViewCID, nsnull, kIViewIID, - (void **)&view); - nsCOMPtr presShell; - aPresContext.GetShell(getter_AddRefs(presShell)); - nsCOMPtr viewMan; - presShell->GetViewManager(getter_AddRefs(viewMan)); - - nsIFrame* parWithView; - nsIView *parView; - GetParentWithView(&aPresContext, &parWithView); - parWithView->GetView(&aPresContext, &parView); - nsRect boundBox(0, 0, aDesiredSize.width, aDesiredSize.height); - result = view->Init(viewMan, boundBox, parView, nsnull); - viewMan->InsertChild(parView, view, 0); - SetView(&aPresContext, view); - // parse the rows= cols= data ParseRowCol(nsHTMLAtoms::rows, mNumRows, &mRowSpecs); ParseRowCol(nsHTMLAtoms::cols, mNumCols, &mColSpecs); diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index 63526f3bfeb0..014afe7a23ad 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -1206,7 +1206,8 @@ nsGfxScrollFrameInner::ReflowFrame( nsIPresContext& aPresContext, childReflowState.mComputedHeight -= childReflowState.mComputedBorderPadding.top + childReflowState.mComputedBorderPadding.bottom; */ - mOuter->ReflowChild(aFrame, aPresContext, aDesiredSize, childReflowState, aStatus); + mOuter->ReflowChild(aFrame, aPresContext, aDesiredSize, childReflowState, + 0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus); NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status"); // if the frame size change then mark the flag @@ -1214,6 +1215,7 @@ nsGfxScrollFrameInner::ReflowFrame( nsIPresContext& aPresContext, aFrame->SizeTo(&aPresContext, aDesiredSize.width, aDesiredSize.height); aResized = PR_TRUE; } + aFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); // add the margin back in aDesiredSize.width += margin.left + margin.right; @@ -1467,13 +1469,29 @@ nsGfxScrollFrameInner::LayoutChildren(nsIPresContext& aPresContext, const nsMargin& border = aReflowState.mComputedBorderPadding; // Place scroll area + nsIView* view; mScrollAreaFrame->MoveTo(&aPresContext, border.left, border.top); + mScrollAreaFrame->GetView(&aPresContext, &view); + if (view) { + nsContainerFrame::SyncFrameViewAfterReflow(&aPresContext, mScrollAreaFrame, + view, nsnull); + } // place vertical scrollbar mVScrollbarFrame->MoveTo(&aPresContext, border.left + scrollAreaSize.width, border.top); + mVScrollbarFrame->GetView(&aPresContext, &view); + if (view) { + nsContainerFrame::SyncFrameViewAfterReflow(&aPresContext, mVScrollbarFrame, + view, nsnull); + } // place horizontal scrollbar mHScrollbarFrame->MoveTo(&aPresContext, border.left, border.top + scrollAreaSize.height); + mHScrollbarFrame->GetView(&aPresContext, &view); + if (view) { + nsContainerFrame::SyncFrameViewAfterReflow(&aPresContext, mHScrollbarFrame, + view, nsnull); + } // Compute our desired size // ---------- compute width ----------- diff --git a/layout/generic/nsHTMLFrame.cpp b/layout/generic/nsHTMLFrame.cpp index 37b1fcda0268..a467ef29ae3f 100644 --- a/layout/generic/nsHTMLFrame.cpp +++ b/layout/generic/nsHTMLFrame.cpp @@ -324,7 +324,8 @@ RootFrame::Reflow(nsIPresContext& aPresContext, // Reflow the frame ReflowChild(kidFrame, aPresContext, kidDesiredSize, kidReflowState, - aStatus); + kidReflowState.mComputedMargin.left, kidReflowState.mComputedMargin.top, + 0, aStatus); // The document element's background should cover the entire canvas, so // take into account the combined area and any space taken up by @@ -385,10 +386,10 @@ RootFrame::Reflow(nsIPresContext& aPresContext, } } - // Position and size the child frame + // Complete the reflow and position and size the child frame nsRect rect(kidReflowState.mComputedMargin.left, kidReflowState.mComputedMargin.top, kidDesiredSize.width, kidDesiredSize.height); - kidFrame->SetRect(&aPresContext, rect); + FinishReflowChild(kidFrame, aPresContext, kidDesiredSize, rect.x, rect.y, 0); // If the child frame was just inserted, then we're responsible for making sure // it repaints diff --git a/layout/generic/nsHTMLReflowCommand.cpp b/layout/generic/nsHTMLReflowCommand.cpp index 813fb5d67682..a116b70ce07b 100644 --- a/layout/generic/nsHTMLReflowCommand.cpp +++ b/layout/generic/nsHTMLReflowCommand.cpp @@ -30,6 +30,7 @@ #include "nsStyleConsts.h" #include "nsHTMLIIDs.h" #include "nsFrame.h" +#include "nsContainerFrame.h" static NS_DEFINE_IID(kIReflowCommandIID, NS_IREFLOWCOMMAND_IID); @@ -133,8 +134,20 @@ NS_IMETHODIMP nsHTMLReflowCommand::Dispatch(nsIPresContext& aPresContext, nsHTMLReflowState reflowState(aPresContext, root, *this, &aRendContext, aMaxSize); nsReflowStatus status; + nsIView* view; + root->WillReflow(aPresContext); + root->GetView(&aPresContext, &view); + if (view) { + nsContainerFrame::PositionFrameView(&aPresContext, root, view); + } root->Reflow(aPresContext, aDesiredSize, reflowState, status); + root->SizeTo(&aPresContext, aDesiredSize.width, aDesiredSize.height); + if (view) { + nsContainerFrame::SyncFrameViewAfterReflow(&aPresContext, root, view, + nsnull); + } + root->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); } return NS_OK; diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index 855abcaf3039..e273b3ae028f 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -32,6 +32,23 @@ #include "nsStyleCoord.h" #include "nsHTMLReflowState.h" +/** + * New rules of reflow: + * 1. you get a WillReflow() followed by a Reflow() followed by a DidReflow() in order + * (no separate pass over the tree) + * 2. it's the parent frame's responsibility to size/position the child's view (not + * the child frame's responsibility as it is today) during reflow (and before + * sending the DidReflow() notification) + * 3. positioning of child frames (and their views) is done on the way down the tree, + * and sizing of child frames (and their views) on the way back up + * 4. if you move a frame (outside of the reflow process, or after reflowing it), + * then you must make sure that its view (or its child frame's views) are re-positioned + * as well. It's reasonable to not position the view until after all reflowing the + * entire line, for example, but the frame should still be positioned and sized (and + * the view sized) during the reflow (i.e., before sending the DidReflow() notification) + * 5. the view system handles moving of widgets, i.e., it's not our problem + */ + class nsIAtom; class nsIContent; class nsIPresContext; @@ -545,6 +562,9 @@ public: * Bounding rect of the frame. The values are in twips, and the origin is * relative to the upper-left of the geometric parent. The size includes the * content area, borders, and padding. + * + * Note: moving or sizing the frame does not affect the view's size or + * position. */ NS_IMETHOD GetRect(nsRect& aRect) const = 0; NS_IMETHOD GetOrigin(nsPoint& aPoint) const = 0; diff --git a/layout/generic/nsLineLayout.cpp b/layout/generic/nsLineLayout.cpp index cfa5498d4524..5e41b2153976 100644 --- a/layout/generic/nsLineLayout.cpp +++ b/layout/generic/nsLineLayout.cpp @@ -35,6 +35,8 @@ #include "nsIDocument.h" #include "nsIHTMLDocument.h" #include "nsIContent.h" +#include "nsIView.h" +#include "nsIViewManager.h" #ifdef DEBUG #undef NOISY_HORIZONTAL_ALIGN @@ -918,7 +920,9 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame, // new starting x,y coordinates for the frame. ApplyLeftMargin(pfd, reflowState); - // Let frame know that are reflowing it + // Let frame know that are reflowing it. Note that we don't bother + // positioning the frame yet, because we're probably going to end up + // moving it when we do the vertical alignment nscoord x = pfd->mBounds.x; nscoord y = pfd->mBounds.y; @@ -1072,14 +1076,21 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame, pfd->mMaxElementSize = *metrics.maxElementSize; } - // Now that frame has been reflowed at least one time make sure that - // the NS_FRAME_FIRST_REFLOW bit is cleared so that never give it an - // initial reflow reason again. - if (eReflowReason_Initial == reason) { - aFrame->GetFrameState(&state); - aFrame->SetFrameState(state & ~NS_FRAME_FIRST_REFLOW); + // Size the frame and size its view (if it has one) + aFrame->SizeTo(&mPresContext, metrics.width, metrics.height); + nsIView* view; + aFrame->GetView(&mPresContext, &view); + if (view) { + nsIViewManager *vm; + + view->GetViewManager(vm); + vm->ResizeView(view, metrics.width, metrics.height); + NS_RELEASE(vm); } + // Tell the frame that we're done reflowing it + aFrame->DidReflow(mPresContext, NS_FRAME_REFLOW_FINISHED); + if (aMetrics) { *aMetrics = metrics; } diff --git a/layout/generic/nsObjectFrame.cpp b/layout/generic/nsObjectFrame.cpp index fb750b9a9df1..3d5951047126 100644 --- a/layout/generic/nsObjectFrame.cpp +++ b/layout/generic/nsObjectFrame.cpp @@ -1037,10 +1037,8 @@ nsObjectFrame::HandleImage(nsIPresContext& aPresContext, } } - ReflowChild(child, aPresContext, kidDesiredSize, kidReflowState, status); - - nsRect rect(0, 0, kidDesiredSize.width, kidDesiredSize.height); - child->SetRect(&aPresContext, rect); + ReflowChild(child, aPresContext, kidDesiredSize, kidReflowState, 0, 0, 0, status); + FinishReflowChild(child, aPresContext, kidDesiredSize, 0, 0, 0); aMetrics.width = kidDesiredSize.width; aMetrics.height = kidDesiredSize.height; diff --git a/layout/generic/nsPageFrame.cpp b/layout/generic/nsPageFrame.cpp index 0dbe8bd9cd0b..cb2094b21a96 100644 --- a/layout/generic/nsPageFrame.cpp +++ b/layout/generic/nsPageFrame.cpp @@ -80,7 +80,7 @@ NS_METHOD nsPageFrame::Reflow(nsIPresContext& aPresContext, kidReflowState.isTopOfPage = PR_TRUE; ReflowChild(mFrames.FirstChild(), aPresContext, aDesiredSize, - kidReflowState, aStatus); + kidReflowState, 0, 0, 0, aStatus); // Place and size the child. Make sure the child is at least as // tall as our max size (the containing window) @@ -88,8 +88,8 @@ NS_METHOD nsPageFrame::Reflow(nsIPresContext& aPresContext, aDesiredSize.height = aReflowState.availableHeight; } - nsRect rect(0, 0, aDesiredSize.width, aDesiredSize.height); - mFrames.FirstChild()->SetRect(&aPresContext, rect); + FinishReflowChild(mFrames.FirstChild(), aPresContext, aDesiredSize, + 0, 0, 0); } else { // Do we have any children? @@ -122,7 +122,7 @@ NS_METHOD nsPageFrame::Reflow(nsIPresContext& aPresContext, kidReflowState.isTopOfPage = PR_TRUE; // Get the child's desired size - ReflowChild(frame, aPresContext, aDesiredSize, kidReflowState, aStatus); + ReflowChild(frame, aPresContext, aDesiredSize, kidReflowState, 0, 0, 0, aStatus); // Make sure the child is at least as tall as our max size (the containing window) if (aDesiredSize.height < aReflowState.availableHeight) { @@ -130,10 +130,7 @@ NS_METHOD nsPageFrame::Reflow(nsIPresContext& aPresContext, } // Place and size the child - nsRect rect(0, 0, aDesiredSize.width, aDesiredSize.height); - frame->SetRect(&aPresContext, rect); - // XXX Should we be sending the DidReflow? - frame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); + FinishReflowChild(frame, aPresContext, aDesiredSize, 0, 0, 0); // Is the frame complete? if (NS_FRAME_IS_COMPLETE(aStatus)) { diff --git a/layout/generic/nsSimplePageSequence.cpp b/layout/generic/nsSimplePageSequence.cpp index 98105d24fa18..50b7271c9be6 100644 --- a/layout/generic/nsSimplePageSequence.cpp +++ b/layout/generic/nsSimplePageSequence.cpp @@ -126,12 +126,11 @@ nsSimplePageSequenceFrame::IncrementalReflow(nsIPresContext& aPresConte // Dispatch the reflow command to our child frame. Allow it to be as high // as it wants - ReflowChild(nextFrame, aPresContext, kidSize, kidReflowState, status); + ReflowChild(nextFrame, aPresContext, kidSize, kidReflowState, aX, aY, 0, status); // Place and size the page. If the page is narrower than our max width, then // center it horizontally - nsRect rect(aX, aY, kidSize.width, kidSize.height); - nextFrame->SetRect(&aPresContext, rect); + FinishReflowChild(nextFrame, aPresContext, kidSize, aX, aY, 0); aY += kidSize.height + PAGE_SPACING_TWIPS; // Check if the page is complete... @@ -169,8 +168,9 @@ nsSimplePageSequenceFrame::IncrementalReflow(nsIPresContext& aPresConte // Place and size the page. If the page is narrower than our // max width then center it horizontally ReflowChild(kidFrame, aPresContext, childSize, childReflowState, - status); - kidFrame->SetRect(&aPresContext, nsRect(aX, aY, childSize.width, childSize.height)); + aX, aY, 0, status); + + FinishReflowChild(kidFrame, aPresContext, childSize, aX, aY, 0); aY += childSize.height; // Leave a slight gap between the pages @@ -242,8 +242,9 @@ nsSimplePageSequenceFrame::Reflow(nsIPresContext& aPresContext, // Place and size the page. If the page is narrower than our // max width then center it horizontally - ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, status); - kidFrame->SetRect(&aPresContext, nsRect(x, y, kidSize.width, kidSize.height)); + ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, x, y, 0, status); + + FinishReflowChild(kidFrame, aPresContext, kidSize, x, y, 0); y += kidSize.height; // Leave a slight gap between the pages diff --git a/layout/generic/nsViewportFrame.cpp b/layout/generic/nsViewportFrame.cpp index d86ea68eebac..f5aafad0c6af 100644 --- a/layout/generic/nsViewportFrame.cpp +++ b/layout/generic/nsViewportFrame.cpp @@ -332,8 +332,6 @@ ViewportFrame::ReflowFixedFrame(nsIPresContext& aPresContext, // Reflow the frame nsresult rv; - aKidFrame->WillReflow(aPresContext); - nsHTMLReflowMetrics kidDesiredSize(nsnull); nsSize availSize(aReflowState.availableWidth, NS_UNCONSTRAINEDSIZE); nsHTMLReflowState kidReflowState(aPresContext, aReflowState, aKidFrame, @@ -345,6 +343,18 @@ ViewportFrame::ReflowFixedFrame(nsIPresContext& aPresContext, kidReflowState.reason = eReflowReason_Initial; } + // Send the WillReflow() notification and position the frame + aKidFrame->WillReflow(aPresContext); + aKidFrame->MoveTo(&aPresContext, + kidReflowState.mComputedOffsets.left + kidReflowState.mComputedMargin.left, + kidReflowState.mComputedOffsets.top + kidReflowState.mComputedMargin.top); + + // Position its view + nsIView* kidView; + aKidFrame->GetView(&aPresContext, &kidView); + nsContainerFrame::PositionFrameView(&aPresContext, aKidFrame, kidView); + + // Do the reflow rv = aKidFrame->Reflow(aPresContext, kidDesiredSize, kidReflowState, aStatus); // XXX If the child had a fixed height, then make sure it respected it... @@ -361,8 +371,12 @@ ViewportFrame::ReflowFixedFrame(nsIPresContext& aPresContext, kidReflowState.mComputedOffsets.top + kidReflowState.mComputedMargin.top, kidDesiredSize.width, kidDesiredSize.height); aKidFrame->SetRect(&aPresContext, rect); - aKidFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); + // Size and position the view and set its opacity, visibility, content + // transparency, and clip + nsContainerFrame::SyncFrameViewAfterReflow(&aPresContext, aKidFrame, kidView, + &kidDesiredSize.mCombinedArea); + aKidFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); return rv; } @@ -509,15 +523,9 @@ ViewportFrame::Reflow(nsIPresContext& aPresContext, // Reflow the frame kidReflowState.mComputedHeight = aReflowState.availableHeight; ReflowChild(kidFrame, aPresContext, kidDesiredSize, kidReflowState, - aStatus); + 0, 0, 0, aStatus); - nsRect rect(0, 0, kidDesiredSize.width, kidDesiredSize.height); - kidFrame->SetRect(&aPresContext, rect); - kidRect = rect; - - // XXX We should resolve the details of who/when DidReflow() - // notifications are sent... - kidFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); + FinishReflowChild(kidFrame, aPresContext, kidDesiredSize, 0, 0, 0); } // If it's a 'initial', 'resize', or 'style change' reflow command (anything diff --git a/layout/html/base/src/nsAbsoluteContainingBlock.cpp b/layout/html/base/src/nsAbsoluteContainingBlock.cpp index 95d422450058..b14fe19f6e6d 100644 --- a/layout/html/base/src/nsAbsoluteContainingBlock.cpp +++ b/layout/html/base/src/nsAbsoluteContainingBlock.cpp @@ -260,8 +260,6 @@ nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegat NS_NOTYETIMPLEMENTED("percentage border"); } - aKidFrame->WillReflow(aPresContext); - nsSize availSize(aReflowState.mComputedWidth, NS_UNCONSTRAINEDSIZE); nsHTMLReflowMetrics kidDesiredSize(nsnull); nsHTMLReflowState kidReflowState(aPresContext, aReflowState, aKidFrame, @@ -274,6 +272,19 @@ nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegat kidReflowState.reason = eReflowReason_Initial; } + // XXX TROY + // Send the WillReflow() notification and position the frame + aKidFrame->WillReflow(aPresContext); + aKidFrame->MoveTo(&aPresContext, + border.left + kidReflowState.mComputedOffsets.left + kidReflowState.mComputedMargin.left, + border.top + kidReflowState.mComputedOffsets.top + kidReflowState.mComputedMargin.top); + + // Position its view + nsIView* kidView; + aKidFrame->GetView(&aPresContext, &kidView); + nsContainerFrame::PositionFrameView(&aPresContext, aKidFrame, kidView); + + // Do the reflow rv = aKidFrame->Reflow(aPresContext, kidDesiredSize, kidReflowState, aStatus); // Because we don't know the size of a replaced element until after we reflow @@ -368,6 +379,11 @@ nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegat kidDesiredSize.width, kidDesiredSize.height); aKidFrame->SetRect(&aPresContext, rect); + // Size and position the view and set its opacity, visibility, content + // transparency, and clip + nsContainerFrame::SyncFrameViewAfterReflow(&aPresContext, aKidFrame, kidView, + &kidDesiredSize.mCombinedArea); + aKidFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); return rv; } diff --git a/layout/html/base/src/nsAreaFrame.cpp b/layout/html/base/src/nsAreaFrame.cpp index ce00705f1c0f..4a8d22af98f8 100644 --- a/layout/html/base/src/nsAreaFrame.cpp +++ b/layout/html/base/src/nsAreaFrame.cpp @@ -328,57 +328,6 @@ nsAreaFrame::GetFrameType(nsIAtom** aType) const return NS_OK; } -NS_IMETHODIMP -nsAreaFrame::DidReflow(nsIPresContext& aPresContext, - nsDidReflowStatus aStatus) -{ - if (NS_FRAME_REFLOW_FINISHED == aStatus) { - // If we should position our view, and we have child frames that stick - // outside our box, then we need to size our view large enough to include - // those child frames - if ((mState & NS_FRAME_SYNC_FRAME_AND_VIEW) && - (mState & NS_FRAME_OUTSIDE_CHILDREN)) { - - nsIView* view; - const nsStyleDisplay* display = (const nsStyleDisplay*) - mStyleContext->GetStyleData(eStyleStruct_Display); - - GetView(&aPresContext, &view); - if (view && (NS_STYLE_OVERFLOW_VISIBLE == display->mOverflow)) { - // Don't let our base class position the view since we're doing it - mState &= ~NS_FRAME_SYNC_FRAME_AND_VIEW; - - // Set the view's bit that indicates that it has transparent content - nsIViewManager* vm; - - view->GetViewManager(vm); - vm->SetViewContentTransparency(view, PR_TRUE); - - // Position and size view relative to its parent, not relative to our - // parent frame (our parent frame may not have a view). - nsIView* parentWithView; - nsPoint origin; - - // XXX We need to handle the case where child frames stick out on the - // left and top edges as well... - GetOffsetFromView(&aPresContext, origin, &parentWithView); - vm->ResizeView(view, mCombinedArea.XMost(), mCombinedArea.YMost()); - vm->MoveViewTo(view, origin.x, origin.y); - NS_RELEASE(vm); - - // Call our base class - nsresult rv = nsBlockFrame::DidReflow(aPresContext, aStatus); - - // Set the flag again... - mState |= NS_FRAME_SYNC_FRAME_AND_VIEW; - return rv; - } - } - } - - return nsBlockFrame::DidReflow(aPresContext, aStatus); -} - ///////////////////////////////////////////////////////////////////////////// // Diagnostics diff --git a/layout/html/base/src/nsAreaFrame.h b/layout/html/base/src/nsAreaFrame.h index b5f056abb85c..5cd9ddda2123 100644 --- a/layout/html/base/src/nsAreaFrame.h +++ b/layout/html/base/src/nsAreaFrame.h @@ -82,9 +82,6 @@ public: const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus); - NS_IMETHOD DidReflow(nsIPresContext& aPresContext, - nsDidReflowStatus aStatus); - /** * Get the "type" of the frame * diff --git a/layout/html/base/src/nsBlockFrame.cpp b/layout/html/base/src/nsBlockFrame.cpp index 32bf803e5edb..8c6b7aad71c0 100644 --- a/layout/html/base/src/nsBlockFrame.cpp +++ b/layout/html/base/src/nsBlockFrame.cpp @@ -2809,6 +2809,20 @@ nsBlockFrame::PullFrame(nsBlockReflowState& aState, return NS_OK; } +static void +PlaceFrameView(nsIPresContext* aPresContext, + nsIFrame* aFrame) +{ + nsIView* view; + aFrame->GetView(aPresContext, &view); + if (view) { + nsContainerFrame::SyncFrameViewAfterReflow(aPresContext, aFrame, view, nsnull); + + } else { + nsContainerFrame::PositionChildViews(aPresContext, aFrame); + } +} + void nsBlockFrame::SlideLine(nsBlockReflowState& aState, nsLineBox* aLine, nscoord aDY) @@ -2830,6 +2844,9 @@ nsBlockFrame::SlideLine(nsBlockReflowState& aState, kid->SetRect(aState.mPresContext, r); } + // Make sure the frame's view and any child views are updated + ::PlaceFrameView(aState.mPresContext, kid); + // If the child has any floaters that impact the space-manager, // place them now so that they are present in the space-manager // again (they were removed by the space-manager's frame when @@ -2851,16 +2868,21 @@ nsBlockFrame::SlideLine(nsBlockReflowState& aState, } } else { - if (aDY) { - // Adjust the Y coordinate of the frames in the line - nsRect r; - PRInt32 n = aLine->GetChildCount(); - while (--n >= 0) { + // Adjust the Y coordinate of the frames in the line. + // Note: we need to re-position views even if aDY is 0, because + // one of our parent frames may have moved and so the view's position + // relative to its parent may have changed + nsRect r; + PRInt32 n = aLine->GetChildCount(); + while (--n >= 0) { + if (aDY) { kid->GetRect(r); r.y += aDY; kid->SetRect(aState.mPresContext, r); - kid->GetNextSibling(&kid); } + // Make sure the frame's view and any child views are updated + ::PlaceFrameView(aState.mPresContext, kid); + kid->GetNextSibling(&kid); } } } @@ -4161,6 +4183,16 @@ nsBlockFrame::PostPlaceLine(nsBlockReflowState& aState, nsLineBox* aLine, const nsSize& aMaxElementSize) { + // If it's inline elements, then make sure the views are correctly + // positioned and sized + if (aLine->IsInline()) { + nsIFrame* frame = aLine->mFirstChild; + for (PRInt32 i = 0; i < aLine->GetChildCount(); i++) { + ::PlaceFrameView(aState.mPresContext, frame); + frame->GetNextSibling(&frame); + } + } + // Update max-element-size if (aState.mComputeMaxElementSize) { aState.UpdateMaxElementSize(aMaxElementSize); @@ -6087,7 +6119,6 @@ nsBlockFrame::ReflowBullet(nsBlockReflowState& aState, nsReflowStatus status; mBullet->WillReflow(*aState.mPresContext); mBullet->Reflow(*aState.mPresContext, aMetrics, reflowState, status); - mBullet->DidReflow(*aState.mPresContext, NS_FRAME_REFLOW_FINISHED); // Place the bullet now; use its right margin to distance it // from the rest of the frames in the line @@ -6098,6 +6129,7 @@ nsBlockFrame::ReflowBullet(nsBlockReflowState& aState, const nsMargin& bp = aState.BorderPadding(); nscoord y = bp.top; mBullet->SetRect(aState.mPresContext, nsRect(x, y, aMetrics.width, aMetrics.height)); + mBullet->DidReflow(*aState.mPresContext, NS_FRAME_REFLOW_FINISHED); } //XXX get rid of this -- its slow diff --git a/layout/html/base/src/nsBlockReflowContext.cpp b/layout/html/base/src/nsBlockReflowContext.cpp index 1b6d61922bd3..ecce17d09d3e 100644 --- a/layout/html/base/src/nsBlockReflowContext.cpp +++ b/layout/html/base/src/nsBlockReflowContext.cpp @@ -226,6 +226,14 @@ nsBlockReflowContext::ReflowBlock(nsIFrame* aFrame, // Let frame know that we are reflowing it aFrame->WillReflow(*mPresContext); + // Position it and its view (if it has one) + aFrame->MoveTo(mPresContext, mX, mY); + nsIView* view; + aFrame->GetView(mPresContext, &view); + if (view) { + nsContainerFrame::PositionFrameView(mPresContext, aFrame, view); + } + #ifdef DEBUG mMetrics.width = nscoord(0xdeadbeef); mMetrics.height = nscoord(0xdeadbeef); @@ -417,7 +425,9 @@ nsBlockReflowContext::PlaceBlock(PRBool aForceFit, // Empty blocks do not have anything special done to them and they // always fit. Note: don't force the width to 0 nsRect r(x, y, mMetrics.width, 0); - mFrame->SetRect(mPresContext, r); + + // Now place the frame and complete the reflow process + nsContainerFrame::FinishReflowChild(mFrame, *mPresContext, mMetrics, x, y, 0); aInFlowBounds = r; // Retain combined area information in case we contain a floater @@ -544,8 +554,8 @@ nsBlockReflowContext::PlaceBlock(PRBool aForceFit, aCombinedRect.width = mMetrics.mCombinedArea.width; aCombinedRect.height = mMetrics.mCombinedArea.height; - // Now place the frame - mFrame->SetRect(mPresContext, nsRect(x, y, mMetrics.width, mMetrics.height)); + // Now place the frame and complete the reflow process + nsContainerFrame::FinishReflowChild(mFrame, *mPresContext, mMetrics, x, y, 0); // XXX obsolete, i believe... #if 0 @@ -591,6 +601,9 @@ nsBlockReflowContext::PlaceBlock(PRBool aForceFit, } } else { + // Send the DidReflow() notification, but don't bother placing + // the frame + mFrame->DidReflow(*mPresContext, NS_FRAME_REFLOW_FINISHED); fits = PR_FALSE; } } diff --git a/layout/html/base/src/nsBlockReflowState.cpp b/layout/html/base/src/nsBlockReflowState.cpp index 32bf803e5edb..8c6b7aad71c0 100644 --- a/layout/html/base/src/nsBlockReflowState.cpp +++ b/layout/html/base/src/nsBlockReflowState.cpp @@ -2809,6 +2809,20 @@ nsBlockFrame::PullFrame(nsBlockReflowState& aState, return NS_OK; } +static void +PlaceFrameView(nsIPresContext* aPresContext, + nsIFrame* aFrame) +{ + nsIView* view; + aFrame->GetView(aPresContext, &view); + if (view) { + nsContainerFrame::SyncFrameViewAfterReflow(aPresContext, aFrame, view, nsnull); + + } else { + nsContainerFrame::PositionChildViews(aPresContext, aFrame); + } +} + void nsBlockFrame::SlideLine(nsBlockReflowState& aState, nsLineBox* aLine, nscoord aDY) @@ -2830,6 +2844,9 @@ nsBlockFrame::SlideLine(nsBlockReflowState& aState, kid->SetRect(aState.mPresContext, r); } + // Make sure the frame's view and any child views are updated + ::PlaceFrameView(aState.mPresContext, kid); + // If the child has any floaters that impact the space-manager, // place them now so that they are present in the space-manager // again (they were removed by the space-manager's frame when @@ -2851,16 +2868,21 @@ nsBlockFrame::SlideLine(nsBlockReflowState& aState, } } else { - if (aDY) { - // Adjust the Y coordinate of the frames in the line - nsRect r; - PRInt32 n = aLine->GetChildCount(); - while (--n >= 0) { + // Adjust the Y coordinate of the frames in the line. + // Note: we need to re-position views even if aDY is 0, because + // one of our parent frames may have moved and so the view's position + // relative to its parent may have changed + nsRect r; + PRInt32 n = aLine->GetChildCount(); + while (--n >= 0) { + if (aDY) { kid->GetRect(r); r.y += aDY; kid->SetRect(aState.mPresContext, r); - kid->GetNextSibling(&kid); } + // Make sure the frame's view and any child views are updated + ::PlaceFrameView(aState.mPresContext, kid); + kid->GetNextSibling(&kid); } } } @@ -4161,6 +4183,16 @@ nsBlockFrame::PostPlaceLine(nsBlockReflowState& aState, nsLineBox* aLine, const nsSize& aMaxElementSize) { + // If it's inline elements, then make sure the views are correctly + // positioned and sized + if (aLine->IsInline()) { + nsIFrame* frame = aLine->mFirstChild; + for (PRInt32 i = 0; i < aLine->GetChildCount(); i++) { + ::PlaceFrameView(aState.mPresContext, frame); + frame->GetNextSibling(&frame); + } + } + // Update max-element-size if (aState.mComputeMaxElementSize) { aState.UpdateMaxElementSize(aMaxElementSize); @@ -6087,7 +6119,6 @@ nsBlockFrame::ReflowBullet(nsBlockReflowState& aState, nsReflowStatus status; mBullet->WillReflow(*aState.mPresContext); mBullet->Reflow(*aState.mPresContext, aMetrics, reflowState, status); - mBullet->DidReflow(*aState.mPresContext, NS_FRAME_REFLOW_FINISHED); // Place the bullet now; use its right margin to distance it // from the rest of the frames in the line @@ -6098,6 +6129,7 @@ nsBlockFrame::ReflowBullet(nsBlockReflowState& aState, const nsMargin& bp = aState.BorderPadding(); nscoord y = bp.top; mBullet->SetRect(aState.mPresContext, nsRect(x, y, aMetrics.width, aMetrics.height)); + mBullet->DidReflow(*aState.mPresContext, NS_FRAME_REFLOW_FINISHED); } //XXX get rid of this -- its slow diff --git a/layout/html/base/src/nsBlockReflowState.h b/layout/html/base/src/nsBlockReflowState.h index 32bf803e5edb..8c6b7aad71c0 100644 --- a/layout/html/base/src/nsBlockReflowState.h +++ b/layout/html/base/src/nsBlockReflowState.h @@ -2809,6 +2809,20 @@ nsBlockFrame::PullFrame(nsBlockReflowState& aState, return NS_OK; } +static void +PlaceFrameView(nsIPresContext* aPresContext, + nsIFrame* aFrame) +{ + nsIView* view; + aFrame->GetView(aPresContext, &view); + if (view) { + nsContainerFrame::SyncFrameViewAfterReflow(aPresContext, aFrame, view, nsnull); + + } else { + nsContainerFrame::PositionChildViews(aPresContext, aFrame); + } +} + void nsBlockFrame::SlideLine(nsBlockReflowState& aState, nsLineBox* aLine, nscoord aDY) @@ -2830,6 +2844,9 @@ nsBlockFrame::SlideLine(nsBlockReflowState& aState, kid->SetRect(aState.mPresContext, r); } + // Make sure the frame's view and any child views are updated + ::PlaceFrameView(aState.mPresContext, kid); + // If the child has any floaters that impact the space-manager, // place them now so that they are present in the space-manager // again (they were removed by the space-manager's frame when @@ -2851,16 +2868,21 @@ nsBlockFrame::SlideLine(nsBlockReflowState& aState, } } else { - if (aDY) { - // Adjust the Y coordinate of the frames in the line - nsRect r; - PRInt32 n = aLine->GetChildCount(); - while (--n >= 0) { + // Adjust the Y coordinate of the frames in the line. + // Note: we need to re-position views even if aDY is 0, because + // one of our parent frames may have moved and so the view's position + // relative to its parent may have changed + nsRect r; + PRInt32 n = aLine->GetChildCount(); + while (--n >= 0) { + if (aDY) { kid->GetRect(r); r.y += aDY; kid->SetRect(aState.mPresContext, r); - kid->GetNextSibling(&kid); } + // Make sure the frame's view and any child views are updated + ::PlaceFrameView(aState.mPresContext, kid); + kid->GetNextSibling(&kid); } } } @@ -4161,6 +4183,16 @@ nsBlockFrame::PostPlaceLine(nsBlockReflowState& aState, nsLineBox* aLine, const nsSize& aMaxElementSize) { + // If it's inline elements, then make sure the views are correctly + // positioned and sized + if (aLine->IsInline()) { + nsIFrame* frame = aLine->mFirstChild; + for (PRInt32 i = 0; i < aLine->GetChildCount(); i++) { + ::PlaceFrameView(aState.mPresContext, frame); + frame->GetNextSibling(&frame); + } + } + // Update max-element-size if (aState.mComputeMaxElementSize) { aState.UpdateMaxElementSize(aMaxElementSize); @@ -6087,7 +6119,6 @@ nsBlockFrame::ReflowBullet(nsBlockReflowState& aState, nsReflowStatus status; mBullet->WillReflow(*aState.mPresContext); mBullet->Reflow(*aState.mPresContext, aMetrics, reflowState, status); - mBullet->DidReflow(*aState.mPresContext, NS_FRAME_REFLOW_FINISHED); // Place the bullet now; use its right margin to distance it // from the rest of the frames in the line @@ -6098,6 +6129,7 @@ nsBlockFrame::ReflowBullet(nsBlockReflowState& aState, const nsMargin& bp = aState.BorderPadding(); nscoord y = bp.top; mBullet->SetRect(aState.mPresContext, nsRect(x, y, aMetrics.width, aMetrics.height)); + mBullet->DidReflow(*aState.mPresContext, NS_FRAME_REFLOW_FINISHED); } //XXX get rid of this -- its slow diff --git a/layout/html/base/src/nsContainerFrame.cpp b/layout/html/base/src/nsContainerFrame.cpp index d6b960d6c95b..a6f3d9fb37e3 100644 --- a/layout/html/base/src/nsContainerFrame.cpp +++ b/layout/html/base/src/nsContainerFrame.cpp @@ -39,6 +39,7 @@ #include "nsIPresShell.h" #include "nsCOMPtr.h" #include "nsLayoutAtoms.h" +#include "nsIViewManager.h" #ifdef NS_DEBUG #undef NOISY @@ -107,6 +108,8 @@ nsContainerFrame::DidReflow(nsIPresContext& aPresContext, // the NS_FRAME_IN_REFLOW bit nsresult result = nsFrame::DidReflow(aPresContext, aStatus); + // XXX TROY +#if 0 if (NS_FRAME_REFLOW_FINISHED == aStatus) { // Apply DidReflow to each and every list that this frame implements nsIAtom* listName = nsnull; @@ -122,6 +125,7 @@ nsContainerFrame::DidReflow(nsIPresContext& aPresContext, GetAdditionalChildListName(listIndex++, &listName); } while(nsnull != listName); } +#endif NS_FRAME_TRACE_OUT("nsContainerFrame::DidReflow"); return result; @@ -372,17 +376,194 @@ nsContainerFrame::ReplaceFrame(nsIPresContext& aPresContext, ///////////////////////////////////////////////////////////////////////////// // Helper member functions +void +nsContainerFrame::PositionFrameView(nsIPresContext* aPresContext, + nsIFrame* aKidFrame, + nsIView* aView) +{ + if (aView) { + // Position view relative to its parent, not relative to aKidFrame's + // frame which may not have a view + nsIView* containingView; + nsPoint origin; + nsIView* parentView; + + aView->GetParent(parentView); + aKidFrame->GetOffsetFromView(aPresContext, origin, &containingView); + + if (containingView == parentView) { + nsIViewManager *vm; + aView->GetViewManager(vm); + vm->MoveViewTo(aView, origin.x, origin.y); + NS_RELEASE(vm); + } + } +} + +void +nsContainerFrame::SyncFrameViewAfterReflow(nsIPresContext* aPresContext, + nsIFrame* aFrame, + nsIView* aView, + nsRect* aCombinedArea, + PRUint32 aFlags) +{ + if (aView) { + nsIViewManager *vm; + nsFrameState kidState; + nsSize frameSize; + + aView->GetViewManager(vm); + aFrame->GetFrameState(&kidState); + aFrame->GetSize(frameSize); + + // Make sure the view is sized and positioned correctly + if (0 == (aFlags & NS_FRAME_NO_MOVE_VIEW)) { + nsIView* containingView; + nsPoint origin; + nsIView* parentView; + + aView->GetParent(parentView); + aFrame->GetOffsetFromView(aPresContext, origin, &containingView); + + if (containingView == parentView) { + vm->MoveViewTo(aView, origin.x, origin.y); + } + } + + if (0 == (aFlags & NS_FRAME_NO_SIZE_VIEW)) { + // If the frame has child frames that stick outside the content + // area, then size the view large enough to include those child + // frames + if ((kidState & NS_FRAME_OUTSIDE_CHILDREN) && aCombinedArea) { + vm->ResizeView(aView, aCombinedArea->XMost(), aCombinedArea->YMost()); + + } else { + vm->ResizeView(aView, frameSize.width, frameSize.height); + } + } + + const nsStyleColor* color; + const nsStyleDisplay* display; + aFrame->GetStyleData(eStyleStruct_Color, (const nsStyleStruct*&)color); + aFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display); + + // Set the view's opacity + vm->SetViewOpacity(aView, color->mOpacity); + + // See if the view should be hidden or visible + PRBool viewIsVisible = PR_TRUE; + PRBool viewHasTransparentContent = (color->mBackgroundFlags & + NS_STYLE_BG_COLOR_TRANSPARENT) == NS_STYLE_BG_COLOR_TRANSPARENT; + + if (NS_STYLE_VISIBILITY_COLLAPSE == display->mVisible) { + viewIsVisible = PR_FALSE; + } + else if (NS_STYLE_VISIBILITY_HIDDEN == display->mVisible) { + // If it has a widget, hide the view because the widget can't deal with it + nsIWidget* widget = nsnull; + aView->GetWidget(widget); + if (widget) { + viewIsVisible = PR_FALSE; + NS_RELEASE(widget); + } + else { + // If it's a scroll frame, then hide the view. This means that + // child elements can't override their parent's visibility, but + // it's not practical to leave it visible in all cases because + // the scrollbars will be showing + nsIAtom* frameType; + aFrame->GetFrameType(&frameType); + + if (frameType == nsLayoutAtoms::scrollFrame) { + viewIsVisible = PR_FALSE; + + } else { + // If we're a container element, then leave the view visible, but + // mark it as having transparent content. The reason we need to + // do this is that child elements can override their parent's + // hidden visibility and be visible anyway + nsIFrame* firstChild; + + aFrame->FirstChild(nsnull, &firstChild); + if (firstChild) { + // Not a left frame, so the view needs to be visible, but marked + // as having transparent content + viewHasTransparentContent = PR_TRUE; + } else { + // Leaf frame so go ahead and hide the view + viewIsVisible = PR_FALSE; + } + } + NS_IF_RELEASE(frameType); + } + } + + // If the frame has visible content that overflows the content area, then we + // need the view marked as having transparent content + if (NS_STYLE_OVERFLOW_VISIBLE == display->mOverflow) { + if (kidState & NS_FRAME_OUTSIDE_CHILDREN) { + viewHasTransparentContent = PR_TRUE; + } + } + + // Make sure visibility is correct + vm->SetViewVisibility(aView, viewIsVisible ? nsViewVisibility_kShow : + nsViewVisibility_kHide); + + // Make sure content transparency is correct + if (viewIsVisible) { + vm->SetViewContentTransparency(aView, viewHasTransparentContent); + } + + // Clip applies to block-level and replaced elements with overflow + // set to other than 'visible' + if (display->IsBlockLevel()) { + if (display->mOverflow == NS_STYLE_OVERFLOW_HIDDEN) { + nscoord left, top, right, bottom; + + // Start with the 'auto' values and then factor in user + // specified values + left = top = 0; + right = frameSize.width; + bottom = frameSize.height; + + if (0 == (NS_STYLE_CLIP_TOP_AUTO & display->mClipFlags)) { + top += display->mClip.top; + } + if (0 == (NS_STYLE_CLIP_RIGHT_AUTO & display->mClipFlags)) { + right -= display->mClip.right; + } + if (0 == (NS_STYLE_CLIP_BOTTOM_AUTO & display->mClipFlags)) { + bottom -= display->mClip.bottom; + } + if (0 == (NS_STYLE_CLIP_LEFT_AUTO & display->mClipFlags)) { + left += display->mClip.left; + } + aView->SetClip(left, top, right, bottom); + + } else { + // Make sure no clip is set + aView->SetClip(0, 0, 0, 0); + } + } + + NS_RELEASE(vm); + } +} + /** - * Queries the child frame for the nsIHTMLReflow interface and if it's - * supported invokes the WillReflow() and Reflow() member functions. If - * the reflow succeeds and the child frame is complete, deletes any - * next-in-flows using DeleteChildsNextInFlow() + * Invokes the WillReflow() function, positions the frame and its view (if + * requested), and then calls Reflow(). If the reflow succeeds and the child + * frame is complete, deletes any next-in-flows using DeleteChildsNextInFlow() */ nsresult nsContainerFrame::ReflowChild(nsIFrame* aKidFrame, nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, + nscoord aX, + nscoord aY, + PRUint32 aFlags, nsReflowStatus& aStatus) { NS_PRECONDITION(aReflowState.frame == aKidFrame, "bad reflow state"); @@ -399,8 +580,23 @@ nsContainerFrame::ReflowChild(nsIFrame* aKidFrame, #endif #endif - // Send the WillReflow notification, and reflow the child frame + // Send the WillReflow() notification, and position the child frame + // and its view if requested aKidFrame->WillReflow(aPresContext); + + if (0 == (aFlags & NS_FRAME_NO_MOVE_FRAME)) { + aKidFrame->MoveTo(&aPresContext, aX, aY); + } + + if (0 == (aFlags & NS_FRAME_NO_MOVE_VIEW)) { + nsIView* view; + aKidFrame->GetView(&aPresContext, &view); + if (view) { + PositionFrameView(&aPresContext, aKidFrame, view); + } + } + + // Reflow the child frame result = aKidFrame->Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); @@ -441,6 +637,97 @@ nsContainerFrame::ReflowChild(nsIFrame* aKidFrame, return result; } +void +nsContainerFrame::PositionChildViews(nsIPresContext* aPresContext, + nsIFrame* aFrame) +{ + nsIAtom* childListName = nsnull; + PRInt32 childListIndex = 0; + + do { + // Recursively walk aFrame's child frames + nsIFrame* childFrame; + aFrame->FirstChild(childListName, &childFrame); + while (childFrame) { + nsIView* view; + + // See if the child frame has a view + childFrame->GetView(aPresContext, &view); + + if (view) { + // Position the view. Because any child views are relative to their + // parent, there's no need to recurse + PositionFrameView(aPresContext, childFrame, view); + + } else { + // Recursively examine its child frames + PositionChildViews(aPresContext, childFrame); + } + + // Get the next sibling child frame + childFrame->GetNextSibling(&childFrame); + } + + NS_IF_RELEASE(childListName); + aFrame->GetAdditionalChildListName(childListIndex++, &childListName); + } while (childListName); +} + +/** + * The second half of frame reflow. Does the following: + * - sets the frame's bounds + * - sizes and positions (if requested) the frame's view. If the frame's final + * position differs from the current position and the frame itself does not + * have a view, then any child frames with views are positioned so they stay + * in sync + * - sets the view's visibility, opacity, content transparency, and clip + * - invoked the DidReflow() function + * + * Flags: + * NS_FRAME_NO_MOVE_FRAME - don't move the frame. aX and aY are ignored in this + * case. Also implies NS_FRAME_NO_MOVE_VIEW + * NS_FRAME_NO_MOVE_VIEW - don't position the frame's view. Set this if you + * don't want to automatically sync the frame and view + * NS_FRAME_NO_SIZE_VIEW - don't size the frame's view + * NS_FRAME_NO_MOVE_CHILD_VIEWS - don't move child views. This is for the case + * where the frame's new position differs from its current position and the + * frame itself doesn't have a view, so moving the frame would cause any child + * views to be out of sync +*/ +nsresult +nsContainerFrame::FinishReflowChild(nsIFrame* aKidFrame, + nsIPresContext& aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + nscoord aX, + nscoord aY, + PRUint32 aFlags) +{ + nsPoint curOrigin; + nsRect bounds(aX, aY, aDesiredSize.width, aDesiredSize.height); + + aKidFrame->GetOrigin(curOrigin); + aKidFrame->SetRect(&aPresContext, bounds); + + nsIView* view; + aKidFrame->GetView(&aPresContext, &view); + if (view) { + // Make sure the frame's view is properly sized and positioned and has + // things like opacity correct + SyncFrameViewAfterReflow(&aPresContext, aKidFrame, view, + &aDesiredSize.mCombinedArea, + aFlags); + + } else if (0 == (aFlags & NS_FRAME_NO_MOVE_CHILD_VIEWS)) { + // If the frame has moved, then we need to make sure any child views are + // correctly positioned + if ((curOrigin.x != aX) || (curOrigin.y != aY)) { + PositionChildViews(&aPresContext, aKidFrame); + } + } + + return aKidFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); +} + /** * Remove and delete aChild's next-in-flow(s). Updates the sibling and flow * pointers diff --git a/layout/html/base/src/nsContainerFrame.h b/layout/html/base/src/nsContainerFrame.h index 5fd59b6c5930..6a0c6f6e0496 100644 --- a/layout/html/base/src/nsContainerFrame.h +++ b/layout/html/base/src/nsContainerFrame.h @@ -25,6 +25,13 @@ #include "nsSplittableFrame.h" #include "nsFrameList.h" +// Option flags for ReflowChild() and FinishReflowChild() +// member functions +#define NS_FRAME_NO_MOVE_VIEW 0x0001 +#define NS_FRAME_NO_MOVE_FRAME (0x0002 | NS_FRAME_NO_MOVE_VIEW) +#define NS_FRAME_NO_SIZE_VIEW 0x0004 +#define NS_FRAME_NO_MOVE_CHILD_VIEWS 0x0008 + /** * Implementation of a container frame. */ @@ -67,6 +74,82 @@ public: return tmp.GetLength(); } + // Positions the frame's view based on the frame's origin + static void PositionFrameView(nsIPresContext* aPresContext, + nsIFrame* aKidFrame, + nsIView* aView); + + // Sets several view attributes: + // - if requested sizes the frame's view based on the current size and origin. + // Takes into account the combined area and (if overflow is visible) whether + // the frame has children that extend outside + // - opacity + // - visibility + // - content transparency + // - clip + // + // Flags: + // NS_FRAME_NO_MOVE_VIEW - don't position the frame's view. Set this if you + // don't want to automatically sync the frame and view + // NS_FRAME_NO_MOVE_VIEW - don't move the frame. aX and aY are ignored in this + // case. Also implies NS_FRAME_NO_MOVE_VIEW + static void SyncFrameViewAfterReflow(nsIPresContext* aPresContext, + nsIFrame* aFrame, + nsIView* aView, + nsRect* aCombinedArea, + PRUint32 aFlags = 0); + + /** + * Invokes the WillReflow() function, positions the frame and its view (if + * requested), and then calls Reflow(). If the reflow succeeds and the child + * frame is complete, deletes any next-in-flows using DeleteChildsNextInFlow() + * + * Flags: + * NS_FRAME_NO_MOVE_VIEW - don't position the frame's view. Set this if you + * don't want to automatically sync the frame and view + * NS_FRAME_NO_MOVE_VIEW - don't move the frame. aX and aY are ignored in this + * case. Also implies NS_FRAME_NO_MOVE_VIEW + */ + nsresult ReflowChild(nsIFrame* aKidFrame, + nsIPresContext& aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nscoord aX, + nscoord aY, + PRUint32 aFlags, + nsReflowStatus& aStatus); + + /** + * The second half of frame reflow. Does the following: + * - sets the frame's bounds + * - sizes and positions (if requested) the frame's view. If the frame's final + * position differs from the current position and the frame itself does not + * have a view, then any child frames with views are positioned so they stay + * in sync + * - sets the view's visibility, opacity, content transparency, and clip + * - invoked the DidReflow() function + * + * Flags: + * NS_FRAME_NO_MOVE_FRAME - don't move the frame. aX and aY are ignored in this + * case. Also implies NS_FRAME_NO_MOVE_VIEW + * NS_FRAME_NO_MOVE_VIEW - don't position the frame's view. Set this if you + * don't want to automatically sync the frame and view + * NS_FRAME_NO_SIZE_VIEW - don't size the frame's view + * NS_FRAME_NO_MOVE_CHILD_VIEWS - don't move child views. This is for the case + * where the frame's new position differs from its current position and the + * frame itself doesn't have a view, so moving the frame would cause any child + * views to be out of sync + */ + static nsresult FinishReflowChild(nsIFrame* aKidFrame, + nsIPresContext& aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + nscoord aX, + nscoord aY, + PRUint32 aFlags); + + static void PositionChildViews(nsIPresContext* aPresContext, + nsIFrame* aFrame); + protected: nsContainerFrame(); ~nsContainerFrame(); @@ -87,18 +170,6 @@ protected: nsIFrame* aFrame, nsFramePaintLayer aWhichLayer); - /** - * Queries the child frame for the nsIHTMLReflow interface and if it's - * supported invokes the WillReflow() and Reflow() member functions. If - * the reflow succeeds and the child frame is complete, deletes any - * next-in-flows using DeleteChildsNextInFlow() - */ - nsresult ReflowChild(nsIFrame* aKidFrame, - nsIPresContext& aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus); - /** * Get the frames on the overflow list */ diff --git a/layout/html/base/src/nsFirstLetterFrame.cpp b/layout/html/base/src/nsFirstLetterFrame.cpp index 90c1a7cb3905..ca02fef22a9f 100644 --- a/layout/html/base/src/nsFirstLetterFrame.cpp +++ b/layout/html/base/src/nsFirstLetterFrame.cpp @@ -247,6 +247,7 @@ nsFirstLetterFrame::Reflow(nsIPresContext& aPresContext, // Place and size the child and update the output metrics kid->MoveTo(&aPresContext, bp.left, bp.top); kid->SizeTo(&aPresContext, aMetrics.width, aMetrics.height); + kid->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); aMetrics.width += lr; aMetrics.height += tb; aMetrics.ascent += bp.top; diff --git a/layout/html/base/src/nsFrame.cpp b/layout/html/base/src/nsFrame.cpp index 5ef77927479c..103d35d81e70 100644 --- a/layout/html/base/src/nsFrame.cpp +++ b/layout/html/base/src/nsFrame.cpp @@ -507,6 +507,8 @@ NS_IMETHODIMP nsFrame::MoveTo(nsIPresContext* aPresContext, nscoord aX, nscoord mRect.x = aX; mRect.y = aY; + // XXX TROY +#if 0 nsIView* view; GetView(aPresContext, &view); if (view) { @@ -526,6 +528,7 @@ NS_IMETHODIMP nsFrame::MoveTo(nsIPresContext* aPresContext, nscoord aX, nscoord NS_RELEASE(vm); } } +#endif return NS_OK; } @@ -535,6 +538,8 @@ NS_IMETHODIMP nsFrame::SizeTo(nsIPresContext* aPresContext, nscoord aWidth, nsco mRect.width = aWidth; mRect.height = aHeight; + // XXX TROY +#if 0 // Let the view know nsIView* view; GetView(aPresContext, &view); @@ -551,6 +556,7 @@ NS_IMETHODIMP nsFrame::SizeTo(nsIPresContext* aPresContext, nscoord aWidth, nsco NS_RELEASE(vm); } } +#endif return NS_OK; } @@ -1266,6 +1272,8 @@ nsFrame::DidReflow(nsIPresContext& aPresContext, if (NS_FRAME_REFLOW_FINISHED == aStatus) { mState &= ~(NS_FRAME_IN_REFLOW | NS_FRAME_FIRST_REFLOW | NS_FRAME_IS_DIRTY); + // XXX TROY +#if 0 // Make sure the view is sized and positioned correctly and it's // visibility, opacity, content transparency, and clip are correct nsIView* view; @@ -1390,6 +1398,7 @@ nsFrame::DidReflow(nsIPresContext& aPresContext, } NS_RELEASE(vm); } +#endif } return NS_OK; } diff --git a/layout/html/base/src/nsGfxScrollFrame.cpp b/layout/html/base/src/nsGfxScrollFrame.cpp index 63526f3bfeb0..014afe7a23ad 100644 --- a/layout/html/base/src/nsGfxScrollFrame.cpp +++ b/layout/html/base/src/nsGfxScrollFrame.cpp @@ -1206,7 +1206,8 @@ nsGfxScrollFrameInner::ReflowFrame( nsIPresContext& aPresContext, childReflowState.mComputedHeight -= childReflowState.mComputedBorderPadding.top + childReflowState.mComputedBorderPadding.bottom; */ - mOuter->ReflowChild(aFrame, aPresContext, aDesiredSize, childReflowState, aStatus); + mOuter->ReflowChild(aFrame, aPresContext, aDesiredSize, childReflowState, + 0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus); NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status"); // if the frame size change then mark the flag @@ -1214,6 +1215,7 @@ nsGfxScrollFrameInner::ReflowFrame( nsIPresContext& aPresContext, aFrame->SizeTo(&aPresContext, aDesiredSize.width, aDesiredSize.height); aResized = PR_TRUE; } + aFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); // add the margin back in aDesiredSize.width += margin.left + margin.right; @@ -1467,13 +1469,29 @@ nsGfxScrollFrameInner::LayoutChildren(nsIPresContext& aPresContext, const nsMargin& border = aReflowState.mComputedBorderPadding; // Place scroll area + nsIView* view; mScrollAreaFrame->MoveTo(&aPresContext, border.left, border.top); + mScrollAreaFrame->GetView(&aPresContext, &view); + if (view) { + nsContainerFrame::SyncFrameViewAfterReflow(&aPresContext, mScrollAreaFrame, + view, nsnull); + } // place vertical scrollbar mVScrollbarFrame->MoveTo(&aPresContext, border.left + scrollAreaSize.width, border.top); + mVScrollbarFrame->GetView(&aPresContext, &view); + if (view) { + nsContainerFrame::SyncFrameViewAfterReflow(&aPresContext, mVScrollbarFrame, + view, nsnull); + } // place horizontal scrollbar mHScrollbarFrame->MoveTo(&aPresContext, border.left, border.top + scrollAreaSize.height); + mHScrollbarFrame->GetView(&aPresContext, &view); + if (view) { + nsContainerFrame::SyncFrameViewAfterReflow(&aPresContext, mHScrollbarFrame, + view, nsnull); + } // Compute our desired size // ---------- compute width ----------- diff --git a/layout/html/base/src/nsHTMLFrame.cpp b/layout/html/base/src/nsHTMLFrame.cpp index 37b1fcda0268..a467ef29ae3f 100644 --- a/layout/html/base/src/nsHTMLFrame.cpp +++ b/layout/html/base/src/nsHTMLFrame.cpp @@ -324,7 +324,8 @@ RootFrame::Reflow(nsIPresContext& aPresContext, // Reflow the frame ReflowChild(kidFrame, aPresContext, kidDesiredSize, kidReflowState, - aStatus); + kidReflowState.mComputedMargin.left, kidReflowState.mComputedMargin.top, + 0, aStatus); // The document element's background should cover the entire canvas, so // take into account the combined area and any space taken up by @@ -385,10 +386,10 @@ RootFrame::Reflow(nsIPresContext& aPresContext, } } - // Position and size the child frame + // Complete the reflow and position and size the child frame nsRect rect(kidReflowState.mComputedMargin.left, kidReflowState.mComputedMargin.top, kidDesiredSize.width, kidDesiredSize.height); - kidFrame->SetRect(&aPresContext, rect); + FinishReflowChild(kidFrame, aPresContext, kidDesiredSize, rect.x, rect.y, 0); // If the child frame was just inserted, then we're responsible for making sure // it repaints diff --git a/layout/html/base/src/nsHTMLReflowCommand.cpp b/layout/html/base/src/nsHTMLReflowCommand.cpp index 813fb5d67682..a116b70ce07b 100644 --- a/layout/html/base/src/nsHTMLReflowCommand.cpp +++ b/layout/html/base/src/nsHTMLReflowCommand.cpp @@ -30,6 +30,7 @@ #include "nsStyleConsts.h" #include "nsHTMLIIDs.h" #include "nsFrame.h" +#include "nsContainerFrame.h" static NS_DEFINE_IID(kIReflowCommandIID, NS_IREFLOWCOMMAND_IID); @@ -133,8 +134,20 @@ NS_IMETHODIMP nsHTMLReflowCommand::Dispatch(nsIPresContext& aPresContext, nsHTMLReflowState reflowState(aPresContext, root, *this, &aRendContext, aMaxSize); nsReflowStatus status; + nsIView* view; + root->WillReflow(aPresContext); + root->GetView(&aPresContext, &view); + if (view) { + nsContainerFrame::PositionFrameView(&aPresContext, root, view); + } root->Reflow(aPresContext, aDesiredSize, reflowState, status); + root->SizeTo(&aPresContext, aDesiredSize.width, aDesiredSize.height); + if (view) { + nsContainerFrame::SyncFrameViewAfterReflow(&aPresContext, root, view, + nsnull); + } + root->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); } return NS_OK; diff --git a/layout/html/base/src/nsLineLayout.cpp b/layout/html/base/src/nsLineLayout.cpp index cfa5498d4524..5e41b2153976 100644 --- a/layout/html/base/src/nsLineLayout.cpp +++ b/layout/html/base/src/nsLineLayout.cpp @@ -35,6 +35,8 @@ #include "nsIDocument.h" #include "nsIHTMLDocument.h" #include "nsIContent.h" +#include "nsIView.h" +#include "nsIViewManager.h" #ifdef DEBUG #undef NOISY_HORIZONTAL_ALIGN @@ -918,7 +920,9 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame, // new starting x,y coordinates for the frame. ApplyLeftMargin(pfd, reflowState); - // Let frame know that are reflowing it + // Let frame know that are reflowing it. Note that we don't bother + // positioning the frame yet, because we're probably going to end up + // moving it when we do the vertical alignment nscoord x = pfd->mBounds.x; nscoord y = pfd->mBounds.y; @@ -1072,14 +1076,21 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame, pfd->mMaxElementSize = *metrics.maxElementSize; } - // Now that frame has been reflowed at least one time make sure that - // the NS_FRAME_FIRST_REFLOW bit is cleared so that never give it an - // initial reflow reason again. - if (eReflowReason_Initial == reason) { - aFrame->GetFrameState(&state); - aFrame->SetFrameState(state & ~NS_FRAME_FIRST_REFLOW); + // Size the frame and size its view (if it has one) + aFrame->SizeTo(&mPresContext, metrics.width, metrics.height); + nsIView* view; + aFrame->GetView(&mPresContext, &view); + if (view) { + nsIViewManager *vm; + + view->GetViewManager(vm); + vm->ResizeView(view, metrics.width, metrics.height); + NS_RELEASE(vm); } + // Tell the frame that we're done reflowing it + aFrame->DidReflow(mPresContext, NS_FRAME_REFLOW_FINISHED); + if (aMetrics) { *aMetrics = metrics; } diff --git a/layout/html/base/src/nsObjectFrame.cpp b/layout/html/base/src/nsObjectFrame.cpp index fb750b9a9df1..3d5951047126 100644 --- a/layout/html/base/src/nsObjectFrame.cpp +++ b/layout/html/base/src/nsObjectFrame.cpp @@ -1037,10 +1037,8 @@ nsObjectFrame::HandleImage(nsIPresContext& aPresContext, } } - ReflowChild(child, aPresContext, kidDesiredSize, kidReflowState, status); - - nsRect rect(0, 0, kidDesiredSize.width, kidDesiredSize.height); - child->SetRect(&aPresContext, rect); + ReflowChild(child, aPresContext, kidDesiredSize, kidReflowState, 0, 0, 0, status); + FinishReflowChild(child, aPresContext, kidDesiredSize, 0, 0, 0); aMetrics.width = kidDesiredSize.width; aMetrics.height = kidDesiredSize.height; diff --git a/layout/html/base/src/nsPageFrame.cpp b/layout/html/base/src/nsPageFrame.cpp index 0dbe8bd9cd0b..cb2094b21a96 100644 --- a/layout/html/base/src/nsPageFrame.cpp +++ b/layout/html/base/src/nsPageFrame.cpp @@ -80,7 +80,7 @@ NS_METHOD nsPageFrame::Reflow(nsIPresContext& aPresContext, kidReflowState.isTopOfPage = PR_TRUE; ReflowChild(mFrames.FirstChild(), aPresContext, aDesiredSize, - kidReflowState, aStatus); + kidReflowState, 0, 0, 0, aStatus); // Place and size the child. Make sure the child is at least as // tall as our max size (the containing window) @@ -88,8 +88,8 @@ NS_METHOD nsPageFrame::Reflow(nsIPresContext& aPresContext, aDesiredSize.height = aReflowState.availableHeight; } - nsRect rect(0, 0, aDesiredSize.width, aDesiredSize.height); - mFrames.FirstChild()->SetRect(&aPresContext, rect); + FinishReflowChild(mFrames.FirstChild(), aPresContext, aDesiredSize, + 0, 0, 0); } else { // Do we have any children? @@ -122,7 +122,7 @@ NS_METHOD nsPageFrame::Reflow(nsIPresContext& aPresContext, kidReflowState.isTopOfPage = PR_TRUE; // Get the child's desired size - ReflowChild(frame, aPresContext, aDesiredSize, kidReflowState, aStatus); + ReflowChild(frame, aPresContext, aDesiredSize, kidReflowState, 0, 0, 0, aStatus); // Make sure the child is at least as tall as our max size (the containing window) if (aDesiredSize.height < aReflowState.availableHeight) { @@ -130,10 +130,7 @@ NS_METHOD nsPageFrame::Reflow(nsIPresContext& aPresContext, } // Place and size the child - nsRect rect(0, 0, aDesiredSize.width, aDesiredSize.height); - frame->SetRect(&aPresContext, rect); - // XXX Should we be sending the DidReflow? - frame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); + FinishReflowChild(frame, aPresContext, aDesiredSize, 0, 0, 0); // Is the frame complete? if (NS_FRAME_IS_COMPLETE(aStatus)) { diff --git a/layout/html/base/src/nsPresShell.cpp b/layout/html/base/src/nsPresShell.cpp index 947a0559e894..d91684eb48e0 100644 --- a/layout/html/base/src/nsPresShell.cpp +++ b/layout/html/base/src/nsPresShell.cpp @@ -992,10 +992,21 @@ PresShell::InitialReflow(nscoord aWidth, nscoord aHeight) nsHTMLReflowState reflowState(*mPresContext, rootFrame, eReflowReason_Initial, rcx, maxSize); + nsIView* view; + rootFrame->WillReflow(*mPresContext); + rootFrame->GetView(mPresContext, &view); + if (view) { + nsContainerFrame::PositionFrameView(mPresContext, rootFrame, view); + } rootFrame->Reflow(*mPresContext, desiredSize, reflowState, status); rootFrame->SizeTo(mPresContext, desiredSize.width, desiredSize.height); mPresContext->SetVisibleArea(nsRect(0,0,desiredSize.width,desiredSize.height)); + if (view) { + nsContainerFrame::SyncFrameViewAfterReflow(mPresContext, rootFrame, view, + nsnull); + } + rootFrame->DidReflow(*mPresContext, NS_FRAME_REFLOW_FINISHED); #ifdef NS_DEBUG if (nsIFrameDebug::GetVerifyTreeEnable()) { @@ -1077,9 +1088,20 @@ PresShell::ResizeReflow(nscoord aWidth, nscoord aHeight) nsHTMLReflowState reflowState(*mPresContext, rootFrame, eReflowReason_Resize, rcx, maxSize); + nsIView* view; + rootFrame->WillReflow(*mPresContext); + rootFrame->GetView(mPresContext, &view); + if (view) { + nsContainerFrame::PositionFrameView(mPresContext, rootFrame, view); + } rootFrame->Reflow(*mPresContext, desiredSize, reflowState, status); rootFrame->SizeTo(mPresContext, desiredSize.width, desiredSize.height); + if (view) { + nsContainerFrame::SyncFrameViewAfterReflow(mPresContext, rootFrame, view, + nsnull); + } + rootFrame->DidReflow(*mPresContext, NS_FRAME_REFLOW_FINISHED); #ifdef NS_DEBUG if (nsIFrameDebug::GetVerifyTreeEnable()) { nsIFrameDebug* frameDebug; @@ -1262,9 +1284,21 @@ PresShell::StyleChangeReflow() // XXX We should be using eReflowReason_StyleChange nsHTMLReflowState reflowState(*mPresContext, rootFrame, eReflowReason_Resize, rcx, maxSize); + nsIView* view; + rootFrame->WillReflow(*mPresContext); + rootFrame->GetView(mPresContext, &view); + if (view) { + nsContainerFrame::PositionFrameView(mPresContext, rootFrame, view); + } rootFrame->Reflow(*mPresContext, desiredSize, reflowState, status); rootFrame->SizeTo(mPresContext, desiredSize.width, desiredSize.height); + mPresContext->SetVisibleArea(nsRect(0,0,desiredSize.width,desiredSize.height)); + if (view) { + nsContainerFrame::SyncFrameViewAfterReflow(mPresContext, rootFrame, view, + nsnull); + } + rootFrame->DidReflow(*mPresContext, NS_FRAME_REFLOW_FINISHED); #ifdef NS_DEBUG if (nsIFrameDebug::GetVerifyTreeEnable()) { nsIFrameDebug* frameDebug; diff --git a/layout/html/base/src/nsScrollFrame.cpp b/layout/html/base/src/nsScrollFrame.cpp index bbb380121db6..e28a0b3600e3 100644 --- a/layout/html/base/src/nsScrollFrame.cpp +++ b/layout/html/base/src/nsScrollFrame.cpp @@ -164,6 +164,8 @@ nsScrollFrame::DidReflow(nsIPresContext& aPresContext, // and size and position our view rv = nsFrame::DidReflow(aPresContext, aStatus); + // XXX TROY +#if 0 // Send the DidReflow notification to the scrolled frame's view nsIFrame* frame = mFrames.FirstChild(); @@ -179,6 +181,7 @@ nsScrollFrame::DidReflow(nsIPresContext& aPresContext, scrolledView->GetViewManager(vm); vm->ResizeView(scrolledView, size.width, size.height); NS_RELEASE(vm); +#endif // Have the scrolling view layout nsIScrollableView* scrollingView; @@ -617,7 +620,7 @@ nsScrollFrame::Reflow(nsIPresContext& aPresContext, kidReflowState.mComputedHeight = theHeight; ReflowChild(kidFrame, aPresContext, kidDesiredSize, kidReflowState, - aStatus); + border.left, border.top, NS_FRAME_NO_MOVE_VIEW, aStatus); NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status"); CalculateChildTotalSize(kidFrame, kidDesiredSize); @@ -683,7 +686,7 @@ nsScrollFrame::Reflow(nsIPresContext& aPresContext, // Reflow the child frame with a reflow reason of reflow kidReflowState.reason = eReflowReason_Resize; ReflowChild(kidFrame, aPresContext, kidDesiredSize, kidReflowState, - aStatus); + border.left, border.top, NS_FRAME_NO_MOVE_VIEW, aStatus); NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status"); CalculateChildTotalSize(kidFrame, kidDesiredSize); } @@ -711,10 +714,8 @@ nsScrollFrame::Reflow(nsIPresContext& aPresContext, } // Place and size the child. - nscoord x = border.left; - nscoord y = border.top; - nsRect rect(x, y, kidDesiredSize.width, kidDesiredSize.height); - kidFrame->SetRect(&aPresContext, rect); + FinishReflowChild(kidFrame, aPresContext, kidDesiredSize, border.left, + border.top, NS_FRAME_NO_MOVE_VIEW); // Compute our desired size aDesiredSize.width = scrollAreaSize.width; diff --git a/layout/html/base/src/nsScrollPortFrame.cpp b/layout/html/base/src/nsScrollPortFrame.cpp index f1046f46fbd7..52c5b2ca4015 100644 --- a/layout/html/base/src/nsScrollPortFrame.cpp +++ b/layout/html/base/src/nsScrollPortFrame.cpp @@ -174,11 +174,11 @@ nsScrollPortFrame::DidReflow(nsIPresContext& aPresContext, // and size and position our view rv = nsFrame::DidReflow(aPresContext, aStatus); +// XXX TROY +#if 0 // Send the DidReflow notification to the scrolled frame's view nsIFrame* frame = mFrames.FirstChild(); - frame->DidReflow(aPresContext, aStatus); - // Size the scrolled frame's view. Leave its position alone nsSize size; nsRect bounds; @@ -203,8 +203,18 @@ nsScrollPortFrame::DidReflow(nsIPresContext& aPresContext, if (NS_SUCCEEDED(view->QueryInterface(kScrollViewIID, (void**)&scrollingView))) { scrollingView->ComputeScrollOffsets(PR_TRUE); } - } + + frame->DidReflow(aPresContext, aStatus); +#else + // Have the scrolling view layout + nsIScrollableView* scrollingView; + nsIView* view; + GetView(&aPresContext, &view); + if (NS_SUCCEEDED(view->QueryInterface(kScrollViewIID, (void**)&scrollingView))) { + scrollingView->ComputeScrollOffsets(PR_TRUE); + } +#endif } return rv; @@ -440,7 +450,7 @@ nsScrollPortFrame::Reflow(nsIPresContext& aPresContext, ReflowChild(kidFrame, aPresContext, kidDesiredSize, kidReflowState, - aStatus); + border.left, border.top, 0, aStatus); NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status"); CalculateChildTotalSize(kidFrame, kidDesiredSize); @@ -471,8 +481,7 @@ nsScrollPortFrame::Reflow(nsIPresContext& aPresContext, aDesiredSize.height += border.top + border.bottom; - nsRect rect(x, y, kidDesiredSize.width, kidDesiredSize.height); - kidFrame->SetRect(&aPresContext, rect); + FinishReflowChild(kidFrame, aPresContext, kidDesiredSize, x, y, 0); //printf("width=%d, height=%d\n", kidDesiredSize.width, kidDesiredSize.height); @@ -648,7 +657,8 @@ nsScrollPortFrame::GetChildBoxInfo(nsIPresContext& aPresContext, const nsHTMLRef nsReflowStatus status = NS_FRAME_COMPLETE; ReflowChild(aFrame, aPresContext, kidDesiredSize, kidReflowState, - status); + 0, 0, NS_FRAME_NO_MOVE_FRAME, status); + aFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); NS_ASSERTION(NS_FRAME_IS_COMPLETE(status), "bad status"); diff --git a/layout/html/base/src/nsSimplePageSequence.cpp b/layout/html/base/src/nsSimplePageSequence.cpp index 98105d24fa18..50b7271c9be6 100644 --- a/layout/html/base/src/nsSimplePageSequence.cpp +++ b/layout/html/base/src/nsSimplePageSequence.cpp @@ -126,12 +126,11 @@ nsSimplePageSequenceFrame::IncrementalReflow(nsIPresContext& aPresConte // Dispatch the reflow command to our child frame. Allow it to be as high // as it wants - ReflowChild(nextFrame, aPresContext, kidSize, kidReflowState, status); + ReflowChild(nextFrame, aPresContext, kidSize, kidReflowState, aX, aY, 0, status); // Place and size the page. If the page is narrower than our max width, then // center it horizontally - nsRect rect(aX, aY, kidSize.width, kidSize.height); - nextFrame->SetRect(&aPresContext, rect); + FinishReflowChild(nextFrame, aPresContext, kidSize, aX, aY, 0); aY += kidSize.height + PAGE_SPACING_TWIPS; // Check if the page is complete... @@ -169,8 +168,9 @@ nsSimplePageSequenceFrame::IncrementalReflow(nsIPresContext& aPresConte // Place and size the page. If the page is narrower than our // max width then center it horizontally ReflowChild(kidFrame, aPresContext, childSize, childReflowState, - status); - kidFrame->SetRect(&aPresContext, nsRect(aX, aY, childSize.width, childSize.height)); + aX, aY, 0, status); + + FinishReflowChild(kidFrame, aPresContext, childSize, aX, aY, 0); aY += childSize.height; // Leave a slight gap between the pages @@ -242,8 +242,9 @@ nsSimplePageSequenceFrame::Reflow(nsIPresContext& aPresContext, // Place and size the page. If the page is narrower than our // max width then center it horizontally - ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, status); - kidFrame->SetRect(&aPresContext, nsRect(x, y, kidSize.width, kidSize.height)); + ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, x, y, 0, status); + + FinishReflowChild(kidFrame, aPresContext, kidSize, x, y, 0); y += kidSize.height; // Leave a slight gap between the pages diff --git a/layout/html/base/src/nsViewportFrame.cpp b/layout/html/base/src/nsViewportFrame.cpp index d86ea68eebac..f5aafad0c6af 100644 --- a/layout/html/base/src/nsViewportFrame.cpp +++ b/layout/html/base/src/nsViewportFrame.cpp @@ -332,8 +332,6 @@ ViewportFrame::ReflowFixedFrame(nsIPresContext& aPresContext, // Reflow the frame nsresult rv; - aKidFrame->WillReflow(aPresContext); - nsHTMLReflowMetrics kidDesiredSize(nsnull); nsSize availSize(aReflowState.availableWidth, NS_UNCONSTRAINEDSIZE); nsHTMLReflowState kidReflowState(aPresContext, aReflowState, aKidFrame, @@ -345,6 +343,18 @@ ViewportFrame::ReflowFixedFrame(nsIPresContext& aPresContext, kidReflowState.reason = eReflowReason_Initial; } + // Send the WillReflow() notification and position the frame + aKidFrame->WillReflow(aPresContext); + aKidFrame->MoveTo(&aPresContext, + kidReflowState.mComputedOffsets.left + kidReflowState.mComputedMargin.left, + kidReflowState.mComputedOffsets.top + kidReflowState.mComputedMargin.top); + + // Position its view + nsIView* kidView; + aKidFrame->GetView(&aPresContext, &kidView); + nsContainerFrame::PositionFrameView(&aPresContext, aKidFrame, kidView); + + // Do the reflow rv = aKidFrame->Reflow(aPresContext, kidDesiredSize, kidReflowState, aStatus); // XXX If the child had a fixed height, then make sure it respected it... @@ -361,8 +371,12 @@ ViewportFrame::ReflowFixedFrame(nsIPresContext& aPresContext, kidReflowState.mComputedOffsets.top + kidReflowState.mComputedMargin.top, kidDesiredSize.width, kidDesiredSize.height); aKidFrame->SetRect(&aPresContext, rect); - aKidFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); + // Size and position the view and set its opacity, visibility, content + // transparency, and clip + nsContainerFrame::SyncFrameViewAfterReflow(&aPresContext, aKidFrame, kidView, + &kidDesiredSize.mCombinedArea); + aKidFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); return rv; } @@ -509,15 +523,9 @@ ViewportFrame::Reflow(nsIPresContext& aPresContext, // Reflow the frame kidReflowState.mComputedHeight = aReflowState.availableHeight; ReflowChild(kidFrame, aPresContext, kidDesiredSize, kidReflowState, - aStatus); + 0, 0, 0, aStatus); - nsRect rect(0, 0, kidDesiredSize.width, kidDesiredSize.height); - kidFrame->SetRect(&aPresContext, rect); - kidRect = rect; - - // XXX We should resolve the details of who/when DidReflow() - // notifications are sent... - kidFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); + FinishReflowChild(kidFrame, aPresContext, kidDesiredSize, 0, 0, 0); } // If it's a 'initial', 'resize', or 'style change' reflow command (anything diff --git a/layout/html/document/src/nsFrameFrame.cpp b/layout/html/document/src/nsFrameFrame.cpp index 7f8a070b16ba..7ed495115b34 100644 --- a/layout/html/document/src/nsFrameFrame.cpp +++ b/layout/html/document/src/nsFrameFrame.cpp @@ -360,12 +360,12 @@ nsHTMLFrameOuterFrame::Reflow(nsIPresContext& aPresContext, nsHTMLReflowMetrics kidMetrics(aDesiredSize.maxElementSize); nsHTMLReflowState kidReflowState(aPresContext, aReflowState, firstChild, innerSize); - ReflowChild(firstChild, aPresContext, kidMetrics, kidReflowState, aStatus); + ReflowChild(firstChild, aPresContext, kidMetrics, kidReflowState, + offset.x, offset.y, 0, aStatus); NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status"); // Place and size the child - nsRect rect(offset.x, offset.y, innerSize.width, innerSize.height); - firstChild->SetRect(&aPresContext, rect); + FinishReflowChild(firstChild, aPresContext, kidMetrics, offset.x, offset.y, 0); // XXX what should the max-element-size of an iframe be? Shouldn't // iframe's normally shrink wrap around their content when they diff --git a/layout/html/document/src/nsFrameSetFrame.cpp b/layout/html/document/src/nsFrameSetFrame.cpp index 380bad672c0d..81a64d3b0026 100644 --- a/layout/html/document/src/nsFrameSetFrame.cpp +++ b/layout/html/document/src/nsFrameSetFrame.cpp @@ -234,6 +234,9 @@ nsresult nsHTMLFramesetFrame::QueryInterface(const nsIID& aIID, return nsHTMLContainerFrame::QueryInterface(aIID, aInstancePtr); } +static NS_DEFINE_IID(kViewCID, NS_VIEW_CID); +static NS_DEFINE_IID(kIViewIID, NS_IVIEW_IID); + NS_IMETHODIMP nsHTMLFramesetFrame::Init(nsIPresContext& aPresContext, nsIContent* aContent, @@ -258,6 +261,25 @@ nsHTMLFramesetFrame::Init(nsIPresContext& aPresContext, break; } } + + // create the view. a view is needed since it needs to be a mouse grabber + nsIView* view; + nsresult result = nsComponentManager::CreateInstance(kViewCID, nsnull, kIViewIID, + (void **)&view); + nsCOMPtr presShell; + aPresContext.GetShell(getter_AddRefs(presShell)); + nsCOMPtr viewMan; + presShell->GetViewManager(getter_AddRefs(viewMan)); + + nsIFrame* parWithView; + nsIView *parView; + GetParentWithView(&aPresContext, &parWithView); + parWithView->GetView(&aPresContext, &parView); + nsRect boundBox(0, 0, 0, 0); + result = view->Init(viewMan, boundBox, parView, nsnull); + viewMan->InsertChild(parView, view, 0); + SetView(&aPresContext, view); + return rv; } @@ -785,13 +807,14 @@ nsHTMLFramesetFrame::ReflowPlaceChild(nsIFrame* aChild, metrics.height= aSize.height; nsReflowStatus status; - ReflowChild(aChild, aPresContext, metrics, reflowState, status); + ReflowChild(aChild, aPresContext, metrics, reflowState, aOffset.x, + aOffset.y, 0, status); NS_ASSERTION(NS_FRAME_IS_COMPLETE(status), "bad status"); // Place and size the child - nsRect rect(aOffset.x, aOffset.y, aSize.width, aSize.height); - aChild->SetRect(&aPresContext, rect); - aChild->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); // this call is needed + metrics.width = aSize.width; + metrics.height = aSize.height; + FinishReflowChild(aChild, aPresContext, metrics, aOffset.x, aOffset.y, 0); } static @@ -902,10 +925,6 @@ nscolor nsHTMLFramesetFrame::GetBorderColor(nsIContent* aContent) #define FRAME 1 #define BLANK 2 - -static NS_DEFINE_IID(kViewCID, NS_VIEW_CID); -static NS_DEFINE_IID(kIViewIID, NS_IVIEW_IID); - NS_IMETHODIMP nsHTMLFramesetFrame::Reflow(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, @@ -918,25 +937,6 @@ nsHTMLFramesetFrame::Reflow(nsIPresContext& aPresContext, PRBool firstTime = (0 == mNumRows); if (firstTime) { - // create the view. a view is needed since it needs to be a mouse grabber - - nsIView* view; - nsresult result = nsComponentManager::CreateInstance(kViewCID, nsnull, kIViewIID, - (void **)&view); - nsCOMPtr presShell; - aPresContext.GetShell(getter_AddRefs(presShell)); - nsCOMPtr viewMan; - presShell->GetViewManager(getter_AddRefs(viewMan)); - - nsIFrame* parWithView; - nsIView *parView; - GetParentWithView(&aPresContext, &parWithView); - parWithView->GetView(&aPresContext, &parView); - nsRect boundBox(0, 0, aDesiredSize.width, aDesiredSize.height); - result = view->Init(viewMan, boundBox, parView, nsnull); - viewMan->InsertChild(parView, view, 0); - SetView(&aPresContext, view); - // parse the rows= cols= data ParseRowCol(nsHTMLAtoms::rows, mNumRows, &mRowSpecs); ParseRowCol(nsHTMLAtoms::cols, mNumCols, &mColSpecs); diff --git a/layout/html/forms/src/nsComboboxControlFrame.cpp b/layout/html/forms/src/nsComboboxControlFrame.cpp index fbbca2a812ae..e2ab094b966b 100644 --- a/layout/html/forms/src/nsComboboxControlFrame.cpp +++ b/layout/html/forms/src/nsComboboxControlFrame.cpp @@ -424,14 +424,13 @@ nsComboboxControlFrame::ReflowComboChildFrame(nsIFrame* aFrame, kidReflowState.mComputedHeight = aAvailableHeight; // Reflow child - nsresult rv = ReflowChild(aFrame, aPresContext, aDesiredSize, kidReflowState, aStatus); - - // Set the child's width and height to it's desired size nsRect rect; aFrame->GetRect(rect); - rect.width = aDesiredSize.width; - rect.height = aDesiredSize.height; - aFrame->SetRect(&aPresContext, rect); + nsresult rv = ReflowChild(aFrame, aPresContext, aDesiredSize, kidReflowState, + rect.x, rect.y, 0, aStatus); + + // Set the child's width and height to it's desired size + FinishReflowChild(aFrame, aPresContext, aDesiredSize, rect.x, rect.y, 0); return rv; } diff --git a/layout/html/forms/src/nsFieldSetFrame.cpp b/layout/html/forms/src/nsFieldSetFrame.cpp index 80b331de9a57..74747f03dd34 100644 --- a/layout/html/forms/src/nsFieldSetFrame.cpp +++ b/layout/html/forms/src/nsFieldSetFrame.cpp @@ -318,7 +318,8 @@ nsFieldSetFrame::Reflow(nsIPresContext& aPresContext, legendReflowState.mComputedWidth = NS_INTRINSICSIZE; legendReflowState.mComputedHeight = NS_INTRINSICSIZE; - ReflowChild(mLegendFrame, aPresContext, aDesiredSize, legendReflowState, aStatus); + ReflowChild(mLegendFrame, aPresContext, aDesiredSize, legendReflowState, + 0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus); // get the legend's margin nsIStyleContext* legendSC = nsnull; @@ -354,20 +355,23 @@ nsFieldSetFrame::Reflow(nsIPresContext& aPresContext, if (availSize.width < mLegendRect.width) availSize.width = mLegendRect.width; } - + + // Tell the legend we're done with the reflow. We'll size and place it later on + mLegendFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); } // Try to reflow the area frame into the available space. nsHTMLReflowState contentReflowState(aPresContext, aReflowState, mContentFrame, availSize); - ReflowChild(mContentFrame, aPresContext, aDesiredSize, contentReflowState, aStatus); + ReflowChild(mContentFrame, aPresContext, aDesiredSize, contentReflowState, + borderPadding.left, borderPadding.top + mLegendSpace, 0, aStatus); // set the rect. make sure we add the margin back in. nsRect contentRect(borderPadding.left,borderPadding.top + mLegendSpace,aDesiredSize.width ,aDesiredSize.height); // Place the content area frame. - mContentFrame->SetRect(&aPresContext, contentRect); + FinishReflowChild(mContentFrame, aPresContext, aDesiredSize, contentRect.x, contentRect.y, 0); if (mLegendFrame) { diff --git a/layout/html/forms/src/nsGfxTextControlFrame.cpp b/layout/html/forms/src/nsGfxTextControlFrame.cpp index 913a51cbf444..faffb56297b7 100644 --- a/layout/html/forms/src/nsGfxTextControlFrame.cpp +++ b/layout/html/forms/src/nsGfxTextControlFrame.cpp @@ -1864,6 +1864,12 @@ nsGfxTextControlFrame::Reflow(nsIPresContext& aPresContext, // Send the WillReflow notification, and reflow the child frame mDisplayFrame->WillReflow(aPresContext); + mDisplayFrame->MoveTo(&aPresContext, subBounds.x, subBounds.y); + nsIView* view; + mDisplayFrame->GetView(&aPresContext, &view); + if (view) { + nsContainerFrame::PositionFrameView(&aPresContext, mDisplayFrame, view); + } nsReflowStatus status; rv = mDisplayFrame->Reflow(aPresContext, kidSize, kidReflowState, status); // notice how status is ignored here diff --git a/layout/html/forms/src/nsHTMLButtonControlFrame.cpp b/layout/html/forms/src/nsHTMLButtonControlFrame.cpp index c1b97cc7d9b0..8e8ec5684226 100644 --- a/layout/html/forms/src/nsHTMLButtonControlFrame.cpp +++ b/layout/html/forms/src/nsHTMLButtonControlFrame.cpp @@ -516,6 +516,9 @@ nsHTMLButtonControlFrame::Reflow(nsIPresContext& aPresContext, // the view also breaks the outline code. For some reason you can not reset // the clip rect to draw outside you bounds if you have a view. And you need to // because the outline must be drawn outside of our bounds according to CSS. -EDV + + // XXX If you do decide you need a view, then create it in the Init() function + // and not here... #if 0 if (!mDidInit) { // create our view, we need a view to grab the mouse @@ -596,11 +599,15 @@ nsHTMLButtonControlFrame::Reflow(nsIPresContext& aPresContext, } } - ReflowChild(firstKid, aPresContext, aDesiredSize, reflowState, aStatus); + ReflowChild(firstKid, aPresContext, aDesiredSize, reflowState, + focusPadding.left + aReflowState.mComputedBorderPadding.left, + focusPadding.top + aReflowState.mComputedBorderPadding.top, + 0, aStatus); // Place the child - nsRect rect = nsRect(focusPadding.left + aReflowState.mComputedBorderPadding.left, focusPadding.top + aReflowState.mComputedBorderPadding.top, aDesiredSize.width, aDesiredSize.height); - firstKid->SetRect(&aPresContext, rect); + FinishReflowChild(firstKid, aPresContext, aDesiredSize, + focusPadding.left + aReflowState.mComputedBorderPadding.left, + focusPadding.top + aReflowState.mComputedBorderPadding.top, 0); #if 0 // old way // if computed use the computed values. diff --git a/layout/html/forms/src/nsImageControlFrame.cpp b/layout/html/forms/src/nsImageControlFrame.cpp index 914ecec0f81c..e7836ef7a88d 100644 --- a/layout/html/forms/src/nsImageControlFrame.cpp +++ b/layout/html/forms/src/nsImageControlFrame.cpp @@ -70,6 +70,12 @@ public: NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); + NS_IMETHOD Init(nsIPresContext& aPresContext, + nsIContent* aContent, + nsIFrame* aParent, + nsIStyleContext* aContext, + nsIFrame* aPrevInFlow); + NS_IMETHOD Reflow(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, @@ -202,6 +208,46 @@ nsrefcnt nsImageControlFrame::Release(void) return 1; } +NS_IMETHODIMP +nsImageControlFrame::Init(nsIPresContext& aPresContext, + nsIContent* aContent, + nsIFrame* aParent, + nsIStyleContext* aContext, + nsIFrame* aPrevInFlow) +{ + // call our base class + nsresult rv = nsImageControlFrameSuper::Init(aPresContext, aContent, aParent, + aContext, aPrevInFlow); + + // create our view, we need a view to grab the mouse + nsIView* view; + GetView(&aPresContext, &view); + if (!view) { + nsresult result = nsComponentManager::CreateInstance(kViewCID, nsnull, kIViewIID, (void **)&view); + nsCOMPtr presShell; + aPresContext.GetShell(getter_AddRefs(presShell)); + nsCOMPtr viewMan; + presShell->GetViewManager(getter_AddRefs(viewMan)); + + nsIFrame* parWithView; + nsIView *parView; + GetParentWithView(&aPresContext, &parWithView); + parWithView->GetView(&aPresContext, &parView); + // the view's size is not know yet, but its size will be kept in synch with our frame. + nsRect boundBox(0, 0, 0, 0); + result = view->Init(viewMan, boundBox, parView, nsnull); + view->SetContentTransparency(PR_TRUE); + viewMan->InsertChild(parView, view, 0); + SetView(&aPresContext, view); + + const nsStyleColor* color = (const nsStyleColor*) mStyleContext->GetStyleData(eStyleStruct_Color); + // set the opacity + viewMan->SetViewOpacity(view, color->mOpacity); + } + + return NS_OK; +} + NS_METHOD nsImageControlFrame::Reflow(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, @@ -211,32 +257,6 @@ nsImageControlFrame::Reflow(nsIPresContext& aPresContext, if (!mFormFrame && (eReflowReason_Initial == aReflowState.reason)) { // add ourself as an nsIFormControlFrame nsFormFrame::AddFormControlFrame(aPresContext, *this); - - // create our view, we need a view to grab the mouse - nsIView* view; - GetView(&aPresContext, &view); - if (!view) { - nsresult result = nsComponentManager::CreateInstance(kViewCID, nsnull, kIViewIID, (void **)&view); - nsCOMPtr presShell; - aPresContext.GetShell(getter_AddRefs(presShell)); - nsCOMPtr viewMan; - presShell->GetViewManager(getter_AddRefs(viewMan)); - - nsIFrame* parWithView; - nsIView *parView; - GetParentWithView(&aPresContext, &parWithView); - parWithView->GetView(&aPresContext, &parView); - // the view's size is not know yet, but its size will be kept in synch with our frame. - nsRect boundBox(0, 0, 500, 500); - result = view->Init(viewMan, boundBox, parView, nsnull); - view->SetContentTransparency(PR_TRUE); - viewMan->InsertChild(parView, view, 0); - SetView(&aPresContext, view); - - const nsStyleColor* color = (const nsStyleColor*) mStyleContext->GetStyleData(eStyleStruct_Color); - // set the opacity - viewMan->SetViewOpacity(view, color->mOpacity); - } } return nsImageControlFrameSuper::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); } diff --git a/layout/html/forms/src/nsLabelFrame.cpp b/layout/html/forms/src/nsLabelFrame.cpp index f1794cc9ffbc..bd6cff5879b5 100644 --- a/layout/html/forms/src/nsLabelFrame.cpp +++ b/layout/html/forms/src/nsLabelFrame.cpp @@ -76,6 +76,12 @@ class nsLabelFrame : public nsHTMLContainerFrame public: nsLabelFrame(); + NS_IMETHOD Init(nsIPresContext& aPresContext, + nsIContent* aContent, + nsIFrame* aParent, + nsIStyleContext* aContext, + nsIFrame* aPrevInFlow); + NS_IMETHOD Paint(nsIPresContext& aPresContext, nsIRenderingContext& aRenderingContext, const nsRect& aDirtyRect, @@ -116,7 +122,6 @@ protected: PRBool mControlIsInside; nsIFormControlFrame* mControlFrame; nsRect mTranslatedRect; - PRBool mDidInit; }; nsresult @@ -143,7 +148,6 @@ nsLabelFrame::nsLabelFrame() mControlIsInside = PR_FALSE; mControlFrame = nsnull; mTranslatedRect = nsRect(0,0,0,0); - mDidInit = PR_FALSE; } void @@ -423,6 +427,43 @@ void LabelHack(nsHTMLReflowState& aReflowState, char* aMessage) } } +NS_IMETHODIMP +nsLabelFrame::Init(nsIPresContext& aPresContext, + nsIContent* aContent, + nsIFrame* aParent, + nsIStyleContext* aContext, + nsIFrame* aPrevInFlow) +{ + // call our base class + nsresult rv = nsHTMLContainerFrame::Init(aPresContext, aContent, aParent, + aContext, aPrevInFlow); + + // create our view, we need a view to grab the mouse + nsIView* view; + GetView(&aPresContext, &view); + if (!view) { + nsresult result = nsComponentManager::CreateInstance(kViewCID, nsnull, kIViewIID, + (void **)&view); + nsCOMPtr presShell; + aPresContext.GetShell(getter_AddRefs(presShell)); + nsCOMPtr viewMan; + presShell->GetViewManager(getter_AddRefs(viewMan)); + + nsIFrame* parWithView; + nsIView *parView; + GetParentWithView(&aPresContext, &parWithView); + parWithView->GetView(&aPresContext, &parView); + // the view's size is not know yet, but its size will be kept in synch with our frame. + nsRect boundBox(0, 0, 0, 0); + result = view->Init(viewMan, boundBox, parView, nsnull); + view->SetContentTransparency(PR_TRUE); + viewMan->InsertChild(parView, view, 0); + SetView(&aPresContext, view); + } + + return rv; +} + NS_IMETHODIMP nsLabelFrame::Reflow(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, @@ -431,31 +472,6 @@ nsLabelFrame::Reflow(nsIPresContext& aPresContext, { // XXX remove the following when the reflow state is fixed LabelHack((nsHTMLReflowState&)aReflowState, "BUG - label"); - if (!mDidInit) { - // create our view, we need a view to grab the mouse - nsIView* view; - GetView(&aPresContext, &view); - if (!view) { - nsresult result = nsComponentManager::CreateInstance(kViewCID, nsnull, kIViewIID, - (void **)&view); - nsCOMPtr presShell; - aPresContext.GetShell(getter_AddRefs(presShell)); - nsCOMPtr viewMan; - presShell->GetViewManager(getter_AddRefs(viewMan)); - - nsIFrame* parWithView; - nsIView *parView; - GetParentWithView(&aPresContext, &parWithView); - parWithView->GetView(&aPresContext, &parView); - // the view's size is not know yet, but its size will be kept in synch with our frame. - nsRect boundBox(0, 0, 500, 500); - result = view->Init(viewMan, boundBox, parView, nsnull); - view->SetContentTransparency(PR_TRUE); - viewMan->InsertChild(parView, view, 0); - SetView(&aPresContext, view); - } - mDidInit = PR_TRUE; - } if (nsnull == mControlFrame) { // check to see if a form control is referenced via the "for" attribute @@ -489,11 +505,12 @@ nsLabelFrame::Reflow(nsIPresContext& aPresContext, nsHTMLReflowState reflowState(aPresContext, aReflowState, firstKid, availSize); // XXX remove when reflow state is fixed LabelHack(reflowState, "label's area"); - ReflowChild(firstKid, aPresContext, aDesiredSize, reflowState, aStatus); + ReflowChild(firstKid, aPresContext, aDesiredSize, reflowState, + borderPadding.left, borderPadding.top, 0, aStatus); // Place the child - nsRect rect = nsRect(borderPadding.left, borderPadding.top, aDesiredSize.width, aDesiredSize.height); - firstKid->SetRect(&aPresContext, rect); + FinishReflowChild(firstKid, aPresContext, aDesiredSize, + borderPadding.left, borderPadding.top, 0); // add in our border and padding to the size of the child aDesiredSize.width += borderPadding.left + borderPadding.right; diff --git a/layout/html/table/src/nsTableCellFrame.cpp b/layout/html/table/src/nsTableCellFrame.cpp index 34f1f1bd0a85..4e8e5b7c2cbf 100644 --- a/layout/html/table/src/nsTableCellFrame.cpp +++ b/layout/html/table/src/nsTableCellFrame.cpp @@ -469,6 +469,11 @@ void nsTableCellFrame::VerticallyAlignChild(nsIPresContext* aPresContext) kidYTop = (height - childHeight - bottomInset + topInset) / 2; } firstKid->MoveTo(aPresContext, kidRect.x, kidYTop); + if (kidYTop != kidRect.y) { + // Make sure any child views are correctly positioned. We know the inner table + // cell won't have a view + nsContainerFrame::PositionChildViews(aPresContext, firstKid); + } } PRInt32 nsTableCellFrame::GetRowSpan() @@ -649,8 +654,18 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext& aPresContext, kidReflowState.reflowCommand = nsnull; } + // Assume the inner child will stay positioned exactly where it is. Later in + // VerticallyAlignChild() we'll move it if it turns out to be wrong. This + // avoids excessive movement and is more stable + nsPoint kidOrigin; + if (eReflowReason_Initial == aReflowState.reason) { + kidOrigin.MoveTo(leftInset, topInset); + } else { + firstKid->GetOrigin(kidOrigin); + } if (nsDebugTable::gRflArea) nsTableFrame::DebugReflow("Area::Rfl en", firstKid, &kidReflowState, nsnull); - ReflowChild(firstKid, aPresContext, kidSize, kidReflowState, aStatus); + ReflowChild(firstKid, aPresContext, kidSize, kidReflowState, + kidOrigin.x, kidOrigin.y, 0, aStatus); if (nsDebugTable::gRflArea) nsTableFrame::DebugReflow("Area::Rfl ex", firstKid, nsnull, &kidSize); #ifdef NS_DEBUG @@ -727,8 +742,8 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext& aPresContext, //////////////////////////////// HACK ////////////////////////////// kidSize.width = PR_MIN(kidSize.width, availSize.width); ///////////////////////////// END HACK ///////////////////////////// - firstKid->SetRect(&aPresContext, nsRect(leftInset, topInset, - kidSize.width, kidSize.height)); + FinishReflowChild(firstKid, aPresContext, kidSize, + kidOrigin.x, kidOrigin.y, 0); // Return our size and our result diff --git a/layout/html/table/src/nsTableColGroupFrame.cpp b/layout/html/table/src/nsTableColGroupFrame.cpp index f66f3615af71..45797e978912 100644 --- a/layout/html/table/src/nsTableColGroupFrame.cpp +++ b/layout/html/table/src/nsTableColGroupFrame.cpp @@ -343,9 +343,8 @@ NS_METHOD nsTableColGroupFrame::Reflow(nsIPresContext& aPresContext, nsSize(0,0), eReflowReason_Initial); nsReflowStatus status; - ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, status); - // note that DidReflow is called as the result of some ancestor firing off a DidReflow above me - kidFrame->SetRect(&aPresContext, nsRect(0,0,0,0)); + ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, 0, 0, 0, status); + FinishReflowChild(kidFrame, aPresContext, kidSize, 0, 0, 0); } aDesiredSize.width=0; @@ -454,7 +453,8 @@ NS_METHOD nsTableColGroupFrame::IR_TargetIsChild(nsIPresContext& aPresC nsHTMLReflowState kidReflowState(aPresContext, aReflowState, aNextFrame, nsSize(aReflowState.availableWidth, aReflowState.availableHeight)); - rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, aStatus); + rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, 0, 0, 0, aStatus); + aNextFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); if (NS_FAILED(rv)) return rv; diff --git a/layout/html/table/src/nsTableFrame.cpp b/layout/html/table/src/nsTableFrame.cpp index dbcd835726e3..e043a9ec3f3f 100644 --- a/layout/html/table/src/nsTableFrame.cpp +++ b/layout/html/table/src/nsTableFrame.cpp @@ -1388,7 +1388,8 @@ NS_METHOD nsTableFrame::ResizeReflowPass1(nsIPresContext& aPresContext, nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame, availSize, aReason); // rv intentionally not set here - ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, aStatus); + ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, 0, 0, 0, aStatus); + kidFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); continue; } nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame, @@ -1396,10 +1397,10 @@ NS_METHOD nsTableFrame::ResizeReflowPass1(nsIPresContext& aPresContext, // Note: we don't bother checking here for whether we should clear the // isTopOfPage reflow state flag, because we're dealing with an unconstrained // height and it isn't an issue... - ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, aStatus); + ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, 0, 0, 0, aStatus); // Place the child since some of its content fit in us. - kidFrame->SetRect(&aPresContext, nsRect(0, 0, kidSize.width, kidSize.height)); + FinishReflowChild(kidFrame, aPresContext, kidSize, 0, 0, 0); if (NS_UNCONSTRAINEDSIZE==kidSize.height) y = NS_UNCONSTRAINEDSIZE; else @@ -1428,8 +1429,8 @@ NS_METHOD nsTableFrame::ResizeReflowPass1(nsIPresContext& aPresContext, { nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame, availSize, aReason); - ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, aStatus); - kidFrame->SetRect(&aPresContext, nsRect(0, 0, 0, 0)); + ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, 0, 0, 0, aStatus); + FinishReflowChild(kidFrame, aPresContext, kidSize, 0, 0, 0); } } } @@ -2356,22 +2357,23 @@ NS_METHOD nsTableFrame::IR_TargetIsChild(nsIPresContext& aPresContext, nsHTMLReflowState kidReflowState(aPresContext, aReflowState.reflowState, aNextFrame, aReflowState.availSize); - rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, aStatus); + nscoord x = aReflowState.mBorderPadding.left; + nscoord y = aReflowState.mBorderPadding.top + aReflowState.y; + rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, + x, y, 0, aStatus); // Place the row group frame. Don't use PlaceChild(), because it moves // the footer frame as well. We'll adjust the footer frame later on in // AdjustSiblingsAfterReflow() - nscoord x = aReflowState.mBorderPadding.left; - nscoord y = aReflowState.mBorderPadding.top + aReflowState.y; nsRect kidRect(x, y, desiredSize.width, desiredSize.height); - aNextFrame->SetRect(&aPresContext, kidRect); + FinishReflowChild(aNextFrame, aPresContext, desiredSize, x, y, 0); // Adjust the running y-offset - aReflowState.y += kidRect.height; + aReflowState.y += desiredSize.height; // If our height is constrained, then update the available height if (PR_FALSE == aReflowState.unconstrainedHeight) { - aReflowState.availSize.height -= kidRect.height; + aReflowState.availSize.height -= desiredSize.height; } // Update the max element size @@ -2459,22 +2461,24 @@ nscoord nsTableFrame::ComputeDesiredWidth(const nsHTMLReflowState& aReflowState) // Position and size aKidFrame and update our reflow state. The origin of // aKidRect is relative to the upper-left origin of our frame -void nsTableFrame::PlaceChild(nsIPresContext& aPresContext, +void nsTableFrame::PlaceChild(nsIPresContext& aPresContext, InnerTableReflowState& aReflowState, - nsIFrame* aKidFrame, - const nsRect& aKidRect, - nsSize* aMaxElementSize, - nsSize& aKidMaxElementSize) + nsIFrame* aKidFrame, + nsHTMLReflowMetrics& aDesiredSize, + nscoord aX, + nscoord aY, + nsSize* aMaxElementSize, + nsSize& aKidMaxElementSize) { // Place and size the child - aKidFrame->SetRect(&aPresContext, aKidRect); + FinishReflowChild(aKidFrame, aPresContext, aDesiredSize, aX, aY, 0); // Adjust the running y-offset - aReflowState.y += aKidRect.height; + aReflowState.y += aDesiredSize.height; // If our height is constrained, then update the available height if (PR_FALSE == aReflowState.unconstrainedHeight) { - aReflowState.availSize.height -= aKidRect.height; + aReflowState.availSize.height -= aDesiredSize.height; } // If this is a footer row group, remember it @@ -2500,7 +2504,7 @@ void nsTableFrame::PlaceChild(nsIPresContext& aPresContext, // Move the footer below the body row group frame aReflowState.footerFrame->GetOrigin(origin); - origin.y += aKidRect.height; + origin.y += aDesiredSize.height; aReflowState.footerFrame->MoveTo(&aPresContext, origin.x, origin.y); } @@ -2606,7 +2610,8 @@ NS_METHOD nsTableFrame::ReflowMappedChildren(nsIPresContext& aPresContext, } } - rv = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, aStatus); + rv = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, + x, y, 0, aStatus); // Did the child fit? if (desiredSize.height > kidAvailSize.height) { if (aReflowState.firstBodySection && (kidFrame != aReflowState.firstBodySection)) { @@ -2619,7 +2624,6 @@ NS_METHOD nsTableFrame::ReflowMappedChildren(nsIPresContext& aPresContext, } // Place the child - nsRect kidRect (x, y, desiredSize.width, desiredSize.height); if (PR_TRUE==IsRowGroup(childDisplay->mDisplay)) { // we don't want to adjust the maxElementSize if this is an initial reflow @@ -2627,8 +2631,10 @@ NS_METHOD nsTableFrame::ReflowMappedChildren(nsIPresContext& aPresContext, nsSize *requestedMaxElementSize = nsnull; if (eReflowReason_Initial != aReflowState.reflowState.reason) requestedMaxElementSize = aDesiredSize.maxElementSize; - PlaceChild(aPresContext, aReflowState, kidFrame, kidRect, - requestedMaxElementSize, kidMaxElementSize); + PlaceChild(aPresContext, aReflowState, kidFrame, desiredSize, + x, y, requestedMaxElementSize, kidMaxElementSize); + } else { + kidFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); } childCount++; @@ -2677,7 +2683,9 @@ NS_METHOD nsTableFrame::ReflowMappedChildren(nsIPresContext& aPresContext, aReflowState.reflowState, kidFrame, nsSize(0,0), eReflowReason_Resize); nsHTMLReflowMetrics unusedDesiredSize(nsnull); - ReflowChild(kidFrame, aPresContext, unusedDesiredSize, kidReflowState, aStatus); + ReflowChild(kidFrame, aPresContext, unusedDesiredSize, kidReflowState, + 0, 0, 0, aStatus); + kidFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); } // Get the next child @@ -2749,7 +2757,8 @@ NS_METHOD nsTableFrame::PullUpChildren(nsIPresContext& aPresContext, kidFrame, aReflowState.availSize, eReflowReason_Resize); - rv = ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, aStatus); + rv = ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, + 0, aReflowState.y, 0, aStatus); // Did the child fit? if ((kidSize.height > aReflowState.availSize.height) && mFrames.NotEmpty()) { @@ -2760,13 +2769,14 @@ NS_METHOD nsTableFrame::PullUpChildren(nsIPresContext& aPresContext, break; } - nsRect kidRect (0, 0, kidSize.width, kidSize.height); - kidRect.y += aReflowState.y; const nsStyleDisplay *childDisplay; kidFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)childDisplay)); if (PR_TRUE==IsRowGroup(childDisplay->mDisplay)) { - PlaceChild(aPresContext, aReflowState, kidFrame, kidRect, aDesiredSize.maxElementSize, *pKidMaxElementSize); + PlaceChild(aPresContext, aReflowState, kidFrame, kidSize, 0, + aReflowState.y, aDesiredSize.maxElementSize, *pKidMaxElementSize); + } else { + kidFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); } // Remove the frame from its current parent diff --git a/layout/html/table/src/nsTableFrame.h b/layout/html/table/src/nsTableFrame.h index 907276e7f100..0e23d6746335 100644 --- a/layout/html/table/src/nsTableFrame.h +++ b/layout/html/table/src/nsTableFrame.h @@ -505,7 +505,9 @@ protected: void PlaceChild(nsIPresContext& aPresContext, InnerTableReflowState& aReflowState, nsIFrame* aKidFrame, - const nsRect& aKidRect, + nsHTMLReflowMetrics& aDesiredSize, + nscoord aX, + nscoord aY, nsSize* aMaxElementSize, nsSize& aKidMaxElementSize); diff --git a/layout/html/table/src/nsTableOuterFrame.cpp b/layout/html/table/src/nsTableOuterFrame.cpp index 8de208c16c93..50ed912ed757 100644 --- a/layout/html/table/src/nsTableOuterFrame.cpp +++ b/layout/html/table/src/nsTableOuterFrame.cpp @@ -403,7 +403,10 @@ nsresult nsTableOuterFrame::IR_TargetIsCaptionFrame(nsIPresContext& aPres nsSize(mRect.width, aReflowState.reflowState.availableHeight), aReflowState.reflowState.reason); captionReflowState.reflowCommand = aReflowState.reflowState.reflowCommand; - rv = ReflowChild(mCaptionFrame, aPresContext, captionSize, captionReflowState, aStatus); + + rv = ReflowChild(mCaptionFrame, aPresContext, captionSize, captionReflowState, + 0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus); + mCaptionFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); if (NS_FAILED(rv)) { return rv; } @@ -440,7 +443,9 @@ nsresult nsTableOuterFrame::IR_TargetIsCaptionFrame(nsIPresContext& aPres nsHTMLReflowState innerReflowState(aPresContext, aReflowState.reflowState, mInnerTableFrame, nsSize(tableWidth, aReflowState.reflowState.availableHeight), eReflowReason_Resize); - rv = ReflowChild(mInnerTableFrame, aPresContext, innerSize, innerReflowState, aStatus); + rv = ReflowChild(mInnerTableFrame, aPresContext, innerSize, innerReflowState, + 0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus); + mInnerTableFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); if (NS_FAILED(rv)) { return rv; } @@ -579,7 +584,9 @@ nsresult nsTableOuterFrame::IR_InnerTableReflow(nsIPresContext& aPresCont nscoord tableMaxWidth = PR_MAX(aReflowState.reflowState.availableWidth, mMinCaptionWidth); nsHTMLReflowState innerReflowState(aPresContext, aReflowState.reflowState, mInnerTableFrame, nsSize(tableMaxWidth, aReflowState.reflowState.availableHeight)); - rv = ReflowChild(mInnerTableFrame, aPresContext, innerSize, innerReflowState, aStatus); + rv = ReflowChild(mInnerTableFrame, aPresContext, innerSize, innerReflowState, + 0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus); + mInnerTableFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); // if there is a caption and the width or height of the inner table changed from a successful reflow, // then reflow or move the caption as needed if ((nsnull != mCaptionFrame) && (PR_TRUE==NS_SUCCEEDED(rv))) { @@ -597,6 +604,7 @@ nsresult nsTableOuterFrame::IR_InnerTableReflow(nsIPresContext& aPresCont // reflow the caption mCaptionFrame->WillReflow(aPresContext); rv = mCaptionFrame->Reflow(aPresContext, captionSize, captionReflowState, aStatus); + mCaptionFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); captionWasReflowed = PR_TRUE; if ((oldCaptionRect.height!=captionSize.height) || (oldCaptionRect.width!=captionSize.width)) { @@ -694,7 +702,9 @@ nsresult nsTableOuterFrame::IR_CaptionInserted(nsIPresContext& aPresConte nsHTMLReflowState innerReflowState(aPresContext, aReflowState.reflowState, mInnerTableFrame, nsSize(mMinCaptionWidth, aReflowState.reflowState.availableHeight), eReflowReason_Resize); - rv = ReflowChild(mInnerTableFrame, aPresContext, innerSize, innerReflowState, aStatus); + rv = ReflowChild(mInnerTableFrame, aPresContext, innerSize, innerReflowState, + 0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus); + mInnerTableFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); } else { // set innerSize as if the inner table were reflowed innerSize.height = mRect.height; @@ -868,6 +878,7 @@ NS_METHOD nsTableOuterFrame::Reflow(nsIPresContext& aPresContext, mCaptionFrame->WillReflow(aPresContext); rv = mCaptionFrame->Reflow(aPresContext, captionSize, captionReflowState, aStatus); + mCaptionFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); mMinCaptionWidth = maxElementSize.width; } } @@ -896,8 +907,11 @@ NS_METHOD nsTableOuterFrame::Reflow(nsIPresContext& aPresContext, } innerReflowState.mComputedHeight = aReflowState.mComputedHeight; nsHTMLReflowMetrics innerSize(aDesiredSize.maxElementSize); - - rv = ReflowChild(mInnerTableFrame, aPresContext, innerSize, innerReflowState, aStatus); + // XXX To do this efficiently we really need to know where the inner + // table will be placed. In the case of a top caption that means + // reflowing the caption first and getting its desired height... + rv = ReflowChild(mInnerTableFrame, aPresContext, innerSize, innerReflowState, + 0, 0, 0, aStatus); // Table's max element size is the MAX of the caption's max element size // and the inner table's max element size... @@ -910,6 +924,7 @@ NS_METHOD nsTableOuterFrame::Reflow(nsIPresContext& aPresContext, // Now that we know the table width we can reflow the caption, and // place the caption and the inner table + nscoord innerY = 0; if (nsnull != mCaptionFrame) { // Get the caption's margin nsMargin captionMargin; @@ -934,9 +949,8 @@ NS_METHOD nsTableOuterFrame::Reflow(nsIPresContext& aPresContext, nsRect captionRect(captionMargin.left, captionY, 0, 0); nsReflowStatus captionStatus; - mCaptionFrame->WillReflow(aPresContext); - mCaptionFrame->Reflow(aPresContext, captionSize, captionReflowState, - captionStatus); + ReflowChild(mCaptionFrame, aPresContext, captionSize, captionReflowState, + captionRect.x, captionRect.y, 0, captionStatus); NS_ASSERTION(NS_FRAME_IS_COMPLETE(captionStatus), "unexpected reflow status"); // XXX If the height is constrained then we need to check whether the inner @@ -944,10 +958,10 @@ NS_METHOD nsTableOuterFrame::Reflow(nsIPresContext& aPresContext, // Place the caption captionRect.SizeTo(captionSize.width, captionSize.height); - mCaptionFrame->SetRect(&aPresContext, captionRect); + FinishReflowChild(mCaptionFrame, aPresContext, captionSize, + captionRect.x, captionRect.y, 0); // Place the inner table - nscoord innerY; if (NS_SIDE_BOTTOM != captionTableStyle->mCaptionSide) { // top caption innerY = captionRect.YMost() + captionMargin.bottom; @@ -958,16 +972,17 @@ NS_METHOD nsTableOuterFrame::Reflow(nsIPresContext& aPresContext, innerY = 0; state.y = captionRect.YMost() + captionMargin.bottom; } - nsRect innerRect(0, innerY, innerSize.width, innerSize.height); - mInnerTableFrame->SetRect(&aPresContext, innerRect); } else { - // Place the inner table - nsRect innerRect(0, 0, innerSize.width, innerSize.height); - mInnerTableFrame->SetRect(&aPresContext, innerRect); + // Place the inner table at 0 + innerY = 0; state.y = innerSize.height; } + + // Finish the inner table reflow + FinishReflowChild(mInnerTableFrame, aPresContext, innerSize, + 0, innerY, 0); } // Return our desired rect @@ -980,38 +995,6 @@ NS_METHOD nsTableOuterFrame::Reflow(nsIPresContext& aPresContext, return rv; } -// Position and size aKidFrame and update our reflow state. The origin of -// aKidRect is relative to the upper-left origin of our frame, and includes -// any left/top margin. -void nsTableOuterFrame::PlaceChild(OuterTableReflowState& aReflowState, - nsIFrame* aKidFrame, - const nsRect& aKidRect, - nsSize* aMaxElementSize, - nsSize& aKidMaxElementSize) -{ - // Place and size the child - aKidFrame->SetRect(aReflowState.pc, aKidRect); - - // Adjust the running y-offset - aReflowState.y += aKidRect.height; - - // If our height is constrained then update the available height - if (PR_FALSE == aReflowState.unconstrainedHeight) { - aReflowState.availSize.height -= aKidRect.height; - } - - /* Update the maximum element size, which is the max of: - * the maxElementSize of our first row - * or the maxElementSize of the caption if we include it - */ - if (aKidFrame == mCaptionFrame) { - if (nsnull != aMaxElementSize) { - aMaxElementSize->width = aKidMaxElementSize.width; - aMaxElementSize->height = aKidMaxElementSize.height; - } - } -} - NS_METHOD nsTableOuterFrame::VerifyTree() const { return NS_OK; diff --git a/layout/html/table/src/nsTableOuterFrame.h b/layout/html/table/src/nsTableOuterFrame.h index f46350e41f35..2e01bb5b0ded 100644 --- a/layout/html/table/src/nsTableOuterFrame.h +++ b/layout/html/table/src/nsTableOuterFrame.h @@ -137,25 +137,6 @@ protected: */ PRBool NeedsReflow(const nsHTMLReflowState& aReflowState); - /** position the child frame - * @param aReflowState the state of the reflow process - * @param aKidFrame the frame to place. - * @param aKidRect the computed dimensions of aKidFrame. The origin of aKidRect - * is relative to the upper-left origin of this frame. - * @param aMaxElementSize the table's maxElementSize - * may be nsnull, meaning that we're not computing maxElementSize during this reflow - * set to the caption's maxElementSize, if aKidFrame is the caption - * the tables maxElementSize eventually gets set to the max of - * the value here and the value of the inner table, elsewhere during reflow. - * @param aKidMaxElementSize the maxElementSize of aKidFrame, if available - */ - void PlaceChild(OuterTableReflowState& aReflowState, - nsIFrame* aKidFrame, - const nsRect& aKidRect, - nsSize* aMaxElementSize, - nsSize& aKidMaxElementSize); - - /** compute the width available to the table during reflow, based on * the reflow state and the table's style. * @return the computed width diff --git a/layout/html/table/src/nsTableRowFrame.cpp b/layout/html/table/src/nsTableRowFrame.cpp index 13cc68b09e8e..3cea7765e8de 100644 --- a/layout/html/table/src/nsTableRowFrame.cpp +++ b/layout/html/table/src/nsTableRowFrame.cpp @@ -334,6 +334,9 @@ nsTableRowFrame::DidResize(nsIPresContext& aPresContext, cellFrame->GetSize(cellFrameSize); //if (cellFrameSize.height!=cellHeight) { + // XXX If the cell frame has a view, then we need to resize + // it as well. We would like to only do that if the cell's size + // is changing. Why is the 'if' stmt above commented out? cellFrame->SizeTo(&aPresContext, cellFrameSize.width, cellHeight); // realign cell content based on the new height /*nsHTMLReflowMetrics desiredSize(nsnull); @@ -595,18 +598,20 @@ void nsTableRowFrame::FixMinCellHeight(nsTableFrame *aTableFrame) // Position and size aKidFrame and update our reflow state. The origin of // aKidRect is relative to the upper-left origin of our frame, and includes // any left/top margin. -void nsTableRowFrame::PlaceChild(nsIPresContext& aPresContext, - RowReflowState& aReflowState, - nsIFrame* aKidFrame, - const nsRect& aKidRect, - nsSize* aMaxElementSize, - nsSize* aKidMaxElementSize) +void nsTableRowFrame::PlaceChild(nsIPresContext& aPresContext, + RowReflowState& aReflowState, + nsIFrame* aKidFrame, + nsHTMLReflowMetrics& aDesiredSize, + nscoord aX, + nscoord aY, + nsSize* aMaxElementSize, + nsSize* aKidMaxElementSize) { - // Place and size the child - aKidFrame->SetRect(&aPresContext, aKidRect); + // Complete the reflow + FinishReflowChild(aKidFrame, aPresContext, aDesiredSize, aX, aY, 0); // update the running total for the row width - aReflowState.x += aKidRect.width; + aReflowState.x += aDesiredSize.width; // Update the maximum element size PRInt32 rowSpan = aReflowState.tableFrame->GetEffectiveRowSpan((nsTableCellFrame*)aKidFrame); @@ -644,14 +649,14 @@ void nsTableRowFrame::PlaceChild(nsIPresContext& aPresContext, #else if (1 == rowSpan) { // Update maxCellHeight - if (aKidRect.height > aReflowState.maxCellHeight) - aReflowState.maxCellHeight = aKidRect.height; + if (aDesiredSize.height > aReflowState.maxCellHeight) + aReflowState.maxCellHeight = aDesiredSize.height; // Update maxCellVertSpace nsMargin margin; if (aReflowState.tableFrame->GetCellMarginData((nsTableCellFrame *)aKidFrame, margin) == NS_OK) { - nscoord height = aKidRect.height + margin.top + margin.bottom; + nscoord height = aDesiredSize.height + margin.top + margin.bottom; if (height > aReflowState.maxCellVertSpace) aReflowState.maxCellVertSpace = height; @@ -887,7 +892,8 @@ NS_METHOD nsTableRowFrame::ResizeReflow(nsIPresContext& aPresContext, kidAvailSize, reason); nsReflowStatus status; - rv = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, status); + rv = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, + aReflowState.x, GetChildMaxTopMargin(), 0, status); #ifdef NS_DEBUG if (desiredSize.width > availWidth) { @@ -925,10 +931,8 @@ NS_METHOD nsTableRowFrame::ResizeReflow(nsIPresContext& aPresContext, desiredSize.height, availWidth); // Place the child - nsRect kidRect (aReflowState.x, GetChildMaxTopMargin(), desiredSize.width, - desiredSize.height); - - PlaceChild(aPresContext, aReflowState, kidFrame, kidRect, + PlaceChild(aPresContext, aReflowState, kidFrame, desiredSize, + aReflowState.x, GetChildMaxTopMargin(), aDesiredSize.maxElementSize, kidMaxElementSize); } @@ -939,7 +943,8 @@ NS_METHOD nsTableRowFrame::ResizeReflow(nsIPresContext& aPresContext, nsSize(0,0), eReflowReason_Resize); nsHTMLReflowMetrics desiredSize(nsnull); nsReflowStatus status; - ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, status); + ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, 0, 0, 0, status); + kidFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); } } @@ -1037,7 +1042,8 @@ nsTableRowFrame::InitialReflow(nsIPresContext& aPresContext, kidFrame, kidAvailSize, eReflowReason_Initial); - rv = ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, aStatus); + rv = ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, + x + kidMargin.left, kidMargin.top, 0, aStatus); // the following signals bugs in the content frames. if (kidMaxElementSize.width > kidSize.width) { @@ -1057,9 +1063,8 @@ nsTableRowFrame::InitialReflow(nsIPresContext& aPresContext, // Place the child x += kidMargin.left; - nsRect kidRect(x, kidMargin.top, kidSize.width, kidSize.height); - PlaceChild(aPresContext, aReflowState, kidFrame, kidRect, aDesiredSize.maxElementSize, - &kidMaxElementSize); + PlaceChild(aPresContext, aReflowState, kidFrame, kidSize, x, kidMargin.top, + aDesiredSize.maxElementSize, &kidMaxElementSize); x += kidSize.width + kidMargin.right; } else @@ -1067,7 +1072,8 @@ nsTableRowFrame::InitialReflow(nsIPresContext& aPresContext, nsHTMLReflowState kidReflowState(aPresContext, aReflowState.reflowState, kidFrame, nsSize(0,0), eReflowReason_Initial); nsHTMLReflowMetrics desiredSize(nsnull); - ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, aStatus); + ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, 0, 0, 0, aStatus); + kidFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); } if (PR_FALSE==aDoSiblings) break; @@ -1291,7 +1297,8 @@ NS_METHOD nsTableRowFrame::IR_TargetIsChild(nsIPresContext& aPresContext, // Reflow the cell passing it the incremental reflow command. We can't pass // in a max width of NS_UNCONSTRAINEDSIZE, because the max width must match // the width of the previous reflow... - rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, aStatus); + rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, + aReflowState.x, GetChildMaxTopMargin(), 0, aStatus); //XXX: this is a hack, shouldn't it be the case that a min size is // never larger than a desired size? @@ -1325,7 +1332,8 @@ NS_METHOD nsTableRowFrame::IR_TargetIsChild(nsIPresContext& aPresContext, kidReflowState.reason = eReflowReason_Initial; kidReflowState.reflowCommand = nsnull; kidReflowState.availableWidth = NS_UNCONSTRAINEDSIZE; - rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, aStatus); + rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, + aReflowState.x, GetChildMaxTopMargin(), 0, aStatus); //XXX: this is a hack, shouldn't it be the case that a min size is // never larger than a desired size? @@ -1355,7 +1363,8 @@ NS_METHOD nsTableRowFrame::IR_TargetIsChild(nsIPresContext& aPresContext, // again this time constraining the width back to the column width again kidReflowState.reason = eReflowReason_Resize; kidReflowState.availableWidth = cellAvailWidth; - rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, aStatus); + rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, + aReflowState.x, GetChildMaxTopMargin(), 0, aStatus); } else { // The column widths need to be rebalanced, so don't waste time reflowing @@ -1371,10 +1380,8 @@ NS_METHOD nsTableRowFrame::IR_TargetIsChild(nsIPresContext& aPresContext, cellAvailWidth); // Now place the child - nsRect kidRect (aReflowState.x, GetChildMaxTopMargin(), desiredSize.width, - desiredSize.height); - PlaceChild(aPresContext, aReflowState, aNextFrame, kidRect, - aDesiredSize.maxElementSize, &kidMaxElementSize); + PlaceChild(aPresContext, aReflowState, aNextFrame, desiredSize, aReflowState.x, + GetChildMaxTopMargin(), aDesiredSize.maxElementSize, &kidMaxElementSize); SetMaxChildHeight(aReflowState.maxCellHeight); @@ -1517,9 +1524,11 @@ void nsTableRowFrame::ReflowCellFrame(nsIPresContext& aPresContext, eReflowReason_Resize); nsHTMLReflowMetrics desiredSize(nsnull); - ReflowChild(aCellFrame, aPresContext, desiredSize, cellReflowState, aStatus); + ReflowChild(aCellFrame, aPresContext, desiredSize, cellReflowState, + 0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus); aCellFrame->SizeTo(&aPresContext, cellSize.width, aAvailableHeight); aCellFrame->VerticallyAlignChild(&aPresContext); + aCellFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); } /** diff --git a/layout/html/table/src/nsTableRowFrame.h b/layout/html/table/src/nsTableRowFrame.h index 1db66fa5286f..ff964cf08d2d 100644 --- a/layout/html/table/src/nsTableRowFrame.h +++ b/layout/html/table/src/nsTableRowFrame.h @@ -248,12 +248,14 @@ protected: nsIFrame* aKidFrame, nsSize* aMaxElementSize); - void PlaceChild(nsIPresContext& aPresContext, - RowReflowState& aState, - nsIFrame* aKidFrame, - const nsRect& aKidRect, - nsSize* aMaxElementSize, - nsSize* aKidMaxElementSize); + void PlaceChild(nsIPresContext& aPresContext, + RowReflowState& aState, + nsIFrame* aKidFrame, + nsHTMLReflowMetrics& aDesiredSize, + nscoord aX, + nscoord aY, + nsSize* aMaxElementSize, + nsSize* aKidMaxElementSize); nscoord ComputeCellXOffset(const RowReflowState& aState, nsIFrame* aKidFrame, diff --git a/layout/html/table/src/nsTableRowGroupFrame.cpp b/layout/html/table/src/nsTableRowGroupFrame.cpp index 23b60c0015a1..2cd4983eebf1 100644 --- a/layout/html/table/src/nsTableRowGroupFrame.cpp +++ b/layout/html/table/src/nsTableRowGroupFrame.cpp @@ -342,19 +342,21 @@ nsTableRowGroupFrame::GetFrameForPoint(nsIPresContext* aPresContext, void nsTableRowGroupFrame::PlaceChild(nsIPresContext& aPresContext, RowGroupReflowState& aReflowState, nsIFrame* aKidFrame, - const nsRect& aKidRect, + nsHTMLReflowMetrics& aDesiredSize, + nscoord aX, + nscoord aY, nsSize* aMaxElementSize, nsSize& aKidMaxElementSize) { // Place and size the child - aKidFrame->SetRect(&aPresContext, aKidRect); + FinishReflowChild(aKidFrame, aPresContext, aDesiredSize, aX, aY, 0); // Adjust the running y-offset - aReflowState.y += aKidRect.height; + aReflowState.y += aDesiredSize.height; // If our height is constrained then update the available height if (PR_FALSE == aReflowState.unconstrainedHeight) { - aReflowState.availSize.height -= aKidRect.height; + aReflowState.availSize.height -= aDesiredSize.height; } // Update the maximum element size @@ -457,12 +459,13 @@ NS_METHOD nsTableRowGroupFrame::ReflowMappedChildren(nsIPresContext& aPresC } } - rv = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, aStatus); + rv = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, + 0, aReflowState.y, 0, aStatus); // Place the child nsRect kidRect (0, aReflowState.y, desiredSize.width, desiredSize.height); - PlaceChild(aPresContext, aReflowState, kidFrame, kidRect, aDesiredSize.maxElementSize, - kidMaxElementSize); + PlaceChild(aPresContext, aReflowState, kidFrame, desiredSize, 0, + aReflowState.y, aDesiredSize.maxElementSize, kidMaxElementSize); /* if the table has collapsing borders, we need to reset the length of the shared vertical borders * for the table and the cells that overlap this row @@ -877,8 +880,10 @@ nsTableRowGroupFrame::SplitRowGroup(nsIPresContext& aPresContext, availSize, eReflowReason_Resize); nsHTMLReflowMetrics desiredSize(nsnull); - rv = ReflowChild(rowFrame, aPresContext, desiredSize, rowReflowState, aStatus); + rv = ReflowChild(rowFrame, aPresContext, desiredSize, rowReflowState, + 0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus); rowFrame->SizeTo(&aPresContext, desiredSize.width, desiredSize.height); + rowFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); ((nsTableRowFrame *)rowFrame)->DidResize(aPresContext, aReflowState); aDesiredSize.height = desiredSize.height; @@ -1507,12 +1512,13 @@ NS_METHOD nsTableRowGroupFrame::IR_TargetIsChild(nsIPresContext& aPresConte nsSize kidMaxElementSize; nsHTMLReflowMetrics desiredSize(aDesiredSize.maxElementSize ? &kidMaxElementSize : nsnull); - rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, aStatus); + rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, + 0, aReflowState.y, 0, aStatus); // Place the row frame nsRect kidRect(0, aReflowState.y, desiredSize.width, desiredSize.height); - PlaceChild(aPresContext, aReflowState, aNextFrame, kidRect, - aDesiredSize.maxElementSize, kidMaxElementSize); + PlaceChild(aPresContext, aReflowState, aNextFrame, desiredSize, 0, + aReflowState.y, aDesiredSize.maxElementSize, kidMaxElementSize); // See if the table needs a reflow (e.g., if the column widths have // changed). If so, just return and don't bother adjusting the rows diff --git a/layout/html/table/src/nsTableRowGroupFrame.h b/layout/html/table/src/nsTableRowGroupFrame.h index 607f27e2bf81..80cd29f3fd72 100644 --- a/layout/html/table/src/nsTableRowGroupFrame.h +++ b/layout/html/table/src/nsTableRowGroupFrame.h @@ -205,7 +205,9 @@ protected: void PlaceChild(nsIPresContext& aPresContext, RowGroupReflowState& aReflowState, nsIFrame* aKidFrame, - const nsRect& aKidRect, + nsHTMLReflowMetrics& aDesiredSize, + nscoord aX, + nscoord aY, nsSize* aMaxElementSize, nsSize& aKidMaxElementSize); diff --git a/layout/tables/nsTableCellFrame.cpp b/layout/tables/nsTableCellFrame.cpp index 34f1f1bd0a85..4e8e5b7c2cbf 100644 --- a/layout/tables/nsTableCellFrame.cpp +++ b/layout/tables/nsTableCellFrame.cpp @@ -469,6 +469,11 @@ void nsTableCellFrame::VerticallyAlignChild(nsIPresContext* aPresContext) kidYTop = (height - childHeight - bottomInset + topInset) / 2; } firstKid->MoveTo(aPresContext, kidRect.x, kidYTop); + if (kidYTop != kidRect.y) { + // Make sure any child views are correctly positioned. We know the inner table + // cell won't have a view + nsContainerFrame::PositionChildViews(aPresContext, firstKid); + } } PRInt32 nsTableCellFrame::GetRowSpan() @@ -649,8 +654,18 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext& aPresContext, kidReflowState.reflowCommand = nsnull; } + // Assume the inner child will stay positioned exactly where it is. Later in + // VerticallyAlignChild() we'll move it if it turns out to be wrong. This + // avoids excessive movement and is more stable + nsPoint kidOrigin; + if (eReflowReason_Initial == aReflowState.reason) { + kidOrigin.MoveTo(leftInset, topInset); + } else { + firstKid->GetOrigin(kidOrigin); + } if (nsDebugTable::gRflArea) nsTableFrame::DebugReflow("Area::Rfl en", firstKid, &kidReflowState, nsnull); - ReflowChild(firstKid, aPresContext, kidSize, kidReflowState, aStatus); + ReflowChild(firstKid, aPresContext, kidSize, kidReflowState, + kidOrigin.x, kidOrigin.y, 0, aStatus); if (nsDebugTable::gRflArea) nsTableFrame::DebugReflow("Area::Rfl ex", firstKid, nsnull, &kidSize); #ifdef NS_DEBUG @@ -727,8 +742,8 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext& aPresContext, //////////////////////////////// HACK ////////////////////////////// kidSize.width = PR_MIN(kidSize.width, availSize.width); ///////////////////////////// END HACK ///////////////////////////// - firstKid->SetRect(&aPresContext, nsRect(leftInset, topInset, - kidSize.width, kidSize.height)); + FinishReflowChild(firstKid, aPresContext, kidSize, + kidOrigin.x, kidOrigin.y, 0); // Return our size and our result diff --git a/layout/tables/nsTableColGroupFrame.cpp b/layout/tables/nsTableColGroupFrame.cpp index f66f3615af71..45797e978912 100644 --- a/layout/tables/nsTableColGroupFrame.cpp +++ b/layout/tables/nsTableColGroupFrame.cpp @@ -343,9 +343,8 @@ NS_METHOD nsTableColGroupFrame::Reflow(nsIPresContext& aPresContext, nsSize(0,0), eReflowReason_Initial); nsReflowStatus status; - ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, status); - // note that DidReflow is called as the result of some ancestor firing off a DidReflow above me - kidFrame->SetRect(&aPresContext, nsRect(0,0,0,0)); + ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, 0, 0, 0, status); + FinishReflowChild(kidFrame, aPresContext, kidSize, 0, 0, 0); } aDesiredSize.width=0; @@ -454,7 +453,8 @@ NS_METHOD nsTableColGroupFrame::IR_TargetIsChild(nsIPresContext& aPresC nsHTMLReflowState kidReflowState(aPresContext, aReflowState, aNextFrame, nsSize(aReflowState.availableWidth, aReflowState.availableHeight)); - rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, aStatus); + rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, 0, 0, 0, aStatus); + aNextFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); if (NS_FAILED(rv)) return rv; diff --git a/layout/tables/nsTableFrame.cpp b/layout/tables/nsTableFrame.cpp index dbcd835726e3..e043a9ec3f3f 100644 --- a/layout/tables/nsTableFrame.cpp +++ b/layout/tables/nsTableFrame.cpp @@ -1388,7 +1388,8 @@ NS_METHOD nsTableFrame::ResizeReflowPass1(nsIPresContext& aPresContext, nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame, availSize, aReason); // rv intentionally not set here - ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, aStatus); + ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, 0, 0, 0, aStatus); + kidFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); continue; } nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame, @@ -1396,10 +1397,10 @@ NS_METHOD nsTableFrame::ResizeReflowPass1(nsIPresContext& aPresContext, // Note: we don't bother checking here for whether we should clear the // isTopOfPage reflow state flag, because we're dealing with an unconstrained // height and it isn't an issue... - ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, aStatus); + ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, 0, 0, 0, aStatus); // Place the child since some of its content fit in us. - kidFrame->SetRect(&aPresContext, nsRect(0, 0, kidSize.width, kidSize.height)); + FinishReflowChild(kidFrame, aPresContext, kidSize, 0, 0, 0); if (NS_UNCONSTRAINEDSIZE==kidSize.height) y = NS_UNCONSTRAINEDSIZE; else @@ -1428,8 +1429,8 @@ NS_METHOD nsTableFrame::ResizeReflowPass1(nsIPresContext& aPresContext, { nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame, availSize, aReason); - ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, aStatus); - kidFrame->SetRect(&aPresContext, nsRect(0, 0, 0, 0)); + ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, 0, 0, 0, aStatus); + FinishReflowChild(kidFrame, aPresContext, kidSize, 0, 0, 0); } } } @@ -2356,22 +2357,23 @@ NS_METHOD nsTableFrame::IR_TargetIsChild(nsIPresContext& aPresContext, nsHTMLReflowState kidReflowState(aPresContext, aReflowState.reflowState, aNextFrame, aReflowState.availSize); - rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, aStatus); + nscoord x = aReflowState.mBorderPadding.left; + nscoord y = aReflowState.mBorderPadding.top + aReflowState.y; + rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, + x, y, 0, aStatus); // Place the row group frame. Don't use PlaceChild(), because it moves // the footer frame as well. We'll adjust the footer frame later on in // AdjustSiblingsAfterReflow() - nscoord x = aReflowState.mBorderPadding.left; - nscoord y = aReflowState.mBorderPadding.top + aReflowState.y; nsRect kidRect(x, y, desiredSize.width, desiredSize.height); - aNextFrame->SetRect(&aPresContext, kidRect); + FinishReflowChild(aNextFrame, aPresContext, desiredSize, x, y, 0); // Adjust the running y-offset - aReflowState.y += kidRect.height; + aReflowState.y += desiredSize.height; // If our height is constrained, then update the available height if (PR_FALSE == aReflowState.unconstrainedHeight) { - aReflowState.availSize.height -= kidRect.height; + aReflowState.availSize.height -= desiredSize.height; } // Update the max element size @@ -2459,22 +2461,24 @@ nscoord nsTableFrame::ComputeDesiredWidth(const nsHTMLReflowState& aReflowState) // Position and size aKidFrame and update our reflow state. The origin of // aKidRect is relative to the upper-left origin of our frame -void nsTableFrame::PlaceChild(nsIPresContext& aPresContext, +void nsTableFrame::PlaceChild(nsIPresContext& aPresContext, InnerTableReflowState& aReflowState, - nsIFrame* aKidFrame, - const nsRect& aKidRect, - nsSize* aMaxElementSize, - nsSize& aKidMaxElementSize) + nsIFrame* aKidFrame, + nsHTMLReflowMetrics& aDesiredSize, + nscoord aX, + nscoord aY, + nsSize* aMaxElementSize, + nsSize& aKidMaxElementSize) { // Place and size the child - aKidFrame->SetRect(&aPresContext, aKidRect); + FinishReflowChild(aKidFrame, aPresContext, aDesiredSize, aX, aY, 0); // Adjust the running y-offset - aReflowState.y += aKidRect.height; + aReflowState.y += aDesiredSize.height; // If our height is constrained, then update the available height if (PR_FALSE == aReflowState.unconstrainedHeight) { - aReflowState.availSize.height -= aKidRect.height; + aReflowState.availSize.height -= aDesiredSize.height; } // If this is a footer row group, remember it @@ -2500,7 +2504,7 @@ void nsTableFrame::PlaceChild(nsIPresContext& aPresContext, // Move the footer below the body row group frame aReflowState.footerFrame->GetOrigin(origin); - origin.y += aKidRect.height; + origin.y += aDesiredSize.height; aReflowState.footerFrame->MoveTo(&aPresContext, origin.x, origin.y); } @@ -2606,7 +2610,8 @@ NS_METHOD nsTableFrame::ReflowMappedChildren(nsIPresContext& aPresContext, } } - rv = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, aStatus); + rv = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, + x, y, 0, aStatus); // Did the child fit? if (desiredSize.height > kidAvailSize.height) { if (aReflowState.firstBodySection && (kidFrame != aReflowState.firstBodySection)) { @@ -2619,7 +2624,6 @@ NS_METHOD nsTableFrame::ReflowMappedChildren(nsIPresContext& aPresContext, } // Place the child - nsRect kidRect (x, y, desiredSize.width, desiredSize.height); if (PR_TRUE==IsRowGroup(childDisplay->mDisplay)) { // we don't want to adjust the maxElementSize if this is an initial reflow @@ -2627,8 +2631,10 @@ NS_METHOD nsTableFrame::ReflowMappedChildren(nsIPresContext& aPresContext, nsSize *requestedMaxElementSize = nsnull; if (eReflowReason_Initial != aReflowState.reflowState.reason) requestedMaxElementSize = aDesiredSize.maxElementSize; - PlaceChild(aPresContext, aReflowState, kidFrame, kidRect, - requestedMaxElementSize, kidMaxElementSize); + PlaceChild(aPresContext, aReflowState, kidFrame, desiredSize, + x, y, requestedMaxElementSize, kidMaxElementSize); + } else { + kidFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); } childCount++; @@ -2677,7 +2683,9 @@ NS_METHOD nsTableFrame::ReflowMappedChildren(nsIPresContext& aPresContext, aReflowState.reflowState, kidFrame, nsSize(0,0), eReflowReason_Resize); nsHTMLReflowMetrics unusedDesiredSize(nsnull); - ReflowChild(kidFrame, aPresContext, unusedDesiredSize, kidReflowState, aStatus); + ReflowChild(kidFrame, aPresContext, unusedDesiredSize, kidReflowState, + 0, 0, 0, aStatus); + kidFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); } // Get the next child @@ -2749,7 +2757,8 @@ NS_METHOD nsTableFrame::PullUpChildren(nsIPresContext& aPresContext, kidFrame, aReflowState.availSize, eReflowReason_Resize); - rv = ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, aStatus); + rv = ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, + 0, aReflowState.y, 0, aStatus); // Did the child fit? if ((kidSize.height > aReflowState.availSize.height) && mFrames.NotEmpty()) { @@ -2760,13 +2769,14 @@ NS_METHOD nsTableFrame::PullUpChildren(nsIPresContext& aPresContext, break; } - nsRect kidRect (0, 0, kidSize.width, kidSize.height); - kidRect.y += aReflowState.y; const nsStyleDisplay *childDisplay; kidFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)childDisplay)); if (PR_TRUE==IsRowGroup(childDisplay->mDisplay)) { - PlaceChild(aPresContext, aReflowState, kidFrame, kidRect, aDesiredSize.maxElementSize, *pKidMaxElementSize); + PlaceChild(aPresContext, aReflowState, kidFrame, kidSize, 0, + aReflowState.y, aDesiredSize.maxElementSize, *pKidMaxElementSize); + } else { + kidFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); } // Remove the frame from its current parent diff --git a/layout/tables/nsTableFrame.h b/layout/tables/nsTableFrame.h index 907276e7f100..0e23d6746335 100644 --- a/layout/tables/nsTableFrame.h +++ b/layout/tables/nsTableFrame.h @@ -505,7 +505,9 @@ protected: void PlaceChild(nsIPresContext& aPresContext, InnerTableReflowState& aReflowState, nsIFrame* aKidFrame, - const nsRect& aKidRect, + nsHTMLReflowMetrics& aDesiredSize, + nscoord aX, + nscoord aY, nsSize* aMaxElementSize, nsSize& aKidMaxElementSize); diff --git a/layout/tables/nsTableOuterFrame.cpp b/layout/tables/nsTableOuterFrame.cpp index 8de208c16c93..50ed912ed757 100644 --- a/layout/tables/nsTableOuterFrame.cpp +++ b/layout/tables/nsTableOuterFrame.cpp @@ -403,7 +403,10 @@ nsresult nsTableOuterFrame::IR_TargetIsCaptionFrame(nsIPresContext& aPres nsSize(mRect.width, aReflowState.reflowState.availableHeight), aReflowState.reflowState.reason); captionReflowState.reflowCommand = aReflowState.reflowState.reflowCommand; - rv = ReflowChild(mCaptionFrame, aPresContext, captionSize, captionReflowState, aStatus); + + rv = ReflowChild(mCaptionFrame, aPresContext, captionSize, captionReflowState, + 0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus); + mCaptionFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); if (NS_FAILED(rv)) { return rv; } @@ -440,7 +443,9 @@ nsresult nsTableOuterFrame::IR_TargetIsCaptionFrame(nsIPresContext& aPres nsHTMLReflowState innerReflowState(aPresContext, aReflowState.reflowState, mInnerTableFrame, nsSize(tableWidth, aReflowState.reflowState.availableHeight), eReflowReason_Resize); - rv = ReflowChild(mInnerTableFrame, aPresContext, innerSize, innerReflowState, aStatus); + rv = ReflowChild(mInnerTableFrame, aPresContext, innerSize, innerReflowState, + 0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus); + mInnerTableFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); if (NS_FAILED(rv)) { return rv; } @@ -579,7 +584,9 @@ nsresult nsTableOuterFrame::IR_InnerTableReflow(nsIPresContext& aPresCont nscoord tableMaxWidth = PR_MAX(aReflowState.reflowState.availableWidth, mMinCaptionWidth); nsHTMLReflowState innerReflowState(aPresContext, aReflowState.reflowState, mInnerTableFrame, nsSize(tableMaxWidth, aReflowState.reflowState.availableHeight)); - rv = ReflowChild(mInnerTableFrame, aPresContext, innerSize, innerReflowState, aStatus); + rv = ReflowChild(mInnerTableFrame, aPresContext, innerSize, innerReflowState, + 0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus); + mInnerTableFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); // if there is a caption and the width or height of the inner table changed from a successful reflow, // then reflow or move the caption as needed if ((nsnull != mCaptionFrame) && (PR_TRUE==NS_SUCCEEDED(rv))) { @@ -597,6 +604,7 @@ nsresult nsTableOuterFrame::IR_InnerTableReflow(nsIPresContext& aPresCont // reflow the caption mCaptionFrame->WillReflow(aPresContext); rv = mCaptionFrame->Reflow(aPresContext, captionSize, captionReflowState, aStatus); + mCaptionFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); captionWasReflowed = PR_TRUE; if ((oldCaptionRect.height!=captionSize.height) || (oldCaptionRect.width!=captionSize.width)) { @@ -694,7 +702,9 @@ nsresult nsTableOuterFrame::IR_CaptionInserted(nsIPresContext& aPresConte nsHTMLReflowState innerReflowState(aPresContext, aReflowState.reflowState, mInnerTableFrame, nsSize(mMinCaptionWidth, aReflowState.reflowState.availableHeight), eReflowReason_Resize); - rv = ReflowChild(mInnerTableFrame, aPresContext, innerSize, innerReflowState, aStatus); + rv = ReflowChild(mInnerTableFrame, aPresContext, innerSize, innerReflowState, + 0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus); + mInnerTableFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); } else { // set innerSize as if the inner table were reflowed innerSize.height = mRect.height; @@ -868,6 +878,7 @@ NS_METHOD nsTableOuterFrame::Reflow(nsIPresContext& aPresContext, mCaptionFrame->WillReflow(aPresContext); rv = mCaptionFrame->Reflow(aPresContext, captionSize, captionReflowState, aStatus); + mCaptionFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); mMinCaptionWidth = maxElementSize.width; } } @@ -896,8 +907,11 @@ NS_METHOD nsTableOuterFrame::Reflow(nsIPresContext& aPresContext, } innerReflowState.mComputedHeight = aReflowState.mComputedHeight; nsHTMLReflowMetrics innerSize(aDesiredSize.maxElementSize); - - rv = ReflowChild(mInnerTableFrame, aPresContext, innerSize, innerReflowState, aStatus); + // XXX To do this efficiently we really need to know where the inner + // table will be placed. In the case of a top caption that means + // reflowing the caption first and getting its desired height... + rv = ReflowChild(mInnerTableFrame, aPresContext, innerSize, innerReflowState, + 0, 0, 0, aStatus); // Table's max element size is the MAX of the caption's max element size // and the inner table's max element size... @@ -910,6 +924,7 @@ NS_METHOD nsTableOuterFrame::Reflow(nsIPresContext& aPresContext, // Now that we know the table width we can reflow the caption, and // place the caption and the inner table + nscoord innerY = 0; if (nsnull != mCaptionFrame) { // Get the caption's margin nsMargin captionMargin; @@ -934,9 +949,8 @@ NS_METHOD nsTableOuterFrame::Reflow(nsIPresContext& aPresContext, nsRect captionRect(captionMargin.left, captionY, 0, 0); nsReflowStatus captionStatus; - mCaptionFrame->WillReflow(aPresContext); - mCaptionFrame->Reflow(aPresContext, captionSize, captionReflowState, - captionStatus); + ReflowChild(mCaptionFrame, aPresContext, captionSize, captionReflowState, + captionRect.x, captionRect.y, 0, captionStatus); NS_ASSERTION(NS_FRAME_IS_COMPLETE(captionStatus), "unexpected reflow status"); // XXX If the height is constrained then we need to check whether the inner @@ -944,10 +958,10 @@ NS_METHOD nsTableOuterFrame::Reflow(nsIPresContext& aPresContext, // Place the caption captionRect.SizeTo(captionSize.width, captionSize.height); - mCaptionFrame->SetRect(&aPresContext, captionRect); + FinishReflowChild(mCaptionFrame, aPresContext, captionSize, + captionRect.x, captionRect.y, 0); // Place the inner table - nscoord innerY; if (NS_SIDE_BOTTOM != captionTableStyle->mCaptionSide) { // top caption innerY = captionRect.YMost() + captionMargin.bottom; @@ -958,16 +972,17 @@ NS_METHOD nsTableOuterFrame::Reflow(nsIPresContext& aPresContext, innerY = 0; state.y = captionRect.YMost() + captionMargin.bottom; } - nsRect innerRect(0, innerY, innerSize.width, innerSize.height); - mInnerTableFrame->SetRect(&aPresContext, innerRect); } else { - // Place the inner table - nsRect innerRect(0, 0, innerSize.width, innerSize.height); - mInnerTableFrame->SetRect(&aPresContext, innerRect); + // Place the inner table at 0 + innerY = 0; state.y = innerSize.height; } + + // Finish the inner table reflow + FinishReflowChild(mInnerTableFrame, aPresContext, innerSize, + 0, innerY, 0); } // Return our desired rect @@ -980,38 +995,6 @@ NS_METHOD nsTableOuterFrame::Reflow(nsIPresContext& aPresContext, return rv; } -// Position and size aKidFrame and update our reflow state. The origin of -// aKidRect is relative to the upper-left origin of our frame, and includes -// any left/top margin. -void nsTableOuterFrame::PlaceChild(OuterTableReflowState& aReflowState, - nsIFrame* aKidFrame, - const nsRect& aKidRect, - nsSize* aMaxElementSize, - nsSize& aKidMaxElementSize) -{ - // Place and size the child - aKidFrame->SetRect(aReflowState.pc, aKidRect); - - // Adjust the running y-offset - aReflowState.y += aKidRect.height; - - // If our height is constrained then update the available height - if (PR_FALSE == aReflowState.unconstrainedHeight) { - aReflowState.availSize.height -= aKidRect.height; - } - - /* Update the maximum element size, which is the max of: - * the maxElementSize of our first row - * or the maxElementSize of the caption if we include it - */ - if (aKidFrame == mCaptionFrame) { - if (nsnull != aMaxElementSize) { - aMaxElementSize->width = aKidMaxElementSize.width; - aMaxElementSize->height = aKidMaxElementSize.height; - } - } -} - NS_METHOD nsTableOuterFrame::VerifyTree() const { return NS_OK; diff --git a/layout/tables/nsTableOuterFrame.h b/layout/tables/nsTableOuterFrame.h index f46350e41f35..2e01bb5b0ded 100644 --- a/layout/tables/nsTableOuterFrame.h +++ b/layout/tables/nsTableOuterFrame.h @@ -137,25 +137,6 @@ protected: */ PRBool NeedsReflow(const nsHTMLReflowState& aReflowState); - /** position the child frame - * @param aReflowState the state of the reflow process - * @param aKidFrame the frame to place. - * @param aKidRect the computed dimensions of aKidFrame. The origin of aKidRect - * is relative to the upper-left origin of this frame. - * @param aMaxElementSize the table's maxElementSize - * may be nsnull, meaning that we're not computing maxElementSize during this reflow - * set to the caption's maxElementSize, if aKidFrame is the caption - * the tables maxElementSize eventually gets set to the max of - * the value here and the value of the inner table, elsewhere during reflow. - * @param aKidMaxElementSize the maxElementSize of aKidFrame, if available - */ - void PlaceChild(OuterTableReflowState& aReflowState, - nsIFrame* aKidFrame, - const nsRect& aKidRect, - nsSize* aMaxElementSize, - nsSize& aKidMaxElementSize); - - /** compute the width available to the table during reflow, based on * the reflow state and the table's style. * @return the computed width diff --git a/layout/tables/nsTableRowFrame.cpp b/layout/tables/nsTableRowFrame.cpp index 13cc68b09e8e..3cea7765e8de 100644 --- a/layout/tables/nsTableRowFrame.cpp +++ b/layout/tables/nsTableRowFrame.cpp @@ -334,6 +334,9 @@ nsTableRowFrame::DidResize(nsIPresContext& aPresContext, cellFrame->GetSize(cellFrameSize); //if (cellFrameSize.height!=cellHeight) { + // XXX If the cell frame has a view, then we need to resize + // it as well. We would like to only do that if the cell's size + // is changing. Why is the 'if' stmt above commented out? cellFrame->SizeTo(&aPresContext, cellFrameSize.width, cellHeight); // realign cell content based on the new height /*nsHTMLReflowMetrics desiredSize(nsnull); @@ -595,18 +598,20 @@ void nsTableRowFrame::FixMinCellHeight(nsTableFrame *aTableFrame) // Position and size aKidFrame and update our reflow state. The origin of // aKidRect is relative to the upper-left origin of our frame, and includes // any left/top margin. -void nsTableRowFrame::PlaceChild(nsIPresContext& aPresContext, - RowReflowState& aReflowState, - nsIFrame* aKidFrame, - const nsRect& aKidRect, - nsSize* aMaxElementSize, - nsSize* aKidMaxElementSize) +void nsTableRowFrame::PlaceChild(nsIPresContext& aPresContext, + RowReflowState& aReflowState, + nsIFrame* aKidFrame, + nsHTMLReflowMetrics& aDesiredSize, + nscoord aX, + nscoord aY, + nsSize* aMaxElementSize, + nsSize* aKidMaxElementSize) { - // Place and size the child - aKidFrame->SetRect(&aPresContext, aKidRect); + // Complete the reflow + FinishReflowChild(aKidFrame, aPresContext, aDesiredSize, aX, aY, 0); // update the running total for the row width - aReflowState.x += aKidRect.width; + aReflowState.x += aDesiredSize.width; // Update the maximum element size PRInt32 rowSpan = aReflowState.tableFrame->GetEffectiveRowSpan((nsTableCellFrame*)aKidFrame); @@ -644,14 +649,14 @@ void nsTableRowFrame::PlaceChild(nsIPresContext& aPresContext, #else if (1 == rowSpan) { // Update maxCellHeight - if (aKidRect.height > aReflowState.maxCellHeight) - aReflowState.maxCellHeight = aKidRect.height; + if (aDesiredSize.height > aReflowState.maxCellHeight) + aReflowState.maxCellHeight = aDesiredSize.height; // Update maxCellVertSpace nsMargin margin; if (aReflowState.tableFrame->GetCellMarginData((nsTableCellFrame *)aKidFrame, margin) == NS_OK) { - nscoord height = aKidRect.height + margin.top + margin.bottom; + nscoord height = aDesiredSize.height + margin.top + margin.bottom; if (height > aReflowState.maxCellVertSpace) aReflowState.maxCellVertSpace = height; @@ -887,7 +892,8 @@ NS_METHOD nsTableRowFrame::ResizeReflow(nsIPresContext& aPresContext, kidAvailSize, reason); nsReflowStatus status; - rv = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, status); + rv = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, + aReflowState.x, GetChildMaxTopMargin(), 0, status); #ifdef NS_DEBUG if (desiredSize.width > availWidth) { @@ -925,10 +931,8 @@ NS_METHOD nsTableRowFrame::ResizeReflow(nsIPresContext& aPresContext, desiredSize.height, availWidth); // Place the child - nsRect kidRect (aReflowState.x, GetChildMaxTopMargin(), desiredSize.width, - desiredSize.height); - - PlaceChild(aPresContext, aReflowState, kidFrame, kidRect, + PlaceChild(aPresContext, aReflowState, kidFrame, desiredSize, + aReflowState.x, GetChildMaxTopMargin(), aDesiredSize.maxElementSize, kidMaxElementSize); } @@ -939,7 +943,8 @@ NS_METHOD nsTableRowFrame::ResizeReflow(nsIPresContext& aPresContext, nsSize(0,0), eReflowReason_Resize); nsHTMLReflowMetrics desiredSize(nsnull); nsReflowStatus status; - ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, status); + ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, 0, 0, 0, status); + kidFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); } } @@ -1037,7 +1042,8 @@ nsTableRowFrame::InitialReflow(nsIPresContext& aPresContext, kidFrame, kidAvailSize, eReflowReason_Initial); - rv = ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, aStatus); + rv = ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, + x + kidMargin.left, kidMargin.top, 0, aStatus); // the following signals bugs in the content frames. if (kidMaxElementSize.width > kidSize.width) { @@ -1057,9 +1063,8 @@ nsTableRowFrame::InitialReflow(nsIPresContext& aPresContext, // Place the child x += kidMargin.left; - nsRect kidRect(x, kidMargin.top, kidSize.width, kidSize.height); - PlaceChild(aPresContext, aReflowState, kidFrame, kidRect, aDesiredSize.maxElementSize, - &kidMaxElementSize); + PlaceChild(aPresContext, aReflowState, kidFrame, kidSize, x, kidMargin.top, + aDesiredSize.maxElementSize, &kidMaxElementSize); x += kidSize.width + kidMargin.right; } else @@ -1067,7 +1072,8 @@ nsTableRowFrame::InitialReflow(nsIPresContext& aPresContext, nsHTMLReflowState kidReflowState(aPresContext, aReflowState.reflowState, kidFrame, nsSize(0,0), eReflowReason_Initial); nsHTMLReflowMetrics desiredSize(nsnull); - ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, aStatus); + ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, 0, 0, 0, aStatus); + kidFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); } if (PR_FALSE==aDoSiblings) break; @@ -1291,7 +1297,8 @@ NS_METHOD nsTableRowFrame::IR_TargetIsChild(nsIPresContext& aPresContext, // Reflow the cell passing it the incremental reflow command. We can't pass // in a max width of NS_UNCONSTRAINEDSIZE, because the max width must match // the width of the previous reflow... - rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, aStatus); + rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, + aReflowState.x, GetChildMaxTopMargin(), 0, aStatus); //XXX: this is a hack, shouldn't it be the case that a min size is // never larger than a desired size? @@ -1325,7 +1332,8 @@ NS_METHOD nsTableRowFrame::IR_TargetIsChild(nsIPresContext& aPresContext, kidReflowState.reason = eReflowReason_Initial; kidReflowState.reflowCommand = nsnull; kidReflowState.availableWidth = NS_UNCONSTRAINEDSIZE; - rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, aStatus); + rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, + aReflowState.x, GetChildMaxTopMargin(), 0, aStatus); //XXX: this is a hack, shouldn't it be the case that a min size is // never larger than a desired size? @@ -1355,7 +1363,8 @@ NS_METHOD nsTableRowFrame::IR_TargetIsChild(nsIPresContext& aPresContext, // again this time constraining the width back to the column width again kidReflowState.reason = eReflowReason_Resize; kidReflowState.availableWidth = cellAvailWidth; - rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, aStatus); + rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, + aReflowState.x, GetChildMaxTopMargin(), 0, aStatus); } else { // The column widths need to be rebalanced, so don't waste time reflowing @@ -1371,10 +1380,8 @@ NS_METHOD nsTableRowFrame::IR_TargetIsChild(nsIPresContext& aPresContext, cellAvailWidth); // Now place the child - nsRect kidRect (aReflowState.x, GetChildMaxTopMargin(), desiredSize.width, - desiredSize.height); - PlaceChild(aPresContext, aReflowState, aNextFrame, kidRect, - aDesiredSize.maxElementSize, &kidMaxElementSize); + PlaceChild(aPresContext, aReflowState, aNextFrame, desiredSize, aReflowState.x, + GetChildMaxTopMargin(), aDesiredSize.maxElementSize, &kidMaxElementSize); SetMaxChildHeight(aReflowState.maxCellHeight); @@ -1517,9 +1524,11 @@ void nsTableRowFrame::ReflowCellFrame(nsIPresContext& aPresContext, eReflowReason_Resize); nsHTMLReflowMetrics desiredSize(nsnull); - ReflowChild(aCellFrame, aPresContext, desiredSize, cellReflowState, aStatus); + ReflowChild(aCellFrame, aPresContext, desiredSize, cellReflowState, + 0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus); aCellFrame->SizeTo(&aPresContext, cellSize.width, aAvailableHeight); aCellFrame->VerticallyAlignChild(&aPresContext); + aCellFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); } /** diff --git a/layout/tables/nsTableRowFrame.h b/layout/tables/nsTableRowFrame.h index 1db66fa5286f..ff964cf08d2d 100644 --- a/layout/tables/nsTableRowFrame.h +++ b/layout/tables/nsTableRowFrame.h @@ -248,12 +248,14 @@ protected: nsIFrame* aKidFrame, nsSize* aMaxElementSize); - void PlaceChild(nsIPresContext& aPresContext, - RowReflowState& aState, - nsIFrame* aKidFrame, - const nsRect& aKidRect, - nsSize* aMaxElementSize, - nsSize* aKidMaxElementSize); + void PlaceChild(nsIPresContext& aPresContext, + RowReflowState& aState, + nsIFrame* aKidFrame, + nsHTMLReflowMetrics& aDesiredSize, + nscoord aX, + nscoord aY, + nsSize* aMaxElementSize, + nsSize* aKidMaxElementSize); nscoord ComputeCellXOffset(const RowReflowState& aState, nsIFrame* aKidFrame, diff --git a/layout/tables/nsTableRowGroupFrame.cpp b/layout/tables/nsTableRowGroupFrame.cpp index 23b60c0015a1..2cd4983eebf1 100644 --- a/layout/tables/nsTableRowGroupFrame.cpp +++ b/layout/tables/nsTableRowGroupFrame.cpp @@ -342,19 +342,21 @@ nsTableRowGroupFrame::GetFrameForPoint(nsIPresContext* aPresContext, void nsTableRowGroupFrame::PlaceChild(nsIPresContext& aPresContext, RowGroupReflowState& aReflowState, nsIFrame* aKidFrame, - const nsRect& aKidRect, + nsHTMLReflowMetrics& aDesiredSize, + nscoord aX, + nscoord aY, nsSize* aMaxElementSize, nsSize& aKidMaxElementSize) { // Place and size the child - aKidFrame->SetRect(&aPresContext, aKidRect); + FinishReflowChild(aKidFrame, aPresContext, aDesiredSize, aX, aY, 0); // Adjust the running y-offset - aReflowState.y += aKidRect.height; + aReflowState.y += aDesiredSize.height; // If our height is constrained then update the available height if (PR_FALSE == aReflowState.unconstrainedHeight) { - aReflowState.availSize.height -= aKidRect.height; + aReflowState.availSize.height -= aDesiredSize.height; } // Update the maximum element size @@ -457,12 +459,13 @@ NS_METHOD nsTableRowGroupFrame::ReflowMappedChildren(nsIPresContext& aPresC } } - rv = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, aStatus); + rv = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, + 0, aReflowState.y, 0, aStatus); // Place the child nsRect kidRect (0, aReflowState.y, desiredSize.width, desiredSize.height); - PlaceChild(aPresContext, aReflowState, kidFrame, kidRect, aDesiredSize.maxElementSize, - kidMaxElementSize); + PlaceChild(aPresContext, aReflowState, kidFrame, desiredSize, 0, + aReflowState.y, aDesiredSize.maxElementSize, kidMaxElementSize); /* if the table has collapsing borders, we need to reset the length of the shared vertical borders * for the table and the cells that overlap this row @@ -877,8 +880,10 @@ nsTableRowGroupFrame::SplitRowGroup(nsIPresContext& aPresContext, availSize, eReflowReason_Resize); nsHTMLReflowMetrics desiredSize(nsnull); - rv = ReflowChild(rowFrame, aPresContext, desiredSize, rowReflowState, aStatus); + rv = ReflowChild(rowFrame, aPresContext, desiredSize, rowReflowState, + 0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus); rowFrame->SizeTo(&aPresContext, desiredSize.width, desiredSize.height); + rowFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); ((nsTableRowFrame *)rowFrame)->DidResize(aPresContext, aReflowState); aDesiredSize.height = desiredSize.height; @@ -1507,12 +1512,13 @@ NS_METHOD nsTableRowGroupFrame::IR_TargetIsChild(nsIPresContext& aPresConte nsSize kidMaxElementSize; nsHTMLReflowMetrics desiredSize(aDesiredSize.maxElementSize ? &kidMaxElementSize : nsnull); - rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, aStatus); + rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, + 0, aReflowState.y, 0, aStatus); // Place the row frame nsRect kidRect(0, aReflowState.y, desiredSize.width, desiredSize.height); - PlaceChild(aPresContext, aReflowState, aNextFrame, kidRect, - aDesiredSize.maxElementSize, kidMaxElementSize); + PlaceChild(aPresContext, aReflowState, aNextFrame, desiredSize, 0, + aReflowState.y, aDesiredSize.maxElementSize, kidMaxElementSize); // See if the table needs a reflow (e.g., if the column widths have // changed). If so, just return and don't bother adjusting the rows diff --git a/layout/tables/nsTableRowGroupFrame.h b/layout/tables/nsTableRowGroupFrame.h index 607f27e2bf81..80cd29f3fd72 100644 --- a/layout/tables/nsTableRowGroupFrame.h +++ b/layout/tables/nsTableRowGroupFrame.h @@ -205,7 +205,9 @@ protected: void PlaceChild(nsIPresContext& aPresContext, RowGroupReflowState& aReflowState, nsIFrame* aKidFrame, - const nsRect& aKidRect, + nsHTMLReflowMetrics& aDesiredSize, + nscoord aX, + nscoord aY, nsSize* aMaxElementSize, nsSize& aKidMaxElementSize); diff --git a/layout/xul/base/src/nsBoxFrame.cpp b/layout/xul/base/src/nsBoxFrame.cpp index 82a96a346752..991a3f01b346 100644 --- a/layout/xul/base/src/nsBoxFrame.cpp +++ b/layout/xul/base/src/nsBoxFrame.cpp @@ -971,10 +971,23 @@ nsBoxFrame::PlaceChildren(nsIPresContext& aPresContext, nsRect& boxRect) } nsRect rect; + nsIView* view; childFrame->GetRect(rect); rect.x = x; rect.y = y; childFrame->SetRect(&aPresContext, rect); + childFrame->GetView(&aPresContext, &view); + // XXX Because we didn't position the frame or its view when reflowing + // it we must re-position all child views. This isn't optimal, and if + // we knew its final position, it would be better to position the frame + // and its view when doing the reflow... + if (view) { + nsContainerFrame::SyncFrameViewAfterReflow(&aPresContext, childFrame, + view, nsnull); + } else { + // Re-position any child frame views + nsContainerFrame::PositionChildViews(&aPresContext, childFrame); + } // add in the right margin if (mInner->mHorizontal) @@ -1131,6 +1144,9 @@ nsBoxFrame::FlowChildAt(nsIFrame* childFrame, printf("because (%s)\n", ch); #endif // do the flow + // Note that we don't position the frame (or its view) now. If we knew + // where we were going to place the child, then it would be more + // efficient to position it now... childFrame->WillReflow(aPresContext); childFrame->Reflow(aPresContext, desiredSize, reflowState, aStatus); @@ -1183,8 +1199,20 @@ nsBoxFrame::FlowChildAt(nsIFrame* childFrame, } - // set the rect + // set the rect and size the view (if it has one).. Don't position the view + // and sync its properties (like opacity) until later when we know its final + // position childFrame->SizeTo(&aPresContext, desiredSize.width, desiredSize.height); + nsIView* view; + childFrame->GetView(&aPresContext, &view); + if (view) { + nsIViewManager *vm; + + view->GetViewManager(vm); + vm->ResizeView(view, desiredSize.width, desiredSize.height); + NS_RELEASE(vm); + } + childFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); // Stub out desiredSize.maxElementSize so that when go out of // scope, nothing bad happens! diff --git a/layout/xul/base/src/nsMenuFrame.cpp b/layout/xul/base/src/nsMenuFrame.cpp index ee8b0cecad06..baf7e169d138 100644 --- a/layout/xul/base/src/nsMenuFrame.cpp +++ b/layout/xul/base/src/nsMenuFrame.cpp @@ -619,14 +619,16 @@ nsMenuFrame::Reflow(nsIPresContext& aPresContext, if (kidReflowState.reason == eReflowReason_Incremental) kidReflowState.reason = eReflowReason_Resize; - rv = ReflowChild(frame, aPresContext, aDesiredSize, kidReflowState, aStatus); - - // Set the child's width and height to its desired size nsRect rect; frame->GetRect(rect); - rect.width = aDesiredSize.width; - rect.height = aDesiredSize.height; - frame->SetRect(&aPresContext, rect); + rv = ReflowChild(frame, aPresContext, aDesiredSize, kidReflowState, + rect.x, rect.y, NS_FRAME_NO_MOVE_VIEW, aStatus); + + // Set the child's width and height to its desired size + // Note: don't position or size the view now, we'll do that in the + // DidReflow() function + frame->SizeTo(&aPresContext, aDesiredSize.width, aDesiredSize.height); + frame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); // Don't let it affect our size. aDesiredSize.width = w; @@ -652,7 +654,10 @@ nsMenuFrame::DidReflow(nsIPresContext& aPresContext, mMenuParent->IsMenuBar(onMenuBar); menuPopup->SyncViewWithFrame(aPresContext, onMenuBar, this, -1, -1); +// XXX TROY +#if 0 menuPopup->DidReflow(aPresContext, aStatus); +#endif } return rv; diff --git a/layout/xul/base/src/nsMenuPopupFrame.cpp b/layout/xul/base/src/nsMenuPopupFrame.cpp index 9bb097360c5f..4cc99f6db3bb 100644 --- a/layout/xul/base/src/nsMenuPopupFrame.cpp +++ b/layout/xul/base/src/nsMenuPopupFrame.cpp @@ -271,6 +271,8 @@ nsMenuPopupFrame::DidReflow(nsIPresContext& aPresContext, // wrong place. nsresult result = NS_OK; /* = nsFrame::DidReflow(aPresContext, aStatus) */ + // XXX TROY +#if 0 if (NS_FRAME_REFLOW_FINISHED == aStatus) { // Apply DidReflow to each and every list that this frame implements nsIAtom* listName = nsnull; @@ -286,6 +288,7 @@ nsMenuPopupFrame::DidReflow(nsIPresContext& aPresContext, GetAdditionalChildListName(listIndex++, &listName); } while(nsnull != listName); } +#endif NS_FRAME_TRACE_OUT("nsContainerFrame::DidReflow"); return result; diff --git a/layout/xul/base/src/nsPopupSetFrame.cpp b/layout/xul/base/src/nsPopupSetFrame.cpp index 6fa13cb91222..5fe909286fa1 100644 --- a/layout/xul/base/src/nsPopupSetFrame.cpp +++ b/layout/xul/base/src/nsPopupSetFrame.cpp @@ -225,14 +225,13 @@ nsPopupSetFrame::Reflow(nsIPresContext& aPresContext, nscoord w = aDesiredSize.width; nscoord h = aDesiredSize.height; - rv = ReflowChild(frame, aPresContext, aDesiredSize, kidReflowState, aStatus); - - // Set the child's width and height to its desired size nsRect rect; frame->GetRect(rect); - rect.width = aDesiredSize.width; - rect.height = aDesiredSize.height; - frame->SetRect(&aPresContext, rect); + rv = ReflowChild(frame, aPresContext, aDesiredSize, kidReflowState, + rect.x, rect.y, 0, aStatus); + + // Set the child's width and height to its desired size + FinishReflowChild(frame, aPresContext, aDesiredSize, rect.x, rect.y, 0); // Don't let it affect our size. aDesiredSize.width = w; diff --git a/layout/xul/base/src/nsSliderFrame.cpp b/layout/xul/base/src/nsSliderFrame.cpp index 64b47c3bc33b..834edc3a8639 100644 --- a/layout/xul/base/src/nsSliderFrame.cpp +++ b/layout/xul/base/src/nsSliderFrame.cpp @@ -313,7 +313,9 @@ nsSliderFrame::ReflowThumb(nsIPresContext& aPresContext, if (thumbReflowState.mComputedHeight != NS_INTRINSICSIZE) thumbReflowState.mComputedHeight -= total.top + total.bottom; - ReflowChild(thumbFrame, aPresContext, aDesiredSize, thumbReflowState, aStatus); + ReflowChild(thumbFrame, aPresContext, aDesiredSize, thumbReflowState, + 0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus); + thumbFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); // add the margin back in aDesiredSize.width += margin.left + margin.right; @@ -442,7 +444,13 @@ nsSliderFrame::Reflow(nsIPresContext& aPresContext, else thumbRect.y += pos; + nsIView* view; thumbFrame->SetRect(&aPresContext, thumbRect); + thumbFrame->GetView(&aPresContext, &view); + if (view) { + nsContainerFrame::SyncFrameViewAfterReflow(&aPresContext, thumbFrame, + view, nsnull); + } // add in our border aDesiredSize.width += borderPadding.left + borderPadding.right; diff --git a/layout/xul/base/src/nsTreeRowGroupFrame.cpp b/layout/xul/base/src/nsTreeRowGroupFrame.cpp index 67f0d2146afc..0978426032d7 100644 --- a/layout/xul/base/src/nsTreeRowGroupFrame.cpp +++ b/layout/xul/base/src/nsTreeRowGroupFrame.cpp @@ -877,7 +877,8 @@ nsTreeRowGroupFrame::IR_TargetIsChild(nsIPresContext& aPresContext, kidReflowState.mComputedHeight = mRowGroupHeight; nsHTMLReflowMetrics desiredSize(nsnull); - rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, aStatus); + rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, + 0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus); nscoord xpos = 0; @@ -890,8 +891,7 @@ nsTreeRowGroupFrame::IR_TargetIsChild(nsIPresContext& aPresContext, } // Place the child - nsRect kidRect (xpos, 0, desiredSize.width, mRowGroupHeight); - mScrollbar->SetRect(&aPresContext, kidRect); + FinishReflowChild(aNextFrame, aPresContext, desiredSize, xpos, 0, 0); // Return our desired width aDesiredSize.width = aReflowState.reflowState.availableWidth; @@ -999,7 +999,8 @@ nsTreeRowGroupFrame::ReflowAfterRowLayout(nsIPresContext& aPresContext, kidAvailSize, aReason); kidReflowState.mComputedHeight = mRowGroupHeight; - rv = ReflowChild(mScrollbar, aPresContext, desiredSize, kidReflowState, aStatus); + rv = ReflowChild(mScrollbar, aPresContext, desiredSize, kidReflowState, + 0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus); if (NS_FAILED(rv)) return rv; @@ -1014,8 +1015,7 @@ nsTreeRowGroupFrame::ReflowAfterRowLayout(nsIPresContext& aPresContext, } // Place the child - nsRect kidRect (xpos, 0, desiredSize.width, mRowGroupHeight); - mScrollbar->SetRect(&aPresContext, kidRect); + FinishReflowChild(mScrollbar, aPresContext, desiredSize, xpos, 0, 0); } return rv; }