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

git-svn-id: svn://10.0.0.236/trunk@118697 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
waterson%netscape.com
2002-04-11 01:13:41 +00:00
parent 5707942d3f
commit 27b2245dbd
13 changed files with 180 additions and 262 deletions

View File

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