layout/xul/nsLeafBoxFrame.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/layout/xul/nsLeafBoxFrame.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,381 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; 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 +//
    1.10 +// Eric Vaughan
    1.11 +// Netscape Communications
    1.12 +//
    1.13 +// See documentation in associated header file
    1.14 +//
    1.15 +
    1.16 +#include "nsLeafBoxFrame.h"
    1.17 +#include "nsBoxFrame.h"
    1.18 +#include "nsCOMPtr.h"
    1.19 +#include "nsGkAtoms.h"
    1.20 +#include "nsPresContext.h"
    1.21 +#include "nsStyleContext.h"
    1.22 +#include "nsIContent.h"
    1.23 +#include "nsNameSpaceManager.h"
    1.24 +#include "nsBoxLayoutState.h"
    1.25 +#include "nsWidgetsCID.h"
    1.26 +#include "nsViewManager.h"
    1.27 +#include "nsContainerFrame.h"
    1.28 +#include "nsDisplayList.h"
    1.29 +#include <algorithm>
    1.30 +
    1.31 +//
    1.32 +// NS_NewLeafBoxFrame
    1.33 +//
    1.34 +// Creates a new Toolbar frame and returns it
    1.35 +//
    1.36 +nsIFrame*
    1.37 +NS_NewLeafBoxFrame (nsIPresShell* aPresShell, nsStyleContext* aContext)
    1.38 +{
    1.39 +  return new (aPresShell) nsLeafBoxFrame(aPresShell, aContext);
    1.40 +}
    1.41 +
    1.42 +NS_IMPL_FRAMEARENA_HELPERS(nsLeafBoxFrame)
    1.43 +
    1.44 +nsLeafBoxFrame::nsLeafBoxFrame(nsIPresShell* aShell, nsStyleContext* aContext)
    1.45 +    : nsLeafFrame(aContext)
    1.46 +{
    1.47 +}
    1.48 +
    1.49 +#ifdef DEBUG_LAYOUT
    1.50 +void
    1.51 +nsLeafBoxFrame::GetBoxName(nsAutoString& aName)
    1.52 +{
    1.53 +   GetFrameName(aName);
    1.54 +}
    1.55 +#endif
    1.56 +
    1.57 +
    1.58 +/**
    1.59 + * Initialize us. This is a good time to get the alignment of the box
    1.60 + */
    1.61 +void
    1.62 +nsLeafBoxFrame::Init(
    1.63 +              nsIContent*      aContent,
    1.64 +              nsIFrame*        aParent,
    1.65 +              nsIFrame*        aPrevInFlow)
    1.66 +{
    1.67 +  nsLeafFrame::Init(aContent, aParent, aPrevInFlow);
    1.68 +
    1.69 +  if (GetStateBits() & NS_FRAME_FONT_INFLATION_CONTAINER) {
    1.70 +    AddStateBits(NS_FRAME_FONT_INFLATION_FLOW_ROOT);
    1.71 +  }
    1.72 +
    1.73 +  UpdateMouseThrough();
    1.74 +}
    1.75 +
    1.76 +nsresult
    1.77 +nsLeafBoxFrame::AttributeChanged(int32_t aNameSpaceID,
    1.78 +                                 nsIAtom* aAttribute,
    1.79 +                                 int32_t aModType)
    1.80 +{
    1.81 +  nsresult rv = nsLeafFrame::AttributeChanged(aNameSpaceID, aAttribute,
    1.82 +                                              aModType);
    1.83 +
    1.84 +  if (aAttribute == nsGkAtoms::mousethrough) 
    1.85 +    UpdateMouseThrough();
    1.86 +
    1.87 +  return rv;
    1.88 +}
    1.89 +
    1.90 +void nsLeafBoxFrame::UpdateMouseThrough()
    1.91 +{
    1.92 +  if (mContent) {
    1.93 +    static nsIContent::AttrValuesArray strings[] =
    1.94 +      {&nsGkAtoms::never, &nsGkAtoms::always, nullptr};
    1.95 +    switch (mContent->FindAttrValueIn(kNameSpaceID_None,
    1.96 +                                      nsGkAtoms::mousethrough,
    1.97 +                                      strings, eCaseMatters)) {
    1.98 +      case 0: AddStateBits(NS_FRAME_MOUSE_THROUGH_NEVER); break;
    1.99 +      case 1: AddStateBits(NS_FRAME_MOUSE_THROUGH_ALWAYS); break;
   1.100 +      case 2: {
   1.101 +          RemoveStateBits(NS_FRAME_MOUSE_THROUGH_ALWAYS);
   1.102 +          RemoveStateBits(NS_FRAME_MOUSE_THROUGH_NEVER);
   1.103 +          break;
   1.104 +      }
   1.105 +    }
   1.106 +  }
   1.107 +}
   1.108 +
   1.109 +void
   1.110 +nsLeafBoxFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
   1.111 +                                 const nsRect&           aDirtyRect,
   1.112 +                                 const nsDisplayListSet& aLists)
   1.113 +{
   1.114 +  // REVIEW: GetFrameForPoint used to not report events for the background
   1.115 +  // layer, whereas this code will put an event receiver for this frame in the
   1.116 +  // BlockBorderBackground() list. But I don't see any need to preserve
   1.117 +  // that anomalous behaviour. The important thing I'm preserving is that
   1.118 +  // leaf boxes continue to receive events in the foreground layer.
   1.119 +  DisplayBorderBackgroundOutline(aBuilder, aLists);
   1.120 +
   1.121 +  if (!aBuilder->IsForEventDelivery() || !IsVisibleForPainting(aBuilder))
   1.122 +    return;
   1.123 +
   1.124 +  aLists.Content()->AppendNewToTop(new (aBuilder)
   1.125 +    nsDisplayEventReceiver(aBuilder, this));
   1.126 +}
   1.127 +
   1.128 +/* virtual */ nscoord
   1.129 +nsLeafBoxFrame::GetMinWidth(nsRenderingContext *aRenderingContext)
   1.130 +{
   1.131 +  nscoord result;
   1.132 +  DISPLAY_MIN_WIDTH(this, result);
   1.133 +  nsBoxLayoutState state(PresContext(), aRenderingContext);
   1.134 +  nsSize minSize = GetMinSize(state);
   1.135 +
   1.136 +  // GetMinSize returns border-box width, and we want to return content
   1.137 +  // width.  Since Reflow uses the reflow state's border and padding, we
   1.138 +  // actually just want to subtract what GetMinSize added, which is the
   1.139 +  // result of GetBorderAndPadding.
   1.140 +  nsMargin bp;
   1.141 +  GetBorderAndPadding(bp);
   1.142 +
   1.143 +  result = minSize.width - bp.LeftRight();
   1.144 +
   1.145 +  return result;
   1.146 +}
   1.147 +
   1.148 +/* virtual */ nscoord
   1.149 +nsLeafBoxFrame::GetPrefWidth(nsRenderingContext *aRenderingContext)
   1.150 +{
   1.151 +  nscoord result;
   1.152 +  DISPLAY_PREF_WIDTH(this, result);
   1.153 +  nsBoxLayoutState state(PresContext(), aRenderingContext);
   1.154 +  nsSize prefSize = GetPrefSize(state);
   1.155 +
   1.156 +  // GetPrefSize returns border-box width, and we want to return content
   1.157 +  // width.  Since Reflow uses the reflow state's border and padding, we
   1.158 +  // actually just want to subtract what GetPrefSize added, which is the
   1.159 +  // result of GetBorderAndPadding.
   1.160 +  nsMargin bp;
   1.161 +  GetBorderAndPadding(bp);
   1.162 +
   1.163 +  result = prefSize.width - bp.LeftRight();
   1.164 +
   1.165 +  return result;
   1.166 +}
   1.167 +
   1.168 +nscoord
   1.169 +nsLeafBoxFrame::GetIntrinsicWidth()
   1.170 +{
   1.171 +  // No intrinsic width
   1.172 +  return 0;
   1.173 +}
   1.174 +
   1.175 +nsSize
   1.176 +nsLeafBoxFrame::ComputeAutoSize(nsRenderingContext *aRenderingContext,
   1.177 +                                nsSize aCBSize, nscoord aAvailableWidth,
   1.178 +                                nsSize aMargin, nsSize aBorder,
   1.179 +                                nsSize aPadding, bool aShrinkWrap)
   1.180 +{
   1.181 +  // Important: NOT calling our direct superclass here!
   1.182 +  return nsFrame::ComputeAutoSize(aRenderingContext, aCBSize, aAvailableWidth,
   1.183 +                                  aMargin, aBorder, aPadding, aShrinkWrap);
   1.184 +}
   1.185 +
   1.186 +nsresult
   1.187 +nsLeafBoxFrame::Reflow(nsPresContext*   aPresContext,
   1.188 +                     nsHTMLReflowMetrics&     aDesiredSize,
   1.189 +                     const nsHTMLReflowState& aReflowState,
   1.190 +                     nsReflowStatus&          aStatus)
   1.191 +{
   1.192 +  // This is mostly a copy of nsBoxFrame::Reflow().
   1.193 +  // We aren't able to share an implementation because of the frame
   1.194 +  // class hierarchy.  If you make changes here, please keep
   1.195 +  // nsBoxFrame::Reflow in sync.
   1.196 +
   1.197 +  DO_GLOBAL_REFLOW_COUNT("nsLeafBoxFrame");
   1.198 +  DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
   1.199 +
   1.200 +  NS_ASSERTION(aReflowState.ComputedWidth() >=0 &&
   1.201 +               aReflowState.ComputedHeight() >= 0, "Computed Size < 0");
   1.202 +
   1.203 +#ifdef DO_NOISY_REFLOW
   1.204 +  printf("\n-------------Starting LeafBoxFrame Reflow ----------------------------\n");
   1.205 +  printf("%p ** nsLBF::Reflow %d R: ", this, myCounter++);
   1.206 +  switch (aReflowState.reason) {
   1.207 +    case eReflowReason_Initial:
   1.208 +      printf("Ini");break;
   1.209 +    case eReflowReason_Incremental:
   1.210 +      printf("Inc");break;
   1.211 +    case eReflowReason_Resize:
   1.212 +      printf("Rsz");break;
   1.213 +    case eReflowReason_StyleChange:
   1.214 +      printf("Sty");break;
   1.215 +    case eReflowReason_Dirty:
   1.216 +      printf("Drt ");
   1.217 +      break;
   1.218 +    default:printf("<unknown>%d", aReflowState.reason);break;
   1.219 +  }
   1.220 +  
   1.221 +  printSize("AW", aReflowState.AvailableWidth());
   1.222 +  printSize("AH", aReflowState.AvailableHeight());
   1.223 +  printSize("CW", aReflowState.ComputedWidth());
   1.224 +  printSize("CH", aReflowState.ComputedHeight());
   1.225 +
   1.226 +  printf(" *\n");
   1.227 +
   1.228 +#endif
   1.229 +
   1.230 +  aStatus = NS_FRAME_COMPLETE;
   1.231 +
   1.232 +  // create the layout state
   1.233 +  nsBoxLayoutState state(aPresContext, aReflowState.rendContext);
   1.234 +
   1.235 +  nsSize computedSize(aReflowState.ComputedWidth(),aReflowState.ComputedHeight());
   1.236 +
   1.237 +  nsMargin m;
   1.238 +  m = aReflowState.ComputedPhysicalBorderPadding();
   1.239 +
   1.240 +  //GetBorderAndPadding(m);
   1.241 +
   1.242 +  // this happens sometimes. So lets handle it gracefully.
   1.243 +  if (aReflowState.ComputedHeight() == 0) {
   1.244 +    nsSize minSize = GetMinSize(state);
   1.245 +    computedSize.height = minSize.height - m.top - m.bottom;
   1.246 +  }
   1.247 +
   1.248 +  nsSize prefSize(0,0);
   1.249 +
   1.250 +  // if we are told to layout intrinic then get our preferred size.
   1.251 +  if (computedSize.width == NS_INTRINSICSIZE || computedSize.height == NS_INTRINSICSIZE) {
   1.252 +     prefSize = GetPrefSize(state);
   1.253 +     nsSize minSize = GetMinSize(state);
   1.254 +     nsSize maxSize = GetMaxSize(state);
   1.255 +     prefSize = BoundsCheck(minSize, prefSize, maxSize);
   1.256 +  }
   1.257 +
   1.258 +  // get our desiredSize
   1.259 +  if (aReflowState.ComputedWidth() == NS_INTRINSICSIZE) {
   1.260 +    computedSize.width = prefSize.width;
   1.261 +  } else {
   1.262 +    computedSize.width += m.left + m.right;
   1.263 +  }
   1.264 +
   1.265 +  if (aReflowState.ComputedHeight() == NS_INTRINSICSIZE) {
   1.266 +    computedSize.height = prefSize.height;
   1.267 +  } else {
   1.268 +    computedSize.height += m.top + m.bottom;
   1.269 +  }
   1.270 +
   1.271 +  // handle reflow state min and max sizes
   1.272 +  // XXXbz the width handling here seems to be wrong, since
   1.273 +  // mComputedMin/MaxWidth is a content-box size, whole
   1.274 +  // computedSize.width is a border-box size...
   1.275 +  if (computedSize.width > aReflowState.ComputedMaxWidth())
   1.276 +    computedSize.width = aReflowState.ComputedMaxWidth();
   1.277 +
   1.278 +  if (computedSize.width < aReflowState.ComputedMinWidth())
   1.279 +    computedSize.width = aReflowState.ComputedMinWidth();
   1.280 +
   1.281 +  // Now adjust computedSize.height for our min and max computed
   1.282 +  // height.  The only problem is that those are content-box sizes,
   1.283 +  // while computedSize.height is a border-box size.  So subtract off
   1.284 +  // m.TopBottom() before adjusting, then readd it.
   1.285 +  computedSize.height = std::max(0, computedSize.height - m.TopBottom());
   1.286 +  computedSize.height = NS_CSS_MINMAX(computedSize.height,
   1.287 +                                      aReflowState.ComputedMinHeight(),
   1.288 +                                      aReflowState.ComputedMaxHeight());
   1.289 +  computedSize.height += m.TopBottom();
   1.290 +
   1.291 +  nsRect r(mRect.x, mRect.y, computedSize.width, computedSize.height);
   1.292 +
   1.293 +  SetBounds(state, r);
   1.294 + 
   1.295 +  // layout our children
   1.296 +  Layout(state);
   1.297 +  
   1.298 +  // ok our child could have gotten bigger. So lets get its bounds
   1.299 +  aDesiredSize.Width() = mRect.width;
   1.300 +  aDesiredSize.Height() = mRect.height;
   1.301 +  aDesiredSize.SetTopAscent(GetBoxAscent(state));
   1.302 +
   1.303 +  // the overflow rect is set in SetBounds() above
   1.304 +  aDesiredSize.mOverflowAreas = GetOverflowAreas();
   1.305 +
   1.306 +#ifdef DO_NOISY_REFLOW
   1.307 +  {
   1.308 +    printf("%p ** nsLBF(done) W:%d H:%d  ", this, aDesiredSize.Width(), aDesiredSize.Height());
   1.309 +
   1.310 +    if (maxElementWidth) {
   1.311 +      printf("MW:%d\n", *maxElementWidth); 
   1.312 +    } else {
   1.313 +      printf("MW:?\n"); 
   1.314 +    }
   1.315 +
   1.316 +  }
   1.317 +#endif
   1.318 +
   1.319 +  return NS_OK;
   1.320 +}
   1.321 +
   1.322 +#ifdef DEBUG_FRAME_DUMP
   1.323 +nsresult
   1.324 +nsLeafBoxFrame::GetFrameName(nsAString& aResult) const
   1.325 +{
   1.326 +  return MakeFrameName(NS_LITERAL_STRING("LeafBox"), aResult);
   1.327 +}
   1.328 +#endif
   1.329 +
   1.330 +nsIAtom*
   1.331 +nsLeafBoxFrame::GetType() const
   1.332 +{
   1.333 +  return nsGkAtoms::leafBoxFrame;
   1.334 +}
   1.335 +
   1.336 +nsresult
   1.337 +nsLeafBoxFrame::CharacterDataChanged(CharacterDataChangeInfo* aInfo)
   1.338 +{
   1.339 +  MarkIntrinsicWidthsDirty();
   1.340 +  return nsLeafFrame::CharacterDataChanged(aInfo);
   1.341 +}
   1.342 +
   1.343 +/* virtual */ nsSize
   1.344 +nsLeafBoxFrame::GetPrefSize(nsBoxLayoutState& aState)
   1.345 +{
   1.346 +    return nsBox::GetPrefSize(aState);
   1.347 +}
   1.348 +
   1.349 +/* virtual */ nsSize
   1.350 +nsLeafBoxFrame::GetMinSize(nsBoxLayoutState& aState)
   1.351 +{
   1.352 +    return nsBox::GetMinSize(aState);
   1.353 +}
   1.354 +
   1.355 +/* virtual */ nsSize
   1.356 +nsLeafBoxFrame::GetMaxSize(nsBoxLayoutState& aState)
   1.357 +{
   1.358 +    return nsBox::GetMaxSize(aState);
   1.359 +}
   1.360 +
   1.361 +/* virtual */ nscoord
   1.362 +nsLeafBoxFrame::GetFlex(nsBoxLayoutState& aState)
   1.363 +{
   1.364 +    return nsBox::GetFlex(aState);
   1.365 +}
   1.366 +
   1.367 +/* virtual */ nscoord
   1.368 +nsLeafBoxFrame::GetBoxAscent(nsBoxLayoutState& aState)
   1.369 +{
   1.370 +    return nsBox::GetBoxAscent(aState);
   1.371 +}
   1.372 +
   1.373 +/* virtual */ void
   1.374 +nsLeafBoxFrame::MarkIntrinsicWidthsDirty()
   1.375 +{
   1.376 +  // Don't call base class method, since everything it does is within an
   1.377 +  // IsBoxWrapped check.
   1.378 +}
   1.379 +
   1.380 +NS_IMETHODIMP
   1.381 +nsLeafBoxFrame::DoLayout(nsBoxLayoutState& aState)
   1.382 +{
   1.383 +    return nsBox::DoLayout(aState);
   1.384 +}

mercurial