Backed out changeset 496886cb30a5 (bug 1867152) for bc failures on browser_user_input...
[gecko.git] / layout / generic / nsIFrame.h
blob1ca9e9e0356805b69d04fc122384c3500110a8aa
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 */
9 #ifndef nsIFrame_h___
10 #define nsIFrame_h___
12 #ifndef MOZILLA_INTERNAL_API
13 #error This header/class should only be used within Mozilla code. It should not be used by extensions.
14 #endif
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
37 #else
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
42 #endif
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 */
49 #include <algorithm>
50 #include <stdio.h>
52 #include "CaretAssociationHint.h"
53 #include "FrameProperties.h"
54 #include "LayoutConstants.h"
55 #include "mozilla/AspectRatio.h"
56 #include "mozilla/Attributes.h"
57 #include "mozilla/Baseline.h"
58 #include "mozilla/EnumSet.h"
59 #include "mozilla/EventForwards.h"
60 #include "mozilla/Maybe.h"
61 #include "mozilla/RelativeTo.h"
62 #include "mozilla/Result.h"
63 #include "mozilla/SmallPointerArray.h"
64 #include "mozilla/ToString.h"
65 #include "mozilla/WritingModes.h"
66 #include "nsDirection.h"
67 #include "nsFrameList.h"
68 #include "nsFrameState.h"
69 #include "mozilla/ReflowInput.h"
70 #include "nsIContent.h"
71 #include "nsITheme.h"
72 #include "nsQueryFrame.h"
73 #include "mozilla/ComputedStyle.h"
74 #include "nsStyleStruct.h"
75 #include "Visibility.h"
76 #include "nsChangeHint.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 "mozilla/intl/BidiEmbeddingLevel.h"
82 #include "nsDisplayItemTypes.h"
83 #include "nsPresContext.h"
84 #include "nsTHashSet.h"
86 #ifdef ACCESSIBILITY
87 # include "mozilla/a11y/AccTypes.h"
88 #endif
90 /**
91 * New rules of reflow:
92 * 1. you get a WillReflow() followed by a Reflow() followed by a DidReflow() in
93 * order (no separate pass over the tree)
94 * 2. it's the parent frame's responsibility to size/position the child's view
95 * (not the child frame's responsibility as it is today) during reflow (and
96 * before sending the DidReflow() notification)
97 * 3. positioning of child frames (and their views) is done on the way down the
98 * tree, and sizing of child frames (and their views) on the way back up
99 * 4. if you move a frame (outside of the reflow process, or after reflowing
100 * it), then you must make sure that its view (or its child frame's views)
101 * are re-positioned as well. It's reasonable to not position the view until
102 * after all reflowing the entire line, for example, but the frame should
103 * still be positioned and sized (and the view sized) during the reflow
104 * (i.e., before sending the DidReflow() notification)
105 * 5. the view system handles moving of widgets, i.e., it's not our problem
108 class nsAtom;
109 class nsView;
110 class nsFrameSelection;
111 class nsIWidget;
112 class nsIScrollableFrame;
113 class nsISelectionController;
114 class nsILineIterator;
115 class gfxSkipChars;
116 class gfxSkipCharsIterator;
117 class gfxContext;
118 class nsLineList_iterator;
119 class nsAbsoluteContainingBlock;
120 class nsContainerFrame;
121 class nsPlaceholderFrame;
122 class nsStyleChangeList;
123 class nsViewManager;
124 class nsWindowSizes;
126 struct CharacterDataChangeInfo;
128 namespace mozilla {
130 enum class PeekOffsetOption : uint16_t;
131 enum class PseudoStyleType : uint8_t;
132 enum class TableSelectionMode : uint32_t;
134 class nsDisplayItem;
135 class nsDisplayList;
136 class nsDisplayListBuilder;
137 class nsDisplayListSet;
139 class ServoRestyleState;
140 class EffectSet;
141 class LazyLogModule;
142 class PresShell;
143 class WidgetGUIEvent;
144 class WidgetMouseEvent;
146 struct PeekOffsetStruct;
148 namespace layers {
149 class Layer;
150 class LayerManager;
151 } // namespace layers
153 namespace layout {
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 //----------------------------------------------------------------------
169 namespace mozilla {
171 enum class LayoutFrameType : uint8_t {
172 #define FRAME_TYPE(ty_, ...) ty_,
173 #include "mozilla/FrameTypeList.h"
174 #undef FRAME_TYPE
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
186 eSelectWord = 2,
187 eSelectWordNoSpace = 3, // select a "word" without selecting the following
188 // space, no matter what the default platform
189 // behavior is
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,
196 eSelectEndLine = 6,
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 public:
205 nsReflowStatus()
206 : mFloatClearType(mozilla::StyleClear::None),
207 mInlineBreak(InlineBreak::None),
208 mCompletion(Completion::FullyComplete),
209 mNextInFlowNeedsReflow(false),
210 mFirstLetterComplete(false) {}
212 // Reset all the member variables.
213 void Reset() {
214 mFloatClearType = mozilla::StyleClear::None;
215 mInlineBreak = InlineBreak::None;
216 mCompletion = Completion::FullyComplete;
217 mNextInFlowNeedsReflow = false;
218 mFirstLetterComplete = false;
221 // Return true if all member variables have their default values.
222 bool IsEmpty() const {
223 return (IsFullyComplete() && !IsInlineBreak() && !mNextInFlowNeedsReflow &&
224 !mFirstLetterComplete);
227 // There are three possible completion statuses, represented by
228 // mCompletion.
230 // Incomplete means the frame does *not* map all its content, and the
231 // parent frame should create a continuing frame.
233 // OverflowIncomplete means that the frame has an overflow that is not
234 // complete, but its own box is complete. (This happens when the content
235 // overflows a fixed-height box.) The reflower should place and size the
236 // frame and continue its reflow, but it needs to create an overflow
237 // container as a continuation for this frame. See "Overflow containers"
238 // documentation in nsContainerFrame.h for more information.
240 // FullyComplete means the frame is neither Incomplete nor
241 // OverflowIncomplete. This is the default state for a nsReflowStatus.
243 enum class Completion : uint8_t {
244 // The order of the enum values is important, which represents the
245 // precedence when merging.
246 FullyComplete,
247 OverflowIncomplete,
248 Incomplete,
251 bool IsIncomplete() const { return mCompletion == Completion::Incomplete; }
252 bool IsOverflowIncomplete() const {
253 return mCompletion == Completion::OverflowIncomplete;
255 bool IsFullyComplete() const {
256 return mCompletion == Completion::FullyComplete;
258 // Just for convenience; not a distinct state.
259 bool IsComplete() const { return !IsIncomplete(); }
261 void SetIncomplete() { mCompletion = Completion::Incomplete; }
262 void SetOverflowIncomplete() { mCompletion = Completion::OverflowIncomplete; }
264 // mNextInFlowNeedsReflow bit flag means that the next-in-flow is dirty,
265 // and also needs to be reflowed. This status only makes sense for a frame
266 // that is not complete, i.e. you wouldn't set mNextInFlowNeedsReflow when
267 // IsComplete() is true.
268 bool NextInFlowNeedsReflow() const { return mNextInFlowNeedsReflow; }
269 void SetNextInFlowNeedsReflow() { mNextInFlowNeedsReflow = true; }
271 // Merge the frame completion status bits from aStatus into this.
272 void MergeCompletionStatusFrom(const nsReflowStatus& aStatus) {
273 if (mCompletion < aStatus.mCompletion) {
274 mCompletion = aStatus.mCompletion;
277 // These asserts ensure that the mCompletion merging works as we expect.
278 // (Incomplete beats OverflowIncomplete, which beats FullyComplete.)
279 static_assert(
280 Completion::Incomplete > Completion::OverflowIncomplete &&
281 Completion::OverflowIncomplete > Completion::FullyComplete,
282 "mCompletion merging won't work without this!");
284 mNextInFlowNeedsReflow |= aStatus.mNextInFlowNeedsReflow;
287 // There are three possible inline-break statuses, represented by
288 // mInlineBreak.
290 // "None" means no break is requested.
291 // "Before" means the break should occur before the frame.
292 // "After" means the break should occur after the frame.
293 // (Here, "the frame" is the frame whose reflow results are being reported by
294 // this nsReflowStatus.)
296 enum class InlineBreak : uint8_t {
297 None,
298 Before,
299 After,
302 bool IsInlineBreak() const { return mInlineBreak != InlineBreak::None; }
303 bool IsInlineBreakBefore() const {
304 return mInlineBreak == InlineBreak::Before;
306 bool IsInlineBreakAfter() const { return mInlineBreak == InlineBreak::After; }
307 mozilla::StyleClear FloatClearType() const { return mFloatClearType; }
309 // Set the inline line-break-before status, and reset other bit flags. Note
310 // that other frame completion status isn't expected to matter after calling
311 // this method.
313 // Here's one scenario where a child frame would report this status. Suppose
314 // the child has "break-inside:avoid" in its style, and the child (and its
315 // content) won't fit in the available block-size. This child would want to
316 // report this status so that it gets pushed (in its entirety) to the next
317 // column/page where it will hopefully fit.
318 void SetInlineLineBreakBeforeAndReset() {
319 Reset();
320 mFloatClearType = mozilla::StyleClear::None;
321 mInlineBreak = InlineBreak::Before;
324 // Set the inline line-break-after status. The clear type can be changed
325 // via the optional aClearType param.
326 void SetInlineLineBreakAfter(
327 mozilla::StyleClear aClearType = mozilla::StyleClear::None) {
328 mFloatClearType = aClearType;
329 mInlineBreak = InlineBreak::After;
332 // mFirstLetterComplete bit flag means the break was induced by
333 // completion of a first-letter.
334 bool FirstLetterComplete() const { return mFirstLetterComplete; }
335 void SetFirstLetterComplete() { mFirstLetterComplete = true; }
337 private:
338 mozilla::StyleClear mFloatClearType;
339 InlineBreak mInlineBreak;
340 Completion mCompletion;
341 bool mNextInFlowNeedsReflow : 1;
342 bool mFirstLetterComplete : 1;
345 // Convert nsReflowStatus to a human-readable string.
346 std::ostream& operator<<(std::ostream& aStream, const nsReflowStatus& aStatus);
348 namespace mozilla {
350 // Loosely: https://drafts.csswg.org/css-align-3/#shared-alignment-context
351 enum class AlignmentContext {
352 Inline,
353 Table,
354 Flexbox,
355 Grid,
359 * For replaced elements only. Gets the intrinsic dimensions of this element,
360 * which can be specified on a per-axis basis.
362 struct IntrinsicSize {
363 Maybe<nscoord> width;
364 Maybe<nscoord> height;
366 IntrinsicSize() = default;
368 IntrinsicSize(nscoord aWidth, nscoord aHeight)
369 : width(Some(aWidth)), height(Some(aHeight)) {}
371 explicit IntrinsicSize(const nsSize& aSize)
372 : IntrinsicSize(aSize.Width(), aSize.Height()) {}
374 Maybe<nsSize> ToSize() const {
375 return width && height ? Some(nsSize(*width, *height)) : Nothing();
378 bool operator==(const IntrinsicSize& rhs) const {
379 return width == rhs.width && height == rhs.height;
381 bool operator!=(const IntrinsicSize& rhs) const { return !(*this == rhs); }
384 // Pseudo bidi embedding level indicating nonexistence.
385 constexpr mozilla::intl::BidiEmbeddingLevel kBidiLevelNone(0xff);
387 struct FrameBidiData {
388 mozilla::intl::BidiEmbeddingLevel baseLevel;
389 mozilla::intl::BidiEmbeddingLevel embeddingLevel;
390 // The embedding level of virtual bidi formatting character before
391 // this frame if any. kBidiLevelNone is used to indicate nonexistence
392 // or unnecessity of such virtual character.
393 mozilla::intl::BidiEmbeddingLevel precedingControl;
396 } // namespace mozilla
398 /// Generic destructor for frame properties. Calls delete.
399 template <typename T>
400 static void DeleteValue(T* aPropertyValue) {
401 delete aPropertyValue;
404 /// Generic destructor for frame properties. Calls Release().
405 template <typename T>
406 static void ReleaseValue(T* aPropertyValue) {
407 aPropertyValue->Release();
410 //----------------------------------------------------------------------
413 * nsIFrame logging constants. We redefine the nspr
414 * PRLogModuleInfo.level field to be a bitfield. Each bit controls a
415 * specific type of logging. Each logging operation has associated
416 * inline methods defined below.
418 * Due to the redefinition of the level field we cannot use MOZ_LOG directly
419 * as that will cause assertions due to invalid log levels.
421 #define NS_FRAME_TRACE_CALLS 0x1
422 #define NS_FRAME_TRACE_PUSH_PULL 0x2
423 #define NS_FRAME_TRACE_CHILD_REFLOW 0x4
424 #define NS_FRAME_TRACE_NEW_FRAMES 0x8
426 #define NS_FRAME_LOG_TEST(_lm, _bit) \
427 (int(((mozilla::LogModule*)(_lm))->Level()) & (_bit))
429 #ifdef DEBUG
430 # define NS_FRAME_LOG(_bit, _args) \
431 PR_BEGIN_MACRO \
432 if (NS_FRAME_LOG_TEST(nsIFrame::sFrameLogModule, _bit)) { \
433 printf_stderr _args; \
435 PR_END_MACRO
436 #else
437 # define NS_FRAME_LOG(_bit, _args)
438 #endif
440 // XXX Need to rework this so that logging is free when it's off
441 #ifdef DEBUG
442 # define NS_FRAME_TRACE_IN(_method) Trace(_method, true)
444 # define NS_FRAME_TRACE_OUT(_method) Trace(_method, false)
446 # define NS_FRAME_TRACE(_bit, _args) \
447 PR_BEGIN_MACRO \
448 if (NS_FRAME_LOG_TEST(nsIFrame::sFrameLogModule, _bit)) { \
449 TraceMsg _args; \
451 PR_END_MACRO
453 # define NS_FRAME_TRACE_REFLOW_IN(_method) Trace(_method, true)
455 # define NS_FRAME_TRACE_REFLOW_OUT(_method, _status) \
456 Trace(_method, false, _status)
458 #else
459 # define NS_FRAME_TRACE(_bits, _args)
460 # define NS_FRAME_TRACE_IN(_method)
461 # define NS_FRAME_TRACE_OUT(_method)
462 # define NS_FRAME_TRACE_REFLOW_IN(_method)
463 # define NS_FRAME_TRACE_REFLOW_OUT(_method, _status)
464 #endif
466 //----------------------------------------------------------------------
468 // Frame allocation boilerplate macros. Every subclass of nsFrame must
469 // either use NS_{DECL,IMPL}_FRAMEARENA_HELPERS pair for allocating
470 // memory correctly, or use NS_DECL_ABSTRACT_FRAME to declare a frame
471 // class abstract and stop it from being instantiated. If a frame class
472 // without its own operator new and GetFrameId gets instantiated, the
473 // per-frame recycler lists in nsPresArena will not work correctly,
474 // with potentially catastrophic consequences (not enough memory is
475 // allocated for a frame object).
477 #define NS_DECL_FRAMEARENA_HELPERS(class) \
478 NS_DECL_QUERYFRAME_TARGET(class) \
479 static constexpr nsIFrame::ClassID kClassID = nsIFrame::ClassID::class##_id; \
480 void* operator new(size_t, mozilla::PresShell*) MOZ_MUST_OVERRIDE; \
481 nsQueryFrame::FrameIID GetFrameId() const override MOZ_MUST_OVERRIDE { \
482 return nsQueryFrame::class##_id; \
485 #define NS_IMPL_FRAMEARENA_HELPERS(class) \
486 void* class ::operator new(size_t sz, mozilla::PresShell * aShell) { \
487 return aShell->AllocateFrame(nsQueryFrame::class##_id, sz); \
490 #define NS_DECL_ABSTRACT_FRAME(class) \
491 void* operator new(size_t, mozilla::PresShell*) MOZ_MUST_OVERRIDE = delete; \
492 nsQueryFrame::FrameIID GetFrameId() const override MOZ_MUST_OVERRIDE = 0;
494 //----------------------------------------------------------------------
496 namespace mozilla {
498 // A simple class to group stuff that we need to keep around when tearing down
499 // a frame tree.
501 // Native anonymous content created by the frames need to get unbound _after_
502 // the frame has been destroyed, see bug 1400618.
504 // We destroy the anonymous content bottom-up (so, in reverse order), because
505 // it's a bit simpler, though we generally don't have that much nested anonymous
506 // content (except for scrollbars).
507 struct MOZ_RAII FrameDestroyContext {
508 explicit FrameDestroyContext(PresShell* aPs) : mPresShell(aPs) {}
510 void AddAnonymousContent(already_AddRefed<nsIContent>&& aContent) {
511 if (RefPtr<nsIContent> content = aContent) {
512 mAnonymousContent.AppendElement(std::move(content));
516 ~FrameDestroyContext();
518 private:
519 PresShell* const mPresShell;
520 AutoTArray<RefPtr<nsIContent>, 100> mAnonymousContent;
524 * Bit-flags specific to a given layout class id.
526 enum class LayoutFrameClassFlags : uint16_t {
527 None = 0,
528 Leaf = 1 << 0,
529 LeafDynamic = 1 << 1,
530 MathML = 1 << 2,
531 SVG = 1 << 3,
532 SVGContainer = 1 << 4,
533 BidiInlineContainer = 1 << 5,
534 // The frame is for a replaced element, such as an image
535 Replaced = 1 << 6,
536 // Frame that contains a block but looks like a replaced element from the
537 // outside.
538 ReplacedContainsBlock = 1 << 7,
539 // A replaced element that has replaced-element sizing characteristics (i.e.,
540 // like images or iframes), as opposed to inline-block sizing characteristics
541 // (like form controls).
542 ReplacedSizing = 1 << 8,
543 // A frame that participates in inline reflow, i.e., one that requires
544 // ReflowInput::mLineLayout.
545 LineParticipant = 1 << 9,
546 // Whether this frame is a table part (but not a table or table wrapper).
547 TablePart = 1 << 10,
548 CanContainOverflowContainers = 1 << 11,
549 // Whether the frame supports CSS transforms.
550 SupportsCSSTransforms = 1 << 12,
551 // Whether this frame class supports 'contain: layout' and 'contain: paint'
552 // (supporting one is equivalent to supporting the other).
553 SupportsContainLayoutAndPaint = 1 << 13,
554 // Whether this frame class supports the `aspect-ratio` property.
555 SupportsAspectRatio = 1 << 14,
558 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(LayoutFrameClassFlags)
560 } // namespace mozilla
563 * A frame in the layout model. This interface is supported by all frame
564 * objects.
566 * Frames can have multiple child lists: the default child list
567 * (referred to as the <i>principal</i> child list, and additional named
568 * child lists. There is an ordering of frames within a child list, but
569 * there is no order defined between frames in different child lists of
570 * the same parent frame.
572 * Frames are NOT reference counted. Use the Destroy() member function
573 * to destroy a frame. The lifetime of the frame hierarchy is bounded by the
574 * lifetime of the presentation shell which owns the frames.
576 * nsIFrame is a private Gecko interface. If you are not Gecko then you
577 * should not use it. If you're not in layout, then you won't be able to
578 * link to many of the functions defined here. Too bad.
580 * If you're not in layout but you must call functions in here, at least
581 * restrict yourself to calling virtual methods, which won't hurt you as badly.
583 class nsIFrame : public nsQueryFrame {
584 public:
585 using AlignmentContext = mozilla::AlignmentContext;
586 using BaselineSharingGroup = mozilla::BaselineSharingGroup;
587 using BaselineExportContext = mozilla::BaselineExportContext;
588 template <typename T>
589 using Maybe = mozilla::Maybe<T>;
590 template <typename T, typename E>
591 using Result = mozilla::Result<T, E>;
592 using Nothing = mozilla::Nothing;
593 using OnNonvisible = mozilla::OnNonvisible;
594 using ReflowInput = mozilla::ReflowInput;
595 using ReflowOutput = mozilla::ReflowOutput;
596 using Visibility = mozilla::Visibility;
597 using LengthPercentage = mozilla::LengthPercentage;
598 using ContentRelevancy = mozilla::ContentRelevancy;
600 using nsDisplayItem = mozilla::nsDisplayItem;
601 using nsDisplayList = mozilla::nsDisplayList;
602 using nsDisplayListSet = mozilla::nsDisplayListSet;
603 using nsDisplayListBuilder = mozilla::nsDisplayListBuilder;
605 typedef mozilla::ComputedStyle ComputedStyle;
606 typedef mozilla::FrameProperties FrameProperties;
607 typedef mozilla::layers::LayerManager LayerManager;
608 typedef mozilla::gfx::DrawTarget DrawTarget;
609 typedef mozilla::gfx::Matrix Matrix;
610 typedef mozilla::gfx::Matrix4x4 Matrix4x4;
611 typedef mozilla::gfx::Matrix4x4Flagged Matrix4x4Flagged;
612 typedef mozilla::Sides Sides;
613 typedef mozilla::LogicalSides LogicalSides;
614 typedef mozilla::SmallPointerArray<nsDisplayItem> DisplayItemArray;
616 typedef nsQueryFrame::ClassID ClassID;
618 using ClassFlags = mozilla::LayoutFrameClassFlags;
620 protected:
621 using ChildList = mozilla::FrameChildList;
622 using ChildListID = mozilla::FrameChildListID;
623 using ChildListIDs = mozilla::FrameChildListIDs;
625 public:
626 // nsQueryFrame
627 NS_DECL_QUERYFRAME
628 NS_DECL_QUERYFRAME_TARGET(nsIFrame)
630 explicit nsIFrame(ComputedStyle* aStyle, nsPresContext* aPresContext,
631 ClassID aID)
632 : mContent(nullptr),
633 mComputedStyle(aStyle),
634 mPresContext(aPresContext),
635 mParent(nullptr),
636 mNextSibling(nullptr),
637 mPrevSibling(nullptr),
638 mState(NS_FRAME_FIRST_REFLOW | NS_FRAME_IS_DIRTY),
639 mWritingMode(aStyle),
640 mClass(aID),
641 mMayHaveRoundedCorners(false),
642 mHasImageRequest(false),
643 mHasFirstLetterChild(false),
644 mParentIsWrapperAnonBox(false),
645 mIsWrapperBoxNeedingRestyle(false),
646 mReflowRequestedForCharDataChange(false),
647 mForceDescendIntoIfVisible(false),
648 mBuiltDisplayList(false),
649 mFrameIsModified(false),
650 mHasModifiedDescendants(false),
651 mHasOverrideDirtyRegion(false),
652 mMayHaveWillChangeBudget(false),
653 #ifdef DEBUG
654 mWasVisitedByAutoFrameConstructionPageName(false),
655 #endif
656 mIsPrimaryFrame(false),
657 mMayHaveTransformAnimation(false),
658 mMayHaveOpacityAnimation(false),
659 mAllDescendantsAreInvisible(false),
660 mHasBSizeChange(false),
661 mHasPaddingChange(false),
662 mInScrollAnchorChain(false),
663 mHasColumnSpanSiblings(false),
664 mDescendantMayDependOnItsStaticPosition(false),
665 mShouldGenerateComputedInfo(false) {
666 MOZ_ASSERT(mComputedStyle);
667 MOZ_ASSERT(mPresContext);
668 mozilla::PodZero(&mOverflow);
669 MOZ_COUNT_CTOR(nsIFrame);
671 explicit nsIFrame(ComputedStyle* aStyle, nsPresContext* aPresContext)
672 : nsIFrame(aStyle, aPresContext, ClassID::nsIFrame_id) {}
674 nsPresContext* PresContext() const { return mPresContext; }
676 mozilla::PresShell* PresShell() const { return PresContext()->PresShell(); }
678 virtual nsQueryFrame::FrameIID GetFrameId() const MOZ_MUST_OVERRIDE {
679 return kFrameIID;
683 * Called to initialize the frame. This is called immediately after creating
684 * the frame.
686 * If the frame is a continuing frame, then aPrevInFlow indicates the previous
687 * frame (the frame that was split).
689 * Each subclass that need a view should override this method and call
690 * CreateView() after calling its base class Init().
692 * @param aContent the content object associated with the frame
693 * @param aParent the parent frame
694 * @param aPrevInFlow the prev-in-flow frame
696 virtual void Init(nsIContent* aContent, nsContainerFrame* aParent,
697 nsIFrame* aPrevInFlow);
699 void* operator new(size_t, mozilla::PresShell*) MOZ_MUST_OVERRIDE;
701 using DestroyContext = mozilla::FrameDestroyContext;
704 * Flags for PeekOffsetCharacter, PeekOffsetNoAmount, PeekOffsetWord return
705 * values.
707 enum FrameSearchResult {
708 // Peek found a appropriate offset within frame.
709 FOUND = 0x00,
710 // try next frame for offset.
711 CONTINUE = 0x1,
712 // offset not found because the frame was empty of text.
713 CONTINUE_EMPTY = 0x2 | CONTINUE,
714 // offset not found because the frame didn't contain any text that could be
715 // selected.
716 CONTINUE_UNSELECTABLE = 0x4 | CONTINUE,
720 * Options for PeekOffsetCharacter().
722 struct MOZ_STACK_CLASS PeekOffsetCharacterOptions {
723 // Whether to restrict result to valid cursor locations (between grapheme
724 // clusters) - if this is included, maintains "normal" behavior, otherwise,
725 // used for selection by "code unit" (instead of "character")
726 bool mRespectClusters;
727 // Whether to check user-select style value - if this is included, checks
728 // if user-select is all, then, it may return CONTINUE_UNSELECTABLE.
729 bool mIgnoreUserStyleAll;
731 PeekOffsetCharacterOptions()
732 : mRespectClusters(true), mIgnoreUserStyleAll(false) {}
735 virtual void Destroy(DestroyContext&);
737 protected:
739 * Return true if the frame is part of a Selection.
740 * Helper method to implement the public IsSelected() API.
742 virtual bool IsFrameSelected() const;
744 template <class Source>
745 friend class do_QueryFrameHelper; // to read mClass
746 friend class nsBlockFrame; // for GetCaretBaseline
747 friend class nsContainerFrame; // for ReparentFrameViewTo
749 virtual ~nsIFrame();
751 // Overridden to prevent the global delete from being called, since
752 // the memory came out of an arena instead of the heap.
754 // Ideally this would be private and undefined, like the normal
755 // operator new. Unfortunately, the C++ standard requires an
756 // overridden operator delete to be accessible to any subclass that
757 // defines a virtual destructor, so we can only make it protected;
758 // worse, some C++ compilers will synthesize calls to this function
759 // from the "deleting destructors" that they emit in case of
760 // delete-expressions, so it can't even be undefined.
761 void operator delete(void* aPtr, size_t sz);
763 private:
764 // Left undefined; nsFrame objects are never allocated from the heap.
765 void* operator new(size_t sz) noexcept(true);
767 // Returns true if this frame has any kind of CSS animations.
768 bool HasCSSAnimations();
770 // Returns true if this frame has any kind of CSS transitions.
771 bool HasCSSTransitions();
773 public:
775 * Get the content object associated with this frame. Does not add a
776 * reference.
778 nsIContent* GetContent() const { return mContent; }
781 * @brief Get the closest native anonymous subtree root if the content is in a
782 * native anonymous subtree.
784 * @return The root of native anonymous subtree which the content belongs to.
785 * Otherwise, nullptr.
787 nsIContent* GetClosestNativeAnonymousSubtreeRoot() const {
788 return mContent ? mContent->GetClosestNativeAnonymousSubtreeRoot()
789 : nullptr;
793 * Get the frame that should be the parent for the frames of child elements
794 * May return nullptr during reflow
796 virtual nsContainerFrame* GetContentInsertionFrame() { return nullptr; }
799 * Move any frames on our overflow list to the end of our principal list.
800 * @return true if there were any overflow frames
802 virtual bool DrainSelfOverflowList() { return false; }
805 * Get the frame that should be scrolled if the content associated
806 * with this frame is targeted for scrolling. For frames implementing
807 * nsIScrollableFrame this will return the frame itself. For frames
808 * like nsTextControlFrame that contain a scrollframe, will return
809 * that scrollframe.
811 virtual nsIScrollableFrame* GetScrollTargetFrame() const { return nullptr; }
814 * Get the offsets of the frame. most will be 0,0
817 virtual std::pair<int32_t, int32_t> GetOffsets() const;
820 * Reset the offsets when splitting frames during Bidi reordering
823 virtual void AdjustOffsetsForBidi(int32_t aStart, int32_t aEnd) {}
826 * Get the style associated with this frame.
828 ComputedStyle* Style() const { return mComputedStyle; }
830 void AssertNewStyleIsSane(ComputedStyle&)
831 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
833 #else
836 #endif
838 void SetComputedStyle(ComputedStyle* aStyle) {
839 if (aStyle != mComputedStyle) {
840 AssertNewStyleIsSane(*aStyle);
841 RefPtr<ComputedStyle> oldComputedStyle = std::move(mComputedStyle);
842 mComputedStyle = aStyle;
843 DidSetComputedStyle(oldComputedStyle);
848 * SetComputedStyleWithoutNotification is for changes to the style
849 * context that should suppress style change processing, in other
850 * words, those that aren't really changes. This generally means only
851 * changes that happen during frame construction.
853 void SetComputedStyleWithoutNotification(ComputedStyle* aStyle) {
854 if (aStyle != mComputedStyle) {
855 mComputedStyle = aStyle;
859 protected:
860 // Style post processing hook
861 // Attention: the old style is the one we're forgetting,
862 // and hence possibly completely bogus for GetStyle* purposes.
863 // Use PeekStyleData instead.
864 virtual void DidSetComputedStyle(ComputedStyle* aOldComputedStyle);
866 public:
868 * Define typesafe getter functions for each style struct by
869 * preprocessing the list of style structs. These functions are the
870 * preferred way to get style data. The macro creates functions like:
871 * const nsStyleBorder* StyleBorder();
872 * const nsStyleColor* StyleColor();
874 * Callers outside of libxul should use nsIDOMWindow::GetComputedStyle()
875 * instead of these accessors.
877 * Callers can use Style*WithOptionalParam if they're in a function that
878 * accepts an *optional* pointer the style struct.
880 #define STYLE_STRUCT(name_) \
881 const nsStyle##name_* Style##name_() const MOZ_NONNULL_RETURN { \
882 NS_ASSERTION(mComputedStyle, "No style found!"); \
883 return mComputedStyle->Style##name_(); \
885 const nsStyle##name_* Style##name_##WithOptionalParam( \
886 const nsStyle##name_* aStyleStruct) const MOZ_NONNULL_RETURN { \
887 if (aStyleStruct) { \
888 MOZ_ASSERT(aStyleStruct == Style##name_()); \
889 return aStyleStruct; \
891 return Style##name_(); \
893 #include "nsStyleStructList.h"
894 #undef STYLE_STRUCT
896 /** Also forward GetVisitedDependentColor to the style */
897 template <typename T, typename S>
898 nscolor GetVisitedDependentColor(T S::*aField) {
899 return mComputedStyle->GetVisitedDependentColor(aField);
903 * These methods are to access any additional ComputedStyles that
904 * the frame may be holding.
906 * These are styles that are children of the frame's primary style and are NOT
907 * used as styles for any child frames.
909 * These contexts also MUST NOT have any child styles whatsoever. If you need
910 * to insert styles into the style tree, then you should create pseudo element
911 * frames to own them.
913 * The indicies must be consecutive and implementations MUST return null if
914 * asked for an index that is out of range.
916 virtual ComputedStyle* GetAdditionalComputedStyle(int32_t aIndex) const;
918 virtual void SetAdditionalComputedStyle(int32_t aIndex,
919 ComputedStyle* aComputedStyle);
922 * @param aSelectionStatus nsISelectionController::getDisplaySelection.
924 already_AddRefed<ComputedStyle> ComputeSelectionStyle(
925 int16_t aSelectionStatus) const;
927 already_AddRefed<ComputedStyle> ComputeHighlightSelectionStyle(
928 nsAtom* aHighlightName);
931 * Accessor functions for geometric parent.
933 nsContainerFrame* GetParent() const { return mParent; }
935 bool CanBeDynamicReflowRoot() const;
938 * Gets the parent of a frame, using the parent of the placeholder for
939 * out-of-flow frames.
941 inline nsContainerFrame* GetInFlowParent() const;
944 * Gets the primary frame of the closest flattened tree ancestor that has a
945 * frame (flattened tree ancestors may not have frames in presence of display:
946 * contents).
948 inline nsIFrame* GetClosestFlattenedTreeAncestorPrimaryFrame() const;
951 * Return the placeholder for this frame (which must be out-of-flow).
952 * @note this will only return non-null if |this| is the first-in-flow
953 * although we don't assert that here for legacy reasons.
955 inline nsPlaceholderFrame* GetPlaceholderFrame() const {
956 MOZ_ASSERT(HasAnyStateBits(NS_FRAME_OUT_OF_FLOW));
957 return GetProperty(PlaceholderFrameProperty());
961 * Set this frame's parent to aParent.
962 * If the frame may have moved into or out of a scrollframe's
963 * frame subtree,
964 * StickyScrollContainer::NotifyReparentedFrameAcrossScrollFrameBoundary must
965 * also be called.
967 void SetParent(nsContainerFrame* aParent);
970 * The frame's writing-mode, used for logical layout computations.
971 * It's usually the 'writing-mode' computed value, but there are exceptions:
972 * * inner table frames copy the value from the table frame
973 * (@see nsTableRowGroupFrame::Init, nsTableRowFrame::Init etc)
974 * * the root element frame propagates its value to its ancestors.
975 * The value may obtain from the principal <body> element.
976 * (@see nsCSSFrameConstructor::ConstructDocElementFrame)
977 * * the internal anonymous frames of the root element copy their value
978 * from the parent.
979 * (@see nsIFrame::Init)
980 * * a scrolled frame propagates its value to its ancestor scroll frame
981 * (@see nsHTMLScrollFrame::ReloadChildFrames)
983 mozilla::WritingMode GetWritingMode() const { return mWritingMode; }
986 * Construct a writing mode for line layout in this frame. This is
987 * the writing mode of this frame, except that if this frame is styled with
988 * unicode-bidi:plaintext, we reset the direction to the resolved paragraph
989 * level of the given subframe (typically the first frame on the line),
990 * because the container frame could be split by hard line breaks into
991 * multiple paragraphs with different base direction.
992 * @param aSelfWM the WM of 'this'
994 mozilla::WritingMode WritingModeForLine(mozilla::WritingMode aSelfWM,
995 nsIFrame* aSubFrame) const;
998 * Bounding rect of the frame.
1000 * For frames that are laid out according to CSS box model rules the values
1001 * are in app units, and the origin is relative to the upper-left of the
1002 * geometric parent. The size includes the content area, borders, and
1003 * padding.
1005 * Frames that are laid out according to SVG's coordinate space based rules
1006 * (frames with the NS_FRAME_SVG_LAYOUT bit set, which *excludes*
1007 * SVGOuterSVGFrame) are different. Many frames of this type do not set or
1008 * use mRect, in which case the frame rect is undefined. The exceptions are:
1010 * - SVGInnerSVGFrame
1011 * - SVGGeometryFrame (used for <path>, <circle>, etc.)
1012 * - SVGImageFrame
1013 * - SVGForeignObjectFrame
1015 * For these frames the frame rect contains the frame's element's userspace
1016 * bounds including fill, stroke and markers, but converted to app units
1017 * rather than being in user units (CSS px). In the SVG code "userspace" is
1018 * defined to be the coordinate system for the attributes that define an
1019 * element's geometry (such as the 'cx' attribute for <circle>). For more
1020 * precise details see these frames' implementations of the ReflowSVG method
1021 * where mRect is set.
1023 * Note: moving or sizing the frame does not affect the view's size or
1024 * position.
1026 nsRect GetRect() const { return mRect; }
1027 nsPoint GetPosition() const { return mRect.TopLeft(); }
1028 nsSize GetSize() const { return mRect.Size(); }
1029 nsRect GetRectRelativeToSelf() const {
1030 return nsRect(nsPoint(0, 0), mRect.Size());
1034 * Like the frame's rect (see |GetRect|), which is the border rect,
1035 * other rectangles of the frame, in app units, relative to the parent.
1037 nsRect GetPaddingRect() const;
1038 nsRect GetPaddingRectRelativeToSelf() const;
1039 nsRect GetContentRect() const;
1040 nsRect GetContentRectRelativeToSelf() const;
1041 nsRect GetMarginRect() const;
1042 nsRect GetMarginRectRelativeToSelf() const;
1045 * Dimensions and position in logical coordinates in the frame's writing mode
1046 * or another writing mode
1048 mozilla::LogicalRect GetLogicalRect(const nsSize& aContainerSize) const {
1049 return GetLogicalRect(GetWritingMode(), aContainerSize);
1051 mozilla::LogicalPoint GetLogicalPosition(const nsSize& aContainerSize) const {
1052 return GetLogicalPosition(GetWritingMode(), aContainerSize);
1054 mozilla::LogicalSize GetLogicalSize() const {
1055 return GetLogicalSize(GetWritingMode());
1057 mozilla::LogicalRect GetLogicalRect(mozilla::WritingMode aWritingMode,
1058 const nsSize& aContainerSize) const {
1059 return mozilla::LogicalRect(aWritingMode, GetRect(), aContainerSize);
1061 mozilla::LogicalPoint GetLogicalPosition(mozilla::WritingMode aWritingMode,
1062 const nsSize& aContainerSize) const {
1063 return GetLogicalRect(aWritingMode, aContainerSize).Origin(aWritingMode);
1065 mozilla::LogicalSize GetLogicalSize(mozilla::WritingMode aWritingMode) const {
1066 return mozilla::LogicalSize(aWritingMode, GetSize());
1068 nscoord IStart(const nsSize& aContainerSize) const {
1069 return IStart(GetWritingMode(), aContainerSize);
1071 nscoord IStart(mozilla::WritingMode aWritingMode,
1072 const nsSize& aContainerSize) const {
1073 return GetLogicalPosition(aWritingMode, aContainerSize).I(aWritingMode);
1075 nscoord BStart(const nsSize& aContainerSize) const {
1076 return BStart(GetWritingMode(), aContainerSize);
1078 nscoord BStart(mozilla::WritingMode aWritingMode,
1079 const nsSize& aContainerSize) const {
1080 return GetLogicalPosition(aWritingMode, aContainerSize).B(aWritingMode);
1082 nscoord ISize() const { return ISize(GetWritingMode()); }
1083 nscoord ISize(mozilla::WritingMode aWritingMode) const {
1084 return GetLogicalSize(aWritingMode).ISize(aWritingMode);
1086 nscoord BSize() const { return BSize(GetWritingMode()); }
1087 nscoord BSize(mozilla::WritingMode aWritingMode) const {
1088 return GetLogicalSize(aWritingMode).BSize(aWritingMode);
1090 mozilla::LogicalSize ContentSize() const {
1091 return ContentSize(GetWritingMode());
1093 mozilla::LogicalSize ContentSize(mozilla::WritingMode aWritingMode) const {
1094 mozilla::WritingMode wm = GetWritingMode();
1095 const auto bp = GetLogicalUsedBorderAndPadding(wm)
1096 .ApplySkipSides(GetLogicalSkipSides())
1097 .ConvertTo(aWritingMode, wm);
1098 const auto size = GetLogicalSize(aWritingMode);
1099 return mozilla::LogicalSize(
1100 aWritingMode,
1101 std::max(0, size.ISize(aWritingMode) - bp.IStartEnd(aWritingMode)),
1102 std::max(0, size.BSize(aWritingMode) - bp.BStartEnd(aWritingMode)));
1104 nscoord ContentISize(mozilla::WritingMode aWritingMode) const {
1105 return ContentSize(aWritingMode).ISize(aWritingMode);
1107 nscoord ContentBSize(mozilla::WritingMode aWritingMode) const {
1108 return ContentSize(aWritingMode).BSize(aWritingMode);
1112 * When we change the size of the frame's border-box rect, we may need to
1113 * reset the overflow rect if it was previously stored as deltas.
1114 * (If it is currently a "large" overflow and could be re-packed as deltas,
1115 * we don't bother as the cost of the allocation has already been paid.)
1116 * @param aRebuildDisplayItems If true, then adds this frame to the
1117 * list of modified frames for display list building if the rect has changed.
1118 * Only pass false if you're sure that the relevant display items will be
1119 * rebuilt already (possibly by an ancestor being in the modified list), or if
1120 * this is a temporary change.
1122 void SetRect(const nsRect& aRect, bool aRebuildDisplayItems = true) {
1123 if (aRect == mRect) {
1124 return;
1126 if (mOverflow.mType != OverflowStorageType::Large &&
1127 mOverflow.mType != OverflowStorageType::None) {
1128 mozilla::OverflowAreas overflow = GetOverflowAreas();
1129 mRect = aRect;
1130 SetOverflowAreas(overflow);
1131 } else {
1132 mRect = aRect;
1134 if (aRebuildDisplayItems) {
1135 MarkNeedsDisplayItemRebuild();
1139 * Set this frame's rect from a logical rect in its own writing direction
1141 void SetRect(const mozilla::LogicalRect& aRect,
1142 const nsSize& aContainerSize) {
1143 SetRect(GetWritingMode(), aRect, aContainerSize);
1146 * Set this frame's rect from a logical rect in a different writing direction
1147 * (GetPhysicalRect will assert if the writing mode doesn't match)
1149 void SetRect(mozilla::WritingMode aWritingMode,
1150 const mozilla::LogicalRect& aRect,
1151 const nsSize& aContainerSize) {
1152 SetRect(aRect.GetPhysicalRect(aWritingMode, aContainerSize));
1156 * Set this frame's size from a logical size in its own writing direction.
1157 * This leaves the frame's logical position unchanged, which means its
1158 * physical position may change (for right-to-left modes).
1160 void SetSize(const mozilla::LogicalSize& aSize) {
1161 SetSize(GetWritingMode(), aSize);
1164 * Set this frame's size from a logical size in a different writing direction.
1165 * This leaves the frame's logical position in the given mode unchanged,
1166 * which means its physical position may change (for right-to-left modes).
1168 void SetSize(mozilla::WritingMode aWritingMode,
1169 const mozilla::LogicalSize& aSize) {
1170 if (aWritingMode.IsPhysicalRTL()) {
1171 nscoord oldWidth = mRect.Width();
1172 SetSize(aSize.GetPhysicalSize(aWritingMode));
1173 mRect.x -= mRect.Width() - oldWidth;
1174 } else {
1175 SetSize(aSize.GetPhysicalSize(aWritingMode));
1180 * Set this frame's physical size. This leaves the frame's physical position
1181 * (topLeft) unchanged.
1182 * @param aRebuildDisplayItems If true, then adds this frame to the
1183 * list of modified frames for display list building if the size has changed.
1184 * Only pass false if you're sure that the relevant display items will be
1185 * rebuilt already (possibly by an ancestor being in the modified list), or if
1186 * this is a temporary change.
1188 void SetSize(const nsSize& aSize, bool aRebuildDisplayItems = true) {
1189 SetRect(nsRect(mRect.TopLeft(), aSize), aRebuildDisplayItems);
1192 void SetPosition(const nsPoint& aPt);
1193 void SetPosition(mozilla::WritingMode aWritingMode,
1194 const mozilla::LogicalPoint& aPt,
1195 const nsSize& aContainerSize) {
1196 // We subtract mRect.Size() from the container size to account for
1197 // the fact that logical origins in RTL coordinate systems are at
1198 // the top right of the frame instead of the top left.
1199 SetPosition(
1200 aPt.GetPhysicalPoint(aWritingMode, aContainerSize - mRect.Size()));
1204 * Move the frame, accounting for relative positioning. Use this when
1205 * adjusting the frame's position by a known amount, to properly update its
1206 * saved normal position (see GetNormalPosition below).
1208 * This must be used only when moving a frame *after*
1209 * ReflowInput::ApplyRelativePositioning is called. When moving
1210 * a frame during the reflow process prior to calling
1211 * ReflowInput::ApplyRelativePositioning, the position should
1212 * simply be adjusted directly (e.g., using SetPosition()).
1214 void MovePositionBy(const nsPoint& aTranslation);
1217 * As above, using a logical-point delta in a given writing mode.
1219 void MovePositionBy(mozilla::WritingMode aWritingMode,
1220 const mozilla::LogicalPoint& aTranslation) {
1221 // The LogicalPoint represents a vector rather than a point within a
1222 // rectangular coordinate space, so we use a null containerSize when
1223 // converting logical to physical.
1224 const nsSize nullContainerSize;
1225 MovePositionBy(
1226 aTranslation.GetPhysicalPoint(aWritingMode, nullContainerSize));
1230 * Return frame's rect without relative positioning
1232 nsRect GetNormalRect() const;
1233 mozilla::LogicalRect GetLogicalNormalRect(
1234 mozilla::WritingMode aWritingMode, const nsSize& aContainerSize) const {
1235 return mozilla::LogicalRect(aWritingMode, GetNormalRect(), aContainerSize);
1239 * Returns frame's rect as required by the GetBoundingClientRect() DOM API.
1241 nsRect GetBoundingClientRect();
1244 * Return frame's position without relative positioning.
1245 * If aHasProperty is provided, returns whether the normal position
1246 * was stored in a frame property.
1248 inline nsPoint GetNormalPosition(bool* aHasProperty = nullptr) const;
1249 inline mozilla::LogicalPoint GetLogicalNormalPosition(
1250 mozilla::WritingMode aWritingMode, const nsSize& aContainerSize) const;
1252 virtual nsPoint GetPositionOfChildIgnoringScrolling(const nsIFrame* aChild) {
1253 return aChild->GetPosition();
1256 nsPoint GetPositionIgnoringScrolling() const;
1258 #define NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(prop, type, dtor) \
1259 static const mozilla::FramePropertyDescriptor<type>* prop() { \
1260 /* Use of constexpr caused startup crashes with MSVC2015u1 PGO. */ \
1261 static const auto descriptor = \
1262 mozilla::FramePropertyDescriptor<type>::NewWithDestructor<dtor>(); \
1263 return &descriptor; \
1266 // Don't use this unless you really know what you're doing!
1267 #define NS_DECLARE_FRAME_PROPERTY_WITH_FRAME_IN_DTOR(prop, type, dtor) \
1268 static const mozilla::FramePropertyDescriptor<type>* prop() { \
1269 /* Use of constexpr caused startup crashes with MSVC2015u1 PGO. */ \
1270 static const auto descriptor = mozilla::FramePropertyDescriptor< \
1271 type>::NewWithDestructorWithFrame<dtor>(); \
1272 return &descriptor; \
1275 #define NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(prop, type) \
1276 static const mozilla::FramePropertyDescriptor<type>* prop() { \
1277 /* Use of constexpr caused startup crashes with MSVC2015u1 PGO. */ \
1278 static const auto descriptor = \
1279 mozilla::FramePropertyDescriptor<type>::NewWithoutDestructor(); \
1280 return &descriptor; \
1283 #define NS_DECLARE_FRAME_PROPERTY_DELETABLE(prop, type) \
1284 NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(prop, type, DeleteValue)
1286 #define NS_DECLARE_FRAME_PROPERTY_RELEASABLE(prop, type) \
1287 NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(prop, type, ReleaseValue)
1289 #define NS_DECLARE_FRAME_PROPERTY_WITH_DTOR_NEVER_CALLED(prop, type) \
1290 static void AssertOnDestroyingProperty##prop(type*) { \
1291 MOZ_ASSERT_UNREACHABLE( \
1292 "Frame property " #prop \
1293 " should never be destroyed by the FrameProperties class"); \
1295 NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(prop, type, \
1296 AssertOnDestroyingProperty##prop)
1298 #define NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(prop, type) \
1299 NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(prop, mozilla::SmallValueHolder<type>)
1301 NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(IBSplitSibling, nsContainerFrame)
1302 NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(IBSplitPrevSibling, nsContainerFrame)
1304 NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(NormalPositionProperty, nsPoint)
1305 NS_DECLARE_FRAME_PROPERTY_DELETABLE(ComputedOffsetProperty, nsMargin)
1307 NS_DECLARE_FRAME_PROPERTY_DELETABLE(OutlineInnerRectProperty, nsRect)
1308 NS_DECLARE_FRAME_PROPERTY_DELETABLE(PreEffectsBBoxProperty, nsRect)
1309 NS_DECLARE_FRAME_PROPERTY_DELETABLE(PreTransformOverflowAreasProperty,
1310 mozilla::OverflowAreas)
1312 NS_DECLARE_FRAME_PROPERTY_DELETABLE(OverflowAreasProperty,
1313 mozilla::OverflowAreas)
1315 // The initial overflow area passed to FinishAndStoreOverflow. This is only
1316 // set on frames that Preserve3D() or HasPerspective() or IsTransformed(), and
1317 // when at least one of the overflow areas differs from the frame bound rect.
1318 NS_DECLARE_FRAME_PROPERTY_DELETABLE(InitialOverflowProperty,
1319 mozilla::OverflowAreas)
1321 #ifdef DEBUG
1322 // InitialOverflowPropertyDebug is added to the frame to indicate that either
1323 // the InitialOverflowProperty has been stored or the InitialOverflowProperty
1324 // has been suppressed due to being set to the default value (frame bounds)
1325 NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(DebugInitialOverflowPropertyApplied,
1326 bool)
1327 #endif
1329 NS_DECLARE_FRAME_PROPERTY_DELETABLE(UsedMarginProperty, nsMargin)
1330 NS_DECLARE_FRAME_PROPERTY_DELETABLE(UsedPaddingProperty, nsMargin)
1332 // This tracks the start and end page value for a frame.
1334 // https://www.w3.org/TR/css-page-3/#using-named-pages
1336 // This is only tracked during paginated frame construction.
1337 // This is used to implement fragmentation based on CSS page names. During
1338 // frame construction, we insert page breaks when we begin a new page box and
1339 // the previous page box had a different name.
1340 struct PageValues {
1341 // A value of null indicates that the value is equal to what auto resolves
1342 // to for this frame.
1343 RefPtr<const nsAtom> mStartPageValue = nullptr;
1344 RefPtr<const nsAtom> mEndPageValue = nullptr;
1346 NS_DECLARE_FRAME_PROPERTY_DELETABLE(PageValuesProperty, PageValues)
1348 const nsAtom* GetStartPageValue() const {
1349 if (const PageValues* const values = GetProperty(PageValuesProperty())) {
1350 return values->mStartPageValue;
1352 return nullptr;
1355 const nsAtom* GetEndPageValue() const {
1356 if (const PageValues* const values = GetProperty(PageValuesProperty())) {
1357 return values->mEndPageValue;
1359 return nullptr;
1362 // Returns the page name based on style information for this frame, or null
1363 // if the value is auto.
1364 const nsAtom* GetStylePageName() const {
1365 const mozilla::StylePageName& pageName = StylePage()->mPage;
1366 if (pageName.IsPageName()) {
1367 return pageName.AsPageName().AsAtom();
1369 MOZ_ASSERT(pageName.IsAuto(), "Impossible page name");
1370 return nullptr;
1373 private:
1374 // The value that the CSS page-name "auto" keyword resolves to for children
1375 // of this frame.
1377 // A missing value for this property indicates that the auto value is the
1378 // empty string, which is the default if no ancestors of a frame specify a
1379 // page name. This avoids ever storing this property if the document doesn't
1380 // use named pages.
1382 // https://www.w3.org/TR/css-page-3/#using-named-pages
1384 // Ideally this would be a const atom, but that isn't possible with the
1385 // Release() call. This isn't too bad, since it's hidden behind constness-
1386 // preserving getter/setter.
1387 NS_DECLARE_FRAME_PROPERTY_RELEASABLE(AutoPageValueProperty, nsAtom)
1389 public:
1390 // Get the value that the CSS page-name "auto" keyword resolves to for
1391 // children of this frame.
1392 // This is needed when propagating page-name values up the frame tree.
1393 const nsAtom* GetAutoPageValue() const {
1394 if (const nsAtom* const atom = GetProperty(AutoPageValueProperty())) {
1395 return atom;
1397 return nsGkAtoms::_empty;
1399 void SetAutoPageValue(const nsAtom* aAtom) {
1400 MOZ_ASSERT(aAtom, "Atom must not be null");
1401 nsAtom* const atom = const_cast<nsAtom*>(aAtom);
1402 if (atom != nsGkAtoms::_empty) {
1403 SetProperty(AutoPageValueProperty(), do_AddRef(atom).take());
1407 NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(LineBaselineOffset, nscoord)
1409 NS_DECLARE_FRAME_PROPERTY_DELETABLE(InvalidationRect, nsRect)
1411 NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(RefusedAsyncAnimationProperty, bool)
1413 NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(FragStretchBSizeProperty, nscoord)
1415 // The block-axis margin-box size associated with eBClampMarginBoxMinSize.
1416 NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(BClampMarginBoxMinSizeProperty, nscoord)
1418 NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(IBaselinePadProperty, nscoord)
1419 NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(BBaselinePadProperty, nscoord)
1421 NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(BidiDataProperty,
1422 mozilla::FrameBidiData)
1424 NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(PlaceholderFrameProperty,
1425 nsPlaceholderFrame)
1427 NS_DECLARE_FRAME_PROPERTY_RELEASABLE(OffsetPathCache, mozilla::gfx::Path)
1429 mozilla::FrameBidiData GetBidiData() const {
1430 bool exists;
1431 mozilla::FrameBidiData bidiData = GetProperty(BidiDataProperty(), &exists);
1432 if (!exists) {
1433 bidiData.precedingControl = mozilla::kBidiLevelNone;
1435 return bidiData;
1438 mozilla::intl::BidiEmbeddingLevel GetBaseLevel() const {
1439 return GetBidiData().baseLevel;
1442 mozilla::intl::BidiEmbeddingLevel GetEmbeddingLevel() const {
1443 return GetBidiData().embeddingLevel;
1447 * Return the distance between the border edge of the frame and the
1448 * margin edge of the frame. Like GetRect(), returns the dimensions
1449 * as of the most recent reflow.
1451 * This doesn't include any margin collapsing that may have occurred.
1452 * It also doesn't consider GetSkipSides()/GetLogicalSkipSides(), so
1453 * may report nonzero values on sides that are actually skipped for
1454 * this fragment.
1456 * It also treats 'auto' margins as zero, and treats any margins that
1457 * should have been turned into 'auto' because of overconstraint as
1458 * having their original values.
1460 virtual nsMargin GetUsedMargin() const;
1461 virtual mozilla::LogicalMargin GetLogicalUsedMargin(
1462 mozilla::WritingMode aWritingMode) const {
1463 return mozilla::LogicalMargin(aWritingMode, GetUsedMargin());
1467 * Return the distance between the border edge of the frame (which is
1468 * its rect) and the padding edge of the frame. Like GetRect(), returns
1469 * the dimensions as of the most recent reflow.
1471 * This doesn't consider GetSkipSides()/GetLogicalSkipSides(), so
1472 * may report nonzero values on sides that are actually skipped for
1473 * this fragment.
1475 * Note that this differs from StyleBorder()->GetComputedBorder() in
1476 * that this describes a region of the frame's box, and
1477 * StyleBorder()->GetComputedBorder() describes a border. They differ
1478 * for tables (particularly border-collapse tables) and themed
1479 * elements.
1481 virtual nsMargin GetUsedBorder() const;
1482 virtual mozilla::LogicalMargin GetLogicalUsedBorder(
1483 mozilla::WritingMode aWritingMode) const {
1484 return mozilla::LogicalMargin(aWritingMode, GetUsedBorder());
1488 * Return the distance between the padding edge of the frame and the
1489 * content edge of the frame. Like GetRect(), returns the dimensions
1490 * as of the most recent reflow.
1492 * This doesn't consider GetSkipSides()/GetLogicalSkipSides(), so
1493 * may report nonzero values on sides that are actually skipped for
1494 * this fragment.
1496 virtual nsMargin GetUsedPadding() const;
1497 virtual mozilla::LogicalMargin GetLogicalUsedPadding(
1498 mozilla::WritingMode aWritingMode) const {
1499 return mozilla::LogicalMargin(aWritingMode, GetUsedPadding());
1502 nsMargin GetUsedBorderAndPadding() const {
1503 return GetUsedBorder() + GetUsedPadding();
1505 mozilla::LogicalMargin GetLogicalUsedBorderAndPadding(
1506 mozilla::WritingMode aWritingMode) const {
1507 return mozilla::LogicalMargin(aWritingMode, GetUsedBorderAndPadding());
1511 * The area to paint box-shadows around. The default is the border rect.
1512 * (nsFieldSetFrame overrides this).
1514 virtual nsRect VisualBorderRectRelativeToSelf() const {
1515 return nsRect(0, 0, mRect.Width(), mRect.Height());
1519 * Get the size, in app units, of the border radii. It returns FALSE iff all
1520 * returned radii == 0 (so no border radii), TRUE otherwise.
1521 * For the aRadii indexes, use the enum HalfCorner constants in gfx/2d/Types.h
1522 * If a side is skipped via aSkipSides, its corners are forced to 0.
1524 * All corner radii are then adjusted so they do not require more
1525 * space than aBorderArea, according to the algorithm in css3-background.
1527 * aFrameSize is used as the basis for percentage widths and heights.
1528 * aBorderArea is used for the adjustment of radii that might be too
1529 * large.
1531 * Return whether any radii are nonzero.
1533 static bool ComputeBorderRadii(const mozilla::BorderRadius&,
1534 const nsSize& aFrameSize,
1535 const nsSize& aBorderArea, Sides aSkipSides,
1536 nscoord aRadii[8]);
1539 * Given a set of border radii for one box (e.g., border box), convert
1540 * it to the equivalent set of radii for another box (e.g., in to
1541 * padding box, out to outline box) by reducing radii or increasing
1542 * nonzero radii as appropriate.
1544 * Indices into aRadii are the enum HalfCorner constants in gfx/2d/Types.h
1546 * Note that insetting the radii is lossy, since it can turn nonzero radii
1547 * into zero, and re-adjusting does not inflate zero radii.
1549 * Therefore, callers should always adjust directly from the original value
1550 * coming from style.
1552 static void AdjustBorderRadii(nscoord aRadii[8], const nsMargin& aOffsets);
1555 * Fill in border radii for this frame. Return whether any are nonzero.
1556 * Indices into aRadii are the enum HalfCorner constants in gfx/2d/Types.h
1557 * aSkipSides is a union of SideBits::eLeft/Right/Top/Bottom bits that says
1558 * which side(s) to skip.
1560 * Note: GetMarginBoxBorderRadii() and GetShapeBoxBorderRadii() work only
1561 * on frames that establish block formatting contexts since they don't
1562 * participate in margin-collapsing.
1564 virtual bool GetBorderRadii(const nsSize& aFrameSize,
1565 const nsSize& aBorderArea, Sides aSkipSides,
1566 nscoord aRadii[8]) const;
1567 bool GetBorderRadii(nscoord aRadii[8]) const;
1568 bool GetMarginBoxBorderRadii(nscoord aRadii[8]) const;
1569 bool GetPaddingBoxBorderRadii(nscoord aRadii[8]) const;
1570 bool GetContentBoxBorderRadii(nscoord aRadii[8]) const;
1571 bool GetBoxBorderRadii(nscoord aRadii[8], const nsMargin& aOffset) const;
1572 bool GetShapeBoxBorderRadii(nscoord aRadii[8]) const;
1575 * `GetNaturalBaselineBOffset`, but determines the baseline sharing group
1576 * through `GetDefaultBaselineSharingGroup` (If not specified), assuming line
1577 * layout context, and never fails, returning a synthesized baseline through
1578 * `SynthesizeFallbackBaseline`. Unlike `GetNaturalBaselineBOffset`, Result is
1579 * always relative to the block start of the frame.
1581 nscoord GetLogicalBaseline(mozilla::WritingMode aWM) const;
1583 * Same as the above, but with baseline sharing group & export
1584 * context specified.
1586 nscoord GetLogicalBaseline(mozilla::WritingMode aWM,
1587 BaselineSharingGroup aBaselineGroup,
1588 BaselineExportContext aExportContext) const;
1591 * Return true if the frame has a first(last) inline-axis baseline per
1592 * CSS Box Alignment. If so, the returned baseline is the distance from
1593 * the relevant block-axis border-box edge (Start for
1594 * BaselineSharingGroup::First, end for BaselineSharingGroup::Last), where
1595 * a positive value points towards the content-box.
1596 * Some frames can export different baselines depending if it's in a line
1597 * layout context or any other context (e.g. Flex, grid).
1598 * https://drafts.csswg.org/css-align-3/#baseline-export
1599 * @note The returned value is only valid when reflow is not needed.
1600 * @note You should only call this on frames with a WM that's parallel to aWM.
1601 * @note We're approaching `nsLayoutUtils::Get(First|Last)LineBaseline` ==
1602 * `GetNaturalBaselineBOffset(aWM, (First|Last), Other)`. Grid relies on
1603 * baseline synthesis behaviour in `nsLayoutUtils` implementations (bug
1604 * 1609403), which blocks its removal.
1605 * @param aWM the writing-mode of the alignment context.
1606 * @return the baseline offset, if one exists
1608 virtual Maybe<nscoord> GetNaturalBaselineBOffset(
1609 mozilla::WritingMode aWM, BaselineSharingGroup aBaselineGroup,
1610 BaselineExportContext aExportContext) const {
1611 return Nothing{};
1614 struct CaretBlockAxisMetrics {
1615 nscoord mOffset = 0;
1616 nscoord mExtent = 0;
1619 * Get the offset (Block start of the caret) and extent of the caret in this
1620 * frame. The returned offset is corrected for vertical & line-inverted
1621 * writing modes.
1623 CaretBlockAxisMetrics GetCaretBlockAxisMetrics(mozilla::WritingMode,
1624 const nsFontMetrics&) const;
1625 // Gets the page-name value to be used for the page that contains this frame
1626 // during paginated reflow.
1627 // This only inspects the first in-flow child of this frame, and if that
1628 // is a container frame then its first in-flow child, until it reaches the
1629 // deepest child of the tree.
1630 // This will resolve auto values, including the case where no frame has a
1631 // page-name set in which case it will return the empty atom. It will never
1632 // return null.
1633 // This is intended to be used either on the root frame to find the first
1634 // page's page-name, or on a newly created continuation to find what the new
1635 // page's page-name will be.
1636 const nsAtom* ComputePageValue() const MOZ_NONNULL_RETURN;
1638 ///////////////////////////////////////////////////////////////////////////////
1639 // The public visibility API.
1640 ///////////////////////////////////////////////////////////////////////////////
1642 /// @return true if we're tracking visibility for this frame.
1643 bool TrackingVisibility() const {
1644 return HasAnyStateBits(NS_FRAME_VISIBILITY_IS_TRACKED);
1647 /// @return the visibility state of this frame. See the Visibility enum
1648 /// for the possible return values and their meanings.
1649 Visibility GetVisibility() const;
1651 /// Update the visibility state of this frame synchronously.
1652 /// XXX(seth): Avoid using this method; we should be relying on the refresh
1653 /// driver for visibility updates. This method, which replaces
1654 /// nsLayoutUtils::UpdateApproximateFrameVisibility(), exists purely as a
1655 /// temporary measure to avoid changing behavior during the transition from
1656 /// the old image visibility code.
1657 void UpdateVisibilitySynchronously();
1659 // A frame property which stores the visibility state of this frame. Right
1660 // now that consists of an approximate visibility counter represented as a
1661 // uint32_t. When the visibility of this frame is not being tracked, this
1662 // property is absent.
1663 NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(VisibilityStateProperty, uint32_t);
1665 protected:
1667 * Get the position of the baseline on which the caret needs to be placed,
1668 * relative to the top of the frame. This is mostly needed for frames
1669 * which return a baseline from GetBaseline which is not useful for
1670 * caret positioning.
1672 virtual nscoord GetCaretBaseline() const {
1673 return GetLogicalBaseline(GetWritingMode());
1677 * Subclasses can call this method to enable visibility tracking for this
1678 * frame.
1680 * If visibility tracking was previously disabled, this will schedule an
1681 * update an asynchronous update of visibility.
1683 void EnableVisibilityTracking();
1686 * Subclasses can call this method to disable visibility tracking for this
1687 * frame.
1689 * Note that if visibility tracking was previously enabled, disabling
1690 * visibility tracking will cause a synchronous call to OnVisibilityChange().
1692 void DisableVisibilityTracking();
1695 * Called when a frame transitions between visibility states (for example,
1696 * from nonvisible to visible, or from visible to nonvisible).
1698 * @param aNewVisibility The new visibility state.
1699 * @param aNonvisibleAction A requested action if the frame has become
1700 * nonvisible. If Nothing(), no action is
1701 * requested. If DISCARD_IMAGES is specified, the
1702 * frame is requested to ask any images it's
1703 * associated with to discard their surfaces if
1704 * possible.
1706 * Subclasses which override this method should call their parent class's
1707 * implementation.
1709 virtual void OnVisibilityChange(
1710 Visibility aNewVisibility,
1711 const Maybe<OnNonvisible>& aNonvisibleAction = Nothing());
1714 * Synthesize a baseline for this element. The returned baseline is the
1715 * distance from the relevant block-axis border-box edge (Start for
1716 * BaselineSharingGroup::First, end for BaselineSharingGroup::Last), where a
1717 * positive value points towards the content-box.
1718 * @note This always returns a synthesized baseline, even if the element may
1719 * have an actual baseline.
1721 virtual nscoord SynthesizeFallbackBaseline(
1722 mozilla::WritingMode aWM, BaselineSharingGroup aBaselineGroup) const;
1724 public:
1726 * Get the suitable baseline sharing group for this element, assuming line
1727 * layout.
1729 virtual BaselineSharingGroup GetDefaultBaselineSharingGroup() const {
1730 return BaselineSharingGroup::First;
1733 ///////////////////////////////////////////////////////////////////////////////
1734 // Internal implementation for the approximate frame visibility API.
1735 ///////////////////////////////////////////////////////////////////////////////
1738 * We track the approximate visibility of frames using a counter; if it's
1739 * non-zero, then the frame is considered visible. Using a counter allows us
1740 * to account for situations where the frame may be visible in more than one
1741 * place (for example, via -moz-element), and it simplifies the
1742 * implementation of our approximate visibility tracking algorithms.
1744 * @param aNonvisibleAction A requested action if the frame has become
1745 * nonvisible. If Nothing(), no action is
1746 * requested. If DISCARD_IMAGES is specified, the
1747 * frame is requested to ask any images it's
1748 * associated with to discard their surfaces if
1749 * possible.
1751 void DecApproximateVisibleCount(
1752 const Maybe<OnNonvisible>& aNonvisibleAction = Nothing());
1753 void IncApproximateVisibleCount();
1756 * Get the specified child list.
1758 * @param aListID identifies the requested child list.
1759 * @return the child list. If the requested list is unsupported by this
1760 * frame type, an empty list will be returned.
1762 virtual const nsFrameList& GetChildList(ChildListID aListID) const;
1763 const nsFrameList& PrincipalChildList() const {
1764 return GetChildList(mozilla::FrameChildListID::Principal);
1768 * Sub-classes should override this methods if they want to append their own
1769 * child lists into aLists.
1771 virtual void GetChildLists(nsTArray<ChildList>* aLists) const;
1774 * Returns the child lists for this frame.
1776 AutoTArray<ChildList, 4> ChildLists() const {
1777 AutoTArray<ChildList, 4> childLists;
1778 GetChildLists(&childLists);
1779 return childLists;
1783 * Returns the child lists for this frame, including ones belong to a child
1784 * document.
1786 AutoTArray<ChildList, 4> CrossDocChildLists();
1789 * Child frames are linked together in a doubly-linked list
1791 nsIFrame* GetNextSibling() const { return mNextSibling; }
1792 void SetNextSibling(nsIFrame* aNextSibling) {
1793 NS_ASSERTION(this != aNextSibling,
1794 "Creating a circular frame list, this is very bad.");
1795 if (mNextSibling && mNextSibling->GetPrevSibling() == this) {
1796 mNextSibling->mPrevSibling = nullptr;
1798 mNextSibling = aNextSibling;
1799 if (mNextSibling) {
1800 mNextSibling->mPrevSibling = this;
1804 nsIFrame* GetPrevSibling() const { return mPrevSibling; }
1807 * Builds the display lists for the content represented by this frame
1808 * and its descendants. The background+borders of this element must
1809 * be added first, before any other content.
1811 * This should only be called by methods in nsFrame. Instead of calling this
1812 * directly, call either BuildDisplayListForStackingContext or
1813 * BuildDisplayListForChild.
1815 * See nsDisplayList.h for more information about display lists.
1817 virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
1818 const nsDisplayListSet& aLists) {}
1820 * Displays the caret onto the given display list builder. The caret is
1821 * painted on top of the rest of the display list items.
1823 void DisplayCaret(nsDisplayListBuilder* aBuilder, nsDisplayList* aList);
1826 * Get the preferred caret color at the offset.
1828 * @param aOffset is offset of the content.
1830 virtual nscolor GetCaretColorAt(int32_t aOffset);
1832 bool IsThemed(nsITheme::Transparency* aTransparencyState = nullptr) const {
1833 return IsThemed(StyleDisplay(), aTransparencyState);
1835 bool IsThemed(const nsStyleDisplay* aDisp,
1836 nsITheme::Transparency* aTransparencyState = nullptr) const {
1837 if (!aDisp->HasAppearance()) {
1838 return false;
1840 nsIFrame* mutable_this = const_cast<nsIFrame*>(this);
1841 nsPresContext* pc = PresContext();
1842 nsITheme* theme = pc->Theme();
1843 if (!theme->ThemeSupportsWidget(pc, mutable_this,
1844 aDisp->EffectiveAppearance())) {
1845 return false;
1847 if (aTransparencyState) {
1848 *aTransparencyState = theme->GetWidgetTransparency(
1849 mutable_this, aDisp->EffectiveAppearance());
1851 return true;
1855 * Builds a display list for the content represented by this frame,
1856 * treating this frame as the root of a stacking context.
1857 * Optionally sets aCreatedContainerItem to true if we created a
1858 * single container display item for the stacking context, and no
1859 * other wrapping items are needed.
1861 void BuildDisplayListForStackingContext(
1862 nsDisplayListBuilder* aBuilder, nsDisplayList* aList,
1863 bool* aCreatedContainerItem = nullptr);
1865 enum class DisplayChildFlag {
1866 ForcePseudoStackingContext,
1867 ForceStackingContext,
1868 Inline,
1870 using DisplayChildFlags = mozilla::EnumSet<DisplayChildFlag>;
1873 * Adjusts aDirtyRect for the child's offset, checks that the dirty rect
1874 * actually intersects the child (or its descendants), calls BuildDisplayList
1875 * on the child if necessary, and puts things in the right lists if the child
1876 * is positioned.
1878 * @param aFlags a set of of DisplayChildFlag values that are applicable for
1879 * this operation.
1881 void BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
1882 nsIFrame* aChild,
1883 const nsDisplayListSet& aLists,
1884 DisplayChildFlags aFlags = {});
1886 void BuildDisplayListForSimpleChild(nsDisplayListBuilder* aBuilder,
1887 nsIFrame* aChild,
1888 const nsDisplayListSet& aLists);
1891 * Helper for BuildDisplayListForChild, to implement this special-case for
1892 * grid (and flex) items from the spec:
1893 * The painting order of grid items is exactly the same as inline blocks,
1894 * except that [...], and 'z-index' values other than 'auto' create a
1895 * stacking context even if 'position' is 'static' (behaving exactly as if
1896 * 'position' were 'relative'). https://drafts.csswg.org/css-grid/#z-order
1898 * Flex items also have the same special-case described in
1899 * https://drafts.csswg.org/css-flexbox/#painting
1901 static DisplayChildFlags DisplayFlagsForFlexOrGridItem() {
1902 return DisplayChildFlags{DisplayChildFlag::ForcePseudoStackingContext};
1905 bool RefusedAsyncAnimation() const {
1906 return GetProperty(RefusedAsyncAnimationProperty());
1910 * Returns true if this frame is transformed (e.g. has CSS, SVG, or custom
1911 * transforms) or if its parent is an SVG frame that has children-only
1912 * transforms (e.g. an SVG viewBox attribute) or if its transform-style is
1913 * preserve-3d or the frame has transform animations.
1915 bool IsTransformed() const;
1918 * Same as IsTransformed, except that it doesn't take SVG transforms
1919 * into account.
1921 bool IsCSSTransformed() const;
1924 * True if this frame has any animation of transform in effect.
1926 bool HasAnimationOfTransform() const;
1929 * True if this frame has any animation of opacity in effect.
1931 * EffectSet is just an optimization.
1933 bool HasAnimationOfOpacity(mozilla::EffectSet* = nullptr) const;
1936 * Returns true if the frame is translucent or the frame has opacity
1937 * animations for the purposes of creating a stacking context.
1939 * @param aStyleDisplay: This function needs style display struct.
1941 * @param aStyleEffects: This function needs style effects struct.
1943 * @param aEffectSet: This function may need to look up EffectSet property.
1944 * If a caller already have one, pass it in can save property look up
1945 * time; otherwise, just leave it as nullptr.
1947 bool HasOpacity(const nsStyleDisplay* aStyleDisplay,
1948 const nsStyleEffects* aStyleEffects,
1949 mozilla::EffectSet* aEffectSet = nullptr) const {
1950 return HasOpacityInternal(1.0f, aStyleDisplay, aStyleEffects, aEffectSet);
1953 * Returns true if the frame is translucent for display purposes.
1955 * @param aStyleDisplay: This function needs style display struct.
1957 * @param aStyleEffects: This function needs style effects struct.
1959 * @param aEffectSet: This function may need to look up EffectSet property.
1960 * If a caller already have one, pass it in can save property look up
1961 * time; otherwise, just leave it as nullptr.
1963 bool HasVisualOpacity(const nsStyleDisplay* aStyleDisplay,
1964 const nsStyleEffects* aStyleEffects,
1965 mozilla::EffectSet* aEffectSet = nullptr) const {
1966 // Treat an opacity value of 0.99 and above as opaque. This is an
1967 // optimization aimed at Web content which use opacity:0.99 as a hint for
1968 // creating a stacking context only.
1969 return HasOpacityInternal(0.99f, aStyleDisplay, aStyleEffects, aEffectSet);
1973 * Returns a matrix (in pixels) for the current frame. The matrix should be
1974 * relative to the current frame's coordinate space.
1976 * @param aFrame The frame to compute the transform for.
1977 * @param aAppUnitsPerPixel The number of app units per graphics unit.
1979 using ComputeTransformFunction = Matrix4x4 (*)(const nsIFrame*,
1980 float aAppUnitsPerPixel);
1981 /** Returns the transform getter of this frame, if any. */
1982 virtual ComputeTransformFunction GetTransformGetter() const {
1983 return nullptr;
1987 * Returns true if this frame is an SVG frame that has SVG transforms applied
1988 * to it, or if its parent frame is an SVG frame that has children-only
1989 * transforms (e.g. an SVG viewBox attribute).
1990 * If aOwnTransforms is non-null and the frame has its own SVG transforms,
1991 * aOwnTransforms will be set to these transforms. If aFromParentTransforms
1992 * is non-null and the frame has an SVG parent with children-only transforms,
1993 * then aFromParentTransforms will be set to these transforms.
1995 virtual bool IsSVGTransformed(Matrix* aOwnTransforms = nullptr,
1996 Matrix* aFromParentTransforms = nullptr) const;
1999 * Returns whether this frame will attempt to extend the 3d transforms of its
2000 * children. This requires transform-style: preserve-3d, as well as no
2001 * clipping or svg effects.
2003 * @param aStyleDisplay: If the caller has this->StyleDisplay(), providing
2004 * it here will improve performance.
2006 * @param aStyleEffects: If the caller has this->StyleEffects(), providing
2007 * it here will improve performance.
2009 * @param aEffectSetForOpacity: This function may need to look up the
2010 * EffectSet for opacity animations on this frame.
2011 * If the caller already has looked up this EffectSet, it may pass it in to
2012 * save an extra property lookup.
2014 bool Extend3DContext(
2015 const nsStyleDisplay* aStyleDisplay, const nsStyleEffects* aStyleEffects,
2016 mozilla::EffectSet* aEffectSetForOpacity = nullptr) const;
2017 bool Extend3DContext(
2018 mozilla::EffectSet* aEffectSetForOpacity = nullptr) const {
2019 return Extend3DContext(StyleDisplay(), StyleEffects(),
2020 aEffectSetForOpacity);
2024 * Returns whether this frame has a parent that Extend3DContext() and has
2025 * its own transform (or hidden backface) to be combined with the parent's
2026 * transform.
2028 bool Combines3DTransformWithAncestors() const;
2031 * Returns whether this frame has a hidden backface and has a parent that
2032 * Extend3DContext(). This is useful because in some cases the hidden
2033 * backface can safely be ignored if it could not be visible anyway.
2036 bool In3DContextAndBackfaceIsHidden() const;
2038 bool IsPreserve3DLeaf(const nsStyleDisplay* aStyleDisplay,
2039 mozilla::EffectSet* aEffectSet = nullptr) const {
2040 return Combines3DTransformWithAncestors() &&
2041 !Extend3DContext(aStyleDisplay, StyleEffects(), aEffectSet);
2043 bool IsPreserve3DLeaf(mozilla::EffectSet* aEffectSet = nullptr) const {
2044 return IsPreserve3DLeaf(StyleDisplay(), aEffectSet);
2047 bool HasPerspective() const;
2049 bool ChildrenHavePerspective(const nsStyleDisplay* aStyleDisplay) const;
2050 bool ChildrenHavePerspective() const {
2051 return ChildrenHavePerspective(StyleDisplay());
2055 * Includes the overflow area of all descendants that participate in the
2056 * current 3d context into aOverflowAreas.
2058 void ComputePreserve3DChildrenOverflow(
2059 mozilla::OverflowAreas& aOverflowAreas);
2061 void RecomputePerspectiveChildrenOverflow(const nsIFrame* aStartFrame);
2064 * Returns whether z-index applies to this frame.
2066 bool ZIndexApplies() const;
2069 * Returns the computed z-index for this frame, returning Nothing() for
2070 * z-index: auto, and for frames that don't support z-index.
2072 Maybe<int32_t> ZIndex() const;
2075 * Returns whether this frame is the anchor of some ancestor scroll frame. As
2076 * this frame is moved, the scroll frame will apply adjustments to keep this
2077 * scroll frame in the same relative position.
2079 * aOutContainer will optionally be set to the scroll anchor container for
2080 * this frame if this frame is an anchor.
2082 bool IsScrollAnchor(
2083 mozilla::layout::ScrollAnchorContainer** aOutContainer = nullptr);
2086 * Returns whether this frame is the anchor of some ancestor scroll frame, or
2087 * has a descendant which is the scroll anchor.
2089 bool IsInScrollAnchorChain() const;
2090 void SetInScrollAnchorChain(bool aInChain);
2093 * Returns the number of ancestors between this and the root of our frame tree
2095 uint32_t GetDepthInFrameTree() const;
2098 * Event handling of GUI events.
2100 * @param aEvent event structure describing the type of event and rge widget
2101 * where the event originated. The |point| member of this is in the coordinate
2102 * system of the view returned by GetOffsetFromView.
2104 * @param aEventStatus a return value indicating whether the event was
2105 * handled and whether default processing should be done
2107 * XXX From a frame's perspective it's unclear what the effect of the event
2108 * status is. Does it cause the event to continue propagating through the
2109 * frame hierarchy or is it just returned to the widgets?
2111 * @see WidgetGUIEvent
2112 * @see nsEventStatus
2114 MOZ_CAN_RUN_SCRIPT_BOUNDARY
2115 virtual nsresult HandleEvent(nsPresContext* aPresContext,
2116 mozilla::WidgetGUIEvent* aEvent,
2117 nsEventStatus* aEventStatus);
2120 * Search for selectable content at point and attempt to select
2121 * based on the start and end selection behaviours.
2123 * @param aPresContext Presentation context
2124 * @param aPoint Point at which selection will occur. Coordinates
2125 * should be relative to this frame.
2126 * @param aBeginAmountType, aEndAmountType Selection behavior, see
2127 * nsIFrame for definitions.
2128 * @param aSelectFlags Selection flags defined in nsIFrame.h.
2129 * @return success or failure at finding suitable content to select.
2131 MOZ_CAN_RUN_SCRIPT nsresult
2132 SelectByTypeAtPoint(nsPresContext* aPresContext, const nsPoint& aPoint,
2133 nsSelectionAmount aBeginAmountType,
2134 nsSelectionAmount aEndAmountType, uint32_t aSelectFlags);
2136 MOZ_CAN_RUN_SCRIPT nsresult PeekBackwardAndForward(
2137 nsSelectionAmount aAmountBack, nsSelectionAmount aAmountForward,
2138 int32_t aStartPos, bool aJumpLines, uint32_t aSelectFlags);
2140 enum { SELECT_ACCUMULATE = 0x01 };
2142 protected:
2143 // Fire DOM event. If no aContent argument use frame's mContent.
2144 void FireDOMEvent(const nsAString& aDOMEventName,
2145 nsIContent* aContent = nullptr);
2147 // Selection Methods
2149 MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHOD
2150 HandlePress(nsPresContext* aPresContext, mozilla::WidgetGUIEvent* aEvent,
2151 nsEventStatus* aEventStatus);
2154 * MoveCaretToEventPoint() moves caret at the point of aMouseEvent.
2156 * @param aPresContext Must not be nullptr.
2157 * @param aMouseEvent Must not be nullptr, the message must be
2158 * eMouseDown and its button must be primary or
2159 * middle button.
2160 * @param aEventStatus [out] Must not be nullptr. This method ignores
2161 * its initial value, but callees may refer it.
2163 MOZ_CAN_RUN_SCRIPT nsresult MoveCaretToEventPoint(
2164 nsPresContext* aPresContext, mozilla::WidgetMouseEvent* aMouseEvent,
2165 nsEventStatus* aEventStatus);
2168 * Check whether aSecondaryButtonMouseEvent should or should not cause moving
2169 * caret at event point. This is designed only for the secondary mouse button
2170 * event (i.e., right button event in general).
2172 * @param aFrameSelection The nsFrameSelection which should handle the
2173 * caret move with.
2174 * @param aSecondaryButtonEvent Must be the button value is
2175 * MouseButton::eSecondary.
2176 * @param aContentAtEventPoint The content node at the event point.
2177 * @param aOffsetAtEventPoint The offset in aContentAtEventPoint where
2178 * aSecondaryButtonEvent clicked.
2180 [[nodiscard]] bool MovingCaretToEventPointAllowedIfSecondaryButtonEvent(
2181 const nsFrameSelection& aFrameSelection,
2182 mozilla::WidgetMouseEvent& aSecondaryButtonEvent,
2183 const nsIContent& aContentAtEventPoint,
2184 int32_t aOffsetAtEventPoint) const;
2186 MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHOD HandleMultiplePress(
2187 nsPresContext* aPresContext, mozilla::WidgetGUIEvent* aEvent,
2188 nsEventStatus* aEventStatus, bool aControlHeld);
2191 * @param aPresContext must be non-nullptr.
2192 * @param aEvent must be non-nullptr.
2193 * @param aEventStatus must be non-nullptr.
2195 MOZ_CAN_RUN_SCRIPT
2196 NS_IMETHOD HandleDrag(nsPresContext* aPresContext,
2197 mozilla::WidgetGUIEvent* aEvent,
2198 nsEventStatus* aEventStatus);
2200 MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHOD
2201 HandleRelease(nsPresContext* aPresContext, mozilla::WidgetGUIEvent* aEvent,
2202 nsEventStatus* aEventStatus);
2204 // Test if we are selecting a table object:
2205 // Most table/cell selection requires that Ctrl (Cmd on Mac) key is down
2206 // during a mouse click or drag. Exception is using Shift+click when
2207 // already in "table/cell selection mode" to extend a block selection
2208 // Get the parent content node and offset of the frame
2209 // of the enclosing cell or table (if not inside a cell)
2210 // aTarget tells us what table element to select (currently only cell and
2211 // table supported) (enums for this are defined in nsIFrame.h)
2212 nsresult GetDataForTableSelection(const nsFrameSelection* aFrameSelection,
2213 mozilla::PresShell* aPresShell,
2214 mozilla::WidgetMouseEvent* aMouseEvent,
2215 nsIContent** aParentContent,
2216 int32_t* aContentOffset,
2217 mozilla::TableSelectionMode* aTarget);
2220 * @return see nsISelectionController.idl's `getDisplaySelection`.
2222 int16_t DetermineDisplaySelection();
2224 public:
2225 virtual nsresult GetContentForEvent(const mozilla::WidgetEvent* aEvent,
2226 nsIContent** aContent);
2228 // This structure keeps track of the content node and offsets associated with
2229 // a point; there is a primary and a secondary offset associated with any
2230 // point. The primary and secondary offsets differ when the point is over a
2231 // non-text object. The primary offset is the expected position of the
2232 // cursor calculated from a point; the secondary offset, when it is different,
2233 // indicates that the point is in the boundaries of some selectable object.
2234 // Note that the primary offset can be after the secondary offset; for places
2235 // that need the beginning and end of the object, the StartOffset and
2236 // EndOffset helpers can be used.
2237 struct MOZ_STACK_CLASS ContentOffsets {
2238 ContentOffsets()
2239 : offset(0),
2240 secondaryOffset(0),
2241 associate(mozilla::CARET_ASSOCIATE_BEFORE) {}
2242 bool IsNull() { return !content; }
2243 // Helpers for places that need the ends of the offsets and expect them in
2244 // numerical order, as opposed to wanting the primary and secondary offsets
2245 int32_t StartOffset() { return std::min(offset, secondaryOffset); }
2246 int32_t EndOffset() { return std::max(offset, secondaryOffset); }
2248 nsCOMPtr<nsIContent> content;
2249 int32_t offset;
2250 int32_t secondaryOffset;
2251 // This value indicates whether the associated content is before or after
2252 // the offset; the most visible use is to allow the caret to know which line
2253 // to display on.
2254 mozilla::CaretAssociationHint associate;
2256 enum {
2257 IGNORE_SELECTION_STYLE = 0x01,
2258 // Treat visibility:hidden frames as non-selectable
2259 SKIP_HIDDEN = 0x02
2262 * This function calculates the content offsets for selection relative to
2263 * a point. Note that this should generally only be callled on the event
2264 * frame associated with an event because this function does not account
2265 * for frame lists other than the primary one.
2266 * @param aPoint point relative to this frame
2268 ContentOffsets GetContentOffsetsFromPoint(const nsPoint& aPoint,
2269 uint32_t aFlags = 0);
2271 virtual ContentOffsets GetContentOffsetsFromPointExternal(
2272 const nsPoint& aPoint, uint32_t aFlags = 0) {
2273 return GetContentOffsetsFromPoint(aPoint, aFlags);
2276 // Helper for GetContentAndOffsetsFromPoint; calculation of content offsets
2277 // in this function assumes there is no child frame that can be targeted.
2278 virtual ContentOffsets CalcContentOffsetsFromFramePoint(
2279 const nsPoint& aPoint);
2282 * Ensure that `this` gets notifed when `aImage`s underlying image request
2283 * loads or animates.
2285 * This in practice is only needed for the canvas frame and table cell
2286 * backgrounds, which are the only cases that should paint a background that
2287 * isn't its own. The canvas paints the background from the root element or
2288 * body, and the table cell paints the background for its row.
2290 * For regular frames, this is done in DidSetComputedStyle.
2292 * NOTE: It's unclear if we even actually _need_ this for the second case, as
2293 * invalidating the row should invalidate all the cells. For the canvas case
2294 * this is definitely needed as it paints the background from somewhere "down"
2295 * in the frame tree.
2297 * Returns whether the image was in fact associated with the frame.
2299 [[nodiscard]] bool AssociateImage(const mozilla::StyleImage&);
2302 * This needs to be called if the above caller returned true, once the above
2303 * caller doesn't care about getting notified anymore.
2305 void DisassociateImage(const mozilla::StyleImage&);
2307 mozilla::StyleImageRendering UsedImageRendering() const;
2308 mozilla::StyleTouchAction UsedTouchAction() const;
2310 enum class AllowCustomCursorImage {
2312 Yes,
2316 * This structure holds information about a cursor. AllowCustomCursorImage
2317 * is `No`, then no cursor image should be loaded from the style specified on
2318 * `mStyle`, or the frame's style.
2320 * The `mStyle` member is used for `<area>` elements.
2322 struct MOZ_STACK_CLASS Cursor {
2323 mozilla::StyleCursorKind mCursor = mozilla::StyleCursorKind::Auto;
2324 AllowCustomCursorImage mAllowCustomCursor = AllowCustomCursorImage::Yes;
2325 RefPtr<mozilla::ComputedStyle> mStyle;
2329 * Get the cursor for a given frame.
2331 virtual Maybe<Cursor> GetCursor(const nsPoint&);
2334 * Get a point (in the frame's coordinate space) given an offset into
2335 * the content. This point should be on the baseline of text with
2336 * the correct horizontal offset
2338 virtual nsresult GetPointFromOffset(int32_t inOffset, nsPoint* outPoint);
2341 * Get a list of character rects in a given range.
2342 * This is similar version of GetPointFromOffset.
2344 virtual nsresult GetCharacterRectsInRange(int32_t aInOffset, int32_t aLength,
2345 nsTArray<nsRect>& aRects);
2348 * Get the child frame of this frame which contains the given
2349 * content offset. outChildFrame may be this frame, or nullptr on return.
2350 * outContentOffset returns the content offset relative to the start
2351 * of the returned node. You can also pass a hint which tells the method
2352 * to stick to the end of the first found frame or the beginning of the
2353 * next in case the offset falls on a boundary.
2355 virtual nsresult GetChildFrameContainingOffset(
2356 int32_t inContentOffset,
2357 bool inHint, // false stick left
2358 int32_t* outFrameContentOffset, nsIFrame** outChildFrame);
2361 * Get the current frame-state value for this frame. aResult is
2362 * filled in with the state bits.
2364 nsFrameState GetStateBits() const { return mState; }
2367 * Update the current frame-state value for this frame.
2369 void AddStateBits(nsFrameState aBits) { mState |= aBits; }
2370 void RemoveStateBits(nsFrameState aBits) { mState &= ~aBits; }
2371 void AddOrRemoveStateBits(nsFrameState aBits, bool aVal) {
2372 aVal ? AddStateBits(aBits) : RemoveStateBits(aBits);
2376 * Checks if the current frame-state includes all of the listed bits
2378 bool HasAllStateBits(nsFrameState aBits) const {
2379 return (mState & aBits) == aBits;
2383 * Checks if the current frame-state includes any of the listed bits
2385 bool HasAnyStateBits(nsFrameState aBits) const { return mState & aBits; }
2387 private:
2389 * Called when this frame becomes primary for mContent.
2391 void InitPrimaryFrame();
2393 public:
2395 * Return true if this frame is the primary frame for mContent.
2397 bool IsPrimaryFrame() const { return mIsPrimaryFrame; }
2399 void SetIsPrimaryFrame(bool aIsPrimary) {
2400 mIsPrimaryFrame = aIsPrimary;
2401 if (aIsPrimary) {
2402 InitPrimaryFrame();
2406 bool IsPrimaryFrameOfRootOrBodyElement() const;
2409 * @return true if this frame is used as a fieldset's rendered legend.
2411 bool IsRenderedLegend() const;
2414 * This call is invoked on the primary frame for a character data content
2415 * node, when it is changed in the content tree.
2417 virtual nsresult CharacterDataChanged(const CharacterDataChangeInfo&);
2420 * This call is invoked when the value of a content objects's attribute
2421 * is changed.
2422 * The first frame that maps that content is asked to deal
2423 * with the change by doing whatever is appropriate.
2425 * @param aNameSpaceID the namespace of the attribute
2426 * @param aAttribute the atom name of the attribute
2427 * @param aModType Whether or not the attribute was added, changed, or
2428 * removed. The constants are defined in MutationEvent.webidl.
2430 virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute,
2431 int32_t aModType);
2434 * When the element states of mContent change, this method is invoked on the
2435 * primary frame of that element.
2437 * @param aStates the changed states
2439 virtual void ElementStateChanged(mozilla::dom::ElementState aStates);
2442 * Continuation member functions
2444 virtual nsIFrame* GetPrevContinuation() const;
2445 virtual void SetPrevContinuation(nsIFrame*);
2446 virtual nsIFrame* GetNextContinuation() const;
2447 virtual void SetNextContinuation(nsIFrame*);
2448 virtual nsIFrame* FirstContinuation() const {
2449 return const_cast<nsIFrame*>(this);
2451 virtual nsIFrame* LastContinuation() const {
2452 return const_cast<nsIFrame*>(this);
2456 * GetTailContinuation gets the last non-overflow-container continuation
2457 * in the continuation chain, i.e. where the next sibling element
2458 * should attach).
2460 nsIFrame* GetTailContinuation();
2463 * Flow member functions
2465 virtual nsIFrame* GetPrevInFlow() const;
2466 virtual void SetPrevInFlow(nsIFrame*);
2468 virtual nsIFrame* GetNextInFlow() const;
2469 virtual void SetNextInFlow(nsIFrame*);
2472 * Return the first frame in our current flow.
2474 virtual nsIFrame* FirstInFlow() const { return const_cast<nsIFrame*>(this); }
2477 * Return the last frame in our current flow.
2479 virtual nsIFrame* LastInFlow() const { return const_cast<nsIFrame*>(this); }
2482 * Note: "width" in the names and comments on the following methods
2483 * means inline-size, which could be height in vertical layout
2487 * Mark any stored intrinsic width information as dirty (requiring
2488 * re-calculation). Note that this should generally not be called
2489 * directly; PresShell::FrameNeedsReflow() will call it instead.
2491 virtual void MarkIntrinsicISizesDirty();
2493 public:
2495 * Make this frame and all descendants dirty (if not already).
2496 * Exceptions: TableColGroupFrame children.
2498 void MarkSubtreeDirty();
2501 * Get the min-content intrinsic inline size of the frame. This must be
2502 * less than or equal to the max-content intrinsic inline size.
2504 * This is *not* affected by the CSS 'min-width', 'width', and
2505 * 'max-width' properties on this frame, but it is affected by the
2506 * values of those properties on this frame's descendants. (It may be
2507 * called during computation of the values of those properties, so it
2508 * cannot depend on any values in the nsStylePosition for this frame.)
2510 * The value returned should **NOT** include the space required for
2511 * padding and border.
2513 * Note that many frames will cache the result of this function call
2514 * unless MarkIntrinsicISizesDirty is called.
2516 * It is not acceptable for a frame to mark itself dirty when this
2517 * method is called.
2519 * This method must not return a negative value.
2521 virtual nscoord GetMinISize(gfxContext* aRenderingContext);
2524 * Get the max-content intrinsic inline size of the frame. This must be
2525 * greater than or equal to the min-content intrinsic inline size.
2527 * Otherwise, all the comments for |GetMinISize| above apply.
2529 virtual nscoord GetPrefISize(gfxContext* aRenderingContext);
2532 * |InlineIntrinsicISize| represents the intrinsic width information
2533 * in inline layout. Code that determines the intrinsic width of a
2534 * region of inline layout accumulates the result into this structure.
2535 * This pattern is needed because we need to maintain state
2536 * information about whitespace (for both collapsing and trimming).
2538 struct InlineIntrinsicISizeData {
2539 InlineIntrinsicISizeData()
2540 : mLine(nullptr),
2541 mLineContainer(nullptr),
2542 mPrevLines(0),
2543 mCurrentLine(0),
2544 mTrailingWhitespace(0),
2545 mSkipWhitespace(true) {}
2547 // The line. This may be null if the inlines are not associated with
2548 // a block or if we just don't know the line.
2549 const nsLineList_iterator* mLine;
2551 // The line container. Private, to ensure we always use SetLineContainer
2552 // to update it.
2554 // Note that nsContainerFrame::DoInlineIntrinsicISize will clear the
2555 // |mLine| and |mLineContainer| fields when following a next-in-flow link,
2556 // so we must not assume these can always be dereferenced.
2557 private:
2558 nsIFrame* mLineContainer;
2560 // Setter and getter for the lineContainer field:
2561 public:
2562 void SetLineContainer(nsIFrame* aLineContainer) {
2563 mLineContainer = aLineContainer;
2565 nsIFrame* LineContainer() const { return mLineContainer; }
2567 // The maximum intrinsic width for all previous lines.
2568 nscoord mPrevLines;
2570 // The maximum intrinsic width for the current line. At a line
2571 // break (mandatory for preferred width; allowed for minimum width),
2572 // the caller should call |Break()|.
2573 nscoord mCurrentLine;
2575 // This contains the width of the trimmable whitespace at the end of
2576 // |mCurrentLine|; it is zero if there is no such whitespace.
2577 nscoord mTrailingWhitespace;
2579 // True if initial collapsable whitespace should be skipped. This
2580 // should be true at the beginning of a block, after hard breaks
2581 // and when the last text ended with whitespace.
2582 bool mSkipWhitespace;
2584 // Floats encountered in the lines.
2585 class FloatInfo {
2586 public:
2587 FloatInfo(const nsIFrame* aFrame, nscoord aWidth)
2588 : mFrame(aFrame), mWidth(aWidth) {}
2589 const nsIFrame* Frame() const { return mFrame; }
2590 nscoord Width() const { return mWidth; }
2592 private:
2593 const nsIFrame* mFrame;
2594 nscoord mWidth;
2597 nsTArray<FloatInfo> mFloats;
2600 struct InlineMinISizeData : public InlineIntrinsicISizeData {
2601 InlineMinISizeData() : mAtStartOfLine(true) {}
2603 // The default implementation for nsIFrame::AddInlineMinISize.
2604 void DefaultAddInlineMinISize(nsIFrame* aFrame, nscoord aISize,
2605 bool aAllowBreak = true);
2607 // We need to distinguish forced and optional breaks for cases where the
2608 // current line total is negative. When it is, we need to ignore
2609 // optional breaks to prevent min-width from ending up bigger than
2610 // pref-width.
2611 void ForceBreak();
2613 // If the break here is actually taken, aHyphenWidth must be added to the
2614 // width of the current line.
2615 void OptionallyBreak(nscoord aHyphenWidth = 0);
2617 // Whether we're currently at the start of the line. If we are, we
2618 // can't break (for example, between the text-indent and the first
2619 // word).
2620 bool mAtStartOfLine;
2623 struct InlinePrefISizeData : public InlineIntrinsicISizeData {
2624 InlinePrefISizeData() : mLineIsEmpty(true) {}
2627 * Finish the current line and start a new line.
2629 * @param aClearType controls whether isize of floats are considered
2630 * and what floats are kept for the next line:
2631 * * |None| skips handling floats, which means no floats are
2632 * removed, and isizes of floats are not considered either.
2633 * * |Both| takes floats into consideration when computing isize
2634 * of the current line, and removes all floats after that.
2635 * * |Left| and |Right| do the same as |Both| except that they only
2636 * remove floats on the given side, and any floats on the other
2637 * side that are prior to a float on the given side that has a
2638 * 'clear' property that clears them.
2640 void ForceBreak(mozilla::StyleClear aClearType = mozilla::StyleClear::Both);
2642 // The default implementation for nsIFrame::AddInlinePrefISize.
2643 void DefaultAddInlinePrefISize(nscoord aISize);
2645 // True if the current line contains nothing other than placeholders.
2646 bool mLineIsEmpty;
2650 * Add the intrinsic minimum width of a frame in a way suitable for
2651 * use in inline layout to an |InlineIntrinsicISizeData| object that
2652 * represents the intrinsic width information of all the previous
2653 * frames in the inline layout region.
2655 * All *allowed* breakpoints within the frame determine what counts as
2656 * a line for the |InlineIntrinsicISizeData|. This means that
2657 * |aData->mTrailingWhitespace| will always be zero (unlike for
2658 * AddInlinePrefISize).
2660 * All the comments for |GetMinISize| apply, except that this function
2661 * is responsible for adding padding, border, and margin and for
2662 * considering the effects of 'width', 'min-width', and 'max-width'.
2664 * This may be called on any frame. Frames that do not participate in
2665 * line breaking can inherit the default implementation on nsFrame,
2666 * which calls |GetMinISize|.
2668 virtual void AddInlineMinISize(gfxContext* aRenderingContext,
2669 InlineMinISizeData* aData);
2672 * Add the intrinsic preferred width of a frame in a way suitable for
2673 * use in inline layout to an |InlineIntrinsicISizeData| object that
2674 * represents the intrinsic width information of all the previous
2675 * frames in the inline layout region.
2677 * All the comments for |AddInlineMinISize| and |GetPrefISize| apply,
2678 * except that this fills in an |InlineIntrinsicISizeData| structure
2679 * based on using all *mandatory* breakpoints within the frame.
2681 virtual void AddInlinePrefISize(gfxContext* aRenderingContext,
2682 InlinePrefISizeData* aData);
2685 * Intrinsic size of a frame in a single axis.
2687 * This can represent either isize or bsize.
2689 struct IntrinsicSizeOffsetData {
2690 nscoord padding = 0;
2691 nscoord border = 0;
2692 nscoord margin = 0;
2693 nscoord BorderPadding() const { return border + padding; };
2697 * Return the isize components of padding, border, and margin
2698 * that contribute to the intrinsic width that applies to the parent.
2699 * @param aPercentageBasis the percentage basis to use for padding/margin -
2700 * i.e. the Containing Block's inline-size
2702 virtual IntrinsicSizeOffsetData IntrinsicISizeOffsets(
2703 nscoord aPercentageBasis = NS_UNCONSTRAINEDSIZE);
2706 * Return the bsize components of padding, border, and margin
2707 * that contribute to the intrinsic width that applies to the parent.
2708 * @param aPercentageBasis the percentage basis to use for padding/margin -
2709 * i.e. the Containing Block's inline-size
2711 IntrinsicSizeOffsetData IntrinsicBSizeOffsets(
2712 nscoord aPercentageBasis = NS_UNCONSTRAINEDSIZE);
2714 virtual mozilla::IntrinsicSize GetIntrinsicSize();
2717 * Get the preferred aspect ratio of this frame, or a default-constructed
2718 * AspectRatio if it has none.
2720 * https://drafts.csswg.org/css-sizing-4/#preferred-aspect-ratio
2722 mozilla::AspectRatio GetAspectRatio() const;
2725 * Get the intrinsic aspect ratio of this frame, or a default-constructed
2726 * AspectRatio if it has no intrinsic ratio.
2728 * The intrinsic ratio is the ratio of the width/height of a box with an
2729 * intrinsic size or the intrinsic aspect ratio of a scalable vector image
2730 * without an intrinsic size. A frame class implementing a replaced element
2731 * should override this method if it has a intrinsic ratio.
2733 virtual mozilla::AspectRatio GetIntrinsicRatio() const;
2736 * Compute the size that a frame will occupy. Called while
2737 * constructing the ReflowInput to be used to Reflow the frame,
2738 * in order to fill its mComputedWidth and mComputedHeight member
2739 * variables.
2741 * Note that the reason that border and padding need to be passed
2742 * separately is so that the 'box-sizing' property can be handled.
2743 * Thus aMargin includes absolute positioning offsets as well.
2745 * @param aWM The writing mode to use for the returned size (need not match
2746 * this frame's writing mode). This is also the writing mode of
2747 * the passed-in LogicalSize parameters.
2748 * @param aCBSize The size of the element's containing block. (Well,
2749 * the BSize() component isn't really.)
2750 * @param aAvailableISize The available inline-size for 'auto' inline-size.
2751 * This is usually the same as aCBSize.ISize(),
2752 * but differs in cases such as block
2753 * formatting context roots next to floats, or
2754 * in some cases of float reflow in quirks
2755 * mode.
2756 * @param aMargin The sum of the inline / block margins ***AND***
2757 * absolute positioning offsets (inset-block and
2758 * inset-inline) of the frame, including actual values
2759 * resulting from percentages and from the
2760 * "hypothetical box" for absolute positioning, but
2761 * not including actual values resulting from 'auto'
2762 * margins or ignored 'auto' values in absolute
2763 * positioning.
2764 * @param aBorderPadding The sum of the frame's inline / block border-widths
2765 * and padding (including actual values resulting from
2766 * percentage padding values).
2767 * @param aSizeOverride Optional override values for size properties, which
2768 * this function will use internally instead of the
2769 * actual property values.
2770 * @param aFlags Flags to further customize behavior (definitions in
2771 * LayoutConstants.h).
2773 * The return value includes the computed LogicalSize and AspectRatioUsage
2774 * which indicates whether the inline/block size is affected by aspect-ratio
2775 * or not. The BSize() of the returned LogicalSize may be
2776 * NS_UNCONSTRAINEDSIZE, but the ISize() must not be. We need AspectRatioUsage
2777 * during reflow because the final size may be affected by the content size
2778 * after applying aspect-ratio.
2779 * https://drafts.csswg.org/css-sizing-4/#aspect-ratio-minimum
2782 enum class AspectRatioUsage : uint8_t {
2783 None,
2784 ToComputeISize,
2785 ToComputeBSize,
2787 struct SizeComputationResult {
2788 mozilla::LogicalSize mLogicalSize;
2789 AspectRatioUsage mAspectRatioUsage = AspectRatioUsage::None;
2791 virtual SizeComputationResult ComputeSize(
2792 gfxContext* aRenderingContext, mozilla::WritingMode aWM,
2793 const mozilla::LogicalSize& aCBSize, nscoord aAvailableISize,
2794 const mozilla::LogicalSize& aMargin,
2795 const mozilla::LogicalSize& aBorderPadding,
2796 const mozilla::StyleSizeOverrides& aSizeOverrides,
2797 mozilla::ComputeSizeFlags aFlags);
2799 protected:
2801 * A helper, used by |nsIFrame::ComputeSize| (for frames that need to
2802 * override only this part of ComputeSize), that computes the size
2803 * that should be returned when inline-size, block-size, and
2804 * [min|max]-[inline-size|block-size] are all 'auto' or equivalent.
2806 * In general, frames that can accept any computed inline-size/block-size
2807 * should override only ComputeAutoSize, and frames that cannot do so need to
2808 * override ComputeSize to enforce their inline-size/block-size invariants.
2810 * Implementations may optimize by returning a garbage inline-size if
2811 * StylePosition()->ISize() is not 'auto' (or inline-size override in
2812 * aSizeOverrides is not 'auto' if provided), and likewise for BSize(), since
2813 * in such cases the result is guaranteed to be unused.
2815 * Most of the frame are not expected to check the aSizeOverrides parameter
2816 * apart from checking the inline size override for 'auto' if they want to
2817 * optimize and return garbage inline-size.
2819 virtual mozilla::LogicalSize ComputeAutoSize(
2820 gfxContext* aRenderingContext, mozilla::WritingMode aWM,
2821 const mozilla::LogicalSize& aCBSize, nscoord aAvailableISize,
2822 const mozilla::LogicalSize& aMargin,
2823 const mozilla::LogicalSize& aBorderPadding,
2824 const mozilla::StyleSizeOverrides& aSizeOverrides,
2825 mozilla::ComputeSizeFlags aFlags);
2828 * Utility function for ComputeAutoSize implementations. Return
2829 * max(GetMinISize(), min(aISizeInCB, GetPrefISize()))
2831 nscoord ShrinkISizeToFit(gfxContext* aRenderingContext, nscoord aISizeInCB,
2832 mozilla::ComputeSizeFlags aFlags);
2834 public:
2836 * Compute a tight bounding rectangle for the frame. This is a rectangle
2837 * that encloses the pixels that are actually drawn. We're allowed to be
2838 * conservative and currently we don't try very hard. The rectangle is
2839 * in appunits and relative to the origin of this frame.
2841 * This probably only needs to include frame bounds, glyph bounds, and
2842 * text decorations, but today it sometimes includes other things that
2843 * contribute to ink overflow.
2845 * @param aDrawTarget a draw target that can be used if we need
2846 * to do measurement
2848 virtual nsRect ComputeTightBounds(DrawTarget* aDrawTarget) const;
2851 * This function is similar to GetPrefISize and ComputeTightBounds: it
2852 * computes the left and right coordinates of a preferred tight bounding
2853 * rectangle for the frame. This is a rectangle that would enclose the pixels
2854 * that are drawn if we lay out the element without taking any optional line
2855 * breaks. The rectangle is in appunits and relative to the origin of this
2856 * frame. Currently, this function is only implemented for nsBlockFrame and
2857 * nsTextFrame and is used to determine intrinsic widths of MathML token
2858 * elements.
2860 * @param aContext a rendering context that can be used if we need
2861 * to do measurement
2862 * @param aX computed left coordinate of the tight bounding rectangle
2863 * @param aXMost computed intrinsic width of the tight bounding rectangle
2866 virtual nsresult GetPrefWidthTightBounds(gfxContext* aContext, nscoord* aX,
2867 nscoord* aXMost);
2870 * The frame is given an available size and asked for its desired
2871 * size. This is the frame's opportunity to reflow its children.
2873 * If the frame has the NS_FRAME_IS_DIRTY bit set then it is
2874 * responsible for completely reflowing itself and all of its
2875 * descendants.
2877 * Otherwise, if the frame has the NS_FRAME_HAS_DIRTY_CHILDREN bit
2878 * set, then it is responsible for reflowing at least those
2879 * children that have NS_FRAME_HAS_DIRTY_CHILDREN or NS_FRAME_IS_DIRTY
2880 * set.
2882 * If a difference in available size from the previous reflow causes
2883 * the frame's size to change, it should reflow descendants as needed.
2885 * Calculates the size of this frame after reflowing (calling Reflow on, and
2886 * updating the size and position of) its children, as necessary. The
2887 * calculated size is returned to the caller via the ReflowOutput
2888 * outparam. (The caller is responsible for setting the actual size and
2889 * position of this frame.)
2891 * A frame's children must _all_ be reflowed if the frame is dirty (the
2892 * NS_FRAME_IS_DIRTY bit is set on it). Otherwise, individual children
2893 * must be reflowed if they are dirty or have the NS_FRAME_HAS_DIRTY_CHILDREN
2894 * bit set on them. Otherwise, whether children need to be reflowed depends
2895 * on the frame's type (it's up to individual Reflow methods), and on what
2896 * has changed. For example, a change in the width of the frame may require
2897 * all of its children to be reflowed (even those without dirty bits set on
2898 * them), whereas a change in its height might not.
2899 * (ReflowInput::ShouldReflowAllKids may be helpful in deciding whether
2900 * to reflow all the children, but for some frame types it might result in
2901 * over-reflow.)
2903 * Note: if it's only the overflow rect(s) of a frame that need to be
2904 * updated, then UpdateOverflow should be called instead of Reflow.
2906 * @param aReflowOutput <i>out</i> parameter where you should return the
2907 * desired size and ascent/descent info. You should include any
2908 * space you want for border/padding in the desired size you return.
2910 * It's okay to return a desired size that exceeds the avail
2911 * size if that's the smallest you can be, i.e. it's your
2912 * minimum size.
2914 * For an incremental reflow you are responsible for invalidating
2915 * any area within your frame that needs repainting (including
2916 * borders). If your new desired size is different than your current
2917 * size, then your parent frame is responsible for making sure that
2918 * the difference between the two rects is repainted
2920 * @param aReflowInput information about your reflow including the reason
2921 * for the reflow and the available space in which to lay out. Each
2922 * dimension of the available space can either be constrained or
2923 * unconstrained (a value of NS_UNCONSTRAINEDSIZE).
2925 * Note that the available space can be negative. In this case you
2926 * still must return an accurate desired size. If you're a container
2927 * you must <b>always</b> reflow at least one frame regardless of the
2928 * available space
2930 * @param aStatus a return value indicating whether the frame is complete
2931 * and whether the next-in-flow is dirty and needs to be reflowed
2933 virtual void Reflow(nsPresContext* aPresContext, ReflowOutput& aReflowOutput,
2934 const ReflowInput& aReflowInput, nsReflowStatus& aStatus);
2936 // Option flags for ReflowChild(), FinishReflowChild(), and
2937 // SyncFrameViewAfterReflow().
2938 enum class ReflowChildFlags : uint32_t {
2939 Default = 0,
2941 // Don't position the frame's view. Set this if you don't want to
2942 // automatically sync the frame and view.
2943 NoMoveView = 1 << 0,
2945 // Don't move the frame. Also implies NoMoveView.
2946 NoMoveFrame = (1 << 1) | NoMoveView,
2948 // Don't size the frame's view.
2949 NoSizeView = 1 << 2,
2951 // Only applies to ReflowChild; if true, don't delete the next-in-flow, even
2952 // if the reflow is fully complete.
2953 NoDeleteNextInFlowChild = 1 << 3,
2955 // Only applies to FinishReflowChild. Tell it to call
2956 // ApplyRelativePositioning.
2957 ApplyRelativePositioning = 1 << 4,
2961 * Post-reflow hook. After a frame is reflowed this method will be called
2962 * informing the frame that this reflow process is complete, and telling the
2963 * frame the status returned by the Reflow member function.
2965 * This call may be invoked many times, while NS_FRAME_IN_REFLOW is set,
2966 * before it is finally called once with a NS_FRAME_REFLOW_COMPLETE value.
2967 * When called with a NS_FRAME_REFLOW_COMPLETE value the NS_FRAME_IN_REFLOW
2968 * bit in the frame state will be cleared.
2970 * XXX This doesn't make sense. If the frame is reflowed but not complete,
2971 * then the status should have IsIncomplete() equal to true.
2972 * XXX Don't we want the semantics to dictate that we only call this once for
2973 * a given reflow?
2975 virtual void DidReflow(nsPresContext* aPresContext,
2976 const ReflowInput* aReflowInput);
2978 void FinishReflowWithAbsoluteFrames(nsPresContext* aPresContext,
2979 ReflowOutput& aDesiredSize,
2980 const ReflowInput& aReflowInput,
2981 nsReflowStatus& aStatus,
2982 bool aConstrainBSize = true);
2985 * Updates the overflow areas of the frame. This can be called if an
2986 * overflow area of the frame's children has changed without reflowing.
2987 * @return true if either of the overflow areas for this frame have changed.
2989 bool UpdateOverflow();
2992 * Computes any overflow area created by the frame itself (outside of the
2993 * frame bounds) and includes it into aOverflowAreas.
2995 * Returns false if updating overflow isn't supported for this frame.
2996 * If the frame requires a reflow instead, then it is responsible
2997 * for scheduling one.
2999 virtual bool ComputeCustomOverflow(mozilla::OverflowAreas& aOverflowAreas);
3002 * Computes any overflow area created by children of this frame and
3003 * includes it into aOverflowAreas.
3005 virtual void UnionChildOverflow(mozilla::OverflowAreas& aOverflowAreas);
3007 // Returns the applicable overflow-clip-margin values.
3008 using PhysicalAxes = mozilla::PhysicalAxes;
3010 nsSize OverflowClipMargin(PhysicalAxes aClipAxes) const;
3011 // Returns the axes on which this frame should apply overflow clipping.
3012 PhysicalAxes ShouldApplyOverflowClipping(const nsStyleDisplay* aDisp) const;
3015 * Helper method used by block reflow to identify runs of text so
3016 * that proper word-breaking can be done.
3018 * @return
3019 * true if we can continue a "text run" through the frame. A
3020 * text run is text that should be treated contiguously for line
3021 * and word breaking.
3023 virtual bool CanContinueTextRun() const;
3026 * Computes an approximation of the rendered text of the frame and its
3027 * continuations. Returns nothing for non-text frames.
3028 * The appended text will often not contain all the whitespace from source,
3029 * depending on CSS white-space processing.
3030 * if aEndOffset goes past end, use the text up to the string's end.
3031 * Call this on the primary frame for a text node.
3032 * aStartOffset and aEndOffset can be content offsets or offsets in the
3033 * rendered text, depending on aOffsetType.
3034 * Returns a string, as well as offsets identifying the start of the text
3035 * within the rendered text for the whole node, and within the text content
3036 * of the node.
3038 struct RenderedText {
3039 nsAutoString mString;
3040 uint32_t mOffsetWithinNodeRenderedText;
3041 int32_t mOffsetWithinNodeText;
3042 RenderedText()
3043 : mOffsetWithinNodeRenderedText(0), mOffsetWithinNodeText(0) {}
3045 enum class TextOffsetType {
3046 // Passed-in start and end offsets are within the content text.
3047 OffsetsInContentText,
3048 // Passed-in start and end offsets are within the rendered text.
3049 OffsetsInRenderedText,
3051 enum class TrailingWhitespace {
3052 Trim,
3053 // Spaces preceding a caret at the end of a line should not be trimmed
3054 DontTrim,
3056 virtual RenderedText GetRenderedText(
3057 uint32_t aStartOffset = 0, uint32_t aEndOffset = UINT32_MAX,
3058 TextOffsetType aOffsetType = TextOffsetType::OffsetsInContentText,
3059 TrailingWhitespace aTrimTrailingWhitespace = TrailingWhitespace::Trim) {
3060 return RenderedText();
3064 * Returns true if the frame contains any non-collapsed characters.
3065 * This method is only available for text frames, and it will return false
3066 * for all other frame types.
3068 virtual bool HasAnyNoncollapsedCharacters() { return false; }
3071 * Returns true if events of the given type targeted at this frame
3072 * should only be dispatched to the system group.
3074 virtual bool OnlySystemGroupDispatch(mozilla::EventMessage aMessage) const {
3075 return false;
3079 // Accessor functions to an associated view object:
3081 bool HasView() const { return !!(mState & NS_FRAME_HAS_VIEW); }
3083 // Returns true iff this frame's computed block-size property is one of the
3084 // intrinsic-sizing keywords.
3085 bool HasIntrinsicKeywordForBSize() const {
3086 const auto& bSize = StylePosition()->BSize(GetWritingMode());
3087 return bSize.IsFitContent() || bSize.IsMinContent() ||
3088 bSize.IsMaxContent() || bSize.IsFitContentFunction();
3091 * Helper method to create a view for a frame. Only used by a few sub-classes
3092 * that need a view.
3094 void CreateView();
3096 protected:
3097 virtual nsView* GetViewInternal() const {
3098 MOZ_ASSERT_UNREACHABLE("method should have been overridden by subclass");
3099 return nullptr;
3101 virtual void SetViewInternal(nsView* aView) {
3102 MOZ_ASSERT_UNREACHABLE("method should have been overridden by subclass");
3105 public:
3106 nsView* GetView() const {
3107 if (MOZ_LIKELY(!HasView())) {
3108 return nullptr;
3110 nsView* view = GetViewInternal();
3111 MOZ_ASSERT(view, "GetViewInternal() should agree with HasView()");
3112 return view;
3114 void SetView(nsView* aView);
3117 * Find the closest view (on |this| or an ancestor).
3118 * If aOffset is non-null, it will be set to the offset of |this|
3119 * from the returned view.
3121 nsView* GetClosestView(nsPoint* aOffset = nullptr) const;
3124 * Find the closest ancestor (excluding |this| !) that has a view
3126 nsIFrame* GetAncestorWithView() const;
3129 * Sets the view's attributes from the frame style.
3130 * Call this for nsChangeHint_SyncFrameView style changes or when the view
3131 * has just been created.
3132 * @param aView the frame's view or use GetView() if nullptr is given
3134 void SyncFrameViewProperties(nsView* aView = nullptr);
3137 * Get the offset between the coordinate systems of |this| and aOther.
3138 * Adding the return value to a point in the coordinate system of |this|
3139 * will transform the point to the coordinate system of aOther.
3141 * aOther must be non-null.
3143 * This function is fastest when aOther is an ancestor of |this|.
3145 * This function _DOES NOT_ work across document boundaries.
3146 * Use this function only when |this| and aOther are in the same document.
3148 * NOTE: this actually returns the offset from aOther to |this|, but
3149 * that offset is added to transform _coordinates_ from |this| to
3150 * aOther.
3152 nsPoint GetOffsetTo(const nsIFrame* aOther) const;
3155 * Just like GetOffsetTo, but treats all scrollframes as scrolled to
3156 * their origin.
3158 nsPoint GetOffsetToIgnoringScrolling(const nsIFrame* aOther) const;
3161 * Get the offset between the coordinate systems of |this| and aOther
3162 * expressed in appunits per dev pixel of |this|' document. Adding the return
3163 * value to a point that is relative to the origin of |this| will make the
3164 * point relative to the origin of aOther but in the appunits per dev pixel
3165 * ratio of |this|.
3167 * aOther must be non-null.
3169 * This function is fastest when aOther is an ancestor of |this|.
3171 * This function works across document boundaries.
3173 * Because this function may cross document boundaries that have different
3174 * app units per dev pixel ratios it needs to be used very carefully.
3176 * NOTE: this actually returns the offset from aOther to |this|, but
3177 * that offset is added to transform _coordinates_ from |this| to
3178 * aOther.
3180 nsPoint GetOffsetToCrossDoc(const nsIFrame* aOther) const;
3183 * Like GetOffsetToCrossDoc, but the caller can specify which appunits
3184 * to return the result in.
3186 nsPoint GetOffsetToCrossDoc(const nsIFrame* aOther, const int32_t aAPD) const;
3189 * Get the rect of the frame relative to the top-left corner of the
3190 * screen in CSS pixels.
3191 * @return the CSS pixel rect of the frame relative to the top-left
3192 * corner of the screen.
3194 mozilla::CSSIntRect GetScreenRect() const;
3197 * Get the screen rect of the frame in app units.
3198 * @return the app unit rect of the frame in screen coordinates.
3200 nsRect GetScreenRectInAppUnits() const;
3203 * Returns the offset from this frame to the closest geometric parent that
3204 * has a view. Also returns the containing view or null in case of error
3206 void GetOffsetFromView(nsPoint& aOffset, nsView** aView) const;
3209 * Returns the nearest widget containing this frame. If this frame has a
3210 * view and the view has a widget, then this frame's widget is
3211 * returned, otherwise this frame's geometric parent is checked
3212 * recursively upwards.
3214 nsIWidget* GetNearestWidget() const;
3217 * Whether the frame is a subgrid right now.
3219 bool IsSubgrid() const;
3222 * Same as GetNearestWidget() above but uses an outparam to return the offset
3223 * of this frame to the returned widget expressed in appunits of |this| (the
3224 * widget might be in a different document with a different zoom).
3226 nsIWidget* GetNearestWidget(nsPoint& aOffset) const;
3229 * Whether the content for this frame is disabled, used for event handling.
3231 bool IsContentDisabled() const;
3233 enum class IncludeContentVisibility {
3234 Auto,
3235 Hidden,
3238 constexpr static mozilla::EnumSet<IncludeContentVisibility>
3239 IncludeAllContentVisibility() {
3240 return {IncludeContentVisibility::Auto, IncludeContentVisibility::Hidden};
3244 * Returns true if this frame's `content-visibility: auto` element is
3245 * considered relevant content.
3247 bool IsContentRelevant() const;
3250 * Whether this frame hides its contents via the `content-visibility`
3251 * property.
3252 * @param aInclude specifies what kind of `content-visibility` to include.
3254 bool HidesContent(const mozilla::EnumSet<IncludeContentVisibility>& =
3255 IncludeAllContentVisibility()) const;
3258 * Whether this frame hides its contents via the `content-visibility`
3259 * property, while doing layout. This might be true when `HidesContent()` is
3260 * true in the case that hidden content is being forced to lay out by position
3261 * or size queries from script.
3263 bool HidesContentForLayout() const;
3266 * returns the closest ancestor with `content-visibility` property.
3267 * @param aInclude specifies what kind of `content-visibility` to include.
3269 nsIFrame* GetClosestContentVisibilityAncestor(
3270 const mozilla::EnumSet<IncludeContentVisibility>& =
3271 IncludeAllContentVisibility()) const;
3274 * Returns true if this frame is entirely hidden due the `content-visibility`
3275 * property on an ancestor.
3276 * @param aInclude specifies what kind of `content-visibility` to include.
3278 bool IsHiddenByContentVisibilityOnAnyAncestor(
3279 const mozilla::EnumSet<IncludeContentVisibility>& =
3280 IncludeAllContentVisibility()) const;
3283 * Returns true is this frame is hidden by its first unskipped in flow
3284 * ancestor due to `content-visibility`.
3286 bool IsHiddenByContentVisibilityOfInFlowParentForLayout() const;
3289 * Whether or not this frame's content is a descendant of a top layer element
3290 * used to determine if this frame is relevant content for
3291 * `content-visibility: auto`.
3293 bool IsDescendantOfTopLayerElement() const;
3296 * Returns true if this frame has a SelectionType::eNormal type selection in
3297 * somewhere in its subtree of frames. This is used to determine content
3298 * relevancy for `content-visibility: auto`.
3300 bool HasSelectionInSubtree();
3303 * Update the whether or not this frame is considered relevant content for the
3304 * purposes of `content-visibility: auto` according to the rules specified in
3305 * https://drafts.csswg.org/css-contain-2/#relevant-to-the-user.
3306 * Returns true if the over-all relevancy changed.
3308 [[nodiscard]] bool UpdateIsRelevantContent(
3309 const ContentRelevancy& aRelevancyToUpdate);
3312 * Get the "type" of the frame.
3314 * @see mozilla::LayoutFrameType
3316 mozilla::LayoutFrameType Type() const {
3317 MOZ_ASSERT(uint8_t(mClass) < mozilla::ArrayLength(sLayoutFrameTypes));
3318 return sLayoutFrameTypes[uint8_t(mClass)];
3322 * Get the type flags of the frame.
3324 * @see mozilla::LayoutFrameType
3326 ClassFlags GetClassFlags() const {
3327 MOZ_ASSERT(uint8_t(mClass) < mozilla::ArrayLength(sLayoutFrameClassFlags));
3328 return sLayoutFrameClassFlags[uint8_t(mClass)];
3331 bool HasAnyClassFlag(ClassFlags aFlag) const {
3332 return bool(GetClassFlags() & aFlag);
3336 * Is this a leaf frame? Frames that want the frame constructor to be able to
3337 * construct kids for them should return false, all others should return true.
3339 * Note that returning true here does not mean that the frame _can't_ have
3340 * kids. It could still have kids created via nsIAnonymousContentCreator.
3342 * Returning true indicates that "normal" (non-anonymous, CSS generated
3343 * content, etc) children should not be constructed.
3345 bool IsLeaf() const {
3346 auto bits = GetClassFlags();
3347 if (MOZ_UNLIKELY(bits & ClassFlags::LeafDynamic)) {
3348 return IsLeafDynamic();
3350 return bool(bits & ClassFlags::Leaf);
3352 virtual bool IsLeafDynamic() const { return false; }
3354 #define CLASS_FLAG_METHOD(name_, flag_) \
3355 bool name_() const { return HasAnyClassFlag(ClassFlags::flag_); }
3356 #define CLASS_FLAG_METHOD0(name_) CLASS_FLAG_METHOD(name_, name_)
3358 CLASS_FLAG_METHOD(IsMathMLFrame, MathML);
3359 CLASS_FLAG_METHOD(IsSVGFrame, SVG);
3360 CLASS_FLAG_METHOD(IsSVGContainerFrame, SVGContainer);
3361 CLASS_FLAG_METHOD(IsBidiInlineContainer, BidiInlineContainer);
3362 CLASS_FLAG_METHOD(IsLineParticipant, LineParticipant);
3363 CLASS_FLAG_METHOD(IsReplaced, Replaced);
3364 CLASS_FLAG_METHOD(IsReplacedWithBlock, ReplacedContainsBlock);
3365 CLASS_FLAG_METHOD(HasReplacedSizing, ReplacedSizing);
3366 CLASS_FLAG_METHOD(IsTablePart, TablePart);
3367 CLASS_FLAG_METHOD0(CanContainOverflowContainers)
3368 CLASS_FLAG_METHOD0(SupportsCSSTransforms);
3369 CLASS_FLAG_METHOD0(SupportsContainLayoutAndPaint)
3370 CLASS_FLAG_METHOD0(SupportsAspectRatio)
3372 #undef CLASS_FLAG_METHOD
3373 #undef CLASS_FLAG_METHOD0
3375 #ifdef __GNUC__
3376 # pragma GCC diagnostic push
3377 # pragma GCC diagnostic ignored "-Wtype-limits"
3378 #endif
3379 #ifdef __clang__
3380 # pragma clang diagnostic push
3381 # pragma clang diagnostic ignored "-Wunknown-pragmas"
3382 # pragma clang diagnostic ignored "-Wtautological-unsigned-zero-compare"
3383 #endif
3385 #define FRAME_TYPE(name_, first_class_, last_class_) \
3386 bool Is##name_##Frame() const { \
3387 return uint8_t(mClass) >= uint8_t(ClassID::first_class_##_id) && \
3388 uint8_t(mClass) <= uint8_t(ClassID::last_class_##_id); \
3390 #include "mozilla/FrameTypeList.h"
3391 #undef FRAME_TYPE
3393 #ifdef __GNUC__
3394 # pragma GCC diagnostic pop
3395 #endif
3396 #ifdef __clang__
3397 # pragma clang diagnostic pop
3398 #endif
3401 * Returns a transformation matrix that converts points in this frame's
3402 * coordinate space to points in some ancestor frame's coordinate space.
3403 * The frame decides which ancestor it will use as a reference point.
3404 * If this frame has no ancestor, aOutAncestor will be set to null.
3406 * @param aViewportType specifies whether the starting point is layout
3407 * or visual coordinates
3408 * @param aStopAtAncestor don't look further than aStopAtAncestor. If null,
3409 * all ancestors (including across documents) will be traversed.
3410 * @param aOutAncestor [out] The ancestor frame the frame has chosen. If
3411 * this frame has no ancestor, *aOutAncestor will be set to null. If
3412 * this frame is not a root frame, then *aOutAncestor will be in the same
3413 * document as this frame. If this frame IsTransformed(), then *aOutAncestor
3414 * will be the parent frame (if not preserve-3d) or the nearest
3415 * non-transformed ancestor (if preserve-3d).
3416 * @return A Matrix4x4 that converts points in the coordinate space
3417 * RelativeTo{this, aViewportType} into points in aOutAncestor's
3418 * coordinate space.
3420 enum {
3421 IN_CSS_UNITS = 1 << 0,
3422 STOP_AT_STACKING_CONTEXT_AND_DISPLAY_PORT = 1 << 1
3424 Matrix4x4Flagged GetTransformMatrix(mozilla::ViewportType aViewportType,
3425 mozilla::RelativeTo aStopAtAncestor,
3426 nsIFrame** aOutAncestor,
3427 uint32_t aFlags = 0) const;
3430 * Return true if this frame's preferred size property or max size property
3431 * contains a percentage value that should be resolved against zero when
3432 * calculating its min-content contribution in the corresponding axis.
3434 * This is a special case for webcompat required by CSS Sizing 3 §5.2.1c
3435 * https://drafts.csswg.org/css-sizing-3/#replaced-percentage-min-contribution,
3436 * and applies only to some replaced elements and form control elements. See
3437 * CSS Sizing 3 §5.2.2 for the list of elements this rule applies to.
3438 * https://drafts.csswg.org/css-sizing-3/#min-content-zero
3440 * Bug 1463700: some callers may not match the spec by resolving the entire
3441 * preferred size property or max size property against zero.
3443 bool IsPercentageResolvedAgainstZero(
3444 const mozilla::StyleSize& aStyleSize,
3445 const mozilla::StyleMaxSize& aStyleMaxSize) const;
3447 // Type of preferred size/min size/max size.
3448 enum class SizeProperty { Size, MinSize, MaxSize };
3450 * This is simliar to the above method but accepts LengthPercentage. Return
3451 * true if the frame's preferred size property or max size property contains
3452 * a percentage value that should be resolved against zero. For min size, it
3453 * always returns true.
3455 bool IsPercentageResolvedAgainstZero(const mozilla::LengthPercentage& aSize,
3456 SizeProperty aProperty) const;
3459 * Returns true if the frame is a block wrapper.
3461 bool IsBlockWrapper() const;
3464 * Returns true if the frame is an instance of nsBlockFrame or one of its
3465 * subclasses.
3467 bool IsBlockFrameOrSubclass() const;
3470 * Returns true if the frame is an instance of nsImageFrame or one of its
3471 * subclasses.
3473 bool IsImageFrameOrSubclass() const;
3476 * Get this frame's CSS containing block.
3478 * The algorithm is defined in
3479 * http://www.w3.org/TR/CSS2/visudet.html#containing-block-details.
3481 * NOTE: This is guaranteed to return a non-null pointer when invoked on any
3482 * frame other than the root frame.
3484 * Requires SKIP_SCROLLED_FRAME to get behaviour matching the spec, otherwise
3485 * it can return anonymous inner scrolled frames. Bug 1204044 is filed for
3486 * investigating whether any of the callers actually require the default
3487 * behaviour.
3489 enum {
3490 // If the containing block is an anonymous scrolled frame, then skip over
3491 // this and return the outer scroll frame.
3492 SKIP_SCROLLED_FRAME = 0x01
3494 nsIFrame* GetContainingBlock(uint32_t aFlags,
3495 const nsStyleDisplay* aStyleDisplay) const;
3496 nsIFrame* GetContainingBlock(uint32_t aFlags = 0) const {
3497 return GetContainingBlock(aFlags, StyleDisplay());
3501 * If this frame can be a block container, i.e. whether it can serve as a
3502 * containing block for its descendants. See also GetNearestBlockContainer()
3503 * and GetContainingBlock().
3505 bool IsBlockContainer() const;
3508 * Is this frame a containing block for floating elements?
3509 * Note that very few frames are, so default to false.
3511 virtual bool IsFloatContainingBlock() const { return false; }
3514 * Marks all display items created by this frame as needing a repaint,
3515 * and calls SchedulePaint() if requested and one is not already pending.
3517 * This includes all display items created by this frame, including
3518 * container types.
3520 * @param aDisplayItemKey If specified, only issues an invalidate
3521 * if this frame painted a display item of that type during the
3522 * previous paint. SVG rendering observers are always notified.
3523 * @param aRebuildDisplayItems If true, then adds this frame to the
3524 * list of modified frames for display list building. Only pass false
3525 * if you're sure that the relevant display items will be rebuilt
3526 * already (possibly by an ancestor being in the modified list).
3528 virtual void InvalidateFrame(uint32_t aDisplayItemKey = 0,
3529 bool aRebuildDisplayItems = true);
3532 * Same as InvalidateFrame(), but only mark a fixed rect as needing
3533 * repainting.
3535 * @param aRect The rect to invalidate, relative to the TopLeft of the
3536 * frame's border box.
3537 * @param aDisplayItemKey If specified, only issues an invalidate
3538 * if this frame painted a display item of that type during the
3539 * previous paint. SVG rendering observers are always notified.
3540 * @param aRebuildDisplayItems If true, then adds this frame to the
3541 * list of modified frames for display list building. Only pass false
3542 * if you're sure that the relevant display items will be rebuilt
3543 * already (possibly by an ancestor being in the modified list).
3545 virtual void InvalidateFrameWithRect(const nsRect& aRect,
3546 uint32_t aDisplayItemKey = 0,
3547 bool aRebuildDisplayItems = true);
3550 * Calls InvalidateFrame() on all frames descendant frames (including
3551 * this one).
3553 * This function doesn't walk through placeholder frames to invalidate
3554 * the out-of-flow frames.
3556 * @param aRebuildDisplayItems If true, then adds this frame to the
3557 * list of modified frames for display list building. Only pass false
3558 * if you're sure that the relevant display items will be rebuilt
3559 * already (possibly by an ancestor being in the modified list).
3561 void InvalidateFrameSubtree(bool aRebuildDisplayItems = true);
3564 * Called when a frame is about to be removed and needs to be invalidated.
3565 * Normally does nothing since DLBI handles removed frames.
3567 virtual void InvalidateFrameForRemoval() {}
3570 * When HasUserData(frame->LayerIsPrerenderedDataKey()), then the
3571 * entire overflow area of this frame has been rendered in its
3572 * layer(s).
3574 static void* LayerIsPrerenderedDataKey() {
3575 return &sLayerIsPrerenderedDataKey;
3577 static uint8_t sLayerIsPrerenderedDataKey;
3580 * Checks if a frame has had InvalidateFrame() called on it since the
3581 * last paint.
3583 * If true, then the invalid rect is returned in aRect, with an
3584 * empty rect meaning all pixels drawn by this frame should be
3585 * invalidated.
3586 * If false, aRect is left unchanged.
3588 bool IsInvalid(nsRect& aRect);
3591 * Check if any frame within the frame subtree (including this frame)
3592 * returns true for IsInvalid().
3594 bool HasInvalidFrameInSubtree() {
3595 return HasAnyStateBits(NS_FRAME_NEEDS_PAINT |
3596 NS_FRAME_DESCENDANT_NEEDS_PAINT);
3600 * Removes the invalid state from the current frame and all
3601 * descendant frames.
3603 void ClearInvalidationStateBits();
3606 * Ensures that the refresh driver is running, and schedules a view
3607 * manager flush on the next tick.
3609 * The view manager flush will update the layer tree, repaint any
3610 * invalid areas in the layer tree and schedule a layer tree
3611 * composite operation to display the layer tree.
3613 * In general it is not necessary for frames to call this when they change.
3614 * For example, changes that result in a reflow will have this called for
3615 * them by PresContext::DoReflow when the reflow begins. Style changes that
3616 * do not trigger a reflow should have this called for them by
3617 * DoApplyRenderingChangeToTree.
3619 * @param aType PAINT_COMPOSITE_ONLY : No changes have been made
3620 * that require a layer tree update, so only schedule a layer
3621 * tree composite.
3623 enum PaintType { PAINT_DEFAULT = 0, PAINT_COMPOSITE_ONLY };
3624 void SchedulePaint(PaintType aType = PAINT_DEFAULT,
3625 bool aFrameChanged = true);
3627 // Similar to SchedulePaint() but without calling
3628 // InvalidateRenderingObservers() for SVG.
3629 void SchedulePaintWithoutInvalidatingObservers(
3630 PaintType aType = PAINT_DEFAULT);
3633 * Checks if the layer tree includes a dedicated layer for this
3634 * frame/display item key pair, and invalidates at least aDamageRect
3635 * area within that layer.
3637 * If no layer is found, calls InvalidateFrame() instead.
3639 * @param aDamageRect Area of the layer to invalidate.
3640 * @param aFrameDamageRect If no layer is found, the area of the frame to
3641 * invalidate. If null, the entire frame will be
3642 * invalidated.
3643 * @param aDisplayItemKey Display item type.
3644 * @param aFlags UPDATE_IS_ASYNC : Will skip the invalidation
3645 * if the found layer is being composited by a remote
3646 * compositor.
3647 * @return Layer, if found, nullptr otherwise.
3649 enum { UPDATE_IS_ASYNC = 1 << 0 };
3650 void InvalidateLayer(DisplayItemType aDisplayItemKey,
3651 const nsIntRect* aDamageRect = nullptr,
3652 const nsRect* aFrameDamageRect = nullptr,
3653 uint32_t aFlags = 0);
3655 void MarkNeedsDisplayItemRebuild();
3658 * Returns a rect that encompasses everything that might be painted by
3659 * this frame. This includes this frame, all its descendant frames, this
3660 * frame's outline, and descendant frames' outline, but does not include
3661 * areas clipped out by the CSS "overflow" and "clip" properties.
3663 * HasOverflowAreas() (below) will return true when this overflow
3664 * rect has been explicitly set, even if it matches mRect.
3665 * XXX Note: because of a space optimization using the formula above,
3666 * during reflow this function does not give accurate data if
3667 * FinishAndStoreOverflow has been called but mRect hasn't yet been
3668 * updated yet. FIXME: This actually isn't true, but it should be.
3670 * The ink overflow rect should NEVER be used for things that
3671 * affect layout. The scrollable overflow rect is permitted to affect
3672 * layout.
3674 * @return the rect relative to this frame's origin, but after
3675 * CSS transforms have been applied (i.e. not really this frame's coordinate
3676 * system, and may not contain the frame's border-box, e.g. if there
3677 * is a CSS transform scaling it down)
3679 nsRect InkOverflowRect() const {
3680 return GetOverflowRect(mozilla::OverflowType::Ink);
3684 * Returns a rect that encompasses the area of this frame that the
3685 * user should be able to scroll to reach. This is similar to
3686 * InkOverflowRect, but does not include outline or shadows, and
3687 * may in the future include more margins than ink overflow does.
3688 * It does not include areas clipped out by the CSS "overflow" and
3689 * "clip" properties.
3691 * HasOverflowAreas() (below) will return true when this overflow
3692 * rect has been explicitly set, even if it matches mRect.
3693 * XXX Note: because of a space optimization using the formula above,
3694 * during reflow this function does not give accurate data if
3695 * FinishAndStoreOverflow has been called but mRect hasn't yet been
3696 * updated yet.
3698 * @return the rect relative to this frame's origin, but after
3699 * CSS transforms have been applied (i.e. not really this frame's coordinate
3700 * system, and may not contain the frame's border-box, e.g. if there
3701 * is a CSS transform scaling it down)
3703 nsRect ScrollableOverflowRect() const {
3704 return GetOverflowRect(mozilla::OverflowType::Scrollable);
3707 mozilla::OverflowAreas GetOverflowAreas() const;
3710 * Same as GetOverflowAreas, except in this frame's coordinate
3711 * system (before transforms are applied).
3713 * @return the overflow areas relative to this frame, before any CSS
3714 * transforms have been applied, i.e. in this frame's coordinate system
3716 mozilla::OverflowAreas GetOverflowAreasRelativeToSelf() const;
3719 * Same as GetOverflowAreas, except relative to the parent frame.
3721 * @return the overflow area relative to the parent frame, in the parent
3722 * frame's coordinate system
3724 mozilla::OverflowAreas GetOverflowAreasRelativeToParent() const;
3727 * Same as GetOverflowAreasRelativeToParent(), except that it also unions in
3728 * the normal position overflow area if this frame is relatively or sticky
3729 * positioned.
3731 * @return the overflow area relative to the parent frame, in the parent
3732 * frame's coordinate system
3734 mozilla::OverflowAreas GetActualAndNormalOverflowAreasRelativeToParent()
3735 const;
3738 * Same as ScrollableOverflowRect, except relative to the parent
3739 * frame.
3741 * @return the rect relative to the parent frame, in the parent frame's
3742 * coordinate system
3744 nsRect ScrollableOverflowRectRelativeToParent() const;
3747 * Same as ScrollableOverflowRect, except in this frame's coordinate
3748 * system (before transforms are applied).
3750 * @return the rect relative to this frame, before any CSS transforms have
3751 * been applied, i.e. in this frame's coordinate system
3753 nsRect ScrollableOverflowRectRelativeToSelf() const;
3756 * Like InkOverflowRect, except in this frame's
3757 * coordinate system (before transforms are applied).
3759 * @return the rect relative to this frame, before any CSS transforms have
3760 * been applied, i.e. in this frame's coordinate system
3762 nsRect InkOverflowRectRelativeToSelf() const;
3765 * Same as InkOverflowRect, except relative to the parent
3766 * frame.
3768 * @return the rect relative to the parent frame, in the parent frame's
3769 * coordinate system
3771 nsRect InkOverflowRectRelativeToParent() const;
3774 * Returns this frame's ink overflow rect as it would be before taking
3775 * account of SVG effects or transforms. The rect returned is relative to
3776 * this frame.
3778 nsRect PreEffectsInkOverflowRect() const;
3781 * Store the overflow area in the frame's mOverflow.mInkOverflowDeltas
3782 * fields or as a frame property in OverflowAreasProperty() so that it can
3783 * be retrieved later without reflowing the frame. Returns true if either of
3784 * the overflow areas changed.
3786 bool FinishAndStoreOverflow(mozilla::OverflowAreas& aOverflowAreas,
3787 nsSize aNewSize, nsSize* aOldSize = nullptr,
3788 const nsStyleDisplay* aStyleDisplay = nullptr);
3790 bool FinishAndStoreOverflow(ReflowOutput* aMetrics,
3791 const nsStyleDisplay* aStyleDisplay = nullptr) {
3792 return FinishAndStoreOverflow(aMetrics->mOverflowAreas,
3793 nsSize(aMetrics->Width(), aMetrics->Height()),
3794 nullptr, aStyleDisplay);
3798 * Returns whether the frame has an overflow rect that is different from
3799 * its border-box.
3801 bool HasOverflowAreas() const {
3802 return mOverflow.mType != OverflowStorageType::None;
3806 * Removes any stored overflow rects (visual and scrollable) from the frame.
3807 * Returns true if the overflow changed.
3809 bool ClearOverflowRects();
3812 * Determine whether borders, padding, margins etc should NOT be applied
3813 * on certain sides of the frame.
3814 * @see mozilla::Sides in gfx/2d/BaseMargin.h
3815 * @see mozilla::LogicalSides in layout/generic/WritingModes.h
3817 * @note (See also bug 743402, comment 11) GetSkipSides() checks to see
3818 * if this frame has a previous or next continuation to determine
3819 * if a side should be skipped.
3820 * So this only works after the entire frame tree has been reflowed.
3821 * During reflow, if this frame can be split in the block axis, you
3822 * should use nsSplittableFrame::PreReflowBlockLevelLogicalSkipSides().
3824 Sides GetSkipSides() const;
3825 virtual LogicalSides GetLogicalSkipSides() const {
3826 return LogicalSides(mWritingMode);
3830 * @returns true if this frame is selected.
3832 bool IsSelected() const {
3833 return (GetContent() && GetContent()->IsMaybeSelected()) ? IsFrameSelected()
3834 : false;
3838 * Shouldn't be called if this is a `nsTextFrame`. Call the
3839 * `nsTextFrame::SelectionStateChanged` overload instead.
3841 void SelectionStateChanged() {
3842 MOZ_ASSERT(!IsTextFrame());
3843 InvalidateFrameSubtree(); // TODO: should this deal with continuations?
3847 * Called to discover where this frame, or a parent frame has user-select
3848 * style applied, which affects that way that it is selected.
3850 * @param aSelectStyle out param. Returns the type of selection style found
3851 * (using values defined in nsStyleConsts.h).
3853 * @return Whether the frame can be selected (i.e. is not affected by
3854 * user-select: none)
3856 bool IsSelectable(mozilla::StyleUserSelect* aSelectStyle) const;
3859 * Returns whether this frame should have the content-block-size of a line,
3860 * even if empty.
3862 bool ShouldHaveLineIfEmpty() const;
3865 * Called to retrieve the SelectionController associated with the frame.
3867 * @param aSelCon will contain the selection controller associated with
3868 * the frame.
3870 nsresult GetSelectionController(nsPresContext* aPresContext,
3871 nsISelectionController** aSelCon);
3874 * Call to get nsFrameSelection for this frame.
3876 already_AddRefed<nsFrameSelection> GetFrameSelection();
3879 * GetConstFrameSelection returns an object which methods are safe to use for
3880 * example in nsIFrame code.
3882 const nsFrameSelection* GetConstFrameSelection() const;
3885 * called to find the previous/next character, word, or line. Returns the
3886 * actual nsIFrame and the frame offset. THIS DOES NOT CHANGE SELECTION STATE.
3887 * Uses frame's begin selection state to start. If no selection on this frame
3888 * will return NS_ERROR_FAILURE.
3890 * @param aPos is defined in nsFrameSelection
3892 virtual nsresult PeekOffset(mozilla::PeekOffsetStruct* aPos);
3894 private:
3895 nsresult PeekOffsetForCharacter(mozilla::PeekOffsetStruct* aPos,
3896 int32_t aOffset);
3897 nsresult PeekOffsetForWord(mozilla::PeekOffsetStruct* aPos, int32_t aOffset);
3898 nsresult PeekOffsetForLine(mozilla::PeekOffsetStruct* aPos);
3899 nsresult PeekOffsetForLineEdge(mozilla::PeekOffsetStruct* aPos);
3902 * Search for the first paragraph boundary before or after the given position
3903 * @param aPos See description in nsFrameSelection.h. The following fields
3904 * are used by this method:
3905 * Input: mDirection
3906 * Output: mResultContent, mContentOffset
3908 nsresult PeekOffsetForParagraph(mozilla::PeekOffsetStruct* aPos);
3910 public:
3911 // given a frame five me the first/last leaf available
3912 // XXX Robert O'Callahan wants to move these elsewhere
3913 static void GetLastLeaf(nsIFrame** aFrame);
3914 static void GetFirstLeaf(nsIFrame** aFrame);
3916 struct SelectablePeekReport {
3917 /** the previous/next selectable leaf frame */
3918 nsIFrame* mFrame = nullptr;
3920 * 0 indicates that we arrived at the beginning of the output frame; -1
3921 * indicates that we arrived at its end.
3923 int32_t mOffset = 0;
3924 /** whether the input frame and the returned frame are on different lines */
3925 bool mJumpedLine = false;
3926 /** whether we met a hard break between the input and the returned frame */
3927 bool mJumpedHardBreak = false;
3928 /** whether we met a child placeholder frame */
3929 bool mFoundPlaceholder = false;
3930 /** whether we jumped over a non-selectable frame during the search */
3931 bool mMovedOverNonSelectableText = false;
3932 /** whether we met selectable text frame that isn't editable during the
3933 * search */
3934 bool mHasSelectableFrame = false;
3935 /** whether we ignored a br frame */
3936 bool mIgnoredBrFrame = false;
3938 FrameSearchResult PeekOffsetNoAmount(bool aForward) {
3939 return mFrame->PeekOffsetNoAmount(aForward, &mOffset);
3941 FrameSearchResult PeekOffsetCharacter(bool aForward,
3942 PeekOffsetCharacterOptions aOptions) {
3943 return mFrame->PeekOffsetCharacter(aForward, &mOffset, aOptions);
3946 /** Transfers frame and offset info for PeekOffset() result */
3947 void TransferTo(mozilla::PeekOffsetStruct& aPos) const;
3948 bool Failed() { return !mFrame; }
3950 explicit SelectablePeekReport(nsIFrame* aFrame = nullptr,
3951 int32_t aOffset = 0)
3952 : mFrame(aFrame), mOffset(aOffset) {}
3953 MOZ_IMPLICIT SelectablePeekReport(
3954 const mozilla::GenericErrorResult<nsresult>&& aErr);
3958 * Called to find the previous/next non-anonymous selectable leaf frame.
3960 * @param aDirection the direction to move in (eDirPrevious or eDirNext)
3961 * @param aOptions the other options which is same as
3962 * PeekOffsetStruct::mOptions.
3963 * FIXME: Due to the include hell, we cannot use the alias, PeekOffsetOptions
3964 * is not available in this header file.
3966 SelectablePeekReport GetFrameFromDirection(
3967 nsDirection aDirection,
3968 const mozilla::EnumSet<mozilla::PeekOffsetOption>& aOptions);
3969 SelectablePeekReport GetFrameFromDirection(
3970 const mozilla::PeekOffsetStruct& aPos);
3973 * Return:
3974 * (1) the containing block frame for a line; i.e. the frame which
3975 * supports a line iterator, or null if none can be found; and
3976 * (2) the frame to use to get a line number, which will be direct child of
3977 * the returned containing block.
3978 * @param aLockScroll true to avoid breaking outside scrollframes.
3980 std::pair<nsIFrame*, nsIFrame*> GetContainingBlockForLine(
3981 bool aLockScroll) const;
3983 private:
3984 Result<bool, nsresult> IsVisuallyAtLineEdge(nsILineIterator* aLineIterator,
3985 int32_t aLine,
3986 nsDirection aDirection);
3987 Result<bool, nsresult> IsLogicallyAtLineEdge(nsILineIterator* aLineIterator,
3988 int32_t aLine,
3989 nsDirection aDirection);
3991 public:
3993 * Called to tell a frame that one of its child frames is dirty (i.e.,
3994 * has the NS_FRAME_IS_DIRTY *or* NS_FRAME_HAS_DIRTY_CHILDREN bit
3995 * set). This should always set the NS_FRAME_HAS_DIRTY_CHILDREN on
3996 * the frame, and may do other work.
3998 virtual void ChildIsDirty(nsIFrame* aChild);
4001 * Called to retrieve this frame's accessible.
4002 * If this frame implements Accessibility return a valid accessible
4003 * If not return NS_ERROR_NOT_IMPLEMENTED.
4004 * Note: LocalAccessible must be refcountable. Do not implement directly on
4005 * your frame Use a mediatior of some kind.
4007 #ifdef ACCESSIBILITY
4008 virtual mozilla::a11y::AccType AccessibleType();
4009 #endif
4012 * Get the frame whose style should be the parent of this frame's style (i.e.,
4013 * provide the parent style).
4015 * This frame must either be an ancestor of this frame or a child. If
4016 * this returns a child frame, then the child frame must be sure to
4017 * return a grandparent or higher! Furthermore, if a child frame is
4018 * returned it must have the same GetContent() as this frame.
4020 * @param aProviderFrame (out) the frame associated with the returned value
4021 * or nullptr if the style is for display:contents content.
4022 * @return The style that should be the parent of this frame's style. Null is
4023 * permitted, and means that this frame's style should be the root of
4024 * the style tree.
4026 virtual ComputedStyle* GetParentComputedStyle(
4027 nsIFrame** aProviderFrame) const {
4028 return DoGetParentComputedStyle(aProviderFrame);
4032 * Do the work for getting the parent ComputedStyle frame so that
4033 * other frame's |GetParentComputedStyle| methods can call this
4034 * method on *another* frame. (This function handles out-of-flow
4035 * frames by using the frame manager's placeholder map and it also
4036 * handles block-within-inline and generated content wrappers.)
4038 * @param aProviderFrame (out) the frame associated with the returned value
4039 * or null if the ComputedStyle is for display:contents content.
4040 * @return The ComputedStyle that should be the parent of this frame's
4041 * ComputedStyle. Null is permitted, and means that this frame's
4042 * ComputedStyle should be the root of the ComputedStyle tree.
4044 ComputedStyle* DoGetParentComputedStyle(nsIFrame** aProviderFrame) const;
4047 * Adjust the given parent frame to the right ComputedStyle parent frame for
4048 * the child, given the pseudo-type of the prospective child. This handles
4049 * things like walking out of table pseudos and so forth.
4051 * @param aProspectiveParent what GetParent() on the child returns.
4052 * Must not be null.
4053 * @param aChildPseudo the child's pseudo type, if any.
4055 static nsIFrame* CorrectStyleParentFrame(
4056 nsIFrame* aProspectiveParent, mozilla::PseudoStyleType aChildPseudo);
4059 * Called by RestyleManager to update the style of anonymous boxes
4060 * directly associated with this frame.
4062 * The passed-in ServoRestyleState can be used to create new ComputedStyles as
4063 * needed, as well as posting changes to the change list.
4065 * It's guaranteed to already have a change in it for this frame and this
4066 * frame's content.
4068 * This function will be called after this frame's style has already been
4069 * updated. This function will only be called on frames which have the
4070 * NS_FRAME_OWNS_ANON_BOXES bit set.
4072 void UpdateStyleOfOwnedAnonBoxes(mozilla::ServoRestyleState& aRestyleState) {
4073 if (HasAnyStateBits(NS_FRAME_OWNS_ANON_BOXES)) {
4074 DoUpdateStyleOfOwnedAnonBoxes(aRestyleState);
4078 mozilla::ContainSizeAxes GetContainSizeAxes() const {
4079 return StyleDisplay()->GetContainSizeAxes(*this);
4082 Maybe<nscoord> ContainIntrinsicBSize(nscoord aNoneValue = 0) const {
4083 return GetContainSizeAxes().ContainIntrinsicBSize(*this, aNoneValue);
4086 Maybe<nscoord> ContainIntrinsicISize(nscoord aNoneValue = 0) const {
4087 return GetContainSizeAxes().ContainIntrinsicISize(*this, aNoneValue);
4090 protected:
4091 // This does the actual work of UpdateStyleOfOwnedAnonBoxes. It calls
4092 // AppendDirectlyOwnedAnonBoxes to find all of the anonymous boxes
4093 // owned by this frame, and then updates styles on each of them.
4094 void DoUpdateStyleOfOwnedAnonBoxes(mozilla::ServoRestyleState& aRestyleState);
4096 // A helper for DoUpdateStyleOfOwnedAnonBoxes for the specific case
4097 // of the owned anon box being a child of this frame.
4098 void UpdateStyleOfChildAnonBox(nsIFrame* aChildFrame,
4099 mozilla::ServoRestyleState& aRestyleState);
4101 // Allow ServoRestyleState to call UpdateStyleOfChildAnonBox.
4102 friend class mozilla::ServoRestyleState;
4104 public:
4105 // A helper both for UpdateStyleOfChildAnonBox, and to update frame-backed
4106 // pseudo-elements in RestyleManager.
4108 // This gets a ComputedStyle that will be the new style for `aChildFrame`, and
4109 // takes care of updating it, calling CalcStyleDifference, and adding to the
4110 // change list as appropriate.
4112 // If aContinuationComputedStyle is not Nothing, it should be used for
4113 // continuations instead of aNewComputedStyle. In either case, changehints
4114 // are only computed based on aNewComputedStyle.
4116 // Returns the generated change hint for the frame.
4117 static nsChangeHint UpdateStyleOfOwnedChildFrame(
4118 nsIFrame* aChildFrame, ComputedStyle* aNewComputedStyle,
4119 mozilla::ServoRestyleState& aRestyleState,
4120 const Maybe<ComputedStyle*>& aContinuationComputedStyle = Nothing());
4122 struct OwnedAnonBox {
4123 typedef void (*UpdateStyleFn)(nsIFrame* aOwningFrame, nsIFrame* aAnonBox,
4124 mozilla::ServoRestyleState& aRestyleState);
4126 explicit OwnedAnonBox(nsIFrame* aAnonBoxFrame,
4127 UpdateStyleFn aUpdateStyleFn = nullptr)
4128 : mAnonBoxFrame(aAnonBoxFrame), mUpdateStyleFn(aUpdateStyleFn) {}
4130 nsIFrame* mAnonBoxFrame;
4131 UpdateStyleFn mUpdateStyleFn;
4135 * Appends information about all of the anonymous boxes owned by this frame,
4136 * including other anonymous boxes owned by those which this frame owns
4137 * directly.
4139 void AppendOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult) {
4140 if (HasAnyStateBits(NS_FRAME_OWNS_ANON_BOXES)) {
4141 if (IsInlineFrame()) {
4142 // See comment in nsIFrame::DoUpdateStyleOfOwnedAnonBoxes for why
4143 // we skip nsInlineFrames.
4144 return;
4146 DoAppendOwnedAnonBoxes(aResult);
4150 protected:
4151 // This does the actual work of AppendOwnedAnonBoxes.
4152 void DoAppendOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult);
4154 public:
4156 * Hook subclasses can override to return their owned anonymous boxes.
4158 * This function only appends anonymous boxes that are directly owned by
4159 * this frame, i.e. direct children or (for certain frames) a wrapper
4160 * parent, unlike AppendOwnedAnonBoxes, which will append all anonymous
4161 * boxes transitively owned by this frame.
4163 virtual void AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult);
4166 * Determines whether a frame is visible for painting;
4167 * taking into account whether it is painting a selection or printing.
4169 bool IsVisibleForPainting() const;
4171 * Determines whether a frame is visible for painting or collapsed;
4172 * taking into account whether it is painting a selection or printing,
4174 bool IsVisibleOrCollapsedForPainting() const;
4177 * Determines if this frame is a stacking context.
4179 bool IsStackingContext(const nsStyleDisplay*, const nsStyleEffects*);
4180 bool IsStackingContext();
4182 // Whether we should paint backgrounds or not.
4183 struct ShouldPaintBackground {
4184 bool mColor = false;
4185 bool mImage = false;
4187 ShouldPaintBackground ComputeShouldPaintBackground() const;
4190 * Determine whether the frame is logically empty, which is roughly
4191 * whether the layout would be the same whether or not the frame is
4192 * present. Placeholder frames should return true. Block frames
4193 * should be considered empty whenever margins collapse through them,
4194 * even though those margins are relevant. Text frames containing
4195 * only whitespace that does not contribute to the height of the line
4196 * should return true.
4198 virtual bool IsEmpty();
4200 * Return the same as IsEmpty(). This may only be called after the frame
4201 * has been reflowed and before any further style or content changes.
4203 virtual bool CachedIsEmpty();
4205 * Determine whether the frame is logically empty, assuming that all
4206 * its children are empty.
4208 virtual bool IsSelfEmpty();
4211 * IsGeneratedContentFrame returns whether a frame corresponds to
4212 * generated content
4214 * @return whether the frame correspods to generated content
4216 bool IsGeneratedContentFrame() const {
4217 return HasAnyStateBits(NS_FRAME_GENERATED_CONTENT);
4221 * IsPseudoFrame returns whether a frame is a pseudo frame (eg an
4222 * anonymous table-row frame created for a CSS table-cell without an
4223 * enclosing table-row.
4225 * @param aParentContent the content node corresponding to the parent frame
4226 * @return whether the frame is a pseudo frame
4228 bool IsPseudoFrame(const nsIContent* aParentContent) {
4229 return mContent == aParentContent;
4233 * Support for reading and writing properties on the frame.
4234 * These call through to the frame's FrameProperties object, if it
4235 * exists, but avoid creating it if no property is ever set.
4237 template <typename T>
4238 FrameProperties::PropertyType<T> GetProperty(
4239 FrameProperties::Descriptor<T> aProperty,
4240 bool* aFoundResult = nullptr) const {
4241 return mProperties.Get(aProperty, aFoundResult);
4244 template <typename T>
4245 bool HasProperty(FrameProperties::Descriptor<T> aProperty) const {
4246 return mProperties.Has(aProperty);
4250 * Add a property, or update an existing property for the given descriptor.
4252 * Note: This function asserts if updating an existing nsFrameList property.
4254 template <typename T>
4255 void SetProperty(FrameProperties::Descriptor<T> aProperty,
4256 FrameProperties::PropertyType<T> aValue) {
4257 if constexpr (std::is_same_v<T, nsFrameList>) {
4258 MOZ_ASSERT(aValue, "Shouldn't set nullptr to a nsFrameList property!");
4259 MOZ_ASSERT(!HasProperty(aProperty),
4260 "Shouldn't update an existing nsFrameList property!");
4262 mProperties.Set(aProperty, aValue, this);
4265 // Unconditionally add a property; use ONLY if the descriptor is known
4266 // to NOT already be present.
4267 template <typename T>
4268 void AddProperty(FrameProperties::Descriptor<T> aProperty,
4269 FrameProperties::PropertyType<T> aValue) {
4270 mProperties.Add(aProperty, aValue);
4274 * Remove a property and return its value without destroying it. May return
4275 * nullptr.
4277 * Note: The caller is responsible for handling the life cycle of the returned
4278 * value.
4280 template <typename T>
4281 [[nodiscard]] FrameProperties::PropertyType<T> TakeProperty(
4282 FrameProperties::Descriptor<T> aProperty, bool* aFoundResult = nullptr) {
4283 return mProperties.Take(aProperty, aFoundResult);
4286 template <typename T>
4287 void RemoveProperty(FrameProperties::Descriptor<T> aProperty) {
4288 mProperties.Remove(aProperty, this);
4291 void RemoveAllProperties() { mProperties.RemoveAll(this); }
4293 // nsIFrames themselves are in the nsPresArena, and so are not measured here.
4294 // Instead, this measures heap-allocated things hanging off the nsIFrame, and
4295 // likewise for its descendants.
4296 virtual void AddSizeOfExcludingThisForTree(nsWindowSizes& aWindowSizes) const;
4299 * Return true if and only if this frame obeys visibility:hidden.
4300 * if it does not, then nsContainerFrame will hide its view even though
4301 * this means children can't be made visible again.
4303 virtual bool SupportsVisibilityHidden() { return true; }
4306 * Returns the clip rect set via the 'clip' property, if the 'clip' property
4307 * applies to this frame; otherwise returns Nothing(). The 'clip' property
4308 * applies to HTML frames if they are absolutely positioned. The 'clip'
4309 * property applies to SVG frames regardless of the value of the 'position'
4310 * property.
4312 * The coordinates of the returned rectangle are relative to this frame's
4313 * origin.
4315 Maybe<nsRect> GetClipPropClipRect(const nsStyleDisplay* aDisp,
4316 const nsStyleEffects* aEffects,
4317 const nsSize& aSize) const;
4320 * Check if this frame is focusable and in the current tab order.
4321 * Tabbable is indicated by a nonnegative tabindex & is a subset of focusable.
4322 * For example, only the selected radio button in a group is in the
4323 * tab order, unless the radio group has no selection in which case
4324 * all of the visible, non-disabled radio buttons in the group are
4325 * in the tab order. On the other hand, all of the visible, non-disabled
4326 * radio buttons are always focusable via clicking or script.
4327 * Also, depending on the pref accessibility.tabfocus some widgets may be
4328 * focusable but removed from the tab order. This is the default on
4329 * Mac OS X, where fewer items are focusable.
4330 * @param [in, optional] aWithMouse, is this focus query for mouse clicking
4331 * @param [in, optional] aCheckVisibility, whether to treat an invisible
4332 * frame as not focusable
4333 * @return whether the frame is focusable via mouse, kbd or script.
4335 [[nodiscard]] Focusable IsFocusable(bool aWithMouse = false,
4336 bool aCheckVisibility = true);
4338 protected:
4339 // Helper for IsFocusable.
4340 bool IsFocusableDueToScrollFrame();
4343 * Returns true if this box clips its children, e.g., if this box is an
4344 * scrollbox or has overflow: clip in both axes.
4346 bool DoesClipChildrenInBothAxes() const;
4349 * NOTE: aStatus is assumed to be already-initialized. The reflow statuses of
4350 * any reflowed absolute children will be merged into aStatus; aside from
4351 * that, this method won't modify aStatus.
4353 void ReflowAbsoluteFrames(nsPresContext* aPresContext,
4354 ReflowOutput& aDesiredSize,
4355 const ReflowInput& aReflowInput,
4356 nsReflowStatus& aStatus,
4357 bool aConstrainBSize = true);
4359 private:
4360 Maybe<nscoord> ComputeInlineSizeFromAspectRatio(
4361 mozilla::WritingMode aWM, const mozilla::LogicalSize& aCBSize,
4362 const mozilla::LogicalSize& aContentEdgeToBoxSizing,
4363 const mozilla::StyleSizeOverrides& aSizeOverrides,
4364 mozilla::ComputeSizeFlags aFlags) const;
4366 public:
4368 * @return true if this text frame ends with a newline character. It
4369 * should return false if this is not a text frame.
4371 virtual bool HasSignificantTerminalNewline() const;
4373 struct CaretPosition {
4374 CaretPosition();
4375 ~CaretPosition();
4377 nsCOMPtr<nsIContent> mResultContent;
4378 int32_t mContentOffset;
4382 * gets the first or last possible caret position within the frame
4384 * @param [in] aStart
4385 * true for getting the first possible caret position
4386 * false for getting the last possible caret position
4387 * @return The caret position in a CaretPosition.
4388 * the returned value is a 'best effort' in case errors
4389 * are encountered rummaging through the frame.
4391 CaretPosition GetExtremeCaretPosition(bool aStart);
4394 * Query whether this frame supports getting a line iterator.
4395 * @return true if a line iterator is supported.
4397 virtual bool CanProvideLineIterator() const { return false; }
4400 * Get a line iterator for this frame, if supported.
4402 * @return nullptr if no line iterator is supported.
4403 * @note dispose the line iterator using nsILineIterator::DisposeLineIterator
4405 virtual nsILineIterator* GetLineIterator() { return nullptr; }
4408 * If this frame is a next-in-flow, and its prev-in-flow has something on its
4409 * overflow list, pull those frames into the child list of this one.
4411 virtual void PullOverflowsFromPrevInFlow() {}
4414 * Accessors for the absolute containing block.
4416 bool IsAbsoluteContainer() const {
4417 return !!(mState & NS_FRAME_HAS_ABSPOS_CHILDREN);
4419 bool HasAbsolutelyPositionedChildren() const;
4420 nsAbsoluteContainingBlock* GetAbsoluteContainingBlock() const;
4421 void MarkAsAbsoluteContainingBlock();
4422 void MarkAsNotAbsoluteContainingBlock();
4423 // Child frame types override this function to select their own child list
4424 // name
4425 virtual mozilla::FrameChildListID GetAbsoluteListID() const {
4426 return mozilla::FrameChildListID::Absolute;
4429 // Checks if we (or any of our descendants) have NS_FRAME_PAINTED_THEBES set,
4430 // and clears this bit if so.
4431 bool CheckAndClearPaintedState();
4433 // Checks if we (or any of our descendents) have mBuiltDisplayList set, and
4434 // clears this bit if so.
4435 bool CheckAndClearDisplayListState();
4437 // CSS visibility just doesn't cut it because it doesn't inherit through
4438 // documents. Also if this frame is in a hidden card of a deck then it isn't
4439 // visible either and that isn't expressed using CSS visibility. Also if it
4440 // is in a hidden view (there are a few cases left and they are hopefully
4441 // going away soon).
4442 // If the VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY flag is passed then we
4443 // ignore the chrome/content boundary, otherwise we stop looking when we
4444 // reach it.
4445 enum { VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY = 0x01 };
4446 bool IsVisibleConsideringAncestors(uint32_t aFlags = 0) const;
4448 struct FrameWithDistance {
4449 nsIFrame* mFrame;
4450 nscoord mXDistance;
4451 nscoord mYDistance;
4455 * Finds a frame that is closer to a specified point than a current
4456 * distance. Distance is measured as for text selection -- a closer x
4457 * distance beats a closer y distance.
4459 * Normally, this function will only check the distance between this
4460 * frame's rectangle and the specified point. SVGTextFrame overrides
4461 * this so that it can manage all of its descendant frames and take
4462 * into account any SVG text layout.
4464 * If aPoint is closer to this frame's rectangle than aCurrentBestFrame
4465 * indicates, then aCurrentBestFrame is updated with the distance between
4466 * aPoint and this frame's rectangle, and with a pointer to this frame.
4467 * If aPoint is not closer, then aCurrentBestFrame is left unchanged.
4469 * @param aPoint The point to check for its distance to this frame.
4470 * @param aCurrentBestFrame Pointer to a struct that will be updated with
4471 * a pointer to this frame and its distance to aPoint, if this frame
4472 * is indeed closer than the current distance in aCurrentBestFrame.
4474 virtual void FindCloserFrameForSelection(
4475 const nsPoint& aPoint, FrameWithDistance* aCurrentBestFrame);
4478 * Is this a flex item? (i.e. a non-abs-pos child of a flex container)
4480 inline bool IsFlexItem() const;
4482 * Is this a grid item? (i.e. a non-abs-pos child of a grid container)
4484 inline bool IsGridItem() const;
4486 * Is this a flex or grid item? (i.e. a non-abs-pos child of a flex/grid
4487 * container)
4489 inline bool IsFlexOrGridItem() const;
4490 inline bool IsFlexOrGridContainer() const;
4493 * Return true if this frame has masonry layout in aAxis.
4494 * @note only valid to call on nsGridContainerFrames
4496 inline bool IsMasonry(mozilla::LogicalAxis aAxis) const;
4499 * @return true if this frame is used as a table caption.
4501 inline bool IsTableCaption() const;
4503 inline bool IsBlockOutside() const;
4504 inline bool IsInlineOutside() const;
4505 inline mozilla::StyleDisplay GetDisplay() const;
4506 inline bool IsFloating() const;
4507 inline bool IsAbsPosContainingBlock() const;
4508 inline bool IsFixedPosContainingBlock() const;
4509 inline bool IsRelativelyOrStickyPositioned() const;
4511 // Note: In general, you'd want to call IsRelativelyOrStickyPositioned()
4512 // unless you want to deal with "position:relative" and "position:sticky"
4513 // differently.
4514 inline bool IsRelativelyPositioned() const;
4515 inline bool IsStickyPositioned() const;
4517 inline bool IsAbsolutelyPositioned(
4518 const nsStyleDisplay* aStyleDisplay = nullptr) const;
4519 inline bool IsTrueOverflowContainer() const;
4521 // Does this frame have "column-span: all" style.
4523 // Note this only checks computed style, but not testing whether the
4524 // containing block formatting context was established by a multicol. Callers
4525 // need to use IsColumnSpanInMulticolSubtree() to check whether multi-column
4526 // effects apply or not.
4527 inline bool IsColumnSpan() const;
4529 // Like IsColumnSpan(), but this also checks whether the frame has a
4530 // multi-column ancestor or not.
4531 inline bool IsColumnSpanInMulticolSubtree() const;
4534 * Returns the vertical-align value to be used for layout, if it is one
4535 * of the enumerated values. If this is an SVG text frame, it returns a value
4536 * that corresponds to the value of dominant-baseline. If the
4537 * vertical-align property has length or percentage value, this returns
4538 * Nothing().
4540 Maybe<mozilla::StyleVerticalAlignKeyword> VerticalAlignEnum() const;
4543 * Adds the NS_FRAME_IN_POPUP state bit to aFrame, and
4544 * all descendant frames (including cross-doc ones).
4546 static void AddInPopupStateBitToDescendants(nsIFrame* aFrame);
4548 * Removes the NS_FRAME_IN_POPUP state bit from aFrame and
4549 * all descendant frames (including cross-doc ones), unless
4550 * the frame is a popup itself.
4552 static void RemoveInPopupStateBitFromDescendants(nsIFrame* aFrame);
4555 * Return true if aFrame is in an {ib} split and is NOT one of the
4556 * continuations of the first inline in it.
4558 bool FrameIsNonFirstInIBSplit() const {
4559 return HasAnyStateBits(NS_FRAME_PART_OF_IBSPLIT) &&
4560 FirstContinuation()->GetProperty(nsIFrame::IBSplitPrevSibling());
4564 * Return true if aFrame is in an {ib} split and is NOT one of the
4565 * continuations of the last inline in it.
4567 bool FrameIsNonLastInIBSplit() const {
4568 return HasAnyStateBits(NS_FRAME_PART_OF_IBSPLIT) &&
4569 FirstContinuation()->GetProperty(nsIFrame::IBSplitSibling());
4573 * Return whether this is a frame whose width is used when computing
4574 * the font size inflation of its descendants.
4576 bool IsContainerForFontSizeInflation() const {
4577 return HasAnyStateBits(NS_FRAME_FONT_INFLATION_CONTAINER);
4581 * Return whether this frame or any of its children is dirty.
4583 bool IsSubtreeDirty() const {
4584 return HasAnyStateBits(NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN);
4588 * Returns true if the frame is an SVGTextFrame or one of its descendants.
4590 bool IsInSVGTextSubtree() const {
4591 return HasAnyStateBits(NS_FRAME_IS_SVG_TEXT);
4595 * Returns true if the frame is an SVG Rendering Observer container.
4597 bool IsRenderingObserverContainer() const {
4598 // NS_FRAME_SVG_LAYOUT is used as a proxy to check for an SVG frame because
4599 // NS_STATE_SVG_RENDERING_OBSERVER_CONTAINER is an SVG specific state bit.
4600 return HasAllStateBits(NS_FRAME_SVG_LAYOUT |
4601 NS_STATE_SVG_RENDERING_OBSERVER_CONTAINER) ||
4602 IsSVGOuterSVGFrame();
4606 * Return whether this frame keeps track of overflow areas. (Frames for
4607 * non-display SVG elements -- e.g. <clipPath> -- do not maintain overflow
4608 * areas, because they're never painted.)
4610 bool FrameMaintainsOverflow() const {
4611 return !HasAllStateBits(NS_FRAME_SVG_LAYOUT | NS_FRAME_IS_NONDISPLAY) &&
4612 !(IsSVGOuterSVGFrame() && HasAnyStateBits(NS_FRAME_IS_NONDISPLAY));
4616 * @param aStyleDisplay: If the caller has this->StyleDisplay(), providing
4617 * it here will improve performance.
4619 bool BackfaceIsHidden(const nsStyleDisplay* aStyleDisplay) const {
4620 MOZ_ASSERT(aStyleDisplay == StyleDisplay());
4621 return aStyleDisplay->BackfaceIsHidden();
4623 bool BackfaceIsHidden() const { return StyleDisplay()->BackfaceIsHidden(); }
4626 * Returns true if the frame is scrolled out of view.
4628 bool IsScrolledOutOfView() const;
4631 * Computes a 2D matrix from the -moz-window-transform and
4632 * -moz-window-transform-origin properties on aFrame.
4633 * Values that don't result in a 2D matrix will be ignored and an identity
4634 * matrix will be returned instead.
4636 Matrix ComputeWidgetTransform() const;
4639 * @return true iff this frame has one or more associated image requests.
4640 * @see mozilla::css::ImageLoader.
4642 bool HasImageRequest() const { return mHasImageRequest; }
4645 * Update this frame's image request state.
4647 void SetHasImageRequest(bool aHasRequest) { mHasImageRequest = aHasRequest; }
4650 * Whether this frame has a first-letter child. If it does, the frame is
4651 * actually an nsContainerFrame and the first-letter frame can be gotten by
4652 * walking up to the nearest ancestor blockframe and getting its first
4653 * continuation's nsContainerFrame::FirstLetterProperty() property. This will
4654 * only return true for the first continuation of the first-letter's parent.
4656 bool HasFirstLetterChild() const { return mHasFirstLetterChild; }
4659 * Whether this frame's parent is a wrapper anonymous box. See documentation
4660 * for mParentIsWrapperAnonBox.
4662 bool ParentIsWrapperAnonBox() const { return mParentIsWrapperAnonBox; }
4663 void SetParentIsWrapperAnonBox() { mParentIsWrapperAnonBox = true; }
4666 * Whether this is a wrapper anonymous box needing a restyle.
4668 bool IsWrapperAnonBoxNeedingRestyle() const {
4669 return mIsWrapperBoxNeedingRestyle;
4671 void SetIsWrapperAnonBoxNeedingRestyle(bool aNeedsRestyle) {
4672 mIsWrapperBoxNeedingRestyle = aNeedsRestyle;
4675 bool MayHaveTransformAnimation() const { return mMayHaveTransformAnimation; }
4676 void SetMayHaveTransformAnimation() {
4677 AddStateBits(NS_FRAME_MAY_BE_TRANSFORMED);
4678 mMayHaveTransformAnimation = true;
4680 bool MayHaveOpacityAnimation() const { return mMayHaveOpacityAnimation; }
4681 void SetMayHaveOpacityAnimation() { mMayHaveOpacityAnimation = true; }
4683 // Returns true if this frame is visible or may have visible descendants.
4684 // Note: This function is accurate only on primary frames, because
4685 // mAllDescendantsAreInvisible is not updated on continuations.
4686 bool IsVisibleOrMayHaveVisibleDescendants() const {
4687 return !mAllDescendantsAreInvisible || StyleVisibility()->IsVisible();
4689 // Update mAllDescendantsAreInvisible flag for this frame and ancestors.
4690 void UpdateVisibleDescendantsState();
4692 void UpdateAnimationVisibility();
4695 * If this returns true, the frame it's called on should get the
4696 * NS_FRAME_HAS_DIRTY_CHILDREN bit set on it by the caller; either directly
4697 * if it's already in reflow, or via calling FrameNeedsReflow() to schedule a
4698 * reflow.
4700 virtual bool RenumberFrameAndDescendants(int32_t* aOrdinal, int32_t aDepth,
4701 int32_t aIncrement,
4702 bool aForCounting) {
4703 return false;
4706 enum class ExtremumLength {
4707 MinContent,
4708 MaxContent,
4709 MozAvailable,
4710 FitContent,
4711 FitContentFunction,
4714 template <typename SizeOrMaxSize>
4715 static Maybe<ExtremumLength> ToExtremumLength(const SizeOrMaxSize& aSize) {
4716 switch (aSize.tag) {
4717 case SizeOrMaxSize::Tag::MinContent:
4718 return mozilla::Some(ExtremumLength::MinContent);
4719 case SizeOrMaxSize::Tag::MaxContent:
4720 return mozilla::Some(ExtremumLength::MaxContent);
4721 case SizeOrMaxSize::Tag::MozAvailable:
4722 return mozilla::Some(ExtremumLength::MozAvailable);
4723 case SizeOrMaxSize::Tag::FitContent:
4724 return mozilla::Some(ExtremumLength::FitContent);
4725 case SizeOrMaxSize::Tag::FitContentFunction:
4726 return mozilla::Some(ExtremumLength::FitContentFunction);
4727 default:
4728 return mozilla::Nothing();
4733 * Helper function - computes the content-box inline size for aSize, which is
4734 * a more complex version to resolve a StyleExtremumLength.
4735 * @param aAvailableISizeOverride If this has a value, it is used as the
4736 * available inline-size instead of
4737 * aContainingBlockSize.ISize(aWM) when
4738 * resolving fit-content.
4740 struct ISizeComputationResult {
4741 nscoord mISize = 0;
4742 AspectRatioUsage mAspectRatioUsage = AspectRatioUsage::None;
4744 ISizeComputationResult ComputeISizeValue(
4745 gfxContext* aRenderingContext, const mozilla::WritingMode aWM,
4746 const mozilla::LogicalSize& aContainingBlockSize,
4747 const mozilla::LogicalSize& aContentEdgeToBoxSizing,
4748 nscoord aBoxSizingToMarginEdge, ExtremumLength aSize,
4749 Maybe<nscoord> aAvailableISizeOverride,
4750 const mozilla::StyleSizeOverrides& aSizeOverrides,
4751 mozilla::ComputeSizeFlags aFlags);
4754 * Helper function - computes the content-box inline size for aSize, which is
4755 * a simpler version to resolve a LengthPercentage.
4757 nscoord ComputeISizeValue(const mozilla::WritingMode aWM,
4758 const mozilla::LogicalSize& aContainingBlockSize,
4759 const mozilla::LogicalSize& aContentEdgeToBoxSizing,
4760 const LengthPercentage& aSize);
4762 template <typename SizeOrMaxSize>
4763 ISizeComputationResult ComputeISizeValue(
4764 gfxContext* aRenderingContext, const mozilla::WritingMode aWM,
4765 const mozilla::LogicalSize& aContainingBlockSize,
4766 const mozilla::LogicalSize& aContentEdgeToBoxSizing,
4767 nscoord aBoxSizingToMarginEdge, const SizeOrMaxSize& aSize,
4768 const mozilla::StyleSizeOverrides& aSizeOverrides = {},
4769 mozilla::ComputeSizeFlags aFlags = {}) {
4770 if (aSize.IsLengthPercentage()) {
4771 return {ComputeISizeValue(aWM, aContainingBlockSize,
4772 aContentEdgeToBoxSizing,
4773 aSize.AsLengthPercentage())};
4775 auto length = ToExtremumLength(aSize);
4776 MOZ_ASSERT(length, "This doesn't handle none / auto");
4777 Maybe<nscoord> availbleISizeOverride;
4778 if (aSize.IsFitContentFunction()) {
4779 availbleISizeOverride.emplace(aSize.AsFitContentFunction().Resolve(
4780 aContainingBlockSize.ISize(aWM)));
4782 return ComputeISizeValue(aRenderingContext, aWM, aContainingBlockSize,
4783 aContentEdgeToBoxSizing, aBoxSizingToMarginEdge,
4784 length.valueOr(ExtremumLength::MinContent),
4785 availbleISizeOverride, aSizeOverrides, aFlags);
4788 DisplayItemArray& DisplayItems() { return mDisplayItems; }
4789 const DisplayItemArray& DisplayItems() const { return mDisplayItems; }
4791 void AddDisplayItem(nsDisplayItem* aItem);
4792 bool RemoveDisplayItem(nsDisplayItem* aItem);
4793 void RemoveDisplayItemDataForDeletion();
4794 bool HasDisplayItems();
4795 bool HasDisplayItem(nsDisplayItem* aItem);
4796 bool HasDisplayItem(uint32_t aKey);
4798 static void PrintDisplayList(nsDisplayListBuilder* aBuilder,
4799 const nsDisplayList& aList,
4800 bool aDumpHtml = false);
4801 static void PrintDisplayList(nsDisplayListBuilder* aBuilder,
4802 const nsDisplayList& aList,
4803 std::stringstream& aStream,
4804 bool aDumpHtml = false);
4805 static void PrintDisplayItem(nsDisplayListBuilder* aBuilder,
4806 nsDisplayItem* aItem, std::stringstream& aStream,
4807 uint32_t aIndent = 0, bool aDumpSublist = false,
4808 bool aDumpHtml = false);
4809 #ifdef MOZ_DUMP_PAINTING
4810 static void PrintDisplayListSet(nsDisplayListBuilder* aBuilder,
4811 const nsDisplayListSet& aSet,
4812 std::stringstream& aStream,
4813 bool aDumpHtml = false);
4814 #endif
4817 * Adds display items for standard CSS background if necessary.
4818 * Does not check IsVisibleForPainting.
4819 * @return whether a themed background item was created.
4821 bool DisplayBackgroundUnconditional(nsDisplayListBuilder* aBuilder,
4822 const nsDisplayListSet& aLists);
4824 * Adds display items for standard CSS borders, background and outline for
4825 * for this frame, as necessary. Checks IsVisibleForPainting and won't
4826 * display anything if the frame is not visible.
4828 void DisplayBorderBackgroundOutline(nsDisplayListBuilder* aBuilder,
4829 const nsDisplayListSet& aLists);
4831 * Add a display item for the CSS outline. Does not check visibility.
4833 void DisplayOutlineUnconditional(nsDisplayListBuilder* aBuilder,
4834 const nsDisplayListSet& aLists);
4836 * Add a display item for the CSS outline, after calling
4837 * IsVisibleForPainting to confirm we are visible.
4839 void DisplayOutline(nsDisplayListBuilder* aBuilder,
4840 const nsDisplayListSet& aLists);
4843 * Add a display item for CSS inset box shadows. Does not check visibility.
4845 void DisplayInsetBoxShadowUnconditional(nsDisplayListBuilder* aBuilder,
4846 nsDisplayList* aList);
4849 * Add a display item for CSS inset box shadow, after calling
4850 * IsVisibleForPainting to confirm we are visible.
4852 void DisplayInsetBoxShadow(nsDisplayListBuilder* aBuilder,
4853 nsDisplayList* aList);
4856 * Add a display item for CSS outset box shadows. Does not check visibility.
4858 void DisplayOutsetBoxShadowUnconditional(nsDisplayListBuilder* aBuilder,
4859 nsDisplayList* aList);
4862 * Add a display item for CSS outset box shadow, after calling
4863 * IsVisibleForPainting to confirm we are visible.
4865 void DisplayOutsetBoxShadow(nsDisplayListBuilder* aBuilder,
4866 nsDisplayList* aList);
4868 bool ForceDescendIntoIfVisible() const { return mForceDescendIntoIfVisible; }
4869 void SetForceDescendIntoIfVisible(bool aForce) {
4870 mForceDescendIntoIfVisible = aForce;
4873 bool BuiltDisplayList() const { return mBuiltDisplayList; }
4874 void SetBuiltDisplayList(const bool aBuilt) { mBuiltDisplayList = aBuilt; }
4876 bool IsFrameModified() const { return mFrameIsModified; }
4877 void SetFrameIsModified(const bool aFrameIsModified) {
4878 mFrameIsModified = aFrameIsModified;
4881 bool HasModifiedDescendants() const { return mHasModifiedDescendants; }
4882 void SetHasModifiedDescendants(const bool aHasModifiedDescendants) {
4883 mHasModifiedDescendants = aHasModifiedDescendants;
4886 bool HasOverrideDirtyRegion() const { return mHasOverrideDirtyRegion; }
4887 void SetHasOverrideDirtyRegion(const bool aHasDirtyRegion) {
4888 mHasOverrideDirtyRegion = aHasDirtyRegion;
4891 bool MayHaveWillChangeBudget() const { return mMayHaveWillChangeBudget; }
4892 void SetMayHaveWillChangeBudget(const bool aHasBudget) {
4893 mMayHaveWillChangeBudget = aHasBudget;
4896 bool HasBSizeChange() const { return mHasBSizeChange; }
4897 void SetHasBSizeChange(const bool aHasBSizeChange) {
4898 mHasBSizeChange = aHasBSizeChange;
4901 bool HasPaddingChange() const { return mHasPaddingChange; }
4902 void SetHasPaddingChange(const bool aHasPaddingChange) {
4903 mHasPaddingChange = aHasPaddingChange;
4906 bool HasColumnSpanSiblings() const { return mHasColumnSpanSiblings; }
4907 void SetHasColumnSpanSiblings(bool aHasColumnSpanSiblings) {
4908 mHasColumnSpanSiblings = aHasColumnSpanSiblings;
4911 bool DescendantMayDependOnItsStaticPosition() const {
4912 return mDescendantMayDependOnItsStaticPosition;
4914 void SetDescendantMayDependOnItsStaticPosition(bool aValue) {
4915 mDescendantMayDependOnItsStaticPosition = aValue;
4918 bool ShouldGenerateComputedInfo() const {
4919 return mShouldGenerateComputedInfo;
4921 void SetShouldGenerateComputedInfo(bool aValue) {
4922 mShouldGenerateComputedInfo = aValue;
4926 * Returns the hit test area of the frame.
4928 nsRect GetCompositorHitTestArea(nsDisplayListBuilder* aBuilder);
4931 * Returns the set of flags indicating the properties of the frame that the
4932 * compositor might care about for hit-testing purposes. Note that this
4933 * function must be called during Gecko display list construction time (i.e
4934 * while the frame tree is being traversed) because that is when the display
4935 * list builder has the necessary state set up correctly.
4937 mozilla::gfx::CompositorHitTestInfo GetCompositorHitTestInfo(
4938 nsDisplayListBuilder* aBuilder);
4941 * Copies aWM to mWritingMode on 'this' and all its ancestors.
4943 inline void PropagateWritingModeToSelfAndAncestors(mozilla::WritingMode aWM);
4946 * Observes or unobserves the element with an internal ResizeObserver,
4947 * depending on whether it needs to update its last remembered size.
4948 * Also removes a previously stored last remembered size if the element
4949 * can no longer have it.
4950 * @see {@link https://drafts.csswg.org/css-sizing-4/#last-remembered}
4952 void HandleLastRememberedSize();
4954 protected:
4956 * Reparent this frame's view if it has one.
4958 void ReparentFrameViewTo(nsViewManager* aViewManager, nsView* aNewParentView);
4960 // Members
4961 nsRect mRect;
4962 nsCOMPtr<nsIContent> mContent;
4963 RefPtr<ComputedStyle> mComputedStyle;
4965 private:
4966 nsPresContext* const mPresContext;
4967 nsContainerFrame* mParent;
4968 nsIFrame* mNextSibling; // doubly-linked list of frames
4969 nsIFrame* mPrevSibling; // Do not touch outside SetNextSibling!
4971 DisplayItemArray mDisplayItems;
4973 void MarkAbsoluteFramesForDisplayList(nsDisplayListBuilder* aBuilder);
4975 protected:
4976 void MarkInReflow() {
4977 #ifdef DEBUG_dbaron_off
4978 // bug 81268
4979 NS_ASSERTION(!(mState & NS_FRAME_IN_REFLOW), "frame is already in reflow");
4980 #endif
4981 AddStateBits(NS_FRAME_IN_REFLOW);
4984 private:
4985 nsFrameState mState;
4987 protected:
4989 * List of properties attached to the frame.
4991 FrameProperties mProperties;
4993 // When there is no scrollable overflow area, and the ink overflow area only
4994 // slightly larger than mRect, the ink overflow area may be stored a set of
4995 // four 1-byte deltas from the edges of mRect rather than allocating a whole
4996 // separate rectangle property. If all four deltas are zero, this means that
4997 // no overflow area has actually been set (this is the initial state of
4998 // newly-created frames).
5000 // Note that these are unsigned values, all measured "outwards" from the edges
5001 // of mRect, so mLeft and mTop are reversed from our normal coordinate system.
5002 struct InkOverflowDeltas {
5003 // The maximum delta value we can store in any of the four edges.
5004 static constexpr uint8_t kMax = 0xfe;
5006 uint8_t mLeft;
5007 uint8_t mTop;
5008 uint8_t mRight;
5009 uint8_t mBottom;
5010 bool operator==(const InkOverflowDeltas& aOther) const {
5011 return mLeft == aOther.mLeft && mTop == aOther.mTop &&
5012 mRight == aOther.mRight && mBottom == aOther.mBottom;
5014 bool operator!=(const InkOverflowDeltas& aOther) const {
5015 return !(*this == aOther);
5018 enum class OverflowStorageType : uint32_t {
5019 // No overflow area; code relies on this being an all-zero value.
5020 None = 0x00000000u,
5022 // Ink overflow is too large to stored in InkOverflowDeltas.
5023 Large = 0x000000ffu,
5025 // If mOverflow.mType is OverflowStorageType::Large, then the delta values are
5026 // not meaningful and the overflow area is stored in OverflowAreasProperty()
5027 // instead.
5028 union {
5029 OverflowStorageType mType;
5030 InkOverflowDeltas mInkOverflowDeltas;
5031 } mOverflow;
5033 /** @see GetWritingMode() */
5034 mozilla::WritingMode mWritingMode;
5036 /** The ClassID of the concrete class of this instance. */
5037 ClassID mClass; // 1 byte
5039 bool mMayHaveRoundedCorners : 1;
5042 * True iff this frame has one or more associated image requests.
5043 * @see mozilla::css::ImageLoader.
5045 bool mHasImageRequest : 1;
5048 * True if this frame has a continuation that has a first-letter frame, or its
5049 * placeholder, as a child. In that case this frame has a blockframe ancestor
5050 * that has the first-letter frame hanging off it in the
5051 * nsContainerFrame::FirstLetterProperty() property.
5053 bool mHasFirstLetterChild : 1;
5056 * True if this frame's parent is a wrapper anonymous box (e.g. a table
5057 * anonymous box as specified at
5058 * <https://www.w3.org/TR/CSS21/tables.html#anonymous-boxes>).
5060 * We could compute this information directly when we need it, but it wouldn't
5061 * be all that cheap, and since this information is immutable for the lifetime
5062 * of the frame we might as well cache it.
5064 * Note that our parent may itself have mParentIsWrapperAnonBox set to true.
5066 bool mParentIsWrapperAnonBox : 1;
5069 * True if this is a wrapper anonymous box needing a restyle. This is used to
5070 * track, during stylo post-traversal, whether we've already recomputed the
5071 * style of this anonymous box, if we end up seeing it twice.
5073 bool mIsWrapperBoxNeedingRestyle : 1;
5076 * This bit is used in nsTextFrame::CharacterDataChanged() as an optimization
5077 * to skip redundant reflow-requests when the character data changes multiple
5078 * times between reflows. If this flag is set, then it implies that the
5079 * NS_FRAME_IS_DIRTY state bit is also set (and that intrinsic sizes have
5080 * been marked as dirty on our ancestor chain).
5082 * XXXdholbert This bit is *only* used on nsTextFrame, but it lives here on
5083 * nsIFrame simply because this is where we've got unused state bits
5084 * available in a gap. If bits become more scarce, we should perhaps consider
5085 * expanding the range of frame-specific state bits in nsFrameStateBits.h and
5086 * moving this to be one of those (e.g. by swapping one of the adjacent
5087 * general-purpose bits to take the place of this bool:1 here, so we can grow
5088 * that range of frame-specific bits by 1).
5090 bool mReflowRequestedForCharDataChange : 1;
5093 * This bit is used during BuildDisplayList to mark frames that need to
5094 * have display items rebuilt. We will descend into them if they are
5095 * currently visible, even if they don't intersect the dirty area.
5097 bool mForceDescendIntoIfVisible : 1;
5100 * True if we have built display items for this frame since
5101 * the last call to CheckAndClearDisplayListState, false
5102 * otherwise. Used for the reftest harness to verify minimal
5103 * display list building.
5105 bool mBuiltDisplayList : 1;
5108 * True if the frame has been marked modified by
5109 * |MarkNeedsDisplayItemRebuild()|, usually due to a style change or reflow.
5111 bool mFrameIsModified : 1;
5114 * True if the frame has modified descendants. Set before display list
5115 * preprocessing and only used during partial display list builds.
5117 bool mHasModifiedDescendants : 1;
5120 * Used by merging based retained display lists to restrict the dirty area
5121 * during partial display list builds.
5123 bool mHasOverrideDirtyRegion : 1;
5126 * True if frame has will-change, and currently has display
5127 * items consuming some of the will-change budget.
5129 bool mMayHaveWillChangeBudget : 1;
5131 #ifdef DEBUG
5132 public:
5134 * True if this frame has already been been visited by
5135 * nsCSSFrameConstructor::AutoFrameConstructionPageName.
5137 * This is used to assert that we have visited each frame only once, and is
5138 * not useful otherwise.
5140 bool mWasVisitedByAutoFrameConstructionPageName : 1;
5141 #endif
5143 private:
5145 * True if this is the primary frame for mContent.
5147 bool mIsPrimaryFrame : 1;
5149 bool mMayHaveTransformAnimation : 1;
5150 bool mMayHaveOpacityAnimation : 1;
5153 * True if we are certain that all descendants are not visible.
5155 * This flag is conservative in that it might sometimes be false even if, in
5156 * fact, all descendants are invisible.
5157 * For example; an element is visibility:visible and has a visibility:hidden
5158 * child. This flag is stil false in such case.
5160 bool mAllDescendantsAreInvisible : 1;
5162 bool mHasBSizeChange : 1;
5165 * True if the frame seems to be in the process of being reflowed with a
5166 * different amount of inline-axis padding as compared to its most recent
5167 * reflow. This flag's purpose is to detect cases where the frame's
5168 * inline-axis content-box-size has changed, without any style change or any
5169 * change to the border-box size, so that we can mark/invalidate things
5170 * appropriately in ReflowInput::InitResizeFlags().
5172 * This flag is set in SizeComputationResult::InitOffsets() and cleared in
5173 * nsIFrame::DidReflow().
5175 bool mHasPaddingChange : 1;
5178 * True if we are or contain the scroll anchor for a scrollable frame.
5180 bool mInScrollAnchorChain : 1;
5183 * Suppose a frame was split into multiple parts to separate parts containing
5184 * column-spans from parts not containing column-spans. This bit is set on all
5185 * continuations *not* containing column-spans except for the those after the
5186 * last column-span/non-column-span boundary (i.e., the bit really means it
5187 * has a *later* sibling across a split). Note that the last part is always
5188 * created to containing no columns-spans even if it has no children. See
5189 * nsCSSFrameConstructor::CreateColumnSpanSiblings() for the implementation.
5191 * If the frame having this bit set is removed, we need to reframe the
5192 * multi-column container.
5194 bool mHasColumnSpanSiblings : 1;
5197 * True if we may have any descendant whose positioning may depend on its
5198 * static position (and thus which we need to recompute the position for if we
5199 * move).
5201 bool mDescendantMayDependOnItsStaticPosition : 1;
5204 * True if the next reflow of this frame should generate computed info
5205 * metrics. These are used by devtools to reveal details of the layout
5206 * process.
5208 bool mShouldGenerateComputedInfo : 1;
5210 protected:
5211 // Helpers
5213 * Can we stop inside this frame when we're skipping non-rendered whitespace?
5215 * @param aForward [in] Are we moving forward (or backward) in content order.
5217 * @param aOffset [in/out] At what offset into the frame to start looking.
5218 * at offset was reached (whether or not we found a place to stop).
5220 * @return
5221 * * STOP: An appropriate offset was found within this frame,
5222 * and is given by aOffset.
5223 * * CONTINUE: Not found within this frame, need to try the next frame.
5224 * See enum FrameSearchResult for more details.
5226 virtual FrameSearchResult PeekOffsetNoAmount(bool aForward, int32_t* aOffset);
5229 * Search the frame for the next character
5231 * @param aForward [in] Are we moving forward (or backward) in content order.
5233 * @param aOffset [in/out] At what offset into the frame to start looking.
5234 * on output - what offset was reached (whether or not we found a place to
5235 * stop).
5237 * @param aOptions [in] Options, see the comment in PeekOffsetCharacterOptions
5238 * for the detail.
5240 * @return
5241 * * STOP: An appropriate offset was found within this frame, and is given
5242 * by aOffset.
5243 * * CONTINUE: Not found within this frame, need to try the next frame. See
5244 * enum FrameSearchResult for more details.
5246 virtual FrameSearchResult PeekOffsetCharacter(
5247 bool aForward, int32_t* aOffset,
5248 PeekOffsetCharacterOptions aOptions = PeekOffsetCharacterOptions());
5249 static_assert(sizeof(PeekOffsetCharacterOptions) <= sizeof(intptr_t),
5250 "aOptions should be changed to const reference");
5252 struct PeekWordState {
5253 // true when we're still at the start of the search, i.e., we can't return
5254 // this point as a valid offset!
5255 bool mAtStart;
5256 // true when we've encountered at least one character of the type before the
5257 // boundary we're looking for:
5258 // 1. If we're moving forward and eating whitepace, looking for a word
5259 // beginning (i.e. a boundary between whitespace and non-whitespace),
5260 // then mSawBeforeType==true means "we already saw some whitespace".
5261 // 2. Otherwise, looking for a word beginning (i.e. a boundary between
5262 // non-whitespace and whitespace), then mSawBeforeType==true means "we
5263 // already saw some non-whitespace".
5264 bool mSawBeforeType;
5265 // true when we've encountered at least one non-newline character
5266 bool mSawInlineCharacter;
5267 // true when the last character encountered was punctuation
5268 bool mLastCharWasPunctuation;
5269 // true when the last character encountered was whitespace
5270 bool mLastCharWasWhitespace;
5271 // true when we've seen non-punctuation since the last whitespace
5272 bool mSeenNonPunctuationSinceWhitespace;
5273 // text that's *before* the current frame when aForward is true, *after*
5274 // the current frame when aForward is false. Only includes the text
5275 // on the current line.
5276 nsAutoString mContext;
5278 PeekWordState()
5279 : mAtStart(true),
5280 mSawBeforeType(false),
5281 mSawInlineCharacter(false),
5282 mLastCharWasPunctuation(false),
5283 mLastCharWasWhitespace(false),
5284 mSeenNonPunctuationSinceWhitespace(false) {}
5285 void SetSawBeforeType() { mSawBeforeType = true; }
5286 void SetSawInlineCharacter() { mSawInlineCharacter = true; }
5287 void Update(bool aAfterPunctuation, bool aAfterWhitespace) {
5288 mLastCharWasPunctuation = aAfterPunctuation;
5289 mLastCharWasWhitespace = aAfterWhitespace;
5290 if (aAfterWhitespace) {
5291 mSeenNonPunctuationSinceWhitespace = false;
5292 } else if (!aAfterPunctuation) {
5293 mSeenNonPunctuationSinceWhitespace = true;
5295 mAtStart = false;
5300 * Search the frame for the next word boundary
5301 * @param aForward [in] Are we moving forward (or backward) in content order.
5302 * @param aWordSelectEatSpace [in] true: look for non-whitespace following
5303 * whitespace (in the direction of movement).
5304 * false: look for whitespace following non-whitespace (in the
5305 * direction of movement).
5306 * @param aIsKeyboardSelect [in] Was the action initiated by a keyboard
5307 * operation? If true, punctuation immediately following a word is considered
5308 * part of that word. Otherwise, a sequence of punctuation is always
5309 * considered as a word on its own.
5310 * @param aOffset [in/out] At what offset into the frame to start looking.
5311 * on output - what offset was reached (whether or not we found a
5312 * place to stop).
5313 * @param aState [in/out] the state that is carried from frame to frame
5315 virtual FrameSearchResult PeekOffsetWord(
5316 bool aForward, bool aWordSelectEatSpace, bool aIsKeyboardSelect,
5317 int32_t* aOffset, PeekWordState* aState, bool aTrimSpaces);
5319 protected:
5321 * Check whether we should break at a boundary between punctuation and
5322 * non-punctuation. Only call it at a punctuation boundary
5323 * (i.e. exactly one of the previous and next characters are punctuation).
5324 * @param aForward true if we're moving forward in content order
5325 * @param aPunctAfter true if the next character is punctuation
5326 * @param aWhitespaceAfter true if the next character is whitespace
5328 static bool BreakWordBetweenPunctuation(const PeekWordState* aState,
5329 bool aForward, bool aPunctAfter,
5330 bool aWhitespaceAfter,
5331 bool aIsKeyboardSelect);
5333 private:
5334 nsRect GetOverflowRect(mozilla::OverflowType aType) const;
5336 // Get a pointer to the overflow areas property attached to the frame.
5337 mozilla::OverflowAreas* GetOverflowAreasProperty() const {
5338 MOZ_ASSERT(mOverflow.mType == OverflowStorageType::Large);
5339 mozilla::OverflowAreas* overflow = GetProperty(OverflowAreasProperty());
5340 MOZ_ASSERT(overflow);
5341 return overflow;
5344 nsRect InkOverflowFromDeltas() const {
5345 MOZ_ASSERT(mOverflow.mType != OverflowStorageType::Large,
5346 "should not be called when overflow is in a property");
5347 // Calculate the rect using deltas from the frame's border rect.
5348 // Note that the mOverflow.mInkOverflowDeltas fields are unsigned, but we
5349 // will often need to return negative values for the left and top, so take
5350 // care to cast away the unsigned-ness.
5351 return nsRect(-(int32_t)mOverflow.mInkOverflowDeltas.mLeft,
5352 -(int32_t)mOverflow.mInkOverflowDeltas.mTop,
5353 mRect.Width() + mOverflow.mInkOverflowDeltas.mRight +
5354 mOverflow.mInkOverflowDeltas.mLeft,
5355 mRect.Height() + mOverflow.mInkOverflowDeltas.mBottom +
5356 mOverflow.mInkOverflowDeltas.mTop);
5360 * Set the OverflowArea rect, storing it as deltas or a separate rect
5361 * depending on its size in relation to the primary frame rect.
5363 * @return true if any overflow changed.
5365 bool SetOverflowAreas(const mozilla::OverflowAreas& aOverflowAreas);
5367 bool HasOpacityInternal(float aThreshold, const nsStyleDisplay* aStyleDisplay,
5368 const nsStyleEffects* aStyleEffects,
5369 mozilla::EffectSet* aEffectSet = nullptr) const;
5371 static constexpr size_t kFrameClassCount =
5372 #define FRAME_ID(...) 1 +
5373 #define ABSTRACT_FRAME_ID(...)
5374 #include "mozilla/FrameIdList.h"
5375 #undef FRAME_ID
5376 #undef ABSTRACT_FRAME_ID
5379 // Maps mClass to LayoutFrameType.
5380 static const mozilla::LayoutFrameType sLayoutFrameTypes[kFrameClassCount];
5381 // Maps mClass to LayoutFrameTypeFlags.
5382 static const ClassFlags sLayoutFrameClassFlags[kFrameClassCount];
5384 #ifdef DEBUG_FRAME_DUMP
5385 public:
5386 static void IndentBy(FILE* out, int32_t aIndent) {
5387 while (--aIndent >= 0) fputs(" ", out);
5389 void ListTag(FILE* out) const { fputs(ListTag().get(), out); }
5390 nsAutoCString ListTag() const;
5392 enum class ListFlag{TraverseSubdocumentFrames, DisplayInCSSPixels};
5393 using ListFlags = mozilla::EnumSet<ListFlag>;
5395 template <typename T>
5396 static std::string ConvertToString(const T& aValue, ListFlags aFlags) {
5397 // This method can convert all physical types in app units to CSS pixels.
5398 return aFlags.contains(ListFlag::DisplayInCSSPixels)
5399 ? mozilla::ToString(mozilla::CSSPixel::FromAppUnits(aValue))
5400 : mozilla::ToString(aValue);
5402 static std::string ConvertToString(const mozilla::LogicalRect& aRect,
5403 const mozilla::WritingMode aWM,
5404 ListFlags aFlags);
5405 static std::string ConvertToString(const mozilla::LogicalSize& aSize,
5406 const mozilla::WritingMode aWM,
5407 ListFlags aFlags);
5409 void ListGeneric(nsACString& aTo, const char* aPrefix = "",
5410 ListFlags aFlags = ListFlags()) const;
5411 virtual void List(FILE* out = stderr, const char* aPrefix = "",
5412 ListFlags aFlags = ListFlags()) const;
5414 void ListTextRuns(FILE* out = stderr) const;
5415 virtual void ListTextRuns(FILE* out, nsTHashSet<const void*>& aSeen) const;
5417 virtual void ListWithMatchedRules(FILE* out = stderr,
5418 const char* aPrefix = "") const;
5419 void ListMatchedRules(FILE* out, const char* aPrefix) const;
5422 * Dump the frame tree beginning from the root frame.
5424 void DumpFrameTree() const;
5425 void DumpFrameTreeInCSSPixels() const;
5428 * Dump the frame tree beginning from ourselves.
5430 void DumpFrameTreeLimited() const;
5431 void DumpFrameTreeLimitedInCSSPixels() const;
5434 * Get a printable from of the name of the frame type.
5435 * XXX This should be eliminated and we use GetType() instead...
5437 virtual nsresult GetFrameName(nsAString& aResult) const;
5438 nsresult MakeFrameName(const nsAString& aType, nsAString& aResult) const;
5439 // Helper function to return the index in parent of the frame's content
5440 // object. Returns Nothing on error or if the frame doesn't have a content
5441 // object
5442 static mozilla::Maybe<uint32_t> ContentIndexInContainer(
5443 const nsIFrame* aFrame);
5444 #endif
5446 #ifdef DEBUG
5448 * Tracing method that writes a method enter/exit routine to the
5449 * nspr log using the nsIFrame log module. The tracing is only
5450 * done when the NS_FRAME_TRACE_CALLS bit is set in the log module's
5451 * level field.
5453 void Trace(const char* aMethod, bool aEnter);
5454 void Trace(const char* aMethod, bool aEnter, const nsReflowStatus& aStatus);
5455 void TraceMsg(const char* aFormatString, ...) MOZ_FORMAT_PRINTF(2, 3);
5457 // Helper function that verifies that each frame in the list has the
5458 // NS_FRAME_IS_DIRTY bit set
5459 static void VerifyDirtyBitSet(const nsFrameList& aFrameList);
5461 // Display Reflow Debugging
5462 static void* DisplayReflowEnter(nsPresContext* aPresContext, nsIFrame* aFrame,
5463 const ReflowInput& aReflowInput);
5464 static void* DisplayLayoutEnter(nsIFrame* aFrame);
5465 static void* DisplayIntrinsicISizeEnter(nsIFrame* aFrame, const char* aType);
5466 static void* DisplayIntrinsicSizeEnter(nsIFrame* aFrame, const char* aType);
5467 static void DisplayReflowExit(nsPresContext* aPresContext, nsIFrame* aFrame,
5468 ReflowOutput& aMetrics,
5469 const nsReflowStatus& aStatus,
5470 void* aFrameTreeNode);
5471 static void DisplayLayoutExit(nsIFrame* aFrame, void* aFrameTreeNode);
5472 static void DisplayIntrinsicISizeExit(nsIFrame* aFrame, const char* aType,
5473 nscoord aResult, void* aFrameTreeNode);
5474 static void DisplayIntrinsicSizeExit(nsIFrame* aFrame, const char* aType,
5475 nsSize aResult, void* aFrameTreeNode);
5477 static void DisplayReflowStartup();
5478 static void DisplayReflowShutdown();
5480 static mozilla::LazyLogModule sFrameLogModule;
5481 #endif
5484 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(nsIFrame::ReflowChildFlags)
5486 //----------------------------------------------------------------------
5489 * AutoWeakFrame can be used to keep a reference to a nsIFrame in a safe way.
5490 * Whenever an nsIFrame object is deleted, the AutoWeakFrames pointing
5491 * to it will be cleared. AutoWeakFrame is for variables on the stack or
5492 * in static storage only, there is also a WeakFrame below for heap uses.
5494 * Create AutoWeakFrame object when it is sure that nsIFrame object
5495 * is alive and after some operations which may destroy the nsIFrame
5496 * (for example any DOM modifications) use IsAlive() or GetFrame() methods to
5497 * check whether it is safe to continue to use the nsIFrame object.
5499 * @note The usage of this class should be kept to a minimum.
5501 class WeakFrame;
5502 class MOZ_NONHEAP_CLASS AutoWeakFrame {
5503 public:
5504 explicit AutoWeakFrame() : mPrev(nullptr), mFrame(nullptr) {}
5506 AutoWeakFrame(const AutoWeakFrame& aOther) : mPrev(nullptr), mFrame(nullptr) {
5507 Init(aOther.GetFrame());
5510 MOZ_IMPLICIT AutoWeakFrame(const WeakFrame& aOther);
5512 MOZ_IMPLICIT AutoWeakFrame(nsIFrame* aFrame)
5513 : mPrev(nullptr), mFrame(nullptr) {
5514 Init(aFrame);
5517 AutoWeakFrame& operator=(AutoWeakFrame& aOther) {
5518 Init(aOther.GetFrame());
5519 return *this;
5522 AutoWeakFrame& operator=(nsIFrame* aFrame) {
5523 Init(aFrame);
5524 return *this;
5527 nsIFrame* operator->() { return mFrame; }
5529 operator nsIFrame*() { return mFrame; }
5531 void Clear(mozilla::PresShell* aPresShell);
5533 bool IsAlive() const { return !!mFrame; }
5535 nsIFrame* GetFrame() const { return mFrame; }
5537 AutoWeakFrame* GetPreviousWeakFrame() { return mPrev; }
5539 void SetPreviousWeakFrame(AutoWeakFrame* aPrev) { mPrev = aPrev; }
5541 ~AutoWeakFrame();
5543 private:
5544 // Not available for the heap!
5545 void* operator new(size_t) = delete;
5546 void* operator new[](size_t) = delete;
5547 void operator delete(void*) = delete;
5548 void operator delete[](void*) = delete;
5550 void Init(nsIFrame* aFrame);
5552 AutoWeakFrame* mPrev;
5553 nsIFrame* mFrame;
5556 // Use nsIFrame's fast-path to avoid QueryFrame:
5557 inline do_QueryFrameHelper<nsIFrame> do_QueryFrame(AutoWeakFrame& s) {
5558 return do_QueryFrameHelper<nsIFrame>(s.GetFrame());
5562 * @see AutoWeakFrame
5564 class MOZ_HEAP_CLASS WeakFrame {
5565 public:
5566 WeakFrame() : mFrame(nullptr) {}
5568 WeakFrame(const WeakFrame& aOther) : mFrame(nullptr) {
5569 Init(aOther.GetFrame());
5572 MOZ_IMPLICIT WeakFrame(const AutoWeakFrame& aOther) : mFrame(nullptr) {
5573 Init(aOther.GetFrame());
5576 MOZ_IMPLICIT WeakFrame(nsIFrame* aFrame) : mFrame(nullptr) { Init(aFrame); }
5578 ~WeakFrame() {
5579 Clear(mFrame ? mFrame->PresContext()->GetPresShell() : nullptr);
5582 WeakFrame& operator=(WeakFrame& aOther) {
5583 Init(aOther.GetFrame());
5584 return *this;
5587 WeakFrame& operator=(nsIFrame* aFrame) {
5588 Init(aFrame);
5589 return *this;
5592 nsIFrame* operator->() { return mFrame; }
5593 operator nsIFrame*() { return mFrame; }
5595 bool operator==(nsIFrame* const aOther) const { return mFrame == aOther; }
5597 void Clear(mozilla::PresShell* aPresShell);
5599 bool IsAlive() const { return !!mFrame; }
5600 nsIFrame* GetFrame() const { return mFrame; }
5602 private:
5603 void Init(nsIFrame* aFrame);
5605 nsIFrame* mFrame;
5608 // Use nsIFrame's fast-path to avoid QueryFrame:
5609 inline do_QueryFrameHelper<nsIFrame> do_QueryFrame(WeakFrame& s) {
5610 return do_QueryFrameHelper<nsIFrame>(s.GetFrame());
5613 inline bool nsFrameList::ContinueRemoveFrame(nsIFrame* aFrame) {
5614 MOZ_ASSERT(!aFrame->GetPrevSibling() || !aFrame->GetNextSibling(),
5615 "Forgot to call StartRemoveFrame?");
5616 if (aFrame == mLastChild) {
5617 MOZ_ASSERT(!aFrame->GetNextSibling(), "broken frame list");
5618 nsIFrame* prevSibling = aFrame->GetPrevSibling();
5619 if (!prevSibling) {
5620 MOZ_ASSERT(aFrame == mFirstChild, "broken frame list");
5621 mFirstChild = mLastChild = nullptr;
5622 return true;
5624 MOZ_ASSERT(prevSibling->GetNextSibling() == aFrame, "Broken frame linkage");
5625 prevSibling->SetNextSibling(nullptr);
5626 mLastChild = prevSibling;
5627 return true;
5629 if (aFrame == mFirstChild) {
5630 MOZ_ASSERT(!aFrame->GetPrevSibling(), "broken frame list");
5631 mFirstChild = aFrame->GetNextSibling();
5632 aFrame->SetNextSibling(nullptr);
5633 MOZ_ASSERT(mFirstChild, "broken frame list");
5634 return true;
5636 return false;
5639 inline bool nsFrameList::StartRemoveFrame(nsIFrame* aFrame) {
5640 if (aFrame->GetPrevSibling() && aFrame->GetNextSibling()) {
5641 UnhookFrameFromSiblings(aFrame);
5642 return true;
5644 return ContinueRemoveFrame(aFrame);
5647 // Operators of nsFrameList::Iterator
5648 // ---------------------------------------------------
5650 inline nsIFrame* nsFrameList::ForwardFrameTraversal::Next(nsIFrame* aFrame) {
5651 MOZ_ASSERT(aFrame);
5652 return aFrame->GetNextSibling();
5654 inline nsIFrame* nsFrameList::ForwardFrameTraversal::Prev(nsIFrame* aFrame) {
5655 MOZ_ASSERT(aFrame);
5656 return aFrame->GetPrevSibling();
5659 inline nsIFrame* nsFrameList::BackwardFrameTraversal::Next(nsIFrame* aFrame) {
5660 MOZ_ASSERT(aFrame);
5661 return aFrame->GetPrevSibling();
5663 inline nsIFrame* nsFrameList::BackwardFrameTraversal::Prev(nsIFrame* aFrame) {
5664 MOZ_ASSERT(aFrame);
5665 return aFrame->GetNextSibling();
5668 #endif /* nsIFrame_h___ */