diff --git a/layout/generic/nsGfxScrollFrame.h b/layout/generic/nsGfxScrollFrame.h index aa02373457e..1d56bec26e6 100644 --- a/layout/generic/nsGfxScrollFrame.h +++ b/layout/generic/nsGfxScrollFrame.h @@ -270,6 +270,7 @@ public: bool IsLTR() const; bool IsScrollbarOnRight() const; bool IsScrollingActive() const { return mScrollingActive || mShouldBuildScrollableLayer; } + bool IsProcessingAsyncScroll() const { return mAsyncScroll != nullptr; } void ResetScrollPositionForLayerPixelAlignment() { mScrollPosForLayerPixelAlignment = GetScrollPosition(); @@ -636,6 +637,9 @@ public: virtual bool IsScrollingActive() MOZ_OVERRIDE { return mHelper.IsScrollingActive(); } + virtual bool IsProcessingAsyncScroll() MOZ_OVERRIDE { + return mHelper.IsProcessingAsyncScroll(); + } virtual void ResetScrollPositionForLayerPixelAlignment() MOZ_OVERRIDE { mHelper.ResetScrollPositionForLayerPixelAlignment(); } @@ -934,6 +938,9 @@ public: virtual bool IsScrollingActive() MOZ_OVERRIDE { return mHelper.IsScrollingActive(); } + virtual bool IsProcessingAsyncScroll() MOZ_OVERRIDE { + return mHelper.IsProcessingAsyncScroll(); + } virtual void ResetScrollPositionForLayerPixelAlignment() MOZ_OVERRIDE { mHelper.ResetScrollPositionForLayerPixelAlignment(); } diff --git a/layout/generic/nsIScrollableFrame.h b/layout/generic/nsIScrollableFrame.h index ff05fa66de3..a0ba1721c79 100644 --- a/layout/generic/nsIScrollableFrame.h +++ b/layout/generic/nsIScrollableFrame.h @@ -250,6 +250,11 @@ public: * expectation that scrolling is going to happen. */ virtual bool IsScrollingActive() = 0; + /** + * Returns true if the scrollframe is currently processing an async + * or smooth scroll. + */ + virtual bool IsProcessingAsyncScroll() = 0; /** * Call this when the layer(s) induced by active scrolling are being * completely redrawn. diff --git a/widget/xpwidgets/APZCCallbackHelper.cpp b/widget/xpwidgets/APZCCallbackHelper.cpp index 0ccb9a8d455..43cb79c6ede 100644 --- a/widget/xpwidgets/APZCCallbackHelper.cpp +++ b/widget/xpwidgets/APZCCallbackHelper.cpp @@ -92,7 +92,9 @@ ScrollFrameTo(nsIScrollableFrame* aFrame, const CSSPoint& aPoint) return CSSPoint(); } - // If the scrollable frame got a scroll request from something other than us + // If the scrollable frame is currently in the middle of an async or smooth + // scroll then we don't want to interrupt it (see bug 961280). + // Also if the scrollable frame got a scroll request from something other than us // since the last layers update, then we don't want to push our scroll request // because we'll clobber that one, which is bad. // Note that content may have just finished sending a layers update with a scroll @@ -101,7 +103,8 @@ ScrollFrameTo(nsIScrollableFrame* aFrame, const CSSPoint& aPoint) // scroll offset. This is unavoidable because of the async communication between // APZ and content; however the code in NotifyLayersUpdated should reissue a new // repaint request to bring everything back into sync. - if (!aFrame->OriginOfLastScroll() || aFrame->OriginOfLastScroll() == nsGkAtoms::apz) { + if (!aFrame->IsProcessingAsyncScroll() && + (!aFrame->OriginOfLastScroll() || aFrame->OriginOfLastScroll() == nsGkAtoms::apz)) { aFrame->ScrollToCSSPixelsApproximate(aPoint, nsGkAtoms::apz); } // Return the final scroll position after setting it so that anything that relies