зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1102427 - Ensure scroll parents of an active scrollframe are layerized. r=tn
This commit is contained in:
Родитель
05c71da4ba
Коммит
53a4b66a34
|
@ -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 ==
|
||||
|
|
Загрузка…
Ссылка в новой задаче