diff --git a/layout/generic/crashtests/crashtests.list b/layout/generic/crashtests/crashtests.list index 1417fadfb961..1d0e397c7f0c 100644 --- a/layout/generic/crashtests/crashtests.list +++ b/layout/generic/crashtests/crashtests.list @@ -701,7 +701,7 @@ load 1474768.html load 1478178.html load 1483972.html load 1486457.html -asserts(2-4) load 1488762-1.html # asserts from integer overflow & bogus sizes +asserts(1-4) load 1488762-1.html # asserts from integer overflow & bogus sizes load 1489287.html load 1489863.html load 1489770.html @@ -798,5 +798,5 @@ pref(layout.css.aspect-ratio.enabled,true) load 1682032.html pref(layout.css.aspect-ratio.enabled,true) load 1699263.html pref(layout.css.aspect-ratio.enabled,true) load 1699468.html load 1728319.html -asserts(4-8) load 1730506.html # asserts from integer overflow & bogus sizes +asserts(2-8) load 1730506.html # asserts from integer overflow & bogus sizes asserts(1-4) load 1730570.html # asserts from integer overflow & bogus sizes diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index a8c331aa63df..8d080fadcbe6 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -351,6 +351,10 @@ struct MOZ_STACK_CLASS ScrollReflowInput { // === Filled in by ReflowScrolledFrame === OverflowAreas mContentsOverflowAreas; + // The scrollbar gutter sizes used in the most recent reflow of + // mHelper.mScrolledFrame. The writing-mode is the same as the scroll + // container. + LogicalMargin mScrollbarGutterFromLastReflow; // True if the most recent reflow of mHelper.mScrolledFrame is with the // horizontal scrollbar. bool mReflowedContentsWithHScrollbar = false; @@ -410,6 +414,8 @@ struct MOZ_STACK_CLASS ScrollReflowInput { nsSize mVScrollbarPrefSize; nsSize mHScrollbarMinSize; nsSize mHScrollbarPrefSize; + // The scrollbar gutter sizes resolved from the scrollbar-gutter and + // scrollbar-width property. nsMargin mScrollbarGutter; }; @@ -421,7 +427,8 @@ ScrollReflowInput::ScrollReflowInput(nsHTMLScrollFrame* aFrame, mBoxState(aReflowInput.mFrame->PresContext(), aReflowInput.mRenderingContext), mComputedBorder(aReflowInput.ComputedPhysicalBorderPadding() - - aReflowInput.ComputedPhysicalPadding()) { + aReflowInput.ComputedPhysicalPadding()), + mScrollbarGutterFromLastReflow(aFrame->GetWritingMode()) { ScrollStyles styles = aFrame->GetScrollStyles(); mHScrollbar = ShouldShowScrollbar(styles.mHorizontal); mVScrollbar = ShouldShowScrollbar(styles.mVertical); @@ -546,23 +553,23 @@ bool nsHTMLScrollFrame::TryLayout(ScrollReflowInput& aState, return false; } - const bool assumeVScrollChanged = - aAssumeVScroll != aState.mReflowedContentsWithVScrollbar; - const bool assumeHScrollChanged = - aAssumeHScroll != aState.mReflowedContentsWithHScrollbar; - const bool isVertical = GetWritingMode().IsVertical(); + const auto wm = GetWritingMode(); + const nsMargin scrollbarGutter = aState.ScrollbarGutter( + aAssumeVScroll, aAssumeHScroll, IsScrollbarOnRight()); + const LogicalMargin logicalScrollbarGutter(wm, scrollbarGutter); - const bool shouldReflowScolledFrame = [=]() { - if (isVertical) { - return assumeHScrollChanged || - (assumeVScrollChanged && ScrolledContentDependsOnBSize(aState)); - } - return assumeVScrollChanged || - (assumeHScrollChanged && ScrolledContentDependsOnBSize(aState)); - }(); + const bool inlineEndsGutterChanged = + aState.mScrollbarGutterFromLastReflow.IStartEnd(wm) != + logicalScrollbarGutter.IStartEnd(wm); + const bool blockEndsGutterChanged = + aState.mScrollbarGutterFromLastReflow.BStartEnd(wm) != + logicalScrollbarGutter.BStartEnd(wm); + const bool shouldReflowScrolledFrame = + inlineEndsGutterChanged || + (blockEndsGutterChanged && ScrolledContentDependsOnBSize(aState)); - if (shouldReflowScolledFrame) { - if (isVertical ? assumeVScrollChanged : assumeHScrollChanged) { + if (shouldReflowScrolledFrame) { + if (blockEndsGutterChanged) { nsLayoutUtils::MarkIntrinsicISizesDirtyIfDependentOnBSize( mHelper.mScrolledFrame); } @@ -573,8 +580,6 @@ bool nsHTMLScrollFrame::TryLayout(ScrollReflowInput& aState, ReflowScrolledFrame(aState, aAssumeHScroll, aAssumeVScroll, aKidMetrics); } - const nsMargin scrollbarGutter = aState.ScrollbarGutter( - aAssumeVScroll, aAssumeHScroll, IsScrollbarOnRight()); const nsSize scrollbarGutterSize(scrollbarGutter.LeftRight(), scrollbarGutter.TopBottom()); @@ -644,15 +649,17 @@ bool nsHTMLScrollFrame::TryLayout(ScrollReflowInput& aState, ToString(scrollPortSize).c_str()); nscoord oneDevPixel = aState.mBoxState.PresContext()->DevPixelsToAppUnits(1); + bool showHScrollbar = aAssumeHScroll; + bool showVScrollbar = aAssumeVScroll; if (!aForce) { nsSize sizeToCompare = visualViewportSize; if (gfxPlatform::UseDesktopZoomingScrollbars()) { sizeToCompare = scrollPortSize; } - // If the style is HIDDEN then we already know that aAssumeHScroll is false + // No need to compute showHScrollbar if we got ShowScrollbar::Never. if (aState.mHScrollbar != ShowScrollbar::Never) { - bool wantHScrollbar = + showHScrollbar = aState.mHScrollbar == ShowScrollbar::Always || scrolledRect.XMost() >= sizeToCompare.width + oneDevPixel || scrolledRect.x <= -oneDevPixel; @@ -660,18 +667,15 @@ bool nsHTMLScrollFrame::TryLayout(ScrollReflowInput& aState, // in both axes, for consistency? if (aState.mHScrollbar == ShowScrollbar::Auto && scrollPortSize.width < aState.HScrollbarMinWidth()) { - wantHScrollbar = false; + showHScrollbar = false; } ROOT_SCROLLBAR_LOG("TryLayout wants H Scrollbar: %d =? %d\n", - wantHScrollbar, aAssumeHScroll); - if (wantHScrollbar != aAssumeHScroll) { - return false; - } + showHScrollbar, aAssumeHScroll); } - // If the style is HIDDEN then we already know that aAssumeVScroll is false + // No need to compute showVScrollbar if we got ShowScrollbar::Never. if (aState.mVScrollbar != ShowScrollbar::Never) { - bool wantVScrollbar = + showVScrollbar = aState.mVScrollbar == ShowScrollbar::Always || scrolledRect.YMost() >= sizeToCompare.height + oneDevPixel || scrolledRect.y <= -oneDevPixel; @@ -679,18 +683,27 @@ bool nsHTMLScrollFrame::TryLayout(ScrollReflowInput& aState, // in both axes, for consistency? if (aState.mVScrollbar == ShowScrollbar::Auto && scrollPortSize.height < aState.VScrollbarMinHeight()) { - wantVScrollbar = false; + showVScrollbar = false; } ROOT_SCROLLBAR_LOG("TryLayout wants V Scrollbar: %d =? %d\n", - wantVScrollbar, aAssumeVScroll); - if (wantVScrollbar != aAssumeVScroll) { + showVScrollbar, aAssumeVScroll); + } + + if (showHScrollbar != aAssumeHScroll || showVScrollbar != aAssumeVScroll) { + const nsMargin wantedScrollbarGutter = aState.ScrollbarGutter( + showVScrollbar, showHScrollbar, IsScrollbarOnRight()); + // We report an inconsistent layout only when the desired visibility of + // the scrollbars can change the size of the scrollbar gutters. + if (scrollbarGutter != wantedScrollbarGutter) { return false; } } } - aState.mShowHScrollbar = aAssumeHScroll; - aState.mShowVScrollbar = aAssumeVScroll; + // If we reach here, the layout is consistent. Record the desired visibility + // of the scrollbars. + aState.mShowHScrollbar = showHScrollbar; + aState.mShowVScrollbar = showVScrollbar; const nsPoint scrollPortOrigin( aState.mComputedBorder.left + scrollbarGutter.left, aState.mComputedBorder.top + scrollbarGutter.top); @@ -752,7 +765,7 @@ void nsHTMLScrollFrame::ReflowScrolledFrame(ScrollReflowInput& aState, bool aAssumeHScroll, bool aAssumeVScroll, ReflowOutput* aMetrics) { - WritingMode wm = mHelper.mScrolledFrame->GetWritingMode(); + const WritingMode wm = GetWritingMode(); // these could be NS_UNCONSTRAINEDSIZE ... std::min arithmetic should // be OK @@ -884,6 +897,7 @@ void nsHTMLScrollFrame::ReflowScrolledFrame(ScrollReflowInput& aState, } aState.mContentsOverflowAreas = aMetrics->mOverflowAreas; + aState.mScrollbarGutterFromLastReflow = scrollbarGutter; aState.mReflowedContentsWithHScrollbar = aAssumeHScroll; aState.mReflowedContentsWithVScrollbar = aAssumeVScroll; } diff --git a/testing/web-platform/mozilla/meta/css/css-overflow/scrollbar-gutter-reflow-counts-001.html.ini b/testing/web-platform/mozilla/meta/css/css-overflow/scrollbar-gutter-reflow-counts-001.html.ini new file mode 100644 index 000000000000..3489dc31c9ef --- /dev/null +++ b/testing/web-platform/mozilla/meta/css/css-overflow/scrollbar-gutter-reflow-counts-001.html.ini @@ -0,0 +1,24 @@ +[scrollbar-gutter-reflow-counts-001.html] + [Enlarge the child's block-size to 200%] + expected: + if os == "android": FAIL # Overlay scrollbars do not create scrollbar gutters. + + [Enlarge the child's block-size to 300px] + expected: + if os == "android": FAIL # Overlay scrollbars do not create scrollbar gutters. + + [Enlarge the child's block-size to 200% in a vertical-lr scroll container] + expected: + if os == "android": FAIL # Overlay scrollbars do not create scrollbar gutters. + + [Enlarge the child's block-size to 300px in a vertical-lr scroll container] + expected: + if os == "android": FAIL # Overlay scrollbars do not create scrollbar gutters. + + [Enlarge the child's block-size to 200% in a vertical-rl scroll container] + expected: + if os == "android": FAIL # Overlay scrollbars do not create scrollbar gutters. + + [Enlarge the child's block-size to 300px in a vertical-rl scroll container] + expected: + if os == "android": FAIL # Overlay scrollbars do not create scrollbar gutters. diff --git a/testing/web-platform/mozilla/tests/css/css-overflow/scrollbar-gutter-reflow-counts-001.html b/testing/web-platform/mozilla/tests/css/css-overflow/scrollbar-gutter-reflow-counts-001.html new file mode 100644 index 000000000000..aa4ed4667b97 --- /dev/null +++ b/testing/web-platform/mozilla/tests/css/css-overflow/scrollbar-gutter-reflow-counts-001.html @@ -0,0 +1,115 @@ + + + + CSS Overflow: Test scrollbar-gutter reflow counts + + + + + + + + +

Here is a scroll contaier for testing:

+
+
+
+ + +