Bug 1402995 - Reflow scrollbars after partial reflow of scroll frame. r=tnikkel
MozReview-Commit-ID: 6ZuOkjfL1Jg
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -4652,17 +4652,17 @@ ScrollFrameHelper::UpdateScrollbarPositi
if (!weakFrame.IsAlive()) {
return;
}
}
mFrameIsUpdatingScrollbar = false;
}
-void ScrollFrameHelper::CurPosAttributeChanged(nsIContent* aContent)
+void ScrollFrameHelper::CurPosAttributeChanged(nsIContent* aContent, bool aDoScroll)
{
NS_ASSERTION(aContent, "aContent must not be null");
NS_ASSERTION((mHScrollbarBox && mHScrollbarBox->GetContent() == aContent) ||
(mVScrollbarBox && mVScrollbarBox->GetContent() == aContent),
"unexpected child");
// Attribute changes on the scrollbars happen in one of three ways:
// 1) The scrollbar changed the attribute in response to some user event
@@ -4708,19 +4708,22 @@ void ScrollFrameHelper::CurPosAttributeC
// see that the scroll position is not (yet) what they thought it
// was.
AutoWeakFrame weakFrame(mOuter);
UpdateScrollbarPosition();
if (!weakFrame.IsAlive()) {
return;
}
}
- ScrollToWithOrigin(dest,
- isSmooth ? nsIScrollableFrame::SMOOTH : nsIScrollableFrame::INSTANT,
- nsGkAtoms::scrollbars, &allowedRange);
+
+ if (aDoScroll) {
+ ScrollToWithOrigin(dest,
+ isSmooth ? nsIScrollableFrame::SMOOTH : nsIScrollableFrame::INSTANT,
+ nsGkAtoms::scrollbars, &allowedRange);
+ }
// 'this' might be destroyed here
}
/* ============= Scroll events ========== */
ScrollFrameHelper::ScrollEvent::ScrollEvent(ScrollFrameHelper* aHelper)
: Runnable("ScrollFrameHelper::ScrollEvent")
, mHelper(aHelper)
@@ -5307,34 +5310,38 @@ ScrollFrameHelper::FinishReflowForScroll
SetCoordAttribute(aContent, nsGkAtoms::increment, aIncrement);
}
bool
ScrollFrameHelper::ReflowFinished()
{
mPostedReflowCallback = false;
+ bool doScroll = true;
if (NS_SUBTREE_DIRTY(mOuter)) {
// We will get another call after the next reflow and scrolling
// later is less janky.
- return false;
+ doScroll = false;
}
nsAutoScriptBlocker scriptBlocker;
- ScrollToRestoredPosition();
-
- // Clamp current scroll position to new bounds. Normally this won't
- // do anything.
- nsPoint currentScrollPos = GetScrollPosition();
- ScrollToImpl(currentScrollPos, nsRect(currentScrollPos, nsSize(0, 0)));
- if (!mAsyncScroll && !mAsyncSmoothMSDScroll && !mApzSmoothScrollDestination) {
- // We need to have mDestination track the current scroll position,
- // in case it falls outside the new reflow area. mDestination is used
- // by ScrollBy as its starting position.
- mDestination = GetScrollPosition();
+
+ if (doScroll) {
+ ScrollToRestoredPosition();
+
+ // Clamp current scroll position to new bounds. Normally this won't
+ // do anything.
+ nsPoint currentScrollPos = GetScrollPosition();
+ ScrollToImpl(currentScrollPos, nsRect(currentScrollPos, nsSize(0, 0)));
+ if (!mAsyncScroll && !mAsyncSmoothMSDScroll && !mApzSmoothScrollDestination) {
+ // We need to have mDestination track the current scroll position,
+ // in case it falls outside the new reflow area. mDestination is used
+ // by ScrollBy as its starting position.
+ mDestination = GetScrollPosition();
+ }
}
if (!mUpdateScrollbarAttributes) {
return false;
}
mUpdateScrollbarAttributes = false;
// Update scrollbar attributes.
@@ -5416,18 +5423,19 @@ ScrollFrameHelper::ReflowFinished()
// mFrameIsUpdatingScrollbar and call CurPosAttributeChanged here.
// (It actually even works some of the time without this, thanks to
// nsSliderFrame::AttributeChanged's handling of maxpos, but not when
// we hide the scrollbar on a large size change, such as
// maximization.)
if (!mHScrollbarBox && !mVScrollbarBox)
return false;
CurPosAttributeChanged(mVScrollbarBox ? mVScrollbarBox->GetContent()
- : mHScrollbarBox->GetContent());
- return true;
+ : mHScrollbarBox->GetContent(),
+ doScroll);
+ return doScroll;
}
void
ScrollFrameHelper::ReflowCallbackCanceled()
{
mPostedReflowCallback = false;
}
--- a/layout/generic/nsGfxScrollFrame.h
+++ b/layout/generic/nsGfxScrollFrame.h
@@ -83,17 +83,17 @@ public:
// nsIReflowCallback
virtual bool ReflowFinished() override;
virtual void ReflowCallbackCanceled() override;
/**
* @note This method might destroy the frame, pres shell and other objects.
* Called when the 'curpos' attribute on one of the scrollbars changes.
*/
- void CurPosAttributeChanged(nsIContent* aChild);
+ void CurPosAttributeChanged(nsIContent* aChild, bool aDoScroll = true);
void PostScrollEvent();
void FireScrollEvent();
void PostScrolledAreaEvent();
void FireScrolledAreaEvent();
bool IsSmoothScrollingEnabled();