Bug 1877662 - expose mozconfig as an artifact from build-fat-aar. r=glandium,geckovie...
[gecko.git] / layout / base / nsFrameManager.cpp
blob87328ccb80ca88208cb8fa1bb477757890621f8c
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 /* storage of the frame tree and information about it */
9 #include "nsFrameManager.h"
11 #include "nscore.h"
12 #include "nsCOMPtr.h"
13 #include "plhash.h"
14 #include "nsPlaceholderFrame.h"
15 #include "nsGkAtoms.h"
16 #include "nsILayoutHistoryState.h"
17 #include "mozilla/PresShell.h"
18 #include "mozilla/PresState.h"
19 #include "mozilla/ComputedStyle.h"
20 #include "mozilla/dom/Element.h"
21 #include "mozilla/dom/Document.h"
23 #include "nsError.h"
24 #include "nsAbsoluteContainingBlock.h"
25 #include "ChildIterator.h"
27 #include "GeckoProfiler.h"
28 #include "nsIStatefulFrame.h"
29 #include "nsContainerFrame.h"
30 #include "nsWindowSizes.h"
32 #include "mozilla/MemoryReporting.h"
34 // #define DEBUG_UNDISPLAYED_MAP
35 // #define DEBUG_DISPLAY_CONTENTS_MAP
37 using namespace mozilla;
38 using namespace mozilla::dom;
40 //----------------------------------------------------------------------
42 nsFrameManager::~nsFrameManager() {
43 NS_ASSERTION(!mPresShell, "nsFrameManager::Destroy never called");
46 void nsFrameManager::Destroy() {
47 NS_ASSERTION(mPresShell, "Frame manager already shut down.");
49 // Destroy the frame hierarchy.
50 mPresShell->SetIgnoreFrameDestruction(true);
52 if (mRootFrame) {
53 FrameDestroyContext context(mPresShell);
54 mRootFrame->Destroy(context);
55 mRootFrame = nullptr;
58 mPresShell = nullptr;
61 //----------------------------------------------------------------------
62 void nsFrameManager::AppendFrames(nsContainerFrame* aParentFrame,
63 FrameChildListID aListID,
64 nsFrameList&& aFrameList) {
65 if (aParentFrame->IsAbsoluteContainer() &&
66 aListID == aParentFrame->GetAbsoluteListID()) {
67 aParentFrame->GetAbsoluteContainingBlock()->AppendFrames(
68 aParentFrame, aListID, std::move(aFrameList));
69 } else {
70 aParentFrame->AppendFrames(aListID, std::move(aFrameList));
74 void nsFrameManager::InsertFrames(nsContainerFrame* aParentFrame,
75 FrameChildListID aListID,
76 nsIFrame* aPrevFrame,
77 nsFrameList&& aFrameList) {
78 MOZ_ASSERT(
79 !aPrevFrame ||
80 (!aPrevFrame->GetNextContinuation() ||
81 (aPrevFrame->GetNextContinuation()->HasAnyStateBits(
82 NS_FRAME_IS_OVERFLOW_CONTAINER) &&
83 !aPrevFrame->HasAnyStateBits(NS_FRAME_IS_OVERFLOW_CONTAINER))),
84 "aPrevFrame must be the last continuation in its chain!");
86 if (aParentFrame->IsAbsoluteContainer() &&
87 aListID == aParentFrame->GetAbsoluteListID()) {
88 aParentFrame->GetAbsoluteContainingBlock()->InsertFrames(
89 aParentFrame, aListID, aPrevFrame, std::move(aFrameList));
90 } else {
91 aParentFrame->InsertFrames(aListID, aPrevFrame, nullptr,
92 std::move(aFrameList));
96 void nsFrameManager::RemoveFrame(DestroyContext& aContext,
97 FrameChildListID aListID,
98 nsIFrame* aOldFrame) {
99 // In case the reflow doesn't invalidate anything since it just leaves
100 // a gap where the old frame was, we invalidate it here. (This is
101 // reasonably likely to happen when removing a last child in a way
102 // that doesn't change the size of the parent.)
103 // This has to sure to invalidate the entire overflow rect; this
104 // is important in the presence of absolute positioning
105 aOldFrame->InvalidateFrameForRemoval();
107 NS_ASSERTION(!aOldFrame->GetPrevContinuation() ||
108 // exception for
109 // nsCSSFrameConstructor::RemoveFloatingFirstLetterFrames
110 aOldFrame->IsTextFrame(),
111 "Must remove first continuation.");
112 NS_ASSERTION(!(aOldFrame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW) &&
113 aOldFrame->GetPlaceholderFrame()),
114 "Must call RemoveFrame on placeholder for out-of-flows.");
115 nsContainerFrame* parentFrame = aOldFrame->GetParent();
116 if (parentFrame->IsAbsoluteContainer() &&
117 aListID == parentFrame->GetAbsoluteListID()) {
118 parentFrame->GetAbsoluteContainingBlock()->RemoveFrame(aContext, aListID,
119 aOldFrame);
120 } else {
121 parentFrame->RemoveFrame(aContext, aListID, aOldFrame);
125 //----------------------------------------------------------------------
127 // Capture state for a given frame.
128 // Accept a content id here, in some cases we may not have content (scroll
129 // position)
130 void nsFrameManager::CaptureFrameStateFor(nsIFrame* aFrame,
131 nsILayoutHistoryState* aState) {
132 if (!aFrame || !aState) {
133 NS_WARNING("null frame, or state");
134 return;
137 // Only capture state for stateful frames
138 nsIStatefulFrame* statefulFrame = do_QueryFrame(aFrame);
139 if (!statefulFrame) {
140 return;
143 // Capture the state, exit early if we get null (nothing to save)
144 UniquePtr<PresState> frameState = statefulFrame->SaveState();
145 if (!frameState) {
146 return;
149 // Generate the hash key to store the state under
150 // Exit early if we get empty key
151 nsAutoCString stateKey;
152 nsIContent* content = aFrame->GetContent();
153 Document* doc = content ? content->GetUncomposedDoc() : nullptr;
154 statefulFrame->GenerateStateKey(content, doc, stateKey);
155 if (stateKey.IsEmpty()) {
156 return;
159 // Store the state. aState owns frameState now.
160 aState->AddState(stateKey, std::move(frameState));
163 void nsFrameManager::CaptureFrameState(nsIFrame* aFrame,
164 nsILayoutHistoryState* aState) {
165 MOZ_ASSERT(nullptr != aFrame && nullptr != aState,
166 "null parameters passed in");
168 CaptureFrameStateFor(aFrame, aState);
170 // Now capture state recursively for the frame hierarchy rooted at aFrame
171 for (const auto& childList : aFrame->ChildLists()) {
172 for (nsIFrame* child : childList.mList) {
173 if (child->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW)) {
174 // We'll pick it up when we get to its placeholder
175 continue;
177 // Make sure to walk through placeholders as needed, so that we
178 // save state for out-of-flows which may not be our descendants
179 // themselves but whose placeholders are our descendants.
180 CaptureFrameState(nsPlaceholderFrame::GetRealFrameFor(child), aState);
185 // Restore state for a given frame.
186 // Accept a content id here, in some cases we may not have content (scroll
187 // position)
188 void nsFrameManager::RestoreFrameStateFor(nsIFrame* aFrame,
189 nsILayoutHistoryState* aState) {
190 if (!aFrame || !aState) {
191 NS_WARNING("null frame or state");
192 return;
195 // Only restore state for stateful frames
196 nsIStatefulFrame* statefulFrame = do_QueryFrame(aFrame);
197 if (!statefulFrame) {
198 return;
201 // Generate the hash key the state was stored under
202 // Exit early if we get empty key
203 nsIContent* content = aFrame->GetContent();
204 // If we don't have content, we can't generate a hash
205 // key and there's probably no state information for us.
206 if (!content) {
207 return;
210 nsAutoCString stateKey;
211 Document* doc = content->GetUncomposedDoc();
212 statefulFrame->GenerateStateKey(content, doc, stateKey);
213 if (stateKey.IsEmpty()) {
214 return;
217 // Get the state from the hash
218 PresState* frameState = aState->GetState(stateKey);
219 if (!frameState) {
220 return;
223 // Restore it
224 nsresult rv = statefulFrame->RestoreState(frameState);
225 if (NS_FAILED(rv)) {
226 return;
229 // If we restore ok, remove the state from the state table
230 aState->RemoveState(stateKey);
233 void nsFrameManager::RestoreFrameState(nsIFrame* aFrame,
234 nsILayoutHistoryState* aState) {
235 MOZ_ASSERT(nullptr != aFrame && nullptr != aState,
236 "null parameters passed in");
238 RestoreFrameStateFor(aFrame, aState);
240 // Now restore state recursively for the frame hierarchy rooted at aFrame
241 for (const auto& childList : aFrame->ChildLists()) {
242 for (nsIFrame* child : childList.mList) {
243 RestoreFrameState(child, aState);
248 void nsFrameManager::AddSizeOfIncludingThis(nsWindowSizes& aSizes) const {
249 aSizes.mLayoutPresShellSize += aSizes.mState.mMallocSizeOf(this);