From fbaf0bb26397aa498eb9156f06d5a6fe34dd7dd8 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 03:14:29 +0200 Subject: Merging upstream version 125.0.1. Signed-off-by: Daniel Baumann --- layout/generic/nsIFrame.cpp | 108 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 83 insertions(+), 25 deletions(-) (limited to 'layout/generic/nsIFrame.cpp') diff --git a/layout/generic/nsIFrame.cpp b/layout/generic/nsIFrame.cpp index 81109151ff..479c26d18b 100644 --- a/layout/generic/nsIFrame.cpp +++ b/layout/generic/nsIFrame.cpp @@ -2117,8 +2117,8 @@ nsIFrame::CaretBlockAxisMetrics nsIFrame::GetCaretBlockAxisMetrics( return CaretBlockAxisMetrics{.mOffset = baseline - ascent, .mExtent = height}; } -const nsAtom* nsIFrame::ComputePageValue() const { - const nsAtom* value = nsGkAtoms::_empty; +const nsAtom* nsIFrame::ComputePageValue(const nsAtom* aAutoValue) const { + const nsAtom* value = aAutoValue ? aAutoValue : nsGkAtoms::_empty; const nsIFrame* frame = this; // Find what CSS page name value this frame's subtree has, if any. // Starting with this frame, check if a page name other than auto is present, @@ -2484,7 +2484,7 @@ bool nsIFrame::CanBeDynamicReflowRoot() const { // If we participate in a container's block reflow context, or margins // can collapse through us, we can't be a dynamic reflow root. - if (IsBlockFrameOrSubclass() && !HasAnyStateBits(NS_BLOCK_BFC_STATE_BITS)) { + if (IsBlockFrameOrSubclass() && !HasAnyStateBits(NS_BLOCK_BFC)) { return false; } @@ -3409,6 +3409,9 @@ void nsIFrame::BuildDisplayListForStackingContext( ApplyClipProp(transformedCssClip); } + uint32_t numActiveScrollframesEncounteredBefore = + aBuilder->GetNumActiveScrollframesEncountered(); + nsDisplayListCollection set(aBuilder); Maybe clipForMask; { @@ -3692,17 +3695,22 @@ void nsIFrame::BuildDisplayListForStackingContext( if (transformItem) { resultList.AppendToTop(transformItem); createdContainer = true; - } - if (hasPerspective) { - transformItem->MarkWithAssociatedPerspective(); + if (numActiveScrollframesEncounteredBefore != + aBuilder->GetNumActiveScrollframesEncountered()) { + transformItem->SetContainsASRs(true); + } + + if (hasPerspective) { + transformItem->MarkWithAssociatedPerspective(); - if (clipCapturedBy == ContainerItemType::Perspective) { - clipState.Restore(); + if (clipCapturedBy == ContainerItemType::Perspective) { + clipState.Restore(); + } + resultList.AppendNewToTop(aBuilder, this, + &resultList); + createdContainer = true; } - resultList.AppendNewToTop(aBuilder, this, - &resultList); - createdContainer = true; } } @@ -5413,7 +5421,15 @@ static FrameTarget GetSelectionClosestFrame(nsIFrame* aFrame, const nsPoint& aPoint, uint32_t aFlags); -static bool SelfIsSelectable(nsIFrame* aFrame, uint32_t aFlags) { +static bool SelfIsSelectable(nsIFrame* aFrame, nsIFrame* aParentFrame, + uint32_t aFlags) { + // We should not move selection into a native anonymous subtree when handling + // selection outside it. + if ((aFlags & nsIFrame::IGNORE_NATIVE_ANONYMOUS_SUBTREE) && + aParentFrame->GetClosestNativeAnonymousSubtreeRoot() != + aFrame->GetClosestNativeAnonymousSubtreeRoot()) { + return false; + } if ((aFlags & nsIFrame::SKIP_HIDDEN) && !aFrame->StyleVisibility()->IsVisible()) { return false; @@ -5476,21 +5492,28 @@ static FrameTarget DrillDownToSelectionFrame(nsIFrame* aFrame, bool aEndFrame, nsIFrame* result = nullptr; nsIFrame* frame = aFrame->PrincipalChildList().FirstChild(); if (!aEndFrame) { - while (frame && (!SelfIsSelectable(frame, aFlags) || frame->IsEmpty())) + while (frame && + (!SelfIsSelectable(frame, aFrame, aFlags) || frame->IsEmpty())) { frame = frame->GetNextSibling(); - if (frame) result = frame; + } + if (frame) { + result = frame; + } } else { // Because the frame tree is singly linked, to find the last frame, // we have to iterate through all the frames // XXX I have a feeling this could be slow for long blocks, although // I can't find any slowdowns while (frame) { - if (!frame->IsEmpty() && SelfIsSelectable(frame, aFlags)) + if (!frame->IsEmpty() && SelfIsSelectable(frame, aFrame, aFlags)) { result = frame; + } frame = frame->GetNextSibling(); } } - if (result) return DrillDownToSelectionFrame(result, aEndFrame, aFlags); + if (result) { + return DrillDownToSelectionFrame(result, aEndFrame, aFlags); + } } // If the current frame has no targetable children, target the current frame return FrameTarget{aFrame, true, aEndFrame}; @@ -5502,8 +5525,9 @@ static FrameTarget GetSelectionClosestFrameForLine( nsBlockFrame* aParent, nsBlockFrame::LineIterator aLine, const nsPoint& aPoint, uint32_t aFlags) { // Account for end of lines (any iterator from the block is valid) - if (aLine == aParent->LinesEnd()) + if (aLine == aParent->LinesEnd()) { return DrillDownToSelectionFrame(aParent, true, aFlags); + } nsIFrame* frame = aLine->mFirstChild; nsIFrame* closestFromIStart = nullptr; nsIFrame* closestFromIEnd = nullptr; @@ -5519,7 +5543,7 @@ static FrameTarget GetSelectionClosestFrameForLine( // the previous thing had a different editableness than us, since then we // may end up not being able to select after it if the br is the last thing // on the line. - if (!SelfIsSelectable(frame, aFlags) || frame->IsEmpty() || + if (!SelfIsSelectable(frame, aParent, aFlags) || frame->IsEmpty() || (canSkipBr && frame->IsBrFrame() && lastFrameWasEditable == frame->GetContent()->IsEditable())) { continue; @@ -5699,7 +5723,7 @@ static FrameTarget GetSelectionClosestFrame(nsIFrame* aFrame, // Go through all the child frames to find the closest one nsIFrame::FrameWithDistance closest = {nullptr, nscoord_MAX, nscoord_MAX}; for (; kid; kid = kid->GetNextSibling()) { - if (!SelfIsSelectable(kid, aFlags) || kid->IsEmpty()) { + if (!SelfIsSelectable(kid, aFrame, aFlags) || kid->IsEmpty()) { continue; } @@ -9368,7 +9392,8 @@ nsresult nsIFrame::PeekOffsetForLineEdge(PeekOffsetStruct* aPos) { } } } - FrameTarget targetFrame = DrillDownToSelectionFrame(baseFrame, endOfLine, 0); + FrameTarget targetFrame = DrillDownToSelectionFrame( + baseFrame, endOfLine, nsIFrame::IGNORE_NATIVE_ANONYMOUS_SUBTREE); SetPeekResultFromFrame(*aPos, targetFrame.frame, endOfLine ? -1 : 0, OffsetIsAtLineEdge::Yes); if (endOfLine && targetFrame.frame->HasSignificantTerminalNewline()) { @@ -11538,11 +11563,44 @@ nsIFrame::PhysicalAxes nsIFrame::ShouldApplyOverflowClipping( return PhysicalAxes::None; } - // If we're paginated and a block, and have NS_BLOCK_CLIP_PAGINATED_OVERFLOW - // set, then we want to clip our overflow. - bool clip = HasAnyStateBits(NS_BLOCK_CLIP_PAGINATED_OVERFLOW) && - PresContext()->IsPaginated() && IsBlockFrame(); - return clip ? PhysicalAxes::Both : PhysicalAxes::None; + return IsSuppressedScrollableBlockForPrint() ? PhysicalAxes::Both + : PhysicalAxes::None; +} + +bool nsIFrame::IsSuppressedScrollableBlockForPrint() const { + // This condition needs to match the suppressScrollFrame logic in the frame + // constructor. + if (!PresContext()->IsPaginated() || !IsBlockFrame() || + !StyleDisplay()->IsScrollableOverflow() || + !StyleDisplay()->IsBlockOutsideStyle() || + mContent->IsInNativeAnonymousSubtree()) { + return false; + } + if (auto* element = Element::FromNode(mContent); + element && PresContext()->ElementWouldPropagateScrollStyles(*element)) { + return false; + } + return true; +} + +bool nsIFrame::HasUnreflowedContainerQueryAncestor() const { + // If this frame has done the first reflow, its ancestors are guaranteed to + // have as well. + if (!HasAnyStateBits(NS_FRAME_FIRST_REFLOW) || + !PresContext()->HasContainerQueryFrames()) { + return false; + } + for (nsIFrame* cur = GetInFlowParent(); cur; cur = cur->GetInFlowParent()) { + if (!cur->HasAnyStateBits(NS_FRAME_FIRST_REFLOW)) { + // Done first reflow from this ancestor up, including query containers. + return false; + } + if (cur->StyleDisplay()->IsQueryContainer()) { + return true; + } + } + // No query container from this frame up to root. + return false; } #ifdef DEBUG -- cgit v1.2.3