Bug 1932800 - Use ShouldHaveLineIfEmpty() to guarantee buttons have at least one line of height. r=dshin

This is similar to how we treat <div contenteditable>, and allows us to
remove the specialness about anon boxes.

Differential Revision: https://phabricator.services.mozilla.com/D229939
This commit is contained in:
Emilio Cobos Álvarez
2024-11-24 14:46:16 +00:00
parent b1269ccea6
commit 074210e88e
6 changed files with 32 additions and 56 deletions

View File

@@ -4969,26 +4969,9 @@ void nsBlockFrame::DoReflowInlineFrames(
// because it might get disabled there
aLine->EnableResizeReflowOptimization();
// We want to be able to collapse the height of empty inline elements in empty
// lines in general - See [1]. Two exceptions:
// 1. There is an outside ::marker frame, which is physical on this line, but
// is not part of the line layout.
// 2. The line is inside an anonymous box, like `<input type=button>`. A
// scrolled block frame internally has an anonymous box of the scrolled
// content, which we still want to carry out the collapsing for.
//
// [1]: https://drafts.csswg.org/css-inline-3/#invisible-line-boxes
auto collapseEmptyInlineFramesInLine =
HasOutsideMarker() ||
(Style()->IsAnonBox() &&
Style()->GetPseudoType() != PseudoStyleType::scrolledContent)
? CollapseEmptyInlineFramesInLine::Preserve
: CollapseEmptyInlineFramesInLine::Collapse;
aLineLayout.BeginLineReflow(iStart, aState.mBCoord, availISize, availBSize,
aFloatAvailableSpace.HasFloats(),
false /*XXX isTopOfPage*/,
collapseEmptyInlineFramesInLine, lineWM,
false /*XXX isTopOfPage*/, lineWM,
aState.mContainerSize, aState.mInsetForBalance);
aState.mFlags.mIsLineLayoutEmpty = false;

View File

@@ -226,7 +226,7 @@ void nsFirstLetterFrame::Reflow(nsPresContext* aPresContext,
// `CollapseEmptyInlineFramesInLine` should not matter.
ll.BeginLineReflow(
bp.IStart(wm), bp.BStart(wm), availSize.ISize(wm), NS_UNCONSTRAINEDSIZE,
false, true, CollapseEmptyInlineFramesInLine::Collapse, kidWritingMode,
false, true, kidWritingMode,
nsSize(aReflowInput.AvailableWidth(), aReflowInput.AvailableHeight()));
rs.mLineLayout = &ll;
ll.SetInFirstLetter(true);

View File

@@ -4673,9 +4673,18 @@ bool nsIFrame::IsSelectable(StyleUserSelect* aSelectStyle) const {
}
bool nsIFrame::ShouldHaveLineIfEmpty() const {
if (Style()->IsPseudoOrAnonBox() &&
Style()->GetPseudoType() != PseudoStyleType::scrolledContent) {
return false;
switch (Style()->GetPseudoType()) {
case PseudoStyleType::NotPseudo:
break;
case PseudoStyleType::scrolledContent:
return GetParent()->ShouldHaveLineIfEmpty();
case PseudoStyleType::mozTextControlEditingRoot:
return true;
case PseudoStyleType::buttonContent:
// HTML quirk.
return GetContent()->IsHTMLElement(nsGkAtoms::input);
default:
return false;
}
return IsEditingHost(this);
}

View File

@@ -91,11 +91,12 @@ nsLineLayout::nsLineLayout(nsPresContext* aPresContext,
}
}
void nsLineLayout::BeginLineReflow(
nscoord aICoord, nscoord aBCoord, nscoord aISize, nscoord aBSize,
bool aImpactedByFloats, bool aIsTopOfPage,
CollapseEmptyInlineFramesInLine aCollapseEmptyInlineFramesInLine,
WritingMode aWritingMode, const nsSize& aContainerSize, nscoord aInset) {
void nsLineLayout::BeginLineReflow(nscoord aICoord, nscoord aBCoord,
nscoord aISize, nscoord aBSize,
bool aImpactedByFloats, bool aIsTopOfPage,
WritingMode aWritingMode,
const nsSize& aContainerSize,
nscoord aInset) {
MOZ_ASSERT(nullptr == mRootSpan, "bad linelayout user");
LAYOUT_WARN_IF_FALSE(aISize != NS_UNCONSTRAINEDSIZE,
"have unconstrained width; this should only result from "
@@ -148,9 +149,6 @@ void nsLineLayout::BeginLineReflow(
psd->mIStart = aICoord;
psd->mICoord = aICoord;
psd->mIEnd = aICoord + aISize;
psd->mDoCollapseEmptyInlineFramesInLine =
aCollapseEmptyInlineFramesInLine ==
CollapseEmptyInlineFramesInLine::Collapse;
// Set up inset to be used for text-wrap:balance implementation, but only if
// the available size is greater than inset.
psd->mInset = aISize > aInset ? aInset : 0;
@@ -356,7 +354,6 @@ nsLineLayout::PerSpanData* nsLineLayout::NewPerSpanData() {
psd->mContainsFloat = false;
psd->mHasNonemptyContent = false;
psd->mBaseline = nullptr;
psd->mDoCollapseEmptyInlineFramesInLine = false;
#ifdef DEBUG
outerLineLayout->mSpansAllocated++;
@@ -1381,6 +1378,7 @@ void nsLineLayout::AddMarkerFrame(nsIFrame* aFrame,
nsBlockFrame* blockFrame = do_QueryFrame(LineContainerFrame());
MOZ_ASSERT(blockFrame, "must be for block");
if (!blockFrame->MarkerIsEmpty(aFrame)) {
mLineIsEmpty = false;
mHasMarker = true;
mLineBox->SetHasMarker();
}
@@ -1493,7 +1491,7 @@ void nsLineLayout::VerticalAlignLine() {
// this operation is set to zero so that the y coordinates for all
// of the placed children will be relative to there.
PerSpanData* psd = mRootSpan;
if (mLineIsEmpty && psd->mDoCollapseEmptyInlineFramesInLine) {
if (mLineIsEmpty) {
// This line is empty, and should be consisting of only inline elements.
// (inline-block elements would make the line non-empty).
WritingMode lineWM = psd->mWritingMode;

View File

@@ -20,18 +20,6 @@
class nsFloatManager;
struct nsStyleText;
/**
* Flag indicating if inline frames within a line should be collapsed
* to zero block-size if all frames within it are empty.
* Declared as typed enum for clearer semantics in function calls, though
* it is reflected as a boolean in
* PerSpanData::mDoCollapseEmptyInlineFramesInLine.
*/
enum class CollapseEmptyInlineFramesInLine {
Preserve,
Collapse,
};
class nsLineLayout {
using BlockReflowState = mozilla::BlockReflowState;
using ReflowInput = mozilla::ReflowInput;
@@ -61,14 +49,13 @@ class nsLineLayout {
int32_t GetLineNumber() const { return mLineNumber; }
void BeginLineReflow(
nscoord aICoord, nscoord aBCoord, nscoord aISize, nscoord aBSize,
bool aImpactedByFloats, bool aIsTopOfPage,
CollapseEmptyInlineFramesInLine aCollapseEmptyInlineFramesInLine,
mozilla::WritingMode aWritingMode, const nsSize& aContainerSize,
// aInset is used during text-wrap:balance to reduce
// the effective available space on the line.
nscoord aInset = 0);
void BeginLineReflow(nscoord aICoord, nscoord aBCoord, nscoord aISize,
nscoord aBSize, bool aImpactedByFloats,
bool aIsTopOfPage, mozilla::WritingMode aWritingMode,
const nsSize& aContainerSize,
// aInset is used during text-wrap:balance to reduce
// the effective available space on the line.
nscoord aInset = 0);
/**
* Returns true if the line had to use an overflow-wrap break position.
@@ -510,7 +497,6 @@ class nsLineLayout {
mozilla::WritingMode mWritingMode;
bool mContainsFloat;
bool mHasNonemptyContent;
bool mDoCollapseEmptyInlineFramesInLine;
nscoord mIStart;
nscoord mICoord;

View File

@@ -341,9 +341,9 @@ void nsRubyBaseContainerFrame::Reflow(nsPresContext* aPresContext,
// If the writing mode is vertical-rl, the horizontal position of
// rt frames will be updated when reflowing this text container,
// hence leave container size 0 here for now.
lineLayout->BeginLineReflow(
0, 0, reflowInput->ComputedISize(), NS_UNCONSTRAINEDSIZE, false, false,
CollapseEmptyInlineFramesInLine::Collapse, reflowWM, nsSize(0, 0));
lineLayout->BeginLineReflow(0, 0, reflowInput->ComputedISize(),
NS_UNCONSTRAINEDSIZE, false, false, reflowWM,
nsSize(0, 0));
lineLayout->AttachRootFrameToBaseLineLayout();
}