Bug 962791. Fail to create a scrollable layer if it would cause incorrect clipping of absolutely position items. r=roc

We incorrectly wrap abs pos items, but not wrapping them leads to too many sites failing to create scrollable layers that we can't do that. So instead just fix the clipping issue for now until a more robust solution can be developed.
This commit is contained in:
Timothy Nikkel 2014-02-03 23:16:20 -06:00
parent 1f1ea86463
commit ab269009e3
2 changed files with 36 additions and 2 deletions

View File

@ -3652,6 +3652,30 @@ nsDisplayScrollLayer::GetLayerState(nsDisplayListBuilder* aBuilder,
return LAYER_ACTIVE_FORCE;
}
// Check if we are going to clip an abs pos item that we don't contain.
// Root scroll frames clip all their descendants, so we don't need to worry
// about them.
bool
WouldCauseIncorrectClippingOnAbsPosItem(nsDisplayListBuilder* aBuilder,
nsDisplayScrollLayer* aItem)
{
nsIFrame* scrollFrame = aItem->GetScrollFrame();
nsIPresShell* presShell = scrollFrame->PresContext()->PresShell();
if (scrollFrame == presShell->GetRootScrollFrame()) {
return false;
}
nsIFrame* scrolledFrame = aItem->GetScrolledFrame();
nsIFrame* frame = aItem->Frame();
if (frame == scrolledFrame || !frame->IsAbsolutelyPositioned() ||
nsLayoutUtils::IsAncestorFrameCrossDoc(scrollFrame, frame, presShell->GetRootFrame())) {
return false;
}
if (!aItem->GetClip().IsRectAffectedByClip(aItem->GetChildren()->GetBounds(aBuilder))) {
return false;
}
return true;
}
bool
nsDisplayScrollLayer::TryMerge(nsDisplayListBuilder* aBuilder,
nsDisplayItem* aItem)
@ -3667,6 +3691,11 @@ nsDisplayScrollLayer::TryMerge(nsDisplayListBuilder* aBuilder,
return false;
}
if (WouldCauseIncorrectClippingOnAbsPosItem(aBuilder, this) ||
WouldCauseIncorrectClippingOnAbsPosItem(aBuilder, other)) {
return false;
}
NS_ASSERTION(other->mReferenceFrame == mReferenceFrame,
"Must have the same reference frame!");
@ -3704,12 +3733,16 @@ PropagateClip(nsDisplayListBuilder* aBuilder, const DisplayItemClip& aClip,
bool
nsDisplayScrollLayer::ShouldFlattenAway(nsDisplayListBuilder* aBuilder)
{
if (GetScrollLayerCount() > 1) {
bool badAbsPosClip = WouldCauseIncorrectClippingOnAbsPosItem(aBuilder, this);
if (GetScrollLayerCount() > 1 || badAbsPosClip) {
// Propagate our clip to our children. The clip for the scroll frame is
// on this item, but not our child items so that they can draw non-visible
// parts of the display port. But if we are flattening we failed and can't
// draw the extra content, so it needs to be clipped.
PropagateClip(aBuilder, GetClip(), &mList);
// But don't induce our clip on abs pos frames that we shouldn't be clipping.
if (!badAbsPosClip) {
PropagateClip(aBuilder, GetClip(), &mList);
}
return true;
}
if (mFrame != mScrolledFrame) {

View File

@ -2810,6 +2810,7 @@ public:
// after merging, all the nsDisplayScrollLayers should flatten away.
intptr_t GetScrollLayerCount();
virtual nsIFrame* GetScrollFrame() { return mScrollFrame; }
virtual nsIFrame* GetScrolledFrame() { return mScrolledFrame; }
#ifdef MOZ_DUMP_PAINTING