Change the way we determine the style context parent frame to skip css anonboxes unless we're determining the style context parent for something that isitself a css anon box (and is not a non-element frame). Fixes bug 323656(which is where the patch is), bug 85872, bug 280610. As far as I can tell,also fixes bug 317876, bug 372376, bug 374297. r+sr=dbaron

This commit is contained in:
2007-04-15 16:14:26 -07:00
parent 80e27a8e0b
commit b571007aaf
18 changed files with 587 additions and 53 deletions

View File

@@ -118,6 +118,7 @@
#include "nsWidgetsCID.h" // for NS_LOOKANDFEEL_CID
#include "nsUnicharUtils.h"
#include "nsLayoutErrors.h"
#include "nsContentErrors.h"
#include "nsHTMLContainerFrame.h"
#include "nsBoxLayoutState.h"
#include "nsBlockFrame.h"
@@ -5433,25 +5434,15 @@ GetIBSpecialSibling(nsPresContext* aPresContext,
aPresContext->PropertyTable()->GetProperty(aFrame,
nsGkAtoms::IBSplitSpecialPrevSibling, &rv));
if (NS_OK == rv) {
if (NS_PROPTABLE_PROP_NOT_THERE == rv) {
*aSpecialSibling = nsnull;
rv = NS_OK;
} else if (NS_SUCCEEDED(rv)) {
NS_ASSERTION(specialSibling, "null special sibling");
*aSpecialSibling = specialSibling;
}
return NS_OK;
}
static PRBool
IsTablePseudo(nsIAtom* aPseudo)
{
return
aPseudo == nsCSSAnonBoxes::tableOuter ||
aPseudo == nsCSSAnonBoxes::table ||
aPseudo == nsCSSAnonBoxes::tableRowGroup ||
aPseudo == nsCSSAnonBoxes::tableRow ||
aPseudo == nsCSSAnonBoxes::tableCell ||
aPseudo == nsCSSAnonBoxes::tableColGroup ||
aPseudo == nsCSSAnonBoxes::tableCol;
return rv;
}
/**
@@ -5469,37 +5460,73 @@ GetCorrectedParent(nsPresContext* aPresContext, nsIFrame* aFrame,
nsIFrame** aSpecialParent)
{
nsIFrame *parent = aFrame->GetParent();
*aSpecialParent = parent;
if (parent) {
nsIAtom* pseudo = aFrame->GetStyleContext()->GetPseudoType();
// if this frame itself is not scrolled-content, then skip any scrolled-content
// parents since they're basically anonymous as far as the style system goes
if (pseudo != nsCSSAnonBoxes::scrolledContent) {
while (parent->GetStyleContext()->GetPseudoType() ==
nsCSSAnonBoxes::scrolledContent) {
parent = parent->GetParent();
}
}
// If the frame is not a table pseudo frame, we want to move up
// the tree till we get to a non-table-pseudo frame.
if (!IsTablePseudo(pseudo)) {
while (IsTablePseudo(parent->GetStyleContext()->GetPseudoType())) {
parent = parent->GetParent();
}
}
if (parent->GetStateBits() & NS_FRAME_IS_SPECIAL) {
GetIBSpecialSibling(aPresContext, parent, aSpecialParent);
} else {
*aSpecialParent = parent;
}
if (!parent) {
*aSpecialParent = nsnull;
} else {
*aSpecialParent =
nsFrame::CorrectStyleParentFrame(parent,
aFrame->GetStyleContext()->
GetPseudoType());
}
return NS_OK;
}
/* static */
nsIFrame*
nsFrame::CorrectStyleParentFrame(nsIFrame* aProspectiveParent,
nsIAtom* aChildPseudo)
{
NS_PRECONDITION(aProspectiveParent, "Must have a prospective parent");
// Anon boxes are parented to their actual parent already, except
// for non-elements. Those should not be treated as an anon box.
if (aChildPseudo && aChildPseudo != nsCSSAnonBoxes::mozNonElement &&
nsCSSAnonBoxes::IsAnonBox(aChildPseudo)) {
NS_ASSERTION(aChildPseudo != nsCSSAnonBoxes::mozAnonymousBlock &&
aChildPseudo != nsCSSAnonBoxes::mozAnonymousPositionedBlock,
"Should have dealt with kids that have NS_FRAME_IS_SPECIAL "
"elsewhere");
return aProspectiveParent;
}
// Otherwise, walk up out of all anon boxes
nsIFrame* parent = aProspectiveParent;
do {
if (parent->GetStateBits() & NS_FRAME_IS_SPECIAL) {
nsIFrame* sibling;
nsresult rv =
GetIBSpecialSibling(parent->PresContext(), parent, &sibling);
if (NS_FAILED(rv)) {
// If GetIBSpecialSibling fails, then what? we used to return what is
// now |aProspectiveParent|, but maybe |parent| would make more sense?
NS_NOTREACHED("Shouldn't get here");
return aProspectiveParent;
}
if (sibling) {
// |parent| was the block in an {ib} split; use the inline as
// |the style parent.
parent = sibling;
}
}
nsIAtom* parentPseudo = parent->GetStyleContext()->GetPseudoType();
if (!parentPseudo || !nsCSSAnonBoxes::IsAnonBox(parentPseudo)) {
return parent;
}
parent = parent->GetParent();
} while (parent);
// We can get here if aProspectiveParent is the scrollframe for a viewport
// and the kids are the anonymous scrollbars.
NS_ASSERTION(aProspectiveParent->GetStyleContext()->GetPseudoType() ==
nsCSSAnonBoxes::viewportScroll,
"Should have found a parent before this");
return aProspectiveParent;
}
nsresult
nsFrame::DoGetParentStyleContextFrame(nsPresContext* aPresContext,
nsIFrame** aProviderFrame,
@@ -5521,9 +5548,16 @@ nsFrame::DoGetParentStyleContextFrame(nsPresContext* aPresContext,
* using GetIBSpecialSibling
*/
if (mState & NS_FRAME_IS_SPECIAL) {
GetIBSpecialSibling(aPresContext, this, aProviderFrame);
if (*aProviderFrame)
nsresult rv = GetIBSpecialSibling(aPresContext, this, aProviderFrame);
if (NS_FAILED(rv)) {
NS_NOTREACHED("Shouldn't get here");
*aProviderFrame = nsnull;
return rv;
}
if (*aProviderFrame) {
return NS_OK;
}
}
// If this frame is one of the blocks that split an inline, we must