From bb653520dc2a503c8387d2e6564ff6fba7fe7e18 Mon Sep 17 00:00:00 2001 From: "troy%netscape.com" Date: Tue, 2 May 2000 02:23:31 +0000 Subject: [PATCH] b=33150 Fixed problem where reflow commands in different child lists were being coalesced git-svn-id: svn://10.0.0.236/trunk@67826 18797224-902f-48f8-a5cc-f745e15eee43 --- .../generic/nsAbsoluteContainingBlock.cpp | 39 +++++++++++-------- .../generic/nsAbsoluteContainingBlock.h | 2 +- mozilla/layout/generic/nsAreaFrame.cpp | 34 ++++++++++++++++ mozilla/layout/generic/nsAreaFrame.h | 2 + .../base/src/nsAbsoluteContainingBlock.cpp | 39 +++++++++++-------- .../html/base/src/nsAbsoluteContainingBlock.h | 2 +- mozilla/layout/html/base/src/nsAreaFrame.cpp | 34 ++++++++++++++++ mozilla/layout/html/base/src/nsAreaFrame.h | 2 + 8 files changed, 118 insertions(+), 36 deletions(-) diff --git a/mozilla/layout/generic/nsAbsoluteContainingBlock.cpp b/mozilla/layout/generic/nsAbsoluteContainingBlock.cpp index 71354c153d5..4adf2cbb76a 100644 --- a/mozilla/layout/generic/nsAbsoluteContainingBlock.cpp +++ b/mozilla/layout/generic/nsAbsoluteContainingBlock.cpp @@ -193,18 +193,23 @@ nsAbsoluteContainingBlock::Reflow(nsIFrame* aDelegatingFrame, nsIFrame* kidFrame; for (kidFrame = mAbsoluteFrames.FirstChild(); nsnull != kidFrame; kidFrame->GetNextSibling(&kidFrame)) { - // if the positioned frame has never had a reflow, change the reason to initial - PRBool initialReflow = PR_FALSE; + nsReflowReason reason = aReflowState.reason; + nsFrameState kidState; kidFrame->GetFrameState(&kidState); if (NS_FRAME_FIRST_REFLOW & kidState) { - initialReflow = PR_TRUE; + // The frame has never had a reflow, so change the reason to eReflowReason_Initial + reason = eReflowReason_Initial; + + } else if (NS_FRAME_IS_DIRTY & kidState) { + // The frame is dirty so give it the correct reflow reason + reason = eReflowReason_Dirty; } // Reflow the frame nsReflowStatus kidStatus; ReflowAbsoluteFrame(aDelegatingFrame, aPresContext, reflowState, aContainingBlockWidth, - aContainingBlockHeight, kidFrame, initialReflow, kidStatus); + aContainingBlockHeight, kidFrame, reason, kidStatus); // Add in the child's bounds nsRect kidBounds; @@ -303,13 +308,16 @@ nsAbsoluteContainingBlock::IncrementalReflow(nsIFrame* aDelegatin f->GetFrameState(&frameState); if (frameState & NS_FRAME_IS_DIRTY) { nsReflowStatus status; + nsReflowReason reason; - // Note: the only reason the frame would be dirty would be if it had - // just been inserted or appended - NS_ASSERTION(frameState & NS_FRAME_FIRST_REFLOW, "unexpected frame state"); + if (frameState & NS_FRAME_FIRST_REFLOW) { + reason = eReflowReason_Initial; + } else { + reason = eReflowReason_Dirty; + } ReflowAbsoluteFrame(aDelegatingFrame, aPresContext, aReflowState, aContainingBlockWidth, aContainingBlockHeight, f, - PR_TRUE, status); + reason, status); } } @@ -334,7 +342,7 @@ nsAbsoluteContainingBlock::IncrementalReflow(nsIFrame* aDelegatin nsReflowStatus kidStatus; ReflowAbsoluteFrame(aDelegatingFrame, aPresContext, aReflowState, aContainingBlockWidth, aContainingBlockHeight, nextFrame, - PR_FALSE, kidStatus); + aReflowState.reason, kidStatus); // We don't need to invalidate anything because the frame should // invalidate any area within its frame that needs repainting, and // because it has a view if it changes size the view manager will @@ -366,7 +374,7 @@ nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegat nscoord aContainingBlockWidth, nscoord aContainingBlockHeight, nsIFrame* aKidFrame, - PRBool aInitialReflow, + nsReflowReason aReason, nsReflowStatus& aStatus) { nsresult rv; @@ -377,24 +385,22 @@ nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegat NS_NOTYETIMPLEMENTED("percentage border"); } + nsFrameState kidFrameState; nsSize availSize(aReflowState.mComputedWidth, NS_UNCONSTRAINEDSIZE); nsHTMLReflowMetrics kidDesiredSize(nsnull); nsHTMLReflowState kidReflowState(aPresContext, aReflowState, aKidFrame, availSize, aContainingBlockWidth, aContainingBlockHeight); - // If it's the initial reflow, then override the reflow reason. This is - // used when frames are inserted incrementally - if (aInitialReflow) { - kidReflowState.reason = eReflowReason_Initial; - } + // Set the reflow reason + kidReflowState.reason = aReason; // Send the WillReflow() notification and position the frame nscoord x; aKidFrame->WillReflow(aPresContext); if (NS_AUTOOFFSET == kidReflowState.mComputedOffsets.left) { - // Just current the current x-offset + // Just use the current x-offset nsPoint origin; aKidFrame->GetOrigin(origin); x = origin.x; @@ -456,7 +462,6 @@ nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegat // If the frame has visible overflow, then store it as a property on the // frame. This allows us to be able to recover it without having to reflow // the frame - nsFrameState kidFrameState; aKidFrame->GetFrameState(&kidFrameState); if (kidFrameState & NS_FRAME_OUTSIDE_CHILDREN) { // Get the property (creating a rect struct if necessary) diff --git a/mozilla/layout/generic/nsAbsoluteContainingBlock.h b/mozilla/layout/generic/nsAbsoluteContainingBlock.h index fcffdb8ca28..780efe16bde 100644 --- a/mozilla/layout/generic/nsAbsoluteContainingBlock.h +++ b/mozilla/layout/generic/nsAbsoluteContainingBlock.h @@ -107,7 +107,7 @@ protected: nscoord aContainingBlockWidth, nscoord aContainingBlockHeight, nsIFrame* aKidFrame, - PRBool aInitialReflow, + nsReflowReason aReason, nsReflowStatus& aStatus); void CalculateChildBounds(nsIPresContext* aPresContext, nsRect& aChildBounds); diff --git a/mozilla/layout/generic/nsAreaFrame.cpp b/mozilla/layout/generic/nsAreaFrame.cpp index 4492e65f0f1..0f476285ab9 100644 --- a/mozilla/layout/generic/nsAreaFrame.cpp +++ b/mozilla/layout/generic/nsAreaFrame.cpp @@ -311,6 +311,40 @@ nsAreaFrame::Reflow(nsIPresContext* aPresContext, return rv; } + +NS_IMETHODIMP +nsAreaFrame::ReflowDirtyChild(nsIPresShell* aPresShell, nsIFrame* aChild) +{ + if (aChild) { + // See if the child is absolutely positioned + nsFrameState childState; + aChild->GetFrameState(&childState); + if (childState & NS_FRAME_OUT_OF_FLOW) { + const nsStylePosition* position; + aChild->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)position); + + if (position->IsAbsolutelyPositioned()) { + // Generate a reflow command to reflow our dirty absolutely + // positioned child frames. + // XXX Note that we don't currently try and coalesce the reflow commands, + // although we should. We can't use the NS_FRAME_HAS_DIRTY_CHILDREN + // flag, because that's used to indicate whether in-flow children are + // dirty... + nsIReflowCommand* reflowCmd; + nsresult rv = NS_NewHTMLReflowCommand(&reflowCmd, this, + nsIReflowCommand::ReflowDirty); + if (NS_SUCCEEDED(rv)) { + reflowCmd->SetChildListName(nsLayoutAtoms::absoluteList); + aPresShell->AppendReflowCommand(reflowCmd); + NS_RELEASE(reflowCmd); + } + return rv; + } + } + } + + return nsBlockFrame::ReflowDirtyChild(aPresShell, aChild); +} NS_IMETHODIMP nsAreaFrame::GetFrameType(nsIAtom** aType) const diff --git a/mozilla/layout/generic/nsAreaFrame.h b/mozilla/layout/generic/nsAreaFrame.h index 32f8c405ea4..49fb2ee9e15 100644 --- a/mozilla/layout/generic/nsAreaFrame.h +++ b/mozilla/layout/generic/nsAreaFrame.h @@ -80,6 +80,8 @@ public: const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus); + NS_IMETHOD ReflowDirtyChild(nsIPresShell* aPresShell, nsIFrame* aChild); + /** * Get the "type" of the frame * diff --git a/mozilla/layout/html/base/src/nsAbsoluteContainingBlock.cpp b/mozilla/layout/html/base/src/nsAbsoluteContainingBlock.cpp index 71354c153d5..4adf2cbb76a 100644 --- a/mozilla/layout/html/base/src/nsAbsoluteContainingBlock.cpp +++ b/mozilla/layout/html/base/src/nsAbsoluteContainingBlock.cpp @@ -193,18 +193,23 @@ nsAbsoluteContainingBlock::Reflow(nsIFrame* aDelegatingFrame, nsIFrame* kidFrame; for (kidFrame = mAbsoluteFrames.FirstChild(); nsnull != kidFrame; kidFrame->GetNextSibling(&kidFrame)) { - // if the positioned frame has never had a reflow, change the reason to initial - PRBool initialReflow = PR_FALSE; + nsReflowReason reason = aReflowState.reason; + nsFrameState kidState; kidFrame->GetFrameState(&kidState); if (NS_FRAME_FIRST_REFLOW & kidState) { - initialReflow = PR_TRUE; + // The frame has never had a reflow, so change the reason to eReflowReason_Initial + reason = eReflowReason_Initial; + + } else if (NS_FRAME_IS_DIRTY & kidState) { + // The frame is dirty so give it the correct reflow reason + reason = eReflowReason_Dirty; } // Reflow the frame nsReflowStatus kidStatus; ReflowAbsoluteFrame(aDelegatingFrame, aPresContext, reflowState, aContainingBlockWidth, - aContainingBlockHeight, kidFrame, initialReflow, kidStatus); + aContainingBlockHeight, kidFrame, reason, kidStatus); // Add in the child's bounds nsRect kidBounds; @@ -303,13 +308,16 @@ nsAbsoluteContainingBlock::IncrementalReflow(nsIFrame* aDelegatin f->GetFrameState(&frameState); if (frameState & NS_FRAME_IS_DIRTY) { nsReflowStatus status; + nsReflowReason reason; - // Note: the only reason the frame would be dirty would be if it had - // just been inserted or appended - NS_ASSERTION(frameState & NS_FRAME_FIRST_REFLOW, "unexpected frame state"); + if (frameState & NS_FRAME_FIRST_REFLOW) { + reason = eReflowReason_Initial; + } else { + reason = eReflowReason_Dirty; + } ReflowAbsoluteFrame(aDelegatingFrame, aPresContext, aReflowState, aContainingBlockWidth, aContainingBlockHeight, f, - PR_TRUE, status); + reason, status); } } @@ -334,7 +342,7 @@ nsAbsoluteContainingBlock::IncrementalReflow(nsIFrame* aDelegatin nsReflowStatus kidStatus; ReflowAbsoluteFrame(aDelegatingFrame, aPresContext, aReflowState, aContainingBlockWidth, aContainingBlockHeight, nextFrame, - PR_FALSE, kidStatus); + aReflowState.reason, kidStatus); // We don't need to invalidate anything because the frame should // invalidate any area within its frame that needs repainting, and // because it has a view if it changes size the view manager will @@ -366,7 +374,7 @@ nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegat nscoord aContainingBlockWidth, nscoord aContainingBlockHeight, nsIFrame* aKidFrame, - PRBool aInitialReflow, + nsReflowReason aReason, nsReflowStatus& aStatus) { nsresult rv; @@ -377,24 +385,22 @@ nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegat NS_NOTYETIMPLEMENTED("percentage border"); } + nsFrameState kidFrameState; nsSize availSize(aReflowState.mComputedWidth, NS_UNCONSTRAINEDSIZE); nsHTMLReflowMetrics kidDesiredSize(nsnull); nsHTMLReflowState kidReflowState(aPresContext, aReflowState, aKidFrame, availSize, aContainingBlockWidth, aContainingBlockHeight); - // If it's the initial reflow, then override the reflow reason. This is - // used when frames are inserted incrementally - if (aInitialReflow) { - kidReflowState.reason = eReflowReason_Initial; - } + // Set the reflow reason + kidReflowState.reason = aReason; // Send the WillReflow() notification and position the frame nscoord x; aKidFrame->WillReflow(aPresContext); if (NS_AUTOOFFSET == kidReflowState.mComputedOffsets.left) { - // Just current the current x-offset + // Just use the current x-offset nsPoint origin; aKidFrame->GetOrigin(origin); x = origin.x; @@ -456,7 +462,6 @@ nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegat // If the frame has visible overflow, then store it as a property on the // frame. This allows us to be able to recover it without having to reflow // the frame - nsFrameState kidFrameState; aKidFrame->GetFrameState(&kidFrameState); if (kidFrameState & NS_FRAME_OUTSIDE_CHILDREN) { // Get the property (creating a rect struct if necessary) diff --git a/mozilla/layout/html/base/src/nsAbsoluteContainingBlock.h b/mozilla/layout/html/base/src/nsAbsoluteContainingBlock.h index fcffdb8ca28..780efe16bde 100644 --- a/mozilla/layout/html/base/src/nsAbsoluteContainingBlock.h +++ b/mozilla/layout/html/base/src/nsAbsoluteContainingBlock.h @@ -107,7 +107,7 @@ protected: nscoord aContainingBlockWidth, nscoord aContainingBlockHeight, nsIFrame* aKidFrame, - PRBool aInitialReflow, + nsReflowReason aReason, nsReflowStatus& aStatus); void CalculateChildBounds(nsIPresContext* aPresContext, nsRect& aChildBounds); diff --git a/mozilla/layout/html/base/src/nsAreaFrame.cpp b/mozilla/layout/html/base/src/nsAreaFrame.cpp index 4492e65f0f1..0f476285ab9 100644 --- a/mozilla/layout/html/base/src/nsAreaFrame.cpp +++ b/mozilla/layout/html/base/src/nsAreaFrame.cpp @@ -311,6 +311,40 @@ nsAreaFrame::Reflow(nsIPresContext* aPresContext, return rv; } + +NS_IMETHODIMP +nsAreaFrame::ReflowDirtyChild(nsIPresShell* aPresShell, nsIFrame* aChild) +{ + if (aChild) { + // See if the child is absolutely positioned + nsFrameState childState; + aChild->GetFrameState(&childState); + if (childState & NS_FRAME_OUT_OF_FLOW) { + const nsStylePosition* position; + aChild->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)position); + + if (position->IsAbsolutelyPositioned()) { + // Generate a reflow command to reflow our dirty absolutely + // positioned child frames. + // XXX Note that we don't currently try and coalesce the reflow commands, + // although we should. We can't use the NS_FRAME_HAS_DIRTY_CHILDREN + // flag, because that's used to indicate whether in-flow children are + // dirty... + nsIReflowCommand* reflowCmd; + nsresult rv = NS_NewHTMLReflowCommand(&reflowCmd, this, + nsIReflowCommand::ReflowDirty); + if (NS_SUCCEEDED(rv)) { + reflowCmd->SetChildListName(nsLayoutAtoms::absoluteList); + aPresShell->AppendReflowCommand(reflowCmd); + NS_RELEASE(reflowCmd); + } + return rv; + } + } + } + + return nsBlockFrame::ReflowDirtyChild(aPresShell, aChild); +} NS_IMETHODIMP nsAreaFrame::GetFrameType(nsIAtom** aType) const diff --git a/mozilla/layout/html/base/src/nsAreaFrame.h b/mozilla/layout/html/base/src/nsAreaFrame.h index 32f8c405ea4..49fb2ee9e15 100644 --- a/mozilla/layout/html/base/src/nsAreaFrame.h +++ b/mozilla/layout/html/base/src/nsAreaFrame.h @@ -80,6 +80,8 @@ public: const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus); + NS_IMETHOD ReflowDirtyChild(nsIPresShell* aPresShell, nsIFrame* aChild); + /** * Get the "type" of the frame *