Commit 6e286e14 authored by Ting-Yu Lin's avatar Ting-Yu Lin
Browse files

Bug 1748574 - Rewrite the helper that computes scrollbar's intrinsic size. r=dholbert

This patch fixed the following:

1. Make the helper support the vertical writing modes since its callers
GetMinISize() and GetPrefISize() are fully aware of the vertical writing modes.
`overflow-scroll-intrinsic-001.html` verifies this scenario. This also fixed a
testcase with "writing-mode: vertical-lr" in flexbox's
cross-axis-scrollbar.html.

2. Treat scrollbar's intrinsic size "zero" if we have "scrollbar-width: none"
since no scrollbar is showing at all.
`overflow-auto-scrollbar-gutter-intrinsic-003.html` verifies this scenario.

3. Return the scrollbar size if we have "scrollbar-gutter: stable", or twice the
size if we have "scrollbar-gutter: stable both-edges".
`overflow-auto-scrollbar-gutter-intrinsic-{001,002}.html` verifies this
scenario.

Differential Revision: https://phabricator.services.mozilla.com/D135182
parent 64eea7ce
Loading
Loading
Loading
Loading
+38 −11
Original line number Diff line number Diff line
@@ -1101,19 +1101,46 @@ void nsHTMLScrollFrame::PlaceScrollArea(ScrollReflowInput& aState,
      scrolledArea, ReflowChildFlags::Default);
}

nscoord nsHTMLScrollFrame::GetIntrinsicVScrollbarWidth(
nscoord nsHTMLScrollFrame::IntrinsicScrollbarGutterSizeAtInlineEdges(
    gfxContext* aRenderingContext) {
  const bool isVerticalWM = GetWritingMode().IsVertical();
  nsIFrame* inlineEndScrollbarBox =
      isVerticalWM ? mHelper.mHScrollbarBox : mHelper.mVScrollbarBox;
  if (!inlineEndScrollbarBox) {
    // No scrollbar box frame means no intrinsic size.
    return 0;
  }

  const auto* styleForScrollbar = nsLayoutUtils::StyleForScrollbar(this);
  if (styleForScrollbar->StyleUIReset()->mScrollbarWidth ==
      StyleScrollbarWidth::None) {
    // Scrollbar shouldn't appear at all with "scrollbar-width: none".
    return 0;
  }

  const auto& styleScrollbarGutter =
      styleForScrollbar->StyleDisplay()->mScrollbarGutter;
  ScrollStyles ss = GetScrollStyles();
  if (ss.mVertical != StyleOverflow::Scroll || !mHelper.mVScrollbarBox)
  const StyleOverflow& inlineEndStyleOverflow =
      isVerticalWM ? ss.mHorizontal : ss.mVertical;

  // Return the scrollbar-gutter size only if we have "overflow:scroll" or
  // non-auto "scrollbar-gutter", so early-return here if the conditions aren't
  // satisfied.
  if (inlineEndStyleOverflow != StyleOverflow::Scroll &&
      styleScrollbarGutter == StyleScrollbarGutter::AUTO) {
    return 0;
  }

  // Don't need to worry about reflow depth here since it's
  // just for scrollbars
  // No need to worry about reflow depth here since it's just for scrollbars.
  nsBoxLayoutState bls(PresContext(), aRenderingContext, 0);
  nsSize vScrollbarPrefSize(0, 0);
  GetScrollbarMetrics(bls, mHelper.mVScrollbarBox, nullptr,
                      &vScrollbarPrefSize);
  return vScrollbarPrefSize.width;
  nsSize scrollbarPrefSize;
  GetScrollbarMetrics(bls, inlineEndScrollbarBox, nullptr, &scrollbarPrefSize);
  const nscoord scrollbarSize =
      isVerticalWM ? scrollbarPrefSize.height : scrollbarPrefSize.width;
  const auto bothEdges =
      bool(styleScrollbarGutter & StyleScrollbarGutter::BOTH_EDGES);
  return bothEdges ? scrollbarSize * 2 : scrollbarSize;
}

// Legacy, this sucks!
@@ -1144,7 +1171,7 @@ nscoord nsHTMLScrollFrame::GetMinISize(gfxContext* aRenderingContext) {
  }();

  DISPLAY_MIN_INLINE_SIZE(this, result);
  return result + GetIntrinsicVScrollbarWidth(aRenderingContext);
  return result + IntrinsicScrollbarGutterSizeAtInlineEdges(aRenderingContext);
}

