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
* (@see nsCanvasFrame::MaybePropagateRootElementWritingMode)
899
* * a scrolled frame propagates its value to its ancestor scroll frame
900
* (@see nsHTMLScrollFrame::ReloadChildFrames)
901
*/
902
mozilla::WritingMode GetWritingMode() const { return mWritingMode; }
903
904
/**
905
* Construct a writing mode for line layout in this frame. This is
906
* the writing mode of this frame, except that if this frame is styled with
907
* unicode-bidi:plaintext, we reset the direction to the resolved paragraph
908
* level of the given subframe (typically the first frame on the line),
909
* because the container frame could be split by hard line breaks into
910
* multiple paragraphs with different base direction.
911
* @param aSelfWM the WM of 'this'
912
*/
913
mozilla::WritingMode WritingModeForLine(mozilla::WritingMode aSelfWM,
914
nsIFrame* aSubFrame) const;
915
916
/**
917
* Bounding rect of the frame.
918
*
919
* For frames that are laid out according to CSS box model rules the values
920
* are in app units, and the origin is relative to the upper-left of the
921
* geometric parent. The size includes the content area, borders, and
922
* padding.
923
*
924
* Frames that are laid out according to SVG's coordinate space based rules
925
* (frames with the NS_FRAME_SVG_LAYOUT bit set, which *excludes*
926
* nsSVGOuterSVGFrame) are different. Many frames of this type do not set or
927
* use mRect, in which case the frame rect is undefined. The exceptions are:
928
*
929
* - nsSVGInnerSVGFrame
930
* - SVGGeometryFrame (used for <path>, <circle>, etc.)
931
* - nsSVGImageFrame
932
* - nsSVGForeignObjectFrame
933
*
934
* For these frames the frame rect contains the frame's element's userspace
935
* bounds including fill, stroke and markers, but converted to app units
936
* rather than being in user units (CSS px). In the SVG code "userspace" is
937
* defined to be the coordinate system for the attributes that define an
938
* element's geometry (such as the 'cx' attribute for <circle>). For more
939
* precise details see these frames' implementations of the ReflowSVG method
940
* where mRect is set.
941
*
942
* Note: moving or sizing the frame does not affect the view's size or
943
* position.
944
*/
945
nsRect GetRect() const { return mRect; }
946
nsPoint GetPosition() const { return mRect.TopLeft(); }
947
nsSize GetSize() const { return mRect.Size(); }
948
nsRect GetRectRelativeToSelf() const {
949
return nsRect(nsPoint(0, 0), mRect.Size());
950
}
951
/**
952
* Dimensions and position in logical coordinates in the frame's writing mode
953
* or another writing mode
954
*/
955
mozilla::LogicalRect GetLogicalRect(const nsSize& aContainerSize) const {
956
return GetLogicalRect(GetWritingMode(), aContainerSize);
957
}
958
mozilla::LogicalPoint GetLogicalPosition(const nsSize& aContainerSize) const {
959
return GetLogicalPosition(GetWritingMode(), aContainerSize);
960
}
961
mozilla::LogicalSize GetLogicalSize() const {
962
return GetLogicalSize(GetWritingMode());
963
}
964
mozilla::LogicalRect GetLogicalRect(mozilla::WritingMode aWritingMode,
965
const nsSize& aContainerSize) const {
966
return mozilla::LogicalRect(aWritingMode, GetRect(), aContainerSize);
967
}
968
mozilla::LogicalPoint GetLogicalPosition(mozilla::WritingMode aWritingMode,
969
const nsSize& aContainerSize) const {
970
return GetLogicalRect(aWritingMode, aContainerSize).Origin(aWritingMode);
971
}
972
mozilla::LogicalSize GetLogicalSize(mozilla::WritingMode aWritingMode) const {
973
return mozilla::LogicalSize(aWritingMode, GetSize());
974
}
975
nscoord IStart(const nsSize& aContainerSize) const {
976
return IStart(GetWritingMode(), aContainerSize);
977
}
978
nscoord IStart(mozilla::WritingMode aWritingMode,
979
const nsSize& aContainerSize) const {
980
return GetLogicalPosition(aWritingMode, aContainerSize).I(aWritingMode);
981
}
982
nscoord BStart(const nsSize& aContainerSize) const {
983
return BStart(GetWritingMode(), aContainerSize);
984
}
985
nscoord BStart(mozilla::WritingMode aWritingMode,
986
const nsSize& aContainerSize) const {
987
return GetLogicalPosition(aWritingMode, aContainerSize).B(aWritingMode);
988
}
989
nscoord ISize() const { return ISize(GetWritingMode()); }
990
nscoord ISize(mozilla::WritingMode aWritingMode) const {
991
return GetLogicalSize(aWritingMode).ISize(aWritingMode);
992
}
993
nscoord BSize() const { return BSize(GetWritingMode()); }
994
nscoord BSize(mozilla::WritingMode aWritingMode) const {
995
return GetLogicalSize(aWritingMode).BSize(aWritingMode);
996
}
997
nscoord ContentBSize() const { return ContentBSize(GetWritingMode()); }
998
nscoord ContentBSize(mozilla::WritingMode aWritingMode) const {
999
auto bp = GetLogicalUsedBorderAndPadding(aWritingMode);
1000
bp.ApplySkipSides(GetLogicalSkipSides());
1001
return std::max(0, BSize(aWritingMode) - bp.BStartEnd(aWritingMode));
1002
}
1003
1004
/**
1005
* When we change the size of the frame's border-box rect, we may need to
1006
* reset the overflow rect if it was previously stored as deltas.
1007
* (If it is currently a "large" overflow and could be re-packed as deltas,
1008
* we don't bother as the cost of the allocation has already been paid.)
1009
* @param aRebuildDisplayItems If true, then adds this frame to the
1010
* list of modified frames for display list building if the rect has changed.
1011
* Only pass false if you're sure that the relevant display items will be
1012
* rebuilt already (possibly by an ancestor being in the modified list), or if
1013
* this is a temporary change.
1014
*/
1015
void SetRect(const nsRect& aRect, bool aRebuildDisplayItems = true) {
1016
if (aRect == mRect) {
1017
return;
1018
}
1019
if (mOverflow.mType != NS_FRAME_OVERFLOW_LARGE &&
1020
mOverflow.mType != NS_FRAME_OVERFLOW_NONE) {
1021
nsOverflowAreas overflow = GetOverflowAreas();
1022
mRect = aRect;
1023
SetOverflowAreas(overflow);
1024
} else {
1025
mRect = aRect;
1026
}
1027
if (aRebuildDisplayItems) {
1028
MarkNeedsDisplayItemRebuild();
1029
}
1030
}
1031
/**
1032
* Set this frame's rect from a logical rect in its own writing direction
1033
*/
1034
void SetRect(const mozilla::LogicalRect& aRect,
1035
const nsSize& aContainerSize) {
1036
SetRect(GetWritingMode(), aRect, aContainerSize);
1037
}
1038
/**
1039
* Set this frame's rect from a logical rect in a different writing direction
1040
* (GetPhysicalRect will assert if the writing mode doesn't match)
1041
*/
1042
void SetRect(mozilla::WritingMode aWritingMode,
1043
const mozilla::LogicalRect& aRect,
1044
const nsSize& aContainerSize) {
1045
SetRect(aRect.GetPhysicalRect(aWritingMode, aContainerSize));
1046
}
1047
1048
/**
1049
* Set this frame's size from a logical size in its own writing direction.
1050
* This leaves the frame's logical position unchanged, which means its
1051
* physical position may change (for right-to-left modes).
1052
*/
1053
void SetSize(const mozilla::LogicalSize& aSize) {
1054
SetSize(GetWritingMode(), aSize);
1055
}
1056
/*
1057
* Set this frame's size from a logical size in a different writing direction.
1058
* This leaves the frame's logical position in the given mode unchanged,
1059
* which means its physical position may change (for right-to-left modes).
1060
*/
1061
void SetSize(mozilla::WritingMode aWritingMode,
1062
const mozilla::LogicalSize& aSize) {
1063
if ((!aWritingMode.IsVertical() && !aWritingMode.IsBidiLTR()) ||
1064
aWritingMode.IsVerticalRL()) {
1065
nscoord oldWidth = mRect.Width();
1066
SetSize(aSize.GetPhysicalSize(aWritingMode));
1067
mRect.x -= mRect.Width() - oldWidth;
1068
} else {
1069
SetSize(aSize.GetPhysicalSize(aWritingMode));
1070
}
1071
}
1072
1073
/**
1074
* Set this frame's physical size. This leaves the frame's physical position
1075
* (topLeft) unchanged.
1076
* @param aRebuildDisplayItems If true, then adds this frame to the
1077
* list of modified frames for display list building if the size has changed.
1078
* Only pass false if you're sure that the relevant display items will be
1079
* rebuilt already (possibly by an ancestor being in the modified list), or if
1080
* this is a temporary change.
1081
*/
1082
void SetSize(const nsSize& aSize, bool aRebuildDisplayItems = true) {
1083
SetRect(nsRect(mRect.TopLeft(), aSize), aRebuildDisplayItems);
1084
}
1085
1086
void SetPosition(const nsPoint& aPt) {
1087
if (mRect.TopLeft() == aPt) {
1088
return;
1089
}
1090
mRect.MoveTo(aPt);
1091
MarkNeedsDisplayItemRebuild();
1092
}
1093
void SetPosition(mozilla::WritingMode aWritingMode,
1094
const mozilla::LogicalPoint& aPt,
1095
const nsSize& aContainerSize) {
1096
// We subtract mRect.Size() from the container size to account for
1097
// the fact that logical origins in RTL coordinate systems are at
1098
// the top right of the frame instead of the top left.
1099
SetPosition(
1100
aPt.GetPhysicalPoint(aWritingMode, aContainerSize - mRect.Size()));
1101
}
1102
1103
/**
1104
* Move the frame, accounting for relative positioning. Use this when
1105
* adjusting the frame's position by a known amount, to properly update its
1106
* saved normal position (see GetNormalPosition below).
1107
*
1108
* This must be used only when moving a frame *after*
1109
* ReflowInput::ApplyRelativePositioning is called. When moving
1110
* a frame during the reflow process prior to calling
1111
* ReflowInput::ApplyRelativePositioning, the position should
1112
* simply be adjusted directly (e.g., using SetPosition()).
1113
*/
1114
void MovePositionBy(const nsPoint& aTranslation);
1115
1116
/**
1117
* As above, using a logical-point delta in a given writing mode.
1118
*/
1119
void MovePositionBy(mozilla::WritingMode aWritingMode,
1120
const mozilla::LogicalPoint& aTranslation) {
1121
// The LogicalPoint represents a vector rather than a point within a
1122
// rectangular coordinate space, so we use a null containerSize when
1123
// converting logical to physical.
1124
const nsSize nullContainerSize;
1125
MovePositionBy(
1126
aTranslation.GetPhysicalPoint(aWritingMode, nullContainerSize));
1127
}
1128
1129
/**
1130
* Return frame's rect without relative positioning
1131
*/
1132
nsRect GetNormalRect() const;
1133
1134
/**
1135
* Return frame's position without relative positioning.
1136
* If aHasProperty is provided, returns whether the normal position
1137
* was stored in a frame property.
1138
*/
1139
inline nsPoint GetNormalPosition(bool* aHasProperty = nullptr) const;
1140
1141
mozilla::LogicalPoint GetLogicalNormalPosition(
1142
mozilla::WritingMode aWritingMode, const nsSize& aContainerSize) const {
1143
// Subtract the size of this frame from the container size to get
1144
// the correct position in rtl frames where the origin is on the
1145
// right instead of the left
1146
return mozilla::LogicalPoint(aWritingMode, GetNormalPosition(),
1147
aContainerSize - mRect.Size());
1148
}
1149
1150
virtual nsPoint GetPositionOfChildIgnoringScrolling(const nsIFrame* aChild) {
1151
return aChild->GetPosition();
1152
}
1153
1154
nsPoint GetPositionIgnoringScrolling() const;
1155
1156
typedef AutoTArray<nsDisplayItemBase*, 4> DisplayItemArray;
1157
1158
#define NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(prop, type, dtor) \
1159
static const mozilla::FramePropertyDescriptor<type>* prop() { \
1160
/* Use of constexpr caused startup crashes with MSVC2015u1 PGO. */ \
1161
static const auto descriptor = \
1162
mozilla::FramePropertyDescriptor<type>::NewWithDestructor<dtor>(); \
1163
return &descriptor; \
1164
}
1165
1166
// Don't use this unless you really know what you're doing!
1167
#define NS_DECLARE_FRAME_PROPERTY_WITH_FRAME_IN_DTOR(prop, type, dtor) \
1168
static const mozilla::FramePropertyDescriptor<type>* prop() { \
1169
/* Use of constexpr caused startup crashes with MSVC2015u1 PGO. */ \
1170
static const auto descriptor = mozilla::FramePropertyDescriptor< \
1171
type>::NewWithDestructorWithFrame<dtor>(); \
1172
return &descriptor; \
1173
}
1174
1175
#define NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(prop, type) \
1176
static const mozilla::FramePropertyDescriptor<type>* prop() { \
1177
/* Use of constexpr caused startup crashes with MSVC2015u1 PGO. */ \
1178
static const auto descriptor = \
1179
mozilla::FramePropertyDescriptor<type>::NewWithoutDestructor(); \
1180
return &descriptor; \
1181
}
1182
1183
#define NS_DECLARE_FRAME_PROPERTY_DELETABLE(prop, type) \
1184
NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(prop, type, DeleteValue)
1185
1186
#define NS_DECLARE_FRAME_PROPERTY_RELEASABLE(prop, type) \
1187
NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(prop, type, ReleaseValue)
1188
1189
#define NS_DECLARE_FRAME_PROPERTY_WITH_DTOR_NEVER_CALLED(prop, type) \
1190
static void AssertOnDestroyingProperty##prop(type*) { \
1191
MOZ_ASSERT_UNREACHABLE( \
1192
"Frame property " #prop \
1193
" should never be destroyed by the FrameProperties class"); \
1194
} \
1195
NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(prop, type, \
1196
AssertOnDestroyingProperty##prop)
1197
1198
#define NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(prop, type) \
1199
NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(prop, mozilla::SmallValueHolder<type>)
1200
1201
NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(IBSplitSibling, nsContainerFrame)
1202
NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(IBSplitPrevSibling, nsContainerFrame)
1203
1204
NS_DECLARE_FRAME_PROPERTY_DELETABLE(NormalPositionProperty, nsPoint)
1205
NS_DECLARE_FRAME_PROPERTY_DELETABLE(ComputedOffsetProperty, nsMargin)
1206
1207
NS_DECLARE_FRAME_PROPERTY_DELETABLE(OutlineInnerRectProperty, nsRect)
1208
NS_DECLARE_FRAME_PROPERTY_DELETABLE(PreEffectsBBoxProperty, nsRect)
1209
NS_DECLARE_FRAME_PROPERTY_DELETABLE(PreTransformOverflowAreasProperty,
1210
nsOverflowAreas)
1211
1212
NS_DECLARE_FRAME_PROPERTY_DELETABLE(OverflowAreasProperty, nsOverflowAreas)
1213
1214
// The initial overflow area passed to FinishAndStoreOverflow. This is only
1215
// set on frames that Preserve3D() or HasPerspective() or IsTransformed(), and
1216
// when at least one of the overflow areas differs from the frame bound rect.
1217
NS_DECLARE_FRAME_PROPERTY_DELETABLE(InitialOverflowProperty, nsOverflowAreas)
1218
1219
#ifdef DEBUG
1220
// InitialOverflowPropertyDebug is added to the frame to indicate that either
1221
// the InitialOverflowProperty has been stored or the InitialOverflowProperty
1222
// has been suppressed due to being set to the default value (frame bounds)
1223
NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(DebugInitialOverflowPropertyApplied,
1224
bool)
1225
#endif
1226
1227
NS_DECLARE_FRAME_PROPERTY_DELETABLE(UsedMarginProperty, nsMargin)
1228
NS_DECLARE_FRAME_PROPERTY_DELETABLE(UsedPaddingProperty, nsMargin)
1229
NS_DECLARE_FRAME_PROPERTY_DELETABLE(UsedBorderProperty, nsMargin)
1230
1231
NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(LineBaselineOffset, nscoord)
1232
1233
// Temporary override for a flex item's main-size property (either width
1234
// or height), imposed by its flex container.
1235
NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(FlexItemMainSizeOverride, nscoord)
1236
1237
NS_DECLARE_FRAME_PROPERTY_DELETABLE(InvalidationRect, nsRect)
1238
1239
NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(RefusedAsyncAnimationProperty, bool)
1240
1241
NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(FragStretchBSizeProperty, nscoord)
1242
1243
// The block-axis margin-box size associated with eBClampMarginBoxMinSize.
1244
NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(BClampMarginBoxMinSizeProperty, nscoord)
1245
1246
NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(IBaselinePadProperty, nscoord)
1247
NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(BBaselinePadProperty, nscoord)
1248
1249
NS_DECLARE_FRAME_PROPERTY_DELETABLE(DisplayItems, DisplayItemArray)
1250
1251
NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(BidiDataProperty,
1252
mozilla::FrameBidiData)
1253
1254
NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(PlaceholderFrameProperty,
1255
nsPlaceholderFrame)
1256
1257
mozilla::FrameBidiData GetBidiData() const {
1258
bool exists;
1259
mozilla::FrameBidiData bidiData = GetProperty(BidiDataProperty(), &exists);
1260
if (!exists) {
1261
bidiData.precedingControl = mozilla::kBidiLevelNone;
1262
}
1263
return bidiData;
1264
}
1265
1266
nsBidiLevel GetBaseLevel() const { return GetBidiData().baseLevel; }
1267
1268
nsBidiLevel GetEmbeddingLevel() const { return GetBidiData().embeddingLevel; }
1269
1270
/**
1271
* Return the distance between the border edge of the frame and the
1272
* margin edge of the frame. Like GetRect(), returns the dimensions
1273
* as of the most recent reflow.
1274
*
1275
* This doesn't include any margin collapsing that may have occurred.
1276
*
1277
* It also treats 'auto' margins as zero, and treats any margins that
1278
* should have been turned into 'auto' because of overconstraint as
1279
* having their original values.
1280
*/
1281
virtual nsMargin GetUsedMargin() const;
1282
virtual mozilla::LogicalMargin GetLogicalUsedMargin(
1283
mozilla::WritingMode aWritingMode) const {
1284
return mozilla::LogicalMargin(aWritingMode, GetUsedMargin());
1285
}
1286
1287
/**
1288
* Return the distance between the border edge of the frame (which is
1289
* its rect) and the padding edge of the frame. Like GetRect(), returns
1290
* the dimensions as of the most recent reflow.
1291
*
1292
* Note that this differs from StyleBorder()->GetComputedBorder() in
1293
* that this describes a region of the frame's box, and
1294
* StyleBorder()->GetComputedBorder() describes a border. They differ
1295
* for tables (particularly border-collapse tables) and themed
1296
* elements.
1297
*/
1298
virtual nsMargin GetUsedBorder() const;
1299
virtual mozilla::LogicalMargin GetLogicalUsedBorder(
1300
mozilla::WritingMode aWritingMode) const {
1301
return mozilla::LogicalMargin(aWritingMode, GetUsedBorder());
1302
}
1303
1304
/**
1305
* Return the distance between the padding edge of the frame and the
1306
* content edge of the frame. Like GetRect(), returns the dimensions
1307
* as of the most recent reflow.
1308
*/
1309
virtual nsMargin GetUsedPadding() const;
1310
virtual mozilla::LogicalMargin GetLogicalUsedPadding(
1311
mozilla::WritingMode aWritingMode) const {
1312
return mozilla::LogicalMargin(aWritingMode, GetUsedPadding());
1313
}
1314
1315
nsMargin GetUsedBorderAndPadding() const {
1316
return GetUsedBorder() + GetUsedPadding();
1317
}
1318
mozilla::LogicalMargin GetLogicalUsedBorderAndPadding(
1319
mozilla::WritingMode aWritingMode) const {
1320
return mozilla::LogicalMargin(aWritingMode, GetUsedBorderAndPadding());
1321
}
1322
1323
/**
1324
* Like the frame's rect (see |GetRect|), which is the border rect,
1325
* other rectangles of the frame, in app units, relative to the parent.
1326
*/
1327
nsRect GetPaddingRect() const;
1328
nsRect GetPaddingRectRelativeToSelf() const;
1329
nsRect GetContentRect() const;
1330
nsRect GetContentRectRelativeToSelf() const;
1331
nsRect GetMarginRectRelativeToSelf() const;
1332
1333
/**
1334
* The area to paint box-shadows around. The default is the border rect.
1335
* (nsFieldSetFrame overrides this).
1336
*/
1337
virtual nsRect VisualBorderRectRelativeToSelf() const {
1338
return nsRect(0, 0, mRect.Width(), mRect.Height());
1339
}
1340
1341
/**
1342
* Get the size, in app units, of the border radii. It returns FALSE iff all
1343
* returned radii == 0 (so no border radii), TRUE otherwise.
1344
* For the aRadii indexes, use the enum HalfCorner constants in gfx/2d/Types.h
1345
* If a side is skipped via aSkipSides, its corners are forced to 0.
1346
*
1347
* All corner radii are then adjusted so they do not require more
1348
* space than aBorderArea, according to the algorithm in css3-background.
1349
*
1350
* aFrameSize is used as the basis for percentage widths and heights.
1351
* aBorderArea is used for the adjustment of radii that might be too
1352
* large.
1353
* FIXME: In the long run, we can probably get away with only one of
1354
* these, especially if we change the way we handle outline-radius (by
1355
* removing it and inflating the border radius)
1356
*
1357
* Return whether any radii are nonzero.
1358
*/
1359
static bool ComputeBorderRadii(const mozilla::BorderRadius&,
1360
const nsSize& aFrameSize,
1361
const nsSize& aBorderArea, Sides aSkipSides,
1362
nscoord aRadii[8]);
1363
1364
/*
1365
* Given a set of border radii for one box (e.g., border box), convert
1366
* it to the equivalent set of radii for another box (e.g., in to
1367
* padding box, out to outline box) by reducing radii or increasing
1368
* nonzero radii as appropriate.
1369
*
1370
* Indices into aRadii are the enum HalfCorner constants in gfx/2d/Types.h
1371
*
1372
* Note that InsetBorderRadii is lossy, since it can turn nonzero
1373
* radii into zero, and OutsetBorderRadii does not inflate zero radii.
1374
* Therefore, callers should always inset or outset directly from the
1375
* original value coming from style.
1376
*/
1377
static void InsetBorderRadii(nscoord aRadii[8], const nsMargin& aOffsets);
1378
static void OutsetBorderRadii(nscoord aRadii[8], const nsMargin& aOffsets);
1379
1380
/**
1381
* Fill in border radii for this frame. Return whether any are nonzero.
1382
* Indices into aRadii are the enum HalfCorner constants in gfx/2d/Types.h
1383
* aSkipSides is a union of eSideBitsLeft/Right/Top/Bottom bits that says
1384
* which side(s) to skip.
1385
*
1386
* Note: GetMarginBoxBorderRadii() and GetShapeBoxBorderRadii() work only
1387
* on frames that establish block formatting contexts since they don't
1388
* participate in margin-collapsing.
1389
*/
1390
virtual bool GetBorderRadii(const nsSize& aFrameSize,
1391
const nsSize& aBorderArea, Sides aSkipSides,
1392
nscoord aRadii[8]) const;
1393
bool GetBorderRadii(nscoord aRadii[8]) const;
1394
bool GetMarginBoxBorderRadii(nscoord aRadii[8]) const;
1395
bool GetPaddingBoxBorderRadii(nscoord aRadii[8]) const;
1396
bool GetContentBoxBorderRadii(nscoord aRadii[8]) const;
1397
bool GetBoxBorderRadii(nscoord aRadii[8], nsMargin aOffset,
1398
bool aIsOutset) const;
1399
bool GetShapeBoxBorderRadii(nscoord aRadii[8]) const;
1400
1401
/**
1402
* XXX: this method will likely be replaced by GetVerticalAlignBaseline
1403
* Get the position of the frame's baseline, relative to the top of
1404
* the frame (its top border edge). Only valid when Reflow is not
1405
* needed.
1406
* @note You should only call this on frames with a WM that's parallel to aWM.
1407
* @param aWM the writing-mode of the alignment context, with the ltr/rtl
1408
* direction tweak done by nsIFrame::GetWritingMode(nsIFrame*) in inline
1409
* contexts (see that method).
1410
*/
1411
virtual nscoord GetLogicalBaseline(mozilla::WritingMode aWM) const = 0;
1412
1413
/**
1414
* Synthesize a first(last) inline-axis baseline from our margin-box.
1415
* An alphabetical baseline is at the start(end) edge and a central baseline
1416
* is at the center of our block-axis margin-box (aWM tells which to use).
1418
* @note You should only call this on frames with a WM that's parallel to aWM.
1419
* @param aWM the writing-mode of the alignment context
1420
* @return an offset from our border-box block-axis start(end) edge for
1421
* a first(last) baseline respectively
1422
* (implemented in nsIFrameInlines.h)
1423
*/
1424
inline nscoord SynthesizeBaselineBOffsetFromMarginBox(
1425
mozilla::WritingMode aWM, BaselineSharingGroup aGroup) const;
1426
1427
/**
1428
* Synthesize a first(last) inline-axis baseline from our border-box.
1429
* An alphabetical baseline is at the start(end) edge and a central baseline
1430
* is at the center of our block-axis border-box (aWM tells which to use).
1432
* @note The returned value is only valid when reflow is not needed.
1433
* @note You should only call this on frames with a WM that's parallel to aWM.
1434
* @param aWM the writing-mode of the alignment context
1435
* @return an offset from our border-box block-axis start(end) edge for
1436
* a first(last) baseline respectively
1437
* (implemented in nsIFrameInlines.h)
1438
*/
1439
inline nscoord SynthesizeBaselineBOffsetFromBorderBox(
1440
mozilla::WritingMode aWM, BaselineSharingGroup aGroup) const;
1441
1442
/**
1443
* Return the position of the frame's inline-axis baseline, or synthesize one
1444
* for the given alignment context. The returned baseline is the distance from
1445
* the block-axis border-box start(end) edge for aBaselineGroup eFirst(eLast).
1446
* @note The returned value is only valid when reflow is not needed.
1447
* @note You should only call this on frames with a WM that's parallel to aWM.
1448
* @param aWM the writing-mode of the alignment context
1449
* @param aBaselineOffset out-param, only valid if the method returns true
1450
* (implemented in nsIFrameInlines.h)
1451
*/
1452
inline nscoord BaselineBOffset(mozilla::WritingMode aWM,
1453
BaselineSharingGroup aBaselineGroup,
1454
AlignmentContext aAlignmentContext) const;
1455
1456
/**
1457
* XXX: this method is taking over the role that GetLogicalBaseline has.
1458
* Return true if the frame has a CSS2 'vertical-align' baseline.
1459
* If it has, then the returned baseline is the distance from the block-
1460
* axis border-box start edge.
1461
* @note This method should only be used in AlignmentContext::Inline
1462
* contexts.
1463
* @note The returned value is only valid when reflow is not needed.
1464
* @note You should only call this on frames with a WM that's parallel to aWM.
1465
* @param aWM the writing-mode of the alignment context
1466
* @param aBaseline the baseline offset, only valid if the method returns true
1467
*/
1468
virtual bool GetVerticalAlignBaseline(mozilla::WritingMode aWM,
1469
nscoord* aBaseline) const {
1470
return false;
1471
}
1472
1473
/**
1474
* Return true if the frame has a first(last) inline-axis natural baseline per
1475
* CSS Box Alignment. If so, then the returned baseline is the distance from
1476
* the block-axis border-box start(end) edge for aBaselineGroup eFirst(eLast).
1478
* @note The returned value is only valid when reflow is not needed.
1479
* @note You should only call this on frames with a WM that's parallel to aWM.
1480
* @param aWM the writing-mode of the alignment context
1481
* @param aBaseline the baseline offset, only valid if the method returns true
1482
*/
1483
virtual bool GetNaturalBaselineBOffset(mozilla::WritingMode aWM,
1484
BaselineSharingGroup aBaselineGroup,
1485
nscoord* aBaseline) const {
1486
return false;
1487
}
1488
1489
/**
1490
* Get the position of the baseline on which the caret needs to be placed,
1491
* relative to the top of the frame. This is mostly needed for frames
1492
* which return a baseline from GetBaseline which is not useful for
1493
* caret positioning.
1494
*/
1495
virtual nscoord GetCaretBaseline() const {
1496
return GetLogicalBaseline(GetWritingMode());
1497
}
1498
1499
///////////////////////////////////////////////////////////////////////////////
1500
// The public visibility API.
1501
///////////////////////////////////////////////////////////////////////////////
1502
1503
/// @return true if we're tracking visibility for this frame.
1504
bool TrackingVisibility() const {
1505
return bool(GetStateBits() & NS_FRAME_VISIBILITY_IS_TRACKED);
1506
}
1507
1508
/// @return the visibility state of this frame. See the Visibility enum
1509
/// for the possible return values and their meanings.
1510
Visibility GetVisibility() const;
1511
1512
/// Update the visibility state of this frame synchronously.
1513
/// XXX(seth): Avoid using this method; we should be relying on the refresh
1514
/// driver for visibility updates. This method, which replaces
1515
/// nsLayoutUtils::UpdateApproximateFrameVisibility(), exists purely as a
1516
/// temporary measure to avoid changing behavior during the transition from
1517
/// the old image visibility code.
1518
void UpdateVisibilitySynchronously();
1519
1520
// A frame property which stores the visibility state of this frame. Right
1521
// now that consists of an approximate visibility counter represented as a
1522
// uint32_t. When the visibility of this frame is not being tracked, this
1523
// property is absent.
1524
NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(VisibilityStateProperty, uint32_t);
1525
1526
protected:
1527
/**
1528
* Subclasses can call this method to enable visibility tracking for this
1529
* frame.
1530
*
1531
* If visibility tracking was previously disabled, this will schedule an
1532
* update an asynchronous update of visibility.
1533
*/
1534
void EnableVisibilityTracking();
1535
1536
/**
1537
* Subclasses can call this method to disable visibility tracking for this
1538
* frame.
1539
*
1540
* Note that if visibility tracking was previously enabled, disabling
1541
* visibility tracking will cause a synchronous call to OnVisibilityChange().
1542
*/
1543
void DisableVisibilityTracking();
1544
1545
/**
1546
* Called when a frame transitions between visibility states (for example,
1547
* from nonvisible to visible, or from visible to nonvisible).
1548
*
1549
* @param aNewVisibility The new visibility state.
1550
* @param aNonvisibleAction A requested action if the frame has become
1551
* nonvisible. If Nothing(), no action is
1552
* requested. If DISCARD_IMAGES is specified, the
1553
* frame is requested to ask any images it's
1554
* associated with to discard their surfaces if
1555
* possible.
1556
*
1557
* Subclasses which override this method should call their parent class's
1558
* implementation.
1559
*/
1560
virtual void OnVisibilityChange(
1561
Visibility aNewVisibility,
1562
const Maybe<OnNonvisible>& aNonvisibleAction = Nothing());
1563
1564
public:
1565
///////////////////////////////////////////////////////////////////////////////
1566
// Internal implementation for the approximate frame visibility API.
1567
///////////////////////////////////////////////////////////////////////////////
1568
1569
/**
1570
* We track the approximate visibility of frames using a counter; if it's
1571
* non-zero, then the frame is considered visible. Using a counter allows us
1572
* to account for situations where the frame may be visible in more than one
1573
* place (for example, via -moz-element), and it simplifies the
1574
* implementation of our approximate visibility tracking algorithms.
1575
*
1576
* @param aNonvisibleAction A requested action if the frame has become
1577
* nonvisible. If Nothing(), no action is
1578
* requested. If DISCARD_IMAGES is specified, the
1579
* frame is requested to ask any images it's
1580
* associated with to discard their surfaces if
1581
* possible.
1582
*/
1583
void DecApproximateVisibleCount(
1584
const Maybe<OnNonvisible>& aNonvisibleAction = Nothing());
1585
void IncApproximateVisibleCount();
1586
1587
/**
1588
* Get the specified child list.
1589
*
1590
* @param aListID identifies the requested child list.
1591
* @return the child list. If the requested list is unsupported by this
1592
* frame type, an empty list will be returned.
1593
*/
1594
virtual const nsFrameList& GetChildList(ChildListID aListID) const = 0;
1595
const nsFrameList& PrincipalChildList() const {
1596
return GetChildList(kPrincipalList);
1597
}
1598
virtual void GetChildLists(nsTArray<ChildList>* aLists) const = 0;
1599
1600
/**
1601
* Gets the child lists for this frame, including
1602
* ones belong to a child document.
1603
*/
1604
void GetCrossDocChildLists(nsTArray<ChildList>* aLists);
1605
1606
// The individual concrete child lists.
1607
static const ChildListID kPrincipalList = mozilla::layout::kPrincipalList;
1608
static const ChildListID kAbsoluteList = mozilla::layout::kAbsoluteList;
1609
static const ChildListID kBulletList = mozilla::layout::kBulletList;
1610
static const ChildListID kCaptionList = mozilla::layout::kCaptionList;
1611
static const ChildListID kColGroupList = mozilla::layout::kColGroupList;
1612
static const ChildListID kExcessOverflowContainersList =
1613
mozilla::layout::kExcessOverflowContainersList;
1614
static const ChildListID kFixedList = mozilla::layout::kFixedList;
1615
static const ChildListID kFloatList = mozilla::layout::kFloatList;
1616
static const ChildListID kOverflowContainersList =
1617
mozilla::layout::kOverflowContainersList;
1618
static const ChildListID kOverflowList = mozilla::layout::kOverflowList;
1619
static const ChildListID kOverflowOutOfFlowList =
1620
mozilla::layout::kOverflowOutOfFlowList;
1621
static const ChildListID kPopupList = mozilla::layout::kPopupList;
1622
static const ChildListID kPushedFloatsList =
1623
mozilla::layout::kPushedFloatsList;
1624
static const ChildListID kSelectPopupList = mozilla::layout::kSelectPopupList;
1625
static const ChildListID kBackdropList = mozilla::layout::kBackdropList;
1626
// A special alias for kPrincipalList that do not request reflow.
1627
static const ChildListID kNoReflowPrincipalList =
1628
mozilla::layout::kNoReflowPrincipalList;
1629
1630
/**
1631
* Child frames are linked together in a doubly-linked list
1632
*/
1633
nsIFrame* GetNextSibling() const { return mNextSibling; }
1634
void SetNextSibling(nsIFrame* aNextSibling) {
1635
NS_ASSERTION(this != aNextSibling,
1636
"Creating a circular frame list, this is very bad.");
1637
if (mNextSibling && mNextSibling->GetPrevSibling() == this) {
1638
mNextSibling->mPrevSibling = nullptr;
1639
}
1640
mNextSibling = aNextSibling;
1641
if (mNextSibling) {
1642
mNextSibling->mPrevSibling = this;
1643
}
1644
}
1645
1646
nsIFrame* GetPrevSibling() const { return mPrevSibling; }
1647
1648
/**
1649
* Builds the display lists for the content represented by this frame
1650
* and its descendants. The background+borders of this element must
1651
* be added first, before any other content.
1652
*
1653
* This should only be called by methods in nsFrame. Instead of calling this
1654
* directly, call either BuildDisplayListForStackingContext or
1655
* BuildDisplayListForChild.
1656
*
1657
* See nsDisplayList.h for more information about display lists.
1658
*/
1659
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
1660
const nsDisplayListSet& aLists) {}
1661
/**
1662
* Displays the caret onto the given display list builder. The caret is
1663
* painted on top of the rest of the display list items.
1664
*/
1665
void DisplayCaret(nsDisplayListBuilder* aBuilder, nsDisplayList* aList);
1666
1667
/**
1668
* Get the preferred caret color at the offset.
1669
*
1670
* @param aOffset is offset of the content.
1671
*/
1672
virtual nscolor GetCaretColorAt(int32_t aOffset);
1673
1674
bool IsThemed(nsITheme::Transparency* aTransparencyState = nullptr) const {
1675
return IsThemed(StyleDisplay(), aTransparencyState);
1676
}
1677
bool IsThemed(const nsStyleDisplay* aDisp,
1678
nsITheme::Transparency* aTransparencyState = nullptr) const {
1679
if (!aDisp->HasAppearance()) {
1680
return false;
1681
}
1682
nsIFrame* mutable_this = const_cast<nsIFrame*>(this);
1683
nsPresContext* pc = PresContext();
1684
nsITheme* theme = pc->GetTheme();
1685
if (!theme ||
1686
!theme->ThemeSupportsWidget(pc, mutable_this, aDisp->mAppearance))
1687
return false;
1688
if (aTransparencyState) {
1689
*aTransparencyState =
1690
theme->GetWidgetTransparency(mutable_this, aDisp->mAppearance);
1691
}
1692
return true;
1693
}
1694
1695
/**
1696
* Builds a display list for the content represented by this frame,
1697
* treating this frame as the root of a stacking context.
1698
* Optionally sets aCreatedContainerItem to true if we created a
1699
* single container display item for the stacking context, and no
1700
* other wrapping items are needed.
1701
*/
1702
void BuildDisplayListForStackingContext(
1703
nsDisplayListBuilder* aBuilder, nsDisplayList* aList,
1704
bool* aCreatedContainerItem = nullptr);
1705
1706
enum {
1707
DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT = 0x01,
1708
DISPLAY_CHILD_FORCE_STACKING_CONTEXT = 0x02,
1709
DISPLAY_CHILD_INLINE = 0x04
1710
};
1711
/**
1712
* Adjusts aDirtyRect for the child's offset, checks that the dirty rect
1713
* actually intersects the child (or its descendants), calls BuildDisplayList
1714
* on the child if necessary, and puts things in the right lists if the child
1715
* is positioned.
1716
*
1717
* @param aFlags combination of DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT,
1718
* DISPLAY_CHILD_FORCE_STACKING_CONTEXT and DISPLAY_CHILD_INLINE
1719
*/
1720
void BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
1721
nsIFrame* aChild,
1722
const nsDisplayListSet& aLists,
1723
uint32_t aFlags = 0);
1724
1725
void BuildDisplayListForSimpleChild(nsDisplayListBuilder* aBuilder,
1726
nsIFrame* aChild,
1727
const nsDisplayListSet& aLists);
1728
1729
bool RefusedAsyncAnimation() const {
1730
return GetProperty(RefusedAsyncAnimationProperty());
1731
}
1732
1733
/**
1734
* Returns true if this frame is transformed (e.g. has CSS or SVG transforms)
1735
* or if its parent is an SVG frame that has children-only transforms (e.g.
1736
* an SVG viewBox attribute) or if its transform-style is preserve-3d or
1737
* the frame has transform animations.
1738
*
1739
* @param aStyleDisplay: If the caller has this->StyleDisplay(), providing
1740
* it here will improve performance.
1741
*/
1742
bool IsTransformed(const nsStyleDisplay* aStyleDisplay) const;
1743
bool IsTransformed() const { return IsTransformed(StyleDisplay()); }
1744
1745
/**
1746
* Same as IsTransformed, except that it doesn't take SVG transforms
1747
* into account.
1748
*/
1749
bool IsCSSTransformed(const nsStyleDisplay* aStyleDisplay) const;
1750
1751
/**
1752
* True if this frame has any animation of transform in effect.
1753
*
1754
*/
1755
bool HasAnimationOfTransform() const;
1756
1757
/**
1758
* Returns true if the frame is translucent or the frame has opacity
1759
* animations for the purposes of creating a stacking context.
1760
*
1761
* @param aStyleDisplay: This function needs style display struct.
1762
*
1763
* @param aStyleEffects: This function needs style effects struct.
1764
*
1765
* @param aEffectSet: This function may need to look up EffectSet property.
1766
* If a caller already have one, pass it in can save property look up
1767
* time; otherwise, just leave it as nullptr.
1768
*/
1769
bool HasOpacity(const nsStyleDisplay* aStyleDisplay,
1770
const nsStyleEffects* aStyleEffects,
1771
mozilla::EffectSet* aEffectSet = nullptr) const {
1772
return HasOpacityInternal(1.0f, aStyleDisplay, aStyleEffects, aEffectSet);
1773
}
1774
/**
1775
* Returns true if the frame is translucent for display purposes.
1776
*
1777
* @param aStyleDisplay: This function needs style display struct.
1778
*
1779
* @param aStyleEffects: This function needs style effects struct.
1780
*
1781
* @param aEffectSet: This function may need to look up EffectSet property.
1782
* If a caller already have one, pass it in can save property look up
1783
* time; otherwise, just leave it as nullptr.
1784
*/
1785
bool HasVisualOpacity(const nsStyleDisplay* aStyleDisplay,
1786
const nsStyleEffects* aStyleEffects,
1787
mozilla::EffectSet* aEffectSet = nullptr) const {
1788
// Treat an opacity value of 0.99 and above as opaque. This is an
1789
// optimization aimed at Web content which use opacity:0.99 as a hint for
1790
// creating a stacking context only.
1791
return HasOpacityInternal(0.99f, aStyleDisplay, aStyleEffects, aEffectSet);
1792
}
1793
1794
/**
1795
* Return true if this frame might be using a transform getter.
1796
*/
1797
virtual bool HasTransformGetter() const { return false; }
1798
1799
/**
1800
* Returns true if this frame is an SVG frame that has SVG transforms applied
1801
* to it, or if its parent frame is an SVG frame that has children-only
1802
* transforms (e.g. an SVG viewBox attribute).
1803
* If aOwnTransforms is non-null and the frame has its own SVG transforms,
1804
* aOwnTransforms will be set to these transforms. If aFromParentTransforms
1805
* is non-null and the frame has an SVG parent with children-only transforms,
1806
* then aFromParentTransforms will be set to these transforms.
1807
*/
1808
virtual bool IsSVGTransformed(Matrix* aOwnTransforms = nullptr,
1809
Matrix* aFromParentTransforms = nullptr) const;
1810
1811
/**
1812
* Return true if this frame should form a backdrop root container.
1814
*/
1815
bool FormsBackdropRoot(const nsStyleDisplay* aStyleDisplay,
1816
const nsStyleEffects* aStyleEffects,
1817
const nsStyleSVGReset* aStyleSvgReset);
1818
1819
/**
1820
* Returns whether this frame will attempt to extend the 3d transforms of its
1821
* children. This requires transform-style: preserve-3d, as well as no
1822
* clipping or svg effects.
1823
*
1824
* @param aStyleDisplay: If the caller has this->StyleDisplay(), providing
1825
* it here will improve performance.
1826
*
1827
* @param aStyleEffects: If the caller has this->StyleEffects(), providing
1828
* it here will improve performance.
1829
*
1830
* @param aEffectSetForOpacity: This function may need to look up the
1831
* EffectSet for opacity animations on this frame.
1832
* If the caller already has looked up this EffectSet, it may pass it in to
1833
* save an extra property lookup.
1834
*/
1835
bool Extend3DContext(
1836
const nsStyleDisplay* aStyleDisplay, const nsStyleEffects* aStyleEffects,
1837
mozilla::EffectSet* aEffectSetForOpacity = nullptr) const;
1838
bool Extend3DContext(
1839
mozilla::EffectSet* aEffectSetForOpacity = nullptr) const {
1840
return Extend3DContext(StyleDisplay(), StyleEffects(),
1841
aEffectSetForOpacity);
1842
}
1843
1844
/**
1845
* Returns whether this frame has a parent that Extend3DContext() and has
1846
* its own transform (or hidden backface) to be combined with the parent's
1847
* transform.
1848
*
1849
* @param aStyleDisplay: If the caller has this->StyleDisplay(), providing
1850
* it here will improve performance.
1851
*/
1852
bool Combines3DTransformWithAncestors(
1853
const nsStyleDisplay* aStyleDisplay) const;
1854
bool Combines3DTransformWithAncestors() const {
1855
return Combines3DTransformWithAncestors(StyleDisplay());
1856
}
1857
1858
/**
1859
* Returns whether this frame has a hidden backface and has a parent that
1860
* Extend3DContext(). This is useful because in some cases the hidden
1861
* backface can safely be ignored if it could not be visible anyway.
1862
*
1863
*/
1864
bool In3DContextAndBackfaceIsHidden() const;
1865
1866
bool IsPreserve3DLeaf(const nsStyleDisplay* aStyleDisplay,
1867
mozilla::EffectSet* aEffectSet = nullptr) const {
1868
return Combines3DTransformWithAncestors(aStyleDisplay) &&
1869
!Extend3DContext(aStyleDisplay, StyleEffects(), aEffectSet);
1870
}
1871
bool IsPreserve3DLeaf(mozilla::EffectSet* aEffectSet = nullptr) const {
1872
return IsPreserve3DLeaf(StyleDisplay(), aEffectSet);
1873
}
1874
1875
bool HasPerspective(const nsStyleDisplay* aStyleDisplay) const;
1876
bool HasPerspective() const { return HasPerspective(StyleDisplay()); }
1877
1878
bool ChildrenHavePerspective(const nsStyleDisplay* aStyleDisplay) const;
1879
bool ChildrenHavePerspective() const {
1880
return ChildrenHavePerspective(StyleDisplay());
1881
}
1882
1883
/**
1884
* Includes the overflow area of all descendants that participate in the
1885
* current 3d context into aOverflowAreas.
1886
*/
1887
void ComputePreserve3DChildrenOverflow(nsOverflowAreas& aOverflowAreas);
1888
1889
void RecomputePerspectiveChildrenOverflow(const nsIFrame* aStartFrame);
1890
1891
/**
1892
* Returns the computed z-index for this frame, returning 0 for z-index:auto
1893
* and frames that don't support z-index.
1894
*/
1895
int32_t ZIndex() const;
1896
1897
/**
1898
* Returns whether this frame is the anchor of some ancestor scroll frame. As
1899
* this frame is moved, the scroll frame will apply adjustments to keep this
1900
* scroll frame in the same relative position.
1901
*
1902
* aOutContainer will optionally be set to the scroll anchor container for
1903
* this frame if this frame is an anchor.
1904
*/
1905
bool IsScrollAnchor(
1906
mozilla::layout::ScrollAnchorContainer** aOutContainer = nullptr);
1907
1908
/**
1909
* Returns whether this frame is the anchor of some ancestor scroll frame, or
1910
* has a descendant which is the scroll anchor.
1911
*/
1912
bool IsInScrollAnchorChain() const;
1913
void SetInScrollAnchorChain(bool aInChain);
1914
1915
/**
1916
* Returns the number of ancestors between this and the root of our frame tree
1917
*/
1918
uint32_t GetDepthInFrameTree() const;
1919
1920
/**
1921
* Event handling of GUI events.
1922
*
1923
* @param aEvent event structure describing the type of event and rge widget
1924
* where the event originated. The |point| member of this is in the coordinate
1925
* system of the view returned by GetOffsetFromView.
1926
*
1927
* @param aEventStatus a return value indicating whether the event was
1928
* handled and whether default processing should be done
1929
*
1930
* XXX From a frame's perspective it's unclear what the effect of the event
1931
* status is. Does it cause the event to continue propagating through the
1932
* frame hierarchy or is it just returned to the widgets?
1933
*
1934
* @see WidgetGUIEvent
1935
* @see nsEventStatus
1936
*/
1937
virtual nsresult HandleEvent(nsPresContext* aPresContext,
1938
mozilla::WidgetGUIEvent* aEvent,
1939
nsEventStatus* aEventStatus) = 0;
1940
1941
virtual nsresult GetContentForEvent(mozilla::WidgetEvent* aEvent,
1942
nsIContent** aContent) = 0;
1943
1944
// This structure keeps track of the content node and offsets associated with
1945
// a point; there is a primary and a secondary offset associated with any
1946
// point. The primary and secondary offsets differ when the point is over a
1947
// non-text object. The primary offset is the expected position of the
1948
// cursor calculated from a point; the secondary offset, when it is different,
1949
// indicates that the point is in the boundaries of some selectable object.
1950
// Note that the primary offset can be after the secondary offset; for places
1951
// that need the beginning and end of the object, the StartOffset and
1952
// EndOffset helpers can be used.
1953
struct MOZ_STACK_CLASS ContentOffsets {
1954
ContentOffsets()
1955
: offset(0),
1956
secondaryOffset(0),
1957
associate(mozilla::CARET_ASSOCIATE_BEFORE) {}
1958
bool IsNull() { return !content; }
1959
// Helpers for places that need the ends of the offsets and expect them in
1960
// numerical order, as opposed to wanting the primary and secondary offsets
1961
int32_t StartOffset() { return std::min(offset, secondaryOffset); }
1962
int32_t EndOffset() { return std::max(offset, secondaryOffset); }
1963
1964
nsCOMPtr<nsIContent>