nsRootBoxFrame.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  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. #include "nsHTMLParts.h"
  6. #include "nsStyleConsts.h"
  7. #include "nsGkAtoms.h"
  8. #include "nsIPresShell.h"
  9. #include "nsBoxFrame.h"
  10. #include "nsDisplayList.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"
  17. using namespace mozilla;
  18. // Interface IDs
  19. //#define DEBUG_REFLOW
  20. // static
  21. nsIRootBox*
  22. nsIRootBox::GetRootBox(nsIPresShell* aShell)
  23. {
  24. if (!aShell) {
  25. return nullptr;
  26. }
  27. nsIFrame* rootFrame = aShell->FrameManager()->GetRootFrame();
  28. if (!rootFrame) {
  29. return nullptr;
  30. }
  31. if (rootFrame) {
  32. rootFrame = rootFrame->PrincipalChildList().FirstChild();
  33. }
  34. nsIRootBox* rootBox = do_QueryFrame(rootFrame);
  35. return rootBox;
  36. }
  37. class nsRootBoxFrame : public nsBoxFrame, public nsIRootBox {
  38. public:
  39. friend nsIFrame* NS_NewBoxFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
  40. explicit nsRootBoxFrame(nsStyleContext* aContext);
  41. NS_DECL_QUERYFRAME
  42. NS_DECL_FRAMEARENA_HELPERS
  43. virtual nsPopupSetFrame* GetPopupSetFrame() override;
  44. virtual void SetPopupSetFrame(nsPopupSetFrame* aPopupSet) override;
  45. virtual nsIContent* GetDefaultTooltip() override;
  46. virtual void SetDefaultTooltip(nsIContent* aTooltip) override;
  47. virtual nsresult AddTooltipSupport(nsIContent* aNode) override;
  48. virtual nsresult RemoveTooltipSupport(nsIContent* aNode) override;
  49. virtual void AppendFrames(ChildListID aListID,
  50. nsFrameList& aFrameList) override;
  51. virtual void InsertFrames(ChildListID aListID,
  52. nsIFrame* aPrevFrame,
  53. nsFrameList& aFrameList) override;
  54. virtual void RemoveFrame(ChildListID aListID,
  55. nsIFrame* aOldFrame) override;
  56. virtual void Reflow(nsPresContext* aPresContext,
  57. ReflowOutput& aDesiredSize,
  58. const ReflowInput& aReflowInput,
  59. nsReflowStatus& aStatus) override;
  60. virtual nsresult HandleEvent(nsPresContext* aPresContext,
  61. WidgetGUIEvent* aEvent,
  62. nsEventStatus* aEventStatus) override;
  63. virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
  64. const nsDisplayListSet& aLists) override;
  65. /**
  66. * Get the "type" of the frame
  67. *
  68. * @see nsGkAtoms::rootFrame
  69. */
  70. virtual nsIAtom* GetType() const override;
  71. virtual bool IsFrameOfType(uint32_t aFlags) const override
  72. {
  73. // Override bogus IsFrameOfType in nsBoxFrame.
  74. if (aFlags & (nsIFrame::eReplacedContainsBlock | nsIFrame::eReplaced))
  75. return false;
  76. return nsBoxFrame::IsFrameOfType(aFlags);
  77. }
  78. #ifdef DEBUG_FRAME_DUMP
  79. virtual nsresult GetFrameName(nsAString& aResult) const override;
  80. #endif
  81. nsPopupSetFrame* mPopupSetFrame;
  82. protected:
  83. nsIContent* mDefaultTooltip;
  84. };
  85. //----------------------------------------------------------------------
  86. nsContainerFrame*
  87. NS_NewRootBoxFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
  88. {
  89. return new (aPresShell) nsRootBoxFrame(aContext);
  90. }
  91. NS_IMPL_FRAMEARENA_HELPERS(nsRootBoxFrame)
  92. nsRootBoxFrame::nsRootBoxFrame(nsStyleContext* aContext):
  93. nsBoxFrame(aContext, true)
  94. {
  95. mPopupSetFrame = nullptr;
  96. nsCOMPtr<nsBoxLayout> layout;
  97. NS_NewStackLayout(layout);
  98. SetXULLayoutManager(layout);
  99. }
  100. void
  101. nsRootBoxFrame::AppendFrames(ChildListID aListID,
  102. nsFrameList& aFrameList)
  103. {
  104. MOZ_ASSERT(aListID == kPrincipalList, "unexpected child list ID");
  105. MOZ_ASSERT(mFrames.IsEmpty(), "already have a child frame");
  106. nsBoxFrame::AppendFrames(aListID, aFrameList);
  107. }
  108. void
  109. nsRootBoxFrame::InsertFrames(ChildListID aListID,
  110. nsIFrame* aPrevFrame,
  111. nsFrameList& aFrameList)
  112. {
  113. // Because we only support a single child frame inserting is the same
  114. // as appending.
  115. MOZ_ASSERT(!aPrevFrame, "unexpected previous sibling frame");
  116. AppendFrames(aListID, aFrameList);
  117. }
  118. void
  119. nsRootBoxFrame::RemoveFrame(ChildListID aListID,
  120. nsIFrame* aOldFrame)
  121. {
  122. NS_ASSERTION(aListID == kPrincipalList, "unexpected child list ID");
  123. if (aOldFrame == mFrames.FirstChild()) {
  124. nsBoxFrame::RemoveFrame(aListID, aOldFrame);
  125. } else {
  126. MOZ_CRASH("unknown aOldFrame");
  127. }
  128. }
  129. #ifdef DEBUG_REFLOW
  130. int32_t gReflows = 0;
  131. #endif
  132. void
  133. nsRootBoxFrame::Reflow(nsPresContext* aPresContext,
  134. ReflowOutput& aDesiredSize,
  135. const ReflowInput& aReflowInput,
  136. nsReflowStatus& aStatus)
  137. {
  138. DO_GLOBAL_REFLOW_COUNT("nsRootBoxFrame");
  139. #ifdef DEBUG_REFLOW
  140. gReflows++;
  141. printf("----Reflow %d----\n", gReflows);
  142. #endif
  143. return nsBoxFrame::Reflow(aPresContext, aDesiredSize, aReflowInput, aStatus);
  144. }
  145. void
  146. nsRootBoxFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
  147. const nsDisplayListSet& aLists)
  148. {
  149. if (mContent && mContent->GetProperty(nsGkAtoms::DisplayPortMargins)) {
  150. // The XUL document's root element may have displayport margins set in
  151. // ChromeProcessController::InitializeRoot, and we should to supply the
  152. // base rect.
  153. nsRect displayPortBase =
  154. aBuilder->GetDirtyRect().Intersect(nsRect(nsPoint(0, 0), GetSize()));
  155. nsLayoutUtils::SetDisplayPortBase(mContent, displayPortBase);
  156. }
  157. // root boxes don't need a debug border/outline or a selection overlay...
  158. // They *may* have a background propagated to them, so force creation
  159. // of a background display list element.
  160. DisplayBorderBackgroundOutline(aBuilder, aLists, true);
  161. BuildDisplayListForChildren(aBuilder, aLists);
  162. }
  163. nsresult
  164. nsRootBoxFrame::HandleEvent(nsPresContext* aPresContext,
  165. WidgetGUIEvent* aEvent,
  166. nsEventStatus* aEventStatus)
  167. {
  168. NS_ENSURE_ARG_POINTER(aEventStatus);
  169. if (nsEventStatus_eConsumeNoDefault == *aEventStatus) {
  170. return NS_OK;
  171. }
  172. if (aEvent->mMessage == eMouseUp) {
  173. nsFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
  174. }
  175. return NS_OK;
  176. }
  177. // REVIEW: The override here was doing nothing since nsBoxFrame is our
  178. // parent class
  179. nsIAtom*
  180. nsRootBoxFrame::GetType() const
  181. {
  182. return nsGkAtoms::rootFrame;
  183. }
  184. nsPopupSetFrame*
  185. nsRootBoxFrame::GetPopupSetFrame()
  186. {
  187. return mPopupSetFrame;
  188. }
  189. void
  190. nsRootBoxFrame::SetPopupSetFrame(nsPopupSetFrame* aPopupSet)
  191. {
  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. if (!mPopupSetFrame || !aPopupSet) {
  201. mPopupSetFrame = aPopupSet;
  202. } else {
  203. NS_NOTREACHED("Popup set is already defined! Only 1 allowed.");
  204. }
  205. }
  206. nsIContent*
  207. nsRootBoxFrame::GetDefaultTooltip()
  208. {
  209. return mDefaultTooltip;
  210. }
  211. void
  212. nsRootBoxFrame::SetDefaultTooltip(nsIContent* aTooltip)
  213. {
  214. mDefaultTooltip = aTooltip;
  215. }
  216. nsresult
  217. nsRootBoxFrame::AddTooltipSupport(nsIContent* aNode)
  218. {
  219. NS_ENSURE_TRUE(aNode, NS_ERROR_NULL_POINTER);
  220. nsXULTooltipListener *listener = nsXULTooltipListener::GetInstance();
  221. if (!listener)
  222. return NS_ERROR_OUT_OF_MEMORY;
  223. return listener->AddTooltipSupport(aNode);
  224. }
  225. nsresult
  226. nsRootBoxFrame::RemoveTooltipSupport(nsIContent* aNode)
  227. {
  228. // XXjh yuck, I'll have to implement a way to get at
  229. // the tooltip listener for a given node to make
  230. // this work. Not crucial, we aren't removing
  231. // tooltips from any nodes in the app just yet.
  232. return NS_ERROR_NOT_IMPLEMENTED;
  233. }
  234. NS_QUERYFRAME_HEAD(nsRootBoxFrame)
  235. NS_QUERYFRAME_ENTRY(nsIRootBox)
  236. NS_QUERYFRAME_TAIL_INHERITING(nsBoxFrame)
  237. #ifdef DEBUG_FRAME_DUMP
  238. nsresult
  239. nsRootBoxFrame::GetFrameName(nsAString& aResult) const
  240. {
  241. return MakeFrameName(NS_LITERAL_STRING("RootBox"), aResult);
  242. }
  243. #endif