/* virtual */
@@ -1154,8 +1181,8 @@ nscoord nsHTMLScrollFrame::GetPrefISize(gfxContext* aRenderingContext) {
          ? 0
          : mHelper.mScrolledFrame->GetPrefISize(aRenderingContext);
  DISPLAY_PREF_INLINE_SIZE(this, result);
  return NSCoordSaturatingAdd(result,
                              GetIntrinsicVScrollbarWidth(aRenderingContext));
  return NSCoordSaturatingAdd(
      result, IntrinsicScrollbarGutterSizeAtInlineEdges(aRenderingContext));
}

nsresult nsHTMLScrollFrame::GetXULPadding(nsMargin& aMargin) {
+6 −1
Original line number Diff line number Diff line
@@ -876,7 +876,12 @@ class nsHTMLScrollFrame : public nsContainerFrame,
                      const ReflowOutput& aDesiredSize);
  void PlaceScrollArea(ScrollReflowInput& aState,
                       const nsPoint& aScrollPosition);
  nscoord GetIntrinsicVScrollbarWidth(gfxContext* aRenderingContext);

  // Return the sum of inline-size of the scrollbar gutters (if any) at the
  // inline-start and inline-end edges of the scroll frame (for a potential
  // scrollbar that scrolls in the block axis).
  nscoord IntrinsicScrollbarGutterSizeAtInlineEdges(
      gfxContext* aRenderingContext);

  bool GetBorderRadii(const nsSize& aFrameSize, const nsSize& aBorderArea,
                      Sides aSkipSides, nscoord aRadii[8]) const final {
+0 −4
Original line number Diff line number Diff line
[cross-axis-scrollbar.html]
  expected:
    if os == "android": PASS
    FAIL
+60 −0
Original line number Diff line number Diff line
<!DOCTYPE html>
<html>
  <meta charset="utf-8">
  <title>CSS Overflow Reference: scrollbar-gutter size contributes to the scroll container's intrinsic size with "overflow:auto"</title>
  <link rel="author" title="Ting-Yu Lin" href="mailto:tlin@mozilla.com">
  <link rel="help" href="https://drafts.csswg.org/css-overflow-4/#scrollbar-gutter-property">

  <style>
  .line {
    display: flex;
  }
  .container {
    block-size: 50px;
    border: 5px solid black;
    scrollbar-gutter: stable;
    margin: 10px;
  }
  .hidden {
    overflow: hidden;
  }
  .scroll-x {
    overflow-x: scroll;
  }
  .scroll-y {
    overflow-y: scroll;
  }
  .tall {
    /* trigger overflow */
    block-size: 5000px;
  }
  </style>

  <div class="line">
    <div class="container hidden">
      <div>I should not wrap</div>
    </div>

    <div class="container scroll-y">
      <div class="tall">I should not wrap</div>
    </div>
  </div>

  <div class="line">
    <div class="container hidden" style="writing-mode: vertical-rl">
      <div>I should not wrap</div>
    </div>

    <div class="container scroll-x" style="writing-mode: vertical-rl">
      <div class="tall">I should not wrap</div>
    </div>

    <div class="container hidden" style="writing-mode: vertical-lr">
      <div>I should not wrap</div>
    </div>

    <div class="container scroll-x" style="writing-mode: vertical-lr">
      <div class="tall">I should not wrap</div>
    </div>
  </div>
</html>
+53 −0
Original line number Diff line number Diff line
<!DOCTYPE html>
<html>
  <meta charset="utf-8">
  <title>CSS Overflow Test: scrollbar-gutter size contributes to the scroll container's intrinsic size with "overflow:auto"</title>
  <link rel="author" title="Ting-Yu Lin" href="mailto:tlin@mozilla.com">
  <link rel="help" href="https://drafts.csswg.org/css-overflow-4/#scrollbar-gutter-property">
  <link rel="match" href="overflow-auto-scrollbar-gutter-intrinsic-001-ref.html">

  <style>
  .line {
    display: flex;
  }
  .container {
    block-size: 50px;
    border: 5px solid black;
    overflow: auto;
    scrollbar-gutter: stable;
    margin: 10px;
  }
  .tall {
    /* trigger overflow */
    block-size: 5000px;
  }
  </style>

  <div class="line">
    <div class="container">
      <div>I should not wrap</div>
    </div>

    <div class="container">
      <div class="tall">I should not wrap</div>
    </div>
  </div>

  <div class="line">
    <div class="container" style="writing-mode: vertical-rl">
      <div>I should not wrap</div>
    </div>

    <div class="container" style="writing-mode: vertical-rl">
      <div class="tall">I should not wrap</div>
    </div>

    <div class="container" style="writing-mode: vertical-lr">
      <div>I should not wrap</div>
    </div>

    <div class="container" style="writing-mode: vertical-lr">
      <div class="tall">I should not wrap</div>
    </div>
  </div>
</html>
Loading