Bug 10209 - Part 2: Implement the absolute positioning support for all frames; r=roc
authorEhsan Akhgari <ehsan@mozilla.com>
Fri, 29 Apr 2011 19:02:33 -0400
changeset 77837 0cafa2cbe386b511a03c8c8da3aafda70ab1f5f3
parent 77836 9989f9ef7b908b706316327b4acd40bc3b9aa9f7
child 77838 306153bf7a415a42fd4e07aa6e9f941a6c971970
push idunknown
push userunknown
push dateunknown
reviewersroc
bugs10209
milestone10.0a1
Bug 10209 - Part 2: Implement the absolute positioning support for all frames; r=roc
content/base/src/nsGkAtomList.h
layout/base/nsCSSFrameConstructor.cpp
layout/base/nsCSSRendering.cpp
layout/base/nsFrameManager.cpp
layout/base/nsFrameManager.h
layout/doc/frame_reflow_debug.html
layout/generic/nsAbsoluteContainingBlock.cpp
layout/generic/nsBlockFrame.cpp
layout/generic/nsBlockFrame.h
layout/generic/nsCanvasFrame.cpp
layout/generic/nsCanvasFrame.h
layout/generic/nsContainerFrame.cpp
layout/generic/nsFrame.cpp
layout/generic/nsFrame.h
layout/generic/nsHTMLParts.h
layout/generic/nsHTMLReflowState.cpp
layout/generic/nsIFrame.h
layout/generic/nsInlineFrame.cpp
layout/generic/nsInlineFrame.h
layout/generic/nsLineLayout.cpp
layout/generic/nsPageContentFrame.cpp
layout/generic/nsQueryFrame.h
layout/generic/nsViewportFrame.cpp
layout/generic/nsViewportFrame.h
layout/tables/nsTableOuterFrame.cpp
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -1738,17 +1738,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
@@ -1019,17 +1019,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(),
@@ -1215,17 +1217,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 aChildListID child list yet.
   const nsFrameList& childList = containingBlock->GetChildList(aChildListID);
   nsresult rv = NS_OK;
   if (childList.IsEmpty() &&
       (containingBlock->GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
-    rv = containingBlock->SetInitialChildList(aChildListID, aFrameItems);
+    // If we're injecting absolutely positioned frames, inject them on the
+    // absolute containing block
+    if (aChildListID == containingBlock->GetAbsoluteListID()) {
+      rv = containingBlock->GetAbsoluteContainingBlock()->
+           SetInitialChildList(containingBlock, aChildListID, aFrameItems);
+    } else {
+      rv = containingBlock->SetInitialChildList(aChildListID, 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
@@ -1233,33 +1242,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(aChildListID, aFrameItems);
+      rv = mFrameManager->AppendFrames(containingBlock, aChildListID, 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(aChildListID, insertionPoint,
-                                         aFrameItems);
+      rv = mFrameManager->InsertFrames(containingBlock, aChildListID,
+                                       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?
@@ -2547,16 +2556,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)
 {
@@ -2831,16 +2842,18 @@ nsCSSFrameConstructor::ConstructPageFram
   nsIFrame* prevPageContentFrame = nsnull;
   if (aPrevPageFrame) {
     prevPageContentFrame = aPrevPageFrame->GetFirstPrincipalChild();
     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;
@@ -5525,17 +5538,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);
         }
       }
 
@@ -8484,23 +8497,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);
@@ -10728,30 +10734,26 @@ nsCSSFrameConstructor::ConstructInline(n
   nsStyleContext* const styleContext = aItem.mStyleContext;
 
   nsIFrame *newFrame;
 
   bool 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,
@@ -10845,27 +10847,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
@@ -2544,18 +2544,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
@@ -87,16 +87,17 @@
 #include "nsReadableUtils.h"
 #include "nsUnicharUtils.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"
 #include "nsRuleProcessorData.h"
 
 #ifdef ACCESSIBILITY
 #include "nsAccessibilityService.h"
 #endif
 
@@ -465,29 +466,48 @@ nsFrameManager::ClearAllUndisplayedConte
       if (child->GetParent() != aParentContent) {
         ClearUndisplayedContentIn(child, child->GetParent());
       }
     }
   }
 }
 
 //----------------------------------------------------------------------
+nsresult
+nsFrameManager::AppendFrames(nsIFrame*       aParentFrame,
+                             ChildListID     aListID,
+                             nsFrameList&    aFrameList)
+{
+  if (aParentFrame->IsAbsoluteContainer() &&
+      aListID == aParentFrame->GetAbsoluteListID()) {
+    return aParentFrame->GetAbsoluteContainingBlock()->
+           AppendFrames(aParentFrame, aListID, aFrameList);
+  } else {
+    return aParentFrame->AppendFrames(aListID, aFrameList);
+  }
+}
 
 nsresult
 nsFrameManager::InsertFrames(nsIFrame*       aParentFrame,
                              ChildListID     aListID,
                              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(aListID, aPrevFrame, aFrameList);
+  if (aParentFrame->IsAbsoluteContainer() &&
+      aListID == aParentFrame->GetAbsoluteListID()) {
+    return aParentFrame->GetAbsoluteContainingBlock()->
+           InsertFrames(aParentFrame, aListID, aPrevFrame, aFrameList);
+  } else {
+    return aParentFrame->InsertFrames(aListID, aPrevFrame, aFrameList);
+  }
 }
 
 nsresult
 nsFrameManager::RemoveFrame(ChildListID     aListID,
                             nsIFrame*       aOldFrame)
 {
   bool wasDestroyingFrames = mIsDestroyingFrames;
   mIsDestroyingFrames = PR_TRUE;
@@ -502,17 +522,25 @@ nsFrameManager::RemoveFrame(ChildListID 
 
   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(aListID, aOldFrame);
+  nsresult rv = NS_OK;
+  nsIFrame* parentFrame = aOldFrame->GetParent();
+  if (parentFrame->IsAbsoluteContainer() &&
+      aListID == parentFrame->GetAbsoluteListID()) {
+    parentFrame->GetAbsoluteContainingBlock()->
+      RemoveFrame(parentFrame, aListID, aOldFrame);
+  } else {
+    rv = parentFrame->RemoveFrame(aListID, aOldFrame);
+  }
 
   mIsDestroyingFrames = wasDestroyingFrames;
 
   return rv;
 }
 
 //----------------------------------------------------------------------
 
--- a/layout/base/nsFrameManager.h
+++ b/layout/base/nsFrameManager.h
@@ -120,20 +120,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,
                                     ChildListID     aListID,
-                                    nsFrameList&    aFrameList)
-  {
-    return aParentFrame->AppendFrames(aListID, aFrameList);
-  }
+                                    nsFrameList&    aFrameList);
 
   NS_HIDDEN_(nsresult) InsertFrames(nsIFrame*       aParentFrame,
                                     ChildListID     aListID,
                                     nsIFrame*       aPrevFrame,
                                     nsFrameList&    aFrameList);
 
   NS_HIDDEN_(nsresult) RemoveFrame(ChildListID     aListID,
                                    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);
 
   bool 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
