Bug 982888 - Populate the scroll parent field as appropriate. r=

This commit is contained in:
Kartikaya Gupta 2014-04-11 19:39:22 -04:00
Родитель f22e15107b
Коммит 1665cb02ce
4 изменённых файлов: 76 добавлений и 24 удалений

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

@ -505,6 +505,7 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
mCachedOffset(0, 0),
mGlassDisplayItem(nullptr),
mMode(aMode),
mCurrentScrollParentId(FrameMetrics::NULL_SCROLL_ID),
mBuildCaret(aBuildCaret),
mIgnoreSuppression(false),
mHadToIgnoreSuppression(false),
@ -3524,7 +3525,9 @@ nsDisplayOwnLayer::BuildLayer(nsDisplayListBuilder* aBuilder,
nsDisplaySubDocument::nsDisplaySubDocument(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, nsDisplayList* aList,
uint32_t aFlags)
: nsDisplayOwnLayer(aBuilder, aFrame, aList, aFlags) {
: nsDisplayOwnLayer(aBuilder, aFrame, aList, aFlags)
, mScrollParentId(aBuilder->GetCurrentScrollParentId())
{
MOZ_COUNT_CTOR(nsDisplaySubDocument);
}
@ -3574,6 +3577,7 @@ nsDisplaySubDocument::BuildLayer(nsDisplayListBuilder* aBuilder,
mFrame->GetPosition() +
mFrame->GetOffsetToCrossDoc(ReferenceFrame());
container->SetScrollHandoffParentId(mScrollParentId);
RecordFrameMetrics(mFrame, rootScrollFrame, ReferenceFrame(),
container, mList.GetVisibleRect(), viewport,
(usingDisplayport ? &displayport : nullptr),
@ -3779,6 +3783,7 @@ nsDisplayScrollLayer::nsDisplayScrollLayer(nsDisplayListBuilder* aBuilder,
: nsDisplayWrapList(aBuilder, aForFrame, aList)
, mScrollFrame(aScrollFrame)
, mScrolledFrame(aScrolledFrame)
, mScrollParentId(aBuilder->GetCurrentScrollParentId())
{
#ifdef NS_BUILD_REFCNT_LOGGING
MOZ_COUNT_CTOR(nsDisplayScrollLayer);
@ -3796,6 +3801,7 @@ nsDisplayScrollLayer::nsDisplayScrollLayer(nsDisplayListBuilder* aBuilder,
: nsDisplayWrapList(aBuilder, aForFrame, aItem)
, mScrollFrame(aScrollFrame)
, mScrolledFrame(aScrolledFrame)
, mScrollParentId(aBuilder->GetCurrentScrollParentId())
{
#ifdef NS_BUILD_REFCNT_LOGGING
MOZ_COUNT_CTOR(nsDisplayScrollLayer);
@ -3812,6 +3818,7 @@ nsDisplayScrollLayer::nsDisplayScrollLayer(nsDisplayListBuilder* aBuilder,
: nsDisplayWrapList(aBuilder, aForFrame)
, mScrollFrame(aScrollFrame)
, mScrolledFrame(aScrolledFrame)
, mScrollParentId(aBuilder->GetCurrentScrollParentId())
{
#ifdef NS_BUILD_REFCNT_LOGGING
MOZ_COUNT_CTOR(nsDisplayScrollLayer);
@ -3864,6 +3871,7 @@ nsDisplayScrollLayer::BuildLayer(nsDisplayListBuilder* aBuilder,
usingCriticalDisplayport =
nsLayoutUtils::GetCriticalDisplayPort(content, &criticalDisplayport);
}
layer->SetScrollHandoffParentId(mScrollParentId);
RecordFrameMetrics(mScrolledFrame, mScrollFrame, ReferenceFrame(), layer,
mList.GetVisibleRect(), viewport,
(usingDisplayport ? &displayport : nullptr),

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

@ -114,6 +114,7 @@ public:
typedef mozilla::DisplayListClipState DisplayListClipState;
typedef nsIWidget::ThemeGeometry ThemeGeometry;
typedef mozilla::layers::Layer Layer;
typedef mozilla::layers::FrameMetrics::ViewID ViewID;
/**
* @param aReferenceFrame the frame at the root of the subtree; its origin
@ -248,6 +249,10 @@ public:
* Get the scrollframe to ignore, if any.
*/
nsIFrame* GetIgnoreScrollFrame() { return mIgnoreScrollFrame; }
/**
* Get the ViewID of the nearest scrolling ancestor frame.
*/
ViewID GetCurrentScrollParentId() const { return mCurrentScrollParentId; }
/**
* Calling this setter makes us include all out-of-flow descendant
* frames in the display list, wherever they may be positioned (even
@ -602,6 +607,25 @@ public:
bool mOldValue;
};
/**
* A helper class to temporarily set the value of mCurrentScrollParentId.
*/
class AutoCurrentScrollParentIdSetter;
friend class AutoCurrentScrollParentIdSetter;
class AutoCurrentScrollParentIdSetter {
public:
AutoCurrentScrollParentIdSetter(nsDisplayListBuilder* aBuilder, ViewID aScrollId)
: mBuilder(aBuilder), mOldValue(aBuilder->mCurrentScrollParentId) {
aBuilder->mCurrentScrollParentId = aScrollId;
}
~AutoCurrentScrollParentIdSetter() {
mBuilder->mCurrentScrollParentId = mOldValue;
}
private:
nsDisplayListBuilder* mBuilder;
ViewID mOldValue;
};
// Helpers for tables
nsDisplayTableItem* GetCurrentTableItem() { return mCurrentTableItem; }
void SetCurrentTableItem(nsDisplayTableItem* aTableItem) { mCurrentTableItem = aTableItem; }
@ -706,6 +730,7 @@ private:
nsDisplayItem* mGlassDisplayItem;
nsTArray<DisplayItemClip*> mDisplayItemClipsToDestroy;
Mode mMode;
ViewID mCurrentScrollParentId;
bool mBuildCaret;
bool mIgnoreSuppression;
bool mHadToIgnoreSuppression;
@ -2834,6 +2859,8 @@ public:
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE;
NS_DISPLAY_DECL_NAME("SubDocument", TYPE_SUBDOCUMENT)
protected:
ViewID mScrollParentId;
};
/**
@ -2971,6 +2998,7 @@ public:
protected:
nsIFrame* mScrollFrame;
nsIFrame* mScrolledFrame;
ViewID mScrollParentId;
};
/**

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

@ -2523,8 +2523,41 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder,
dirtyRect = ExpandRect(dirtyRect);
}
// Since making new layers is expensive, only use nsDisplayScrollLayer
// if the area is scrollable and we're the content process (unless we're on
// B2G, where we support async scrolling for scrollable elements in the
// parent process as well).
// When a displayport is being used, force building of a layer so that
// CompositorParent can always find the scrollable layer for the root content
// document.
// If the element is marked 'scrollgrab', also force building of a layer
// so that APZ can implement scroll grabbing.
mShouldBuildScrollableLayer = usingDisplayport || nsContentUtils::HasScrollgrab(mOuter->GetContent());
bool shouldBuildLayer = false;
if (mShouldBuildScrollableLayer) {
shouldBuildLayer = true;
} else {
shouldBuildLayer =
nsLayoutUtils::WantSubAPZC() &&
WantAsyncScroll() &&
// If we are the root scroll frame for the display root then we don't need a scroll
// info layer to make a RecordFrameMetrics call for us as
// nsDisplayList::PaintForFrame already calls RecordFrameMetrics for us.
(!mIsRoot || aBuilder->RootReferenceFrame()->PresContext() != mOuter->PresContext());
}
nsDisplayListCollection scrolledContent;
{
// Note that setting the current scroll parent id here means that positioned children
// of this scroll info layer will pick up the scroll info layer as their scroll handoff
// parent. This is intentional because that is what happens for positioned children
// of scroll layers, and we want to maintain consistent behaviour between scroll layers
// and scroll info layers.
nsDisplayListBuilder::AutoCurrentScrollParentIdSetter idSetter(
aBuilder,
shouldBuildLayer && mScrolledFrame->GetContent()
? nsLayoutUtils::FindOrCreateIDFor(mScrolledFrame->GetContent())
: aBuilder->GetCurrentScrollParentId());
DisplayListClipState::AutoSaveRestore clipState(aBuilder);
if (usingDisplayport) {
@ -2585,29 +2618,6 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder,
}
}
// Since making new layers is expensive, only use nsDisplayScrollLayer
// if the area is scrollable and we're the content process (unless we're on
// B2G, where we support async scrolling for scrollable elements in the
// parent process as well).
// When a displayport is being used, force building of a layer so that
// CompositorParent can always find the scrollable layer for the root content
// document.
// If the element is marked 'scrollgrab', also force building of a layer
// so that APZ can implement scroll grabbing.
mShouldBuildScrollableLayer = usingDisplayport || nsContentUtils::HasScrollgrab(mOuter->GetContent());
bool shouldBuildLayer = false;
if (mShouldBuildScrollableLayer) {
shouldBuildLayer = true;
} else {
shouldBuildLayer =
nsLayoutUtils::WantSubAPZC() &&
WantAsyncScroll() &&
// If we are the root scroll frame for the display root then we don't need a scroll
// info layer to make a RecordFrameMetrics call for us as
// nsDisplayList::PaintForFrame already calls RecordFrameMetrics for us.
(!mIsRoot || aBuilder->RootReferenceFrame()->PresContext() != mOuter->PresContext());
}
if (shouldBuildLayer) {
// ScrollLayerWrapper must always be created because it initializes the
// scroll layer count. The display lists depend on this.

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

@ -436,6 +436,12 @@ nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
}
if (subdocRootFrame) {
nsDisplayListBuilder::AutoCurrentScrollParentIdSetter idSetter(
aBuilder,
ignoreViewportScrolling && subdocRootFrame->GetContent()
? nsLayoutUtils::FindOrCreateIDFor(subdocRootFrame->GetContent())
: aBuilder->GetCurrentScrollParentId());
aBuilder->SetAncestorHasTouchEventHandler(false);
subdocRootFrame->
BuildDisplayListForStackingContext(aBuilder, dirty, &childItems);