--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -928,16 +928,21 @@ public:
nsContainerFrame* aFloatContainingBlock);
~nsFrameConstructorState();
bool HasAncestorFilter()
{
return mTreeMatchContext && mTreeMatchContext->mAncestorFilter.HasFilter();
}
+
+ // xxxNeerja - write comment
+ void OverwriteAbsoluteState(nsContainerFrame* aNewAbsoluteContainingBlock,
+ nsFrameList& aSplitAbsoluteList,
+ nsFrameConstructorSaveState& aAbsoluteSaveState);
// Function to push the existing absolute containing block state and
// create a new scope. Code that uses this function should get matching
// logic in GetAbsoluteContainingBlock.
// Also makes aNewAbsoluteContainingBlock the containing block for
// fixed-pos elements if necessary.
// aPositionedFrame is the frame whose style actually makes
// aNewAbsoluteContainingBlock a containing block. E.g. for a scrollable element
@@ -1001,17 +1006,21 @@ public:
nsAbsoluteItems& GetFixedItems()
{
return mFixedPosIsAbsPos ? mAbsoluteItems : mFixedItems;
}
const nsAbsoluteItems& GetFixedItems() const
{
return mFixedPosIsAbsPos ? mAbsoluteItems : mFixedItems;
}
-
+
+ nsAbsoluteItems& GetAbsoluteItems()
+ {
+ return mAbsoluteItems;
+ }
/**
* class to automatically push and pop a pending binding in the frame
* constructor state. See nsCSSFrameConstructor::FrameConstructionItem
* mPendingBinding documentation.
*/
class PendingBindingAutoPusher;
friend class PendingBindingAutoPusher;
@@ -1170,16 +1179,55 @@ AdjustAbsoluteContainingBlock(nsContaine
}
// Always use the container's first continuation. (Inline frames can have
// non-fluid bidi continuations...)
return static_cast<nsContainerFrame*>(aContainingBlockIn->FirstContinuation());
}
void
+nsFrameConstructorState::OverwriteAbsoluteState(nsContainerFrame* aNewAbsoluteContainingBlock,
+ nsFrameList& aSplitAbsoluteList,
+ nsFrameConstructorSaveState& aSaveState)
+{
+ // First overwrite the original state and then save it in aSaveState
+ mAbsoluteItems = nsAbsoluteItems(AdjustAbsoluteContainingBlock(aNewAbsoluteContainingBlock));
+ while (aSplitAbsoluteList.NotEmpty()) {
+ mAbsoluteItems.AddChild(aSplitAbsoluteList.RemoveFirstChild());
+ }
+//
+// /* See if we're wiring the fixed-pos and abs-pos lists together. This happens iff
+// * we're a transformed element.
+// */
+// mFixedPosIsAbsPos = aNewAbsoluteContainingBlock &&
+// aNewAbsoluteContainingBlock->IsFixedPosContainingBlock();
+//
+// if (aNewAbsoluteContainingBlock) {
+// aNewAbsoluteContainingBlock->MarkAsAbsoluteContainingBlock();
+// }
+//
+// aSaveState.mItems->containingBlock = AdjustAbsoluteContainingBlock(aNewAbsoluteContainingBlock);
+// while (aSplitAbsoluteList.NotEmpty()) {
+// aSaveState.mItems->AddChild(aSplitAbsoluteList.RemoveFirstChild());
+// }
+// aSaveState.mSavedItems = aSaveState.mItems;
+// aSaveState.mChildListID = nsIFrame::kAbsoluteList;
+// aSaveState.mState = this;
+// aSaveState.mSavedFixedPosIsAbsPos = aNewAbsoluteContainingBlock &&
+// aNewAbsoluteContainingBlock->IsFixedPosContainingBlock();;
+
+ //xxxNeerja - Do we need to do this?
+// if (mFixedPosIsAbsPos) {
+// aSaveState.mSavedFixedItems = mFixedItems;
+// mFixedItems = mAbsoluteItems;
+// }
+
+}
+
+void
nsFrameConstructorState::PushAbsoluteContainingBlock(nsContainerFrame* aNewAbsoluteContainingBlock,
nsIFrame* aPositionedFrame,
nsFrameConstructorSaveState& aSaveState)
{
aSaveState.mItems = &mAbsoluteItems;
aSaveState.mSavedItems = mAbsoluteItems;
aSaveState.mChildListID = nsIFrame::kAbsoluteList;
aSaveState.mState = this;
@@ -12360,60 +12408,54 @@ ProcessColumnSpan(nsFrameConstructorStat
if ((*aNewFrame)->Type() != LayoutFrameType::ColumnSetWrapper) {
MOZ_ASSERT(grandParent->Type() != LayoutFrameType::ColumnSetWrapper,
"Grandparent cannot be columnSetWrapper! In that case newFrame==gparent");
nsFrameItems splitChildren;
SplitBlocks(aState, aOldParent, aChildItems, splitChildren);
MOZ_ASSERT(splitChildren.NotEmpty(), "Child items cannot be empty here!");
- // Clean up the aOldParent and its placeholder, if present
aFrameItems.RemoveFrame(aOldParent);
//aOldParent is guaranteed to be a block here
nsBlockFrame* oldBlockParent = static_cast<nsBlockFrame*>(aOldParent);
oldBlockParent->TransferFloats();
- aOldParent->Destroy();
-
+
*aNewFrame = static_cast<nsContainerFrame*>(splitChildren.FirstChild());
while (splitChildren.NotEmpty()) {
nsContainerFrame* currChild =
static_cast<nsContainerFrame*>(splitChildren.RemoveFirstChild());
aState.AddChild(currChild, aFrameItems, content, styleContext, aFinalParent);
-
- // We should make the outer frame be the absolute containing block,
- // if one is required. We have to do this because absolute
- // positioning must be computed with respect to the CSS dimensions
- // of the element, which are the dimensions of the outer block. But
- // we can't really do that because only blocks can have absolute
- // children. So use the block and try to compensate with hacks
- // in nsBlockFrame::CalculateContainingBlockSizeForAbsolutes.
- nsFrameConstructorSaveState absoluteSaveState;
- currChild->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
- if (aPositionedFrameForAbsPosContainer) {
- aState.PushAbsoluteContainingBlock(currChild,
- aPositionedFrameForAbsPosContainer,
- absoluteSaveState);
+
+ if (aPositionedFrameForAbsPosContainer &&
+ aPositionedFrameForAbsPosContainer == aOldParent) {
+ nsFrameList splitAbsoluteList;
+ SplitAbsoluteListForSplitBlock(currChild, aState.GetAbsoluteItems(), splitAbsoluteList);
+ nsFrameConstructorSaveState absoluteSaveState;
+ currChild->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
+ aState.OverwriteAbsoluteState(currChild, splitAbsoluteList, absoluteSaveState);
+ aState.PushAbsoluteContainingBlock(currChild, currChild, absoluteSaveState);
}
}
} else {
nsFrameItems finalChildItems;
WrapNonSpannerChildrenInColumnSets(aState, aOldParent, aChildItems,
finalChildItems);
MOZ_ASSERT(finalChildItems.NotEmpty(), "Child items cannot be empty here!");
// aOldParent is guaranteed to be a block here
nsBlockFrame* oldBlockParent = static_cast<nsBlockFrame*>(aOldParent);
oldBlockParent->TransferFloats();
MoveChildrenTo(aOldParent, grandParent, finalChildItems);
// Clean up the aOldParent
// Note: In this case aOldParent was never added to aFrameItems
- aOldParent->Destroy();
- }
+ //aOldParent->Destroy();
+ }
+ aOldParent->Destroy();
}
void
nsCSSFrameConstructor::SplitBlocks(nsFrameConstructorState& aState,
nsContainerFrame* aOldParent,
nsFrameList& aUnsplitChildItems,
nsFrameItems& aSplitChildItems,
nsStyleContext* aNonSpannerSC)
@@ -12521,16 +12563,44 @@ WrapNonSpannerChildrenInColumnSets(nsFra
}
// Note: Because of this function, column-span wrappers and ColumnSetFrame
// wrappers are not ib-siblings of each other since we create columnSetFrames
// as one additional wrapper around non-spanning elements and this would upset
// the IB-sibling chain.
}
+void
+nsCSSFrameConstructor::SplitAbsoluteListForSplitBlock(nsContainerFrame* aSplitFrame,
+ nsAbsoluteItems& aOriginalAbsoluteList,
+ nsFrameList& aSplitAbsoluteList)
+{
+ for (nsIFrame* currAbsoluteFrame = aOriginalAbsoluteList.FirstChild(); currAbsoluteFrame != nullptr;) {
+ nsIFrame* placeholder = currAbsoluteFrame->GetPlaceholderFrame();
+ if (placeholder) {
+ // Check if this placeholder is a descendent of aSplitFrame, if it is then move its OOF
+ // into the splitAbsoluteList
+ nsIFrame* parent = placeholder->GetParent();
+ while (parent && parent != aSplitFrame) {
+ parent = parent->GetParent();
+ }
+ if (parent) {
+ nsIFrame* nextAbsoluteFrame = currAbsoluteFrame->GetNextSibling();
+ aOriginalAbsoluteList.RemoveFrame(currAbsoluteFrame);
+
+ // xxxNeerja - Do I need to reparent these absolute frames??
+ aSplitAbsoluteList.AppendFrame(nullptr, currAbsoluteFrame);
+ currAbsoluteFrame = nextAbsoluteFrame;
+ }
+ } else {
+ NS_WARNING("An OOF exists with a null placeholder!");
+ }
+ }
+}
+
nsIFrame*
nsCSSFrameConstructor::ConstructInline(nsFrameConstructorState& aState,
FrameConstructionItem& aItem,
nsContainerFrame* aParentFrame,
const nsStyleDisplay* aDisplay,
nsFrameItems& aFrameItems)
{
// If an inline frame has non-inline kids, then we chop up the child list
--- a/layout/base/nsCSSFrameConstructor.h
+++ b/layout/base/nsCSSFrameConstructor.h
@@ -34,16 +34,17 @@ struct nsGenConInitializer;
class nsContainerFrame;
class nsFirstLineFrame;
class nsFirstLetterFrame;
class nsICSSAnonBoxPseudo;
class nsIDocument;
class nsPageContentFrame;
struct PendingBinding;
class nsGenericDOMDataNode;
+struct nsAbsoluteItems;
class nsFrameConstructorState;
namespace mozilla {
namespace dom {
class FlattenedChildIterator;
@@ -1962,16 +1963,20 @@ private:
* Create ColumnSetFrames around any consecutive non-spanning elements
* present in aInitialChildItems. Let the spanning items stay as is and return
* this new list in aFinalChildItems.
*/
void WrapNonSpannerChildrenInColumnSets(nsFrameConstructorState& aState,
nsContainerFrame* aOldParent,
nsFrameItems& aInitialChildItems,
nsFrameItems& aFinalChildItems);
+
+ void SplitAbsoluteListForSplitBlock(nsContainerFrame* aSplitFrame,
+ nsAbsoluteItems& aOriginalAbsoluteList,
+ nsFrameList& aSplitAbsoluteList);
// |aContentParentFrame| should be null if it's really the same as
// |aParentFrame|.
// @param aFrameItems where we want to put the block in case it's in-flow.
// @param aNewFrame an in/out parameter. On input it is the block to be
// constructed. On output it is reset to the outermost
// frame constructed (e.g. if we need to wrap the block in an
// nsColumnSetFrame.
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -5701,18 +5701,17 @@ nsBlockFrame::TransferFloats()
currFloat->SetParent(finalBlockParent);
nsFrameList temp(currFloat, currFloat);
finalBlockParent->AppendFrames(nsIFrame::kFloatList, temp);
currFloat = nextFloat;
if (nextFloat) {
nextFloat = nextFloat->GetNextSibling();
}
- }
- else {
+ } else {
NS_WARNING("An OOF exists with a null placeholder!");
}
}
}
static nsIFrame*
FindChildContaining(nsBlockFrame* aFrame, nsIFrame* aFindFrame)
{