Bug 951310 - Make <input type=number correctly handle CSS min-height and max-height. r=dholbert

This commit is contained in:
Jonathan Watt
2014-02-05 00:42:57 +00:00
parent a2ea0b107c
commit 3cc070312f
11 changed files with 249 additions and 58 deletions

View File

@@ -83,34 +83,85 @@ nsNumberControlFrame::Reflow(nsPresContext* aPresContext,
nsFormControlFrame::RegUnRegAccessKey(this, true);
}
nsHTMLReflowMetrics wrappersDesiredSize(aReflowState.GetWritingMode());
// The width of our content box, which is the available width
// for our anonymous content:
const nscoord contentBoxWidth = aReflowState.ComputedWidth();
nscoord contentBoxHeight = aReflowState.ComputedHeight();
nsIFrame* outerWrapperFrame = mOuterWrapper->GetPrimaryFrame();
if (outerWrapperFrame) { // display:none?
if (!outerWrapperFrame) { // display:none?
if (contentBoxHeight == NS_INTRINSICSIZE) {
contentBoxHeight = 0;
}
} else {
NS_ASSERTION(outerWrapperFrame == mFrames.FirstChild(), "huh?");
nsresult rv =
ReflowAnonymousContent(aPresContext, wrappersDesiredSize,
aReflowState, outerWrapperFrame);
nsHTMLReflowMetrics wrappersDesiredSize(aReflowState.GetWritingMode());
nsHTMLReflowState wrapperReflowState(aPresContext, aReflowState,
outerWrapperFrame,
nsSize(contentBoxWidth,
NS_UNCONSTRAINEDSIZE));
// offsets of wrapper frame
nscoord xoffset = aReflowState.ComputedPhysicalBorderPadding().left +
wrapperReflowState.ComputedPhysicalMargin().left;
nscoord yoffset = aReflowState.ComputedPhysicalBorderPadding().top +
wrapperReflowState.ComputedPhysicalMargin().top;
nsReflowStatus childStatus;
nsresult rv = ReflowChild(outerWrapperFrame, aPresContext,
wrappersDesiredSize, wrapperReflowState,
xoffset, yoffset, 0, childStatus);
NS_ENSURE_SUCCESS(rv, rv);
ConsiderChildOverflow(aDesiredSize.mOverflowAreas, outerWrapperFrame);
MOZ_ASSERT(NS_FRAME_IS_FULLY_COMPLETE(childStatus),
"We gave our child unconstrained height, so it should be complete");
nscoord wrappersMarginBoxHeight = wrappersDesiredSize.Height() +
wrapperReflowState.ComputedPhysicalMargin().TopBottom();
if (contentBoxHeight == NS_INTRINSICSIZE) {
// We are intrinsically sized -- we should shrinkwrap the outer wrapper's
// height:
contentBoxHeight = wrappersMarginBoxHeight;
// Make sure we obey min/max-height in the case when we're doing intrinsic
// sizing (we get it for free when we have a non-intrinsic
// aReflowState.ComputedHeight()). Note that we do this before
// adjusting for borderpadding, since mComputedMaxHeight and
// mComputedMinHeight are content heights.
contentBoxHeight =
NS_CSS_MINMAX(contentBoxHeight,
aReflowState.ComputedMinHeight(),
aReflowState.ComputedMaxHeight());
}
// Center child vertically
nscoord extraSpace = contentBoxHeight - wrappersMarginBoxHeight;
yoffset += std::max(0, extraSpace / 2);
// Place the child
rv = FinishReflowChild(outerWrapperFrame, aPresContext,
wrappersDesiredSize, &wrapperReflowState,
xoffset, yoffset, 0);
NS_ENSURE_SUCCESS(rv, rv);
aDesiredSize.SetTopAscent(wrappersDesiredSize.TopAscent() +
outerWrapperFrame->GetPosition().y);
}
nscoord computedHeight = aReflowState.ComputedHeight();
if (computedHeight == NS_AUTOHEIGHT) {
computedHeight =
outerWrapperFrame ? outerWrapperFrame->GetSize().height : 0;
}
aDesiredSize.Width() = aReflowState.ComputedWidth() +
aDesiredSize.Width() = contentBoxWidth +
aReflowState.ComputedPhysicalBorderPadding().LeftRight();
aDesiredSize.Height() = computedHeight +
aDesiredSize.Height() = contentBoxHeight +
aReflowState.ComputedPhysicalBorderPadding().TopBottom();
if (outerWrapperFrame) {
aDesiredSize.SetTopAscent(wrappersDesiredSize.TopAscent() +
outerWrapperFrame->GetPosition().y);
}
aDesiredSize.SetOverflowAreasToDesiredBounds();
if (outerWrapperFrame) {
ConsiderChildOverflow(aDesiredSize.mOverflowAreas, outerWrapperFrame);
}
FinishAndStoreOverflow(&aDesiredSize);
aStatus = NS_FRAME_COMPLETE;
@@ -120,41 +171,6 @@ nsNumberControlFrame::Reflow(nsPresContext* aPresContext,
return NS_OK;
}
nsresult
nsNumberControlFrame::
ReflowAnonymousContent(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aWrappersDesiredSize,
const nsHTMLReflowState& aParentReflowState,
nsIFrame* aOuterWrapperFrame)
{
MOZ_ASSERT(aOuterWrapperFrame);
// The width of our content box, which is the available width
// for our anonymous content:
nscoord inputFrameContentBoxWidth = aParentReflowState.ComputedWidth();
nsHTMLReflowState wrapperReflowState(aPresContext, aParentReflowState,
aOuterWrapperFrame,
nsSize(inputFrameContentBoxWidth,
NS_UNCONSTRAINEDSIZE));
nscoord xoffset = aParentReflowState.ComputedPhysicalBorderPadding().left +
wrapperReflowState.ComputedPhysicalMargin().left;
nscoord yoffset = aParentReflowState.ComputedPhysicalBorderPadding().top +
wrapperReflowState.ComputedPhysicalMargin().top;
nsReflowStatus childStatus;
nsresult rv = ReflowChild(aOuterWrapperFrame, aPresContext,
aWrappersDesiredSize, wrapperReflowState,
xoffset, yoffset, 0, childStatus);
NS_ENSURE_SUCCESS(rv, rv);
MOZ_ASSERT(NS_FRAME_IS_FULLY_COMPLETE(childStatus),
"We gave our child unconstrained height, so it should be complete");
return FinishReflowChild(aOuterWrapperFrame, aPresContext,
aWrappersDesiredSize, &wrapperReflowState,
xoffset, yoffset, 0);
}
void
nsNumberControlFrame::SyncDisabledState()
{

View File

@@ -159,11 +159,6 @@ private:
nsCSSPseudoElements::Type aPseudoType,
nsStyleContext* aParentContext);
nsresult ReflowAnonymousContent(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aWrappersDesiredSize,
const nsHTMLReflowState& aReflowState,
nsIFrame* aOuterWrapperFrame);
class SyncDisabledStateEvent;
friend class SyncDisabledStateEvent;
class SyncDisabledStateEvent : public nsRunnable

View File

@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<style>
div {
border: 3px solid black;
width: 308px;
height: 108px;
}
</style>
</head>
<body>
<div></div>
</body>
</html>

View File

@@ -0,0 +1,27 @@
<!DOCTYPE html>
<html>
<head>
<style>
input {
border: 3px solid black;
padding: 4px;
width: 300px;
height: 300px;
max-height: 100px;
box-sizing: content-box;
/* hide the spin buttons: */
-moz-appearance: textfield;
}
* > input[type=number] {
/* get rid of background gradient for Firefox OS */
background-color: transparent ! important;
}
</style>
</head>
<body>
<input type="number">
</body>
</html>

View File

@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<style>
div {
border: 3px solid black;
width: 294px;
height: 94px;
}
</style>
</head>
<body>
<div></div>
</body>
</html>

View File

@@ -0,0 +1,27 @@
<!DOCTYPE html>
<html>
<head>
<style>
input {
border: 3px solid black;
padding: 4px;
width: 300px;
height: 300px;
max-height: 100px;
box-sizing: border-box;
/* hide the spin buttons: */
-moz-appearance: textfield;
}
* > input[type=number] {
/* get rid of background gradient for Firefox OS */
background-color: transparent ! important;
}
</style>
</head>
<body>
<input type="number">
</body>
</html>

View File

@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<style>
div {
border: 3px solid black;
width: 308px;
height: 108px;
}
</style>
</head>
<body>
<div></div>
</body>
</html>

View File

@@ -0,0 +1,26 @@
<!DOCTYPE html>
<html>
<head>
<style>
input {
border: 3px solid black;
padding: 4px;
width: 300px;
min-height: 100px;
box-sizing: content-box;
/* hide the spin buttons: */
-moz-appearance: textfield;
}
* > input[type=number] {
/* get rid of background gradient for Firefox OS */
background-color: transparent ! important;
}
</style>
</head>
<body>
<input type="number">
</body>
</html>

View File

@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<style>
div {
border: 3px solid black;
width: 294px;
height: 94px;
}
</style>
</head>
<body>
<div></div>
</body>
</html>

View File

@@ -0,0 +1,26 @@
<!DOCTYPE html>
<html>
<head>
<style>
input {
border: 3px solid black;
padding: 4px;
width: 300px;
min-height: 100px;
box-sizing: border-box;
/* hide the spin buttons: */
-moz-appearance: textfield;
}
* > input[type=number] {
/* get rid of background gradient for Firefox OS */
background-color: transparent ! important;
}
</style>
</head>
<body>
<input type="number">
</body>
</html>

View File

@@ -20,6 +20,12 @@ fuzzy-if(/^Windows\x20NT\x205\.1/.test(http.oscpu),64,4) fuzzy-if(cocoaWidget,63
# disabled
== number-disabled.html number-disabled-ref.html
# min-height/max-height tests:
skip-if(B2G) == number-min-height-1.html number-min-height-1-ref.html
skip-if(B2G) == number-min-height-2.html number-min-height-2-ref.html
skip-if(B2G) == number-max-height-1.html number-max-height-1-ref.html
skip-if(B2G) == number-max-height-2.html number-max-height-2-ref.html
# focus
# autofocus is disabled on B2G
# https://bugzilla.mozilla.org/show_bug.cgi?id=965763