зеркало из https://github.com/mozilla/pjs.git
Bug 282754. When laying out absolute children, use the computed width/height of the primary frame as the container metrics if they're available. r+sr=dbaron
This commit is contained in:
Родитель
01fcf62a47
Коммит
b5f18e8607
|
@ -7886,45 +7886,33 @@ nsCSSFrameConstructor::GetAbsoluteContainingBlock(nsIFrame* aFrame)
|
|||
// Starting with aFrame, look for a frame that is absolutely positioned or
|
||||
// relatively positioned
|
||||
nsIFrame* containingBlock = nsnull;
|
||||
for (nsIFrame* frame = aFrame; frame; frame = frame->GetParent()) {
|
||||
for (nsIFrame* frame = aFrame; frame && !containingBlock;
|
||||
frame = frame->GetParent()) {
|
||||
// Is it positioned?
|
||||
// If it's a table then ignore it, because for the time being tables
|
||||
// are not containers for absolutely positioned child frames
|
||||
const nsStyleDisplay* disp = frame->GetStyleDisplay();
|
||||
|
||||
if (disp->IsPositioned() && disp->mDisplay != NS_STYLE_DISPLAY_TABLE) {
|
||||
nsIAtom* frameType = frame->GetType();
|
||||
if (nsLayoutAtoms::scrollFrame == frameType) {
|
||||
// We want the scrolled frame, not either of the two scroll frames
|
||||
nsIFrame* scrolledFrame = frame->GetFirstChild(nsnull);
|
||||
if (scrolledFrame) {
|
||||
frameType = scrolledFrame->GetType();
|
||||
if (nsLayoutAtoms::areaFrame == frameType) {
|
||||
containingBlock = scrolledFrame;
|
||||
break;
|
||||
} else if (nsLayoutAtoms::scrollFrame == frameType) {
|
||||
scrolledFrame = scrolledFrame->GetFirstChild(nsnull);
|
||||
if (scrolledFrame) {
|
||||
if (nsLayoutAtoms::areaFrame == scrolledFrame->GetType()) {
|
||||
containingBlock = scrolledFrame;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Find the outermost wrapped block under this frame
|
||||
for (nsIFrame* wrappedFrame = frame->GetContentInsertionFrame();
|
||||
wrappedFrame != frame->GetParent();
|
||||
wrappedFrame = wrappedFrame->GetParent()) {
|
||||
nsIAtom* frameType = wrappedFrame->GetType();
|
||||
if (nsLayoutAtoms::areaFrame == frameType ||
|
||||
nsLayoutAtoms::blockFrame == frameType ||
|
||||
nsLayoutAtoms::positionedInlineFrame == frameType) {
|
||||
containingBlock = frame;
|
||||
} else if (nsLayoutAtoms::fieldSetFrame == frameType) {
|
||||
// If the positioned frame is a fieldset, use the area frame inside it.
|
||||
// We don't use GetContentInsertionFrame for fieldsets yet.
|
||||
containingBlock = frame->GetFirstChild(nsnull);
|
||||
}
|
||||
} else if ((nsLayoutAtoms::areaFrame == frameType) ||
|
||||
(nsLayoutAtoms::positionedInlineFrame == frameType)) {
|
||||
containingBlock = frame;
|
||||
break;
|
||||
} else if (nsLayoutAtoms::fieldSetFrame == frameType) {
|
||||
// If the positioned frame is a fieldset, use the area frame inside it
|
||||
containingBlock = frame->GetFirstChild(nsnull);
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
else {
|
||||
if (!containingBlock)
|
||||
NS_WARNING("Positioned frame that does not handle positioned kids; looking further up the parent chain");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -12848,10 +12836,13 @@ nsCSSFrameConstructor::ConstructBlock(nsFrameConstructorState& aState,
|
|||
blockFrame->AddStateBits(NS_BLOCK_SPACE_MGR | NS_BLOCK_MARGIN_ROOT);
|
||||
}
|
||||
|
||||
// ...and that we're the absolute containing block.
|
||||
// This makes absolute children of a block in columns be positioned
|
||||
// relative to the container, not flowed into columns. I don't know if this
|
||||
// is right...
|
||||
// We should make the outer frame be the absolute containing block,
|
||||
// if one is required. We have to do this because absolute
|
||||
// positioning must be computed with respect to the CSS dimensions
|
||||
// of the element, which are the dimensions of the outer block. But
|
||||
// we can't really do that because only blocks can have absolute
|
||||
// children. So use the block and try to compensate with hacks
|
||||
// in nsBlockFrame::CalculateContainingBlockSizeForAbsolutes.
|
||||
nsFrameConstructorSaveState absoluteSaveState;
|
||||
if (aAbsPosContainer || !aState.mAbsoluteItems.containingBlock) {
|
||||
// NS_ASSERTION(aRelPos, "should have made area frame for this");
|
||||
|
|
|
@ -555,9 +555,11 @@ CalculateContainingBlockSizeForAbsolutes(const nsHTMLReflowState& aReflowState,
|
|||
{
|
||||
// The issue here is that for a 'height' of 'auto' the reflow state
|
||||
// code won't know how to calculate the containing block height
|
||||
// because it's calculated bottom up. We don't really want to do
|
||||
// this for the initial containing block.
|
||||
if (nsLayoutUtils::IsInitialContainingBlock(aReflowState.frame)) {
|
||||
// because it's calculated bottom up. So we use our own computed
|
||||
// size as the dimensions. We don't really want to do this for the
|
||||
// initial containing block
|
||||
nsIFrame* frame = aReflowState.frame;
|
||||
if (nsLayoutUtils::IsInitialContainingBlock(frame)) {
|
||||
return nsSize(-1, -1);
|
||||
}
|
||||
|
||||
|
@ -569,6 +571,35 @@ CalculateContainingBlockSizeForAbsolutes(const nsHTMLReflowState& aReflowState,
|
|||
}
|
||||
cbSize.width -= border.left + border.right;
|
||||
cbSize.height -= border.top + border.bottom;
|
||||
|
||||
if (frame->GetParent()->GetContent() == frame->GetContent()) {
|
||||
// We are a wrapped frame for the content. Use the container's
|
||||
// dimensions, if they have been precomputed.
|
||||
// XXX This is a hack! We really should be waiting until the outermost
|
||||
// frame is fully reflowed and using the resulting dimensions, even
|
||||
// if they're intrinsic.
|
||||
// In fact we should be attaching absolute children to the outermost
|
||||
// frame and not always sticking them in block frames.
|
||||
|
||||
// First, find the reflow state for the outermost frame for this
|
||||
// content.
|
||||
const nsHTMLReflowState* aLastRS = &aReflowState;
|
||||
while (aLastRS->parentReflowState &&
|
||||
aLastRS->parentReflowState->frame->GetContent() == frame->GetContent()) {
|
||||
aLastRS = aLastRS->parentReflowState;
|
||||
}
|
||||
if (aLastRS != &aReflowState) {
|
||||
// We found a reflow state for the outermost wrapping frame, so use
|
||||
// its computed metrics if available
|
||||
if (aLastRS->mComputedWidth != NS_UNCONSTRAINEDSIZE) {
|
||||
cbSize.width = aLastRS->mComputedWidth;
|
||||
}
|
||||
if (aLastRS->mComputedHeight != NS_UNCONSTRAINEDSIZE) {
|
||||
cbSize.height = aLastRS->mComputedHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cbSize;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче