Bug 951467. Give scroll layer items the bounds of the scroll port, not the bounds of the display port. r=roc

The bounds of the scroll port match what will actually be drawn on the screen.

The bounds of the contained content (sized to the display port) are still accessible via mList.GetBounds, and similarly the visible rect of the contained content is mList.GetVisibleRect. The external bounds/visible rect are GetBounds and GetVisibleRect on the nsDisplayScrollLayer object itself.

We implement nsDisplayScrollInfoLayer::GetBounds solely so that it continues to return an empty rect because we expect active empty layers to have empty visible rects.

We no longer have to set our mVisibleRect in nsDisplayScrollLayer::ComputeVisibility because nsDisplayList::ComputeVisibilityForSublist now does it correctly for us (like other items).

We also have to teach ContainerState::ProcessDisplayItems to not set the visible region for scroll layers because it has the external visible region, not the larger internal display port sized visible region. We instead let BuildContainerLayer set the visible region of the layer.
This commit is contained in:
Timothy Nikkel 2013-12-17 23:02:56 -06:00
parent 02a858e731
commit a969eaf546
3 changed files with 47 additions and 22 deletions

View File

@ -2261,11 +2261,12 @@ ContainerState::ProcessDisplayItems(const nsDisplayList& aList,
nsDisplayItem::Type type = item->GetType();
bool setVisibleRegion = type != nsDisplayItem::TYPE_TRANSFORM;
if (setVisibleRegion) {
mParameters.mAncestorClipRect = nullptr;
} else {
bool setVisibleRegion = (type != nsDisplayItem::TYPE_TRANSFORM) &&
(type != nsDisplayItem::TYPE_SCROLL_LAYER);
if (type == nsDisplayItem::TYPE_TRANSFORM) {
mParameters.mAncestorClipRect = itemClip.HasClip() ? &clipRect : nullptr;
} else {
mParameters.mAncestorClipRect = nullptr;
}
// Just use its layer.

View File

@ -3484,6 +3484,17 @@ nsDisplayScrollLayer::~nsDisplayScrollLayer()
}
#endif
nsRect
nsDisplayScrollLayer::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
{
nsIScrollableFrame* sf = do_QueryFrame(mScrollFrame);
if (sf) {
*aSnap = false;
return sf->GetScrollPortRect() + aBuilder->ToReferenceFrame(mScrollFrame);
}
return nsDisplayWrapList::GetBounds(aBuilder, aSnap);
}
already_AddRefed<Layer>
nsDisplayScrollLayer::BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
@ -3510,7 +3521,7 @@ nsDisplayScrollLayer::BuildLayer(nsDisplayListBuilder* aBuilder,
nsLayoutUtils::GetCriticalDisplayPort(content, &criticalDisplayport);
}
RecordFrameMetrics(mScrolledFrame, mScrollFrame, ReferenceFrame(), layer,
mVisibleRect, viewport,
mList.GetVisibleRect(), viewport,
(usingDisplayport ? &displayport : nullptr),
(usingCriticalDisplayport ? &criticalDisplayport : nullptr),
scrollId, false, aContainerParameters);
@ -3534,28 +3545,29 @@ nsDisplayScrollLayer::ComputeVisibility(nsDisplayListBuilder* aBuilder,
const nsRect& aAllowVisibleRegionExpansion)
{
nsRect displayport;
if (nsLayoutUtils::GetDisplayPort(mScrolledFrame->GetContent(), &displayport)) {
bool usingDisplayPort =
nsLayoutUtils::GetDisplayPort(mScrolledFrame->GetContent(), &displayport);
nsRegion childVisibleRegion;
if (usingDisplayPort) {
// The visible region for the children may be much bigger than the hole we
// are viewing the children from, so that the compositor process has enough
// content to asynchronously pan while content is being refreshed.
nsRegion childVisibleRegion = displayport + mScrollFrame->GetOffsetToCrossDoc(ReferenceFrame());
nsRect boundedRect =
childVisibleRegion.GetBounds().Intersect(mList.GetBounds(aBuilder));
nsRect allowExpansion = boundedRect.Intersect(aAllowVisibleRegionExpansion);
bool visible = mList.ComputeVisibilityForSublist(
aBuilder, &childVisibleRegion, boundedRect, allowExpansion);
// We don't allow this computation to influence aVisibleRegion, on the
// assumption that the layer can be asynchronously scrolled so we'll
// definitely need all the content under it.
mVisibleRect = boundedRect;
return visible;
childVisibleRegion = displayport + mScrollFrame->GetOffsetToCrossDoc(ReferenceFrame());
} else {
return nsDisplayWrapList::ComputeVisibility(aBuilder, aVisibleRegion,
aAllowVisibleRegionExpansion);
bool snap;
childVisibleRegion = GetBounds(aBuilder, &snap);
}
nsRect boundedRect =
childVisibleRegion.GetBounds().Intersect(mList.GetBounds(aBuilder));
nsRect allowExpansion = boundedRect.Intersect(aAllowVisibleRegionExpansion);
bool visible = mList.ComputeVisibilityForSublist(
aBuilder, &childVisibleRegion, boundedRect, allowExpansion);
// We don't allow this computation to influence aVisibleRegion, on the
// assumption that the layer can be asynchronously scrolled so we'll
// definitely need all the content under it.
return visible;
}
LayerState
@ -3668,6 +3680,12 @@ nsDisplayScrollInfoLayer::~nsDisplayScrollInfoLayer()
MOZ_COUNT_DTOR(nsDisplayScrollInfoLayer);
}
nsRect
nsDisplayScrollInfoLayer::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
{
return nsDisplayWrapList::GetBounds(aBuilder, aSnap);
}
LayerState
nsDisplayScrollInfoLayer::GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,

View File

@ -1512,6 +1512,8 @@ public:
bool DidComputeVisibility() const { return mDidComputeVisibility; }
#endif
nsRect GetVisibleRect() const { return mVisibleRect; }
private:
// This class is only used on stack, so we don't have to worry about leaking
// it. Don't let us be heap-allocated!
@ -2709,6 +2711,8 @@ public:
virtual ~nsDisplayScrollLayer();
#endif
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE;
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE;
@ -2760,6 +2764,8 @@ public:
virtual ~nsDisplayScrollInfoLayer();
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE;
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters) MOZ_OVERRIDE;