diff --git a/mozilla/layout/html/base/src/nsBodyFrame.cpp b/mozilla/layout/html/base/src/nsBodyFrame.cpp index fdeccb1f207..38a95ef66e7 100644 --- a/mozilla/layout/html/base/src/nsBodyFrame.cpp +++ b/mozilla/layout/html/base/src/nsBodyFrame.cpp @@ -87,6 +87,19 @@ nsBodyFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) ///////////////////////////////////////////////////////////////////////////// // nsIFrame +nscoord nsBodyFrame::GetConstrainingHeight(const nsReflowState& aReflowState) const +{ + // Walk up the reflow state hierarchy until we find a height that is + // constrained + const nsReflowState* state = &aReflowState; + while (NS_UNCONSTRAINEDSIZE == state->maxSize.height) { + state = state->parentReflowState; + NS_ASSERTION(nsnull != state, "unexpected reflow hierarchy"); + } + + return state->maxSize.height; +} + NS_METHOD nsBodyFrame::Reflow(nsIPresContext& aPresContext, nsReflowMetrics& aDesiredSize, const nsReflowState& aReflowState, @@ -106,13 +119,19 @@ NS_METHOD nsBodyFrame::Reflow(nsIPresContext& aPresContext, NS_ASSERTION(eReflowReason_Initial != aReflowState.reason, "bad reason"); } + nsIFrame* reflowCmdTarget; + nsIReflowCommand::ReflowType reflowCmdType; + if (eReflowReason_Incremental == aReflowState.reason) { + NS_ASSERTION(nsnull != aReflowState.reflowCommand, "null reflow command"); + + // Get the target and the type of reflow command + aReflowState.reflowCommand->GetTarget(reflowCmdTarget); + aReflowState.reflowCommand->GetType(reflowCmdType); + // The reflow command should never be target for us #ifdef NS_DEBUG - NS_ASSERTION(nsnull != aReflowState.reflowCommand, "null reflow command"); - nsIFrame* target; - aReflowState.reflowCommand->GetTarget(target); - NS_ASSERTION(target != this, "bad reflow command target"); + NS_ASSERTION(this != reflowCmdTarget, "bad reflow command target"); #endif // Is the next frame in the reflow chain the pseudo block-frame or an @@ -121,21 +140,24 @@ NS_METHOD nsBodyFrame::Reflow(nsIPresContext& aPresContext, // If the next frame is the pseudo block-frame then fall thru to the main // code below. The only thing that should be handled below is absolutely // positioned elements... - nsIFrame* next; - aReflowState.reflowCommand->GetNext(next); - if (mFirstChild != next) { - NS_ASSERTION(this != next, "huh?"); + nsIFrame* nextFrame; + aReflowState.reflowCommand->GetNext(nextFrame); + if (mFirstChild != nextFrame) { + NS_ASSERTION(this != nextFrame, "huh?"); NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS, ("nsBodyFrame::Reflow: reflowing frame=%p", - next)); + nextFrame)); // It's an absolutely positioned frame that's the target. // XXX FIX ME. For an absolutely positioned item we need to properly // compute the available space and then resize the frame if necessary... - nsReflowState reflowState(next, aReflowState, aReflowState.maxSize); - return next->Reflow(aPresContext, aDesiredSize, reflowState, aStatus); + nsReflowState reflowState(nextFrame, aReflowState, aReflowState.maxSize); + return nextFrame->Reflow(aPresContext, aDesiredSize, reflowState, aStatus); } } + // The area that needs to be repainted. Depends on the reflow type. + nsRect damageArea(0, 0, 0, 0); + // Reflow the child frame if (nsnull != mFirstChild) { // Get our border/padding info @@ -155,6 +177,10 @@ NS_METHOD nsBodyFrame::Reflow(nsIPresContext& aPresContext, mSpaceManager->ClearRegions(); } + // Get the child's current rect + nsRect kidOldRect; + mFirstChild->GetRect(kidOldRect); + // Get the column's desired rect nsIRunaround* reflowRunaround; nsReflowState reflowState(mFirstChild, aReflowState, kidMaxSize); @@ -201,6 +227,42 @@ NS_METHOD nsBodyFrame::Reflow(nsIPresContext& aPresContext, // Return our desired size ComputeDesiredSize(desiredRect, aReflowState.maxSize, borderPadding, aDesiredSize); + + // Decide how much to repaint based on the reflow type. + switch (aReflowState.reason) { + case eReflowReason_Initial: + // If this is the initial reflow of the child then repaint the entire + // visible area + damageArea.width = aReflowState.maxSize.width; + damageArea.height = GetConstrainingHeight(aReflowState); + break; + + case eReflowReason_Resize: + // For a resize just repaint the entire frame + damageArea.width = aDesiredSize.width; + damageArea.height = aDesiredSize.height; + break; + + case eReflowReason_Incremental: + // For append reflow commands that target the body just repaint the newly + // added part of the frame. + if ((nsIReflowCommand::FrameAppended == reflowCmdType) && + (reflowCmdTarget == mFirstChild)) { + // It's an append reflow command targeted at us + damageArea.y = kidOldRect.YMost(); + damageArea.width = aDesiredSize.width; + damageArea.height = aDesiredSize.height - kidOldRect.height; + + } else { + // Ideally the frame that is the target of the reflow command (or its parent + // frame) would generate a damage rect, but since none of the frame classes + // know how to do this then for the time being just repaint the entire + // frame + damageArea.width = aDesiredSize.width; + damageArea.height = aDesiredSize.height; + } + } + } else { aDesiredSize.width = 0; @@ -212,6 +274,11 @@ NS_METHOD nsBodyFrame::Reflow(nsIPresContext& aPresContext, aDesiredSize.maxElementSize->height = 0; } } + + // Now force a repaint of the damage area + if (!mIsPseudoFrame && !damageArea.IsEmpty()) { + Invalidate(damageArea); + } NS_FRAME_TRACE_MSG(NS_FRAME_TRACE_CALLS, ("exit nsBodyFrame::Reflow: status=%d width=%d height=%d", diff --git a/mozilla/layout/html/base/src/nsBodyFrame.h b/mozilla/layout/html/base/src/nsBodyFrame.h index fbf5df90fa7..cb9c179b4cc 100644 --- a/mozilla/layout/html/base/src/nsBodyFrame.h +++ b/mozilla/layout/html/base/src/nsBodyFrame.h @@ -112,6 +112,8 @@ protected: void AddFrame(nsIFrame* aFrame); + nscoord GetConstrainingHeight(const nsReflowState&) const; + private: nsSpaceManager* mSpaceManager; nsVoidArray mAbsoluteItems;