mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 769541 - Fix display list creation for positioned descendants of fixed position frames. r=roc
Positioned descendants of positioned frames escape the child display list to their parent's positioned descendants list when they don't have a z-index set. This caused their invalidations to be logged against the incorrect layer. To fix this, wrap each extra positioned descendant of a fixed-position frame in its own nsDisplayFixedPosition so they receive their own layers.
This commit is contained in:
parent
aca5b79b25
commit
f61563bc07
@ -65,6 +65,7 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
|
||||
mIsPaintingToWindow(false),
|
||||
mHasDisplayPort(false),
|
||||
mHasFixedItems(false),
|
||||
mIsInFixedPosition(false),
|
||||
mIsCompositingCheap(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsDisplayListBuilder);
|
||||
@ -2072,8 +2073,10 @@ nsDisplayOwnLayer::BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||
|
||||
nsDisplayFixedPosition::nsDisplayFixedPosition(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aFrame,
|
||||
nsIFrame* aFixedPosFrame,
|
||||
nsDisplayList* aList)
|
||||
: nsDisplayOwnLayer(aBuilder, aFrame, aList) {
|
||||
: nsDisplayOwnLayer(aBuilder, aFrame, aList)
|
||||
, mFixedPosFrame(aFixedPosFrame) {
|
||||
MOZ_COUNT_CTOR(nsDisplayFixedPosition);
|
||||
}
|
||||
|
||||
@ -2094,7 +2097,7 @@ nsDisplayFixedPosition::BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||
// any positioning set (left/top/right/bottom) indicates that the
|
||||
// corresponding side of its container should be the anchor point,
|
||||
// defaulting to top-left.
|
||||
nsIFrame* viewportFrame = mFrame->GetParent();
|
||||
nsIFrame* viewportFrame = mFixedPosFrame->GetParent();
|
||||
nsPresContext *presContext = viewportFrame->PresContext();
|
||||
|
||||
// Fixed position frames are reflowed into the scroll-port size if one has
|
||||
@ -2121,7 +2124,7 @@ nsDisplayFixedPosition::BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||
|
||||
gfxPoint anchor(anchorRect.x, anchorRect.y);
|
||||
|
||||
const nsStylePosition* position = mFrame->GetStylePosition();
|
||||
const nsStylePosition* position = mFixedPosFrame->GetStylePosition();
|
||||
if (position->mOffset.GetRightUnit() != eStyleUnit_Auto)
|
||||
anchor.x = anchorRect.XMost();
|
||||
if (position->mOffset.GetBottomUnit() != eStyleUnit_Auto)
|
||||
|
@ -222,6 +222,12 @@ public:
|
||||
void SetPaintingToWindow(bool aToWindow) { mIsPaintingToWindow = aToWindow; }
|
||||
bool IsPaintingToWindow() const { return mIsPaintingToWindow; }
|
||||
|
||||
/**
|
||||
* @return Returns if the builder is currently building an
|
||||
* nsDisplayFixedPosition sub-tree.
|
||||
*/
|
||||
bool IsInFixedPosition() const { return mIsInFixedPosition; }
|
||||
|
||||
bool SetIsCompositingCheap(bool aCompositingCheap) {
|
||||
bool temp = mIsCompositingCheap;
|
||||
mIsCompositingCheap = aCompositingCheap;
|
||||
@ -391,8 +397,8 @@ public:
|
||||
|
||||
/**
|
||||
* A helper class to temporarily set the value of
|
||||
* mIsAtRootOfPseudoStackingContext and temporarily update
|
||||
* mCachedOffsetFrame/mCachedOffset from a frame to its child.
|
||||
* mIsAtRootOfPseudoStackingContext and mIsInFixedPosition, and temporarily
|
||||
* update mCachedOffsetFrame/mCachedOffset from a frame to its child.
|
||||
*/
|
||||
class AutoBuildingDisplayList;
|
||||
friend class AutoBuildingDisplayList;
|
||||
@ -406,11 +412,13 @@ public:
|
||||
aBuilder->mIsAtRootOfPseudoStackingContext = aIsRoot;
|
||||
}
|
||||
AutoBuildingDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aForChild, bool aIsRoot)
|
||||
nsIFrame* aForChild, bool aIsRoot,
|
||||
bool aIsInFixedPosition)
|
||||
: mBuilder(aBuilder),
|
||||
mPrevCachedOffsetFrame(aBuilder->mCachedOffsetFrame),
|
||||
mPrevCachedOffset(aBuilder->mCachedOffset),
|
||||
mPrevIsAtRootOfPseudoStackingContext(aBuilder->mIsAtRootOfPseudoStackingContext) {
|
||||
mPrevIsAtRootOfPseudoStackingContext(aBuilder->mIsAtRootOfPseudoStackingContext),
|
||||
mPrevIsInFixedPosition(aBuilder->mIsInFixedPosition) {
|
||||
if (mPrevCachedOffsetFrame == aForChild->GetParent()) {
|
||||
aBuilder->mCachedOffset += aForChild->GetPosition();
|
||||
} else {
|
||||
@ -418,17 +426,22 @@ public:
|
||||
}
|
||||
aBuilder->mCachedOffsetFrame = aForChild;
|
||||
aBuilder->mIsAtRootOfPseudoStackingContext = aIsRoot;
|
||||
if (aIsInFixedPosition) {
|
||||
aBuilder->mIsInFixedPosition = aIsInFixedPosition;
|
||||
}
|
||||
}
|
||||
~AutoBuildingDisplayList() {
|
||||
mBuilder->mCachedOffsetFrame = mPrevCachedOffsetFrame;
|
||||
mBuilder->mCachedOffset = mPrevCachedOffset;
|
||||
mBuilder->mIsAtRootOfPseudoStackingContext = mPrevIsAtRootOfPseudoStackingContext;
|
||||
mBuilder->mIsInFixedPosition = mPrevIsInFixedPosition;
|
||||
}
|
||||
private:
|
||||
nsDisplayListBuilder* mBuilder;
|
||||
const nsIFrame* mPrevCachedOffsetFrame;
|
||||
nsPoint mPrevCachedOffset;
|
||||
bool mPrevIsAtRootOfPseudoStackingContext;
|
||||
bool mPrevIsInFixedPosition;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -535,6 +548,7 @@ private:
|
||||
bool mIsPaintingToWindow;
|
||||
bool mHasDisplayPort;
|
||||
bool mHasFixedItems;
|
||||
bool mIsInFixedPosition;
|
||||
bool mIsCompositingCheap;
|
||||
};
|
||||
|
||||
@ -1920,7 +1934,7 @@ public:
|
||||
class nsDisplayFixedPosition : public nsDisplayOwnLayer {
|
||||
public:
|
||||
nsDisplayFixedPosition(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
|
||||
nsDisplayList* aList);
|
||||
nsIFrame* aFixedPosFrame, nsDisplayList* aList);
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
virtual ~nsDisplayFixedPosition();
|
||||
#endif
|
||||
@ -1929,6 +1943,9 @@ public:
|
||||
LayerManager* aManager,
|
||||
const ContainerParameters& aContainerParameters);
|
||||
NS_DISPLAY_DECL_NAME("FixedPosition", TYPE_FIXED_POSITION)
|
||||
|
||||
protected:
|
||||
nsIFrame* mFixedPosFrame;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -2103,8 +2103,15 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
|
||||
pseudoStackingContext = true;
|
||||
}
|
||||
|
||||
// This controls later whether we build an nsDisplayWrapList or an
|
||||
// nsDisplayFixedPosition. We check if we're already building a fixed-pos
|
||||
// item and disallow nesting, to prevent the situation of bug #769541
|
||||
// occurring.
|
||||
bool buildFixedPositionItem = disp->mPosition == NS_STYLE_POSITION_FIXED
|
||||
&& !child->GetParent()->GetParent() && !isSVG && !aBuilder->IsInFixedPosition();
|
||||
|
||||
nsDisplayListBuilder::AutoBuildingDisplayList
|
||||
buildingForChild(aBuilder, child, pseudoStackingContext);
|
||||
buildingForChild(aBuilder, child, pseudoStackingContext, buildFixedPositionItem);
|
||||
|
||||
nsRect overflowClip;
|
||||
nscoord overflowClipRadii[8];
|
||||
@ -2204,9 +2211,8 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
|
||||
// Make sure the root of a fixed position frame sub-tree gets the
|
||||
// correct displaylist item type.
|
||||
nsDisplayItem* item;
|
||||
if (!isSVG && !child->GetParent()->GetParent() &&
|
||||
disp->mPosition == NS_STYLE_POSITION_FIXED) {
|
||||
item = new (aBuilder) nsDisplayFixedPosition(aBuilder, child, &list);
|
||||
if (buildFixedPositionItem) {
|
||||
item = new (aBuilder) nsDisplayFixedPosition(aBuilder, child, child, &list);
|
||||
} else {
|
||||
item = new (aBuilder) nsDisplayWrapList(aBuilder, child, &list);
|
||||
}
|
||||
@ -2216,6 +2222,19 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
|
||||
rv = aLists.PositionedDescendants()->AppendNewToTop(item);
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Make sure that extra positioned descendants don't escape having
|
||||
// their fixed-position metadata applied to them.
|
||||
if (buildFixedPositionItem) {
|
||||
while (!extraPositionedDescendants.IsEmpty()) {
|
||||
item = extraPositionedDescendants.RemoveBottom();
|
||||
nsDisplayList fixedPosDescendantList;
|
||||
fixedPosDescendantList.AppendToTop(item);
|
||||
aLists.PositionedDescendants()->AppendNewToTop(
|
||||
new (aBuilder) nsDisplayFixedPosition(aBuilder, item->GetUnderlyingFrame(),
|
||||
child, &fixedPosDescendantList));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (!isSVG && disp->IsFloating()) {
|
||||
if (!list.IsEmpty()) {
|
||||
|
Loading…
Reference in New Issue
Block a user