author | Ehsan Akhgari <ehsan@mozilla.com> |
Fri, 29 Apr 2011 19:02:33 -0400 | |
changeset 69051 | 14fe8a6cfd45575ab1ccde56ad33abd562eaf61a |
parent 69050 | b5c0b85194d651f43176c644d2b34d5eb2f52596 |
child 69052 | cfd13e3ed2cf8068d0e242d3f730bb14cfed2452 |
push id | 19841 |
push user | eakhgari@mozilla.com |
push date | Fri, 06 May 2011 18:18:50 +0000 |
treeherder | mozilla-central@14fe8a6cfd45 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | roc |
bugs | 10209 |
milestone | 6.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/content/base/src/nsGkAtomList.h +++ b/content/base/src/nsGkAtomList.h @@ -1743,17 +1743,16 @@ GK_ATOM(menuBarFrame,"MenuBarFrame") GK_ATOM(menuFrame,"MenuFrame") GK_ATOM(menuPopupFrame,"MenuPopupFrame") GK_ATOM(objectFrame, "ObjectFrame") GK_ATOM(pageFrame, "PageFrame") GK_ATOM(pageBreakFrame, "PageBreakFrame") GK_ATOM(pageContentFrame, "PageContentFrame") GK_ATOM(placeholderFrame, "PlaceholderFrame") GK_ATOM(popupSetFrame, "PopupSetFrame") -GK_ATOM(positionedInlineFrame, "PositionedInlineFrame") GK_ATOM(canvasFrame, "CanvasFrame") GK_ATOM(rootFrame, "RootFrame") GK_ATOM(scrollFrame, "ScrollFrame") GK_ATOM(scrollbarFrame, "ScrollbarFrame") GK_ATOM(sequenceFrame, "SequenceFrame") GK_ATOM(sliderFrame, "sliderFrame") GK_ATOM(tableCaptionFrame, "TableCaptionFrame") GK_ATOM(tableCellFrame, "TableCellFrame")
--- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -1018,17 +1018,19 @@ nsFrameConstructorState::PushAbsoluteCon nsAbsoluteItems(AdjustAbsoluteContainingBlock(aNewAbsoluteContainingBlock)); /* See if we're wiring the fixed-pos and abs-pos lists together. This happens iff * we're a transformed element. */ mFixedPosIsAbsPos = (aNewAbsoluteContainingBlock && aNewAbsoluteContainingBlock->GetStyleDisplay()->HasTransform()); - aNewAbsoluteContainingBlock->MarkAsAbsoluteContainingBlock(); + if (aNewAbsoluteContainingBlock) { + aNewAbsoluteContainingBlock->MarkAsAbsoluteContainingBlock(); + } } void nsFrameConstructorState::PushFloatContainingBlock(nsIFrame* aNewFloatContainingBlock, nsFrameConstructorSaveState& aSaveState) { NS_PRECONDITION(!aNewFloatContainingBlock || aNewFloatContainingBlock->IsFloatContainingBlock(), @@ -1214,17 +1216,24 @@ nsFrameConstructorState::ProcessFrameIns // Insert the frames hanging out in aItems. We can use SetInitialChildList() // if the containing block hasn't been reflowed yet (so NS_FRAME_FIRST_REFLOW // is set) and doesn't have any frames in the aChildListName child list yet. const nsFrameList& childList = containingBlock->GetChildList(aChildListName); nsresult rv = NS_OK; if (childList.IsEmpty() && (containingBlock->GetStateBits() & NS_FRAME_FIRST_REFLOW)) { - rv = containingBlock->SetInitialChildList(aChildListName, aFrameItems); + // If we're injecting absolutely positioned frames, inject them on the + // absolute containing block + if (aChildListName == containingBlock->GetAbsoluteListName()) { + rv = containingBlock->GetAbsoluteContainingBlock()-> + SetInitialChildList(containingBlock, aChildListName, aFrameItems); + } else { + rv = containingBlock->SetInitialChildList(aChildListName, aFrameItems); + } } else { // Note that whether the frame construction context is doing an append or // not is not helpful here, since it could be appending to some frame in // the middle of the document, which means we're not necessarily // appending to the children of the containing block. // // We need to make sure the 'append to the end of document' case is fast. // So first test the last child of the containing block @@ -1232,33 +1241,33 @@ nsFrameConstructorState::ProcessFrameIns // CompareTreePosition uses placeholder hierarchy for out of flow frames, // so this will make out-of-flows respect the ordering of placeholders, // which is great because it takes care of anonymous content. nsIFrame* firstNewFrame = aFrameItems.FirstChild(); if (!lastChild || nsLayoutUtils::CompareTreePosition(lastChild, firstNewFrame, containingBlock) < 0) { // no lastChild, or lastChild comes before the new children, so just append - rv = containingBlock->AppendFrames(aChildListName, aFrameItems); + rv = mFrameManager->AppendFrames(containingBlock, aChildListName, aFrameItems); } else { // try the other children nsIFrame* insertionPoint = nsnull; for (nsIFrame* f = childList.FirstChild(); f != lastChild; f = f->GetNextSibling()) { PRInt32 compare = nsLayoutUtils::CompareTreePosition(f, firstNewFrame, containingBlock); if (compare > 0) { // f comes after the new children, so stop here and insert after // the previous frame break; } insertionPoint = f; } - rv = containingBlock->InsertFrames(aChildListName, insertionPoint, - aFrameItems); + rv = mFrameManager->InsertFrames(containingBlock, aChildListName, + insertionPoint, aFrameItems); } } NS_POSTCONDITION(aFrameItems.IsEmpty(), "How did that happen?"); // XXXbz And if NS_FAILED(rv), what? I guess we need to clean up the list // and deal with all the placeholders... but what if the placeholders aren't // in the document yet? Could that happen? @@ -2555,16 +2564,18 @@ nsCSSFrameConstructor::ConstructRootFram nsContainerFrame::SyncFrameViewProperties(mPresShell->GetPresContext(), viewportFrame, viewportPseudoStyle, rootView); nsContainerFrame::SyncWindowProperties(mPresShell->GetPresContext(), viewportFrame, rootView); // The viewport is the containing block for 'fixed' elements mFixedContainingBlock = viewportFrame; + // Make it an absolute container for fixed-pos elements + mFixedContainingBlock->MarkAsAbsoluteContainingBlock(); *aNewFrame = viewportFrame; return NS_OK; } nsresult nsCSSFrameConstructor::SetUpDocElementContainingBlock(nsIContent* aDocElement) { @@ -2839,16 +2850,18 @@ nsCSSFrameConstructor::ConstructPageFram nsIFrame* prevPageContentFrame = nsnull; if (aPrevPageFrame) { prevPageContentFrame = aPrevPageFrame->GetFirstChild(nsnull); NS_ASSERTION(prevPageContentFrame, "missing page content frame"); } pageContentFrame->Init(nsnull, aPageFrame, prevPageContentFrame); SetInitialSingleChild(aPageFrame, pageContentFrame); mFixedContainingBlock = pageContentFrame; + // Make it an absolute container for fixed-pos elements + mFixedContainingBlock->MarkAsAbsoluteContainingBlock(); nsRefPtr<nsStyleContext> canvasPseudoStyle; canvasPseudoStyle = styleSet->ResolveAnonymousBoxStyle(nsCSSAnonBoxes::canvas, pageContentPseudoStyle); aCanvasFrame = NS_NewCanvasFrame(aPresShell, canvasPseudoStyle); if (NS_UNLIKELY(!aCanvasFrame)) return NS_ERROR_OUT_OF_MEMORY; @@ -5534,17 +5547,17 @@ nsCSSFrameConstructor::GetAbsoluteContai // Find the outermost wrapped block under this frame for (nsIFrame* wrappedFrame = aFrame; wrappedFrame != frame->GetParent(); wrappedFrame = wrappedFrame->GetParent()) { nsIAtom* frameType = wrappedFrame->GetType(); if (nsGkAtoms::blockFrame == frameType || #ifdef MOZ_XUL nsGkAtoms::XULLabelFrame == frameType || #endif - nsGkAtoms::positionedInlineFrame == frameType) { + (nsGkAtoms::inlineFrame == frameType && wrappedFrame->IsAbsoluteContainer())) { containingBlock = wrappedFrame; } else if (nsGkAtoms::fieldSetFrame == frameType) { // If the positioned frame is a fieldset, use the area frame inside it. // We don't use GetContentInsertionFrame for fieldsets yet. containingBlock = GetFieldSetBlockFrame(wrappedFrame); } } @@ -8498,23 +8511,16 @@ nsCSSFrameConstructor::CreateContinuingF } #endif } else if (nsGkAtoms::columnSetFrame == frameType) { newFrame = NS_NewColumnSetFrame(shell, styleContext, 0); if (newFrame) { newFrame->Init(content, aParentFrame, aFrame); } - - } else if (nsGkAtoms::positionedInlineFrame == frameType) { - newFrame = NS_NewPositionedInlineFrame(shell, styleContext); - - if (newFrame) { - newFrame->Init(content, aParentFrame, aFrame); - } } else if (nsGkAtoms::pageFrame == frameType) { nsIFrame* canvasFrame; rv = ConstructPageFrame(shell, aPresContext, aParentFrame, aFrame, newFrame, canvasFrame); } else if (nsGkAtoms::tableOuterFrame == frameType) { rv = CreateContinuingOuterTableFrame(shell, aPresContext, aFrame, aParentFrame, content, styleContext, &newFrame); @@ -10715,30 +10721,26 @@ nsCSSFrameConstructor::ConstructInline(n nsStyleContext* const styleContext = aItem.mStyleContext; nsIFrame *newFrame; PRBool positioned = NS_STYLE_DISPLAY_INLINE == aDisplay->mDisplay && (NS_STYLE_POSITION_RELATIVE == aDisplay->mPosition || aDisplay->HasTransform()); - if (positioned) { - newFrame = NS_NewPositionedInlineFrame(mPresShell, styleContext); - } else { - newFrame = NS_NewInlineFrame(mPresShell, styleContext); - } + newFrame = NS_NewInlineFrame(mPresShell, styleContext); // Initialize the frame InitAndRestoreFrame(aState, content, aParentFrame, nsnull, newFrame); nsFrameConstructorSaveState absoluteSaveState; // definition cannot be inside next block // because the object's destructor is significant // this is part of the fix for bug 42372 - if (positioned) { + if (positioned) { // Relatively positioned frames becomes a container for child // frames that are positioned aState.PushAbsoluteContainingBlock(newFrame, absoluteSaveState); } // Process the child content nsFrameItems childItems; nsresult rv = ConstructFramesFromItemList(aState, aItem.mChildItems, newFrame, @@ -10827,27 +10829,25 @@ nsCSSFrameConstructor::CreateIBSiblings( MoveChildrenTo(aState.mPresContext, aInitialInline, blockFrame, blockKids); SetFrameIsSpecial(lastNewInline, blockFrame); aSiblings.AddChild(blockFrame); // Now grab the initial inlines in aChildItems and put them into an inline // frame - nsIFrame* inlineFrame; - if (aIsPositioned) { - inlineFrame = NS_NewPositionedInlineFrame(mPresShell, styleContext); - } - else { - inlineFrame = NS_NewInlineFrame(mPresShell, styleContext); - } + nsIFrame* inlineFrame = NS_NewInlineFrame(mPresShell, styleContext); InitAndRestoreFrame(aState, content, parentFrame, nsnull, inlineFrame, PR_FALSE); + if (aIsPositioned) { + inlineFrame->MarkAsAbsoluteContainingBlock(); + } + if (aChildItems.NotEmpty()) { nsFrameList::FrameLinkEnumerator firstBlock(aChildItems); FindFirstBlock(firstBlock); nsFrameList inlineKids = aChildItems.ExtractHead(firstBlock); MoveChildrenTo(aState.mPresContext, aInitialInline, inlineFrame, inlineKids); }
--- a/layout/base/nsCSSRendering.cpp +++ b/layout/base/nsCSSRendering.cpp @@ -2538,18 +2538,17 @@ PrepareBackgroundLayer(nsPresContext* aP } // Compute background origin area relative to aBorderArea now as we may need // it to compute the effective image size for a CSS gradient. nsRect bgPositioningArea(0, 0, 0, 0); nsIAtom* frameType = aForFrame->GetType(); nsIFrame* geometryFrame = aForFrame; - if (frameType == nsGkAtoms::inlineFrame || - frameType == nsGkAtoms::positionedInlineFrame) { + if (frameType == nsGkAtoms::inlineFrame) { // XXXjwalden Strictly speaking this is not quite faithful to how // background-break is supposed to interact with background-origin values, // but it's a non-trivial amount of work to make it fully conformant, and // until the specification is more finalized (and assuming background-break // even makes the cut) it doesn't make sense to hammer out exact behavior. switch (aBackground.mBackgroundInlinePolicy) { case NS_STYLE_BG_INLINE_POLICY_EACH_BOX: bgPositioningArea = nsRect(nsPoint(0,0), aBorderArea.Size());
--- a/layout/base/nsFrameManager.cpp +++ b/layout/base/nsFrameManager.cpp @@ -88,16 +88,17 @@ #include "nsUnicharUtils.h" #include "nsPrintfCString.h" #include "nsLayoutErrors.h" #include "nsLayoutUtils.h" #include "nsAutoPtr.h" #include "imgIRequest.h" #include "nsTransitionManager.h" #include "RestyleTracker.h" +#include "nsAbsoluteContainingBlock.h" #include "nsFrameManager.h" #ifdef ACCESSIBILITY #include "nsAccessibilityService.h" #endif #ifdef DEBUG @@ -467,29 +468,48 @@ nsFrameManager::ClearAllUndisplayedConte if (child->GetParent() != aParentContent) { ClearUndisplayedContentIn(child, child->GetParent()); } } } } //---------------------------------------------------------------------- +nsresult +nsFrameManager::AppendFrames(nsIFrame* aParentFrame, + nsIAtom* aListName, + nsFrameList& aFrameList) +{ + if (aParentFrame->IsAbsoluteContainer() && + aListName == aParentFrame->GetAbsoluteListName()) { + return aParentFrame->GetAbsoluteContainingBlock()-> + AppendFrames(aParentFrame, aListName, aFrameList); + } else { + return aParentFrame->AppendFrames(aListName, aFrameList); + } +} nsresult nsFrameManager::InsertFrames(nsIFrame* aParentFrame, nsIAtom* aListName, nsIFrame* aPrevFrame, nsFrameList& aFrameList) { NS_PRECONDITION(!aPrevFrame || (!aPrevFrame->GetNextContinuation() || IS_TRUE_OVERFLOW_CONTAINER(aPrevFrame->GetNextContinuation())) && !IS_TRUE_OVERFLOW_CONTAINER(aPrevFrame), "aPrevFrame must be the last continuation in its chain!"); - return aParentFrame->InsertFrames(aListName, aPrevFrame, aFrameList); + if (aParentFrame->IsAbsoluteContainer() && + aListName == aParentFrame->GetAbsoluteListName()) { + return aParentFrame->GetAbsoluteContainingBlock()-> + InsertFrames(aParentFrame, aListName, aPrevFrame, aFrameList); + } else { + return aParentFrame->InsertFrames(aListName, aPrevFrame, aFrameList); + } } nsresult nsFrameManager::RemoveFrame(nsIAtom* aListName, nsIFrame* aOldFrame) { PRBool wasDestroyingFrames = mIsDestroyingFrames; mIsDestroyingFrames = PR_TRUE; @@ -504,17 +524,25 @@ nsFrameManager::RemoveFrame(nsIAtom* NS_ASSERTION(!aOldFrame->GetPrevContinuation() || // exception for nsCSSFrameConstructor::RemoveFloatingFirstLetterFrames aOldFrame->GetType() == nsGkAtoms::textFrame, "Must remove first continuation."); NS_ASSERTION(!(aOldFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW && GetPlaceholderFrameFor(aOldFrame)), "Must call RemoveFrame on placeholder for out-of-flows."); - nsresult rv = aOldFrame->GetParent()->RemoveFrame(aListName, aOldFrame); + nsresult rv = NS_OK; + nsIFrame* parentFrame = aOldFrame->GetParent(); + if (parentFrame->IsAbsoluteContainer() && + aListName == parentFrame->GetAbsoluteListName()) { + parentFrame->GetAbsoluteContainingBlock()-> + RemoveFrame(parentFrame, aListName, aOldFrame); + } else { + rv = parentFrame->RemoveFrame(aListName, aOldFrame); + } mIsDestroyingFrames = wasDestroyingFrames; return rv; } //----------------------------------------------------------------------
--- a/layout/base/nsFrameManager.h +++ b/layout/base/nsFrameManager.h @@ -117,20 +117,17 @@ public: nsStyleContext* aStyleContext); NS_HIDDEN_(void) ClearUndisplayedContentIn(nsIContent* aContent, nsIContent* aParentContent); NS_HIDDEN_(void) ClearAllUndisplayedContentIn(nsIContent* aParentContent); // Functions for manipulating the frame model NS_HIDDEN_(nsresult) AppendFrames(nsIFrame* aParentFrame, nsIAtom* aListName, - nsFrameList& aFrameList) - { - return aParentFrame->AppendFrames(aListName, aFrameList); - } + nsFrameList& aFrameList); NS_HIDDEN_(nsresult) InsertFrames(nsIFrame* aParentFrame, nsIAtom* aListName, nsIFrame* aPrevFrame, nsFrameList& aFrameList); NS_HIDDEN_(nsresult) RemoveFrame(nsIAtom* aListName, nsIFrame* aOldFrame);
--- a/layout/doc/frame_reflow_debug.html +++ b/layout/doc/frame_reflow_debug.html @@ -168,17 +168,16 @@ The entries in the reflow log can be con <tr><td>img</td><td>image</td></tr> <tr><td>inline</td><td>inline</td></tr> <tr><td>letter</td><td>letter</td></tr> <tr><td>line</td><td>line</td></tr> <tr><td>select</td><td>select</td></tr> <tr><td>obj</td><td>object</td></tr> <tr><td>page</td><td>page</td></tr> <tr><td>place</td><td>placeholder</td></tr> - <tr><td>posInline</td><td>positionedInline</td></tr> <tr><td>canvas</td><td>canvas</td></tr> <tr><td>root</td><td>root</td></tr> <tr><td>scroll</td><td>scroll</td></tr> <tr><td>caption</td><td>tableCaption</td></tr> <tr><td>cell</td><td>tableCell</td></tr> <tr><td>bcCell</td><td>bcTableCell</td></tr> <tr><td>col</td><td>tableCol</td></tr> <tr><td>colG</td><td>tableColGroup</td></tr>
--- a/layout/generic/nsAbsoluteContainingBlock.cpp +++ b/layout/generic/nsAbsoluteContainingBlock.cpp @@ -422,17 +422,17 @@ nsAbsoluteContainingBlock::ReflowAbsolut aContainingBlockHeight); // Send the WillReflow() notification and position the frame aKidFrame->WillReflow(aPresContext); PRBool constrainHeight = (aReflowState.availableHeight != NS_UNCONSTRAINEDSIZE) && aConstrainHeight // Don't split if told not to (e.g. for fixed frames) - && (aDelegatingFrame->GetType() != nsGkAtoms::positionedInlineFrame) + && (aDelegatingFrame->GetType() != nsGkAtoms::inlineFrame) //XXX we don't handle splitting frames for inline absolute containing blocks yet && (aKidFrame->GetRect().y <= aReflowState.availableHeight); // Don't split things below the fold. (Ideally we shouldn't *have* // anything totally below the fold, but we can't position frames // across next-in-flow breaks yet. if (constrainHeight) { kidReflowState.availableHeight = aReflowState.availableHeight - border.top - kidReflowState.mComputedMargin.top;
--- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -300,17 +300,17 @@ NS_IMPL_FRAMEARENA_HELPERS(nsBlockFrame) nsBlockFrame::~nsBlockFrame() { } void nsBlockFrame::DestroyFrom(nsIFrame* aDestructRoot) { - mAbsoluteContainer.DestroyFrames(this, aDestructRoot); + DestroyAbsoluteFrames(aDestructRoot); // Outside bullets are not in our child-list so check for them here // and delete them when present. if (mBullet && HaveOutsideBullet()) { mBullet->DestroyFrom(aDestructRoot); mBullet = nsnull; } mFloats.DestroyFramesFrom(aDestructRoot); @@ -577,20 +577,17 @@ nsBlockFrame::GetCaretBaseline() const } ///////////////////////////////////////////////////////////////////////////// // Child frame enumeration nsFrameList nsBlockFrame::GetChildList(nsIAtom* aListName) const { - if (nsGkAtoms::absoluteList == aListName) { - return mAbsoluteContainer.GetChildList(); - } - else if (nsnull == aListName) { + if (nsnull == aListName) { return mFrames; } else if (aListName == nsGkAtoms::overflowList) { // XXXbz once we start using nsFrameList for our overflow list, we // could switch GetChildList to returning a |const nsFrameList&|. nsLineList* overflowLines = GetOverflowLines(); return overflowLines ? nsFrameList(overflowLines->front()->mFirstChild, overflowLines->back()->LastChild()) @@ -612,35 +609,32 @@ nsBlockFrame::GetChildList(nsIAtom* aLis : nsFrameList::EmptyList(); } return nsContainerFrame::GetChildList(aListName); } #define NS_BLOCK_FRAME_OVERFLOW_OOF_LIST_INDEX (NS_CONTAINER_LIST_COUNT_INCL_OC + 0) #define NS_BLOCK_FRAME_FLOAT_LIST_INDEX (NS_CONTAINER_LIST_COUNT_INCL_OC + 1) #define NS_BLOCK_FRAME_BULLET_LIST_INDEX (NS_CONTAINER_LIST_COUNT_INCL_OC + 2) -#define NS_BLOCK_FRAME_ABSOLUTE_LIST_INDEX (NS_CONTAINER_LIST_COUNT_INCL_OC + 3) -#define NS_BLOCK_FRAME_PUSHED_FLOATS_LIST_INDEX (NS_CONTAINER_LIST_COUNT_INCL_OC + 4) +#define NS_BLOCK_FRAME_PUSHED_FLOATS_LIST_INDEX (NS_CONTAINER_LIST_COUNT_INCL_OC + 3) // If adding/removing lists, don't forget to update the count in nsBlockFrame.h nsIAtom* nsBlockFrame::GetAdditionalChildListName(PRInt32 aIndex) const { if (aIndex < NS_CONTAINER_LIST_COUNT_INCL_OC) return nsContainerFrame::GetAdditionalChildListName(aIndex); switch (aIndex) { case NS_BLOCK_FRAME_FLOAT_LIST_INDEX: return nsGkAtoms::floatList; case NS_BLOCK_FRAME_BULLET_LIST_INDEX: return nsGkAtoms::bulletList; case NS_BLOCK_FRAME_OVERFLOW_OOF_LIST_INDEX: return nsGkAtoms::overflowOutOfFlowList; - case NS_BLOCK_FRAME_ABSOLUTE_LIST_INDEX: - return nsGkAtoms::absoluteList; case NS_BLOCK_FRAME_PUSHED_FLOATS_LIST_INDEX: return nsGkAtoms::pushedFloatsList; default: return nsnull; } } /* virtual */ PRBool @@ -1168,30 +1162,31 @@ nsBlockFrame::Reflow(nsPresContext* // condition 1. // XXX checking oldSize is bogus, there are various reasons we might have // reflowed but our size might not have been changed to what we // asked for (e.g., we ended up being pushed to a new page) // When WillReflowAgainForClearance is true, we will reflow again without // resetting the size. Because of this, we must not reflow our abs-pos children // in that situation --- what we think is our "new size" // will not be our real new size. This also happens to be more efficient. - if (mAbsoluteContainer.HasAbsoluteFrames()) { + if (HasAbsolutelyPositionedChildren()) { + nsAbsoluteContainingBlock* absoluteContainer = GetAbsoluteContainingBlock(); PRBool haveInterrupt = aPresContext->HasPendingInterrupt(); if (reflowState->WillReflowAgainForClearance() || haveInterrupt) { // Make sure that when we reflow again we'll actually reflow all the abs // pos frames that might conceivably depend on our size (or all of them, // if we're dirty right now and interrupted; in that case we also need // to mark them all with NS_FRAME_IS_DIRTY). Sadly, we can't do much // better than that, because we don't really know what our size will be, // and it might in fact not change on the followup reflow! if (haveInterrupt && (GetStateBits() & NS_FRAME_IS_DIRTY)) { - mAbsoluteContainer.MarkAllFramesDirty(); + absoluteContainer->MarkAllFramesDirty(); } else { - mAbsoluteContainer.MarkSizeDependentFramesDirty(); + absoluteContainer->MarkSizeDependentFramesDirty(); } } else { nsSize containingBlockSize = CalculateContainingBlockSizeForAbsolutes(*reflowState, nsSize(aMetrics.width, aMetrics.height)); // Mark frames that depend on changes we just made to this frame as dirty: @@ -1205,22 +1200,22 @@ nsBlockFrame::Reflow(nsPresContext* // If isRoot and we have auto height, then we are the initial // containing block and the containing block height is the // viewport height, which can't change during incremental // reflow. PRBool cbHeightChanged = !(isRoot && NS_UNCONSTRAINEDSIZE == reflowState->ComputedHeight()) && aMetrics.height != oldSize.height; - rv = mAbsoluteContainer.Reflow(this, aPresContext, *reflowState, - state.mReflowStatus, - containingBlockSize.width, - containingBlockSize.height, PR_TRUE, - cbWidthChanged, cbHeightChanged, - &aMetrics.mOverflowAreas); + absoluteContainer->Reflow(this, aPresContext, *reflowState, + state.mReflowStatus, + containingBlockSize.width, + containingBlockSize.height, PR_TRUE, + cbWidthChanged, cbHeightChanged, + &aMetrics.mOverflowAreas); //XXXfr Why isn't this rv (and others in this file) checked/returned? } } // Determine if we need to repaint our border, background or outline CheckInvalidateSizeChange(aMetrics); @@ -4705,20 +4700,17 @@ nsBlockFrame::RemovePushedFloats() NS_IMETHODIMP nsBlockFrame::AppendFrames(nsIAtom* aListName, nsFrameList& aFrameList) { if (aFrameList.IsEmpty()) { return NS_OK; } if (aListName) { - if (nsGkAtoms::absoluteList == aListName) { - return mAbsoluteContainer.AppendFrames(this, aListName, aFrameList); - } - else if (nsGkAtoms::floatList == aListName) { + if (nsGkAtoms::floatList == aListName) { mFloats.AppendFrames(nsnull, aFrameList); return NS_OK; } else { NS_ERROR("unexpected child list"); return NS_ERROR_INVALID_ARG; } } @@ -4753,21 +4745,17 @@ NS_IMETHODIMP nsBlockFrame::InsertFrames(nsIAtom* aListName, nsIFrame* aPrevFrame, nsFrameList& aFrameList) { NS_ASSERTION(!aPrevFrame || aPrevFrame->GetParent() == this, "inserting after sibling frame with different parent"); if (aListName) { - if (nsGkAtoms::absoluteList == aListName) { - return mAbsoluteContainer.InsertFrames(this, aListName, aPrevFrame, - aFrameList); - } - else if (nsGkAtoms::floatList == aListName) { + if (nsGkAtoms::floatList == aListName) { mFloats.InsertFrames(this, aPrevFrame, aFrameList); return NS_OK; } #ifdef IBMBIDI else if (nsGkAtoms::nextBidi == aListName) {} #endif // IBMBIDI else { NS_ERROR("unexpected child list"); @@ -5018,20 +5006,16 @@ nsBlockFrame::RemoveFrame(nsIAtom* aLis if (nsnull == aListName) { PRBool hasFloats = BlockHasAnyFloats(aOldFrame); rv = DoRemoveFrame(aOldFrame, REMOVE_FIXED_CONTINUATIONS); if (hasFloats) { MarkSameFloatManagerLinesDirty(this); } } - else if (nsGkAtoms::absoluteList == aListName) { - mAbsoluteContainer.RemoveFrame(this, aListName, aOldFrame); - return NS_OK; - } else if (nsGkAtoms::floatList == aListName) { // Make sure to mark affected lines dirty for the float frame // we are removing; this way is a bit messy, but so is the rest of the code. // See bug 390762. NS_ASSERTION(!aOldFrame->GetPrevContinuation(), "RemoveFrame should not be called on pushed floats."); for (nsIFrame* f = aOldFrame; f && !(f->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER); @@ -5064,19 +5048,19 @@ nsBlockFrame::DoRemoveOutOfFlowFrame(nsI { // The containing block is always the parent of aFrame. nsBlockFrame* block = (nsBlockFrame*)aFrame->GetParent(); // Remove aFrame from the appropriate list. const nsStyleDisplay* display = aFrame->GetStyleDisplay(); if (display->IsAbsolutelyPositioned()) { // This also deletes the next-in-flows - block->mAbsoluteContainer.RemoveFrame(block, - nsGkAtoms::absoluteList, - aFrame); + block->GetAbsoluteContainingBlock()->RemoveFrame(block, + nsGkAtoms::absoluteList, + aFrame); } else { // First remove aFrame's next-in-flows nsIFrame* nif = aFrame->GetNextInFlow(); if (nif) { static_cast<nsContainerFrame*>(nif->GetParent()) ->DeleteNextInFlowChild(aFrame->PresContext(), nif, PR_FALSE); } @@ -6251,18 +6235,16 @@ nsBlockFrame::BuildDisplayList(nsDisplay DisplayOverflowContainers(aBuilder, aDirtyRect, aLists); for (nsIFrame* f = mFloats.FirstChild(); f; f = f->GetNextSibling()) { if (f->GetStateBits() & NS_FRAME_IS_PUSHED_FLOAT) BuildDisplayListForChild(aBuilder, f, aDirtyRect, aLists); } } aBuilder->MarkFramesForDisplayList(this, mFloats, aDirtyRect); - aBuilder->MarkFramesForDisplayList(this, mAbsoluteContainer.GetChildList(), - aDirtyRect); // Don't use the line cursor if we might have a descendant placeholder ... // it might skip lines that contain placeholders but don't themselves // intersect with the dirty area. // In particular, we really want to check ShouldDescendIntoFrame() // on all our child frames, but that might be expensive. So we // approximate it by checking it on |this|; if it's true for any // frame in our child list, it's also true for |this|. @@ -6507,20 +6489,17 @@ nsBlockFrame::Init(nsIContent* aCon } NS_IMETHODIMP nsBlockFrame::SetInitialChildList(nsIAtom* aListName, nsFrameList& aChildList) { nsresult rv = NS_OK; - if (nsGkAtoms::absoluteList == aListName) { - mAbsoluteContainer.SetInitialChildList(this, aListName, aChildList); - } - else if (nsGkAtoms::floatList == aListName) { + if (nsGkAtoms::floatList == aListName) { mFloats.SetFrames(aChildList); } else { nsPresContext* presContext = PresContext(); #ifdef DEBUG // The only times a block that is an anonymous box is allowed to have a // first-letter frame are when it's the block inside a non-anonymous cell,
--- a/layout/generic/nsBlockFrame.h +++ b/layout/generic/nsBlockFrame.h @@ -79,17 +79,17 @@ class nsBlockInFlowLineIterator; class nsBulletFrame; class nsLineBox; class nsFirstLineFrame; class nsIntervalSet; /** * Child list name indices * @see #GetAdditionalChildListName() */ -#define NS_BLOCK_LIST_COUNT (NS_CONTAINER_LIST_COUNT_INCL_OC + 5) +#define NS_BLOCK_LIST_COUNT (NS_CONTAINER_LIST_COUNT_INCL_OC + 4) /** * Some invariants: * -- The overflow out-of-flows list contains the out-of- * flow frames whose placeholders are in the overflow list. * -- A given piece of content has at most one placeholder * frame in a block's normal child list. * -- While a block is being reflowed, and from then until @@ -336,17 +336,16 @@ public: */ static nsBlockFrame* GetNearestAncestorBlock(nsIFrame* aCandidate); protected: nsBlockFrame(nsStyleContext* aContext) : nsHTMLContainerFrame(aContext) , mMinWidth(NS_INTRINSIC_WIDTH_UNKNOWN) , mPrefWidth(NS_INTRINSIC_WIDTH_UNKNOWN) - , mAbsoluteContainer(nsGkAtoms::absoluteList) { #ifdef DEBUG InitDebugFlags(); #endif } virtual ~nsBlockFrame(); #ifdef DEBUG @@ -771,20 +770,16 @@ protected: // XXX_fix_me: subclass one more time! // For list-item frames, this is the bullet frame. nsBulletFrame* mBullet; friend class nsBlockReflowState; friend class nsBlockInFlowLineIterator; -private: - nsAbsoluteContainingBlock mAbsoluteContainer; - - #ifdef DEBUG public: static PRBool gLamePaintMetrics; static PRBool gLameReflowMetrics; static PRBool gNoisy; static PRBool gNoisyDamageRepair; static PRBool gNoisyIntrinsic; static PRBool gNoisyReflow;
--- a/layout/generic/nsCanvasFrame.cpp +++ b/layout/generic/nsCanvasFrame.cpp @@ -47,49 +47,45 @@ #include "nsRenderingContext.h" #include "nsGUIEvent.h" #include "nsStyleConsts.h" #include "nsGkAtoms.h" #include "nsEventStateManager.h" #include "nsIPresShell.h" #include "nsIScrollPositionListener.h" #include "nsDisplayList.h" -#include "nsAbsoluteContainingBlock.h" #include "nsCSSFrameConstructor.h" #include "nsFrameManager.h" // for focus #include "nsIDOMWindowInternal.h" #include "nsIScrollableFrame.h" #include "nsIDocShell.h" #ifdef DEBUG_rods //#define DEBUG_CANVAS_FOCUS #endif -#define CANVAS_ABS_POS_CHILD_LIST NS_CONTAINER_LIST_COUNT_INCL_OC - nsIFrame* NS_NewCanvasFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) { return new (aPresShell) nsCanvasFrame(aContext); } NS_IMPL_FRAMEARENA_HELPERS(nsCanvasFrame) NS_QUERYFRAME_HEAD(nsCanvasFrame) NS_QUERYFRAME_ENTRY(nsCanvasFrame) NS_QUERYFRAME_TAIL_INHERITING(nsHTMLContainerFrame) void nsCanvasFrame::DestroyFrom(nsIFrame* aDestructRoot) { - mAbsoluteContainer.DestroyFrames(this, aDestructRoot); - + DestroyAbsoluteFrames(aDestructRoot); nsIScrollableFrame* sf = PresContext()->GetPresShell()->GetRootScrollFrameAsScrollable(); if (sf) { sf->RemoveScrollPositionListener(this); } nsHTMLContainerFrame::DestroyFrom(aDestructRoot); } @@ -121,31 +117,25 @@ nsCanvasFrame::SetHasFocus(PRBool aHasFo } return NS_OK; } NS_IMETHODIMP nsCanvasFrame::SetInitialChildList(nsIAtom* aListName, nsFrameList& aChildList) { - if (nsGkAtoms::absoluteList == aListName) - return mAbsoluteContainer.SetInitialChildList(this, aListName, aChildList); - NS_ASSERTION(aListName || aChildList.IsEmpty() || aChildList.OnlyChild(), "Primary child list can have at most one frame in it"); return nsHTMLContainerFrame::SetInitialChildList(aListName, aChildList); } NS_IMETHODIMP nsCanvasFrame::AppendFrames(nsIAtom* aListName, nsFrameList& aFrameList) { - if (nsGkAtoms::absoluteList == aListName) - return mAbsoluteContainer.AppendFrames(this, aListName, aFrameList); - NS_ASSERTION(!aListName, "unexpected child list name"); NS_PRECONDITION(mFrames.IsEmpty(), "already have a child frame"); if (aListName) { // We only support unnamed principal child list return NS_ERROR_INVALID_ARG; } if (!mFrames.IsEmpty()) { @@ -168,37 +158,29 @@ nsCanvasFrame::AppendFrames(nsIAtom* return NS_OK; } NS_IMETHODIMP nsCanvasFrame::InsertFrames(nsIAtom* aListName, nsIFrame* aPrevFrame, nsFrameList& aFrameList) { - if (nsGkAtoms::absoluteList == aListName) - return mAbsoluteContainer.InsertFrames(this, aListName, aPrevFrame, aFrameList); - // Because we only support a single child frame inserting is the same // as appending NS_PRECONDITION(!aPrevFrame, "unexpected previous sibling frame"); if (aPrevFrame) return NS_ERROR_UNEXPECTED; return AppendFrames(aListName, aFrameList); } NS_IMETHODIMP nsCanvasFrame::RemoveFrame(nsIAtom* aListName, nsIFrame* aOldFrame) { - if (nsGkAtoms::absoluteList == aListName) { - mAbsoluteContainer.RemoveFrame(this, aListName, aOldFrame); - return NS_OK; - } - NS_ASSERTION(!aListName, "unexpected child list name"); if (aListName) { // We only support the unnamed principal child list return NS_ERROR_INVALID_ARG; } if (aOldFrame != mFrames.FirstChild()) return NS_ERROR_FAILURE; @@ -213,34 +195,16 @@ nsCanvasFrame::RemoveFrame(nsIAtom* mFrames.DestroyFrame(aOldFrame); PresContext()->PresShell()-> FrameNeedsReflow(this, nsIPresShell::eTreeChange, NS_FRAME_HAS_DIRTY_CHILDREN); return NS_OK; } -nsIAtom* -nsCanvasFrame::GetAdditionalChildListName(PRInt32 aIndex) const -{ - if (CANVAS_ABS_POS_CHILD_LIST == aIndex) - return nsGkAtoms::absoluteList; - - return nsHTMLContainerFrame::GetAdditionalChildListName(aIndex); -} - -nsFrameList -nsCanvasFrame::GetChildList(nsIAtom* aListName) const -{ - if (nsGkAtoms::absoluteList == aListName) - return mAbsoluteContainer.GetChildList(); - - return nsHTMLContainerFrame::GetChildList(aListName); -} - nsRect nsCanvasFrame::CanvasArea() const { // Not clear which overflow rect we want here, but it probably doesn't // matter. nsRect result(GetVisualOverflowRect()); nsIScrollableFrame *scrollableFrame = do_QueryFrame(GetParent()); if (scrollableFrame) { @@ -309,19 +273,16 @@ nsCanvasFrame::BuildDisplayList(nsDispla const nsDisplayListSet& aLists) { nsresult rv; if (GetPrevInFlow()) { DisplayOverflowContainers(aBuilder, aDirtyRect, aLists); } - aBuilder->MarkFramesForDisplayList(this, mAbsoluteContainer.GetChildList(), - aDirtyRect); - // Force a background to be shown. We may have a background propagated to us, // in which case GetStyleBackground wouldn't have the right background // and the code in nsFrame::DisplayBorderBackgroundOutline might not give us // a background. // We don't have any border or outline, and our background draws over // the overflow area, so just add nsDisplayCanvasBackground instead of // calling DisplayBorderBackgroundOutline. if (IsVisibleForPainting(aBuilder)) { @@ -548,25 +509,16 @@ nsCanvasFrame::Reflow(nsPresContext* } else { aDesiredSize.height = aReflowState.ComputedHeight(); } aDesiredSize.SetOverflowAreasToDesiredBounds(); aDesiredSize.mOverflowAreas.UnionWith( kidDesiredSize.mOverflowAreas + kidPt); - if (mAbsoluteContainer.HasAbsoluteFrames()) { - PRBool widthChanged = aDesiredSize.width != mRect.width; - PRBool heightChanged = aDesiredSize.height != mRect.height; - mAbsoluteContainer.Reflow(this, aPresContext, aReflowState, aStatus, - aDesiredSize.width, aDesiredSize.height, - PR_TRUE, widthChanged, heightChanged, - &aDesiredSize.mOverflowAreas); - } - // Handle invalidating fixed-attachment backgrounds propagated to the // canvas when the canvas size (and therefore the background positioning // area's size) changes. Such backgrounds are not invalidated in the // normal manner because the size of the original frame for that background // may not have changed. // // This isn't the right fix for this issue, taken more generally. In // particular, this doesn't handle fixed-attachment backgrounds that are *not* @@ -597,17 +549,17 @@ nsCanvasFrame::Reflow(nsPresContext* } if (prevCanvasFrame) { ReflowOverflowContainerChildren(aPresContext, aReflowState, aDesiredSize.mOverflowAreas, 0, aStatus); } - FinishAndStoreOverflow(&aDesiredSize); + FinishReflowWithAbsoluteFrames(aPresContext, aDesiredSize, aReflowState, aStatus); NS_FRAME_TRACE_REFLOW_OUT("nsCanvasFrame::Reflow", aStatus); NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); return NS_OK; } PRIntn nsCanvasFrame::GetSkipSides() const
--- a/layout/generic/nsCanvasFrame.h +++ b/layout/generic/nsCanvasFrame.h @@ -37,17 +37,16 @@ /* rendering object that goes directly inside the document's scrollbars */ #ifndef nsCanvasFrame_h___ #define nsCanvasFrame_h___ #include "nsHTMLContainerFrame.h" #include "nsIScrollPositionListener.h" -#include "nsAbsoluteContainingBlock.h" #include "nsDisplayList.h" #include "nsGkAtoms.h" class nsPresContext; class nsRenderingContext; class nsEvent; /** @@ -59,18 +58,17 @@ class nsEvent; */ class nsCanvasFrame : public nsHTMLContainerFrame, public nsIScrollPositionListener { public: nsCanvasFrame(nsStyleContext* aContext) : nsHTMLContainerFrame(aContext), mDoPaintFocus(PR_FALSE), - mAddedScrollPositionListener(PR_FALSE), - mAbsoluteContainer(nsGkAtoms::absoluteList) {} + mAddedScrollPositionListener(PR_FALSE) {} NS_DECL_QUERYFRAME_TARGET(nsCanvasFrame) NS_DECL_QUERYFRAME NS_DECL_FRAMEARENA_HELPERS virtual void DestroyFrom(nsIFrame* aDestructRoot); @@ -79,19 +77,16 @@ public: NS_IMETHOD AppendFrames(nsIAtom* aListName, nsFrameList& aFrameList); NS_IMETHOD InsertFrames(nsIAtom* aListName, nsIFrame* aPrevFrame, nsFrameList& aFrameList); NS_IMETHOD RemoveFrame(nsIAtom* aListName, nsIFrame* aOldFrame); - virtual nsIAtom* GetAdditionalChildListName(PRInt32 aIndex) const; - virtual nsFrameList GetChildList(nsIAtom* aListName) const; - virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext); virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext); NS_IMETHOD Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus); virtual PRBool IsContainingBlock() const { return PR_TRUE; } virtual PRBool IsFrameOfType(PRUint32 aFlags) const @@ -147,17 +142,16 @@ public: nsRect CanvasArea() const; protected: virtual PRIntn GetSkipSides() const; // Data members PRPackedBool mDoPaintFocus; PRPackedBool mAddedScrollPositionListener; - nsAbsoluteContainingBlock mAbsoluteContainer; }; /** * Override nsDisplayBackground methods so that we pass aBGClipRect to * PaintBackground, covering the whole overflow area. * We can also paint an "extra background color" behind the normal * background. */
--- a/layout/generic/nsContainerFrame.cpp +++ b/layout/generic/nsContainerFrame.cpp @@ -314,37 +314,37 @@ nsContainerFrame::GetChildList(nsIAtom* } if (nsGkAtoms::excessOverflowContainersList == aListName) { nsFrameList* list = GetPropTableFrames(PresContext(), ExcessOverflowContainersProperty()); return list ? *list : nsFrameList::EmptyList(); } - return nsFrameList::EmptyList(); + return nsSplittableFrame::GetChildList(aListName); } -#define NS_CONTAINER_FRAME_OVERFLOW_LIST_INDEX 0 -#define NS_CONTAINER_FRAME_OVERFLOW_CONTAINERS_LIST_INDEX 1 -#define NS_CONTAINER_FRAME_EXCESS_OVERFLOW_CONTAINERS_LIST_INDEX 2 +#define NS_CONTAINER_FRAME_OVERFLOW_LIST_INDEX 1 +#define NS_CONTAINER_FRAME_OVERFLOW_CONTAINERS_LIST_INDEX 2 +#define NS_CONTAINER_FRAME_EXCESS_OVERFLOW_CONTAINERS_LIST_INDEX 3 // If adding/removing lists, don't forget to update count in .h file nsIAtom* nsContainerFrame::GetAdditionalChildListName(PRInt32 aIndex) const { if (NS_CONTAINER_FRAME_OVERFLOW_LIST_INDEX == aIndex) return nsGkAtoms::overflowList; else if (IsFrameOfType(nsIFrame::eCanContainOverflowContainers)) { if (NS_CONTAINER_FRAME_OVERFLOW_CONTAINERS_LIST_INDEX == aIndex) return nsGkAtoms::overflowContainersList; else if (NS_CONTAINER_FRAME_EXCESS_OVERFLOW_CONTAINERS_LIST_INDEX == aIndex) return nsGkAtoms::excessOverflowContainersList; } - return nsnull; + return nsSplittableFrame::GetAdditionalChildListName(aIndex); } ///////////////////////////////////////////////////////////////////////////// // Painting/Events NS_IMETHODIMP nsContainerFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, const nsRect& aDirtyRect,
--- a/layout/generic/nsContainerFrame.h +++ b/layout/generic/nsContainerFrame.h @@ -45,19 +45,17 @@ #include "nsFrameList.h" #include "nsLayoutUtils.h" #include "nsAutoPtr.h" /** * Child list name indices * @see #GetAdditionalChildListName() */ -#define NS_CONTAINER_LIST_COUNT_SANS_OC 1 - // for frames that don't use overflow containers -#define NS_CONTAINER_LIST_COUNT_INCL_OC 3 +#define NS_CONTAINER_LIST_COUNT_INCL_OC 4 // for frames that support overflow containers // Option flags for ReflowChild() and FinishReflowChild() // member functions #define NS_FRAME_NO_MOVE_VIEW 0x0001 #define NS_FRAME_NO_MOVE_FRAME (0x0002 | NS_FRAME_NO_MOVE_VIEW) #define NS_FRAME_NO_SIZE_VIEW 0x0004 #define NS_FRAME_NO_VISIBILITY 0x0008
--- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -954,23 +954,33 @@ nsFrame::GetBaseline() const } // Child frame enumeration nsIAtom* nsFrame::GetAdditionalChildListName(PRInt32 aIndex) const { NS_PRECONDITION(aIndex >= 0, "invalid index number"); + // An index of 0 should always be an absolute list, we should ignore anything + // else if child frame types have ignored them. + if (aIndex == 0) { + return GetAbsoluteListName(); + } return nsnull; } nsFrameList nsFrame::GetChildList(nsIAtom* aListName) const { - return nsFrameList::EmptyList(); + if (IsAbsoluteContainer() && + aListName == GetAbsoluteListName()) { + return GetAbsoluteContainingBlock()->GetChildList(); + } else { + return nsFrameList::EmptyList(); + } } static nsIFrame* GetActiveSelectionFrame(nsPresContext* aPresContext, nsIFrame* aFrame) { nsIContent* capturingContent = nsIPresShell::GetCapturingContent(); if (capturingContent) { nsIFrame* activeFrame = aPresContext->GetPrimaryFrameFor(capturingContent); @@ -1482,16 +1492,19 @@ nsIFrame::BuildDisplayListForStackingCon #ifdef MOZ_SVG PRBool usingSVGEffects = nsSVGIntegrationUtils::UsingEffectsForFrame(this); if (usingSVGEffects) { dirtyRect = nsSVGIntegrationUtils::GetRequiredSourceForInvalidArea(this, dirtyRect); } #endif + // Mark the display list items for absolutely positioned children + MarkAbsoluteFramesForDisplayList(aBuilder, aDirtyRect); + nsDisplayListCollection set; nsresult rv; { nsDisplayListBuilder::AutoIsRootSetter rootSetter(aBuilder, PR_TRUE); nsDisplayListBuilder::AutoInTransformSetter inTransformSetter(aBuilder, inTransform); rv = BuildDisplayList(aBuilder, dirtyRect, set); } @@ -1616,17 +1629,17 @@ nsIFrame::BuildDisplayListForChild(nsDis PRUint32 aFlags) { // If painting is restricted to just the background of the top level frame, // then we have nothing to do here. if (aBuilder->IsBackgroundOnly()) return NS_OK; if (aChild->GetStateBits() & NS_FRAME_TOO_DEEP_IN_FRAME_TREE) return NS_OK; - + const nsStyleDisplay* disp = aChild->GetStyleDisplay(); // PR_TRUE if this is a real or pseudo stacking context PRBool pseudoStackingContext = (aFlags & DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT) != 0; // XXX we REALLY need a "are you an inline-block sort of thing?" here!!! if ((aFlags & DISPLAY_CHILD_INLINE) && (disp->mDisplay != NS_STYLE_DISPLAY_INLINE || aChild->IsContainingBlock() || @@ -1662,19 +1675,25 @@ nsIFrame::BuildDisplayListForChild(nsDis dirty = *savedDirty; } else { // The out-of-flow frame did not intersect the dirty area. We may still // need to traverse into it, since it may contain placeholders we need // to enter to reach other out-of-flow frames that are visible. dirty.SetEmpty(); } pseudoStackingContext = PR_TRUE; - } else if (aBuilder->GetSelectedFramesOnly() && - aChild->IsLeaf() && - !(aChild->GetStateBits() & NS_FRAME_SELECTED_CONTENT)) { + } + + // Mark the display list items for absolutely positioned children + aChild->MarkAbsoluteFramesForDisplayList(aBuilder, dirty); + + if (childType != nsGkAtoms::placeholderFrame && + aBuilder->GetSelectedFramesOnly() && + aChild->IsLeaf() && + !(aChild->GetStateBits() & NS_FRAME_SELECTED_CONTENT)) { return NS_OK; } if (aBuilder->GetIncludeAllOutOfFlows() && (aChild->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) { dirty = aChild->GetVisualOverflowRect(); } else if (!(aChild->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO)) { // No need to descend into aChild to catch placeholders for visible @@ -1830,16 +1849,25 @@ nsIFrame::BuildDisplayListForChild(nsDis // This doesn't affect correctness because the positioned descendants list // is sorted by z-order and content in BuildDisplayListForStackingContext, // but it means that sort routine needs to do less work. aLists.PositionedDescendants()->AppendToTop(&extraPositionedDescendants); return NS_OK; } void +nsIFrame::MarkAbsoluteFramesForDisplayList(nsDisplayListBuilder* aBuilder, + const nsRect& aDirtyRect) +{ + if (IsAbsoluteContainer()) { + aBuilder->MarkFramesForDisplayList(this, GetAbsoluteContainingBlock()->GetChildList(), aDirtyRect); + } +} + +void nsIFrame::WrapReplacedContentForBorderRadius(nsDisplayListBuilder* aBuilder, nsDisplayList* aFromList, const nsDisplayListSet& aToLists) { nscoord radii[8]; if (GetContentBoxBorderRadii(radii)) { // If we have a border-radius, we have to clip our content to that // radius. @@ -3579,16 +3607,17 @@ nsFrame::WillReflow(nsPresContext* aPres NS_IMETHODIMP nsFrame::DidReflow(nsPresContext* aPresContext, const nsHTMLReflowState* aReflowState, nsDidReflowStatus aStatus) { NS_FRAME_TRACE_MSG(NS_FRAME_TRACE_CALLS, ("nsFrame::DidReflow: aStatus=%d", aStatus)); + if (NS_FRAME_REFLOW_FINISHED == aStatus) { mState &= ~(NS_FRAME_IN_REFLOW | NS_FRAME_FIRST_REFLOW | NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN); } // Notify the percent height observer if there is a percent height. // The observer may be able to initiate another reflow with a computed // height. This happens in the case where a table cell has no computed @@ -3599,16 +3628,65 @@ nsFrame::DidReflow(nsPresContext* if (height.HasPercent()) { aReflowState->mPercentHeightObserver->NotifyPercentHeight(*aReflowState); } } return NS_OK; } +void +nsFrame::FinishReflowWithAbsoluteFrames(nsPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus) +{ + ReflowAbsoluteFrames(aPresContext, aDesiredSize, aReflowState, aStatus); + + FinishAndStoreOverflow(&aDesiredSize); +} + +void +nsFrame::DestroyAbsoluteFrames(nsIFrame* aDestructRoot) +{ + if (IsAbsoluteContainer()) { + GetAbsoluteContainingBlock()->DestroyFrames(this, aDestructRoot); + } +} + +void +nsFrame::ReflowAbsoluteFrames(nsPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus) +{ + if (HasAbsolutelyPositionedChildren()) { + nsAbsoluteContainingBlock* absoluteContainer = GetAbsoluteContainingBlock(); + + // Let the absolutely positioned container reflow any absolutely positioned + // child frames that need to be reflowed + + // The containing block for the abs pos kids is formed by our padding edge. + nsMargin computedBorder = + aReflowState.mComputedBorderPadding - aReflowState.mComputedPadding; + nscoord containingBlockWidth = + aDesiredSize.width - computedBorder.LeftRight(); + nscoord containingBlockHeight = + aDesiredSize.height - computedBorder.TopBottom(); + + nsContainerFrame* container = do_QueryFrame(this); + NS_ASSERTION(container, "Abs-pos children only supported on container frames for now"); + + absoluteContainer->Reflow(container, aPresContext, aReflowState, aStatus, + containingBlockWidth, containingBlockHeight, + PR_TRUE, PR_TRUE, PR_TRUE, // XXX could be optimized + &aDesiredSize.mOverflowAreas); + } +} + /* virtual */ PRBool nsFrame::CanContinueTextRun() const { // By default, a frame will *not* allow a text run to be continued // through it. return PR_FALSE; } @@ -6184,18 +6262,17 @@ nsIFrame::SetOverflowAreas(const nsOverf *overflow = aOverflowAreas; } } inline PRBool IsInlineFrame(nsIFrame *aFrame) { nsIAtom *type = aFrame->GetType(); - return type == nsGkAtoms::inlineFrame || - type == nsGkAtoms::positionedInlineFrame; + return type == nsGkAtoms::inlineFrame; } void nsIFrame::FinishAndStoreOverflow(nsOverflowAreas& aOverflowAreas, nsSize aNewSize) { nsRect bounds(nsPoint(0, 0), aNewSize); @@ -7900,17 +7977,16 @@ void DR_State::InitFrameTypeTable() AddFrameTypeInfo(nsGkAtoms::imageFrame, "img", "image"); AddFrameTypeInfo(nsGkAtoms::inlineFrame, "inline", "inline"); AddFrameTypeInfo(nsGkAtoms::letterFrame, "letter", "letter"); AddFrameTypeInfo(nsGkAtoms::lineFrame, "line", "line"); AddFrameTypeInfo(nsGkAtoms::listControlFrame, "select", "select"); AddFrameTypeInfo(nsGkAtoms::objectFrame, "obj", "object"); AddFrameTypeInfo(nsGkAtoms::pageFrame, "page", "page"); AddFrameTypeInfo(nsGkAtoms::placeholderFrame, "place", "placeholder"); - AddFrameTypeInfo(nsGkAtoms::positionedInlineFrame, "posInline", "positionedInline"); AddFrameTypeInfo(nsGkAtoms::canvasFrame, "canvas", "canvas"); AddFrameTypeInfo(nsGkAtoms::rootFrame, "root", "root"); AddFrameTypeInfo(nsGkAtoms::scrollFrame, "scroll", "scroll"); AddFrameTypeInfo(nsGkAtoms::tableCaptionFrame, "caption", "tableCaption"); AddFrameTypeInfo(nsGkAtoms::tableCellFrame, "cell", "tableCell"); AddFrameTypeInfo(nsGkAtoms::bcTableCellFrame, "bcCell", "bcTableCell"); AddFrameTypeInfo(nsGkAtoms::tableColFrame, "col", "tableCol"); AddFrameTypeInfo(nsGkAtoms::tableColGroupFrame, "colG", "tableColGroup");
--- a/layout/generic/nsFrame.h +++ b/layout/generic/nsFrame.h @@ -323,16 +323,25 @@ public: NS_IMETHOD WillReflow(nsPresContext* aPresContext); NS_IMETHOD Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus); NS_IMETHOD DidReflow(nsPresContext* aPresContext, const nsHTMLReflowState* aReflowState, nsDidReflowStatus aStatus); + void ReflowAbsoluteFrames(nsPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus); + void FinishReflowWithAbsoluteFrames(nsPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus); + void DestroyAbsoluteFrames(nsIFrame* aDestructRoot); virtual PRBool CanContinueTextRun() const; // Selection Methods // XXX Doc me... (in nsIFrame.h puhleeze) // XXX If these are selection specific, then the name should imply selection // rather than generic event processing, e.g., SelectionHandlePress... NS_IMETHOD HandlePress(nsPresContext* aPresContext, nsGUIEvent * aEvent,
--- a/layout/generic/nsHTMLParts.h +++ b/layout/generic/nsHTMLParts.h @@ -134,18 +134,16 @@ nsIFrame* NS_NewViewportFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); nsIFrame* NS_NewCanvasFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); nsIFrame* NS_NewImageFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); nsIFrame* NS_NewInlineFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); nsIFrame* -NS_NewPositionedInlineFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); -nsIFrame* NS_NewObjectFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); nsIFrame* NS_NewTextFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); nsIFrame* NS_NewContinuingTextFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); nsIFrame* NS_NewEmptyFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); inline nsIFrame*
--- a/layout/generic/nsHTMLReflowState.cpp +++ b/layout/generic/nsHTMLReflowState.cpp @@ -1570,17 +1570,17 @@ nsHTMLReflowState::ComputeContainingBloc aContainingBlockWidth = aContainingBlockRS->mComputedWidth; aContainingBlockHeight = aContainingBlockRS->mComputedHeight; if (NS_FRAME_GET_TYPE(mFrameType) == NS_CSS_FRAME_TYPE_ABSOLUTE) { // See if the ancestor is block-level or inline-level if (NS_FRAME_GET_TYPE(aContainingBlockRS->mFrameType) == NS_CSS_FRAME_TYPE_INLINE) { // Base our size on the actual size of the frame. In cases when this is // completely bogus (eg initial reflow), this code shouldn't even be - // called, since the code in nsPositionedInlineFrame::Reflow will pass in + // called, since the code in nsInlineFrame::Reflow will pass in // the containing block dimensions to our constructor. // XXXbz we should be taking the in-flows into account too, but // that's very hard. nsMargin computedBorder = aContainingBlockRS->mComputedBorderPadding - aContainingBlockRS->mComputedPadding; aContainingBlockWidth = aContainingBlockRS->frame->GetRect().width - computedBorder.LeftRight();; NS_ASSERTION(aContainingBlockWidth >= 0,
--- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -583,16 +583,18 @@ public: * * This is only called once for a given child list, and won't be called * at all for child lists with no initial list of frames. * * @param aListName the name of the child list. A NULL pointer for the atom * name means the unnamed principal child list * @param aChildList list of child frames. Each of the frames has its * NS_FRAME_IS_DIRTY bit set. Must not be empty. + * This method cannot handle the child list returned by + * GetAbsoluteListName(). * @return NS_ERROR_INVALID_ARG if there is no child list with the specified * name, * NS_ERROR_UNEXPECTED if the frame is an atomic frame or if the * initial list of frames has already been set for that child list, * NS_OK otherwise. In this case, SetInitialChildList empties out * aChildList in the process of moving the frames over to its own * child list. * @see #Init() @@ -2719,16 +2721,18 @@ protected: nsRect mRect; nsIContent* mContent; nsStyleContext* mStyleContext; nsIFrame* mParent; private: nsIFrame* mNextSibling; // doubly-linked list of frames nsIFrame* mPrevSibling; // Do not touch outside SetNextSibling! + void MarkAbsoluteFramesForDisplayList(nsDisplayListBuilder* aBuilder, const nsRect& aDirtyRect); + static void DestroyPaintedPresShellList(void* propertyValue) { nsTArray<nsWeakPtr>* list = static_cast<nsTArray<nsWeakPtr>*>(propertyValue); list->Clear(); delete list; } // Stores weak references to all the PresShells that were painted during // the last paint event so that we can increment their paint count during
--- a/layout/generic/nsInlineFrame.cpp +++ b/layout/generic/nsInlineFrame.cpp @@ -42,17 +42,16 @@ #include "nsBlockFrame.h" #include "nsPlaceholderFrame.h" #include "nsGkAtoms.h" #include "nsHTMLParts.h" #include "nsStyleContext.h" #include "nsIPresShell.h" #include "nsPresContext.h" #include "nsRenderingContext.h" -#include "nsAbsoluteContainingBlock.h" #include "nsCSSAnonBoxes.h" #include "nsAutoPtr.h" #include "nsFrameManager.h" #ifdef ACCESSIBILITY #include "nsIServiceManager.h" #include "nsAccessibilityService.h" #endif #include "nsDisplayList.h" @@ -409,17 +408,19 @@ nsInlineFrame::Reflow(nsPresContext* if (mFrames.IsEmpty()) { // Try to pull over one frame before starting so that we know // whether we have an anonymous block or not. PRBool complete; (void) PullOneFrame(aPresContext, irs, &complete); } rv = ReflowFrames(aPresContext, aReflowState, irs, aMetrics, aStatus); - + + ReflowAbsoluteFrames(aPresContext, aMetrics, aReflowState, aStatus); + // Note: the line layout code will properly compute our // overflow-rect state for us. NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics); return rv; } /* virtual */ PRBool @@ -917,16 +918,23 @@ nsInlineFrame::GetBaseline() const nsRefPtr<nsFontMetrics> fm; nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm)); if (fm) { ascent = fm->MaxAscent(); } return NS_MIN(mRect.height, ascent + GetUsedBorderAndPadding().top); } +void +nsInlineFrame::DestroyFrom(nsIFrame* aDestructRoot) +{ + DestroyAbsoluteFrames(aDestructRoot); + nsInlineFrameSuper::DestroyFrom(aDestructRoot); +} + #ifdef ACCESSIBILITY already_AddRefed<nsAccessible> nsInlineFrame::CreateAccessible() { // Broken image accessibles are created here, because layout // replaces the image or image control frame with an inline frame nsIAtom *tagAtom = mContent->Tag(); if ((tagAtom == nsGkAtoms::img || tagAtom == nsGkAtoms::input || @@ -1096,16 +1104,18 @@ nsFirstLineFrame::Reflow(nsPresContext* } NS_ASSERTION(!aReflowState.mLineLayout->GetInFirstLine(), "Nested first-line frames? BOGUS"); aReflowState.mLineLayout->SetInFirstLine(PR_TRUE); rv = ReflowFrames(aPresContext, aReflowState, irs, aMetrics, aStatus); aReflowState.mLineLayout->SetInFirstLine(PR_FALSE); + ReflowAbsoluteFrames(aPresContext, aMetrics, aReflowState, aStatus); + // Note: the line layout code will properly compute our overflow state for us return rv; } /* virtual */ void nsFirstLineFrame::PullOverflowsFromPrevInFlow() { @@ -1116,167 +1126,8 @@ nsFirstLineFrame::PullOverflowsFromPrevI // Assume that our prev-in-flow has the same line container that we do. const nsFrameList::Slice& newFrames = mFrames.InsertFrames(this, nsnull, *prevOverflowFrames); ReparentChildListStyle(PresContext(), newFrames, this); } } } -////////////////////////////////////////////////////////////////////// - -nsIFrame* -NS_NewPositionedInlineFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) -{ - return new (aPresShell) nsPositionedInlineFrame(aContext); -} - -NS_IMPL_FRAMEARENA_HELPERS(nsPositionedInlineFrame) - -void -nsPositionedInlineFrame::DestroyFrom(nsIFrame* aDestructRoot) -{ - mAbsoluteContainer.DestroyFrames(this, aDestructRoot); - nsInlineFrame::DestroyFrom(aDestructRoot); -} - -NS_IMETHODIMP -nsPositionedInlineFrame::SetInitialChildList(nsIAtom* aListName, - nsFrameList& aChildList) -{ - nsresult rv; - - if (nsGkAtoms::absoluteList == aListName) { - rv = mAbsoluteContainer.SetInitialChildList(this, aListName, aChildList); - } else { - rv = nsInlineFrame::SetInitialChildList(aListName, aChildList); - } - - return rv; -} - -NS_IMETHODIMP -nsPositionedInlineFrame::AppendFrames(nsIAtom* aListName, - nsFrameList& aFrameList) -{ - nsresult rv; - - if (nsGkAtoms::absoluteList == aListName) { - rv = mAbsoluteContainer.AppendFrames(this, aListName, aFrameList); - } else { - rv = nsInlineFrame::AppendFrames(aListName, aFrameList); - } - - return rv; -} - -NS_IMETHODIMP -nsPositionedInlineFrame::InsertFrames(nsIAtom* aListName, - nsIFrame* aPrevFrame, - nsFrameList& aFrameList) -{ - nsresult rv; - - if (nsGkAtoms::absoluteList == aListName) { - rv = mAbsoluteContainer.InsertFrames(this, aListName, aPrevFrame, - aFrameList); - } else { - rv = nsInlineFrame::InsertFrames(aListName, aPrevFrame, aFrameList); - } - - return rv; -} - -NS_IMETHODIMP -nsPositionedInlineFrame::RemoveFrame(nsIAtom* aListName, - nsIFrame* aOldFrame) -{ - nsresult rv; - - if (nsGkAtoms::absoluteList == aListName) { - mAbsoluteContainer.RemoveFrame(this, aListName, aOldFrame); - rv = NS_OK; - } else { - rv = nsInlineFrame::RemoveFrame(aListName, aOldFrame); - } - - return rv; -} - -NS_IMETHODIMP -nsPositionedInlineFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, - const nsDisplayListSet& aLists) -{ - aBuilder->MarkFramesForDisplayList(this, mAbsoluteContainer.GetChildList(), - aDirtyRect); - return nsHTMLContainerFrame::BuildDisplayList(aBuilder, aDirtyRect, aLists); -} - -nsIAtom* -nsPositionedInlineFrame::GetAdditionalChildListName(PRInt32 aIndex) const -{ - if (0 == aIndex) { - return nsGkAtoms::absoluteList; - } - return nsnull; -} - -nsFrameList -nsPositionedInlineFrame::GetChildList(nsIAtom* aListName) const -{ - if (nsGkAtoms::absoluteList == aListName) - return mAbsoluteContainer.GetChildList(); - - return nsInlineFrame::GetChildList(aListName); -} - -nsIAtom* -nsPositionedInlineFrame::GetType() const -{ - return nsGkAtoms::positionedInlineFrame; -} - -NS_IMETHODIMP -nsPositionedInlineFrame::Reflow(nsPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus) -{ - nsresult rv = NS_OK; - - // Don't bother optimizing for fast incremental reflow of absolute - // children of an inline - - // Let the inline frame do its reflow first - rv = nsInlineFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); - - // Let the absolutely positioned container reflow any absolutely positioned - // child frames that need to be reflowed - // We want to do this under either of two conditions: - // 1. If we didn't do the incremental reflow above. - // 2. If our size changed. - // Even though it's the padding edge that's the containing block, we - // can use our rect (the border edge) since if the border style - // changed, the reflow would have been targeted at us so we'd satisfy - // condition 1. - if (NS_SUCCEEDED(rv) && - mAbsoluteContainer.HasAbsoluteFrames()) { - // The containing block for the abs pos kids is formed by our padding edge. - nsMargin computedBorder = - aReflowState.mComputedBorderPadding - aReflowState.mComputedPadding; - nscoord containingBlockWidth = - aDesiredSize.width - computedBorder.LeftRight(); - nscoord containingBlockHeight = - aDesiredSize.height - computedBorder.TopBottom(); - - // Factor the absolutely positioned child bounds into the overflow area - // Don't include this frame's bounds, nor its inline descendants' bounds, - // and don't store the overflow property. - // That will all be done by nsLineLayout::RelativePositionFrames. - rv = mAbsoluteContainer.Reflow(this, aPresContext, aReflowState, aStatus, - containingBlockWidth, containingBlockHeight, - PR_TRUE, PR_TRUE, PR_TRUE, // XXX could be optimized - &aDesiredSize.mOverflowAreas); - } - - return rv; -}
--- a/layout/generic/nsInlineFrame.h +++ b/layout/generic/nsInlineFrame.h @@ -36,17 +36,16 @@ * ***** END LICENSE BLOCK ***** */ /* rendering object for CSS display:inline objects */ #ifndef nsInlineFrame_h___ #define nsInlineFrame_h___ #include "nsHTMLContainerFrame.h" -#include "nsAbsoluteContainingBlock.h" #include "nsLineLayout.h" class nsAnonymousBlockFrame; #define nsInlineFrameSuper nsHTMLContainerFrame /** In Bidi left (or right) margin/padding/border should be applied to left * (or right) most frame (or a continuation frame). @@ -92,16 +91,18 @@ public: { return nsInlineFrameSuper::IsFrameOfType(aFlags & ~(nsIFrame::eBidiInlineContainer | nsIFrame::eLineParticipant)); } virtual PRBool IsEmpty(); virtual PRBool IsSelfEmpty(); + virtual void DestroyFrom(nsIFrame* aDestructRoot); + virtual PRBool PeekOffsetCharacter(PRBool aForward, PRInt32* aOffset, PRBool aRespectClusters = PR_TRUE); // nsIHTMLReflow overrides virtual void AddInlineMinWidth(nsRenderingContext *aRenderingContext, InlineMinWidthData *aData); virtual void AddInlinePrefWidth(nsRenderingContext *aRenderingContext, InlinePrefWidthData *aData); @@ -222,58 +223,9 @@ public: protected: nsFirstLineFrame(nsStyleContext* aContext) : nsInlineFrame(aContext) {} virtual nsIFrame* PullOneFrame(nsPresContext* aPresContext, InlineReflowState& rs, PRBool* aIsComplete); }; -//---------------------------------------------------------------------- - -// Derived class created for relatively positioned inline-level elements -// that acts as a containing block for child absolutely positioned -// elements - -class nsPositionedInlineFrame : public nsInlineFrame -{ -public: - NS_DECL_FRAMEARENA_HELPERS - - nsPositionedInlineFrame(nsStyleContext* aContext) - : nsInlineFrame(aContext) - , mAbsoluteContainer(nsGkAtoms::absoluteList) - {} - - virtual ~nsPositionedInlineFrame() { } // useful for debugging - - virtual void DestroyFrom(nsIFrame* aDestructRoot); - - NS_IMETHOD SetInitialChildList(nsIAtom* aListName, - nsFrameList& aChildList); - NS_IMETHOD AppendFrames(nsIAtom* aListName, - nsFrameList& aFrameList); - NS_IMETHOD InsertFrames(nsIAtom* aListName, - nsIFrame* aPrevFrame, - nsFrameList& aFrameList); - NS_IMETHOD RemoveFrame(nsIAtom* aListName, - nsIFrame* aOldFrame); - - NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, - const nsDisplayListSet& aLists); - - virtual nsIAtom* GetAdditionalChildListName(PRInt32 aIndex) const; - - virtual nsFrameList GetChildList(nsIAtom* aListName) const; - - NS_IMETHOD Reflow(nsPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus); - - virtual nsIAtom* GetType() const; - -protected: - nsAbsoluteContainingBlock mAbsoluteContainer; -}; - #endif /* nsInlineFrame_h___ */
--- a/layout/generic/nsLineLayout.cpp +++ b/layout/generic/nsLineLayout.cpp @@ -657,18 +657,17 @@ IsPercentageAware(const nsIFrame* aFrame nsIAtom *fType = aFrame->GetType(); if (fType == nsGkAtoms::textFrame) { // None of these things can ever be true for text frames. return PR_FALSE; } // Some of these things don't apply to non-replaced inline frames - // (that is, fType == nsGkAtoms::inlineFrame || fType == - // nsGkAtoms::positionedInlineFrame), but we won't bother making + // (that is, fType == nsGkAtoms::inlineFrame), but we won't bother making // things unnecessarily complicated, since they'll probably be set // quite rarely. const nsStyleMargin* margin = aFrame->GetStyleMargin(); if (HasPercentageUnitSide(margin->mMargin)) { return PR_TRUE; }
--- a/layout/generic/nsPageContentFrame.cpp +++ b/layout/generic/nsPageContentFrame.cpp @@ -132,23 +132,20 @@ nsPageContentFrame::Reflow(nsPresContext } // Place and size the child FinishReflowChild(frame, aPresContext, &kidReflowState, aDesiredSize, 0, 0, 0); NS_ASSERTION(aPresContext->IsDynamic() || !NS_FRAME_IS_FULLY_COMPLETE(aStatus) || !frame->GetNextInFlow(), "bad child flow list"); } - // Reflow our fixed frames + + // Reflow our fixed frames nsReflowStatus fixedStatus = NS_FRAME_COMPLETE; - mFixedContainer.Reflow(this, aPresContext, aReflowState, fixedStatus, - aReflowState.availableWidth, - aReflowState.availableHeight, - PR_FALSE, PR_TRUE, PR_TRUE, // XXX could be optimized - nsnull /* ignore overflow */); + ReflowAbsoluteFrames(aPresContext, aDesiredSize, aReflowState, fixedStatus); NS_ASSERTION(NS_FRAME_IS_COMPLETE(fixedStatus), "fixed frames can be truncated, but not incomplete"); // Return our desired size aDesiredSize.width = aReflowState.availableWidth; if (aReflowState.availableHeight != NS_UNCONSTRAINEDSIZE) { aDesiredSize.height = aReflowState.availableHeight; }
--- a/layout/generic/nsQueryFrame.h +++ b/layout/generic/nsQueryFrame.h @@ -180,17 +180,16 @@ public: nsMenuFrame_id, nsMenuPopupFrame_id, nsObjectFrame_id, nsPageBreakFrame_id, nsPageContentFrame_id, nsPageFrame_id, nsPlaceholderFrame_id, nsPopupSetFrame_id, - nsPositionedInlineFrame_id, nsProgressMeterFrame_id, nsResizerFrame_id, nsRootBoxFrame_id, nsScrollbarButtonFrame_id, nsScrollbarFrame_id, nsSelectsAreaFrame_id, nsSimplePageSequenceFrame_id, nsSliderFrame_id,
--- a/layout/generic/nsViewportFrame.cpp +++ b/layout/generic/nsViewportFrame.cpp @@ -42,16 +42,17 @@ #include "nsCOMPtr.h" #include "nsViewportFrame.h" #include "nsHTMLParts.h" #include "nsGkAtoms.h" #include "nsIScrollableFrame.h" #include "nsDisplayList.h" #include "FrameLayerBuilder.h" +#include "nsAbsoluteContainingBlock.h" using namespace mozilla; nsIFrame* NS_NewViewportFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) { return new (aPresShell) ViewportFrame(aContext); } @@ -64,164 +65,95 @@ ViewportFrame::Init(nsIContent* aCo nsIFrame* aPrevInFlow) { return Super::Init(aContent, aParent, aPrevInFlow); } void ViewportFrame::DestroyFrom(nsIFrame* aDestructRoot) { - mFixedContainer.DestroyFrames(this, aDestructRoot); + DestroyAbsoluteFrames(aDestructRoot); nsContainerFrame::DestroyFrom(aDestructRoot); } NS_IMETHODIMP ViewportFrame::SetInitialChildList(nsIAtom* aListName, nsFrameList& aChildList) { - nsresult rv = NS_OK; - // See which child list to add the frames to #ifdef NS_DEBUG nsFrame::VerifyDirtyBitSet(aChildList); #endif - if (nsGkAtoms::fixedList == aListName) { - rv = mFixedContainer.SetInitialChildList(this, aListName, aChildList); - } - else { - rv = nsContainerFrame::SetInitialChildList(aListName, aChildList); - } - - return rv; + return nsContainerFrame::SetInitialChildList(aListName, aChildList); } NS_IMETHODIMP ViewportFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, const nsRect& aDirtyRect, const nsDisplayListSet& aLists) { - // We don't need any special painting or event handling. We just need to - // mark our visible out-of-flow frames (i.e., the fixed position frames) so - // that display list construction is guaranteed to recurse into their - // ancestors. - aBuilder->MarkFramesForDisplayList(this, mFixedContainer.GetChildList(), - aDirtyRect); - nsIFrame* kid = mFrames.FirstChild(); if (!kid) return NS_OK; // make the kid's BorderBackground our own. This ensures that the canvas // frame's background becomes our own background and therefore appears // below negative z-index elements. return BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists); } NS_IMETHODIMP ViewportFrame::AppendFrames(nsIAtom* aListName, nsFrameList& aFrameList) { - nsresult rv = NS_OK; - - if (nsGkAtoms::fixedList == aListName) { - rv = mFixedContainer.AppendFrames(this, aListName, aFrameList); - } - else { - NS_ASSERTION(!aListName, "unexpected child list"); - NS_ASSERTION(GetChildList(nsnull).IsEmpty(), "Shouldn't have any kids!"); - rv = nsContainerFrame::AppendFrames(aListName, aFrameList); - } - - return rv; + NS_ASSERTION(!aListName, "unexpected child list"); + NS_ASSERTION(GetChildList(nsnull).IsEmpty(), "Shouldn't have any kids!"); + return nsContainerFrame::AppendFrames(aListName, aFrameList); } NS_IMETHODIMP ViewportFrame::InsertFrames(nsIAtom* aListName, nsIFrame* aPrevFrame, nsFrameList& aFrameList) { - nsresult rv = NS_OK; - - if (nsGkAtoms::fixedList == aListName) { - rv = mFixedContainer.InsertFrames(this, aListName, aPrevFrame, aFrameList); - } - else { - NS_ASSERTION(!aListName, "unexpected child list"); - NS_ASSERTION(GetChildList(nsnull).IsEmpty(), "Shouldn't have any kids!"); - rv = nsContainerFrame::InsertFrames(aListName, aPrevFrame, aFrameList); - } - - return rv; + NS_ASSERTION(!aListName, "unexpected child list"); + NS_ASSERTION(GetChildList(nsnull).IsEmpty(), "Shouldn't have any kids!"); + return nsContainerFrame::InsertFrames(aListName, aPrevFrame, aFrameList); } NS_IMETHODIMP ViewportFrame::RemoveFrame(nsIAtom* aListName, nsIFrame* aOldFrame) { - nsresult rv = NS_OK; - - if (nsGkAtoms::fixedList == aListName) { - mFixedContainer.RemoveFrame(this, aListName, aOldFrame); - rv = NS_OK; - } - else { - NS_ASSERTION(!aListName, "unexpected child list"); - rv = nsContainerFrame::RemoveFrame(aListName, aOldFrame); - } - - return rv; -} - -nsIAtom* -ViewportFrame::GetAdditionalChildListName(PRInt32 aIndex) const -{ - NS_PRECONDITION(aIndex >= 0, "illegal index"); - - if (0 == aIndex) { - return nsGkAtoms::fixedList; - } - - return nsnull; -} - -nsFrameList -ViewportFrame::GetChildList(nsIAtom* aListName) const -{ - if (nsGkAtoms::fixedList == aListName) - return mFixedContainer.GetChildList(); - - return nsContainerFrame::GetChildList(aListName); + NS_ASSERTION(!aListName, "unexpected child list"); + return nsContainerFrame::RemoveFrame(aListName, aOldFrame); } /* virtual */ nscoord ViewportFrame::GetMinWidth(nsRenderingContext *aRenderingContext) { nscoord result; DISPLAY_MIN_WIDTH(this, result); if (mFrames.IsEmpty()) result = 0; else result = mFrames.FirstChild()->GetMinWidth(aRenderingContext); - - // XXXldb Deal with mFixedContainer (matters for SizeToContent)! return result; } /* virtual */ nscoord ViewportFrame::GetPrefWidth(nsRenderingContext *aRenderingContext) { nscoord result; DISPLAY_PREF_WIDTH(this, result); if (mFrames.IsEmpty()) result = 0; else result = mFrames.FirstChild()->GetPrefWidth(aRenderingContext); - - // XXXldb Deal with mFixedContainer (matters for SizeToContent)! return result; } nsPoint ViewportFrame::AdjustReflowStateForScrollbars(nsHTMLReflowState* aReflowState) const { // Calculate how much room is available for fixed frames. That means @@ -309,30 +241,34 @@ ViewportFrame::Reflow(nsPresContext* aDesiredSize.height = aReflowState.ComputedHeight() != NS_UNCONSTRAINEDSIZE ? aReflowState.ComputedHeight() : kidHeight; // Make a copy of the reflow state and change the computed width and height // to reflect the available space for the fixed items nsHTMLReflowState reflowState(aReflowState); nsPoint offset = AdjustReflowStateForScrollbars(&reflowState); - + #ifdef DEBUG - NS_ASSERTION(mFixedContainer.GetChildList().IsEmpty() || - (offset.x == 0 && offset.y == 0), - "We don't handle correct positioning of fixed frames with " - "scrollbars in odd positions"); + if (IsAbsoluteContainer()) { + NS_ASSERTION(GetAbsoluteContainingBlock()->GetChildList().IsEmpty() || + (offset.x == 0 && offset.y == 0), + "We don't handle correct positioning of fixed frames with " + "scrollbars in odd positions"); + } #endif - // Just reflow all the fixed-pos frames. - rv = mFixedContainer.Reflow(this, aPresContext, reflowState, aStatus, - reflowState.ComputedWidth(), - reflowState.ComputedHeight(), - PR_FALSE, PR_TRUE, PR_TRUE, // XXX could be optimized - nsnull /* ignore overflow */); + if (IsAbsoluteContainer()) { + // Just reflow all the fixed-pos frames. + rv = GetAbsoluteContainingBlock()->Reflow(this, aPresContext, reflowState, aStatus, + reflowState.ComputedWidth(), + reflowState.ComputedHeight(), + PR_FALSE, PR_TRUE, PR_TRUE, // XXX could be optimized + nsnull /* ignore overflow */); + } // If we were dirty then do a repaint if (GetStateBits() & NS_FRAME_IS_DIRTY) { nsRect damageRect(0, 0, aDesiredSize.width, aDesiredSize.height); Invalidate(damageRect); } // XXX Should we do something to clip our children to this?
--- a/layout/generic/nsViewportFrame.h +++ b/layout/generic/nsViewportFrame.h @@ -40,35 +40,32 @@ * the document's scrollbars and contains fixed-positioned elements */ #ifndef nsViewportFrame_h___ #define nsViewportFrame_h___ #include "nsContainerFrame.h" #include "nsGkAtoms.h" -#include "nsAbsoluteContainingBlock.h" class nsPresContext; /** * ViewportFrame is the parent of a single child - the doc root frame or a scroll frame * containing the doc root frame. ViewportFrame stores this child in its primary child - * list. It stores fixed positioned items in a secondary child list and its mFixedContainer - * delegate handles them. + * list. */ class ViewportFrame : public nsContainerFrame { public: NS_DECL_FRAMEARENA_HELPERS typedef nsContainerFrame Super; ViewportFrame(nsStyleContext* aContext) : nsContainerFrame(aContext) - , mFixedContainer(nsGkAtoms::fixedList) {} virtual ~ViewportFrame() { } // useful for debugging virtual void DestroyFrom(nsIFrame* aDestructRoot); NS_IMETHOD Init(nsIContent* aContent, nsIFrame* aParent, nsIFrame* asPrevInFlow); @@ -81,20 +78,16 @@ public: NS_IMETHOD InsertFrames(nsIAtom* aListName, nsIFrame* aPrevFrame, nsFrameList& aFrameList); NS_IMETHOD RemoveFrame(nsIAtom* aListName, nsIFrame* aOldFrame); - virtual nsIAtom* GetAdditionalChildListName(PRInt32 aIndex) const; - - virtual nsFrameList GetChildList(nsIAtom* aListName) const; - NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder, const nsRect& aDirtyRect, const nsDisplayListSet& aLists); virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext); virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext); NS_IMETHOD Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, @@ -118,17 +111,12 @@ public: NS_IMETHOD GetFrameName(nsAString& aResult) const; #endif private: virtual nsIAtom* GetAbsoluteListName() const { return nsGkAtoms::fixedList; } protected: nsPoint AdjustReflowStateForScrollbars(nsHTMLReflowState* aReflowState) const; - -protected: - // position: fixed content is really content which is absolutely positioned with - // respect to the viewport. - nsAbsoluteContainingBlock mFixedContainer; }; #endif // nsViewportFrame_h___
--- a/layout/tables/nsTableFrame.cpp +++ b/layout/tables/nsTableFrame.cpp @@ -1081,17 +1081,17 @@ nsIAtom* nsTableFrame::GetAdditionalChildListName(PRInt32 aIndex) const { if (aIndex == NS_TABLE_FRAME_COLGROUP_LIST_INDEX) { return nsGkAtoms::colGroupList; } if (aIndex == NS_TABLE_FRAME_OVERFLOW_LIST_INDEX) { return nsGkAtoms::overflowList; } - return nsnull; + return nsHTMLContainerFrame::GetAdditionalChildListName(aIndex); } nsRect nsDisplayTableItem::GetBounds(nsDisplayListBuilder* aBuilder) { return mFrame->GetVisualOverflowRect() + ToReferenceFrame(); } PRBool
--- a/layout/tables/nsTableOuterFrame.cpp +++ b/layout/tables/nsTableOuterFrame.cpp @@ -222,26 +222,26 @@ nsFrameList nsTableOuterFrame::GetChildList(nsIAtom* aListName) const { if (nsGkAtoms::captionList == aListName) { return mCaptionFrames; } if (!aListName) { return mFrames; } - return nsFrameList::EmptyList(); + return nsHTMLContainerFrame::GetChildList(aListName); } nsIAtom* nsTableOuterFrame::GetAdditionalChildListName(PRInt32 aIndex) const { if (aIndex == NS_TABLE_FRAME_CAPTION_LIST_INDEX) { return nsGkAtoms::captionList; } - return nsnull; + return nsHTMLContainerFrame::GetAdditionalChildListName(aIndex); } NS_IMETHODIMP nsTableOuterFrame::SetInitialChildList(nsIAtom* aListName, nsFrameList& aChildList) { if (nsGkAtoms::captionList == aListName) { // the frame constructor already checked for table-caption display type
--- a/layout/xul/base/src/nsMenuFrame.cpp +++ b/layout/xul/base/src/nsMenuFrame.cpp @@ -395,17 +395,17 @@ nsMenuFrame::SetInitialChildList(nsIAtom } nsIAtom* nsMenuFrame::GetAdditionalChildListName(PRInt32 aIndex) const { if (NS_MENU_POPUP_LIST_INDEX == aIndex) { return nsGkAtoms::popupList; } - return nsnull; + return nsBoxFrame::GetAdditionalChildListName(aIndex); } void nsMenuFrame::DestroyFrom(nsIFrame* aDestructRoot) { // Kill our timer if one is active. This is not strictly necessary as // the pointer to this frame will be cleared from the mediator, but // this is done for added safety.