Bug 1087956: Fix clipping of position:fixed layers inside displayports. r=roc

This commit is contained in:
Matt Woodrow 2015-02-20 10:55:28 -08:00
Родитель cd23dedd4c
Коммит c2394710e5
2 изменённых файлов: 33 добавлений и 8 удалений

Просмотреть файл

@ -21,9 +21,7 @@ namespace mozilla {
void void
DisplayItemClip::SetTo(const nsRect& aRect) DisplayItemClip::SetTo(const nsRect& aRect)
{ {
mHaveClipRect = true; SetTo(aRect, nullptr);
mClipRect = aRect;
mRoundedClipRects.Clear();
} }
void void
@ -31,9 +29,13 @@ DisplayItemClip::SetTo(const nsRect& aRect, const nscoord* aRadii)
{ {
mHaveClipRect = true; mHaveClipRect = true;
mClipRect = aRect; mClipRect = aRect;
mRoundedClipRects.SetLength(1); if (aRadii) {
mRoundedClipRects[0].mRect = aRect; mRoundedClipRects.SetLength(1);
memcpy(mRoundedClipRects[0].mRadii, aRadii, sizeof(nscoord)*8); mRoundedClipRects[0].mRect = aRect;
memcpy(mRoundedClipRects[0].mRadii, aRadii, sizeof(nscoord)*8);
} else {
mRoundedClipRects.Clear();
}
} }
void void

Просмотреть файл

@ -641,6 +641,8 @@ void nsDisplayListBuilder::MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame,
const nsRect& aDirtyRect) const nsRect& aDirtyRect)
{ {
nsRect dirtyRectRelativeToDirtyFrame = aDirtyRect; nsRect dirtyRectRelativeToDirtyFrame = aDirtyRect;
DisplayItemClip clip;
const DisplayItemClip* clipPtr = nullptr;
if (nsLayoutUtils::IsFixedPosFrameInDisplayPort(aFrame) && if (nsLayoutUtils::IsFixedPosFrameInDisplayPort(aFrame) &&
IsPaintingToWindow()) { IsPaintingToWindow()) {
NS_ASSERTION(aDirtyFrame == aFrame->GetParent(), "Dirty frame should be viewport frame"); NS_ASSERTION(aDirtyFrame == aFrame->GetParent(), "Dirty frame should be viewport frame");
@ -654,6 +656,19 @@ void nsDisplayListBuilder::MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame,
} else { } else {
dirtyRectRelativeToDirtyFrame.SizeTo(aDirtyFrame->GetSize()); dirtyRectRelativeToDirtyFrame.SizeTo(aDirtyFrame->GetSize());
} }
// Always clip fixed items to the root scroll frame's scrollport, because
// we skip setting the clip in ScrollFrameHelper if we have a displayport.
nsIFrame* rootScroll = aFrame->PresContext()->PresShell()->GetRootScrollFrame();
if (rootScroll) {
nsIScrollableFrame* scrollable = do_QueryFrame(rootScroll);
nsRect clipRect = scrollable->GetScrollPortRect() + ToReferenceFrame(rootScroll);
nscoord radii[8];
bool haveRadii = rootScroll->GetPaddingBoxBorderRadii(radii);
clip.SetTo(clipRect, haveRadii ? radii : nullptr);
clipPtr = &clip;
}
} }
nsRect dirty = dirtyRectRelativeToDirtyFrame - aFrame->GetOffsetTo(aDirtyFrame); nsRect dirty = dirtyRectRelativeToDirtyFrame - aFrame->GetOffsetTo(aDirtyFrame);
@ -672,8 +687,16 @@ void nsDisplayListBuilder::MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame,
if (!dirty.IntersectRect(dirty, overflowRect)) if (!dirty.IntersectRect(dirty, overflowRect))
return; return;
const DisplayItemClip* clip = mClipState.GetClipForContainingBlockDescendants();
OutOfFlowDisplayData* data = clip ? new OutOfFlowDisplayData(*clip, dirty) // Combine clips if necessary
const DisplayItemClip* oldClip = mClipState.GetClipForContainingBlockDescendants();
if (clipPtr && oldClip) {
clip.IntersectWith(*oldClip);
} else if (oldClip) {
clipPtr = oldClip;
}
OutOfFlowDisplayData* data = clipPtr ? new OutOfFlowDisplayData(*clipPtr, dirty)
: new OutOfFlowDisplayData(dirty); : new OutOfFlowDisplayData(dirty);
aFrame->Properties().Set(nsDisplayListBuilder::OutOfFlowDisplayDataProperty(), data); aFrame->Properties().Set(nsDisplayListBuilder::OutOfFlowDisplayDataProperty(), data);