Bug 640443: Allow positioned display:-moz-box elements to be containers for absolutely-positioned content. r=bz

This commit is contained in:
Daniel Holbert 2012-03-10 14:49:10 -08:00
parent eaff5fa503
commit efab9b17ef
10 changed files with 258 additions and 2 deletions

View File

@ -3914,6 +3914,12 @@ bool IsXULDisplayType(const nsStyleDisplay* aDisplay)
#define SCROLLABLE_XUL_FCDATA(_func) \
FCDATA_DECL(FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_SKIP_ABSPOS_PUSH | \
FCDATA_MAY_NEED_SCROLLFRAME, _func)
// .. but we allow some XUL frames to be _containers_ for out-of-flow content
// (This is the same as SCROLLABLE_XUL_FCDATA, but w/o FCDATA_SKIP_ABSPOS_PUSH)
#define SCROLLABLE_ABSPOS_CONTAINER_XUL_FCDATA(_func) \
FCDATA_DECL(FCDATA_DISALLOW_OUT_OF_FLOW | \
FCDATA_MAY_NEED_SCROLLFRAME, _func)
#define SIMPLE_XUL_CREATE(_tag, _func) \
{ &nsGkAtoms::_tag, SIMPLE_XUL_FCDATA(_func) }
#define SCROLLABLE_XUL_CREATE(_tag, _func) \
@ -3922,6 +3928,8 @@ bool IsXULDisplayType(const nsStyleDisplay* aDisplay)
{ _int, SIMPLE_XUL_FCDATA(_func) }
#define SCROLLABLE_XUL_INT_CREATE(_int, _func) \
{ _int, SCROLLABLE_XUL_FCDATA(_func) }
#define SCROLLABLE_ABSPOS_CONTAINER_XUL_INT_CREATE(_int, _func) \
{ _int, SCROLLABLE_ABSPOS_CONTAINER_XUL_FCDATA(_func) }
static
nsIFrame* NS_NewGridBoxFrame(nsIPresShell* aPresShell,
@ -4117,8 +4125,10 @@ nsCSSFrameConstructor::FindXULDisplayData(const nsStyleDisplay* aDisplay,
nsStyleContext* aStyleContext)
{
static const FrameConstructionDataByInt sXULDisplayData[] = {
SCROLLABLE_XUL_INT_CREATE(NS_STYLE_DISPLAY_INLINE_BOX, NS_NewBoxFrame),
SCROLLABLE_XUL_INT_CREATE(NS_STYLE_DISPLAY_BOX, NS_NewBoxFrame),
SCROLLABLE_ABSPOS_CONTAINER_XUL_INT_CREATE(NS_STYLE_DISPLAY_INLINE_BOX,
NS_NewBoxFrame),
SCROLLABLE_ABSPOS_CONTAINER_XUL_INT_CREATE(NS_STYLE_DISPLAY_BOX,
NS_NewBoxFrame),
#ifdef MOZ_XUL
SCROLLABLE_XUL_INT_CREATE(NS_STYLE_DISPLAY_INLINE_GRID, NS_NewGridBoxFrame),
SCROLLABLE_XUL_INT_CREATE(NS_STYLE_DISPLAY_GRID, NS_NewGridBoxFrame),

View File

@ -0,0 +1,27 @@
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<html>
<head>
<style>
.relpos_parent {
position: relative;
width: 100px;
height: 100px;
background: lightblue;
}
.abspos_child {
position: absolute;
left: 30px;
bottom: 10px;
width: 20px;
height: 20px;
background: purple;
}
</style>
</head>
<body>
<div class="relpos_parent">
<div class="abspos_child"></div>
</div>
</body>
</html>

View File

@ -0,0 +1,30 @@
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<!-- This testcase has a relatively-positioned -moz-box element, which should
form a containing block for its absolutely positioned child. -->
<html>
<head>
<style>
.box { display: -moz-box }
.relpos_parent {
position: relative;
width: 100px;
height: 100px;
background: lightblue;
}
.abspos_child {
position: absolute;
left: 30px;
bottom: 10px;
width: 20px;
height: 20px;
background: purple;
}
</style>
</head>
<body>
<div class="box relpos_parent">
<div class="abspos_child"></div>
</div>
</body>
</html>

View File

@ -0,0 +1,29 @@
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<!-- This testcase is the same as the -1a version, but with -moz-inline-box. -->
<html>
<head>
<style>
.box { display: -moz-inline-box }
.relpos_parent {
position: relative;
width: 100px;
height: 100px;
background: lightblue;
}
.abspos_child {
position: absolute;
left: 30px;
bottom: 10px;
width: 20px;
height: 20px;
background: purple;
}
</style>
</head>
<body>
<div class="box relpos_parent">
<div class="abspos_child"></div>
</div>
</body>
</html>

View File

@ -0,0 +1,33 @@
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<!-- This testcase is the same as the -1a version, but with an additional
-moz-box wrapper, so that our relatively positioned box will never get a
call to Reflow. -->
<html>
<head>
<style>
.box { display: -moz-box }
.relpos_parent {
position: relative;
width: 100px;
height: 100px;
background: lightblue;
}
.abspos_child {
position: absolute;
left: 30px;
bottom: 10px;
width: 20px;
height: 20px;
background: purple;
}
</style>
</head>
<body>
<div class="box">
<div class="box relpos_parent">
<div class="abspos_child"></div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,31 @@
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<!-- This testcase is the same as the -1c version, but with -moz-inline-box. -->
<html>
<head>
<style>
.box { display: -moz-inline-box }
.relpos_parent {
position: relative;
width: 100px;
height: 100px;
background: lightblue;
}
.abspos_child {
position: absolute;
left: 30px;
bottom: 10px;
width: 20px;
height: 20px;
background: purple;
}
</style>
</head>
<body>
<div class="box">
<div class="box relpos_parent">
<div class="abspos_child"></div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,27 @@
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<html>
<head>
<style>
.relpos_parent {
position: relative;
width: 100px;
height: 100px;
background: lightblue;
}
.abspos_child {
position: absolute;
left: 30px;
top: 10px;
width: 20px;
height: 150px;
background: purple;
}
</style>
</head>
<body>
<div class="relpos_parent">
<div class="abspos_child"></div>
</div>
</body>
</html>

View File

@ -0,0 +1,31 @@
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<!-- This testcase has a relatively-positioned -moz-box element, which should
form a containing block for its absolutely positioned child. Also: in
this case, the child is taller than its container. -->
<html>
<head>
<style>
.box { display: -moz-box }
.relpos_parent {
position: relative;
width: 100px;
height: 100px;
background: lightblue;
}
.abspos_child {
position: absolute;
left: 30px;
top: 10px;
width: 20px;
height: 150px;
background: purple;
}
</style>
</head>
<body>
<div class="box relpos_parent">
<div class="abspos_child"></div>
</div>
</body>
</html>

View File

@ -1,3 +1,8 @@
== flexbox-abspos-container-1a.html flexbox-abspos-container-1-ref.html
== flexbox-abspos-container-1b.html flexbox-abspos-container-1-ref.html
== flexbox-abspos-container-1c.html flexbox-abspos-container-1-ref.html
== flexbox-abspos-container-1d.html flexbox-abspos-container-1-ref.html
== flexbox-abspos-container-2.html flexbox-abspos-container-2-ref.html
== flexbox-attributes-no-box-horizontal.xhtml flexbox-attributes-no-box-horizontal-ref.xhtml
== flexbox-attributes-no-box-vertical.xhtml flexbox-attributes-no-box-vertical-ref.xhtml
== flexbox-attributes-no-input-horizontal.xhtml flexbox-attributes-no-input-horizontal-ref.xhtml

View File

@ -758,6 +758,8 @@ nsBoxFrame::Reflow(nsPresContext* aPresContext,
}
#endif
ReflowAbsoluteFrames(aPresContext, aDesiredSize, aReflowState, aStatus);
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
return NS_OK;
}
@ -934,6 +936,35 @@ nsBoxFrame::DoLayout(nsBoxLayoutState& aState)
aState.SetLayoutFlags(oldFlags);
if (HasAbsolutelyPositionedChildren()) {
// Set up a |reflowState| to pass into ReflowAbsoluteFrames
nsHTMLReflowState reflowState(aState.PresContext(), this,
aState.GetRenderingContext(),
nsSize(mRect.width, NS_UNCONSTRAINEDSIZE));
// Set up a |desiredSize| to pass into ReflowAbsoluteFrames
nsHTMLReflowMetrics desiredSize;
desiredSize.width = mRect.width;
desiredSize.height = mRect.height;
// get the ascent (cribbed from ::Reflow)
nscoord ascent = mRect.height;
// getting the ascent could be a lot of work. Don't get it if
// we are the root. The viewport doesn't care about it.
if (!(mState & NS_STATE_IS_ROOT)) {
ascent = GetBoxAscent(aState);
}
desiredSize.ascent = ascent;
desiredSize.mOverflowAreas = GetOverflowAreas();
// Set up a |reflowStatus| to pass into ReflowAbsoluteFrames
// (just a dummy value; hopefully that's OK)
nsReflowStatus reflowStatus = NS_FRAME_COMPLETE;
ReflowAbsoluteFrames(aState.PresContext(), desiredSize,
reflowState, reflowStatus);
}
return rv;
}
@ -946,6 +977,8 @@ nsBoxFrame::DestroyFrom(nsIFrame* aDestructRoot)
// clean up the container box's layout manager and child boxes
SetLayoutManager(nsnull);
DestroyAbsoluteFrames(aDestructRoot);
nsContainerFrame::DestroyFrom(aDestructRoot);
}