Wed, 31 Dec 2014 06:55:50 +0100
Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2
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/. */
6 #include "nsHTMLParts.h"
7 #include "nsStyleConsts.h"
8 #include "nsGkAtoms.h"
9 #include "nsIPresShell.h"
10 #include "nsBoxFrame.h"
11 #include "nsStackLayout.h"
12 #include "nsIRootBox.h"
13 #include "nsIContent.h"
14 #include "nsXULTooltipListener.h"
15 #include "nsFrameManager.h"
16 #include "mozilla/BasicEvents.h"
18 using namespace mozilla;
20 // Interface IDs
22 //#define DEBUG_REFLOW
24 // static
25 nsIRootBox*
26 nsIRootBox::GetRootBox(nsIPresShell* aShell)
27 {
28 if (!aShell) {
29 return nullptr;
30 }
31 nsIFrame* rootFrame = aShell->FrameManager()->GetRootFrame();
32 if (!rootFrame) {
33 return nullptr;
34 }
36 if (rootFrame) {
37 rootFrame = rootFrame->GetFirstPrincipalChild();
38 }
40 nsIRootBox* rootBox = do_QueryFrame(rootFrame);
41 return rootBox;
42 }
44 class nsRootBoxFrame : public nsBoxFrame, public nsIRootBox {
45 public:
47 friend nsIFrame* NS_NewBoxFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
49 nsRootBoxFrame(nsIPresShell* aShell, nsStyleContext *aContext);
51 NS_DECL_QUERYFRAME
52 NS_DECL_FRAMEARENA_HELPERS
54 virtual nsPopupSetFrame* GetPopupSetFrame() MOZ_OVERRIDE;
55 virtual void SetPopupSetFrame(nsPopupSetFrame* aPopupSet) MOZ_OVERRIDE;
56 virtual nsIContent* GetDefaultTooltip() MOZ_OVERRIDE;
57 virtual void SetDefaultTooltip(nsIContent* aTooltip) MOZ_OVERRIDE;
58 virtual nsresult AddTooltipSupport(nsIContent* aNode) MOZ_OVERRIDE;
59 virtual nsresult RemoveTooltipSupport(nsIContent* aNode) MOZ_OVERRIDE;
61 virtual nsresult AppendFrames(ChildListID aListID,
62 nsFrameList& aFrameList) MOZ_OVERRIDE;
63 virtual nsresult InsertFrames(ChildListID aListID,
64 nsIFrame* aPrevFrame,
65 nsFrameList& aFrameList) MOZ_OVERRIDE;
66 virtual nsresult RemoveFrame(ChildListID aListID,
67 nsIFrame* aOldFrame) MOZ_OVERRIDE;
69 virtual nsresult Reflow(nsPresContext* aPresContext,
70 nsHTMLReflowMetrics& aDesiredSize,
71 const nsHTMLReflowState& aReflowState,
72 nsReflowStatus& aStatus) MOZ_OVERRIDE;
73 virtual nsresult HandleEvent(nsPresContext* aPresContext,
74 WidgetGUIEvent* aEvent,
75 nsEventStatus* aEventStatus) MOZ_OVERRIDE;
77 virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
78 const nsRect& aDirtyRect,
79 const nsDisplayListSet& aLists) MOZ_OVERRIDE;
81 /**
82 * Get the "type" of the frame
83 *
84 * @see nsGkAtoms::rootFrame
85 */
86 virtual nsIAtom* GetType() const MOZ_OVERRIDE;
88 virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE
89 {
90 // Override bogus IsFrameOfType in nsBoxFrame.
91 if (aFlags & (nsIFrame::eReplacedContainsBlock | nsIFrame::eReplaced))
92 return false;
93 return nsBoxFrame::IsFrameOfType(aFlags);
94 }
96 #ifdef DEBUG_FRAME_DUMP
97 virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE;
98 #endif
100 nsPopupSetFrame* mPopupSetFrame;
102 protected:
103 nsIContent* mDefaultTooltip;
104 };
106 //----------------------------------------------------------------------
108 nsIFrame*
109 NS_NewRootBoxFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
110 {
111 return new (aPresShell) nsRootBoxFrame (aPresShell, aContext);
112 }
114 NS_IMPL_FRAMEARENA_HELPERS(nsRootBoxFrame)
116 nsRootBoxFrame::nsRootBoxFrame(nsIPresShell* aShell, nsStyleContext* aContext):
117 nsBoxFrame(aShell, aContext, true)
118 {
119 mPopupSetFrame = nullptr;
121 nsCOMPtr<nsBoxLayout> layout;
122 NS_NewStackLayout(aShell, layout);
123 SetLayoutManager(layout);
124 }
126 nsresult
127 nsRootBoxFrame::AppendFrames(ChildListID aListID,
128 nsFrameList& aFrameList)
129 {
130 nsresult rv;
132 NS_ASSERTION(aListID == kPrincipalList, "unexpected child list ID");
133 NS_PRECONDITION(mFrames.IsEmpty(), "already have a child frame");
134 if (aListID != kPrincipalList) {
135 // We only support the principal child list.
136 rv = NS_ERROR_INVALID_ARG;
137 } else if (!mFrames.IsEmpty()) {
138 // We only allow a single child frame.
139 rv = NS_ERROR_FAILURE;
140 } else {
141 rv = nsBoxFrame::AppendFrames(aListID, aFrameList);
142 }
144 return rv;
145 }
147 nsresult
148 nsRootBoxFrame::InsertFrames(ChildListID aListID,
149 nsIFrame* aPrevFrame,
150 nsFrameList& aFrameList)
151 {
152 nsresult rv;
154 // Because we only support a single child frame inserting is the same
155 // as appending.
156 NS_PRECONDITION(!aPrevFrame, "unexpected previous sibling frame");
157 if (aPrevFrame) {
158 rv = NS_ERROR_UNEXPECTED;
159 } else {
160 rv = AppendFrames(aListID, aFrameList);
161 }
163 return rv;
164 }
166 nsresult
167 nsRootBoxFrame::RemoveFrame(ChildListID aListID,
168 nsIFrame* aOldFrame)
169 {
170 nsresult rv;
172 NS_ASSERTION(aListID == kPrincipalList, "unexpected child list ID");
173 if (aListID != kPrincipalList) {
174 // We only support the principal child list.
175 rv = NS_ERROR_INVALID_ARG;
176 } else if (aOldFrame == mFrames.FirstChild()) {
177 rv = nsBoxFrame::RemoveFrame(aListID, aOldFrame);
178 } else {
179 rv = NS_ERROR_FAILURE;
180 }
182 return rv;
183 }
185 #ifdef DEBUG_REFLOW
186 int32_t gReflows = 0;
187 #endif
189 nsresult
190 nsRootBoxFrame::Reflow(nsPresContext* aPresContext,
191 nsHTMLReflowMetrics& aDesiredSize,
192 const nsHTMLReflowState& aReflowState,
193 nsReflowStatus& aStatus)
194 {
195 DO_GLOBAL_REFLOW_COUNT("nsRootBoxFrame");
197 #ifdef DEBUG_REFLOW
198 gReflows++;
199 printf("----Reflow %d----\n", gReflows);
200 #endif
201 return nsBoxFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
202 }
204 void
205 nsRootBoxFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
206 const nsRect& aDirtyRect,
207 const nsDisplayListSet& aLists)
208 {
209 // root boxes don't need a debug border/outline or a selection overlay...
210 // They *may* have a background propagated to them, so force creation
211 // of a background display list element.
212 DisplayBorderBackgroundOutline(aBuilder, aLists, true);
214 BuildDisplayListForChildren(aBuilder, aDirtyRect, aLists);
215 }
217 nsresult
218 nsRootBoxFrame::HandleEvent(nsPresContext* aPresContext,
219 WidgetGUIEvent* aEvent,
220 nsEventStatus* aEventStatus)
221 {
222 NS_ENSURE_ARG_POINTER(aEventStatus);
223 if (nsEventStatus_eConsumeNoDefault == *aEventStatus) {
224 return NS_OK;
225 }
227 if (aEvent->message == NS_MOUSE_BUTTON_UP) {
228 nsFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
229 }
231 return NS_OK;
232 }
234 // REVIEW: The override here was doing nothing since nsBoxFrame is our
235 // parent class
236 nsIAtom*
237 nsRootBoxFrame::GetType() const
238 {
239 return nsGkAtoms::rootFrame;
240 }
242 nsPopupSetFrame*
243 nsRootBoxFrame::GetPopupSetFrame()
244 {
245 return mPopupSetFrame;
246 }
248 void
249 nsRootBoxFrame::SetPopupSetFrame(nsPopupSetFrame* aPopupSet)
250 {
251 // Under normal conditions this should only be called once. However,
252 // if something triggers ReconstructDocElementHierarchy, we will
253 // destroy this frame's child (the nsDocElementBoxFrame), but not this
254 // frame. This will cause the popupset to remove itself by calling
255 // |SetPopupSetFrame(nullptr)|, and then we'll be able to accept a new
256 // popupset. Since the anonymous content is associated with the
257 // nsDocElementBoxFrame, we'll get a new popupset when the new doc
258 // element box frame is created.
259 if (!mPopupSetFrame || !aPopupSet) {
260 mPopupSetFrame = aPopupSet;
261 } else {
262 NS_NOTREACHED("Popup set is already defined! Only 1 allowed.");
263 }
264 }
266 nsIContent*
267 nsRootBoxFrame::GetDefaultTooltip()
268 {
269 return mDefaultTooltip;
270 }
272 void
273 nsRootBoxFrame::SetDefaultTooltip(nsIContent* aTooltip)
274 {
275 mDefaultTooltip = aTooltip;
276 }
278 nsresult
279 nsRootBoxFrame::AddTooltipSupport(nsIContent* aNode)
280 {
281 NS_ENSURE_TRUE(aNode, NS_ERROR_NULL_POINTER);
283 nsXULTooltipListener *listener = nsXULTooltipListener::GetInstance();
284 if (!listener)
285 return NS_ERROR_OUT_OF_MEMORY;
287 return listener->AddTooltipSupport(aNode);
288 }
290 nsresult
291 nsRootBoxFrame::RemoveTooltipSupport(nsIContent* aNode)
292 {
293 // XXjh yuck, I'll have to implement a way to get at
294 // the tooltip listener for a given node to make
295 // this work. Not crucial, we aren't removing
296 // tooltips from any nodes in the app just yet.
297 return NS_ERROR_NOT_IMPLEMENTED;
298 }
300 NS_QUERYFRAME_HEAD(nsRootBoxFrame)
301 NS_QUERYFRAME_ENTRY(nsIRootBox)
302 NS_QUERYFRAME_TAIL_INHERITING(nsBoxFrame)
304 #ifdef DEBUG_FRAME_DUMP
305 nsresult
306 nsRootBoxFrame::GetFrameName(nsAString& aResult) const
307 {
308 return MakeFrameName(NS_LITERAL_STRING("RootBox"), aResult);
309 }
310 #endif