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/. */
6 
7 /* storage of the frame tree and information about it */
8 
9 #ifndef _nsFrameManager_h_
10 #define _nsFrameManager_h_
11 
12 #include "nsDebug.h"
13 #include "mozilla/Attributes.h"
14 #include "nsFrameList.h"
15 
16 class nsContainerFrame;
17 class nsIFrame;
18 class nsILayoutHistoryState;
19 class nsIPresShell;
20 class nsPlaceholderFrame;
21 class nsStyleContext;
22 class nsWindowSizes;
23 namespace mozilla {
24 struct UndisplayedNode;
25 }
26 
27 /**
28  * Frame manager interface. The frame manager serves one purpose:
29  * <li>handles structural modifications to the frame model. If the frame model
30  * lock can be acquired, then the changes are processed immediately; otherwise,
31  * they're queued and processed later.
32  *
33  * FIXME(emilio): The comment above doesn't make any sense, there's no "frame
34  * model lock" of any sort afaict.
35  */
36 class nsFrameManager {
37   typedef mozilla::layout::FrameChildListID ChildListID;
38   typedef mozilla::UndisplayedNode UndisplayedNode;
39 
40  public:
nsFrameManager(nsIPresShell * aPresShell)41   explicit nsFrameManager(nsIPresShell* aPresShell)
42       : mPresShell(aPresShell),
43         mRootFrame(nullptr),
44         mDisplayNoneMap(nullptr),
45         mDisplayContentsMap(nullptr),
46         mIsDestroyingFrames(false) {
47     MOZ_ASSERT(mPresShell, "need a pres shell");
48   }
49   ~nsFrameManager();
50 
IsDestroyingFrames()51   bool IsDestroyingFrames() const { return mIsDestroyingFrames; }
52 
53   /*
54    * Gets and sets the root frame (typically the viewport). The lifetime of the
55    * root frame is controlled by the frame manager. When the frame manager is
56    * destroyed, it destroys the entire frame hierarchy.
57    */
GetRootFrame()58   nsIFrame* GetRootFrame() const { return mRootFrame; }
SetRootFrame(nsIFrame * aRootFrame)59   void SetRootFrame(nsIFrame* aRootFrame) {
60     NS_ASSERTION(!mRootFrame, "already have a root frame");
61     mRootFrame = aRootFrame;
62   }
63 
64   /*
65    * After Destroy is called, it is an error to call any FrameManager methods.
66    * Destroy should be called when the frame tree managed by the frame
67    * manager is no longer being displayed.
68    */
69   void Destroy();
70 
71   // display:none and display:contents content does not get an nsIFrame.  To
72   // enable the style context for such content to be obtained we store the
73   // contexts in a couple of hash tables.  The following methods provide the
74   // API that's used to set, reset, obtain and clear these style contexts.
75 
76   /**
77    * Register the style context for the display:none content, aContent.
78    */
79   void RegisterDisplayNoneStyleFor(nsIContent* aContent,
80                                    nsStyleContext* aStyleContext);
81 
82   /**
83    * Register the style context for the display:contents content, aContent.
84    */
85   void RegisterDisplayContentsStyleFor(nsIContent* aContent,
86                                        nsStyleContext* aStyleContext);
87 
88   /**
89    * Change the style context for the display:none content, aContent.
90    */
ChangeRegisteredDisplayNoneStyleFor(nsIContent * aContent,nsStyleContext * aStyleContext)91   void ChangeRegisteredDisplayNoneStyleFor(nsIContent* aContent,
92                                            nsStyleContext* aStyleContext) {
93     ChangeStyleContextInMap(mDisplayNoneMap, aContent, aStyleContext);
94   }
95 
96   /**
97    * Change the style context for the display:contents content, aContent.
98    */
ChangeRegisteredDisplayContentsStyleFor(nsIContent * aContent,nsStyleContext * aStyleContext)99   void ChangeRegisteredDisplayContentsStyleFor(nsIContent* aContent,
100                                                nsStyleContext* aStyleContext) {
101     ChangeStyleContextInMap(mDisplayContentsMap, aContent, aStyleContext);
102   }
103 
104   /**
105    * Get the style context for the display:none content, aContent, if any.
106    */
GetDisplayNoneStyleFor(const nsIContent * aContent)107   nsStyleContext* GetDisplayNoneStyleFor(const nsIContent* aContent) {
108     if (!mDisplayNoneMap) {
109       return nullptr;
110     }
111     return GetStyleContextInMap(mDisplayNoneMap, aContent);
112   }
113 
114   /**
115    * Get the style context for the display:contents content, aContent, if any.
116    */
GetDisplayContentsStyleFor(const nsIContent * aContent)117   nsStyleContext* GetDisplayContentsStyleFor(const nsIContent* aContent) {
118     if (!mDisplayContentsMap) {
119       return nullptr;
120     }
121     return GetStyleContextInMap(mDisplayContentsMap, aContent);
122   }
123 
124   /**
125    * Return the linked list of UndisplayedNodes that contain the style contexts
126    * that have been registered for the display:none children of
127    * aParentContent.
128    */
129   UndisplayedNode* GetAllRegisteredDisplayNoneStylesIn(
130       nsIContent* aParentContent);
131 
132   /**
133    * Return the linked list of UndisplayedNodes that contain the style contexts
134    * that have been registered for the display:contents children of
135    * aParentContent.
136    */
137   UndisplayedNode* GetAllRegisteredDisplayContentsStylesIn(
138       nsIContent* aParentContent);
139 
140   /**
141    * Unregister the style context for the display:none content, aContent,
142    * if any.  If found, then this method also unregisters the style contexts
143    * for any display:contents and display:none descendants of aContent.
144    */
145   void UnregisterDisplayNoneStyleFor(nsIContent* aContent,
146                                      nsIContent* aParentContent);
147 
148   /**
149    * Unregister the style context for the display:contents content, aContent,
150    * if any.  If found, then this method also unregisters the style contexts
151    * for any display:contents and display:none descendants of aContent.
152    */
153   void UnregisterDisplayContentsStyleFor(nsIContent* aContent,
154                                          nsIContent* aParentContent);
155 
156   // Functions for manipulating the frame model
157   void AppendFrames(nsContainerFrame* aParentFrame, ChildListID aListID,
158                     nsFrameList& aFrameList);
159 
160   void InsertFrames(nsContainerFrame* aParentFrame, ChildListID aListID,
161                     nsIFrame* aPrevFrame, nsFrameList& aFrameList);
162 
163   void RemoveFrame(ChildListID aListID, nsIFrame* aOldFrame);
164 
165   /*
166    * Notification that a frame is about to be destroyed. This allows any
167    * outstanding references to the frame to be cleaned up.
168    */
169   void NotifyDestroyingFrame(nsIFrame* aFrame);
170 
171   /*
172    * Capture/restore frame state for the frame subtree rooted at aFrame.
173    * aState is the document state storage object onto which each frame
174    * stores its state.  Callers of CaptureFrameState are responsible for
175    * traversing next continuations of special siblings of aFrame as
176    * needed; this method will only work with actual frametree descendants
177    * of aFrame.
178    */
179 
180   void CaptureFrameState(nsIFrame* aFrame, nsILayoutHistoryState* aState);
181 
182   void RestoreFrameState(nsIFrame* aFrame, nsILayoutHistoryState* aState);
183 
184   /*
185    * Add/restore state for one frame
186    */
187   void CaptureFrameStateFor(nsIFrame* aFrame, nsILayoutHistoryState* aState);
188 
189   void RestoreFrameStateFor(nsIFrame* aFrame, nsILayoutHistoryState* aState);
190 
191   void DestroyAnonymousContent(already_AddRefed<nsIContent> aContent);
192 
193   void AddSizeOfIncludingThis(nsWindowSizes& aSizes) const;
194 
195  protected:
196   class UndisplayedMap;
197 
198   static nsIContent* ParentForUndisplayedMap(const nsIContent* aContent);
199 
200   void ClearAllMapsFor(nsIContent* aParentContent);
201 
202   static nsStyleContext* GetStyleContextInMap(UndisplayedMap* aMap,
203                                               const nsIContent* aContent);
204   static UndisplayedNode* GetUndisplayedNodeInMapFor(
205       UndisplayedMap* aMap, const nsIContent* aContent);
206   static UndisplayedNode* GetAllUndisplayedNodesInMapFor(
207       UndisplayedMap* aMap, nsIContent* aParentContent);
208   static void SetStyleContextInMap(UndisplayedMap* aMap, nsIContent* aContent,
209                                    nsStyleContext* aStyleContext);
210   static void ChangeStyleContextInMap(UndisplayedMap* aMap,
211                                       nsIContent* aContent,
212                                       nsStyleContext* aStyleContext);
213 
214   // weak link, because the pres shell owns us
215   nsIPresShell* MOZ_NON_OWNING_REF mPresShell;
216   nsIFrame* mRootFrame;
217   UndisplayedMap* mDisplayNoneMap;
218   UndisplayedMap* mDisplayContentsMap;
219   bool mIsDestroyingFrames;  // The frame manager is destroying some frame(s).
220 };
221 
222 #endif
223