Bug 1363922 - Part 1: Remember about the reference frame during BuildDisplayList for ScrollFrameHelper so GetScrolledRect can use it. r=mstange
MozReview-Commit-ID: 8GO6xuSH5xY
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -3129,9 +3129,26 @@ public:
nsUnsetAttrRunnable(nsIContent* aContent, nsIAtom* aAttrName);
NS_DECL_NSIRUNNABLE
nsCOMPtr<nsIContent> mContent;
nsCOMPtr<nsIAtom> mAttrName;
};
+// This class allows you to easily set any pointer variable and ensure it's
+// set to nullptr when leaving its scope.
+template<typename T>
+class MOZ_RAII SetAndNullOnExit
+{
+public:
+ SetAndNullOnExit(T* &aVariable, T* aValue) {
+ aVariable = aValue;
+ mVariable = &aVariable;
+ }
+ ~SetAndNullOnExit() {
+ *mVariable = nullptr;
+ }
+private:
+ T** mVariable;
+};
+
#endif // nsLayoutUtils_h__
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -2001,16 +2001,17 @@ static uint32_t sScrollGenerationCounter
ScrollFrameHelper::ScrollFrameHelper(nsContainerFrame* aOuter,
bool aIsRoot)
: mHScrollbarBox(nullptr)
, mVScrollbarBox(nullptr)
, mScrolledFrame(nullptr)
, mScrollCornerBox(nullptr)
, mResizerBox(nullptr)
, mOuter(aOuter)
+ , mReferenceFrameDuringPainting(nullptr)
, mAsyncScroll(nullptr)
, mAsyncSmoothMSDScroll(nullptr)
, mLastScrollOrigin(nsGkAtoms::other)
, mAllowScrollOriginDowngrade(false)
, mLastSmoothScrollOrigin(nullptr)
, mScrollGeneration(++sScrollGenerationCounter)
, mDestination(0, 0)
, mScrollPosAtLastPaint(0, 0)
@@ -3264,16 +3265,17 @@ ClipListsExceptCaret(nsDisplayListCollec
ClipItemsExceptCaret(aLists->Outlines(), aBuilder, aClipFrame, aExtraClip, cache);
ClipItemsExceptCaret(aLists->Content(), aBuilder, aClipFrame, aExtraClip, cache);
}
void
ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aLists)
{
+ SetAndNullOnExit<const nsIFrame> tmpBuilder(mReferenceFrameDuringPainting, aBuilder->GetCurrentReferenceFrame());
if (aBuilder->IsForFrameVisibility()) {
NotifyApproximateFrameVisibilityUpdate(false);
}
mOuter->DisplayBorderBackgroundOutline(aBuilder, aLists);
if (aBuilder->IsPaintingToWindow()) {
mScrollPosAtLastPaint = GetScrollPosition();
@@ -5861,17 +5863,18 @@ ScrollFrameHelper::GetScrolledRect() con
// so we can skip all the work below.
return result;
}
// For that, we first convert the scroll port and the scrolled rect to rects
// relative to the reference frame, since that's the space where painting does
// snapping.
nsSize scrollPortSize = GetScrollPositionClampingScrollPortSize();
- nsIFrame* referenceFrame = nsLayoutUtils::GetReferenceFrame(mOuter);
+ const nsIFrame* referenceFrame =
+ mReferenceFrameDuringPainting ? mReferenceFrameDuringPainting : nsLayoutUtils::GetReferenceFrame(mOuter);
nsPoint toReferenceFrame = mOuter->GetOffsetToCrossDoc(referenceFrame);
nsRect scrollPort(mScrollPort.TopLeft() + toReferenceFrame, scrollPortSize);
nsRect scrolledRect = result + scrollPort.TopLeft();
if (scrollPort.Overflows() || scrolledRect.Overflows()) {
return result;
}
--- a/layout/generic/nsGfxScrollFrame.h
+++ b/layout/generic/nsGfxScrollFrame.h
@@ -482,16 +482,17 @@ public:
nsRevocableEventPtr<AsyncScrollPortEvent> mAsyncScrollPortEvent;
nsRevocableEventPtr<ScrolledAreaEvent> mScrolledAreaEvent;
nsIFrame* mHScrollbarBox;
nsIFrame* mVScrollbarBox;
nsIFrame* mScrolledFrame;
nsIFrame* mScrollCornerBox;
nsIFrame* mResizerBox;
nsContainerFrame* mOuter;
+ const nsIFrame* mReferenceFrameDuringPainting;
RefPtr<AsyncScroll> mAsyncScroll;
RefPtr<AsyncSmoothMSDScroll> mAsyncSmoothMSDScroll;
RefPtr<ScrollbarActivity> mScrollbarActivity;
nsTArray<nsIScrollPositionListener*> mListeners;
nsIAtom* mLastScrollOrigin;
bool mAllowScrollOriginDowngrade;
nsIAtom* mLastSmoothScrollOrigin;
Maybe<nsPoint> mApzSmoothScrollDestination;