Rewrote nsContainerFrame::PositionChildViews to use the view tree instead of doing a recursive walk of the frame tree. Should improve page load performance bug 70211 r=attinasi@netscape.com sr=hyatt@netscape.com

This commit is contained in:
kmcclusk%netscape.com 2001-03-12 04:19:10 +00:00
parent ba0abcd4c2
commit ce1acffe03
5 changed files with 158 additions and 55 deletions

View File

@ -731,40 +731,84 @@ nsContainerFrame::ReflowChild(nsIFrame* aKidFrame,
return result;
}
PRBool nsContainerFrame::IsDescendant(nsIFrame* aAncestor,
nsIFrame *aFrame,
nsIFrame *aStopFrame)
{
// Walk up the frame's parent's until either aAncestor or aStopFrame is found
// If aAncestor is found return PR_TRUE, otherwide return PR_FALSE.
nsIFrame* currentFrame = aFrame;
while (currentFrame != nsnull) {
if (currentFrame == aStopFrame) {
return PR_FALSE;
}
if (currentFrame == aAncestor) {
return PR_TRUE;
}
currentFrame->GetParent(&currentFrame);
}
// Neither aAncestor or aStopFrame was found.
return PR_FALSE;
}
void
nsContainerFrame::PositionChildViews(nsIPresContext* aPresContext,
nsIFrame* aFrame)
{
nsIAtom* childListName = nsnull;
PRInt32 childListIndex = 0;
// Look at only the views which are direct descendants of the frame's view.
// If the frame owns a view then all we need to do is reposition the frame's
// associated with the view children. If the frame does not own the view then
// we also need to check to see if the child view's frame is a descendant of this
// frame. In most cases the view will have no children at all and this method returns
// almost immediately.
do {
// Recursively walk aFrame's child frames
nsIFrame* childFrame;
aFrame->FirstChild(aPresContext, childListName, &childFrame);
while (childFrame) {
nsIView* view;
// See if the child frame has a view
childFrame->GetView(aPresContext, &view);
if (view) {
// Position the view. Because any child views are relative to their
// parent, there's no need to recurse
PositionFrameView(aPresContext, childFrame, view);
} else {
// Recursively examine its child frames
PositionChildViews(aPresContext, childFrame);
}
// Get the next sibling child frame
childFrame->GetNextSibling(&childFrame);
// Check to see if this frame owns a view
nsIFrame* frameWithView = aFrame;
nsIView* framesView = nsnull;
aFrame->GetView(aPresContext, &framesView);
if (nsnull == framesView) {
// this frame doesn't own a view so we need to find the ancestor frame that
// has a view.
aFrame->GetParentWithView(aPresContext, &frameWithView);
if (frameWithView) {
frameWithView->GetView(aPresContext, &framesView);
}
}
NS_IF_RELEASE(childListName);
aFrame->GetAdditionalChildListName(childListIndex++, &childListName);
} while (childListName);
if (nsnull == framesView ) {
NS_ASSERTION(PR_FALSE, "Could not find any view");
return;
}
// Cycle through all of the children of the frame's view.
nsIView * childView = nsnull;
for (framesView->GetChild(0, childView); nsnull != childView; childView->GetNextSibling(childView))
{
void *data = nsnull;
nsIFrame *childFrame = nsnull;
childView->GetClientData(data);
NS_ASSERTION(data != nsnull, "The view does not contain a frame pointer");
childFrame = (nsIFrame*) data;
if (childFrame) {
nsFrameState kidState;
childFrame->GetFrameState(&kidState);
// Position the frame only if flag is set to synchronize them.
if (NS_FRAME_SYNC_FRAME_AND_VIEW & kidState) {
if (aFrame == frameWithView) {
PositionFrameView(aPresContext, childFrame, childView);
} else {
// Need to check to see if the view's frame is a
// descendant of this frame.
if (IsDescendant(aFrame, childFrame, frameWithView)) {
PositionFrameView(aPresContext, childFrame, childView);
}
}
}
}
}
}
/**

View File

@ -147,6 +147,11 @@ public:
nscoord aX,
nscoord aY,
PRUint32 aFlags);
static PRBool IsDescendant(nsIFrame* aAncestor,
nsIFrame *aFrame,
nsIFrame *aStopFrame);
static void PositionChildViews(nsIPresContext* aPresContext,
nsIFrame* aFrame);

View File

@ -731,40 +731,84 @@ nsContainerFrame::ReflowChild(nsIFrame* aKidFrame,
return result;
}
PRBool nsContainerFrame::IsDescendant(nsIFrame* aAncestor,
nsIFrame *aFrame,
nsIFrame *aStopFrame)
{
// Walk up the frame's parent's until either aAncestor or aStopFrame is found
// If aAncestor is found return PR_TRUE, otherwide return PR_FALSE.
nsIFrame* currentFrame = aFrame;
while (currentFrame != nsnull) {
if (currentFrame == aStopFrame) {
return PR_FALSE;
}
if (currentFrame == aAncestor) {
return PR_TRUE;
}
currentFrame->GetParent(&currentFrame);
}
// Neither aAncestor or aStopFrame was found.
return PR_FALSE;
}
void
nsContainerFrame::PositionChildViews(nsIPresContext* aPresContext,
nsIFrame* aFrame)
{
nsIAtom* childListName = nsnull;
PRInt32 childListIndex = 0;
// Look at only the views which are direct descendants of the frame's view.
// If the frame owns a view then all we need to do is reposition the frame's
// associated with the view children. If the frame does not own the view then
// we also need to check to see if the child view's frame is a descendant of this
// frame. In most cases the view will have no children at all and this method returns
// almost immediately.
do {
// Recursively walk aFrame's child frames
nsIFrame* childFrame;
aFrame->FirstChild(aPresContext, childListName, &childFrame);
while (childFrame) {
nsIView* view;
// See if the child frame has a view
childFrame->GetView(aPresContext, &view);
if (view) {
// Position the view. Because any child views are relative to their
// parent, there's no need to recurse
PositionFrameView(aPresContext, childFrame, view);
} else {
// Recursively examine its child frames
PositionChildViews(aPresContext, childFrame);
}
// Get the next sibling child frame
childFrame->GetNextSibling(&childFrame);
// Check to see if this frame owns a view
nsIFrame* frameWithView = aFrame;
nsIView* framesView = nsnull;
aFrame->GetView(aPresContext, &framesView);
if (nsnull == framesView) {
// this frame doesn't own a view so we need to find the ancestor frame that
// has a view.
aFrame->GetParentWithView(aPresContext, &frameWithView);
if (frameWithView) {
frameWithView->GetView(aPresContext, &framesView);
}
}
NS_IF_RELEASE(childListName);
aFrame->GetAdditionalChildListName(childListIndex++, &childListName);
} while (childListName);
if (nsnull == framesView ) {
NS_ASSERTION(PR_FALSE, "Could not find any view");
return;
}
// Cycle through all of the children of the frame's view.
nsIView * childView = nsnull;
for (framesView->GetChild(0, childView); nsnull != childView; childView->GetNextSibling(childView))
{
void *data = nsnull;
nsIFrame *childFrame = nsnull;
childView->GetClientData(data);
NS_ASSERTION(data != nsnull, "The view does not contain a frame pointer");
childFrame = (nsIFrame*) data;
if (childFrame) {
nsFrameState kidState;
childFrame->GetFrameState(&kidState);
// Position the frame only if flag is set to synchronize them.
if (NS_FRAME_SYNC_FRAME_AND_VIEW & kidState) {
if (aFrame == frameWithView) {
PositionFrameView(aPresContext, childFrame, childView);
} else {
// Need to check to see if the view's frame is a
// descendant of this frame.
if (IsDescendant(aFrame, childFrame, frameWithView)) {
PositionFrameView(aPresContext, childFrame, childView);
}
}
}
}
}
}
/**

View File

@ -147,6 +147,11 @@ public:
nscoord aX,
nscoord aY,
PRUint32 aFlags);
static PRBool IsDescendant(nsIFrame* aAncestor,
nsIFrame *aFrame,
nsIFrame *aStopFrame);
static void PositionChildViews(nsIPresContext* aPresContext,
nsIFrame* aFrame);

View File

@ -107,7 +107,12 @@ nsMenuPopupFrame::nsMenuPopupFrame(nsIPresShell* aShell)
mMenuCanOverlapOSBar(PR_FALSE)
{
SetIsContextMenu(PR_FALSE); // we're not a context menu by default
// Don't allow container frames to automatically position
// the popup because they will put it in the wrong position.
nsFrameState state;
GetFrameState(&state);
state &= ~NS_FRAME_SYNC_FRAME_AND_VIEW;
SetFrameState(state);
} // ctor