mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Bug 827577. Be a lot more careful about saving and restoring frame constructor state for fixed-pos descendants of CSS-transformed elements. r=bzbarsky
--HG-- extra : rebase_source : b78a8cb774b961696e59c2c27a8ade56d629b78f
This commit is contained in:
parent
69fa838f1a
commit
7ab390b69a
@ -683,16 +683,19 @@ public:
|
||||
~nsFrameConstructorSaveState();
|
||||
|
||||
private:
|
||||
nsAbsoluteItems* mItems; // pointer to struct whose data we save/restore
|
||||
bool* mFixedPosIsAbsPos;
|
||||
|
||||
nsAbsoluteItems mSavedItems; // copy of original data
|
||||
bool mSavedFixedPosIsAbsPos;
|
||||
nsAbsoluteItems* mItems; // pointer to struct whose data we save/restore
|
||||
nsAbsoluteItems mSavedItems; // copy of original data
|
||||
|
||||
// The name of the child list in which our frames would belong
|
||||
ChildListID mChildListID;
|
||||
nsFrameConstructorState* mState;
|
||||
|
||||
// State used only when we're saving the abs-pos state for a transformed
|
||||
// element.
|
||||
nsAbsoluteItems mSavedFixedItems;
|
||||
|
||||
bool mSavedFixedPosIsAbsPos;
|
||||
|
||||
friend class nsFrameConstructorState;
|
||||
};
|
||||
|
||||
@ -781,6 +784,8 @@ public:
|
||||
// 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.
|
||||
void PushAbsoluteContainingBlock(nsIFrame* aNewAbsoluteContainingBlock,
|
||||
nsFrameConstructorSaveState& aSaveState);
|
||||
|
||||
@ -1027,11 +1032,15 @@ nsFrameConstructorState::PushAbsoluteContainingBlock(nsIFrame* aNewAbsoluteConta
|
||||
aSaveState.mSavedItems = mAbsoluteItems;
|
||||
aSaveState.mChildListID = nsIFrame::kAbsoluteList;
|
||||
aSaveState.mState = this;
|
||||
|
||||
/* Store whether we're wiring the abs-pos and fixed-pos lists together. */
|
||||
aSaveState.mFixedPosIsAbsPos = &mFixedPosIsAbsPos;
|
||||
aSaveState.mSavedFixedPosIsAbsPos = mFixedPosIsAbsPos;
|
||||
|
||||
if (mFixedPosIsAbsPos) {
|
||||
// Since we're going to replace mAbsoluteItems, we need to save it into
|
||||
// mFixedItems now (and save the current value of mFixedItems).
|
||||
aSaveState.mSavedFixedItems = mFixedItems;
|
||||
mFixedItems = mAbsoluteItems;
|
||||
}
|
||||
|
||||
mAbsoluteItems =
|
||||
nsAbsoluteItems(AdjustAbsoluteContainingBlock(aNewAbsoluteContainingBlock));
|
||||
|
||||
@ -1235,7 +1244,13 @@ nsFrameConstructorState::ProcessFrameInsertions(nsAbsoluteItems& aFrameItems,
|
||||
|
||||
NS_ASSERTION(containingBlock,
|
||||
"Child list without containing block?");
|
||||
|
||||
|
||||
if (aChildListID == nsIFrame::kFixedList &&
|
||||
containingBlock->GetStyleDisplay()->HasTransform(containingBlock)) {
|
||||
// Put this frame on the transformed-frame's abs-pos list instead.
|
||||
aChildListID = nsIFrame::kAbsoluteList;
|
||||
}
|
||||
|
||||
// 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.
|
||||
@ -1299,11 +1314,11 @@ nsFrameConstructorState::ProcessFrameInsertions(nsAbsoluteItems& aFrameItems,
|
||||
|
||||
nsFrameConstructorSaveState::nsFrameConstructorSaveState()
|
||||
: mItems(nullptr),
|
||||
mFixedPosIsAbsPos(nullptr),
|
||||
mSavedItems(nullptr),
|
||||
mSavedFixedPosIsAbsPos(false),
|
||||
mChildListID(kPrincipalList),
|
||||
mState(nullptr)
|
||||
mState(nullptr),
|
||||
mSavedFixedItems(nullptr),
|
||||
mSavedFixedPosIsAbsPos(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -1319,9 +1334,20 @@ nsFrameConstructorSaveState::~nsFrameConstructorSaveState()
|
||||
// Note that this only matters for the assert in ~nsAbsoluteItems.
|
||||
mSavedItems.Clear();
|
||||
#endif
|
||||
}
|
||||
if (mFixedPosIsAbsPos) {
|
||||
*mFixedPosIsAbsPos = mSavedFixedPosIsAbsPos;
|
||||
if (mItems == &mState->mAbsoluteItems) {
|
||||
mState->mFixedPosIsAbsPos = mSavedFixedPosIsAbsPos;
|
||||
if (mSavedFixedPosIsAbsPos) {
|
||||
// mAbsoluteItems was moved to mFixedItems, so move mFixedItems back
|
||||
// and repair the old mFixedItems now.
|
||||
mState->mAbsoluteItems = mState->mFixedItems;
|
||||
mState->mFixedItems = mSavedFixedItems;
|
||||
#ifdef DEBUG
|
||||
mSavedFixedItems.Clear();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
NS_ASSERTION(!mItems->LastChild() || !mItems->LastChild()->GetNextSibling(),
|
||||
"Something corrupted our list");
|
||||
}
|
||||
}
|
||||
|
||||
@ -5613,6 +5639,21 @@ nsCSSFrameConstructor::GetAbsoluteContainingBlock(nsIFrame* aFrame)
|
||||
return mHasRootAbsPosContainingBlock ? mDocElementContainingBlock : nullptr;
|
||||
}
|
||||
|
||||
nsIFrame*
|
||||
nsCSSFrameConstructor::GetFixedContainingBlock(nsIFrame* aFrame)
|
||||
{
|
||||
NS_PRECONDITION(nullptr != mRootElementFrame, "no root element frame");
|
||||
|
||||
// Starting with aFrame, look for a frame that is CSS-transformed
|
||||
for (nsIFrame* frame = aFrame; frame; frame = frame->GetParent()) {
|
||||
if (frame->GetStyleDisplay()->HasTransform(frame)) {
|
||||
return frame;
|
||||
}
|
||||
}
|
||||
|
||||
return mFixedContainingBlock;
|
||||
}
|
||||
|
||||
nsIFrame*
|
||||
nsCSSFrameConstructor::GetFloatContainingBlock(nsIFrame* aFrame)
|
||||
{
|
||||
@ -6607,7 +6648,7 @@ nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer,
|
||||
&parentAfterFrame);
|
||||
|
||||
// Create some new frames
|
||||
nsFrameConstructorState state(mPresShell, mFixedContainingBlock,
|
||||
nsFrameConstructorState state(mPresShell, GetFixedContainingBlock(parentFrame),
|
||||
GetAbsoluteContainingBlock(parentFrame),
|
||||
GetFloatContainingBlock(parentFrame));
|
||||
state.mTreeMatchContext.InitAncestors(aContainer->AsElement());
|
||||
@ -7042,7 +7083,7 @@ nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aContainer,
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsFrameConstructorState state(mPresShell, mFixedContainingBlock,
|
||||
nsFrameConstructorState state(mPresShell, GetFixedContainingBlock(parentFrame),
|
||||
GetAbsoluteContainingBlock(parentFrame),
|
||||
GetFloatContainingBlock(parentFrame),
|
||||
aFrameState);
|
||||
|
@ -1464,6 +1464,7 @@ private:
|
||||
*/
|
||||
public:
|
||||
nsIFrame* GetAbsoluteContainingBlock(nsIFrame* aFrame);
|
||||
nsIFrame* GetFixedContainingBlock(nsIFrame* aFrame);
|
||||
private:
|
||||
nsIFrame* GetFloatContainingBlock(nsIFrame* aFrame);
|
||||
|
||||
|
7
layout/reftests/bugs/827577-1-ref.html
Normal file
7
layout/reftests/bugs/827577-1-ref.html
Normal file
@ -0,0 +1,7 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<body>
|
||||
<div style="margin-left:100px; width:200px; height:200px; border:1px solid black">
|
||||
<div style="margin-left:150px; width:50px; height:80px; background:yellow;">
|
||||
</div>
|
||||
</div>
|
11
layout/reftests/bugs/827577-1a.html
Normal file
11
layout/reftests/bugs/827577-1a.html
Normal file
@ -0,0 +1,11 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<body>
|
||||
<div style="transform:translateX(100px); width:200px; height:200px; border:1px solid black">
|
||||
<div style="position:absolute;">
|
||||
</div>
|
||||
<div style="position:absolute;">
|
||||
<div style="position:fixed; right:0; width:50px; height:80px; background:yellow;">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
18
layout/reftests/bugs/827577-1b.html
Normal file
18
layout/reftests/bugs/827577-1b.html
Normal file
@ -0,0 +1,18 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html class="reftest-wait">
|
||||
<body>
|
||||
<div style="transform:translateX(100px); width:200px; height:200px; border:1px solid black">
|
||||
<div style="position:absolute;">
|
||||
</div>
|
||||
<div style="position:absolute;">
|
||||
<div id="d" style="display:none; position:fixed; right:0; width:50px; height:80px; background:yellow;">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
function doTest() {
|
||||
document.getElementById("d").style.display = "";
|
||||
document.documentElement.removeAttribute("class");
|
||||
}
|
||||
window.addEventListener("MozReftestInvalidate", doTest, false);
|
||||
</script>
|
11
layout/reftests/bugs/827577-2.html
Normal file
11
layout/reftests/bugs/827577-2.html
Normal file
@ -0,0 +1,11 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html class="reftest-wait>
|
||||
<body>
|
||||
<div style="transform:translateX(100px); width:200px; height:200px; border:1px solid black">
|
||||
<div style="position:absolute;">
|
||||
</div>
|
||||
<div style="position:absolute;">
|
||||
<div style="position:fixed; right:0; width:50px; height:80px; background:yellow;">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1738,3 +1738,5 @@ skip-if(B2G) == 814952-1.html 814952-1-ref.html
|
||||
== 816458-1.html 816458-1-ref.html
|
||||
== 816359-1.html 816359-1-ref.html
|
||||
skip-if(B2G) == 818276-1.html 818276-1-ref.html
|
||||
== 827577-1a.html 827577-1-ref.html
|
||||
== 827577-1b.html 827577-1-ref.html
|
||||
|
Loading…
Reference in New Issue
Block a user