Bumping manifests a=b2g-bump
[gecko.git] / layout / generic / nsIFrame.h
blobdc4c5e3538eee353ed73647eb6c9a95106c50908
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 sw=2 et tw=78: */
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 #define MAX_REFLOW_DEPTH 200
18 /* nsIFrame is in the process of being deCOMtaminated, i.e., this file is eventually
19 going to be eliminated, and all callers will use nsFrame instead. At the moment
20 we're midway through this process, so you will see inlined functions and member
21 variables in this file. -dwh */
23 #include <stdio.h>
24 #include "nsQueryFrame.h"
25 #include "nsStyleContext.h"
26 #include "nsStyleStruct.h"
27 #include "nsHTMLReflowMetrics.h"
28 #include "nsFrameList.h"
29 #include "mozilla/layout/FrameChildList.h"
30 #include "FramePropertyTable.h"
31 #include "mozilla/TypedEnum.h"
32 #include "nsDirection.h"
33 #include "WritingModes.h"
34 #include <algorithm>
35 #include "nsITheme.h"
36 #include "nsLayoutUtils.h"
37 #include "nsFrameState.h"
38 #include "CaretAssociationHint.h"
40 #ifdef ACCESSIBILITY
41 #include "mozilla/a11y/AccTypes.h"
42 #endif
44 /**
45 * New rules of reflow:
46 * 1. you get a WillReflow() followed by a Reflow() followed by a DidReflow() in order
47 * (no separate pass over the tree)
48 * 2. it's the parent frame's responsibility to size/position the child's view (not
49 * the child frame's responsibility as it is today) during reflow (and before
50 * sending the DidReflow() notification)
51 * 3. positioning of child frames (and their views) is done on the way down the tree,
52 * and sizing of child frames (and their views) on the way back up
53 * 4. if you move a frame (outside of the reflow process, or after reflowing it),
54 * then you must make sure that its view (or its child frame's views) are re-positioned
55 * as well. It's reasonable to not position the view until after all reflowing the
56 * entire line, for example, but the frame should still be positioned and sized (and
57 * the view sized) during the reflow (i.e., before sending the DidReflow() notification)
58 * 5. the view system handles moving of widgets, i.e., it's not our problem
61 struct nsHTMLReflowState;
62 class nsHTMLReflowCommand;
63 class nsIAtom;
64 class nsPresContext;
65 class nsIPresShell;
66 class nsRenderingContext;
67 class nsView;
68 class nsIWidget;
69 class nsIDOMRange;
70 class nsISelectionController;
71 class nsBoxLayoutState;
72 class nsBoxLayout;
73 class nsILineIterator;
74 class nsDisplayListBuilder;
75 class nsDisplayListSet;
76 class nsDisplayList;
77 class gfxSkipChars;
78 class gfxSkipCharsIterator;
79 class gfxContext;
80 class nsLineList_iterator;
81 class nsAbsoluteContainingBlock;
82 class nsIContent;
83 class nsContainerFrame;
85 struct nsPeekOffsetStruct;
86 struct nsPoint;
87 struct nsRect;
88 struct nsSize;
89 struct nsMargin;
90 struct CharacterDataChangeInfo;
92 namespace mozilla {
94 class EventStates;
96 namespace layers {
97 class Layer;
100 namespace gfx {
101 class Matrix;
106 * Indication of how the frame can be split. This is used when doing runaround
107 * of floats, and when pulling up child frames from a next-in-flow.
109 * The choices are splittable, not splittable at all, and splittable in
110 * a non-rectangular fashion. This last type only applies to block-level
111 * elements, and indicates whether splitting can be used when doing runaround.
112 * If you can split across page boundaries, but you expect each continuing
113 * frame to be the same width then return frSplittable and not
114 * frSplittableNonRectangular.
116 * @see #GetSplittableType()
118 typedef uint32_t nsSplittableType;
120 #define NS_FRAME_NOT_SPLITTABLE 0 // Note: not a bit!
121 #define NS_FRAME_SPLITTABLE 0x1
122 #define NS_FRAME_SPLITTABLE_NON_RECTANGULAR 0x3
124 #define NS_FRAME_IS_SPLITTABLE(type)\
125 (0 != ((type) & NS_FRAME_SPLITTABLE))
127 #define NS_FRAME_IS_NOT_SPLITTABLE(type)\
128 (0 == ((type) & NS_FRAME_SPLITTABLE))
130 #define NS_INTRINSIC_WIDTH_UNKNOWN nscoord_MIN
132 //----------------------------------------------------------------------
134 #define NS_SUBTREE_DIRTY(_frame) \
135 (((_frame)->GetStateBits() & \
136 (NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN)) != 0)
139 * Constant used to indicate an unconstrained size.
141 * @see #Reflow()
143 #define NS_UNCONSTRAINEDSIZE NS_MAXSIZE
145 #define NS_INTRINSICSIZE NS_UNCONSTRAINEDSIZE
146 #define NS_AUTOHEIGHT NS_UNCONSTRAINEDSIZE
147 #define NS_AUTOMARGIN NS_UNCONSTRAINEDSIZE
148 #define NS_AUTOOFFSET NS_UNCONSTRAINEDSIZE
149 // NOTE: there are assumptions all over that these have the same value, namely NS_UNCONSTRAINEDSIZE
150 // if any are changed to be a value other than NS_UNCONSTRAINEDSIZE
151 // at least update AdjustComputedHeight/Width and test ad nauseum
153 //----------------------------------------------------------------------
155 enum nsSelectionAmount {
156 eSelectCharacter = 0, // a single Unicode character;
157 // do not use this (prefer Cluster) unless you
158 // are really sure it's what you want
159 eSelectCluster = 1, // a grapheme cluster: this is usually the right
160 // choice for movement or selection by "character"
161 // as perceived by the user
162 eSelectWord = 2,
163 eSelectLine = 3, // previous drawn line in flow.
164 eSelectBeginLine = 4,
165 eSelectEndLine = 5,
166 eSelectNoAmount = 6, // just bounce back current offset.
167 eSelectParagraph = 7, // select a "paragraph"
168 eSelectWordNoSpace = 8 // select a "word" without selecting the following
169 // space, no matter what the default platform
170 // behavior is
173 enum nsSpread {
174 eSpreadNone = 0,
175 eSpreadAcross = 1,
176 eSpreadDown = 2
179 // Carried out margin flags
180 #define NS_CARRIED_TOP_MARGIN_IS_AUTO 0x1
181 #define NS_CARRIED_BOTTOM_MARGIN_IS_AUTO 0x2
183 //----------------------------------------------------------------------
186 * Reflow status returned by the reflow methods. There are three
187 * completion statuses, represented by two bit flags.
189 * NS_FRAME_COMPLETE means the frame is fully complete.
191 * NS_FRAME_NOT_COMPLETE bit flag means the frame does not map all its
192 * content, and that the parent frame should create a continuing frame.
193 * If this bit isn't set it means the frame does map all its content.
194 * This bit is mutually exclusive with NS_FRAME_OVERFLOW_INCOMPLETE.
196 * NS_FRAME_OVERFLOW_INCOMPLETE bit flag means that the frame has
197 * overflow that is not complete, but its own box is complete.
198 * (This happens when content overflows a fixed-height box.)
199 * The reflower should place and size the frame and continue its reflow,
200 * but needs to create an overflow container as a continuation for this
201 * frame. See nsContainerFrame.h for more information.
202 * This bit is mutually exclusive with NS_FRAME_NOT_COMPLETE.
204 * Please use the SET macro for handling
205 * NS_FRAME_NOT_COMPLETE and NS_FRAME_OVERFLOW_INCOMPLETE.
207 * NS_FRAME_REFLOW_NEXTINFLOW bit flag means that the next-in-flow is
208 * dirty, and also needs to be reflowed. This status only makes sense
209 * for a frame that is not complete, i.e. you wouldn't set both
210 * NS_FRAME_COMPLETE and NS_FRAME_REFLOW_NEXTINFLOW.
212 * The low 8 bits of the nsReflowStatus are reserved for future extensions;
213 * the remaining 24 bits are zero (and available for extensions; however
214 * API's that accept/return nsReflowStatus must not receive/return any
215 * extension bits).
217 * @see #Reflow()
219 typedef uint32_t nsReflowStatus;
221 #define NS_FRAME_COMPLETE 0 // Note: not a bit!
222 #define NS_FRAME_NOT_COMPLETE 0x1
223 #define NS_FRAME_REFLOW_NEXTINFLOW 0x2
224 #define NS_FRAME_OVERFLOW_INCOMPLETE 0x4
226 #define NS_FRAME_IS_COMPLETE(status) \
227 (0 == ((status) & NS_FRAME_NOT_COMPLETE))
229 #define NS_FRAME_IS_NOT_COMPLETE(status) \
230 (0 != ((status) & NS_FRAME_NOT_COMPLETE))
232 #define NS_FRAME_OVERFLOW_IS_INCOMPLETE(status) \
233 (0 != ((status) & NS_FRAME_OVERFLOW_INCOMPLETE))
235 #define NS_FRAME_IS_FULLY_COMPLETE(status) \
236 (NS_FRAME_IS_COMPLETE(status) && !NS_FRAME_OVERFLOW_IS_INCOMPLETE(status))
238 // These macros set or switch incomplete statuses without touching the
239 // NS_FRAME_REFLOW_NEXTINFLOW bit.
240 #define NS_FRAME_SET_INCOMPLETE(status) \
241 status = (status & ~NS_FRAME_OVERFLOW_INCOMPLETE) | NS_FRAME_NOT_COMPLETE
243 #define NS_FRAME_SET_OVERFLOW_INCOMPLETE(status) \
244 status = (status & ~NS_FRAME_NOT_COMPLETE) | NS_FRAME_OVERFLOW_INCOMPLETE
246 // This macro tests to see if an nsReflowStatus is an error value
247 // or just a regular return value
248 #define NS_IS_REFLOW_ERROR(_status) (int32_t(_status) < 0)
251 * Extensions to the reflow status bits defined by nsIFrameReflow
254 // This bit is set, when a break is requested. This bit is orthogonal
255 // to the nsIFrame::nsReflowStatus completion bits.
256 #define NS_INLINE_BREAK 0x0100
258 // When a break is requested, this bit when set indicates that the
259 // break should occur after the frame just reflowed; when the bit is
260 // clear the break should occur before the frame just reflowed.
261 #define NS_INLINE_BREAK_BEFORE 0x0000
262 #define NS_INLINE_BREAK_AFTER 0x0200
264 // The type of break requested can be found in these bits.
265 #define NS_INLINE_BREAK_TYPE_MASK 0xF000
267 // Set when a break was induced by completion of a first-letter
268 #define NS_INLINE_BREAK_FIRST_LETTER_COMPLETE 0x10000
270 //----------------------------------------
271 // Macros that use those bits
273 #define NS_INLINE_IS_BREAK(_status) \
274 (0 != ((_status) & NS_INLINE_BREAK))
276 #define NS_INLINE_IS_BREAK_AFTER(_status) \
277 (0 != ((_status) & NS_INLINE_BREAK_AFTER))
279 #define NS_INLINE_IS_BREAK_BEFORE(_status) \
280 (NS_INLINE_BREAK == ((_status) & (NS_INLINE_BREAK|NS_INLINE_BREAK_AFTER)))
282 #define NS_INLINE_GET_BREAK_TYPE(_status) (((_status) >> 12) & 0xF)
284 #define NS_INLINE_MAKE_BREAK_TYPE(_type) ((_type) << 12)
286 // Construct a line-break-before status. Note that there is no
287 // completion status for a line-break before because we *know* that
288 // the frame will be reflowed later and hence its current completion
289 // status doesn't matter.
290 #define NS_INLINE_LINE_BREAK_BEFORE() \
291 (NS_INLINE_BREAK | NS_INLINE_BREAK_BEFORE | \
292 NS_INLINE_MAKE_BREAK_TYPE(NS_STYLE_CLEAR_LINE))
294 // Take a completion status and add to it the desire to have a
295 // line-break after. For this macro we do need the completion status
296 // because the user of the status will need to know whether to
297 // continue the frame or not.
298 #define NS_INLINE_LINE_BREAK_AFTER(_completionStatus) \
299 ((_completionStatus) | NS_INLINE_BREAK | NS_INLINE_BREAK_AFTER | \
300 NS_INLINE_MAKE_BREAK_TYPE(NS_STYLE_CLEAR_LINE))
302 // A frame is "truncated" if the part of the frame before the first
303 // possible break point was unable to fit in the available vertical
304 // space. Therefore, the entire frame should be moved to the next page.
305 // A frame that begins at the top of the page must never be "truncated".
306 // Doing so would likely cause an infinite loop.
307 #define NS_FRAME_TRUNCATED 0x0010
308 #define NS_FRAME_IS_TRUNCATED(status) \
309 (0 != ((status) & NS_FRAME_TRUNCATED))
310 #define NS_FRAME_SET_TRUNCATION(status, aReflowState, aMetrics) \
311 aReflowState.SetTruncated(aMetrics, &status);
313 // Merge the incompleteness, truncation and NS_FRAME_REFLOW_NEXTINFLOW
314 // status from aSecondary into aPrimary.
315 void NS_MergeReflowStatusInto(nsReflowStatus* aPrimary,
316 nsReflowStatus aSecondary);
318 //----------------------------------------------------------------------
321 * DidReflow status values.
323 MOZ_BEGIN_ENUM_CLASS(nsDidReflowStatus, uint32_t)
324 NOT_FINISHED,
325 FINISHED
326 MOZ_END_ENUM_CLASS(nsDidReflowStatus)
329 * When there is no scrollable overflow rect, the visual overflow rect
330 * may be stored as four 1-byte deltas each strictly LESS THAN 0xff, for
331 * the four edges of the rectangle, or the four bytes may be read as a
332 * single 32-bit "overflow-rect type" value including at least one 0xff
333 * byte as an indicator that the value does NOT represent four deltas.
334 * If all four deltas are zero, this means that no overflow rect has
335 * actually been set (this is the initial state of newly-created frames).
337 #define NS_FRAME_OVERFLOW_DELTA_MAX 0xfe // max delta we can store
339 #define NS_FRAME_OVERFLOW_NONE 0x00000000 // there are no overflow rects;
340 // code relies on this being
341 // the all-zero value
343 #define NS_FRAME_OVERFLOW_LARGE 0x000000ff // overflow is stored as a
344 // separate rect property
346 namespace mozilla {
348 * For replaced elements only. Gets the intrinsic dimensions of this element.
349 * The dimensions may only be one of the following two types:
351 * eStyleUnit_Coord - a length in app units
352 * eStyleUnit_None - the element has no intrinsic size in this dimension
354 struct IntrinsicSize {
355 nsStyleCoord width, height;
357 IntrinsicSize()
358 : width(eStyleUnit_None), height(eStyleUnit_None)
360 IntrinsicSize(const IntrinsicSize& rhs)
361 : width(rhs.width), height(rhs.height)
363 IntrinsicSize& operator=(const IntrinsicSize& rhs) {
364 width = rhs.width; height = rhs.height; return *this;
366 bool operator==(const IntrinsicSize& rhs) {
367 return width == rhs.width && height == rhs.height;
369 bool operator!=(const IntrinsicSize& rhs) {
370 return !(*this == rhs);
375 //----------------------------------------------------------------------
378 * A frame in the layout model. This interface is supported by all frame
379 * objects.
381 * Frames can have multiple child lists: the default child list
382 * (referred to as the <i>principal</i> child list, and additional named
383 * child lists. There is an ordering of frames within a child list, but
384 * there is no order defined between frames in different child lists of
385 * the same parent frame.
387 * Frames are NOT reference counted. Use the Destroy() member function
388 * to destroy a frame. The lifetime of the frame hierarchy is bounded by the
389 * lifetime of the presentation shell which owns the frames.
391 * nsIFrame is a private Gecko interface. If you are not Gecko then you
392 * should not use it. If you're not in layout, then you won't be able to
393 * link to many of the functions defined here. Too bad.
395 * If you're not in layout but you must call functions in here, at least
396 * restrict yourself to calling virtual methods, which won't hurt you as badly.
398 class nsIFrame : public nsQueryFrame
400 public:
401 typedef mozilla::FramePropertyDescriptor FramePropertyDescriptor;
402 typedef mozilla::FrameProperties FrameProperties;
403 typedef mozilla::layers::Layer Layer;
404 typedef mozilla::layout::FrameChildList ChildList;
405 typedef mozilla::layout::FrameChildListID ChildListID;
406 typedef mozilla::layout::FrameChildListIDs ChildListIDs;
407 typedef mozilla::layout::FrameChildListIterator ChildListIterator;
408 typedef mozilla::layout::FrameChildListArrayIterator ChildListArrayIterator;
409 typedef mozilla::gfx::Matrix Matrix;
410 typedef mozilla::gfx::Matrix4x4 Matrix4x4;
411 typedef mozilla::Sides Sides;
412 typedef mozilla::LogicalSides LogicalSides;
414 NS_DECL_QUERYFRAME_TARGET(nsIFrame)
416 nsPresContext* PresContext() const {
417 return StyleContext()->RuleNode()->PresContext();
421 * Called to initialize the frame. This is called immediately after creating
422 * the frame.
424 * If the frame is a continuing frame, then aPrevInFlow indicates the previous
425 * frame (the frame that was split).
427 * If you want a view associated with your frame, you should create the view
428 * after Init() has returned.
430 * @param aContent the content object associated with the frame
431 * @param aParent the parent frame
432 * @param aPrevInFlow the prev-in-flow frame
434 virtual void Init(nsIContent* aContent,
435 nsContainerFrame* aParent,
436 nsIFrame* aPrevInFlow) = 0;
439 * Destroys this frame and each of its child frames (recursively calls
440 * Destroy() for each child). If this frame is a first-continuation, this
441 * also removes the frame from the primary frame map and clears undisplayed
442 * content for its content node.
443 * If the frame is a placeholder, it also ensures the out-of-flow frame's
444 * removal and destruction.
446 void Destroy() { DestroyFrom(this); }
448 /** Flags for PeekOffsetCharacter, PeekOffsetNoAmount, PeekOffsetWord return values.
450 enum FrameSearchResult {
451 // Peek found a appropriate offset within frame.
452 FOUND = 0x00,
453 // try next frame for offset.
454 CONTINUE = 0x1,
455 // offset not found because the frame was empty of text.
456 CONTINUE_EMPTY = 0x2 | CONTINUE,
457 // offset not found because the frame didn't contain any text that could be selected.
458 CONTINUE_UNSELECTABLE = 0x4 | CONTINUE,
461 protected:
463 * Return true if the frame is part of a Selection.
464 * Helper method to implement the public IsSelected() API.
466 virtual bool IsFrameSelected() const;
469 * Implements Destroy(). Do not call this directly except from within a
470 * DestroyFrom() implementation.
472 * @note This will always be called, so it is not necessary to override
473 * Destroy() in subclasses of nsFrame, just DestroyFrom().
475 * @param aDestructRoot is the root of the subtree being destroyed
477 virtual void DestroyFrom(nsIFrame* aDestructRoot) = 0;
478 friend class nsFrameList; // needed to pass aDestructRoot through to children
479 friend class nsLineBox; // needed to pass aDestructRoot through to children
480 friend class nsContainerFrame; // needed to pass aDestructRoot through to children
481 friend class nsFrame; // need to assign mParent
482 public:
485 * Get the content object associated with this frame. Does not add a reference.
487 nsIContent* GetContent() const { return mContent; }
490 * Get the frame that should be the parent for the frames of child elements
491 * May return nullptr during reflow
493 virtual nsContainerFrame* GetContentInsertionFrame() { return nullptr; }
496 * Move any frames on our overflow list to the end of our principal list.
497 * @return true if there were any overflow frames
499 virtual bool DrainSelfOverflowList() { return false; }
502 * Get the frame that should be scrolled if the content associated
503 * with this frame is targeted for scrolling. For frames implementing
504 * nsIScrollableFrame this will return the frame itself. For frames
505 * like nsTextControlFrame that contain a scrollframe, will return
506 * that scrollframe.
508 virtual nsIScrollableFrame* GetScrollTargetFrame() { return nullptr; }
511 * Get the offsets of the frame. most will be 0,0
514 virtual nsresult GetOffsets(int32_t &start, int32_t &end) const = 0;
517 * Reset the offsets when splitting frames during Bidi reordering
520 virtual void AdjustOffsetsForBidi(int32_t aStart, int32_t aEnd) {}
523 * Get the style context associated with this frame.
525 nsStyleContext* StyleContext() const { return mStyleContext; }
526 void SetStyleContext(nsStyleContext* aContext)
528 if (aContext != mStyleContext) {
529 nsStyleContext* oldStyleContext = mStyleContext;
530 mStyleContext = aContext;
531 aContext->AddRef();
532 DidSetStyleContext(oldStyleContext);
533 oldStyleContext->Release();
538 * SetStyleContextWithoutNotification is for changes to the style
539 * context that should suppress style change processing, in other
540 * words, those that aren't really changes. This generally means only
541 * changes that happen during frame construction.
543 void SetStyleContextWithoutNotification(nsStyleContext* aContext)
545 if (aContext != mStyleContext) {
546 mStyleContext->Release();
547 mStyleContext = aContext;
548 aContext->AddRef();
552 // Style post processing hook
553 // Attention: the old style context is the one we're forgetting,
554 // and hence possibly completely bogus for GetStyle* purposes.
555 // Use PeekStyleData instead.
556 virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext) = 0;
559 * Define typesafe getter functions for each style struct by
560 * preprocessing the list of style structs. These functions are the
561 * preferred way to get style data. The macro creates functions like:
562 * const nsStyleBorder* StyleBorder();
563 * const nsStyleColor* StyleColor();
565 * Callers outside of libxul should use nsIDOMWindow::GetComputedStyle()
566 * instead of these accessors.
568 #define STYLE_STRUCT(name_, checkdata_cb_) \
569 const nsStyle##name_ * Style##name_ () const { \
570 NS_ASSERTION(mStyleContext, "No style context found!"); \
571 return mStyleContext->Style##name_ (); \
573 #include "nsStyleStructList.h"
574 #undef STYLE_STRUCT
576 /** Also forward GetVisitedDependentColor to the style context */
577 nscolor GetVisitedDependentColor(nsCSSProperty aProperty)
578 { return mStyleContext->GetVisitedDependentColor(aProperty); }
581 * These methods are to access any additional style contexts that
582 * the frame may be holding. These are contexts that are children
583 * of the frame's primary context and are NOT used as style contexts
584 * for any child frames. These contexts also MUST NOT have any child
585 * contexts whatsoever. If you need to insert style contexts into the
586 * style tree, then you should create pseudo element frames to own them
587 * The indicies must be consecutive and implementations MUST return an
588 * NS_ERROR_INVALID_ARG if asked for an index that is out of range.
590 virtual nsStyleContext* GetAdditionalStyleContext(int32_t aIndex) const = 0;
592 virtual void SetAdditionalStyleContext(int32_t aIndex,
593 nsStyleContext* aStyleContext) = 0;
596 * Accessor functions for geometric parent.
598 nsContainerFrame* GetParent() const { return mParent; }
600 * Set this frame's parent to aParent.
601 * If the frame may have moved into or out of a scrollframe's
602 * frame subtree, StickyScrollContainer::NotifyReparentedFrameAcrossScrollFrameBoundary
603 * must also be called.
605 void SetParent(nsContainerFrame* aParent);
608 * The frame's writing-mode, used for logical layout computations.
610 mozilla::WritingMode GetWritingMode() const {
611 return mozilla::WritingMode(StyleVisibility());
615 * Get the writing mode of this frame, but if it is styled with
616 * unicode-bidi: plaintext, reset the direction to the resolved paragraph
617 * level of the given subframe (typically the first frame on the line),
618 * not this frame's writing mode, because the container frame could be split
619 * by hard line breaks into multiple paragraphs with different base direction.
621 mozilla::WritingMode GetWritingMode(nsIFrame* aSubFrame) const;
624 * Bounding rect of the frame. The values are in app units, and the origin is
625 * relative to the upper-left of the geometric parent. The size includes the
626 * content area, borders, and padding.
628 * Note: moving or sizing the frame does not affect the view's size or
629 * position.
631 nsRect GetRect() const { return mRect; }
632 nsPoint GetPosition() const { return mRect.TopLeft(); }
633 nsSize GetSize() const { return mRect.Size(); }
634 nsRect GetRectRelativeToSelf() const {
635 return nsRect(nsPoint(0, 0), mRect.Size());
638 * Dimensions and position in logical coordinates in the frame's writing mode
639 * or another writing mode
641 mozilla::LogicalRect GetLogicalRect(nscoord aContainerWidth) const {
642 return GetLogicalRect(GetWritingMode(), aContainerWidth);
644 mozilla::LogicalPoint GetLogicalPosition(nscoord aContainerWidth) const {
645 return GetLogicalPosition(GetWritingMode(), aContainerWidth);
647 mozilla::LogicalSize GetLogicalSize() const {
648 return GetLogicalSize(GetWritingMode());
650 mozilla::LogicalRect GetLogicalRect(mozilla::WritingMode aWritingMode,
651 nscoord aContainerWidth) const {
652 return mozilla::LogicalRect(aWritingMode, GetRect(), aContainerWidth);
654 mozilla::LogicalPoint GetLogicalPosition(mozilla::WritingMode aWritingMode,
655 nscoord aContainerWidth) const {
656 return GetLogicalRect(aWritingMode, aContainerWidth).Origin(aWritingMode);
658 mozilla::LogicalSize GetLogicalSize(mozilla::WritingMode aWritingMode) const {
659 return mozilla::LogicalSize(aWritingMode, GetSize());
661 nscoord IStart(nscoord aContainerWidth) const {
662 return IStart(GetWritingMode(), aContainerWidth);
664 nscoord IStart(mozilla::WritingMode aWritingMode,
665 nscoord aContainerWidth) const {
666 return GetLogicalPosition(aWritingMode, aContainerWidth).I(aWritingMode);
668 nscoord BStart(nscoord aContainerWidth) const {
669 return BStart(GetWritingMode(), aContainerWidth);
671 nscoord BStart(mozilla::WritingMode aWritingMode,
672 nscoord aContainerWidth) const {
673 return GetLogicalPosition(aWritingMode, aContainerWidth).B(aWritingMode);
675 nscoord ISize() const { return ISize(GetWritingMode()); }
676 nscoord ISize(mozilla::WritingMode aWritingMode) const {
677 return GetLogicalSize(aWritingMode).ISize(aWritingMode);
679 nscoord BSize() const { return BSize(GetWritingMode()); }
680 nscoord BSize(mozilla::WritingMode aWritingMode) const {
681 return GetLogicalSize(aWritingMode).BSize(aWritingMode);
685 * When we change the size of the frame's border-box rect, we may need to
686 * reset the overflow rect if it was previously stored as deltas.
687 * (If it is currently a "large" overflow and could be re-packed as deltas,
688 * we don't bother as the cost of the allocation has already been paid.)
690 void SetRect(const nsRect& aRect) {
691 if (mOverflow.mType != NS_FRAME_OVERFLOW_LARGE &&
692 mOverflow.mType != NS_FRAME_OVERFLOW_NONE) {
693 nsOverflowAreas overflow = GetOverflowAreas();
694 mRect = aRect;
695 SetOverflowAreas(overflow);
696 } else {
697 mRect = aRect;
701 * Set this frame's rect from a logical rect in its own writing direction
703 void SetRect(const mozilla::LogicalRect& aRect, nscoord aContainerWidth) {
704 SetRect(GetWritingMode(), aRect, aContainerWidth);
707 * Set this frame's rect from a logical rect in a different writing direction
708 * (GetPhysicalRect will assert if the writing mode doesn't match)
710 void SetRect(mozilla::WritingMode aWritingMode,
711 const mozilla::LogicalRect& aRect,
712 nscoord aContainerWidth) {
713 SetRect(aRect.GetPhysicalRect(aWritingMode, aContainerWidth));
717 * Set this frame's size from a logical size in its own writing direction
719 void SetSize(const mozilla::LogicalSize& aSize) {
720 SetSize(GetWritingMode(), aSize);
723 * Set this frame's size from a logical size in a different writing direction
725 void SetSize(mozilla::WritingMode aWritingMode,
726 const mozilla::LogicalSize& aSize) {
727 SetSize(aSize.GetPhysicalSize(aWritingMode));
729 void SetSize(const nsSize& aSize) {
730 SetRect(nsRect(mRect.TopLeft(), aSize));
732 void SetPosition(const nsPoint& aPt) { mRect.MoveTo(aPt); }
735 * Move the frame, accounting for relative positioning. Use this when
736 * adjusting the frame's position by a known amount, to properly update its
737 * saved normal position (see GetNormalPosition below).
739 * This must be used only when moving a frame *after*
740 * nsHTMLReflowState::ApplyRelativePositioning is called. When moving
741 * a frame during the reflow process prior to calling
742 * nsHTMLReflowState::ApplyRelativePositioning, the position should
743 * simply be adjusted directly (e.g., using SetPosition()).
745 void MovePositionBy(const nsPoint& aTranslation);
748 * Return frame's position without relative positioning
750 nsPoint GetNormalPosition() const;
751 mozilla::LogicalPoint
752 GetLogicalNormalPosition(mozilla::WritingMode aWritingMode,
753 nscoord aContainerWidth) const
755 return mozilla::LogicalPoint(aWritingMode,
756 GetNormalPosition(), aContainerWidth);
759 virtual nsPoint GetPositionOfChildIgnoringScrolling(nsIFrame* aChild)
760 { return aChild->GetPosition(); }
762 nsPoint GetPositionIgnoringScrolling();
764 static void DestroyRegion(void* aPropertyValue);
766 static void DestroyMargin(void* aPropertyValue)
768 delete static_cast<nsMargin*>(aPropertyValue);
771 static void DestroyRect(void* aPropertyValue)
773 delete static_cast<nsRect*>(aPropertyValue);
776 static void DestroyPoint(void* aPropertyValue)
778 delete static_cast<nsPoint*>(aPropertyValue);
781 static void DestroyOverflowAreas(void* aPropertyValue)
783 delete static_cast<nsOverflowAreas*>(aPropertyValue);
786 static void DestroySurface(void* aPropertyValue);
787 static void DestroyDT(void* aPropertyValue);
789 #ifdef _MSC_VER
790 // XXX Workaround MSVC issue by making the static FramePropertyDescriptor
791 // non-const. See bug 555727.
792 #define NS_PROPERTY_DESCRIPTOR_CONST
793 #else
794 #define NS_PROPERTY_DESCRIPTOR_CONST const
795 #endif
797 #define NS_DECLARE_FRAME_PROPERTY(prop, dtor) \
798 static const FramePropertyDescriptor* prop() { \
799 static NS_PROPERTY_DESCRIPTOR_CONST FramePropertyDescriptor descriptor = { dtor, nullptr }; \
800 return &descriptor; \
802 // Don't use this unless you really know what you're doing!
803 #define NS_DECLARE_FRAME_PROPERTY_WITH_FRAME_IN_DTOR(prop, dtor) \
804 static const FramePropertyDescriptor* prop() { \
805 static NS_PROPERTY_DESCRIPTOR_CONST FramePropertyDescriptor descriptor = { nullptr, dtor }; \
806 return &descriptor; \
809 NS_DECLARE_FRAME_PROPERTY(IBSplitSibling, nullptr)
810 NS_DECLARE_FRAME_PROPERTY(IBSplitPrevSibling, nullptr)
812 NS_DECLARE_FRAME_PROPERTY(NormalPositionProperty, DestroyPoint)
813 NS_DECLARE_FRAME_PROPERTY(ComputedOffsetProperty, DestroyMargin)
815 NS_DECLARE_FRAME_PROPERTY(OutlineInnerRectProperty, DestroyRect)
816 NS_DECLARE_FRAME_PROPERTY(PreEffectsBBoxProperty, DestroyRect)
817 NS_DECLARE_FRAME_PROPERTY(PreTransformOverflowAreasProperty,
818 DestroyOverflowAreas)
820 // The initial overflow area passed to FinishAndStoreOverflow. This is only set
821 // on frames that Preserve3D() or HasPerspective() or IsTransformed(), and
822 // when at least one of the overflow areas differs from the frame bound rect.
823 NS_DECLARE_FRAME_PROPERTY(InitialOverflowProperty, DestroyOverflowAreas)
825 #ifdef DEBUG
826 // InitialOverflowPropertyDebug is added to the frame to indicate that either
827 // the InitialOverflowProperty has been stored or the InitialOverflowProperty
828 // has been suppressed due to being set to the default value (frame bounds)
829 NS_DECLARE_FRAME_PROPERTY(DebugInitialOverflowPropertyApplied, nullptr)
830 #endif
832 NS_DECLARE_FRAME_PROPERTY(UsedMarginProperty, DestroyMargin)
833 NS_DECLARE_FRAME_PROPERTY(UsedPaddingProperty, DestroyMargin)
834 NS_DECLARE_FRAME_PROPERTY(UsedBorderProperty, DestroyMargin)
836 NS_DECLARE_FRAME_PROPERTY(ScrollLayerCount, nullptr)
838 NS_DECLARE_FRAME_PROPERTY(LineBaselineOffset, nullptr)
840 NS_DECLARE_FRAME_PROPERTY(CachedBackgroundImage, DestroySurface)
841 NS_DECLARE_FRAME_PROPERTY(CachedBackgroundImageDT, DestroyDT)
843 NS_DECLARE_FRAME_PROPERTY(InvalidationRect, DestroyRect)
845 NS_DECLARE_FRAME_PROPERTY(RefusedAsyncAnimation, nullptr)
848 * Return the distance between the border edge of the frame and the
849 * margin edge of the frame. Like GetRect(), returns the dimensions
850 * as of the most recent reflow.
852 * This doesn't include any margin collapsing that may have occurred.
854 * It also treats 'auto' margins as zero, and treats any margins that
855 * should have been turned into 'auto' because of overconstraint as
856 * having their original values.
858 virtual nsMargin GetUsedMargin() const;
859 virtual mozilla::LogicalMargin
860 GetLogicalUsedMargin(mozilla::WritingMode aWritingMode) const {
861 return mozilla::LogicalMargin(aWritingMode, GetUsedMargin());
865 * Return the distance between the border edge of the frame (which is
866 * its rect) and the padding edge of the frame. Like GetRect(), returns
867 * the dimensions as of the most recent reflow.
869 * Note that this differs from StyleBorder()->GetBorder() in that
870 * this describes region of the frame's box, and
871 * StyleBorder()->GetBorder() describes a border. They differ only
872 * for tables, particularly border-collapse tables.
874 virtual nsMargin GetUsedBorder() const;
875 virtual mozilla::LogicalMargin
876 GetLogicalUsedBorder(mozilla::WritingMode aWritingMode) const {
877 return mozilla::LogicalMargin(aWritingMode, GetUsedBorder());
881 * Return the distance between the padding edge of the frame and the
882 * content edge of the frame. Like GetRect(), returns the dimensions
883 * as of the most recent reflow.
885 virtual nsMargin GetUsedPadding() const;
886 virtual mozilla::LogicalMargin
887 GetLogicalUsedPadding(mozilla::WritingMode aWritingMode) const {
888 return mozilla::LogicalMargin(aWritingMode, GetUsedPadding());
891 nsMargin GetUsedBorderAndPadding() const {
892 return GetUsedBorder() + GetUsedPadding();
894 mozilla::LogicalMargin
895 GetLogicalUsedBorderAndPadding(mozilla::WritingMode aWritingMode) const {
896 return mozilla::LogicalMargin(aWritingMode, GetUsedBorderAndPadding());
900 * Like the frame's rect (see |GetRect|), which is the border rect,
901 * other rectangles of the frame, in app units, relative to the parent.
903 nsRect GetPaddingRect() const;
904 nsRect GetPaddingRectRelativeToSelf() const;
905 nsRect GetContentRect() const;
906 nsRect GetContentRectRelativeToSelf() const;
907 nsRect GetMarginRectRelativeToSelf() const;
910 * The area to paint box-shadows around. The default is the border rect.
911 * (nsFieldSetFrame overrides this).
913 virtual nsRect VisualBorderRectRelativeToSelf() const {
914 return nsRect(0, 0, mRect.width, mRect.height);
918 * Get the size, in app units, of the border radii. It returns FALSE iff all
919 * returned radii == 0 (so no border radii), TRUE otherwise.
920 * For the aRadii indexes, use the NS_CORNER_* constants in nsStyleConsts.h
921 * If a side is skipped via aSkipSides, its corners are forced to 0.
923 * All corner radii are then adjusted so they do not require more
924 * space than aBorderArea, according to the algorithm in css3-background.
926 * aFrameSize is used as the basis for percentage widths and heights.
927 * aBorderArea is used for the adjustment of radii that might be too
928 * large.
929 * FIXME: In the long run, we can probably get away with only one of
930 * these, especially if we change the way we handle outline-radius (by
931 * removing it and inflating the border radius)
933 * Return whether any radii are nonzero.
935 static bool ComputeBorderRadii(const nsStyleCorners& aBorderRadius,
936 const nsSize& aFrameSize,
937 const nsSize& aBorderArea,
938 Sides aSkipSides,
939 nscoord aRadii[8]);
942 * Given a set of border radii for one box (e.g., border box), convert
943 * it to the equivalent set of radii for another box (e.g., in to
944 * padding box, out to outline box) by reducing radii or increasing
945 * nonzero radii as appropriate.
947 * Indices into aRadii are the NS_CORNER_* constants in nsStyleConsts.h
949 * Note that InsetBorderRadii is lossy, since it can turn nonzero
950 * radii into zero, and OutsetBorderRadii does not inflate zero radii.
951 * Therefore, callers should always inset or outset directly from the
952 * original value coming from style.
954 static void InsetBorderRadii(nscoord aRadii[8], const nsMargin &aOffsets);
955 static void OutsetBorderRadii(nscoord aRadii[8], const nsMargin &aOffsets);
958 * Fill in border radii for this frame. Return whether any are nonzero.
959 * Indices into aRadii are the NS_CORNER_* constants in nsStyleConsts.h
960 * aSkipSides is a union of SIDE_BIT_LEFT/RIGHT/TOP/BOTTOM bits that says
961 * which side(s) to skip.
963 virtual bool GetBorderRadii(const nsSize& aFrameSize,
964 const nsSize& aBorderArea,
965 Sides aSkipSides,
966 nscoord aRadii[8]) const;
967 bool GetBorderRadii(nscoord aRadii[8]) const;
969 bool GetPaddingBoxBorderRadii(nscoord aRadii[8]) const;
970 bool GetContentBoxBorderRadii(nscoord aRadii[8]) const;
973 * Get the position of the frame's baseline, relative to the top of
974 * the frame (its top border edge). Only valid when Reflow is not
975 * needed.
977 virtual nscoord GetLogicalBaseline(mozilla::WritingMode aWritingMode) const = 0;
980 * Get the position of the baseline on which the caret needs to be placed,
981 * relative to the top of the frame. This is mostly needed for frames
982 * which return a baseline from GetBaseline which is not useful for
983 * caret positioning.
985 virtual nscoord GetCaretBaseline() const {
986 return GetLogicalBaseline(GetWritingMode());
990 * Get the specified child list.
992 * @param aListID identifies the requested child list.
993 * @return the child list. If the requested list is unsupported by this
994 * frame type, an empty list will be returned.
996 virtual const nsFrameList& GetChildList(ChildListID aListID) const = 0;
997 const nsFrameList& PrincipalChildList() { return GetChildList(kPrincipalList); }
998 virtual void GetChildLists(nsTArray<ChildList>* aLists) const = 0;
1001 * Gets the child lists for this frame, including
1002 * ones belong to a child document.
1004 void GetCrossDocChildLists(nsTArray<ChildList>* aLists);
1006 // XXXbz this method should go away
1007 nsIFrame* GetFirstChild(ChildListID aListID) const {
1008 return GetChildList(aListID).FirstChild();
1010 // XXXmats this method should also go away then
1011 nsIFrame* GetLastChild(ChildListID aListID) const {
1012 return GetChildList(aListID).LastChild();
1014 nsIFrame* GetFirstPrincipalChild() const {
1015 return GetFirstChild(kPrincipalList);
1018 // The individual concrete child lists.
1019 static const ChildListID kPrincipalList = mozilla::layout::kPrincipalList;
1020 static const ChildListID kAbsoluteList = mozilla::layout::kAbsoluteList;
1021 static const ChildListID kBulletList = mozilla::layout::kBulletList;
1022 static const ChildListID kCaptionList = mozilla::layout::kCaptionList;
1023 static const ChildListID kColGroupList = mozilla::layout::kColGroupList;
1024 static const ChildListID kExcessOverflowContainersList = mozilla::layout::kExcessOverflowContainersList;
1025 static const ChildListID kFixedList = mozilla::layout::kFixedList;
1026 static const ChildListID kFloatList = mozilla::layout::kFloatList;
1027 static const ChildListID kOverflowContainersList = mozilla::layout::kOverflowContainersList;
1028 static const ChildListID kOverflowList = mozilla::layout::kOverflowList;
1029 static const ChildListID kOverflowOutOfFlowList = mozilla::layout::kOverflowOutOfFlowList;
1030 static const ChildListID kPopupList = mozilla::layout::kPopupList;
1031 static const ChildListID kPushedFloatsList = mozilla::layout::kPushedFloatsList;
1032 static const ChildListID kSelectPopupList = mozilla::layout::kSelectPopupList;
1033 // A special alias for kPrincipalList that do not request reflow.
1034 static const ChildListID kNoReflowPrincipalList = mozilla::layout::kNoReflowPrincipalList;
1037 * Child frames are linked together in a doubly-linked list
1039 nsIFrame* GetNextSibling() const { return mNextSibling; }
1040 void SetNextSibling(nsIFrame* aNextSibling) {
1041 NS_ASSERTION(this != aNextSibling, "Creating a circular frame list, this is very bad.");
1042 if (mNextSibling && mNextSibling->GetPrevSibling() == this) {
1043 mNextSibling->mPrevSibling = nullptr;
1045 mNextSibling = aNextSibling;
1046 if (mNextSibling) {
1047 mNextSibling->mPrevSibling = this;
1051 nsIFrame* GetPrevSibling() const { return mPrevSibling; }
1054 * Builds the display lists for the content represented by this frame
1055 * and its descendants. The background+borders of this element must
1056 * be added first, before any other content.
1058 * This should only be called by methods in nsFrame. Instead of calling this
1059 * directly, call either BuildDisplayListForStackingContext or
1060 * BuildDisplayListForChild.
1062 * See nsDisplayList.h for more information about display lists.
1064 * @param aDirtyRect content outside this rectangle can be ignored; the
1065 * rectangle is in frame coordinates
1067 virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
1068 const nsRect& aDirtyRect,
1069 const nsDisplayListSet& aLists) {}
1071 * Displays the caret onto the given display list builder. The caret is
1072 * painted on top of the rest of the display list items.
1074 * @param aDirtyRect is the dirty rectangle that we're repainting.
1076 void DisplayCaret(nsDisplayListBuilder* aBuilder,
1077 const nsRect& aDirtyRect,
1078 nsDisplayList* aList);
1081 * Get the preferred caret color at the offset.
1083 * @param aOffset is offset of the content.
1085 virtual nscolor GetCaretColorAt(int32_t aOffset);
1088 bool IsThemed(nsITheme::Transparency* aTransparencyState = nullptr) const {
1089 return IsThemed(StyleDisplay(), aTransparencyState);
1091 bool IsThemed(const nsStyleDisplay* aDisp,
1092 nsITheme::Transparency* aTransparencyState = nullptr) const {
1093 nsIFrame* mutable_this = const_cast<nsIFrame*>(this);
1094 if (!aDisp->mAppearance)
1095 return false;
1096 nsPresContext* pc = PresContext();
1097 nsITheme *theme = pc->GetTheme();
1098 if(!theme ||
1099 !theme->ThemeSupportsWidget(pc, mutable_this, aDisp->mAppearance))
1100 return false;
1101 if (aTransparencyState) {
1102 *aTransparencyState =
1103 theme->GetWidgetTransparency(mutable_this, aDisp->mAppearance);
1105 return true;
1109 * Builds a display list for the content represented by this frame,
1110 * treating this frame as the root of a stacking context.
1111 * @param aDirtyRect content outside this rectangle can be ignored; the
1112 * rectangle is in frame coordinates
1114 void BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
1115 const nsRect& aDirtyRect,
1116 nsDisplayList* aList);
1118 enum {
1119 DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT = 0x01,
1120 DISPLAY_CHILD_FORCE_STACKING_CONTEXT = 0x02,
1121 DISPLAY_CHILD_INLINE = 0x04
1124 * Adjusts aDirtyRect for the child's offset, checks that the dirty rect
1125 * actually intersects the child (or its descendants), calls BuildDisplayList
1126 * on the child if necessary, and puts things in the right lists if the child
1127 * is positioned.
1129 * @param aFlags combination of DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT,
1130 * DISPLAY_CHILD_FORCE_STACKING_CONTEXT and DISPLAY_CHILD_INLINE
1132 void BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
1133 nsIFrame* aChild,
1134 const nsRect& aDirtyRect,
1135 const nsDisplayListSet& aLists,
1136 uint32_t aFlags = 0);
1139 * Does this frame need a view?
1141 virtual bool NeedsView() { return false; }
1144 * Returns true if this frame is transformed (e.g. has CSS or SVG transforms)
1145 * or if its parent is an SVG frame that has children-only transforms (e.g.
1146 * an SVG viewBox attribute).
1148 bool IsTransformed() const;
1151 * Returns true if the frame is translucent for the purposes of creating a
1152 * stacking context.
1154 bool HasOpacity() const
1156 return HasOpacityInternal(1.0f);
1159 * Returns true if the frame is translucent for display purposes.
1161 bool HasVisualOpacity() const
1163 // Treat an opacity value of 0.99 and above as opaque. This is an
1164 // optimization aimed at Web content which use opacity:0.99 as a hint for
1165 // creating a stacking context only.
1166 return HasOpacityInternal(0.99f);
1170 * Return true if this frame might be using a transform getter.
1172 virtual bool HasTransformGetter() const { return false; }
1175 * Returns true if this frame is an SVG frame that has SVG transforms applied
1176 * to it, or if its parent frame is an SVG frame that has children-only
1177 * transforms (e.g. an SVG viewBox attribute).
1178 * If aOwnTransforms is non-null and the frame has its own SVG transforms,
1179 * aOwnTransforms will be set to these transforms. If aFromParentTransforms
1180 * is non-null and the frame has an SVG parent with children-only transforms,
1181 * then aFromParentTransforms will be set to these transforms.
1183 virtual bool IsSVGTransformed(Matrix *aOwnTransforms = nullptr,
1184 Matrix *aFromParentTransforms = nullptr) const;
1187 * Returns whether this frame will attempt to preserve the 3d transforms of its
1188 * children. This requires transform-style: preserve-3d, as well as no clipping
1189 * or svg effects.
1191 bool Preserves3DChildren() const;
1194 * Returns whether this frame has a parent that Preserves3DChildren() and has
1195 * its own transform (or hidden backface) to be combined with the parent's
1196 * transform.
1198 bool Preserves3D() const;
1200 bool HasPerspective() const;
1202 bool ChildrenHavePerspective() const;
1204 // Calculate the overflow size of all child frames, taking preserve-3d into account
1205 void ComputePreserve3DChildrenOverflow(nsOverflowAreas& aOverflowAreas, const nsRect& aBounds);
1207 void RecomputePerspectiveChildrenOverflow(const nsStyleContext* aStartStyle, const nsRect* aBounds);
1210 * Returns the number of ancestors between this and the root of our frame tree
1212 uint32_t GetDepthInFrameTree() const;
1215 * Event handling of GUI events.
1217 * @param aEvent event structure describing the type of event and rge widget
1218 * where the event originated
1219 * The |point| member of this is in the coordinate system of the
1220 * view returned by GetOffsetFromView.
1221 * @param aEventStatus a return value indicating whether the event was handled
1222 * and whether default processing should be done
1224 * XXX From a frame's perspective it's unclear what the effect of the event status
1225 * is. Does it cause the event to continue propagating through the frame hierarchy
1226 * or is it just returned to the widgets?
1228 * @see WidgetGUIEvent
1229 * @see nsEventStatus
1231 virtual nsresult HandleEvent(nsPresContext* aPresContext,
1232 mozilla::WidgetGUIEvent* aEvent,
1233 nsEventStatus* aEventStatus) = 0;
1235 virtual nsresult GetContentForEvent(mozilla::WidgetEvent* aEvent,
1236 nsIContent** aContent) = 0;
1238 // This structure keeps track of the content node and offsets associated with
1239 // a point; there is a primary and a secondary offset associated with any
1240 // point. The primary and secondary offsets differ when the point is over a
1241 // non-text object. The primary offset is the expected position of the
1242 // cursor calculated from a point; the secondary offset, when it is different,
1243 // indicates that the point is in the boundaries of some selectable object.
1244 // Note that the primary offset can be after the secondary offset; for places
1245 // that need the beginning and end of the object, the StartOffset and
1246 // EndOffset helpers can be used.
1247 struct MOZ_STACK_CLASS ContentOffsets {
1248 ContentOffsets();
1249 ContentOffsets(const ContentOffsets&);
1250 ~ContentOffsets();
1251 nsCOMPtr<nsIContent> content;
1252 bool IsNull() { return !content; }
1253 int32_t offset;
1254 int32_t secondaryOffset;
1255 // Helpers for places that need the ends of the offsets and expect them in
1256 // numerical order, as opposed to wanting the primary and secondary offsets
1257 int32_t StartOffset() { return std::min(offset, secondaryOffset); }
1258 int32_t EndOffset() { return std::max(offset, secondaryOffset); }
1259 // This value indicates whether the associated content is before or after
1260 // the offset; the most visible use is to allow the caret to know which line
1261 // to display on.
1262 mozilla::CaretAssociationHint associate;
1264 enum {
1265 IGNORE_SELECTION_STYLE = 0x01,
1266 // Treat visibility:hidden frames as non-selectable
1267 SKIP_HIDDEN = 0x02
1270 * This function calculates the content offsets for selection relative to
1271 * a point. Note that this should generally only be callled on the event
1272 * frame associated with an event because this function does not account
1273 * for frame lists other than the primary one.
1274 * @param aPoint point relative to this frame
1276 ContentOffsets GetContentOffsetsFromPoint(nsPoint aPoint,
1277 uint32_t aFlags = 0);
1279 virtual ContentOffsets GetContentOffsetsFromPointExternal(nsPoint aPoint,
1280 uint32_t aFlags = 0)
1281 { return GetContentOffsetsFromPoint(aPoint, aFlags); }
1284 * Ensure that aImage gets notifed when the underlying image request loads
1285 * or animates.
1287 void AssociateImage(const nsStyleImage& aImage, nsPresContext* aPresContext);
1290 * This structure holds information about a cursor. mContainer represents a
1291 * loaded image that should be preferred. If it is not possible to use it, or
1292 * if it is null, mCursor should be used.
1294 struct MOZ_STACK_CLASS Cursor {
1295 nsCOMPtr<imgIContainer> mContainer;
1296 int32_t mCursor;
1297 bool mHaveHotspot;
1298 float mHotspotX, mHotspotY;
1301 * Get the cursor for a given frame.
1303 virtual nsresult GetCursor(const nsPoint& aPoint,
1304 Cursor& aCursor) = 0;
1307 * Get a point (in the frame's coordinate space) given an offset into
1308 * the content. This point should be on the baseline of text with
1309 * the correct horizontal offset
1311 virtual nsresult GetPointFromOffset(int32_t inOffset,
1312 nsPoint* outPoint) = 0;
1315 * Get the child frame of this frame which contains the given
1316 * content offset. outChildFrame may be this frame, or nullptr on return.
1317 * outContentOffset returns the content offset relative to the start
1318 * of the returned node. You can also pass a hint which tells the method
1319 * to stick to the end of the first found frame or the beginning of the
1320 * next in case the offset falls on a boundary.
1322 virtual nsresult GetChildFrameContainingOffset(int32_t inContentOffset,
1323 bool inHint,//false stick left
1324 int32_t* outFrameContentOffset,
1325 nsIFrame** outChildFrame) = 0;
1328 * Get the current frame-state value for this frame. aResult is
1329 * filled in with the state bits.
1331 nsFrameState GetStateBits() const { return mState; }
1334 * Update the current frame-state value for this frame.
1336 void AddStateBits(nsFrameState aBits) { mState |= aBits; }
1337 void RemoveStateBits(nsFrameState aBits) { mState &= ~aBits; }
1340 * Checks if the current frame-state includes all of the listed bits
1342 bool HasAllStateBits(nsFrameState aBits) const
1344 return (mState & aBits) == aBits;
1348 * Checks if the current frame-state includes any of the listed bits
1350 bool HasAnyStateBits(nsFrameState aBits) const
1352 return mState & aBits;
1356 * This call is invoked on the primary frame for a character data content
1357 * node, when it is changed in the content tree.
1359 virtual nsresult CharacterDataChanged(CharacterDataChangeInfo* aInfo) = 0;
1362 * This call is invoked when the value of a content objects's attribute
1363 * is changed.
1364 * The first frame that maps that content is asked to deal
1365 * with the change by doing whatever is appropriate.
1367 * @param aNameSpaceID the namespace of the attribute
1368 * @param aAttribute the atom name of the attribute
1369 * @param aModType Whether or not the attribute was added, changed, or removed.
1370 * The constants are defined in nsIDOMMutationEvent.h.
1372 virtual nsresult AttributeChanged(int32_t aNameSpaceID,
1373 nsIAtom* aAttribute,
1374 int32_t aModType) = 0;
1377 * When the content states of a content object change, this method is invoked
1378 * on the primary frame of that content object.
1380 * @param aStates the changed states
1382 virtual void ContentStatesChanged(mozilla::EventStates aStates);
1385 * Return how your frame can be split.
1387 virtual nsSplittableType GetSplittableType() const = 0;
1390 * Continuation member functions
1392 virtual nsIFrame* GetPrevContinuation() const = 0;
1393 virtual void SetPrevContinuation(nsIFrame*) = 0;
1394 virtual nsIFrame* GetNextContinuation() const = 0;
1395 virtual void SetNextContinuation(nsIFrame*) = 0;
1396 virtual nsIFrame* FirstContinuation() const {
1397 return const_cast<nsIFrame*>(this);
1399 virtual nsIFrame* LastContinuation() const {
1400 return const_cast<nsIFrame*>(this);
1404 * GetTailContinuation gets the last non-overflow-container continuation
1405 * in the continuation chain, i.e. where the next sibling element
1406 * should attach).
1408 nsIFrame* GetTailContinuation();
1411 * Flow member functions
1413 virtual nsIFrame* GetPrevInFlowVirtual() const = 0;
1414 nsIFrame* GetPrevInFlow() const { return GetPrevInFlowVirtual(); }
1415 virtual void SetPrevInFlow(nsIFrame*) = 0;
1417 virtual nsIFrame* GetNextInFlowVirtual() const = 0;
1418 nsIFrame* GetNextInFlow() const { return GetNextInFlowVirtual(); }
1419 virtual void SetNextInFlow(nsIFrame*) = 0;
1422 * Return the first frame in our current flow.
1424 virtual nsIFrame* FirstInFlow() const {
1425 return const_cast<nsIFrame*>(this);
1429 * Return the last frame in our current flow.
1431 virtual nsIFrame* LastInFlow() const {
1432 return const_cast<nsIFrame*>(this);
1436 * Note: "width" in the names and comments on the following methods
1437 * means inline-size, which could be height in vertical layout
1441 * Mark any stored intrinsic width information as dirty (requiring
1442 * re-calculation). Note that this should generally not be called
1443 * directly; nsPresShell::FrameNeedsReflow will call it instead.
1445 virtual void MarkIntrinsicISizesDirty() = 0;
1448 * Get the min-content intrinsic inline size of the frame. This must be
1449 * less than or equal to the max-content intrinsic inline size.
1451 * This is *not* affected by the CSS 'min-width', 'width', and
1452 * 'max-width' properties on this frame, but it is affected by the
1453 * values of those properties on this frame's descendants. (It may be
1454 * called during computation of the values of those properties, so it
1455 * cannot depend on any values in the nsStylePosition for this frame.)
1457 * The value returned should **NOT** include the space required for
1458 * padding and border.
1460 * Note that many frames will cache the result of this function call
1461 * unless MarkIntrinsicISizesDirty is called.
1463 * It is not acceptable for a frame to mark itself dirty when this
1464 * method is called.
1466 * This method must not return a negative value.
1468 virtual nscoord GetMinISize(nsRenderingContext *aRenderingContext) = 0;
1471 * Get the max-content intrinsic inline size of the frame. This must be
1472 * greater than or equal to the min-content intrinsic inline size.
1474 * Otherwise, all the comments for |GetMinISize| above apply.
1476 virtual nscoord GetPrefISize(nsRenderingContext *aRenderingContext) = 0;
1479 * |InlineIntrinsicISize| represents the intrinsic width information
1480 * in inline layout. Code that determines the intrinsic width of a
1481 * region of inline layout accumulates the result into this structure.
1482 * This pattern is needed because we need to maintain state
1483 * information about whitespace (for both collapsing and trimming).
1485 struct InlineIntrinsicISizeData {
1486 InlineIntrinsicISizeData()
1487 : line(nullptr)
1488 , lineContainer(nullptr)
1489 , prevLines(0)
1490 , currentLine(0)
1491 , skipWhitespace(true)
1492 , trailingWhitespace(0)
1495 // The line. This may be null if the inlines are not associated with
1496 // a block or if we just don't know the line.
1497 const nsLineList_iterator* line;
1499 // The line container.
1500 nsIFrame* lineContainer;
1502 // The maximum intrinsic width for all previous lines.
1503 nscoord prevLines;
1505 // The maximum intrinsic width for the current line. At a line
1506 // break (mandatory for preferred width; allowed for minimum width),
1507 // the caller should call |Break()|.
1508 nscoord currentLine;
1510 // True if initial collapsable whitespace should be skipped. This
1511 // should be true at the beginning of a block, after hard breaks
1512 // and when the last text ended with whitespace.
1513 bool skipWhitespace;
1515 // This contains the width of the trimmable whitespace at the end of
1516 // |currentLine|; it is zero if there is no such whitespace.
1517 nscoord trailingWhitespace;
1519 // Floats encountered in the lines.
1520 class FloatInfo {
1521 public:
1522 FloatInfo(const nsIFrame* aFrame, nscoord aWidth)
1523 : mFrame(aFrame), mWidth(aWidth)
1525 const nsIFrame* Frame() const { return mFrame; }
1526 nscoord Width() const { return mWidth; }
1528 private:
1529 const nsIFrame* mFrame;
1530 nscoord mWidth;
1533 nsTArray<FloatInfo> floats;
1536 struct InlineMinISizeData : public InlineIntrinsicISizeData {
1537 InlineMinISizeData()
1538 : trailingTextFrame(nullptr)
1539 , atStartOfLine(true)
1542 // We need to distinguish forced and optional breaks for cases where the
1543 // current line total is negative. When it is, we need to ignore
1544 // optional breaks to prevent min-width from ending up bigger than
1545 // pref-width.
1546 void ForceBreak(nsRenderingContext *aRenderingContext);
1548 // If the break here is actually taken, aHyphenWidth must be added to the
1549 // width of the current line.
1550 void OptionallyBreak(nsRenderingContext *aRenderingContext,
1551 nscoord aHyphenWidth = 0);
1553 // The last text frame processed so far in the current line, when
1554 // the last characters in that text frame are relevant for line
1555 // break opportunities.
1556 nsIFrame *trailingTextFrame;
1558 // Whether we're currently at the start of the line. If we are, we
1559 // can't break (for example, between the text-indent and the first
1560 // word).
1561 bool atStartOfLine;
1564 struct InlinePrefISizeData : public InlineIntrinsicISizeData {
1565 void ForceBreak(nsRenderingContext *aRenderingContext);
1569 * Add the intrinsic minimum width of a frame in a way suitable for
1570 * use in inline layout to an |InlineIntrinsicISizeData| object that
1571 * represents the intrinsic width information of all the previous
1572 * frames in the inline layout region.
1574 * All *allowed* breakpoints within the frame determine what counts as
1575 * a line for the |InlineIntrinsicISizeData|. This means that
1576 * |aData->trailingWhitespace| will always be zero (unlike for
1577 * AddInlinePrefISize).
1579 * All the comments for |GetMinISize| apply, except that this function
1580 * is responsible for adding padding, border, and margin and for
1581 * considering the effects of 'width', 'min-width', and 'max-width'.
1583 * This may be called on any frame. Frames that do not participate in
1584 * line breaking can inherit the default implementation on nsFrame,
1585 * which calls |GetMinISize|.
1587 virtual void
1588 AddInlineMinISize(nsRenderingContext *aRenderingContext,
1589 InlineMinISizeData *aData) = 0;
1592 * Add the intrinsic preferred width of a frame in a way suitable for
1593 * use in inline layout to an |InlineIntrinsicISizeData| object that
1594 * represents the intrinsic width information of all the previous
1595 * frames in the inline layout region.
1597 * All the comments for |AddInlineMinISize| and |GetPrefISize| apply,
1598 * except that this fills in an |InlineIntrinsicISizeData| structure
1599 * based on using all *mandatory* breakpoints within the frame.
1601 virtual void
1602 AddInlinePrefISize(nsRenderingContext *aRenderingContext,
1603 InlinePrefISizeData *aData) = 0;
1606 * Return the horizontal components of padding, border, and margin
1607 * that contribute to the intrinsic width that applies to the parent.
1609 struct IntrinsicISizeOffsetData {
1610 nscoord hPadding, hBorder, hMargin;
1611 float hPctPadding, hPctMargin;
1613 IntrinsicISizeOffsetData()
1614 : hPadding(0), hBorder(0), hMargin(0)
1615 , hPctPadding(0.0f), hPctMargin(0.0f)
1618 virtual IntrinsicISizeOffsetData
1619 IntrinsicISizeOffsets(nsRenderingContext* aRenderingContext) = 0;
1621 virtual mozilla::IntrinsicSize GetIntrinsicSize() = 0;
1624 * Get the intrinsic ratio of this element, or nsSize(0,0) if it has
1625 * no intrinsic ratio. The intrinsic ratio is the ratio of the
1626 * height/width of a box with an intrinsic size or the intrinsic
1627 * aspect ratio of a scalable vector image without an intrinsic size.
1629 * Either one of the sides may be zero, indicating a zero or infinite
1630 * ratio.
1632 virtual nsSize GetIntrinsicRatio() = 0;
1635 * Bit-flags to pass to ComputeSize in |aFlags| parameter.
1637 enum {
1638 /* Set if the frame is in a context where non-replaced blocks should
1639 * shrink-wrap (e.g., it's floating, absolutely positioned, or
1640 * inline-block). */
1641 eShrinkWrap = 1 << 0,
1642 /* Set if we'd like to compute our 'auto' height, regardless of our actual
1643 * computed value of 'height'. (e.g. to get an intrinsic height for flex
1644 * items with "min-height: auto" to use during flexbox layout.) */
1645 eUseAutoHeight = 1 << 1
1649 * Compute the size that a frame will occupy. Called while
1650 * constructing the nsHTMLReflowState to be used to Reflow the frame,
1651 * in order to fill its mComputedWidth and mComputedHeight member
1652 * variables.
1654 * The |height| member of the return value may be
1655 * NS_UNCONSTRAINEDSIZE, but the |width| member must not be.
1657 * Note that the reason that border and padding need to be passed
1658 * separately is so that the 'box-sizing' property can be handled.
1659 * Thus aMargin includes absolute positioning offsets as well.
1661 * @param aWritingMode The writing mode to use for the returned size
1662 * (need not match this frame's writing mode).
1663 * This is also the writing mode of the passed-in
1664 * LogicalSize parameters.
1665 * @param aCBSize The size of the element's containing block. (Well,
1666 * the |height| component isn't really.)
1667 * @param aAvailableWidth The available width for 'auto' widths.
1668 * This is usually the same as aCBSize.width,
1669 * but differs in cases such as block
1670 * formatting context roots next to floats, or
1671 * in some cases of float reflow in quirks
1672 * mode.
1673 * @param aMargin The sum of the vertical / horizontal margins
1674 * ***AND*** absolute positioning offsets (top, right,
1675 * bottom, left) of the frame, including actual values
1676 * resulting from percentages and from the
1677 * "hypothetical box" for absolute positioning, but
1678 * not including actual values resulting from 'auto'
1679 * margins or ignored 'auto' values in absolute
1680 * positioning.
1681 * @param aBorder The sum of the vertical / horizontal border widths
1682 * of the frame.
1683 * @param aPadding The sum of the vertical / horizontal margins of
1684 * the frame, including actual values resulting from
1685 * percentages.
1686 * @param aFlags Flags to further customize behavior (definitions above).
1688 virtual mozilla::LogicalSize
1689 ComputeSize(nsRenderingContext *aRenderingContext,
1690 mozilla::WritingMode aWritingMode,
1691 const mozilla::LogicalSize& aCBSize,
1692 nscoord aAvailableISize,
1693 const mozilla::LogicalSize& aMargin,
1694 const mozilla::LogicalSize& aBorder,
1695 const mozilla::LogicalSize& aPadding,
1696 uint32_t aFlags) = 0;
1699 * Compute a tight bounding rectangle for the frame. This is a rectangle
1700 * that encloses the pixels that are actually drawn. We're allowed to be
1701 * conservative and currently we don't try very hard. The rectangle is
1702 * in appunits and relative to the origin of this frame.
1704 * This probably only needs to include frame bounds, glyph bounds, and
1705 * text decorations, but today it sometimes includes other things that
1706 * contribute to visual overflow.
1708 * @param aContext a rendering context that can be used if we need
1709 * to do measurement
1711 virtual nsRect ComputeTightBounds(gfxContext* aContext) const;
1714 * This function is similar to GetPrefISize and ComputeTightBounds: it
1715 * computes the left and right coordinates of a preferred tight bounding
1716 * rectangle for the frame. This is a rectangle that would enclose the pixels
1717 * that are drawn if we lay out the element without taking any optional line
1718 * breaks. The rectangle is in appunits and relative to the origin of this
1719 * frame. Currently, this function is only implemented for nsBlockFrame and
1720 * nsTextFrame and is used to determine intrinsic widths of MathML token
1721 * elements.
1723 * @param aContext a rendering context that can be used if we need
1724 * to do measurement
1725 * @param aX computed left coordinate of the tight bounding rectangle
1726 * @param aXMost computed intrinsic width of the tight bounding rectangle
1729 virtual nsresult GetPrefWidthTightBounds(nsRenderingContext* aContext,
1730 nscoord* aX,
1731 nscoord* aXMost);
1734 * Pre-reflow hook. Before a frame is reflowed this method will be called.
1735 * This call will always be invoked at least once before a subsequent Reflow
1736 * and DidReflow call. It may be called more than once, In general you will
1737 * receive on WillReflow notification before each Reflow request.
1739 * XXX Is this really the semantics we want? Because we have the NS_FRAME_IN_REFLOW
1740 * bit we can ensure we don't call it more than once...
1742 virtual void WillReflow(nsPresContext* aPresContext) = 0;
1745 * The frame is given an available size and asked for its desired
1746 * size. This is the frame's opportunity to reflow its children.
1748 * If the frame has the NS_FRAME_IS_DIRTY bit set then it is
1749 * responsible for completely reflowing itself and all of its
1750 * descendants.
1752 * Otherwise, if the frame has the NS_FRAME_HAS_DIRTY_CHILDREN bit
1753 * set, then it is responsible for reflowing at least those
1754 * children that have NS_FRAME_HAS_DIRTY_CHILDREN or NS_FRAME_IS_DIRTY
1755 * set.
1757 * If a difference in available size from the previous reflow causes
1758 * the frame's size to change, it should reflow descendants as needed.
1760 * @param aReflowMetrics <i>out</i> parameter where you should return the
1761 * desired size and ascent/descent info. You should include any
1762 * space you want for border/padding in the desired size you return.
1764 * It's okay to return a desired size that exceeds the avail
1765 * size if that's the smallest you can be, i.e. it's your
1766 * minimum size.
1768 * For an incremental reflow you are responsible for invalidating
1769 * any area within your frame that needs repainting (including
1770 * borders). If your new desired size is different than your current
1771 * size, then your parent frame is responsible for making sure that
1772 * the difference between the two rects is repainted
1774 * @param aReflowState information about your reflow including the reason
1775 * for the reflow and the available space in which to lay out. Each
1776 * dimension of the available space can either be constrained or
1777 * unconstrained (a value of NS_UNCONSTRAINEDSIZE).
1779 * Note that the available space can be negative. In this case you
1780 * still must return an accurate desired size. If you're a container
1781 * you must <b>always</b> reflow at least one frame regardless of the
1782 * available space
1784 * @param aStatus a return value indicating whether the frame is complete
1785 * and whether the next-in-flow is dirty and needs to be reflowed
1787 virtual void Reflow(nsPresContext* aPresContext,
1788 nsHTMLReflowMetrics& aReflowMetrics,
1789 const nsHTMLReflowState& aReflowState,
1790 nsReflowStatus& aStatus) = 0;
1793 * Post-reflow hook. After a frame is reflowed this method will be called
1794 * informing the frame that this reflow process is complete, and telling the
1795 * frame the status returned by the Reflow member function.
1797 * This call may be invoked many times, while NS_FRAME_IN_REFLOW is set, before
1798 * it is finally called once with a NS_FRAME_REFLOW_COMPLETE value. When called
1799 * with a NS_FRAME_REFLOW_COMPLETE value the NS_FRAME_IN_REFLOW bit in the
1800 * frame state will be cleared.
1802 * XXX This doesn't make sense. If the frame is reflowed but not complete, then
1803 * the status should be NS_FRAME_NOT_COMPLETE and not NS_FRAME_COMPLETE
1804 * XXX Don't we want the semantics to dictate that we only call this once for
1805 * a given reflow?
1807 virtual void DidReflow(nsPresContext* aPresContext,
1808 const nsHTMLReflowState* aReflowState,
1809 nsDidReflowStatus aStatus) = 0;
1811 // XXX Maybe these three should be a separate interface?
1814 * Updates the overflow areas of the frame. This can be called if an
1815 * overflow area of the frame's children has changed without reflowing.
1816 * @return true if either of the overflow areas for this frame have changed.
1818 virtual bool UpdateOverflow() = 0;
1821 * Helper method used by block reflow to identify runs of text so
1822 * that proper word-breaking can be done.
1824 * @return
1825 * true if we can continue a "text run" through the frame. A
1826 * text run is text that should be treated contiguously for line
1827 * and word breaking.
1829 virtual bool CanContinueTextRun() const = 0;
1832 * Append the rendered text to the passed-in string.
1833 * The appended text will often not contain all the whitespace from source,
1834 * depending on whether the CSS rule "white-space: pre" is active for this frame.
1835 * if aStartOffset + aLength goes past end, or if aLength is not specified
1836 * then use the text up to the string's end.
1837 * Call this on the primary frame for a text node.
1838 * @param aAppendToString String to append text to, or null if text should not be returned
1839 * @param aSkipChars if aSkipIter is non-null, this must also be non-null.
1840 * This gets used as backing data for the iterator so it should outlive the iterator.
1841 * @param aSkipIter Where to fill in the gfxSkipCharsIterator info, or null if not needed by caller
1842 * @param aStartOffset Skipped (rendered text) start offset
1843 * @param aSkippedMaxLength Maximum number of characters to return
1844 * The iterator can be used to map content offsets to offsets in the returned string, or vice versa.
1846 virtual nsresult GetRenderedText(nsAString* aAppendToString = nullptr,
1847 gfxSkipChars* aSkipChars = nullptr,
1848 gfxSkipCharsIterator* aSkipIter = nullptr,
1849 uint32_t aSkippedStartOffset = 0,
1850 uint32_t aSkippedMaxLength = UINT32_MAX)
1851 { return NS_ERROR_NOT_IMPLEMENTED; }
1854 * Returns true if the frame contains any non-collapsed characters.
1855 * This method is only available for text frames, and it will return false
1856 * for all other frame types.
1858 virtual bool HasAnyNoncollapsedCharacters()
1859 { return false; }
1862 * Accessor functions to get/set the associated view object
1864 * GetView returns non-null if and only if |HasView| returns true.
1866 bool HasView() const { return !!(mState & NS_FRAME_HAS_VIEW); }
1867 nsView* GetView() const;
1868 virtual nsView* GetViewExternal() const;
1869 nsresult SetView(nsView* aView);
1872 * Find the closest view (on |this| or an ancestor).
1873 * If aOffset is non-null, it will be set to the offset of |this|
1874 * from the returned view.
1876 nsView* GetClosestView(nsPoint* aOffset = nullptr) const;
1879 * Find the closest ancestor (excluding |this| !) that has a view
1881 nsIFrame* GetAncestorWithView() const;
1882 virtual nsIFrame* GetAncestorWithViewExternal() const;
1885 * Get the offset between the coordinate systems of |this| and aOther.
1886 * Adding the return value to a point in the coordinate system of |this|
1887 * will transform the point to the coordinate system of aOther.
1889 * aOther must be non-null.
1891 * This function is fastest when aOther is an ancestor of |this|.
1893 * This function _DOES NOT_ work across document boundaries.
1894 * Use this function only when |this| and aOther are in the same document.
1896 * NOTE: this actually returns the offset from aOther to |this|, but
1897 * that offset is added to transform _coordinates_ from |this| to
1898 * aOther.
1900 nsPoint GetOffsetTo(const nsIFrame* aOther) const;
1901 virtual nsPoint GetOffsetToExternal(const nsIFrame* aOther) const;
1904 * Get the offset between the coordinate systems of |this| and aOther
1905 * expressed in appunits per dev pixel of |this|' document. Adding the return
1906 * value to a point that is relative to the origin of |this| will make the
1907 * point relative to the origin of aOther but in the appunits per dev pixel
1908 * ratio of |this|.
1910 * aOther must be non-null.
1912 * This function is fastest when aOther is an ancestor of |this|.
1914 * This function works across document boundaries.
1916 * Because this function may cross document boundaries that have different
1917 * app units per dev pixel ratios it needs to be used very carefully.
1919 * NOTE: this actually returns the offset from aOther to |this|, but
1920 * that offset is added to transform _coordinates_ from |this| to
1921 * aOther.
1923 nsPoint GetOffsetToCrossDoc(const nsIFrame* aOther) const;
1926 * Like GetOffsetToCrossDoc, but the caller can specify which appunits
1927 * to return the result in.
1929 nsPoint GetOffsetToCrossDoc(const nsIFrame* aOther, const int32_t aAPD) const;
1932 * Get the screen rect of the frame in pixels.
1933 * @return the pixel rect of the frame in screen coordinates.
1935 nsIntRect GetScreenRect() const;
1936 virtual nsIntRect GetScreenRectExternal() const;
1939 * Get the screen rect of the frame in app units.
1940 * @return the app unit rect of the frame in screen coordinates.
1942 nsRect GetScreenRectInAppUnits() const;
1943 virtual nsRect GetScreenRectInAppUnitsExternal() const;
1946 * Returns the offset from this frame to the closest geometric parent that
1947 * has a view. Also returns the containing view or null in case of error
1949 void GetOffsetFromView(nsPoint& aOffset, nsView** aView) const;
1952 * Returns the nearest widget containing this frame. If this frame has a
1953 * view and the view has a widget, then this frame's widget is
1954 * returned, otherwise this frame's geometric parent is checked
1955 * recursively upwards.
1956 * XXX virtual because gfx callers use it! (themes)
1958 virtual nsIWidget* GetNearestWidget() const;
1961 * Same as GetNearestWidget() above but uses an outparam to return the offset
1962 * of this frame to the returned widget expressed in appunits of |this| (the
1963 * widget might be in a different document with a different zoom).
1965 virtual nsIWidget* GetNearestWidget(nsPoint& aOffset) const;
1968 * Get the "type" of the frame. May return nullptr.
1970 * @see nsGkAtoms
1972 virtual nsIAtom* GetType() const = 0;
1975 * Returns a transformation matrix that converts points in this frame's
1976 * coordinate space to points in some ancestor frame's coordinate space.
1977 * The frame decides which ancestor it will use as a reference point.
1978 * If this frame has no ancestor, aOutAncestor will be set to null.
1980 * @param aStopAtAncestor don't look further than aStopAtAncestor. If null,
1981 * all ancestors (including across documents) will be traversed.
1982 * @param aOutAncestor [out] The ancestor frame the frame has chosen. If
1983 * this frame has no ancestor, *aOutAncestor will be set to null. If
1984 * this frame is not a root frame, then *aOutAncestor will be in the same
1985 * document as this frame. If this frame IsTransformed(), then *aOutAncestor
1986 * will be the parent frame (if not preserve-3d) or the nearest non-transformed
1987 * ancestor (if preserve-3d).
1988 * @return A Matrix4x4 that converts points in this frame's coordinate space
1989 * into points in aOutAncestor's coordinate space.
1991 Matrix4x4 GetTransformMatrix(const nsIFrame* aStopAtAncestor,
1992 nsIFrame **aOutAncestor);
1995 * Bit-flags to pass to IsFrameOfType()
1997 enum {
1998 eMathML = 1 << 0,
1999 eSVG = 1 << 1,
2000 eSVGForeignObject = 1 << 2,
2001 eSVGContainer = 1 << 3,
2002 eSVGGeometry = 1 << 4,
2003 eSVGPaintServer = 1 << 5,
2004 eBidiInlineContainer = 1 << 6,
2005 // the frame is for a replaced element, such as an image
2006 eReplaced = 1 << 7,
2007 // Frame that contains a block but looks like a replaced element
2008 // from the outside
2009 eReplacedContainsBlock = 1 << 8,
2010 // A frame that participates in inline reflow, i.e., one that
2011 // requires nsHTMLReflowState::mLineLayout.
2012 eLineParticipant = 1 << 9,
2013 eXULBox = 1 << 10,
2014 eCanContainOverflowContainers = 1 << 11,
2015 eBlockFrame = 1 << 12,
2016 eTablePart = 1 << 13,
2017 // If this bit is set, the frame doesn't allow ignorable whitespace as
2018 // children. For example, the whitespace between <table>\n<tr>\n<td>
2019 // will be excluded during the construction of children.
2020 eExcludesIgnorableWhitespace = 1 << 14,
2021 eSupportsCSSTransforms = 1 << 15,
2023 // These are to allow nsFrame::Init to assert that IsFrameOfType
2024 // implementations all call the base class method. They are only
2025 // meaningful in DEBUG builds.
2026 eDEBUGAllFrames = 1 << 30,
2027 eDEBUGNoFrames = 1 << 31
2031 * API for doing a quick check if a frame is of a given
2032 * type. Returns true if the frame matches ALL flags passed in.
2034 * Implementations should always override with inline virtual
2035 * functions that call the base class's IsFrameOfType method.
2037 virtual bool IsFrameOfType(uint32_t aFlags) const
2039 #ifdef DEBUG
2040 return !(aFlags & ~(nsIFrame::eDEBUGAllFrames | nsIFrame::eSupportsCSSTransforms));
2041 #else
2042 return !(aFlags & ~nsIFrame::eSupportsCSSTransforms);
2043 #endif
2047 * Returns true if the frame is a block wrapper.
2049 bool IsBlockWrapper() const;
2052 * Get this frame's CSS containing block.
2054 * The algorithm is defined in
2055 * http://www.w3.org/TR/CSS2/visudet.html#containing-block-details.
2057 * NOTE: This is guaranteed to return a non-null pointer when invoked on any
2058 * frame other than the root frame.
2060 nsIFrame* GetContainingBlock() const;
2063 * Is this frame a containing block for floating elements?
2064 * Note that very few frames are, so default to false.
2066 virtual bool IsFloatContainingBlock() const { return false; }
2069 * Is this a leaf frame? Frames that want the frame constructor to be able
2070 * to construct kids for them should return false, all others should return
2071 * true. Note that returning true here does not mean that the frame _can't_
2072 * have kids. It could still have kids created via
2073 * nsIAnonymousContentCreator. Returning true indicates that "normal"
2074 * (non-anonymous, XBL-bound, CSS generated content, etc) children should not
2075 * be constructed.
2077 virtual bool IsLeaf() const;
2080 * Marks all display items created by this frame as needing a repaint,
2081 * and calls SchedulePaint() if requested and one is not already pending.
2083 * This includes all display items created by this frame, including
2084 * container types.
2086 * @param aDisplayItemKey If specified, only issues an invalidate
2087 * if this frame painted a display item of that type during the
2088 * previous paint. SVG rendering observers are always notified.
2090 virtual void InvalidateFrame(uint32_t aDisplayItemKey = 0);
2093 * Same as InvalidateFrame(), but only mark a fixed rect as needing
2094 * repainting.
2096 * @param aRect The rect to invalidate, relative to the TopLeft of the
2097 * frame's border box.
2098 * @param aDisplayItemKey If specified, only issues an invalidate
2099 * if this frame painted a display item of that type during the
2100 * previous paint. SVG rendering observers are always notified.
2102 virtual void InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey = 0);
2105 * Calls InvalidateFrame() on all frames descendant frames (including
2106 * this one).
2108 * This function doesn't walk through placeholder frames to invalidate
2109 * the out-of-flow frames.
2111 * @param aDisplayItemKey If specified, only issues an invalidate
2112 * if this frame painted a display item of that type during the
2113 * previous paint. SVG rendering observers are always notified.
2115 void InvalidateFrameSubtree(uint32_t aDisplayItemKey = 0);
2118 * Called when a frame is about to be removed and needs to be invalidated.
2119 * Normally does nothing since DLBI handles removed frames.
2121 virtual void InvalidateFrameForRemoval() {}
2124 * When HasUserData(frame->LayerIsPrerenderedDataKey()), then the
2125 * entire overflow area of this frame has been rendered in its
2126 * layer(s).
2128 static void* LayerIsPrerenderedDataKey() {
2129 return &sLayerIsPrerenderedDataKey;
2131 static uint8_t sLayerIsPrerenderedDataKey;
2134 * Try to update this frame's transform without invalidating any
2135 * content. Return true iff successful. If unsuccessful, the
2136 * caller is responsible for scheduling an invalidating paint.
2138 * If the result is true, aLayerResult will be filled in with the
2139 * transform layer for the frame.
2141 bool TryUpdateTransformOnly(Layer** aLayerResult);
2144 * Checks if a frame has had InvalidateFrame() called on it since the
2145 * last paint.
2147 * If true, then the invalid rect is returned in aRect, with an
2148 * empty rect meaning all pixels drawn by this frame should be
2149 * invalidated.
2150 * If false, aRect is left unchanged.
2152 bool IsInvalid(nsRect& aRect);
2155 * Check if any frame within the frame subtree (including this frame)
2156 * returns true for IsInvalid().
2158 bool HasInvalidFrameInSubtree()
2160 return HasAnyStateBits(NS_FRAME_NEEDS_PAINT | NS_FRAME_DESCENDANT_NEEDS_PAINT);
2164 * Removes the invalid state from the current frame and all
2165 * descendant frames.
2167 void ClearInvalidationStateBits();
2170 * Ensures that the refresh driver is running, and schedules a view
2171 * manager flush on the next tick.
2173 * The view manager flush will update the layer tree, repaint any
2174 * invalid areas in the layer tree and schedule a layer tree
2175 * composite operation to display the layer tree.
2177 * In general it is not necessary for frames to call this when they change.
2178 * For example, changes that result in a reflow will have this called for
2179 * them by PresContext::DoReflow when the reflow begins. Style changes that
2180 * do not trigger a reflow should have this called for them by
2181 * DoApplyRenderingChangeToTree.
2183 * @param aType PAINT_COMPOSITE_ONLY : No changes have been made
2184 * that require a layer tree update, so only schedule a layer
2185 * tree composite.
2186 * PAINT_DELAYED_COMPRESS : Schedule a paint to be executed after a delay, and
2187 * put FrameLayerBuilder in 'compressed' mode that avoids short cut optimizations.
2189 enum PaintType {
2190 PAINT_DEFAULT = 0,
2191 PAINT_COMPOSITE_ONLY,
2192 PAINT_DELAYED_COMPRESS
2194 void SchedulePaint(PaintType aType = PAINT_DEFAULT);
2197 * Checks if the layer tree includes a dedicated layer for this
2198 * frame/display item key pair, and invalidates at least aDamageRect
2199 * area within that layer.
2201 * If no layer is found, calls InvalidateFrame() instead.
2203 * @param aDamageRect Area of the layer to invalidate.
2204 * @param aDisplayItemKey Display item type.
2205 * @param aFlags UPDATE_IS_ASYNC : Will skip the invalidation
2206 * if the found layer is being composited by a remote
2207 * compositor.
2208 * @return Layer, if found, nullptr otherwise.
2210 enum {
2211 UPDATE_IS_ASYNC = 1 << 0
2213 Layer* InvalidateLayer(uint32_t aDisplayItemKey, const nsIntRect* aDamageRect = nullptr, uint32_t aFlags = 0);
2216 * Returns a rect that encompasses everything that might be painted by
2217 * this frame. This includes this frame, all its descendent frames, this
2218 * frame's outline, and descentant frames' outline, but does not include
2219 * areas clipped out by the CSS "overflow" and "clip" properties.
2221 * HasOverflowRects() (below) will return true when this overflow
2222 * rect has been explicitly set, even if it matches mRect.
2223 * XXX Note: because of a space optimization using the formula above,
2224 * during reflow this function does not give accurate data if
2225 * FinishAndStoreOverflow has been called but mRect hasn't yet been
2226 * updated yet. FIXME: This actually isn't true, but it should be.
2228 * The visual overflow rect should NEVER be used for things that
2229 * affect layout. The scrollable overflow rect is permitted to affect
2230 * layout.
2232 * @return the rect relative to this frame's origin, but after
2233 * CSS transforms have been applied (i.e. not really this frame's coordinate
2234 * system, and may not contain the frame's border-box, e.g. if there
2235 * is a CSS transform scaling it down)
2237 nsRect GetVisualOverflowRect() const {
2238 return GetOverflowRect(eVisualOverflow);
2242 * Returns a rect that encompasses the area of this frame that the
2243 * user should be able to scroll to reach. This is similar to
2244 * GetVisualOverflowRect, but does not include outline or shadows, and
2245 * may in the future include more margins than visual overflow does.
2246 * It does not include areas clipped out by the CSS "overflow" and
2247 * "clip" properties.
2249 * HasOverflowRects() (below) will return true when this overflow
2250 * rect has been explicitly set, even if it matches mRect.
2251 * XXX Note: because of a space optimization using the formula above,
2252 * during reflow this function does not give accurate data if
2253 * FinishAndStoreOverflow has been called but mRect hasn't yet been
2254 * updated yet.
2256 * @return the rect relative to this frame's origin, but after
2257 * CSS transforms have been applied (i.e. not really this frame's coordinate
2258 * system, and may not contain the frame's border-box, e.g. if there
2259 * is a CSS transform scaling it down)
2261 nsRect GetScrollableOverflowRect() const {
2262 return GetOverflowRect(eScrollableOverflow);
2265 nsRect GetOverflowRect(nsOverflowType aType) const;
2267 nsOverflowAreas GetOverflowAreas() const;
2270 * Same as GetOverflowAreas, except in this frame's coordinate
2271 * system (before transforms are applied).
2273 * @return the overflow areas relative to this frame, before any CSS transforms have
2274 * been applied, i.e. in this frame's coordinate system
2276 nsOverflowAreas GetOverflowAreasRelativeToSelf() const;
2279 * Same as GetScrollableOverflowRect, except relative to the parent
2280 * frame.
2282 * @return the rect relative to the parent frame, in the parent frame's
2283 * coordinate system
2285 nsRect GetScrollableOverflowRectRelativeToParent() const;
2288 * Same as GetScrollableOverflowRect, except in this frame's coordinate
2289 * system (before transforms are applied).
2291 * @return the rect relative to this frame, before any CSS transforms have
2292 * been applied, i.e. in this frame's coordinate system
2294 nsRect GetScrollableOverflowRectRelativeToSelf() const;
2297 * Like GetVisualOverflowRect, except in this frame's
2298 * coordinate system (before transforms are applied).
2300 * @return the rect relative to this frame, before any CSS transforms have
2301 * been applied, i.e. in this frame's coordinate system
2303 nsRect GetVisualOverflowRectRelativeToSelf() const;
2306 * Same as GetVisualOverflowRect, except relative to the parent
2307 * frame.
2309 * @return the rect relative to the parent frame, in the parent frame's
2310 * coordinate system
2312 nsRect GetVisualOverflowRectRelativeToParent() const;
2315 * Returns this frame's visual overflow rect as it would be before taking
2316 * account of SVG effects or transforms. The rect returned is relative to
2317 * this frame.
2319 nsRect GetPreEffectsVisualOverflowRect() const;
2322 * Store the overflow area in the frame's mOverflow.mVisualDeltas
2323 * fields or as a frame property in the frame manager so that it can
2324 * be retrieved later without reflowing the frame. Returns true if either of
2325 * the overflow areas changed.
2327 bool FinishAndStoreOverflow(nsOverflowAreas& aOverflowAreas,
2328 nsSize aNewSize, nsSize* aOldSize = nullptr);
2330 bool FinishAndStoreOverflow(nsHTMLReflowMetrics* aMetrics) {
2331 return FinishAndStoreOverflow(aMetrics->mOverflowAreas,
2332 nsSize(aMetrics->Width(), aMetrics->Height()));
2336 * Returns whether the frame has an overflow rect that is different from
2337 * its border-box.
2339 bool HasOverflowAreas() const {
2340 return mOverflow.mType != NS_FRAME_OVERFLOW_NONE;
2344 * Removes any stored overflow rects (visual and scrollable) from the frame.
2345 * Returns true if the overflow changed.
2347 bool ClearOverflowRects();
2350 * Determine whether borders, padding, margins etc should NOT be applied
2351 * on certain sides of the frame.
2352 * @see mozilla::Sides in gfx/2d/BaseMargin.h
2353 * @see mozilla::LogicalSides in layout/generic/WritingModes.h
2355 * @note (See also bug 743402, comment 11) GetSkipSides() checks to see
2356 * if this frame has a previous or next continuation to determine
2357 * if a side should be skipped.
2358 * Unfortunately, this only works after reflow has been completed. In
2359 * lieu of this, during reflow, an nsHTMLReflowState parameter can be
2360 * passed in, indicating that it should be used to determine if sides
2361 * should be skipped during reflow.
2363 Sides GetSkipSides(const nsHTMLReflowState* aReflowState = nullptr) const;
2364 virtual LogicalSides
2365 GetLogicalSkipSides(const nsHTMLReflowState* aReflowState = nullptr) const {
2366 return LogicalSides();
2370 * @returns true if this frame is selected.
2372 bool IsSelected() const;
2375 * called to discover where this frame, or a parent frame has user-select style
2376 * applied, which affects that way that it is selected.
2378 * @param aIsSelectable out param. Set to true if the frame can be selected
2379 * (i.e. is not affected by user-select: none)
2380 * @param aSelectStyle out param. Returns the type of selection style found
2381 * (using values defined in nsStyleConsts.h).
2383 virtual nsresult IsSelectable(bool* aIsSelectable, uint8_t* aSelectStyle) const = 0;
2385 /**
2386 * Called to retrieve the SelectionController associated with the frame.
2387 * @param aSelCon will contain the selection controller associated with
2388 * the frame.
2390 virtual nsresult GetSelectionController(nsPresContext *aPresContext, nsISelectionController **aSelCon) = 0;
2393 * Call to get nsFrameSelection for this frame.
2395 already_AddRefed<nsFrameSelection> GetFrameSelection();
2398 * GetConstFrameSelection returns an object which methods are safe to use for
2399 * example in nsIFrame code.
2401 const nsFrameSelection* GetConstFrameSelection() const;
2404 * called to find the previous/next character, word, or line returns the actual
2405 * nsIFrame and the frame offset. THIS DOES NOT CHANGE SELECTION STATE
2406 * uses frame's begin selection state to start. if no selection on this frame will
2407 * return NS_ERROR_FAILURE
2408 * @param aPOS is defined in nsFrameSelection
2410 virtual nsresult PeekOffset(nsPeekOffsetStruct *aPos);
2413 * called to find the previous/next selectable leaf frame.
2414 * @param aDirection [in] the direction to move in (eDirPrevious or eDirNext)
2415 * @param aVisual [in] whether bidi caret behavior is visual (true) or logical (false)
2416 * @param aJumpLines [in] whether to allow jumping across line boundaries
2417 * @param aScrollViewStop [in] whether to stop when reaching a scroll frame boundary
2418 * @param aOutFrame [out] the previous/next selectable leaf frame
2419 * @param aOutOffset [out] 0 indicates that we arrived at the beginning of the output frame;
2420 * -1 indicates that we arrived at its end.
2421 * @param aOutJumpedLine [out] whether this frame and the returned frame are on different lines
2423 nsresult GetFrameFromDirection(nsDirection aDirection, bool aVisual,
2424 bool aJumpLines, bool aScrollViewStop,
2425 nsIFrame** aOutFrame, int32_t* aOutOffset, bool* aOutJumpedLine);
2428 * called to see if the children of the frame are visible from indexstart to index end.
2429 * this does not change any state. returns true only if the indexes are valid and any of
2430 * the children are visible. for textframes this index is the character index.
2431 * if aStart = aEnd result will be false
2432 * @param aStart start index of first child from 0-N (number of children)
2433 * @param aEnd end index of last child from 0-N
2434 * @param aRecurse should this frame talk to siblings to get to the contents other children?
2435 * @param aFinished did this frame have the aEndIndex? or is there more work to do
2436 * @param _retval return value true or false. false = range is not rendered.
2438 virtual nsresult CheckVisibility(nsPresContext* aContext, int32_t aStartIndex, int32_t aEndIndex, bool aRecurse, bool *aFinished, bool *_retval)=0;
2441 * Called to tell a frame that one of its child frames is dirty (i.e.,
2442 * has the NS_FRAME_IS_DIRTY *or* NS_FRAME_HAS_DIRTY_CHILDREN bit
2443 * set). This should always set the NS_FRAME_HAS_DIRTY_CHILDREN on
2444 * the frame, and may do other work.
2446 virtual void ChildIsDirty(nsIFrame* aChild) = 0;
2449 * Called to retrieve this frame's accessible.
2450 * If this frame implements Accessibility return a valid accessible
2451 * If not return NS_ERROR_NOT_IMPLEMENTED.
2452 * Note: Accessible must be refcountable. Do not implement directly on your frame
2453 * Use a mediatior of some kind.
2455 #ifdef ACCESSIBILITY
2456 virtual mozilla::a11y::AccType AccessibleType() = 0;
2457 #endif
2460 * Get the frame whose style context should be the parent of this
2461 * frame's style context (i.e., provide the parent style context).
2462 * This frame must either be an ancestor of this frame or a child. If
2463 * this returns a child frame, then the child frame must be sure to
2464 * return a grandparent or higher! Furthermore, if a child frame is
2465 * returned it must have the same GetContent() as this frame.
2467 * @return The frame whose style context should be the parent of this frame's
2468 * style context. Null is permitted, and means that this frame's
2469 * style context should be the root of the style context tree.
2471 virtual nsIFrame* GetParentStyleContextFrame() const = 0;
2474 * Determines whether a frame is visible for painting;
2475 * taking into account whether it is painting a selection or printing.
2477 bool IsVisibleForPainting(nsDisplayListBuilder* aBuilder);
2479 * Determines whether a frame is visible for painting or collapsed;
2480 * taking into account whether it is painting a selection or printing,
2482 bool IsVisibleOrCollapsedForPainting(nsDisplayListBuilder* aBuilder);
2484 * As above, but slower because we have to recompute some stuff that
2485 * aBuilder already has.
2487 bool IsVisibleForPainting();
2489 * Check whether this frame is visible in the current selection. Returns
2490 * true if there is no current selection.
2492 bool IsVisibleInSelection(nsDisplayListBuilder* aBuilder);
2495 * Overridable function to determine whether this frame should be considered
2496 * "in" the given non-null aSelection for visibility purposes.
2498 virtual bool IsVisibleInSelection(nsISelection* aSelection);
2501 * Determines whether this frame is a pseudo stacking context, looking
2502 * only as style --- i.e., assuming that it's in-flow and not a replaced
2503 * element and not an SVG element.
2504 * XXX maybe check IsTransformed()?
2506 bool IsPseudoStackingContextFromStyle();
2508 virtual bool HonorPrintBackgroundSettings() { return true; }
2511 * Determine whether the frame is logically empty, which is roughly
2512 * whether the layout would be the same whether or not the frame is
2513 * present. Placeholder frames should return true. Block frames
2514 * should be considered empty whenever margins collapse through them,
2515 * even though those margins are relevant. Text frames containing
2516 * only whitespace that does not contribute to the height of the line
2517 * should return true.
2519 virtual bool IsEmpty() = 0;
2521 * Return the same as IsEmpty(). This may only be called after the frame
2522 * has been reflowed and before any further style or content changes.
2524 virtual bool CachedIsEmpty();
2526 * Determine whether the frame is logically empty, assuming that all
2527 * its children are empty.
2529 virtual bool IsSelfEmpty() = 0;
2532 * IsGeneratedContentFrame returns whether a frame corresponds to
2533 * generated content
2535 * @return whether the frame correspods to generated content
2537 bool IsGeneratedContentFrame() {
2538 return (mState & NS_FRAME_GENERATED_CONTENT) != 0;
2542 * IsPseudoFrame returns whether a frame is a pseudo frame (eg an
2543 * anonymous table-row frame created for a CSS table-cell without an
2544 * enclosing table-row.
2546 * @param aParentContent the content node corresponding to the parent frame
2547 * @return whether the frame is a pseudo frame
2549 bool IsPseudoFrame(nsIContent* aParentContent) {
2550 return mContent == aParentContent;
2553 FrameProperties Properties() const {
2554 return FrameProperties(PresContext()->PropertyTable(), this);
2557 NS_DECLARE_FRAME_PROPERTY(BaseLevelProperty, nullptr)
2558 NS_DECLARE_FRAME_PROPERTY(EmbeddingLevelProperty, nullptr)
2559 NS_DECLARE_FRAME_PROPERTY(ParagraphDepthProperty, nullptr)
2561 #define NS_GET_BASE_LEVEL(frame) \
2562 NS_PTR_TO_INT32(frame->Properties().Get(nsIFrame::BaseLevelProperty()))
2564 #define NS_GET_EMBEDDING_LEVEL(frame) \
2565 NS_PTR_TO_INT32(frame->Properties().Get(nsIFrame::EmbeddingLevelProperty()))
2567 #define NS_GET_PARAGRAPH_DEPTH(frame) \
2568 NS_PTR_TO_INT32(frame->Properties().Get(nsIFrame::ParagraphDepthProperty()))
2571 * Return true if and only if this frame obeys visibility:hidden.
2572 * if it does not, then nsContainerFrame will hide its view even though
2573 * this means children can't be made visible again.
2575 virtual bool SupportsVisibilityHidden() { return true; }
2578 * Returns true if the frame has a valid clip rect set via the 'clip'
2579 * property, and the 'clip' property applies to this frame. The 'clip'
2580 * property applies to HTML frames if they are absolutely positioned. The
2581 * 'clip' property applies to SVG frames regardless of the value of the
2582 * 'position' property.
2584 * If this method returns true, then we also set aRect to the computed clip
2585 * rect, with coordinates relative to this frame's origin. aRect must not be
2586 * null!
2588 bool GetClipPropClipRect(const nsStyleDisplay* aDisp, nsRect* aRect,
2589 const nsSize& aSize) const;
2592 * Check if this frame is focusable and in the current tab order.
2593 * Tabbable is indicated by a nonnegative tabindex & is a subset of focusable.
2594 * For example, only the selected radio button in a group is in the
2595 * tab order, unless the radio group has no selection in which case
2596 * all of the visible, non-disabled radio buttons in the group are
2597 * in the tab order. On the other hand, all of the visible, non-disabled
2598 * radio buttons are always focusable via clicking or script.
2599 * Also, depending on the pref accessibility.tabfocus some widgets may be
2600 * focusable but removed from the tab order. This is the default on
2601 * Mac OS X, where fewer items are focusable.
2602 * @param [in, optional] aTabIndex the computed tab index
2603 * < 0 if not tabbable
2604 * == 0 if in normal tab order
2605 * > 0 can be tabbed to in the order specified by this value
2606 * @param [in, optional] aWithMouse, is this focus query for mouse clicking
2607 * @return whether the frame is focusable via mouse, kbd or script.
2609 virtual bool IsFocusable(int32_t *aTabIndex = nullptr, bool aWithMouse = false);
2611 // BOX LAYOUT METHODS
2612 // These methods have been migrated from nsIBox and are in the process of
2613 // being refactored. DO NOT USE OUTSIDE OF XUL.
2614 bool IsBoxFrame() const
2616 return IsFrameOfType(nsIFrame::eXULBox);
2619 enum Halignment {
2620 hAlign_Left,
2621 hAlign_Right,
2622 hAlign_Center
2625 enum Valignment {
2626 vAlign_Top,
2627 vAlign_Middle,
2628 vAlign_BaseLine,
2629 vAlign_Bottom
2633 * This calculates the minimum size required for a box based on its state
2634 * @param[in] aBoxLayoutState The desired state to calculate for
2635 * @return The minimum size
2637 virtual nsSize GetMinSize(nsBoxLayoutState& aBoxLayoutState) = 0;
2640 * This calculates the preferred size of a box based on its state
2641 * @param[in] aBoxLayoutState The desired state to calculate for
2642 * @return The preferred size
2644 virtual nsSize GetPrefSize(nsBoxLayoutState& aBoxLayoutState) = 0;
2647 * This calculates the maximum size for a box based on its state
2648 * @param[in] aBoxLayoutState The desired state to calculate for
2649 * @return The maximum size
2651 virtual nsSize GetMaxSize(nsBoxLayoutState& aBoxLayoutState) = 0;
2654 * This returns the minimum size for the scroll area if this frame is
2655 * being scrolled. Usually it's (0,0).
2657 virtual nsSize GetMinSizeForScrollArea(nsBoxLayoutState& aBoxLayoutState) = 0;
2659 // Implemented in nsBox, used in nsBoxFrame
2660 uint32_t GetOrdinal();
2662 virtual nscoord GetFlex(nsBoxLayoutState& aBoxLayoutState) = 0;
2663 virtual nscoord GetBoxAscent(nsBoxLayoutState& aBoxLayoutState) = 0;
2664 virtual bool IsCollapsed() = 0;
2665 // This does not alter the overflow area. If the caller is changing
2666 // the box size, the caller is responsible for updating the overflow
2667 // area. It's enough to just call Layout or SyncLayout on the
2668 // box. You can pass true to aRemoveOverflowArea as a
2669 // convenience.
2670 virtual void SetBounds(nsBoxLayoutState& aBoxLayoutState, const nsRect& aRect,
2671 bool aRemoveOverflowAreas = false) = 0;
2672 nsresult Layout(nsBoxLayoutState& aBoxLayoutState);
2673 // Box methods. Note that these do NOT just get the CSS border, padding,
2674 // etc. They also talk to nsITheme.
2675 virtual nsresult GetBorderAndPadding(nsMargin& aBorderAndPadding);
2676 virtual nsresult GetBorder(nsMargin& aBorder)=0;
2677 virtual nsresult GetPadding(nsMargin& aBorderAndPadding)=0;
2678 virtual nsresult GetMargin(nsMargin& aMargin)=0;
2679 virtual void SetLayoutManager(nsBoxLayout* aLayout) { }
2680 virtual nsBoxLayout* GetLayoutManager() { return nullptr; }
2681 nsresult GetClientRect(nsRect& aContentRect);
2683 // For nsSprocketLayout
2684 virtual Valignment GetVAlign() const = 0;
2685 virtual Halignment GetHAlign() const = 0;
2687 bool IsHorizontal() const { return (mState & NS_STATE_IS_HORIZONTAL) != 0; }
2688 bool IsNormalDirection() const { return (mState & NS_STATE_IS_DIRECTION_NORMAL) != 0; }
2690 nsresult Redraw(nsBoxLayoutState& aState);
2691 virtual nsresult RelayoutChildAtOrdinal(nsBoxLayoutState& aState, nsIFrame* aChild)=0;
2692 // XXX take this out after we've branched
2693 virtual bool GetMouseThrough() const { return false; }
2695 #ifdef DEBUG_LAYOUT
2696 virtual nsresult SetDebug(nsBoxLayoutState& aState, bool aDebug)=0;
2697 virtual nsresult GetDebug(bool& aDebug)=0;
2699 virtual nsresult DumpBox(FILE* out)=0;
2700 #endif
2703 * @return true if this text frame ends with a newline character. It
2704 * should return false if this is not a text frame.
2706 virtual bool HasSignificantTerminalNewline() const;
2708 static bool AddCSSPrefSize(nsIFrame* aBox, nsSize& aSize, bool& aWidth, bool& aHeightSet);
2709 static bool AddCSSMinSize(nsBoxLayoutState& aState, nsIFrame* aBox,
2710 nsSize& aSize, bool& aWidth, bool& aHeightSet);
2711 static bool AddCSSMaxSize(nsIFrame* aBox, nsSize& aSize, bool& aWidth, bool& aHeightSet);
2712 static bool AddCSSFlex(nsBoxLayoutState& aState, nsIFrame* aBox, nscoord& aFlex);
2714 // END OF BOX LAYOUT METHODS
2715 // The above methods have been migrated from nsIBox and are in the process of
2716 // being refactored. DO NOT USE OUTSIDE OF XUL.
2718 struct CaretPosition {
2719 CaretPosition();
2720 ~CaretPosition();
2722 nsCOMPtr<nsIContent> mResultContent;
2723 int32_t mContentOffset;
2727 * gets the first or last possible caret position within the frame
2729 * @param [in] aStart
2730 * true for getting the first possible caret position
2731 * false for getting the last possible caret position
2732 * @return The caret position in a CaretPosition.
2733 * the returned value is a 'best effort' in case errors
2734 * are encountered rummaging through the frame.
2736 CaretPosition GetExtremeCaretPosition(bool aStart);
2739 * Get a line iterator for this frame, if supported.
2741 * @return nullptr if no line iterator is supported.
2742 * @note dispose the line iterator using nsILineIterator::DisposeLineIterator
2744 virtual nsILineIterator* GetLineIterator() = 0;
2747 * If this frame is a next-in-flow, and its prev-in-flow has something on its
2748 * overflow list, pull those frames into the child list of this one.
2750 virtual void PullOverflowsFromPrevInFlow() {}
2753 * Clear the list of child PresShells generated during the last paint
2754 * so that we can begin generating a new one.
2756 void ClearPresShellsFromLastPaint() {
2757 PaintedPresShellList()->Clear();
2761 * Flag a child PresShell as painted so that it will get its paint count
2762 * incremented during empty transactions.
2764 void AddPaintedPresShell(nsIPresShell* shell) {
2765 nsWeakPtr weakShell = do_GetWeakReference(shell);
2766 PaintedPresShellList()->AppendElement(weakShell);
2770 * Increment the paint count of all child PresShells that were painted during
2771 * the last repaint.
2773 void UpdatePaintCountForPaintedPresShells() {
2774 nsTArray<nsWeakPtr> * list = PaintedPresShellList();
2775 for (int i = 0, l = list->Length(); i < l; i++) {
2776 nsCOMPtr<nsIPresShell> shell = do_QueryReferent(list->ElementAt(i));
2778 if (shell) {
2779 shell->IncrementPaintCount();
2785 * Accessors for the absolute containing block.
2787 bool IsAbsoluteContainer() const { return !!(mState & NS_FRAME_HAS_ABSPOS_CHILDREN); }
2788 bool HasAbsolutelyPositionedChildren() const;
2789 nsAbsoluteContainingBlock* GetAbsoluteContainingBlock() const;
2790 void MarkAsAbsoluteContainingBlock();
2791 void MarkAsNotAbsoluteContainingBlock();
2792 // Child frame types override this function to select their own child list name
2793 virtual mozilla::layout::FrameChildListID GetAbsoluteListID() const { return kAbsoluteList; }
2795 // Checks if we (or any of our descendents) have NS_FRAME_PAINTED_THEBES set, and
2796 // clears this bit if so.
2797 bool CheckAndClearPaintedState();
2799 // CSS visibility just doesn't cut it because it doesn't inherit through
2800 // documents. Also if this frame is in a hidden card of a deck then it isn't
2801 // visible either and that isn't expressed using CSS visibility. Also if it
2802 // is in a hidden view (there are a few cases left and they are hopefully
2803 // going away soon).
2804 // If the VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY flag is passed then we
2805 // ignore the chrome/content boundary, otherwise we stop looking when we
2806 // reach it.
2807 enum {
2808 VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY = 0x01
2810 bool IsVisibleConsideringAncestors(uint32_t aFlags = 0) const;
2812 struct FrameWithDistance
2814 nsIFrame* mFrame;
2815 nscoord mXDistance;
2816 nscoord mYDistance;
2820 * Finds a frame that is closer to a specified point than a current
2821 * distance. Distance is measured as for text selection -- a closer x
2822 * distance beats a closer y distance.
2824 * Normally, this function will only check the distance between this
2825 * frame's rectangle and the specified point. SVGTextFrame overrides
2826 * this so that it can manage all of its descendant frames and take
2827 * into account any SVG text layout.
2829 * If aPoint is closer to this frame's rectangle than aCurrentBestFrame
2830 * indicates, then aCurrentBestFrame is updated with the distance between
2831 * aPoint and this frame's rectangle, and with a pointer to this frame.
2832 * If aPoint is not closer, then aCurrentBestFrame is left unchanged.
2834 * @param aPoint The point to check for its distance to this frame.
2835 * @param aCurrentBestFrame Pointer to a struct that will be updated with
2836 * a pointer to this frame and its distance to aPoint, if this frame
2837 * is indeed closer than the current distance in aCurrentBestFrame.
2839 virtual void FindCloserFrameForSelection(nsPoint aPoint,
2840 FrameWithDistance* aCurrentBestFrame);
2843 * Is this a flex item? (i.e. a non-abs-pos child of a flex container)
2845 inline bool IsFlexItem() const;
2847 * Is this a flex or grid item? (i.e. a non-abs-pos child of a flex/grid container)
2849 inline bool IsFlexOrGridItem() const;
2851 inline bool IsBlockInside() const;
2852 inline bool IsBlockOutside() const;
2853 inline bool IsInlineOutside() const;
2854 inline uint8_t GetDisplay() const;
2855 inline bool IsFloating() const;
2856 inline bool IsPositioned() const;
2857 inline bool IsRelativelyPositioned() const;
2858 inline bool IsAbsolutelyPositioned() const;
2861 * Returns the vertical-align value to be used for layout, if it is one
2862 * of the enumerated values. If this is an SVG text frame, it returns a value
2863 * that corresponds to the value of dominant-baseline. If the
2864 * vertical-align property has length or percentage value, this returns
2865 * eInvalidVerticalAlign.
2867 uint8_t VerticalAlignEnum() const;
2868 enum { eInvalidVerticalAlign = 0xFF };
2870 bool IsSVGText() const { return mState & NS_FRAME_IS_SVG_TEXT; }
2872 void CreateOwnLayerIfNeeded(nsDisplayListBuilder* aBuilder, nsDisplayList* aList);
2875 * Adds the NS_FRAME_IN_POPUP state bit to aFrame, and
2876 * all descendant frames (including cross-doc ones).
2878 static void AddInPopupStateBitToDescendants(nsIFrame* aFrame);
2880 * Removes the NS_FRAME_IN_POPUP state bit from aFrame and
2881 * all descendant frames (including cross-doc ones), unless
2882 * the frame is a popup itself.
2884 static void RemoveInPopupStateBitFromDescendants(nsIFrame* aFrame);
2887 * Sorts the given nsFrameList, so that for every two adjacent frames in the
2888 * list, the former is less than or equal to the latter, according to the
2889 * templated IsLessThanOrEqual method.
2891 * Note: this method uses a stable merge-sort algorithm.
2893 template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
2894 static void SortFrameList(nsFrameList& aFrameList);
2897 * Returns true if the given frame list is already sorted, according to the
2898 * templated IsLessThanOrEqual function.
2900 template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
2901 static bool IsFrameListSorted(nsFrameList& aFrameList);
2904 * Return true if aFrame is in an {ib} split and is NOT one of the
2905 * continuations of the first inline in it.
2907 bool FrameIsNonFirstInIBSplit() const {
2908 return (GetStateBits() & NS_FRAME_PART_OF_IBSPLIT) &&
2909 FirstContinuation()->Properties().Get(nsIFrame::IBSplitPrevSibling());
2913 * Return true if aFrame is in an {ib} split and is NOT one of the
2914 * continuations of the last inline in it.
2916 bool FrameIsNonLastInIBSplit() const {
2917 return (GetStateBits() & NS_FRAME_PART_OF_IBSPLIT) &&
2918 FirstContinuation()->Properties().Get(nsIFrame::IBSplitSibling());
2922 * Return whether this is a frame whose width is used when computing
2923 * the font size inflation of its descendants.
2925 bool IsContainerForFontSizeInflation() const {
2926 return GetStateBits() & NS_FRAME_FONT_INFLATION_CONTAINER;
2930 * Returns the content node within the anonymous content that this frame
2931 * generated and which corresponds to the specified pseudo-element type,
2932 * or nullptr if there is no such anonymous content.
2934 virtual mozilla::dom::Element* GetPseudoElement(nsCSSPseudoElements::Type aType);
2936 protected:
2937 // Members
2938 nsRect mRect;
2939 nsIContent* mContent;
2940 nsStyleContext* mStyleContext;
2941 private:
2942 nsContainerFrame* mParent;
2943 nsIFrame* mNextSibling; // doubly-linked list of frames
2944 nsIFrame* mPrevSibling; // Do not touch outside SetNextSibling!
2946 void MarkAbsoluteFramesForDisplayList(nsDisplayListBuilder* aBuilder, const nsRect& aDirtyRect);
2948 static void DestroyPaintedPresShellList(void* propertyValue) {
2949 nsTArray<nsWeakPtr>* list = static_cast<nsTArray<nsWeakPtr>*>(propertyValue);
2950 list->Clear();
2951 delete list;
2954 // Stores weak references to all the PresShells that were painted during
2955 // the last paint event so that we can increment their paint count during
2956 // empty transactions
2957 NS_DECLARE_FRAME_PROPERTY(PaintedPresShellsProperty, DestroyPaintedPresShellList)
2959 nsTArray<nsWeakPtr>* PaintedPresShellList() {
2960 nsTArray<nsWeakPtr>* list = static_cast<nsTArray<nsWeakPtr>*>(
2961 Properties().Get(PaintedPresShellsProperty())
2964 if (!list) {
2965 list = new nsTArray<nsWeakPtr>();
2966 Properties().Set(PaintedPresShellsProperty(), list);
2969 return list;
2972 protected:
2973 nsFrameState mState;
2975 // When there is an overflow area only slightly larger than mRect,
2976 // we store a set of four 1-byte deltas from the edges of mRect
2977 // rather than allocating a whole separate rectangle property.
2978 // Note that these are unsigned values, all measured "outwards"
2979 // from the edges of mRect, so /mLeft/ and /mTop/ are reversed from
2980 // our normal coordinate system.
2981 // If mOverflow.mType == NS_FRAME_OVERFLOW_LARGE, then the
2982 // delta values are not meaningful and the overflow area is stored
2983 // as a separate rect property.
2984 struct VisualDeltas {
2985 uint8_t mLeft;
2986 uint8_t mTop;
2987 uint8_t mRight;
2988 uint8_t mBottom;
2989 bool operator==(const VisualDeltas& aOther) const
2991 return mLeft == aOther.mLeft && mTop == aOther.mTop &&
2992 mRight == aOther.mRight && mBottom == aOther.mBottom;
2994 bool operator!=(const VisualDeltas& aOther) const
2996 return !(*this == aOther);
2999 union {
3000 uint32_t mType;
3001 VisualDeltas mVisualDeltas;
3002 } mOverflow;
3004 // Helpers
3006 * Can we stop inside this frame when we're skipping non-rendered whitespace?
3007 * @param aForward [in] Are we moving forward (or backward) in content order.
3008 * @param aOffset [in/out] At what offset into the frame to start looking.
3009 * on output - what offset was reached (whether or not we found a place to stop).
3010 * @return STOP: An appropriate offset was found within this frame,
3011 * and is given by aOffset.
3012 * CONTINUE: Not found within this frame, need to try the next frame.
3013 * see enum FrameSearchResult for more details.
3015 virtual FrameSearchResult PeekOffsetNoAmount(bool aForward, int32_t* aOffset) = 0;
3018 * Search the frame for the next character
3019 * @param aForward [in] Are we moving forward (or backward) in content order.
3020 * @param aOffset [in/out] At what offset into the frame to start looking.
3021 * on output - what offset was reached (whether or not we found a place to stop).
3022 * @param aRespectClusters [in] Whether to restrict result to valid cursor locations
3023 * (between grapheme clusters) - default TRUE maintains "normal" behavior,
3024 * FALSE is used for selection by "code unit" (instead of "character")
3025 * @return STOP: An appropriate offset was found within this frame,
3026 * and is given by aOffset.
3027 * CONTINUE: Not found within this frame, need to try the next frame.
3028 * see enum FrameSearchResult for more details.
3030 virtual FrameSearchResult PeekOffsetCharacter(bool aForward, int32_t* aOffset,
3031 bool aRespectClusters = true) = 0;
3034 * Search the frame for the next word boundary
3035 * @param aForward [in] Are we moving forward (or backward) in content order.
3036 * @param aWordSelectEatSpace [in] true: look for non-whitespace following
3037 * whitespace (in the direction of movement).
3038 * false: look for whitespace following non-whitespace (in the
3039 * direction of movement).
3040 * @param aIsKeyboardSelect [in] Was the action initiated by a keyboard operation?
3041 * If true, punctuation immediately following a word is considered part
3042 * of that word. Otherwise, a sequence of punctuation is always considered
3043 * as a word on its own.
3044 * @param aOffset [in/out] At what offset into the frame to start looking.
3045 * on output - what offset was reached (whether or not we found a place to stop).
3046 * @param aState [in/out] the state that is carried from frame to frame
3047 * @return true: An appropriate offset was found within this frame,
3048 * and is given by aOffset.
3049 * false: Not found within this frame, need to try the next frame.
3051 struct PeekWordState {
3052 // true when we're still at the start of the search, i.e., we can't return
3053 // this point as a valid offset!
3054 bool mAtStart;
3055 // true when we've encountered at least one character of the pre-boundary type
3056 // (whitespace if aWordSelectEatSpace is true, non-whitespace otherwise)
3057 bool mSawBeforeType;
3058 // true when the last character encountered was punctuation
3059 bool mLastCharWasPunctuation;
3060 // true when the last character encountered was whitespace
3061 bool mLastCharWasWhitespace;
3062 // true when we've seen non-punctuation since the last whitespace
3063 bool mSeenNonPunctuationSinceWhitespace;
3064 // text that's *before* the current frame when aForward is true, *after*
3065 // the current frame when aForward is false. Only includes the text
3066 // on the current line.
3067 nsAutoString mContext;
3069 PeekWordState() : mAtStart(true), mSawBeforeType(false),
3070 mLastCharWasPunctuation(false), mLastCharWasWhitespace(false),
3071 mSeenNonPunctuationSinceWhitespace(false) {}
3072 void SetSawBeforeType() { mSawBeforeType = true; }
3073 void Update(bool aAfterPunctuation, bool aAfterWhitespace) {
3074 mLastCharWasPunctuation = aAfterPunctuation;
3075 mLastCharWasWhitespace = aAfterWhitespace;
3076 if (aAfterWhitespace) {
3077 mSeenNonPunctuationSinceWhitespace = false;
3078 } else if (!aAfterPunctuation) {
3079 mSeenNonPunctuationSinceWhitespace = true;
3081 mAtStart = false;
3084 virtual FrameSearchResult PeekOffsetWord(bool aForward, bool aWordSelectEatSpace, bool aIsKeyboardSelect,
3085 int32_t* aOffset, PeekWordState* aState) = 0;
3088 * Search for the first paragraph boundary before or after the given position
3089 * @param aPos See description in nsFrameSelection.h. The following fields are
3090 * used by this method:
3091 * Input: mDirection
3092 * Output: mResultContent, mContentOffset
3094 nsresult PeekOffsetParagraph(nsPeekOffsetStruct *aPos);
3096 private:
3097 nsOverflowAreas* GetOverflowAreasProperty();
3098 nsRect GetVisualOverflowFromDeltas() const {
3099 NS_ABORT_IF_FALSE(mOverflow.mType != NS_FRAME_OVERFLOW_LARGE,
3100 "should not be called when overflow is in a property");
3101 // Calculate the rect using deltas from the frame's border rect.
3102 // Note that the mOverflow.mDeltas fields are unsigned, but we will often
3103 // need to return negative values for the left and top, so take care
3104 // to cast away the unsigned-ness.
3105 return nsRect(-(int32_t)mOverflow.mVisualDeltas.mLeft,
3106 -(int32_t)mOverflow.mVisualDeltas.mTop,
3107 mRect.width + mOverflow.mVisualDeltas.mRight +
3108 mOverflow.mVisualDeltas.mLeft,
3109 mRect.height + mOverflow.mVisualDeltas.mBottom +
3110 mOverflow.mVisualDeltas.mTop);
3113 * Returns true if any overflow changed.
3115 bool SetOverflowAreas(const nsOverflowAreas& aOverflowAreas);
3117 // Helper-functions for SortFrameList():
3118 template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
3119 static nsIFrame* SortedMerge(nsIFrame *aLeft, nsIFrame *aRight);
3121 template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
3122 static nsIFrame* MergeSort(nsIFrame *aSource);
3124 bool HasOpacityInternal(float aThreshold) const;
3126 #ifdef DEBUG_FRAME_DUMP
3127 public:
3128 static void IndentBy(FILE* out, int32_t aIndent) {
3129 while (--aIndent >= 0) fputs(" ", out);
3131 void ListTag(FILE* out) const {
3132 ListTag(out, this);
3134 static void ListTag(FILE* out, const nsIFrame* aFrame) {
3135 nsAutoCString t;
3136 ListTag(t, aFrame);
3137 fputs(t.get(), out);
3139 void ListTag(nsACString& aTo) const;
3140 static void ListTag(nsACString& aTo, const nsIFrame* aFrame);
3141 void ListGeneric(nsACString& aTo, const char* aPrefix = "", uint32_t aFlags = 0) const;
3142 enum {
3143 TRAVERSE_SUBDOCUMENT_FRAMES = 0x01
3145 virtual void List(FILE* out = stderr, const char* aPrefix = "", uint32_t aFlags = 0) const;
3147 * lists the frames beginning from the root frame
3148 * - calls root frame's List(...)
3150 static void RootFrameList(nsPresContext* aPresContext,
3151 FILE* out = stderr, const char* aPrefix = "");
3152 virtual void DumpFrameTree();
3153 void DumpFrameTreeLimited();
3155 virtual nsresult GetFrameName(nsAString& aResult) const = 0;
3156 #endif
3158 #ifdef DEBUG
3159 public:
3160 virtual nsFrameState GetDebugStateBits() const = 0;
3161 virtual nsresult DumpRegressionData(nsPresContext* aPresContext,
3162 FILE* out, int32_t aIndent) = 0;
3163 #endif
3166 //----------------------------------------------------------------------
3169 * nsWeakFrame can be used to keep a reference to a nsIFrame in a safe way.
3170 * Whenever an nsIFrame object is deleted, the nsWeakFrames pointing
3171 * to it will be cleared.
3173 * Create nsWeakFrame object when it is sure that nsIFrame object
3174 * is alive and after some operations which may destroy the nsIFrame
3175 * (for example any DOM modifications) use IsAlive() or GetFrame() methods to
3176 * check whether it is safe to continue to use the nsIFrame object.
3178 * @note The usage of this class should be kept to a minimum.
3181 class nsWeakFrame {
3182 public:
3183 nsWeakFrame() : mPrev(nullptr), mFrame(nullptr) { }
3185 nsWeakFrame(const nsWeakFrame& aOther) : mPrev(nullptr), mFrame(nullptr)
3187 Init(aOther.GetFrame());
3190 MOZ_IMPLICIT nsWeakFrame(nsIFrame* aFrame) : mPrev(nullptr), mFrame(nullptr)
3192 Init(aFrame);
3195 nsWeakFrame& operator=(nsWeakFrame& aOther) {
3196 Init(aOther.GetFrame());
3197 return *this;
3200 nsWeakFrame& operator=(nsIFrame* aFrame) {
3201 Init(aFrame);
3202 return *this;
3205 nsIFrame* operator->()
3207 return mFrame;
3210 operator nsIFrame*()
3212 return mFrame;
3215 void Clear(nsIPresShell* aShell) {
3216 if (aShell) {
3217 aShell->RemoveWeakFrame(this);
3219 mFrame = nullptr;
3220 mPrev = nullptr;
3223 bool IsAlive() { return !!mFrame; }
3225 nsIFrame* GetFrame() const { return mFrame; }
3227 nsWeakFrame* GetPreviousWeakFrame() { return mPrev; }
3229 void SetPreviousWeakFrame(nsWeakFrame* aPrev) { mPrev = aPrev; }
3231 ~nsWeakFrame()
3233 Clear(mFrame ? mFrame->PresContext()->GetPresShell() : nullptr);
3235 private:
3236 void Init(nsIFrame* aFrame);
3238 nsWeakFrame* mPrev;
3239 nsIFrame* mFrame;
3242 inline bool
3243 nsFrameList::ContinueRemoveFrame(nsIFrame* aFrame)
3245 MOZ_ASSERT(!aFrame->GetPrevSibling() || !aFrame->GetNextSibling(),
3246 "Forgot to call StartRemoveFrame?");
3247 if (aFrame == mLastChild) {
3248 MOZ_ASSERT(!aFrame->GetNextSibling(), "broken frame list");
3249 nsIFrame* prevSibling = aFrame->GetPrevSibling();
3250 if (!prevSibling) {
3251 MOZ_ASSERT(aFrame == mFirstChild, "broken frame list");
3252 mFirstChild = mLastChild = nullptr;
3253 return true;
3255 MOZ_ASSERT(prevSibling->GetNextSibling() == aFrame, "Broken frame linkage");
3256 prevSibling->SetNextSibling(nullptr);
3257 mLastChild = prevSibling;
3258 return true;
3260 if (aFrame == mFirstChild) {
3261 MOZ_ASSERT(!aFrame->GetPrevSibling(), "broken frame list");
3262 mFirstChild = aFrame->GetNextSibling();
3263 aFrame->SetNextSibling(nullptr);
3264 MOZ_ASSERT(mFirstChild, "broken frame list");
3265 return true;
3267 return false;
3270 inline bool
3271 nsFrameList::StartRemoveFrame(nsIFrame* aFrame)
3273 if (aFrame->GetPrevSibling() && aFrame->GetNextSibling()) {
3274 UnhookFrameFromSiblings(aFrame);
3275 return true;
3277 return ContinueRemoveFrame(aFrame);
3280 inline void
3281 nsFrameList::Enumerator::Next()
3283 NS_ASSERTION(!AtEnd(), "Should have checked AtEnd()!");
3284 mFrame = mFrame->GetNextSibling();
3287 inline
3288 nsFrameList::FrameLinkEnumerator::
3289 FrameLinkEnumerator(const nsFrameList& aList, nsIFrame* aPrevFrame)
3290 : Enumerator(aList)
3292 mPrev = aPrevFrame;
3293 mFrame = aPrevFrame ? aPrevFrame->GetNextSibling() : aList.FirstChild();
3296 inline void
3297 nsFrameList::FrameLinkEnumerator::Next()
3299 mPrev = mFrame;
3300 Enumerator::Next();
3303 // Helper-functions for nsIFrame::SortFrameList()
3304 // ---------------------------------------------------
3306 template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
3307 /* static */ nsIFrame*
3308 nsIFrame::SortedMerge(nsIFrame *aLeft, nsIFrame *aRight)
3310 NS_PRECONDITION(aLeft && aRight, "SortedMerge must have non-empty lists");
3312 nsIFrame *result;
3313 // Unroll first iteration to avoid null-check 'result' inside the loop.
3314 if (IsLessThanOrEqual(aLeft, aRight)) {
3315 result = aLeft;
3316 aLeft = aLeft->GetNextSibling();
3317 if (!aLeft) {
3318 result->SetNextSibling(aRight);
3319 return result;
3322 else {
3323 result = aRight;
3324 aRight = aRight->GetNextSibling();
3325 if (!aRight) {
3326 result->SetNextSibling(aLeft);
3327 return result;
3331 nsIFrame *last = result;
3332 for (;;) {
3333 if (IsLessThanOrEqual(aLeft, aRight)) {
3334 last->SetNextSibling(aLeft);
3335 last = aLeft;
3336 aLeft = aLeft->GetNextSibling();
3337 if (!aLeft) {
3338 last->SetNextSibling(aRight);
3339 return result;
3342 else {
3343 last->SetNextSibling(aRight);
3344 last = aRight;
3345 aRight = aRight->GetNextSibling();
3346 if (!aRight) {
3347 last->SetNextSibling(aLeft);
3348 return result;
3354 template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
3355 /* static */ nsIFrame*
3356 nsIFrame::MergeSort(nsIFrame *aSource)
3358 NS_PRECONDITION(aSource, "MergeSort null arg");
3360 nsIFrame *sorted[32] = { nullptr };
3361 nsIFrame **fill = &sorted[0];
3362 nsIFrame **left;
3363 nsIFrame *rest = aSource;
3365 do {
3366 nsIFrame *current = rest;
3367 rest = rest->GetNextSibling();
3368 current->SetNextSibling(nullptr);
3370 // Merge it with sorted[0] if present; then merge the result with sorted[1] etc.
3371 // sorted[0] is a list of length 1 (or nullptr).
3372 // sorted[1] is a list of length 2 (or nullptr).
3373 // sorted[2] is a list of length 4 (or nullptr). etc.
3374 for (left = &sorted[0]; left != fill && *left; ++left) {
3375 current = SortedMerge<IsLessThanOrEqual>(*left, current);
3376 *left = nullptr;
3379 // Fill the empty slot that we couldn't merge with the last result.
3380 *left = current;
3382 if (left == fill)
3383 ++fill;
3384 } while (rest);
3386 // Collect and merge the results.
3387 nsIFrame *result = nullptr;
3388 for (left = &sorted[0]; left != fill; ++left) {
3389 if (*left) {
3390 result = result ? SortedMerge<IsLessThanOrEqual>(*left, result) : *left;
3393 return result;
3396 template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
3397 /* static */ void
3398 nsIFrame::SortFrameList(nsFrameList& aFrameList)
3400 nsIFrame* head = MergeSort<IsLessThanOrEqual>(aFrameList.FirstChild());
3401 aFrameList = nsFrameList(head, nsLayoutUtils::GetLastSibling(head));
3402 MOZ_ASSERT(IsFrameListSorted<IsLessThanOrEqual>(aFrameList),
3403 "After we sort a frame list, it should be in sorted order...");
3406 template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
3407 /* static */ bool
3408 nsIFrame::IsFrameListSorted(nsFrameList& aFrameList)
3410 if (aFrameList.IsEmpty()) {
3411 // empty lists are trivially sorted.
3412 return true;
3415 // We'll walk through the list with two iterators, one trailing behind the
3416 // other. The list is sorted IFF trailingIter <= iter, across the whole list.
3417 nsFrameList::Enumerator trailingIter(aFrameList);
3418 nsFrameList::Enumerator iter(aFrameList);
3419 iter.Next(); // Skip |iter| past first frame. (List is nonempty, so we can.)
3421 // Now, advance the iterators in parallel, comparing each adjacent pair.
3422 while (!iter.AtEnd()) {
3423 MOZ_ASSERT(!trailingIter.AtEnd(), "trailing iter shouldn't finish first");
3424 if (!IsLessThanOrEqual(trailingIter.get(), iter.get())) {
3425 return false;
3427 trailingIter.Next();
3428 iter.Next();
3431 // We made it to the end without returning early, so the list is sorted.
3432 return true;
3435 #endif /* nsIFrame_h___ */