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/. */
9 // Netscape Communications
11 // See documentation in associated header file
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
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
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.
34 #include "nsBoxFrame.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"
45 #include "nsNameSpaceManager.h"
46 #include "nsGkAtoms.h"
47 #include "nsIContent.h"
48 #include "nsHTMLParts.h"
49 #include "nsViewManager.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"
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"
71 // Needed for Print Preview
74 #include "mozilla/TouchEvents.h"
76 using namespace mozilla
;
77 using namespace mozilla::dom
;
78 using namespace mozilla::gfx
;
82 #define DEBUG_SPRING_SIZE 8
83 #define DEBUG_BORDER_SIZE 2
89 //#define DO_NOISY_REFLOW
93 bool nsBoxFrame::gDebug
= false;
94 nsIFrame
* nsBoxFrame::mDebugChild
= nullptr;
98 NS_NewBoxFrame(nsIPresShell
* aPresShell
, nsStyleContext
* aContext
, bool aIsRoot
, nsBoxLayout
* aLayoutManager
)
100 return new (aPresShell
) nsBoxFrame(aContext
, aIsRoot
, aLayoutManager
);
104 NS_NewBoxFrame(nsIPresShell
* aPresShell
, nsStyleContext
* aContext
)
106 return new (aPresShell
) nsBoxFrame(aContext
);
109 NS_IMPL_FRAMEARENA_HELPERS(nsBoxFrame
)
112 NS_QUERYFRAME_HEAD(nsBoxFrame
)
113 NS_QUERYFRAME_ENTRY(nsBoxFrame
)
114 NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame
)
117 nsBoxFrame::nsBoxFrame(nsStyleContext
* aContext
,
119 nsBoxLayout
* aLayoutManager
) :
120 nsContainerFrame(aContext
)
122 mState
|= NS_STATE_IS_HORIZONTAL
;
123 mState
|= NS_STATE_AUTO_STRETCH
;
126 mState
|= NS_STATE_IS_ROOT
;
128 mValign
= vAlign_Top
;
129 mHalign
= hAlign_Left
;
131 // if no layout manager specified us the static sprocket layout
132 nsCOMPtr
<nsBoxLayout
> layout
= aLayoutManager
;
134 if (layout
== nullptr) {
135 NS_NewSprocketLayout(PresContext()->PresShell(), layout
);
138 SetLayoutManager(layout
);
141 nsBoxFrame::~nsBoxFrame()
146 nsBoxFrame::SetInitialChildList(ChildListID aListID
,
147 nsFrameList
& aChildList
)
149 nsContainerFrame::SetInitialChildList(aListID
, aChildList
);
150 // initialize our list of infos.
151 nsBoxLayoutState
state(PresContext());
154 mLayoutManager
->ChildrenSet(this, state
, mFrames
.FirstChild());
158 nsBoxFrame::DidSetStyleContext(nsStyleContext
* aOldStyleContext
)
160 nsContainerFrame::DidSetStyleContext(aOldStyleContext
);
162 // The values that CacheAttributes() computes depend on our style,
163 // so we need to recompute them here...
168 * Initialize us. This is a good time to get the alignment of the box
171 nsBoxFrame::Init(nsIContent
* aContent
,
172 nsContainerFrame
* aParent
,
173 nsIFrame
* aPrevInFlow
)
175 nsContainerFrame::Init(aContent
, aParent
, aPrevInFlow
);
177 if (GetStateBits() & NS_FRAME_FONT_INFLATION_CONTAINER
) {
178 AddStateBits(NS_FRAME_FONT_INFLATION_FLOW_ROOT
);
181 MarkIntrinsicISizesDirty();
186 // if we are root and this
187 if (mState
& NS_STATE_IS_ROOT
)
188 GetDebugPref(GetPresContext());
191 UpdateMouseThrough();
193 // register access key
194 RegUnregAccessKey(true);
197 void nsBoxFrame::UpdateMouseThrough()
200 static nsIContent::AttrValuesArray strings
[] =
201 {&nsGkAtoms::never
, &nsGkAtoms::always
, nullptr};
202 switch (mContent
->FindAttrValueIn(kNameSpaceID_None
,
203 nsGkAtoms::mousethrough
, strings
, eCaseMatters
)) {
204 case 0: AddStateBits(NS_FRAME_MOUSE_THROUGH_NEVER
); break;
205 case 1: AddStateBits(NS_FRAME_MOUSE_THROUGH_ALWAYS
); break;
207 RemoveStateBits(NS_FRAME_MOUSE_THROUGH_ALWAYS
);
208 RemoveStateBits(NS_FRAME_MOUSE_THROUGH_NEVER
);
216 nsBoxFrame::CacheAttributes()
224 mValign
= vAlign_Top
;
225 mHalign
= hAlign_Left
;
228 GetInitialOrientation(orient
);
230 mState
|= NS_STATE_IS_HORIZONTAL
;
232 mState
&= ~NS_STATE_IS_HORIZONTAL
;
235 GetInitialDirection(normal
);
237 mState
|= NS_STATE_IS_DIRECTION_NORMAL
;
239 mState
&= ~NS_STATE_IS_DIRECTION_NORMAL
;
241 GetInitialVAlignment(mValign
);
242 GetInitialHAlignment(mHalign
);
244 bool equalSize
= false;
245 GetInitialEqualSize(equalSize
);
247 mState
|= NS_STATE_EQUAL_SIZE
;
249 mState
&= ~NS_STATE_EQUAL_SIZE
;
251 bool autostretch
= !!(mState
& NS_STATE_AUTO_STRETCH
);
252 GetInitialAutoStretch(autostretch
);
254 mState
|= NS_STATE_AUTO_STRETCH
;
256 mState
&= ~NS_STATE_AUTO_STRETCH
;
260 bool debug
= mState
& NS_STATE_SET_TO_DEBUG
;
261 bool debugSet
= GetInitialDebug(debug
);
263 mState
|= NS_STATE_DEBUG_WAS_SET
;
265 mState
|= NS_STATE_SET_TO_DEBUG
;
267 mState
&= ~NS_STATE_SET_TO_DEBUG
;
269 mState
&= ~NS_STATE_DEBUG_WAS_SET
;
276 nsBoxFrame::GetInitialDebug(bool& aDebug
)
281 static nsIContent::AttrValuesArray strings
[] =
282 {&nsGkAtoms::_false
, &nsGkAtoms::_true
, nullptr};
283 int32_t index
= GetContent()->FindAttrValueIn(kNameSpaceID_None
,
284 nsGkAtoms::debug
, strings
, eCaseMatters
);
295 nsBoxFrame::GetInitialHAlignment(nsBoxFrame::Halignment
& aHalign
)
300 // XXXdwh Everything inside this if statement is deprecated code.
301 static nsIContent::AttrValuesArray alignStrings
[] =
302 {&nsGkAtoms::left
, &nsGkAtoms::right
, nullptr};
303 static const Halignment alignValues
[] = {hAlign_Left
, hAlign_Right
};
304 int32_t index
= GetContent()->FindAttrValueIn(kNameSpaceID_None
, nsGkAtoms::align
,
305 alignStrings
, eCaseMatters
);
307 aHalign
= alignValues
[index
];
311 // Now that the deprecated stuff is out of the way, we move on to check the appropriate
312 // attribute. For horizontal boxes, we are checking the PACK attribute. For vertical boxes
313 // we are checking the ALIGN attribute.
314 nsIAtom
* attrName
= IsHorizontal() ? nsGkAtoms::pack
: nsGkAtoms::align
;
315 static nsIContent::AttrValuesArray strings
[] =
316 {&nsGkAtoms::_empty
, &nsGkAtoms::start
, &nsGkAtoms::center
, &nsGkAtoms::end
, nullptr};
317 static const Halignment values
[] =
318 {hAlign_Left
/*not used*/, hAlign_Left
, hAlign_Center
, hAlign_Right
};
319 index
= GetContent()->FindAttrValueIn(kNameSpaceID_None
, attrName
,
320 strings
, eCaseMatters
);
322 if (index
== nsIContent::ATTR_VALUE_NO_MATCH
) {
323 // The attr was present but had a nonsensical value. Revert to the default.
327 aHalign
= values
[index
];
331 // Now that we've checked for the attribute it's time to check CSS. For
332 // horizontal boxes we're checking PACK. For vertical boxes we are checking
334 const nsStyleXUL
* boxInfo
= StyleXUL();
335 if (IsHorizontal()) {
336 switch (boxInfo
->mBoxPack
) {
337 case NS_STYLE_BOX_PACK_START
:
338 aHalign
= nsBoxFrame::hAlign_Left
;
340 case NS_STYLE_BOX_PACK_CENTER
:
341 aHalign
= nsBoxFrame::hAlign_Center
;
343 case NS_STYLE_BOX_PACK_END
:
344 aHalign
= nsBoxFrame::hAlign_Right
;
346 default: // Nonsensical value. Just bail.
351 switch (boxInfo
->mBoxAlign
) {
352 case NS_STYLE_BOX_ALIGN_START
:
353 aHalign
= nsBoxFrame::hAlign_Left
;
355 case NS_STYLE_BOX_ALIGN_CENTER
:
356 aHalign
= nsBoxFrame::hAlign_Center
;
358 case NS_STYLE_BOX_ALIGN_END
:
359 aHalign
= nsBoxFrame::hAlign_Right
;
361 default: // Nonsensical value. Just bail.
370 nsBoxFrame::GetInitialVAlignment(nsBoxFrame::Valignment
& aValign
)
375 static nsIContent::AttrValuesArray valignStrings
[] =
376 {&nsGkAtoms::top
, &nsGkAtoms::baseline
, &nsGkAtoms::middle
, &nsGkAtoms::bottom
, nullptr};
377 static const Valignment valignValues
[] =
378 {vAlign_Top
, vAlign_BaseLine
, vAlign_Middle
, vAlign_Bottom
};
379 int32_t index
= GetContent()->FindAttrValueIn(kNameSpaceID_None
, nsGkAtoms::valign
,
380 valignStrings
, eCaseMatters
);
382 aValign
= valignValues
[index
];
386 // Now that the deprecated stuff is out of the way, we move on to check the appropriate
387 // attribute. For horizontal boxes, we are checking the ALIGN attribute. For vertical boxes
388 // we are checking the PACK attribute.
389 nsIAtom
* attrName
= IsHorizontal() ? nsGkAtoms::align
: nsGkAtoms::pack
;
390 static nsIContent::AttrValuesArray strings
[] =
391 {&nsGkAtoms::_empty
, &nsGkAtoms::start
, &nsGkAtoms::center
,
392 &nsGkAtoms::baseline
, &nsGkAtoms::end
, nullptr};
393 static const Valignment values
[] =
394 {vAlign_Top
/*not used*/, vAlign_Top
, vAlign_Middle
, vAlign_BaseLine
, vAlign_Bottom
};
395 index
= GetContent()->FindAttrValueIn(kNameSpaceID_None
, attrName
,
396 strings
, eCaseMatters
);
397 if (index
== nsIContent::ATTR_VALUE_NO_MATCH
) {
398 // The attr was present but had a nonsensical value. Revert to the default.
402 aValign
= values
[index
];
406 // Now that we've checked for the attribute it's time to check CSS. For
407 // horizontal boxes we're checking ALIGN. For vertical boxes we are checking
409 const nsStyleXUL
* boxInfo
= StyleXUL();
410 if (IsHorizontal()) {
411 switch (boxInfo
->mBoxAlign
) {
412 case NS_STYLE_BOX_ALIGN_START
:
413 aValign
= nsBoxFrame::vAlign_Top
;
415 case NS_STYLE_BOX_ALIGN_CENTER
:
416 aValign
= nsBoxFrame::vAlign_Middle
;
418 case NS_STYLE_BOX_ALIGN_BASELINE
:
419 aValign
= nsBoxFrame::vAlign_BaseLine
;
421 case NS_STYLE_BOX_ALIGN_END
:
422 aValign
= nsBoxFrame::vAlign_Bottom
;
424 default: // Nonsensical value. Just bail.
429 switch (boxInfo
->mBoxPack
) {
430 case NS_STYLE_BOX_PACK_START
:
431 aValign
= nsBoxFrame::vAlign_Top
;
433 case NS_STYLE_BOX_PACK_CENTER
:
434 aValign
= nsBoxFrame::vAlign_Middle
;
436 case NS_STYLE_BOX_PACK_END
:
437 aValign
= nsBoxFrame::vAlign_Bottom
;
439 default: // Nonsensical value. Just bail.
448 nsBoxFrame::GetInitialOrientation(bool& aIsHorizontal
)
450 // see if we are a vertical or horizontal box.
454 // Check the style system first.
455 const nsStyleXUL
* boxInfo
= StyleXUL();
456 if (boxInfo
->mBoxOrient
== NS_STYLE_BOX_ORIENT_HORIZONTAL
)
457 aIsHorizontal
= true;
459 aIsHorizontal
= false;
461 // Now see if we have an attribute. The attribute overrides
462 // the style system value.
463 static nsIContent::AttrValuesArray strings
[] =
464 {&nsGkAtoms::vertical
, &nsGkAtoms::horizontal
, nullptr};
465 int32_t index
= GetContent()->FindAttrValueIn(kNameSpaceID_None
, nsGkAtoms::orient
,
466 strings
, eCaseMatters
);
468 aIsHorizontal
= index
== 1;
473 nsBoxFrame::GetInitialDirection(bool& aIsNormal
)
478 if (IsHorizontal()) {
479 // For horizontal boxes only, we initialize our value based off the CSS 'direction' property.
480 // This means that BiDI users will end up with horizontally inverted chrome.
481 aIsNormal
= (StyleVisibility()->mDirection
== NS_STYLE_DIRECTION_LTR
); // If text runs RTL then so do we.
484 aIsNormal
= true; // Assume a normal direction in the vertical case.
486 // Now check the style system to see if we should invert aIsNormal.
487 const nsStyleXUL
* boxInfo
= StyleXUL();
488 if (boxInfo
->mBoxDirection
== NS_STYLE_BOX_DIRECTION_REVERSE
)
489 aIsNormal
= !aIsNormal
; // Invert our direction.
491 // Now see if we have an attribute. The attribute overrides
492 // the style system value.
493 if (IsHorizontal()) {
494 static nsIContent::AttrValuesArray strings
[] =
495 {&nsGkAtoms::reverse
, &nsGkAtoms::ltr
, &nsGkAtoms::rtl
, nullptr};
496 int32_t index
= GetContent()->FindAttrValueIn(kNameSpaceID_None
, nsGkAtoms::dir
,
497 strings
, eCaseMatters
);
499 bool values
[] = {!aIsNormal
, true, false};
500 aIsNormal
= values
[index
];
502 } else if (GetContent()->AttrValueIs(kNameSpaceID_None
, nsGkAtoms::dir
,
503 nsGkAtoms::reverse
, eCaseMatters
)) {
504 aIsNormal
= !aIsNormal
;
508 /* Returns true if it was set.
511 nsBoxFrame::GetInitialEqualSize(bool& aEqualSize
)
513 // see if we are a vertical or horizontal box.
517 if (GetContent()->AttrValueIs(kNameSpaceID_None
, nsGkAtoms::equalsize
,
518 nsGkAtoms::always
, eCaseMatters
)) {
526 /* Returns true if it was set.
529 nsBoxFrame::GetInitialAutoStretch(bool& aStretch
)
534 // Check the align attribute.
535 static nsIContent::AttrValuesArray strings
[] =
536 {&nsGkAtoms::_empty
, &nsGkAtoms::stretch
, nullptr};
537 int32_t index
= GetContent()->FindAttrValueIn(kNameSpaceID_None
, nsGkAtoms::align
,
538 strings
, eCaseMatters
);
539 if (index
!= nsIContent::ATTR_MISSING
&& index
!= 0) {
540 aStretch
= index
== 1;
544 // Check the CSS box-align property.
545 const nsStyleXUL
* boxInfo
= StyleXUL();
546 aStretch
= (boxInfo
->mBoxAlign
== NS_STYLE_BOX_ALIGN_STRETCH
);
552 nsBoxFrame::DidReflow(nsPresContext
* aPresContext
,
553 const nsHTMLReflowState
* aReflowState
,
554 nsDidReflowStatus aStatus
)
556 nsFrameState preserveBits
=
557 mState
& (NS_FRAME_IS_DIRTY
| NS_FRAME_HAS_DIRTY_CHILDREN
);
558 nsFrame::DidReflow(aPresContext
, aReflowState
, aStatus
);
559 mState
|= preserveBits
;
563 nsBoxFrame::HonorPrintBackgroundSettings()
565 return (!mContent
|| !mContent
->IsInNativeAnonymousSubtree()) &&
566 nsContainerFrame::HonorPrintBackgroundSettings();
569 #ifdef DO_NOISY_REFLOW
570 static int myCounter
= 0;
571 static void printSize(char * aDesc
, nscoord aSize
)
573 printf(" %s: ", aDesc
);
574 if (aSize
== NS_UNCONSTRAINEDSIZE
) {
582 /* virtual */ nscoord
583 nsBoxFrame::GetMinISize(nsRenderingContext
*aRenderingContext
)
586 DISPLAY_MIN_WIDTH(this, result
);
588 nsBoxLayoutState
state(PresContext(), aRenderingContext
);
589 nsSize minSize
= GetMinSize(state
);
591 // GetMinSize returns border-box width, and we want to return content
592 // width. Since Reflow uses the reflow state's border and padding, we
593 // actually just want to subtract what GetMinSize added, which is the
594 // result of GetBorderAndPadding.
596 GetBorderAndPadding(bp
);
598 result
= minSize
.width
- bp
.LeftRight();
599 result
= std::max(result
, 0);
604 /* virtual */ nscoord
605 nsBoxFrame::GetPrefISize(nsRenderingContext
*aRenderingContext
)
608 DISPLAY_PREF_WIDTH(this, result
);
610 nsBoxLayoutState
state(PresContext(), aRenderingContext
);
611 nsSize prefSize
= GetPrefSize(state
);
613 // GetPrefSize returns border-box width, and we want to return content
614 // width. Since Reflow uses the reflow state's border and padding, we
615 // actually just want to subtract what GetPrefSize added, which is the
616 // result of GetBorderAndPadding.
618 GetBorderAndPadding(bp
);
620 result
= prefSize
.width
- bp
.LeftRight();
621 result
= std::max(result
, 0);
627 nsBoxFrame::Reflow(nsPresContext
* aPresContext
,
628 nsHTMLReflowMetrics
& aDesiredSize
,
629 const nsHTMLReflowState
& aReflowState
,
630 nsReflowStatus
& aStatus
)
632 // If you make changes to this method, please keep nsLeafBoxFrame::Reflow
633 // in sync, if the changes are applicable there.
635 DO_GLOBAL_REFLOW_COUNT("nsBoxFrame");
636 DISPLAY_REFLOW(aPresContext
, this, aReflowState
, aDesiredSize
, aStatus
);
638 NS_ASSERTION(aReflowState
.ComputedWidth() >=0 &&
639 aReflowState
.ComputedHeight() >= 0, "Computed Size < 0");
641 #ifdef DO_NOISY_REFLOW
642 printf("\n-------------Starting BoxFrame Reflow ----------------------------\n");
643 printf("%p ** nsBF::Reflow %d ", this, myCounter
++);
645 printSize("AW", aReflowState
.AvailableWidth());
646 printSize("AH", aReflowState
.AvailableHeight());
647 printSize("CW", aReflowState
.ComputedWidth());
648 printSize("CH", aReflowState
.ComputedHeight());
654 aStatus
= NS_FRAME_COMPLETE
;
656 // create the layout state
657 nsBoxLayoutState
state(aPresContext
, aReflowState
.rendContext
,
658 &aReflowState
, aReflowState
.mReflowDepth
);
660 WritingMode wm
= aReflowState
.GetWritingMode();
661 LogicalSize
computedSize(wm
, aReflowState
.ComputedISize(),
662 aReflowState
.ComputedBSize());
664 LogicalMargin m
= aReflowState
.ComputedLogicalBorderPadding();
665 // GetBorderAndPadding(m);
667 LogicalSize
prefSize(wm
);
669 // if we are told to layout intrinsic then get our preferred size.
670 NS_ASSERTION(computedSize
.ISize(wm
) != NS_INTRINSICSIZE
,
671 "computed inline size should always be computed");
672 if (computedSize
.BSize(wm
) == NS_INTRINSICSIZE
) {
673 nsSize physicalPrefSize
= GetPrefSize(state
);
674 nsSize minSize
= GetMinSize(state
);
675 nsSize maxSize
= GetMaxSize(state
);
676 // XXXbz isn't GetPrefSize supposed to bounds-check for us?
677 physicalPrefSize
= BoundsCheck(minSize
, physicalPrefSize
, maxSize
);
678 prefSize
= LogicalSize(wm
, physicalPrefSize
);
681 // get our desiredSize
682 computedSize
.ISize(wm
) += m
.IStart(wm
) + m
.IEnd(wm
);
684 if (aReflowState
.ComputedBSize() == NS_INTRINSICSIZE
) {
685 computedSize
.BSize(wm
) = prefSize
.BSize(wm
);
686 // prefSize is border-box but min/max constraints are content-box.
687 nscoord blockDirBorderPadding
=
688 aReflowState
.ComputedLogicalBorderPadding().BStartEnd(wm
);
689 nscoord contentBSize
= computedSize
.BSize(wm
) - blockDirBorderPadding
;
690 // Note: contentHeight might be negative, but that's OK because min-height
691 // is never negative.
692 computedSize
.BSize(wm
) = aReflowState
.ApplyMinMaxHeight(contentBSize
) +
693 blockDirBorderPadding
;
695 computedSize
.BSize(wm
) += m
.BStart(wm
) + m
.BEnd(wm
);
698 nsSize physicalSize
= computedSize
.GetPhysicalSize(wm
);
699 nsRect
r(mRect
.x
, mRect
.y
, physicalSize
.width
, physicalSize
.height
);
703 // layout our children
706 // ok our child could have gotten bigger. So lets get its bounds
709 LogicalSize boxSize
= GetLogicalSize(wm
);
710 nscoord ascent
= boxSize
.BSize(wm
);
712 // getting the ascent could be a lot of work. Don't get it if
713 // we are the root. The viewport doesn't care about it.
714 if (!(mState
& NS_STATE_IS_ROOT
)) {
715 ascent
= GetBoxAscent(state
);
718 aDesiredSize
.SetSize(wm
, boxSize
);
719 aDesiredSize
.SetBlockStartAscent(ascent
);
721 aDesiredSize
.mOverflowAreas
= GetOverflowAreas();
723 #ifdef DO_NOISY_REFLOW
725 printf("%p ** nsBF(done) W:%d H:%d ", this, aDesiredSize
.Width(), aDesiredSize
.Height());
727 if (maxElementSize
) {
728 printf("MW:%d\n", *maxElementWidth
);
736 ReflowAbsoluteFrames(aPresContext
, aDesiredSize
, aReflowState
, aStatus
);
738 NS_FRAME_SET_TRUNCATION(aStatus
, aReflowState
, aDesiredSize
);
742 nsBoxFrame::GetPrefSize(nsBoxLayoutState
& aBoxLayoutState
)
744 NS_ASSERTION(aBoxLayoutState
.GetRenderingContext(),
745 "must have rendering context");
748 DISPLAY_PREF_SIZE(this, size
);
749 if (!DoesNeedRecalc(mPrefSize
)) {
754 PropagateDebug(aBoxLayoutState
);
760 // if the size was not completely redefined in CSS then ask our children
761 bool widthSet
, heightSet
;
762 if (!nsIFrame::AddCSSPrefSize(this, size
, widthSet
, heightSet
))
764 if (mLayoutManager
) {
765 nsSize layoutSize
= mLayoutManager
->GetPrefSize(this, aBoxLayoutState
);
767 size
.width
= layoutSize
.width
;
769 size
.height
= layoutSize
.height
;
772 size
= nsBox::GetPrefSize(aBoxLayoutState
);
776 nsSize minSize
= GetMinSize(aBoxLayoutState
);
777 nsSize maxSize
= GetMaxSize(aBoxLayoutState
);
778 mPrefSize
= BoundsCheck(minSize
, size
, maxSize
);
784 nsBoxFrame::GetBoxAscent(nsBoxLayoutState
& aBoxLayoutState
)
786 if (!DoesNeedRecalc(mAscent
))
790 PropagateDebug(aBoxLayoutState
);
797 mAscent
= mLayoutManager
->GetAscent(this, aBoxLayoutState
);
799 mAscent
= nsBox::GetBoxAscent(aBoxLayoutState
);
805 nsBoxFrame::GetMinSize(nsBoxLayoutState
& aBoxLayoutState
)
807 NS_ASSERTION(aBoxLayoutState
.GetRenderingContext(),
808 "must have rendering context");
811 DISPLAY_MIN_SIZE(this, size
);
812 if (!DoesNeedRecalc(mMinSize
)) {
817 PropagateDebug(aBoxLayoutState
);
823 // if the size was not completely redefined in CSS then ask our children
824 bool widthSet
, heightSet
;
825 if (!nsIFrame::AddCSSMinSize(aBoxLayoutState
, this, size
, widthSet
, heightSet
))
827 if (mLayoutManager
) {
828 nsSize layoutSize
= mLayoutManager
->GetMinSize(this, aBoxLayoutState
);
830 size
.width
= layoutSize
.width
;
832 size
.height
= layoutSize
.height
;
835 size
= nsBox::GetMinSize(aBoxLayoutState
);
845 nsBoxFrame::GetMaxSize(nsBoxLayoutState
& aBoxLayoutState
)
847 NS_ASSERTION(aBoxLayoutState
.GetRenderingContext(),
848 "must have rendering context");
850 nsSize
size(NS_INTRINSICSIZE
, NS_INTRINSICSIZE
);
851 DISPLAY_MAX_SIZE(this, size
);
852 if (!DoesNeedRecalc(mMaxSize
)) {
857 PropagateDebug(aBoxLayoutState
);
863 // if the size was not completely redefined in CSS then ask our children
864 bool widthSet
, heightSet
;
865 if (!nsIFrame::AddCSSMaxSize(this, size
, widthSet
, heightSet
))
867 if (mLayoutManager
) {
868 nsSize layoutSize
= mLayoutManager
->GetMaxSize(this, aBoxLayoutState
);
870 size
.width
= layoutSize
.width
;
872 size
.height
= layoutSize
.height
;
875 size
= nsBox::GetMaxSize(aBoxLayoutState
);
885 nsBoxFrame::GetFlex(nsBoxLayoutState
& aBoxLayoutState
)
887 if (!DoesNeedRecalc(mFlex
))
890 mFlex
= nsBox::GetFlex(aBoxLayoutState
);
896 * If subclassing please subclass this method not layout.
897 * layout will call this method.
900 nsBoxFrame::DoLayout(nsBoxLayoutState
& aState
)
902 uint32_t oldFlags
= aState
.LayoutFlags();
903 aState
.SetLayoutFlags(0);
906 if (mLayoutManager
) {
907 CoordNeedsRecalc(mAscent
);
908 rv
= mLayoutManager
->Layout(this, aState
);
911 aState
.SetLayoutFlags(oldFlags
);
913 if (HasAbsolutelyPositionedChildren()) {
914 // Set up a |reflowState| to pass into ReflowAbsoluteFrames
915 WritingMode wm
= GetWritingMode();
916 nsHTMLReflowState
reflowState(aState
.PresContext(), this,
917 aState
.GetRenderingContext(),
918 LogicalSize(wm
, GetLogicalSize().ISize(wm
),
919 NS_UNCONSTRAINEDSIZE
));
921 // Set up a |desiredSize| to pass into ReflowAbsoluteFrames
922 nsHTMLReflowMetrics
desiredSize(reflowState
);
923 desiredSize
.Width() = mRect
.width
;
924 desiredSize
.Height() = mRect
.height
;
926 // get the ascent (cribbed from ::Reflow)
927 nscoord ascent
= mRect
.height
;
929 // getting the ascent could be a lot of work. Don't get it if
930 // we are the root. The viewport doesn't care about it.
931 if (!(mState
& NS_STATE_IS_ROOT
)) {
932 ascent
= GetBoxAscent(aState
);
934 desiredSize
.SetBlockStartAscent(ascent
);
935 desiredSize
.mOverflowAreas
= GetOverflowAreas();
937 AddStateBits(NS_FRAME_IN_REFLOW
);
938 // Set up a |reflowStatus| to pass into ReflowAbsoluteFrames
939 // (just a dummy value; hopefully that's OK)
940 nsReflowStatus reflowStatus
= NS_FRAME_COMPLETE
;
941 ReflowAbsoluteFrames(aState
.PresContext(), desiredSize
,
942 reflowState
, reflowStatus
);
943 RemoveStateBits(NS_FRAME_IN_REFLOW
);
950 nsBoxFrame::DestroyFrom(nsIFrame
* aDestructRoot
)
952 // unregister access key
953 RegUnregAccessKey(false);
955 // clean up the container box's layout manager and child boxes
956 SetLayoutManager(nullptr);
958 nsContainerFrame::DestroyFrom(aDestructRoot
);
963 nsBoxFrame::SetDebug(nsBoxLayoutState
& aState
, bool aDebug
)
965 // see if our state matches the given debug state
966 bool debugSet
= mState
& NS_STATE_CURRENTLY_IN_DEBUG
;
967 bool debugChanged
= (!aDebug
&& debugSet
) || (aDebug
&& !debugSet
);
969 // if it doesn't then tell each child below us the new debug state
973 mState
|= NS_STATE_CURRENTLY_IN_DEBUG
;
975 mState
&= ~NS_STATE_CURRENTLY_IN_DEBUG
;
978 SetDebugOnChildList(aState
, mFirstChild
, aDebug
);
980 MarkIntrinsicISizesDirty();
988 nsBoxFrame::MarkIntrinsicISizesDirty()
990 SizeNeedsRecalc(mPrefSize
);
991 SizeNeedsRecalc(mMinSize
);
992 SizeNeedsRecalc(mMaxSize
);
993 CoordNeedsRecalc(mFlex
);
994 CoordNeedsRecalc(mAscent
);
996 if (mLayoutManager
) {
997 nsBoxLayoutState
state(PresContext());
998 mLayoutManager
->IntrinsicISizesDirty(this, state
);
1001 // Don't call base class method, since everything it does is within an
1002 // IsBoxWrapped check.
1006 nsBoxFrame::RemoveFrame(ChildListID aListID
,
1007 nsIFrame
* aOldFrame
)
1009 NS_PRECONDITION(aListID
== kPrincipalList
, "We don't support out-of-flow kids");
1010 nsPresContext
* presContext
= PresContext();
1011 nsBoxLayoutState
state(presContext
);
1013 // remove the child frame
1014 mFrames
.RemoveFrame(aOldFrame
);
1016 // notify the layout manager
1018 mLayoutManager
->ChildrenRemoved(this, state
, aOldFrame
);
1020 // destroy the child frame
1021 aOldFrame
->Destroy();
1023 // mark us dirty and generate a reflow command
1024 PresContext()->PresShell()->
1025 FrameNeedsReflow(this, nsIPresShell::eTreeChange
,
1026 NS_FRAME_HAS_DIRTY_CHILDREN
);
1030 nsBoxFrame::InsertFrames(ChildListID aListID
,
1031 nsIFrame
* aPrevFrame
,
1032 nsFrameList
& aFrameList
)
1034 NS_ASSERTION(!aPrevFrame
|| aPrevFrame
->GetParent() == this,
1035 "inserting after sibling frame with different parent");
1036 NS_ASSERTION(!aPrevFrame
|| mFrames
.ContainsFrame(aPrevFrame
),
1037 "inserting after sibling frame not in our child list");
1038 NS_PRECONDITION(aListID
== kPrincipalList
, "We don't support out-of-flow kids");
1039 nsBoxLayoutState
state(PresContext());
1041 // insert the child frames
1042 const nsFrameList::Slice
& newFrames
=
1043 mFrames
.InsertFrames(this, aPrevFrame
, aFrameList
);
1045 // notify the layout manager
1047 mLayoutManager
->ChildrenInserted(this, state
, aPrevFrame
, newFrames
);
1049 // Make sure to check box order _after_ notifying the layout
1050 // manager; otherwise the slice we give the layout manager will
1051 // just be bogus. If the layout manager cares about the order, we
1056 // if we are in debug make sure our children are in debug as well.
1057 if (mState
& NS_STATE_CURRENTLY_IN_DEBUG
)
1058 SetDebugOnChildList(state
, mFrames
.FirstChild(), true);
1061 PresContext()->PresShell()->
1062 FrameNeedsReflow(this, nsIPresShell::eTreeChange
,
1063 NS_FRAME_HAS_DIRTY_CHILDREN
);
1068 nsBoxFrame::AppendFrames(ChildListID aListID
,
1069 nsFrameList
& aFrameList
)
1071 NS_PRECONDITION(aListID
== kPrincipalList
, "We don't support out-of-flow kids");
1072 nsBoxLayoutState
state(PresContext());
1074 // append the new frames
1075 const nsFrameList::Slice
& newFrames
= mFrames
.AppendFrames(this, aFrameList
);
1077 // notify the layout manager
1079 mLayoutManager
->ChildrenAppended(this, state
, newFrames
);
1081 // Make sure to check box order _after_ notifying the layout
1082 // manager; otherwise the slice we give the layout manager will
1083 // just be bogus. If the layout manager cares about the order, we
1088 // if we are in debug make sure our children are in debug as well.
1089 if (mState
& NS_STATE_CURRENTLY_IN_DEBUG
)
1090 SetDebugOnChildList(state
, mFrames
.FirstChild(), true);
1093 // XXXbz why is this NS_FRAME_FIRST_REFLOW check here?
1094 if (!(GetStateBits() & NS_FRAME_FIRST_REFLOW
)) {
1095 PresContext()->PresShell()->
1096 FrameNeedsReflow(this, nsIPresShell::eTreeChange
,
1097 NS_FRAME_HAS_DIRTY_CHILDREN
);
1101 /* virtual */ nsContainerFrame
*
1102 nsBoxFrame::GetContentInsertionFrame()
1104 if (GetStateBits() & NS_STATE_BOX_WRAPS_KIDS_IN_BLOCK
)
1105 return GetFirstPrincipalChild()->GetContentInsertionFrame();
1106 return nsContainerFrame::GetContentInsertionFrame();
1110 nsBoxFrame::AttributeChanged(int32_t aNameSpaceID
,
1111 nsIAtom
* aAttribute
,
1114 nsresult rv
= nsContainerFrame::AttributeChanged(aNameSpaceID
, aAttribute
,
1117 // Ignore 'width', 'height', 'screenX', 'screenY' and 'sizemode' on a
1119 nsIAtom
*tag
= mContent
->Tag();
1120 if ((tag
== nsGkAtoms::window
||
1121 tag
== nsGkAtoms::page
||
1122 tag
== nsGkAtoms::dialog
||
1123 tag
== nsGkAtoms::wizard
) &&
1124 (nsGkAtoms::width
== aAttribute
||
1125 nsGkAtoms::height
== aAttribute
||
1126 nsGkAtoms::screenX
== aAttribute
||
1127 nsGkAtoms::screenY
== aAttribute
||
1128 nsGkAtoms::sizemode
== aAttribute
)) {
1132 if (aAttribute
== nsGkAtoms::width
||
1133 aAttribute
== nsGkAtoms::height
||
1134 aAttribute
== nsGkAtoms::align
||
1135 aAttribute
== nsGkAtoms::valign
||
1136 aAttribute
== nsGkAtoms::left
||
1137 aAttribute
== nsGkAtoms::top
||
1138 aAttribute
== nsGkAtoms::right
||
1139 aAttribute
== nsGkAtoms::bottom
||
1140 aAttribute
== nsGkAtoms::start
||
1141 aAttribute
== nsGkAtoms::end
||
1142 aAttribute
== nsGkAtoms::minwidth
||
1143 aAttribute
== nsGkAtoms::maxwidth
||
1144 aAttribute
== nsGkAtoms::minheight
||
1145 aAttribute
== nsGkAtoms::maxheight
||
1146 aAttribute
== nsGkAtoms::flex
||
1147 aAttribute
== nsGkAtoms::orient
||
1148 aAttribute
== nsGkAtoms::pack
||
1149 aAttribute
== nsGkAtoms::dir
||
1150 aAttribute
== nsGkAtoms::mousethrough
||
1151 aAttribute
== nsGkAtoms::equalsize
) {
1153 if (aAttribute
== nsGkAtoms::align
||
1154 aAttribute
== nsGkAtoms::valign
||
1155 aAttribute
== nsGkAtoms::orient
||
1156 aAttribute
== nsGkAtoms::pack
||
1158 aAttribute
== nsGkAtoms::debug
||
1160 aAttribute
== nsGkAtoms::dir
) {
1162 mValign
= nsBoxFrame::vAlign_Top
;
1163 mHalign
= nsBoxFrame::hAlign_Left
;
1166 GetInitialOrientation(orient
);
1168 mState
|= NS_STATE_IS_HORIZONTAL
;
1170 mState
&= ~NS_STATE_IS_HORIZONTAL
;
1173 GetInitialDirection(normal
);
1175 mState
|= NS_STATE_IS_DIRECTION_NORMAL
;
1177 mState
&= ~NS_STATE_IS_DIRECTION_NORMAL
;
1179 GetInitialVAlignment(mValign
);
1180 GetInitialHAlignment(mHalign
);
1182 bool equalSize
= false;
1183 GetInitialEqualSize(equalSize
);
1185 mState
|= NS_STATE_EQUAL_SIZE
;
1187 mState
&= ~NS_STATE_EQUAL_SIZE
;
1190 bool debug
= mState
& NS_STATE_SET_TO_DEBUG
;
1191 bool debugSet
= GetInitialDebug(debug
);
1193 mState
|= NS_STATE_DEBUG_WAS_SET
;
1196 mState
|= NS_STATE_SET_TO_DEBUG
;
1198 mState
&= ~NS_STATE_SET_TO_DEBUG
;
1200 mState
&= ~NS_STATE_DEBUG_WAS_SET
;
1204 bool autostretch
= !!(mState
& NS_STATE_AUTO_STRETCH
);
1205 GetInitialAutoStretch(autostretch
);
1207 mState
|= NS_STATE_AUTO_STRETCH
;
1209 mState
&= ~NS_STATE_AUTO_STRETCH
;
1211 else if (aAttribute
== nsGkAtoms::left
||
1212 aAttribute
== nsGkAtoms::top
||
1213 aAttribute
== nsGkAtoms::right
||
1214 aAttribute
== nsGkAtoms::bottom
||
1215 aAttribute
== nsGkAtoms::start
||
1216 aAttribute
== nsGkAtoms::end
) {
1217 mState
&= ~NS_STATE_STACK_NOT_POSITIONED
;
1219 else if (aAttribute
== nsGkAtoms::mousethrough
) {
1220 UpdateMouseThrough();
1223 PresContext()->PresShell()->
1224 FrameNeedsReflow(this, nsIPresShell::eStyleChange
, NS_FRAME_IS_DIRTY
);
1226 else if (aAttribute
== nsGkAtoms::ordinal
) {
1227 nsBoxLayoutState
state(PresContext());
1228 nsIFrame
* parent
= GetParentBox(this);
1229 // If our parent is not a box, there's not much we can do... but in that
1230 // case our ordinal doesn't matter anyway, so that's ok.
1231 // Also don't bother with popup frames since they are kept on the
1232 // kPopupList and RelayoutChildAtOrdinal() only handles
1233 // principal children.
1234 if (parent
&& !(GetStateBits() & NS_FRAME_OUT_OF_FLOW
) &&
1235 StyleDisplay()->mDisplay
!= NS_STYLE_DISPLAY_POPUP
) {
1236 parent
->RelayoutChildAtOrdinal(state
, this);
1237 // XXXldb Should this instead be a tree change on the child or parent?
1238 PresContext()->PresShell()->
1239 FrameNeedsReflow(parent
, nsIPresShell::eStyleChange
,
1243 // If the accesskey changed, register for the new value
1244 // The old value has been unregistered in nsXULElement::SetAttr
1245 else if (aAttribute
== nsGkAtoms::accesskey
) {
1246 RegUnregAccessKey(true);
1248 else if (aAttribute
== nsGkAtoms::rows
&&
1249 tag
== nsGkAtoms::tree
) {
1250 // Reflow ourselves and all our children if "rows" changes, since
1251 // nsTreeBodyFrame's layout reads this from its parent (this frame).
1252 PresContext()->PresShell()->
1253 FrameNeedsReflow(this, nsIPresShell::eStyleChange
, NS_FRAME_IS_DIRTY
);
1261 nsBoxFrame::GetDebugPref(nsPresContext
* aPresContext
)
1263 gDebug
= Preferences::GetBool("xul.debug.box");
1266 class nsDisplayXULDebug
: public nsDisplayItem
{
1268 nsDisplayXULDebug(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
) :
1269 nsDisplayItem(aBuilder
, aFrame
) {
1270 MOZ_COUNT_CTOR(nsDisplayXULDebug
);
1272 #ifdef NS_BUILD_REFCNT_LOGGING
1273 virtual ~nsDisplayXULDebug() {
1274 MOZ_COUNT_DTOR(nsDisplayXULDebug
);
1278 virtual void HitTest(nsDisplayListBuilder
* aBuilder
, nsRect aRect
,
1279 HitTestState
* aState
, nsTArray
<nsIFrame
*> *aOutFrames
) {
1280 nsPoint
rectCenter(aRect
.x
+ aRect
.width
/ 2, aRect
.y
+ aRect
.height
/ 2);
1281 static_cast<nsBoxFrame
*>(mFrame
)->
1282 DisplayDebugInfoFor(this, rectCenter
- ToReferenceFrame());
1283 aOutFrames
->AppendElement(this);
1285 virtual void Paint(nsDisplayListBuilder
* aBuilder
1286 nsRenderingContext
* aCtx
);
1287 NS_DISPLAY_DECL_NAME("XULDebug", TYPE_XUL_DEBUG
)
1291 nsDisplayXULDebug::Paint(nsDisplayListBuilder
* aBuilder
,
1292 nsRenderingContext
* aCtx
)
1294 static_cast<nsBoxFrame
*>(mFrame
)->
1295 PaintXULDebugOverlay(*aCtx
->GetDrawTarget(), ToReferenceFrame());
1299 PaintXULDebugBackground(nsIFrame
* aFrame
, nsRenderingContext
* aCtx
,
1300 const nsRect
& aDirtyRect
, nsPoint aPt
)
1302 static_cast<nsBoxFrame
*>(aFrame
)->PaintXULDebugBackground(*aCtx
, aPt
);
1307 nsBoxFrame::BuildDisplayList(nsDisplayListBuilder
* aBuilder
,
1308 const nsRect
& aDirtyRect
,
1309 const nsDisplayListSet
& aLists
)
1311 bool forceLayer
= false;
1313 mozilla::layers::FrameMetrics::ViewID scrollTargetId
=
1314 mozilla::layers::FrameMetrics::NULL_SCROLL_ID
;
1316 if (GetContent()->IsXUL()) {
1317 // forcelayer is only supported on XUL elements with box layout
1318 if (GetContent()->HasAttr(kNameSpaceID_None
, nsGkAtoms::layer
)) {
1321 nsIFrame
* parent
= GetParentBox(this);
1322 if (parent
&& parent
->GetType() == nsGkAtoms::sliderFrame
) {
1323 aBuilder
->GetScrollbarInfo(&scrollTargetId
, &flags
);
1324 forceLayer
= (scrollTargetId
!= layers::FrameMetrics::NULL_SCROLL_ID
);
1325 nsLayoutUtils::SetScrollbarThumbLayerization(this, forceLayer
);
1328 // Check for frames that are marked as a part of the region used
1329 // in calculating glass margins on Windows.
1330 const nsStyleDisplay
* styles
= StyleDisplay();
1331 if (styles
&& styles
->mAppearance
== NS_THEME_WIN_EXCLUDE_GLASS
) {
1332 aBuilder
->AddWindowExcludeGlassRegion(
1333 nsRect(aBuilder
->ToReferenceFrame(this), GetSize()));
1336 aBuilder
->AdjustWindowDraggingRegion(this);
1339 nsDisplayListCollection tempLists
;
1340 const nsDisplayListSet
& destination
= forceLayer
? tempLists
: aLists
;
1342 DisplayBorderBackgroundOutline(aBuilder
, destination
);
1345 if (mState
& NS_STATE_CURRENTLY_IN_DEBUG
) {
1346 destination
.BorderBackground()->AppendNewToTop(new (aBuilder
)
1347 nsDisplayGeneric(aBuilder
, this, PaintXULDebugBackground
,
1348 "XULDebugBackground"));
1349 destination
.Outlines()->AppendNewToTop(new (aBuilder
)
1350 nsDisplayXULDebug(aBuilder
, this));
1354 BuildDisplayListForChildren(aBuilder
, aDirtyRect
, destination
);
1356 // see if we have to draw a selection frame around this container
1357 DisplaySelectionOverlay(aBuilder
, destination
.Content());
1360 // This is a bit of a hack. Collect up all descendant display items
1361 // and merge them into a single Content() list. This can cause us
1362 // to violate CSS stacking order, but forceLayer is a magic
1363 // XUL-only extension anyway.
1364 nsDisplayList masterList
;
1365 masterList
.AppendToTop(tempLists
.BorderBackground());
1366 masterList
.AppendToTop(tempLists
.BlockBorderBackgrounds());
1367 masterList
.AppendToTop(tempLists
.Floats());
1368 masterList
.AppendToTop(tempLists
.Content());
1369 masterList
.AppendToTop(tempLists
.PositionedDescendants());
1370 masterList
.AppendToTop(tempLists
.Outlines());
1372 // Wrap the list to make it its own layer
1373 aLists
.Content()->AppendNewToTop(new (aBuilder
)
1374 nsDisplayOwnLayer(aBuilder
, this, &masterList
, flags
, scrollTargetId
));
1379 nsBoxFrame::BuildDisplayListForChildren(nsDisplayListBuilder
* aBuilder
,
1380 const nsRect
& aDirtyRect
,
1381 const nsDisplayListSet
& aLists
)
1383 nsIFrame
* kid
= mFrames
.FirstChild();
1384 // Put each child's background onto the BlockBorderBackgrounds list
1385 // to emulate the existing two-layer XUL painting scheme.
1386 nsDisplayListSet
set(aLists
, aLists
.BlockBorderBackgrounds());
1387 // The children should be in the right order
1389 BuildDisplayListForChild(aBuilder
, kid
, aDirtyRect
, set
);
1390 kid
= kid
->GetNextSibling();
1394 // REVIEW: PaintChildren did a few things none of which are a big deal
1396 // * Paint some debugging rects for this frame.
1397 // This is done by nsDisplayXULDebugBackground, which goes in the
1398 // BorderBackground() layer so it isn't clipped by OVERFLOW_CLIP.
1399 // * Apply OVERFLOW_CLIP to the children.
1400 // This is now in nsFrame::BuildDisplayListForStackingContext/Child.
1401 // * Actually paint the children.
1402 // Moved to BuildDisplayList.
1403 // * Paint per-kid debug information.
1404 // This is done by nsDisplayXULDebug, which is in the Outlines()
1405 // layer so it goes on top. This means it is not clipped by OVERFLOW_CLIP,
1406 // whereas it did used to respect OVERFLOW_CLIP, but too bad.
1409 nsBoxFrame::PaintXULDebugBackground(nsRenderingContext
& aRenderingContext
,
1415 nsMargin debugBorder
;
1416 nsMargin debugMargin
;
1417 nsMargin debugPadding
;
1419 bool isHorizontal
= IsHorizontal();
1421 GetDebugBorder(debugBorder
);
1422 PixelMarginToTwips(GetPresContext(), debugBorder
);
1424 GetDebugMargin(debugMargin
);
1425 PixelMarginToTwips(GetPresContext(), debugMargin
);
1427 GetDebugPadding(debugPadding
);
1428 PixelMarginToTwips(GetPresContext(), debugPadding
);
1430 nsRect
inner(mRect
);
1432 inner
.Deflate(debugMargin
);
1433 inner
.Deflate(border
);
1434 //nsRect borderRect(inner);
1436 int32_t appUnitsPerDevPixel
= PresContext()->AppUnitsPerDevPixel();
1438 ColorPattern
color(ToDeviceColor(isHorizontal
? Color(0.f
, 0.f
, 1.f
, 1.f
) :
1439 Color(1.f
, 0.f
, 0.f
, 1.f
));
1441 DrawTarget
* drawTarget
= aRenderingContext
.GetDrawTarget();
1445 r
.width
= debugBorder
.left
;
1446 drawTarget
->FillRect(NSRectToRect(r
, appUnitsPerDevPixel
), color
);
1450 r
.height
= debugBorder
.top
;
1451 drawTarget
->FillRect(NSRectToRect(r
, appUnitsPerDevPixel
), color
);
1455 r
.x
= r
.x
+ r
.width
- debugBorder
.right
;
1456 r
.width
= debugBorder
.right
;
1457 drawTarget
->FillRect(NSRectToRect(r
, appUnitsPerDevPixel
), color
);
1461 r
.y
= r
.y
+ r
.height
- debugBorder
.bottom
;
1462 r
.height
= debugBorder
.bottom
;
1463 drawTarget
->FillRect(NSRectToRect(r
, appUnitsPerDevPixel
), color
);
1465 // if we have dirty children or we are dirty
1466 // place a green border around us.
1467 if (NS_SUBTREE_DIRTY(this)) {
1468 nsRect
dirty(inner
);
1469 ColorPattern
green(ToDeviceColor(Color0
.f
, 1.f
, 0.f
, 1.f
)));
1470 drawTarget
->StrokeRect(NSRectToRect(dirty
, appUnitsPerDevPixel
), green
);
1475 nsBoxFrame::PaintXULDebugOverlay(DrawTarget
& aDrawTarget
, nsPoint aPt
)
1479 nsMargin debugMargin
;
1480 GetDebugMargin(debugMargin
);
1481 PixelMarginToTwips(GetPresContext(), debugMargin
);
1483 nsRect
inner(mRect
);
1485 inner
.Deflate(debugMargin
);
1486 inner
.Deflate(border
);
1488 nscoord onePixel
= GetPresContext()->IntScaledPixelsToTwips(1);
1490 kid
= nsBox::GetChildBox(this);
1491 while (nullptr != kid
) {
1492 bool isHorizontal
= IsHorizontal();
1494 nscoord x
, y
, borderSize
, spacerSize
;
1496 nsRect
cr(kid
->mRect
);
1498 kid
->GetMargin(margin
);
1505 y
= cr
.y
+ onePixel
;
1506 spacerSize
= debugBorder
.top
- onePixel
*4;
1510 y
= cr
.x
+ onePixel
;
1511 spacerSize
= debugBorder
.left
- onePixel
*4;
1514 nsBoxLayoutState
state(GetPresContext());
1515 nscoord flex
= kid
->GetFlex(state
);
1517 if (!kid
->IsCollapsed()) {
1519 borderSize
= cr
.width
;
1521 borderSize
= cr
.height
;
1523 DrawSpacer(GetPresContext(), aDrawTarget
, isHorizontal
, flex
, x
, y
, borderSize
, spacerSize
);
1526 kid
= GetNextBox(kid
);
1533 nsBoxFrame::GetBoxName(nsAutoString
& aName
)
1535 GetFrameName(aName
);
1539 #ifdef DEBUG_FRAME_DUMP
1541 nsBoxFrame::GetFrameName(nsAString
& aResult
) const
1543 return MakeFrameName(NS_LITERAL_STRING("Box"), aResult
);
1548 nsBoxFrame::GetType() const
1550 return nsGkAtoms::boxFrame
;
1555 nsBoxFrame::GetDebug(bool& aDebug
)
1557 aDebug
= (mState
& NS_STATE_CURRENTLY_IN_DEBUG
);
1562 // REVIEW: nsBoxFrame::GetFrameForPoint is a problem because of 'mousethrough'
1563 // attribute support. Here's how it works:
1564 // * For each child frame F, we determine the target frame T(F) by recursively
1565 // invoking GetFrameForPoint on the child
1566 // * Let F' be the last child frame such that T(F') doesn't have mousethrough.
1567 // If F' exists, return T(F')
1568 // * Otherwise let F'' be the first child frame such that T(F'') is non-null.
1569 // If F'' exists, return T(F'')
1570 // * Otherwise return this frame, if this frame contains the point
1571 // * Otherwise return null
1572 // It's not clear how this should work for more complex z-ordering situations.
1573 // The basic principle seems to be that if a frame F has a descendant
1574 // 'mousethrough' frame that includes the target position, then F
1575 // will not receive events (unless it overrides GetFrameForPoint).
1576 // A 'mousethrough' frame will only receive an event if, after applying that rule,
1577 // all eligible frames are 'mousethrough'; the bottom-most inner-most 'mousethrough'
1578 // frame is then chosen (the first eligible frame reached in a
1579 // traversal of the frame tree --- pre/post is irrelevant since ancestors
1580 // of the mousethrough frames can't be eligible).
1581 // IMHO this is very bogus and adds a great deal of complexity for something
1582 // that is very rarely used. So I'm redefining 'mousethrough' to the following:
1583 // a frame with mousethrough is transparent to mouse events. This is compatible
1584 // with the way 'mousethrough' is used in Seamonkey's navigator.xul and
1585 // Firefox's browser.xul. The only other place it's used is in the 'expander'
1586 // XBL binding, which in our tree is only used by Thunderbird SMIME Advanced
1587 // Preferences, and I can't figure out what that does, so I'll have to test it.
1588 // If it's broken I'll probably just change the binding to use it more sensibly.
1589 // This new behaviour is implemented in nsDisplayList::HitTest.
1590 // REVIEW: This debug-box stuff is annoying. I'm just going to put debug boxes
1591 // in the outline layer and avoid GetDebugBoxAt.
1593 // REVIEW: GetCursor had debug-only event dumping code. I have replaced it
1594 // with instrumentation in nsDisplayXULDebug.
1598 nsBoxFrame::DrawLine(DrawTarget
& aDrawTarget
, bool aHorizontal
, nscoord x1
, nscoord y1
, nscoord x2
, nscoord y2
)
1606 ColorPattern
white(ToDeviceColor(Color(1.f
, 1.f
, 1.f
, 1.f
)));
1607 StrokeLineWithSnapping(p1
, p2
, PresContext()->AppUnitsPerDevPixel(),
1608 aDrawTarget
, color
);
1612 nsBoxFrame::FillRect(DrawTarget
& aDrawTarget
, bool aHorizontal
, nscoord x
, nscoord y
, nscoord width
, nscoord height
)
1614 Rect rect
= NSRectToSnappedRect(aHorizontal
? nsRect(x
, y
, width
, height
) :
1615 nsRect(y
, x
, height
, width
),
1616 PresContext()->AppUnitsPerDevPixel(),
1618 ColorPattern
white(ToDeviceColor(Color(1.f
, 1.f
, 1.f
, 1.f
)));
1619 aDrawTarget
.FillRect(rect
, white
);
1623 nsBoxFrame::DrawSpacer(nsPresContext
* aPresContext
, DrawTarget
& aDrawTarget
,
1624 bool aHorizontal
, int32_t flex
, nscoord x
, nscoord y
,
1625 nscoord size
, nscoord spacerSize
)
1627 nscoord onePixel
= aPresContext
->IntScaledPixelsToTwips(1);
1629 // if we do draw the coils
1633 int coilSize
= COIL_SIZE
*onePixel
;
1634 int halfSpacer
= spacerSize
/2;
1637 center
= y
+ halfSpacer
;
1640 int coils
= distance
/coilSize
;
1642 int halfCoilSize
= coilSize
/2;
1645 DrawLine(aDrawTarget
, aHorizontal
, x
,y
+ spacerSize
/2, x
+ size
, y
+ spacerSize
/2);
1647 for (int i
=0; i
< coils
; i
++)
1649 DrawLine(aDrawTarget
, aHorizontal
, offset
, center
+halfSpacer
, offset
+halfCoilSize
, center
-halfSpacer
);
1650 DrawLine(aDrawTarget
, aHorizontal
, offset
+halfCoilSize
, center
-halfSpacer
, offset
+coilSize
, center
+halfSpacer
);
1656 FillRect(aDrawTarget
, aHorizontal
, x
+ size
- spacerSize
/2, y
, spacerSize
/2, spacerSize
);
1657 FillRect(aDrawTarget
, aHorizontal
, x
, y
, spacerSize
/2, spacerSize
);
1661 nsBoxFrame::GetDebugBorder(nsMargin
& aInset
)
1663 aInset
.SizeTo(2,2,2,2);
1672 nsBoxFrame::GetDebugMargin(nsMargin
& aInset
)
1674 aInset
.SizeTo(2,2,2,2);
1678 nsBoxFrame::GetDebugPadding(nsMargin
& aPadding
)
1680 aPadding
.SizeTo(2,2,2,2);
1684 nsBoxFrame::PixelMarginToTwips(nsPresContext
* aPresContext
, nsMargin
& aMarginPixels
)
1686 nscoord onePixel
= nsPresContext::CSSPixelsToAppUnits(1);
1687 aMarginPixels
.left
*= onePixel
;
1688 aMarginPixels
.right
*= onePixel
;
1689 aMarginPixels
.top
*= onePixel
;
1690 aMarginPixels
.bottom
*= onePixel
;
1694 nsBoxFrame::GetValue(nsPresContext
* aPresContext
, const nsSize
& a
, const nsSize
& b
, char* ch
)
1696 float p2t
= aPresContext
->ScaledPixelsToTwips();
1701 if (a
.width
== NS_INTRINSICSIZE
)
1702 sprintf(width
,"%s","INF");
1704 sprintf(width
,"%d", nscoord(a
.width
/*/p2t*/));
1706 if (a
.height
== NS_INTRINSICSIZE
)
1707 sprintf(height
,"%s","INF");
1709 sprintf(height
,"%d", nscoord(a
.height
/*/p2t*/));
1712 sprintf(ch
, "(%s%s, %s%s)", width
, (b
.width
!= NS_INTRINSICSIZE
? "[SET]" : ""),
1713 height
, (b
.height
!= NS_INTRINSICSIZE
? "[SET]" : ""));
1718 nsBoxFrame::GetValue(nsPresContext
* aPresContext
, int32_t a
, int32_t b
, char* ch
)
1720 if (a
== NS_INTRINSICSIZE
)
1721 sprintf(ch
, "%d[SET]", b
);
1723 sprintf(ch
, "%d", a
);
1727 nsBoxFrame::DisplayDebugInfoFor(nsIFrame
* aBox
,
1730 nsBoxLayoutState
state(GetPresContext());
1732 nscoord x
= aPoint
.x
;
1733 nscoord y
= aPoint
.y
;
1735 // get the area inside our border but not our debug margins.
1736 nsRect
insideBorder(aBox
->mRect
);
1737 insideBorder
.MoveTo(0,0):
1738 nsMargin
border(0,0,0,0);
1739 aBox
->GetBorderAndPadding(border
);
1740 insideBorder
.Deflate(border
);
1742 bool isHorizontal
= IsHorizontal();
1744 if (!insideBorder
.Contains(nsPoint(x
,y
)))
1745 return NS_ERROR_FAILURE
;
1747 //printf("%%%%%% inside box %%%%%%%\n");
1750 nsIFrame
* child
= nsBox::GetChildBox(aBox
);
1755 PixelMarginToTwips(aPresContext
, m
);
1758 PixelMarginToTwips(aPresContext
, m2
);
1762 if ((isHorizontal
&& y
< insideBorder
.y
+ m
.top
) ||
1763 (!isHorizontal
&& x
< insideBorder
.x
+ m
.left
)) {
1764 //printf("**** inside debug border *******\n");
1767 const nsRect
& r
= child
->mRect
;
1769 // if we are not in the child. But in the spacer above the child.
1770 if ((isHorizontal
&& x
>= r
.x
&& x
< r
.x
+ r
.width
) ||
1771 (!isHorizontal
&& y
>= r
.y
&& y
< r
.y
+ r
.height
)) {
1772 aCursor
= NS_STYLE_CURSOR_POINTER
;
1773 // found it but we already showed it.
1774 if (mDebugChild
== child
)
1777 if (aBox
->GetContent()) {
1778 printf("---------------\n");
1783 if (child
->GetContent()) {
1784 printf("child #%d: ", count
);
1785 child
->DumpBox(stdout
);
1789 mDebugChild
= child
;
1791 nsSize
prefSizeCSS(NS_INTRINSICSIZE
, NS_INTRINSICSIZE
);
1792 nsSize
minSizeCSS (NS_INTRINSICSIZE
, NS_INTRINSICSIZE
);
1793 nsSize
maxSizeCSS (NS_INTRINSICSIZE
, NS_INTRINSICSIZE
);
1794 nscoord flexCSS
= NS_INTRINSICSIZE
;
1796 bool widthSet
, heightSet
;
1797 nsIFrame::AddCSSPrefSize(child
, prefSizeCSS
, widthSet
, heightSet
);
1798 nsIFrame::AddCSSMinSize (state
, child
, minSizeCSS
, widthSet
, heightSet
);
1799 nsIFrame::AddCSSMaxSize (child
, maxSizeCSS
, widthSet
, heightSet
);
1800 nsIFrame::AddCSSFlex (state
, child
, flexCSS
);
1802 nsSize prefSize
= child
->GetPrefSize(state
);
1803 nsSize minSize
= child
->GetMinSize(state
);
1804 nsSize maxSize
= child
->GetMaxSize(state
);
1805 nscoord flexSize
= child
->GetFlex(state
);
1806 nscoord ascentSize
= child
->GetBoxAscent(state
);
1816 GetFrameSizeWithMargin(child
, actualSize
);
1817 nsSize
actualSizeCSS (NS_INTRINSICSIZE
, NS_INTRINSICSIZE
);
1819 GetValue(aPresContext
, minSize
, minSizeCSS
, min
);
1820 GetValue(aPresContext
, prefSize
, prefSizeCSS
, pref
);
1821 GetValue(aPresContext
, maxSize
, maxSizeCSS
, max
);
1822 GetValue(aPresContext
, actualSize
, actualSizeCSS
, calc
);
1823 GetValue(aPresContext
, flexSize
, flexCSS
, flex
);
1824 GetValue(aPresContext
, ascentSize
, NS_INTRINSICSIZE
, ascent
);
1827 printf("min%s, pref%s, max%s, actual%s, flex=%s, ascent=%s\n\n",
1839 child
= GetNextBox(child
);
1845 mDebugChild
= nullptr;
1851 nsBoxFrame::SetDebugOnChildList(nsBoxLayoutState
& aState
, nsIFrame
* aChild
, bool aDebug
)
1853 nsIFrame
* child
= nsBox::GetChildBox(this);
1856 child
->SetDebug(aState
, aDebug
);
1857 child
= GetNextBox(child
);
1862 nsBoxFrame::GetFrameSizeWithMargin(nsIFrame
* aBox
, nsSize
& aSize
)
1864 nsRect
rect(aBox
->GetRect());
1865 nsMargin
margin(0,0,0,0);
1866 aBox
->GetMargin(margin
);
1867 rect
.Inflate(margin
);
1868 aSize
.width
= rect
.width
;
1869 aSize
.height
= rect
.height
;
1874 // If you make changes to this function, check its counterparts
1875 // in nsTextBoxFrame and nsXULLabelFrame
1877 nsBoxFrame::RegUnregAccessKey(bool aDoReg
)
1879 MOZ_ASSERT(mContent
);
1881 // find out what type of element this is
1882 nsIAtom
*atom
= mContent
->Tag();
1884 // only support accesskeys for the following elements
1885 if (atom
!= nsGkAtoms::button
&&
1886 atom
!= nsGkAtoms::toolbarbutton
&&
1887 atom
!= nsGkAtoms::checkbox
&&
1888 atom
!= nsGkAtoms::textbox
&&
1889 atom
!= nsGkAtoms::tab
&&
1890 atom
!= nsGkAtoms::radio
) {
1894 nsAutoString accessKey
;
1895 mContent
->GetAttr(kNameSpaceID_None
, nsGkAtoms::accesskey
, accessKey
);
1897 if (accessKey
.IsEmpty())
1900 // With a valid PresContext we can get the ESM
1901 // and register the access key
1902 EventStateManager
* esm
= PresContext()->EventStateManager();
1904 uint32_t key
= accessKey
.First();
1906 esm
->RegisterAccessKey(mContent
, key
);
1908 esm
->UnregisterAccessKey(mContent
, key
);
1912 nsBoxFrame::SupportsOrdinalsInChildren()
1917 // Helper less-than-or-equal function, used in CheckBoxOrder() as a
1918 // template-parameter for the sorting functions.
1920 IsBoxOrdinalLEQ(nsIFrame
* aFrame1
,
1923 // If we've got a placeholder frame, use its out-of-flow frame's ordinal val.
1924 nsIFrame
* aRealFrame1
= nsPlaceholderFrame::GetRealFrameFor(aFrame1
);
1925 nsIFrame
* aRealFrame2
= nsPlaceholderFrame::GetRealFrameFor(aFrame2
);
1926 return aRealFrame1
->GetOrdinal() <= aRealFrame2
->GetOrdinal();
1930 nsBoxFrame::CheckBoxOrder()
1932 if (SupportsOrdinalsInChildren() &&
1933 !nsIFrame::IsFrameListSorted
<IsBoxOrdinalLEQ
>(mFrames
)) {
1934 nsIFrame::SortFrameList
<IsBoxOrdinalLEQ
>(mFrames
);
1939 nsBoxFrame::LayoutChildAt(nsBoxLayoutState
& aState
, nsIFrame
* aBox
, const nsRect
& aRect
)
1941 // get the current rect
1942 nsRect
oldRect(aBox
->GetRect());
1943 aBox
->SetBounds(aState
, aRect
);
1945 bool layout
= NS_SUBTREE_DIRTY(aBox
);
1947 if (layout
|| (oldRect
.width
!= aRect
.width
|| oldRect
.height
!= aRect
.height
)) {
1948 return aBox
->Layout(aState
);
1955 nsBoxFrame::RelayoutChildAtOrdinal(nsBoxLayoutState
& aState
, nsIFrame
* aChild
)
1957 if (!SupportsOrdinalsInChildren())
1960 uint32_t ord
= aChild
->GetOrdinal();
1962 nsIFrame
* child
= mFrames
.FirstChild();
1963 nsIFrame
* newPrevSib
= nullptr;
1966 if (ord
< child
->GetOrdinal()) {
1970 if (child
!= aChild
) {
1974 child
= GetNextBox(child
);
1977 if (aChild
->GetPrevSibling() == newPrevSib
) {
1978 // This box is not moving.
1982 // Take |aChild| out of its old position in the child list.
1983 mFrames
.RemoveFrame(aChild
);
1985 // Insert it after |newPrevSib| or at the start if it's null.
1986 mFrames
.InsertFrame(nullptr, newPrevSib
, aChild
);
1992 * This wrapper class lets us redirect mouse hits from descendant frames
1993 * of a menu to the menu itself, if they didn't specify 'allowevents'.
1995 * The wrapper simply turns a hit on a descendant element
1996 * into a hit on the menu itself, unless there is an element between the target
1997 * and the menu with the "allowevents" attribute.
1999 * This is used by nsMenuFrame and nsTreeColFrame.
2001 * Note that turning a hit on a descendant element into nullptr, so events
2002 * could fall through to the menu background, might be an appealing simplification
2003 * but it would mean slightly strange behaviour in some cases, because grabber
2004 * wrappers can be created for many individual lists and items, so the exact
2005 * fallthrough behaviour would be complex. E.g. an element with "allowevents"
2006 * on top of the Content() list could receive the event even if it was covered
2007 * by a PositionedDescenants() element without "allowevents". It is best to
2008 * never convert a non-null hit into null.
2010 // REVIEW: This is roughly of what nsMenuFrame::GetFrameForPoint used to do.
2011 // I've made 'allowevents' affect child elements because that seems the only
2012 // reasonable thing to do.
2013 class nsDisplayXULEventRedirector
: public nsDisplayWrapList
{
2015 nsDisplayXULEventRedirector(nsDisplayListBuilder
* aBuilder
,
2016 nsIFrame
* aFrame
, nsDisplayItem
* aItem
,
2017 nsIFrame
* aTargetFrame
)
2018 : nsDisplayWrapList(aBuilder
, aFrame
, aItem
), mTargetFrame(aTargetFrame
) {}
2019 nsDisplayXULEventRedirector(nsDisplayListBuilder
* aBuilder
,
2020 nsIFrame
* aFrame
, nsDisplayList
* aList
,
2021 nsIFrame
* aTargetFrame
)
2022 : nsDisplayWrapList(aBuilder
, aFrame
, aList
), mTargetFrame(aTargetFrame
) {}
2023 virtual void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
2024 HitTestState
* aState
,
2025 nsTArray
<nsIFrame
*> *aOutFrames
) MOZ_OVERRIDE
;
2026 virtual bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) MOZ_OVERRIDE
{
2029 NS_DISPLAY_DECL_NAME("XULEventRedirector", TYPE_XUL_EVENT_REDIRECTOR
)
2031 nsIFrame
* mTargetFrame
;
2034 void nsDisplayXULEventRedirector::HitTest(nsDisplayListBuilder
* aBuilder
,
2035 const nsRect
& aRect
, HitTestState
* aState
, nsTArray
<nsIFrame
*> *aOutFrames
)
2037 nsTArray
<nsIFrame
*> outFrames
;
2038 mList
.HitTest(aBuilder
, aRect
, aState
, &outFrames
);
2040 bool topMostAdded
= false;
2041 uint32_t localLength
= outFrames
.Length();
2043 for (uint32_t i
= 0; i
< localLength
; i
++) {
2045 for (nsIContent
* content
= outFrames
.ElementAt(i
)->GetContent();
2046 content
&& content
!= mTargetFrame
->GetContent();
2047 content
= content
->GetParent()) {
2048 if (content
->AttrValueIs(kNameSpaceID_None
, nsGkAtoms::allowevents
,
2049 nsGkAtoms::_true
, eCaseMatters
)) {
2050 // Events are allowed on 'frame', so let it go.
2051 aOutFrames
->AppendElement(outFrames
.ElementAt(i
));
2052 topMostAdded
= true;
2056 // If there was no hit on the topmost frame or its ancestors,
2057 // add the target frame itself as the first candidate (see bug 562554).
2058 if (!topMostAdded
) {
2059 topMostAdded
= true;
2060 aOutFrames
->AppendElement(mTargetFrame
);
2065 class nsXULEventRedirectorWrapper
: public nsDisplayWrapper
2068 explicit nsXULEventRedirectorWrapper(nsIFrame
* aTargetFrame
)
2069 : mTargetFrame(aTargetFrame
) {}
2070 virtual nsDisplayItem
* WrapList(nsDisplayListBuilder
* aBuilder
,
2072 nsDisplayList
* aList
) MOZ_OVERRIDE
{
2073 return new (aBuilder
)
2074 nsDisplayXULEventRedirector(aBuilder
, aFrame
, aList
, mTargetFrame
);
2076 virtual nsDisplayItem
* WrapItem(nsDisplayListBuilder
* aBuilder
,
2077 nsDisplayItem
* aItem
) MOZ_OVERRIDE
{
2078 return new (aBuilder
)
2079 nsDisplayXULEventRedirector(aBuilder
, aItem
->Frame(), aItem
,
2083 nsIFrame
* mTargetFrame
;
2087 nsBoxFrame::WrapListsInRedirector(nsDisplayListBuilder
* aBuilder
,
2088 const nsDisplayListSet
& aIn
,
2089 const nsDisplayListSet
& aOut
)
2091 nsXULEventRedirectorWrapper
wrapper(this);
2092 wrapper
.WrapLists(aBuilder
, this, aIn
, aOut
);
2096 nsBoxFrame::GetEventPoint(WidgetGUIEvent
* aEvent
, nsPoint
&aPoint
) {
2097 nsIntPoint refPoint
;
2098 bool res
= GetEventPoint(aEvent
, refPoint
);
2099 aPoint
= nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent
, refPoint
, this);
2104 nsBoxFrame::GetEventPoint(WidgetGUIEvent
* aEvent
, nsIntPoint
&aPoint
) {
2105 NS_ENSURE_TRUE(aEvent
, false);
2107 WidgetTouchEvent
* touchEvent
= aEvent
->AsTouchEvent();
2109 // return false if there is more than one touch on the page, or if
2110 // we can't find a touch point
2111 if (touchEvent
->touches
.Length() != 1) {
2115 dom::Touch
* touch
= touchEvent
->touches
.SafeElementAt(0);
2119 aPoint
= touch
->mRefPoint
;
2121 aPoint
= LayoutDeviceIntPoint::ToUntyped(aEvent
->refPoint
);