Bug 135146. Implement NS_FRAME_REFLOW_ROOT to allow reflows for <textarea> and <input type='text'> to be dispatched from the scroll frame within the nsGfxTextControlFrame2. r=kin, sr=attinasi

This commit is contained in:
waterson%netscape.com 2002-04-11 01:13:41 +00:00
Родитель e87a5b9301
Коммит b6fb7fe914
13 изменённых файлов: 180 добавлений и 262 удалений

Просмотреть файл

@ -209,6 +209,10 @@ typedef PRUint32 nsFrameState;
// If this bit is set the frame has descendant with a view
#define NS_FRAME_HAS_CHILD_WITH_VIEW 0x00040000
// If this bit is set, then reflow may be dispatched from the current
// frame instead of the root frame.
#define NS_FRAME_REFLOW_ROOT 0x00080000
// The lower 20 bits of the frame state word are reserved by this API.
#define NS_FRAME_RESERVED 0x000FFFFF

Просмотреть файл

@ -845,24 +845,21 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
NS_ASSERTION(NS_SUCCEEDED(rv), "reflow dirty lines failed");
if (NS_FAILED(rv)) return rv;
if (!state.GetFlag(BRS_ISINLINEINCRREFLOW)) {
// XXXwaterson are we sure we don't need to do this work if BRS_ISINLINEINCRREFLOW?
aStatus = state.mReflowStatus;
if (NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
if (NS_STYLE_OVERFLOW_HIDDEN == aReflowState.mStyleDisplay->mOverflow) {
aStatus = NS_FRAME_COMPLETE;
}
else {
#ifdef DEBUG_kipp
ListTag(stdout); printf(": block is not complete\n");
#endif
}
aStatus = state.mReflowStatus;
if (NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
if (NS_STYLE_OVERFLOW_HIDDEN == aReflowState.mStyleDisplay->mOverflow) {
aStatus = NS_FRAME_COMPLETE;
}
else {
#ifdef DEBUG_kipp
ListTag(stdout); printf(": block is not complete\n");
#endif
}
// XXX_perf get rid of this! This is one of the things that makes
// incremental reflow O(N^2).
BuildFloaterList();
}
// XXX_perf get rid of this! This is one of the things that makes
// incremental reflow O(N^2).
BuildFloaterList();
// Compute our final size
ComputeFinalSize(aReflowState, state, aMetrics);
@ -919,10 +916,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
// If this is an incremental reflow and we changed size, then make sure our
// border is repainted if necessary
//
// XXXwaterson are we sure we can skip this if BRS_ISINLINEINCRREFLOW?
if (!state.GetFlag(BRS_ISINLINEINCRREFLOW) &&
(eReflowReason_Incremental == aReflowState.reason ||
if ((eReflowReason_Incremental == aReflowState.reason ||
eReflowReason_Dirty == aReflowState.reason)) {
if (isStyleChange) {
// This is only true if it's a style change reflow targeted at this
@ -1005,10 +999,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
// Let the absolutely positioned container reflow any absolutely positioned
// child frames that need to be reflowed, e.g., elements with a percentage
// based width/height
//
// XXXwaterson are we sure we can skip this if BRS_ISINLINEINCRREFLOW?
if (NS_SUCCEEDED(rv) && mAbsoluteContainer.HasAbsoluteFrames()
&& !state.GetFlag(BRS_ISINLINEINCRREFLOW)) {
if (NS_SUCCEEDED(rv) && mAbsoluteContainer.HasAbsoluteFrames()) {
nscoord containingBlockWidth;
nscoord containingBlockHeight;
nsRect childBounds;
@ -1576,8 +1567,6 @@ nsBlockFrame::PrepareChildIncrementalReflow(nsBlockReflowState& aState)
}
if (line->IsInline()) {
aState.SetFlag(BRS_ISINLINEINCRREFLOW, PR_TRUE);
if (aState.GetFlag(BRS_COMPUTEMAXWIDTH)) {
// We've been asked to compute the maximum width of the block
// frame, which ReflowLine() will handle this by performing an
@ -2131,9 +2120,8 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
aState.mReflowState.reflowCommand->GetType(type);
IndentBy(stdout, gNoiseIndent);
ListTag(stdout);
printf(": incrementally reflowing dirty lines: type=%s(%d) isInline=%s",
kReflowCommandType[type], type,
aState.GetFlag(BRS_ISINLINEINCRREFLOW) ? "true" : "false");
printf(": incrementally reflowing dirty lines: type=%s(%d)",
kReflowCommandType[type], type);
}
else {
IndentBy(stdout, gNoiseIndent);

Просмотреть файл

@ -176,8 +176,6 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
mMinLineHeight = nsHTMLReflowState::CalcLineHeight(mPresContext,
aReflowState.rendContext,
aReflowState.frame);
SetFlag(BRS_DAMAGECONSTRAINED, IsIncrementalDamageConstrained(aFrame));
}
nsBlockReflowState::~nsBlockReflowState()
@ -190,32 +188,6 @@ nsBlockReflowState::~nsBlockReflowState()
}
}
PRBool
nsBlockReflowState::IsIncrementalDamageConstrained(nsIFrame* aBlockFrame) const
{
// see if the reflow will go through a text control. if so, we can optimize
// because we know the text control won't change size.
if ((eReflowReason_Incremental == mReflowState.reason) && (mReflowState.reflowCommand)) {
nsIFrame* target;
mReflowState.reflowCommand->GetTarget(target);
while (target) {
// starting with the target's parent, scan for a text control
nsIFrame* parent;
target->GetParent(&parent);
if ((aBlockFrame == parent) || !parent) // the null check is paranoia, it should never happen
break; // we found the block, so we know there's no text control between the block and target
nsCOMPtr<nsIAtom> frameType;
parent->GetFrameType(getter_AddRefs(frameType));
if (frameType) {
if (nsLayoutAtoms::textInputFrame == frameType.get())
return PR_TRUE; // damage is constrained to the text control innards
}
target = parent; // advance the loop up the frame tree
}
}
return PR_FALSE; // default case, damage is not constrained (or unknown)
}
nsLineBox*
nsBlockReflowState::NewLineBox(nsIFrame* aFrame,
PRInt32 aCount,

Просмотреть файл

@ -112,10 +112,6 @@ public:
protected:
void RecoverFloaters(nsLineList::iterator aLine, nscoord aDeltaY);
// return PR_TRUE if the incremental reflow is 100% contained
// within the bounds of an ancestor frame, relative to aBlockFrame
PRBool IsIncrementalDamageConstrained(nsIFrame* aBlockFrame) const;
public:
void RecoverStateFrom(nsLineList::iterator aLine, nscoord aDeltaY);
@ -248,14 +244,13 @@ public:
#define BRS_UNCONSTRAINEDHEIGHT 0x00000002
#define BRS_SHRINKWRAPWIDTH 0x00000004
#define BRS_NEEDRESIZEREFLOW 0x00000008
#define BRS_ISINLINEINCRREFLOW 0x00000010
#define BRS_NOWRAP 0x00000020
#define BRS_ISTOPMARGINROOT 0x00000040 // Is this frame a root for top/bottom margin collapsing?
#define BRS_ISBOTTOMMARGINROOT 0x00000080
#define BRS_APPLYTOPMARGIN 0x00000100 // See ShouldApplyTopMargin
#define BRS_COMPUTEMAXELEMENTSIZE 0x00000200
#define BRS_COMPUTEMAXWIDTH 0x00000400
#define BRS_DAMAGECONSTRAINED 0x00000800 // is the target of an incremental reflow command inside a text control
#define BRS_NOWRAP 0x00000010
#define BRS_ISTOPMARGINROOT 0x00000020 // Is this frame a root for top/bottom margin collapsing?
#define BRS_ISBOTTOMMARGINROOT 0x00000040
#define BRS_APPLYTOPMARGIN 0x00000080 // See ShouldApplyTopMargin
#define BRS_COMPUTEMAXELEMENTSIZE 0x00000100
#define BRS_COMPUTEMAXWIDTH 0x00000200
#define BRS_DAMAGECONSTRAINED 0x00000400 // is the target of an incremental reflow command inside a text control
#define BRS_LASTFLAG BRS_DAMAGECONSTRAINED
PRInt16 mFlags;

Просмотреть файл

@ -46,7 +46,7 @@
#include "nsHTMLIIDs.h"
#include "nsFrame.h"
#include "nsContainerFrame.h"
#include "nsLayoutAtoms.h"
nsresult
NS_NewHTMLReflowCommand(nsHTMLReflowCommand** aInstancePtrResult,
@ -144,13 +144,6 @@ nsHTMLReflowCommand::~nsHTMLReflowCommand()
NS_IF_RELEASE(mListName);
}
nsIFrame* nsHTMLReflowCommand::GetContainingBlock(nsIFrame* aFloater) const
{
nsIFrame* containingBlock;
aFloater->GetParent(&containingBlock);
return containingBlock;
}
void nsHTMLReflowCommand::BuildPath()
{
#ifdef DEBUG_jesup
@ -164,22 +157,15 @@ void nsHTMLReflowCommand::BuildPath()
mPath.Clear();
// Floating frames are handled differently. The path goes from the target
// frame to the containing block, and then up the hierarchy
const nsStyleDisplay* display;
mTargetFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
if (NS_STYLE_FLOAT_NONE != display->mFloats) {
mPath.AppendElement((void*)mTargetFrame);
for (nsIFrame* f = GetContainingBlock(mTargetFrame); nsnull != f; f->GetParent(&f)) {
mPath.AppendElement((void*)f);
}
} else {
for (nsIFrame* f = mTargetFrame; nsnull != f; f->GetParent(&f)) {
mPath.AppendElement((void*)f);
}
}
// Construct the reflow path by walking up the through the frames'
// parent chain until we reach either a `reflow root' or the root
// frame in the frame hierarchy.
nsIFrame *f = mTargetFrame;
nsFrameState state;
do {
mPath.AppendElement(f);
f->GetFrameState(&state);
} while (!(state & NS_FRAME_REFLOW_ROOT) && (f->GetParent(&f), f != nsnull));
}
nsresult
@ -188,41 +174,61 @@ nsHTMLReflowCommand::Dispatch(nsIPresContext* aPresContext,
const nsSize& aMaxSize,
nsIRenderingContext& aRendContext)
{
// Build the path from the target frame (index 0) to the root frame
// Build the path from the target frame (index 0)
BuildPath();
// Send an incremental reflow notification to the root frame
nsIFrame* root = (nsIFrame*)mPath[mPath.Count() - 1];
// Send an incremental reflow notification to the first frame in the
// path.
nsIFrame* first = (nsIFrame*)mPath[mPath.Count() - 1];
#ifdef NS_DEBUG
nsCOMPtr<nsIPresShell> shell;
aPresContext->GetShell(getter_AddRefs(shell));
if (shell) {
nsIFrame* rootFrame;
shell->GetRootFrame(&rootFrame);
NS_ASSERTION(rootFrame == root, "bad root frame");
}
#endif
if (nsnull != root) {
mPath.RemoveElementAt(mPath.Count() - 1);
nsIFrame* root;
shell->GetRootFrame(&root);
nsHTMLReflowState reflowState(aPresContext, root, *this,
&aRendContext, aMaxSize);
nsReflowStatus status;
// Remove the first frame from the path and reflow it.
mPath.RemoveElementAt(mPath.Count() - 1);
root->WillReflow(aPresContext);
nsContainerFrame::PositionFrameView(aPresContext, root);
root->Reflow(aPresContext, aDesiredSize, reflowState, status);
root->SizeTo(aPresContext, aDesiredSize.width, aDesiredSize.height);
nsIView* view;
root->GetView(aPresContext, &view);
if (view) {
nsContainerFrame::SyncFrameViewAfterReflow(aPresContext, root, view,
nsnull);
}
root->DidReflow(aPresContext, nsnull, NS_FRAME_REFLOW_FINISHED);
}
first->WillReflow(aPresContext);
nsContainerFrame::PositionFrameView(aPresContext, first);
// If the first frame in the path is the root of the frame
// hierarchy, then use all the available space. If it's simply a
// `reflow root', then use the first frame's size as the available
// space.
//
// XXXwaterson Beware that this is not sufficiently general to allow
// arbitrary frames to be reflow roots. For example, and inline
// frame cannot be a reflow root because nsHTMLReflowState::Init()
// will try to walk up through the reflow state chain to find the
// containing block.
nsSize size;
if (first == root)
size = aMaxSize;
else
first->GetSize(size);
nsHTMLReflowState reflowState(aPresContext, first, *this,
&aRendContext, size);
nsReflowStatus status;
first->Reflow(aPresContext, aDesiredSize, reflowState, status);
// If an incremental reflow is initiated at a frame other than the
// root frame, then its desired size had better not change!
NS_ASSERTION(first == root ||
(aDesiredSize.width == size.width && aDesiredSize.height == size.height),
"non-root frame's desired size changed during an incremental reflow");
first->SizeTo(aPresContext, aDesiredSize.width, aDesiredSize.height);
nsIView* view;
first->GetView(aPresContext, &view);
if (view)
nsContainerFrame::SyncFrameViewAfterReflow(aPresContext, first, view, nsnull);
first->DidReflow(aPresContext, nsnull, NS_FRAME_REFLOW_FINISHED);
return NS_OK;
}
@ -344,17 +350,8 @@ nsHTMLReflowCommand::List(FILE* out) const
// Show the path, but without using mPath which is in an undefined
// state at this point.
if (mTargetFrame) {
// Floating frames are handled differently. The path goes from the target
// frame to the containing block, and then up the hierarchy
PRBool didOne = PR_FALSE;
nsIFrame* start = mTargetFrame;
const nsStyleDisplay* display;
mTargetFrame->GetStyleData(eStyleStruct_Display,
(const nsStyleStruct*&) display);
if (NS_STYLE_FLOAT_NONE != display->mFloats) {
start = GetContainingBlock(mTargetFrame);
}
for (nsIFrame* f = start; nsnull != f; f->GetParent(&f)) {
for (nsIFrame* f = mTargetFrame; nsnull != f; f->GetParent(&f)) {
if (f != mTargetFrame) {
fprintf(out, " ");
nsFrame::ListTag(out, f);

Просмотреть файл

@ -175,7 +175,6 @@ public:
protected:
void BuildPath();
nsIFrame* GetContainingBlock(nsIFrame* aFloater) const;
private:
nsReflowType mType;

Просмотреть файл

@ -209,6 +209,10 @@ typedef PRUint32 nsFrameState;
// If this bit is set the frame has descendant with a view
#define NS_FRAME_HAS_CHILD_WITH_VIEW 0x00040000
// If this bit is set, then reflow may be dispatched from the current
// frame instead of the root frame.
#define NS_FRAME_REFLOW_ROOT 0x00080000
// The lower 20 bits of the frame state word are reserved by this API.
#define NS_FRAME_RESERVED 0x000FFFFF

Просмотреть файл

@ -845,24 +845,21 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
NS_ASSERTION(NS_SUCCEEDED(rv), "reflow dirty lines failed");
if (NS_FAILED(rv)) return rv;
if (!state.GetFlag(BRS_ISINLINEINCRREFLOW)) {
// XXXwaterson are we sure we don't need to do this work if BRS_ISINLINEINCRREFLOW?
aStatus = state.mReflowStatus;
if (NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
if (NS_STYLE_OVERFLOW_HIDDEN == aReflowState.mStyleDisplay->mOverflow) {
aStatus = NS_FRAME_COMPLETE;
}
else {
#ifdef DEBUG_kipp
ListTag(stdout); printf(": block is not complete\n");
#endif
}
aStatus = state.mReflowStatus;
if (NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
if (NS_STYLE_OVERFLOW_HIDDEN == aReflowState.mStyleDisplay->mOverflow) {
aStatus = NS_FRAME_COMPLETE;
}
else {
#ifdef DEBUG_kipp
ListTag(stdout); printf(": block is not complete\n");
#endif
}
// XXX_perf get rid of this! This is one of the things that makes
// incremental reflow O(N^2).
BuildFloaterList();
}
// XXX_perf get rid of this! This is one of the things that makes
// incremental reflow O(N^2).
BuildFloaterList();
// Compute our final size
ComputeFinalSize(aReflowState, state, aMetrics);
@ -919,10 +916,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
// If this is an incremental reflow and we changed size, then make sure our
// border is repainted if necessary
//
// XXXwaterson are we sure we can skip this if BRS_ISINLINEINCRREFLOW?
if (!state.GetFlag(BRS_ISINLINEINCRREFLOW) &&
(eReflowReason_Incremental == aReflowState.reason ||
if ((eReflowReason_Incremental == aReflowState.reason ||
eReflowReason_Dirty == aReflowState.reason)) {
if (isStyleChange) {
// This is only true if it's a style change reflow targeted at this
@ -1005,10 +999,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
// Let the absolutely positioned container reflow any absolutely positioned
// child frames that need to be reflowed, e.g., elements with a percentage
// based width/height
//
// XXXwaterson are we sure we can skip this if BRS_ISINLINEINCRREFLOW?
if (NS_SUCCEEDED(rv) && mAbsoluteContainer.HasAbsoluteFrames()
&& !state.GetFlag(BRS_ISINLINEINCRREFLOW)) {
if (NS_SUCCEEDED(rv) && mAbsoluteContainer.HasAbsoluteFrames()) {
nscoord containingBlockWidth;
nscoord containingBlockHeight;
nsRect childBounds;
@ -1576,8 +1567,6 @@ nsBlockFrame::PrepareChildIncrementalReflow(nsBlockReflowState& aState)
}
if (line->IsInline()) {
aState.SetFlag(BRS_ISINLINEINCRREFLOW, PR_TRUE);
if (aState.GetFlag(BRS_COMPUTEMAXWIDTH)) {
// We've been asked to compute the maximum width of the block
// frame, which ReflowLine() will handle this by performing an
@ -2131,9 +2120,8 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
aState.mReflowState.reflowCommand->GetType(type);
IndentBy(stdout, gNoiseIndent);
ListTag(stdout);
printf(": incrementally reflowing dirty lines: type=%s(%d) isInline=%s",
kReflowCommandType[type], type,
aState.GetFlag(BRS_ISINLINEINCRREFLOW) ? "true" : "false");
printf(": incrementally reflowing dirty lines: type=%s(%d)",
kReflowCommandType[type], type);
}
else {
IndentBy(stdout, gNoiseIndent);

Просмотреть файл

@ -176,8 +176,6 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
mMinLineHeight = nsHTMLReflowState::CalcLineHeight(mPresContext,
aReflowState.rendContext,
aReflowState.frame);
SetFlag(BRS_DAMAGECONSTRAINED, IsIncrementalDamageConstrained(aFrame));
}
nsBlockReflowState::~nsBlockReflowState()
@ -190,32 +188,6 @@ nsBlockReflowState::~nsBlockReflowState()
}
}
PRBool
nsBlockReflowState::IsIncrementalDamageConstrained(nsIFrame* aBlockFrame) const
{
// see if the reflow will go through a text control. if so, we can optimize
// because we know the text control won't change size.
if ((eReflowReason_Incremental == mReflowState.reason) && (mReflowState.reflowCommand)) {
nsIFrame* target;
mReflowState.reflowCommand->GetTarget(target);
while (target) {
// starting with the target's parent, scan for a text control
nsIFrame* parent;
target->GetParent(&parent);
if ((aBlockFrame == parent) || !parent) // the null check is paranoia, it should never happen
break; // we found the block, so we know there's no text control between the block and target
nsCOMPtr<nsIAtom> frameType;
parent->GetFrameType(getter_AddRefs(frameType));
if (frameType) {
if (nsLayoutAtoms::textInputFrame == frameType.get())
return PR_TRUE; // damage is constrained to the text control innards
}
target = parent; // advance the loop up the frame tree
}
}
return PR_FALSE; // default case, damage is not constrained (or unknown)
}
nsLineBox*
nsBlockReflowState::NewLineBox(nsIFrame* aFrame,
PRInt32 aCount,

Просмотреть файл

@ -112,10 +112,6 @@ public:
protected:
void RecoverFloaters(nsLineList::iterator aLine, nscoord aDeltaY);
// return PR_TRUE if the incremental reflow is 100% contained
// within the bounds of an ancestor frame, relative to aBlockFrame
PRBool IsIncrementalDamageConstrained(nsIFrame* aBlockFrame) const;
public:
void RecoverStateFrom(nsLineList::iterator aLine, nscoord aDeltaY);
@ -248,14 +244,13 @@ public:
#define BRS_UNCONSTRAINEDHEIGHT 0x00000002
#define BRS_SHRINKWRAPWIDTH 0x00000004
#define BRS_NEEDRESIZEREFLOW 0x00000008
#define BRS_ISINLINEINCRREFLOW 0x00000010
#define BRS_NOWRAP 0x00000020
#define BRS_ISTOPMARGINROOT 0x00000040 // Is this frame a root for top/bottom margin collapsing?
#define BRS_ISBOTTOMMARGINROOT 0x00000080
#define BRS_APPLYTOPMARGIN 0x00000100 // See ShouldApplyTopMargin
#define BRS_COMPUTEMAXELEMENTSIZE 0x00000200
#define BRS_COMPUTEMAXWIDTH 0x00000400
#define BRS_DAMAGECONSTRAINED 0x00000800 // is the target of an incremental reflow command inside a text control
#define BRS_NOWRAP 0x00000010
#define BRS_ISTOPMARGINROOT 0x00000020 // Is this frame a root for top/bottom margin collapsing?
#define BRS_ISBOTTOMMARGINROOT 0x00000040
#define BRS_APPLYTOPMARGIN 0x00000080 // See ShouldApplyTopMargin
#define BRS_COMPUTEMAXELEMENTSIZE 0x00000100
#define BRS_COMPUTEMAXWIDTH 0x00000200
#define BRS_DAMAGECONSTRAINED 0x00000400 // is the target of an incremental reflow command inside a text control
#define BRS_LASTFLAG BRS_DAMAGECONSTRAINED
PRInt16 mFlags;

Просмотреть файл

@ -46,7 +46,7 @@
#include "nsHTMLIIDs.h"
#include "nsFrame.h"
#include "nsContainerFrame.h"
#include "nsLayoutAtoms.h"
nsresult
NS_NewHTMLReflowCommand(nsHTMLReflowCommand** aInstancePtrResult,
@ -144,13 +144,6 @@ nsHTMLReflowCommand::~nsHTMLReflowCommand()
NS_IF_RELEASE(mListName);
}
nsIFrame* nsHTMLReflowCommand::GetContainingBlock(nsIFrame* aFloater) const
{
nsIFrame* containingBlock;
aFloater->GetParent(&containingBlock);
return containingBlock;
}
void nsHTMLReflowCommand::BuildPath()
{
#ifdef DEBUG_jesup
@ -164,22 +157,15 @@ void nsHTMLReflowCommand::BuildPath()
mPath.Clear();
// Floating frames are handled differently. The path goes from the target
// frame to the containing block, and then up the hierarchy
const nsStyleDisplay* display;
mTargetFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
if (NS_STYLE_FLOAT_NONE != display->mFloats) {
mPath.AppendElement((void*)mTargetFrame);
for (nsIFrame* f = GetContainingBlock(mTargetFrame); nsnull != f; f->GetParent(&f)) {
mPath.AppendElement((void*)f);
}
} else {
for (nsIFrame* f = mTargetFrame; nsnull != f; f->GetParent(&f)) {
mPath.AppendElement((void*)f);
}
}
// Construct the reflow path by walking up the through the frames'
// parent chain until we reach either a `reflow root' or the root
// frame in the frame hierarchy.
nsIFrame *f = mTargetFrame;
nsFrameState state;
do {
mPath.AppendElement(f);
f->GetFrameState(&state);
} while (!(state & NS_FRAME_REFLOW_ROOT) && (f->GetParent(&f), f != nsnull));
}
nsresult
@ -188,41 +174,61 @@ nsHTMLReflowCommand::Dispatch(nsIPresContext* aPresContext,
const nsSize& aMaxSize,
nsIRenderingContext& aRendContext)
{
// Build the path from the target frame (index 0) to the root frame
// Build the path from the target frame (index 0)
BuildPath();
// Send an incremental reflow notification to the root frame
nsIFrame* root = (nsIFrame*)mPath[mPath.Count() - 1];
// Send an incremental reflow notification to the first frame in the
// path.
nsIFrame* first = (nsIFrame*)mPath[mPath.Count() - 1];
#ifdef NS_DEBUG
nsCOMPtr<nsIPresShell> shell;
aPresContext->GetShell(getter_AddRefs(shell));
if (shell) {
nsIFrame* rootFrame;
shell->GetRootFrame(&rootFrame);
NS_ASSERTION(rootFrame == root, "bad root frame");
}
#endif
if (nsnull != root) {
mPath.RemoveElementAt(mPath.Count() - 1);
nsIFrame* root;
shell->GetRootFrame(&root);
nsHTMLReflowState reflowState(aPresContext, root, *this,
&aRendContext, aMaxSize);
nsReflowStatus status;
// Remove the first frame from the path and reflow it.
mPath.RemoveElementAt(mPath.Count() - 1);
root->WillReflow(aPresContext);
nsContainerFrame::PositionFrameView(aPresContext, root);
root->Reflow(aPresContext, aDesiredSize, reflowState, status);
root->SizeTo(aPresContext, aDesiredSize.width, aDesiredSize.height);
nsIView* view;
root->GetView(aPresContext, &view);
if (view) {
nsContainerFrame::SyncFrameViewAfterReflow(aPresContext, root, view,
nsnull);
}
root->DidReflow(aPresContext, nsnull, NS_FRAME_REFLOW_FINISHED);
}
first->WillReflow(aPresContext);
nsContainerFrame::PositionFrameView(aPresContext, first);
// If the first frame in the path is the root of the frame
// hierarchy, then use all the available space. If it's simply a
// `reflow root', then use the first frame's size as the available
// space.
//
// XXXwaterson Beware that this is not sufficiently general to allow
// arbitrary frames to be reflow roots. For example, and inline
// frame cannot be a reflow root because nsHTMLReflowState::Init()
// will try to walk up through the reflow state chain to find the
// containing block.
nsSize size;
if (first == root)
size = aMaxSize;
else
first->GetSize(size);
nsHTMLReflowState reflowState(aPresContext, first, *this,
&aRendContext, size);
nsReflowStatus status;
first->Reflow(aPresContext, aDesiredSize, reflowState, status);
// If an incremental reflow is initiated at a frame other than the
// root frame, then its desired size had better not change!
NS_ASSERTION(first == root ||
(aDesiredSize.width == size.width && aDesiredSize.height == size.height),
"non-root frame's desired size changed during an incremental reflow");
first->SizeTo(aPresContext, aDesiredSize.width, aDesiredSize.height);
nsIView* view;
first->GetView(aPresContext, &view);
if (view)
nsContainerFrame::SyncFrameViewAfterReflow(aPresContext, first, view, nsnull);
first->DidReflow(aPresContext, nsnull, NS_FRAME_REFLOW_FINISHED);
return NS_OK;
}
@ -344,17 +350,8 @@ nsHTMLReflowCommand::List(FILE* out) const
// Show the path, but without using mPath which is in an undefined
// state at this point.
if (mTargetFrame) {
// Floating frames are handled differently. The path goes from the target
// frame to the containing block, and then up the hierarchy
PRBool didOne = PR_FALSE;
nsIFrame* start = mTargetFrame;
const nsStyleDisplay* display;
mTargetFrame->GetStyleData(eStyleStruct_Display,
(const nsStyleStruct*&) display);
if (NS_STYLE_FLOAT_NONE != display->mFloats) {
start = GetContainingBlock(mTargetFrame);
}
for (nsIFrame* f = start; nsnull != f; f->GetParent(&f)) {
for (nsIFrame* f = mTargetFrame; nsnull != f; f->GetParent(&f)) {
if (f != mTargetFrame) {
fprintf(out, " ");
nsFrame::ListTag(out, f);

Просмотреть файл

@ -175,7 +175,6 @@ public:
protected:
void BuildPath();
nsIFrame* GetContainingBlock(nsIFrame* aFloater) const;
private:
nsReflowType mType;

Просмотреть файл

@ -3342,6 +3342,14 @@ nsGfxTextControlFrame2::SetInitialChildList(nsIPresContext* aPresContext,
nsIFrame *first;
FirstChild(aPresContext,nsnull, &first);
// Mark the scroll frame as being a reflow root. This will allow
// incremental reflows to be initiated at the scroll frame, rather
// than descending from the root frame of the frame hierarchy.
nsFrameState state;
first->GetFrameState(&state);
state |= NS_FRAME_REFLOW_ROOT;
first->SetFrameState(state);
//we must turn off scrollbars for singleline text controls
PRInt32 type;
GetType(&type);