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