1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/xul/nsRootBoxFrame.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,310 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "nsHTMLParts.h" 1.10 +#include "nsStyleConsts.h" 1.11 +#include "nsGkAtoms.h" 1.12 +#include "nsIPresShell.h" 1.13 +#include "nsBoxFrame.h" 1.14 +#include "nsStackLayout.h" 1.15 +#include "nsIRootBox.h" 1.16 +#include "nsIContent.h" 1.17 +#include "nsXULTooltipListener.h" 1.18 +#include "nsFrameManager.h" 1.19 +#include "mozilla/BasicEvents.h" 1.20 + 1.21 +using namespace mozilla; 1.22 + 1.23 +// Interface IDs 1.24 + 1.25 +//#define DEBUG_REFLOW 1.26 + 1.27 +// static 1.28 +nsIRootBox* 1.29 +nsIRootBox::GetRootBox(nsIPresShell* aShell) 1.30 +{ 1.31 + if (!aShell) { 1.32 + return nullptr; 1.33 + } 1.34 + nsIFrame* rootFrame = aShell->FrameManager()->GetRootFrame(); 1.35 + if (!rootFrame) { 1.36 + return nullptr; 1.37 + } 1.38 + 1.39 + if (rootFrame) { 1.40 + rootFrame = rootFrame->GetFirstPrincipalChild(); 1.41 + } 1.42 + 1.43 + nsIRootBox* rootBox = do_QueryFrame(rootFrame); 1.44 + return rootBox; 1.45 +} 1.46 + 1.47 +class nsRootBoxFrame : public nsBoxFrame, public nsIRootBox { 1.48 +public: 1.49 + 1.50 + friend nsIFrame* NS_NewBoxFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); 1.51 + 1.52 + nsRootBoxFrame(nsIPresShell* aShell, nsStyleContext *aContext); 1.53 + 1.54 + NS_DECL_QUERYFRAME 1.55 + NS_DECL_FRAMEARENA_HELPERS 1.56 + 1.57 + virtual nsPopupSetFrame* GetPopupSetFrame() MOZ_OVERRIDE; 1.58 + virtual void SetPopupSetFrame(nsPopupSetFrame* aPopupSet) MOZ_OVERRIDE; 1.59 + virtual nsIContent* GetDefaultTooltip() MOZ_OVERRIDE; 1.60 + virtual void SetDefaultTooltip(nsIContent* aTooltip) MOZ_OVERRIDE; 1.61 + virtual nsresult AddTooltipSupport(nsIContent* aNode) MOZ_OVERRIDE; 1.62 + virtual nsresult RemoveTooltipSupport(nsIContent* aNode) MOZ_OVERRIDE; 1.63 + 1.64 + virtual nsresult AppendFrames(ChildListID aListID, 1.65 + nsFrameList& aFrameList) MOZ_OVERRIDE; 1.66 + virtual nsresult InsertFrames(ChildListID aListID, 1.67 + nsIFrame* aPrevFrame, 1.68 + nsFrameList& aFrameList) MOZ_OVERRIDE; 1.69 + virtual nsresult RemoveFrame(ChildListID aListID, 1.70 + nsIFrame* aOldFrame) MOZ_OVERRIDE; 1.71 + 1.72 + virtual nsresult Reflow(nsPresContext* aPresContext, 1.73 + nsHTMLReflowMetrics& aDesiredSize, 1.74 + const nsHTMLReflowState& aReflowState, 1.75 + nsReflowStatus& aStatus) MOZ_OVERRIDE; 1.76 + virtual nsresult HandleEvent(nsPresContext* aPresContext, 1.77 + WidgetGUIEvent* aEvent, 1.78 + nsEventStatus* aEventStatus) MOZ_OVERRIDE; 1.79 + 1.80 + virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, 1.81 + const nsRect& aDirtyRect, 1.82 + const nsDisplayListSet& aLists) MOZ_OVERRIDE; 1.83 + 1.84 + /** 1.85 + * Get the "type" of the frame 1.86 + * 1.87 + * @see nsGkAtoms::rootFrame 1.88 + */ 1.89 + virtual nsIAtom* GetType() const MOZ_OVERRIDE; 1.90 + 1.91 + virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE 1.92 + { 1.93 + // Override bogus IsFrameOfType in nsBoxFrame. 1.94 + if (aFlags & (nsIFrame::eReplacedContainsBlock | nsIFrame::eReplaced)) 1.95 + return false; 1.96 + return nsBoxFrame::IsFrameOfType(aFlags); 1.97 + } 1.98 + 1.99 +#ifdef DEBUG_FRAME_DUMP 1.100 + virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE; 1.101 +#endif 1.102 + 1.103 + nsPopupSetFrame* mPopupSetFrame; 1.104 + 1.105 +protected: 1.106 + nsIContent* mDefaultTooltip; 1.107 +}; 1.108 + 1.109 +//---------------------------------------------------------------------- 1.110 + 1.111 +nsIFrame* 1.112 +NS_NewRootBoxFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) 1.113 +{ 1.114 + return new (aPresShell) nsRootBoxFrame (aPresShell, aContext); 1.115 +} 1.116 + 1.117 +NS_IMPL_FRAMEARENA_HELPERS(nsRootBoxFrame) 1.118 + 1.119 +nsRootBoxFrame::nsRootBoxFrame(nsIPresShell* aShell, nsStyleContext* aContext): 1.120 + nsBoxFrame(aShell, aContext, true) 1.121 +{ 1.122 + mPopupSetFrame = nullptr; 1.123 + 1.124 + nsCOMPtr<nsBoxLayout> layout; 1.125 + NS_NewStackLayout(aShell, layout); 1.126 + SetLayoutManager(layout); 1.127 +} 1.128 + 1.129 +nsresult 1.130 +nsRootBoxFrame::AppendFrames(ChildListID aListID, 1.131 + nsFrameList& aFrameList) 1.132 +{ 1.133 + nsresult rv; 1.134 + 1.135 + NS_ASSERTION(aListID == kPrincipalList, "unexpected child list ID"); 1.136 + NS_PRECONDITION(mFrames.IsEmpty(), "already have a child frame"); 1.137 + if (aListID != kPrincipalList) { 1.138 + // We only support the principal child list. 1.139 + rv = NS_ERROR_INVALID_ARG; 1.140 + } else if (!mFrames.IsEmpty()) { 1.141 + // We only allow a single child frame. 1.142 + rv = NS_ERROR_FAILURE; 1.143 + } else { 1.144 + rv = nsBoxFrame::AppendFrames(aListID, aFrameList); 1.145 + } 1.146 + 1.147 + return rv; 1.148 +} 1.149 + 1.150 +nsresult 1.151 +nsRootBoxFrame::InsertFrames(ChildListID aListID, 1.152 + nsIFrame* aPrevFrame, 1.153 + nsFrameList& aFrameList) 1.154 +{ 1.155 + nsresult rv; 1.156 + 1.157 + // Because we only support a single child frame inserting is the same 1.158 + // as appending. 1.159 + NS_PRECONDITION(!aPrevFrame, "unexpected previous sibling frame"); 1.160 + if (aPrevFrame) { 1.161 + rv = NS_ERROR_UNEXPECTED; 1.162 + } else { 1.163 + rv = AppendFrames(aListID, aFrameList); 1.164 + } 1.165 + 1.166 + return rv; 1.167 +} 1.168 + 1.169 +nsresult 1.170 +nsRootBoxFrame::RemoveFrame(ChildListID aListID, 1.171 + nsIFrame* aOldFrame) 1.172 +{ 1.173 + nsresult rv; 1.174 + 1.175 + NS_ASSERTION(aListID == kPrincipalList, "unexpected child list ID"); 1.176 + if (aListID != kPrincipalList) { 1.177 + // We only support the principal child list. 1.178 + rv = NS_ERROR_INVALID_ARG; 1.179 + } else if (aOldFrame == mFrames.FirstChild()) { 1.180 + rv = nsBoxFrame::RemoveFrame(aListID, aOldFrame); 1.181 + } else { 1.182 + rv = NS_ERROR_FAILURE; 1.183 + } 1.184 + 1.185 + return rv; 1.186 +} 1.187 + 1.188 +#ifdef DEBUG_REFLOW 1.189 +int32_t gReflows = 0; 1.190 +#endif 1.191 + 1.192 +nsresult 1.193 +nsRootBoxFrame::Reflow(nsPresContext* aPresContext, 1.194 + nsHTMLReflowMetrics& aDesiredSize, 1.195 + const nsHTMLReflowState& aReflowState, 1.196 + nsReflowStatus& aStatus) 1.197 +{ 1.198 + DO_GLOBAL_REFLOW_COUNT("nsRootBoxFrame"); 1.199 + 1.200 +#ifdef DEBUG_REFLOW 1.201 + gReflows++; 1.202 + printf("----Reflow %d----\n", gReflows); 1.203 +#endif 1.204 + return nsBoxFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); 1.205 +} 1.206 + 1.207 +void 1.208 +nsRootBoxFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, 1.209 + const nsRect& aDirtyRect, 1.210 + const nsDisplayListSet& aLists) 1.211 +{ 1.212 + // root boxes don't need a debug border/outline or a selection overlay... 1.213 + // They *may* have a background propagated to them, so force creation 1.214 + // of a background display list element. 1.215 + DisplayBorderBackgroundOutline(aBuilder, aLists, true); 1.216 + 1.217 + BuildDisplayListForChildren(aBuilder, aDirtyRect, aLists); 1.218 +} 1.219 + 1.220 +nsresult 1.221 +nsRootBoxFrame::HandleEvent(nsPresContext* aPresContext, 1.222 + WidgetGUIEvent* aEvent, 1.223 + nsEventStatus* aEventStatus) 1.224 +{ 1.225 + NS_ENSURE_ARG_POINTER(aEventStatus); 1.226 + if (nsEventStatus_eConsumeNoDefault == *aEventStatus) { 1.227 + return NS_OK; 1.228 + } 1.229 + 1.230 + if (aEvent->message == NS_MOUSE_BUTTON_UP) { 1.231 + nsFrame::HandleEvent(aPresContext, aEvent, aEventStatus); 1.232 + } 1.233 + 1.234 + return NS_OK; 1.235 +} 1.236 + 1.237 +// REVIEW: The override here was doing nothing since nsBoxFrame is our 1.238 +// parent class 1.239 +nsIAtom* 1.240 +nsRootBoxFrame::GetType() const 1.241 +{ 1.242 + return nsGkAtoms::rootFrame; 1.243 +} 1.244 + 1.245 +nsPopupSetFrame* 1.246 +nsRootBoxFrame::GetPopupSetFrame() 1.247 +{ 1.248 + return mPopupSetFrame; 1.249 +} 1.250 + 1.251 +void 1.252 +nsRootBoxFrame::SetPopupSetFrame(nsPopupSetFrame* aPopupSet) 1.253 +{ 1.254 + // Under normal conditions this should only be called once. However, 1.255 + // if something triggers ReconstructDocElementHierarchy, we will 1.256 + // destroy this frame's child (the nsDocElementBoxFrame), but not this 1.257 + // frame. This will cause the popupset to remove itself by calling 1.258 + // |SetPopupSetFrame(nullptr)|, and then we'll be able to accept a new 1.259 + // popupset. Since the anonymous content is associated with the 1.260 + // nsDocElementBoxFrame, we'll get a new popupset when the new doc 1.261 + // element box frame is created. 1.262 + if (!mPopupSetFrame || !aPopupSet) { 1.263 + mPopupSetFrame = aPopupSet; 1.264 + } else { 1.265 + NS_NOTREACHED("Popup set is already defined! Only 1 allowed."); 1.266 + } 1.267 +} 1.268 + 1.269 +nsIContent* 1.270 +nsRootBoxFrame::GetDefaultTooltip() 1.271 +{ 1.272 + return mDefaultTooltip; 1.273 +} 1.274 + 1.275 +void 1.276 +nsRootBoxFrame::SetDefaultTooltip(nsIContent* aTooltip) 1.277 +{ 1.278 + mDefaultTooltip = aTooltip; 1.279 +} 1.280 + 1.281 +nsresult 1.282 +nsRootBoxFrame::AddTooltipSupport(nsIContent* aNode) 1.283 +{ 1.284 + NS_ENSURE_TRUE(aNode, NS_ERROR_NULL_POINTER); 1.285 + 1.286 + nsXULTooltipListener *listener = nsXULTooltipListener::GetInstance(); 1.287 + if (!listener) 1.288 + return NS_ERROR_OUT_OF_MEMORY; 1.289 + 1.290 + return listener->AddTooltipSupport(aNode); 1.291 +} 1.292 + 1.293 +nsresult 1.294 +nsRootBoxFrame::RemoveTooltipSupport(nsIContent* aNode) 1.295 +{ 1.296 + // XXjh yuck, I'll have to implement a way to get at 1.297 + // the tooltip listener for a given node to make 1.298 + // this work. Not crucial, we aren't removing 1.299 + // tooltips from any nodes in the app just yet. 1.300 + return NS_ERROR_NOT_IMPLEMENTED; 1.301 +} 1.302 + 1.303 +NS_QUERYFRAME_HEAD(nsRootBoxFrame) 1.304 + NS_QUERYFRAME_ENTRY(nsIRootBox) 1.305 +NS_QUERYFRAME_TAIL_INHERITING(nsBoxFrame) 1.306 + 1.307 +#ifdef DEBUG_FRAME_DUMP 1.308 +nsresult 1.309 +nsRootBoxFrame::GetFrameName(nsAString& aResult) const 1.310 +{ 1.311 + return MakeFrameName(NS_LITERAL_STRING("RootBox"), aResult); 1.312 +} 1.313 +#endif