layout/xul/nsRootBoxFrame.cpp

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

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

mercurial