Bug 1178745 - Respect scroll clips when flattening. r=roc

This commit is contained in:
Markus Stange 2015-07-02 17:04:14 -04:00
parent e9f76277b5
commit 34c169f5e7

View File

@ -3618,6 +3618,39 @@ IsCaretWithCustomClip(nsDisplayItem* aItem, nsDisplayItem::Type aItemType)
static_cast<nsDisplayCaret*>(aItem)->NeedsCustomScrollClip(); static_cast<nsDisplayCaret*>(aItem)->NeedsCustomScrollClip();
} }
static DisplayItemClip
GetScrollClipIntersection(nsDisplayListBuilder* aBuilder, const nsIFrame* aAnimatedGeometryRoot,
const nsIFrame* aStopAtAnimatedGeometryRoot, bool aIsCaret)
{
DisplayItemClip resultClip;
nsIFrame* fParent;
for (const nsIFrame* f = aAnimatedGeometryRoot;
f != aStopAtAnimatedGeometryRoot;
f = nsLayoutUtils::GetAnimatedGeometryRootForFrame(aBuilder,
fParent, aStopAtAnimatedGeometryRoot)) {
fParent = nsLayoutUtils::GetCrossDocParentFrame(f);
if (!fParent) {
// This means aStopAtAnimatedGeometryRoot was not an ancestor
// of aAnimatedGeometryRoot. This is a weird case but it
// can happen, e.g. when a scrolled frame contains a frame with opacity
// which contains a frame that is not scrolled by the scrolled frame.
// For now, we just don't apply any specific scroll clip to this layer.
return DisplayItemClip();
}
nsIScrollableFrame* scrollFrame = nsLayoutUtils::GetScrollableFrameFor(f);
if (!scrollFrame) {
continue;
}
const DisplayItemClip* clip = scrollFrame->ComputeScrollClip(aIsCaret);
if (clip) {
resultClip.IntersectWith(*clip);
}
}
return resultClip;
}
/* /*
* Iterate through the non-clip items in aList and its descendants. * Iterate through the non-clip items in aList and its descendants.
* For each item we compute the effective clip rect. Each item is assigned * For each item we compute the effective clip rect. Each item is assigned
@ -3694,13 +3727,15 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList)
bool forceInactive; bool forceInactive;
const nsIFrame* animatedGeometryRoot; const nsIFrame* animatedGeometryRoot;
const nsIFrame* realAnimatedGeometryRootOfItem =
nsLayoutUtils::GetAnimatedGeometryRootFor(item, mBuilder, mManager);
if (mFlattenToSingleLayer) { if (mFlattenToSingleLayer) {
forceInactive = true; forceInactive = true;
animatedGeometryRoot = lastAnimatedGeometryRoot; animatedGeometryRoot = lastAnimatedGeometryRoot;
} else { } else {
forceInactive = false; forceInactive = false;
if (mManager->IsWidgetLayerManager()) { if (mManager->IsWidgetLayerManager()) {
animatedGeometryRoot = nsLayoutUtils::GetAnimatedGeometryRootFor(item, mBuilder, mManager); animatedGeometryRoot = realAnimatedGeometryRootOfItem;
} else { } else {
// For inactive layer subtrees, splitting content into PaintedLayers // For inactive layer subtrees, splitting content into PaintedLayers
// based on animated geometry roots is pointless. It's more efficient // based on animated geometry roots is pointless. It's more efficient
@ -3714,9 +3749,20 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList)
} }
} }
nsDisplayItem::Type itemType = item->GetType();
if (animatedGeometryRoot != realAnimatedGeometryRootOfItem) {
// Pick up any scroll clips that should apply to the item and apply them.
DisplayItemClip clip =
GetScrollClipIntersection(mBuilder, realAnimatedGeometryRootOfItem,
animatedGeometryRoot,
IsCaretWithCustomClip(item, itemType));
clip.IntersectWith(item->GetClip());
item->SetClip(mBuilder, clip);
}
bool snap; bool snap;
nsRect itemContent = item->GetBounds(mBuilder, &snap); nsRect itemContent = item->GetBounds(mBuilder, &snap);
nsDisplayItem::Type itemType = item->GetType();
if (itemType == nsDisplayItem::TYPE_LAYER_EVENT_REGIONS) { if (itemType == nsDisplayItem::TYPE_LAYER_EVENT_REGIONS) {
nsDisplayLayerEventRegions* eventRegions = nsDisplayLayerEventRegions* eventRegions =
static_cast<nsDisplayLayerEventRegions*>(item); static_cast<nsDisplayLayerEventRegions*>(item);