--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -753,21 +753,23 @@ public:
// Frames destined for the kPopupList.
nsAbsoluteItems mPopupItems;
#endif
// Containing block information for out-of-flow frames.
nsAbsoluteItems mFixedItems;
nsAbsoluteItems mAbsoluteItems;
nsAbsoluteItems mFloatedItems;
- // Items in the top layer are always fixed positioned children of the
- // viewport frame. It differs from mFixedItems that the items here
- // should not be caught by any other fixed-pos containing block like
- // frames with transform or filter.
- nsAbsoluteItems mTopLayerItems;
+ // The containing block of a frame in the top layer is defined by the
+ // spec: fixed-positioned frames are children of the viewport frame,
+ // and absolutely-positioned frames are children of the initial
+ // containing block. They would not be caught by any other containing
+ // block, e.g. frames with transform or filter.
+ nsAbsoluteItems mTopLayerFixedItems;
+ nsAbsoluteItems mTopLayerAbsoluteItems;
nsCOMPtr<nsILayoutHistoryState> mFrameState;
// These bits will be added to the state bits of any frame we construct
// using this state.
nsFrameState mAdditionalStateBits;
// When working with the transform and filter properties, we want to hook
// the abs-pos and fixed-pos lists together, since such
@@ -943,16 +945,18 @@ protected:
* whether the returned list really has a containing block.
*/
nsAbsoluteItems* GetOutOfFlowFrameItems(nsIFrame* aNewFrame,
bool aCanBePositioned,
bool aCanBeFloated,
bool aIsOutOfFlowPopup,
nsFrameState* aPlaceholderType);
+ void ConstructBackdropFrameFor(nsIContent* aContent, nsIFrame* aFrame);
+
// Our list of all pending bindings. When we're done, we need to call
// AddToAttachedQueue on all of them, in order.
LinkedList<PendingBinding> mPendingBindings;
PendingBinding* mCurrentPendingBindingInsertionPoint;
};
nsFrameConstructorState::nsFrameConstructorState(
@@ -965,17 +969,20 @@ nsFrameConstructorState::nsFrameConstruc
mPresShell(aPresShell),
mFrameManager(aPresShell->FrameManager()),
#ifdef MOZ_XUL
mPopupItems(nullptr),
#endif
mFixedItems(aFixedContainingBlock),
mAbsoluteItems(aAbsoluteContainingBlock),
mFloatedItems(aFloatContainingBlock),
- mTopLayerItems(do_QueryFrame(mFrameManager->GetRootFrame())),
+ mTopLayerFixedItems(
+ static_cast<nsContainerFrame*>(mFrameManager->GetRootFrame())),
+ mTopLayerAbsoluteItems(
+ aPresShell->FrameConstructor()->GetDocElementContainingBlock()),
// See PushAbsoluteContaningBlock below
mFrameState(aHistoryState),
mAdditionalStateBits(nsFrameState(0)),
// If the fixed-pos containing block is equal to the abs-pos containing
// block, use the abs-pos containing block's abs-pos list for fixed-pos
// frames.
mFixedPosIsAbsPos(aFixedContainingBlock == aAbsoluteContainingBlock),
mHavePendingPopupgroup(false),
@@ -1002,18 +1009,18 @@ nsFrameConstructorState::nsFrameConstruc
aFloatContainingBlock,
aPresShell->GetDocument()->GetLayoutHistoryState())
{
}
nsFrameConstructorState::~nsFrameConstructorState()
{
MOZ_COUNT_DTOR(nsFrameConstructorState);
- // Items in the top layer are fixed positioned children of the viewport frame.
- ProcessFrameInsertions(mTopLayerItems, nsIFrame::kFixedList);
+ ProcessFrameInsertions(mTopLayerFixedItems, nsIFrame::kFixedList);
+ ProcessFrameInsertions(mTopLayerAbsoluteItems, nsIFrame::kAbsoluteList);
ProcessFrameInsertions(mFloatedItems, nsIFrame::kFloatList);
ProcessFrameInsertions(mAbsoluteItems, nsIFrame::kAbsoluteList);
ProcessFrameInsertions(mFixedItems, nsIFrame::kFixedList);
#ifdef MOZ_XUL
ProcessFrameInsertions(mPopupItems, nsIFrame::kPopupList);
#endif
for (int32_t i = mGeneratedTextNodesWithInitializer.Count() - 1; i >= 0; --i) {
mGeneratedTextNodesWithInitializer[i]->
@@ -1122,20 +1129,25 @@ nsFrameConstructorState::GetGeometricPar
NS_ASSERTION(!aStyleDisplay->IsAbsolutelyPositionedStyle(),
"Absolutely positioned _and_ floating?");
return mFloatedItems.containingBlock;
}
if (aStyleDisplay->mTopLayer != NS_STYLE_TOP_LAYER_NONE) {
MOZ_ASSERT(aStyleDisplay->mTopLayer == NS_STYLE_TOP_LAYER_TOP,
"-moz-top-layer should be either none or top");
- MOZ_ASSERT(mTopLayerItems.containingBlock, "No root frame?");
MOZ_ASSERT(aStyleDisplay->IsAbsolutelyPositionedStyle(),
"Top layer items should always be absolutely positioned");
- return mTopLayerItems.containingBlock;
+ if (aStyleDisplay->mPosition == NS_STYLE_POSITION_FIXED) {
+ MOZ_ASSERT(mTopLayerFixedItems.containingBlock, "No root frame?");
+ return mTopLayerFixedItems.containingBlock;
+ }
+ MOZ_ASSERT(aStyleDisplay->mPosition == NS_STYLE_POSITION_ABSOLUTE);
+ MOZ_ASSERT(mTopLayerAbsoluteItems.containingBlock);
+ return mTopLayerAbsoluteItems.containingBlock;
}
if (aStyleDisplay->mPosition == NS_STYLE_POSITION_ABSOLUTE &&
mAbsoluteItems.containingBlock) {
return mAbsoluteItems.containingBlock;
}
if (aStyleDisplay->mPosition == NS_STYLE_POSITION_FIXED &&
@@ -1164,31 +1176,73 @@ nsFrameConstructorState::GetOutOfFlowFra
*aPlaceholderType = PLACEHOLDER_FOR_FLOAT;
return &mFloatedItems;
}
if (aCanBePositioned) {
const nsStyleDisplay* disp = aNewFrame->StyleDisplay();
if (disp->mTopLayer != NS_STYLE_TOP_LAYER_NONE) {
*aPlaceholderType = PLACEHOLDER_FOR_TOPLAYER;
- return &mTopLayerItems;
+ if (disp->mPosition == NS_STYLE_POSITION_FIXED) {
+ return &mTopLayerFixedItems;
+ }
+ return &mTopLayerAbsoluteItems;
}
if (disp->mPosition == NS_STYLE_POSITION_ABSOLUTE) {
*aPlaceholderType = PLACEHOLDER_FOR_ABSPOS;
return &mAbsoluteItems;
}
if (disp->mPosition == NS_STYLE_POSITION_FIXED) {
*aPlaceholderType = PLACEHOLDER_FOR_FIXEDPOS;
return &GetFixedItems();
}
}
return nullptr;
}
void
+nsFrameConstructorState::ConstructBackdropFrameFor(nsIContent* aContent,
+ nsIFrame* aFrame)
+{
+ MOZ_ASSERT(aFrame->StyleDisplay()->mTopLayer == NS_STYLE_TOP_LAYER_TOP);
+ nsContainerFrame* frame = do_QueryFrame(aFrame);
+ if (!frame) {
+ NS_WARNING("Cannot create backdrop frame for non-container frame");
+ return;
+ }
+
+ RefPtr<nsStyleContext> style = mPresShell->StyleSet()->
+ ResolvePseudoElementStyle(aContent->AsElement(),
+ CSSPseudoElementType::backdrop,
+ /* aParentStyleContext */ nullptr,
+ /* aPseudoElement */ nullptr);
+ MOZ_ASSERT(style->StyleDisplay()->mTopLayer == NS_STYLE_TOP_LAYER_TOP);
+ nsContainerFrame* parentFrame =
+ GetGeometricParent(style->StyleDisplay(), nullptr);
+
+ nsBackdropFrame* backdropFrame = new (mPresShell) nsBackdropFrame(style);
+ backdropFrame->Init(aContent, parentFrame, nullptr);
+
+ nsFrameState placeholderType;
+ nsAbsoluteItems* frameItems = GetOutOfFlowFrameItems(backdropFrame,
+ true, true, false,
+ &placeholderType);
+ MOZ_ASSERT(placeholderType == PLACEHOLDER_FOR_TOPLAYER);
+
+ nsIFrame* placeholder = nsCSSFrameConstructor::
+ CreatePlaceholderFrameFor(mPresShell, aContent, backdropFrame,
+ frame->StyleContext(), frame, nullptr,
+ PLACEHOLDER_FOR_TOPLAYER);
+ nsFrameList temp(placeholder, placeholder);
+ frame->SetInitialChildList(nsIFrame::kBackdropList, temp);
+
+ frameItems->AddChild(backdropFrame);
+}
+
+void
nsFrameConstructorState::AddChild(nsIFrame* aNewFrame,
nsFrameItems& aFrameItems,
nsIContent* aContent,
nsStyleContext* aStyleContext,
nsContainerFrame* aParentFrame,
bool aCanBePositioned,
bool aCanBeFloated,
bool aIsOutOfFlowPopup,
@@ -1228,22 +1282,17 @@ nsFrameConstructorState::AddChild(nsIFra
nullptr,
placeholderType);
placeholderFrame->AddStateBits(mAdditionalStateBits);
// Add the placeholder frame to the flow
aFrameItems.AddChild(placeholderFrame);
if (placeholderType == PLACEHOLDER_FOR_TOPLAYER) {
- nsIFrame* backdropFrame = nsCSSFrameConstructor::
- CreateBackdropFrameFor(mPresShell, aContent, aNewFrame,
- outOfFlowFrameItems->containingBlock);
- if (backdropFrame) {
- frameItems->AddChild(backdropFrame);
- }
+ ConstructBackdropFrameFor(aContent, aNewFrame);
}
}
#ifdef DEBUG
else {
NS_ASSERTION(aNewFrame->GetParent() == aParentFrame,
"In-flow frame has wrong parent");
}
#endif
@@ -1256,20 +1305,21 @@ nsFrameConstructorState::AddChild(nsIFra
}
void
nsFrameConstructorState::ProcessFrameInsertions(nsAbsoluteItems& aFrameItems,
ChildListID aChildListID)
{
#define NS_NONXUL_LIST_TEST (&aFrameItems == &mFloatedItems && \
aChildListID == nsIFrame::kFloatList) || \
- (&aFrameItems == &mAbsoluteItems && \
+ ((&aFrameItems == &mAbsoluteItems || \
+ &aFrameItems == &mTopLayerAbsoluteItems) && \
aChildListID == nsIFrame::kAbsoluteList) || \
((&aFrameItems == &mFixedItems || \
- &aFrameItems == &mTopLayerItems) && \
+ &aFrameItems == &mTopLayerFixedItems) && \
aChildListID == nsIFrame::kFixedList)
#ifdef MOZ_XUL
NS_PRECONDITION(NS_NONXUL_LIST_TEST ||
(&aFrameItems == &mPopupItems &&
aChildListID == nsIFrame::kPopupList),
"Unexpected aFrameItems/aChildListID combination");
#else
NS_PRECONDITION(NS_NONXUL_LIST_TEST,
@@ -2967,48 +3017,16 @@ nsCSSFrameConstructor::CreatePlaceholder
aFrame->AddStateBits(NS_FRAME_OUT_OF_FLOW);
// Add mapping from absolutely positioned frame to its placeholder frame
aPresShell->FrameManager()->RegisterPlaceholderFrame(placeholderFrame);
return placeholderFrame;
}
-/* static */ nsIFrame*
-nsCSSFrameConstructor::CreateBackdropFrameFor(nsIPresShell* aPresShell,
- nsIContent* aContent,
- nsIFrame* aFrame,
- nsContainerFrame* aParentFrame)
-{
- MOZ_ASSERT(aFrame->StyleDisplay()->mTopLayer == NS_STYLE_TOP_LAYER_TOP);
- nsContainerFrame* frame = do_QueryFrame(aFrame);
- if (!frame) {
- NS_WARNING("Cannot create backdrop frame for non-container frame");
- return nullptr;
- }
-
- RefPtr<nsStyleContext> style = aPresShell->StyleSet()->
- ResolvePseudoElementStyle(aContent->AsElement(),
- CSSPseudoElementType::backdrop,
- /* aParentStyleContext */ nullptr,
- /* aPseudoElement */ nullptr);
- nsBackdropFrame* backdropFrame = new (aPresShell) nsBackdropFrame(style);
- backdropFrame->Init(aContent, aParentFrame, nullptr);
-
- nsIFrame* placeholder = CreatePlaceholderFrameFor(aPresShell, aContent,
- backdropFrame,
- frame->StyleContext(),
- frame, nullptr,
- PLACEHOLDER_FOR_TOPLAYER);
- nsFrameList temp(placeholder, placeholder);
- frame->SetInitialChildList(nsIFrame::kBackdropList, temp);
-
- return backdropFrame;
-}
-
// Clears any lazy bits set in the range [aStartContent, aEndContent). If
// aEndContent is null, that means to clear bits in all siblings starting with
// aStartContent. aStartContent must not be null unless aEndContent is also
// null. We do this so that when new children are inserted under elements whose
// frame is a leaf the new children don't cause us to try to construct frames
// for the existing children again.
static inline void
ClearLazyBits(nsIContent* aStartContent, nsIContent* aEndContent)