Bug 113083. Concentrate view setup code into a few shared functions in nsContainerFrame. Only change style-dependent view properties after style change, not during reflow, in response to nsChangeHint_SyncFrameView. Change 'clip' to only do SyncFrameView, not reflow. r=dbaron,sr=kin

git-svn-id: svn://10.0.0.236/trunk@130792 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
roc+%cs.cmu.edu
2002-09-30 11:56:37 +00:00
parent f2d14853a0
commit e25496d35f
24 changed files with 1482 additions and 1687 deletions

View File

@@ -427,21 +427,6 @@ nsHTMLContainerFrame::ReparentFrameViewList(nsIPresContext* aPresContext,
return NS_OK;
}
static PRBool
IsContainerContent(nsIFrame* aFrame)
{
nsIContent* content;
PRBool result = PR_FALSE;
aFrame->GetContent(&content);
if (content) {
content->CanContainChildren(result);
NS_RELEASE(content);
}
return result;
}
nsresult
nsHTMLContainerFrame::CreateViewForFrame(nsIPresContext* aPresContext,
nsIFrame* aFrame,
@@ -449,244 +434,92 @@ nsHTMLContainerFrame::CreateViewForFrame(nsIPresContext* aPresContext,
nsIFrame* aContentParentFrame,
PRBool aForce)
{
PRBool isTopMostView = PR_FALSE;
nsIView* view;
aFrame->GetView(aPresContext, &view);
if (nsnull != view) {
return NS_OK;
}
// If we don't yet have a view, see if we need a view
if (nsnull == view) {
PRBool fixedBackgroundAttachment = PR_FALSE;
if (!(aForce || FrameNeedsView(aPresContext, aFrame, aStyleContext))) {
// don't need a view
return NS_OK;
}
// Get nsStyleColor and nsStyleDisplay
const nsStyleDisplay* display = (const nsStyleDisplay*)
aStyleContext->GetStyleData(eStyleStruct_Display);
const nsStylePosition* position = (const nsStylePosition*)
aStyleContext->GetStyleData(eStyleStruct_Position);
const nsStyleVisibility* vis = (const nsStyleVisibility*)
aStyleContext->GetStyleData(eStyleStruct_Visibility);
// Create a view
nsIFrame* parent = nsnull;
aFrame->GetParentWithView(aPresContext, &parent);
NS_ASSERTION(parent, "GetParentWithView failed");
nsIView* parentView = nsnull;
parent->GetView(aPresContext, &parentView);
NS_ASSERTION(parentView, "no parent with view");
// Create a view
static NS_DEFINE_CID(kViewCID, NS_VIEW_CID);
nsresult result = CallCreateInstance(kViewCID, &view);
if (NS_FAILED(result)) {
return result;
}
if (vis->mOpacity != 1.0f) {
NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
("nsHTMLContainerFrame::CreateViewForFrame: frame=%p opacity=%g",
aFrame, vis->mOpacity));
aForce = PR_TRUE;
}
// See if the frame has a fixed background attachment
const nsStyleBackground *color;
PRBool isCanvas;
PRBool hasBackground =
nsCSSRendering::FindBackground(aPresContext, aFrame, &color, &isCanvas);
if (hasBackground &&
NS_STYLE_BG_ATTACHMENT_FIXED == color->mBackgroundAttachment) {
aForce = PR_TRUE;
fixedBackgroundAttachment = PR_TRUE;
}
nsCOMPtr<nsIViewManager> viewManager;
parentView->GetViewManager(*getter_AddRefs(viewManager));
NS_ASSERTION(nsnull != viewManager, "null view manager");
// See if the frame is being relatively positioned or absolutely
// positioned
if (!aForce) {
if (NS_STYLE_POSITION_RELATIVE == display->mPosition) {
NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
("nsHTMLContainerFrame::CreateViewForFrame: frame=%p relatively positioned",
aFrame));
aForce = PR_TRUE;
isTopMostView = PR_TRUE;
} else if (display->IsAbsolutelyPositioned()) {
NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
("nsHTMLContainerFrame::CreateViewForFrame: frame=%p absolutely positioned",
aFrame));
aForce = PR_TRUE;
isTopMostView = PR_TRUE;
}
}
// Initialize the view
nsRect bounds;
aFrame->GetRect(bounds);
view->Init(viewManager, bounds, parentView);
if (NS_STYLE_POSITION_FIXED == display->mPosition) {
isTopMostView = PR_TRUE;
}
SyncFrameViewProperties(aPresContext, aFrame, aStyleContext, view);
// See if the frame is a scrolled frame
if (!aForce) {
nsIAtom* pseudoTag;
aStyleContext->GetPseudoType(pseudoTag);
if (pseudoTag == nsLayoutAtoms::scrolledContentPseudo) {
NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
("nsHTMLContainerFrame::CreateViewForFrame: scrolled frame=%p", aFrame));
aForce = PR_TRUE;
}
NS_IF_RELEASE(pseudoTag);
}
// Insert the view into the view hierarchy. If the parent view is a
// scrolling view we need to do this differently
nsIScrollableView* scrollingView;
if (NS_SUCCEEDED(CallQueryInterface(parentView, &scrollingView))) {
scrollingView->SetScrolledView(view);
} else {
// XXX Drop it at the end of the document order until we can do better
viewManager->InsertChild(parentView, view, nsnull, PR_TRUE);
// See if the frame is block-level and has 'overflow' set to 'hidden'. If
// so and it can have child frames, then we need to give it a view so clipping
// of any child views works correctly. Note that if it's floated it is also
// block-level, but we can't trust that the style context 'display' value is
// set correctly
if (!aForce) {
if ((display->IsBlockLevel() || display->IsFloating()) &&
(display->mOverflow == NS_STYLE_OVERFLOW_HIDDEN)) {
// The reason for the check of whether it can contain children is just
// to avoid giving it a view unnecessarily
if (::IsContainerContent(aFrame)) {
// XXX Check for the frame being a block frame and only force a view
// in that case, because adding a view for box frames seems to cause
// problems for XUL...
nsIAtom* frameType;
aFrame->GetFrameType(&frameType);
if ((frameType == nsLayoutAtoms::blockFrame) ||
(frameType == nsLayoutAtoms::areaFrame)) {
aForce = PR_TRUE;
}
NS_IF_RELEASE(frameType);
}
}
}
if (aForce) {
// Create a view
nsIFrame* parent = nsnull;
nsIView* parentView = nsnull;
aFrame->GetParentWithView(aPresContext, &parent);
NS_ASSERTION(parent, "GetParentWithView failed");
parent->GetView(aPresContext, &parentView);
NS_ASSERTION(parentView, "no parent with view");
// Create a view
static NS_DEFINE_CID(kViewCID, NS_VIEW_CID);
nsresult result = nsComponentManager::CreateInstance(kViewCID,
nsnull,
NS_GET_IID(nsIView),
(void **)&view);
if (NS_OK == result) {
nsIViewManager* viewManager;
parentView->GetViewManager(viewManager);
NS_ASSERTION(nsnull != viewManager, "null view manager");
// Initialize the view
nsRect bounds;
aFrame->GetRect(bounds);
view->Init(viewManager, bounds, parentView);
// If the frame has a fixed background attachment, then indicate that the
// view's contents should be repainted and not bitblt'd
if (fixedBackgroundAttachment) {
viewManager->SetViewBitBltEnabled(view, PR_FALSE);
}
if (nsnull != aContentParentFrame) {
// If, for some reason, GetView below fails to initialize zParentView,
// then ensure that we completely bypass InsertZPlaceholder below.
// The effect will be as if we never knew about aContentParentFrame
// in the first place, so at least this code won't be doing any damage.
nsIView* zParentView = parentView;
aContentParentFrame->GetView(aPresContext, &zParentView);
if (nsnull == zParentView) {
nsIFrame* zParentFrame = nsnull;
// Insert the view into the view hierarchy. If the parent view is a
// scrolling view we need to do this differently
nsIScrollableView* scrollingView;
if (NS_SUCCEEDED(parentView->QueryInterface(NS_GET_IID(nsIScrollableView), (void**)&scrollingView))) {
scrollingView->SetScrolledView(view);
} else {
PRInt32 zIndex = 0;
PRBool autoZIndex = PR_FALSE;
// Get the z-index to use
if (position->mZIndex.GetUnit() == eStyleUnit_Integer) {
zIndex = position->mZIndex.GetIntValue();
} else if (position->mZIndex.GetUnit() == eStyleUnit_Auto) {
autoZIndex = PR_TRUE;
}
viewManager->SetViewZIndex(view, autoZIndex, zIndex, isTopMostView);
// XXX Drop it at the end of the document order until we can do better
viewManager->InsertChild(parentView, view, nsnull, PR_TRUE);
if (nsnull != aContentParentFrame) {
// If, for some reason, GetView below fails to initialize zParentView,
// then ensure that we completely bypass InsertZPlaceholder below.
// The effect will be as if we never knew about aContentParentFrame
// in the first place, so at least this code won't be doing any damage.
nsIView* zParentView = parentView;
aContentParentFrame->GetView(aPresContext, &zParentView);
if (nsnull == zParentView) {
nsIFrame* zParentFrame = nsnull;
aContentParentFrame->GetParentWithView(aPresContext, &zParentFrame);
NS_ASSERTION(zParentFrame, "GetParentWithView failed");
zParentFrame->GetView(aPresContext, &zParentView);
NS_ASSERTION(zParentView, "no parent with view");
}
if (zParentView != parentView) {
viewManager->InsertZPlaceholder(zParentView, view, nsnull, PR_TRUE);
}
}
}
// See if the view should be hidden
PRBool viewIsVisible = PR_TRUE;
PRBool viewHasTransparentContent =
!isCanvas &&
(!hasBackground ||
(color->mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT));
if (NS_STYLE_VISIBILITY_COLLAPSE == vis->mVisible) {
viewIsVisible = PR_FALSE;
}
else if (NS_STYLE_VISIBILITY_HIDDEN == vis->mVisible) {
// If it has a widget, hide the view because the widget can't deal with it
nsIWidget* widget = nsnull;
view->GetWidget(widget);
if (widget) {
viewIsVisible = PR_FALSE;
NS_RELEASE(widget);
}
else {
// If it's a container element, then leave the view visible, but
// mark it as having transparent content. The reason we need to
// do this is that child elements can override their parent's
// hidden visibility and be visible anyway.
//
// Because this function is called before processing the content
// object's child elements, we can't tell if it's a leaf by looking
// at whether the frame has any child frames
if (::IsContainerContent(aFrame)) {
// The view needs to be visible, but marked as having transparent
// content
viewHasTransparentContent = PR_TRUE;
} else {
// Go ahead and hide the view
viewIsVisible = PR_FALSE;
}
}
}
if (viewIsVisible) {
if (viewHasTransparentContent) {
viewManager->SetViewContentTransparency(view, PR_TRUE);
}
} else {
viewManager->SetViewVisibility(view, nsViewVisibility_kHide);
}
// XXX If it's fixed positioned, then create a widget so it floats
// above the scrolling area
if (NS_STYLE_POSITION_FIXED == display->mPosition) {
view->CreateWidget(kCChildCID);
}
viewManager->SetViewOpacity(view, vis->mOpacity);
NS_RELEASE(viewManager);
aContentParentFrame->GetParentWithView(aPresContext, &zParentFrame);
NS_ASSERTION(zParentFrame, "GetParentWithView failed");
zParentFrame->GetView(aPresContext, &zParentView);
NS_ASSERTION(zParentView, "no parent with view");
}
if (zParentView != parentView) {
viewManager->InsertZPlaceholder(zParentView, view, nsnull, PR_TRUE);
}
// Remember our view
aFrame->SetView(aPresContext, view);
NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
("nsHTMLContainerFrame::CreateViewForFrame: frame=%p view=%p",
aFrame));
return result;
}
}
// XXX If it's fixed positioned, then create a widget so it floats
// above the scrolling area
const nsStyleDisplay* display;
::GetStyleData(aStyleContext, &display);
if (NS_STYLE_POSITION_FIXED == display->mPosition) {
view->CreateWidget(kCChildCID);
}
// Remember our view
aFrame->SetView(aPresContext, view);
NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
("nsHTMLContainerFrame::CreateViewForFrame: frame=%p view=%p",
aFrame));
return NS_OK;
}