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
This commit is contained in:
troy%netscape.com 1999-07-27 14:15:42 +00:00
parent 177b8110fa
commit dd72d8029f
9 changed files with 411 additions and 167 deletions

View File

@ -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 <b>after</b>
* @param aFrameList list of child frames to insert <b>after</b> 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,

View File

@ -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);
}

View File

@ -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

View File

@ -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 <b>after</b>
* @param aFrameList list of child frames to insert <b>after</b> 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,

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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

View File

@ -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;
}

View File

@ -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);
}
}