mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-04 11:26:09 +00:00
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:
parent
ba0abcd4c2
commit
ce1acffe03
@ -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(¤tFrame);
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
|
@ -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(¤tFrame);
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user