Bug 1656802. Add state variables to the scroll frame to track when scrollbars are only created to scroll the visual viewport within the layout viewport. r=emilio,kats

We need to distinguish these special scrollbars for several different reasons in upcoming patches.

Differential Revision: https://phabricator.services.mozilla.com/D85702
This commit is contained in:
Timothy Nikkel 2020-08-07 10:03:33 +00:00
Родитель 738ce628b6
Коммит ba33b7857b
2 изменённых файлов: 39 добавлений и 2 удалений

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

@ -323,6 +323,13 @@ struct MOZ_STACK_CLASS ScrollReflowInput {
// Whether we decided to show the vertical scrollbar
MOZ_INIT_OUTSIDE_CTOR
bool mShowVScrollbar;
// If mShow(H|V)Scrollbar is true then
// mOnlyNeed(V|H)ScrollbarToScrollVVInsideLV indicates if the only reason we
// need that scrollbar is to scroll the visual viewport inside the layout
// viewport. These scrollbars are special in that even if they are layout
// scrollbars they do not take up any layout space.
bool mOnlyNeedHScrollbarToScrollVVInsideLV = false;
bool mOnlyNeedVScrollbarToScrollVVInsideLV = false;
ScrollReflowInput(nsIScrollableFrame* aFrame, const ReflowInput& aReflowInput)
: mReflowInput(aReflowInput),
@ -602,6 +609,7 @@ bool nsHTMLScrollFrame::TryLayout(ScrollReflowInput* aState,
vvChanged = true;
visualViewportSize.height -= hScrollbarPrefSize.height;
aState->mShowHScrollbar = true;
aState->mOnlyNeedHScrollbarToScrollVVInsideLV = true;
ROOT_SCROLLBAR_LOG("TryLayout added H scrollbar for VV, VV now %s\n",
Stringify(visualViewportSize).c_str());
}
@ -615,6 +623,7 @@ bool nsHTMLScrollFrame::TryLayout(ScrollReflowInput* aState,
vvChanged = true;
visualViewportSize.width -= vScrollbarPrefSize.width;
aState->mShowVScrollbar = true;
aState->mOnlyNeedVScrollbarToScrollVVInsideLV = true;
ROOT_SCROLLBAR_LOG("TryLayout added V scrollbar for VV, VV now %s\n",
Stringify(visualViewportSize).c_str());
}
@ -801,7 +810,12 @@ bool nsHTMLScrollFrame::GuessHScrollbarNeeded(const ScrollReflowInput& aState) {
// no guessing required
return aState.mHScrollbar == ShowScrollbar::Always;
}
return mHelper.mHasHorizontalScrollbar;
// We only care about scrollbars that might take up space when trying to guess
// if we need a scrollbar, so we ignore scrollbars only created to scroll the
// visual viewport inside the layout viewport because they take up no layout
// space.
return mHelper.mHasHorizontalScrollbar &&
!mHelper.mOnlyNeedHScrollbarToScrollVVInsideLV;
}
bool nsHTMLScrollFrame::GuessVScrollbarNeeded(const ScrollReflowInput& aState) {
@ -814,7 +828,12 @@ bool nsHTMLScrollFrame::GuessVScrollbarNeeded(const ScrollReflowInput& aState) {
// the state of the vertical scrollbar will be what we determined
// last time.
if (mHelper.mHadNonInitialReflow) {
return mHelper.mHasVerticalScrollbar;
// We only care about scrollbars that might take up space when trying to
// guess if we need a scrollbar, so we ignore scrollbars only created to
// scroll the visual viewport inside the layout viewport because they take
// up no layout space.
return mHelper.mHasVerticalScrollbar &&
!mHelper.mOnlyNeedVScrollbarToScrollVVInsideLV;
}
// If this is the initial reflow, guess false because usually
@ -1277,6 +1296,13 @@ void nsHTMLScrollFrame::Reflow(nsPresContext* aPresContext,
mHelper.mPostedReflowCallback = true;
}
bool didOnlyHScrollbar = mHelper.mOnlyNeedHScrollbarToScrollVVInsideLV;
bool didOnlyVScrollbar = mHelper.mOnlyNeedVScrollbarToScrollVVInsideLV;
mHelper.mOnlyNeedHScrollbarToScrollVVInsideLV =
state.mOnlyNeedHScrollbarToScrollVVInsideLV;
mHelper.mOnlyNeedVScrollbarToScrollVVInsideLV =
state.mOnlyNeedVScrollbarToScrollVVInsideLV;
bool didHaveHScrollbar = mHelper.mHasHorizontalScrollbar;
bool didHaveVScrollbar = mHelper.mHasVerticalScrollbar;
mHelper.mHasHorizontalScrollbar = state.mShowHScrollbar;
@ -1288,6 +1314,8 @@ void nsHTMLScrollFrame::Reflow(nsPresContext* aPresContext,
reflowScrollCorner || HasAnyStateBits(NS_FRAME_IS_DIRTY) ||
didHaveHScrollbar != state.mShowHScrollbar ||
didHaveVScrollbar != state.mShowVScrollbar ||
didOnlyHScrollbar != mHelper.mOnlyNeedHScrollbarToScrollVVInsideLV ||
didOnlyVScrollbar != mHelper.mOnlyNeedVScrollbarToScrollVVInsideLV ||
!oldScrollAreaBounds.IsEqualEdges(newScrollAreaBounds) ||
!oldScrolledAreaBounds.IsEqualEdges(newScrolledAreaBounds)) {
if (!mHelper.mSuppressScrollbarUpdate) {
@ -2214,6 +2242,8 @@ ScrollFrameHelper::ScrollFrameHelper(nsContainerFrame* aOuter, bool aIsRoot)
mNeverHasHorizontalScrollbar(false),
mHasVerticalScrollbar(false),
mHasHorizontalScrollbar(false),
mOnlyNeedVScrollbarToScrollVVInsideLV(false),
mOnlyNeedHScrollbarToScrollVVInsideLV(false),
mFrameIsUpdatingScrollbar(false),
mDidHistoryRestore(false),
mIsRoot(aIsRoot),

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

@ -630,6 +630,13 @@ class ScrollFrameHelper : public nsIReflowCallback {
bool mNeverHasHorizontalScrollbar : 1;
bool mHasVerticalScrollbar : 1;
bool mHasHorizontalScrollbar : 1;
// If mHas(Vertical|Horizontal)Scrollbar is true then
// mOnlyNeed(V|H)ScrollbarToScrollVVInsideLV indicates if the only reason we
// need that scrollbar is to scroll the visual viewport inside the layout
// viewport. These scrollbars are special in that even if they are layout
// scrollbars they do not take up any layout space.
bool mOnlyNeedVScrollbarToScrollVVInsideLV : 1;
bool mOnlyNeedHScrollbarToScrollVVInsideLV : 1;
bool mFrameIsUpdatingScrollbar : 1;
bool mDidHistoryRestore : 1;
// Is this the scrollframe for the document's viewport?