mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-30 00:01:50 +00:00
Bug 640048 Fix edge case for z-ordering for async scrollable elements r=roc
This commit is contained in:
parent
16c85e6947
commit
1b6808fa69
@ -189,7 +189,7 @@ static void UnmarkFrameForDisplay(nsIFrame* aFrame) {
|
||||
}
|
||||
|
||||
static void RecordFrameMetrics(nsIFrame* aForFrame,
|
||||
nsIFrame* aViewportFrame,
|
||||
nsIFrame* aScrollFrame,
|
||||
ContainerLayer* aRoot,
|
||||
nsRect aVisibleRect,
|
||||
nsRect aViewport,
|
||||
@ -209,8 +209,8 @@ static void RecordFrameMetrics(nsIFrame* aForFrame,
|
||||
}
|
||||
|
||||
nsIScrollableFrame* scrollableFrame = nsnull;
|
||||
if (aViewportFrame)
|
||||
scrollableFrame = aViewportFrame->GetScrollTargetFrame();
|
||||
if (aScrollFrame)
|
||||
scrollableFrame = aScrollFrame->GetScrollTargetFrame();
|
||||
|
||||
if (scrollableFrame) {
|
||||
nsSize contentSize =
|
||||
@ -464,6 +464,16 @@ nsDisplayList::ComputeVisibilityForSublist(nsDisplayListBuilder* aBuilder,
|
||||
continue;
|
||||
}
|
||||
|
||||
nsDisplayList* list = item->GetList();
|
||||
if (list && item->ShouldFlattenAway(aBuilder)) {
|
||||
// The elements on the list >= i no longer serve any use.
|
||||
elements.SetLength(i);
|
||||
list->FlattenTo(&elements);
|
||||
i = elements.Length();
|
||||
item->~nsDisplayItem();
|
||||
continue;
|
||||
}
|
||||
|
||||
nsRect bounds = item->GetBounds(aBuilder);
|
||||
|
||||
nsRegion itemVisible;
|
||||
@ -1496,6 +1506,11 @@ nsDisplayWrapList::nsDisplayWrapList(nsDisplayListBuilder* aBuilder,
|
||||
mList.AppendToTop(aItem);
|
||||
}
|
||||
|
||||
nsDisplayWrapList::nsDisplayWrapList(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aFrame)
|
||||
: nsDisplayItem(aBuilder, aFrame) {
|
||||
}
|
||||
|
||||
nsDisplayWrapList::~nsDisplayWrapList() {
|
||||
mList.DeleteAll();
|
||||
}
|
||||
@ -1761,18 +1776,60 @@ nsDisplayOwnLayer::BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||
nsDisplayScrollLayer::nsDisplayScrollLayer(nsDisplayListBuilder* aBuilder,
|
||||
nsDisplayList* aList,
|
||||
nsIFrame* aForFrame,
|
||||
nsIFrame* aViewportFrame)
|
||||
: nsDisplayOwnLayer(aBuilder, aForFrame, aList)
|
||||
, mViewportFrame(aViewportFrame)
|
||||
nsIFrame* aScrolledFrame,
|
||||
nsIFrame* aScrollFrame)
|
||||
: nsDisplayWrapList(aBuilder, aForFrame, aList)
|
||||
, mScrollFrame(aScrollFrame)
|
||||
, mScrolledFrame(aScrolledFrame)
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
MOZ_COUNT_CTOR(nsDisplayScrollLayer);
|
||||
#endif
|
||||
|
||||
NS_ASSERTION(mFrame && mFrame->GetContent(),
|
||||
NS_ASSERTION(mScrolledFrame && mScrolledFrame->GetContent(),
|
||||
"Need a child frame with content");
|
||||
}
|
||||
|
||||
nsDisplayScrollLayer::nsDisplayScrollLayer(nsDisplayListBuilder* aBuilder,
|
||||
nsDisplayItem* aItem,
|
||||
nsIFrame* aForFrame,
|
||||
nsIFrame* aScrolledFrame,
|
||||
nsIFrame* aScrollFrame)
|
||||
: nsDisplayWrapList(aBuilder, aForFrame, aItem)
|
||||
, mScrollFrame(aScrollFrame)
|
||||
, mScrolledFrame(aScrolledFrame)
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
MOZ_COUNT_CTOR(nsDisplayScrollLayer);
|
||||
#endif
|
||||
|
||||
NS_ASSERTION(mScrolledFrame && mScrolledFrame->GetContent(),
|
||||
"Need a child frame with content");
|
||||
}
|
||||
|
||||
nsDisplayScrollLayer::nsDisplayScrollLayer(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aForFrame,
|
||||
nsIFrame* aScrolledFrame,
|
||||
nsIFrame* aScrollFrame)
|
||||
: nsDisplayWrapList(aBuilder, aForFrame)
|
||||
, mScrollFrame(aScrollFrame)
|
||||
, mScrolledFrame(aScrolledFrame)
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
MOZ_COUNT_CTOR(nsDisplayScrollLayer);
|
||||
#endif
|
||||
|
||||
NS_ASSERTION(mScrolledFrame && mScrolledFrame->GetContent(),
|
||||
"Need a child frame with content");
|
||||
}
|
||||
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
nsDisplayScrollLayer::~nsDisplayScrollLayer()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsDisplayScrollLayer);
|
||||
}
|
||||
#endif
|
||||
|
||||
already_AddRefed<Layer>
|
||||
nsDisplayScrollLayer::BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager) {
|
||||
@ -1781,19 +1838,19 @@ nsDisplayScrollLayer::BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||
|
||||
// Get the already set unique ID for scrolling this content remotely.
|
||||
// Or, if not set, generate a new ID.
|
||||
nsIContent* content = mFrame->GetContent();
|
||||
nsIContent* content = mScrolledFrame->GetContent();
|
||||
ViewID scrollId = nsLayoutUtils::FindIDFor(content);
|
||||
|
||||
nsRect viewport = mViewportFrame->GetRect() -
|
||||
mViewportFrame->GetPosition() +
|
||||
aBuilder->ToReferenceFrame(mViewportFrame);
|
||||
nsRect viewport = mScrollFrame->GetRect() -
|
||||
mScrollFrame->GetPosition() +
|
||||
aBuilder->ToReferenceFrame(mScrollFrame);
|
||||
|
||||
bool usingDisplayport = false;
|
||||
nsRect displayport;
|
||||
if (content) {
|
||||
usingDisplayport = nsLayoutUtils::GetDisplayPort(content, &displayport);
|
||||
}
|
||||
RecordFrameMetrics(mFrame, mViewportFrame, layer, mVisibleRect, viewport,
|
||||
RecordFrameMetrics(mScrolledFrame, mScrollFrame, layer, mVisibleRect, viewport,
|
||||
(usingDisplayport ? &displayport : nsnull), scrollId);
|
||||
|
||||
return layer.forget();
|
||||
@ -1806,12 +1863,12 @@ nsDisplayScrollLayer::ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
PRBool& aContainsRootContentDocBG)
|
||||
{
|
||||
nsRect displayport;
|
||||
if (nsLayoutUtils::GetDisplayPort(mFrame->GetContent(), &displayport)) {
|
||||
if (nsLayoutUtils::GetDisplayPort(mScrolledFrame->GetContent(), &displayport)) {
|
||||
// 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 + aBuilder->ToReferenceFrame(mViewportFrame);
|
||||
nsRegion childVisibleRegion = displayport + aBuilder->ToReferenceFrame(mScrollFrame);
|
||||
|
||||
nsRect boundedRect;
|
||||
boundedRect.IntersectRect(childVisibleRegion.GetBounds(), mList.GetBounds(aBuilder));
|
||||
@ -1824,25 +1881,82 @@ nsDisplayScrollLayer::ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
return visible;
|
||||
|
||||
} else {
|
||||
return nsDisplayOwnLayer::ComputeVisibility(aBuilder, aVisibleRegion,
|
||||
return nsDisplayWrapList::ComputeVisibility(aBuilder, aVisibleRegion,
|
||||
aAllowVisibleRegionExpansion,
|
||||
aContainsRootContentDocBG);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
nsDisplayScrollLayer::~nsDisplayScrollLayer()
|
||||
LayerState
|
||||
nsDisplayScrollLayer::GetLayerState(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager)
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsDisplayScrollLayer);
|
||||
// Force this as a layer so we can scroll asynchronously.
|
||||
// This causes incorrect rendering for rounded clips!
|
||||
return LAYER_ACTIVE_FORCE;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsDisplayScrollLayer::TryMerge(nsDisplayListBuilder* aBuilder,
|
||||
nsDisplayItem* aItem)
|
||||
{
|
||||
if (aItem->GetType() != TYPE_SCROLL_LAYER) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsDisplayScrollLayer* other = static_cast<nsDisplayScrollLayer*>(aItem);
|
||||
if (other->mScrolledFrame != this->mScrolledFrame) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
FrameProperties props = mScrolledFrame->Properties();
|
||||
props.Set(nsIFrame::ScrollLayerCount(),
|
||||
reinterpret_cast<void*>(GetScrollLayerCount() - 1));
|
||||
|
||||
mList.AppendToBottom(&other->mList);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsDisplayScrollLayer::ShouldFlattenAway(nsDisplayListBuilder* aBuilder)
|
||||
{
|
||||
return GetScrollLayerCount() > 1;
|
||||
}
|
||||
|
||||
PRWord
|
||||
nsDisplayScrollLayer::GetScrollLayerCount()
|
||||
{
|
||||
FrameProperties props = mScrolledFrame->Properties();
|
||||
#ifdef DEBUG
|
||||
PRBool hasCount = PR_FALSE;
|
||||
PRWord result = reinterpret_cast<PRWord>(
|
||||
props.Get(nsIFrame::ScrollLayerCount(), &hasCount));
|
||||
// If this aborts, then the property was either not added before scroll
|
||||
// layers were created or the property was deleted to early. If the latter,
|
||||
// make sure that nsDisplayScrollInfoLayer is on the bottom of the list so
|
||||
// that it is processed last.
|
||||
NS_ABORT_IF_FALSE(hasCount, "nsDisplayScrollLayer should always be defined");
|
||||
return result;
|
||||
#else
|
||||
return reinterpret_cast<PRWord>(props.Get(nsIFrame::ScrollLayerCount()));
|
||||
#endif
|
||||
}
|
||||
|
||||
PRWord
|
||||
nsDisplayScrollLayer::RemoveScrollLayerCount()
|
||||
{
|
||||
PRWord result = GetScrollLayerCount();
|
||||
FrameProperties props = mScrolledFrame->Properties();
|
||||
props.Remove(nsIFrame::ScrollLayerCount());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
nsDisplayScrollInfoLayer::nsDisplayScrollInfoLayer(
|
||||
nsDisplayListBuilder* aBuilder,
|
||||
nsDisplayList* aList,
|
||||
nsIFrame* aForFrame,
|
||||
nsIFrame* aViewportFrame)
|
||||
: nsDisplayScrollLayer(aBuilder, aList, aForFrame, aViewportFrame)
|
||||
nsIFrame* aScrolledFrame,
|
||||
nsIFrame* aScrollFrame)
|
||||
: nsDisplayScrollLayer(aBuilder, aScrolledFrame, aScrolledFrame, aScrollFrame)
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
MOZ_COUNT_CTOR(nsDisplayScrollInfoLayer);
|
||||
@ -1856,6 +1970,30 @@ nsDisplayScrollInfoLayer::~nsDisplayScrollInfoLayer()
|
||||
}
|
||||
#endif
|
||||
|
||||
LayerState
|
||||
nsDisplayScrollInfoLayer::GetLayerState(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager)
|
||||
{
|
||||
return LAYER_ACTIVE_EMPTY;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsDisplayScrollInfoLayer::TryMerge(nsDisplayListBuilder* aBuilder,
|
||||
nsDisplayItem* aItem)
|
||||
{
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsDisplayScrollInfoLayer::ShouldFlattenAway(nsDisplayListBuilder* aBuilder)
|
||||
{
|
||||
// Layer metadata for a particular scroll frame needs to be unique. Only
|
||||
// one nsDisplayScrollLayer (with rendered content) or one
|
||||
// nsDisplayScrollInfoLayer (with only the metadata) should survive the
|
||||
// visibility computation.
|
||||
return RemoveScrollLayerCount() == 1;
|
||||
}
|
||||
|
||||
nsDisplayClip::nsDisplayClip(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aFrame, nsDisplayItem* aItem,
|
||||
const nsRect& aRect)
|
||||
|
@ -750,7 +750,17 @@ public:
|
||||
virtual PRBool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* During the visibility computation and after TryMerge, display lists may
|
||||
* return PR_TRUE here to flatten themselves away, removing them. This
|
||||
* flattening is distinctly different from FlattenTo, which occurs before
|
||||
* items are merged together.
|
||||
*/
|
||||
virtual PRBool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* If this is a leaf item we return null, otherwise we return the wrapped
|
||||
* list.
|
||||
@ -1656,6 +1666,7 @@ public:
|
||||
nsDisplayList* aList);
|
||||
nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
|
||||
nsDisplayItem* aItem);
|
||||
nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame);
|
||||
virtual ~nsDisplayWrapList();
|
||||
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
|
||||
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
|
||||
@ -1788,9 +1799,9 @@ public:
|
||||
};
|
||||
|
||||
/**
|
||||
* This creates a layer for the given list of items, whose visibility is
|
||||
* determined by the displayport for the given frame instead of what is
|
||||
* passed in to ComputeVisibility.
|
||||
* This potentially creates a layer for the given list of items, whose
|
||||
* visibility is determined by the displayport for the given frame instead of
|
||||
* what is passed in to ComputeVisibility.
|
||||
*
|
||||
* Here in content, we can use this to render more content than is actually
|
||||
* visible. Then, the compositing process can manipulate the generated layer
|
||||
@ -1799,17 +1810,34 @@ public:
|
||||
* Note that setting the displayport will not change any hit testing! The
|
||||
* content process will know nothing about what the user is actually seeing,
|
||||
* so it can only do hit testing for what is supposed to be the visible region.
|
||||
*
|
||||
* It is possible for scroll boxes to have content that can be both above and
|
||||
* below content outside of the scroll box. We cannot create layers for these
|
||||
* cases. This is accomplished by wrapping display items with
|
||||
* nsDisplayScrollLayers. nsDisplayScrollLayers with the same scroll frame will
|
||||
* be merged together. If more than one nsDisplayScrollLayer exists after
|
||||
* merging, all nsDisplayScrollLayers will be flattened out so that no new
|
||||
* layer is created at all.
|
||||
*/
|
||||
class nsDisplayScrollLayer : public nsDisplayOwnLayer
|
||||
class nsDisplayScrollLayer : public nsDisplayWrapList
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @param aForFrame This will determine what the displayport is. It should be
|
||||
* the root content frame of the scrolled area.
|
||||
* @param aViewportFrame The viewport frame you see this content through.
|
||||
* @param aScrolledFrame This will determine what the displayport is. It should be
|
||||
* the root content frame of the scrolled area. Note
|
||||
* that nsDisplayScrollLayer will expect for
|
||||
* ScrollLayerCount to be defined on aScrolledFrame.
|
||||
* @param aScrollFrame The viewport frame you see this content through.
|
||||
*/
|
||||
nsDisplayScrollLayer(nsDisplayListBuilder* aBuilder, nsDisplayList* aList,
|
||||
nsIFrame* aForFrame, nsIFrame* aViewportFrame);
|
||||
nsIFrame* aForFrame, nsIFrame* aScrolledFrame,
|
||||
nsIFrame* aScrollFrame);
|
||||
nsDisplayScrollLayer(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem,
|
||||
nsIFrame* aForFrame, nsIFrame* aScrolledFrame,
|
||||
nsIFrame* aScrollFrame);
|
||||
nsDisplayScrollLayer(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aForFrame, nsIFrame* aScrolledFrame,
|
||||
nsIFrame* aScrollFrame);
|
||||
NS_DISPLAY_DECL_NAME("ScrollLayer", TYPE_SCROLL_LAYER)
|
||||
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
@ -1825,26 +1853,40 @@ public:
|
||||
PRBool& aContainsRootContentDocBG);
|
||||
|
||||
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager)
|
||||
{
|
||||
// Force this as a layer so we can scroll asynchronously.
|
||||
// This causes incorrect rendering for rounded clips!
|
||||
return mozilla::LAYER_ACTIVE_FORCE;
|
||||
}
|
||||
LayerManager* aManager);
|
||||
|
||||
virtual PRBool TryMerge(nsDisplayListBuilder* aBuilder,
|
||||
nsDisplayItem* aItem);
|
||||
|
||||
virtual PRBool ShouldFlattenAway(nsDisplayListBuilder* aBuilder);
|
||||
|
||||
// Get the number of nsDisplayScrollLayers for a scroll frame. Note that this
|
||||
// number does not include nsDisplayScrollInfoLayers. If this number is not 1
|
||||
// after merging, all the nsDisplayScrollLayers should flatten away.
|
||||
PRWord GetScrollLayerCount();
|
||||
PRWord RemoveScrollLayerCount();
|
||||
|
||||
private:
|
||||
nsIFrame* mViewportFrame;
|
||||
nsIFrame* mScrollFrame;
|
||||
nsIFrame* mScrolledFrame;
|
||||
};
|
||||
|
||||
/**
|
||||
* Like nsDisplayScrollLayer, but only has metadata on the scroll frame. This
|
||||
* creates a layer that has no Thebes child layer, but still allows the
|
||||
* compositor process to know of the scroll frame's existence.
|
||||
*
|
||||
* After visibility computation, nsDisplayScrollInfoLayers should only exist if
|
||||
* nsDisplayScrollLayers were all flattened away.
|
||||
*
|
||||
* Important!! Add info layers to the bottom of the list so they are only
|
||||
* considered after the others have flattened out!
|
||||
*/
|
||||
class nsDisplayScrollInfoLayer : public nsDisplayScrollLayer
|
||||
{
|
||||
public:
|
||||
nsDisplayScrollInfoLayer(nsDisplayListBuilder* aBuilder, nsDisplayList* aList,
|
||||
nsIFrame* aForFrame, nsIFrame* aViewportFrame);
|
||||
nsDisplayScrollInfoLayer(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aScrolledFrame, nsIFrame* aScrollFrame);
|
||||
NS_DISPLAY_DECL_NAME("ScrollInfoLayer", TYPE_SCROLL_INFO_LAYER)
|
||||
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
@ -1852,11 +1894,12 @@ public:
|
||||
#endif
|
||||
|
||||
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager)
|
||||
{
|
||||
return mozilla::LAYER_ACTIVE_EMPTY;
|
||||
}
|
||||
LayerManager* aManager);
|
||||
|
||||
virtual PRBool TryMerge(nsDisplayListBuilder* aBuilder,
|
||||
nsDisplayItem* aItem);
|
||||
|
||||
virtual PRBool ShouldFlattenAway(nsDisplayListBuilder* aBuilder);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1905,6 +1905,43 @@ nsGfxScrollFrameInner::ShouldBuildLayer() const
|
||||
return mShouldBuildLayer;
|
||||
}
|
||||
|
||||
class ScrollLayerWrapper : public nsDisplayWrapper
|
||||
{
|
||||
public:
|
||||
ScrollLayerWrapper(nsIFrame* aScrollFrame, nsIFrame* aScrolledFrame)
|
||||
: mCount(0)
|
||||
, mProps(aScrolledFrame->Properties())
|
||||
, mScrollFrame(aScrollFrame)
|
||||
, mScrolledFrame(aScrolledFrame)
|
||||
{
|
||||
SetCount(0);
|
||||
}
|
||||
|
||||
virtual nsDisplayItem* WrapList(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aFrame,
|
||||
nsDisplayList* aList) {
|
||||
SetCount(++mCount);
|
||||
return new (aBuilder) nsDisplayScrollLayer(aBuilder, aList, nsnull, mScrolledFrame, mScrollFrame);
|
||||
}
|
||||
|
||||
virtual nsDisplayItem* WrapItem(nsDisplayListBuilder* aBuilder,
|
||||
nsDisplayItem* aItem) {
|
||||
|
||||
SetCount(++mCount);
|
||||
return new (aBuilder) nsDisplayScrollLayer(aBuilder, aItem, aItem->GetUnderlyingFrame(), mScrolledFrame, mScrollFrame);
|
||||
}
|
||||
|
||||
protected:
|
||||
void SetCount(PRWord aCount) {
|
||||
mProps.Set(nsIFrame::ScrollLayerCount(), reinterpret_cast<void*>(aCount));
|
||||
}
|
||||
|
||||
PRWord mCount;
|
||||
FrameProperties mProps;
|
||||
nsIFrame* mScrollFrame;
|
||||
nsIFrame* mScrolledFrame;
|
||||
};
|
||||
|
||||
nsresult
|
||||
nsGfxScrollFrameInner::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
const nsRect& aDirtyRect,
|
||||
@ -1965,16 +2002,11 @@ nsGfxScrollFrameInner::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
nsLayoutUtils::GetDisplayPort(mOuter->GetContent(), &dirtyRect);
|
||||
|
||||
nsDisplayListCollection set;
|
||||
rv = mOuter->BuildDisplayListForChild(aBuilder, mScrolledFrame, dirtyRect, set);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Since making new layers is expensive, only use nsDisplayScrollLayer
|
||||
// if the area is scrollable.
|
||||
//
|
||||
// Scroll frames can be generated with a scroll range that is 0, 0.
|
||||
// Furthermore, it is not worth the memory tradeoff to allow asynchronous
|
||||
// scrolling of small scroll frames. We use an arbitrary minimum scroll
|
||||
// range of 20 pixels to eliminate many gfx scroll frames from becoming a
|
||||
// layer.
|
||||
//
|
||||
nsRect scrollRange = GetScrollRange();
|
||||
ScrollbarStyles styles = GetScrollbarStylesFromFrame();
|
||||
mShouldBuildLayer =
|
||||
@ -1986,37 +2018,25 @@ nsGfxScrollFrameInner::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
(!mIsRoot || !mOuter->PresContext()->IsRootContentDocument()));
|
||||
|
||||
if (ShouldBuildLayer()) {
|
||||
nsDisplayList list;
|
||||
// ScrollLayerWrapper must always be created because it initializes the
|
||||
// scroll layer count. The display lists depend on this.
|
||||
ScrollLayerWrapper wrapper(mOuter, mScrolledFrame);
|
||||
|
||||
if (usingDisplayport) {
|
||||
// Once a displayport is set, assume that scrolling needs to be fast
|
||||
// so create a layer with all the content inside. The compositor
|
||||
// process will be able to scroll the content asynchronously.
|
||||
//
|
||||
// Note that using StackingContext breaks z order, so the resulting
|
||||
// rendering can be incorrect for weird edge cases!
|
||||
|
||||
rv = mScrolledFrame->BuildDisplayListForStackingContext(
|
||||
aBuilder, dirtyRect + mOuter->GetOffsetTo(mScrolledFrame), &list);
|
||||
|
||||
nsDisplayScrollLayer* layerItem = new (aBuilder) nsDisplayScrollLayer(
|
||||
aBuilder, &list, mScrolledFrame, mOuter);
|
||||
set.Content()->AppendNewToTop(layerItem);
|
||||
} else {
|
||||
// If there is no displayport set, there is no reason here to force a
|
||||
// layer that needs a memory-expensive allocation, but the compositor
|
||||
// process would still like to know that it exists.
|
||||
|
||||
nsDisplayScrollLayer* layerItem = new (aBuilder) nsDisplayScrollInfoLayer(
|
||||
aBuilder, &list, mScrolledFrame, mOuter);
|
||||
set.Content()->AppendNewToTop(layerItem);
|
||||
|
||||
rv = mOuter->BuildDisplayListForChild(aBuilder, mScrolledFrame, dirtyRect, set);
|
||||
wrapper.WrapListsInPlace(aBuilder, mOuter, set);
|
||||
}
|
||||
} else {
|
||||
rv = mOuter->BuildDisplayListForChild(aBuilder, mScrolledFrame, dirtyRect, set);
|
||||
|
||||
// In case we are not using displayport or the nsDisplayScrollLayers are
|
||||
// flattened during visibility computation, we still need to export the
|
||||
// metadata about this scroll box to the compositor process.
|
||||
nsDisplayScrollInfoLayer* layerItem = new (aBuilder) nsDisplayScrollInfoLayer(
|
||||
aBuilder, mScrolledFrame, mOuter);
|
||||
set.Content()->AppendNewToBottom(layerItem);
|
||||
}
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsRect clip;
|
||||
clip = mScrollPort + aBuilder->ToReferenceFrame(mOuter);
|
||||
|
||||
|
@ -894,6 +894,8 @@ public:
|
||||
NS_DECLARE_FRAME_PROPERTY(UsedPaddingProperty, DestroyMargin)
|
||||
NS_DECLARE_FRAME_PROPERTY(UsedBorderProperty, DestroyMargin)
|
||||
|
||||
NS_DECLARE_FRAME_PROPERTY(ScrollLayerCount, nsnull)
|
||||
|
||||
/**
|
||||
* Return the distance between the border edge of the frame and the
|
||||
* margin edge of the frame. Like GetRect(), returns the dimensions
|
||||
|
Loading…
Reference in New Issue
Block a user