From dd72d8029f1b0aec70ffbee2ffd303b43665c3fb Mon Sep 17 00:00:00 2001 From: "troy%netscape.com" Date: Tue, 27 Jul 1999 14:15:42 +0000 Subject: [PATCH] Changed root frame class over to new reflow command handling git-svn-id: svn://10.0.0.236/trunk@41287 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/layout/base/public/nsIFrame.h | 20 ++- .../generic/nsAbsoluteContainingBlock.cpp | 6 +- mozilla/layout/generic/nsHTMLFrame.cpp | 160 ++++++++++++++---- mozilla/layout/generic/nsIFrame.h | 20 ++- mozilla/layout/generic/nsViewportFrame.cpp | 102 ++++++----- .../base/src/nsAbsoluteContainingBlock.cpp | 6 +- mozilla/layout/html/base/src/nsHTMLFrame.cpp | 160 ++++++++++++++---- .../layout/html/base/src/nsScrollFrame.cpp | 2 +- .../layout/html/base/src/nsViewportFrame.cpp | 102 ++++++----- 9 files changed, 411 insertions(+), 167 deletions(-) diff --git a/mozilla/layout/base/public/nsIFrame.h b/mozilla/layout/base/public/nsIFrame.h index 43939d0d83f..7f2c807d8b1 100644 --- a/mozilla/layout/base/public/nsIFrame.h +++ b/mozilla/layout/base/public/nsIFrame.h @@ -226,7 +226,7 @@ public: * @param aListName the name of the child list. A NULL pointer for the atom * name means the unnamed principal child list * @param aChildList list of child frames. Each of the frames has its - * NS_FRAME_IS_DIRTY bit set + * NS_FRAME_IS_DIRTY bit set * @return NS_ERROR_INVALID_ARG if there is no child list with the specified * name, * NS_ERROR_UNEXPECTED if the frame is an atomic frame or if the @@ -246,10 +246,10 @@ public: * @param aListName the name of the child list. A NULL pointer for the atom * name means the unnamed principal child list * @param aFrameList list of child frames to append. Each of the frames has - * its NS_FRAME_IS_DIRTY bit set + * its NS_FRAME_IS_DIRTY bit set * @return NS_ERROR_INVALID_ARG if there is no child list with the specified * name, - * NS_ERROR_UNEXPECTED if the frame is an atomic frame + * NS_ERROR_UNEXPECTED if the frame is an atomic frame, * NS_OK otherwise */ NS_IMETHOD AppendFrames(nsIPresContext& aPresContext, @@ -266,10 +266,10 @@ public: * name means the unnamed principal child list * @param aPrevFrame the frame to insert frames after * @param aFrameList list of child frames to insert after aPrevFrame. - * Each of the frames has its NS_FRAME_IS_DIRTY bit set + * Each of the frames has its NS_FRAME_IS_DIRTY bit set * @return NS_ERROR_INVALID_ARG if there is no child list with the specified * name, - * NS_ERROR_UNEXPECTED if the frame is an atomic frame + * NS_ERROR_UNEXPECTED if the frame is an atomic frame, * NS_OK otherwise */ NS_IMETHOD InsertFrames(nsIPresContext& aPresContext, @@ -289,7 +289,9 @@ public: * @param aOldFrame the frame to remove * @return NS_ERROR_INVALID_ARG if there is no child list with the specified * name, - * NS_ERROR_UNEXPECTED if the frame is an atomic frame + * NS_ERROR_FAILURE if the child frame is not in the specified + * child list, + * NS_ERROR_UNEXPECTED if the frame is an atomic frame, * NS_OK otherwise */ NS_IMETHOD RemoveFrame(nsIPresContext& aPresContext, @@ -306,10 +308,12 @@ public: * name means the unnamed principal child list * @param aOldFrame the frame to remove * @param aNewFrame the frame to replace it with. The new frame has its - * NS_FRAME_IS_DIRTY bit set + * NS_FRAME_IS_DIRTY bit set * @return NS_ERROR_INVALID_ARG if there is no child list with the specified * name, - * NS_ERROR_UNEXPECTED if the frame is an atomic frame + * NS_ERROR_FAILURE if the old child frame is not in the specified + * child list, + * NS_ERROR_UNEXPECTED if the frame is an atomic frame, * NS_OK otherwise */ NS_IMETHOD ReplaceFrame(nsIPresContext& aPresContext, diff --git a/mozilla/layout/generic/nsAbsoluteContainingBlock.cpp b/mozilla/layout/generic/nsAbsoluteContainingBlock.cpp index 936eb751ffd..7168cbef305 100644 --- a/mozilla/layout/generic/nsAbsoluteContainingBlock.cpp +++ b/mozilla/layout/generic/nsAbsoluteContainingBlock.cpp @@ -120,7 +120,7 @@ nsAbsoluteContainingBlock::RemoveFrame(nsIFrame* aDelegatingFrame, // Because positioned frames aren't part of a flow, there's no additional // work to do, e.g. reflowing sibling frames. And because positioned frames // have a view, we don't need to repaint - return NS_OK; + return result ? NS_OK : NS_ERROR_FAILURE; } nsresult @@ -184,6 +184,10 @@ nsAbsoluteContainingBlock::IncrementalReflow(nsIFrame* aDelegatin f->GetFrameState(&frameState); if (frameState & NS_FRAME_IS_DIRTY) { nsReflowStatus status; + + // 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"); ReflowAbsoluteFrame(aDelegatingFrame, aPresContext, aReflowState, f, PR_TRUE, status); } diff --git a/mozilla/layout/generic/nsHTMLFrame.cpp b/mozilla/layout/generic/nsHTMLFrame.cpp index 13a62100cb5..c03c125ef7d 100644 --- a/mozilla/layout/generic/nsHTMLFrame.cpp +++ b/mozilla/layout/generic/nsHTMLFrame.cpp @@ -39,6 +39,7 @@ #include "nsIScrollableView.h" #include "nsIAreaFrame.h" #include "nsLayoutAtoms.h" +#include "nsIPresShell.h" // Interface IDs static NS_DEFINE_IID(kAreaFrameIID, NS_IAREAFRAME_IID); @@ -54,6 +55,20 @@ static NS_DEFINE_IID(kIFrameIID, NS_IFRAME_IID); */ class RootFrame : public nsHTMLContainerFrame { public: + NS_IMETHOD AppendFrames(nsIPresContext& aPresContext, + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aFrameList); + NS_IMETHOD InsertFrames(nsIPresContext& aPresContext, + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aPrevFrame, + nsIFrame* aFrameList); + NS_IMETHOD RemoveFrame(nsIPresContext& aPresContext, + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aOldFrame); + NS_IMETHOD Reflow(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, @@ -132,6 +147,102 @@ RootFrame::SetRect(const nsRect& aRect) return rv; } +NS_IMETHODIMP +RootFrame::AppendFrames(nsIPresContext& aPresContext, + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aFrameList) +{ + nsresult rv; + + NS_ASSERTION(!aListName, "unexpected child list name"); + NS_PRECONDITION(mFrames.IsEmpty(), "already have a child frame"); + if (aListName) { + // We only support unnamed principal child list + rv = NS_ERROR_INVALID_ARG; + + } else if (!mFrames.IsEmpty()) { + // We only allow a single child frame + rv = NS_ERROR_FAILURE; + + } else { + // Insert the new frames +#ifdef NS_DEBUG + nsFrame::VerifyDirtyBitSet(aFrameList); +#endif + mFrames.AppendFrame(nsnull, aFrameList); + + // Generate a reflow command to reflow the newly inserted frame + nsIReflowCommand* reflowCmd; + rv = NS_NewHTMLReflowCommand(&reflowCmd, this, nsIReflowCommand::ReflowDirty); + if (NS_SUCCEEDED(rv)) { + aPresShell.AppendReflowCommand(reflowCmd); + NS_RELEASE(reflowCmd); + } + } + + return rv; +} + +NS_IMETHODIMP +RootFrame::InsertFrames(nsIPresContext& aPresContext, + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aPrevFrame, + nsIFrame* aFrameList) +{ + nsresult rv; + + // Because we only support a single child frame inserting is the same + // as appending + NS_PRECONDITION(!aPrevFrame, "unexpected previous sibling frame"); + if (aPrevFrame) { + rv = NS_ERROR_UNEXPECTED; + } else { + rv = AppendFrames(aPresContext, aPresShell, aListName, aFrameList); + } + + return rv; +} + +NS_IMETHODIMP +RootFrame::RemoveFrame(nsIPresContext& aPresContext, + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aOldFrame) +{ + nsresult rv; + + NS_ASSERTION(!aListName, "unexpected child list name"); + if (aListName) { + // We only support the unnamed principal child list + rv = NS_ERROR_INVALID_ARG; + + } else if (aOldFrame == mFrames.FirstChild()) { + // It's our one and only child frame + // Damage the area occupied by the deleted frame + nsRect damageRect; + aOldFrame->GetRect(damageRect); + Invalidate(damageRect, PR_FALSE); + + // Remove the frame and destroy it + mFrames.DestroyFrame(aPresContext, aOldFrame); + + // Generate a reflow command so we get reflowed + nsIReflowCommand* reflowCmd; + rv = NS_NewHTMLReflowCommand(&reflowCmd, this, nsIReflowCommand::ReflowDirty); + if (NS_SUCCEEDED(rv)) { + aPresShell.AppendReflowCommand(reflowCmd); + NS_RELEASE(reflowCmd); + } + + } else { + rv = NS_ERROR_FAILURE; + } + + return rv; +} + NS_IMETHODIMP RootFrame::Reflow(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, @@ -144,50 +255,22 @@ RootFrame::Reflow(nsIPresContext& aPresContext, // Initialize OUT parameter aStatus = NS_FRAME_COMPLETE; - PRBool isChildInitialReflow = PR_FALSE; PRBool isStyleChange = PR_FALSE; + PRBool isDirtyChildReflow = PR_FALSE; // Check for an incremental reflow - // XXX This needs to use the new reflow command handling instead... if (eReflowReason_Incremental == aReflowState.reason) { // See if we're the target frame nsIFrame* targetFrame; aReflowState.reflowCommand->GetTarget(targetFrame); if (this == targetFrame) { - nsIReflowCommand::ReflowType reflowType; - nsIFrame* childFrame; - nsIFrame* deletedFrame; - // Get the reflow type + nsIReflowCommand::ReflowType reflowType; aReflowState.reflowCommand->GetType(reflowType); switch (reflowType) { - case nsIReflowCommand::FrameAppended: - case nsIReflowCommand::FrameInserted: - NS_ASSERTION(mFrames.IsEmpty(), "only one child frame allowed"); - - // Insert the frame into the child list - aReflowState.reflowCommand->GetChildFrame(childFrame); - mFrames.SetFrames(childFrame); - - // It's the child frame's initial reflow - isChildInitialReflow = PR_TRUE; - break; - - case nsIReflowCommand::FrameRemoved: - // Get the child frame we should delete - aReflowState.reflowCommand->GetChildFrame(deletedFrame); - NS_ASSERTION(deletedFrame == mFrames.FirstChild(), "not a child frame"); - - // Remove it from the child list - if (deletedFrame == mFrames.FirstChild()) { - // Damage the area occupied by the deleted frame - nsRect damageRect; - deletedFrame->GetRect(damageRect); - Invalidate(damageRect, PR_FALSE); - - mFrames.DestroyFrame(aPresContext, deletedFrame); - } + case nsIReflowCommand::ReflowDirty: + isDirtyChildReflow = PR_TRUE; break; case nsIReflowCommand::StyleChanged: @@ -210,7 +293,7 @@ RootFrame::Reflow(nsIPresContext& aPresContext, // Reflow our one and only child frame nsHTMLReflowMetrics kidDesiredSize(nsnull); if (mFrames.IsEmpty()) { - // Return our desired size + // We have no child frame, so return an empty size aDesiredSize.width = aDesiredSize.height = 0; aDesiredSize.ascent = aDesiredSize.descent = 0; @@ -222,7 +305,9 @@ RootFrame::Reflow(nsIPresContext& aPresContext, nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame, nsSize(aReflowState.availableWidth, NS_UNCONSTRAINEDSIZE)); - if (isChildInitialReflow) { + if (isDirtyChildReflow) { + // Note: the only reason the frame would be dirty would be if it had + // just been inserted or appended kidReflowState.reason = eReflowReason_Initial; kidReflowState.reflowCommand = nsnull; } else if (isStyleChange) { @@ -297,6 +382,13 @@ RootFrame::Reflow(nsIPresContext& aPresContext, nsRect rect(kidReflowState.mComputedMargin.left, kidReflowState.mComputedMargin.top, kidDesiredSize.width, kidDesiredSize.height); kidFrame->SetRect(rect); + + // If the child frame was just inserted, then we're responsible for making sure + // it repaints + if (isDirtyChildReflow) { + // Damage the area occupied by the deleted frame + Invalidate(rect, PR_FALSE); + } } // Return our desired size diff --git a/mozilla/layout/generic/nsIFrame.h b/mozilla/layout/generic/nsIFrame.h index 43939d0d83f..7f2c807d8b1 100644 --- a/mozilla/layout/generic/nsIFrame.h +++ b/mozilla/layout/generic/nsIFrame.h @@ -226,7 +226,7 @@ public: * @param aListName the name of the child list. A NULL pointer for the atom * name means the unnamed principal child list * @param aChildList list of child frames. Each of the frames has its - * NS_FRAME_IS_DIRTY bit set + * NS_FRAME_IS_DIRTY bit set * @return NS_ERROR_INVALID_ARG if there is no child list with the specified * name, * NS_ERROR_UNEXPECTED if the frame is an atomic frame or if the @@ -246,10 +246,10 @@ public: * @param aListName the name of the child list. A NULL pointer for the atom * name means the unnamed principal child list * @param aFrameList list of child frames to append. Each of the frames has - * its NS_FRAME_IS_DIRTY bit set + * its NS_FRAME_IS_DIRTY bit set * @return NS_ERROR_INVALID_ARG if there is no child list with the specified * name, - * NS_ERROR_UNEXPECTED if the frame is an atomic frame + * NS_ERROR_UNEXPECTED if the frame is an atomic frame, * NS_OK otherwise */ NS_IMETHOD AppendFrames(nsIPresContext& aPresContext, @@ -266,10 +266,10 @@ public: * name means the unnamed principal child list * @param aPrevFrame the frame to insert frames after * @param aFrameList list of child frames to insert after aPrevFrame. - * Each of the frames has its NS_FRAME_IS_DIRTY bit set + * Each of the frames has its NS_FRAME_IS_DIRTY bit set * @return NS_ERROR_INVALID_ARG if there is no child list with the specified * name, - * NS_ERROR_UNEXPECTED if the frame is an atomic frame + * NS_ERROR_UNEXPECTED if the frame is an atomic frame, * NS_OK otherwise */ NS_IMETHOD InsertFrames(nsIPresContext& aPresContext, @@ -289,7 +289,9 @@ public: * @param aOldFrame the frame to remove * @return NS_ERROR_INVALID_ARG if there is no child list with the specified * name, - * NS_ERROR_UNEXPECTED if the frame is an atomic frame + * NS_ERROR_FAILURE if the child frame is not in the specified + * child list, + * NS_ERROR_UNEXPECTED if the frame is an atomic frame, * NS_OK otherwise */ NS_IMETHOD RemoveFrame(nsIPresContext& aPresContext, @@ -306,10 +308,12 @@ public: * name means the unnamed principal child list * @param aOldFrame the frame to remove * @param aNewFrame the frame to replace it with. The new frame has its - * NS_FRAME_IS_DIRTY bit set + * NS_FRAME_IS_DIRTY bit set * @return NS_ERROR_INVALID_ARG if there is no child list with the specified * name, - * NS_ERROR_UNEXPECTED if the frame is an atomic frame + * NS_ERROR_FAILURE if the old child frame is not in the specified + * child list, + * NS_ERROR_UNEXPECTED if the frame is an atomic frame, * NS_OK otherwise */ NS_IMETHOD ReplaceFrame(nsIPresContext& aPresContext, diff --git a/mozilla/layout/generic/nsViewportFrame.cpp b/mozilla/layout/generic/nsViewportFrame.cpp index 35e68242a9d..5ad0c71f099 100644 --- a/mozilla/layout/generic/nsViewportFrame.cpp +++ b/mozilla/layout/generic/nsViewportFrame.cpp @@ -135,7 +135,7 @@ ViewportFrame::SetInitialChildList(nsIPresContext& aPresContext, nsIAtom* aListName, nsIFrame* aChildList) { - nsresult rv = NS_OK; + nsresult rv; // See which child list to add the frames to #ifdef NS_DEBUG @@ -143,6 +143,8 @@ ViewportFrame::SetInitialChildList(nsIPresContext& aPresContext, #endif if (nsLayoutAtoms::fixedList == aListName) { mFixedFrames.SetFrames(aChildList); + rv = NS_OK; + } else { rv = nsContainerFrame::SetInitialChildList(aPresContext, aListName, aChildList); } @@ -156,24 +158,28 @@ ViewportFrame::AppendFrames(nsIPresContext& aPresContext, nsIAtom* aListName, nsIFrame* aFrameList) { - nsresult rv = NS_OK; + nsresult rv; - // We only expect incremental changes for our fixed frames NS_PRECONDITION(nsLayoutAtoms::fixedList == aListName, "unexpected child list"); - - // Add the frames to our list of fixed position frames -#ifdef NS_DEBUG - nsFrame::VerifyDirtyBitSet(aFrameList); -#endif - mFixedFrames.AppendFrames(nsnull, aFrameList); - - // Generate a reflow command to reflow the dirty frames - nsIReflowCommand* reflowCmd; - rv = NS_NewHTMLReflowCommand(&reflowCmd, this, nsIReflowCommand::ReflowDirty); - if (NS_SUCCEEDED(rv)) { - reflowCmd->SetChildListName(nsLayoutAtoms::fixedList); - aPresShell.AppendReflowCommand(reflowCmd); - NS_RELEASE(reflowCmd); + if (aListName != nsLayoutAtoms::fixedList) { + // We only expect incremental changes for our fixed frames + rv = NS_ERROR_INVALID_ARG; + + } else { + // Add the frames to our list of fixed position frames + #ifdef NS_DEBUG + nsFrame::VerifyDirtyBitSet(aFrameList); + #endif + mFixedFrames.AppendFrames(nsnull, aFrameList); + + // Generate a reflow command to reflow the dirty frames + nsIReflowCommand* reflowCmd; + rv = NS_NewHTMLReflowCommand(&reflowCmd, this, nsIReflowCommand::ReflowDirty); + if (NS_SUCCEEDED(rv)) { + reflowCmd->SetChildListName(nsLayoutAtoms::fixedList); + aPresShell.AppendReflowCommand(reflowCmd); + NS_RELEASE(reflowCmd); + } } return rv; @@ -186,24 +192,28 @@ ViewportFrame::InsertFrames(nsIPresContext& aPresContext, nsIFrame* aPrevFrame, nsIFrame* aFrameList) { - nsresult rv = NS_OK; + nsresult rv; - // We only expect incremental changes for our fixed frames NS_PRECONDITION(nsLayoutAtoms::fixedList == aListName, "unexpected child list"); - - // Insert the new frames -#ifdef NS_DEBUG - nsFrame::VerifyDirtyBitSet(aFrameList); -#endif - mFixedFrames.InsertFrames(nsnull, aPrevFrame, aFrameList); + if (aListName != nsLayoutAtoms::fixedList) { + // We only expect incremental changes for our fixed frames + rv = NS_ERROR_INVALID_ARG; - // Generate a reflow command to reflow the dirty frames - nsIReflowCommand* reflowCmd; - rv = NS_NewHTMLReflowCommand(&reflowCmd, this, nsIReflowCommand::ReflowDirty); - if (NS_SUCCEEDED(rv)) { - reflowCmd->SetChildListName(nsLayoutAtoms::fixedList); - aPresShell.AppendReflowCommand(reflowCmd); - NS_RELEASE(reflowCmd); + } else { + // Insert the new frames +#ifdef NS_DEBUG + nsFrame::VerifyDirtyBitSet(aFrameList); +#endif + mFixedFrames.InsertFrames(nsnull, aPrevFrame, aFrameList); + + // Generate a reflow command to reflow the dirty frames + nsIReflowCommand* reflowCmd; + rv = NS_NewHTMLReflowCommand(&reflowCmd, this, nsIReflowCommand::ReflowDirty); + if (NS_SUCCEEDED(rv)) { + reflowCmd->SetChildListName(nsLayoutAtoms::fixedList); + aPresShell.AppendReflowCommand(reflowCmd); + NS_RELEASE(reflowCmd); + } } return rv; @@ -215,15 +225,23 @@ ViewportFrame::RemoveFrame(nsIPresContext& aPresContext, nsIAtom* aListName, nsIFrame* aOldFrame) { - // We only expect incremental changes for our fixed frames + nsresult rv; + NS_PRECONDITION(nsLayoutAtoms::fixedList == aListName, "unexpected child list"); - - PRBool result = mFixedFrames.DestroyFrame(aPresContext, aOldFrame); - NS_ASSERTION(result, "didn't find frame to delete"); - // Because fixed frames aren't part of a flow, there's no additional - // work to do, e.g. reflowing sibling frames. And because fixed frames - // have a view, we don't need to repaint - return NS_OK; + if (aListName != nsLayoutAtoms::fixedList) { + // We only expect incremental changes for our fixed frames + rv = NS_ERROR_INVALID_ARG; + + } else { + PRBool result = mFixedFrames.DestroyFrame(aPresContext, aOldFrame); + NS_ASSERTION(result, "didn't find frame to delete"); + // Because fixed frames aren't part of a flow, there's no additional + // work to do, e.g. reflowing sibling frames. And because fixed frames + // have a view, we don't need to repaint + rv = result ? NS_OK : NS_ERROR_FAILURE; + } + + return rv; } NS_IMETHODIMP @@ -412,6 +430,10 @@ ViewportFrame::IncrementalReflow(nsIPresContext& aPresContext, f->GetFrameState(&frameState); if (frameState & NS_FRAME_IS_DIRTY) { nsReflowStatus status; + + // 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"); ReflowFixedFrame(aPresContext, reflowState, f, PR_TRUE, status); } } diff --git a/mozilla/layout/html/base/src/nsAbsoluteContainingBlock.cpp b/mozilla/layout/html/base/src/nsAbsoluteContainingBlock.cpp index 936eb751ffd..7168cbef305 100644 --- a/mozilla/layout/html/base/src/nsAbsoluteContainingBlock.cpp +++ b/mozilla/layout/html/base/src/nsAbsoluteContainingBlock.cpp @@ -120,7 +120,7 @@ nsAbsoluteContainingBlock::RemoveFrame(nsIFrame* aDelegatingFrame, // Because positioned frames aren't part of a flow, there's no additional // work to do, e.g. reflowing sibling frames. And because positioned frames // have a view, we don't need to repaint - return NS_OK; + return result ? NS_OK : NS_ERROR_FAILURE; } nsresult @@ -184,6 +184,10 @@ nsAbsoluteContainingBlock::IncrementalReflow(nsIFrame* aDelegatin f->GetFrameState(&frameState); if (frameState & NS_FRAME_IS_DIRTY) { nsReflowStatus status; + + // 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"); ReflowAbsoluteFrame(aDelegatingFrame, aPresContext, aReflowState, f, PR_TRUE, status); } diff --git a/mozilla/layout/html/base/src/nsHTMLFrame.cpp b/mozilla/layout/html/base/src/nsHTMLFrame.cpp index 13a62100cb5..c03c125ef7d 100644 --- a/mozilla/layout/html/base/src/nsHTMLFrame.cpp +++ b/mozilla/layout/html/base/src/nsHTMLFrame.cpp @@ -39,6 +39,7 @@ #include "nsIScrollableView.h" #include "nsIAreaFrame.h" #include "nsLayoutAtoms.h" +#include "nsIPresShell.h" // Interface IDs static NS_DEFINE_IID(kAreaFrameIID, NS_IAREAFRAME_IID); @@ -54,6 +55,20 @@ static NS_DEFINE_IID(kIFrameIID, NS_IFRAME_IID); */ class RootFrame : public nsHTMLContainerFrame { public: + NS_IMETHOD AppendFrames(nsIPresContext& aPresContext, + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aFrameList); + NS_IMETHOD InsertFrames(nsIPresContext& aPresContext, + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aPrevFrame, + nsIFrame* aFrameList); + NS_IMETHOD RemoveFrame(nsIPresContext& aPresContext, + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aOldFrame); + NS_IMETHOD Reflow(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, @@ -132,6 +147,102 @@ RootFrame::SetRect(const nsRect& aRect) return rv; } +NS_IMETHODIMP +RootFrame::AppendFrames(nsIPresContext& aPresContext, + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aFrameList) +{ + nsresult rv; + + NS_ASSERTION(!aListName, "unexpected child list name"); + NS_PRECONDITION(mFrames.IsEmpty(), "already have a child frame"); + if (aListName) { + // We only support unnamed principal child list + rv = NS_ERROR_INVALID_ARG; + + } else if (!mFrames.IsEmpty()) { + // We only allow a single child frame + rv = NS_ERROR_FAILURE; + + } else { + // Insert the new frames +#ifdef NS_DEBUG + nsFrame::VerifyDirtyBitSet(aFrameList); +#endif + mFrames.AppendFrame(nsnull, aFrameList); + + // Generate a reflow command to reflow the newly inserted frame + nsIReflowCommand* reflowCmd; + rv = NS_NewHTMLReflowCommand(&reflowCmd, this, nsIReflowCommand::ReflowDirty); + if (NS_SUCCEEDED(rv)) { + aPresShell.AppendReflowCommand(reflowCmd); + NS_RELEASE(reflowCmd); + } + } + + return rv; +} + +NS_IMETHODIMP +RootFrame::InsertFrames(nsIPresContext& aPresContext, + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aPrevFrame, + nsIFrame* aFrameList) +{ + nsresult rv; + + // Because we only support a single child frame inserting is the same + // as appending + NS_PRECONDITION(!aPrevFrame, "unexpected previous sibling frame"); + if (aPrevFrame) { + rv = NS_ERROR_UNEXPECTED; + } else { + rv = AppendFrames(aPresContext, aPresShell, aListName, aFrameList); + } + + return rv; +} + +NS_IMETHODIMP +RootFrame::RemoveFrame(nsIPresContext& aPresContext, + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aOldFrame) +{ + nsresult rv; + + NS_ASSERTION(!aListName, "unexpected child list name"); + if (aListName) { + // We only support the unnamed principal child list + rv = NS_ERROR_INVALID_ARG; + + } else if (aOldFrame == mFrames.FirstChild()) { + // It's our one and only child frame + // Damage the area occupied by the deleted frame + nsRect damageRect; + aOldFrame->GetRect(damageRect); + Invalidate(damageRect, PR_FALSE); + + // Remove the frame and destroy it + mFrames.DestroyFrame(aPresContext, aOldFrame); + + // Generate a reflow command so we get reflowed + nsIReflowCommand* reflowCmd; + rv = NS_NewHTMLReflowCommand(&reflowCmd, this, nsIReflowCommand::ReflowDirty); + if (NS_SUCCEEDED(rv)) { + aPresShell.AppendReflowCommand(reflowCmd); + NS_RELEASE(reflowCmd); + } + + } else { + rv = NS_ERROR_FAILURE; + } + + return rv; +} + NS_IMETHODIMP RootFrame::Reflow(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, @@ -144,50 +255,22 @@ RootFrame::Reflow(nsIPresContext& aPresContext, // Initialize OUT parameter aStatus = NS_FRAME_COMPLETE; - PRBool isChildInitialReflow = PR_FALSE; PRBool isStyleChange = PR_FALSE; + PRBool isDirtyChildReflow = PR_FALSE; // Check for an incremental reflow - // XXX This needs to use the new reflow command handling instead... if (eReflowReason_Incremental == aReflowState.reason) { // See if we're the target frame nsIFrame* targetFrame; aReflowState.reflowCommand->GetTarget(targetFrame); if (this == targetFrame) { - nsIReflowCommand::ReflowType reflowType; - nsIFrame* childFrame; - nsIFrame* deletedFrame; - // Get the reflow type + nsIReflowCommand::ReflowType reflowType; aReflowState.reflowCommand->GetType(reflowType); switch (reflowType) { - case nsIReflowCommand::FrameAppended: - case nsIReflowCommand::FrameInserted: - NS_ASSERTION(mFrames.IsEmpty(), "only one child frame allowed"); - - // Insert the frame into the child list - aReflowState.reflowCommand->GetChildFrame(childFrame); - mFrames.SetFrames(childFrame); - - // It's the child frame's initial reflow - isChildInitialReflow = PR_TRUE; - break; - - case nsIReflowCommand::FrameRemoved: - // Get the child frame we should delete - aReflowState.reflowCommand->GetChildFrame(deletedFrame); - NS_ASSERTION(deletedFrame == mFrames.FirstChild(), "not a child frame"); - - // Remove it from the child list - if (deletedFrame == mFrames.FirstChild()) { - // Damage the area occupied by the deleted frame - nsRect damageRect; - deletedFrame->GetRect(damageRect); - Invalidate(damageRect, PR_FALSE); - - mFrames.DestroyFrame(aPresContext, deletedFrame); - } + case nsIReflowCommand::ReflowDirty: + isDirtyChildReflow = PR_TRUE; break; case nsIReflowCommand::StyleChanged: @@ -210,7 +293,7 @@ RootFrame::Reflow(nsIPresContext& aPresContext, // Reflow our one and only child frame nsHTMLReflowMetrics kidDesiredSize(nsnull); if (mFrames.IsEmpty()) { - // Return our desired size + // We have no child frame, so return an empty size aDesiredSize.width = aDesiredSize.height = 0; aDesiredSize.ascent = aDesiredSize.descent = 0; @@ -222,7 +305,9 @@ RootFrame::Reflow(nsIPresContext& aPresContext, nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame, nsSize(aReflowState.availableWidth, NS_UNCONSTRAINEDSIZE)); - if (isChildInitialReflow) { + if (isDirtyChildReflow) { + // Note: the only reason the frame would be dirty would be if it had + // just been inserted or appended kidReflowState.reason = eReflowReason_Initial; kidReflowState.reflowCommand = nsnull; } else if (isStyleChange) { @@ -297,6 +382,13 @@ RootFrame::Reflow(nsIPresContext& aPresContext, nsRect rect(kidReflowState.mComputedMargin.left, kidReflowState.mComputedMargin.top, kidDesiredSize.width, kidDesiredSize.height); kidFrame->SetRect(rect); + + // If the child frame was just inserted, then we're responsible for making sure + // it repaints + if (isDirtyChildReflow) { + // Damage the area occupied by the deleted frame + Invalidate(rect, PR_FALSE); + } } // Return our desired size diff --git a/mozilla/layout/html/base/src/nsScrollFrame.cpp b/mozilla/layout/html/base/src/nsScrollFrame.cpp index 14c8d88265b..48a54291e6b 100644 --- a/mozilla/layout/html/base/src/nsScrollFrame.cpp +++ b/mozilla/layout/html/base/src/nsScrollFrame.cpp @@ -142,7 +142,7 @@ nsScrollFrame::RemoveFrame(nsIPresContext& aPresContext, nsIAtom* aListName, nsIFrame* aOldFrame) { - // Scroll frames doesn't support incremental changes + // Scroll frame doesn't support incremental changes return NS_ERROR_NOT_IMPLEMENTED; } diff --git a/mozilla/layout/html/base/src/nsViewportFrame.cpp b/mozilla/layout/html/base/src/nsViewportFrame.cpp index 35e68242a9d..5ad0c71f099 100644 --- a/mozilla/layout/html/base/src/nsViewportFrame.cpp +++ b/mozilla/layout/html/base/src/nsViewportFrame.cpp @@ -135,7 +135,7 @@ ViewportFrame::SetInitialChildList(nsIPresContext& aPresContext, nsIAtom* aListName, nsIFrame* aChildList) { - nsresult rv = NS_OK; + nsresult rv; // See which child list to add the frames to #ifdef NS_DEBUG @@ -143,6 +143,8 @@ ViewportFrame::SetInitialChildList(nsIPresContext& aPresContext, #endif if (nsLayoutAtoms::fixedList == aListName) { mFixedFrames.SetFrames(aChildList); + rv = NS_OK; + } else { rv = nsContainerFrame::SetInitialChildList(aPresContext, aListName, aChildList); } @@ -156,24 +158,28 @@ ViewportFrame::AppendFrames(nsIPresContext& aPresContext, nsIAtom* aListName, nsIFrame* aFrameList) { - nsresult rv = NS_OK; + nsresult rv; - // We only expect incremental changes for our fixed frames NS_PRECONDITION(nsLayoutAtoms::fixedList == aListName, "unexpected child list"); - - // Add the frames to our list of fixed position frames -#ifdef NS_DEBUG - nsFrame::VerifyDirtyBitSet(aFrameList); -#endif - mFixedFrames.AppendFrames(nsnull, aFrameList); - - // Generate a reflow command to reflow the dirty frames - nsIReflowCommand* reflowCmd; - rv = NS_NewHTMLReflowCommand(&reflowCmd, this, nsIReflowCommand::ReflowDirty); - if (NS_SUCCEEDED(rv)) { - reflowCmd->SetChildListName(nsLayoutAtoms::fixedList); - aPresShell.AppendReflowCommand(reflowCmd); - NS_RELEASE(reflowCmd); + if (aListName != nsLayoutAtoms::fixedList) { + // We only expect incremental changes for our fixed frames + rv = NS_ERROR_INVALID_ARG; + + } else { + // Add the frames to our list of fixed position frames + #ifdef NS_DEBUG + nsFrame::VerifyDirtyBitSet(aFrameList); + #endif + mFixedFrames.AppendFrames(nsnull, aFrameList); + + // Generate a reflow command to reflow the dirty frames + nsIReflowCommand* reflowCmd; + rv = NS_NewHTMLReflowCommand(&reflowCmd, this, nsIReflowCommand::ReflowDirty); + if (NS_SUCCEEDED(rv)) { + reflowCmd->SetChildListName(nsLayoutAtoms::fixedList); + aPresShell.AppendReflowCommand(reflowCmd); + NS_RELEASE(reflowCmd); + } } return rv; @@ -186,24 +192,28 @@ ViewportFrame::InsertFrames(nsIPresContext& aPresContext, nsIFrame* aPrevFrame, nsIFrame* aFrameList) { - nsresult rv = NS_OK; + nsresult rv; - // We only expect incremental changes for our fixed frames NS_PRECONDITION(nsLayoutAtoms::fixedList == aListName, "unexpected child list"); - - // Insert the new frames -#ifdef NS_DEBUG - nsFrame::VerifyDirtyBitSet(aFrameList); -#endif - mFixedFrames.InsertFrames(nsnull, aPrevFrame, aFrameList); + if (aListName != nsLayoutAtoms::fixedList) { + // We only expect incremental changes for our fixed frames + rv = NS_ERROR_INVALID_ARG; - // Generate a reflow command to reflow the dirty frames - nsIReflowCommand* reflowCmd; - rv = NS_NewHTMLReflowCommand(&reflowCmd, this, nsIReflowCommand::ReflowDirty); - if (NS_SUCCEEDED(rv)) { - reflowCmd->SetChildListName(nsLayoutAtoms::fixedList); - aPresShell.AppendReflowCommand(reflowCmd); - NS_RELEASE(reflowCmd); + } else { + // Insert the new frames +#ifdef NS_DEBUG + nsFrame::VerifyDirtyBitSet(aFrameList); +#endif + mFixedFrames.InsertFrames(nsnull, aPrevFrame, aFrameList); + + // Generate a reflow command to reflow the dirty frames + nsIReflowCommand* reflowCmd; + rv = NS_NewHTMLReflowCommand(&reflowCmd, this, nsIReflowCommand::ReflowDirty); + if (NS_SUCCEEDED(rv)) { + reflowCmd->SetChildListName(nsLayoutAtoms::fixedList); + aPresShell.AppendReflowCommand(reflowCmd); + NS_RELEASE(reflowCmd); + } } return rv; @@ -215,15 +225,23 @@ ViewportFrame::RemoveFrame(nsIPresContext& aPresContext, nsIAtom* aListName, nsIFrame* aOldFrame) { - // We only expect incremental changes for our fixed frames + nsresult rv; + NS_PRECONDITION(nsLayoutAtoms::fixedList == aListName, "unexpected child list"); - - PRBool result = mFixedFrames.DestroyFrame(aPresContext, aOldFrame); - NS_ASSERTION(result, "didn't find frame to delete"); - // Because fixed frames aren't part of a flow, there's no additional - // work to do, e.g. reflowing sibling frames. And because fixed frames - // have a view, we don't need to repaint - return NS_OK; + if (aListName != nsLayoutAtoms::fixedList) { + // We only expect incremental changes for our fixed frames + rv = NS_ERROR_INVALID_ARG; + + } else { + PRBool result = mFixedFrames.DestroyFrame(aPresContext, aOldFrame); + NS_ASSERTION(result, "didn't find frame to delete"); + // Because fixed frames aren't part of a flow, there's no additional + // work to do, e.g. reflowing sibling frames. And because fixed frames + // have a view, we don't need to repaint + rv = result ? NS_OK : NS_ERROR_FAILURE; + } + + return rv; } NS_IMETHODIMP @@ -412,6 +430,10 @@ ViewportFrame::IncrementalReflow(nsIPresContext& aPresContext, f->GetFrameState(&frameState); if (frameState & NS_FRAME_IS_DIRTY) { nsReflowStatus status; + + // 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"); ReflowFixedFrame(aPresContext, reflowState, f, PR_TRUE, status); } }