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:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user