@@ -302,17 +302,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);
@@ -581,18 +581,16 @@ nsBlockFrame::GetChildList(ChildListID a
     case kOverflowList: {
       // 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())
                            : nsFrameList::EmptyList();
     }
-    case kAbsoluteList:
-      return mAbsoluteContainer.GetChildList();
     case kFloatList:
       return mFloats;
     case kOverflowOutOfFlowList: {
       const nsFrameList* list = GetOverflowOutOfFlows();
       return list ? *list : nsFrameList::EmptyList();
     }
     case kPushedFloatsList: {
       const nsFrameList* list = GetPushedFloats();
@@ -620,17 +618,16 @@ nsBlockFrame::GetChildLists(nsTArray<Chi
   if (list) {
     list->AppendIfNonempty(aLists, kOverflowOutOfFlowList);
   }
   mFloats.AppendIfNonempty(aLists, kFloatList);
   if (HaveOutsideBullet()) {
     nsFrameList bullet(mBullet, mBullet);
     bullet.AppendIfNonempty(aLists, kBulletList);
   }
-  mAbsoluteContainer.AppendChildList(aLists, kAbsoluteList);
   list = GetPushedFloats();
   if (list) {
     list->AppendIfNonempty(aLists, kPushedFloatsList);
   }
 }
 
 /* virtual */ bool
 nsBlockFrame::IsContainingBlock() const
@@ -1157,30 +1154,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();
     bool 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:
@@ -1194,22 +1192,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.
       bool 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, 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);
 
@@ -4677,17 +4675,17 @@ NS_IMETHODIMP
 nsBlockFrame::AppendFrames(ChildListID  aListID,
                            nsFrameList& aFrameList)
 {
   if (aFrameList.IsEmpty()) {
     return NS_OK;
   }
   if (aListID != kPrincipalList) {
     if (kAbsoluteList == aListID) {
-      return mAbsoluteContainer.AppendFrames(this, aListID, aFrameList);
+      return nsContainerFrame::AppendFrames(aListID, aFrameList);
     }
     else if (kFloatList == aListID) {
       mFloats.AppendFrames(nsnull, aFrameList);
       return NS_OK;
     }
     else {
       NS_ERROR("unexpected child list");
       return NS_ERROR_INVALID_ARG;
@@ -4725,18 +4723,17 @@ nsBlockFrame::InsertFrames(ChildListID a
                            nsIFrame* aPrevFrame,
                            nsFrameList& aFrameList)
 {
   NS_ASSERTION(!aPrevFrame || aPrevFrame->GetParent() == this,
                "inserting after sibling frame with different parent");
 
   if (aListID != kPrincipalList) {
     if (kAbsoluteList == aListID) {
-      return mAbsoluteContainer.InsertFrames(this, aListID, aPrevFrame,
-                                             aFrameList);
+      return nsContainerFrame::InsertFrames(aListID, aPrevFrame, aFrameList);
     }
     else if (kFloatList == aListID) {
       mFloats.InsertFrames(this, aPrevFrame, aFrameList);
       return NS_OK;
     }
 #ifdef IBMBIDI
     else if (kNoReflowPrincipalList == aListID) {}
 #endif // IBMBIDI
@@ -5009,17 +5006,17 @@ nsBlockFrame::RemoveFrame(ChildListID aL
   if (aListID == kPrincipalList) {
     bool hasFloats = BlockHasAnyFloats(aOldFrame);
     rv = DoRemoveFrame(aOldFrame, REMOVE_FIXED_CONTINUATIONS);
     if (hasFloats) {
       MarkSameFloatManagerLinesDirty(this);
     }
   }
   else if (kAbsoluteList == aListID) {
-    mAbsoluteContainer.RemoveFrame(this, aListID, aOldFrame);
+    nsContainerFrame::RemoveFrame(aListID, aOldFrame);
     return NS_OK;
   }
   else if (kFloatList == aListID) {
     // 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.");
@@ -5054,19 +5051,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,
-                                          kAbsoluteList,
-                                          aFrame);
+    block->GetAbsoluteContainingBlock()->RemoveFrame(block,
+                                                     kAbsoluteList,
+                                                     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);
     }
@@ -6184,18 +6181,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);
 
   // Prepare for text-overflow processing.
   nsAutoPtr<TextOverflow> textOverflow(
     TextOverflow::WillProcessLines(aBuilder, aLists, this));
 
   // 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.
@@ -6450,17 +6445,17 @@ nsBlockFrame::Init(nsIContent*      aCon
 
 NS_IMETHODIMP
 nsBlockFrame::SetInitialChildList(ChildListID     aListID,
                                   nsFrameList&    aChildList)
 {
   nsresult rv = NS_OK;
 
   if (kAbsoluteList == aListID) {
-    mAbsoluteContainer.SetInitialChildList(this, aListID, aChildList);
+    nsContainerFrame::SetInitialChildList(aListID, aChildList);
   }
   else if (kFloatList == aListID) {
     mFloats.SetFrames(aChildList);
   }
   else {
     nsPresContext* presContext = PresContext();
 
 #ifdef DEBUG
--- a/layout/generic/nsBlockFrame.h
+++ b/layout/generic/nsBlockFrame.h
@@ -329,17 +329,16 @@ public:
    */
   static nsBlockFrame* GetNearestAncestorBlock(nsIFrame* aCandidate);
   
 protected:
   nsBlockFrame(nsStyleContext* aContext)
     : nsHTMLContainerFrame(aContext)
     , mMinWidth(NS_INTRINSIC_WIDTH_UNKNOWN)
     , mPrefWidth(NS_INTRINSIC_WIDTH_UNKNOWN)
-    , mAbsoluteContainer(kAbsoluteList)
   {
 #ifdef DEBUG
   InitDebugFlags();
 #endif
   }
   virtual ~nsBlockFrame();
 
 #ifdef DEBUG
@@ -746,20 +745,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 bool gLamePaintMetrics;
   static bool gLameReflowMetrics;
   static bool gNoisy;
   static bool gNoisyDamageRepair;
   static bool gNoisyIntrinsic;
   static bool gNoisyReflow;
--- a/layout/generic/nsCanvasFrame.cpp
+++ b/layout/generic/nsCanvasFrame.cpp
@@ -47,48 +47,44 @@
 #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 "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);
 }
@@ -120,34 +116,30 @@ nsCanvasFrame::SetHasFocus(bool aHasFocu
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsCanvasFrame::SetInitialChildList(ChildListID     aListID,
                                    nsFrameList&    aChildList)
 {
-  if (kAbsoluteList == aListID)
-    return mAbsoluteContainer.SetInitialChildList(this, aListID, aChildList);
-
   NS_ASSERTION(aListID != kPrincipalList ||
                aChildList.IsEmpty() || aChildList.OnlyChild(),
                "Primary child list can have at most one frame in it");
   return nsHTMLContainerFrame::SetInitialChildList(aListID, aChildList);
 }
 
 NS_IMETHODIMP
 nsCanvasFrame::AppendFrames(ChildListID     aListID,
                             nsFrameList&    aFrameList)
 {
-  if (kAbsoluteList == aListID)
-    return mAbsoluteContainer.AppendFrames(this, aListID, aFrameList);
-
-  NS_ASSERTION(aListID == kPrincipalList, "unexpected child list ID");
-  NS_PRECONDITION(mFrames.IsEmpty(), "already have a child frame");
+  NS_ASSERTION(aListID == kPrincipalList ||
+               aListID == kAbsoluteList, "unexpected child list ID");
+  NS_PRECONDITION(aListID != kAbsoluteList ||
+                  mFrames.IsEmpty(), "already have a child frame");
   if (aListID != kPrincipalList) {
     // We only support the Principal and Absolute child lists.
     return NS_ERROR_INVALID_ARG;
   }
 
   if (!mFrames.IsEmpty()) {
     // We only allow a single principal child frame.
     return NS_ERROR_INVALID_ARG;
@@ -168,39 +160,32 @@ nsCanvasFrame::AppendFrames(ChildListID 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsCanvasFrame::InsertFrames(ChildListID     aListID,
                             nsIFrame*       aPrevFrame,
                             nsFrameList&    aFrameList)
 {
-  if (kAbsoluteList == aListID)
-    return mAbsoluteContainer.InsertFrames(this, aListID, 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(aListID, aFrameList);
 }
 
 NS_IMETHODIMP
 nsCanvasFrame::RemoveFrame(ChildListID     aListID,
                            nsIFrame*       aOldFrame)
 {
-  if (kAbsoluteList == aListID) {
-    mAbsoluteContainer.RemoveFrame(this, aListID, aOldFrame);
-    return NS_OK;
-  }
-
-  NS_ASSERTION(aListID == kPrincipalList, "unexpected child list ID");
-  if (aListID != kPrincipalList) {
+  NS_ASSERTION(aListID == kPrincipalList ||
+               aListID == kAbsoluteList, "unexpected child list ID");
+  if (aListID != kPrincipalList || aListID != kAbsoluteList) {
     // We only support the Principal and Absolute child lists.
     return NS_ERROR_INVALID_ARG;
   }
 
   if (aOldFrame != mFrames.FirstChild())
     return NS_ERROR_FAILURE;
 
   // It's our one and only child frame
@@ -213,32 +198,16 @@ nsCanvasFrame::RemoveFrame(ChildListID  
   mFrames.DestroyFrame(aOldFrame);
 
   PresContext()->PresShell()->
     FrameNeedsReflow(this, nsIPresShell::eTreeChange,
                      NS_FRAME_HAS_DIRTY_CHILDREN);
   return NS_OK;
 }
 
-nsFrameList
-nsCanvasFrame::GetChildList(ChildListID aListID) const
-{
-  if (kAbsoluteList == aListID)
-    return mAbsoluteContainer.GetChildList();
-
-  return nsHTMLContainerFrame::GetChildList(aListID);
-}
-
-void
-nsCanvasFrame::GetChildLists(nsTArray<ChildList>* aLists) const
-{
-  nsHTMLContainerFrame::GetChildLists(aLists);
-  mAbsoluteContainer.AppendChildList(aLists, kAbsoluteList);
-}
-
 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) {
@@ -307,19 +276,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)) { 
@@ -546,25 +512,16 @@ nsCanvasFrame::Reflow(nsPresContext*    
     } else {
       aDesiredSize.height = aReflowState.ComputedHeight();
     }
 
     aDesiredSize.SetOverflowAreasToDesiredBounds();
     aDesiredSize.mOverflowAreas.UnionWith(
       kidDesiredSize.mOverflowAreas + kidPt);
 
-    if (mAbsoluteContainer.HasAbsoluteFrames()) {
-      bool widthChanged = aDesiredSize.width != mRect.width;
-      bool 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*
@@ -595,17 +552,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(kAbsoluteList) {}
+    mAddedScrollPositionListener(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(ChildListID     aListID,
                           nsFrameList&    aFrameList);
   NS_IMETHOD InsertFrames(ChildListID     aListID,
                           nsIFrame*       aPrevFrame,
                           nsFrameList&    aFrameList);
   NS_IMETHOD RemoveFrame(ChildListID     aListID,
                          nsIFrame*       aOldFrame);
 
-  virtual nsFrameList GetChildList(ChildListID aListID) const;
-  virtual void GetChildLists(nsTArray<ChildList>* aLists) const;
-
   virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext);
   virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext);
   NS_IMETHOD Reflow(nsPresContext*          aPresContext,
                     nsHTMLReflowMetrics&     aDesiredSize,
                     const nsHTMLReflowState& aReflowState,
                     nsReflowStatus&          aStatus);
   virtual bool IsContainingBlock() const { return true; }
   virtual bool IsFrameOfType(PRUint32 aFlags) const
@@ -146,17 +141,16 @@ public:
   nsRect CanvasArea() const;
 
 protected:
   virtual PRIntn GetSkipSides() const;
 
   // Data members
   bool                      mDoPaintFocus;
   bool                      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
@@ -340,16 +340,17 @@ nsContainerFrame::GetChildLists(nsTArray
   ::AppendIfNonempty(this, propTable, OverflowProperty(),
                      aLists, kOverflowList);
   if (IsFrameOfType(nsIFrame::eCanContainOverflowContainers)) {
     ::AppendIfNonempty(this, propTable, OverflowContainersProperty(),
                        aLists, kOverflowContainersList);
     ::AppendIfNonempty(this, propTable, ExcessOverflowContainersProperty(),
                        aLists, kExcessOverflowContainersList);
   }
+  nsSplittableFrame::GetChildLists(aLists);
 }
 
 /////////////////////////////////////////////////////////////////////////////
 // Painting/Events
 
 NS_IMETHODIMP
 nsContainerFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                    const nsRect&           aDirtyRect,
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -1021,16 +1021,36 @@ nsFrame::GetBaseline() const
 {
   NS_ASSERTION(!NS_SUBTREE_DIRTY(this),
                "frame must not be dirty");
   // Default to the bottom margin edge, per CSS2.1's definition of the
   // 'baseline' value of 'vertical-align'.
   return mRect.height + GetUsedMargin().bottom;
 }
 
+nsFrameList
+nsFrame::GetChildList(ChildListID aListID) const
+{
+  if (IsAbsoluteContainer() &&
+      aListID == GetAbsoluteListID()) {
+    return GetAbsoluteContainingBlock()->GetChildList();
+  } else {
+    return nsFrameList::EmptyList();
+  }
+}
+
+void
+nsFrame::GetChildLists(nsTArray<ChildList>* aLists) const
+{
+  if (IsAbsoluteContainer()) {
+    nsFrameList absoluteList = GetAbsoluteContainingBlock()->GetChildList();
+    absoluteList.AppendIfNonempty(aLists, GetAbsoluteListID());
+  }
+}
+
 static nsIFrame*
 GetActiveSelectionFrame(nsPresContext* aPresContext, nsIFrame* aFrame)
 {
   nsIContent* capturingContent = nsIPresShell::GetCapturingContent();
   if (capturingContent) {
     nsIFrame* activeFrame = aPresContext->GetPrimaryFrameFor(capturingContent);
     return activeFrame ? activeFrame : aFrame;
   }
@@ -1591,16 +1611,19 @@ nsIFrame::BuildDisplayListForStackingCon
   }
 
   bool usingSVGEffects = nsSVGIntegrationUtils::UsingEffectsForFrame(this);
   if (usingSVGEffects) {
     dirtyRect =
       nsSVGIntegrationUtils::GetRequiredSourceForInvalidArea(this, dirtyRect);
   }
 
+  // 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);
   }
@@ -1751,17 +1774,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
   bool 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() ||
@@ -1797,19 +1820,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
@@ -1964,16 +1993,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.
@@ -3710,16 +3748,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
@@ -3730,16 +3769,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,
+                              true, true, true, // XXX could be optimized
+                              &aDesiredSize.mOverflowAreas);
+  }
+}
+
 /* virtual */ bool
 nsFrame::CanContinueTextRun() const
 {
   // By default, a frame will *not* allow a text run to be continued
   // through it.
   return PR_FALSE;
 }
 
@@ -6344,18 +6432,17 @@ nsIFrame::SetOverflowAreas(const nsOverf
     *overflow = aOverflowAreas;
   }
 }
 
 inline bool
 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);
 
@@ -8069,17 +8156,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
@@ -185,20 +185,18 @@ public:
   NS_IMETHOD  RemoveFrame(ChildListID     aListID,
                           nsIFrame*       aOldFrame);
   virtual void DestroyFrom(nsIFrame* aDestructRoot);
   virtual nsStyleContext* GetAdditionalStyleContext(PRInt32 aIndex) const;
   virtual void SetAdditionalStyleContext(PRInt32 aIndex,
                                          nsStyleContext* aStyleContext);
   virtual void SetParent(nsIFrame* aParent);
   virtual nscoord GetBaseline() const;
-  virtual nsFrameList GetChildList(ChildListID aListID) const {
-    return nsFrameList::EmptyList();
-  }
-  virtual void GetChildLists(nsTArray<ChildList>* aLists) const {}
+  virtual nsFrameList GetChildList(ChildListID aListID) const;
+  virtual void GetChildLists(nsTArray<ChildList>* aLists) const;
 
   NS_IMETHOD  HandleEvent(nsPresContext* aPresContext, 
                           nsGUIEvent*     aEvent,
                           nsEventStatus*  aEventStatus);
   NS_IMETHOD  GetContentForEvent(nsEvent* aEvent,
                                  nsIContent** aContent);
   NS_IMETHOD  GetCursor(const nsPoint&    aPoint,
                         nsIFrame::Cursor& aCursor);
@@ -334,16 +332,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 bool 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
@@ -1568,17 +1568,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
@@ -588,16 +588,18 @@ public:
    * has been initialized.
    *
    * 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   aListID the child list identifier.
    * @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
+   *            GetAbsoluteListID().
    * @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()
@@ -2743,16 +2745,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.
     bool 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 */ bool
@@ -913,16 +914,23 @@ nsInlineFrame::GetSkipSides() const
 }
 
 nscoord
 nsInlineFrame::GetBaseline() const
 {
   return mBaseline;
 }
 
+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 || 
@@ -1092,16 +1100,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()
 {
@@ -1112,165 +1122,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(ChildListID     aListID,
-                                             nsFrameList&    aChildList)
-{
-  nsresult  rv;
-
-  if (kAbsoluteList == aListID) {
-    rv = mAbsoluteContainer.SetInitialChildList(this, aListID, aChildList);
-  } else {
-    rv = nsInlineFrame::SetInitialChildList(aListID, aChildList);
-  }
-
-  return rv;
-}
-
-NS_IMETHODIMP
-nsPositionedInlineFrame::AppendFrames(ChildListID     aListID,
-                                      nsFrameList&    aFrameList)
-{
-  nsresult  rv;
-  
-  if (kAbsoluteList == aListID) {
-    rv = mAbsoluteContainer.AppendFrames(this, aListID, aFrameList);
-  } else {
-    rv = nsInlineFrame::AppendFrames(aListID, aFrameList);
-  }
-
-  return rv;
-}
-  
-NS_IMETHODIMP
-nsPositionedInlineFrame::InsertFrames(ChildListID     aListID,
-                                      nsIFrame*       aPrevFrame,
-                                      nsFrameList&    aFrameList)
-{
-  nsresult  rv;
-
-  if (kAbsoluteList == aListID) {
-    rv = mAbsoluteContainer.InsertFrames(this, aListID, aPrevFrame,
-                                         aFrameList);
-  } else {
-    rv = nsInlineFrame::InsertFrames(aListID, aPrevFrame, aFrameList);
-  }
-
-  return rv;
-}
-  
-NS_IMETHODIMP
-nsPositionedInlineFrame::RemoveFrame(ChildListID     aListID,
-                                     nsIFrame*       aOldFrame)
-{
-  nsresult  rv;
-
-  if (kAbsoluteList == aListID) {
-    mAbsoluteContainer.RemoveFrame(this, aListID, aOldFrame);
-    rv = NS_OK;
-  } else {
-    rv = nsInlineFrame::RemoveFrame(aListID, 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);
-}
-
-nsFrameList
-nsPositionedInlineFrame::GetChildList(ChildListID aListID) const
-{
-  if (kAbsoluteList == aListID)
-    return mAbsoluteContainer.GetChildList();
-
-  return nsInlineFrame::GetChildList(aListID);
-}
-
-void
-nsPositionedInlineFrame::GetChildLists(nsTArray<ChildList>* aLists) const
-{
-  nsInlineFrame::GetChildLists(aLists);
-  mAbsoluteContainer.AppendChildList(aLists, kAbsoluteList);
-}
-
-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 bool IsEmpty();
   virtual bool IsSelfEmpty();
 
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
+
   virtual bool PeekOffsetCharacter(bool aForward, PRInt32* aOffset,
                                      bool aRespectClusters = true);
   
   // nsIHTMLReflow overrides
   virtual void AddInlineMinWidth(nsRenderingContext *aRenderingContext,
                                  InlineMinWidthData *aData);
   virtual void AddInlinePrefWidth(nsRenderingContext *aRenderingContext,
                                   InlinePrefWidthData *aData);
@@ -224,57 +225,9 @@ public:
 protected:
   nsFirstLineFrame(nsStyleContext* aContext) : nsInlineFrame(aContext) {}
 
   virtual nsIFrame* PullOneFrame(nsPresContext* aPresContext,
                                  InlineReflowState& rs,
                                  bool* 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(kAbsoluteList)
-  {}
-
-  virtual ~nsPositionedInlineFrame() { } // useful for debugging
-
-  virtual void DestroyFrom(nsIFrame* aDestructRoot);
-
-  NS_IMETHOD SetInitialChildList(ChildListID  aListID,
-                                 nsFrameList& aChildList);
-  NS_IMETHOD AppendFrames(ChildListID  aListID,
-                          nsFrameList& aFrameList);
-  NS_IMETHOD InsertFrames(ChildListID  aListID,
-                          nsIFrame*    aPrevFrame,
-                          nsFrameList& aFrameList);
-  NS_IMETHOD RemoveFrame(ChildListID aListID,
-                         nsIFrame*   aOldFrame);
-
-  NS_IMETHOD BuildDisplayList(nsDisplayListBuilder*   aBuilder,
-                              const nsRect&           aDirtyRect,
-                              const nsDisplayListSet& aLists);
-
-  virtual nsFrameList GetChildList(ChildListID aListID) const;
-  virtual void GetChildLists(nsTArray<ChildList>* aLists) 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
@@ -659,18 +659,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
@@ -177,17 +177,16 @@ public:
     nsMenuFrame_id,
     nsMenuPopupFrame_id,
     nsObjectFrame_id,
     nsPageBreakFrame_id,
     nsPageContentFrame_id,
     nsPageFrame_id,
     nsPlaceholderFrame_id,
     nsPopupSetFrame_id,
-    nsPositionedInlineFrame_id,
     nsProgressFrame_id,
     nsProgressMeterFrame_id,
     nsResizerFrame_id,
     nsRootBoxFrame_id,
     nsScrollbarButtonFrame_id,
     nsScrollbarFrame_id,
     nsSelectsAreaFrame_id,
     nsSimplePageSequenceFrame_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,159 +65,100 @@ 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(ChildListID     aListID,
                                    nsFrameList&    aChildList)
 {
-  nsresult rv = NS_OK;
-
   // See which child list to add the frames to
 #ifdef NS_DEBUG
   nsFrame::VerifyDirtyBitSet(aChildList);
 #endif
-  if (kFixedList == aListID) {
-    rv = mFixedContainer.SetInitialChildList(this, aListID, aChildList);
-  } 
-  else {
-    rv = nsContainerFrame::SetInitialChildList(aListID, aChildList);
-  }
-
-  return rv;
+  return nsContainerFrame::SetInitialChildList(aListID, 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(ChildListID     aListID,
                             nsFrameList&    aFrameList)
 {
-  nsresult rv = NS_OK;
-
-  if (kFixedList == aListID) {
-    rv = mFixedContainer.AppendFrames(this, aListID, aFrameList);
-  }
-  else {
-    NS_ASSERTION(aListID == kPrincipalList, "unexpected child list");
-    NS_ASSERTION(GetChildList(aListID).IsEmpty(), "Shouldn't have any kids!");
-    rv = nsContainerFrame::AppendFrames(aListID, aFrameList);
-  }
-
-  return rv;
+  NS_ASSERTION(aListID == kPrincipalList ||
+               aListID == GetAbsoluteListID(), "unexpected child list");
+  NS_ASSERTION(aListID != GetAbsoluteListID() ||
+               GetChildList(aListID).IsEmpty(), "Shouldn't have any kids!");
+  return nsContainerFrame::AppendFrames(aListID, aFrameList);
 }
 
 NS_IMETHODIMP
 ViewportFrame::InsertFrames(ChildListID     aListID,
                             nsIFrame*       aPrevFrame,
                             nsFrameList&    aFrameList)
 {
-  nsresult rv = NS_OK;
-
-  if (kFixedList == aListID) {
-    rv = mFixedContainer.InsertFrames(this, aListID, aPrevFrame, aFrameList);
-  }
-  else {
-    NS_ASSERTION(aListID == kPrincipalList, "unexpected child list");
-    NS_ASSERTION(GetChildList(aListID).IsEmpty(), "Shouldn't have any kids!");
-    rv = nsContainerFrame::InsertFrames(aListID, aPrevFrame, aFrameList);
-  }
-
-  return rv;
+  NS_ASSERTION(aListID == kPrincipalList ||
+               aListID == GetAbsoluteListID(), "unexpected child list");
+  NS_ASSERTION(aListID != GetAbsoluteListID() ||
+               GetChildList(aListID).IsEmpty(), "Shouldn't have any kids!");
+  return nsContainerFrame::InsertFrames(aListID, aPrevFrame, aFrameList);
 }
 
 NS_IMETHODIMP
 ViewportFrame::RemoveFrame(ChildListID     aListID,
                            nsIFrame*       aOldFrame)
 {
-  nsresult rv = NS_OK;
-
-  if (kFixedList == aListID) {
-    mFixedContainer.RemoveFrame(this, aListID, aOldFrame);
-    rv = NS_OK;
-  }
-  else {
-    NS_ASSERTION(aListID == kPrincipalList, "unexpected child list");
-    rv = nsContainerFrame::RemoveFrame(aListID, aOldFrame);
-  }
-
-  return rv;
-}
-
-nsFrameList
-ViewportFrame::GetChildList(ChildListID aListID) const
-{
-  if (kFixedList == aListID)
-    return mFixedContainer.GetChildList();
-
-  return nsContainerFrame::GetChildList(aListID);
-}
-
-void
-ViewportFrame::GetChildLists(nsTArray<ChildList>* aLists) const
-{
-  nsContainerFrame::GetChildLists(aLists);
-  mFixedContainer.AppendChildList(aLists, kFixedList);
+  NS_ASSERTION(aListID == kPrincipalList ||
+               aListID == GetAbsoluteListID(), "unexpected child list");
+  return nsContainerFrame::RemoveFrame(aListID, 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
@@ -304,30 +246,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(),
+                                              false, true, 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(kFixedList)
   {}
   virtual ~ViewportFrame() { } // useful for debugging
 
   virtual void DestroyFrom(nsIFrame* aDestructRoot);
 
   NS_IMETHOD Init(nsIContent*      aContent,
                   nsIFrame*        aParent,
                   nsIFrame*        asPrevInFlow);
@@ -81,19 +78,16 @@ public:
 
   NS_IMETHOD InsertFrames(ChildListID     aListID,
                           nsIFrame*       aPrevFrame,
                           nsFrameList&    aFrameList);
 
   NS_IMETHOD RemoveFrame(ChildListID     aListID,
                          nsIFrame*       aOldFrame);
 
-  virtual nsFrameList GetChildList(ChildListID aListID) const;
-  virtual void GetChildLists(nsTArray<ChildList>* aLists) 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,
@@ -113,20 +107,16 @@ public:
                                   nscoord aX, nscoord aY, nsIFrame* aForChild,
                                   PRUint32 aFlags);
 
 #ifdef DEBUG
   NS_IMETHOD GetFrameName(nsAString& aResult) const;
 #endif
 
 private:
-  virtual mozilla::layout::FrameChildListID GetAbsoluteListName() const { return kFixedList; }
+  virtual mozilla::layout::FrameChildListID GetAbsoluteListID() const { return kFixedList; }
 
 protected:
   nsPoint AdjustReflowStateForScrollbars(nsHTMLReflowState* aReflowState) const;
-
-  // position: fixed content is really content which is absolutely positioned with
-  // respect to the viewport.
-  nsAbsoluteContainingBlock mFixedContainer;
 };
 
 
 #endif // nsViewportFrame_h___
--- a/layout/tables/nsTableOuterFrame.cpp
+++ b/layout/tables/nsTableOuterFrame.cpp
@@ -210,29 +210,27 @@ nsTableOuterFrame::DestroyFrom(nsIFrame*
 {
   mCaptionFrames.DestroyFramesFrom(aDestructRoot);
   nsHTMLContainerFrame::DestroyFrom(aDestructRoot);
 }
 
 nsFrameList
 nsTableOuterFrame::GetChildList(ChildListID aListID) const
 {
-  switch (aListID) {
-    case kPrincipalList:
-      return mFrames;
-    case kCaptionList:
-      return mCaptionFrames;
-    default:
-      return nsFrameList::EmptyList();
+  if (aListID == kCaptionList) {
+    return mCaptionFrames;
   }
+
+  return nsHTMLContainerFrame::GetChildList(aListID);
 }
 
 void
 nsTableOuterFrame::GetChildLists(nsTArray<ChildList>* aLists) const
 {
+  nsHTMLContainerFrame::GetChildLists(aLists);
   mFrames.AppendIfNonempty(aLists, kPrincipalList);
   mCaptionFrames.AppendIfNonempty(aLists, kCaptionList);
 }
 
 NS_IMETHODIMP 
 nsTableOuterFrame::SetInitialChildList(ChildListID     aListID,
                                        nsFrameList&    aChildList)
 {