Bug 261064. Compute static absolute positions more accurately. Also, ensure that static absolutely positioned frames are moved when their placeholders move. Also, ensure that absolutely positioned frames positioned relative to the left or bottom edge of their container move when the container size changes. r+sr=dbaron (rubberstamp)
git-svn-id: svn://10.0.0.236/trunk@165349 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -251,19 +251,160 @@ nsAbsoluteContainingBlock::CalculateChildBounds(nsPresContext* aPresContext,
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
PRBool
|
||||
nsAbsoluteContainingBlock::ReflowingAbsolutesOnly(nsIFrame* aDelegatingFrame,
|
||||
const nsHTMLReflowState& aReflowState)
|
||||
{
|
||||
// See if the reflow command is targeted at us.
|
||||
nsReflowPath *path = aReflowState.path;
|
||||
nsHTMLReflowCommand *command = path->mReflowCommand;
|
||||
|
||||
if (command) {
|
||||
// It's targeted at us. See if it's for the positioned child frames
|
||||
nsCOMPtr<nsIAtom> listName;
|
||||
command->GetChildListName(*getter_AddRefs(listName));
|
||||
|
||||
if (GetChildListName() != listName) {
|
||||
// A reflow command is targeted directly at this block.
|
||||
// The block will have to do a proper reflow.
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
nsReflowPath::iterator iter = path->FirstChild();
|
||||
nsReflowPath::iterator end = path->EndChildren();
|
||||
|
||||
if (iter != end && mAbsoluteFrames.NotEmpty()) {
|
||||
for ( ; iter != end; ++iter) {
|
||||
// See if it's one of our absolutely positioned child frames
|
||||
if (!mAbsoluteFrames.ContainsFrame(*iter)) {
|
||||
// At least one of the frames along the reflow path wasn't
|
||||
// absolutely positioned, so we'll need to deal with it in
|
||||
// normal block reflow.
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
static PRBool IsFixedBorderSize(nsStyleUnit aUnit) {
|
||||
return aUnit == eStyleUnit_Coord || aUnit == eStyleUnit_Enumerated
|
||||
|| aUnit == eStyleUnit_Null;
|
||||
}
|
||||
static PRBool IsFixedPaddingSize(nsStyleUnit aUnit) {
|
||||
return aUnit == eStyleUnit_Coord || aUnit == eStyleUnit_Null;
|
||||
}
|
||||
static PRBool IsFixedMarginSize(nsStyleUnit aUnit) {
|
||||
return aUnit == eStyleUnit_Coord || aUnit == eStyleUnit_Null;
|
||||
}
|
||||
static PRBool IsFixedMaxSize(nsStyleUnit aUnit) {
|
||||
return aUnit == eStyleUnit_Null || aUnit == eStyleUnit_Coord;
|
||||
}
|
||||
|
||||
// XXX this logic should eventually be combined into the Reflow methods
|
||||
// so we reflow only those frames that need it
|
||||
PRBool
|
||||
nsAbsoluteContainingBlock::FramesDependOnContainer(PRBool aWidthChanged,
|
||||
PRBool aHeightChanged)
|
||||
{
|
||||
for (nsIFrame* f = mAbsoluteFrames.FirstChild(); f; f = f->GetNextSibling()) {
|
||||
const nsStylePosition* pos = f->GetStylePosition();
|
||||
// See if f's position might have changed because it depends on a
|
||||
// placeholder's position
|
||||
if (pos->mOffset.GetTopUnit() == eStyleUnit_Auto ||
|
||||
(f->GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL
|
||||
? pos->mOffset.GetRightUnit() : pos->mOffset.GetLeftUnit()) == eStyleUnit_Auto) {
|
||||
// Note that in CSS2.1, 'bottom:auto' can never actually induce a dependence
|
||||
// on the position of the placeholder
|
||||
return PR_TRUE;
|
||||
}
|
||||
if (!aWidthChanged && !aHeightChanged) {
|
||||
// skip getting style data
|
||||
continue;
|
||||
}
|
||||
const nsStyleBorder* border = f->GetStyleBorder();
|
||||
const nsStylePadding* padding = f->GetStylePadding();
|
||||
const nsStyleMargin* margin = f->GetStyleMargin();
|
||||
if (aWidthChanged) {
|
||||
// See if f's width might have changed.
|
||||
// If border-left, border-right, padding-left, padding-right,
|
||||
// width, min-width, and max-width are all lengths, 'none', or enumerated,
|
||||
// then our frame width does not depend on the parent width.
|
||||
if (pos->mWidth.GetUnit() != eStyleUnit_Coord ||
|
||||
pos->mMinWidth.GetUnit() != eStyleUnit_Coord ||
|
||||
!IsFixedMaxSize(pos->mMaxWidth.GetUnit()) ||
|
||||
!IsFixedBorderSize(border->mBorder.GetLeftUnit()) ||
|
||||
!IsFixedBorderSize(border->mBorder.GetRightUnit()) ||
|
||||
!IsFixedPaddingSize(padding->mPadding.GetLeftUnit()) ||
|
||||
!IsFixedPaddingSize(padding->mPadding.GetRightUnit())) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
// See if f's position might have changed. If we're RTL then the
|
||||
// rules are slightly different. We'll assume percentage or auto
|
||||
// margins will always induce a dependency on the size
|
||||
if (!IsFixedMarginSize(margin->mMargin.GetLeftUnit()) ||
|
||||
!IsFixedMarginSize(margin->mMargin.GetRightUnit())) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
if (f->GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) {
|
||||
// Note that even if 'left' is a length, our position can
|
||||
// still depend on the containing block width, because if
|
||||
// 'right' is also a length we will discard 'left' and be
|
||||
// positioned relative to the containing block right edge.
|
||||
// 'left' length and 'right' auto is the only combination
|
||||
// we can be sure of.
|
||||
if (pos->mOffset.GetLeftUnit() != eStyleUnit_Coord ||
|
||||
pos->mOffset.GetRightUnit() != eStyleUnit_Auto) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
} else {
|
||||
if (pos->mOffset.GetLeftUnit() != eStyleUnit_Coord) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (aHeightChanged) {
|
||||
// See if f's height might have changed.
|
||||
// If border-top, border-bottom, padding-top, padding-bottom,
|
||||
// min-height, and max-height are all lengths or 'none',
|
||||
// and height is a length or height and bottom are auto and top is not auto,
|
||||
// then our frame height does not depend on the parent height.
|
||||
if (!(pos->mHeight.GetUnit() == eStyleUnit_Coord ||
|
||||
(pos->mHeight.GetUnit() == eStyleUnit_Auto &&
|
||||
pos->mOffset.GetBottomUnit() == eStyleUnit_Auto &&
|
||||
pos->mOffset.GetTopUnit() != eStyleUnit_Auto)) ||
|
||||
pos->mMinHeight.GetUnit() != eStyleUnit_Coord ||
|
||||
!IsFixedMaxSize(pos->mMaxHeight.GetUnit()) ||
|
||||
!IsFixedBorderSize(border->mBorder.GetTopUnit()) ||
|
||||
!IsFixedBorderSize(border->mBorder.GetBottomUnit()) ||
|
||||
!IsFixedPaddingSize(padding->mPadding.GetTopUnit()) ||
|
||||
!IsFixedPaddingSize(padding->mPadding.GetBottomUnit())) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
// See if f's position might have changed.
|
||||
if (!IsFixedMarginSize(margin->mMargin.GetTopUnit()) ||
|
||||
!IsFixedMarginSize(margin->mMargin.GetBottomUnit())) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
if (pos->mOffset.GetTopUnit() != eStyleUnit_Coord) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
nsAbsoluteContainingBlock::IncrementalReflow(nsIFrame* aDelegatingFrame,
|
||||
nsPresContext* aPresContext,
|
||||
nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nscoord aContainingBlockWidth,
|
||||
nscoord aContainingBlockHeight,
|
||||
PRBool& aWasHandled)
|
||||
nscoord aContainingBlockHeight)
|
||||
{
|
||||
// Initialize the OUT parameters
|
||||
// Assume we handled the incremental reflow
|
||||
// until we find something that requires a full block reflow
|
||||
aWasHandled = PR_TRUE;
|
||||
|
||||
// See if the reflow command is targeted at us.
|
||||
nsReflowPath *path = aReflowState.path;
|
||||
nsHTMLReflowCommand *command = path->mReflowCommand;
|
||||
@@ -300,11 +441,6 @@ nsAbsoluteContainingBlock::IncrementalReflow(nsIFrame* aDelegatin
|
||||
reason, status);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// A reflow command is targeted directly at this block.
|
||||
// The block will have to do a proper reflow.
|
||||
// But keep going to make sure that we process any dirty absolute frames, below.
|
||||
aWasHandled = PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -326,20 +462,10 @@ nsAbsoluteContainingBlock::IncrementalReflow(nsIFrame* aDelegatin
|
||||
// repainting, and because it has a view if it changes size
|
||||
// the view manager will damage the dirty area
|
||||
|
||||
// Prune the path so we don't flow the block frame _again_
|
||||
// when returning to the caller.
|
||||
aReflowState.path->Remove(iter);
|
||||
}
|
||||
else {
|
||||
// At least one of the frames along the reflow path wasn't
|
||||
// absolutely positioned, so we'll need to deal with it in
|
||||
// normal block reflow.
|
||||
aWasHandled = PR_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -526,7 +652,7 @@ nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegat
|
||||
strcpy(aBuf, "UC");
|
||||
}
|
||||
else {
|
||||
if(0xdeadbeef == aSize)
|
||||
if((PRInt32)0xdeadbeef == aSize)
|
||||
{
|
||||
strcpy(aBuf, "deadbeef");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user