LCOV - code coverage report
Current view: top level - layout/xul - nsBoxFrame.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 457 640 71.4 %
Date: 2017-07-14 16:53:18 Functions: 41 59 69.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=2 sw=2 et tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : //
       8             : // Eric Vaughan
       9             : // Netscape Communications
      10             : //
      11             : // See documentation in associated header file
      12             : //
      13             : 
      14             : // How boxes layout
      15             : // ----------------
      16             : // Boxes layout a bit differently than html. html does a bottom up layout. Where boxes do a top down.
      17             : // 1) First thing a box does it goes out and askes each child for its min, max, and preferred sizes.
      18             : // 2) It then adds them up to determine its size.
      19             : // 3) If the box was asked to layout it self intrinically it will layout its children at their preferred size
      20             : //    otherwise it will layout the child at the size it was told to. It will squeeze or stretch its children if
      21             : //    Necessary.
      22             : //
      23             : // However there is a catch. Some html components like block frames can not determine their preferred size.
      24             : // this is their size if they were laid out intrinsically. So the box will flow the child to determine this can
      25             : // cache the value.
      26             : 
      27             : // Boxes and Incremental Reflow
      28             : // ----------------------------
      29             : // Boxes layout out top down by adding up their children's min, max, and preferred sizes. Only problem is if a incremental
      30             : // reflow occurs. The preferred size of a child deep in the hierarchy could change. And this could change
      31             : // any number of syblings around the box. Basically any children in the reflow chain must have their caches cleared
      32             : // so when asked for there current size they can relayout themselves.
      33             : 
      34             : #include "nsBoxFrame.h"
      35             : 
      36             : #include "gfxUtils.h"
      37             : #include "mozilla/gfx/2D.h"
      38             : #include "nsBoxLayoutState.h"
      39             : #include "mozilla/dom/Touch.h"
      40             : #include "mozilla/Move.h"
      41             : #include "nsStyleContext.h"
      42             : #include "nsPlaceholderFrame.h"
      43             : #include "nsPresContext.h"
      44             : #include "nsCOMPtr.h"
      45             : #include "nsNameSpaceManager.h"
      46             : #include "nsGkAtoms.h"
      47             : #include "nsIContent.h"
      48             : #include "nsHTMLParts.h"
      49             : #include "nsViewManager.h"
      50             : #include "nsView.h"
      51             : #include "nsIPresShell.h"
      52             : #include "nsCSSRendering.h"
      53             : #include "nsIServiceManager.h"
      54             : #include "nsBoxLayout.h"
      55             : #include "nsSprocketLayout.h"
      56             : #include "nsIScrollableFrame.h"
      57             : #include "nsWidgetsCID.h"
      58             : #include "nsCSSAnonBoxes.h"
      59             : #include "nsContainerFrame.h"
      60             : #include "nsIDOMElement.h"
      61             : #include "nsITheme.h"
      62             : #include "nsTransform2D.h"
      63             : #include "mozilla/EventStateManager.h"
      64             : #include "nsIDOMEvent.h"
      65             : #include "nsDisplayList.h"
      66             : #include "mozilla/Preferences.h"
      67             : #include "nsThemeConstants.h"
      68             : #include "nsLayoutUtils.h"
      69             : #include "nsSliderFrame.h"
      70             : #include <algorithm>
      71             : 
      72             : // Needed for Print Preview
      73             : #include "nsIURI.h"
      74             : 
      75             : #include "mozilla/TouchEvents.h"
      76             : 
      77             : using namespace mozilla;
      78             : using namespace mozilla::dom;
      79             : using namespace mozilla::gfx;
      80             : 
      81             : //define DEBUG_REDRAW
      82             : 
      83             : #define DEBUG_SPRING_SIZE 8
      84             : #define DEBUG_BORDER_SIZE 2
      85             : #define COIL_SIZE 8
      86             : 
      87             : //#define TEST_SANITY
      88             : 
      89             : #ifdef DEBUG_rods
      90             : //#define DO_NOISY_REFLOW
      91             : #endif
      92             : 
      93             : #ifdef DEBUG_LAYOUT
      94             : bool nsBoxFrame::gDebug = false;
      95             : nsIFrame* nsBoxFrame::mDebugChild = nullptr;
      96             : #endif
      97             : 
      98             : nsIFrame*
      99           0 : NS_NewBoxFrame(nsIPresShell* aPresShell, nsStyleContext* aContext, bool aIsRoot, nsBoxLayout* aLayoutManager)
     100             : {
     101             :   return new (aPresShell) nsBoxFrame(aContext, nsBoxFrame::kClassID,
     102           0 :                                      aIsRoot, aLayoutManager);
     103             : }
     104             : 
     105             : nsIFrame*
     106         105 : NS_NewBoxFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
     107             : {
     108         105 :   return new (aPresShell) nsBoxFrame(aContext);
     109             : }
     110             : 
     111         105 : NS_IMPL_FRAMEARENA_HELPERS(nsBoxFrame)
     112             : 
     113             : #ifdef DEBUG
     114        5714 : NS_QUERYFRAME_HEAD(nsBoxFrame)
     115           0 :   NS_QUERYFRAME_ENTRY(nsBoxFrame)
     116        5714 : NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
     117             : #endif
     118             : 
     119         232 : nsBoxFrame::nsBoxFrame(nsStyleContext* aContext,
     120             :                        ClassID aID,
     121             :                        bool aIsRoot,
     122         232 :                        nsBoxLayout* aLayoutManager)
     123             :   : nsContainerFrame(aContext, aID)
     124             :   , mFlex(0)
     125         232 :   , mAscent(0)
     126             : {
     127         232 :   mState |= NS_STATE_IS_HORIZONTAL;
     128         232 :   mState |= NS_STATE_AUTO_STRETCH;
     129             : 
     130         232 :   if (aIsRoot)
     131           2 :      mState |= NS_STATE_IS_ROOT;
     132             : 
     133         232 :   mValign = vAlign_Top;
     134         232 :   mHalign = hAlign_Left;
     135             : 
     136             :   // if no layout manager specified us the static sprocket layout
     137         464 :   nsCOMPtr<nsBoxLayout> layout = aLayoutManager;
     138             : 
     139         232 :   if (layout == nullptr) {
     140         232 :     NS_NewSprocketLayout(layout);
     141             :   }
     142             : 
     143         232 :   SetXULLayoutManager(layout);
     144         232 : }
     145             : 
     146          56 : nsBoxFrame::~nsBoxFrame()
     147             : {
     148          56 : }
     149             : 
     150             : void
     151         232 : nsBoxFrame::SetInitialChildList(ChildListID     aListID,
     152             :                                 nsFrameList&    aChildList)
     153             : {
     154         232 :   nsContainerFrame::SetInitialChildList(aListID, aChildList);
     155         232 :   if (aListID == kPrincipalList) {
     156             :     // initialize our list of infos.
     157         464 :     nsBoxLayoutState state(PresContext());
     158         232 :     CheckBoxOrder();
     159         232 :     if (mLayoutManager)
     160         224 :       mLayoutManager->ChildrenSet(this, state, mFrames.FirstChild());
     161             :   }
     162         232 : }
     163             : 
     164             : /* virtual */ void
     165         623 : nsBoxFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
     166             : {
     167         623 :   nsContainerFrame::DidSetStyleContext(aOldStyleContext);
     168             : 
     169             :   // The values that CacheAttributes() computes depend on our style,
     170             :   // so we need to recompute them here...
     171         623 :   CacheAttributes();
     172         623 : }
     173             : 
     174             : /**
     175             :  * Initialize us. This is a good time to get the alignment of the box
     176             :  */
     177             : void
     178         232 : nsBoxFrame::Init(nsIContent*       aContent,
     179             :                  nsContainerFrame* aParent,
     180             :                  nsIFrame*         aPrevInFlow)
     181             : {
     182         232 :   nsContainerFrame::Init(aContent, aParent, aPrevInFlow);
     183             : 
     184         232 :   if (GetStateBits() & NS_FRAME_FONT_INFLATION_CONTAINER) {
     185         226 :     AddStateBits(NS_FRAME_FONT_INFLATION_FLOW_ROOT);
     186             :   }
     187             : 
     188         232 :   MarkIntrinsicISizesDirty();
     189             : 
     190         232 :   CacheAttributes();
     191             : 
     192             : #ifdef DEBUG_LAYOUT
     193             :     // if we are root and this
     194             :   if (mState & NS_STATE_IS_ROOT) {
     195             :     GetDebugPref();
     196             :   }
     197             : #endif
     198             : 
     199         232 :   UpdateMouseThrough();
     200             : 
     201             :   // register access key
     202         232 :   RegUnregAccessKey(true);
     203         232 : }
     204             : 
     205         200 : void nsBoxFrame::UpdateMouseThrough()
     206             : {
     207         200 :   if (mContent) {
     208             :     static nsIContent::AttrValuesArray strings[] =
     209             :       {&nsGkAtoms::never, &nsGkAtoms::always, nullptr};
     210         400 :     switch (mContent->FindAttrValueIn(kNameSpaceID_None,
     211         200 :               nsGkAtoms::mousethrough, strings, eCaseMatters)) {
     212           1 :       case 0: AddStateBits(NS_FRAME_MOUSE_THROUGH_NEVER); break;
     213           3 :       case 1: AddStateBits(NS_FRAME_MOUSE_THROUGH_ALWAYS); break;
     214             :       case 2: {
     215           0 :         RemoveStateBits(NS_FRAME_MOUSE_THROUGH_ALWAYS);
     216           0 :         RemoveStateBits(NS_FRAME_MOUSE_THROUGH_NEVER);
     217           0 :         break;
     218             :       }
     219             :     }
     220             :   }
     221         200 : }
     222             : 
     223             : void
     224         855 : nsBoxFrame::CacheAttributes()
     225             : {
     226             :   /*
     227             :   printf("Caching: ");
     228             :   XULDumpBox(stdout);
     229             :   printf("\n");
     230             :    */
     231             : 
     232         855 :   mValign = vAlign_Top;
     233         855 :   mHalign = hAlign_Left;
     234             : 
     235         855 :   bool orient = false;
     236         855 :   GetInitialOrientation(orient);
     237         855 :   if (orient)
     238         572 :     mState |= NS_STATE_IS_HORIZONTAL;
     239             :   else
     240         283 :     mState &= ~NS_STATE_IS_HORIZONTAL;
     241             : 
     242         855 :   bool normal = true;
     243         855 :   GetInitialDirection(normal);
     244         855 :   if (normal)
     245         855 :     mState |= NS_STATE_IS_DIRECTION_NORMAL;
     246             :   else
     247           0 :     mState &= ~NS_STATE_IS_DIRECTION_NORMAL;
     248             : 
     249         855 :   GetInitialVAlignment(mValign);
     250         855 :   GetInitialHAlignment(mHalign);
     251             : 
     252         855 :   bool equalSize = false;
     253         855 :   GetInitialEqualSize(equalSize);
     254         855 :   if (equalSize)
     255           0 :         mState |= NS_STATE_EQUAL_SIZE;
     256             :     else
     257         855 :         mState &= ~NS_STATE_EQUAL_SIZE;
     258             : 
     259         855 :   bool autostretch = !!(mState & NS_STATE_AUTO_STRETCH);
     260         855 :   GetInitialAutoStretch(autostretch);
     261         855 :   if (autostretch)
     262         611 :         mState |= NS_STATE_AUTO_STRETCH;
     263             :      else
     264         244 :         mState &= ~NS_STATE_AUTO_STRETCH;
     265             : 
     266             : 
     267             : #ifdef DEBUG_LAYOUT
     268             :   bool debug = mState & NS_STATE_SET_TO_DEBUG;
     269             :   bool debugSet = GetInitialDebug(debug);
     270             :   if (debugSet) {
     271             :         mState |= NS_STATE_DEBUG_WAS_SET;
     272             :         if (debug)
     273             :             mState |= NS_STATE_SET_TO_DEBUG;
     274             :         else
     275             :             mState &= ~NS_STATE_SET_TO_DEBUG;
     276             :   } else {
     277             :         mState &= ~NS_STATE_DEBUG_WAS_SET;
     278             :   }
     279             : #endif
     280         855 : }
     281             : 
     282             : #ifdef DEBUG_LAYOUT
     283             : bool
     284             : nsBoxFrame::GetInitialDebug(bool& aDebug)
     285             : {
     286             :   if (!GetContent())
     287             :     return false;
     288             : 
     289             :   static nsIContent::AttrValuesArray strings[] =
     290             :     {&nsGkAtoms::_false, &nsGkAtoms::_true, nullptr};
     291             :   int32_t index = GetContent()->FindAttrValueIn(kNameSpaceID_None,
     292             :       nsGkAtoms::debug, strings, eCaseMatters);
     293             :   if (index >= 0) {
     294             :     aDebug = index == 1;
     295             :     return true;
     296             :   }
     297             : 
     298             :   return false;
     299             : }
     300             : #endif
     301             : 
     302             : bool
     303         856 : nsBoxFrame::GetInitialHAlignment(nsBoxFrame::Halignment& aHalign)
     304             : {
     305         856 :   if (!GetContent())
     306           0 :     return false;
     307             : 
     308             :   // XXXdwh Everything inside this if statement is deprecated code.
     309             :   static nsIContent::AttrValuesArray alignStrings[] =
     310             :     {&nsGkAtoms::left, &nsGkAtoms::right, nullptr};
     311             :   static const Halignment alignValues[] = {hAlign_Left, hAlign_Right};
     312        1712 :   int32_t index = GetContent()->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::align,
     313        1712 :       alignStrings, eCaseMatters);
     314         856 :   if (index >= 0) {
     315           0 :     aHalign = alignValues[index];
     316           0 :     return true;
     317             :   }
     318             : 
     319             :   // Now that the deprecated stuff is out of the way, we move on to check the appropriate
     320             :   // attribute.  For horizontal boxes, we are checking the PACK attribute.  For vertical boxes
     321             :   // we are checking the ALIGN attribute.
     322         856 :   nsIAtom* attrName = IsXULHorizontal() ? nsGkAtoms::pack : nsGkAtoms::align;
     323             :   static nsIContent::AttrValuesArray strings[] =
     324             :     {&nsGkAtoms::_empty, &nsGkAtoms::start, &nsGkAtoms::center, &nsGkAtoms::end, nullptr};
     325             :   static const Halignment values[] =
     326             :     {hAlign_Left/*not used*/, hAlign_Left, hAlign_Center, hAlign_Right};
     327         856 :   index = GetContent()->FindAttrValueIn(kNameSpaceID_None, attrName,
     328         856 :       strings, eCaseMatters);
     329             : 
     330         856 :   if (index == nsIContent::ATTR_VALUE_NO_MATCH) {
     331             :     // The attr was present but had a nonsensical value. Revert to the default.
     332           0 :     return false;
     333             :   }
     334         856 :   if (index > 0) {
     335          19 :     aHalign = values[index];
     336          19 :     return true;
     337             :   }
     338             : 
     339             :   // Now that we've checked for the attribute it's time to check CSS.  For
     340             :   // horizontal boxes we're checking PACK.  For vertical boxes we are checking
     341             :   // ALIGN.
     342         837 :   const nsStyleXUL* boxInfo = StyleXUL();
     343         837 :   if (IsXULHorizontal()) {
     344         566 :     switch (boxInfo->mBoxPack) {
     345             :       case StyleBoxPack::Start:
     346         439 :         aHalign = nsBoxFrame::hAlign_Left;
     347         439 :         return true;
     348             :       case StyleBoxPack::Center:
     349         127 :         aHalign = nsBoxFrame::hAlign_Center;
     350         127 :         return true;
     351             :       case StyleBoxPack::End:
     352           0 :         aHalign = nsBoxFrame::hAlign_Right;
     353           0 :         return true;
     354             :       default: // Nonsensical value. Just bail.
     355           0 :         return false;
     356             :     }
     357             :   }
     358             :   else {
     359         271 :     switch (boxInfo->mBoxAlign) {
     360             :       case StyleBoxAlign::Start:
     361           0 :         aHalign = nsBoxFrame::hAlign_Left;
     362           0 :         return true;
     363             :       case StyleBoxAlign::Center:
     364           3 :         aHalign = nsBoxFrame::hAlign_Center;
     365           3 :         return true;
     366             :       case StyleBoxAlign::End:
     367           0 :         aHalign = nsBoxFrame::hAlign_Right;
     368           0 :         return true;
     369             :       default: // Nonsensical value. Just bail.
     370         268 :         return false;
     371             :     }
     372             :   }
     373             : 
     374             :   return false;
     375             : }
     376             : 
     377             : bool
     378         856 : nsBoxFrame::GetInitialVAlignment(nsBoxFrame::Valignment& aValign)
     379             : {
     380         856 :   if (!GetContent())
     381           0 :     return false;
     382             : 
     383             :   static nsIContent::AttrValuesArray valignStrings[] =
     384             :     {&nsGkAtoms::top, &nsGkAtoms::baseline, &nsGkAtoms::middle, &nsGkAtoms::bottom, nullptr};
     385             :   static const Valignment valignValues[] =
     386             :     {vAlign_Top, vAlign_BaseLine, vAlign_Middle, vAlign_Bottom};
     387        1712 :   int32_t index = GetContent()->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::valign,
     388        1712 :       valignStrings, eCaseMatters);
     389         856 :   if (index >= 0) {
     390           0 :     aValign = valignValues[index];
     391           0 :     return true;
     392             :   }
     393             : 
     394             :   // Now that the deprecated stuff is out of the way, we move on to check the appropriate
     395             :   // attribute.  For horizontal boxes, we are checking the ALIGN attribute.  For vertical boxes
     396             :   // we are checking the PACK attribute.
     397         856 :   nsIAtom* attrName = IsXULHorizontal() ? nsGkAtoms::align : nsGkAtoms::pack;
     398             :   static nsIContent::AttrValuesArray strings[] =
     399             :     {&nsGkAtoms::_empty, &nsGkAtoms::start, &nsGkAtoms::center,
     400             :      &nsGkAtoms::baseline, &nsGkAtoms::end, nullptr};
     401             :   static const Valignment values[] =
     402             :     {vAlign_Top/*not used*/, vAlign_Top, vAlign_Middle, vAlign_BaseLine, vAlign_Bottom};
     403         856 :   index = GetContent()->FindAttrValueIn(kNameSpaceID_None, attrName,
     404         856 :       strings, eCaseMatters);
     405         856 :   if (index == nsIContent::ATTR_VALUE_NO_MATCH) {
     406             :     // The attr was present but had a nonsensical value. Revert to the default.
     407           0 :     return false;
     408             :   }
     409         856 :   if (index > 0) {
     410          54 :     aValign = values[index];
     411          54 :     return true;
     412             :   }
     413             : 
     414             :   // Now that we've checked for the attribute it's time to check CSS.  For
     415             :   // horizontal boxes we're checking ALIGN.  For vertical boxes we are checking
     416             :   // PACK.
     417         802 :   const nsStyleXUL* boxInfo = StyleXUL();
     418         802 :   if (IsXULHorizontal()) {
     419         526 :     switch (boxInfo->mBoxAlign) {
     420             :       case StyleBoxAlign::Start:
     421           0 :         aValign = nsBoxFrame::vAlign_Top;
     422           0 :         return true;
     423             :       case StyleBoxAlign::Center:
     424         180 :         aValign = nsBoxFrame::vAlign_Middle;
     425         180 :         return true;
     426             :       case StyleBoxAlign::Baseline:
     427           0 :         aValign = nsBoxFrame::vAlign_BaseLine;
     428           0 :         return true;
     429             :       case StyleBoxAlign::End:
     430           2 :         aValign = nsBoxFrame::vAlign_Bottom;
     431           2 :         return true;
     432             :       default: // Nonsensical value. Just bail.
     433         344 :         return false;
     434             :     }
     435             :   }
     436             :   else {
     437         276 :     switch (boxInfo->mBoxPack) {
     438             :       case StyleBoxPack::Start:
     439         273 :         aValign = nsBoxFrame::vAlign_Top;
     440         273 :         return true;
     441             :       case StyleBoxPack::Center:
     442           3 :         aValign = nsBoxFrame::vAlign_Middle;
     443           3 :         return true;
     444             :       case StyleBoxPack::End:
     445           0 :         aValign = nsBoxFrame::vAlign_Bottom;
     446           0 :         return true;
     447             :       default: // Nonsensical value. Just bail.
     448           0 :         return false;
     449             :     }
     450             :   }
     451             : 
     452             :   return false;
     453             : }
     454             : 
     455             : void
     456         853 : nsBoxFrame::GetInitialOrientation(bool& aIsHorizontal)
     457             : {
     458             :  // see if we are a vertical or horizontal box.
     459         853 :   if (!GetContent())
     460           0 :     return;
     461             : 
     462             :   // Check the style system first.
     463         853 :   const nsStyleXUL* boxInfo = StyleXUL();
     464         853 :   if (boxInfo->mBoxOrient == StyleBoxOrient::Horizontal) {
     465         590 :     aIsHorizontal = true;
     466             :   } else {
     467         263 :     aIsHorizontal = false;
     468             :   }
     469             : 
     470             :   // Now see if we have an attribute.  The attribute overrides
     471             :   // the style system value.
     472             :   static nsIContent::AttrValuesArray strings[] =
     473             :     {&nsGkAtoms::vertical, &nsGkAtoms::horizontal, nullptr};
     474        1706 :   int32_t index = GetContent()->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::orient,
     475        1706 :       strings, eCaseMatters);
     476         853 :   if (index >= 0) {
     477          86 :     aIsHorizontal = index == 1;
     478             :   }
     479             : }
     480             : 
     481             : void
     482         856 : nsBoxFrame::GetInitialDirection(bool& aIsNormal)
     483             : {
     484         856 :   if (!GetContent())
     485           0 :     return;
     486             : 
     487         856 :   if (IsXULHorizontal()) {
     488             :     // For horizontal boxes only, we initialize our value based off the CSS 'direction' property.
     489             :     // This means that BiDI users will end up with horizontally inverted chrome.
     490         573 :     aIsNormal = (StyleVisibility()->mDirection == NS_STYLE_DIRECTION_LTR); // If text runs RTL then so do we.
     491             :   }
     492             :   else
     493         283 :     aIsNormal = true; // Assume a normal direction in the vertical case.
     494             : 
     495             :   // Now check the style system to see if we should invert aIsNormal.
     496         856 :   const nsStyleXUL* boxInfo = StyleXUL();
     497         856 :   if (boxInfo->mBoxDirection == StyleBoxDirection::Reverse) {
     498           0 :     aIsNormal = !aIsNormal; // Invert our direction.
     499             :   }
     500             : 
     501             :   // Now see if we have an attribute.  The attribute overrides
     502             :   // the style system value.
     503         856 :   if (IsXULHorizontal()) {
     504             :     static nsIContent::AttrValuesArray strings[] =
     505             :       {&nsGkAtoms::reverse, &nsGkAtoms::ltr, &nsGkAtoms::rtl, nullptr};
     506        1146 :     int32_t index = GetContent()->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::dir,
     507        1146 :         strings, eCaseMatters);
     508         573 :     if (index >= 0) {
     509           0 :       bool values[] = {!aIsNormal, true, false};
     510           0 :       aIsNormal = values[index];
     511             :     }
     512         283 :   } else if (GetContent()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::dir,
     513             :                                        nsGkAtoms::reverse, eCaseMatters)) {
     514           0 :     aIsNormal = !aIsNormal;
     515             :   }
     516             : }
     517             : 
     518             : /* Returns true if it was set.
     519             :  */
     520             : bool
     521         856 : nsBoxFrame::GetInitialEqualSize(bool& aEqualSize)
     522             : {
     523             :  // see if we are a vertical or horizontal box.
     524         856 :   if (!GetContent())
     525           0 :      return false;
     526             : 
     527         856 :   if (GetContent()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::equalsize,
     528             :                            nsGkAtoms::always, eCaseMatters)) {
     529           0 :     aEqualSize = true;
     530           0 :     return true;
     531             :   }
     532             : 
     533         856 :   return false;
     534             : }
     535             : 
     536             : /* Returns true if it was set.
     537             :  */
     538             : bool
     539         856 : nsBoxFrame::GetInitialAutoStretch(bool& aStretch)
     540             : {
     541         856 :   if (!GetContent())
     542           0 :      return false;
     543             : 
     544             :   // Check the align attribute.
     545             :   static nsIContent::AttrValuesArray strings[] =
     546             :     {&nsGkAtoms::_empty, &nsGkAtoms::stretch, nullptr};
     547        1712 :   int32_t index = GetContent()->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::align,
     548        1712 :       strings, eCaseMatters);
     549         856 :   if (index != nsIContent::ATTR_MISSING && index != 0) {
     550          59 :     aStretch = index == 1;
     551          59 :     return true;
     552             :   }
     553             : 
     554             :   // Check the CSS box-align property.
     555         797 :   const nsStyleXUL* boxInfo = StyleXUL();
     556         797 :   aStretch = (boxInfo->mBoxAlign == StyleBoxAlign::Stretch);
     557             : 
     558         797 :   return true;
     559             : }
     560             : 
     561             : void
     562          32 : nsBoxFrame::DidReflow(nsPresContext*           aPresContext,
     563             :                       const ReflowInput*  aReflowInput,
     564             :                       nsDidReflowStatus         aStatus)
     565             : {
     566             :   nsFrameState preserveBits =
     567          32 :     mState & (NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN);
     568          32 :   nsFrame::DidReflow(aPresContext, aReflowInput, aStatus);
     569          32 :   mState |= preserveBits;
     570          32 : }
     571             : 
     572             : bool
     573         438 : nsBoxFrame::HonorPrintBackgroundSettings()
     574             : {
     575         756 :   return (!mContent || !mContent->IsInNativeAnonymousSubtree()) &&
     576         756 :     nsContainerFrame::HonorPrintBackgroundSettings();
     577             : }
     578             : 
     579             : #ifdef DO_NOISY_REFLOW
     580             : static int myCounter = 0;
     581             : static void printSize(char * aDesc, nscoord aSize)
     582             : {
     583             :   printf(" %s: ", aDesc);
     584             :   if (aSize == NS_UNCONSTRAINEDSIZE) {
     585             :     printf("UC");
     586             :   } else {
     587             :     printf("%d", aSize);
     588             :   }
     589             : }
     590             : #endif
     591             : 
     592             : /* virtual */ nscoord
     593           8 : nsBoxFrame::GetMinISize(gfxContext *aRenderingContext)
     594             : {
     595             :   nscoord result;
     596          16 :   DISPLAY_MIN_WIDTH(this, result);
     597             : 
     598          16 :   nsBoxLayoutState state(PresContext(), aRenderingContext);
     599           8 :   nsSize minSize = GetXULMinSize(state);
     600             : 
     601             :   // GetXULMinSize returns border-box width, and we want to return content
     602             :   // width.  Since Reflow uses the reflow state's border and padding, we
     603             :   // actually just want to subtract what GetXULMinSize added, which is the
     604             :   // result of GetXULBorderAndPadding.
     605           8 :   nsMargin bp;
     606           8 :   GetXULBorderAndPadding(bp);
     607             : 
     608           8 :   result = minSize.width - bp.LeftRight();
     609           8 :   result = std::max(result, 0);
     610             : 
     611          16 :   return result;
     612             : }
     613             : 
     614             : /* virtual */ nscoord
     615           7 : nsBoxFrame::GetPrefISize(gfxContext *aRenderingContext)
     616             : {
     617             :   nscoord result;
     618          14 :   DISPLAY_PREF_WIDTH(this, result);
     619             : 
     620          14 :   nsBoxLayoutState state(PresContext(), aRenderingContext);
     621           7 :   nsSize prefSize = GetXULPrefSize(state);
     622             : 
     623             :   // GetXULPrefSize returns border-box width, and we want to return content
     624             :   // width.  Since Reflow uses the reflow state's border and padding, we
     625             :   // actually just want to subtract what GetXULPrefSize added, which is the
     626             :   // result of GetXULBorderAndPadding.
     627           7 :   nsMargin bp;
     628           7 :   GetXULBorderAndPadding(bp);
     629             : 
     630           7 :   result = prefSize.width - bp.LeftRight();
     631           7 :   result = std::max(result, 0);
     632             : 
     633          14 :   return result;
     634             : }
     635             : 
     636             : void
     637          32 : nsBoxFrame::Reflow(nsPresContext*          aPresContext,
     638             :                    ReflowOutput&     aDesiredSize,
     639             :                    const ReflowInput& aReflowInput,
     640             :                    nsReflowStatus&          aStatus)
     641             : {
     642          32 :   MarkInReflow();
     643             :   // If you make changes to this method, please keep nsLeafBoxFrame::Reflow
     644             :   // in sync, if the changes are applicable there.
     645             : 
     646          32 :   DO_GLOBAL_REFLOW_COUNT("nsBoxFrame");
     647          64 :   DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);
     648             : 
     649          32 :   NS_ASSERTION(aReflowInput.ComputedWidth() >=0 &&
     650             :                aReflowInput.ComputedHeight() >= 0, "Computed Size < 0");
     651             : 
     652             : #ifdef DO_NOISY_REFLOW
     653             :   printf("\n-------------Starting BoxFrame Reflow ----------------------------\n");
     654             :   printf("%p ** nsBF::Reflow %d ", this, myCounter++);
     655             : 
     656             :   printSize("AW", aReflowInput.AvailableWidth());
     657             :   printSize("AH", aReflowInput.AvailableHeight());
     658             :   printSize("CW", aReflowInput.ComputedWidth());
     659             :   printSize("CH", aReflowInput.ComputedHeight());
     660             : 
     661             :   printf(" *\n");
     662             : 
     663             : #endif
     664             : 
     665          32 :   aStatus.Reset();
     666             : 
     667             :   // create the layout state
     668          32 :   nsBoxLayoutState state(aPresContext, aReflowInput.mRenderingContext,
     669          96 :                          &aReflowInput, aReflowInput.mReflowDepth);
     670             : 
     671          32 :   WritingMode wm = aReflowInput.GetWritingMode();
     672             :   LogicalSize computedSize(wm, aReflowInput.ComputedISize(),
     673          32 :                            aReflowInput.ComputedBSize());
     674             : 
     675          32 :   LogicalMargin m = aReflowInput.ComputedLogicalBorderPadding();
     676             :   // GetXULBorderAndPadding(m);
     677             : 
     678          32 :   LogicalSize prefSize(wm);
     679             : 
     680             :   // if we are told to layout intrinsic then get our preferred size.
     681          32 :   NS_ASSERTION(computedSize.ISize(wm) != NS_INTRINSICSIZE,
     682             :                "computed inline size should always be computed");
     683          32 :   if (computedSize.BSize(wm) == NS_INTRINSICSIZE) {
     684           2 :     nsSize physicalPrefSize = GetXULPrefSize(state);
     685           2 :     nsSize minSize = GetXULMinSize(state);
     686           2 :     nsSize maxSize = GetXULMaxSize(state);
     687             :     // XXXbz isn't GetXULPrefSize supposed to bounds-check for us?
     688           2 :     physicalPrefSize = BoundsCheck(minSize, physicalPrefSize, maxSize);
     689           2 :     prefSize = LogicalSize(wm, physicalPrefSize);
     690             :   }
     691             : 
     692             :   // get our desiredSize
     693          32 :   computedSize.ISize(wm) += m.IStart(wm) + m.IEnd(wm);
     694             : 
     695          32 :   if (aReflowInput.ComputedBSize() == NS_INTRINSICSIZE) {
     696           2 :     computedSize.BSize(wm) = prefSize.BSize(wm);
     697             :     // prefSize is border-box but min/max constraints are content-box.
     698             :     nscoord blockDirBorderPadding =
     699           2 :       aReflowInput.ComputedLogicalBorderPadding().BStartEnd(wm);
     700           2 :     nscoord contentBSize = computedSize.BSize(wm) - blockDirBorderPadding;
     701             :     // Note: contentHeight might be negative, but that's OK because min-height
     702             :     // is never negative.
     703           2 :     computedSize.BSize(wm) = aReflowInput.ApplyMinMaxHeight(contentBSize) +
     704             :                              blockDirBorderPadding;
     705             :   } else {
     706          30 :     computedSize.BSize(wm) += m.BStart(wm) + m.BEnd(wm);
     707             :   }
     708             : 
     709          32 :   nsSize physicalSize = computedSize.GetPhysicalSize(wm);
     710          64 :   nsRect r(mRect.x, mRect.y, physicalSize.width, physicalSize.height);
     711             : 
     712          32 :   SetXULBounds(state, r);
     713             : 
     714             :   // layout our children
     715          32 :   XULLayout(state);
     716             : 
     717             :   // ok our child could have gotten bigger. So lets get its bounds
     718             : 
     719             :   // get the ascent
     720          32 :   LogicalSize boxSize = GetLogicalSize(wm);
     721          32 :   nscoord ascent = boxSize.BSize(wm);
     722             : 
     723             :   // getting the ascent could be a lot of work. Don't get it if
     724             :   // we are the root. The viewport doesn't care about it.
     725          32 :   if (!(mState & NS_STATE_IS_ROOT)) {
     726          10 :     ascent = GetXULBoxAscent(state);
     727             :   }
     728             : 
     729          32 :   aDesiredSize.SetSize(wm, boxSize);
     730          32 :   aDesiredSize.SetBlockStartAscent(ascent);
     731             : 
     732          32 :   aDesiredSize.mOverflowAreas = GetOverflowAreas();
     733             : 
     734             : #ifdef DO_NOISY_REFLOW
     735             :   {
     736             :     printf("%p ** nsBF(done) W:%d H:%d  ", this, aDesiredSize.Width(), aDesiredSize.Height());
     737             : 
     738             :     if (maxElementSize) {
     739             :       printf("MW:%d\n", *maxElementWidth);
     740             :     } else {
     741             :       printf("MW:?\n");
     742             :     }
     743             : 
     744             :   }
     745             : #endif
     746             : 
     747          32 :   ReflowAbsoluteFrames(aPresContext, aDesiredSize, aReflowInput, aStatus);
     748             : 
     749          32 :   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
     750          32 : }
     751             : 
     752             : nsSize
     753        1801 : nsBoxFrame::GetXULPrefSize(nsBoxLayoutState& aBoxLayoutState)
     754             : {
     755        1801 :   NS_ASSERTION(aBoxLayoutState.GetRenderingContext(),
     756             :                "must have rendering context");
     757             : 
     758        1801 :   nsSize size(0,0);
     759        3602 :   DISPLAY_PREF_SIZE(this, size);
     760        1801 :   if (!DoesNeedRecalc(mPrefSize)) {
     761        1414 :      return mPrefSize;
     762             :   }
     763             : 
     764             : #ifdef DEBUG_LAYOUT
     765             :   PropagateDebug(aBoxLayoutState);
     766             : #endif
     767             : 
     768         387 :   if (IsXULCollapsed())
     769          17 :     return size;
     770             : 
     771             :   // if the size was not completely redefined in CSS then ask our children
     772             :   bool widthSet, heightSet;
     773         370 :   if (!nsIFrame::AddXULPrefSize(this, size, widthSet, heightSet))
     774             :   {
     775         367 :     if (mLayoutManager) {
     776         367 :       nsSize layoutSize = mLayoutManager->GetXULPrefSize(this, aBoxLayoutState);
     777         367 :       if (!widthSet)
     778         332 :         size.width = layoutSize.width;
     779         367 :       if (!heightSet)
     780         360 :         size.height = layoutSize.height;
     781             :     }
     782             :     else {
     783           0 :       size = nsBox::GetXULPrefSize(aBoxLayoutState);
     784             :     }
     785             :   }
     786             : 
     787         370 :   nsSize minSize = GetXULMinSize(aBoxLayoutState);
     788         370 :   nsSize maxSize = GetXULMaxSize(aBoxLayoutState);
     789         370 :   mPrefSize = BoundsCheck(minSize, size, maxSize);
     790             : 
     791         370 :   return mPrefSize;
     792             : }
     793             : 
     794             : nscoord
     795        1837 : nsBoxFrame::GetXULBoxAscent(nsBoxLayoutState& aBoxLayoutState)
     796             : {
     797        1837 :   if (!DoesNeedRecalc(mAscent))
     798        1040 :      return mAscent;
     799             : 
     800             : #ifdef DEBUG_LAYOUT
     801             :   PropagateDebug(aBoxLayoutState);
     802             : #endif
     803             : 
     804         797 :   if (IsXULCollapsed())
     805         125 :     return 0;
     806             : 
     807         672 :   if (mLayoutManager)
     808         672 :     mAscent = mLayoutManager->GetAscent(this, aBoxLayoutState);
     809             :   else
     810           0 :     mAscent = nsBox::GetXULBoxAscent(aBoxLayoutState);
     811             : 
     812         672 :   return mAscent;
     813             : }
     814             : 
     815             : nsSize
     816        2495 : nsBoxFrame::GetXULMinSize(nsBoxLayoutState& aBoxLayoutState)
     817             : {
     818        2495 :   NS_ASSERTION(aBoxLayoutState.GetRenderingContext(),
     819             :                "must have rendering context");
     820             : 
     821        2495 :   nsSize size(0,0);
     822        4990 :   DISPLAY_MIN_SIZE(this, size);
     823        2495 :   if (!DoesNeedRecalc(mMinSize)) {
     824        2079 :     return mMinSize;
     825             :   }
     826             : 
     827             : #ifdef DEBUG_LAYOUT
     828             :   PropagateDebug(aBoxLayoutState);
     829             : #endif
     830             : 
     831         416 :   if (IsXULCollapsed())
     832          33 :     return size;
     833             : 
     834             :   // if the size was not completely redefined in CSS then ask our children
     835             :   bool widthSet, heightSet;
     836         383 :   if (!nsIFrame::AddXULMinSize(aBoxLayoutState, this, size, widthSet, heightSet))
     837             :   {
     838         343 :     if (mLayoutManager) {
     839         343 :       nsSize layoutSize = mLayoutManager->GetXULMinSize(this, aBoxLayoutState);
     840         343 :       if (!widthSet)
     841         262 :         size.width = layoutSize.width;
     842         343 :       if (!heightSet)
     843         320 :         size.height = layoutSize.height;
     844             :     }
     845             :     else {
     846           0 :       size = nsBox::GetXULMinSize(aBoxLayoutState);
     847             :     }
     848             :   }
     849             : 
     850         383 :   mMinSize = size;
     851             : 
     852         383 :   return size;
     853             : }
     854             : 
     855             : nsSize
     856        1960 : nsBoxFrame::GetXULMaxSize(nsBoxLayoutState& aBoxLayoutState)
     857             : {
     858        1960 :   NS_ASSERTION(aBoxLayoutState.GetRenderingContext(),
     859             :                "must have rendering context");
     860             : 
     861        1960 :   nsSize size(NS_INTRINSICSIZE, NS_INTRINSICSIZE);
     862        3920 :   DISPLAY_MAX_SIZE(this, size);
     863        1960 :   if (!DoesNeedRecalc(mMaxSize)) {
     864        1542 :     return mMaxSize;
     865             :   }
     866             : 
     867             : #ifdef DEBUG_LAYOUT
     868             :   PropagateDebug(aBoxLayoutState);
     869             : #endif
     870             : 
     871         418 :   if (IsXULCollapsed())
     872          29 :     return size;
     873             : 
     874             :   // if the size was not completely redefined in CSS then ask our children
     875             :   bool widthSet, heightSet;
     876         389 :   if (!nsIFrame::AddXULMaxSize(this, size, widthSet, heightSet))
     877             :   {
     878         363 :     if (mLayoutManager) {
     879         363 :       nsSize layoutSize = mLayoutManager->GetXULMaxSize(this, aBoxLayoutState);
     880         363 :       if (!widthSet)
     881         363 :         size.width = layoutSize.width;
     882         363 :       if (!heightSet)
     883         363 :         size.height = layoutSize.height;
     884             :     }
     885             :     else {
     886           0 :       size = nsBox::GetXULMaxSize(aBoxLayoutState);
     887             :     }
     888             :   }
     889             : 
     890         389 :   mMaxSize = size;
     891             : 
     892         389 :   return size;
     893             : }
     894             : 
     895             : nscoord
     896        1395 : nsBoxFrame::GetXULFlex()
     897             : {
     898        1395 :   if (!DoesNeedRecalc(mFlex))
     899        1031 :      return mFlex;
     900             : 
     901         364 :   mFlex = nsBox::GetXULFlex();
     902             : 
     903         364 :   return mFlex;
     904             : }
     905             : 
     906             : /**
     907             :  * If subclassing please subclass this method not layout.
     908             :  * layout will call this method.
     909             :  */
     910             : NS_IMETHODIMP
     911         594 : nsBoxFrame::DoXULLayout(nsBoxLayoutState& aState)
     912             : {
     913         594 :   uint32_t oldFlags = aState.LayoutFlags();
     914         594 :   aState.SetLayoutFlags(0);
     915             : 
     916         594 :   nsresult rv = NS_OK;
     917         594 :   if (mLayoutManager) {
     918         594 :     CoordNeedsRecalc(mAscent);
     919         594 :     rv = mLayoutManager->XULLayout(this, aState);
     920             :   }
     921             : 
     922         594 :   aState.SetLayoutFlags(oldFlags);
     923             : 
     924         594 :   if (HasAbsolutelyPositionedChildren()) {
     925             :     // Set up a |reflowInput| to pass into ReflowAbsoluteFrames
     926           0 :     WritingMode wm = GetWritingMode();
     927             :     ReflowInput reflowInput(aState.PresContext(), this,
     928             :                                   aState.GetRenderingContext(),
     929           0 :                                   LogicalSize(wm, GetLogicalSize().ISize(wm),
     930           0 :                                               NS_UNCONSTRAINEDSIZE));
     931             : 
     932             :     // Set up a |desiredSize| to pass into ReflowAbsoluteFrames
     933           0 :     ReflowOutput desiredSize(reflowInput);
     934           0 :     desiredSize.Width() = mRect.width;
     935           0 :     desiredSize.Height() = mRect.height;
     936             : 
     937             :     // get the ascent (cribbed from ::Reflow)
     938           0 :     nscoord ascent = mRect.height;
     939             : 
     940             :     // getting the ascent could be a lot of work. Don't get it if
     941             :     // we are the root. The viewport doesn't care about it.
     942           0 :     if (!(mState & NS_STATE_IS_ROOT)) {
     943           0 :       ascent = GetXULBoxAscent(aState);
     944             :     }
     945           0 :     desiredSize.SetBlockStartAscent(ascent);
     946           0 :     desiredSize.mOverflowAreas = GetOverflowAreas();
     947             : 
     948           0 :     AddStateBits(NS_FRAME_IN_REFLOW);
     949             :     // Set up a |reflowStatus| to pass into ReflowAbsoluteFrames
     950             :     // (just a dummy value; hopefully that's OK)
     951           0 :     nsReflowStatus reflowStatus;
     952           0 :     ReflowAbsoluteFrames(aState.PresContext(), desiredSize,
     953           0 :                          reflowInput, reflowStatus);
     954           0 :     RemoveStateBits(NS_FRAME_IN_REFLOW);
     955             :   }
     956             : 
     957         594 :   return rv;
     958             : }
     959             : 
     960             : void
     961          56 : nsBoxFrame::DestroyFrom(nsIFrame* aDestructRoot)
     962             : {
     963             :   // unregister access key
     964          56 :   RegUnregAccessKey(false);
     965             : 
     966             :   // clean up the container box's layout manager and child boxes
     967          56 :   SetXULLayoutManager(nullptr);
     968             : 
     969          56 :   nsContainerFrame::DestroyFrom(aDestructRoot);
     970          56 : }
     971             : 
     972             : #ifdef DEBUG_LAYOUT
     973             : nsresult
     974             : nsBoxFrame::SetXULDebug(nsBoxLayoutState& aState, bool aDebug)
     975             : {
     976             :   // see if our state matches the given debug state
     977             :   bool debugSet = mState & NS_STATE_CURRENTLY_IN_DEBUG;
     978             :   bool debugChanged = (!aDebug && debugSet) || (aDebug && !debugSet);
     979             : 
     980             :   // if it doesn't then tell each child below us the new debug state
     981             :   if (debugChanged)
     982             :   {
     983             :      if (aDebug) {
     984             :          mState |= NS_STATE_CURRENTLY_IN_DEBUG;
     985             :      } else {
     986             :          mState &= ~NS_STATE_CURRENTLY_IN_DEBUG;
     987             :      }
     988             : 
     989             :      SetDebugOnChildList(aState, mFirstChild, aDebug);
     990             : 
     991             :     MarkIntrinsicISizesDirty();
     992             :   }
     993             : 
     994             :   return NS_OK;
     995             : }
     996             : #endif
     997             : 
     998             : /* virtual */ void
     999        1285 : nsBoxFrame::MarkIntrinsicISizesDirty()
    1000             : {
    1001        1285 :   SizeNeedsRecalc(mPrefSize);
    1002        1285 :   SizeNeedsRecalc(mMinSize);
    1003        1285 :   SizeNeedsRecalc(mMaxSize);
    1004        1285 :   CoordNeedsRecalc(mFlex);
    1005        1285 :   CoordNeedsRecalc(mAscent);
    1006             : 
    1007        1285 :   if (mLayoutManager) {
    1008        2444 :     nsBoxLayoutState state(PresContext());
    1009        1222 :     mLayoutManager->IntrinsicISizesDirty(this, state);
    1010             :   }
    1011             : 
    1012             :   // Don't call base class method, since everything it does is within an
    1013             :   // IsXULBoxWrapped check.
    1014        1285 : }
    1015             : 
    1016             : void
    1017          13 : nsBoxFrame::RemoveFrame(ChildListID     aListID,
    1018             :                         nsIFrame*       aOldFrame)
    1019             : {
    1020          13 :   NS_PRECONDITION(aListID == kPrincipalList, "We don't support out-of-flow kids");
    1021          13 :   nsPresContext* presContext = PresContext();
    1022          26 :   nsBoxLayoutState state(presContext);
    1023             : 
    1024             :   // remove the child frame
    1025          13 :   mFrames.RemoveFrame(aOldFrame);
    1026             : 
    1027             :   // notify the layout manager
    1028          13 :   if (mLayoutManager)
    1029          13 :     mLayoutManager->ChildrenRemoved(this, state, aOldFrame);
    1030             : 
    1031             :   // destroy the child frame
    1032          13 :   aOldFrame->Destroy();
    1033             : 
    1034             :   // mark us dirty and generate a reflow command
    1035          13 :   PresContext()->PresShell()->
    1036          13 :     FrameNeedsReflow(this, nsIPresShell::eTreeChange,
    1037          26 :                      NS_FRAME_HAS_DIRTY_CHILDREN);
    1038          13 : }
    1039             : 
    1040             : void
    1041          22 : nsBoxFrame::InsertFrames(ChildListID     aListID,
    1042             :                          nsIFrame*       aPrevFrame,
    1043             :                          nsFrameList&    aFrameList)
    1044             : {
    1045          22 :    NS_ASSERTION(!aPrevFrame || aPrevFrame->GetParent() == this,
    1046             :                 "inserting after sibling frame with different parent");
    1047          22 :    NS_ASSERTION(!aPrevFrame || mFrames.ContainsFrame(aPrevFrame),
    1048             :                 "inserting after sibling frame not in our child list");
    1049          22 :    NS_PRECONDITION(aListID == kPrincipalList, "We don't support out-of-flow kids");
    1050          44 :    nsBoxLayoutState state(PresContext());
    1051             : 
    1052             :    // insert the child frames
    1053             :    const nsFrameList::Slice& newFrames =
    1054          22 :      mFrames.InsertFrames(this, aPrevFrame, aFrameList);
    1055             : 
    1056             :    // notify the layout manager
    1057          22 :    if (mLayoutManager)
    1058          22 :      mLayoutManager->ChildrenInserted(this, state, aPrevFrame, newFrames);
    1059             : 
    1060             :    // Make sure to check box order _after_ notifying the layout
    1061             :    // manager; otherwise the slice we give the layout manager will
    1062             :    // just be bogus.  If the layout manager cares about the order, we
    1063             :    // just lose.
    1064          22 :    CheckBoxOrder();
    1065             : 
    1066             : #ifdef DEBUG_LAYOUT
    1067             :    // if we are in debug make sure our children are in debug as well.
    1068             :    if (mState & NS_STATE_CURRENTLY_IN_DEBUG)
    1069             :        SetDebugOnChildList(state, mFrames.FirstChild(), true);
    1070             : #endif
    1071             : 
    1072          22 :    PresContext()->PresShell()->
    1073          22 :      FrameNeedsReflow(this, nsIPresShell::eTreeChange,
    1074          44 :                       NS_FRAME_HAS_DIRTY_CHILDREN);
    1075          22 : }
    1076             : 
    1077             : 
    1078             : void
    1079           8 : nsBoxFrame::AppendFrames(ChildListID     aListID,
    1080             :                          nsFrameList&    aFrameList)
    1081             : {
    1082           8 :    NS_PRECONDITION(aListID == kPrincipalList, "We don't support out-of-flow kids");
    1083          16 :    nsBoxLayoutState state(PresContext());
    1084             : 
    1085             :    // append the new frames
    1086           8 :    const nsFrameList::Slice& newFrames = mFrames.AppendFrames(this, aFrameList);
    1087             : 
    1088             :    // notify the layout manager
    1089           8 :    if (mLayoutManager)
    1090           0 :      mLayoutManager->ChildrenAppended(this, state, newFrames);
    1091             : 
    1092             :    // Make sure to check box order _after_ notifying the layout
    1093             :    // manager; otherwise the slice we give the layout manager will
    1094             :    // just be bogus.  If the layout manager cares about the order, we
    1095             :    // just lose.
    1096           8 :    CheckBoxOrder();
    1097             : 
    1098             : #ifdef DEBUG_LAYOUT
    1099             :    // if we are in debug make sure our children are in debug as well.
    1100             :    if (mState & NS_STATE_CURRENTLY_IN_DEBUG)
    1101             :        SetDebugOnChildList(state, mFrames.FirstChild(), true);
    1102             : #endif
    1103             : 
    1104             :    // XXXbz why is this NS_FRAME_FIRST_REFLOW check here?
    1105           8 :    if (!(GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
    1106           0 :      PresContext()->PresShell()->
    1107           0 :        FrameNeedsReflow(this, nsIPresShell::eTreeChange,
    1108           0 :                         NS_FRAME_HAS_DIRTY_CHILDREN);
    1109             :    }
    1110           8 : }
    1111             : 
    1112             : /* virtual */ nsContainerFrame*
    1113         688 : nsBoxFrame::GetContentInsertionFrame()
    1114             : {
    1115         688 :   if (GetStateBits() & NS_STATE_BOX_WRAPS_KIDS_IN_BLOCK)
    1116           0 :     return PrincipalChildList().FirstChild()->GetContentInsertionFrame();
    1117         688 :   return nsContainerFrame::GetContentInsertionFrame();
    1118             : }
    1119             : 
    1120             : nsresult
    1121         114 : nsBoxFrame::AttributeChanged(int32_t aNameSpaceID,
    1122             :                              nsIAtom* aAttribute,
    1123             :                              int32_t aModType)
    1124             : {
    1125         114 :   nsresult rv = nsContainerFrame::AttributeChanged(aNameSpaceID, aAttribute,
    1126         114 :                                                    aModType);
    1127             : 
    1128             :   // Ignore 'width', 'height', 'screenX', 'screenY' and 'sizemode' on a
    1129             :   // <window>.
    1130         228 :   if (mContent->IsAnyOfXULElements(nsGkAtoms::window,
    1131             :                                    nsGkAtoms::page,
    1132             :                                    nsGkAtoms::dialog,
    1133         119 :                                    nsGkAtoms::wizard) &&
    1134           5 :       (nsGkAtoms::width == aAttribute ||
    1135           3 :        nsGkAtoms::height == aAttribute ||
    1136           2 :        nsGkAtoms::screenX == aAttribute ||
    1137           2 :        nsGkAtoms::screenY == aAttribute ||
    1138           1 :        nsGkAtoms::sizemode == aAttribute)) {
    1139           2 :     return rv;
    1140             :   }
    1141             : 
    1142         224 :   if (aAttribute == nsGkAtoms::width       ||
    1143         224 :       aAttribute == nsGkAtoms::height      ||
    1144         224 :       aAttribute == nsGkAtoms::align       ||
    1145         224 :       aAttribute == nsGkAtoms::valign      ||
    1146         224 :       aAttribute == nsGkAtoms::left        ||
    1147         224 :       aAttribute == nsGkAtoms::top         ||
    1148         224 :       aAttribute == nsGkAtoms::right        ||
    1149         224 :       aAttribute == nsGkAtoms::bottom       ||
    1150         224 :       aAttribute == nsGkAtoms::start        ||
    1151         224 :       aAttribute == nsGkAtoms::end          ||
    1152         224 :       aAttribute == nsGkAtoms::minwidth     ||
    1153         224 :       aAttribute == nsGkAtoms::maxwidth     ||
    1154         224 :       aAttribute == nsGkAtoms::minheight    ||
    1155         224 :       aAttribute == nsGkAtoms::maxheight    ||
    1156         224 :       aAttribute == nsGkAtoms::flex         ||
    1157         223 :       aAttribute == nsGkAtoms::orient       ||
    1158         222 :       aAttribute == nsGkAtoms::pack         ||
    1159         222 :       aAttribute == nsGkAtoms::dir          ||
    1160         222 :       aAttribute == nsGkAtoms::mousethrough ||
    1161         111 :       aAttribute == nsGkAtoms::equalsize) {
    1162             : 
    1163           2 :     if (aAttribute == nsGkAtoms::align  ||
    1164           2 :         aAttribute == nsGkAtoms::valign ||
    1165           1 :         aAttribute == nsGkAtoms::orient  ||
    1166           0 :         aAttribute == nsGkAtoms::pack    ||
    1167             : #ifdef DEBUG_LAYOUT
    1168             :         aAttribute == nsGkAtoms::debug   ||
    1169             : #endif
    1170           0 :         aAttribute == nsGkAtoms::dir) {
    1171             : 
    1172           1 :       mValign = nsBoxFrame::vAlign_Top;
    1173           1 :       mHalign = nsBoxFrame::hAlign_Left;
    1174             : 
    1175           1 :       bool orient = true;
    1176           1 :       GetInitialOrientation(orient);
    1177           1 :       if (orient)
    1178           1 :         mState |= NS_STATE_IS_HORIZONTAL;
    1179             :       else
    1180           0 :         mState &= ~NS_STATE_IS_HORIZONTAL;
    1181             : 
    1182           1 :       bool normal = true;
    1183           1 :       GetInitialDirection(normal);
    1184           1 :       if (normal)
    1185           1 :         mState |= NS_STATE_IS_DIRECTION_NORMAL;
    1186             :       else
    1187           0 :         mState &= ~NS_STATE_IS_DIRECTION_NORMAL;
    1188             : 
    1189           1 :       GetInitialVAlignment(mValign);
    1190           1 :       GetInitialHAlignment(mHalign);
    1191             : 
    1192           1 :       bool equalSize = false;
    1193           1 :       GetInitialEqualSize(equalSize);
    1194           1 :       if (equalSize)
    1195           0 :         mState |= NS_STATE_EQUAL_SIZE;
    1196             :       else
    1197           1 :         mState &= ~NS_STATE_EQUAL_SIZE;
    1198             : 
    1199             : #ifdef DEBUG_LAYOUT
    1200             :       bool debug = mState & NS_STATE_SET_TO_DEBUG;
    1201             :       bool debugSet = GetInitialDebug(debug);
    1202             :       if (debugSet) {
    1203             :         mState |= NS_STATE_DEBUG_WAS_SET;
    1204             : 
    1205             :         if (debug)
    1206             :           mState |= NS_STATE_SET_TO_DEBUG;
    1207             :         else
    1208             :           mState &= ~NS_STATE_SET_TO_DEBUG;
    1209             :       } else {
    1210             :         mState &= ~NS_STATE_DEBUG_WAS_SET;
    1211             :       }
    1212             : #endif
    1213             : 
    1214           1 :       bool autostretch = !!(mState & NS_STATE_AUTO_STRETCH);
    1215           1 :       GetInitialAutoStretch(autostretch);
    1216           1 :       if (autostretch)
    1217           1 :         mState |= NS_STATE_AUTO_STRETCH;
    1218             :       else
    1219           0 :         mState &= ~NS_STATE_AUTO_STRETCH;
    1220             :     }
    1221           0 :     else if (aAttribute == nsGkAtoms::left ||
    1222           0 :              aAttribute == nsGkAtoms::top ||
    1223           0 :              aAttribute == nsGkAtoms::right ||
    1224           0 :              aAttribute == nsGkAtoms::bottom ||
    1225           0 :              aAttribute == nsGkAtoms::start ||
    1226           0 :              aAttribute == nsGkAtoms::end) {
    1227           0 :       mState &= ~NS_STATE_STACK_NOT_POSITIONED;
    1228             :     }
    1229           0 :     else if (aAttribute == nsGkAtoms::mousethrough) {
    1230           0 :       UpdateMouseThrough();
    1231             :     }
    1232             : 
    1233           1 :     PresContext()->PresShell()->
    1234           1 :       FrameNeedsReflow(this, nsIPresShell::eStyleChange, NS_FRAME_IS_DIRTY);
    1235             :   }
    1236         111 :   else if (aAttribute == nsGkAtoms::ordinal) {
    1237           0 :     nsIFrame* parent = GetParentXULBox(this);
    1238             :     // If our parent is not a box, there's not much we can do... but in that
    1239             :     // case our ordinal doesn't matter anyway, so that's ok.
    1240             :     // Also don't bother with popup frames since they are kept on the
    1241             :     // kPopupList and XULRelayoutChildAtOrdinal() only handles
    1242             :     // principal children.
    1243           0 :     if (parent && !(GetStateBits() & NS_FRAME_OUT_OF_FLOW) &&
    1244           0 :         StyleDisplay()->mDisplay != mozilla::StyleDisplay::MozPopup) {
    1245           0 :       parent->XULRelayoutChildAtOrdinal(this);
    1246             :       // XXXldb Should this instead be a tree change on the child or parent?
    1247           0 :       PresContext()->PresShell()->
    1248             :         FrameNeedsReflow(parent, nsIPresShell::eStyleChange,
    1249           0 :                          NS_FRAME_IS_DIRTY);
    1250             :     }
    1251             :   }
    1252             :   // If the accesskey changed, register for the new value
    1253             :   // The old value has been unregistered in nsXULElement::SetAttr
    1254         111 :   else if (aAttribute == nsGkAtoms::accesskey) {
    1255           0 :     RegUnregAccessKey(true);
    1256             :   }
    1257         111 :   else if (aAttribute == nsGkAtoms::rows &&
    1258           0 :            mContent->IsXULElement(nsGkAtoms::tree)) {
    1259             :     // Reflow ourselves and all our children if "rows" changes, since
    1260             :     // nsTreeBodyFrame's layout reads this from its parent (this frame).
    1261           0 :     PresContext()->PresShell()->
    1262           0 :       FrameNeedsReflow(this, nsIPresShell::eStyleChange, NS_FRAME_IS_DIRTY);
    1263             :   }
    1264             : 
    1265         112 :   return rv;
    1266             : }
    1267             : 
    1268             : #ifdef DEBUG_LAYOUT
    1269             : void
    1270             : nsBoxFrame::GetDebugPref()
    1271             : {
    1272             :   gDebug = Preferences::GetBool("xul.debug.box");
    1273             : }
    1274             : 
    1275             : class nsDisplayXULDebug : public nsDisplayItem {
    1276             : public:
    1277             :   nsDisplayXULDebug(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) :
    1278             :     nsDisplayItem(aBuilder, aFrame) {
    1279             :     MOZ_COUNT_CTOR(nsDisplayXULDebug);
    1280             :   }
    1281             : #ifdef NS_BUILD_REFCNT_LOGGING
    1282             :   virtual ~nsDisplayXULDebug() {
    1283             :     MOZ_COUNT_DTOR(nsDisplayXULDebug);
    1284             :   }
    1285             : #endif
    1286             : 
    1287             :   virtual void HitTest(nsDisplayListBuilder* aBuilder, nsRect aRect,
    1288             :                        HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) {
    1289             :     nsPoint rectCenter(aRect.x + aRect.width / 2, aRect.y + aRect.height / 2);
    1290             :     static_cast<nsBoxFrame*>(mFrame)->
    1291             :       DisplayDebugInfoFor(this, rectCenter - ToReferenceFrame());
    1292             :     aOutFrames->AppendElement(this);
    1293             :   }
    1294             :   virtual void Paint(nsDisplayListBuilder* aBuilder
    1295             :                      gfxContext* aCtx);
    1296             :   NS_DISPLAY_DECL_NAME("XULDebug", TYPE_XUL_DEBUG)
    1297             : };
    1298             : 
    1299             : void
    1300             : nsDisplayXULDebug::Paint(nsDisplayListBuilder* aBuilder,
    1301             :                          gfxContext* aCtx)
    1302             : {
    1303             :   static_cast<nsBoxFrame*>(mFrame)->
    1304             :     PaintXULDebugOverlay(*aCtx->GetDrawTarget(), ToReferenceFrame());
    1305             : }
    1306             : 
    1307             : static void
    1308             : PaintXULDebugBackground(nsIFrame* aFrame, DrawTarget* aDrawTarget,
    1309             :                         const nsRect& aDirtyRect, nsPoint aPt)
    1310             : {
    1311             :   static_cast<nsBoxFrame*>(aFrame)->PaintXULDebugBackground(aDrawTarget, aPt);
    1312             : }
    1313             : #endif
    1314             : 
    1315             : void
    1316        1916 : nsBoxFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
    1317             :                              const nsRect&           aDirtyRect,
    1318             :                              const nsDisplayListSet& aLists)
    1319             : {
    1320        1916 :   bool forceLayer = false;
    1321             : 
    1322        1916 :   if (GetContent()->IsXULElement()) {
    1323             :     // forcelayer is only supported on XUL elements with box layout
    1324        1796 :     if (GetContent()->HasAttr(kNameSpaceID_None, nsGkAtoms::layer)) {
    1325           0 :       forceLayer = true;
    1326             :     }
    1327             :     // Check for frames that are marked as a part of the region used
    1328             :     // in calculating glass margins on Windows.
    1329        1796 :     const nsStyleDisplay* styles = StyleDisplay();
    1330        1796 :     if (styles && styles->mAppearance == NS_THEME_WIN_EXCLUDE_GLASS) {
    1331           0 :       aBuilder->AddWindowExcludeGlassRegion(
    1332           0 :           nsRect(aBuilder->ToReferenceFrame(this), GetSize()));
    1333             :     }
    1334             :   }
    1335             : 
    1336        3832 :   nsDisplayListCollection tempLists;
    1337        1916 :   const nsDisplayListSet& destination = forceLayer ? tempLists : aLists;
    1338             : 
    1339        1916 :   DisplayBorderBackgroundOutline(aBuilder, destination);
    1340             : 
    1341             : #ifdef DEBUG_LAYOUT
    1342             :   if (mState & NS_STATE_CURRENTLY_IN_DEBUG) {
    1343             :     destination.BorderBackground()->AppendNewToTop(new (aBuilder)
    1344             :       nsDisplayGeneric(aBuilder, this, PaintXULDebugBackground,
    1345             :                        "XULDebugBackground"));
    1346             :     destination.Outlines()->AppendNewToTop(new (aBuilder)
    1347             :       nsDisplayXULDebug(aBuilder, this));
    1348             :   }
    1349             : #endif
    1350             : 
    1351        3832 :   Maybe<nsDisplayListBuilder::AutoContainerASRTracker> contASRTracker;
    1352        1916 :   if (forceLayer) {
    1353           0 :     contASRTracker.emplace(aBuilder);
    1354             :   }
    1355             : 
    1356        1916 :   BuildDisplayListForChildren(aBuilder, aDirtyRect, destination);
    1357             : 
    1358             :   // see if we have to draw a selection frame around this container
    1359        1916 :   DisplaySelectionOverlay(aBuilder, destination.Content());
    1360             : 
    1361        1916 :   if (forceLayer) {
    1362             :     // This is a bit of a hack. Collect up all descendant display items
    1363             :     // and merge them into a single Content() list. This can cause us
    1364             :     // to violate CSS stacking order, but forceLayer is a magic
    1365             :     // XUL-only extension anyway.
    1366           0 :     nsDisplayList masterList;
    1367           0 :     masterList.AppendToTop(tempLists.BorderBackground());
    1368           0 :     masterList.AppendToTop(tempLists.BlockBorderBackgrounds());
    1369           0 :     masterList.AppendToTop(tempLists.Floats());
    1370           0 :     masterList.AppendToTop(tempLists.Content());
    1371           0 :     masterList.AppendToTop(tempLists.PositionedDescendants());
    1372           0 :     masterList.AppendToTop(tempLists.Outlines());
    1373             : 
    1374           0 :     const ActiveScrolledRoot* ownLayerASR = contASRTracker->GetContainerASR();
    1375             : 
    1376           0 :     DisplayListClipState::AutoSaveRestore ownLayerClipState(aBuilder);
    1377           0 :     ownLayerClipState.ClearUpToASR(ownLayerASR);
    1378             : 
    1379             :     // Wrap the list to make it its own layer
    1380           0 :     aLists.Content()->AppendNewToTop(new (aBuilder)
    1381           0 :       nsDisplayOwnLayer(aBuilder, this, &masterList, ownLayerASR));
    1382             :   }
    1383        1916 : }
    1384             : 
    1385             : void
    1386        1745 : nsBoxFrame::BuildDisplayListForChildren(nsDisplayListBuilder*   aBuilder,
    1387             :                                         const nsRect&           aDirtyRect,
    1388             :                                         const nsDisplayListSet& aLists)
    1389             : {
    1390        1745 :   nsIFrame* kid = mFrames.FirstChild();
    1391             :   // Put each child's background onto the BlockBorderBackgrounds list
    1392             :   // to emulate the existing two-layer XUL painting scheme.
    1393        1745 :   nsDisplayListSet set(aLists, aLists.BlockBorderBackgrounds());
    1394             :   // The children should be in the right order
    1395        9479 :   while (kid) {
    1396        3867 :     BuildDisplayListForChild(aBuilder, kid, aDirtyRect, set);
    1397        3867 :     kid = kid->GetNextSibling();
    1398             :   }
    1399        1745 : }
    1400             : 
    1401             : // REVIEW: PaintChildren did a few things none of which are a big deal
    1402             : // anymore:
    1403             : // * Paint some debugging rects for this frame.
    1404             : // This is done by nsDisplayXULDebugBackground, which goes in the
    1405             : // BorderBackground() layer so it isn't clipped by OVERFLOW_CLIP.
    1406             : // * Apply OVERFLOW_CLIP to the children.
    1407             : // This is now in nsFrame::BuildDisplayListForStackingContext/Child.
    1408             : // * Actually paint the children.
    1409             : // Moved to BuildDisplayList.
    1410             : // * Paint per-kid debug information.
    1411             : // This is done by nsDisplayXULDebug, which is in the Outlines()
    1412             : // layer so it goes on top. This means it is not clipped by OVERFLOW_CLIP,
    1413             : // whereas it did used to respect OVERFLOW_CLIP, but too bad.
    1414             : #ifdef DEBUG_LAYOUT
    1415             : void
    1416             : nsBoxFrame::PaintXULDebugBackground(DrawTarget* aDrawTarget, nsPoint aPt)
    1417             : {
    1418             :   nsMargin border;
    1419             :   GetXULBorder(border);
    1420             : 
    1421             :   nsMargin debugBorder;
    1422             :   nsMargin debugMargin;
    1423             :   nsMargin debugPadding;
    1424             : 
    1425             :   bool isHorizontal = IsXULHorizontal();
    1426             : 
    1427             :   GetDebugBorder(debugBorder);
    1428             :   PixelMarginToTwips(debugBorder);
    1429             : 
    1430             :   GetDebugMargin(debugMargin);
    1431             :   PixelMarginToTwips(debugMargin);
    1432             : 
    1433             :   GetDebugPadding(debugPadding);
    1434             :   PixelMarginToTwips(debugPadding);
    1435             : 
    1436             :   nsRect inner(mRect);
    1437             :   inner.MoveTo(aPt);
    1438             :   inner.Deflate(debugMargin);
    1439             :   inner.Deflate(border);
    1440             :   //nsRect borderRect(inner);
    1441             : 
    1442             :   int32_t appUnitsPerDevPixel = PresContext()->AppUnitsPerDevPixel();
    1443             : 
    1444             :   ColorPattern color(ToDeviceColor(isHorizontal ? Color(0.f, 0.f, 1.f, 1.f) :
    1445             :                                                   Color(1.f, 0.f, 0.f, 1.f)));
    1446             : 
    1447             :   //left
    1448             :   nsRect r(inner);
    1449             :   r.width = debugBorder.left;
    1450             :   aDrawTarget->FillRect(NSRectToRect(r, appUnitsPerDevPixel), color);
    1451             : 
    1452             :   // top
    1453             :   r = inner;
    1454             :   r.height = debugBorder.top;
    1455             :   aDrawTarget->FillRect(NSRectToRect(r, appUnitsPerDevPixel), color);
    1456             : 
    1457             :   //right
    1458             :   r = inner;
    1459             :   r.x = r.x + r.width - debugBorder.right;
    1460             :   r.width = debugBorder.right;
    1461             :   aDrawTarget->FillRect(NSRectToRect(r, appUnitsPerDevPixel), color);
    1462             : 
    1463             :   //bottom
    1464             :   r = inner;
    1465             :   r.y = r.y + r.height - debugBorder.bottom;
    1466             :   r.height = debugBorder.bottom;
    1467             :   aDrawTarget->FillRect(NSRectToRect(r, appUnitsPerDevPixel), color);
    1468             : 
    1469             :   // If we have dirty children or we are dirty place a green border around us.
    1470             :   if (NS_SUBTREE_DIRTY(this)) {
    1471             :     nsRect dirty(inner);
    1472             :     ColorPattern green(ToDeviceColor(Color(0.f, 1.f, 0.f, 1.f)));
    1473             :     aDrawTarget->StrokeRect(NSRectToRect(dirty, appUnitsPerDevPixel), green);
    1474             :   }
    1475             : }
    1476             : 
    1477             : void
    1478             : nsBoxFrame::PaintXULDebugOverlay(DrawTarget& aDrawTarget, nsPoint aPt)
    1479             : {
    1480             :   nsMargin border;
    1481             :   GetXULBorder(border);
    1482             : 
    1483             :   nsMargin debugMargin;
    1484             :   GetDebugMargin(debugMargin);
    1485             :   PixelMarginToTwips(debugMargin);
    1486             : 
    1487             :   nsRect inner(mRect);
    1488             :   inner.MoveTo(aPt);
    1489             :   inner.Deflate(debugMargin);
    1490             :   inner.Deflate(border);
    1491             : 
    1492             :   nscoord onePixel = GetPresContext()->IntScaledPixelsToTwips(1);
    1493             : 
    1494             :   kid = nsBox::GetChildXULBox(this);
    1495             :   while (nullptr != kid) {
    1496             :     bool isHorizontal = IsXULHorizontal();
    1497             : 
    1498             :     nscoord x, y, borderSize, spacerSize;
    1499             : 
    1500             :     nsRect cr(kid->mRect);
    1501             :     nsMargin margin;
    1502             :     kid->GetXULMargin(margin);
    1503             :     cr.Inflate(margin);
    1504             : 
    1505             :     if (isHorizontal)
    1506             :     {
    1507             :         cr.y = inner.y;
    1508             :         x = cr.x;
    1509             :         y = cr.y + onePixel;
    1510             :         spacerSize = debugBorder.top - onePixel*4;
    1511             :     } else {
    1512             :         cr.x = inner.x;
    1513             :         x = cr.y;
    1514             :         y = cr.x + onePixel;
    1515             :         spacerSize = debugBorder.left - onePixel*4;
    1516             :     }
    1517             : 
    1518             :     nscoord flex = kid->GetXULFlex();
    1519             : 
    1520             :     if (!kid->IsXULCollapsed()) {
    1521             :       if (isHorizontal)
    1522             :           borderSize = cr.width;
    1523             :       else
    1524             :           borderSize = cr.height;
    1525             : 
    1526             :       DrawSpacer(GetPresContext(), aDrawTarget, isHorizontal, flex, x, y, borderSize, spacerSize);
    1527             :     }
    1528             : 
    1529             :     kid = GetNextXULBox(kid);
    1530             :   }
    1531             : }
    1532             : #endif
    1533             : 
    1534             : #ifdef DEBUG_LAYOUT
    1535             : void
    1536             : nsBoxFrame::GetBoxName(nsAutoString& aName)
    1537             : {
    1538             :    GetFrameName(aName);
    1539             : }
    1540             : #endif
    1541             : 
    1542             : #ifdef DEBUG_FRAME_DUMP
    1543             : nsresult
    1544           0 : nsBoxFrame::GetFrameName(nsAString& aResult) const
    1545             : {
    1546           0 :   return MakeFrameName(NS_LITERAL_STRING("Box"), aResult);
    1547             : }
    1548             : #endif
    1549             : 
    1550             : #ifdef DEBUG_LAYOUT
    1551             : nsresult
    1552             : nsBoxFrame::GetXULDebug(bool& aDebug)
    1553             : {
    1554             :   aDebug = (mState & NS_STATE_CURRENTLY_IN_DEBUG);
    1555             :   return NS_OK;
    1556             : }
    1557             : #endif
    1558             : 
    1559             : // REVIEW: nsBoxFrame::GetFrameForPoint is a problem because of 'mousethrough'
    1560             : // attribute support. Here's how it works:
    1561             : // * For each child frame F, we determine the target frame T(F) by recursively
    1562             : // invoking GetFrameForPoint on the child
    1563             : // * Let F' be the last child frame such that T(F') doesn't have mousethrough.
    1564             : // If F' exists, return T(F')
    1565             : // * Otherwise let F'' be the first child frame such that T(F'') is non-null.
    1566             : // If F'' exists, return T(F'')
    1567             : // * Otherwise return this frame, if this frame contains the point
    1568             : // * Otherwise return null
    1569             : // It's not clear how this should work for more complex z-ordering situations.
    1570             : // The basic principle seems to be that if a frame F has a descendant
    1571             : // 'mousethrough' frame that includes the target position, then F
    1572             : // will not receive events (unless it overrides GetFrameForPoint).
    1573             : // A 'mousethrough' frame will only receive an event if, after applying that rule,
    1574             : // all eligible frames are 'mousethrough'; the bottom-most inner-most 'mousethrough'
    1575             : // frame is then chosen (the first eligible frame reached in a
    1576             : // traversal of the frame tree --- pre/post is irrelevant since ancestors
    1577             : // of the mousethrough frames can't be eligible).
    1578             : // IMHO this is very bogus and adds a great deal of complexity for something
    1579             : // that is very rarely used. So I'm redefining 'mousethrough' to the following:
    1580             : // a frame with mousethrough is transparent to mouse events. This is compatible
    1581             : // with the way 'mousethrough' is used in Seamonkey's navigator.xul and
    1582             : // Firefox's browser.xul. The only other place it's used is in the 'expander'
    1583             : // XBL binding, which in our tree is only used by Thunderbird SMIME Advanced
    1584             : // Preferences, and I can't figure out what that does, so I'll have to test it.
    1585             : // If it's broken I'll probably just change the binding to use it more sensibly.
    1586             : // This new behaviour is implemented in nsDisplayList::HitTest.
    1587             : // REVIEW: This debug-box stuff is annoying. I'm just going to put debug boxes
    1588             : // in the outline layer and avoid GetDebugBoxAt.
    1589             : 
    1590             : // REVIEW: GetCursor had debug-only event dumping code. I have replaced it
    1591             : // with instrumentation in nsDisplayXULDebug.
    1592             : 
    1593             : #ifdef DEBUG_LAYOUT
    1594             : void
    1595             : nsBoxFrame::DrawLine(DrawTarget& aDrawTarget, bool aHorizontal, nscoord x1, nscoord y1, nscoord x2, nscoord y2)
    1596             : {
    1597             :     nsPoint p1(x1, y1);
    1598             :     nsPoint p2(x2, y2);
    1599             :     if (!aHorizontal) {
    1600             :       Swap(p1.x, p1.y);
    1601             :       Swap(p2.x, p2.y);
    1602             :     }
    1603             :     ColorPattern white(ToDeviceColor(Color(1.f, 1.f, 1.f, 1.f)));
    1604             :     StrokeLineWithSnapping(p1, p2, PresContext()->AppUnitsPerDevPixel(),
    1605             :                            aDrawTarget, color);
    1606             : }
    1607             : 
    1608             : void
    1609             : nsBoxFrame::FillRect(DrawTarget& aDrawTarget, bool aHorizontal, nscoord x, nscoord y, nscoord width, nscoord height)
    1610             : {
    1611             :     Rect rect = NSRectToSnappedRect(aHorizontal ? nsRect(x, y, width, height) :
    1612             :                                                   nsRect(y, x, height, width),
    1613             :                                     PresContext()->AppUnitsPerDevPixel(),
    1614             :                                     aDrawTarget);
    1615             :     ColorPattern white(ToDeviceColor(Color(1.f, 1.f, 1.f, 1.f)));
    1616             :     aDrawTarget.FillRect(rect, white);
    1617             : }
    1618             : 
    1619             : void
    1620             : nsBoxFrame::DrawSpacer(nsPresContext* aPresContext, DrawTarget& aDrawTarget,
    1621             :                        bool aHorizontal, int32_t flex, nscoord x, nscoord y,
    1622             :                        nscoord size, nscoord spacerSize)
    1623             : {
    1624             :          nscoord onePixel = aPresContext->IntScaledPixelsToTwips(1);
    1625             : 
    1626             :      // if we do draw the coils
    1627             :         int distance = 0;
    1628             :         int center = 0;
    1629             :         int offset = 0;
    1630             :         int coilSize = COIL_SIZE*onePixel;
    1631             :         int halfSpacer = spacerSize/2;
    1632             : 
    1633             :         distance = size;
    1634             :         center = y + halfSpacer;
    1635             :         offset = x;
    1636             : 
    1637             :         int coils = distance/coilSize;
    1638             : 
    1639             :         int halfCoilSize = coilSize/2;
    1640             : 
    1641             :         if (flex == 0) {
    1642             :             DrawLine(aDrawTarget, aHorizontal, x,y + spacerSize/2, x + size, y + spacerSize/2);
    1643             :         } else {
    1644             :             for (int i=0; i < coils; i++)
    1645             :             {
    1646             :                    DrawLine(aDrawTarget, aHorizontal, offset, center+halfSpacer, offset+halfCoilSize, center-halfSpacer);
    1647             :                    DrawLine(aDrawTarget, aHorizontal, offset+halfCoilSize, center-halfSpacer, offset+coilSize, center+halfSpacer);
    1648             : 
    1649             :                    offset += coilSize;
    1650             :             }
    1651             :         }
    1652             : 
    1653             :         FillRect(aDrawTarget, aHorizontal, x + size - spacerSize/2, y, spacerSize/2, spacerSize);
    1654             :         FillRect(aDrawTarget, aHorizontal, x, y, spacerSize/2, spacerSize);
    1655             : }
    1656             : 
    1657             : void
    1658             : nsBoxFrame::GetDebugBorder(nsMargin& aInset)
    1659             : {
    1660             :     aInset.SizeTo(2,2,2,2);
    1661             : 
    1662             :     if (IsXULHorizontal())
    1663             :        aInset.top = 10;
    1664             :     else
    1665             :        aInset.left = 10;
    1666             : }
    1667             : 
    1668             : void
    1669             : nsBoxFrame::GetDebugMargin(nsMargin& aInset)
    1670             : {
    1671             :     aInset.SizeTo(2,2,2,2);
    1672             : }
    1673             : 
    1674             : void
    1675             : nsBoxFrame::GetDebugPadding(nsMargin& aPadding)
    1676             : {
    1677             :     aPadding.SizeTo(2,2,2,2);
    1678             : }
    1679             : 
    1680             : void
    1681             : nsBoxFrame::PixelMarginToTwips(nsMargin& aMarginPixels)
    1682             : {
    1683             :   nscoord onePixel = nsPresContext::CSSPixelsToAppUnits(1);
    1684             :   aMarginPixels.left   *= onePixel;
    1685             :   aMarginPixels.right  *= onePixel;
    1686             :   aMarginPixels.top    *= onePixel;
    1687             :   aMarginPixels.bottom *= onePixel;
    1688             : }
    1689             : 
    1690             : void
    1691             : nsBoxFrame::GetValue(nsPresContext* aPresContext, const nsSize& a, const nsSize& b, char* ch)
    1692             : {
    1693             :     float p2t = aPresContext->ScaledPixelsToTwips();
    1694             : 
    1695             :     char width[100];
    1696             :     char height[100];
    1697             : 
    1698             :     if (a.width == NS_INTRINSICSIZE)
    1699             :         sprintf(width,"%s","INF");
    1700             :     else
    1701             :         sprintf(width,"%d", nscoord(a.width/*/p2t*/));
    1702             : 
    1703             :     if (a.height == NS_INTRINSICSIZE)
    1704             :         sprintf(height,"%s","INF");
    1705             :     else
    1706             :         sprintf(height,"%d", nscoord(a.height/*/p2t*/));
    1707             : 
    1708             : 
    1709             :     sprintf(ch, "(%s%s, %s%s)", width, (b.width != NS_INTRINSICSIZE ? "[SET]" : ""),
    1710             :                     height, (b.height != NS_INTRINSICSIZE ? "[SET]" : ""));
    1711             : 
    1712             : }
    1713             : 
    1714             : void
    1715             : nsBoxFrame::GetValue(nsPresContext* aPresContext, int32_t a, int32_t b, char* ch)
    1716             : {
    1717             :     if (a == NS_INTRINSICSIZE)
    1718             :       sprintf(ch, "%d[SET]", b);
    1719             :     else
    1720             :       sprintf(ch, "%d", a);
    1721             : }
    1722             : 
    1723             : nsresult
    1724             : nsBoxFrame::DisplayDebugInfoFor(nsIFrame*  aBox,
    1725             :                                 nsPoint& aPoint)
    1726             : {
    1727             :     nsBoxLayoutState state(GetPresContext());
    1728             : 
    1729             :     nscoord x = aPoint.x;
    1730             :     nscoord y = aPoint.y;
    1731             : 
    1732             :     // get the area inside our border but not our debug margins.
    1733             :     nsRect insideBorder(aBox->mRect);
    1734             :     insideBorder.MoveTo(0,0):
    1735             :     nsMargin border(0,0,0,0);
    1736             :     aBox->GetXULBorderAndPadding(border);
    1737             :     insideBorder.Deflate(border);
    1738             : 
    1739             :     bool isHorizontal = IsXULHorizontal();
    1740             : 
    1741             :     if (!insideBorder.Contains(nsPoint(x,y)))
    1742             :         return NS_ERROR_FAILURE;
    1743             : 
    1744             :     //printf("%%%%%% inside box %%%%%%%\n");
    1745             : 
    1746             :     int count = 0;
    1747             :     nsIFrame* child = nsBox::GetChildXULBox(aBox);
    1748             : 
    1749             :     nsMargin m;
    1750             :     nsMargin m2;
    1751             :     GetDebugBorder(m);
    1752             :     PixelMarginToTwips(m);
    1753             : 
    1754             :     GetDebugMargin(m2);
    1755             :     PixelMarginToTwips(m2);
    1756             : 
    1757             :     m += m2;
    1758             : 
    1759             :     if ((isHorizontal && y < insideBorder.y + m.top) ||
    1760             :         (!isHorizontal && x < insideBorder.x + m.left)) {
    1761             :         //printf("**** inside debug border *******\n");
    1762             :         while (child)
    1763             :         {
    1764             :             const nsRect& r = child->mRect;
    1765             : 
    1766             :             // if we are not in the child. But in the spacer above the child.
    1767             :             if ((isHorizontal && x >= r.x && x < r.x + r.width) ||
    1768             :                 (!isHorizontal && y >= r.y && y < r.y + r.height)) {
    1769             :                 aCursor = NS_STYLE_CURSOR_POINTER;
    1770             :                    // found it but we already showed it.
    1771             :                     if (mDebugChild == child)
    1772             :                         return NS_OK;
    1773             : 
    1774             :                     if (aBox->GetContent()) {
    1775             :                       printf("---------------\n");
    1776             :                       XULDumpBox(stdout);
    1777             :                       printf("\n");
    1778             :                     }
    1779             : 
    1780             :                     if (child->GetContent()) {
    1781             :                         printf("child #%d: ", count);
    1782             :                         child->XULDumpBox(stdout);
    1783             :                         printf("\n");
    1784             :                     }
    1785             : 
    1786             :                     mDebugChild = child;
    1787             : 
    1788             :                     nsSize prefSizeCSS(NS_INTRINSICSIZE, NS_INTRINSICSIZE);
    1789             :                     nsSize minSizeCSS (NS_INTRINSICSIZE, NS_INTRINSICSIZE);
    1790             :                     nsSize maxSizeCSS (NS_INTRINSICSIZE, NS_INTRINSICSIZE);
    1791             :                     nscoord flexCSS = NS_INTRINSICSIZE;
    1792             : 
    1793             :                     bool widthSet, heightSet;
    1794             :                     nsIFrame::AddXULPrefSize(child, prefSizeCSS, widthSet, heightSet);
    1795             :                     nsIFrame::AddXULMinSize (state, child, minSizeCSS, widthSet, heightSet);
    1796             :                     nsIFrame::AddXULMaxSize (child, maxSizeCSS, widthSet, heightSet);
    1797             :                     nsIFrame::AddXULFlex    (child, flexCSS);
    1798             : 
    1799             :                     nsSize prefSize = child->GetXULPrefSize(state);
    1800             :                     nsSize minSize = child->GetXULMinSize(state);
    1801             :                     nsSize maxSize = child->GetXULMaxSize(state);
    1802             :                     nscoord flexSize = child->GetXULFlex();
    1803             :                     nscoord ascentSize = child->GetXULBoxAscent(state);
    1804             : 
    1805             :                     char min[100];
    1806             :                     char pref[100];
    1807             :                     char max[100];
    1808             :                     char calc[100];
    1809             :                     char flex[100];
    1810             :                     char ascent[100];
    1811             : 
    1812             :                     nsSize actualSize;
    1813             :                     GetFrameSizeWithMargin(child, actualSize);
    1814             :                     nsSize actualSizeCSS (NS_INTRINSICSIZE, NS_INTRINSICSIZE);
    1815             : 
    1816             :                     GetValue(aPresContext, minSize,  minSizeCSS, min);
    1817             :                     GetValue(aPresContext, prefSize, prefSizeCSS, pref);
    1818             :                     GetValue(aPresContext, maxSize,  maxSizeCSS, max);
    1819             :                     GetValue(aPresContext, actualSize, actualSizeCSS, calc);
    1820             :                     GetValue(aPresContext, flexSize,  flexCSS, flex);
    1821             :                     GetValue(aPresContext, ascentSize,  NS_INTRINSICSIZE, ascent);
    1822             : 
    1823             : 
    1824             :                     printf("min%s, pref%s, max%s, actual%s, flex=%s, ascent=%s\n\n",
    1825             :                         min,
    1826             :                         pref,
    1827             :                         max,
    1828             :                         calc,
    1829             :                         flex,
    1830             :                         ascent
    1831             :                     );
    1832             : 
    1833             :                     return NS_OK;
    1834             :             }
    1835             : 
    1836             :           child = GetNextXULBox(child);
    1837             :           count++;
    1838             :         }
    1839             :     } else {
    1840             :     }
    1841             : 
    1842             :     mDebugChild = nullptr;
    1843             : 
    1844             :     return NS_OK;
    1845             : }
    1846             : 
    1847             : void
    1848             : nsBoxFrame::SetDebugOnChildList(nsBoxLayoutState& aState, nsIFrame* aChild, bool aDebug)
    1849             : {
    1850             :     nsIFrame* child = nsBox::GetChildXULBox(this);
    1851             :      while (child)
    1852             :      {
    1853             :         child->SetXULDebug(aState, aDebug);
    1854             :         child = GetNextXULBox(child);
    1855             :      }
    1856             : }
    1857             : 
    1858             : nsresult
    1859             : nsBoxFrame::GetFrameSizeWithMargin(nsIFrame* aBox, nsSize& aSize)
    1860             : {
    1861             :   nsRect rect(aBox->GetRect());
    1862             :   nsMargin margin(0,0,0,0);
    1863             :   aBox->GetXULMargin(margin);
    1864             :   rect.Inflate(margin);
    1865             :   aSize.width = rect.width;
    1866             :   aSize.height = rect.height;
    1867             :   return NS_OK;
    1868             : }
    1869             : #endif
    1870             : 
    1871             : // If you make changes to this function, check its counterparts
    1872             : // in nsTextBoxFrame and nsXULLabelFrame
    1873             : void
    1874         288 : nsBoxFrame::RegUnregAccessKey(bool aDoReg)
    1875             : {
    1876         288 :   MOZ_ASSERT(mContent);
    1877             : 
    1878             :   // only support accesskeys for the following elements
    1879         288 :   if (!mContent->IsAnyOfXULElements(nsGkAtoms::button,
    1880             :                                     nsGkAtoms::toolbarbutton,
    1881             :                                     nsGkAtoms::checkbox,
    1882             :                                     nsGkAtoms::textbox,
    1883             :                                     nsGkAtoms::tab,
    1884             :                                     nsGkAtoms::radio)) {
    1885         520 :     return;
    1886             :   }
    1887             : 
    1888          56 :   nsAutoString accessKey;
    1889          56 :   mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::accesskey, accessKey);
    1890             : 
    1891          56 :   if (accessKey.IsEmpty())
    1892          56 :     return;
    1893             : 
    1894             :   // With a valid PresContext we can get the ESM
    1895             :   // and register the access key
    1896           0 :   EventStateManager* esm = PresContext()->EventStateManager();
    1897             : 
    1898           0 :   uint32_t key = accessKey.First();
    1899           0 :   if (aDoReg)
    1900           0 :     esm->RegisterAccessKey(mContent, key);
    1901             :   else
    1902           0 :     esm->UnregisterAccessKey(mContent, key);
    1903             : }
    1904             : 
    1905             : bool
    1906         262 : nsBoxFrame::SupportsOrdinalsInChildren()
    1907             : {
    1908         262 :   return true;
    1909             : }
    1910             : 
    1911             : // Helper less-than-or-equal function, used in CheckBoxOrder() as a
    1912             : // template-parameter for the sorting functions.
    1913             : bool
    1914         187 : IsBoxOrdinalLEQ(nsIFrame* aFrame1,
    1915             :                 nsIFrame* aFrame2)
    1916             : {
    1917             :   // If we've got a placeholder frame, use its out-of-flow frame's ordinal val.
    1918         187 :   nsIFrame* aRealFrame1 = nsPlaceholderFrame::GetRealFrameFor(aFrame1);
    1919         187 :   nsIFrame* aRealFrame2 = nsPlaceholderFrame::GetRealFrameFor(aFrame2);
    1920         187 :   return aRealFrame1->GetXULOrdinal() <= aRealFrame2->GetXULOrdinal();
    1921             : }
    1922             : 
    1923             : void
    1924         262 : nsBoxFrame::CheckBoxOrder()
    1925             : {
    1926         524 :   if (SupportsOrdinalsInChildren() &&
    1927         262 :       !nsIFrame::IsFrameListSorted<IsBoxOrdinalLEQ>(mFrames)) {
    1928           0 :     nsIFrame::SortFrameList<IsBoxOrdinalLEQ>(mFrames);
    1929             :   }
    1930         262 : }
    1931             : 
    1932             : nsresult
    1933         141 : nsBoxFrame::LayoutChildAt(nsBoxLayoutState& aState, nsIFrame* aBox, const nsRect& aRect)
    1934             : {
    1935             :   // get the current rect
    1936         282 :   nsRect oldRect(aBox->GetRect());
    1937         141 :   aBox->SetXULBounds(aState, aRect);
    1938             : 
    1939         141 :   bool layout = NS_SUBTREE_DIRTY(aBox);
    1940             : 
    1941         141 :   if (layout || (oldRect.width != aRect.width || oldRect.height != aRect.height))  {
    1942         110 :     return aBox->XULLayout(aState);
    1943             :   }
    1944             : 
    1945          31 :   return NS_OK;
    1946             : }
    1947             : 
    1948             : nsresult
    1949           0 : nsBoxFrame::XULRelayoutChildAtOrdinal(nsIFrame* aChild)
    1950             : {
    1951           0 :   if (!SupportsOrdinalsInChildren())
    1952           0 :     return NS_OK;
    1953             : 
    1954           0 :   uint32_t ord = aChild->GetXULOrdinal();
    1955             : 
    1956           0 :   nsIFrame* child = mFrames.FirstChild();
    1957           0 :   nsIFrame* newPrevSib = nullptr;
    1958             : 
    1959           0 :   while (child) {
    1960           0 :     if (ord < child->GetXULOrdinal()) {
    1961           0 :       break;
    1962             :     }
    1963             : 
    1964           0 :     if (child != aChild) {
    1965           0 :       newPrevSib = child;
    1966             :     }
    1967             : 
    1968           0 :     child = GetNextXULBox(child);
    1969             :   }
    1970             : 
    1971           0 :   if (aChild->GetPrevSibling() == newPrevSib) {
    1972             :     // This box is not moving.
    1973           0 :     return NS_OK;
    1974             :   }
    1975             : 
    1976             :   // Take |aChild| out of its old position in the child list.
    1977           0 :   mFrames.RemoveFrame(aChild);
    1978             : 
    1979             :   // Insert it after |newPrevSib| or at the start if it's null.
    1980           0 :   mFrames.InsertFrame(nullptr, newPrevSib, aChild);
    1981             : 
    1982           0 :   return NS_OK;
    1983             : }
    1984             : 
    1985             : /**
    1986             :  * This wrapper class lets us redirect mouse hits from descendant frames
    1987             :  * of a menu to the menu itself, if they didn't specify 'allowevents'.
    1988             :  *
    1989             :  * The wrapper simply turns a hit on a descendant element
    1990             :  * into a hit on the menu itself, unless there is an element between the target
    1991             :  * and the menu with the "allowevents" attribute.
    1992             :  *
    1993             :  * This is used by nsMenuFrame and nsTreeColFrame.
    1994             :  *
    1995             :  * Note that turning a hit on a descendant element into nullptr, so events
    1996             :  * could fall through to the menu background, might be an appealing simplification
    1997             :  * but it would mean slightly strange behaviour in some cases, because grabber
    1998             :  * wrappers can be created for many individual lists and items, so the exact
    1999             :  * fallthrough behaviour would be complex. E.g. an element with "allowevents"
    2000             :  * on top of the Content() list could receive the event even if it was covered
    2001             :  * by a PositionedDescenants() element without "allowevents". It is best to
    2002             :  * never convert a non-null hit into null.
    2003             :  */
    2004             : // REVIEW: This is roughly of what nsMenuFrame::GetFrameForPoint used to do.
    2005             : // I've made 'allowevents' affect child elements because that seems the only
    2006             : // reasonable thing to do.
    2007           0 : class nsDisplayXULEventRedirector final : public nsDisplayWrapList
    2008             : {
    2009             : public:
    2010           0 :   nsDisplayXULEventRedirector(nsDisplayListBuilder* aBuilder,
    2011             :                               nsIFrame* aFrame, nsDisplayItem* aItem,
    2012             :                               nsIFrame* aTargetFrame)
    2013           0 :     : nsDisplayWrapList(aBuilder, aFrame, aItem), mTargetFrame(aTargetFrame) {}
    2014           0 :   nsDisplayXULEventRedirector(nsDisplayListBuilder* aBuilder,
    2015             :                               nsIFrame* aFrame, nsDisplayList* aList,
    2016             :                               nsIFrame* aTargetFrame)
    2017           0 :     : nsDisplayWrapList(aBuilder, aFrame, aList), mTargetFrame(aTargetFrame) {}
    2018             :   virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
    2019             :                        HitTestState* aState,
    2020             :                        nsTArray<nsIFrame*> *aOutFrames) override;
    2021           0 :   virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override {
    2022           0 :     return false;
    2023             :   }
    2024           0 :   NS_DISPLAY_DECL_NAME("XULEventRedirector", TYPE_XUL_EVENT_REDIRECTOR)
    2025             : private:
    2026             :   nsIFrame* mTargetFrame;
    2027             : };
    2028             : 
    2029           0 : void nsDisplayXULEventRedirector::HitTest(nsDisplayListBuilder* aBuilder,
    2030             :     const nsRect& aRect, HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames)
    2031             : {
    2032           0 :   nsTArray<nsIFrame*> outFrames;
    2033           0 :   mList.HitTest(aBuilder, aRect, aState, &outFrames);
    2034             : 
    2035           0 :   bool topMostAdded = false;
    2036           0 :   uint32_t localLength = outFrames.Length();
    2037             : 
    2038           0 :   for (uint32_t i = 0; i < localLength; i++) {
    2039             : 
    2040           0 :     for (nsIContent* content = outFrames.ElementAt(i)->GetContent();
    2041           0 :          content && content != mTargetFrame->GetContent();
    2042           0 :          content = content->GetParent()) {
    2043           0 :       if (content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::allowevents,
    2044             :                                nsGkAtoms::_true, eCaseMatters)) {
    2045             :         // Events are allowed on 'frame', so let it go.
    2046           0 :         aOutFrames->AppendElement(outFrames.ElementAt(i));
    2047           0 :         topMostAdded = true;
    2048             :       }
    2049             :     }
    2050             : 
    2051             :     // If there was no hit on the topmost frame or its ancestors,
    2052             :     // add the target frame itself as the first candidate (see bug 562554).
    2053           0 :     if (!topMostAdded) {
    2054           0 :       topMostAdded = true;
    2055           0 :       aOutFrames->AppendElement(mTargetFrame);
    2056             :     }
    2057             :   }
    2058           0 : }
    2059             : 
    2060             : class nsXULEventRedirectorWrapper final : public nsDisplayWrapper
    2061             : {
    2062             : public:
    2063           0 :   explicit nsXULEventRedirectorWrapper(nsIFrame* aTargetFrame)
    2064           0 :       : mTargetFrame(aTargetFrame) {}
    2065           0 :   virtual nsDisplayItem* WrapList(nsDisplayListBuilder* aBuilder,
    2066             :                                   nsIFrame* aFrame,
    2067             :                                   nsDisplayList* aList) override {
    2068             :     return new (aBuilder)
    2069           0 :         nsDisplayXULEventRedirector(aBuilder, aFrame, aList, mTargetFrame);
    2070             :   }
    2071           0 :   virtual nsDisplayItem* WrapItem(nsDisplayListBuilder* aBuilder,
    2072             :                                   nsDisplayItem* aItem) override {
    2073             :     return new (aBuilder)
    2074           0 :         nsDisplayXULEventRedirector(aBuilder, aItem->Frame(), aItem,
    2075           0 :                                     mTargetFrame);
    2076             :   }
    2077             : private:
    2078             :   nsIFrame* mTargetFrame;
    2079             : };
    2080             : 
    2081             : void
    2082           0 : nsBoxFrame::WrapListsInRedirector(nsDisplayListBuilder*   aBuilder,
    2083             :                                   const nsDisplayListSet& aIn,
    2084             :                                   const nsDisplayListSet& aOut)
    2085             : {
    2086           0 :   nsXULEventRedirectorWrapper wrapper(this);
    2087           0 :   wrapper.WrapLists(aBuilder, this, aIn, aOut);
    2088           0 : }
    2089             : 
    2090             : bool
    2091           0 : nsBoxFrame::GetEventPoint(WidgetGUIEvent* aEvent, nsPoint &aPoint) {
    2092           0 :   LayoutDeviceIntPoint refPoint;
    2093           0 :   bool res = GetEventPoint(aEvent, refPoint);
    2094           0 :   aPoint = nsLayoutUtils::GetEventCoordinatesRelativeTo(
    2095             :     aEvent, refPoint, this);
    2096           0 :   return res;
    2097             : }
    2098             : 
    2099             : bool
    2100           0 : nsBoxFrame::GetEventPoint(WidgetGUIEvent* aEvent, LayoutDeviceIntPoint& aPoint) {
    2101           0 :   NS_ENSURE_TRUE(aEvent, false);
    2102             : 
    2103           0 :   WidgetTouchEvent* touchEvent = aEvent->AsTouchEvent();
    2104           0 :   if (touchEvent) {
    2105             :     // return false if there is more than one touch on the page, or if
    2106             :     // we can't find a touch point
    2107           0 :     if (touchEvent->mTouches.Length() != 1) {
    2108           0 :       return false;
    2109             :     }
    2110             : 
    2111           0 :     dom::Touch* touch = touchEvent->mTouches.SafeElementAt(0);
    2112           0 :     if (!touch) {
    2113           0 :       return false;
    2114             :     }
    2115           0 :     aPoint = touch->mRefPoint;
    2116             :   } else {
    2117           0 :     aPoint = aEvent->mRefPoint;
    2118             :   }
    2119           0 :   return true;
    2120             : }

Generated by: LCOV version 1.13