Commit 3de2c595 authored by Christian Biesinger's avatar Christian Biesinger Committed by Commit Bot

[layoutng] Handle overflow: auto more correctly

We need to relayout whenever scrollbars change. The change in
https://chromium-review.googlesource.com/1162657 was not quite correct.

The change to CopyFragmentDataToLayoutBox is necessary to not break
virtual/layout_ng_experimental/fragmentation/auto-overflow.html

Cq-Include-Trybots: luci.chromium.try:linux_layout_tests_layout_ng
Change-Id: I589d6a1bd1b3f06224e6c4aeae3e7cdf163206cc
Reviewed-on: https://chromium-review.googlesource.com/1178804Reviewed-by: default avatarEmil A Eklund <eae@chromium.org>
Commit-Queue: Christian Biesinger <cbiesinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#584316}
parent ed4591ba
...@@ -65,7 +65,6 @@ crbug.com/591099 compositing/iframes/floating-self-painting-frame.html [ Failure ...@@ -65,7 +65,6 @@ crbug.com/591099 compositing/iframes/floating-self-painting-frame.html [ Failure
crbug.com/591099 compositing/layer-creation/overlap-animation.html [ Crash ] crbug.com/591099 compositing/layer-creation/overlap-animation.html [ Crash ]
crbug.com/869265 compositing/layer-creation/stacking-context-overlap-nested.html [ Failure ] crbug.com/869265 compositing/layer-creation/stacking-context-overlap-nested.html [ Failure ]
crbug.com/591099 css3/filters/composited-layer-child-bounds-after-composited-to-sw-shadow-change.html [ Failure ] crbug.com/591099 css3/filters/composited-layer-child-bounds-after-composited-to-sw-shadow-change.html [ Failure ]
crbug.com/591099 css3/flexbox/bug646288.html [ Failure ]
crbug.com/591099 css3/flexbox/flex-flow-margins-auto-size.html [ Failure ] crbug.com/591099 css3/flexbox/flex-flow-margins-auto-size.html [ Failure ]
crbug.com/591099 css3/flexbox/intrinsic-width-orthogonal-writing-mode.html [ Failure ] crbug.com/591099 css3/flexbox/intrinsic-width-orthogonal-writing-mode.html [ Failure ]
crbug.com/591099 css3/flexbox/line-wrapping.html [ Failure ] crbug.com/591099 css3/flexbox/line-wrapping.html [ Failure ]
......
...@@ -18,6 +18,10 @@ bool NGBoxStrut::operator==(const NGBoxStrut& other) const { ...@@ -18,6 +18,10 @@ bool NGBoxStrut::operator==(const NGBoxStrut& other) const {
std::tie(inline_start, inline_end, block_start, block_end); std::tie(inline_start, inline_end, block_start, block_end);
} }
bool NGBoxStrut::operator!=(const NGBoxStrut& other) const {
return !(*this == other);
}
NGPhysicalBoxStrut NGBoxStrut::ConvertToPhysical( NGPhysicalBoxStrut NGBoxStrut::ConvertToPhysical(
WritingMode writing_mode, WritingMode writing_mode,
TextDirection direction) const { TextDirection direction) const {
......
...@@ -77,6 +77,7 @@ struct CORE_EXPORT NGBoxStrut { ...@@ -77,6 +77,7 @@ struct CORE_EXPORT NGBoxStrut {
} }
bool operator==(const NGBoxStrut& other) const; bool operator==(const NGBoxStrut& other) const;
bool operator!=(const NGBoxStrut& other) const;
String ToString() const; String ToString() const;
......
...@@ -203,20 +203,40 @@ scoped_refptr<NGLayoutResult> NGBlockNode::Layout( ...@@ -203,20 +203,40 @@ scoped_refptr<NGLayoutResult> NGBlockNode::Layout(
box_->ComputePreferredLogicalWidths(); box_->ComputePreferredLogicalWidths();
} }
bool preferred_logical_widths_were_dirty = NGBoxStrut old_scrollbars = GetScrollbarSizes();
box_->PreferredLogicalWidthsDirty();
layout_result = LayoutWithAlgorithm(*this, constraint_space, break_token, layout_result = LayoutWithAlgorithm(*this, constraint_space, break_token,
/* ignored */ nullptr); /* ignored */ nullptr);
if (!preferred_logical_widths_were_dirty &&
box_->PreferredLogicalWidthsDirty()) { FinishLayout(constraint_space, break_token, layout_result);
// The only thing that should dirty preferred widths at this point is the if (old_scrollbars != GetScrollbarSizes()) {
// addition of overflow:auto scrollbars in a descendant. To avoid a // If our scrollbars have changed, we need to relayout because either:
// potential infinite loop, run layout again with auto scrollbars frozen in // - Our size has changed (if shrinking to fit), or
// their current state. // - Space available to our children has changed.
// This mirrors legacy code in PaintLayerScrollableArea::UpdateAfterLayout.
// TODO(cbiesinger): It seems that we should also check if
// PreferredLogicalWidthsDirty() has changed from false to true during
// layout, so that we correctly size ourselves when shrinking to fit
// and a child gained a vertical scrollbar. However, no test fails
// without that check.
PaintLayerScrollableArea::FreezeScrollbarsScope freeze_scrollbars; PaintLayerScrollableArea::FreezeScrollbarsScope freeze_scrollbars;
layout_result = LayoutWithAlgorithm(*this, constraint_space, break_token, layout_result = LayoutWithAlgorithm(*this, constraint_space, break_token,
/* ignored */ nullptr); /* ignored */ nullptr);
FinishLayout(constraint_space, break_token, layout_result);
} }
return layout_result;
}
void NGBlockNode::FinishLayout(const NGConstraintSpace& constraint_space,
NGBreakToken* break_token,
scoped_refptr<NGLayoutResult> layout_result) {
if (!IsBlockLayoutComplete(constraint_space, *layout_result))
return;
// TODO(kojii): Even when we paint fragments, there seem to be some data we
// need to copy to LayoutBox. Review if we can minimize the copy.
LayoutBlockFlow* block_flow =
box_->IsLayoutNGMixin() ? ToLayoutBlockFlow(box_) : nullptr;
if (block_flow) { if (block_flow) {
block_flow->SetCachedLayoutResult(constraint_space, break_token, block_flow->SetCachedLayoutResult(constraint_space, break_token,
layout_result); layout_result);
...@@ -225,27 +245,24 @@ scoped_refptr<NGLayoutResult> NGBlockNode::Layout( ...@@ -225,27 +245,24 @@ scoped_refptr<NGLayoutResult> NGBlockNode::Layout(
block_flow->SetPaintFragment(break_token, nullptr); block_flow->SetPaintFragment(break_token, nullptr);
} }
if (IsBlockLayoutComplete(constraint_space, *layout_result)) { DCHECK(layout_result->PhysicalFragment());
DCHECK(layout_result->PhysicalFragment());
if (block_flow && first_child && first_child.IsInline()) {
NGBoxStrut scrollbars = GetScrollbarSizes();
CopyFragmentDataToLayoutBoxForInlineChildren(
ToNGPhysicalBoxFragment(*layout_result->PhysicalFragment()),
layout_result->PhysicalFragment()->Size().width -
scrollbars.block_start,
Style().IsFlippedBlocksWritingMode());
block_flow->SetPaintFragment(break_token,
layout_result->PhysicalFragment());
}
// TODO(kojii): Even when we paint fragments, there seem to be some data we NGLayoutInputNode first_child = FirstChild();
// need to copy to LayoutBox. Review if we can minimize the copy. if (block_flow && first_child && first_child.IsInline()) {
CopyFragmentDataToLayoutBox(constraint_space, *layout_result); NGBoxStrut scrollbars = GetScrollbarSizes();
CopyFragmentDataToLayoutBoxForInlineChildren(
ToNGPhysicalBoxFragment(*layout_result->PhysicalFragment()),
layout_result->PhysicalFragment()->Size().width -
scrollbars.block_start,
Style().IsFlippedBlocksWritingMode());
block_flow->SetPaintFragment(break_token,
layout_result->PhysicalFragment());
} }
return layout_result; // TODO(kojii): Even when we paint fragments, there seem to be some data we
// need to copy to LayoutBox. Review if we can minimize the copy.
CopyFragmentDataToLayoutBox(constraint_space, *layout_result);
} }
MinMaxSize NGBlockNode::ComputeMinMaxSize( MinMaxSize NGBlockNode::ComputeMinMaxSize(
...@@ -415,7 +432,11 @@ void NGBlockNode::CopyFragmentDataToLayoutBox( ...@@ -415,7 +432,11 @@ void NGBlockNode::CopyFragmentDataToLayoutBox(
} else { } else {
DCHECK_EQ(box_->LogicalWidth(), fragment_logical_size.inline_size) DCHECK_EQ(box_->LogicalWidth(), fragment_logical_size.inline_size)
<< "Variable fragment inline size not supported"; << "Variable fragment inline size not supported";
logical_height = box_->LogicalHeight(); logical_height =
PreviouslyUsedBlockSpace(constraint_space, physical_fragment);
// TODO(layout-ng): We should store this on the break token instead of
// relying on previously-stored data. Our relayout in NGBlockNode::Layout
// will otherwise lead to wrong data.
intrinsic_content_logical_height = box_->IntrinsicContentLogicalHeight(); intrinsic_content_logical_height = box_->IntrinsicContentLogicalHeight();
} }
logical_height += fragment_logical_size.block_size; logical_height += fragment_logical_size.block_size;
......
...@@ -97,6 +97,10 @@ class CORE_EXPORT NGBlockNode final : public NGLayoutInputNode { ...@@ -97,6 +97,10 @@ class CORE_EXPORT NGBlockNode final : public NGLayoutInputNode {
String ToString() const; String ToString() const;
private: private:
void FinishLayout(const NGConstraintSpace&,
NGBreakToken*,
scoped_refptr<NGLayoutResult>);
// After we run the layout algorithm, this function copies back the geometry // After we run the layout algorithm, this function copies back the geometry
// data to the layout box. // data to the layout box.
void CopyFragmentDataToLayoutBox(const NGConstraintSpace&, void CopyFragmentDataToLayoutBox(const NGConstraintSpace&,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment