layout/xul/nsRootBoxFrame.cpp

changeset 0
6474c204b198
     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

mercurial