diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp index 059ccd87b163..1cb573a0d631 100644 --- a/dom/base/nsDOMWindowUtils.cpp +++ b/dom/base/nsDOMWindowUtils.cpp @@ -558,8 +558,10 @@ nsDOMWindowUtils::GetScrollbarSizes(Element* aElement, return NS_ERROR_INVALID_ARG; } - CSSIntMargin scrollbarSizes = RoundedToInt( - CSSMargin::FromAppUnits(scrollFrame->GetActualScrollbarSizes())); + CSSIntMargin scrollbarSizes = + RoundedToInt(CSSMargin::FromAppUnits(scrollFrame->GetActualScrollbarSizes( + nsIScrollableFrame::ScrollbarSizesOptions:: + INCLUDE_VISUAL_VIEWPORT_SCROLLBARS))); *aOutVerticalScrollbarWidth = scrollbarSizes.LeftRight(); *aOutHorizontalScrollbarHeight = scrollbarSizes.TopBottom(); diff --git a/dom/interfaces/base/nsIDOMWindowUtils.idl b/dom/interfaces/base/nsIDOMWindowUtils.idl index 2e3a54bf94f3..6b884d42bb69 100644 --- a/dom/interfaces/base/nsIDOMWindowUtils.idl +++ b/dom/interfaces/base/nsIDOMWindowUtils.idl @@ -205,6 +205,11 @@ interface nsIDOMWindowUtils : nsISupports { * Note that on some platforms, scrollbars don't take up layout space * ("overlay scrollbars"). On such platforms, the returned sizes are * always zero. + * + * Layout scrollbars that normally take up space but were only shown to + * scroll the visual viewport inside the layout viewport (the layout viewport + * cannot be scrolled) do not take up space but they still return their size + * from this function. */ void getScrollbarSizes(in Element aElement, out uint32_t aVerticalScrollbarWidth, diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 757aeb95277d..b39b8df5fba1 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -8798,7 +8798,9 @@ nsMargin nsLayoutUtils::ScrollbarAreaToExcludeFromCompositionBoundsFor( if (!scrollableFrame) { return nsMargin(); } - return scrollableFrame->GetActualScrollbarSizes(); + return scrollableFrame->GetActualScrollbarSizes( + nsIScrollableFrame::ScrollbarSizesOptions:: + INCLUDE_VISUAL_VIEWPORT_SCROLLBARS); } /* static */ diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index ad2438bb013b..a382dadd306f 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -6905,11 +6905,38 @@ nsRect ScrollFrameHelper::GetUnsnappedScrolledRectInternal( aScrollPortSize, GetScrolledFrameDir()); } -nsMargin ScrollFrameHelper::GetActualScrollbarSizes() const { +nsMargin ScrollFrameHelper::GetActualScrollbarSizes( + nsIScrollableFrame::ScrollbarSizesOptions + aOptions /* = nsIScrollableFrame::ScrollbarSizesOptions::NONE */) + const { nsRect r = mOuter->GetPaddingRectRelativeToSelf(); - return nsMargin(mScrollPort.y - r.y, r.XMost() - mScrollPort.XMost(), - r.YMost() - mScrollPort.YMost(), mScrollPort.x - r.x); + nsMargin m(mScrollPort.y - r.y, r.XMost() - mScrollPort.XMost(), + r.YMost() - mScrollPort.YMost(), mScrollPort.x - r.x); + + if (aOptions == nsIScrollableFrame::ScrollbarSizesOptions:: + INCLUDE_VISUAL_VIEWPORT_SCROLLBARS && + !UsesOverlayScrollbars()) { + // If we are using layout scrollbars and they only exist to scroll the + // visual viewport then they do not take up any layout space (so the + // scrollport is the same as the padding rect) but they do cover everything + // below them so some callers may want to include this special type of + // scrollbars in the returned value. + if (mHScrollbarBox && mHasHorizontalScrollbar && + mOnlyNeedHScrollbarToScrollVVInsideLV) { + m.bottom += mHScrollbarBox->GetRect().height; + } + if (mVScrollbarBox && mHasVerticalScrollbar && + mOnlyNeedVScrollbarToScrollVVInsideLV) { + if (IsScrollbarOnRight()) { + m.right += mVScrollbarBox->GetRect().width; + } else { + m.left += mVScrollbarBox->GetRect().width; + } + } + } + + return m; } void ScrollFrameHelper::SetScrollbarVisibility(nsIFrame* aScrollbar, diff --git a/layout/generic/nsGfxScrollFrame.h b/layout/generic/nsGfxScrollFrame.h index c3bb32ccdb31..285c4fd085be 100644 --- a/layout/generic/nsGfxScrollFrame.h +++ b/layout/generic/nsGfxScrollFrame.h @@ -344,7 +344,9 @@ class ScrollFrameHelper : public nsIReflowCallback { return (mHasVerticalScrollbar ? nsIScrollableFrame::VERTICAL : 0) | (mHasHorizontalScrollbar ? nsIScrollableFrame::HORIZONTAL : 0); } - nsMargin GetActualScrollbarSizes() const; + nsMargin GetActualScrollbarSizes( + nsIScrollableFrame::ScrollbarSizesOptions aOptions = + nsIScrollableFrame::ScrollbarSizesOptions::NONE) const; nsMargin GetDesiredScrollbarSizes(nsBoxLayoutState* aState); nscoord GetNondisappearingScrollbarWidth(nsBoxLayoutState* aState, mozilla::WritingMode aVerticalWM); @@ -905,8 +907,10 @@ class nsHTMLScrollFrame : public nsContainerFrame, uint32_t GetScrollbarVisibility() const final { return mHelper.GetScrollbarVisibility(); } - nsMargin GetActualScrollbarSizes() const final { - return mHelper.GetActualScrollbarSizes(); + nsMargin GetActualScrollbarSizes( + nsIScrollableFrame::ScrollbarSizesOptions aOptions = + nsIScrollableFrame::ScrollbarSizesOptions::NONE) const final { + return mHelper.GetActualScrollbarSizes(aOptions); } nsMargin GetDesiredScrollbarSizes(nsBoxLayoutState* aState) final { return mHelper.GetDesiredScrollbarSizes(aState); @@ -1385,8 +1389,10 @@ class nsXULScrollFrame final : public nsBoxFrame, uint32_t GetScrollbarVisibility() const final { return mHelper.GetScrollbarVisibility(); } - nsMargin GetActualScrollbarSizes() const final { - return mHelper.GetActualScrollbarSizes(); + nsMargin GetActualScrollbarSizes( + nsIScrollableFrame::ScrollbarSizesOptions aOptions = + nsIScrollableFrame::ScrollbarSizesOptions::NONE) const final { + return mHelper.GetActualScrollbarSizes(aOptions); } nsMargin GetDesiredScrollbarSizes(nsBoxLayoutState* aState) final { return mHelper.GetDesiredScrollbarSizes(aState); diff --git a/layout/generic/nsIScrollableFrame.h b/layout/generic/nsIScrollableFrame.h index 59c0dea40a0a..48f7abbdab2d 100644 --- a/layout/generic/nsIScrollableFrame.h +++ b/layout/generic/nsIScrollableFrame.h @@ -114,8 +114,14 @@ class nsIScrollableFrame : public nsIScrollbarMediator { * positions that don't have a scrollbar or where the scrollbar is not * visible. Do not call this while this frame's descendants are being * reflowed, it won't be accurate. + * INCLUDE_VISUAL_VIEWPORT_SCROLLBARS means we include the size of layout + * scrollbars that are only visible to scroll the visual viewport inside the + * layout viewport (ie the layout viewport cannot be scrolled) even though + * there is no layout space set aside for these scrollbars. */ - virtual nsMargin GetActualScrollbarSizes() const = 0; + enum class ScrollbarSizesOptions { NONE, INCLUDE_VISUAL_VIEWPORT_SCROLLBARS }; + virtual nsMargin GetActualScrollbarSizes( + ScrollbarSizesOptions aOptions = ScrollbarSizesOptions::NONE) const = 0; /** * Return the sizes of all scrollbars assuming that any scrollbars that could * be visible due to overflowing content, are. This can be called during