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"
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
;
22 //#define DEBUG_REFLOW
26 nsIRootBox::GetRootBox(nsIPresShell
* aShell
)
31 nsIFrame
* rootFrame
= aShell
->FrameManager()->GetRootFrame();
37 rootFrame
= rootFrame
->GetFirstPrincipalChild();
40 nsIRootBox
* rootBox
= do_QueryFrame(rootFrame
);
44 class nsRootBoxFrame
: public nsBoxFrame
, public nsIRootBox
{
47 friend nsIFrame
* NS_NewBoxFrame(nsIPresShell
* aPresShell
, nsStyleContext
* aContext
);
49 explicit nsRootBoxFrame(nsStyleContext
* aContext
);
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 void AppendFrames(ChildListID aListID
,
62 nsFrameList
& aFrameList
) MOZ_OVERRIDE
;
63 virtual void InsertFrames(ChildListID aListID
,
65 nsFrameList
& aFrameList
) MOZ_OVERRIDE
;
66 virtual void RemoveFrame(ChildListID aListID
,
67 nsIFrame
* aOldFrame
) MOZ_OVERRIDE
;
69 virtual void 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
;
82 * Get the "type" of the frame
84 * @see nsGkAtoms::rootFrame
86 virtual nsIAtom
* GetType() const MOZ_OVERRIDE
;
88 virtual bool IsFrameOfType(uint32_t aFlags
) const MOZ_OVERRIDE
90 // Override bogus IsFrameOfType in nsBoxFrame.
91 if (aFlags
& (nsIFrame::eReplacedContainsBlock
| nsIFrame::eReplaced
))
93 return nsBoxFrame::IsFrameOfType(aFlags
);
96 #ifdef DEBUG_FRAME_DUMP
97 virtual nsresult
GetFrameName(nsAString
& aResult
) const MOZ_OVERRIDE
;
100 nsPopupSetFrame
* mPopupSetFrame
;
103 nsIContent
* mDefaultTooltip
;
106 //----------------------------------------------------------------------
109 NS_NewRootBoxFrame(nsIPresShell
* aPresShell
, nsStyleContext
* aContext
)
111 return new (aPresShell
) nsRootBoxFrame(aContext
);
114 NS_IMPL_FRAMEARENA_HELPERS(nsRootBoxFrame
)
116 nsRootBoxFrame::nsRootBoxFrame(nsStyleContext
* aContext
):
117 nsBoxFrame(aContext
, true)
119 mPopupSetFrame
= nullptr;
121 nsCOMPtr
<nsBoxLayout
> layout
;
122 NS_NewStackLayout(PresContext()->PresShell(), layout
);
123 SetLayoutManager(layout
);
127 nsRootBoxFrame::AppendFrames(ChildListID aListID
,
128 nsFrameList
& aFrameList
)
130 MOZ_ASSERT(aListID
== kPrincipalList
, "unexpected child list ID");
131 MOZ_ASSERT(mFrames
.IsEmpty(), "already have a child frame");
132 nsBoxFrame::AppendFrames(aListID
, aFrameList
);
136 nsRootBoxFrame::InsertFrames(ChildListID aListID
,
137 nsIFrame
* aPrevFrame
,
138 nsFrameList
& aFrameList
)
140 // Because we only support a single child frame inserting is the same
142 MOZ_ASSERT(!aPrevFrame
, "unexpected previous sibling frame");
143 AppendFrames(aListID
, aFrameList
);
147 nsRootBoxFrame::RemoveFrame(ChildListID aListID
,
150 NS_ASSERTION(aListID
== kPrincipalList
, "unexpected child list ID");
151 if (aOldFrame
== mFrames
.FirstChild()) {
152 nsBoxFrame::RemoveFrame(aListID
, aOldFrame
);
154 MOZ_CRASH("unknown aOldFrame");
159 int32_t gReflows
= 0;
163 nsRootBoxFrame::Reflow(nsPresContext
* aPresContext
,
164 nsHTMLReflowMetrics
& aDesiredSize
,
165 const nsHTMLReflowState
& aReflowState
,
166 nsReflowStatus
& aStatus
)
168 DO_GLOBAL_REFLOW_COUNT("nsRootBoxFrame");
172 printf("----Reflow %d----\n", gReflows
);
174 return nsBoxFrame::Reflow(aPresContext
, aDesiredSize
, aReflowState
, aStatus
);
178 nsRootBoxFrame::BuildDisplayList(nsDisplayListBuilder
* aBuilder
,
179 const nsRect
& aDirtyRect
,
180 const nsDisplayListSet
& aLists
)
182 // root boxes don't need a debug border/outline or a selection overlay...
183 // They *may* have a background propagated to them, so force creation
184 // of a background display list element.
185 DisplayBorderBackgroundOutline(aBuilder
, aLists
, true);
187 BuildDisplayListForChildren(aBuilder
, aDirtyRect
, aLists
);
191 nsRootBoxFrame::HandleEvent(nsPresContext
* aPresContext
,
192 WidgetGUIEvent
* aEvent
,
193 nsEventStatus
* aEventStatus
)
195 NS_ENSURE_ARG_POINTER(aEventStatus
);
196 if (nsEventStatus_eConsumeNoDefault
== *aEventStatus
) {
200 if (aEvent
->message
== NS_MOUSE_BUTTON_UP
) {
201 nsFrame::HandleEvent(aPresContext
, aEvent
, aEventStatus
);
207 // REVIEW: The override here was doing nothing since nsBoxFrame is our
210 nsRootBoxFrame::GetType() const
212 return nsGkAtoms::rootFrame
;
216 nsRootBoxFrame::GetPopupSetFrame()
218 return mPopupSetFrame
;
222 nsRootBoxFrame::SetPopupSetFrame(nsPopupSetFrame
* aPopupSet
)
224 // Under normal conditions this should only be called once. However,
225 // if something triggers ReconstructDocElementHierarchy, we will
226 // destroy this frame's child (the nsDocElementBoxFrame), but not this
227 // frame. This will cause the popupset to remove itself by calling
228 // |SetPopupSetFrame(nullptr)|, and then we'll be able to accept a new
229 // popupset. Since the anonymous content is associated with the
230 // nsDocElementBoxFrame, we'll get a new popupset when the new doc
231 // element box frame is created.
232 if (!mPopupSetFrame
|| !aPopupSet
) {
233 mPopupSetFrame
= aPopupSet
;
235 NS_NOTREACHED("Popup set is already defined! Only 1 allowed.");
240 nsRootBoxFrame::GetDefaultTooltip()
242 return mDefaultTooltip
;
246 nsRootBoxFrame::SetDefaultTooltip(nsIContent
* aTooltip
)
248 mDefaultTooltip
= aTooltip
;
252 nsRootBoxFrame::AddTooltipSupport(nsIContent
* aNode
)
254 NS_ENSURE_TRUE(aNode
, NS_ERROR_NULL_POINTER
);
256 nsXULTooltipListener
*listener
= nsXULTooltipListener::GetInstance();
258 return NS_ERROR_OUT_OF_MEMORY
;
260 return listener
->AddTooltipSupport(aNode
);
264 nsRootBoxFrame::RemoveTooltipSupport(nsIContent
* aNode
)
266 // XXjh yuck, I'll have to implement a way to get at
267 // the tooltip listener for a given node to make
268 // this work. Not crucial, we aren't removing
269 // tooltips from any nodes in the app just yet.
270 return NS_ERROR_NOT_IMPLEMENTED
;
273 NS_QUERYFRAME_HEAD(nsRootBoxFrame
)
274 NS_QUERYFRAME_ENTRY(nsIRootBox
)
275 NS_QUERYFRAME_TAIL_INHERITING(nsBoxFrame
)
277 #ifdef DEBUG_FRAME_DUMP
279 nsRootBoxFrame::GetFrameName(nsAString
& aResult
) const
281 return MakeFrameName(NS_LITERAL_STRING("RootBox"), aResult
);