Bug 1707070 - Tweak text/number/search control anonymous tree DOM / paint order. r=dholbert
So that we hit-test the spinners even if they overlap with the editor root's padding. Differential Revision: https://phabricator.services.mozilla.com/D113251
This commit is contained in:
@@ -405,7 +405,6 @@ nsresult nsTextControlFrame::CreateAnonymousContent(
|
||||
return rv;
|
||||
}
|
||||
|
||||
aElements.AppendElement(mRootNode);
|
||||
CreatePlaceholderIfNeeded();
|
||||
if (mPlaceholderDiv) {
|
||||
aElements.AppendElement(mPlaceholderDiv);
|
||||
@@ -415,6 +414,10 @@ nsresult nsTextControlFrame::CreateAnonymousContent(
|
||||
aElements.AppendElement(mPreviewDiv);
|
||||
}
|
||||
|
||||
// NOTE(emilio): We want the root node always after the placeholder so that
|
||||
// background on the placeholder doesn't obscure the caret.
|
||||
aElements.AppendElement(mRootNode);
|
||||
|
||||
rv = UpdateValueDisplay(false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
@@ -516,8 +519,6 @@ void nsTextControlFrame::CreatePreviewIfNeeded() {
|
||||
|
||||
void nsTextControlFrame::AppendAnonymousContentTo(
|
||||
nsTArray<nsIContent*>& aElements, uint32_t aFilter) {
|
||||
aElements.AppendElement(mRootNode);
|
||||
|
||||
if (mPlaceholderDiv && !(aFilter & nsIContent::eSkipPlaceholderContent)) {
|
||||
aElements.AppendElement(mPlaceholderDiv);
|
||||
}
|
||||
@@ -525,6 +526,8 @@ void nsTextControlFrame::AppendAnonymousContentTo(
|
||||
if (mPreviewDiv) {
|
||||
aElements.AppendElement(mPreviewDiv);
|
||||
}
|
||||
|
||||
aElements.AppendElement(mRootNode);
|
||||
}
|
||||
|
||||
nscoord nsTextControlFrame::GetPrefISize(gfxContext* aRenderingContext) {
|
||||
@@ -607,6 +610,12 @@ Maybe<nscoord> nsTextControlFrame::ComputeBaseline(
|
||||
aReflowInput.ComputedLogicalBorderPadding(wm).BStart(wm));
|
||||
}
|
||||
|
||||
static bool IsButtonBox(const nsIFrame* aFrame) {
|
||||
auto pseudoType = aFrame->Style()->GetPseudoType();
|
||||
return pseudoType == PseudoStyleType::mozNumberSpinBox ||
|
||||
pseudoType == PseudoStyleType::mozSearchClearButton;
|
||||
}
|
||||
|
||||
void nsTextControlFrame::Reflow(nsPresContext* aPresContext,
|
||||
ReflowOutput& aDesiredSize,
|
||||
const ReflowInput& aReflowInput,
|
||||
@@ -631,12 +640,32 @@ void nsTextControlFrame::Reflow(nsPresContext* aPresContext,
|
||||
|
||||
// overflow handling
|
||||
aDesiredSize.SetOverflowAreasToDesiredBounds();
|
||||
|
||||
nsIFrame* buttonBox = [&]() -> nsIFrame* {
|
||||
nsIFrame* last = mFrames.LastChild();
|
||||
if (!last || !IsButtonBox(last)) {
|
||||
return nullptr;
|
||||
}
|
||||
return last;
|
||||
}();
|
||||
|
||||
// Reflow the button box first, so that we can use its size for the other
|
||||
// frames.
|
||||
nscoord buttonBoxISize = 0;
|
||||
if (buttonBox) {
|
||||
ReflowTextControlChild(buttonBox, aPresContext, aReflowInput, aStatus,
|
||||
aDesiredSize, buttonBoxISize);
|
||||
}
|
||||
|
||||
// perform reflow on all kids
|
||||
nsIFrame* kid = mFrames.FirstChild();
|
||||
nscoord buttonBoxISize = 0;
|
||||
while (kid) {
|
||||
ReflowTextControlChild(kid, aPresContext, aReflowInput, aStatus,
|
||||
aDesiredSize, buttonBoxISize);
|
||||
if (kid != buttonBox) {
|
||||
MOZ_ASSERT(!IsButtonBox(kid),
|
||||
"Should only have one button box, and should be last");
|
||||
ReflowTextControlChild(kid, aPresContext, aReflowInput, aStatus,
|
||||
aDesiredSize, buttonBoxISize);
|
||||
}
|
||||
kid = kid->GetNextSibling();
|
||||
}
|
||||
|
||||
@@ -657,9 +686,7 @@ void nsTextControlFrame::ReflowTextControlChild(
|
||||
LogicalSize availSize = aReflowInput.ComputedSizeWithPadding(wm);
|
||||
availSize.BSize(wm) = NS_UNCONSTRAINEDSIZE;
|
||||
|
||||
const bool isButtonBox =
|
||||
aKid->Style()->GetPseudoType() == PseudoStyleType::mozNumberSpinBox ||
|
||||
aKid->Style()->GetPseudoType() == PseudoStyleType::mozSearchClearButton;
|
||||
bool isButtonBox = IsButtonBox(aKid);
|
||||
|
||||
ReflowInput kidReflowInput(aPresContext, aReflowInput, aKid, availSize,
|
||||
Nothing(), ReflowInput::InitFlag::CallerWillInit);
|
||||
@@ -1270,12 +1297,6 @@ nsresult nsTextControlFrame::PeekOffset(nsPeekOffsetStruct* aPos) {
|
||||
|
||||
void nsTextControlFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
const nsDisplayListSet& aLists) {
|
||||
/*
|
||||
* The implementation of this method is equivalent as:
|
||||
* nsContainerFrame::BuildDisplayList()
|
||||
* with the difference that we filter-out the placeholder frame when it
|
||||
* should not be visible.
|
||||
*/
|
||||
DO_GLOBAL_REFLOW_COUNT_DSP("nsTextControlFrame");
|
||||
|
||||
DisplayBorderBackgroundOutline(aBuilder, aLists);
|
||||
@@ -1286,20 +1307,7 @@ void nsTextControlFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
nsDisplayList* content = aLists.Content();
|
||||
nsDisplayListSet set(content, content, content, content, content, content);
|
||||
|
||||
// We build the ::placeholder first so that it renders below mRootNode which
|
||||
// draws the caret and we always want that on top (bug 1637476).
|
||||
//
|
||||
// TODO(emilio): We should consider just changing the DOM order instead.
|
||||
if (mPlaceholderDiv && mPlaceholderDiv->GetPrimaryFrame()) {
|
||||
auto* kid = mPlaceholderDiv->GetPrimaryFrame();
|
||||
MOZ_ASSERT(kid->GetParent() == this);
|
||||
BuildDisplayListForChild(aBuilder, kid, set);
|
||||
}
|
||||
|
||||
for (auto* kid : mFrames) {
|
||||
if (kid->GetContent() == mPlaceholderDiv) {
|
||||
continue; // Handled above already.
|
||||
}
|
||||
BuildDisplayListForChild(aBuilder, kid, set);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user