Source code

Revision control

Other Tools

1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
* License, v. 2.0. If a copy of the MPL was not distributed with this
5
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
/* interface for all rendering objects */
8
9
#ifndef nsIFrame_h___
10
#define nsIFrame_h___
11
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
15
16
#if (defined(XP_WIN) && !defined(HAVE_64BIT_BUILD)) || defined(ANDROID)
17
// Blink's magic depth limit from its HTML parser (513) plus as much as fits in
18
// the default run-time stack on armv7 Android on Dalvik when using display:
19
// block minus a bit just to be sure. The Dalvik default stack crashes at 588.
20
// ART can do a few frames more. Using the same number for 32-bit Windows for
21
// consistency. Over there, Blink's magic depth of 513 doesn't fit in the
22
// default stack of 1 MB, but this magic depth fits when the default is grown by
23
// mere 192 KB (tested in 64 KB increments).
24
//
25
// 32-bit Windows has a different limit compared to 64-bit desktop, because the
26
// default stack size affects all threads and consumes address space. Fixing
27
// that is bug 1257522.
28
//
29
// 32-bit Android on ARM already happens to have defaults that are close enough
30
// to what makes sense as a temporary measure on Windows, so adjusting the
31
// Android stack can be a follow-up. The stack on 64-bit ARM needs adjusting in
32
// any case before 64-bit ARM can become tier-1. See bug 1400811.
33
//
34
// Ideally, we'd get rid of this smaller limit and make 32-bit Windows and
35
// Android capable of working with the Linux/Mac/Win64 number below.
36
# define MAX_REFLOW_DEPTH 585
37
#else
38
// Blink's magic depth limit from its HTML parser times two. Also just about
39
// fits within the system default runtime stack limit of 8 MB on 64-bit Mac and
40
// Linux with display: table-cell.
41
# define MAX_REFLOW_DEPTH 1026
42
#endif
43
44
/* nsIFrame is in the process of being deCOMtaminated, i.e., this file is
45
eventually going to be eliminated, and all callers will use nsFrame instead.
46
At the moment we're midway through this process, so you will see inlined
47
functions and member variables in this file. -dwh */
48
49
#include <algorithm>
50
#include <stdio.h>
51
52
#include "CaretAssociationHint.h"
53
#include "FrameProperties.h"
54
#include "LayoutConstants.h"
55
#include "mozilla/layout/FrameChildList.h"
56
#include "mozilla/AspectRatio.h"
57
#include "mozilla/Maybe.h"
58
#include "mozilla/SmallPointerArray.h"
59
#include "mozilla/WritingModes.h"
60
#include "nsDirection.h"
61
#include "nsFrameList.h"
62
#include "nsFrameState.h"
63
#include "mozilla/ReflowOutput.h"
64
#include "nsITheme.h"
65
#include "nsLayoutUtils.h"
66
#include "nsQueryFrame.h"
67
#include "nsString.h"
68
#include "mozilla/ComputedStyle.h"
69
#include "nsStyleStruct.h"
70
#include "Visibility.h"
71
#include "nsChangeHint.h"
72
#include "mozilla/ComputedStyleInlines.h"
73
#include "mozilla/gfx/CompositorHitTestInfo.h"
74
#include "mozilla/gfx/MatrixFwd.h"
75
#include "nsDisplayItemTypes.h"
76
77
#ifdef ACCESSIBILITY
78
# include "mozilla/a11y/AccTypes.h"
79
#endif
80
81
/**
82
* New rules of reflow:
83
* 1. you get a WillReflow() followed by a Reflow() followed by a DidReflow() in
84
* order (no separate pass over the tree)
85
* 2. it's the parent frame's responsibility to size/position the child's view
86
* (not the child frame's responsibility as it is today) during reflow (and
87
* before sending the DidReflow() notification)
88
* 3. positioning of child frames (and their views) is done on the way down the
89
* tree, and sizing of child frames (and their views) on the way back up
90
* 4. if you move a frame (outside of the reflow process, or after reflowing
91
* it), then you must make sure that its view (or its child frame's views)
92
* are re-positioned as well. It's reasonable to not position the view until
93
* after all reflowing the entire line, for example, but the frame should
94
* still be positioned and sized (and the view sized) during the reflow
95
* (i.e., before sending the DidReflow() notification)
96
* 5. the view system handles moving of widgets, i.e., it's not our problem
97
*/
98
99
class nsAtom;
100
class nsPresContext;
101
class nsView;
102
class nsIWidget;
103
class nsISelectionController;
104
class nsBoxLayoutState;
105
class nsBoxLayout;
106
class nsILineIterator;
107
class nsDisplayItemBase;
108
class nsDisplayListBuilder;
109
class nsDisplayListSet;
110
class nsDisplayList;
111
class gfxSkipChars;
112
class gfxSkipCharsIterator;
113
class gfxContext;
114
class nsLineList_iterator;
115
class nsAbsoluteContainingBlock;
116
class nsIContent;
117
class nsContainerFrame;
118
class nsPlaceholderFrame;
119
class nsStyleChangeList;
120
class nsWindowSizes;
121
122
struct nsPeekOffsetStruct;
123
struct nsPoint;
124
struct nsRect;
125
struct nsSize;
126
struct nsMargin;
127
struct CharacterDataChangeInfo;
128
129
namespace mozilla {
130
131
enum class PseudoStyleType : uint8_t;
132
class EventStates;
133
class PresShell;
134
struct ReflowInput;
135
class ReflowOutput;
136
class ServoRestyleState;
137
class DisplayItemData;
138
class EffectSet;
139
140
namespace layers {
141
class Layer;
142
class LayerManager;
143
} // namespace layers
144
145
namespace layout {
146
class ScrollAnchorContainer;
147
} // namespace layout
148
149
namespace dom {
150
class Selection;
151
} // namespace dom
152
153
} // namespace mozilla
154
155
//----------------------------------------------------------------------
156
157
#define NS_SUBTREE_DIRTY(_frame) \
158
(((_frame)->GetStateBits() & \
159
(NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN)) != 0)
160
161
// 1 million CSS pixels less than our max app unit measure.
162
// For reflowing with an "infinite" available inline space per [css-sizing].
163
// (reflowing with an NS_UNCONSTRAINEDSIZE available inline size isn't allowed
164
// and leads to assertions)
165
#define INFINITE_ISIZE_COORD nscoord(NS_MAXSIZE - (1000000 * 60))
166
167
//----------------------------------------------------------------------
168
169
namespace mozilla {
170
171
enum class LayoutFrameType : uint8_t {
172
#define FRAME_TYPE(ty_, ...) ty_,
173
#include "mozilla/FrameTypeList.h"
174
#undef FRAME_TYPE
175
};
176
177
} // namespace mozilla
178
179
enum nsSelectionAmount {
180
eSelectCharacter = 0, // a single Unicode character;
181
// do not use this (prefer Cluster) unless you
182
// are really sure it's what you want
183
eSelectCluster = 1, // a grapheme cluster: this is usually the right
184
// choice for movement or selection by "character"
185
// as perceived by the user
186
eSelectWord = 2,
187
eSelectWordNoSpace = 3, // select a "word" without selecting the following
188
// space, no matter what the default platform
189
// behavior is
190
eSelectLine = 4, // previous drawn line in flow.
191
// NOTE that selection code depends on the ordering of the above values,
192
// allowing simple <= tests to check categories of caret movement.
193
// Don't rearrange without checking the usage in nsSelection.cpp!
194
195
eSelectBeginLine = 5,
196
eSelectEndLine = 6,
197
eSelectNoAmount = 7, // just bounce back current offset.
198
eSelectParagraph = 8 // select a "paragraph"
199
};
200
201
//----------------------------------------------------------------------
202
// Reflow status returned by the Reflow() methods.
203
class nsReflowStatus final {
204
using StyleClear = mozilla::StyleClear;
205
206
public:
207
nsReflowStatus()
208
: mBreakType(StyleClear::None),
209
mInlineBreak(InlineBreak::None),
210
mCompletion(Completion::FullyComplete),
211
mNextInFlowNeedsReflow(false),
212
mTruncated(false),
213
mFirstLetterComplete(false) {}
214
215
// Reset all the member variables.
216
void Reset() {
217
mBreakType = StyleClear::None;
218
mInlineBreak = InlineBreak::None;
219
mCompletion = Completion::FullyComplete;
220
mNextInFlowNeedsReflow = false;
221
mTruncated = false;
222
mFirstLetterComplete = false;
223
}
224
225
// Return true if all member variables have their default values.
226
bool IsEmpty() const {
227
return (IsFullyComplete() && !IsInlineBreak() && !mNextInFlowNeedsReflow &&
228
!mTruncated && !mFirstLetterComplete);
229
}
230
231
// There are three possible completion statuses, represented by
232
// mCompletion.
233
//
234
// Incomplete means the frame does *not* map all its content, and the
235
// parent frame should create a continuing frame.
236
//
237
// OverflowIncomplete means that the frame has an overflow that is not
238
// complete, but its own box is complete. (This happens when the content
239
// overflows a fixed-height box.) The reflower should place and size the
240
// frame and continue its reflow, but it needs to create an overflow
241
// container as a continuation for this frame. See "Overflow containers"
242
// documentation in nsContainerFrame.h for more information.
243
//
244
// FullyComplete means the frame is neither Incomplete nor
245
// OverflowIncomplete. This is the default state for a nsReflowStatus.
246
//
247
enum class Completion : uint8_t {
248
// The order of the enum values is important, which represents the
249
// precedence when merging.
250
FullyComplete,
251
OverflowIncomplete,
252
Incomplete,
253
};
254
255
bool IsIncomplete() const { return mCompletion == Completion::Incomplete; }
256
bool IsOverflowIncomplete() const {
257
return mCompletion == Completion::OverflowIncomplete;
258
}
259
bool IsFullyComplete() const {
260
return mCompletion == Completion::FullyComplete;
261
}
262
// Just for convenience; not a distinct state.
263
bool IsComplete() const { return !IsIncomplete(); }
264
265
void SetIncomplete() { mCompletion = Completion::Incomplete; }
266
void SetOverflowIncomplete() { mCompletion = Completion::OverflowIncomplete; }
267
268
// mNextInFlowNeedsReflow bit flag means that the next-in-flow is dirty,
269
// and also needs to be reflowed. This status only makes sense for a frame
270
// that is not complete, i.e. you wouldn't set mNextInFlowNeedsReflow when
271
// IsComplete() is true.
272
bool NextInFlowNeedsReflow() const { return mNextInFlowNeedsReflow; }
273
void SetNextInFlowNeedsReflow() { mNextInFlowNeedsReflow = true; }
274
275
// mTruncated bit flag means that the part of the frame before the first
276
// possible break point was unable to fit in the available space.
277
// Therefore, the entire frame should be moved to the next continuation of
278
// the parent frame. A frame that begins at the top of the page must never
279
// be truncated. Doing so would likely cause an infinite loop.
280
bool IsTruncated() const { return mTruncated; }
281
void UpdateTruncated(const mozilla::ReflowInput& aReflowInput,
282
const mozilla::ReflowOutput& aMetrics);
283
284
// Merge the frame completion status bits from aStatus into this.
285
void MergeCompletionStatusFrom(const nsReflowStatus& aStatus) {
286
if (mCompletion < aStatus.mCompletion) {
287
mCompletion = aStatus.mCompletion;
288
}
289
290
// These asserts ensure that the mCompletion merging works as we expect.
291
// (Incomplete beats OverflowIncomplete, which beats FullyComplete.)
292
static_assert(
293
Completion::Incomplete > Completion::OverflowIncomplete &&
294
Completion::OverflowIncomplete > Completion::FullyComplete,
295
"mCompletion merging won't work without this!");
296
297
mNextInFlowNeedsReflow |= aStatus.mNextInFlowNeedsReflow;
298
mTruncated |= aStatus.mTruncated;
299
}
300
301
// There are three possible inline-break statuses, represented by
302
// mInlineBreak.
303
//
304
// "None" means no break is requested.
305
// "Before" means the break should occur before the frame.
306
// "After" means the break should occur after the frame.
307
// (Here, "the frame" is the frame whose reflow results are being reported by
308
// this nsReflowStatus.)
309
//
310
enum class InlineBreak : uint8_t {
311
None,
312
Before,
313
After,
314
};
315
316
bool IsInlineBreak() const { return mInlineBreak != InlineBreak::None; }
317
bool IsInlineBreakBefore() const {
318
return mInlineBreak == InlineBreak::Before;
319
}
320
bool IsInlineBreakAfter() const { return mInlineBreak == InlineBreak::After; }
321
StyleClear BreakType() const { return mBreakType; }
322
323
// Set the inline line-break-before status, and reset other bit flags. The
324
// break type is StyleClear::Line. Note that other frame completion status
325
// isn't expected to matter after calling this method.
326
void SetInlineLineBreakBeforeAndReset() {
327
Reset();
328
mBreakType = StyleClear::Line;
329
mInlineBreak = InlineBreak::Before;
330
}
331
332
// Set the inline line-break-after status. The break type can be changed
333
// via the optional aBreakType param.
334
void SetInlineLineBreakAfter(StyleClear aBreakType = StyleClear::Line) {
335
MOZ_ASSERT(aBreakType != StyleClear::None,
336
"Break-after with StyleClear::None is meaningless!");
337
mBreakType = aBreakType;
338
mInlineBreak = InlineBreak::After;
339
}
340
341
// mFirstLetterComplete bit flag means the break was induced by
342
// completion of a first-letter.
343
bool FirstLetterComplete() const { return mFirstLetterComplete; }
344
void SetFirstLetterComplete() { mFirstLetterComplete = true; }
345
346
private:
347
StyleClear mBreakType;
348
InlineBreak mInlineBreak;
349
Completion mCompletion;
350
bool mNextInFlowNeedsReflow : 1;
351
bool mTruncated : 1;
352
bool mFirstLetterComplete : 1;
353
};
354
355
#define NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aMetrics) \
356
aStatus.UpdateTruncated(aReflowInput, aMetrics);
357
358
// Convert nsReflowStatus to a human-readable string.
359
std::ostream& operator<<(std::ostream& aStream, const nsReflowStatus& aStatus);
360
361
//----------------------------------------------------------------------
362
363
/**
364
* When there is no scrollable overflow rect, the visual overflow rect
365
* may be stored as four 1-byte deltas each strictly LESS THAN 0xff, for
366
* the four edges of the rectangle, or the four bytes may be read as a
367
* single 32-bit "overflow-rect type" value including at least one 0xff
368
* byte as an indicator that the value does NOT represent four deltas.
369
* If all four deltas are zero, this means that no overflow rect has
370
* actually been set (this is the initial state of newly-created frames).
371
*/
372
373
// max delta we can store
374
#define NS_FRAME_OVERFLOW_DELTA_MAX 0xfe
375
376
// there are no overflow rects; code relies on this being the all-zero value
377
#define NS_FRAME_OVERFLOW_NONE 0x00000000
378
379
// overflow is stored as a separate rect property
380
#define NS_FRAME_OVERFLOW_LARGE 0x000000ff
381
382
/**
383
* nsBidiLevel is the type of the level values in our Unicode Bidi
384
* implementation.
385
* It holds an embedding level and indicates the visual direction
386
* by its bit 0 (even/odd value).<p>
387
*
388
* <li><code>aParaLevel</code> can be set to the
389
* pseudo-level values <code>NSBIDI_DEFAULT_LTR</code>
390
* and <code>NSBIDI_DEFAULT_RTL</code>.</li></ul>
391
*
392
* @see nsBidi::SetPara
393
*
394
* <p>The related constants are not real, valid level values.
395
* <code>NSBIDI_DEFAULT_XXX</code> can be used to specify
396
* a default for the paragraph level for
397
* when the <code>SetPara</code> function
398
* shall determine it but there is no
399
* strongly typed character in the input.<p>
400
*
401
* Note that the value for <code>NSBIDI_DEFAULT_LTR</code> is even
402
* and the one for <code>NSBIDI_DEFAULT_RTL</code> is odd,
403
* just like with normal LTR and RTL level values -
404
* these special values are designed that way. Also, the implementation
405
* assumes that NSBIDI_MAX_EXPLICIT_LEVEL is odd.
406
*
407
* @see NSBIDI_DEFAULT_LTR
408
* @see NSBIDI_DEFAULT_RTL
409
* @see NSBIDI_LEVEL_OVERRIDE
410
* @see NSBIDI_MAX_EXPLICIT_LEVEL
411
*/
412
typedef uint8_t nsBidiLevel;
413
414
/**
415
* Paragraph level setting.
416
* If there is no strong character, then set the paragraph level to 0
417
* (left-to-right).
418
*/
419
#define NSBIDI_DEFAULT_LTR 0xfe
420
421
/**
422
* Paragraph level setting.
423
* If there is no strong character, then set the paragraph level to 1
424
* (right-to-left).
425
*/
426
#define NSBIDI_DEFAULT_RTL 0xff
427
428
/**
429
* Maximum explicit embedding level.
430
* (The maximum resolved level can be up to
431
* <code>NSBIDI_MAX_EXPLICIT_LEVEL+1</code>).
432
*/
433
#define NSBIDI_MAX_EXPLICIT_LEVEL 125
434
435
/** Bit flag for level input.
436
* Overrides directional properties.
437
*/
438
#define NSBIDI_LEVEL_OVERRIDE 0x80
439
440
/**
441
* <code>nsBidiDirection</code> values indicate the text direction.
442
*/
443
enum nsBidiDirection {
444
/** All left-to-right text This is a 0 value. */
445
NSBIDI_LTR,
446
/** All right-to-left text This is a 1 value. */
447
NSBIDI_RTL,
448
/** Mixed-directional text. */
449
NSBIDI_MIXED
450
};
451
452
namespace mozilla {
453
455
enum class BaselineSharingGroup {
456
// NOTE Used as an array index so must be 0 and 1.
457
First = 0,
458
Last = 1,
459
};
460
462
enum class AlignmentContext {
463
Inline,
464
Table,
465
Flexbox,
466
Grid,
467
};
468
469
/*
470
* For replaced elements only. Gets the intrinsic dimensions of this element,
471
* which can be specified on a per-axis basis.
472
*/
473
struct IntrinsicSize {
474
Maybe<nscoord> width;
475
Maybe<nscoord> height;
476
477
IntrinsicSize() = default;
478
479
IntrinsicSize(nscoord aWidth, nscoord aHeight)
480
: width(Some(aWidth)), height(Some(aHeight)) {}
481
482
bool operator==(const IntrinsicSize& rhs) {
483
return width == rhs.width && height == rhs.height;
484
}
485
bool operator!=(const IntrinsicSize& rhs) { return !(*this == rhs); }
486
};
487
488
// Pseudo bidi embedding level indicating nonexistence.
489
static const nsBidiLevel kBidiLevelNone = 0xff;
490
491
struct FrameBidiData {
492
nsBidiLevel baseLevel;
493
nsBidiLevel embeddingLevel;
494
// The embedding level of virtual bidi formatting character before
495
// this frame if any. kBidiLevelNone is used to indicate nonexistence
496
// or unnecessity of such virtual character.
497
nsBidiLevel precedingControl;
498
};
499
500
} // namespace mozilla
501
502
/// Generic destructor for frame properties. Calls delete.
503
template <typename T>
504
static void DeleteValue(T* aPropertyValue) {
505
delete aPropertyValue;
506
}
507
508
/// Generic destructor for frame properties. Calls Release().
509
template <typename T>
510
static void ReleaseValue(T* aPropertyValue) {
511
aPropertyValue->Release();
512
}
513
514
//----------------------------------------------------------------------
515
516
/**
517
* A frame in the layout model. This interface is supported by all frame
518
* objects.
519
*
520
* Frames can have multiple child lists: the default child list
521
* (referred to as the <i>principal</i> child list, and additional named
522
* child lists. There is an ordering of frames within a child list, but
523
* there is no order defined between frames in different child lists of
524
* the same parent frame.
525
*
526
* Frames are NOT reference counted. Use the Destroy() member function
527
* to destroy a frame. The lifetime of the frame hierarchy is bounded by the
528
* lifetime of the presentation shell which owns the frames.
529
*
530
* nsIFrame is a private Gecko interface. If you are not Gecko then you
531
* should not use it. If you're not in layout, then you won't be able to
532
* link to many of the functions defined here. Too bad.
533
*
534
* If you're not in layout but you must call functions in here, at least
535
* restrict yourself to calling virtual methods, which won't hurt you as badly.
536
*/
537
class nsIFrame : public nsQueryFrame {
538
public:
539
using AlignmentContext = mozilla::AlignmentContext;
540
using BaselineSharingGroup = mozilla::BaselineSharingGroup;
541
template <typename T>
542
using Maybe = mozilla::Maybe<T>;
543
using Nothing = mozilla::Nothing;
544
using OnNonvisible = mozilla::OnNonvisible;
545
template <typename T = void>
546
using PropertyDescriptor = const mozilla::FramePropertyDescriptor<T>*;
547
using ReflowInput = mozilla::ReflowInput;
548
using ReflowOutput = mozilla::ReflowOutput;
549
using Visibility = mozilla::Visibility;
550
using StyleFlexBasis = mozilla::StyleFlexBasis;
551
using StyleSize = mozilla::StyleSize;
552
using LengthPercentage = mozilla::LengthPercentage;
553
using StyleExtremumLength = mozilla::StyleExtremumLength;
554
555
typedef mozilla::ComputedStyle ComputedStyle;
556
typedef mozilla::FrameProperties FrameProperties;
557
typedef mozilla::layers::Layer Layer;
558
typedef mozilla::layers::LayerManager LayerManager;
559
typedef mozilla::layout::FrameChildList ChildList;
560
typedef mozilla::layout::FrameChildListID ChildListID;
561
typedef mozilla::layout::FrameChildListIDs ChildListIDs;
562
typedef mozilla::layout::FrameChildListIterator ChildListIterator;
563
typedef mozilla::layout::FrameChildListArrayIterator ChildListArrayIterator;
564
typedef mozilla::gfx::DrawTarget DrawTarget;
565
typedef mozilla::gfx::Matrix Matrix;
566
typedef mozilla::gfx::Matrix4x4 Matrix4x4;
567
typedef mozilla::gfx::Matrix4x4Flagged Matrix4x4Flagged;
568
typedef mozilla::Sides Sides;
569
typedef mozilla::LogicalSides LogicalSides;
570
typedef mozilla::SmallPointerArray<mozilla::DisplayItemData>
571
DisplayItemDataArray;
572
typedef nsQueryFrame::ClassID ClassID;
573
574
NS_DECL_QUERYFRAME_TARGET(nsIFrame)
575
576
explicit nsIFrame(ComputedStyle* aStyle, nsPresContext* aPresContext,
577
ClassID aID)
578
: mRect(),
579
mContent(nullptr),
580
mComputedStyle(aStyle),
581
mPresContext(aPresContext),
582
mParent(nullptr),
583
mNextSibling(nullptr),
584
mPrevSibling(nullptr),
585
mState(NS_FRAME_FIRST_REFLOW | NS_FRAME_IS_DIRTY),
586
mWritingMode(aStyle),
587
mClass(aID),
588
mMayHaveRoundedCorners(false),
589
mHasImageRequest(false),
590
mHasFirstLetterChild(false),
591
mParentIsWrapperAnonBox(false),
592
mIsWrapperBoxNeedingRestyle(false),
593
mReflowRequestedForCharDataChange(false),
594
mForceDescendIntoIfVisible(false),
595
mBuiltDisplayList(false),
596
mFrameIsModified(false),
597
mHasOverrideDirtyRegion(false),
598
mMayHaveWillChangeBudget(false),
599
mIsPrimaryFrame(false),
600
mMayHaveTransformAnimation(false),
601
mMayHaveOpacityAnimation(false),
602
mAllDescendantsAreInvisible(false),
603
mHasBSizeChange(false),
604
mInScrollAnchorChain(false),
605
mHasColumnSpanSiblings(false),
606
mDescendantMayDependOnItsStaticPosition(false) {
607
MOZ_ASSERT(mComputedStyle);
608
MOZ_ASSERT(mPresContext);
609
mozilla::PodZero(&mOverflow);
610
}
611
612
nsPresContext* PresContext() const { return mPresContext; }
613
614
mozilla::PresShell* PresShell() const { return PresContext()->PresShell(); }
615
616
/**
617
* Called to initialize the frame. This is called immediately after creating
618
* the frame.
619
*
620
* If the frame is a continuing frame, then aPrevInFlow indicates the previous
621
* frame (the frame that was split).
622
*
623
* Each subclass that need a view should override this method and call
624
* CreateView() after calling its base class Init().
625
*
626
* @param aContent the content object associated with the frame
627
* @param aParent the parent frame
628
* @param aPrevInFlow the prev-in-flow frame
629
*/
630
virtual void Init(nsIContent* aContent, nsContainerFrame* aParent,
631
nsIFrame* aPrevInFlow) = 0;
632
633
using PostDestroyData = mozilla::layout::PostFrameDestroyData;
634
struct MOZ_RAII AutoPostDestroyData {
635
explicit AutoPostDestroyData(nsPresContext* aPresContext)
636
: mPresContext(aPresContext) {}
637
~AutoPostDestroyData() {
638
for (auto& content : mozilla::Reversed(mData.mAnonymousContent)) {
639
nsIFrame::DestroyAnonymousContent(mPresContext, content.forget());
640
}
641
}
642
nsPresContext* mPresContext;
643
PostDestroyData mData;
644
};
645
/**
646
* Destroys this frame and each of its child frames (recursively calls
647
* Destroy() for each child). If this frame is a first-continuation, this
648
* also removes the frame from the primary frame map and clears undisplayed
649
* content for its content node.
650
* If the frame is a placeholder, it also ensures the out-of-flow frame's
651
* removal and destruction.
652
*/
653
void Destroy() {
654
AutoPostDestroyData data(PresContext());
655
DestroyFrom(this, data.mData);
656
// Note that |this| is deleted at this point.
657
}
658
659
/**
660
* Flags for PeekOffsetCharacter, PeekOffsetNoAmount, PeekOffsetWord return
661
* values.
662
*/
663
enum FrameSearchResult {
664
// Peek found a appropriate offset within frame.
665
FOUND = 0x00,
666
// try next frame for offset.
667
CONTINUE = 0x1,
668
// offset not found because the frame was empty of text.
669
CONTINUE_EMPTY = 0x2 | CONTINUE,
670
// offset not found because the frame didn't contain any text that could be
671
// selected.
672
CONTINUE_UNSELECTABLE = 0x4 | CONTINUE,
673
};
674
675
/**
676
* Options for PeekOffsetCharacter().
677
*/
678
struct MOZ_STACK_CLASS PeekOffsetCharacterOptions {
679
// Whether to restrict result to valid cursor locations (between grapheme
680
// clusters) - if this is included, maintains "normal" behavior, otherwise,
681
// used for selection by "code unit" (instead of "character")
682
bool mRespectClusters;
683
// Whether to check user-select style value - if this is included, checks
684
// if user-select is all, then, it may return CONTINUE_UNSELECTABLE.
685
bool mIgnoreUserStyleAll;
686
687
PeekOffsetCharacterOptions()
688
: mRespectClusters(true), mIgnoreUserStyleAll(false) {}
689
};
690
691
protected:
692
friend class nsBlockFrame; // for access to DestroyFrom
693
694
/**
695
* Return true if the frame is part of a Selection.
696
* Helper method to implement the public IsSelected() API.
697
*/
698
virtual bool IsFrameSelected() const;
699
700
/**
701
* Implements Destroy(). Do not call this directly except from within a
702
* DestroyFrom() implementation.
703
*
704
* @note This will always be called, so it is not necessary to override
705
* Destroy() in subclasses of nsFrame, just DestroyFrom().
706
*
707
* @param aDestructRoot is the root of the subtree being destroyed
708
*/
709
virtual void DestroyFrom(nsIFrame* aDestructRoot,
710
PostDestroyData& aPostDestroyData) = 0;
711
friend class nsFrameList; // needed to pass aDestructRoot through to children
712
friend class nsLineBox; // needed to pass aDestructRoot through to children
713
friend class nsContainerFrame; // needed to pass aDestructRoot through to
714
// children
715
friend class nsFrame; // need to assign mParent
716
template <class Source>
717
friend class do_QueryFrameHelper; // to read mClass
718
public:
719
/**
720
* Get the content object associated with this frame. Does not add a
721
* reference.
722
*/
723
nsIContent* GetContent() const { return mContent; }
724
725
/**
726
* Get the frame that should be the parent for the frames of child elements
727
* May return nullptr during reflow
728
*/
729
virtual nsContainerFrame* GetContentInsertionFrame() { return nullptr; }
730
731
/**
732
* Move any frames on our overflow list to the end of our principal list.
733
* @return true if there were any overflow frames
734
*/
735
virtual bool DrainSelfOverflowList() { return false; }
736
737
/**
738
* Get the frame that should be scrolled if the content associated
739
* with this frame is targeted for scrolling. For frames implementing
740
* nsIScrollableFrame this will return the frame itself. For frames
741
* like nsTextControlFrame that contain a scrollframe, will return
742
* that scrollframe.
743
*/
744
virtual nsIScrollableFrame* GetScrollTargetFrame() { return nullptr; }
745
746
/**
747
* Get the offsets of the frame. most will be 0,0
748
*
749
*/
750
virtual nsresult GetOffsets(int32_t& start, int32_t& end) const = 0;
751
752
/**
753
* Reset the offsets when splitting frames during Bidi reordering
754
*
755
*/
756
virtual void AdjustOffsetsForBidi(int32_t aStart, int32_t aEnd) {}
757
758
/**
759
* Get the style associated with this frame.
760
*/
761
ComputedStyle* Style() const { return mComputedStyle; }
762
763
void AssertNewStyleIsSane(ComputedStyle&)
764
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
765
;
766
#else
767
{
768
}
769
#endif
770
771
void SetComputedStyle(ComputedStyle* aStyle) {
772
if (aStyle != mComputedStyle) {
773
AssertNewStyleIsSane(*aStyle);
774
RefPtr<ComputedStyle> oldComputedStyle = mComputedStyle.forget();
775
mComputedStyle = aStyle;
776
DidSetComputedStyle(oldComputedStyle);
777
}
778
}
779
780
/**
781
* SetComputedStyleWithoutNotification is for changes to the style
782
* context that should suppress style change processing, in other
783
* words, those that aren't really changes. This generally means only
784
* changes that happen during frame construction.
785
*/
786
void SetComputedStyleWithoutNotification(ComputedStyle* aStyle) {
787
if (aStyle != mComputedStyle) {
788
mComputedStyle = aStyle;
789
}
790
}
791
792
// Style post processing hook
793
// Attention: the old style is the one we're forgetting,
794
// and hence possibly completely bogus for GetStyle* purposes.
795
// Use PeekStyleData instead.
796
virtual void DidSetComputedStyle(ComputedStyle* aOldComputedStyle) = 0;
797
798
/**
799
* Define typesafe getter functions for each style struct by
800
* preprocessing the list of style structs. These functions are the
801
* preferred way to get style data. The macro creates functions like:
802
* const nsStyleBorder* StyleBorder();
803
* const nsStyleColor* StyleColor();
804
*
805
* Callers outside of libxul should use nsIDOMWindow::GetComputedStyle()
806
* instead of these accessors.
807
*
808
* Callers can use Style*WithOptionalParam if they're in a function that
809
* accepts an *optional* pointer the style struct.
810
*/
811
#define STYLE_STRUCT(name_) \
812
const nsStyle##name_* Style##name_() const MOZ_NONNULL_RETURN { \
813
NS_ASSERTION(mComputedStyle, "No style found!"); \
814
return mComputedStyle->Style##name_(); \
815
} \
816
const nsStyle##name_* Style##name_##WithOptionalParam( \
817
const nsStyle##name_* aStyleStruct) const MOZ_NONNULL_RETURN { \
818
if (aStyleStruct) { \
819
MOZ_ASSERT(aStyleStruct == Style##name_()); \
820
return aStyleStruct; \
821
} \
822
return Style##name_(); \
823
}
824
#include "nsStyleStructList.h"
825
#undef STYLE_STRUCT
826
827
/** Also forward GetVisitedDependentColor to the style */
828
template <typename T, typename S>
829
nscolor GetVisitedDependentColor(T S::*aField) {
830
return mComputedStyle->GetVisitedDependentColor(aField);
831
}
832
833
/**
834
* These methods are to access any additional ComputedStyles that
835
* the frame may be holding.
836
*
837
* These are styles that are children of the frame's primary style and are NOT
838
* used as styles for any child frames.
839
*
840
* These contexts also MUST NOT have any child styles whatsoever. If you need
841
* to insert styles into the style tree, then you should create pseudo element
842
* frames to own them.
843
*
844
* The indicies must be consecutive and implementations MUST return null if
845
* asked for an index that is out of range.
846
*/
847
virtual ComputedStyle* GetAdditionalComputedStyle(int32_t aIndex) const = 0;
848
849
virtual void SetAdditionalComputedStyle(int32_t aIndex,
850
ComputedStyle* aComputedStyle) = 0;
851
852
already_AddRefed<ComputedStyle> ComputeSelectionStyle(
853
int16_t aSelectionStatus) const;
854
855
/**
856
* Accessor functions for geometric parent.
857
*/
858
nsContainerFrame* GetParent() const { return mParent; }
859
860
/**
861
* Gets the parent of a frame, using the parent of the placeholder for
862
* out-of-flow frames.
863
*/
864
inline nsContainerFrame* GetInFlowParent() const;
865
866
/**
867
* Gets the primary frame of the closest flattened tree ancestor that has a
868
* frame (flattened tree ancestors may not have frames in presence of display:
869
* contents).
870
*/
871
inline nsIFrame* GetClosestFlattenedTreeAncestorPrimaryFrame() const;
872
873
/**
874
* Return the placeholder for this frame (which must be out-of-flow).
875
* @note this will only return non-null if |this| is the first-in-flow
876
* although we don't assert that here for legacy reasons.
877
*/
878
inline nsPlaceholderFrame* GetPlaceholderFrame() const {
879
MOZ_ASSERT(HasAnyStateBits(NS_FRAME_OUT_OF_FLOW));
880
return GetProperty(PlaceholderFrameProperty());
881
}
882
883
/**
884
* Set this frame's parent to aParent.
885
* If the frame may have moved into or out of a scrollframe's
886
* frame subtree,
887
* StickyScrollContainer::NotifyReparentedFrameAcrossScrollFrameBoundary must
888
* also be called.
889
*/
890
void SetParent(nsContainerFrame* aParent);
891
892
/**
893
* The frame's writing-mode, used for logical layout computations.
894
* It's usually the 'writing-mode' computed value, but there are exceptions:
895
* * inner table frames copy the value from the table frame
896
* (@see nsTableRowGroupFrame::Init, nsTableRowFrame::Init etc)
897
* * the root element frame propagates its value to its ancestors.
898
* The value may obtain from the principal <body> element.
899
* (@see nsCSSFrameConstructor::ConstructDocElementFrame)
900
* * the internal anonymous frames of the root element copy their value
901
* from the parent.
902
* (@see nsFrame::Init)
903
* * a scrolled frame propagates its value to its ancestor scroll frame
904
* (@see nsHTMLScrollFrame::ReloadChildFrames)
905
*/
906
mozilla::WritingMode GetWritingMode() const { return mWritingMode; }
907
908
/**
909
* Construct a writing mode for line layout in this frame. This is
910
* the writing mode of this frame, except that if this frame is styled with
911
* unicode-bidi:plaintext, we reset the direction to the resolved paragraph
912
* level of the given subframe (typically the first frame on the line),
913
* because the container frame could be split by hard line breaks into
914
* multiple paragraphs with different base direction.
915
* @param aSelfWM the WM of 'this'
916
*/
917
mozilla::WritingMode WritingModeForLine(mozilla::WritingMode aSelfWM,
918
nsIFrame* aSubFrame) const;
919
920
/**
921
* Bounding rect of the frame.
922
*
923
* For frames that are laid out according to CSS box model rules the values
924
* are in app units, and the origin is relative to the upper-left of the
925
* geometric parent. The size includes the content area, borders, and
926
* padding.
927
*
928
* Frames that are laid out according to SVG's coordinate space based rules
929
* (frames with the NS_FRAME_SVG_LAYOUT bit set, which *excludes*
930
* nsSVGOuterSVGFrame) are different. Many frames of this type do not set or
931
* use mRect, in which case the frame rect is undefined. The exceptions are:
932
*
933
* - nsSVGInnerSVGFrame
934
* - SVGGeometryFrame (used for <path>, <circle>, etc.)
935
* - nsSVGImageFrame
936
* - nsSVGForeignObjectFrame
937
*
938
* For these frames the frame rect contains the frame's element's userspace
939
* bounds including fill, stroke and markers, but converted to app units
940
* rather than being in user units (CSS px). In the SVG code "userspace" is
941
* defined to be the coordinate system for the attributes that define an
942
* element's geometry (such as the 'cx' attribute for <circle>). For more
943
* precise details see these frames' implementations of the ReflowSVG method
944
* where mRect is set.
945
*
946
* Note: moving or sizing the frame does not affect the view's size or
947
* position.
948
*/
949
nsRect GetRect() const { return mRect; }
950
nsPoint GetPosition() const { return mRect.TopLeft(); }
951
nsSize GetSize() const { return mRect.Size(); }
952
nsRect GetRectRelativeToSelf() const {
953
return nsRect(nsPoint(0, 0), mRect.Size());
954
}
955
/**
956
* Dimensions and position in logical coordinates in the frame's writing mode
957
* or another writing mode
958
*/
959
mozilla::LogicalRect GetLogicalRect(const nsSize& aContainerSize) const {
960
return GetLogicalRect(GetWritingMode(), aContainerSize);
961
}
962
mozilla::LogicalPoint GetLogicalPosition(const nsSize& aContainerSize) const {
963
return GetLogicalPosition(GetWritingMode(), aContainerSize);
964
}
965
mozilla::LogicalSize GetLogicalSize() const {
966
return GetLogicalSize(GetWritingMode());
967
}
968
mozilla::LogicalRect GetLogicalRect(mozilla::WritingMode aWritingMode,
969
const nsSize& aContainerSize) const {
970
return mozilla::LogicalRect(aWritingMode, GetRect(), aContainerSize);
971
}
972
mozilla::LogicalPoint GetLogicalPosition(mozilla::WritingMode aWritingMode,
973
const nsSize& aContainerSize) const {
974
return GetLogicalRect(aWritingMode, aContainerSize).Origin(aWritingMode);
975
}
976
mozilla::LogicalSize GetLogicalSize(mozilla::WritingMode aWritingMode) const {
977
return mozilla::LogicalSize(aWritingMode, GetSize());
978
}
979
nscoord IStart(const nsSize& aContainerSize) const {
980
return IStart(GetWritingMode(), aContainerSize);
981
}
982
nscoord IStart(mozilla::WritingMode aWritingMode,
983
const nsSize& aContainerSize) const {
984
return GetLogicalPosition(aWritingMode, aContainerSize).I(aWritingMode);
985
}
986
nscoord BStart(const nsSize& aContainerSize) const {
987
return BStart(GetWritingMode(), aContainerSize);
988
}
989
nscoord BStart(mozilla::WritingMode aWritingMode,
990
const nsSize& aContainerSize) const {
991
return GetLogicalPosition(aWritingMode, aContainerSize).B(aWritingMode);
992
}
993
nscoord ISize() const { return ISize(GetWritingMode()); }
994
nscoord ISize(mozilla::WritingMode aWritingMode) const {
995
return GetLogicalSize(aWritingMode).ISize(aWritingMode);
996
}
997
nscoord BSize() const { return BSize(GetWritingMode()); }
998
nscoord BSize(mozilla::WritingMode aWritingMode) const {
999
return GetLogicalSize(aWritingMode).BSize(aWritingMode);
1000
}
1001
nscoord ContentBSize() const { return ContentBSize(GetWritingMode()); }
1002
nscoord ContentBSize(mozilla::WritingMode aWritingMode) const {
1003
auto bp = GetLogicalUsedBorderAndPadding(aWritingMode);
1004
bp.ApplySkipSides(GetLogicalSkipSides());
1005
return std::max(0, BSize(aWritingMode) - bp.BStartEnd(aWritingMode));
1006
}
1007
1008
/**
1009
* When we change the size of the frame's border-box rect, we may need to
1010
* reset the overflow rect if it was previously stored as deltas.
1011
* (If it is currently a "large" overflow and could be re-packed as deltas,
1012
* we don't bother as the cost of the allocation has already been paid.)
1013
* @param aRebuildDisplayItems If true, then adds this frame to the
1014
* list of modified frames for display list building if the rect has changed.
1015
* Only pass false if you're sure that the relevant display items will be
1016
* rebuilt already (possibly by an ancestor being in the modified list), or if
1017
* this is a temporary change.
1018
*/
1019
void SetRect(const nsRect& aRect, bool aRebuildDisplayItems = true) {
1020
if (aRect == mRect) {
1021
return;
1022
}
1023
if (mOverflow.mType != NS_FRAME_OVERFLOW_LARGE &&
1024
mOverflow.mType != NS_FRAME_OVERFLOW_NONE) {
1025
nsOverflowAreas overflow = GetOverflowAreas();
1026
mRect = aRect;
1027
SetOverflowAreas(overflow);
1028
} else {
1029
mRect = aRect;
1030
}
1031
if (aRebuildDisplayItems) {
1032
MarkNeedsDisplayItemRebuild();
1033
}
1034
}
1035
/**
1036
* Set this frame's rect from a logical rect in its own writing direction
1037
*/
1038
void SetRect(const mozilla::LogicalRect& aRect,
1039
const nsSize& aContainerSize) {
1040
SetRect(GetWritingMode(), aRect, aContainerSize);
1041
}
1042
/**
1043
* Set this frame's rect from a logical rect in a different writing direction
1044
* (GetPhysicalRect will assert if the writing mode doesn't match)
1045
*/
1046
void SetRect(mozilla::WritingMode aWritingMode,
1047
const mozilla::LogicalRect& aRect,
1048
const nsSize& aContainerSize) {
1049
SetRect(aRect.GetPhysicalRect(aWritingMode, aContainerSize));
1050
}
1051
1052
/**
1053
* Set this frame's size from a logical size in its own writing direction.
1054
* This leaves the frame's logical position unchanged, which means its
1055
* physical position may change (for right-to-left modes).
1056
*/
1057
void SetSize(const mozilla::LogicalSize& aSize) {
1058
SetSize(GetWritingMode(), aSize);
1059
}
1060
/*
1061
* Set this frame's size from a logical size in a different writing direction.
1062
* This leaves the frame's logical position in the given mode unchanged,
1063
* which means its physical position may change (for right-to-left modes).
1064
*/
1065
void SetSize(mozilla::WritingMode aWritingMode,
1066
const mozilla::LogicalSize& aSize) {
1067
if ((!aWritingMode.IsVertical() && !aWritingMode.IsBidiLTR()) ||
1068
aWritingMode.IsVerticalRL()) {
1069
nscoord oldWidth = mRect.Width();
1070
SetSize(aSize.GetPhysicalSize(aWritingMode));
1071
mRect.x -= mRect.Width() - oldWidth;
1072
} else {
1073
SetSize(aSize.GetPhysicalSize(aWritingMode));
1074
}
1075
}
1076
1077
/**
1078
* Set this frame's physical size. This leaves the frame's physical position
1079
* (topLeft) unchanged.
1080
* @param aRebuildDisplayItems If true, then adds this frame to the
1081
* list of modified frames for display list building if the size has changed.
1082
* Only pass false if you're sure that the relevant display items will be
1083
* rebuilt already (possibly by an ancestor being in the modified list), or if
1084
* this is a temporary change.
1085
*/
1086
void SetSize(const nsSize& aSize, bool aRebuildDisplayItems = true) {
1087
SetRect(nsRect(mRect.TopLeft(), aSize), aRebuildDisplayItems);
1088
}
1089
1090
void SetPosition(const nsPoint& aPt) {
1091
if (mRect.TopLeft() == aPt) {
1092
return;
1093
}
1094
mRect.MoveTo(aPt);
1095
MarkNeedsDisplayItemRebuild();
1096
}
1097
void SetPosition(mozilla::WritingMode aWritingMode,
1098
const mozilla::LogicalPoint& aPt,
1099
const nsSize& aContainerSize) {
1100
// We subtract mRect.Size() from the container size to account for
1101
// the fact that logical origins in RTL coordinate systems are at
1102
// the top right of the frame instead of the top left.
1103
SetPosition(
1104
aPt.GetPhysicalPoint(aWritingMode, aContainerSize - mRect.Size()));
1105
}
1106
1107
/**
1108
* Move the frame, accounting for relative positioning. Use this when
1109
* adjusting the frame's position by a known amount, to properly update its
1110
* saved normal position (see GetNormalPosition below).
1111
*
1112
* This must be used only when moving a frame *after*
1113
* ReflowInput::ApplyRelativePositioning is called. When moving
1114
* a frame during the reflow process prior to calling
1115
* ReflowInput::ApplyRelativePositioning, the position should
1116
* simply be adjusted directly (e.g., using SetPosition()).
1117
*/
1118
void MovePositionBy(const nsPoint& aTranslation);
1119
1120
/**
1121
* As above, using a logical-point delta in a given writing mode.
1122
*/
1123
void MovePositionBy(mozilla::WritingMode aWritingMode,
1124
const mozilla::LogicalPoint& aTranslation) {
1125
// The LogicalPoint represents a vector rather than a point within a
1126
// rectangular coordinate space, so we use a null containerSize when
1127
// converting logical to physical.
1128
const nsSize nullContainerSize;
1129
MovePositionBy(
1130
aTranslation.GetPhysicalPoint(aWritingMode, nullContainerSize));
1131
}
1132
1133
/**
1134
* Return frame's rect without relative positioning
1135
*/
1136
nsRect GetNormalRect() const;
1137
1138
/**
1139
* Return frame's position without relative positioning.
1140
* If aHasProperty is provided, returns whether the normal position
1141
* was stored in a frame property.
1142
*/
1143
inline nsPoint GetNormalPosition(bool* aHasProperty = nullptr) const;
1144
1145
mozilla::LogicalPoint GetLogicalNormalPosition(
1146
mozilla::WritingMode aWritingMode, const nsSize& aContainerSize) const {
1147
// Subtract the size of this frame from the container size to get
1148
// the correct position in rtl frames where the origin is on the
1149
// right instead of the left
1150
return mozilla::LogicalPoint(aWritingMode, GetNormalPosition(),
1151
aContainerSize - mRect.Size());
1152
}
1153
1154
virtual nsPoint GetPositionOfChildIgnoringScrolling(const nsIFrame* aChild) {
1155
return aChild->GetPosition();
1156
}
1157
1158
nsPoint GetPositionIgnoringScrolling() const;
1159
1160
typedef AutoTArray<nsDisplayItemBase*, 4> DisplayItemArray;
1161
1162
#define NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(prop, type, dtor) \
1163
static const mozilla::FramePropertyDescriptor<type>* prop() { \
1164
/* Use of constexpr caused startup crashes with MSVC2015u1 PGO. */ \
1165
static const auto descriptor = \
1166
mozilla::FramePropertyDescriptor<type>::NewWithDestructor<dtor>(); \
1167
return &descriptor; \
1168
}
1169
1170
// Don't use this unless you really know what you're doing!
1171
#define NS_DECLARE_FRAME_PROPERTY_WITH_FRAME_IN_DTOR(prop, type, dtor) \
1172
static const mozilla::FramePropertyDescriptor<type>* prop() { \
1173
/* Use of constexpr caused startup crashes with MSVC2015u1 PGO. */ \
1174
static const auto descriptor = mozilla::FramePropertyDescriptor< \
1175
type>::NewWithDestructorWithFrame<dtor>(); \
1176
return &descriptor; \
1177
}
1178
1179
#define NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(prop, type) \
1180
static const mozilla::FramePropertyDescriptor<type>* prop() { \
1181
/* Use of constexpr caused startup crashes with MSVC2015u1 PGO. */ \
1182
static const auto descriptor = \
1183
mozilla::FramePropertyDescriptor<type>::NewWithoutDestructor(); \
1184
return &descriptor; \
1185
}
1186
1187
#define NS_DECLARE_FRAME_PROPERTY_DELETABLE(prop, type) \
1188
NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(prop, type, DeleteValue)
1189
1190
#define NS_DECLARE_FRAME_PROPERTY_RELEASABLE(prop, type) \
1191
NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(prop, type, ReleaseValue)
1192
1193
#define NS_DECLARE_FRAME_PROPERTY_WITH_DTOR_NEVER_CALLED(prop, type) \
1194
static void AssertOnDestroyingProperty##prop(type*) { \
1195
MOZ_ASSERT_UNREACHABLE( \
1196
"Frame property " #prop \
1197
" should never be destroyed by the FrameProperties class"); \
1198
} \
1199
NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(prop, type, \
1200
AssertOnDestroyingProperty##prop)
1201
1202
#define NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(prop, type) \
1203
NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(prop, mozilla::SmallValueHolder<type>)
1204
1205
NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(IBSplitSibling, nsContainerFrame)
1206
NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(IBSplitPrevSibling, nsContainerFrame)
1207
1208
NS_DECLARE_FRAME_PROPERTY_DELETABLE(NormalPositionProperty, nsPoint)
1209
NS_DECLARE_FRAME_PROPERTY_DELETABLE(ComputedOffsetProperty, nsMargin)
1210
1211
NS_DECLARE_FRAME_PROPERTY_DELETABLE(OutlineInnerRectProperty, nsRect)
1212
NS_DECLARE_FRAME_PROPERTY_DELETABLE(PreEffectsBBoxProperty, nsRect)
1213
NS_DECLARE_FRAME_PROPERTY_DELETABLE(PreTransformOverflowAreasProperty,
1214
nsOverflowAreas)
1215
1216
NS_DECLARE_FRAME_PROPERTY_DELETABLE(OverflowAreasProperty, nsOverflowAreas)
1217
1218
// The initial overflow area passed to FinishAndStoreOverflow. This is only
1219
// set on frames that Preserve3D() or HasPerspective() or IsTransformed(), and
1220
// when at least one of the overflow areas differs from the frame bound rect.
1221
NS_DECLARE_FRAME_PROPERTY_DELETABLE(InitialOverflowProperty, nsOverflowAreas)
1222
1223
#ifdef DEBUG
1224
// InitialOverflowPropertyDebug is added to the frame to indicate that either
1225
// the InitialOverflowProperty has been stored or the InitialOverflowProperty
1226
// has been suppressed due to being set to the default value (frame bounds)
1227
NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(DebugInitialOverflowPropertyApplied,
1228
bool)
1229
#endif
1230
1231
NS_DECLARE_FRAME_PROPERTY_DELETABLE(UsedMarginProperty, nsMargin)
1232
NS_DECLARE_FRAME_PROPERTY_DELETABLE(UsedPaddingProperty, nsMargin)
1233
NS_DECLARE_FRAME_PROPERTY_DELETABLE(UsedBorderProperty, nsMargin)
1234
1235
NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(LineBaselineOffset, nscoord)
1236
1237
// Temporary override for a flex item's main-size property (either width
1238
// or height), imposed by its flex container.
1239
NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(FlexItemMainSizeOverride, nscoord)
1240
1241
NS_DECLARE_FRAME_PROPERTY_DELETABLE(InvalidationRect, nsRect)
1242
1243
NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(RefusedAsyncAnimationProperty, bool)
1244
1245
NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(FragStretchBSizeProperty, nscoord)
1246
1247
// The block-axis margin-box size associated with eBClampMarginBoxMinSize.
1248
NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(BClampMarginBoxMinSizeProperty, nscoord)
1249
1250
NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(IBaselinePadProperty, nscoord)
1251
NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(BBaselinePadProperty, nscoord)
1252
1253
NS_DECLARE_FRAME_PROPERTY_DELETABLE(DisplayItems, DisplayItemArray)
1254
1255
NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(BidiDataProperty,
1256
mozilla::FrameBidiData)
1257
1258
NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(PlaceholderFrameProperty,
1259
nsPlaceholderFrame)
1260
1261
mozilla::FrameBidiData GetBidiData() const {
1262
bool exists;
1263
mozilla::FrameBidiData bidiData = GetProperty(BidiDataProperty(), &exists);
1264
if (!exists) {
1265
bidiData.precedingControl = mozilla::kBidiLevelNone;
1266
}
1267
return bidiData;
1268
}
1269
1270
nsBidiLevel GetBaseLevel() const { return GetBidiData().baseLevel; }
1271
1272
nsBidiLevel GetEmbeddingLevel() const { return GetBidiData().embeddingLevel; }
1273
1274
/**
1275
* Return the distance between the border edge of the frame and the
1276
* margin edge of the frame. Like GetRect(), returns the dimensions
1277
* as of the most recent reflow.
1278
*
1279
* This doesn't include any margin collapsing that may have occurred.
1280
*
1281
* It also treats 'auto' margins as zero, and treats any margins that
1282
* should have been turned into 'auto' because of overconstraint as
1283
* having their original values.
1284
*/
1285
virtual nsMargin GetUsedMargin() const;
1286
virtual mozilla::LogicalMargin GetLogicalUsedMargin(
1287
mozilla::WritingMode aWritingMode) const {
1288
return mozilla::LogicalMargin(aWritingMode, GetUsedMargin());
1289
}
1290
1291
/**
1292
* Return the distance between the border edge of the frame (which is
1293
* its rect) and the padding edge of the frame. Like GetRect(), returns
1294
* the dimensions as of the most recent reflow.
1295
*
1296
* Note that this differs from StyleBorder()->GetComputedBorder() in
1297
* that this describes a region of the frame's box, and
1298
* StyleBorder()->GetComputedBorder() describes a border. They differ
1299
* for tables (particularly border-collapse tables) and themed
1300
* elements.
1301
*/
1302
virtual nsMargin GetUsedBorder() const;
1303
virtual mozilla::LogicalMargin GetLogicalUsedBorder(
1304
mozilla::WritingMode aWritingMode) const {
1305
return mozilla::LogicalMargin(aWritingMode, GetUsedBorder());
1306
}
1307
1308
/**
1309
* Return the distance between the padding edge of the frame and the
1310
* content edge of the frame. Like GetRect(), returns the dimensions
1311
* as of the most recent reflow.
1312
*/
1313
virtual nsMargin GetUsedPadding() const;
1314
virtual mozilla::LogicalMargin GetLogicalUsedPadding(
1315
mozilla::WritingMode aWritingMode) const {
1316
return mozilla::LogicalMargin(aWritingMode, GetUsedPadding());
1317
}
1318
1319
nsMargin GetUsedBorderAndPadding() const {
1320
return GetUsedBorder() + GetUsedPadding();
1321
}
1322
mozilla::LogicalMargin GetLogicalUsedBorderAndPadding(
1323
mozilla::WritingMode aWritingMode) const {
1324
return mozilla::LogicalMargin(aWritingMode, GetUsedBorderAndPadding());
1325
}
1326
1327
/**
1328
* Like the frame's rect (see |GetRect|), which is the border rect,
1329
* other rectangles of the frame, in app units, relative to the parent.
1330
*/
1331
nsRect GetPaddingRect() const;
1332
nsRect GetPaddingRectRelativeToSelf() const;
1333
nsRect GetContentRect() const;
1334
nsRect GetContentRectRelativeToSelf() const;
1335
nsRect GetMarginRectRelativeToSelf() const;
1336
1337
/**
1338
* The area to paint box-shadows around. The default is the border rect.
1339
* (nsFieldSetFrame overrides this).
1340
*/
1341
virtual nsRect VisualBorderRectRelativeToSelf() const {
1342
return nsRect(0, 0, mRect.Width(), mRect.Height());
1343
}
1344
1345
/**
1346
* Get the size, in app units, of the border radii. It returns FALSE iff all
1347
* returned radii == 0 (so no border radii), TRUE otherwise.
1348
* For the aRadii indexes, use the enum HalfCorner constants in gfx/2d/Types.h
1349
* If a side is skipped via aSkipSides, its corners are forced to 0.
1350
*
1351
* All corner radii are then adjusted so they do not require more
1352
* space than aBorderArea, according to the algorithm in css3-background.
1353
*
1354
* aFrameSize is used as the basis for percentage widths and heights.
1355
* aBorderArea is used for the adjustment of radii that might be too
1356
* large.
1357
* FIXME: In the long run, we can probably get away with only one of
1358
* these, especially if we change the way we handle outline-radius (by
1359
* removing it and inflating the border radius)
1360
*
1361
* Return whether any radii are nonzero.
1362
*/
1363
static bool ComputeBorderRadii(const mozilla::BorderRadius&,
1364
const nsSize& aFrameSize,
1365
const nsSize& aBorderArea, Sides aSkipSides,
1366
nscoord aRadii[8]);
1367
1368
/*
1369
* Given a set of border radii for one box (e.g., border box), convert
1370
* it to the equivalent set of radii for another box (e.g., in to
1371
* padding box, out to outline box) by reducing radii or increasing
1372
* nonzero radii as appropriate.
1373
*
1374
* Indices into aRadii are the enum HalfCorner constants in gfx/2d/Types.h
1375
*
1376
* Note that InsetBorderRadii is lossy, since it can turn nonzero
1377
* radii into zero, and OutsetBorderRadii does not inflate zero radii.
1378
* Therefore, callers should always inset or outset directly from the
1379
* original value coming from style.
1380
*/
1381
static void InsetBorderRadii(nscoord aRadii[8], const nsMargin& aOffsets);
1382
static void OutsetBorderRadii(nscoord aRadii[8], const nsMargin& aOffsets);
1383
1384
/**
1385
* Fill in border radii for this frame. Return whether any are nonzero.
1386
* Indices into aRadii are the enum HalfCorner constants in gfx/2d/Types.h
1387
* aSkipSides is a union of eSideBitsLeft/Right/Top/Bottom bits that says
1388
* which side(s) to skip.
1389
*
1390
* Note: GetMarginBoxBorderRadii() and GetShapeBoxBorderRadii() work only
1391
* on frames that establish block formatting contexts since they don't
1392
* participate in margin-collapsing.
1393
*/
1394
virtual bool GetBorderRadii(const nsSize& aFrameSize,
1395
const nsSize& aBorderArea, Sides aSkipSides,
1396
nscoord aRadii[8]) const;
1397
bool GetBorderRadii(nscoord aRadii[8]) const;
1398
bool GetMarginBoxBorderRadii(nscoord aRadii[8]) const;
1399
bool GetPaddingBoxBorderRadii(nscoord aRadii[8]) const;
1400
bool GetContentBoxBorderRadii(nscoord aRadii[8]) const;
1401
bool GetBoxBorderRadii(nscoord aRadii[8], nsMargin aOffset,
1402
bool aIsOutset) const;
1403
bool GetShapeBoxBorderRadii(nscoord aRadii[8]) const;
1404
1405
/**
1406
* XXX: this method will likely be replaced by GetVerticalAlignBaseline
1407
* Get the position of the frame's baseline, relative to the top of
1408
* the frame (its top border edge). Only valid when Reflow is not
1409
* needed.
1410
* @note You should only call this on frames with a WM that's parallel to aWM.
1411
* @param aWM the writing-mode of the alignment context, with the ltr/rtl
1412
* direction tweak done by nsIFrame::GetWritingMode(nsIFrame*) in inline
1413
* contexts (see that method).
1414
*/
1415
virtual nscoord GetLogicalBaseline(mozilla::WritingMode aWM) const = 0;
1416
1417
/**
1418
* Synthesize a first(last) inline-axis baseline from our margin-box.
1419
* An alphabetical baseline is at the start(end) edge and a central baseline
1420
* is at the center of our block-axis margin-box (aWM tells which to use).
1422
* @note You should only call this on frames with a WM that's parallel to aWM.
1423
* @param aWM the writing-mode of the alignment context
1424
* @return an offset from our border-box block-axis start(end) edge for
1425
* a first(last) baseline respectively
1426
* (implemented in nsIFrameInlines.h)
1427
*/
1428
inline nscoord SynthesizeBaselineBOffsetFromMarginBox(
1429
mozilla::WritingMode aWM, BaselineSharingGroup aGroup) const;
1430
1431
/**
1432
* Synthesize a first(last) inline-axis baseline from our border-box.
1433
* An alphabetical baseline is at the start(end) edge and a central baseline
1434
* is at the center of our block-axis border-box (aWM tells which to use).
1436
* @note The returned value is only valid when reflow is not needed.
1437
* @note You should only call this on frames with a WM that's parallel to aWM.
1438
* @param aWM the writing-mode of the alignment context
1439
* @return an offset from our border-box block-axis start(end) edge for
1440
* a first(last) baseline respectively
1441
* (implemented in nsIFrameInlines.h)
1442
*/
1443
inline nscoord SynthesizeBaselineBOffsetFromBorderBox(
1444
mozilla::WritingMode aWM, BaselineSharingGroup aGroup) const;
1445
1446
/**
1447
* Return the position of the frame's inline-axis baseline, or synthesize one
1448
* for the given alignment context. The returned baseline is the distance from
1449
* the block-axis border-box start(end) edge for aBaselineGroup eFirst(eLast).
1450
* @note The returned value is only valid when reflow is not needed.
1451
* @note You should only call this on frames with a WM that's parallel to aWM.
1452
* @param aWM the writing-mode of the alignment context
1453
* @param aBaselineOffset out-param, only valid if the method returns true
1454
* (implemented in nsIFrameInlines.h)
1455
*/
1456
inline nscoord BaselineBOffset(mozilla::WritingMode aWM,
1457
BaselineSharingGroup aBaselineGroup,
1458
AlignmentContext aAlignmentContext) const;
1459
1460
/**
1461
* XXX: this method is taking over the role that GetLogicalBaseline has.
1462
* Return true if the frame has a CSS2 'vertical-align' baseline.
1463
* If it has, then the returned baseline is the distance from the block-
1464
* axis border-box start edge.
1465
* @note This method should only be used in AlignmentContext::Inline
1466
* contexts.
1467
* @note The returned value is only valid when reflow is not needed.
1468
* @note You should only call this on frames with a WM that's parallel to aWM.
1469
* @param aWM the writing-mode of the alignment context
1470
* @param aBaseline the baseline offset, only valid if the method returns true
1471
*/
1472
virtual bool GetVerticalAlignBaseline(mozilla::WritingMode aWM,
1473
nscoord* aBaseline) const {
1474
return false;
1475
}
1476
1477
/**
1478
* Return true if the frame has a first(last) inline-axis natural baseline per
1479
* CSS Box Alignment. If so, then the returned baseline is the distance from
1480
* the block-axis border-box start(end) edge for aBaselineGroup eFirst(eLast).
1482
* @note The returned value is only valid when reflow is not needed.
1483
* @note You should only call this on frames with a WM that's parallel to aWM.
1484
* @param aWM the writing-mode of the alignment context
1485
* @param aBaseline the baseline offset, only valid if the method returns true
1486
*/
1487
virtual bool GetNaturalBaselineBOffset(mozilla::WritingMode aWM,
1488
BaselineSharingGroup aBaselineGroup,
1489
nscoord* aBaseline) const {
1490
return false;
1491
}
1492
1493
/**
1494
* Get the position of the baseline on which the caret needs to be placed,
1495
* relative to the top of the frame. This is mostly needed for frames
1496
* which return a baseline from GetBaseline which is not useful for
1497
* caret positioning.
1498
*/
1499
virtual nscoord GetCaretBaseline() const {
1500
return GetLogicalBaseline(GetWritingMode());
1501
}
1502
1503
///////////////////////////////////////////////////////////////////////////////
1504
// The public visibility API.
1505
///////////////////////////////////////////////////////////////////////////////
1506
1507
/// @return true if we're tracking visibility for this frame.
1508
bool TrackingVisibility() const {
1509
return bool(GetStateBits() & NS_FRAME_VISIBILITY_IS_TRACKED);
1510
}
1511
1512
/// @return the visibility state of this frame. See the Visibility enum
1513
/// for the possible return values and their meanings.
1514
Visibility GetVisibility() const;
1515
1516
/// Update the visibility state of this frame synchronously.
1517
/// XXX(seth): Avoid using this method; we should be relying on the refresh
1518
/// driver for visibility updates. This method, which replaces
1519
/// nsLayoutUtils::UpdateApproximateFrameVisibility(), exists purely as a
1520
/// temporary measure to avoid changing behavior during the transition from
1521
/// the old image visibility code.
1522
void UpdateVisibilitySynchronously();
1523
1524
// A frame property which stores the visibility state of this frame. Right
1525
// now that consists of an approximate visibility counter represented as a
1526
// uint32_t. When the visibility of this frame is not being tracked, this
1527
// property is absent.
1528
NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(VisibilityStateProperty, uint32_t);
1529
1530
protected:
1531
/**
1532
* Subclasses can call this method to enable visibility tracking for this
1533
* frame.
1534
*
1535
* If visibility tracking was previously disabled, this will schedule an
1536
* update an asynchronous update of visibility.
1537
*/
1538
void EnableVisibilityTracking();
1539
1540
/**
1541
* Subclasses can call this method to disable visibility tracking for this
1542
* frame.
1543
*
1544
* Note that if visibility tracking was previously enabled, disabling
1545
* visibility tracking will cause a synchronous call to OnVisibilityChange().
1546
*/
1547
void DisableVisibilityTracking();
1548
1549
/**
1550
* Called when a frame transitions between visibility states (for example,
1551
* from nonvisible to visible, or from visible to nonvisible).
1552
*
1553
* @param aNewVisibility The new visibility state.
1554
* @param aNonvisibleAction A requested action if the frame has become
1555
* nonvisible. If Nothing(), no action is
1556
* requested. If DISCARD_IMAGES is specified, the
1557
* frame is requested to ask any images it's
1558
* associated with to discard their surfaces if
1559
* possible.
1560
*
1561
* Subclasses which override this method should call their parent class's
1562
* implementation.
1563
*/
1564
virtual void OnVisibilityChange(
1565
Visibility aNewVisibility,
1566
const Maybe<OnNonvisible>& aNonvisibleAction = Nothing());
1567
1568
public:
1569
///////////////////////////////////////////////////////////////////////////////
1570
// Internal implementation for the approximate frame visibility API.
1571
///////////////////////////////////////////////////////////////////////////////
1572
1573
/**
1574
* We track the approximate visibility of frames using a counter; if it's
1575
* non-zero, then the frame is considered visible. Using a counter allows us
1576
* to account for situations where the frame may be visible in more than one
1577
* place (for example, via -moz-element), and it simplifies the
1578
* implementation of our approximate visibility tracking algorithms.
1579
*
1580
* @param aNonvisibleAction A requested action if the frame has become
1581
* nonvisible. If Nothing(), no action is
1582
* requested. If DISCARD_IMAGES is specified, the
1583
* frame is requested to ask any images it's
1584
* associated with to discard their surfaces if
1585
* possible.
1586
*/
1587
void DecApproximateVisibleCount(
1588
const Maybe<OnNonvisible>& aNonvisibleAction = Nothing());
1589
void IncApproximateVisibleCount();
1590
1591
/**
1592
* Get the specified child list.
1593
*
1594
* @param aListID identifies the requested child list.
1595
* @return the child list. If the requested list is unsupported by this
1596
* frame type, an empty list will be returned.
1597
*/
1598
virtual const nsFrameList& GetChildList(ChildListID aListID) const = 0;
1599
const nsFrameList& PrincipalChildList() const {
1600
return GetChildList(kPrincipalList);
1601
}
1602
virtual void GetChildLists(nsTArray<ChildList>* aLists) const = 0;
1603
1604
/**
1605
* Gets the child lists for this frame, including
1606
* ones belong to a child document.
1607
*/
1608
void GetCrossDocChildLists(nsTArray<ChildList>* aLists);
1609
1610
// The individual concrete child lists.
1611
static const ChildListID kPrincipalList = mozilla::layout::kPrincipalList;
1612
static const ChildListID kAbsoluteList = mozilla::layout::kAbsoluteList;
1613
static const ChildListID kBulletList = mozilla::layout::kBulletList;
1614
static const ChildListID kCaptionList = mozilla::layout::kCaptionList;
1615
static const ChildListID kColGroupList = mozilla::layout::kColGroupList;
1616
static const ChildListID kExcessOverflowContainersList =
1617
mozilla::layout::kExcessOverflowContainersList;
1618
static const ChildListID kFixedList = mozilla::layout::kFixedList;
1619
static const ChildListID kFloatList = mozilla::layout::kFloatList;
1620
static const ChildListID kOverflowContainersList =
1621
mozilla::layout::kOverflowContainersList;
1622
static const ChildListID kOverflowList = mozilla::layout::kOverflowList;
1623
static const ChildListID kOverflowOutOfFlowList =
1624
mozilla::layout::kOverflowOutOfFlowList;
1625
static const ChildListID kPopupList = mozilla::layout::kPopupList;
1626
static const ChildListID kPushedFloatsList =
1627
mozilla::layout::kPushedFloatsList;
1628
static const ChildListID kSelectPopupList = mozilla::layout::kSelectPopupList;
1629
static const ChildListID kBackdropList = mozilla::layout::kBackdropList;
1630
// A special alias for kPrincipalList that do not request reflow.
1631
static const ChildListID kNoReflowPrincipalList =
1632
mozilla::layout::kNoReflowPrincipalList;
1633
1634
/**
1635
* Child frames are linked together in a doubly-linked list
1636
*/
1637
nsIFrame* GetNextSibling() const { return mNextSibling; }
1638
void SetNextSibling(nsIFrame* aNextSibling) {
1639
NS_ASSERTION(this != aNextSibling,
1640
"Creating a circular frame list, this is very bad.");
1641
if (mNextSibling && mNextSibling->GetPrevSibling() == this) {
1642
mNextSibling->mPrevSibling = nullptr;
1643
}
1644
mNextSibling = aNextSibling;
1645
if (mNextSibling) {
1646
mNextSibling->mPrevSibling = this;
1647
}
1648
}
1649
1650
nsIFrame* GetPrevSibling() const { return mPrevSibling; }
1651
1652
/**
1653
* Builds the display lists for the content represented by this frame
1654
* and its descendants. The background+borders of this element must
1655
* be added first, before any other content.
1656
*
1657
* This should only be called by methods in nsFrame. Instead of calling this
1658
* directly, call either BuildDisplayListForStackingContext or
1659
* BuildDisplayListForChild.
1660
*
1661
* See nsDisplayList.h for more information about display lists.
1662
*/
1663
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
1664
const nsDisplayListSet& aLists) {}
1665
/**
1666
* Displays the caret onto the given display list builder. The caret is
1667
* painted on top of the rest of the display list items.
1668
*/
1669
void DisplayCaret(nsDisplayListBuilder* aBuilder, nsDisplayList* aList);
1670
1671
/**
1672
* Get the preferred caret color at the offset.
1673
*
1674
* @param aOffset is offset of the content.
1675
*/
1676
virtual nscolor GetCaretColorAt(int32_t aOffset);
1677
1678
bool IsThemed(nsITheme::Transparency* aTransparencyState = nullptr) const {
1679
return IsThemed(StyleDisplay(), aTransparencyState);
1680
}
1681
bool IsThemed(const nsStyleDisplay* aDisp,
1682
nsITheme::Transparency* aTransparencyState = nullptr) const {
1683
if (!aDisp->HasAppearance()) {
1684
return false;
1685
}
1686
nsIFrame* mutable_this = const_cast<nsIFrame*>(this);
1687
nsPresContext* pc = PresContext();
1688
nsITheme* theme = pc->GetTheme();
1689
if (!theme ||
1690
!theme->ThemeSupportsWidget(pc, mutable_this, aDisp->mAppearance))
1691
return false;
1692
if (aTransparencyState) {
1693
*aTransparencyState =
1694
theme->GetWidgetTransparency(mutable_this, aDisp->mAppearance);
1695
}
1696
return true;
1697
}
1698
1699
/**
1700
* Builds a display list for the content represented by this frame,
1701
* treating this frame as the root of a stacking context.
1702
* Optionally sets aCreatedContainerItem to true if we created a
1703
* single container display item for the stacking context, and no
1704
* other wrapping items are needed.
1705
*/
1706
void BuildDisplayListForStackingContext(
1707
nsDisplayListBuilder* aBuilder, nsDisplayList* aList,
1708
bool* aCreatedContainerItem = nullptr);
1709
1710
enum {
1711
DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT = 0x01,
1712
DISPLAY_CHILD_FORCE_STACKING_CONTEXT = 0x02,
1713
DISPLAY_CHILD_INLINE = 0x04
1714
};
1715
/**
1716
* Adjusts aDirtyRect for the child's offset, checks that the dirty rect
1717
* actually intersects the child (or its descendants), calls BuildDisplayList
1718
* on the child if necessary, and puts things in the right lists if the child
1719
* is positioned.
1720
*
1721
* @param aFlags combination of DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT,
1722
* DISPLAY_CHILD_FORCE_STACKING_CONTEXT and DISPLAY_CHILD_INLINE
1723
*/
1724
void BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
1725
nsIFrame* aChild,
1726
const nsDisplayListSet& aLists,
1727
uint32_t aFlags = 0);
1728
1729
void BuildDisplayListForSimpleChild(nsDisplayListBuilder* aBuilder,
1730
nsIFrame* aChild,
1731
const nsDisplayListSet& aLists);
1732
1733
bool RefusedAsyncAnimation() const {
1734
return GetProperty(RefusedAsyncAnimationProperty());
1735
}
1736
1737
/**
1738
* Returns true if this frame is transformed (e.g. has CSS or SVG transforms)
1739
* or if its parent is an SVG frame that has children-only transforms (e.g.
1740
* an SVG viewBox attribute) or if its transform-style is preserve-3d or
1741
* the frame has transform animations.
1742
*
1743
* @param aStyleDisplay: If the caller has this->StyleDisplay(), providing
1744
* it here will improve performance.
1745
*/
1746
bool IsTransformed(const nsStyleDisplay* aStyleDisplay) const;
1747
bool IsTransformed() const { return IsTransformed(StyleDisplay()); }
1748
1749
/**
1750
* Same as IsTransformed, except that it doesn't take SVG transforms
1751
* into account.
1752
*/
1753
bool IsCSSTransformed(const nsStyleDisplay* aStyleDisplay) const;
1754
1755
/**
1756
* True if this frame has any animation of transform in effect.
1757
*
1758
*/
1759
bool HasAnimationOfTransform() const;
1760
1761
/**
1762
* Returns true if the frame is translucent or the frame has opacity
1763
* animations for the purposes of creating a stacking context.
1764
*
1765
* @param aStyleDisplay: This function needs style display struct.
1766
*
1767
* @param aStyleEffects: This function needs style effects struct.
1768
*
1769
* @param aEffectSet: This function may need to look up EffectSet property.
1770
* If a caller already have one, pass it in can save property look up
1771
* time; otherwise, just leave it as nullptr.
1772
*/
1773
bool HasOpacity(const nsStyleDisplay* aStyleDisplay,
1774
const nsStyleEffects* aStyleEffects,
1775
mozilla::EffectSet* aEffectSet = nullptr) const {
1776
return HasOpacityInternal(1.0f, aStyleDisplay, aStyleEffects, aEffectSet);
1777
}
1778
/**
1779
* Returns true if the frame is translucent for display purposes.
1780
*
1781
* @param aStyleDisplay: This function needs style display struct.
1782
*
1783
* @param aStyleEffects: This function needs style effects struct.
1784
*
1785
* @param aEffectSet: This function may need to look up EffectSet property.
1786
* If a caller already have one, pass it in can save property look up
1787
* time; otherwise, just leave it as nullptr.
1788
*/
1789
bool HasVisualOpacity(const nsStyleDisplay* aStyleDisplay,
1790
const nsStyleEffects* aStyleEffects,
1791
mozilla::EffectSet* aEffectSet = nullptr) const {
1792
// Treat an opacity value of 0.99 and above as opaque. This is an
1793
// optimization aimed at Web content which use opacity:0.99 as a hint for
1794
// creating a stacking context only.
1795
return HasOpacityInternal(0.99f, aStyleDisplay, aStyleEffects, aEffectSet);
1796
}
1797
1798
/**
1799
* Return true if this frame might be using a transform getter.
1800
*/
1801
virtual bool HasTransformGetter() const { return false; }
1802
1803
/**
1804
* Returns true if this frame is an SVG frame that has SVG transforms applied
1805
* to it, or if its parent frame is an SVG frame that has children-only
1806
* transforms (e.g. an SVG viewBox attribute).
1807
* If aOwnTransforms is non-null and the frame has its own SVG transforms,
1808
* aOwnTransforms will be set to these transforms. If aFromParentTransforms
1809
* is non-null and the frame has an SVG parent with children-only transforms,
1810
* then aFromParentTransforms will be set to these transforms.
1811
*/
1812
virtual bool IsSVGTransformed(Matrix* aOwnTransforms = nullptr,
1813
Matrix* aFromParentTransforms = nullptr) const;
1814
1815
/**
1816
* Return true if this frame should form a backdrop root container.
1818
*/
1819
bool FormsBackdropRoot(const nsStyleDisplay* aStyleDisplay,
1820
const nsStyleEffects* aStyleEffects,
1821
const nsStyleSVGReset* aStyleSvgReset);
1822
1823
/**
1824
* Returns whether this frame will attempt to extend the 3d transforms of its
1825
* children. This requires transform-style: preserve-3d, as well as no
1826
* clipping or svg effects.
1827
*
1828
* @param aStyleDisplay: If the caller has this->StyleDisplay(), providing
1829
* it here will improve performance.
1830
*
1831
* @param aStyleEffects: If the caller has this->StyleEffects(), providing
1832
* it here will improve performance.
1833
*
1834
* @param aEffectSetForOpacity: This function may need to look up the
1835
* EffectSet for opacity animations on this frame.
1836
* If the caller already has looked up this EffectSet, it may pass it in to
1837
* save an extra property lookup.
1838
*/
1839
bool Extend3DContext(
1840
const nsStyleDisplay* aStyleDisplay, const nsStyleEffects* aStyleEffects,
1841
mozilla::EffectSet* aEffectSetForOpacity = nullptr) const;
1842
bool Extend3DContext(
1843
mozilla::EffectSet* aEffectSetForOpacity = nullptr) const {
1844
return Extend3DContext(StyleDisplay(), StyleEffects(),
1845
aEffectSetForOpacity);
1846
}
1847
1848
/**
1849
* Returns whether this frame has a parent that Extend3DContext() and has
1850
* its own transform (or hidden backface) to be combined with the parent's
1851
* transform.
1852
*
1853
* @param aStyleDisplay: If the caller has this->StyleDisplay(), providing
1854
* it here will improve performance.
1855
*/
1856
bool Combines3DTransformWithAncestors(
1857
const nsStyleDisplay* aStyleDisplay) const;
1858
bool Combines3DTransformWithAncestors() const {
1859
return Combines3DTransformWithAncestors(StyleDisplay());
1860
}
1861
1862
/**
1863
* Returns whether this frame has a hidden backface and has a parent that
1864
* Extend3DContext(). This is useful because in some cases the hidden
1865
* backface can safely be ignored if it could not be visible anyway.
1866
*
1867
*/
1868
bool In3DContextAndBackfaceIsHidden() const;
1869
1870
bool IsPreserve3DLeaf(const nsStyleDisplay* aStyleDisplay,
1871
mozilla::EffectSet* aEffectSet = nullptr) const {
1872
return Combines3DTransformWithAncestors(aStyleDisplay) &&
1873
!Extend3DContext(aStyleDisplay, StyleEffects(), aEffectSet);
1874
}
1875
bool IsPreserve3DLeaf(mozilla::EffectSet* aEffectSet = nullptr) const {
1876
return IsPreserve3DLeaf(StyleDisplay(), aEffectSet);
1877
}
1878
1879
bool HasPerspective(const nsStyleDisplay* aStyleDisplay) const;
1880
bool HasPerspective() const { return HasPerspective(StyleDisplay()); }
1881
1882
bool ChildrenHavePerspective(const nsStyleDisplay* aStyleDisplay) const;
1883
bool ChildrenHavePerspective() const {
1884
return ChildrenHavePerspective(StyleDisplay());
1885
}
1886
1887
/**
1888
* Includes the overflow area of all descendants that participate in the
1889
* current 3d context into aOverflowAreas.
1890
*/
1891
void ComputePreserve3DChildrenOverflow(nsOverflowAreas& aOverflowAreas);
1892
1893
void RecomputePerspectiveChildrenOverflow(const nsIFrame* aStartFrame);
1894
1895
/**
1896
* Returns the computed z-index for this frame, returning 0 for z-index:auto
1897
* and frames that don't support z-index.
1898
*/
1899
int32_t ZIndex() const;
1900
1901
/**
1902
* Returns whether this frame is the anchor of some ancestor scroll frame. As
1903
* this frame is moved, the scroll frame will apply adjustments to keep this
1904
* scroll frame in the same relative position.
1905
*
1906
* aOutContainer will optionally be set to the scroll anchor container for
1907
* this frame if this frame is an anchor.
1908
*/
1909
bool IsScrollAnchor(
1910
mozilla::layout::ScrollAnchorContainer** aOutContainer = nullptr);
1911
1912
/**
1913
* Returns whether this frame is the anchor of some ancestor scroll frame, or
1914
* has a descendant which is the scroll anchor.
1915
*/
1916
bool IsInScrollAnchorChain() const;
1917
void SetInScrollAnchorChain(bool aInChain);
1918
1919
/**
1920
* Returns the number of ancestors between this and the root of our frame tree
1921
*/
1922
uint32_t GetDepthInFrameTree() const;
1923
1924
/**
1925
* Event handling of GUI events.
1926
*
1927
* @param aEvent event structure describing the type of event and rge widget
1928
* where the event originated. The |point| member of this is in the coordinate
1929
* system of the view returned by GetOffsetFromView.
1930
*
1931
* @param aEventStatus a return value indicating whether the event was
1932
* handled and whether default processing should be done
1933
*
1934
* XXX From a frame's perspective it's unclear what the effect of the event
1935
* status is. Does it cause the event to continue propagating through the
1936
* frame hierarchy or is it just returned to the widgets?
1937
*
1938
* @see WidgetGUIEvent
1939
* @see nsEventStatus
1940
*/
1941
virtual nsresult HandleEvent(nsPresContext* aPresContext,
1942
mozilla::WidgetGUIEvent* aEvent,
1943
nsEventStatus* aEventStatus) = 0;
1944
1945
virtual nsresult GetContentForEvent(mozilla::WidgetEvent* aEvent,
1946
nsIContent** aContent) = 0;
1947
1948
// This structure keeps track of the content node and offsets associated with
1949
// a point; there is a primary and a secondary offset associated with any
1950
// point. The primary and secondary offsets differ when the point is over a
1951
// non-text object. The primary offset is the expected position of the
1952
// cursor calculated from a point; the secondary offset, when it is different,
1953
// indicates that the point is in the boundaries of some selectable object.
1954
// Note that the primary offset can be after the secondary offset; for places
1955
// that need the beginning and end of the object, the StartOffset and
1956
// EndOffset helpers can be used.
1957
struct MOZ_STACK_CLASS ContentOffsets {
1958
ContentOffsets()
1959
: offset(0),
1960
secondaryOffset(0),
1961
associate(mozilla::CARET_ASSOCIATE_BEFORE) {}
1962
bool IsNull() { return !content; }
1963
// Helpers for places that need the ends of the offsets and expect them in
1964
// numerical order, as opposed to wanting the primary and secondary offsets
1965
int32_t StartOffset() { return std::min(offs