nsFrameList nsFrameList::ExtractHead(FrameLinkEnumerator& aLink) { NS_PRECONDITION(&aLink.List() == this, "Unexpected list"); NS_PRECONDITION(!aLink.PrevFrame() || aLink.PrevFrame()->GetNextSibling() == aLink.NextFrame(), "Unexpected PrevFrame()"); NS_PRECONDITION(aLink.PrevFrame() || aLink.NextFrame() == FirstChild(), "Unexpected NextFrame()"); NS_PRECONDITION(!aLink.PrevFrame() || aLink.NextFrame() != FirstChild(), "Unexpected NextFrame()"); NS_PRECONDITION(aLink.mEnd == nullptr, "Unexpected mEnd for frame link enumerator"); nsIFrame* prev = aLink.PrevFrame(); nsIFrame* newFirstFrame = nullptr; if (prev) { // Truncate the list after |prev| and hand the first part to our new list. prev->SetNextSibling(nullptr); newFirstFrame = mFirstChild; mFirstChild = aLink.NextFrame(); if (!mFirstChild) { // we handed over the whole list mLastChild = nullptr; } // Now make sure aLink doesn't point to a frame we no longer have. aLink.mPrev = nullptr; } // else aLink is pointing to before our first frame. Nothing to do. return nsFrameList(newFirstFrame, prev); }
// The following methods are all overridden to ensure that the menupopup frame // is placed in the appropriate list. nsFrameList nsMenuFrame::GetChildList(nsIAtom* aListName) const { if (nsGkAtoms::popupList == aListName) { return nsFrameList(mPopupFrame, mPopupFrame); } return nsBoxFrame::GetChildList(aListName); }
nsFrameList nsFrameList::RemoveFramesAfter(nsIFrame* aAfterFrame) { if (!aAfterFrame) { nsFrameList result; result.InsertFrames(nullptr, nullptr, *this); return result; } NS_PRECONDITION(NotEmpty(), "illegal operation on empty list"); #ifdef DEBUG_FRAME_LIST NS_PRECONDITION(ContainsFrame(aAfterFrame), "wrong list"); #endif nsIFrame* tail = aAfterFrame->GetNextSibling(); // if (!tail) return EmptyList(); -- worth optimizing this case? nsIFrame* oldLastChild = mLastChild; mLastChild = aAfterFrame; aAfterFrame->SetNextSibling(nullptr); return nsFrameList(tail, tail ? oldLastChild : nullptr); }
nsFrameList nsFrameList::ExtractTail(FrameLinkEnumerator& aLink) { NS_PRECONDITION(&aLink.List() == this, "Unexpected list"); NS_PRECONDITION(!aLink.PrevFrame() || aLink.PrevFrame()->GetNextSibling() == aLink.NextFrame(), "Unexpected PrevFrame()"); NS_PRECONDITION(aLink.PrevFrame() || aLink.NextFrame() == FirstChild(), "Unexpected NextFrame()"); NS_PRECONDITION(!aLink.PrevFrame() || aLink.NextFrame() != FirstChild(), "Unexpected NextFrame()"); NS_PRECONDITION(aLink.mEnd == nullptr, "Unexpected mEnd for frame link enumerator"); nsIFrame* prev = aLink.PrevFrame(); nsIFrame* newFirstFrame; nsIFrame* newLastFrame; if (prev) { // Truncate the list after |prev| and hand the second part to our new list prev->SetNextSibling(nullptr); newFirstFrame = aLink.NextFrame(); newLastFrame = newFirstFrame ? mLastChild : nullptr; mLastChild = prev; } else { // Hand the whole list over to our new list newFirstFrame = mFirstChild; newLastFrame = mLastChild; Clear(); } // Now make sure aLink doesn't point to a frame we no longer have. aLink.mFrame = nullptr; NS_POSTCONDITION(aLink.AtEnd(), "What's going on here?"); return nsFrameList(newFirstFrame, newLastFrame); }
NS_IMETHODIMP nsCanvasFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { DO_GLOBAL_REFLOW_COUNT("nsCanvasFrame"); DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus); NS_FRAME_TRACE_REFLOW_IN("nsCanvasFrame::Reflow"); // Initialize OUT parameter aStatus = NS_FRAME_COMPLETE; nsCanvasFrame* prevCanvasFrame = static_cast<nsCanvasFrame*> (GetPrevInFlow()); if (prevCanvasFrame) { nsAutoPtr<nsFrameList> overflow(prevCanvasFrame->StealOverflowFrames()); if (overflow) { NS_ASSERTION(overflow->OnlyChild(), "must have doc root as canvas frame's only child"); nsContainerFrame::ReparentFrameViewList(aPresContext, *overflow, prevCanvasFrame, this); // Prepend overflow to the our child list. There may already be // children placeholders for fixed-pos elements, which don't get // reflowed but must not be lost until the canvas frame is destroyed. mFrames.InsertFrames(this, nullptr, *overflow); } } // Set our size up front, since some parts of reflow depend on it // being already set. Note that the computed height may be // unconstrained; that's ok. Consumers should watch out for that. SetSize(nsSize(aReflowState.ComputedWidth(), aReflowState.ComputedHeight())); // Reflow our one and only normal child frame. It's either the root // element's frame or a placeholder for that frame, if the root element // is abs-pos or fixed-pos. We may have additional children which // are placeholders for continuations of fixed-pos content, but those // don't need to be reflowed. The normal child is always comes before // the fixed-pos placeholders, because we insert it at the start // of the child list, above. nsHTMLReflowMetrics kidDesiredSize; if (mFrames.IsEmpty()) { // We have no child frame, so return an empty size aDesiredSize.width = aDesiredSize.height = 0; } else { nsIFrame* kidFrame = mFrames.FirstChild(); bool kidDirty = (kidFrame->GetStateBits() & NS_FRAME_IS_DIRTY) != 0; nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame, nsSize(aReflowState.availableWidth, aReflowState.availableHeight)); if (aReflowState.mFlags.mVResize && (kidFrame->GetStateBits() & NS_FRAME_CONTAINS_RELATIVE_HEIGHT)) { // Tell our kid it's being vertically resized too. Bit of a // hack for framesets. kidReflowState.mFlags.mVResize = true; } nsPoint kidPt(kidReflowState.mComputedMargin.left, kidReflowState.mComputedMargin.top); // Apply CSS relative positioning const nsStyleDisplay* styleDisp = kidFrame->GetStyleDisplay(); if (NS_STYLE_POSITION_RELATIVE == styleDisp->mPosition) { kidPt += nsPoint(kidReflowState.mComputedOffsets.left, kidReflowState.mComputedOffsets.top); } // Reflow the frame ReflowChild(kidFrame, aPresContext, kidDesiredSize, kidReflowState, kidPt.x, kidPt.y, 0, aStatus); // Complete the reflow and position and size the child frame FinishReflowChild(kidFrame, aPresContext, &kidReflowState, kidDesiredSize, kidPt.x, kidPt.y, 0); if (!NS_FRAME_IS_FULLY_COMPLETE(aStatus)) { nsIFrame* nextFrame = kidFrame->GetNextInFlow(); NS_ASSERTION(nextFrame || aStatus & NS_FRAME_REFLOW_NEXTINFLOW, "If it's incomplete and has no nif yet, it must flag a nif reflow."); if (!nextFrame) { nsresult rv = aPresContext->PresShell()->FrameConstructor()-> CreateContinuingFrame(aPresContext, kidFrame, this, &nextFrame); NS_ENSURE_SUCCESS(rv, rv); SetOverflowFrames(aPresContext, nsFrameList(nextFrame, nextFrame)); // Root overflow containers will be normal children of // the canvas frame, but that's ok because there // aren't any other frames we need to isolate them from // during reflow. } if (NS_FRAME_OVERFLOW_IS_INCOMPLETE(aStatus)) { nextFrame->AddStateBits(NS_FRAME_IS_OVERFLOW_CONTAINER); } } // If the child frame was just inserted, then we're responsible for making sure // it repaints if (kidDirty) { // But we have a new child, which will affect our background, so // invalidate our whole rect. // Note: Even though we request to be sized to our child's size, our // scroll frame ensures that we are always the size of the viewport. // Also note: GetPosition() on a CanvasFrame is always going to return // (0, 0). We only want to invalidate GetRect() since Get*OverflowRect() // could also include overflow to our top and left (out of the viewport) // which doesn't need to be painted. nsIFrame* viewport = PresContext()->GetPresShell()->GetRootFrame(); viewport->InvalidateFrame(); } // Return our desired size. Normally it's what we're told, but // sometimes we can be given an unconstrained height (when a window // is sizing-to-content), and we should compute our desired height. aDesiredSize.width = aReflowState.ComputedWidth(); if (aReflowState.ComputedHeight() == NS_UNCONSTRAINEDSIZE) { aDesiredSize.height = kidFrame->GetRect().height + kidReflowState.mComputedMargin.TopBottom(); } else { aDesiredSize.height = aReflowState.ComputedHeight(); } aDesiredSize.SetOverflowAreasToDesiredBounds(); aDesiredSize.mOverflowAreas.UnionWith( kidDesiredSize.mOverflowAreas + kidPt); } if (prevCanvasFrame) { ReflowOverflowContainerChildren(aPresContext, aReflowState, aDesiredSize.mOverflowAreas, 0, aStatus); } FinishReflowWithAbsoluteFrames(aPresContext, aDesiredSize, aReflowState, aStatus); NS_FRAME_TRACE_REFLOW_OUT("nsCanvasFrame::Reflow", aStatus); NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); return NS_OK; }