mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-08-23 12:53:07 +09:00
parent
5cef146d97
commit
eaf0831388
1 changed files with 70 additions and 147 deletions
|
|
@ -6323,132 +6323,25 @@ nsCSSFrameConstructor::GetFloatContainingBlock(nsIFrame* aFrame)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will check whether aContainer has :after generated content.
|
||||
* If so, appending to it should actually insert. The return value is the
|
||||
* parent to use for newly-appended content. *aAfterFrame points to the :after
|
||||
* frame before which appended content should go, if there is one.
|
||||
*/
|
||||
static nsContainerFrame*
|
||||
AdjustAppendParentForAfterContent(nsFrameManager* aFrameManager,
|
||||
nsIContent* aContainer,
|
||||
nsContainerFrame* aParentFrame,
|
||||
nsIContent* aChild,
|
||||
nsIFrame** aAfterFrame)
|
||||
{
|
||||
// If the parent frame has any pseudo-elements or aContainer is a
|
||||
// display:contents node then we need to walk through the child
|
||||
// frames to find the first one that is either a ::after frame for an
|
||||
// ancestor of aChild or a frame that is for a node later in the
|
||||
// document than aChild and return that in aAfterFrame.
|
||||
nsIFrame* afterBeforeOwnerFrame =
|
||||
nsLayoutUtils::FirstContinuationOrIBSplitSibling(aParentFrame);
|
||||
if (afterBeforeOwnerFrame->GetProperty(nsIFrame::GenConProperty()) ||
|
||||
nsLayoutUtils::HasPseudoStyle(aContainer, aParentFrame->StyleContext(),
|
||||
CSSPseudoElementType::after,
|
||||
aParentFrame->PresContext()) ||
|
||||
aFrameManager->GetDisplayContentsStyleFor(aContainer)) {
|
||||
nsIFrame* afterFrame = nullptr;
|
||||
nsContainerFrame* parent =
|
||||
static_cast<nsContainerFrame*>(aParentFrame->LastContinuation());
|
||||
bool done = false;
|
||||
while (!done && parent) {
|
||||
// Ensure that all normal flow children are on the principal child list.
|
||||
parent->DrainSelfOverflowList();
|
||||
|
||||
nsIFrame* child = parent->GetChildList(nsIFrame::kPrincipalList).LastChild();
|
||||
if (child && child->IsPseudoFrame(aContainer) &&
|
||||
!child->IsGeneratedContentFrame()) {
|
||||
// Drill down into non-generated pseudo frames of aContainer.
|
||||
nsContainerFrame* childAsContainer = do_QueryFrame(child);
|
||||
if (childAsContainer) {
|
||||
parent = nsLayoutUtils::LastContinuationWithChild(childAsContainer);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
for (; child; child = child->GetPrevSibling()) {
|
||||
nsIContent* c = child->GetContent();
|
||||
if (child->IsGeneratedContentFrame()) {
|
||||
nsIContent* p = c->GetParent();
|
||||
if (c->NodeInfo()->NameAtom() == nsGkAtoms::mozgeneratedcontentafter) {
|
||||
if (!nsContentUtils::ContentIsDescendantOf(aChild, p) &&
|
||||
p != aContainer &&
|
||||
nsContentUtils::PositionIsBefore(p, aChild)) {
|
||||
// ::after generated content for content earlier in the doc and not
|
||||
// for an ancestor. "p != aContainer" may seem redundant but it
|
||||
// checks if the ::after belongs to the XBL insertion point we're
|
||||
// inserting aChild into (in which case ContentIsDescendantOf is
|
||||
// false even though p == aContainer).
|
||||
// See layout/reftests/bugs/482592-1a.xhtml for an example of that.
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
} else if (nsContentUtils::PositionIsBefore(p, aChild)) {
|
||||
// Non-::after generated content for content earlier in the doc.
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
} else if (nsContentUtils::PositionIsBefore(c, aChild)) {
|
||||
// Content is before aChild.
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
afterFrame = child;
|
||||
}
|
||||
|
||||
parent = static_cast<nsContainerFrame*>(parent->GetPrevContinuation());
|
||||
}
|
||||
if (afterFrame) {
|
||||
*aAfterFrame = afterFrame;
|
||||
return afterFrame->GetParent();
|
||||
}
|
||||
}
|
||||
|
||||
*aAfterFrame = nullptr;
|
||||
|
||||
if (IsFramePartOfIBSplit(aParentFrame)) {
|
||||
// We might be in a situation where the last part of the {ib} split was
|
||||
// empty. Since we have no ::after pseudo-element, we do in fact want to be
|
||||
// appending to that last part, so advance to it if needed. Note that here
|
||||
// aParentFrame is the result of a GetLastIBSplitSibling call, so must be
|
||||
// either the last or next to last ib-split sibling.
|
||||
nsContainerFrame* trailingInline = GetIBSplitSibling(aParentFrame);
|
||||
if (trailingInline) {
|
||||
aParentFrame = trailingInline;
|
||||
}
|
||||
|
||||
// Always make sure to look at the last continuation of the frame
|
||||
// for the {ib} case, even if that continuation is empty. We
|
||||
// don't do this for the non-ib-split-frame case, since in the
|
||||
// other cases appending to the last nonempty continuation is fine
|
||||
// and in fact not doing that can confuse code that doesn't know
|
||||
// to pull kids from continuations other than its next one.
|
||||
aParentFrame =
|
||||
static_cast<nsContainerFrame*>(aParentFrame->LastContinuation());
|
||||
}
|
||||
|
||||
return aParentFrame;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will get the previous sibling to use for an append operation.
|
||||
* it takes a parent frame (must not be null) and its :after frame (may be
|
||||
* null).
|
||||
*
|
||||
* It takes a parent frame (must not be null) and the next insertion sibling, if
|
||||
* the parent content is display: contents or has ::after content (may be null).
|
||||
*/
|
||||
static nsIFrame*
|
||||
FindAppendPrevSibling(nsIFrame* aParentFrame, nsIFrame* aAfterFrame)
|
||||
FindAppendPrevSibling(nsIFrame* aParentFrame, nsIFrame* aNextSibling)
|
||||
{
|
||||
if (aAfterFrame) {
|
||||
NS_ASSERTION(aAfterFrame->GetParent() == aParentFrame, "Wrong parent");
|
||||
NS_ASSERTION(aAfterFrame->GetPrevSibling() ||
|
||||
aParentFrame->PrincipalChildList().FirstChild() == aAfterFrame,
|
||||
":after frame must be on the principal child list here");
|
||||
return aAfterFrame->GetPrevSibling();
|
||||
}
|
||||
|
||||
aParentFrame->DrainSelfOverflowList();
|
||||
|
||||
if (aNextSibling) {
|
||||
MOZ_ASSERT(aNextSibling->GetParent() == aParentFrame, "Wrong parent");
|
||||
MOZ_ASSERT(aNextSibling->GetPrevSibling() ||
|
||||
aParentFrame->PrincipalChildList().FirstChild() == aNextSibling,
|
||||
"next sibling must be on the principal child list here");
|
||||
return aNextSibling->GetPrevSibling();
|
||||
}
|
||||
|
||||
return aParentFrame->GetChildList(kPrincipalList).LastChild();
|
||||
}
|
||||
|
||||
|
|
@ -7417,7 +7310,7 @@ nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer,
|
|||
// If the frame we are manipulating is a ib-split frame (that is, one
|
||||
// that's been created as a result of a block-in-inline situation) then we
|
||||
// need to append to the last ib-split sibling, not to the frame itself.
|
||||
bool parentIBSplit = IsFramePartOfIBSplit(parentFrame);
|
||||
const bool parentIBSplit = IsFramePartOfIBSplit(parentFrame);
|
||||
if (parentIBSplit) {
|
||||
#ifdef DEBUG
|
||||
if (gNoisyContentUpdates) {
|
||||
|
|
@ -7443,36 +7336,63 @@ nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer,
|
|||
parentFrame->GetType() != nsGkAtoms::detailsFrame,
|
||||
"Parent frame should not be fieldset or details!");
|
||||
|
||||
// Deal with possible :after generated content on the parent
|
||||
nsIFrame* parentAfterFrame;
|
||||
nsContainerFrame* preAdjustedParentFrame = parentFrame;
|
||||
parentFrame =
|
||||
::AdjustAppendParentForAfterContent(this, insertion.mContainer, parentFrame,
|
||||
aFirstNewContent, &parentAfterFrame);
|
||||
|
||||
// See if the containing block has :first-letter style applied.
|
||||
bool haveFirstLetterStyle = false, haveFirstLineStyle = false;
|
||||
nsContainerFrame* containingBlock = GetFloatContainingBlock(parentFrame);
|
||||
if (containingBlock) {
|
||||
haveFirstLetterStyle = HasFirstLetterStyle(containingBlock);
|
||||
haveFirstLineStyle =
|
||||
ShouldHaveFirstLineStyle(containingBlock->GetContent(),
|
||||
containingBlock->StyleContext());
|
||||
// Deal with possible :after generated content on the parent, or display:
|
||||
// contents.
|
||||
nsIFrame* nextSibling = nullptr;
|
||||
if (GetDisplayContentsStyleFor(insertion.mContainer) ||
|
||||
nsLayoutUtils::GetAfterFrame(insertion.mContainer)) {
|
||||
FlattenedChildIterator iter(insertion.mContainer);
|
||||
iter.Seek(insertion.mContainer->GetLastChild());
|
||||
StyleDisplay unused = UNSET_DISPLAY;
|
||||
nextSibling = FindNextSibling(iter, unused);
|
||||
}
|
||||
|
||||
if (nextSibling) {
|
||||
parentFrame = nextSibling->GetParent()->GetContentInsertionFrame();
|
||||
} else if (parentIBSplit) {
|
||||
// We might be in a situation where the last part of the {ib} split was
|
||||
// empty. Since we have no ::after pseudo-element, we do in fact want to be
|
||||
// appending to that last part, so advance to it if needed. Note that here
|
||||
// aParentFrame is the result of a GetLastIBSplitSibling call, so must be
|
||||
// either the last or next to last ib-split sibling.
|
||||
if (nsContainerFrame* trailingInline = GetIBSplitSibling(parentFrame)) {
|
||||
parentFrame = trailingInline;
|
||||
}
|
||||
|
||||
// Always make sure to look at the last continuation of the frame
|
||||
// for the {ib} case, even if that continuation is empty. We
|
||||
// don't do this for the non-ib-split-frame case, since in the
|
||||
// other cases appending to the last nonempty continuation is fine
|
||||
// and in fact not doing that can confuse code that doesn't know
|
||||
// to pull kids from continuations other than its next one.
|
||||
parentFrame =
|
||||
static_cast<nsContainerFrame*>(parentFrame->LastContinuation());
|
||||
}
|
||||
|
||||
nsContainerFrame* containingBlock = GetFloatContainingBlock(parentFrame);
|
||||
|
||||
// See if the containing block has :first-letter style applied.
|
||||
const bool haveFirstLetterStyle =
|
||||
containingBlock && HasFirstLetterStyle(containingBlock);
|
||||
|
||||
const bool haveFirstLineStyle =
|
||||
containingBlock &&
|
||||
ShouldHaveFirstLineStyle(containingBlock->GetContent(),
|
||||
containingBlock->StyleContext());
|
||||
|
||||
if (haveFirstLetterStyle) {
|
||||
nsWeakFrame wf(parentAfterFrame);
|
||||
nsWeakFrame wf(nextSibling);
|
||||
// Before we get going, remove the current letter frames
|
||||
RemoveLetterFrames(mPresShell, containingBlock);
|
||||
|
||||
if (parentAfterFrame && !wf) {
|
||||
// Ouch, parentAfterFrame was a letter frame and we just deleted it!
|
||||
// Retry AdjustAppendParentForAfterContent; fortunately this is rare.
|
||||
parentFrame =
|
||||
::AdjustAppendParentForAfterContent(this, insertion.mContainer,
|
||||
preAdjustedParentFrame,
|
||||
aFirstNewContent, &parentAfterFrame);
|
||||
if (parentFrame != preAdjustedParentFrame) {
|
||||
// Reget nextSibling, since we may have killed it.
|
||||
if (nextSibling && !wf) {
|
||||
FlattenedChildIterator iter(insertion.mContainer);
|
||||
iter.Seek(insertion.mContainer->GetLastChild());
|
||||
StyleDisplay unused = UNSET_DISPLAY;
|
||||
nextSibling = FindNextSibling(iter, unused);
|
||||
if (nextSibling) {
|
||||
parentFrame = nextSibling->GetParent()->GetContentInsertionFrame();
|
||||
containingBlock = GetFloatContainingBlock(parentFrame);
|
||||
}
|
||||
}
|
||||
|
|
@ -7488,7 +7408,7 @@ nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer,
|
|||
nsIAtom* frameType = parentFrame->GetType();
|
||||
|
||||
FlattenedChildIterator iter(aContainer);
|
||||
bool haveNoXBLChildren = (!iter.XBLInvolved() || !iter.GetNextChild());
|
||||
const bool haveNoXBLChildren = !iter.XBLInvolved() || !iter.GetNextChild();
|
||||
FrameConstructionItemList items;
|
||||
if (aFirstNewContent->GetPreviousSibling() &&
|
||||
GetParentType(frameType) == eTypeBlock &&
|
||||
|
|
@ -7513,7 +7433,7 @@ nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer,
|
|||
AddFrameConstructionItems(state, child, false, insertion, items);
|
||||
}
|
||||
|
||||
nsIFrame* prevSibling = ::FindAppendPrevSibling(parentFrame, parentAfterFrame);
|
||||
nsIFrame* prevSibling = ::FindAppendPrevSibling(parentFrame, nextSibling);
|
||||
|
||||
// Perform special check for diddling around with the frames in
|
||||
// a ib-split inline frame.
|
||||
|
|
@ -7536,8 +7456,11 @@ nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer,
|
|||
!prevSibling->IsInlineOutside() ||
|
||||
prevSibling->GetType() == nsGkAtoms::brFrame);
|
||||
// :after content can't be <br> so no need to check it
|
||||
items.SetLineBoundaryAtEnd(!parentAfterFrame ||
|
||||
!parentAfterFrame->IsInlineOutside());
|
||||
//
|
||||
// FIXME(emilio): A display: contents sibling could! Write a test-case and
|
||||
// fix.
|
||||
items.SetLineBoundaryAtEnd(
|
||||
!nextSibling || !nextSibling->IsInlineOutside());
|
||||
}
|
||||
// To suppress whitespace-only text frames, we have to verify that
|
||||
// our container's DOM child list matches its flattened tree child list.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue