Bug 1102427 - Ensure scroll parents of an active scrollframe are layerized. r=tn

This commit is contained in:
Kartikaya Gupta 2015-02-24 01:24:04 -08:00
Родитель 05c71da4ba
Коммит 53a4b66a34
3 изменённых файлов: 53 добавлений и 2 удалений

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

@ -590,7 +590,8 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
mAncestorHasApzAwareEventHandler(false),
mHaveScrollableDisplayPort(false),
mWindowDraggingAllowed(false),
mIsBuildingForPopup(nsLayoutUtils::IsPopup(aReferenceFrame))
mIsBuildingForPopup(nsLayoutUtils::IsPopup(aReferenceFrame)),
mForceLayerForScrollParent(false)
{
MOZ_COUNT_CTOR(nsDisplayListBuilder);
PL_InitArenaPool(&mPool, "displayListArena", 1024,

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

@ -253,6 +253,13 @@ public:
* Get the ViewID of the nearest scrolling ancestor frame.
*/
ViewID GetCurrentScrollParentId() const { return mCurrentScrollParentId; }
/**
* Get and set the flag that indicates if scroll parents should have layers
* forcibly created. This flag is set when a deeply nested scrollframe has
* a displayport, and for scroll handoff to work properly the ancestor
* scrollframes should also get their own scrollable layers.
*/
void ForceLayerForScrollParent() { mForceLayerForScrollParent = true; }
/**
* Get the ViewID and the scrollbar flags corresponding to the scrollbar for
* which we are building display items at the moment.
@ -660,15 +667,41 @@ public:
class AutoCurrentScrollParentIdSetter {
public:
AutoCurrentScrollParentIdSetter(nsDisplayListBuilder* aBuilder, ViewID aScrollId)
: mBuilder(aBuilder), mOldValue(aBuilder->mCurrentScrollParentId) {
: mBuilder(aBuilder)
, mOldValue(aBuilder->mCurrentScrollParentId)
, mOldForceLayer(aBuilder->mForceLayerForScrollParent) {
// If this AutoCurrentScrollParentIdSetter has the same scrollId as the
// previous one on the stack, then that means the scrollframe that
// created this isn't actually scrollable and cannot participate in
// scroll handoff. We set mCanBeScrollParent to false to indicate this.
mCanBeScrollParent = (mOldValue != aScrollId);
aBuilder->mCurrentScrollParentId = aScrollId;
aBuilder->mForceLayerForScrollParent = false;
}
bool ShouldForceLayerForScrollParent() const {
// Only scrollframes participating in scroll handoff can be forced to
// layerize
return mCanBeScrollParent && mBuilder->mForceLayerForScrollParent;
};
~AutoCurrentScrollParentIdSetter() {
mBuilder->mCurrentScrollParentId = mOldValue;
if (mCanBeScrollParent) {
// If this flag is set, caller code is responsible for having dealt
// with the current value of mBuilder->mForceLayerForScrollParent, so
// we can just restore the old value.
mBuilder->mForceLayerForScrollParent = mOldForceLayer;
} else {
// Otherwise we need to keep propagating the force-layerization flag
// upwards to the next ancestor scrollframe that does participate in
// scroll handoff.
mBuilder->mForceLayerForScrollParent |= mOldForceLayer;
}
}
private:
nsDisplayListBuilder* mBuilder;
ViewID mOldValue;
bool mOldForceLayer;
bool mCanBeScrollParent;
};
/**
@ -919,6 +952,7 @@ private:
bool mHaveScrollableDisplayPort;
bool mWindowDraggingAllowed;
bool mIsBuildingForPopup;
bool mForceLayerForScrollParent;
};
class nsDisplayItem;

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

@ -3072,6 +3072,22 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder,
}
mOuter->BuildDisplayListForChild(aBuilder, mScrolledFrame, dirtyRect, scrolledContent);
if (idSetter.ShouldForceLayerForScrollParent() &&
!gfxPrefs::LayoutUseContainersForRootFrames())
{
// Note that forcing layerization of scroll parents follows the scroll
// handoff chain which is subject to the out-of-flow-frames caveat noted
// above (where the idSetter variable is created).
//
// This is not compatible when using containes for root scrollframes.
MOZ_ASSERT(shouldBuildLayer && mScrolledFrame->GetContent());
mShouldBuildScrollableLayer = true;
}
}
if (mShouldBuildScrollableLayer && !gfxPrefs::LayoutUseContainersForRootFrames()) {
aBuilder->ForceLayerForScrollParent();
}
if (MOZ_UNLIKELY(mOuter->StyleDisplay()->mOverflowClipBox ==