|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 /* |
|
7 * rendering object for the point that anchors out-of-flow rendering |
|
8 * objects such as floats and absolutely positioned elements |
|
9 */ |
|
10 |
|
11 /* |
|
12 * Destruction of a placeholder and its out-of-flow must observe the |
|
13 * following constraints: |
|
14 * |
|
15 * - The mapping from the out-of-flow to the placeholder must be |
|
16 * removed from the frame manager before the placeholder is destroyed. |
|
17 * - The mapping from the out-of-flow to the placeholder must be |
|
18 * removed from the frame manager before the out-of-flow is destroyed. |
|
19 * - The placeholder must be removed from the frame tree, or have the |
|
20 * mapping from it to its out-of-flow cleared, before the out-of-flow |
|
21 * is destroyed (so that the placeholder will not point to a destroyed |
|
22 * frame while it's in the frame tree). |
|
23 * |
|
24 * Furthermore, some code assumes that placeholders point to something |
|
25 * useful, so placeholders without an associated out-of-flow should not |
|
26 * remain in the tree. |
|
27 * |
|
28 * The placeholder's Destroy() implementation handles the destruction of |
|
29 * the placeholder and its out-of-flow. To avoid crashes, frame removal |
|
30 * and destruction code that works with placeholders must not assume |
|
31 * that the placeholder points to its out-of-flow. |
|
32 */ |
|
33 |
|
34 #ifndef nsPlaceholderFrame_h___ |
|
35 #define nsPlaceholderFrame_h___ |
|
36 |
|
37 #include "mozilla/Attributes.h" |
|
38 #include "nsFrame.h" |
|
39 #include "nsGkAtoms.h" |
|
40 |
|
41 nsIFrame* NS_NewPlaceholderFrame(nsIPresShell* aPresShell, |
|
42 nsStyleContext* aContext, |
|
43 nsFrameState aTypeBit); |
|
44 |
|
45 #define PLACEHOLDER_TYPE_MASK (PLACEHOLDER_FOR_FLOAT | \ |
|
46 PLACEHOLDER_FOR_ABSPOS | \ |
|
47 PLACEHOLDER_FOR_FIXEDPOS | \ |
|
48 PLACEHOLDER_FOR_POPUP) |
|
49 |
|
50 /** |
|
51 * Implementation of a frame that's used as a placeholder for a frame that |
|
52 * has been moved out of the flow. |
|
53 */ |
|
54 class nsPlaceholderFrame MOZ_FINAL : public nsFrame { |
|
55 public: |
|
56 NS_DECL_FRAMEARENA_HELPERS |
|
57 #ifdef DEBUG |
|
58 NS_DECL_QUERYFRAME_TARGET(nsPlaceholderFrame) |
|
59 NS_DECL_QUERYFRAME |
|
60 #endif |
|
61 |
|
62 /** |
|
63 * Create a new placeholder frame. aTypeBit must be one of the |
|
64 * PLACEHOLDER_FOR_* constants above. |
|
65 */ |
|
66 friend nsIFrame* NS_NewPlaceholderFrame(nsIPresShell* aPresShell, |
|
67 nsStyleContext* aContext, |
|
68 nsFrameState aTypeBit); |
|
69 nsPlaceholderFrame(nsStyleContext* aContext, nsFrameState aTypeBit) |
|
70 : nsFrame(aContext) |
|
71 { |
|
72 NS_PRECONDITION(aTypeBit == PLACEHOLDER_FOR_FLOAT || |
|
73 aTypeBit == PLACEHOLDER_FOR_ABSPOS || |
|
74 aTypeBit == PLACEHOLDER_FOR_FIXEDPOS || |
|
75 aTypeBit == PLACEHOLDER_FOR_POPUP, |
|
76 "Unexpected type bit"); |
|
77 AddStateBits(aTypeBit); |
|
78 } |
|
79 |
|
80 // Get/Set the associated out of flow frame |
|
81 nsIFrame* GetOutOfFlowFrame() const { return mOutOfFlowFrame; } |
|
82 void SetOutOfFlowFrame(nsIFrame* aFrame) { |
|
83 NS_ASSERTION(!aFrame || !aFrame->GetPrevContinuation(), |
|
84 "OOF must be first continuation"); |
|
85 mOutOfFlowFrame = aFrame; |
|
86 } |
|
87 |
|
88 // nsIFrame overrides |
|
89 // We need to override GetMinSize and GetPrefSize because XUL uses |
|
90 // placeholders not within lines. |
|
91 virtual void AddInlineMinWidth(nsRenderingContext* aRenderingContext, |
|
92 InlineMinWidthData* aData) MOZ_OVERRIDE; |
|
93 virtual void AddInlinePrefWidth(nsRenderingContext* aRenderingContext, |
|
94 InlinePrefWidthData* aData) MOZ_OVERRIDE; |
|
95 virtual nsSize GetMinSize(nsBoxLayoutState& aBoxLayoutState) MOZ_OVERRIDE; |
|
96 virtual nsSize GetPrefSize(nsBoxLayoutState& aBoxLayoutState) MOZ_OVERRIDE; |
|
97 virtual nsSize GetMaxSize(nsBoxLayoutState& aBoxLayoutState) MOZ_OVERRIDE; |
|
98 |
|
99 virtual nsresult Reflow(nsPresContext* aPresContext, |
|
100 nsHTMLReflowMetrics& aDesiredSize, |
|
101 const nsHTMLReflowState& aReflowState, |
|
102 nsReflowStatus& aStatus) MOZ_OVERRIDE; |
|
103 |
|
104 virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE; |
|
105 |
|
106 #if defined(DEBUG) || (defined(MOZ_REFLOW_PERF_DSP) && defined(MOZ_REFLOW_PERF)) |
|
107 virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, |
|
108 const nsRect& aDirtyRect, |
|
109 const nsDisplayListSet& aLists) MOZ_OVERRIDE; |
|
110 #endif // DEBUG || (MOZ_REFLOW_PERF_DSP && MOZ_REFLOW_PERF) |
|
111 |
|
112 #ifdef DEBUG_FRAME_DUMP |
|
113 void List(FILE* out = stderr, const char* aPrefix = "", uint32_t aFlags = 0) const MOZ_OVERRIDE; |
|
114 virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE; |
|
115 #endif // DEBUG |
|
116 |
|
117 /** |
|
118 * Get the "type" of the frame |
|
119 * |
|
120 * @see nsGkAtoms::placeholderFrame |
|
121 */ |
|
122 virtual nsIAtom* GetType() const MOZ_OVERRIDE; |
|
123 |
|
124 virtual bool IsEmpty() MOZ_OVERRIDE { return true; } |
|
125 virtual bool IsSelfEmpty() MOZ_OVERRIDE { return true; } |
|
126 |
|
127 virtual bool CanContinueTextRun() const MOZ_OVERRIDE; |
|
128 |
|
129 #ifdef ACCESSIBILITY |
|
130 virtual mozilla::a11y::AccType AccessibleType() MOZ_OVERRIDE |
|
131 { |
|
132 nsIFrame* realFrame = GetRealFrameForPlaceholder(this); |
|
133 return realFrame ? realFrame->AccessibleType() : |
|
134 nsFrame::AccessibleType(); |
|
135 } |
|
136 #endif |
|
137 |
|
138 virtual nsIFrame* GetParentStyleContextFrame() const MOZ_OVERRIDE; |
|
139 |
|
140 /** |
|
141 * @return the out-of-flow for aFrame if aFrame is a placeholder; otherwise |
|
142 * aFrame |
|
143 */ |
|
144 static nsIFrame* GetRealFrameFor(nsIFrame* aFrame) { |
|
145 NS_PRECONDITION(aFrame, "Must have a frame to work with"); |
|
146 if (aFrame->GetType() == nsGkAtoms::placeholderFrame) { |
|
147 return GetRealFrameForPlaceholder(aFrame); |
|
148 } |
|
149 return aFrame; |
|
150 } |
|
151 |
|
152 /** |
|
153 * @return the out-of-flow for aFrame, which is known to be a placeholder |
|
154 */ |
|
155 static nsIFrame* GetRealFrameForPlaceholder(nsIFrame* aFrame) { |
|
156 NS_PRECONDITION(aFrame->GetType() == nsGkAtoms::placeholderFrame, |
|
157 "Must have placeholder frame as input"); |
|
158 nsIFrame* outOfFlow = |
|
159 static_cast<nsPlaceholderFrame*>(aFrame)->GetOutOfFlowFrame(); |
|
160 NS_ASSERTION(outOfFlow, "Null out-of-flow for placeholder?"); |
|
161 return outOfFlow; |
|
162 } |
|
163 |
|
164 protected: |
|
165 nsIFrame* mOutOfFlowFrame; |
|
166 }; |
|
167 |
|
168 #endif /* nsPlaceholderFrame_h___ */ |