Bug 1675375 Part 7: Update expectations in helper_hittest_clippath.html. r=botond
[gecko.git] / layout / xul / nsRootBoxFrame.cpp
blob9cf8757cb4d88e86b780547e59fe2dce7fe55567
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 #include "nsHTMLParts.h"
8 #include "nsStyleConsts.h"
9 #include "nsGkAtoms.h"
10 #include "nsBoxFrame.h"
11 #include "nsDisplayList.h"
12 #include "nsStackLayout.h"
13 #include "nsIPopupContainer.h"
14 #include "nsIContent.h"
15 #include "nsFrameManager.h"
16 #include "nsLayoutUtils.h"
17 #include "mozilla/BasicEvents.h"
18 #include "mozilla/DisplayPortUtils.h"
19 #include "mozilla/PresShell.h"
21 using namespace mozilla;
23 // Interface IDs
25 // static
26 nsIPopupContainer* nsIPopupContainer::GetPopupContainer(PresShell* aPresShell) {
27 if (!aPresShell) {
28 return nullptr;
30 nsIFrame* rootFrame = aPresShell->GetRootFrame();
31 if (!rootFrame) {
32 return nullptr;
35 if (rootFrame) {
36 rootFrame = rootFrame->PrincipalChildList().FirstChild();
39 nsIPopupContainer* rootBox = do_QueryFrame(rootFrame);
41 // If the rootBox was not found yet this may be a top level non-XUL document.
42 if (rootFrame && !rootBox) {
43 // In a non-XUL document the rootFrame here will be a nsHTMLScrollFrame,
44 // get the nsCanvasFrame (which is the popup container) from it.
45 rootFrame = rootFrame->GetContentInsertionFrame();
46 rootBox = do_QueryFrame(rootFrame);
49 return rootBox;
52 class nsRootBoxFrame final : public nsBoxFrame, public nsIPopupContainer {
53 public:
54 friend nsIFrame* NS_NewBoxFrame(mozilla::PresShell* aPresShell,
55 ComputedStyle* aStyle);
57 explicit nsRootBoxFrame(ComputedStyle* aStyle, nsPresContext* aPresContext);
59 NS_DECL_QUERYFRAME
60 NS_DECL_FRAMEARENA_HELPERS(nsRootBoxFrame)
62 virtual nsPopupSetFrame* GetPopupSetFrame() override;
63 virtual void SetPopupSetFrame(nsPopupSetFrame* aPopupSet) override;
64 virtual dom::Element* GetDefaultTooltip() override;
65 virtual void SetDefaultTooltip(dom::Element* aTooltip) override;
67 virtual void AppendFrames(ChildListID aListID,
68 nsFrameList& aFrameList) override;
69 virtual void InsertFrames(ChildListID aListID, nsIFrame* aPrevFrame,
70 const nsLineList::iterator* aPrevFrameLine,
71 nsFrameList& aFrameList) override;
72 virtual void RemoveFrame(ChildListID aListID, nsIFrame* aOldFrame) override;
74 virtual void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
75 const ReflowInput& aReflowInput,
76 nsReflowStatus& aStatus) override;
77 virtual nsresult HandleEvent(nsPresContext* aPresContext,
78 WidgetGUIEvent* aEvent,
79 nsEventStatus* aEventStatus) override;
81 virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
82 const nsDisplayListSet& aLists) override;
84 virtual bool IsFrameOfType(uint32_t aFlags) const override {
85 // Override bogus IsFrameOfType in nsBoxFrame.
86 if (aFlags & (nsIFrame::eReplacedContainsBlock | nsIFrame::eReplaced))
87 return false;
88 return nsBoxFrame::IsFrameOfType(aFlags);
91 #ifdef DEBUG_FRAME_DUMP
92 virtual nsresult GetFrameName(nsAString& aResult) const override;
93 #endif
95 nsPopupSetFrame* mPopupSetFrame;
97 protected:
98 dom::Element* mDefaultTooltip;
101 //----------------------------------------------------------------------
103 nsContainerFrame* NS_NewRootBoxFrame(PresShell* aPresShell,
104 ComputedStyle* aStyle) {
105 return new (aPresShell) nsRootBoxFrame(aStyle, aPresShell->GetPresContext());
108 NS_IMPL_FRAMEARENA_HELPERS(nsRootBoxFrame)
110 nsRootBoxFrame::nsRootBoxFrame(ComputedStyle* aStyle,
111 nsPresContext* aPresContext)
112 : nsBoxFrame(aStyle, aPresContext, kClassID, true),
113 mPopupSetFrame(nullptr),
114 mDefaultTooltip(nullptr) {
115 nsCOMPtr<nsBoxLayout> layout;
116 NS_NewStackLayout(layout);
117 SetXULLayoutManager(layout);
120 void nsRootBoxFrame::AppendFrames(ChildListID aListID,
121 nsFrameList& aFrameList) {
122 MOZ_ASSERT(aListID == kPrincipalList, "unexpected child list ID");
123 MOZ_ASSERT(mFrames.IsEmpty(), "already have a child frame");
124 nsBoxFrame::AppendFrames(aListID, aFrameList);
127 void nsRootBoxFrame::InsertFrames(ChildListID aListID, nsIFrame* aPrevFrame,
128 const nsLineList::iterator* aPrevFrameLine,
129 nsFrameList& aFrameList) {
130 // Because we only support a single child frame inserting is the same
131 // as appending.
132 MOZ_ASSERT(!aPrevFrame, "unexpected previous sibling frame");
133 AppendFrames(aListID, aFrameList);
136 void nsRootBoxFrame::RemoveFrame(ChildListID aListID, nsIFrame* aOldFrame) {
137 NS_ASSERTION(aListID == kPrincipalList, "unexpected child list ID");
138 if (aOldFrame == mFrames.FirstChild()) {
139 nsBoxFrame::RemoveFrame(aListID, aOldFrame);
140 } else {
141 MOZ_CRASH("unknown aOldFrame");
145 void nsRootBoxFrame::Reflow(nsPresContext* aPresContext,
146 ReflowOutput& aDesiredSize,
147 const ReflowInput& aReflowInput,
148 nsReflowStatus& aStatus) {
149 DO_GLOBAL_REFLOW_COUNT("nsRootBoxFrame");
150 MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!");
152 return nsBoxFrame::Reflow(aPresContext, aDesiredSize, aReflowInput, aStatus);
155 void nsRootBoxFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
156 const nsDisplayListSet& aLists) {
157 if (mContent && mContent->GetProperty(nsGkAtoms::DisplayPortMargins)) {
158 // The XUL document's root element may have displayport margins set in
159 // ChromeProcessController::InitializeRoot, and we should to supply the
160 // base rect.
161 nsRect displayPortBase =
162 aBuilder->GetVisibleRect().Intersect(nsRect(nsPoint(0, 0), GetSize()));
163 DisplayPortUtils::SetDisplayPortBase(mContent, displayPortBase);
166 // root boxes don't need a debug border/outline or a selection overlay...
167 // They *may* have a background propagated to them, so force creation
168 // of a background display list element.
169 DisplayBorderBackgroundOutline(aBuilder, aLists, true);
171 BuildDisplayListForChildren(aBuilder, aLists);
174 nsresult nsRootBoxFrame::HandleEvent(nsPresContext* aPresContext,
175 WidgetGUIEvent* aEvent,
176 nsEventStatus* aEventStatus) {
177 NS_ENSURE_ARG_POINTER(aEventStatus);
178 if (nsEventStatus_eConsumeNoDefault == *aEventStatus) {
179 return NS_OK;
182 if (aEvent->mMessage == eMouseUp) {
183 nsIFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
186 return NS_OK;
189 nsPopupSetFrame* nsRootBoxFrame::GetPopupSetFrame() { return mPopupSetFrame; }
191 void nsRootBoxFrame::SetPopupSetFrame(nsPopupSetFrame* aPopupSet) {
192 // Under normal conditions this should only be called once. However,
193 // if something triggers ReconstructDocElementHierarchy, we will
194 // destroy this frame's child (the nsDocElementBoxFrame), but not this
195 // frame. This will cause the popupset to remove itself by calling
196 // |SetPopupSetFrame(nullptr)|, and then we'll be able to accept a new
197 // popupset. Since the anonymous content is associated with the
198 // nsDocElementBoxFrame, we'll get a new popupset when the new doc
199 // element box frame is created.
200 MOZ_ASSERT(!aPopupSet || !mPopupSetFrame,
201 "Popup set is already defined! Only 1 allowed.");
202 mPopupSetFrame = aPopupSet;
205 dom::Element* nsRootBoxFrame::GetDefaultTooltip() { return mDefaultTooltip; }
207 void nsRootBoxFrame::SetDefaultTooltip(dom::Element* aTooltip) {
208 mDefaultTooltip = aTooltip;
211 NS_QUERYFRAME_HEAD(nsRootBoxFrame)
212 NS_QUERYFRAME_ENTRY(nsIPopupContainer)
213 NS_QUERYFRAME_TAIL_INHERITING(nsBoxFrame)
215 #ifdef DEBUG_FRAME_DUMP
216 nsresult nsRootBoxFrame::GetFrameName(nsAString& aResult) const {
217 return MakeFrameName(u"RootBox"_ns, aResult);
219 #endif