1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 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/. */
7 /* interface for all rendering objects */
12 #ifndef MOZILLA_INTERNAL_API
13 #error This header/class should only be used within Mozilla code. It should not be used by extensions.
16 #if (defined(XP_WIN) && !defined(HAVE_64BIT_BUILD)) || defined(ANDROID)
17 // Blink's magic depth limit from its HTML parser (513) plus as much as fits in
18 // the default run-time stack on armv7 Android on Dalvik when using display:
19 // block minus a bit just to be sure. The Dalvik default stack crashes at 588.
20 // ART can do a few frames more. Using the same number for 32-bit Windows for
21 // consistency. Over there, Blink's magic depth of 513 doesn't fit in the
22 // default stack of 1 MB, but this magic depth fits when the default is grown by
23 // mere 192 KB (tested in 64 KB increments).
25 // 32-bit Windows has a different limit compared to 64-bit desktop, because the
26 // default stack size affects all threads and consumes address space. Fixing
27 // that is bug 1257522.
29 // 32-bit Android on ARM already happens to have defaults that are close enough
30 // to what makes sense as a temporary measure on Windows, so adjusting the
31 // Android stack can be a follow-up. The stack on 64-bit ARM needs adjusting in
32 // any case before 64-bit ARM can become tier-1. See bug 1400811.
34 // Ideally, we'd get rid of this smaller limit and make 32-bit Windows and
35 // Android capable of working with the Linux/Mac/Win64 number below.
36 # define MAX_REFLOW_DEPTH 585
38 // Blink's magic depth limit from its HTML parser times two. Also just about
39 // fits within the system default runtime stack limit of 8 MB on 64-bit Mac and
40 // Linux with display: table-cell.
41 # define MAX_REFLOW_DEPTH 1026
44 /* nsIFrame is in the process of being deCOMtaminated, i.e., this file is
45 eventually going to be eliminated, and all callers will use nsFrame instead.
46 At the moment we're midway through this process, so you will see inlined
47 functions and member variables in this file. -dwh */
52 #include "CaretAssociationHint.h"
53 #include "FrameProperties.h"
54 #include "LayoutConstants.h"
55 #include "mozilla/layout/FrameChildList.h"
56 #include "mozilla/AspectRatio.h"
57 #include "mozilla/Attributes.h"
58 #include "mozilla/EventForwards.h"
59 #include "mozilla/Maybe.h"
60 #include "mozilla/RelativeTo.h"
61 #include "mozilla/Result.h"
62 #include "mozilla/SmallPointerArray.h"
63 #include "mozilla/ToString.h"
64 #include "mozilla/WritingModes.h"
65 #include "nsDirection.h"
66 #include "nsFrameList.h"
67 #include "nsFrameState.h"
68 #include "mozilla/ReflowInput.h"
69 #include "nsIContent.h"
71 #include "nsQueryFrame.h"
72 #include "mozilla/ComputedStyle.h"
73 #include "nsStyleStruct.h"
74 #include "Visibility.h"
75 #include "nsChangeHint.h"
76 #include "mozilla/ComputedStyleInlines.h"
77 #include "mozilla/EnumSet.h"
78 #include "mozilla/gfx/2D.h"
79 #include "mozilla/gfx/CompositorHitTestInfo.h"
80 #include "mozilla/gfx/MatrixFwd.h"
81 #include "nsDisplayItemTypes.h"
82 #include "nsPresContext.h"
85 # include "mozilla/a11y/AccTypes.h"
89 * New rules of reflow:
90 * 1. you get a WillReflow() followed by a Reflow() followed by a DidReflow() in
91 * order (no separate pass over the tree)
92 * 2. it's the parent frame's responsibility to size/position the child's view
93 * (not the child frame's responsibility as it is today) during reflow (and
94 * before sending the DidReflow() notification)
95 * 3. positioning of child frames (and their views) is done on the way down the
96 * tree, and sizing of child frames (and their views) on the way back up
97 * 4. if you move a frame (outside of the reflow process, or after reflowing
98 * it), then you must make sure that its view (or its child frame's views)
99 * are re-positioned as well. It's reasonable to not position the view until
100 * after all reflowing the entire line, for example, but the frame should
101 * still be positioned and sized (and the view sized) during the reflow
102 * (i.e., before sending the DidReflow() notification)
103 * 5. the view system handles moving of widgets, i.e., it's not our problem
108 class nsFrameSelection
;
110 class nsIScrollableFrame
;
111 class nsISelectionController
;
112 class nsBoxLayoutState
;
114 class nsILineIterator
;
116 class nsDisplayItemBase
;
117 class nsDisplayListBuilder
;
118 class nsDisplayListSet
;
121 class gfxSkipCharsIterator
;
123 class nsLineList_iterator
;
124 class nsAbsoluteContainingBlock
;
125 class nsContainerFrame
;
126 class nsPlaceholderFrame
;
127 class nsStyleChangeList
;
131 struct nsBoxLayoutMetrics
;
132 struct nsPeekOffsetStruct
;
133 struct CharacterDataChangeInfo
;
137 enum class PseudoStyleType
: uint8_t;
138 enum class TableSelectionMode
: uint32_t;
140 class ServoRestyleState
;
141 class DisplayItemData
;
145 class WidgetGUIEvent
;
146 class WidgetMouseEvent
;
151 } // namespace layers
154 class ScrollAnchorContainer
;
155 } // namespace layout
157 } // namespace mozilla
159 //----------------------------------------------------------------------
161 // 1 million CSS pixels less than our max app unit measure.
162 // For reflowing with an "infinite" available inline space per [css-sizing].
163 // (reflowing with an NS_UNCONSTRAINEDSIZE available inline size isn't allowed
164 // and leads to assertions)
165 #define INFINITE_ISIZE_COORD nscoord(NS_MAXSIZE - (1000000 * 60))
167 //----------------------------------------------------------------------
171 enum class LayoutFrameType
: uint8_t {
172 #define FRAME_TYPE(ty_, ...) ty_,
173 #include "mozilla/FrameTypeList.h"
177 } // namespace mozilla
179 enum nsSelectionAmount
{
180 eSelectCharacter
= 0, // a single Unicode character;
181 // do not use this (prefer Cluster) unless you
182 // are really sure it's what you want
183 eSelectCluster
= 1, // a grapheme cluster: this is usually the right
184 // choice for movement or selection by "character"
185 // as perceived by the user
187 eSelectWordNoSpace
= 3, // select a "word" without selecting the following
188 // space, no matter what the default platform
190 eSelectLine
= 4, // previous drawn line in flow.
191 // NOTE that selection code depends on the ordering of the above values,
192 // allowing simple <= tests to check categories of caret movement.
193 // Don't rearrange without checking the usage in nsSelection.cpp!
195 eSelectBeginLine
= 5,
197 eSelectNoAmount
= 7, // just bounce back current offset.
198 eSelectParagraph
= 8 // select a "paragraph"
201 //----------------------------------------------------------------------
202 // Reflow status returned by the Reflow() methods.
203 class nsReflowStatus final
{
204 using StyleClear
= mozilla::StyleClear
;
208 : mBreakType(StyleClear::None
),
209 mInlineBreak(InlineBreak::None
),
210 mCompletion(Completion::FullyComplete
),
211 mNextInFlowNeedsReflow(false),
213 mFirstLetterComplete(false) {}
215 // Reset all the member variables.
217 mBreakType
= StyleClear::None
;
218 mInlineBreak
= InlineBreak::None
;
219 mCompletion
= Completion::FullyComplete
;
220 mNextInFlowNeedsReflow
= false;
222 mFirstLetterComplete
= false;
225 // Return true if all member variables have their default values.
226 bool IsEmpty() const {
227 return (IsFullyComplete() && !IsInlineBreak() && !mNextInFlowNeedsReflow
&&
228 !mTruncated
&& !mFirstLetterComplete
);
231 // There are three possible completion statuses, represented by
234 // Incomplete means the frame does *not* map all its content, and the
235 // parent frame should create a continuing frame.
237 // OverflowIncomplete means that the frame has an overflow that is not
238 // complete, but its own box is complete. (This happens when the content
239 // overflows a fixed-height box.) The reflower should place and size the
240 // frame and continue its reflow, but it needs to create an overflow
241 // container as a continuation for this frame. See "Overflow containers"
242 // documentation in nsContainerFrame.h for more information.
244 // FullyComplete means the frame is neither Incomplete nor
245 // OverflowIncomplete. This is the default state for a nsReflowStatus.
247 enum class Completion
: uint8_t {
248 // The order of the enum values is important, which represents the
249 // precedence when merging.
255 bool IsIncomplete() const { return mCompletion
== Completion::Incomplete
; }
256 bool IsOverflowIncomplete() const {
257 return mCompletion
== Completion::OverflowIncomplete
;
259 bool IsFullyComplete() const {
260 return mCompletion
== Completion::FullyComplete
;
262 // Just for convenience; not a distinct state.
263 bool IsComplete() const { return !IsIncomplete(); }
265 void SetIncomplete() { mCompletion
= Completion::Incomplete
; }
266 void SetOverflowIncomplete() { mCompletion
= Completion::OverflowIncomplete
; }
268 // mNextInFlowNeedsReflow bit flag means that the next-in-flow is dirty,
269 // and also needs to be reflowed. This status only makes sense for a frame
270 // that is not complete, i.e. you wouldn't set mNextInFlowNeedsReflow when
271 // IsComplete() is true.
272 bool NextInFlowNeedsReflow() const { return mNextInFlowNeedsReflow
; }
273 void SetNextInFlowNeedsReflow() { mNextInFlowNeedsReflow
= true; }
275 // mTruncated bit flag means that the part of the frame before the first
276 // possible break point was unable to fit in the available space.
277 // Therefore, the entire frame should be moved to the next continuation of
278 // the parent frame. A frame that begins at the top of the page must never
279 // be truncated. Doing so would likely cause an infinite loop.
280 bool IsTruncated() const { return mTruncated
; }
281 void UpdateTruncated(const mozilla::ReflowInput
& aReflowInput
,
282 const mozilla::ReflowOutput
& aMetrics
);
284 // Merge the frame completion status bits from aStatus into this.
285 void MergeCompletionStatusFrom(const nsReflowStatus
& aStatus
) {
286 if (mCompletion
< aStatus
.mCompletion
) {
287 mCompletion
= aStatus
.mCompletion
;
290 // These asserts ensure that the mCompletion merging works as we expect.
291 // (Incomplete beats OverflowIncomplete, which beats FullyComplete.)
293 Completion::Incomplete
> Completion::OverflowIncomplete
&&
294 Completion::OverflowIncomplete
> Completion::FullyComplete
,
295 "mCompletion merging won't work without this!");
297 mNextInFlowNeedsReflow
|= aStatus
.mNextInFlowNeedsReflow
;
298 mTruncated
|= aStatus
.mTruncated
;
301 // There are three possible inline-break statuses, represented by
304 // "None" means no break is requested.
305 // "Before" means the break should occur before the frame.
306 // "After" means the break should occur after the frame.
307 // (Here, "the frame" is the frame whose reflow results are being reported by
308 // this nsReflowStatus.)
310 enum class InlineBreak
: uint8_t {
316 bool IsInlineBreak() const { return mInlineBreak
!= InlineBreak::None
; }
317 bool IsInlineBreakBefore() const {
318 return mInlineBreak
== InlineBreak::Before
;
320 bool IsInlineBreakAfter() const { return mInlineBreak
== InlineBreak::After
; }
321 StyleClear
BreakType() const { return mBreakType
; }
323 // Set the inline line-break-before status, and reset other bit flags. The
324 // break type is StyleClear::Line. Note that other frame completion status
325 // isn't expected to matter after calling this method.
326 void SetInlineLineBreakBeforeAndReset() {
328 mBreakType
= StyleClear::Line
;
329 mInlineBreak
= InlineBreak::Before
;
332 // Set the inline line-break-after status. The break type can be changed
333 // via the optional aBreakType param.
334 void SetInlineLineBreakAfter(StyleClear aBreakType
= StyleClear::Line
) {
335 MOZ_ASSERT(aBreakType
!= StyleClear::None
,
336 "Break-after with StyleClear::None is meaningless!");
337 mBreakType
= aBreakType
;
338 mInlineBreak
= InlineBreak::After
;
341 // mFirstLetterComplete bit flag means the break was induced by
342 // completion of a first-letter.
343 bool FirstLetterComplete() const { return mFirstLetterComplete
; }
344 void SetFirstLetterComplete() { mFirstLetterComplete
= true; }
347 StyleClear mBreakType
;
348 InlineBreak mInlineBreak
;
349 Completion mCompletion
;
350 bool mNextInFlowNeedsReflow
: 1;
352 bool mFirstLetterComplete
: 1;
355 #define NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aMetrics) \
356 aStatus.UpdateTruncated(aReflowInput, aMetrics);
358 // Convert nsReflowStatus to a human-readable string.
359 std::ostream
& operator<<(std::ostream
& aStream
, const nsReflowStatus
& aStatus
);
361 //----------------------------------------------------------------------
364 * When there is no scrollable overflow rect, the ink overflow rect
365 * may be stored as four 1-byte deltas each strictly LESS THAN 0xff, for
366 * the four edges of the rectangle, or the four bytes may be read as a
367 * single 32-bit "overflow-rect type" value including at least one 0xff
368 * byte as an indicator that the value does NOT represent four deltas.
369 * If all four deltas are zero, this means that no overflow rect has
370 * actually been set (this is the initial state of newly-created frames).
373 // max delta we can store
374 #define NS_FRAME_OVERFLOW_DELTA_MAX 0xfe
376 // there are no overflow rects; code relies on this being the all-zero value
377 #define NS_FRAME_OVERFLOW_NONE 0x00000000
379 // overflow is stored as a separate rect property
380 #define NS_FRAME_OVERFLOW_LARGE 0x000000ff
383 * nsBidiLevel is the type of the level values in our Unicode Bidi
385 * It holds an embedding level and indicates the visual direction
386 * by its bit 0 (even/odd value).<p>
388 * <li><code>aParaLevel</code> can be set to the
389 * pseudo-level values <code>NSBIDI_DEFAULT_LTR</code>
390 * and <code>NSBIDI_DEFAULT_RTL</code>.</li></ul>
392 * @see nsBidi::SetPara
394 * <p>The related constants are not real, valid level values.
395 * <code>NSBIDI_DEFAULT_XXX</code> can be used to specify
396 * a default for the paragraph level for
397 * when the <code>SetPara</code> function
398 * shall determine it but there is no
399 * strongly typed character in the input.<p>
401 * Note that the value for <code>NSBIDI_DEFAULT_LTR</code> is even
402 * and the one for <code>NSBIDI_DEFAULT_RTL</code> is odd,
403 * just like with normal LTR and RTL level values -
404 * these special values are designed that way. Also, the implementation
405 * assumes that NSBIDI_MAX_EXPLICIT_LEVEL is odd.
407 * @see NSBIDI_DEFAULT_LTR
408 * @see NSBIDI_DEFAULT_RTL
409 * @see NSBIDI_LEVEL_OVERRIDE
410 * @see NSBIDI_MAX_EXPLICIT_LEVEL
412 typedef uint8_t nsBidiLevel
;
415 * Paragraph level setting.
416 * If there is no strong character, then set the paragraph level to 0
419 #define NSBIDI_DEFAULT_LTR 0xfe
422 * Paragraph level setting.
423 * If there is no strong character, then set the paragraph level to 1
426 #define NSBIDI_DEFAULT_RTL 0xff
429 * Maximum explicit embedding level.
430 * (The maximum resolved level can be up to
431 * <code>NSBIDI_MAX_EXPLICIT_LEVEL+1</code>).
433 #define NSBIDI_MAX_EXPLICIT_LEVEL 125
435 /** Bit flag for level input.
436 * Overrides directional properties.
438 #define NSBIDI_LEVEL_OVERRIDE 0x80
441 * <code>nsBidiDirection</code> values indicate the text direction.
443 enum nsBidiDirection
{
444 /** All left-to-right text This is a 0 value. */
446 /** All right-to-left text This is a 1 value. */
448 /** Mixed-directional text. */
454 // https://drafts.csswg.org/css-align-3/#baseline-sharing-group
455 enum class BaselineSharingGroup
{
456 // NOTE Used as an array index so must be 0 and 1.
461 // Loosely: https://drafts.csswg.org/css-align-3/#shared-alignment-context
462 enum class AlignmentContext
{
470 * For replaced elements only. Gets the intrinsic dimensions of this element,
471 * which can be specified on a per-axis basis.
473 struct IntrinsicSize
{
474 Maybe
<nscoord
> width
;
475 Maybe
<nscoord
> height
;
477 IntrinsicSize() = default;
479 IntrinsicSize(nscoord aWidth
, nscoord aHeight
)
480 : width(Some(aWidth
)), height(Some(aHeight
)) {}
482 explicit IntrinsicSize(const nsSize
& aSize
)
483 : IntrinsicSize(aSize
.Width(), aSize
.Height()) {}
485 Maybe
<nsSize
> ToSize() const {
486 return width
&& height
? Some(nsSize(*width
, *height
)) : Nothing();
489 bool operator==(const IntrinsicSize
& rhs
) const {
490 return width
== rhs
.width
&& height
== rhs
.height
;
492 bool operator!=(const IntrinsicSize
& rhs
) const { return !(*this == rhs
); }
495 // Pseudo bidi embedding level indicating nonexistence.
496 static const nsBidiLevel kBidiLevelNone
= 0xff;
498 struct FrameBidiData
{
499 nsBidiLevel baseLevel
;
500 nsBidiLevel embeddingLevel
;
501 // The embedding level of virtual bidi formatting character before
502 // this frame if any. kBidiLevelNone is used to indicate nonexistence
503 // or unnecessity of such virtual character.
504 nsBidiLevel precedingControl
;
507 } // namespace mozilla
509 /// Generic destructor for frame properties. Calls delete.
510 template <typename T
>
511 static void DeleteValue(T
* aPropertyValue
) {
512 delete aPropertyValue
;
515 /// Generic destructor for frame properties. Calls Release().
516 template <typename T
>
517 static void ReleaseValue(T
* aPropertyValue
) {
518 aPropertyValue
->Release();
521 //----------------------------------------------------------------------
524 * nsIFrame logging constants. We redefine the nspr
525 * PRLogModuleInfo.level field to be a bitfield. Each bit controls a
526 * specific type of logging. Each logging operation has associated
527 * inline methods defined below.
529 * Due to the redefinition of the level field we cannot use MOZ_LOG directly
530 * as that will cause assertions due to invalid log levels.
532 #define NS_FRAME_TRACE_CALLS 0x1
533 #define NS_FRAME_TRACE_PUSH_PULL 0x2
534 #define NS_FRAME_TRACE_CHILD_REFLOW 0x4
535 #define NS_FRAME_TRACE_NEW_FRAMES 0x8
537 #define NS_FRAME_LOG_TEST(_lm, _bit) \
538 (int(((mozilla::LogModule*)(_lm))->Level()) & (_bit))
541 # define NS_FRAME_LOG(_bit, _args) \
543 if (NS_FRAME_LOG_TEST(nsIFrame::sFrameLogModule, _bit)) { \
544 printf_stderr _args; \
548 # define NS_FRAME_LOG(_bit, _args)
551 // XXX Need to rework this so that logging is free when it's off
553 # define NS_FRAME_TRACE_IN(_method) Trace(_method, true)
555 # define NS_FRAME_TRACE_OUT(_method) Trace(_method, false)
557 # define NS_FRAME_TRACE(_bit, _args) \
559 if (NS_FRAME_LOG_TEST(nsIFrame::sFrameLogModule, _bit)) { \
564 # define NS_FRAME_TRACE_REFLOW_IN(_method) Trace(_method, true)
566 # define NS_FRAME_TRACE_REFLOW_OUT(_method, _status) \
567 Trace(_method, false, _status)
570 # define NS_FRAME_TRACE(_bits, _args)
571 # define NS_FRAME_TRACE_IN(_method)
572 # define NS_FRAME_TRACE_OUT(_method)
573 # define NS_FRAME_TRACE_REFLOW_IN(_method)
574 # define NS_FRAME_TRACE_REFLOW_OUT(_method, _status)
577 //----------------------------------------------------------------------
579 // Frame allocation boilerplate macros. Every subclass of nsFrame must
580 // either use NS_{DECL,IMPL}_FRAMEARENA_HELPERS pair for allocating
581 // memory correctly, or use NS_DECL_ABSTRACT_FRAME to declare a frame
582 // class abstract and stop it from being instantiated. If a frame class
583 // without its own operator new and GetFrameId gets instantiated, the
584 // per-frame recycler lists in nsPresArena will not work correctly,
585 // with potentially catastrophic consequences (not enough memory is
586 // allocated for a frame object).
588 #define NS_DECL_FRAMEARENA_HELPERS(class) \
589 NS_DECL_QUERYFRAME_TARGET(class) \
590 static constexpr nsIFrame::ClassID kClassID = nsIFrame::ClassID::class##_id; \
591 void* operator new(size_t, mozilla::PresShell*) MOZ_MUST_OVERRIDE; \
592 nsQueryFrame::FrameIID GetFrameId() const override MOZ_MUST_OVERRIDE { \
593 return nsQueryFrame::class##_id; \
596 #define NS_IMPL_FRAMEARENA_HELPERS(class) \
597 void* class ::operator new(size_t sz, mozilla::PresShell* aShell) { \
598 return aShell->AllocateFrame(nsQueryFrame::class##_id, sz); \
601 #define NS_DECL_ABSTRACT_FRAME(class) \
602 void* operator new(size_t, mozilla::PresShell*) MOZ_MUST_OVERRIDE = delete; \
603 nsQueryFrame::FrameIID GetFrameId() const override MOZ_MUST_OVERRIDE = 0;
605 //----------------------------------------------------------------------
608 * A frame in the layout model. This interface is supported by all frame
611 * Frames can have multiple child lists: the default child list
612 * (referred to as the <i>principal</i> child list, and additional named
613 * child lists. There is an ordering of frames within a child list, but
614 * there is no order defined between frames in different child lists of
615 * the same parent frame.
617 * Frames are NOT reference counted. Use the Destroy() member function
618 * to destroy a frame. The lifetime of the frame hierarchy is bounded by the
619 * lifetime of the presentation shell which owns the frames.
621 * nsIFrame is a private Gecko interface. If you are not Gecko then you
622 * should not use it. If you're not in layout, then you won't be able to
623 * link to many of the functions defined here. Too bad.
625 * If you're not in layout but you must call functions in here, at least
626 * restrict yourself to calling virtual methods, which won't hurt you as badly.
628 class nsIFrame
: public nsQueryFrame
{
630 using AlignmentContext
= mozilla::AlignmentContext
;
631 using BaselineSharingGroup
= mozilla::BaselineSharingGroup
;
632 template <typename T
>
633 using Maybe
= mozilla::Maybe
<T
>;
634 template <typename T
, typename E
>
635 using Result
= mozilla::Result
<T
, E
>;
636 using Nothing
= mozilla::Nothing
;
637 using OnNonvisible
= mozilla::OnNonvisible
;
638 using ReflowInput
= mozilla::ReflowInput
;
639 using ReflowOutput
= mozilla::ReflowOutput
;
640 using Visibility
= mozilla::Visibility
;
641 using LengthPercentage
= mozilla::LengthPercentage
;
642 using StyleExtremumLength
= mozilla::StyleExtremumLength
;
644 typedef mozilla::ComputedStyle ComputedStyle
;
645 typedef mozilla::FrameProperties FrameProperties
;
646 typedef mozilla::layers::Layer Layer
;
647 typedef mozilla::layers::LayerManager LayerManager
;
648 typedef mozilla::layout::FrameChildList ChildList
;
649 typedef mozilla::layout::FrameChildListID ChildListID
;
650 typedef mozilla::layout::FrameChildListIDs ChildListIDs
;
651 typedef mozilla::gfx::DrawTarget DrawTarget
;
652 typedef mozilla::gfx::Matrix Matrix
;
653 typedef mozilla::gfx::Matrix4x4 Matrix4x4
;
654 typedef mozilla::gfx::Matrix4x4Flagged Matrix4x4Flagged
;
655 typedef mozilla::Sides Sides
;
656 typedef mozilla::LogicalSides LogicalSides
;
657 typedef mozilla::SmallPointerArray
<mozilla::DisplayItemData
>
658 DisplayItemDataArray
;
659 typedef nsQueryFrame::ClassID ClassID
;
663 NS_DECL_QUERYFRAME_TARGET(nsIFrame
)
665 explicit nsIFrame(ComputedStyle
* aStyle
, nsPresContext
* aPresContext
,
669 mComputedStyle(aStyle
),
670 mPresContext(aPresContext
),
672 mNextSibling(nullptr),
673 mPrevSibling(nullptr),
674 mState(NS_FRAME_FIRST_REFLOW
| NS_FRAME_IS_DIRTY
),
675 mWritingMode(aStyle
),
677 mMayHaveRoundedCorners(false),
678 mHasImageRequest(false),
679 mHasFirstLetterChild(false),
680 mParentIsWrapperAnonBox(false),
681 mIsWrapperBoxNeedingRestyle(false),
682 mReflowRequestedForCharDataChange(false),
683 mForceDescendIntoIfVisible(false),
684 mBuiltDisplayList(false),
685 mFrameIsModified(false),
686 mHasOverrideDirtyRegion(false),
687 mMayHaveWillChangeBudget(false),
688 mIsPrimaryFrame(false),
689 mMayHaveTransformAnimation(false),
690 mMayHaveOpacityAnimation(false),
691 mAllDescendantsAreInvisible(false),
692 mHasBSizeChange(false),
693 mInScrollAnchorChain(false),
694 mHasColumnSpanSiblings(false),
695 mDescendantMayDependOnItsStaticPosition(false),
696 mShouldGenerateComputedInfo(false) {
697 MOZ_ASSERT(mComputedStyle
);
698 MOZ_ASSERT(mPresContext
);
699 mozilla::PodZero(&mOverflow
);
700 MOZ_COUNT_CTOR(nsIFrame
);
702 explicit nsIFrame(ComputedStyle
* aStyle
, nsPresContext
* aPresContext
)
703 : nsIFrame(aStyle
, aPresContext
, ClassID::nsIFrame_id
) {}
705 nsPresContext
* PresContext() const { return mPresContext
; }
707 mozilla::PresShell
* PresShell() const { return PresContext()->PresShell(); }
709 virtual nsQueryFrame::FrameIID
GetFrameId() const MOZ_MUST_OVERRIDE
{
714 * Called to initialize the frame. This is called immediately after creating
717 * If the frame is a continuing frame, then aPrevInFlow indicates the previous
718 * frame (the frame that was split).
720 * Each subclass that need a view should override this method and call
721 * CreateView() after calling its base class Init().
723 * @param aContent the content object associated with the frame
724 * @param aParent the parent frame
725 * @param aPrevInFlow the prev-in-flow frame
727 virtual void Init(nsIContent
* aContent
, nsContainerFrame
* aParent
,
728 nsIFrame
* aPrevInFlow
);
730 void* operator new(size_t, mozilla::PresShell
*) MOZ_MUST_OVERRIDE
;
732 using PostDestroyData
= mozilla::layout::PostFrameDestroyData
;
733 struct MOZ_RAII AutoPostDestroyData
{
734 explicit AutoPostDestroyData(nsPresContext
* aPresContext
)
735 : mPresContext(aPresContext
) {}
736 ~AutoPostDestroyData() {
737 for (auto& content
: mozilla::Reversed(mData
.mAnonymousContent
)) {
738 nsIFrame::DestroyAnonymousContent(mPresContext
, content
.forget());
741 nsPresContext
* mPresContext
;
742 PostDestroyData mData
;
745 * Destroys this frame and each of its child frames (recursively calls
746 * Destroy() for each child). If this frame is a first-continuation, this
747 * also removes the frame from the primary frame map and clears undisplayed
748 * content for its content node.
749 * If the frame is a placeholder, it also ensures the out-of-flow frame's
750 * removal and destruction.
753 AutoPostDestroyData
data(PresContext());
754 DestroyFrom(this, data
.mData
);
755 // Note that |this| is deleted at this point.
759 * Flags for PeekOffsetCharacter, PeekOffsetNoAmount, PeekOffsetWord return
762 enum FrameSearchResult
{
763 // Peek found a appropriate offset within frame.
765 // try next frame for offset.
767 // offset not found because the frame was empty of text.
768 CONTINUE_EMPTY
= 0x2 | CONTINUE
,
769 // offset not found because the frame didn't contain any text that could be
771 CONTINUE_UNSELECTABLE
= 0x4 | CONTINUE
,
775 * Options for PeekOffsetCharacter().
777 struct MOZ_STACK_CLASS PeekOffsetCharacterOptions
{
778 // Whether to restrict result to valid cursor locations (between grapheme
779 // clusters) - if this is included, maintains "normal" behavior, otherwise,
780 // used for selection by "code unit" (instead of "character")
781 bool mRespectClusters
;
782 // Whether to check user-select style value - if this is included, checks
783 // if user-select is all, then, it may return CONTINUE_UNSELECTABLE.
784 bool mIgnoreUserStyleAll
;
786 PeekOffsetCharacterOptions()
787 : mRespectClusters(true), mIgnoreUserStyleAll(false) {}
791 friend class nsBlockFrame
; // for access to DestroyFrom
794 * Return true if the frame is part of a Selection.
795 * Helper method to implement the public IsSelected() API.
797 virtual bool IsFrameSelected() const;
800 * Implements Destroy(). Do not call this directly except from within a
801 * DestroyFrom() implementation.
803 * @note This will always be called, so it is not necessary to override
804 * Destroy() in subclasses of nsFrame, just DestroyFrom().
806 * @param aDestructRoot is the root of the subtree being destroyed
808 virtual void DestroyFrom(nsIFrame
* aDestructRoot
,
809 PostDestroyData
& aPostDestroyData
);
810 friend class nsFrameList
; // needed to pass aDestructRoot through to children
811 friend class nsLineBox
; // needed to pass aDestructRoot through to children
812 friend class nsContainerFrame
; // needed to pass aDestructRoot through to
814 template <class Source
>
815 friend class do_QueryFrameHelper
; // to read mClass
819 // Overridden to prevent the global delete from being called, since
820 // the memory came out of an arena instead of the heap.
822 // Ideally this would be private and undefined, like the normal
823 // operator new. Unfortunately, the C++ standard requires an
824 // overridden operator delete to be accessible to any subclass that
825 // defines a virtual destructor, so we can only make it protected;
826 // worse, some C++ compilers will synthesize calls to this function
827 // from the "deleting destructors" that they emit in case of
828 // delete-expressions, so it can't even be undefined.
829 void operator delete(void* aPtr
, size_t sz
);
832 // Left undefined; nsFrame objects are never allocated from the heap.
833 void* operator new(size_t sz
) noexcept(true);
835 // Returns true if this frame has any kind of CSS animations.
836 bool HasCSSAnimations();
838 // Returns true if this frame has any kind of CSS transitions.
839 bool HasCSSTransitions();
843 * Get the content object associated with this frame. Does not add a
846 nsIContent
* GetContent() const { return mContent
; }
849 * Get the frame that should be the parent for the frames of child elements
850 * May return nullptr during reflow
852 virtual nsContainerFrame
* GetContentInsertionFrame() { return nullptr; }
855 * Move any frames on our overflow list to the end of our principal list.
856 * @return true if there were any overflow frames
858 virtual bool DrainSelfOverflowList() { return false; }
861 * Get the frame that should be scrolled if the content associated
862 * with this frame is targeted for scrolling. For frames implementing
863 * nsIScrollableFrame this will return the frame itself. For frames
864 * like nsTextControlFrame that contain a scrollframe, will return
867 virtual nsIScrollableFrame
* GetScrollTargetFrame() const { return nullptr; }
870 * Get the offsets of the frame. most will be 0,0
873 virtual nsresult
GetOffsets(int32_t& start
, int32_t& end
) const;
876 * Reset the offsets when splitting frames during Bidi reordering
879 virtual void AdjustOffsetsForBidi(int32_t aStart
, int32_t aEnd
) {}
882 * Get the style associated with this frame.
884 ComputedStyle
* Style() const { return mComputedStyle
; }
886 void AssertNewStyleIsSane(ComputedStyle
&)
887 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
894 void SetComputedStyle(ComputedStyle
* aStyle
) {
895 if (aStyle
!= mComputedStyle
) {
896 AssertNewStyleIsSane(*aStyle
);
897 RefPtr
<ComputedStyle
> oldComputedStyle
= std::move(mComputedStyle
);
898 mComputedStyle
= aStyle
;
899 DidSetComputedStyle(oldComputedStyle
);
904 * SetComputedStyleWithoutNotification is for changes to the style
905 * context that should suppress style change processing, in other
906 * words, those that aren't really changes. This generally means only
907 * changes that happen during frame construction.
909 void SetComputedStyleWithoutNotification(ComputedStyle
* aStyle
) {
910 if (aStyle
!= mComputedStyle
) {
911 mComputedStyle
= aStyle
;
916 // Style post processing hook
917 // Attention: the old style is the one we're forgetting,
918 // and hence possibly completely bogus for GetStyle* purposes.
919 // Use PeekStyleData instead.
920 virtual void DidSetComputedStyle(ComputedStyle
* aOldComputedStyle
);
924 * Define typesafe getter functions for each style struct by
925 * preprocessing the list of style structs. These functions are the
926 * preferred way to get style data. The macro creates functions like:
927 * const nsStyleBorder* StyleBorder();
928 * const nsStyleColor* StyleColor();
930 * Callers outside of libxul should use nsIDOMWindow::GetComputedStyle()
931 * instead of these accessors.
933 * Callers can use Style*WithOptionalParam if they're in a function that
934 * accepts an *optional* pointer the style struct.
936 #define STYLE_STRUCT(name_) \
937 const nsStyle##name_* Style##name_() const MOZ_NONNULL_RETURN { \
938 NS_ASSERTION(mComputedStyle, "No style found!"); \
939 return mComputedStyle->Style##name_(); \
941 const nsStyle##name_* Style##name_##WithOptionalParam( \
942 const nsStyle##name_* aStyleStruct) const MOZ_NONNULL_RETURN { \
943 if (aStyleStruct) { \
944 MOZ_ASSERT(aStyleStruct == Style##name_()); \
945 return aStyleStruct; \
947 return Style##name_(); \
949 #include "nsStyleStructList.h"
952 /** Also forward GetVisitedDependentColor to the style */
953 template <typename T
, typename S
>
954 nscolor
GetVisitedDependentColor(T
S::*aField
) {
955 return mComputedStyle
->GetVisitedDependentColor(aField
);
959 * These methods are to access any additional ComputedStyles that
960 * the frame may be holding.
962 * These are styles that are children of the frame's primary style and are NOT
963 * used as styles for any child frames.
965 * These contexts also MUST NOT have any child styles whatsoever. If you need
966 * to insert styles into the style tree, then you should create pseudo element
967 * frames to own them.
969 * The indicies must be consecutive and implementations MUST return null if
970 * asked for an index that is out of range.
972 virtual ComputedStyle
* GetAdditionalComputedStyle(int32_t aIndex
) const;
974 virtual void SetAdditionalComputedStyle(int32_t aIndex
,
975 ComputedStyle
* aComputedStyle
);
978 * @param aSelectionStatus nsISelectionController::getDisplaySelection.
980 already_AddRefed
<ComputedStyle
> ComputeSelectionStyle(
981 int16_t aSelectionStatus
) const;
984 * Accessor functions for geometric parent.
986 nsContainerFrame
* GetParent() const { return mParent
; }
988 bool CanBeDynamicReflowRoot() const;
991 * Gets the parent of a frame, using the parent of the placeholder for
992 * out-of-flow frames.
994 inline nsContainerFrame
* GetInFlowParent() const;
997 * Gets the primary frame of the closest flattened tree ancestor that has a
998 * frame (flattened tree ancestors may not have frames in presence of display:
1001 inline nsIFrame
* GetClosestFlattenedTreeAncestorPrimaryFrame() const;
1004 * Return the placeholder for this frame (which must be out-of-flow).
1005 * @note this will only return non-null if |this| is the first-in-flow
1006 * although we don't assert that here for legacy reasons.
1008 inline nsPlaceholderFrame
* GetPlaceholderFrame() const {
1009 MOZ_ASSERT(HasAnyStateBits(NS_FRAME_OUT_OF_FLOW
));
1010 return GetProperty(PlaceholderFrameProperty());
1014 * Set this frame's parent to aParent.
1015 * If the frame may have moved into or out of a scrollframe's
1017 * StickyScrollContainer::NotifyReparentedFrameAcrossScrollFrameBoundary must
1020 void SetParent(nsContainerFrame
* aParent
);
1023 * The frame's writing-mode, used for logical layout computations.
1024 * It's usually the 'writing-mode' computed value, but there are exceptions:
1025 * * inner table frames copy the value from the table frame
1026 * (@see nsTableRowGroupFrame::Init, nsTableRowFrame::Init etc)
1027 * * the root element frame propagates its value to its ancestors.
1028 * The value may obtain from the principal <body> element.
1029 * (@see nsCSSFrameConstructor::ConstructDocElementFrame)
1030 * * the internal anonymous frames of the root element copy their value
1032 * (@see nsIFrame::Init)
1033 * * a scrolled frame propagates its value to its ancestor scroll frame
1034 * (@see nsHTMLScrollFrame::ReloadChildFrames)
1036 mozilla::WritingMode
GetWritingMode() const { return mWritingMode
; }
1039 * Construct a writing mode for line layout in this frame. This is
1040 * the writing mode of this frame, except that if this frame is styled with
1041 * unicode-bidi:plaintext, we reset the direction to the resolved paragraph
1042 * level of the given subframe (typically the first frame on the line),
1043 * because the container frame could be split by hard line breaks into
1044 * multiple paragraphs with different base direction.
1045 * @param aSelfWM the WM of 'this'
1047 mozilla::WritingMode
WritingModeForLine(mozilla::WritingMode aSelfWM
,
1048 nsIFrame
* aSubFrame
) const;
1051 * Bounding rect of the frame.
1053 * For frames that are laid out according to CSS box model rules the values
1054 * are in app units, and the origin is relative to the upper-left of the
1055 * geometric parent. The size includes the content area, borders, and
1058 * Frames that are laid out according to SVG's coordinate space based rules
1059 * (frames with the NS_FRAME_SVG_LAYOUT bit set, which *excludes*
1060 * SVGOuterSVGFrame) are different. Many frames of this type do not set or
1061 * use mRect, in which case the frame rect is undefined. The exceptions are:
1063 * - SVGInnerSVGFrame
1064 * - SVGGeometryFrame (used for <path>, <circle>, etc.)
1066 * - SVGForeignObjectFrame
1068 * For these frames the frame rect contains the frame's element's userspace
1069 * bounds including fill, stroke and markers, but converted to app units
1070 * rather than being in user units (CSS px). In the SVG code "userspace" is
1071 * defined to be the coordinate system for the attributes that define an
1072 * element's geometry (such as the 'cx' attribute for <circle>). For more
1073 * precise details see these frames' implementations of the ReflowSVG method
1074 * where mRect is set.
1076 * Note: moving or sizing the frame does not affect the view's size or
1079 nsRect
GetRect() const { return mRect
; }
1080 nsPoint
GetPosition() const { return mRect
.TopLeft(); }
1081 nsSize
GetSize() const { return mRect
.Size(); }
1082 nsRect
GetRectRelativeToSelf() const {
1083 return nsRect(nsPoint(0, 0), mRect
.Size());
1087 * Like the frame's rect (see |GetRect|), which is the border rect,
1088 * other rectangles of the frame, in app units, relative to the parent.
1090 nsRect
GetPaddingRect() const;
1091 nsRect
GetPaddingRectRelativeToSelf() const;
1092 nsRect
GetContentRect() const;
1093 nsRect
GetContentRectRelativeToSelf() const;
1094 nsRect
GetMarginRectRelativeToSelf() const;
1097 * Dimensions and position in logical coordinates in the frame's writing mode
1098 * or another writing mode
1100 mozilla::LogicalRect
GetLogicalRect(const nsSize
& aContainerSize
) const {
1101 return GetLogicalRect(GetWritingMode(), aContainerSize
);
1103 mozilla::LogicalPoint
GetLogicalPosition(const nsSize
& aContainerSize
) const {
1104 return GetLogicalPosition(GetWritingMode(), aContainerSize
);
1106 mozilla::LogicalSize
GetLogicalSize() const {
1107 return GetLogicalSize(GetWritingMode());
1109 mozilla::LogicalRect
GetLogicalRect(mozilla::WritingMode aWritingMode
,
1110 const nsSize
& aContainerSize
) const {
1111 return mozilla::LogicalRect(aWritingMode
, GetRect(), aContainerSize
);
1113 mozilla::LogicalPoint
GetLogicalPosition(mozilla::WritingMode aWritingMode
,
1114 const nsSize
& aContainerSize
) const {
1115 return GetLogicalRect(aWritingMode
, aContainerSize
).Origin(aWritingMode
);
1117 mozilla::LogicalSize
GetLogicalSize(mozilla::WritingMode aWritingMode
) const {
1118 return mozilla::LogicalSize(aWritingMode
, GetSize());
1120 nscoord
IStart(const nsSize
& aContainerSize
) const {
1121 return IStart(GetWritingMode(), aContainerSize
);
1123 nscoord
IStart(mozilla::WritingMode aWritingMode
,
1124 const nsSize
& aContainerSize
) const {
1125 return GetLogicalPosition(aWritingMode
, aContainerSize
).I(aWritingMode
);
1127 nscoord
BStart(const nsSize
& aContainerSize
) const {
1128 return BStart(GetWritingMode(), aContainerSize
);
1130 nscoord
BStart(mozilla::WritingMode aWritingMode
,
1131 const nsSize
& aContainerSize
) const {
1132 return GetLogicalPosition(aWritingMode
, aContainerSize
).B(aWritingMode
);
1134 nscoord
ISize() const { return ISize(GetWritingMode()); }
1135 nscoord
ISize(mozilla::WritingMode aWritingMode
) const {
1136 return GetLogicalSize(aWritingMode
).ISize(aWritingMode
);
1138 nscoord
BSize() const { return BSize(GetWritingMode()); }
1139 nscoord
BSize(mozilla::WritingMode aWritingMode
) const {
1140 return GetLogicalSize(aWritingMode
).BSize(aWritingMode
);
1142 mozilla::LogicalSize
ContentSize() const {
1143 return ContentSize(GetWritingMode());
1145 mozilla::LogicalSize
ContentSize(mozilla::WritingMode aWritingMode
) const {
1146 mozilla::WritingMode wm
= GetWritingMode();
1147 const auto bp
= GetLogicalUsedBorderAndPadding(wm
)
1148 .ApplySkipSides(GetLogicalSkipSides())
1149 .ConvertTo(aWritingMode
, wm
);
1150 const auto size
= GetLogicalSize(aWritingMode
);
1151 return mozilla::LogicalSize(
1153 std::max(0, size
.ISize(aWritingMode
) - bp
.IStartEnd(aWritingMode
)),
1154 std::max(0, size
.BSize(aWritingMode
) - bp
.BStartEnd(aWritingMode
)));
1158 * When we change the size of the frame's border-box rect, we may need to
1159 * reset the overflow rect if it was previously stored as deltas.
1160 * (If it is currently a "large" overflow and could be re-packed as deltas,
1161 * we don't bother as the cost of the allocation has already been paid.)
1162 * @param aRebuildDisplayItems If true, then adds this frame to the
1163 * list of modified frames for display list building if the rect has changed.
1164 * Only pass false if you're sure that the relevant display items will be
1165 * rebuilt already (possibly by an ancestor being in the modified list), or if
1166 * this is a temporary change.
1168 void SetRect(const nsRect
& aRect
, bool aRebuildDisplayItems
= true) {
1169 if (aRect
== mRect
) {
1172 if (mOverflow
.mType
!= NS_FRAME_OVERFLOW_LARGE
&&
1173 mOverflow
.mType
!= NS_FRAME_OVERFLOW_NONE
) {
1174 mozilla::OverflowAreas overflow
= GetOverflowAreas();
1176 SetOverflowAreas(overflow
);
1180 if (aRebuildDisplayItems
) {
1181 MarkNeedsDisplayItemRebuild();
1185 * Set this frame's rect from a logical rect in its own writing direction
1187 void SetRect(const mozilla::LogicalRect
& aRect
,
1188 const nsSize
& aContainerSize
) {
1189 SetRect(GetWritingMode(), aRect
, aContainerSize
);
1192 * Set this frame's rect from a logical rect in a different writing direction
1193 * (GetPhysicalRect will assert if the writing mode doesn't match)
1195 void SetRect(mozilla::WritingMode aWritingMode
,
1196 const mozilla::LogicalRect
& aRect
,
1197 const nsSize
& aContainerSize
) {
1198 SetRect(aRect
.GetPhysicalRect(aWritingMode
, aContainerSize
));
1202 * Set this frame's size from a logical size in its own writing direction.
1203 * This leaves the frame's logical position unchanged, which means its
1204 * physical position may change (for right-to-left modes).
1206 void SetSize(const mozilla::LogicalSize
& aSize
) {
1207 SetSize(GetWritingMode(), aSize
);
1210 * Set this frame's size from a logical size in a different writing direction.
1211 * This leaves the frame's logical position in the given mode unchanged,
1212 * which means its physical position may change (for right-to-left modes).
1214 void SetSize(mozilla::WritingMode aWritingMode
,
1215 const mozilla::LogicalSize
& aSize
) {
1216 if (aWritingMode
.IsPhysicalRTL()) {
1217 nscoord oldWidth
= mRect
.Width();
1218 SetSize(aSize
.GetPhysicalSize(aWritingMode
));
1219 mRect
.x
-= mRect
.Width() - oldWidth
;
1221 SetSize(aSize
.GetPhysicalSize(aWritingMode
));
1226 * Set this frame's physical size. This leaves the frame's physical position
1227 * (topLeft) unchanged.
1228 * @param aRebuildDisplayItems If true, then adds this frame to the
1229 * list of modified frames for display list building if the size has changed.
1230 * Only pass false if you're sure that the relevant display items will be
1231 * rebuilt already (possibly by an ancestor being in the modified list), or if
1232 * this is a temporary change.
1234 void SetSize(const nsSize
& aSize
, bool aRebuildDisplayItems
= true) {
1235 SetRect(nsRect(mRect
.TopLeft(), aSize
), aRebuildDisplayItems
);
1238 void SetPosition(const nsPoint
& aPt
) {
1239 if (mRect
.TopLeft() == aPt
) {
1243 MarkNeedsDisplayItemRebuild();
1245 void SetPosition(mozilla::WritingMode aWritingMode
,
1246 const mozilla::LogicalPoint
& aPt
,
1247 const nsSize
& aContainerSize
) {
1248 // We subtract mRect.Size() from the container size to account for
1249 // the fact that logical origins in RTL coordinate systems are at
1250 // the top right of the frame instead of the top left.
1252 aPt
.GetPhysicalPoint(aWritingMode
, aContainerSize
- mRect
.Size()));
1256 * Move the frame, accounting for relative positioning. Use this when
1257 * adjusting the frame's position by a known amount, to properly update its
1258 * saved normal position (see GetNormalPosition below).
1260 * This must be used only when moving a frame *after*
1261 * ReflowInput::ApplyRelativePositioning is called. When moving
1262 * a frame during the reflow process prior to calling
1263 * ReflowInput::ApplyRelativePositioning, the position should
1264 * simply be adjusted directly (e.g., using SetPosition()).
1266 void MovePositionBy(const nsPoint
& aTranslation
);
1269 * As above, using a logical-point delta in a given writing mode.
1271 void MovePositionBy(mozilla::WritingMode aWritingMode
,
1272 const mozilla::LogicalPoint
& aTranslation
) {
1273 // The LogicalPoint represents a vector rather than a point within a
1274 // rectangular coordinate space, so we use a null containerSize when
1275 // converting logical to physical.
1276 const nsSize nullContainerSize
;
1278 aTranslation
.GetPhysicalPoint(aWritingMode
, nullContainerSize
));
1282 * Return frame's rect without relative positioning
1284 nsRect
GetNormalRect() const;
1287 * Return frame's position without relative positioning.
1288 * If aHasProperty is provided, returns whether the normal position
1289 * was stored in a frame property.
1291 inline nsPoint
GetNormalPosition(bool* aHasProperty
= nullptr) const;
1292 inline mozilla::LogicalPoint
GetLogicalNormalPosition(
1293 mozilla::WritingMode aWritingMode
, const nsSize
& aContainerSize
) const;
1295 virtual nsPoint
GetPositionOfChildIgnoringScrolling(const nsIFrame
* aChild
) {
1296 return aChild
->GetPosition();
1299 nsPoint
GetPositionIgnoringScrolling() const;
1301 typedef AutoTArray
<nsDisplayItemBase
*, 4> DisplayItemArray
;
1303 #define NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(prop, type, dtor) \
1304 static const mozilla::FramePropertyDescriptor<type>* prop() { \
1305 /* Use of constexpr caused startup crashes with MSVC2015u1 PGO. */ \
1306 static const auto descriptor = \
1307 mozilla::FramePropertyDescriptor<type>::NewWithDestructor<dtor>(); \
1308 return &descriptor; \
1311 // Don't use this unless you really know what you're doing!
1312 #define NS_DECLARE_FRAME_PROPERTY_WITH_FRAME_IN_DTOR(prop, type, dtor) \
1313 static const mozilla::FramePropertyDescriptor<type>* prop() { \
1314 /* Use of constexpr caused startup crashes with MSVC2015u1 PGO. */ \
1315 static const auto descriptor = mozilla::FramePropertyDescriptor< \
1316 type>::NewWithDestructorWithFrame<dtor>(); \
1317 return &descriptor; \
1320 #define NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(prop, type) \
1321 static const mozilla::FramePropertyDescriptor<type>* prop() { \
1322 /* Use of constexpr caused startup crashes with MSVC2015u1 PGO. */ \
1323 static const auto descriptor = \
1324 mozilla::FramePropertyDescriptor<type>::NewWithoutDestructor(); \
1325 return &descriptor; \
1328 #define NS_DECLARE_FRAME_PROPERTY_DELETABLE(prop, type) \
1329 NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(prop, type, DeleteValue)
1331 #define NS_DECLARE_FRAME_PROPERTY_RELEASABLE(prop, type) \
1332 NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(prop, type, ReleaseValue)
1334 #define NS_DECLARE_FRAME_PROPERTY_WITH_DTOR_NEVER_CALLED(prop, type) \
1335 static void AssertOnDestroyingProperty##prop(type*) { \
1336 MOZ_ASSERT_UNREACHABLE( \
1337 "Frame property " #prop \
1338 " should never be destroyed by the FrameProperties class"); \
1340 NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(prop, type, \
1341 AssertOnDestroyingProperty##prop)
1343 #define NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(prop, type) \
1344 NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(prop, mozilla::SmallValueHolder<type>)
1346 NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(IBSplitSibling
, nsContainerFrame
)
1347 NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(IBSplitPrevSibling
, nsContainerFrame
)
1349 NS_DECLARE_FRAME_PROPERTY_DELETABLE(NormalPositionProperty
, nsPoint
)
1350 NS_DECLARE_FRAME_PROPERTY_DELETABLE(ComputedOffsetProperty
, nsMargin
)
1352 NS_DECLARE_FRAME_PROPERTY_DELETABLE(OutlineInnerRectProperty
, nsRect
)
1353 NS_DECLARE_FRAME_PROPERTY_DELETABLE(PreEffectsBBoxProperty
, nsRect
)
1354 NS_DECLARE_FRAME_PROPERTY_DELETABLE(PreTransformOverflowAreasProperty
,
1355 mozilla::OverflowAreas
)
1357 NS_DECLARE_FRAME_PROPERTY_DELETABLE(CachedBorderImageDataProperty
,
1358 CachedBorderImageData
)
1360 NS_DECLARE_FRAME_PROPERTY_DELETABLE(OverflowAreasProperty
,
1361 mozilla::OverflowAreas
)
1363 // The initial overflow area passed to FinishAndStoreOverflow. This is only
1364 // set on frames that Preserve3D() or HasPerspective() or IsTransformed(), and
1365 // when at least one of the overflow areas differs from the frame bound rect.
1366 NS_DECLARE_FRAME_PROPERTY_DELETABLE(InitialOverflowProperty
,
1367 mozilla::OverflowAreas
)
1370 // InitialOverflowPropertyDebug is added to the frame to indicate that either
1371 // the InitialOverflowProperty has been stored or the InitialOverflowProperty
1372 // has been suppressed due to being set to the default value (frame bounds)
1373 NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(DebugInitialOverflowPropertyApplied
,
1377 NS_DECLARE_FRAME_PROPERTY_DELETABLE(UsedMarginProperty
, nsMargin
)
1378 NS_DECLARE_FRAME_PROPERTY_DELETABLE(UsedPaddingProperty
, nsMargin
)
1379 NS_DECLARE_FRAME_PROPERTY_DELETABLE(UsedBorderProperty
, nsMargin
)
1381 NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(LineBaselineOffset
, nscoord
)
1383 NS_DECLARE_FRAME_PROPERTY_DELETABLE(InvalidationRect
, nsRect
)
1385 NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(RefusedAsyncAnimationProperty
, bool)
1387 NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(FragStretchBSizeProperty
, nscoord
)
1389 // The block-axis margin-box size associated with eBClampMarginBoxMinSize.
1390 NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(BClampMarginBoxMinSizeProperty
, nscoord
)
1392 NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(IBaselinePadProperty
, nscoord
)
1393 NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(BBaselinePadProperty
, nscoord
)
1395 NS_DECLARE_FRAME_PROPERTY_DELETABLE(DisplayItems
, DisplayItemArray
)
1397 NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(BidiDataProperty
,
1398 mozilla::FrameBidiData
)
1400 NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(PlaceholderFrameProperty
,
1403 NS_DECLARE_FRAME_PROPERTY_RELEASABLE(OffsetPathCache
, mozilla::gfx::Path
)
1405 mozilla::FrameBidiData
GetBidiData() const {
1407 mozilla::FrameBidiData bidiData
= GetProperty(BidiDataProperty(), &exists
);
1409 bidiData
.precedingControl
= mozilla::kBidiLevelNone
;
1414 nsBidiLevel
GetBaseLevel() const { return GetBidiData().baseLevel
; }
1416 nsBidiLevel
GetEmbeddingLevel() const { return GetBidiData().embeddingLevel
; }
1419 * Return the distance between the border edge of the frame and the
1420 * margin edge of the frame. Like GetRect(), returns the dimensions
1421 * as of the most recent reflow.
1423 * This doesn't include any margin collapsing that may have occurred.
1424 * It also doesn't consider GetSkipSides()/GetLogicalSkipSides(), so
1425 * may report nonzero values on sides that are actually skipped for
1428 * It also treats 'auto' margins as zero, and treats any margins that
1429 * should have been turned into 'auto' because of overconstraint as
1430 * having their original values.
1432 virtual nsMargin
GetUsedMargin() const;
1433 virtual mozilla::LogicalMargin
GetLogicalUsedMargin(
1434 mozilla::WritingMode aWritingMode
) const {
1435 return mozilla::LogicalMargin(aWritingMode
, GetUsedMargin());
1439 * Return the distance between the border edge of the frame (which is
1440 * its rect) and the padding edge of the frame. Like GetRect(), returns
1441 * the dimensions as of the most recent reflow.
1443 * This doesn't consider GetSkipSides()/GetLogicalSkipSides(), so
1444 * may report nonzero values on sides that are actually skipped for
1447 * Note that this differs from StyleBorder()->GetComputedBorder() in
1448 * that this describes a region of the frame's box, and
1449 * StyleBorder()->GetComputedBorder() describes a border. They differ
1450 * for tables (particularly border-collapse tables) and themed
1453 virtual nsMargin
GetUsedBorder() const;
1454 virtual mozilla::LogicalMargin
GetLogicalUsedBorder(
1455 mozilla::WritingMode aWritingMode
) const {
1456 return mozilla::LogicalMargin(aWritingMode
, GetUsedBorder());
1460 * Return the distance between the padding edge of the frame and the
1461 * content edge of the frame. Like GetRect(), returns the dimensions
1462 * as of the most recent reflow.
1464 * This doesn't consider GetSkipSides()/GetLogicalSkipSides(), so
1465 * may report nonzero values on sides that are actually skipped for
1468 virtual nsMargin
GetUsedPadding() const;
1469 virtual mozilla::LogicalMargin
GetLogicalUsedPadding(
1470 mozilla::WritingMode aWritingMode
) const {
1471 return mozilla::LogicalMargin(aWritingMode
, GetUsedPadding());
1474 nsMargin
GetUsedBorderAndPadding() const {
1475 return GetUsedBorder() + GetUsedPadding();
1477 mozilla::LogicalMargin
GetLogicalUsedBorderAndPadding(
1478 mozilla::WritingMode aWritingMode
) const {
1479 return mozilla::LogicalMargin(aWritingMode
, GetUsedBorderAndPadding());
1483 * The area to paint box-shadows around. The default is the border rect.
1484 * (nsFieldSetFrame overrides this).
1486 virtual nsRect
VisualBorderRectRelativeToSelf() const {
1487 return nsRect(0, 0, mRect
.Width(), mRect
.Height());
1491 * Get the size, in app units, of the border radii. It returns FALSE iff all
1492 * returned radii == 0 (so no border radii), TRUE otherwise.
1493 * For the aRadii indexes, use the enum HalfCorner constants in gfx/2d/Types.h
1494 * If a side is skipped via aSkipSides, its corners are forced to 0.
1496 * All corner radii are then adjusted so they do not require more
1497 * space than aBorderArea, according to the algorithm in css3-background.
1499 * aFrameSize is used as the basis for percentage widths and heights.
1500 * aBorderArea is used for the adjustment of radii that might be too
1502 * FIXME: In the long run, we can probably get away with only one of
1503 * these, especially if we change the way we handle outline-radius (by
1504 * removing it and inflating the border radius)
1506 * Return whether any radii are nonzero.
1508 static bool ComputeBorderRadii(const mozilla::BorderRadius
&,
1509 const nsSize
& aFrameSize
,
1510 const nsSize
& aBorderArea
, Sides aSkipSides
,
1514 * Given a set of border radii for one box (e.g., border box), convert
1515 * it to the equivalent set of radii for another box (e.g., in to
1516 * padding box, out to outline box) by reducing radii or increasing
1517 * nonzero radii as appropriate.
1519 * Indices into aRadii are the enum HalfCorner constants in gfx/2d/Types.h
1521 * Note that InsetBorderRadii is lossy, since it can turn nonzero
1522 * radii into zero, and OutsetBorderRadii does not inflate zero radii.
1523 * Therefore, callers should always inset or outset directly from the
1524 * original value coming from style.
1526 static void InsetBorderRadii(nscoord aRadii
[8], const nsMargin
& aOffsets
);
1527 static void OutsetBorderRadii(nscoord aRadii
[8], const nsMargin
& aOffsets
);
1530 * Fill in border radii for this frame. Return whether any are nonzero.
1531 * Indices into aRadii are the enum HalfCorner constants in gfx/2d/Types.h
1532 * aSkipSides is a union of SideBits::eLeft/Right/Top/Bottom bits that says
1533 * which side(s) to skip.
1535 * Note: GetMarginBoxBorderRadii() and GetShapeBoxBorderRadii() work only
1536 * on frames that establish block formatting contexts since they don't
1537 * participate in margin-collapsing.
1539 virtual bool GetBorderRadii(const nsSize
& aFrameSize
,
1540 const nsSize
& aBorderArea
, Sides aSkipSides
,
1541 nscoord aRadii
[8]) const;
1542 bool GetBorderRadii(nscoord aRadii
[8]) const;
1543 bool GetMarginBoxBorderRadii(nscoord aRadii
[8]) const;
1544 bool GetPaddingBoxBorderRadii(nscoord aRadii
[8]) const;
1545 bool GetContentBoxBorderRadii(nscoord aRadii
[8]) const;
1546 bool GetBoxBorderRadii(nscoord aRadii
[8], nsMargin aOffset
,
1547 bool aIsOutset
) const;
1548 bool GetShapeBoxBorderRadii(nscoord aRadii
[8]) const;
1551 * XXX: this method will likely be replaced by GetVerticalAlignBaseline
1552 * Get the position of the frame's baseline, relative to the top of
1553 * the frame (its top border edge). Only valid when Reflow is not
1555 * @note You should only call this on frames with a WM that's parallel to
1557 * @param aWritingMode the writing-mode of the alignment context, with the
1558 * ltr/rtl direction tweak done by nsIFrame::GetWritingMode(nsIFrame*) in
1559 * inline contexts (see that method).
1561 virtual nscoord
GetLogicalBaseline(mozilla::WritingMode aWritingMode
) const;
1564 * Synthesize a first(last) inline-axis baseline based on our margin-box.
1565 * An alphabetical baseline is at the start(end) edge and a central baseline
1566 * is at the center of our block-axis margin-box (aWM tells which to use).
1567 * https://drafts.csswg.org/css-align-3/#synthesize-baselines
1568 * @note You should only call this on frames with a WM that's parallel to aWM.
1569 * @param aWM the writing-mode of the alignment context
1570 * @return an offset from our border-box block-axis start(end) edge for
1571 * a first(last) baseline respectively
1572 * (implemented in nsIFrameInlines.h)
1574 inline nscoord
SynthesizeBaselineBOffsetFromMarginBox(
1575 mozilla::WritingMode aWM
, BaselineSharingGroup aGroup
) const;
1578 * Synthesize a first(last) inline-axis baseline based on our border-box.
1579 * An alphabetical baseline is at the start(end) edge and a central baseline
1580 * is at the center of our block-axis border-box (aWM tells which to use).
1581 * https://drafts.csswg.org/css-align-3/#synthesize-baselines
1582 * @note The returned value is only valid when reflow is not needed.
1583 * @note You should only call this on frames with a WM that's parallel to aWM.
1584 * @param aWM the writing-mode of the alignment context
1585 * @return an offset from our border-box block-axis start(end) edge for
1586 * a first(last) baseline respectively
1587 * (implemented in nsIFrameInlines.h)
1589 inline nscoord
SynthesizeBaselineBOffsetFromBorderBox(
1590 mozilla::WritingMode aWM
, BaselineSharingGroup aGroup
) const;
1593 * Synthesize a first(last) inline-axis baseline based on our content-box.
1594 * An alphabetical baseline is at the start(end) edge and a central baseline
1595 * is at the center of our block-axis content-box (aWM tells which to use).
1596 * https://drafts.csswg.org/css-align-3/#synthesize-baselines
1597 * @note The returned value is only valid when reflow is not needed.
1598 * @note You should only call this on frames with a WM that's parallel to aWM.
1599 * @param aWM the writing-mode of the alignment context
1600 * @return an offset from our border-box block-axis start(end) edge for
1601 * a first(last) baseline respectively
1602 * (implemented in nsIFrameInlines.h)
1604 inline nscoord
SynthesizeBaselineBOffsetFromContentBox(
1605 mozilla::WritingMode aWM
, BaselineSharingGroup aGroup
) const;
1608 * Return the position of the frame's inline-axis baseline, or synthesize one
1609 * for the given alignment context. The returned baseline is the distance from
1610 * the block-axis border-box start(end) edge for aBaselineGroup ::First(Last).
1611 * @note The returned value is only valid when reflow is not needed.
1612 * @note You should only call this on frames with a WM that's parallel to aWM.
1613 * @param aWM the writing-mode of the alignment context
1614 * @param aBaselineOffset out-param, only valid if the method returns true
1615 * (implemented in nsIFrameInlines.h)
1617 inline nscoord
BaselineBOffset(mozilla::WritingMode aWM
,
1618 BaselineSharingGroup aBaselineGroup
,
1619 AlignmentContext aAlignmentContext
) const;
1622 * XXX: this method is taking over the role that GetLogicalBaseline has.
1623 * Return true if the frame has a CSS2 'vertical-align' baseline.
1624 * If it has, then the returned baseline is the distance from the block-
1625 * axis border-box start edge.
1626 * @note This method should only be used in AlignmentContext::Inline
1628 * @note The returned value is only valid when reflow is not needed.
1629 * @note You should only call this on frames with a WM that's parallel to aWM.
1630 * @param aWM the writing-mode of the alignment context
1631 * @param aBaseline the baseline offset, only valid if the method returns true
1633 virtual bool GetVerticalAlignBaseline(mozilla::WritingMode aWM
,
1634 nscoord
* aBaseline
) const {
1639 * Return true if the frame has a first(last) inline-axis natural baseline per
1640 * CSS Box Alignment. If so, then the returned baseline is the distance from
1641 * the block-axis border-box start(end) edge for aBaselineGroup ::First(Last).
1642 * https://drafts.csswg.org/css-align-3/#natural-baseline
1643 * @note The returned value is only valid when reflow is not needed.
1644 * @note You should only call this on frames with a WM that's parallel to aWM.
1645 * @param aWM the writing-mode of the alignment context
1646 * @param aBaseline the baseline offset, only valid if the method returns true
1648 virtual bool GetNaturalBaselineBOffset(mozilla::WritingMode aWM
,
1649 BaselineSharingGroup aBaselineGroup
,
1650 nscoord
* aBaseline
) const {
1655 * Get the position of the baseline on which the caret needs to be placed,
1656 * relative to the top of the frame. This is mostly needed for frames
1657 * which return a baseline from GetBaseline which is not useful for
1658 * caret positioning.
1660 virtual nscoord
GetCaretBaseline() const {
1661 return GetLogicalBaseline(GetWritingMode());
1664 ///////////////////////////////////////////////////////////////////////////////
1665 // The public visibility API.
1666 ///////////////////////////////////////////////////////////////////////////////
1668 /// @return true if we're tracking visibility for this frame.
1669 bool TrackingVisibility() const {
1670 return HasAnyStateBits(NS_FRAME_VISIBILITY_IS_TRACKED
);
1673 /// @return the visibility state of this frame. See the Visibility enum
1674 /// for the possible return values and their meanings.
1675 Visibility
GetVisibility() const;
1677 /// Update the visibility state of this frame synchronously.
1678 /// XXX(seth): Avoid using this method; we should be relying on the refresh
1679 /// driver for visibility updates. This method, which replaces
1680 /// nsLayoutUtils::UpdateApproximateFrameVisibility(), exists purely as a
1681 /// temporary measure to avoid changing behavior during the transition from
1682 /// the old image visibility code.
1683 void UpdateVisibilitySynchronously();
1685 // A frame property which stores the visibility state of this frame. Right
1686 // now that consists of an approximate visibility counter represented as a
1687 // uint32_t. When the visibility of this frame is not being tracked, this
1688 // property is absent.
1689 NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(VisibilityStateProperty
, uint32_t);
1693 * Subclasses can call this method to enable visibility tracking for this
1696 * If visibility tracking was previously disabled, this will schedule an
1697 * update an asynchronous update of visibility.
1699 void EnableVisibilityTracking();
1702 * Subclasses can call this method to disable visibility tracking for this
1705 * Note that if visibility tracking was previously enabled, disabling
1706 * visibility tracking will cause a synchronous call to OnVisibilityChange().
1708 void DisableVisibilityTracking();
1711 * Called when a frame transitions between visibility states (for example,
1712 * from nonvisible to visible, or from visible to nonvisible).
1714 * @param aNewVisibility The new visibility state.
1715 * @param aNonvisibleAction A requested action if the frame has become
1716 * nonvisible. If Nothing(), no action is
1717 * requested. If DISCARD_IMAGES is specified, the
1718 * frame is requested to ask any images it's
1719 * associated with to discard their surfaces if
1722 * Subclasses which override this method should call their parent class's
1725 virtual void OnVisibilityChange(
1726 Visibility aNewVisibility
,
1727 const Maybe
<OnNonvisible
>& aNonvisibleAction
= Nothing());
1730 ///////////////////////////////////////////////////////////////////////////////
1731 // Internal implementation for the approximate frame visibility API.
1732 ///////////////////////////////////////////////////////////////////////////////
1735 * We track the approximate visibility of frames using a counter; if it's
1736 * non-zero, then the frame is considered visible. Using a counter allows us
1737 * to account for situations where the frame may be visible in more than one
1738 * place (for example, via -moz-element), and it simplifies the
1739 * implementation of our approximate visibility tracking algorithms.
1741 * @param aNonvisibleAction A requested action if the frame has become
1742 * nonvisible. If Nothing(), no action is
1743 * requested. If DISCARD_IMAGES is specified, the
1744 * frame is requested to ask any images it's
1745 * associated with to discard their surfaces if
1748 void DecApproximateVisibleCount(
1749 const Maybe
<OnNonvisible
>& aNonvisibleAction
= Nothing());
1750 void IncApproximateVisibleCount();
1753 * Get the specified child list.
1755 * @param aListID identifies the requested child list.
1756 * @return the child list. If the requested list is unsupported by this
1757 * frame type, an empty list will be returned.
1759 virtual const nsFrameList
& GetChildList(ChildListID aListID
) const;
1760 const nsFrameList
& PrincipalChildList() const {
1761 return GetChildList(kPrincipalList
);
1765 * Sub-classes should override this methods if they want to append their own
1766 * child lists into aLists.
1768 virtual void GetChildLists(nsTArray
<ChildList
>* aLists
) const;
1771 * Returns the child lists for this frame.
1773 AutoTArray
<ChildList
, 4> ChildLists() const {
1774 AutoTArray
<ChildList
, 4> childLists
;
1775 GetChildLists(&childLists
);
1780 * Returns the child lists for this frame, including ones belong to a child
1783 AutoTArray
<ChildList
, 4> CrossDocChildLists();
1785 // The individual concrete child lists.
1786 static const ChildListID kPrincipalList
= mozilla::layout::kPrincipalList
;
1787 static const ChildListID kAbsoluteList
= mozilla::layout::kAbsoluteList
;
1788 static const ChildListID kBulletList
= mozilla::layout::kBulletList
;
1789 static const ChildListID kCaptionList
= mozilla::layout::kCaptionList
;
1790 static const ChildListID kColGroupList
= mozilla::layout::kColGroupList
;
1791 static const ChildListID kExcessOverflowContainersList
=
1792 mozilla::layout::kExcessOverflowContainersList
;
1793 static const ChildListID kFixedList
= mozilla::layout::kFixedList
;
1794 static const ChildListID kFloatList
= mozilla::layout::kFloatList
;
1795 static const ChildListID kOverflowContainersList
=
1796 mozilla::layout::kOverflowContainersList
;
1797 static const ChildListID kOverflowList
= mozilla::layout::kOverflowList
;
1798 static const ChildListID kOverflowOutOfFlowList
=
1799 mozilla::layout::kOverflowOutOfFlowList
;
1800 static const ChildListID kPopupList
= mozilla::layout::kPopupList
;
1801 static const ChildListID kPushedFloatsList
=
1802 mozilla::layout::kPushedFloatsList
;
1803 static const ChildListID kSelectPopupList
= mozilla::layout::kSelectPopupList
;
1804 static const ChildListID kBackdropList
= mozilla::layout::kBackdropList
;
1805 // A special alias for kPrincipalList that do not request reflow.
1806 static const ChildListID kNoReflowPrincipalList
=
1807 mozilla::layout::kNoReflowPrincipalList
;
1810 * Child frames are linked together in a doubly-linked list
1812 nsIFrame
* GetNextSibling() const { return mNextSibling
; }
1813 void SetNextSibling(nsIFrame
* aNextSibling
) {
1814 NS_ASSERTION(this != aNextSibling
,
1815 "Creating a circular frame list, this is very bad.");
1816 if (mNextSibling
&& mNextSibling
->GetPrevSibling() == this) {
1817 mNextSibling
->mPrevSibling
= nullptr;
1819 mNextSibling
= aNextSibling
;
1821 mNextSibling
->mPrevSibling
= this;
1825 nsIFrame
* GetPrevSibling() const { return mPrevSibling
; }
1828 * Builds the display lists for the content represented by this frame
1829 * and its descendants. The background+borders of this element must
1830 * be added first, before any other content.
1832 * This should only be called by methods in nsFrame. Instead of calling this
1833 * directly, call either BuildDisplayListForStackingContext or
1834 * BuildDisplayListForChild.
1836 * See nsDisplayList.h for more information about display lists.
1838 virtual void BuildDisplayList(nsDisplayListBuilder
* aBuilder
,
1839 const nsDisplayListSet
& aLists
) {}
1841 * Displays the caret onto the given display list builder. The caret is
1842 * painted on top of the rest of the display list items.
1844 void DisplayCaret(nsDisplayListBuilder
* aBuilder
, nsDisplayList
* aList
);
1847 * Get the preferred caret color at the offset.
1849 * @param aOffset is offset of the content.
1851 virtual nscolor
GetCaretColorAt(int32_t aOffset
);
1853 bool IsThemed(nsITheme::Transparency
* aTransparencyState
= nullptr) const {
1854 return IsThemed(StyleDisplay(), aTransparencyState
);
1856 bool IsThemed(const nsStyleDisplay
* aDisp
,
1857 nsITheme::Transparency
* aTransparencyState
= nullptr) const {
1858 if (!aDisp
->HasAppearance()) {
1861 nsIFrame
* mutable_this
= const_cast<nsIFrame
*>(this);
1862 nsPresContext
* pc
= PresContext();
1863 nsITheme
* theme
= pc
->Theme();
1864 if (!theme
->ThemeSupportsWidget(pc
, mutable_this
,
1865 aDisp
->EffectiveAppearance())) {
1868 if (aTransparencyState
) {
1869 *aTransparencyState
= theme
->GetWidgetTransparency(
1870 mutable_this
, aDisp
->EffectiveAppearance());
1876 * Builds a display list for the content represented by this frame,
1877 * treating this frame as the root of a stacking context.
1878 * Optionally sets aCreatedContainerItem to true if we created a
1879 * single container display item for the stacking context, and no
1880 * other wrapping items are needed.
1882 void BuildDisplayListForStackingContext(
1883 nsDisplayListBuilder
* aBuilder
, nsDisplayList
* aList
,
1884 bool* aCreatedContainerItem
= nullptr);
1886 enum class DisplayChildFlag
{
1887 ForcePseudoStackingContext
,
1888 ForceStackingContext
,
1891 using DisplayChildFlags
= mozilla::EnumSet
<DisplayChildFlag
>;
1894 * Adjusts aDirtyRect for the child's offset, checks that the dirty rect
1895 * actually intersects the child (or its descendants), calls BuildDisplayList
1896 * on the child if necessary, and puts things in the right lists if the child
1899 * @param aFlags a set of of DisplayChildFlag values that are applicable for
1902 void BuildDisplayListForChild(nsDisplayListBuilder
* aBuilder
,
1904 const nsDisplayListSet
& aLists
,
1905 DisplayChildFlags aFlags
= {});
1907 void BuildDisplayListForSimpleChild(nsDisplayListBuilder
* aBuilder
,
1909 const nsDisplayListSet
& aLists
);
1912 * Helper for BuildDisplayListForChild, to implement this special-case for
1913 * grid (and flex) items from the spec:
1914 * The painting order of grid items is exactly the same as inline blocks,
1915 * except that [...], and 'z-index' values other than 'auto' create a
1916 * stacking context even if 'position' is 'static' (behaving exactly as if
1917 * 'position' were 'relative'). https://drafts.csswg.org/css-grid/#z-order
1919 * Flex items also have the same special-case described in
1920 * https://drafts.csswg.org/css-flexbox/#painting
1922 DisplayChildFlag
DisplayFlagForFlexOrGridItem() const;
1924 bool RefusedAsyncAnimation() const {
1925 return GetProperty(RefusedAsyncAnimationProperty());
1929 * Returns true if this frame is transformed (e.g. has CSS or SVG transforms)
1930 * or if its parent is an SVG frame that has children-only transforms (e.g.
1931 * an SVG viewBox attribute) or if its transform-style is preserve-3d or
1932 * the frame has transform animations.
1934 * @param aStyleDisplay: If the caller has this->StyleDisplay(), providing
1935 * it here will improve performance.
1937 bool IsTransformed(const nsStyleDisplay
* aStyleDisplay
) const;
1938 bool IsTransformed() const { return IsTransformed(StyleDisplay()); }
1941 * Same as IsTransformed, except that it doesn't take SVG transforms
1944 bool IsCSSTransformed(const nsStyleDisplay
* aStyleDisplay
) const;
1947 * True if this frame has any animation of transform in effect.
1949 bool HasAnimationOfTransform() const;
1952 * True if this frame has any animation of opacity in effect.
1954 * EffectSet is just an optimization.
1956 bool HasAnimationOfOpacity(mozilla::EffectSet
* = nullptr) const;
1959 * Returns true if the frame is translucent or the frame has opacity
1960 * animations for the purposes of creating a stacking context.
1962 * @param aStyleDisplay: This function needs style display struct.
1964 * @param aStyleEffects: This function needs style effects struct.
1966 * @param aEffectSet: This function may need to look up EffectSet property.
1967 * If a caller already have one, pass it in can save property look up
1968 * time; otherwise, just leave it as nullptr.
1970 bool HasOpacity(const nsStyleDisplay
* aStyleDisplay
,
1971 const nsStyleEffects
* aStyleEffects
,
1972 mozilla::EffectSet
* aEffectSet
= nullptr) const {
1973 return HasOpacityInternal(1.0f
, aStyleDisplay
, aStyleEffects
, aEffectSet
);
1976 * Returns true if the frame is translucent for display purposes.
1978 * @param aStyleDisplay: This function needs style display struct.
1980 * @param aStyleEffects: This function needs style effects struct.
1982 * @param aEffectSet: This function may need to look up EffectSet property.
1983 * If a caller already have one, pass it in can save property look up
1984 * time; otherwise, just leave it as nullptr.
1986 bool HasVisualOpacity(const nsStyleDisplay
* aStyleDisplay
,
1987 const nsStyleEffects
* aStyleEffects
,
1988 mozilla::EffectSet
* aEffectSet
= nullptr) const {
1989 // Treat an opacity value of 0.99 and above as opaque. This is an
1990 // optimization aimed at Web content which use opacity:0.99 as a hint for
1991 // creating a stacking context only.
1992 return HasOpacityInternal(0.99f
, aStyleDisplay
, aStyleEffects
, aEffectSet
);
1996 * Return true if this frame might be using a transform getter.
1998 virtual bool HasTransformGetter() const { return false; }
2001 * Returns true if this frame is an SVG frame that has SVG transforms applied
2002 * to it, or if its parent frame is an SVG frame that has children-only
2003 * transforms (e.g. an SVG viewBox attribute).
2004 * If aOwnTransforms is non-null and the frame has its own SVG transforms,
2005 * aOwnTransforms will be set to these transforms. If aFromParentTransforms
2006 * is non-null and the frame has an SVG parent with children-only transforms,
2007 * then aFromParentTransforms will be set to these transforms.
2009 virtual bool IsSVGTransformed(Matrix
* aOwnTransforms
= nullptr,
2010 Matrix
* aFromParentTransforms
= nullptr) const;
2013 * Return true if this frame should form a backdrop root container.
2014 * See: https://drafts.fxtf.org/filter-effects-2/#BackdropRootTriggers
2016 bool FormsBackdropRoot(const nsStyleDisplay
* aStyleDisplay
,
2017 const nsStyleEffects
* aStyleEffects
,
2018 const nsStyleSVGReset
* aStyleSvgReset
);
2021 * Returns whether this frame will attempt to extend the 3d transforms of its
2022 * children. This requires transform-style: preserve-3d, as well as no
2023 * clipping or svg effects.
2025 * @param aStyleDisplay: If the caller has this->StyleDisplay(), providing
2026 * it here will improve performance.
2028 * @param aStyleEffects: If the caller has this->StyleEffects(), providing
2029 * it here will improve performance.
2031 * @param aEffectSetForOpacity: This function may need to look up the
2032 * EffectSet for opacity animations on this frame.
2033 * If the caller already has looked up this EffectSet, it may pass it in to
2034 * save an extra property lookup.
2036 bool Extend3DContext(
2037 const nsStyleDisplay
* aStyleDisplay
, const nsStyleEffects
* aStyleEffects
,
2038 mozilla::EffectSet
* aEffectSetForOpacity
= nullptr) const;
2039 bool Extend3DContext(
2040 mozilla::EffectSet
* aEffectSetForOpacity
= nullptr) const {
2041 return Extend3DContext(StyleDisplay(), StyleEffects(),
2042 aEffectSetForOpacity
);
2046 * Returns whether this frame has a parent that Extend3DContext() and has
2047 * its own transform (or hidden backface) to be combined with the parent's
2050 * @param aStyleDisplay: If the caller has this->StyleDisplay(), providing
2051 * it here will improve performance.
2053 bool Combines3DTransformWithAncestors(
2054 const nsStyleDisplay
* aStyleDisplay
) const;
2055 bool Combines3DTransformWithAncestors() const {
2056 return Combines3DTransformWithAncestors(StyleDisplay());
2060 * Returns whether this frame has a hidden backface and has a parent that
2061 * Extend3DContext(). This is useful because in some cases the hidden
2062 * backface can safely be ignored if it could not be visible anyway.
2065 bool In3DContextAndBackfaceIsHidden() const;
2067 bool IsPreserve3DLeaf(const nsStyleDisplay
* aStyleDisplay
,
2068 mozilla::EffectSet
* aEffectSet
= nullptr) const {
2069 return Combines3DTransformWithAncestors(aStyleDisplay
) &&
2070 !Extend3DContext(aStyleDisplay
, StyleEffects(), aEffectSet
);
2072 bool IsPreserve3DLeaf(mozilla::EffectSet
* aEffectSet
= nullptr) const {
2073 return IsPreserve3DLeaf(StyleDisplay(), aEffectSet
);
2076 bool HasPerspective(const nsStyleDisplay
* aStyleDisplay
) const;
2077 bool HasPerspective() const { return HasPerspective(StyleDisplay()); }
2079 bool ChildrenHavePerspective(const nsStyleDisplay
* aStyleDisplay
) const;
2080 bool ChildrenHavePerspective() const {
2081 return ChildrenHavePerspective(StyleDisplay());
2085 * Includes the overflow area of all descendants that participate in the
2086 * current 3d context into aOverflowAreas.
2088 void ComputePreserve3DChildrenOverflow(
2089 mozilla::OverflowAreas
& aOverflowAreas
);
2091 void RecomputePerspectiveChildrenOverflow(const nsIFrame
* aStartFrame
);
2094 * Returns the computed z-index for this frame, returning Nothing() for
2095 * z-index: auto, and for frames that don't support z-index.
2097 Maybe
<int32_t> ZIndex() const;
2100 * Returns whether this frame is the anchor of some ancestor scroll frame. As
2101 * this frame is moved, the scroll frame will apply adjustments to keep this
2102 * scroll frame in the same relative position.
2104 * aOutContainer will optionally be set to the scroll anchor container for
2105 * this frame if this frame is an anchor.
2107 bool IsScrollAnchor(
2108 mozilla::layout::ScrollAnchorContainer
** aOutContainer
= nullptr);
2111 * Returns whether this frame is the anchor of some ancestor scroll frame, or
2112 * has a descendant which is the scroll anchor.
2114 bool IsInScrollAnchorChain() const;
2115 void SetInScrollAnchorChain(bool aInChain
);
2118 * Returns the number of ancestors between this and the root of our frame tree
2120 uint32_t GetDepthInFrameTree() const;
2123 * Event handling of GUI events.
2125 * @param aEvent event structure describing the type of event and rge widget
2126 * where the event originated. The |point| member of this is in the coordinate
2127 * system of the view returned by GetOffsetFromView.
2129 * @param aEventStatus a return value indicating whether the event was
2130 * handled and whether default processing should be done
2132 * XXX From a frame's perspective it's unclear what the effect of the event
2133 * status is. Does it cause the event to continue propagating through the
2134 * frame hierarchy or is it just returned to the widgets?
2136 * @see WidgetGUIEvent
2137 * @see nsEventStatus
2139 MOZ_CAN_RUN_SCRIPT_BOUNDARY
2140 virtual nsresult
HandleEvent(nsPresContext
* aPresContext
,
2141 mozilla::WidgetGUIEvent
* aEvent
,
2142 nsEventStatus
* aEventStatus
);
2145 * Search for selectable content at point and attempt to select
2146 * based on the start and end selection behaviours.
2148 * @param aPresContext Presentation context
2149 * @param aPoint Point at which selection will occur. Coordinates
2150 * should be relative to this frame.
2151 * @param aBeginAmountType, aEndAmountType Selection behavior, see
2152 * nsIFrame for definitions.
2153 * @param aSelectFlags Selection flags defined in nsIFrame.h.
2154 * @return success or failure at finding suitable content to select.
2156 MOZ_CAN_RUN_SCRIPT nsresult
2157 SelectByTypeAtPoint(nsPresContext
* aPresContext
, const nsPoint
& aPoint
,
2158 nsSelectionAmount aBeginAmountType
,
2159 nsSelectionAmount aEndAmountType
, uint32_t aSelectFlags
);
2161 MOZ_CAN_RUN_SCRIPT nsresult
PeekBackwardAndForward(
2162 nsSelectionAmount aAmountBack
, nsSelectionAmount aAmountForward
,
2163 int32_t aStartPos
, bool aJumpLines
, uint32_t aSelectFlags
);
2165 enum { SELECT_ACCUMULATE
= 0x01 };
2168 // Fire DOM event. If no aContent argument use frame's mContent.
2169 void FireDOMEvent(const nsAString
& aDOMEventName
,
2170 nsIContent
* aContent
= nullptr);
2172 // Selection Methods
2174 MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHOD
2175 HandlePress(nsPresContext
* aPresContext
, mozilla::WidgetGUIEvent
* aEvent
,
2176 nsEventStatus
* aEventStatus
);
2178 MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHOD
HandleMultiplePress(
2179 nsPresContext
* aPresContext
, mozilla::WidgetGUIEvent
* aEvent
,
2180 nsEventStatus
* aEventStatus
, bool aControlHeld
);
2183 * @param aPresContext must be non-nullptr.
2184 * @param aEvent must be non-nullptr.
2185 * @param aEventStatus must be non-nullptr.
2188 NS_IMETHOD
HandleDrag(nsPresContext
* aPresContext
,
2189 mozilla::WidgetGUIEvent
* aEvent
,
2190 nsEventStatus
* aEventStatus
);
2192 MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHOD
2193 HandleRelease(nsPresContext
* aPresContext
, mozilla::WidgetGUIEvent
* aEvent
,
2194 nsEventStatus
* aEventStatus
);
2196 // Test if we are selecting a table object:
2197 // Most table/cell selection requires that Ctrl (Cmd on Mac) key is down
2198 // during a mouse click or drag. Exception is using Shift+click when
2199 // already in "table/cell selection mode" to extend a block selection
2200 // Get the parent content node and offset of the frame
2201 // of the enclosing cell or table (if not inside a cell)
2202 // aTarget tells us what table element to select (currently only cell and
2203 // table supported) (enums for this are defined in nsIFrame.h)
2204 nsresult
GetDataForTableSelection(const nsFrameSelection
* aFrameSelection
,
2205 mozilla::PresShell
* aPresShell
,
2206 mozilla::WidgetMouseEvent
* aMouseEvent
,
2207 nsIContent
** aParentContent
,
2208 int32_t* aContentOffset
,
2209 mozilla::TableSelectionMode
* aTarget
);
2212 * @return see nsISelectionController.idl's `getDisplaySelection`.
2214 int16_t DetermineDisplaySelection();
2217 virtual nsresult
GetContentForEvent(mozilla::WidgetEvent
* aEvent
,
2218 nsIContent
** aContent
);
2220 // This structure keeps track of the content node and offsets associated with
2221 // a point; there is a primary and a secondary offset associated with any
2222 // point. The primary and secondary offsets differ when the point is over a
2223 // non-text object. The primary offset is the expected position of the
2224 // cursor calculated from a point; the secondary offset, when it is different,
2225 // indicates that the point is in the boundaries of some selectable object.
2226 // Note that the primary offset can be after the secondary offset; for places
2227 // that need the beginning and end of the object, the StartOffset and
2228 // EndOffset helpers can be used.
2229 struct MOZ_STACK_CLASS ContentOffsets
{
2233 associate(mozilla::CARET_ASSOCIATE_BEFORE
) {}
2234 bool IsNull() { return !content
; }
2235 // Helpers for places that need the ends of the offsets and expect them in
2236 // numerical order, as opposed to wanting the primary and secondary offsets
2237 int32_t StartOffset() { return std::min(offset
, secondaryOffset
); }
2238 int32_t EndOffset() { return std::max(offset
, secondaryOffset
); }
2240 nsCOMPtr
<nsIContent
> content
;
2242 int32_t secondaryOffset
;
2243 // This value indicates whether the associated content is before or after
2244 // the offset; the most visible use is to allow the caret to know which line
2246 mozilla::CaretAssociationHint associate
;
2249 IGNORE_SELECTION_STYLE
= 0x01,
2250 // Treat visibility:hidden frames as non-selectable
2254 * This function calculates the content offsets for selection relative to
2255 * a point. Note that this should generally only be callled on the event
2256 * frame associated with an event because this function does not account
2257 * for frame lists other than the primary one.
2258 * @param aPoint point relative to this frame
2260 ContentOffsets
GetContentOffsetsFromPoint(const nsPoint
& aPoint
,
2261 uint32_t aFlags
= 0);
2263 virtual ContentOffsets
GetContentOffsetsFromPointExternal(
2264 const nsPoint
& aPoint
, uint32_t aFlags
= 0) {
2265 return GetContentOffsetsFromPoint(aPoint
, aFlags
);
2268 // Helper for GetContentAndOffsetsFromPoint; calculation of content offsets
2269 // in this function assumes there is no child frame that can be targeted.
2270 virtual ContentOffsets
CalcContentOffsetsFromFramePoint(
2271 const nsPoint
& aPoint
);
2274 * Ensure that `this` gets notifed when `aImage`s underlying image request
2275 * loads or animates.
2277 * This in practice is only needed for the canvas frame and table cell
2278 * backgrounds, which are the only cases that should paint a background that
2279 * isn't its own. The canvas paints the background from the root element or
2280 * body, and the table cell paints the background for its row.
2282 * For regular frames, this is done in DidSetComputedStyle.
2284 * NOTE: It's unclear if we even actually _need_ this for the second case, as
2285 * invalidating the row should invalidate all the cells. For the canvas case
2286 * this is definitely needed as it paints the background from somewhere "down"
2287 * in the frame tree.
2289 * Returns whether the image was in fact associated with the frame.
2291 [[nodiscard
]] bool AssociateImage(const mozilla::StyleImage
&);
2294 * This needs to be called if the above caller returned true, once the above
2295 * caller doesn't care about getting notified anymore.
2297 void DisassociateImage(const mozilla::StyleImage
&);
2299 enum class AllowCustomCursorImage
{
2305 * This structure holds information about a cursor. AllowCustomCursorImage
2306 * is `No`, then no cursor image should be loaded from the style specified on
2307 * `mStyle`, or the frame's style.
2309 * The `mStyle` member is used for `<area>` elements.
2311 struct MOZ_STACK_CLASS Cursor
{
2312 mozilla::StyleCursorKind mCursor
= mozilla::StyleCursorKind::Auto
;
2313 AllowCustomCursorImage mAllowCustomCursor
= AllowCustomCursorImage::Yes
;
2314 RefPtr
<mozilla::ComputedStyle
> mStyle
;
2318 * Get the cursor for a given frame.
2320 virtual Maybe
<Cursor
> GetCursor(const nsPoint
&);
2323 * Get a point (in the frame's coordinate space) given an offset into
2324 * the content. This point should be on the baseline of text with
2325 * the correct horizontal offset
2327 virtual nsresult
GetPointFromOffset(int32_t inOffset
, nsPoint
* outPoint
);
2330 * Get a list of character rects in a given range.
2331 * This is similar version of GetPointFromOffset.
2333 virtual nsresult
GetCharacterRectsInRange(int32_t aInOffset
, int32_t aLength
,
2334 nsTArray
<nsRect
>& aRects
);
2337 * Get the child frame of this frame which contains the given
2338 * content offset. outChildFrame may be this frame, or nullptr on return.
2339 * outContentOffset returns the content offset relative to the start
2340 * of the returned node. You can also pass a hint which tells the method
2341 * to stick to the end of the first found frame or the beginning of the
2342 * next in case the offset falls on a boundary.
2344 virtual nsresult
GetChildFrameContainingOffset(
2345 int32_t inContentOffset
,
2346 bool inHint
, // false stick left
2347 int32_t* outFrameContentOffset
, nsIFrame
** outChildFrame
);
2350 * Get the current frame-state value for this frame. aResult is
2351 * filled in with the state bits.
2353 nsFrameState
GetStateBits() const { return mState
; }
2356 * Update the current frame-state value for this frame.
2358 void AddStateBits(nsFrameState aBits
) { mState
|= aBits
; }
2359 void RemoveStateBits(nsFrameState aBits
) { mState
&= ~aBits
; }
2360 void AddOrRemoveStateBits(nsFrameState aBits
, bool aVal
) {
2361 aVal
? AddStateBits(aBits
) : RemoveStateBits(aBits
);
2365 * Checks if the current frame-state includes all of the listed bits
2367 bool HasAllStateBits(nsFrameState aBits
) const {
2368 return (mState
& aBits
) == aBits
;
2372 * Checks if the current frame-state includes any of the listed bits
2374 bool HasAnyStateBits(nsFrameState aBits
) const { return mState
& aBits
; }
2377 * Return true if this frame is the primary frame for mContent.
2379 bool IsPrimaryFrame() const { return mIsPrimaryFrame
; }
2381 void SetIsPrimaryFrame(bool aIsPrimary
) { mIsPrimaryFrame
= aIsPrimary
; }
2383 bool IsPrimaryFrameOfRootOrBodyElement() const;
2386 * @return true if this frame is used as a fieldset's rendered legend.
2388 bool IsRenderedLegend() const;
2391 * This call is invoked on the primary frame for a character data content
2392 * node, when it is changed in the content tree.
2394 virtual nsresult
CharacterDataChanged(const CharacterDataChangeInfo
&);
2397 * This call is invoked when the value of a content objects's attribute
2399 * The first frame that maps that content is asked to deal
2400 * with the change by doing whatever is appropriate.
2402 * @param aNameSpaceID the namespace of the attribute
2403 * @param aAttribute the atom name of the attribute
2404 * @param aModType Whether or not the attribute was added, changed, or
2405 * removed. The constants are defined in MutationEvent.webidl.
2407 virtual nsresult
AttributeChanged(int32_t aNameSpaceID
, nsAtom
* aAttribute
,
2411 * When the content states of a content object change, this method is invoked
2412 * on the primary frame of that content object.
2414 * @param aStates the changed states
2416 virtual void ContentStatesChanged(mozilla::EventStates aStates
);
2419 * Continuation member functions
2421 virtual nsIFrame
* GetPrevContinuation() const;
2422 virtual void SetPrevContinuation(nsIFrame
*);
2423 virtual nsIFrame
* GetNextContinuation() const;
2424 virtual void SetNextContinuation(nsIFrame
*);
2425 virtual nsIFrame
* FirstContinuation() const {
2426 return const_cast<nsIFrame
*>(this);
2428 virtual nsIFrame
* LastContinuation() const {
2429 return const_cast<nsIFrame
*>(this);
2433 * GetTailContinuation gets the last non-overflow-container continuation
2434 * in the continuation chain, i.e. where the next sibling element
2437 nsIFrame
* GetTailContinuation();
2440 * Flow member functions
2442 virtual nsIFrame
* GetPrevInFlow() const;
2443 virtual void SetPrevInFlow(nsIFrame
*);
2445 virtual nsIFrame
* GetNextInFlow() const;
2446 virtual void SetNextInFlow(nsIFrame
*);
2449 * Return the first frame in our current flow.
2451 virtual nsIFrame
* FirstInFlow() const { return const_cast<nsIFrame
*>(this); }
2454 * Return the last frame in our current flow.
2456 virtual nsIFrame
* LastInFlow() const { return const_cast<nsIFrame
*>(this); }
2459 * Note: "width" in the names and comments on the following methods
2460 * means inline-size, which could be height in vertical layout
2464 * Mark any stored intrinsic width information as dirty (requiring
2465 * re-calculation). Note that this should generally not be called
2466 * directly; PresShell::FrameNeedsReflow() will call it instead.
2468 virtual void MarkIntrinsicISizesDirty();
2471 nsBoxLayoutMetrics
* BoxMetrics() const;
2475 * Make this frame and all descendants dirty (if not already).
2476 * Exceptions: XULBoxFrame and TableColGroupFrame children.
2478 void MarkSubtreeDirty();
2481 * Get the min-content intrinsic inline size of the frame. This must be
2482 * less than or equal to the max-content intrinsic inline size.
2484 * This is *not* affected by the CSS 'min-width', 'width', and
2485 * 'max-width' properties on this frame, but it is affected by the
2486 * values of those properties on this frame's descendants. (It may be
2487 * called during computation of the values of those properties, so it
2488 * cannot depend on any values in the nsStylePosition for this frame.)
2490 * The value returned should **NOT** include the space required for
2491 * padding and border.
2493 * Note that many frames will cache the result of this function call
2494 * unless MarkIntrinsicISizesDirty is called.
2496 * It is not acceptable for a frame to mark itself dirty when this
2499 * This method must not return a negative value.
2501 virtual nscoord
GetMinISize(gfxContext
* aRenderingContext
);
2504 * Get the max-content intrinsic inline size of the frame. This must be
2505 * greater than or equal to the min-content intrinsic inline size.
2507 * Otherwise, all the comments for |GetMinISize| above apply.
2509 virtual nscoord
GetPrefISize(gfxContext
* aRenderingContext
);
2512 * |InlineIntrinsicISize| represents the intrinsic width information
2513 * in inline layout. Code that determines the intrinsic width of a
2514 * region of inline layout accumulates the result into this structure.
2515 * This pattern is needed because we need to maintain state
2516 * information about whitespace (for both collapsing and trimming).
2518 struct InlineIntrinsicISizeData
{
2519 InlineIntrinsicISizeData()
2521 mLineContainer(nullptr),
2524 mTrailingWhitespace(0),
2525 mSkipWhitespace(true) {}
2527 // The line. This may be null if the inlines are not associated with
2528 // a block or if we just don't know the line.
2529 const nsLineList_iterator
* mLine
;
2531 // The line container. Private, to ensure we always use SetLineContainer
2534 // Note that nsContainerFrame::DoInlineIntrinsicISize will clear the
2535 // |mLine| and |mLineContainer| fields when following a next-in-flow link,
2536 // so we must not assume these can always be dereferenced.
2538 nsIFrame
* mLineContainer
;
2540 // Setter and getter for the lineContainer field:
2542 void SetLineContainer(nsIFrame
* aLineContainer
) {
2543 mLineContainer
= aLineContainer
;
2545 nsIFrame
* LineContainer() const { return mLineContainer
; }
2547 // The maximum intrinsic width for all previous lines.
2550 // The maximum intrinsic width for the current line. At a line
2551 // break (mandatory for preferred width; allowed for minimum width),
2552 // the caller should call |Break()|.
2553 nscoord mCurrentLine
;
2555 // This contains the width of the trimmable whitespace at the end of
2556 // |mCurrentLine|; it is zero if there is no such whitespace.
2557 nscoord mTrailingWhitespace
;
2559 // True if initial collapsable whitespace should be skipped. This
2560 // should be true at the beginning of a block, after hard breaks
2561 // and when the last text ended with whitespace.
2562 bool mSkipWhitespace
;
2564 // Floats encountered in the lines.
2567 FloatInfo(const nsIFrame
* aFrame
, nscoord aWidth
)
2568 : mFrame(aFrame
), mWidth(aWidth
) {}
2569 const nsIFrame
* Frame() const { return mFrame
; }
2570 nscoord
Width() const { return mWidth
; }
2573 const nsIFrame
* mFrame
;
2577 nsTArray
<FloatInfo
> mFloats
;
2580 struct InlineMinISizeData
: public InlineIntrinsicISizeData
{
2581 InlineMinISizeData() : mAtStartOfLine(true) {}
2583 // The default implementation for nsIFrame::AddInlineMinISize.
2584 void DefaultAddInlineMinISize(nsIFrame
* aFrame
, nscoord aISize
,
2585 bool aAllowBreak
= true);
2587 // We need to distinguish forced and optional breaks for cases where the
2588 // current line total is negative. When it is, we need to ignore
2589 // optional breaks to prevent min-width from ending up bigger than
2593 // If the break here is actually taken, aHyphenWidth must be added to the
2594 // width of the current line.
2595 void OptionallyBreak(nscoord aHyphenWidth
= 0);
2597 // Whether we're currently at the start of the line. If we are, we
2598 // can't break (for example, between the text-indent and the first
2600 bool mAtStartOfLine
;
2603 struct InlinePrefISizeData
: public InlineIntrinsicISizeData
{
2604 typedef mozilla::StyleClear StyleClear
;
2606 InlinePrefISizeData() : mLineIsEmpty(true) {}
2609 * Finish the current line and start a new line.
2611 * @param aBreakType controls whether isize of floats are considered
2612 * and what floats are kept for the next line:
2613 * * |None| skips handling floats, which means no floats are
2614 * removed, and isizes of floats are not considered either.
2615 * * |Both| takes floats into consideration when computing isize
2616 * of the current line, and removes all floats after that.
2617 * * |Left| and |Right| do the same as |Both| except that they only
2618 * remove floats on the given side, and any floats on the other
2619 * side that are prior to a float on the given side that has a
2620 * 'clear' property that clears them.
2621 * All other values of StyleClear must be converted to the four
2622 * physical values above for this function.
2624 void ForceBreak(StyleClear aBreakType
= StyleClear::Both
);
2626 // The default implementation for nsIFrame::AddInlinePrefISize.
2627 void DefaultAddInlinePrefISize(nscoord aISize
);
2629 // True if the current line contains nothing other than placeholders.
2634 * Add the intrinsic minimum width of a frame in a way suitable for
2635 * use in inline layout to an |InlineIntrinsicISizeData| object that
2636 * represents the intrinsic width information of all the previous
2637 * frames in the inline layout region.
2639 * All *allowed* breakpoints within the frame determine what counts as
2640 * a line for the |InlineIntrinsicISizeData|. This means that
2641 * |aData->mTrailingWhitespace| will always be zero (unlike for
2642 * AddInlinePrefISize).
2644 * All the comments for |GetMinISize| apply, except that this function
2645 * is responsible for adding padding, border, and margin and for
2646 * considering the effects of 'width', 'min-width', and 'max-width'.
2648 * This may be called on any frame. Frames that do not participate in
2649 * line breaking can inherit the default implementation on nsFrame,
2650 * which calls |GetMinISize|.
2652 virtual void AddInlineMinISize(gfxContext
* aRenderingContext
,
2653 InlineMinISizeData
* aData
);
2656 * Add the intrinsic preferred width of a frame in a way suitable for
2657 * use in inline layout to an |InlineIntrinsicISizeData| object that
2658 * represents the intrinsic width information of all the previous
2659 * frames in the inline layout region.
2661 * All the comments for |AddInlineMinISize| and |GetPrefISize| apply,
2662 * except that this fills in an |InlineIntrinsicISizeData| structure
2663 * based on using all *mandatory* breakpoints within the frame.
2665 virtual void AddInlinePrefISize(gfxContext
* aRenderingContext
,
2666 InlinePrefISizeData
* aData
);
2669 * Intrinsic size of a frame in a single axis.
2671 * This can represent either isize or bsize.
2673 struct IntrinsicSizeOffsetData
{
2674 nscoord padding
= 0;
2677 nscoord
BorderPadding() const { return border
+ padding
; };
2681 * Return the isize components of padding, border, and margin
2682 * that contribute to the intrinsic width that applies to the parent.
2683 * @param aPercentageBasis the percentage basis to use for padding/margin -
2684 * i.e. the Containing Block's inline-size
2686 virtual IntrinsicSizeOffsetData
IntrinsicISizeOffsets(
2687 nscoord aPercentageBasis
= NS_UNCONSTRAINEDSIZE
);
2690 * Return the bsize components of padding, border, and margin
2691 * that contribute to the intrinsic width that applies to the parent.
2692 * @param aPercentageBasis the percentage basis to use for padding/margin -
2693 * i.e. the Containing Block's inline-size
2695 IntrinsicSizeOffsetData
IntrinsicBSizeOffsets(
2696 nscoord aPercentageBasis
= NS_UNCONSTRAINEDSIZE
);
2698 virtual mozilla::IntrinsicSize
GetIntrinsicSize();
2701 * Get the preferred aspect ratio of this frame, or a default-constructed
2702 * AspectRatio if it has none.
2704 * https://drafts.csswg.org/css-sizing-4/#preferred-aspect-ratio
2706 mozilla::AspectRatio
GetAspectRatio() const;
2709 * Get the intrinsic aspect ratio of this frame, or a default-constructed
2710 * AspectRatio if it has no intrinsic ratio.
2712 * The intrinsic ratio is the ratio of the width/height of a box with an
2713 * intrinsic size or the intrinsic aspect ratio of a scalable vector image
2714 * without an intrinsic size. A frame class implementing a replaced element
2715 * should override this method if it has a intrinsic ratio.
2717 virtual mozilla::AspectRatio
GetIntrinsicRatio() const;
2720 * Compute the size that a frame will occupy. Called while
2721 * constructing the ReflowInput to be used to Reflow the frame,
2722 * in order to fill its mComputedWidth and mComputedHeight member
2725 * Note that the reason that border and padding need to be passed
2726 * separately is so that the 'box-sizing' property can be handled.
2727 * Thus aMargin includes absolute positioning offsets as well.
2729 * @param aWM The writing mode to use for the returned size (need not match
2730 * this frame's writing mode). This is also the writing mode of
2731 * the passed-in LogicalSize parameters.
2732 * @param aCBSize The size of the element's containing block. (Well,
2733 * the BSize() component isn't really.)
2734 * @param aAvailableISize The available inline-size for 'auto' inline-size.
2735 * This is usually the same as aCBSize.ISize(),
2736 * but differs in cases such as block
2737 * formatting context roots next to floats, or
2738 * in some cases of float reflow in quirks
2740 * @param aMargin The sum of the inline / block margins ***AND***
2741 * absolute positioning offsets (inset-block and
2742 * inset-inline) of the frame, including actual values
2743 * resulting from percentages and from the
2744 * "hypothetical box" for absolute positioning, but
2745 * not including actual values resulting from 'auto'
2746 * margins or ignored 'auto' values in absolute
2748 * @param aBorderPadding The sum of the frame's inline / block border-widths
2749 * and padding (including actual values resulting from
2750 * percentage padding values).
2751 * @param aSizeOverride Optional override values for size properties, which
2752 * this function will use internally instead of the
2753 * actual property values.
2754 * @param aFlags Flags to further customize behavior (definitions in
2755 * LayoutConstants.h).
2757 * The return value includes the computed LogicalSize and AspectRatioUsage
2758 * which indicates whether the inline/block size is affected by aspect-ratio
2759 * or not. The BSize() of the returned LogicalSize may be
2760 * NS_UNCONSTRAINEDSIZE, but the ISize() must not be. We need AspectRatioUsage
2761 * during reflow because the final size may be affected by the content size
2762 * after applying aspect-ratio.
2763 * https://drafts.csswg.org/css-sizing-4/#aspect-ratio-minimum
2766 enum class AspectRatioUsage
: uint8_t {
2771 struct SizeComputationResult
{
2772 mozilla::LogicalSize mLogicalSize
;
2773 AspectRatioUsage mAspectRatioUsage
= AspectRatioUsage::None
;
2775 virtual SizeComputationResult
ComputeSize(
2776 gfxContext
* aRenderingContext
, mozilla::WritingMode aWM
,
2777 const mozilla::LogicalSize
& aCBSize
, nscoord aAvailableISize
,
2778 const mozilla::LogicalSize
& aMargin
,
2779 const mozilla::LogicalSize
& aBorderPadding
,
2780 const mozilla::StyleSizeOverrides
& aSizeOverrides
,
2781 mozilla::ComputeSizeFlags aFlags
);
2785 * A helper, used by |nsIFrame::ComputeSize| (for frames that need to
2786 * override only this part of ComputeSize), that computes the size
2787 * that should be returned when inline-size, block-size, and
2788 * [min|max]-[inline-size|block-size] are all 'auto' or equivalent.
2790 * In general, frames that can accept any computed inline-size/block-size
2791 * should override only ComputeAutoSize, and frames that cannot do so need to
2792 * override ComputeSize to enforce their inline-size/block-size invariants.
2794 * Implementations may optimize by returning a garbage inline-size if
2795 * StylePosition()->ISize() is not 'auto' (or inline-size override in
2796 * aSizeOverrides is not 'auto' if provided), and likewise for BSize(), since
2797 * in such cases the result is guaranteed to be unused.
2799 * Most of the frame are not expected to check the aSizeOverrides parameter
2800 * apart from checking the inline size override for 'auto' if they want to
2801 * optimize and return garbage inline-size.
2803 virtual mozilla::LogicalSize
ComputeAutoSize(
2804 gfxContext
* aRenderingContext
, mozilla::WritingMode aWM
,
2805 const mozilla::LogicalSize
& aCBSize
, nscoord aAvailableISize
,
2806 const mozilla::LogicalSize
& aMargin
,
2807 const mozilla::LogicalSize
& aBorderPadding
,
2808 const mozilla::StyleSizeOverrides
& aSizeOverrides
,
2809 mozilla::ComputeSizeFlags aFlags
);
2812 * Utility function for ComputeAutoSize implementations. Return
2813 * max(GetMinISize(), min(aISizeInCB, GetPrefISize()))
2815 nscoord
ShrinkWidthToFit(gfxContext
* aRenderingContext
, nscoord aISizeInCB
,
2816 mozilla::ComputeSizeFlags aFlags
);
2820 * Compute a tight bounding rectangle for the frame. This is a rectangle
2821 * that encloses the pixels that are actually drawn. We're allowed to be
2822 * conservative and currently we don't try very hard. The rectangle is
2823 * in appunits and relative to the origin of this frame.
2825 * This probably only needs to include frame bounds, glyph bounds, and
2826 * text decorations, but today it sometimes includes other things that
2827 * contribute to ink overflow.
2829 * @param aDrawTarget a draw target that can be used if we need
2832 virtual nsRect
ComputeTightBounds(DrawTarget
* aDrawTarget
) const;
2835 * This function is similar to GetPrefISize and ComputeTightBounds: it
2836 * computes the left and right coordinates of a preferred tight bounding
2837 * rectangle for the frame. This is a rectangle that would enclose the pixels
2838 * that are drawn if we lay out the element without taking any optional line
2839 * breaks. The rectangle is in appunits and relative to the origin of this
2840 * frame. Currently, this function is only implemented for nsBlockFrame and
2841 * nsTextFrame and is used to determine intrinsic widths of MathML token
2844 * @param aContext a rendering context that can be used if we need
2846 * @param aX computed left coordinate of the tight bounding rectangle
2847 * @param aXMost computed intrinsic width of the tight bounding rectangle
2850 virtual nsresult
GetPrefWidthTightBounds(gfxContext
* aContext
, nscoord
* aX
,
2854 * The frame is given an available size and asked for its desired
2855 * size. This is the frame's opportunity to reflow its children.
2857 * If the frame has the NS_FRAME_IS_DIRTY bit set then it is
2858 * responsible for completely reflowing itself and all of its
2861 * Otherwise, if the frame has the NS_FRAME_HAS_DIRTY_CHILDREN bit
2862 * set, then it is responsible for reflowing at least those
2863 * children that have NS_FRAME_HAS_DIRTY_CHILDREN or NS_FRAME_IS_DIRTY
2866 * If a difference in available size from the previous reflow causes
2867 * the frame's size to change, it should reflow descendants as needed.
2869 * Calculates the size of this frame after reflowing (calling Reflow on, and
2870 * updating the size and position of) its children, as necessary. The
2871 * calculated size is returned to the caller via the ReflowOutput
2872 * outparam. (The caller is responsible for setting the actual size and
2873 * position of this frame.)
2875 * A frame's children must _all_ be reflowed if the frame is dirty (the
2876 * NS_FRAME_IS_DIRTY bit is set on it). Otherwise, individual children
2877 * must be reflowed if they are dirty or have the NS_FRAME_HAS_DIRTY_CHILDREN
2878 * bit set on them. Otherwise, whether children need to be reflowed depends
2879 * on the frame's type (it's up to individual Reflow methods), and on what
2880 * has changed. For example, a change in the width of the frame may require
2881 * all of its children to be reflowed (even those without dirty bits set on
2882 * them), whereas a change in its height might not.
2883 * (ReflowInput::ShouldReflowAllKids may be helpful in deciding whether
2884 * to reflow all the children, but for some frame types it might result in
2887 * Note: if it's only the overflow rect(s) of a frame that need to be
2888 * updated, then UpdateOverflow should be called instead of Reflow.
2890 * @param aReflowOutput <i>out</i> parameter where you should return the
2891 * desired size and ascent/descent info. You should include any
2892 * space you want for border/padding in the desired size you return.
2894 * It's okay to return a desired size that exceeds the avail
2895 * size if that's the smallest you can be, i.e. it's your
2898 * For an incremental reflow you are responsible for invalidating
2899 * any area within your frame that needs repainting (including
2900 * borders). If your new desired size is different than your current
2901 * size, then your parent frame is responsible for making sure that
2902 * the difference between the two rects is repainted
2904 * @param aReflowInput information about your reflow including the reason
2905 * for the reflow and the available space in which to lay out. Each
2906 * dimension of the available space can either be constrained or
2907 * unconstrained (a value of NS_UNCONSTRAINEDSIZE).
2909 * Note that the available space can be negative. In this case you
2910 * still must return an accurate desired size. If you're a container
2911 * you must <b>always</b> reflow at least one frame regardless of the
2914 * @param aStatus a return value indicating whether the frame is complete
2915 * and whether the next-in-flow is dirty and needs to be reflowed
2917 virtual void Reflow(nsPresContext
* aPresContext
, ReflowOutput
& aReflowOutput
,
2918 const ReflowInput
& aReflowInput
, nsReflowStatus
& aStatus
);
2920 // Option flags for ReflowChild(), FinishReflowChild(), and
2921 // SyncFrameViewAfterReflow().
2922 enum class ReflowChildFlags
: uint32_t {
2925 // Don't position the frame's view. Set this if you don't want to
2926 // automatically sync the frame and view.
2927 NoMoveView
= 1 << 0,
2929 // Don't move the frame. Also implies NoMoveView.
2930 NoMoveFrame
= (1 << 1) | NoMoveView
,
2932 // Don't size the frame's view.
2933 NoSizeView
= 1 << 2,
2935 // Only applies to ReflowChild; if true, don't delete the next-in-flow, even
2936 // if the reflow is fully complete.
2937 NoDeleteNextInFlowChild
= 1 << 3,
2939 // Only applies to FinishReflowChild. Tell it to call
2940 // ApplyRelativePositioning.
2941 ApplyRelativePositioning
= 1 << 4,
2945 * Post-reflow hook. After a frame is reflowed this method will be called
2946 * informing the frame that this reflow process is complete, and telling the
2947 * frame the status returned by the Reflow member function.
2949 * This call may be invoked many times, while NS_FRAME_IN_REFLOW is set,
2950 * before it is finally called once with a NS_FRAME_REFLOW_COMPLETE value.
2951 * When called with a NS_FRAME_REFLOW_COMPLETE value the NS_FRAME_IN_REFLOW
2952 * bit in the frame state will be cleared.
2954 * XXX This doesn't make sense. If the frame is reflowed but not complete,
2955 * then the status should have IsIncomplete() equal to true.
2956 * XXX Don't we want the semantics to dictate that we only call this once for
2959 virtual void DidReflow(nsPresContext
* aPresContext
,
2960 const ReflowInput
* aReflowInput
);
2962 void FinishReflowWithAbsoluteFrames(nsPresContext
* aPresContext
,
2963 ReflowOutput
& aDesiredSize
,
2964 const ReflowInput
& aReflowInput
,
2965 nsReflowStatus
& aStatus
,
2966 bool aConstrainBSize
= true);
2969 * Updates the overflow areas of the frame. This can be called if an
2970 * overflow area of the frame's children has changed without reflowing.
2971 * @return true if either of the overflow areas for this frame have changed.
2973 bool UpdateOverflow();
2976 * Computes any overflow area created by the frame itself (outside of the
2977 * frame bounds) and includes it into aOverflowAreas.
2979 * Returns false if updating overflow isn't supported for this frame.
2980 * If the frame requires a reflow instead, then it is responsible
2981 * for scheduling one.
2983 virtual bool ComputeCustomOverflow(mozilla::OverflowAreas
& aOverflowAreas
);
2986 * Computes any overflow area created by children of this frame and
2987 * includes it into aOverflowAreas.
2989 virtual void UnionChildOverflow(mozilla::OverflowAreas
& aOverflowAreas
);
2991 // Represents zero or more physical axes.
2992 enum class PhysicalAxes
: uint8_t {
2996 Both
= Horizontal
| Vertical
,
3000 * Returns true if this frame should apply overflow clipping.
3002 PhysicalAxes
ShouldApplyOverflowClipping(const nsStyleDisplay
* aDisp
) const;
3005 * Helper method used by block reflow to identify runs of text so
3006 * that proper word-breaking can be done.
3009 * true if we can continue a "text run" through the frame. A
3010 * text run is text that should be treated contiguously for line
3011 * and word breaking.
3013 virtual bool CanContinueTextRun() const;
3016 * Computes an approximation of the rendered text of the frame and its
3017 * continuations. Returns nothing for non-text frames.
3018 * The appended text will often not contain all the whitespace from source,
3019 * depending on CSS white-space processing.
3020 * if aEndOffset goes past end, use the text up to the string's end.
3021 * Call this on the primary frame for a text node.
3022 * aStartOffset and aEndOffset can be content offsets or offsets in the
3023 * rendered text, depending on aOffsetType.
3024 * Returns a string, as well as offsets identifying the start of the text
3025 * within the rendered text for the whole node, and within the text content
3028 struct RenderedText
{
3029 nsAutoString mString
;
3030 uint32_t mOffsetWithinNodeRenderedText
;
3031 int32_t mOffsetWithinNodeText
;
3033 : mOffsetWithinNodeRenderedText(0), mOffsetWithinNodeText(0) {}
3035 enum class TextOffsetType
{
3036 // Passed-in start and end offsets are within the content text.
3037 OffsetsInContentText
,
3038 // Passed-in start and end offsets are within the rendered text.
3039 OffsetsInRenderedText
,
3041 enum class TrailingWhitespace
{
3043 // Spaces preceding a caret at the end of a line should not be trimmed
3046 virtual RenderedText
GetRenderedText(
3047 uint32_t aStartOffset
= 0, uint32_t aEndOffset
= UINT32_MAX
,
3048 TextOffsetType aOffsetType
= TextOffsetType::OffsetsInContentText
,
3049 TrailingWhitespace aTrimTrailingWhitespace
= TrailingWhitespace::Trim
) {
3050 return RenderedText();
3054 * Returns true if the frame contains any non-collapsed characters.
3055 * This method is only available for text frames, and it will return false
3056 * for all other frame types.
3058 virtual bool HasAnyNoncollapsedCharacters() { return false; }
3061 * Returns true if events of the given type targeted at this frame
3062 * should only be dispatched to the system group.
3064 virtual bool OnlySystemGroupDispatch(mozilla::EventMessage aMessage
) const {
3069 // Accessor functions to an associated view object:
3071 bool HasView() const { return !!(mState
& NS_FRAME_HAS_VIEW
); }
3074 * Helper method to create a view for a frame. Only used by a few sub-classes
3080 virtual nsView
* GetViewInternal() const {
3081 MOZ_ASSERT_UNREACHABLE("method should have been overridden by subclass");
3084 virtual void SetViewInternal(nsView
* aView
) {
3085 MOZ_ASSERT_UNREACHABLE("method should have been overridden by subclass");
3089 nsView
* GetView() const {
3090 if (MOZ_LIKELY(!HasView())) {
3093 nsView
* view
= GetViewInternal();
3094 MOZ_ASSERT(view
, "GetViewInternal() should agree with HasView()");
3097 void SetView(nsView
* aView
);
3100 * Find the closest view (on |this| or an ancestor).
3101 * If aOffset is non-null, it will be set to the offset of |this|
3102 * from the returned view.
3104 nsView
* GetClosestView(nsPoint
* aOffset
= nullptr) const;
3107 * Find the closest ancestor (excluding |this| !) that has a view
3109 nsIFrame
* GetAncestorWithView() const;
3112 * Sets the view's attributes from the frame style.
3113 * Call this for nsChangeHint_SyncFrameView style changes or when the view
3114 * has just been created.
3115 * @param aView the frame's view or use GetView() if nullptr is given
3117 void SyncFrameViewProperties(nsView
* aView
= nullptr);
3120 * Get the offset between the coordinate systems of |this| and aOther.
3121 * Adding the return value to a point in the coordinate system of |this|
3122 * will transform the point to the coordinate system of aOther.
3124 * aOther must be non-null.
3126 * This function is fastest when aOther is an ancestor of |this|.
3128 * This function _DOES NOT_ work across document boundaries.
3129 * Use this function only when |this| and aOther are in the same document.
3131 * NOTE: this actually returns the offset from aOther to |this|, but
3132 * that offset is added to transform _coordinates_ from |this| to
3135 nsPoint
GetOffsetTo(const nsIFrame
* aOther
) const;
3138 * Just like GetOffsetTo, but treats all scrollframes as scrolled to
3141 nsPoint
GetOffsetToIgnoringScrolling(const nsIFrame
* aOther
) const;
3144 * Get the offset between the coordinate systems of |this| and aOther
3145 * expressed in appunits per dev pixel of |this|' document. Adding the return
3146 * value to a point that is relative to the origin of |this| will make the
3147 * point relative to the origin of aOther but in the appunits per dev pixel
3150 * aOther must be non-null.
3152 * This function is fastest when aOther is an ancestor of |this|.
3154 * This function works across document boundaries.
3156 * Because this function may cross document boundaries that have different
3157 * app units per dev pixel ratios it needs to be used very carefully.
3159 * NOTE: this actually returns the offset from aOther to |this|, but
3160 * that offset is added to transform _coordinates_ from |this| to
3163 nsPoint
GetOffsetToCrossDoc(const nsIFrame
* aOther
) const;
3166 * Like GetOffsetToCrossDoc, but the caller can specify which appunits
3167 * to return the result in.
3169 nsPoint
GetOffsetToCrossDoc(const nsIFrame
* aOther
, const int32_t aAPD
) const;
3172 * Get the rect of the frame relative to the top-left corner of the
3173 * screen in CSS pixels.
3174 * @return the CSS pixel rect of the frame relative to the top-left
3175 * corner of the screen.
3177 mozilla::CSSIntRect
GetScreenRect() const;
3180 * Get the screen rect of the frame in app units.
3181 * @return the app unit rect of the frame in screen coordinates.
3183 nsRect
GetScreenRectInAppUnits() const;
3186 * Returns the offset from this frame to the closest geometric parent that
3187 * has a view. Also returns the containing view or null in case of error
3189 void GetOffsetFromView(nsPoint
& aOffset
, nsView
** aView
) const;
3192 * Returns the nearest widget containing this frame. If this frame has a
3193 * view and the view has a widget, then this frame's widget is
3194 * returned, otherwise this frame's geometric parent is checked
3195 * recursively upwards.
3197 nsIWidget
* GetNearestWidget() const;
3200 * Same as GetNearestWidget() above but uses an outparam to return the offset
3201 * of this frame to the returned widget expressed in appunits of |this| (the
3202 * widget might be in a different document with a different zoom).
3204 nsIWidget
* GetNearestWidget(nsPoint
& aOffset
) const;
3207 * Whether the content for this frame is disabled, used for event handling.
3209 bool IsContentDisabled() const;
3212 * Get the "type" of the frame.
3214 * @see mozilla::LayoutFrameType
3216 mozilla::LayoutFrameType
Type() const {
3217 MOZ_ASSERT(uint8_t(mClass
) < mozilla::ArrayLength(sLayoutFrameTypes
));
3218 return sLayoutFrameTypes
[uint8_t(mClass
)];
3222 # pragma GCC diagnostic push
3223 # pragma GCC diagnostic ignored "-Wtype-limits"
3226 # pragma clang diagnostic push
3227 # pragma clang diagnostic ignored "-Wunknown-pragmas"
3228 # pragma clang diagnostic ignored "-Wtautological-unsigned-zero-compare"
3231 #define FRAME_TYPE(name_, first_class_, last_class_) \
3232 bool Is##name_##Frame() const { \
3233 return uint8_t(mClass) >= uint8_t(ClassID::first_class_##_id) && \
3234 uint8_t(mClass) <= uint8_t(ClassID::last_class_##_id); \
3236 #include "mozilla/FrameTypeList.h"
3240 # pragma GCC diagnostic pop
3243 # pragma clang diagnostic pop
3247 * Returns a transformation matrix that converts points in this frame's
3248 * coordinate space to points in some ancestor frame's coordinate space.
3249 * The frame decides which ancestor it will use as a reference point.
3250 * If this frame has no ancestor, aOutAncestor will be set to null.
3252 * @param aViewportType specifies whether the starting point is layout
3253 * or visual coordinates
3254 * @param aStopAtAncestor don't look further than aStopAtAncestor. If null,
3255 * all ancestors (including across documents) will be traversed.
3256 * @param aOutAncestor [out] The ancestor frame the frame has chosen. If
3257 * this frame has no ancestor, *aOutAncestor will be set to null. If
3258 * this frame is not a root frame, then *aOutAncestor will be in the same
3259 * document as this frame. If this frame IsTransformed(), then *aOutAncestor
3260 * will be the parent frame (if not preserve-3d) or the nearest
3261 * non-transformed ancestor (if preserve-3d).
3262 * @return A Matrix4x4 that converts points in the coordinate space
3263 * RelativeTo{this, aViewportType} into points in aOutAncestor's
3267 IN_CSS_UNITS
= 1 << 0,
3268 STOP_AT_STACKING_CONTEXT_AND_DISPLAY_PORT
= 1 << 1
3270 Matrix4x4Flagged
GetTransformMatrix(mozilla::ViewportType aViewportType
,
3271 mozilla::RelativeTo aStopAtAncestor
,
3272 nsIFrame
** aOutAncestor
,
3273 uint32_t aFlags
= 0) const;
3276 * Bit-flags to pass to IsFrameOfType()
3281 eSVGContainer
= 1 << 2,
3282 eBidiInlineContainer
= 1 << 3,
3283 // the frame is for a replaced element, such as an image
3285 // Frame that contains a block but looks like a replaced element
3287 eReplacedContainsBlock
= 1 << 5,
3288 // A frame that participates in inline reflow, i.e., one that
3289 // requires ReflowInput::mLineLayout.
3290 eLineParticipant
= 1 << 6,
3292 eCanContainOverflowContainers
= 1 << 8,
3293 eTablePart
= 1 << 9,
3294 eSupportsCSSTransforms
= 1 << 10,
3296 // A replaced element that has replaced-element sizing
3297 // characteristics (i.e., like images or iframes), as opposed to
3298 // inline-block sizing characteristics (like form controls).
3299 eReplacedSizing
= 1 << 11,
3301 // Does this frame class support 'contain: layout' and
3302 // 'contain:paint' (supporting one is equivalent to supporting the
3304 eSupportsContainLayoutAndPaint
= 1 << 12,
3306 // Does this frame class support `aspect-ratio` property.
3307 eSupportsAspectRatio
= 1 << 13,
3309 // These are to allow nsIFrame::Init to assert that IsFrameOfType
3310 // implementations all call the base class method. They are only
3311 // meaningful in DEBUG builds.
3312 eDEBUGAllFrames
= 1 << 30,
3313 eDEBUGNoFrames
= 1 << 31
3317 * API for doing a quick check if a frame is of a given
3318 * type. Returns true if the frame matches ALL flags passed in.
3320 * Implementations should always override with inline virtual
3321 * functions that call the base class's IsFrameOfType method.
3323 virtual bool IsFrameOfType(uint32_t aFlags
) const {
3324 return !(aFlags
& ~(
3326 nsIFrame::eDEBUGAllFrames
|
3328 nsIFrame::eSupportsCSSTransforms
|
3329 nsIFrame::eSupportsContainLayoutAndPaint
|
3330 nsIFrame::eSupportsAspectRatio
));
3334 * Return true if this frame's preferred size property or max size property
3335 * contains a percentage value that should be resolved against zero when
3336 * calculating its min-content contribution in the corresponding axis.
3338 * This is a special case for webcompat required by CSS Sizing 3 §5.2.1c
3339 * https://drafts.csswg.org/css-sizing-3/#replaced-percentage-min-contribution,
3340 * and applies only to some replaced elements and form control elements. See
3341 * CSS Sizing 3 §5.2.2 for the list of elements this rule applies to.
3342 * https://drafts.csswg.org/css-sizing-3/#min-content-zero
3344 * Bug 1463700: some callers may not match the spec by resolving the entire
3345 * preferred size property or max size property against zero.
3347 bool IsPercentageResolvedAgainstZero(
3348 const mozilla::StyleSize
& aStyleSize
,
3349 const mozilla::StyleMaxSize
& aStyleMaxSize
) const;
3352 * Returns true if the frame is a block wrapper.
3354 bool IsBlockWrapper() const;
3357 * Returns true if the frame is an instance of nsBlockFrame or one of its
3360 bool IsBlockFrameOrSubclass() const;
3363 * Returns true if the frame is an instance of SVGGeometryFrame or one
3364 * of its subclasses.
3366 inline bool IsSVGGeometryFrameOrSubclass() const;
3369 * Get this frame's CSS containing block.
3371 * The algorithm is defined in
3372 * http://www.w3.org/TR/CSS2/visudet.html#containing-block-details.
3374 * NOTE: This is guaranteed to return a non-null pointer when invoked on any
3375 * frame other than the root frame.
3377 * Requires SKIP_SCROLLED_FRAME to get behaviour matching the spec, otherwise
3378 * it can return anonymous inner scrolled frames. Bug 1204044 is filed for
3379 * investigating whether any of the callers actually require the default
3383 // If the containing block is an anonymous scrolled frame, then skip over
3384 // this and return the outer scroll frame.
3385 SKIP_SCROLLED_FRAME
= 0x01
3387 nsIFrame
* GetContainingBlock(uint32_t aFlags
,
3388 const nsStyleDisplay
* aStyleDisplay
) const;
3389 nsIFrame
* GetContainingBlock(uint32_t aFlags
= 0) const {
3390 return GetContainingBlock(aFlags
, StyleDisplay());
3394 * Is this frame a containing block for floating elements?
3395 * Note that very few frames are, so default to false.
3397 virtual bool IsFloatContainingBlock() const { return false; }
3400 * Is this a leaf frame? Frames that want the frame constructor to be able
3401 * to construct kids for them should return false, all others should return
3402 * true. Note that returning true here does not mean that the frame _can't_
3403 * have kids. It could still have kids created via
3404 * nsIAnonymousContentCreator. Returning true indicates that "normal"
3405 * (non-anonymous, CSS generated content, etc) children should not be
3408 bool IsLeaf() const {
3409 MOZ_ASSERT(uint8_t(mClass
) < mozilla::ArrayLength(sFrameClassBits
));
3410 FrameClassBits bits
= sFrameClassBits
[uint8_t(mClass
)];
3411 if (MOZ_UNLIKELY(bits
& eFrameClassBitsDynamicLeaf
)) {
3412 return IsLeafDynamic();
3414 return bits
& eFrameClassBitsLeaf
;
3418 * Marks all display items created by this frame as needing a repaint,
3419 * and calls SchedulePaint() if requested and one is not already pending.
3421 * This includes all display items created by this frame, including
3424 * @param aDisplayItemKey If specified, only issues an invalidate
3425 * if this frame painted a display item of that type during the
3426 * previous paint. SVG rendering observers are always notified.
3427 * @param aRebuildDisplayItems If true, then adds this frame to the
3428 * list of modified frames for display list building. Only pass false
3429 * if you're sure that the relevant display items will be rebuilt
3430 * already (possibly by an ancestor being in the modified list).
3432 virtual void InvalidateFrame(uint32_t aDisplayItemKey
= 0,
3433 bool aRebuildDisplayItems
= true);
3436 * Same as InvalidateFrame(), but only mark a fixed rect as needing
3439 * @param aRect The rect to invalidate, relative to the TopLeft of the
3440 * frame's border box.
3441 * @param aDisplayItemKey If specified, only issues an invalidate
3442 * if this frame painted a display item of that type during the
3443 * previous paint. SVG rendering observers are always notified.
3444 * @param aRebuildDisplayItems If true, then adds this frame to the
3445 * list of modified frames for display list building. Only pass false
3446 * if you're sure that the relevant display items will be rebuilt
3447 * already (possibly by an ancestor being in the modified list).
3449 virtual void InvalidateFrameWithRect(const nsRect
& aRect
,
3450 uint32_t aDisplayItemKey
= 0,
3451 bool aRebuildDisplayItems
= true);
3454 * Calls InvalidateFrame() on all frames descendant frames (including
3457 * This function doesn't walk through placeholder frames to invalidate
3458 * the out-of-flow frames.
3460 * @param aRebuildDisplayItems If true, then adds this frame to the
3461 * list of modified frames for display list building. Only pass false
3462 * if you're sure that the relevant display items will be rebuilt
3463 * already (possibly by an ancestor being in the modified list).
3465 void InvalidateFrameSubtree(bool aRebuildDisplayItems
= true);
3468 * Called when a frame is about to be removed and needs to be invalidated.
3469 * Normally does nothing since DLBI handles removed frames.
3471 virtual void InvalidateFrameForRemoval() {}
3474 * When HasUserData(frame->LayerIsPrerenderedDataKey()), then the
3475 * entire overflow area of this frame has been rendered in its
3478 static void* LayerIsPrerenderedDataKey() {
3479 return &sLayerIsPrerenderedDataKey
;
3481 static uint8_t sLayerIsPrerenderedDataKey
;
3484 * Try to update this frame's transform without invalidating any
3485 * content. Return true iff successful. If unsuccessful, the
3486 * caller is responsible for scheduling an invalidating paint.
3488 * If the result is true, aLayerResult will be filled in with the
3489 * transform layer for the frame.
3491 bool TryUpdateTransformOnly(Layer
** aLayerResult
);
3494 * Checks if a frame has had InvalidateFrame() called on it since the
3497 * If true, then the invalid rect is returned in aRect, with an
3498 * empty rect meaning all pixels drawn by this frame should be
3500 * If false, aRect is left unchanged.
3502 bool IsInvalid(nsRect
& aRect
);
3505 * Check if any frame within the frame subtree (including this frame)
3506 * returns true for IsInvalid().
3508 bool HasInvalidFrameInSubtree() {
3509 return HasAnyStateBits(NS_FRAME_NEEDS_PAINT
|
3510 NS_FRAME_DESCENDANT_NEEDS_PAINT
);
3514 * Removes the invalid state from the current frame and all
3515 * descendant frames.
3517 void ClearInvalidationStateBits();
3520 * Ensures that the refresh driver is running, and schedules a view
3521 * manager flush on the next tick.
3523 * The view manager flush will update the layer tree, repaint any
3524 * invalid areas in the layer tree and schedule a layer tree
3525 * composite operation to display the layer tree.
3527 * In general it is not necessary for frames to call this when they change.
3528 * For example, changes that result in a reflow will have this called for
3529 * them by PresContext::DoReflow when the reflow begins. Style changes that
3530 * do not trigger a reflow should have this called for them by
3531 * DoApplyRenderingChangeToTree.
3533 * @param aType PAINT_COMPOSITE_ONLY : No changes have been made
3534 * that require a layer tree update, so only schedule a layer
3536 * PAINT_DELAYED_COMPRESS : Schedule a paint to be executed after a delay, and
3537 * put FrameLayerBuilder in 'compressed' mode that avoids short cut
3542 PAINT_COMPOSITE_ONLY
,
3543 PAINT_DELAYED_COMPRESS
3545 void SchedulePaint(PaintType aType
= PAINT_DEFAULT
,
3546 bool aFrameChanged
= true);
3548 // Similar to SchedulePaint() but without calling
3549 // InvalidateRenderingObservers() for SVG.
3550 void SchedulePaintWithoutInvalidatingObservers(
3551 PaintType aType
= PAINT_DEFAULT
);
3554 * Checks if the layer tree includes a dedicated layer for this
3555 * frame/display item key pair, and invalidates at least aDamageRect
3556 * area within that layer.
3558 * If no layer is found, calls InvalidateFrame() instead.
3560 * @param aDamageRect Area of the layer to invalidate.
3561 * @param aFrameDamageRect If no layer is found, the area of the frame to
3562 * invalidate. If null, the entire frame will be
3564 * @param aDisplayItemKey Display item type.
3565 * @param aFlags UPDATE_IS_ASYNC : Will skip the invalidation
3566 * if the found layer is being composited by a remote
3568 * @return Layer, if found, nullptr otherwise.
3570 enum { UPDATE_IS_ASYNC
= 1 << 0 };
3571 Layer
* InvalidateLayer(DisplayItemType aDisplayItemKey
,
3572 const nsIntRect
* aDamageRect
= nullptr,
3573 const nsRect
* aFrameDamageRect
= nullptr,
3574 uint32_t aFlags
= 0);
3576 void MarkNeedsDisplayItemRebuild();
3579 * Returns a rect that encompasses everything that might be painted by
3580 * this frame. This includes this frame, all its descendant frames, this
3581 * frame's outline, and descendant frames' outline, but does not include
3582 * areas clipped out by the CSS "overflow" and "clip" properties.
3584 * HasOverflowAreas() (below) will return true when this overflow
3585 * rect has been explicitly set, even if it matches mRect.
3586 * XXX Note: because of a space optimization using the formula above,
3587 * during reflow this function does not give accurate data if
3588 * FinishAndStoreOverflow has been called but mRect hasn't yet been
3589 * updated yet. FIXME: This actually isn't true, but it should be.
3591 * The ink overflow rect should NEVER be used for things that
3592 * affect layout. The scrollable overflow rect is permitted to affect
3595 * @return the rect relative to this frame's origin, but after
3596 * CSS transforms have been applied (i.e. not really this frame's coordinate
3597 * system, and may not contain the frame's border-box, e.g. if there
3598 * is a CSS transform scaling it down)
3600 nsRect
InkOverflowRect() const {
3601 return GetOverflowRect(mozilla::OverflowType::Ink
);
3605 * Returns a rect that encompasses the area of this frame that the
3606 * user should be able to scroll to reach. This is similar to
3607 * InkOverflowRect, but does not include outline or shadows, and
3608 * may in the future include more margins than ink overflow does.
3609 * It does not include areas clipped out by the CSS "overflow" and
3610 * "clip" properties.
3612 * HasOverflowAreas() (below) will return true when this overflow
3613 * rect has been explicitly set, even if it matches mRect.
3614 * XXX Note: because of a space optimization using the formula above,
3615 * during reflow this function does not give accurate data if
3616 * FinishAndStoreOverflow has been called but mRect hasn't yet been
3619 * @return the rect relative to this frame's origin, but after
3620 * CSS transforms have been applied (i.e. not really this frame's coordinate
3621 * system, and may not contain the frame's border-box, e.g. if there
3622 * is a CSS transform scaling it down)
3624 nsRect
ScrollableOverflowRect() const {
3625 return GetOverflowRect(mozilla::OverflowType::Scrollable
);
3628 nsRect
GetOverflowRect(mozilla::OverflowType aType
) const;
3630 mozilla::OverflowAreas
GetOverflowAreas() const;
3633 * Same as GetOverflowAreas, except in this frame's coordinate
3634 * system (before transforms are applied).
3636 * @return the overflow areas relative to this frame, before any CSS
3637 * transforms have been applied, i.e. in this frame's coordinate system
3639 mozilla::OverflowAreas
GetOverflowAreasRelativeToSelf() const;
3642 * Same as ScrollableOverflowRect, except relative to the parent
3645 * @return the rect relative to the parent frame, in the parent frame's
3648 nsRect
ScrollableOverflowRectRelativeToParent() const;
3651 * Same as ScrollableOverflowRect, except in this frame's coordinate
3652 * system (before transforms are applied).
3654 * @return the rect relative to this frame, before any CSS transforms have
3655 * been applied, i.e. in this frame's coordinate system
3657 nsRect
ScrollableOverflowRectRelativeToSelf() const;
3660 * Like InkOverflowRect, except in this frame's
3661 * coordinate system (before transforms are applied).
3663 * @return the rect relative to this frame, before any CSS transforms have
3664 * been applied, i.e. in this frame's coordinate system
3666 nsRect
InkOverflowRectRelativeToSelf() const;
3669 * Same as InkOverflowRect, except relative to the parent
3672 * @return the rect relative to the parent frame, in the parent frame's
3675 nsRect
InkOverflowRectRelativeToParent() const;
3678 * Returns this frame's ink overflow rect as it would be before taking
3679 * account of SVG effects or transforms. The rect returned is relative to
3682 nsRect
PreEffectsInkOverflowRect() const;
3685 * Store the overflow area in the frame's mOverflow.mVisualDeltas
3686 * fields or as a frame property in the frame manager so that it can
3687 * be retrieved later without reflowing the frame. Returns true if either of
3688 * the overflow areas changed.
3690 bool FinishAndStoreOverflow(mozilla::OverflowAreas
& aOverflowAreas
,
3691 nsSize aNewSize
, nsSize
* aOldSize
= nullptr,
3692 const nsStyleDisplay
* aStyleDisplay
= nullptr);
3694 bool FinishAndStoreOverflow(ReflowOutput
* aMetrics
,
3695 const nsStyleDisplay
* aStyleDisplay
= nullptr) {
3696 return FinishAndStoreOverflow(aMetrics
->mOverflowAreas
,
3697 nsSize(aMetrics
->Width(), aMetrics
->Height()),
3698 nullptr, aStyleDisplay
);
3702 * Returns whether the frame has an overflow rect that is different from
3705 bool HasOverflowAreas() const {
3706 return mOverflow
.mType
!= NS_FRAME_OVERFLOW_NONE
;
3710 * Removes any stored overflow rects (visual and scrollable) from the frame.
3711 * Returns true if the overflow changed.
3713 bool ClearOverflowRects();
3716 * Determine whether borders, padding, margins etc should NOT be applied
3717 * on certain sides of the frame.
3718 * @see mozilla::Sides in gfx/2d/BaseMargin.h
3719 * @see mozilla::LogicalSides in layout/generic/WritingModes.h
3721 * @note (See also bug 743402, comment 11) GetSkipSides() checks to see
3722 * if this frame has a previous or next continuation to determine
3723 * if a side should be skipped.
3724 * So this only works after the entire frame tree has been reflowed.
3725 * During reflow, if this frame can be split in the block axis, you
3726 * should use nsSplittableFrame::PreReflowBlockLevelLogicalSkipSides().
3728 Sides
GetSkipSides() const;
3729 virtual LogicalSides
GetLogicalSkipSides() const {
3730 return LogicalSides(mWritingMode
);
3734 * @returns true if this frame is selected.
3736 bool IsSelected() const {
3737 return (GetContent() && GetContent()->IsMaybeSelected()) ? IsFrameSelected()
3742 * Shouldn't be called if this is a `nsTextFrame`. Call the
3743 * `nsTextFrame::SelectionStateChanged` overload instead.
3745 void SelectionStateChanged() {
3746 MOZ_ASSERT(!IsTextFrame());
3747 InvalidateFrameSubtree(); // TODO: should this deal with continuations?
3751 * Called to discover where this frame, or a parent frame has user-select
3752 * style applied, which affects that way that it is selected.
3754 * @param aSelectStyle out param. Returns the type of selection style found
3755 * (using values defined in nsStyleConsts.h).
3757 * @return Whether the frame can be selected (i.e. is not affected by
3758 * user-select: none)
3760 bool IsSelectable(mozilla::StyleUserSelect
* aSelectStyle
) const;
3763 * Returns whether this frame should have the content-block-size of a line,
3766 bool ShouldHaveLineIfEmpty() const;
3769 * Called to retrieve the SelectionController associated with the frame.
3771 * @param aSelCon will contain the selection controller associated with
3774 nsresult
GetSelectionController(nsPresContext
* aPresContext
,
3775 nsISelectionController
** aSelCon
);
3778 * Call to get nsFrameSelection for this frame.
3780 already_AddRefed
<nsFrameSelection
> GetFrameSelection();
3783 * GetConstFrameSelection returns an object which methods are safe to use for
3784 * example in nsIFrame code.
3786 const nsFrameSelection
* GetConstFrameSelection() const;
3789 * called to find the previous/next character, word, or line. Returns the
3790 * actual nsIFrame and the frame offset. THIS DOES NOT CHANGE SELECTION STATE.
3791 * Uses frame's begin selection state to start. If no selection on this frame
3792 * will return NS_ERROR_FAILURE.
3794 * @param aPos is defined in nsFrameSelection
3796 virtual nsresult
PeekOffset(nsPeekOffsetStruct
* aPos
);
3799 nsresult
PeekOffsetForCharacter(nsPeekOffsetStruct
* aPos
, int32_t aOffset
);
3800 nsresult
PeekOffsetForWord(nsPeekOffsetStruct
* aPos
, int32_t aOffset
);
3801 nsresult
PeekOffsetForLine(nsPeekOffsetStruct
* aPos
);
3802 nsresult
PeekOffsetForLineEdge(nsPeekOffsetStruct
* aPos
);
3805 * Search for the first paragraph boundary before or after the given position
3806 * @param aPos See description in nsFrameSelection.h. The following fields
3807 * are used by this method:
3809 * Output: mResultContent, mContentOffset
3811 nsresult
PeekOffsetForParagraph(nsPeekOffsetStruct
* aPos
);
3814 // given a frame five me the first/last leaf available
3815 // XXX Robert O'Callahan wants to move these elsewhere
3816 static void GetLastLeaf(nsIFrame
** aFrame
);
3817 static void GetFirstLeaf(nsIFrame
** aFrame
);
3819 static nsresult
GetNextPrevLineFromeBlockFrame(nsPresContext
* aPresContext
,
3820 nsPeekOffsetStruct
* aPos
,
3821 nsIFrame
* aBlockFrame
,
3823 int8_t aOutSideLimit
);
3825 struct SelectablePeekReport
{
3826 /** the previous/next selectable leaf frame */
3827 nsIFrame
* mFrame
= nullptr;
3829 * 0 indicates that we arrived at the beginning of the output frame; -1
3830 * indicates that we arrived at its end.
3832 int32_t mOffset
= 0;
3833 /** whether the input frame and the returned frame are on different lines */
3834 bool mJumpedLine
= false;
3835 /** whether we met a hard break between the input and the returned frame */
3836 bool mJumpedHardBreak
= false;
3837 /** whether we jumped over a non-selectable frame during the search */
3838 bool mMovedOverNonSelectableText
= false;
3839 /** whether we met selectable text frame that isn't editable during the
3841 bool mHasSelectableFrame
= false;
3842 /** whether we ignored a br frame */
3843 bool mIgnoredBrFrame
= false;
3845 FrameSearchResult
PeekOffsetNoAmount(bool aForward
) {
3846 return mFrame
->PeekOffsetNoAmount(aForward
, &mOffset
);
3848 FrameSearchResult
PeekOffsetCharacter(bool aForward
,
3849 PeekOffsetCharacterOptions aOptions
) {
3850 return mFrame
->PeekOffsetCharacter(aForward
, &mOffset
, aOptions
);
3853 /** Transfers frame and offset info for PeekOffset() result */
3854 void TransferTo(nsPeekOffsetStruct
& aPos
) const;
3855 bool Failed() { return !mFrame
; }
3857 explicit SelectablePeekReport(nsIFrame
* aFrame
= nullptr,
3858 int32_t aOffset
= 0)
3859 : mFrame(aFrame
), mOffset(aOffset
) {}
3860 MOZ_IMPLICIT
SelectablePeekReport(
3861 const mozilla::GenericErrorResult
<nsresult
>&& aErr
);
3865 * Called to find the previous/next non-anonymous selectable leaf frame.
3867 * @param aDirection the direction to move in (eDirPrevious or eDirNext)
3868 * @param aVisual whether bidi caret behavior is visual (true) or logical
3870 * @param aJumpLines whether to allow jumping across line boundaries
3871 * @param aScrollViewStop whether to stop when reaching a scroll frame
3874 SelectablePeekReport
GetFrameFromDirection(nsDirection aDirection
,
3875 bool aVisual
, bool aJumpLines
,
3876 bool aScrollViewStop
,
3877 bool aForceEditableRegion
);
3879 SelectablePeekReport
GetFrameFromDirection(const nsPeekOffsetStruct
& aPos
);
3882 Result
<bool, nsresult
> IsVisuallyAtLineEdge(nsILineIterator
* aLineIterator
,
3884 nsDirection aDirection
);
3885 Result
<bool, nsresult
> IsLogicallyAtLineEdge(nsILineIterator
* aLineIterator
,
3887 nsDirection aDirection
);
3889 // Return the line number of the aFrame, and (optionally) the containing block
3891 // If aScrollLock is true, don't break outside scrollframes when looking for a
3892 // containing block frame.
3893 Result
<int32_t, nsresult
> GetLineNumber(
3894 bool aLockScroll
, nsIFrame
** aContainingBlock
= nullptr);
3898 * Called to see if the children of the frame are visible from indexstart to
3899 * index end. This does not change any state. Returns true only if the indexes
3900 * are valid and any of the children are visible. For textframes this index
3901 * is the character index. If aStart = aEnd result will be false.
3903 * @param aStart start index of first child from 0-N (number of children)
3905 * @param aEnd end index of last child from 0-N
3907 * @param aRecurse should this frame talk to siblings to get to the contents
3910 * @param aFinished did this frame have the aEndIndex? or is there more work
3913 * @param _retval return value true or false. false = range is not rendered.
3915 virtual nsresult
CheckVisibility(nsPresContext
* aContext
, int32_t aStartIndex
,
3916 int32_t aEndIndex
, bool aRecurse
,
3917 bool* aFinished
, bool* _retval
);
3920 * Called to tell a frame that one of its child frames is dirty (i.e.,
3921 * has the NS_FRAME_IS_DIRTY *or* NS_FRAME_HAS_DIRTY_CHILDREN bit
3922 * set). This should always set the NS_FRAME_HAS_DIRTY_CHILDREN on
3923 * the frame, and may do other work.
3925 virtual void ChildIsDirty(nsIFrame
* aChild
);
3928 * Called to retrieve this frame's accessible.
3929 * If this frame implements Accessibility return a valid accessible
3930 * If not return NS_ERROR_NOT_IMPLEMENTED.
3931 * Note: LocalAccessible must be refcountable. Do not implement directly on
3932 * your frame Use a mediatior of some kind.
3934 #ifdef ACCESSIBILITY
3935 virtual mozilla::a11y::AccType
AccessibleType();
3939 * Get the frame whose style should be the parent of this frame's style (i.e.,
3940 * provide the parent style).
3942 * This frame must either be an ancestor of this frame or a child. If
3943 * this returns a child frame, then the child frame must be sure to
3944 * return a grandparent or higher! Furthermore, if a child frame is
3945 * returned it must have the same GetContent() as this frame.
3947 * @param aProviderFrame (out) the frame associated with the returned value
3948 * or nullptr if the style is for display:contents content.
3949 * @return The style that should be the parent of this frame's style. Null is
3950 * permitted, and means that this frame's style should be the root of
3953 virtual ComputedStyle
* GetParentComputedStyle(
3954 nsIFrame
** aProviderFrame
) const {
3955 return DoGetParentComputedStyle(aProviderFrame
);
3959 * Do the work for getting the parent ComputedStyle frame so that
3960 * other frame's |GetParentComputedStyle| methods can call this
3961 * method on *another* frame. (This function handles out-of-flow
3962 * frames by using the frame manager's placeholder map and it also
3963 * handles block-within-inline and generated content wrappers.)
3965 * @param aProviderFrame (out) the frame associated with the returned value
3966 * or null if the ComputedStyle is for display:contents content.
3967 * @return The ComputedStyle that should be the parent of this frame's
3968 * ComputedStyle. Null is permitted, and means that this frame's
3969 * ComputedStyle should be the root of the ComputedStyle tree.
3971 ComputedStyle
* DoGetParentComputedStyle(nsIFrame
** aProviderFrame
) const;
3974 * Adjust the given parent frame to the right ComputedStyle parent frame for
3975 * the child, given the pseudo-type of the prospective child. This handles
3976 * things like walking out of table pseudos and so forth.
3978 * @param aProspectiveParent what GetParent() on the child returns.
3980 * @param aChildPseudo the child's pseudo type, if any.
3982 static nsIFrame
* CorrectStyleParentFrame(
3983 nsIFrame
* aProspectiveParent
, mozilla::PseudoStyleType aChildPseudo
);
3986 * Called by RestyleManager to update the style of anonymous boxes
3987 * directly associated with this frame.
3989 * The passed-in ServoRestyleState can be used to create new ComputedStyles as
3990 * needed, as well as posting changes to the change list.
3992 * It's guaranteed to already have a change in it for this frame and this
3995 * This function will be called after this frame's style has already been
3996 * updated. This function will only be called on frames which have the
3997 * NS_FRAME_OWNS_ANON_BOXES bit set.
3999 void UpdateStyleOfOwnedAnonBoxes(mozilla::ServoRestyleState
& aRestyleState
) {
4000 if (HasAnyStateBits(NS_FRAME_OWNS_ANON_BOXES
)) {
4001 DoUpdateStyleOfOwnedAnonBoxes(aRestyleState
);
4006 // This does the actual work of UpdateStyleOfOwnedAnonBoxes. It calls
4007 // AppendDirectlyOwnedAnonBoxes to find all of the anonymous boxes
4008 // owned by this frame, and then updates styles on each of them.
4009 void DoUpdateStyleOfOwnedAnonBoxes(mozilla::ServoRestyleState
& aRestyleState
);
4011 // A helper for DoUpdateStyleOfOwnedAnonBoxes for the specific case
4012 // of the owned anon box being a child of this frame.
4013 void UpdateStyleOfChildAnonBox(nsIFrame
* aChildFrame
,
4014 mozilla::ServoRestyleState
& aRestyleState
);
4016 // Allow ServoRestyleState to call UpdateStyleOfChildAnonBox.
4017 friend class mozilla::ServoRestyleState
;
4020 // A helper both for UpdateStyleOfChildAnonBox, and to update frame-backed
4021 // pseudo-elements in RestyleManager.
4023 // This gets a ComputedStyle that will be the new style for `aChildFrame`, and
4024 // takes care of updating it, calling CalcStyleDifference, and adding to the
4025 // change list as appropriate.
4027 // If aContinuationComputedStyle is not Nothing, it should be used for
4028 // continuations instead of aNewComputedStyle. In either case, changehints
4029 // are only computed based on aNewComputedStyle.
4031 // Returns the generated change hint for the frame.
4032 static nsChangeHint
UpdateStyleOfOwnedChildFrame(
4033 nsIFrame
* aChildFrame
, ComputedStyle
* aNewComputedStyle
,
4034 mozilla::ServoRestyleState
& aRestyleState
,
4035 const Maybe
<ComputedStyle
*>& aContinuationComputedStyle
= Nothing());
4037 struct OwnedAnonBox
{
4038 typedef void (*UpdateStyleFn
)(nsIFrame
* aOwningFrame
, nsIFrame
* aAnonBox
,
4039 mozilla::ServoRestyleState
& aRestyleState
);
4041 explicit OwnedAnonBox(nsIFrame
* aAnonBoxFrame
,
4042 UpdateStyleFn aUpdateStyleFn
= nullptr)
4043 : mAnonBoxFrame(aAnonBoxFrame
), mUpdateStyleFn(aUpdateStyleFn
) {}
4045 nsIFrame
* mAnonBoxFrame
;
4046 UpdateStyleFn mUpdateStyleFn
;
4050 * Appends information about all of the anonymous boxes owned by this frame,
4051 * including other anonymous boxes owned by those which this frame owns
4054 void AppendOwnedAnonBoxes(nsTArray
<OwnedAnonBox
>& aResult
) {
4055 if (HasAnyStateBits(NS_FRAME_OWNS_ANON_BOXES
)) {
4056 if (IsInlineFrame()) {
4057 // See comment in nsIFrame::DoUpdateStyleOfOwnedAnonBoxes for why
4058 // we skip nsInlineFrames.
4061 DoAppendOwnedAnonBoxes(aResult
);
4066 // This does the actual work of AppendOwnedAnonBoxes.
4067 void DoAppendOwnedAnonBoxes(nsTArray
<OwnedAnonBox
>& aResult
);
4071 * Hook subclasses can override to return their owned anonymous boxes.
4073 * This function only appends anonymous boxes that are directly owned by
4074 * this frame, i.e. direct children or (for certain frames) a wrapper
4075 * parent, unlike AppendOwnedAnonBoxes, which will append all anonymous
4076 * boxes transitively owned by this frame.
4078 virtual void AppendDirectlyOwnedAnonBoxes(nsTArray
<OwnedAnonBox
>& aResult
);
4081 * Determines whether a frame is visible for painting;
4082 * taking into account whether it is painting a selection or printing.
4084 bool IsVisibleForPainting();
4086 * Determines whether a frame is visible for painting or collapsed;
4087 * taking into account whether it is painting a selection or printing,
4089 bool IsVisibleOrCollapsedForPainting();
4092 * Determines if this frame is a stacking context.
4094 bool IsStackingContext(const nsStyleDisplay
*, const nsStyleEffects
*);
4095 bool IsStackingContext();
4097 virtual bool HonorPrintBackgroundSettings() const { return true; }
4099 // Whether we should paint backgrounds or not.
4100 struct ShouldPaintBackground
{
4101 bool mColor
= false;
4102 bool mImage
= false;
4104 ShouldPaintBackground
ComputeShouldPaintBackground() const;
4107 * Determine whether the frame is logically empty, which is roughly
4108 * whether the layout would be the same whether or not the frame is
4109 * present. Placeholder frames should return true. Block frames
4110 * should be considered empty whenever margins collapse through them,
4111 * even though those margins are relevant. Text frames containing
4112 * only whitespace that does not contribute to the height of the line
4113 * should return true.
4115 virtual bool IsEmpty();
4117 * Return the same as IsEmpty(). This may only be called after the frame
4118 * has been reflowed and before any further style or content changes.
4120 virtual bool CachedIsEmpty();
4122 * Determine whether the frame is logically empty, assuming that all
4123 * its children are empty.
4125 virtual bool IsSelfEmpty();
4128 * IsGeneratedContentFrame returns whether a frame corresponds to
4131 * @return whether the frame correspods to generated content
4133 bool IsGeneratedContentFrame() const {
4134 return (mState
& NS_FRAME_GENERATED_CONTENT
) != 0;
4138 * IsPseudoFrame returns whether a frame is a pseudo frame (eg an
4139 * anonymous table-row frame created for a CSS table-cell without an
4140 * enclosing table-row.
4142 * @param aParentContent the content node corresponding to the parent frame
4143 * @return whether the frame is a pseudo frame
4145 bool IsPseudoFrame(const nsIContent
* aParentContent
) {
4146 return mContent
== aParentContent
;
4150 * Support for reading and writing properties on the frame.
4151 * These call through to the frame's FrameProperties object, if it
4152 * exists, but avoid creating it if no property is ever set.
4154 template <typename T
>
4155 FrameProperties::PropertyType
<T
> GetProperty(
4156 FrameProperties::Descriptor
<T
> aProperty
,
4157 bool* aFoundResult
= nullptr) const {
4158 return mProperties
.Get(aProperty
, aFoundResult
);
4161 template <typename T
>
4162 bool HasProperty(FrameProperties::Descriptor
<T
> aProperty
) const {
4163 return mProperties
.Has(aProperty
);
4167 * Add a property, or update an existing property for the given descriptor.
4169 * Note: This function asserts if updating an existing nsFrameList property.
4171 template <typename T
>
4172 void SetProperty(FrameProperties::Descriptor
<T
> aProperty
,
4173 FrameProperties::PropertyType
<T
> aValue
) {
4174 if constexpr (std::is_same_v
<T
, nsFrameList
>) {
4175 MOZ_ASSERT(aValue
, "Shouldn't set nullptr to a nsFrameList property!");
4176 MOZ_ASSERT(!HasProperty(aProperty
),
4177 "Shouldn't update an existing nsFrameList property!");
4179 mProperties
.Set(aProperty
, aValue
, this);
4182 // Unconditionally add a property; use ONLY if the descriptor is known
4183 // to NOT already be present.
4184 template <typename T
>
4185 void AddProperty(FrameProperties::Descriptor
<T
> aProperty
,
4186 FrameProperties::PropertyType
<T
> aValue
) {
4187 mProperties
.Add(aProperty
, aValue
);
4191 * Remove a property and return its value without destroying it. May return
4194 * Note: The caller is responsible for handling the life cycle of the returned
4197 template <typename T
>
4198 [[nodiscard
]] FrameProperties::PropertyType
<T
> TakeProperty(
4199 FrameProperties::Descriptor
<T
> aProperty
, bool* aFoundResult
= nullptr) {
4200 return mProperties
.Take(aProperty
, aFoundResult
);
4203 template <typename T
>
4204 void RemoveProperty(FrameProperties::Descriptor
<T
> aProperty
) {
4205 mProperties
.Remove(aProperty
, this);
4208 void RemoveAllProperties() { mProperties
.RemoveAll(this); }
4210 // nsIFrames themselves are in the nsPresArena, and so are not measured here.
4211 // Instead, this measures heap-allocated things hanging off the nsIFrame, and
4212 // likewise for its descendants.
4213 virtual void AddSizeOfExcludingThisForTree(nsWindowSizes
& aWindowSizes
) const;
4216 * Return true if and only if this frame obeys visibility:hidden.
4217 * if it does not, then nsContainerFrame will hide its view even though
4218 * this means children can't be made visible again.
4220 virtual bool SupportsVisibilityHidden() { return true; }
4223 * Returns the clip rect set via the 'clip' property, if the 'clip' property
4224 * applies to this frame; otherwise returns Nothing(). The 'clip' property
4225 * applies to HTML frames if they are absolutely positioned. The 'clip'
4226 * property applies to SVG frames regardless of the value of the 'position'
4229 * The coordinates of the returned rectangle are relative to this frame's
4232 Maybe
<nsRect
> GetClipPropClipRect(const nsStyleDisplay
* aDisp
,
4233 const nsStyleEffects
* aEffects
,
4234 const nsSize
& aSize
) const;
4237 bool mFocusable
= false;
4238 // The computed tab index:
4239 // < 0 if not tabbable
4240 // == 0 if in normal tab order
4241 // > 0 can be tabbed to in the order specified by this value
4242 int32_t mTabIndex
= -1;
4244 explicit operator bool() const { return mFocusable
; }
4248 * Check if this frame is focusable and in the current tab order.
4249 * Tabbable is indicated by a nonnegative tabindex & is a subset of focusable.
4250 * For example, only the selected radio button in a group is in the
4251 * tab order, unless the radio group has no selection in which case
4252 * all of the visible, non-disabled radio buttons in the group are
4253 * in the tab order. On the other hand, all of the visible, non-disabled
4254 * radio buttons are always focusable via clicking or script.
4255 * Also, depending on the pref accessibility.tabfocus some widgets may be
4256 * focusable but removed from the tab order. This is the default on
4257 * Mac OS X, where fewer items are focusable.
4258 * @param [in, optional] aWithMouse, is this focus query for mouse clicking
4259 * @return whether the frame is focusable via mouse, kbd or script.
4261 [[nodiscard
]] Focusable
IsFocusable(bool aWithMouse
= false);
4263 // BOX LAYOUT METHODS
4264 // These methods have been migrated from nsIBox and are in the process of
4265 // being refactored. DO NOT USE OUTSIDE OF XUL.
4266 bool IsXULBoxFrame() const { return IsFrameOfType(nsIFrame::eXULBox
); }
4268 enum Halignment
{ hAlign_Left
, hAlign_Right
, hAlign_Center
};
4270 enum Valignment
{ vAlign_Top
, vAlign_Middle
, vAlign_BaseLine
, vAlign_Bottom
};
4273 * This calculates the minimum size required for a box based on its state
4274 * @param[in] aBoxLayoutState The desired state to calculate for
4275 * @return The minimum size
4277 virtual nsSize
GetXULMinSize(nsBoxLayoutState
& aBoxLayoutState
);
4280 * This calculates the preferred size of a box based on its state
4281 * @param[in] aBoxLayoutState The desired state to calculate for
4282 * @return The preferred size
4284 virtual nsSize
GetXULPrefSize(nsBoxLayoutState
& aBoxLayoutState
);
4287 * This calculates the maximum size for a box based on its state
4288 * @param[in] aBoxLayoutState The desired state to calculate for
4289 * @return The maximum size
4291 virtual nsSize
GetXULMaxSize(nsBoxLayoutState
& aBoxLayoutState
);
4294 * This returns the minimum size for the scroll area if this frame is
4295 * being scrolled. Usually it's (0,0).
4297 virtual nsSize
GetXULMinSizeForScrollArea(nsBoxLayoutState
& aBoxLayoutState
);
4299 virtual nscoord
GetXULFlex();
4300 virtual nscoord
GetXULBoxAscent(nsBoxLayoutState
& aBoxLayoutState
);
4301 virtual bool IsXULCollapsed();
4302 // This does not alter the overflow area. If the caller is changing
4303 // the box size, the caller is responsible for updating the overflow
4304 // area. It's enough to just call XULLayout or SyncXULLayout on the
4305 // box. You can pass true to aRemoveOverflowArea as a
4307 virtual void SetXULBounds(nsBoxLayoutState
& aBoxLayoutState
,
4308 const nsRect
& aRect
,
4309 bool aRemoveOverflowAreas
= false);
4310 nsresult
XULLayout(nsBoxLayoutState
& aBoxLayoutState
);
4311 // Box methods. Note that these do NOT just get the CSS border, padding,
4312 // etc. They also talk to nsITheme.
4313 virtual nsresult
GetXULBorderAndPadding(nsMargin
& aBorderAndPadding
);
4314 virtual nsresult
GetXULBorder(nsMargin
& aBorder
);
4315 virtual nsresult
GetXULPadding(nsMargin
& aBorderAndPadding
);
4316 virtual nsresult
GetXULMargin(nsMargin
& aMargin
);
4317 virtual void SetXULLayoutManager(nsBoxLayout
* aLayout
) {}
4318 virtual nsBoxLayout
* GetXULLayoutManager() { return nullptr; }
4319 nsresult
GetXULClientRect(nsRect
& aContentRect
);
4321 virtual ReflowChildFlags
GetXULLayoutFlags() {
4322 return ReflowChildFlags::Default
;
4325 // For nsSprocketLayout
4326 virtual Valignment
GetXULVAlign() const { return vAlign_Top
; }
4327 virtual Halignment
GetXULHAlign() const { return hAlign_Left
; }
4329 bool IsXULHorizontal() const {
4330 return (mState
& NS_STATE_IS_HORIZONTAL
) != 0;
4332 bool IsXULNormalDirection() const {
4333 return (mState
& NS_STATE_IS_DIRECTION_NORMAL
) != 0;
4336 nsresult
XULRedraw(nsBoxLayoutState
& aState
);
4338 static bool AddXULPrefSize(nsIFrame
* aBox
, nsSize
& aSize
, bool& aWidth
,
4340 static bool AddXULMinSize(nsIFrame
* aBox
, nsSize
& aSize
, bool& aWidth
,
4342 static bool AddXULMaxSize(nsIFrame
* aBox
, nsSize
& aSize
, bool& aWidth
,
4344 static bool AddXULFlex(nsIFrame
* aBox
, nscoord
& aFlex
);
4346 void AddXULBorderAndPadding(nsSize
& aSize
);
4348 static void AddXULBorderAndPadding(nsIFrame
* aBox
, nsSize
& aSize
);
4349 static void AddXULMargin(nsIFrame
* aChild
, nsSize
& aSize
);
4350 static void AddXULMargin(nsSize
& aSize
, const nsMargin
& aMargin
);
4352 static nsSize
XULBoundsCheckMinMax(const nsSize
& aMinSize
,
4353 const nsSize
& aMaxSize
);
4354 static nsSize
XULBoundsCheck(const nsSize
& aMinSize
, const nsSize
& aPrefSize
,
4355 const nsSize
& aMaxSize
);
4356 static nscoord
XULBoundsCheck(nscoord aMinSize
, nscoord aPrefSize
,
4359 static nsIFrame
* GetChildXULBox(const nsIFrame
* aFrame
);
4360 static nsIFrame
* GetNextXULBox(const nsIFrame
* aFrame
);
4361 static nsIFrame
* GetParentXULBox(const nsIFrame
* aFrame
);
4364 // Helper for IsFocusable.
4365 bool IsFocusableDueToScrollFrame();
4368 * Returns true if this box clips its children, e.g., if this box is an
4371 virtual bool DoesClipChildrenInBothAxes();
4373 // We compute and store the HTML content's overflow area. So don't
4374 // try to compute it in the box code.
4375 virtual bool XULComputesOwnOverflowArea() { return true; }
4377 nsresult
SyncXULLayout(nsBoxLayoutState
& aBoxLayoutState
);
4379 bool XULNeedsRecalc(const nsSize
& aSize
);
4380 bool XULNeedsRecalc(nscoord aCoord
);
4381 void XULSizeNeedsRecalc(nsSize
& aSize
);
4382 void XULCoordNeedsRecalc(nscoord
& aCoord
);
4384 nsresult
BeginXULLayout(nsBoxLayoutState
& aState
);
4385 NS_IMETHOD
DoXULLayout(nsBoxLayoutState
& aBoxLayoutState
);
4386 nsresult
EndXULLayout(nsBoxLayoutState
& aState
);
4388 nsSize
GetUncachedXULMinSize(nsBoxLayoutState
& aBoxLayoutState
);
4389 nsSize
GetUncachedXULPrefSize(nsBoxLayoutState
& aBoxLayoutState
);
4390 nsSize
GetUncachedXULMaxSize(nsBoxLayoutState
& aBoxLayoutState
);
4392 // END OF BOX LAYOUT METHODS
4393 // The above methods have been migrated from nsIBox and are in the process of
4394 // being refactored. DO NOT USE OUTSIDE OF XUL.
4397 * NOTE: aStatus is assumed to be already-initialized. The reflow statuses of
4398 * any reflowed absolute children will be merged into aStatus; aside from
4399 * that, this method won't modify aStatus.
4401 void ReflowAbsoluteFrames(nsPresContext
* aPresContext
,
4402 ReflowOutput
& aDesiredSize
,
4403 const ReflowInput
& aReflowInput
,
4404 nsReflowStatus
& aStatus
,
4405 bool aConstrainBSize
= true);
4408 void BoxReflow(nsBoxLayoutState
& aState
, nsPresContext
* aPresContext
,
4409 ReflowOutput
& aDesiredSize
, gfxContext
* aRenderingContext
,
4410 nscoord aX
, nscoord aY
, nscoord aWidth
, nscoord aHeight
,
4411 bool aMoveFrame
= true);
4413 NS_IMETHODIMP
RefreshSizeCache(nsBoxLayoutState
& aState
);
4415 Maybe
<nscoord
> ComputeInlineSizeFromAspectRatio(
4416 mozilla::WritingMode aWM
, const mozilla::LogicalSize
& aCBSize
,
4417 const mozilla::LogicalSize
& aContentEdgeToBoxSizing
,
4418 mozilla::ComputeSizeFlags aFlags
) const;
4422 * @return true if this text frame ends with a newline character. It
4423 * should return false if this is not a text frame.
4425 virtual bool HasSignificantTerminalNewline() const;
4427 struct CaretPosition
{
4431 nsCOMPtr
<nsIContent
> mResultContent
;
4432 int32_t mContentOffset
;
4436 * gets the first or last possible caret position within the frame
4438 * @param [in] aStart
4439 * true for getting the first possible caret position
4440 * false for getting the last possible caret position
4441 * @return The caret position in a CaretPosition.
4442 * the returned value is a 'best effort' in case errors
4443 * are encountered rummaging through the frame.
4445 CaretPosition
GetExtremeCaretPosition(bool aStart
);
4448 * Get a line iterator for this frame, if supported.
4450 * @return nullptr if no line iterator is supported.
4451 * @note dispose the line iterator using nsILineIterator::DisposeLineIterator
4453 virtual nsILineIterator
* GetLineIterator() { return nullptr; }
4456 * If this frame is a next-in-flow, and its prev-in-flow has something on its
4457 * overflow list, pull those frames into the child list of this one.
4459 virtual void PullOverflowsFromPrevInFlow() {}
4462 * Clear the list of child PresShells generated during the last paint
4463 * so that we can begin generating a new one.
4465 void ClearPresShellsFromLastPaint() { PaintedPresShellList()->Clear(); }
4468 * Flag a child PresShell as painted so that it will get its paint count
4469 * incremented during empty transactions.
4471 void AddPaintedPresShell(mozilla::PresShell
* aPresShell
);
4474 * Increment the paint count of all child PresShells that were painted during
4477 void UpdatePaintCountForPaintedPresShells();
4480 * @return true if we painted @aPresShell during the last repaint.
4482 bool DidPaintPresShell(mozilla::PresShell
* aPresShell
);
4485 * Accessors for the absolute containing block.
4487 bool IsAbsoluteContainer() const {
4488 return !!(mState
& NS_FRAME_HAS_ABSPOS_CHILDREN
);
4490 bool HasAbsolutelyPositionedChildren() const;
4491 nsAbsoluteContainingBlock
* GetAbsoluteContainingBlock() const;
4492 void MarkAsAbsoluteContainingBlock();
4493 void MarkAsNotAbsoluteContainingBlock();
4494 // Child frame types override this function to select their own child list
4496 virtual mozilla::layout::FrameChildListID
GetAbsoluteListID() const {
4497 return kAbsoluteList
;
4500 // Checks if we (or any of our descendents) have NS_FRAME_PAINTED_THEBES set,
4501 // and clears this bit if so.
4502 bool CheckAndClearPaintedState();
4504 // Checks if we (or any of our descendents) have mBuiltDisplayList set, and
4505 // clears this bit if so.
4506 bool CheckAndClearDisplayListState();
4508 // CSS visibility just doesn't cut it because it doesn't inherit through
4509 // documents. Also if this frame is in a hidden card of a deck then it isn't
4510 // visible either and that isn't expressed using CSS visibility. Also if it
4511 // is in a hidden view (there are a few cases left and they are hopefully
4512 // going away soon).
4513 // If the VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY flag is passed then we
4514 // ignore the chrome/content boundary, otherwise we stop looking when we
4516 enum { VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY
= 0x01 };
4517 bool IsVisibleConsideringAncestors(uint32_t aFlags
= 0) const;
4519 struct FrameWithDistance
{
4526 * Finds a frame that is closer to a specified point than a current
4527 * distance. Distance is measured as for text selection -- a closer x
4528 * distance beats a closer y distance.
4530 * Normally, this function will only check the distance between this
4531 * frame's rectangle and the specified point. SVGTextFrame overrides
4532 * this so that it can manage all of its descendant frames and take
4533 * into account any SVG text layout.
4535 * If aPoint is closer to this frame's rectangle than aCurrentBestFrame
4536 * indicates, then aCurrentBestFrame is updated with the distance between
4537 * aPoint and this frame's rectangle, and with a pointer to this frame.
4538 * If aPoint is not closer, then aCurrentBestFrame is left unchanged.
4540 * @param aPoint The point to check for its distance to this frame.
4541 * @param aCurrentBestFrame Pointer to a struct that will be updated with
4542 * a pointer to this frame and its distance to aPoint, if this frame
4543 * is indeed closer than the current distance in aCurrentBestFrame.
4545 virtual void FindCloserFrameForSelection(
4546 const nsPoint
& aPoint
, FrameWithDistance
* aCurrentBestFrame
);
4549 * Is this a flex item? (i.e. a non-abs-pos child of a flex container)
4551 inline bool IsFlexItem() const;
4553 * Is this a grid item? (i.e. a non-abs-pos child of a grid container)
4555 inline bool IsGridItem() const;
4557 * Is this a flex or grid item? (i.e. a non-abs-pos child of a flex/grid
4560 inline bool IsFlexOrGridItem() const;
4561 inline bool IsFlexOrGridContainer() const;
4564 * Return true if this frame has masonry layout in aAxis.
4565 * @note only valid to call on nsGridContainerFrames
4567 inline bool IsMasonry(mozilla::LogicalAxis aAxis
) const;
4570 * @return true if this frame is used as a table caption.
4572 inline bool IsTableCaption() const;
4574 inline bool IsBlockOutside() const;
4575 inline bool IsInlineOutside() const;
4576 inline mozilla::StyleDisplay
GetDisplay() const;
4577 inline bool IsFloating() const;
4578 inline bool IsAbsPosContainingBlock() const;
4579 inline bool IsFixedPosContainingBlock() const;
4580 inline bool IsRelativelyPositioned() const;
4581 inline bool IsStickyPositioned() const;
4582 inline bool IsAbsolutelyPositioned(
4583 const nsStyleDisplay
* aStyleDisplay
= nullptr) const;
4584 inline bool IsTrueOverflowContainer() const;
4586 // Does this frame have "column-span: all" style.
4588 // Note this only checks computed style, but not testing whether the
4589 // containing block formatting context was established by a multicol. Callers
4590 // need to use IsColumnSpanInMulticolSubtree() to check whether multi-column
4591 // effects apply or not.
4592 inline bool IsColumnSpan() const;
4594 // Like IsColumnSpan(), but this also checks whether the frame has a
4595 // multi-column ancestor or not.
4596 inline bool IsColumnSpanInMulticolSubtree() const;
4599 * Returns the vertical-align value to be used for layout, if it is one
4600 * of the enumerated values. If this is an SVG text frame, it returns a value
4601 * that corresponds to the value of dominant-baseline. If the
4602 * vertical-align property has length or percentage value, this returns
4605 Maybe
<mozilla::StyleVerticalAlignKeyword
> VerticalAlignEnum() const;
4607 void CreateOwnLayerIfNeeded(nsDisplayListBuilder
* aBuilder
,
4608 nsDisplayList
* aList
, uint16_t aType
,
4609 bool* aCreatedContainerItem
= nullptr);
4612 * Adds the NS_FRAME_IN_POPUP state bit to aFrame, and
4613 * all descendant frames (including cross-doc ones).
4615 static void AddInPopupStateBitToDescendants(nsIFrame
* aFrame
);
4617 * Removes the NS_FRAME_IN_POPUP state bit from aFrame and
4618 * all descendant frames (including cross-doc ones), unless
4619 * the frame is a popup itself.
4621 static void RemoveInPopupStateBitFromDescendants(nsIFrame
* aFrame
);
4624 * Return true if aFrame is in an {ib} split and is NOT one of the
4625 * continuations of the first inline in it.
4627 bool FrameIsNonFirstInIBSplit() const {
4628 return HasAnyStateBits(NS_FRAME_PART_OF_IBSPLIT
) &&
4629 FirstContinuation()->GetProperty(nsIFrame::IBSplitPrevSibling());
4633 * Return true if aFrame is in an {ib} split and is NOT one of the
4634 * continuations of the last inline in it.
4636 bool FrameIsNonLastInIBSplit() const {
4637 return HasAnyStateBits(NS_FRAME_PART_OF_IBSPLIT
) &&
4638 FirstContinuation()->GetProperty(nsIFrame::IBSplitSibling());
4642 * Return whether this is a frame whose width is used when computing
4643 * the font size inflation of its descendants.
4645 bool IsContainerForFontSizeInflation() const {
4646 return HasAnyStateBits(NS_FRAME_FONT_INFLATION_CONTAINER
);
4650 * Return whether this frame or any of its children is dirty.
4652 bool IsSubtreeDirty() const {
4653 return HasAnyStateBits(NS_FRAME_IS_DIRTY
| NS_FRAME_HAS_DIRTY_CHILDREN
);
4657 * Return whether this frame keeps track of overflow areas. (Frames for
4658 * non-display SVG elements -- e.g. <clipPath> -- do not maintain overflow
4659 * areas, because they're never painted.)
4661 bool FrameMaintainsOverflow() const {
4662 return !HasAllStateBits(NS_FRAME_SVG_LAYOUT
| NS_FRAME_IS_NONDISPLAY
) &&
4663 !(IsSVGOuterSVGFrame() && HasAnyStateBits(NS_FRAME_IS_NONDISPLAY
));
4667 * @param aStyleDisplay: If the caller has this->StyleDisplay(), providing
4668 * it here will improve performance.
4670 bool BackfaceIsHidden(const nsStyleDisplay
* aStyleDisplay
) const {
4671 MOZ_ASSERT(aStyleDisplay
== StyleDisplay());
4672 return aStyleDisplay
->BackfaceIsHidden();
4674 bool BackfaceIsHidden() const { return StyleDisplay()->BackfaceIsHidden(); }
4677 * Returns true if the frame is scrolled out of view.
4679 bool IsScrolledOutOfView() const;
4682 * Computes a 2D matrix from the -moz-window-transform and
4683 * -moz-window-transform-origin properties on aFrame.
4684 * Values that don't result in a 2D matrix will be ignored and an identity
4685 * matrix will be returned instead.
4687 Matrix
ComputeWidgetTransform();
4690 * @return true iff this frame has one or more associated image requests.
4691 * @see mozilla::css::ImageLoader.
4693 bool HasImageRequest() const { return mHasImageRequest
; }
4696 * Update this frame's image request state.
4698 void SetHasImageRequest(bool aHasRequest
) { mHasImageRequest
= aHasRequest
; }
4701 * Whether this frame has a first-letter child. If it does, the frame is
4702 * actually an nsContainerFrame and the first-letter frame can be gotten by
4703 * walking up to the nearest ancestor blockframe and getting its first
4704 * continuation's nsContainerFrame::FirstLetterProperty() property. This will
4705 * only return true for the first continuation of the first-letter's parent.
4707 bool HasFirstLetterChild() const { return mHasFirstLetterChild
; }
4710 * Whether this frame's parent is a wrapper anonymous box. See documentation
4711 * for mParentIsWrapperAnonBox.
4713 bool ParentIsWrapperAnonBox() const { return mParentIsWrapperAnonBox
; }
4714 void SetParentIsWrapperAnonBox() { mParentIsWrapperAnonBox
= true; }
4717 * Whether this is a wrapper anonymous box needing a restyle.
4719 bool IsWrapperAnonBoxNeedingRestyle() const {
4720 return mIsWrapperBoxNeedingRestyle
;
4722 void SetIsWrapperAnonBoxNeedingRestyle(bool aNeedsRestyle
) {
4723 mIsWrapperBoxNeedingRestyle
= aNeedsRestyle
;
4726 bool MayHaveTransformAnimation() const { return mMayHaveTransformAnimation
; }
4727 void SetMayHaveTransformAnimation() {
4728 AddStateBits(NS_FRAME_MAY_BE_TRANSFORMED
);
4729 mMayHaveTransformAnimation
= true;
4731 bool MayHaveOpacityAnimation() const { return mMayHaveOpacityAnimation
; }
4732 void SetMayHaveOpacityAnimation() { mMayHaveOpacityAnimation
= true; }
4734 // Returns true if this frame is visible or may have visible descendants.
4735 // Note: This function is accurate only on primary frames, because
4736 // mAllDescendantsAreInvisible is not updated on continuations.
4737 bool IsVisibleOrMayHaveVisibleDescendants() const {
4738 return !mAllDescendantsAreInvisible
|| StyleVisibility()->IsVisible();
4740 // Update mAllDescendantsAreInvisible flag for this frame and ancestors.
4741 void UpdateVisibleDescendantsState();
4744 * If this returns true, the frame it's called on should get the
4745 * NS_FRAME_HAS_DIRTY_CHILDREN bit set on it by the caller; either directly
4746 * if it's already in reflow, or via calling FrameNeedsReflow() to schedule a
4749 virtual bool RenumberFrameAndDescendants(int32_t* aOrdinal
, int32_t aDepth
,
4751 bool aForCounting
) {
4756 * Helper function - computes the content-box inline size for aSize, which is
4757 * a more complex version to resolve a StyleExtremumLength.
4759 struct ISizeComputationResult
{
4761 AspectRatioUsage mAspectRatioUsage
= AspectRatioUsage::None
;
4763 ISizeComputationResult
ComputeISizeValue(
4764 gfxContext
* aRenderingContext
, const mozilla::WritingMode aWM
,
4765 const mozilla::LogicalSize
& aContainingBlockSize
,
4766 const mozilla::LogicalSize
& aContentEdgeToBoxSizing
,
4767 nscoord aBoxSizingToMarginEdge
, StyleExtremumLength aSize
,
4768 mozilla::ComputeSizeFlags aFlags
);
4771 * Helper function - computes the content-box inline size for aSize, which is
4772 * a simpler version to resolve a LengthPercentage.
4774 nscoord
ComputeISizeValue(const mozilla::WritingMode aWM
,
4775 const mozilla::LogicalSize
& aContainingBlockSize
,
4776 const mozilla::LogicalSize
& aContentEdgeToBoxSizing
,
4777 const LengthPercentage
& aSize
);
4779 template <typename SizeOrMaxSize
>
4780 ISizeComputationResult
ComputeISizeValue(
4781 gfxContext
* aRenderingContext
, const mozilla::WritingMode aWM
,
4782 const mozilla::LogicalSize
& aContainingBlockSize
,
4783 const mozilla::LogicalSize
& aContentEdgeToBoxSizing
,
4784 nscoord aBoxSizingToMarginEdge
, const SizeOrMaxSize
& aSize
,
4785 mozilla::ComputeSizeFlags aFlags
= {}) {
4786 MOZ_ASSERT(aSize
.IsExtremumLength() || aSize
.IsLengthPercentage(),
4787 "This doesn't handle auto / none");
4788 if (aSize
.IsLengthPercentage()) {
4789 return {ComputeISizeValue(aWM
, aContainingBlockSize
,
4790 aContentEdgeToBoxSizing
,
4791 aSize
.AsLengthPercentage())};
4793 return ComputeISizeValue(aRenderingContext
, aWM
, aContainingBlockSize
,
4794 aContentEdgeToBoxSizing
, aBoxSizingToMarginEdge
,
4795 aSize
.AsExtremumLength(), aFlags
);
4798 DisplayItemDataArray
& DisplayItemData() { return mDisplayItemData
; }
4799 const DisplayItemDataArray
& DisplayItemData() const {
4800 return mDisplayItemData
;
4803 void AddDisplayItem(nsDisplayItemBase
* aItem
);
4804 bool RemoveDisplayItem(nsDisplayItemBase
* aItem
);
4805 void RemoveDisplayItemDataForDeletion();
4806 bool HasDisplayItems();
4807 bool HasDisplayItem(nsDisplayItemBase
* aItem
);
4808 bool HasDisplayItem(uint32_t aKey
);
4810 static void PrintDisplayList(nsDisplayListBuilder
* aBuilder
,
4811 const nsDisplayList
& aList
,
4812 bool aDumpHtml
= false);
4813 static void PrintDisplayList(nsDisplayListBuilder
* aBuilder
,
4814 const nsDisplayList
& aList
,
4815 std::stringstream
& aStream
,
4816 bool aDumpHtml
= false);
4817 static void PrintDisplayItem(nsDisplayListBuilder
* aBuilder
,
4818 nsDisplayItem
* aItem
, std::stringstream
& aStream
,
4819 uint32_t aIndent
= 0, bool aDumpSublist
= false,
4820 bool aDumpHtml
= false);
4821 #ifdef MOZ_DUMP_PAINTING
4822 static void PrintDisplayListSet(nsDisplayListBuilder
* aBuilder
,
4823 const nsDisplayListSet
& aSet
,
4824 std::stringstream
& aStream
,
4825 bool aDumpHtml
= false);
4829 * Adds display items for standard CSS background if necessary.
4830 * Does not check IsVisibleForPainting.
4831 * @param aForceBackground draw the background even if the frame
4832 * background style appears to have no background --- this is useful
4833 * for frames that might receive a propagated background via
4834 * nsCSSRendering::FindBackground
4835 * @return whether a themed background item was created.
4837 bool DisplayBackgroundUnconditional(nsDisplayListBuilder
* aBuilder
,
4838 const nsDisplayListSet
& aLists
,
4839 bool aForceBackground
);
4841 * Adds display items for standard CSS borders, background and outline for
4842 * for this frame, as necessary. Checks IsVisibleForPainting and won't
4843 * display anything if the frame is not visible.
4844 * @param aForceBackground draw the background even if the frame
4845 * background style appears to have no background --- this is useful
4846 * for frames that might receive a propagated background via
4847 * nsCSSRendering::FindBackground
4849 void DisplayBorderBackgroundOutline(nsDisplayListBuilder
* aBuilder
,
4850 const nsDisplayListSet
& aLists
,
4851 bool aForceBackground
= false);
4853 * Add a display item for the CSS outline. Does not check visibility.
4855 void DisplayOutlineUnconditional(nsDisplayListBuilder
* aBuilder
,
4856 const nsDisplayListSet
& aLists
);
4858 * Add a display item for the CSS outline, after calling
4859 * IsVisibleForPainting to confirm we are visible.
4861 void DisplayOutline(nsDisplayListBuilder
* aBuilder
,
4862 const nsDisplayListSet
& aLists
);
4865 * Add a display item for CSS inset box shadows. Does not check visibility.
4867 void DisplayInsetBoxShadowUnconditional(nsDisplayListBuilder
* aBuilder
,
4868 nsDisplayList
* aList
);
4871 * Add a display item for CSS inset box shadow, after calling
4872 * IsVisibleForPainting to confirm we are visible.
4874 void DisplayInsetBoxShadow(nsDisplayListBuilder
* aBuilder
,
4875 nsDisplayList
* aList
);
4878 * Add a display item for CSS outset box shadows. Does not check visibility.
4880 void DisplayOutsetBoxShadowUnconditional(nsDisplayListBuilder
* aBuilder
,
4881 nsDisplayList
* aList
);
4884 * Add a display item for CSS outset box shadow, after calling
4885 * IsVisibleForPainting to confirm we are visible.
4887 void DisplayOutsetBoxShadow(nsDisplayListBuilder
* aBuilder
,
4888 nsDisplayList
* aList
);
4890 bool ForceDescendIntoIfVisible() const { return mForceDescendIntoIfVisible
; }
4891 void SetForceDescendIntoIfVisible(bool aForce
) {
4892 mForceDescendIntoIfVisible
= aForce
;
4895 bool BuiltDisplayList() const { return mBuiltDisplayList
; }
4896 void SetBuiltDisplayList(const bool aBuilt
) { mBuiltDisplayList
= aBuilt
; }
4898 bool IsFrameModified() const { return mFrameIsModified
; }
4899 void SetFrameIsModified(const bool aFrameIsModified
) {
4900 mFrameIsModified
= aFrameIsModified
;
4903 bool HasOverrideDirtyRegion() const { return mHasOverrideDirtyRegion
; }
4904 void SetHasOverrideDirtyRegion(const bool aHasDirtyRegion
) {
4905 mHasOverrideDirtyRegion
= aHasDirtyRegion
;
4908 bool MayHaveWillChangeBudget() const { return mMayHaveWillChangeBudget
; }
4909 void SetMayHaveWillChangeBudget(const bool aHasBudget
) {
4910 mMayHaveWillChangeBudget
= aHasBudget
;
4913 bool HasBSizeChange() const { return mHasBSizeChange
; }
4914 void SetHasBSizeChange(const bool aHasBSizeChange
) {
4915 mHasBSizeChange
= aHasBSizeChange
;
4918 bool HasColumnSpanSiblings() const { return mHasColumnSpanSiblings
; }
4919 void SetHasColumnSpanSiblings(bool aHasColumnSpanSiblings
) {
4920 mHasColumnSpanSiblings
= aHasColumnSpanSiblings
;
4923 bool DescendantMayDependOnItsStaticPosition() const {
4924 return mDescendantMayDependOnItsStaticPosition
;
4926 void SetDescendantMayDependOnItsStaticPosition(bool aValue
) {
4927 mDescendantMayDependOnItsStaticPosition
= aValue
;
4930 bool ShouldGenerateComputedInfo() const {
4931 return mShouldGenerateComputedInfo
;
4933 void SetShouldGenerateComputedInfo(bool aValue
) {
4934 mShouldGenerateComputedInfo
= aValue
;
4938 * Returns the hit test area of the frame.
4940 nsRect
GetCompositorHitTestArea(nsDisplayListBuilder
* aBuilder
);
4943 * Returns the set of flags indicating the properties of the frame that the
4944 * compositor might care about for hit-testing purposes. Note that this
4945 * function must be called during Gecko display list construction time (i.e
4946 * while the frame tree is being traversed) because that is when the display
4947 * list builder has the necessary state set up correctly.
4949 mozilla::gfx::CompositorHitTestInfo
GetCompositorHitTestInfo(
4950 nsDisplayListBuilder
* aBuilder
);
4953 * Copies aWM to mWritingMode on 'this' and all its ancestors.
4955 inline void PropagateWritingModeToSelfAndAncestors(mozilla::WritingMode aWM
);
4958 static void DestroyAnonymousContent(nsPresContext
* aPresContext
,
4959 already_AddRefed
<nsIContent
>&& aContent
);
4962 * Reparent this frame's view if it has one.
4964 void ReparentFrameViewTo(nsViewManager
* aViewManager
, nsView
* aNewParentView
,
4965 nsView
* aOldParentView
);
4968 * To be overridden by frame classes that have a varying IsLeaf() state and
4969 * is indicating that with DynamicLeaf in FrameIdList.h.
4972 virtual bool IsLeafDynamic() const { return false; }
4976 nsCOMPtr
<nsIContent
> mContent
;
4977 RefPtr
<ComputedStyle
> mComputedStyle
;
4980 nsPresContext
* const mPresContext
;
4981 nsContainerFrame
* mParent
;
4982 nsIFrame
* mNextSibling
; // doubly-linked list of frames
4983 nsIFrame
* mPrevSibling
; // Do not touch outside SetNextSibling!
4985 DisplayItemDataArray mDisplayItemData
;
4987 void MarkAbsoluteFramesForDisplayList(nsDisplayListBuilder
* aBuilder
);
4989 // Stores weak references to all the PresShells that were painted during
4990 // the last paint event so that we can increment their paint count during
4991 // empty transactions
4992 NS_DECLARE_FRAME_PROPERTY_DELETABLE(PaintedPresShellsProperty
,
4993 nsTArray
<nsWeakPtr
>)
4995 nsTArray
<nsWeakPtr
>* PaintedPresShellList() {
4997 nsTArray
<nsWeakPtr
>* list
=
4998 GetProperty(PaintedPresShellsProperty(), &found
);
5001 list
= new nsTArray
<nsWeakPtr
>();
5002 AddProperty(PaintedPresShellsProperty(), list
);
5004 MOZ_ASSERT(list
, "this property should only store non-null values");
5011 void MarkInReflow() {
5012 #ifdef DEBUG_dbaron_off
5014 NS_ASSERTION(!(mState
& NS_FRAME_IN_REFLOW
), "frame is already in reflow");
5016 AddStateBits(NS_FRAME_IN_REFLOW
);
5019 nsFrameState mState
;
5022 * List of properties attached to the frame.
5024 FrameProperties mProperties
;
5026 // When there is an overflow area only slightly larger than mRect,
5027 // we store a set of four 1-byte deltas from the edges of mRect
5028 // rather than allocating a whole separate rectangle property.
5029 // Note that these are unsigned values, all measured "outwards"
5030 // from the edges of mRect, so /mLeft/ and /mTop/ are reversed from
5031 // our normal coordinate system.
5032 // If mOverflow.mType == NS_FRAME_OVERFLOW_LARGE, then the
5033 // delta values are not meaningful and the overflow area is stored
5034 // as a separate rect property.
5035 struct VisualDeltas
{
5040 bool operator==(const VisualDeltas
& aOther
) const {
5041 return mLeft
== aOther
.mLeft
&& mTop
== aOther
.mTop
&&
5042 mRight
== aOther
.mRight
&& mBottom
== aOther
.mBottom
;
5044 bool operator!=(const VisualDeltas
& aOther
) const {
5045 return !(*this == aOther
);
5050 VisualDeltas mVisualDeltas
;
5053 /** @see GetWritingMode() */
5054 mozilla::WritingMode mWritingMode
;
5056 /** The ClassID of the concrete class of this instance. */
5057 ClassID mClass
; // 1 byte
5059 bool mMayHaveRoundedCorners
: 1;
5062 * True iff this frame has one or more associated image requests.
5063 * @see mozilla::css::ImageLoader.
5065 bool mHasImageRequest
: 1;
5068 * True if this frame has a continuation that has a first-letter frame, or its
5069 * placeholder, as a child. In that case this frame has a blockframe ancestor
5070 * that has the first-letter frame hanging off it in the
5071 * nsContainerFrame::FirstLetterProperty() property.
5073 bool mHasFirstLetterChild
: 1;
5076 * True if this frame's parent is a wrapper anonymous box (e.g. a table
5077 * anonymous box as specified at
5078 * <https://www.w3.org/TR/CSS21/tables.html#anonymous-boxes>).
5080 * We could compute this information directly when we need it, but it wouldn't
5081 * be all that cheap, and since this information is immutable for the lifetime
5082 * of the frame we might as well cache it.
5084 * Note that our parent may itself have mParentIsWrapperAnonBox set to true.
5086 bool mParentIsWrapperAnonBox
: 1;
5089 * True if this is a wrapper anonymous box needing a restyle. This is used to
5090 * track, during stylo post-traversal, whether we've already recomputed the
5091 * style of this anonymous box, if we end up seeing it twice.
5093 bool mIsWrapperBoxNeedingRestyle
: 1;
5096 * This bit is used in nsTextFrame::CharacterDataChanged() as an optimization
5097 * to skip redundant reflow-requests when the character data changes multiple
5098 * times between reflows. If this flag is set, then it implies that the
5099 * NS_FRAME_IS_DIRTY state bit is also set (and that intrinsic sizes have
5100 * been marked as dirty on our ancestor chain).
5102 * XXXdholbert This bit is *only* used on nsTextFrame, but it lives here on
5103 * nsIFrame simply because this is where we've got unused state bits
5104 * available in a gap. If bits become more scarce, we should perhaps consider
5105 * expanding the range of frame-specific state bits in nsFrameStateBits.h and
5106 * moving this to be one of those (e.g. by swapping one of the adjacent
5107 * general-purpose bits to take the place of this bool:1 here, so we can grow
5108 * that range of frame-specific bits by 1).
5110 bool mReflowRequestedForCharDataChange
: 1;
5113 * This bit is used during BuildDisplayList to mark frames that need to
5114 * have display items rebuilt. We will descend into them if they are
5115 * currently visible, even if they don't intersect the dirty area.
5117 bool mForceDescendIntoIfVisible
: 1;
5120 * True if we have built display items for this frame since
5121 * the last call to CheckAndClearDisplayListState, false
5122 * otherwise. Used for the reftest harness to verify minimal
5123 * display list building.
5125 bool mBuiltDisplayList
: 1;
5127 bool mFrameIsModified
: 1;
5129 bool mHasOverrideDirtyRegion
: 1;
5132 * True if frame has will-change, and currently has display
5133 * items consuming some of the will-change budget.
5135 bool mMayHaveWillChangeBudget
: 1;
5139 * True if this is the primary frame for mContent.
5141 bool mIsPrimaryFrame
: 1;
5143 bool mMayHaveTransformAnimation
: 1;
5144 bool mMayHaveOpacityAnimation
: 1;
5147 * True if we are certain that all descendants are not visible.
5149 * This flag is conservative in that it might sometimes be false even if, in
5150 * fact, all descendants are invisible.
5151 * For example; an element is visibility:visible and has a visibility:hidden
5152 * child. This flag is stil false in such case.
5154 bool mAllDescendantsAreInvisible
: 1;
5156 bool mHasBSizeChange
: 1;
5159 * True if we are or contain the scroll anchor for a scrollable frame.
5161 bool mInScrollAnchorChain
: 1;
5164 * Suppose a frame was split into multiple parts to separate parts containing
5165 * column-spans from parts not containing column-spans. This bit is set on all
5166 * continuations *not* containing column-spans except for the those after the
5167 * last column-span/non-column-span boundary (i.e., the bit really means it
5168 * has a *later* sibling across a split). Note that the last part is always
5169 * created to containing no columns-spans even if it has no children. See
5170 * nsCSSFrameConstructor::CreateColumnSpanSiblings() for the implementation.
5172 * If the frame having this bit set is removed, we need to reframe the
5173 * multi-column container.
5175 bool mHasColumnSpanSiblings
: 1;
5178 * True if we may have any descendant whose positioning may depend on its
5179 * static position (and thus which we need to recompute the position for if we
5182 bool mDescendantMayDependOnItsStaticPosition
: 1;
5185 * True if the next reflow of this frame should generate computed info
5186 * metrics. These are used by devtools to reveal details of the layout
5189 bool mShouldGenerateComputedInfo
: 1;
5194 * Can we stop inside this frame when we're skipping non-rendered whitespace?
5196 * @param aForward [in] Are we moving forward (or backward) in content order.
5198 * @param aOffset [in/out] At what offset into the frame to start looking.
5199 * at offset was reached (whether or not we found a place to stop).
5202 * * STOP: An appropriate offset was found within this frame,
5203 * and is given by aOffset.
5204 * * CONTINUE: Not found within this frame, need to try the next frame.
5205 * See enum FrameSearchResult for more details.
5207 virtual FrameSearchResult
PeekOffsetNoAmount(bool aForward
, int32_t* aOffset
);
5210 * Search the frame for the next character
5212 * @param aForward [in] Are we moving forward (or backward) in content order.
5214 * @param aOffset [in/out] At what offset into the frame to start looking.
5215 * on output - what offset was reached (whether or not we found a place to
5218 * @param aOptions [in] Options, see the comment in PeekOffsetCharacterOptions
5222 * * STOP: An appropriate offset was found within this frame, and is given
5224 * * CONTINUE: Not found within this frame, need to try the next frame. See
5225 * enum FrameSearchResult for more details.
5227 virtual FrameSearchResult
PeekOffsetCharacter(
5228 bool aForward
, int32_t* aOffset
,
5229 PeekOffsetCharacterOptions aOptions
= PeekOffsetCharacterOptions());
5230 static_assert(sizeof(PeekOffsetCharacterOptions
) <= sizeof(intptr_t),
5231 "aOptions should be changed to const reference");
5233 struct PeekWordState
{
5234 // true when we're still at the start of the search, i.e., we can't return
5235 // this point as a valid offset!
5237 // true when we've encountered at least one character of the type before the
5238 // boundary we're looking for:
5239 // 1. If we're moving forward and eating whitepace, looking for a word
5240 // beginning (i.e. a boundary between whitespace and non-whitespace),
5241 // then mSawBeforeType==true means "we already saw some whitespace".
5242 // 2. Otherwise, looking for a word beginning (i.e. a boundary between
5243 // non-whitespace and whitespace), then mSawBeforeType==true means "we
5244 // already saw some non-whitespace".
5245 bool mSawBeforeType
;
5246 // true when we've encountered at least one non-newline character
5247 bool mSawInlineCharacter
;
5248 // true when the last character encountered was punctuation
5249 bool mLastCharWasPunctuation
;
5250 // true when the last character encountered was whitespace
5251 bool mLastCharWasWhitespace
;
5252 // true when we've seen non-punctuation since the last whitespace
5253 bool mSeenNonPunctuationSinceWhitespace
;
5254 // text that's *before* the current frame when aForward is true, *after*
5255 // the current frame when aForward is false. Only includes the text
5256 // on the current line.
5257 nsAutoString mContext
;
5261 mSawBeforeType(false),
5262 mSawInlineCharacter(false),
5263 mLastCharWasPunctuation(false),
5264 mLastCharWasWhitespace(false),
5265 mSeenNonPunctuationSinceWhitespace(false) {}
5266 void SetSawBeforeType() { mSawBeforeType
= true; }
5267 void SetSawInlineCharacter() { mSawInlineCharacter
= true; }
5268 void Update(bool aAfterPunctuation
, bool aAfterWhitespace
) {
5269 mLastCharWasPunctuation
= aAfterPunctuation
;
5270 mLastCharWasWhitespace
= aAfterWhitespace
;
5271 if (aAfterWhitespace
) {
5272 mSeenNonPunctuationSinceWhitespace
= false;
5273 } else if (!aAfterPunctuation
) {
5274 mSeenNonPunctuationSinceWhitespace
= true;
5281 * Search the frame for the next word boundary
5282 * @param aForward [in] Are we moving forward (or backward) in content order.
5283 * @param aWordSelectEatSpace [in] true: look for non-whitespace following
5284 * whitespace (in the direction of movement).
5285 * false: look for whitespace following non-whitespace (in the
5286 * direction of movement).
5287 * @param aIsKeyboardSelect [in] Was the action initiated by a keyboard
5288 * operation? If true, punctuation immediately following a word is considered
5289 * part of that word. Otherwise, a sequence of punctuation is always
5290 * considered as a word on its own.
5291 * @param aOffset [in/out] At what offset into the frame to start looking.
5292 * on output - what offset was reached (whether or not we found a
5294 * @param aState [in/out] the state that is carried from frame to frame
5296 virtual FrameSearchResult
PeekOffsetWord(
5297 bool aForward
, bool aWordSelectEatSpace
, bool aIsKeyboardSelect
,
5298 int32_t* aOffset
, PeekWordState
* aState
, bool aTrimSpaces
);
5302 * Check whether we should break at a boundary between punctuation and
5303 * non-punctuation. Only call it at a punctuation boundary
5304 * (i.e. exactly one of the previous and next characters are punctuation).
5305 * @param aForward true if we're moving forward in content order
5306 * @param aPunctAfter true if the next character is punctuation
5307 * @param aWhitespaceAfter true if the next character is whitespace
5309 static bool BreakWordBetweenPunctuation(const PeekWordState
* aState
,
5310 bool aForward
, bool aPunctAfter
,
5311 bool aWhitespaceAfter
,
5312 bool aIsKeyboardSelect
);
5315 // Get a pointer to the overflow areas property attached to the frame.
5316 mozilla::OverflowAreas
* GetOverflowAreasProperty() const {
5317 MOZ_ASSERT(mOverflow
.mType
== NS_FRAME_OVERFLOW_LARGE
);
5318 mozilla::OverflowAreas
* overflow
= GetProperty(OverflowAreasProperty());
5319 MOZ_ASSERT(overflow
);
5323 nsRect
InkOverflowFromDeltas() const {
5324 MOZ_ASSERT(mOverflow
.mType
!= NS_FRAME_OVERFLOW_LARGE
,
5325 "should not be called when overflow is in a property");
5326 // Calculate the rect using deltas from the frame's border rect.
5327 // Note that the mOverflow.mDeltas fields are unsigned, but we will often
5328 // need to return negative values for the left and top, so take care
5329 // to cast away the unsigned-ness.
5330 return nsRect(-(int32_t)mOverflow
.mVisualDeltas
.mLeft
,
5331 -(int32_t)mOverflow
.mVisualDeltas
.mTop
,
5332 mRect
.Width() + mOverflow
.mVisualDeltas
.mRight
+
5333 mOverflow
.mVisualDeltas
.mLeft
,
5334 mRect
.Height() + mOverflow
.mVisualDeltas
.mBottom
+
5335 mOverflow
.mVisualDeltas
.mTop
);
5338 * Returns true if any overflow changed.
5340 bool SetOverflowAreas(const mozilla::OverflowAreas
& aOverflowAreas
);
5342 bool HasOpacityInternal(float aThreshold
, const nsStyleDisplay
* aStyleDisplay
,
5343 const nsStyleEffects
* aStyleEffects
,
5344 mozilla::EffectSet
* aEffectSet
= nullptr) const;
5346 // Maps mClass to LayoutFrameType.
5347 static const mozilla::LayoutFrameType sLayoutFrameTypes
[
5348 #define FRAME_ID(...) 1 +
5349 #define ABSTRACT_FRAME_ID(...)
5350 #include "mozilla/FrameIdList.h"
5352 #undef ABSTRACT_FRAME_ID
5355 enum FrameClassBits
{
5356 eFrameClassBitsNone
= 0x0,
5357 eFrameClassBitsLeaf
= 0x1,
5358 eFrameClassBitsDynamicLeaf
= 0x2,
5360 // Maps mClass to IsLeaf() flags.
5361 static const FrameClassBits sFrameClassBits
[
5362 #define FRAME_ID(...) 1 +
5363 #define ABSTRACT_FRAME_ID(...)
5364 #include "mozilla/FrameIdList.h"
5366 #undef ABSTRACT_FRAME_ID
5369 #ifdef DEBUG_FRAME_DUMP
5371 static void IndentBy(FILE* out
, int32_t aIndent
) {
5372 while (--aIndent
>= 0) fputs(" ", out
);
5374 void ListTag(FILE* out
) const { fputs(ListTag().get(), out
); }
5375 nsAutoCString
ListTag() const;
5377 enum class ListFlag
{TraverseSubdocumentFrames
, DisplayInCSSPixels
};
5378 using ListFlags
= mozilla::EnumSet
<ListFlag
>;
5380 template <typename T
>
5381 static std::string
ConvertToString(const T
& aValue
, ListFlags aFlags
) {
5382 // This method can convert all physical types in app units to CSS pixels.
5383 return aFlags
.contains(ListFlag::DisplayInCSSPixels
)
5384 ? mozilla::ToString(mozilla::CSSPixel::FromAppUnits(aValue
))
5385 : mozilla::ToString(aValue
);
5387 static std::string
ConvertToString(const mozilla::LogicalRect
& aRect
,
5388 const mozilla::WritingMode aWM
,
5390 static std::string
ConvertToString(const mozilla::LogicalSize
& aSize
,
5391 const mozilla::WritingMode aWM
,
5394 void ListGeneric(nsACString
& aTo
, const char* aPrefix
= "",
5395 ListFlags aFlags
= ListFlags()) const;
5396 virtual void List(FILE* out
= stderr
, const char* aPrefix
= "",
5397 ListFlags aFlags
= ListFlags()) const;
5399 void ListTextRuns(FILE* out
= stderr
) const;
5400 virtual void ListTextRuns(FILE* out
,
5401 nsTHashtable
<nsVoidPtrHashKey
>& aSeen
) const;
5403 virtual void ListWithMatchedRules(FILE* out
= stderr
,
5404 const char* aPrefix
= "") const;
5405 void ListMatchedRules(FILE* out
, const char* aPrefix
) const;
5408 * Dump the frame tree beginning from the root frame.
5410 void DumpFrameTree() const;
5411 void DumpFrameTreeInCSSPixels() const;
5414 * Dump the frame tree beginning from ourselves.
5416 void DumpFrameTreeLimited() const;
5417 void DumpFrameTreeLimitedInCSSPixels() const;
5420 * Get a printable from of the name of the frame type.
5421 * XXX This should be eliminated and we use GetType() instead...
5423 virtual nsresult
GetFrameName(nsAString
& aResult
) const;
5424 nsresult
MakeFrameName(const nsAString
& aType
, nsAString
& aResult
) const;
5425 // Helper function to return the index in parent of the frame's content
5426 // object. Returns -1 on error or if the frame doesn't have a content object
5427 static int32_t ContentIndexInContainer(const nsIFrame
* aFrame
);
5432 * Tracing method that writes a method enter/exit routine to the
5433 * nspr log using the nsIFrame log module. The tracing is only
5434 * done when the NS_FRAME_TRACE_CALLS bit is set in the log module's
5437 void Trace(const char* aMethod
, bool aEnter
);
5438 void Trace(const char* aMethod
, bool aEnter
, const nsReflowStatus
& aStatus
);
5439 void TraceMsg(const char* aFormatString
, ...) MOZ_FORMAT_PRINTF(2, 3);
5441 // Helper function that verifies that each frame in the list has the
5442 // NS_FRAME_IS_DIRTY bit set
5443 static void VerifyDirtyBitSet(const nsFrameList
& aFrameList
);
5445 // Display Reflow Debugging
5446 static void* DisplayReflowEnter(nsPresContext
* aPresContext
, nsIFrame
* aFrame
,
5447 const ReflowInput
& aReflowInput
);
5448 static void* DisplayLayoutEnter(nsIFrame
* aFrame
);
5449 static void* DisplayIntrinsicISizeEnter(nsIFrame
* aFrame
, const char* aType
);
5450 static void* DisplayIntrinsicSizeEnter(nsIFrame
* aFrame
, const char* aType
);
5451 static void DisplayReflowExit(nsPresContext
* aPresContext
, nsIFrame
* aFrame
,
5452 ReflowOutput
& aMetrics
,
5453 const nsReflowStatus
& aStatus
,
5454 void* aFrameTreeNode
);
5455 static void DisplayLayoutExit(nsIFrame
* aFrame
, void* aFrameTreeNode
);
5456 static void DisplayIntrinsicISizeExit(nsIFrame
* aFrame
, const char* aType
,
5457 nscoord aResult
, void* aFrameTreeNode
);
5458 static void DisplayIntrinsicSizeExit(nsIFrame
* aFrame
, const char* aType
,
5459 nsSize aResult
, void* aFrameTreeNode
);
5461 static void DisplayReflowStartup();
5462 static void DisplayReflowShutdown();
5464 static mozilla::LazyLogModule sFrameLogModule
;
5466 // Show frame borders when rendering
5467 static void ShowFrameBorders(bool aEnable
);
5468 static bool GetShowFrameBorders();
5470 // Show frame border of event target
5471 static void ShowEventTargetFrameBorder(bool aEnable
);
5472 static bool GetShowEventTargetFrameBorder();
5476 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(nsIFrame::PhysicalAxes
)
5477 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(nsIFrame::ReflowChildFlags
)
5479 //----------------------------------------------------------------------
5482 * AutoWeakFrame can be used to keep a reference to a nsIFrame in a safe way.
5483 * Whenever an nsIFrame object is deleted, the AutoWeakFrames pointing
5484 * to it will be cleared. AutoWeakFrame is for variables on the stack or
5485 * in static storage only, there is also a WeakFrame below for heap uses.
5487 * Create AutoWeakFrame object when it is sure that nsIFrame object
5488 * is alive and after some operations which may destroy the nsIFrame
5489 * (for example any DOM modifications) use IsAlive() or GetFrame() methods to
5490 * check whether it is safe to continue to use the nsIFrame object.
5492 * @note The usage of this class should be kept to a minimum.
5495 class MOZ_NONHEAP_CLASS AutoWeakFrame
{
5497 explicit AutoWeakFrame() : mPrev(nullptr), mFrame(nullptr) {}
5499 AutoWeakFrame(const AutoWeakFrame
& aOther
) : mPrev(nullptr), mFrame(nullptr) {
5500 Init(aOther
.GetFrame());
5503 MOZ_IMPLICIT
AutoWeakFrame(const WeakFrame
& aOther
);
5505 MOZ_IMPLICIT
AutoWeakFrame(nsIFrame
* aFrame
)
5506 : mPrev(nullptr), mFrame(nullptr) {
5510 AutoWeakFrame
& operator=(AutoWeakFrame
& aOther
) {
5511 Init(aOther
.GetFrame());
5515 AutoWeakFrame
& operator=(nsIFrame
* aFrame
) {
5520 nsIFrame
* operator->() { return mFrame
; }
5522 operator nsIFrame
*() { return mFrame
; }
5524 void Clear(mozilla::PresShell
* aPresShell
);
5526 bool IsAlive() const { return !!mFrame
; }
5528 nsIFrame
* GetFrame() const { return mFrame
; }
5530 AutoWeakFrame
* GetPreviousWeakFrame() { return mPrev
; }
5532 void SetPreviousWeakFrame(AutoWeakFrame
* aPrev
) { mPrev
= aPrev
; }
5537 // Not available for the heap!
5538 void* operator new(size_t) = delete;
5539 void* operator new[](size_t) = delete;
5540 void operator delete(void*) = delete;
5541 void operator delete[](void*) = delete;
5543 void Init(nsIFrame
* aFrame
);
5545 AutoWeakFrame
* mPrev
;
5549 // Use nsIFrame's fast-path to avoid QueryFrame:
5550 inline do_QueryFrameHelper
<nsIFrame
> do_QueryFrame(AutoWeakFrame
& s
) {
5551 return do_QueryFrameHelper
<nsIFrame
>(s
.GetFrame());
5555 * @see AutoWeakFrame
5557 class MOZ_HEAP_CLASS WeakFrame
{
5559 WeakFrame() : mFrame(nullptr) {}
5561 WeakFrame(const WeakFrame
& aOther
) : mFrame(nullptr) {
5562 Init(aOther
.GetFrame());
5565 MOZ_IMPLICIT
WeakFrame(const AutoWeakFrame
& aOther
) : mFrame(nullptr) {
5566 Init(aOther
.GetFrame());
5569 MOZ_IMPLICIT
WeakFrame(nsIFrame
* aFrame
) : mFrame(nullptr) { Init(aFrame
); }
5572 Clear(mFrame
? mFrame
->PresContext()->GetPresShell() : nullptr);
5575 WeakFrame
& operator=(WeakFrame
& aOther
) {
5576 Init(aOther
.GetFrame());
5580 WeakFrame
& operator=(nsIFrame
* aFrame
) {
5585 nsIFrame
* operator->() { return mFrame
; }
5586 operator nsIFrame
*() { return mFrame
; }
5588 void Clear(mozilla::PresShell
* aPresShell
);
5590 bool IsAlive() const { return !!mFrame
; }
5591 nsIFrame
* GetFrame() const { return mFrame
; }
5594 void Init(nsIFrame
* aFrame
);
5599 // Use nsIFrame's fast-path to avoid QueryFrame:
5600 inline do_QueryFrameHelper
<nsIFrame
> do_QueryFrame(WeakFrame
& s
) {
5601 return do_QueryFrameHelper
<nsIFrame
>(s
.GetFrame());
5604 inline bool nsFrameList::ContinueRemoveFrame(nsIFrame
* aFrame
) {
5605 MOZ_ASSERT(!aFrame
->GetPrevSibling() || !aFrame
->GetNextSibling(),
5606 "Forgot to call StartRemoveFrame?");
5607 if (aFrame
== mLastChild
) {
5608 MOZ_ASSERT(!aFrame
->GetNextSibling(), "broken frame list");
5609 nsIFrame
* prevSibling
= aFrame
->GetPrevSibling();
5611 MOZ_ASSERT(aFrame
== mFirstChild
, "broken frame list");
5612 mFirstChild
= mLastChild
= nullptr;
5615 MOZ_ASSERT(prevSibling
->GetNextSibling() == aFrame
, "Broken frame linkage");
5616 prevSibling
->SetNextSibling(nullptr);
5617 mLastChild
= prevSibling
;
5620 if (aFrame
== mFirstChild
) {
5621 MOZ_ASSERT(!aFrame
->GetPrevSibling(), "broken frame list");
5622 mFirstChild
= aFrame
->GetNextSibling();
5623 aFrame
->SetNextSibling(nullptr);
5624 MOZ_ASSERT(mFirstChild
, "broken frame list");
5630 inline bool nsFrameList::StartRemoveFrame(nsIFrame
* aFrame
) {
5631 if (aFrame
->GetPrevSibling() && aFrame
->GetNextSibling()) {
5632 UnhookFrameFromSiblings(aFrame
);
5635 return ContinueRemoveFrame(aFrame
);
5638 inline void nsFrameList::Enumerator::Next() {
5639 NS_ASSERTION(!AtEnd(), "Should have checked AtEnd()!");
5640 mFrame
= mFrame
->GetNextSibling();
5643 inline nsFrameList::FrameLinkEnumerator::FrameLinkEnumerator(
5644 const nsFrameList
& aList
, nsIFrame
* aPrevFrame
)
5645 : Enumerator(aList
) {
5647 mFrame
= aPrevFrame
? aPrevFrame
->GetNextSibling() : aList
.FirstChild();
5650 inline void nsFrameList::FrameLinkEnumerator::Next() {
5655 template <typename Predicate
>
5656 inline void nsFrameList::FrameLinkEnumerator::Find(Predicate
&& aPredicate
) {
5658 std::is_same
<typename
mozilla::FunctionTypeTraits
<Predicate
>::ReturnType
,
5660 mozilla::FunctionTypeTraits
<Predicate
>::arity
== 1 &&
5661 std::is_same
<typename
mozilla::FunctionTypeTraits
<
5662 Predicate
>::template ParameterType
<0>,
5664 "aPredicate should be of this function signature: bool(nsIFrame*)");
5666 for (; !AtEnd(); Next()) {
5667 if (aPredicate(mFrame
)) {
5673 // Operators of nsFrameList::Iterator
5674 // ---------------------------------------------------
5676 inline nsFrameList::Iterator
& nsFrameList::Iterator::operator++() {
5677 mCurrent
= mCurrent
->GetNextSibling();
5681 inline nsFrameList::Iterator
& nsFrameList::Iterator::operator--() {
5683 mCurrent
= mList
.LastChild();
5685 mCurrent
= mCurrent
->GetPrevSibling();
5690 #endif /* nsIFrame_h___ */