Backed out changeset 1b14354719c0 (bug 1895254) for causing bustages on NavigationTra...
[gecko.git] / layout / base / nsChangeHint.h
blob5806abfd849699e867e7d29e09f3b8f13770617f
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 /* constants for what needs to be recomputed in response to style changes */
9 #ifndef nsChangeHint_h___
10 #define nsChangeHint_h___
12 #include "mozilla/Types.h"
13 #include "mozilla/Assertions.h"
15 // Defines for various style related constants
17 enum nsChangeHint : uint32_t {
18 nsChangeHint_Empty = 0,
20 // change was visual only (e.g., COLOR=)
21 // Invalidates all descendant frames (including following
22 // placeholders to out-of-flow frames).
23 nsChangeHint_RepaintFrame = 1 << 0,
25 // For reflow, we want flags to give us arbitrary FrameNeedsReflow behavior.
26 // just do a FrameNeedsReflow.
27 nsChangeHint_NeedReflow = 1 << 1,
29 // Invalidate intrinsic widths on the frame's ancestors. Must not be set
30 // without setting nsChangeHint_NeedReflow.
31 nsChangeHint_ClearAncestorIntrinsics = 1 << 2,
33 // Invalidate intrinsic widths on the frame's descendants. Must not be set
34 // without also setting nsChangeHint_ClearAncestorIntrinsics,
35 // nsChangeHint_NeedDirtyReflow and nsChangeHint_NeedReflow.
36 nsChangeHint_ClearDescendantIntrinsics = 1 << 3,
38 // Force unconditional reflow of all descendants. Must not be set without
39 // setting nsChangeHint_NeedReflow, but can be set regardless of whether the
40 // Clear*Intrinsics flags are set.
41 nsChangeHint_NeedDirtyReflow = 1 << 4,
43 // The currently shown mouse cursor needs to be updated
44 nsChangeHint_UpdateCursor = 1 << 5,
46 /**
47 * Used when the computed value (a URI) of one or more of an element's
48 * filter/mask/clip/etc CSS properties changes, causing the element's frame
49 * to start/stop referencing (or reference different) SVG resource elements.
50 * (_Not_ used to handle changes to referenced resource elements.) Using this
51 * hint results in SVGObserverUtils::UpdateEffects being called on the
52 * element's frame.
54 nsChangeHint_UpdateEffects = 1 << 6,
56 /**
57 * Visual change only, but the change can be handled entirely by
58 * updating the layer(s) for the frame.
59 * Updates all descendants (including following placeholders to out-of-flows).
61 nsChangeHint_UpdateOpacityLayer = 1 << 7,
62 /**
63 * Updates all descendants. Any placeholder descendants' out-of-flows
64 * are also descendants of the transformed frame, so they're updated.
66 nsChangeHint_UpdateTransformLayer = 1 << 8,
68 /**
69 * Change requires frame change (e.g., display:).
70 * Reconstructs all frame descendants, including following placeholders
71 * to out-of-flows.
73 * Note that this subsumes all the other change hints. (see
74 * RestyleManager::ProcessRestyledFrames for details).
76 nsChangeHint_ReconstructFrame = 1 << 9,
78 /**
79 * The frame's overflow area has changed. Does not update any descendant
80 * frames.
82 nsChangeHint_UpdateOverflow = 1 << 10,
84 /**
85 * The overflow area of the frame and all of its descendants has changed. This
86 * can happen through a text-decoration change.
88 nsChangeHint_UpdateSubtreeOverflow = 1 << 11,
90 /**
91 * The frame's overflow area has changed, through a change in its transform.
92 * In other words, the frame's pre-transform overflow is unchanged, but
93 * its post-transform overflow has changed, and thus its effect on its
94 * parent's overflow has changed. If the pre-transform overflow has
95 * changed, see nsChangeHint_UpdateOverflow.
96 * Does not update any descendant frames.
98 nsChangeHint_UpdatePostTransformOverflow = 1 << 12,
101 * This frame's effect on its parent's overflow area has changed.
102 * (But neither its pre-transform nor post-transform overflow have
103 * changed; if those are the case, see
104 * nsChangeHint_UpdatePostTransformOverflow.)
106 nsChangeHint_UpdateParentOverflow = 1 << 13,
109 * The children-only transform of an SVG frame changed, requiring overflows to
110 * be updated.
112 nsChangeHint_ChildrenOnlyTransform = 1 << 14,
115 * The frame's offsets have changed, while its dimensions might have
116 * changed as well. This hint is used for positioned frames if their
117 * offset changes. If we decide that the dimensions are likely to
118 * change, this will trigger a reflow.
120 * Note that this should probably be used in combination with
121 * nsChangeHint_UpdateOverflow in order to get the overflow areas of
122 * the ancestors updated as well.
124 nsChangeHint_RecomputePosition = 1 << 15,
127 * Behaves like ReconstructFrame, but only if the frame has descendants
128 * that are absolutely or fixed position. Use this hint when a style change
129 * has changed whether the frame is a container for fixed-pos or abs-pos
130 * elements, but reframing is otherwise not needed.
132 * Note that ComputedStyle::CalcStyleDifference adjusts results
133 * returned by style struct CalcDifference methods to return this hint
134 * only if there was a change to whether the element's overall style
135 * indicates that it establishes a containing block.
137 nsChangeHint_UpdateContainingBlock = 1 << 16,
140 * This change hint has *no* change handling behavior. However, it
141 * exists to be a non-inherited hint, because when the border-style
142 * changes, and it's inherited by a child, that might require a reflow
143 * due to the border-width change on the child.
145 nsChangeHint_BorderStyleNoneChange = 1 << 17,
148 * This will schedule an invalidating paint. This is useful if something
149 * has changed which will be invalidated by DLBI.
151 nsChangeHint_SchedulePaint = 1 << 18,
154 * A hint reflecting that style data changed with no change handling
155 * behavior. We need to return this, rather than nsChangeHint(0),
156 * so that certain optimizations that manipulate the style tree are
157 * correct.
159 * nsChangeHint_NeutralChange must be returned by CalcDifference on a given
160 * style struct if the data in the style structs are meaningfully different
161 * and if no other change hints are returned. If any other change hints are
162 * set, then nsChangeHint_NeutralChange need not also be included, but it is
163 * safe to do so. (An example of style structs having non-meaningfully
164 * different data would be cached information that would be re-calculated
165 * to the same values, such as nsStyleBorder::mSubImages.)
167 nsChangeHint_NeutralChange = 1 << 19,
170 * This will cause rendering observers to be invalidated.
172 nsChangeHint_InvalidateRenderingObservers = 1 << 20,
175 * Indicates that the reflow changes the size or position of the
176 * element, and thus the reflow must start from at least the frame's
177 * parent. Must be not be set without also setting nsChangeHint_NeedReflow.
178 * And consider adding nsChangeHint_ClearAncestorIntrinsics if needed.
180 nsChangeHint_ReflowChangesSizeOrPosition = 1 << 21,
183 * Indicates that the style changes the computed BSize --- e.g. 'height'.
184 * Must not be set without also setting nsChangeHint_NeedReflow.
186 nsChangeHint_UpdateComputedBSize = 1 << 22,
189 * Indicates that the 'opacity' property changed between 1 and non-1.
191 * Used as extra data for handling UpdateOpacityLayer hints.
193 * Note that we do not send this hint if the non-1 value was 0.99 or
194 * greater, since in that case we send a RepaintFrame hint instead.
196 nsChangeHint_UpdateUsesOpacity = 1 << 23,
199 * Indicates that the 'background-position' property changed.
200 * Regular frames can invalidate these changes using DLBI, but
201 * for some frame types we need to repaint the whole frame because
202 * the frame does not build individual background image display items
203 * for each background layer.
205 nsChangeHint_UpdateBackgroundPosition = 1 << 24,
208 * Indicates that a frame has changed to or from having the CSS
209 * transform property set.
211 nsChangeHint_AddOrRemoveTransform = 1 << 25,
214 * Indicates that the presence of scrollbars might have changed.
216 * This happens when at least one of overflow-{x,y} properties changed.
218 * In most cases, this is equivalent to nsChangeHint_ReconstructFrame. But
219 * in some special cases where the change is really targeting the viewport's
220 * scrollframe, this is instead equivalent to nsChangeHint_AllReflowHints
221 * (because the viewport always has an associated scrollframe).
223 nsChangeHint_ScrollbarChange = 1 << 26,
226 * Indicates that there has been a colspan or rowspan attribute change
227 * on the cells of a table.
229 nsChangeHint_UpdateTableCellSpans = 1 << 27,
232 * Indicates that the visiblity property changed.
233 * This change hint is used for skip restyling for animations on
234 * visibility:hidden elements in the case where the elements have no visible
235 * descendants.
237 nsChangeHint_VisibilityChange = 1u << 28,
239 // IMPORTANT NOTE: When adding a new hint, you will need to add it to
240 // one of:
242 // * nsChangeHint_Hints_NeverHandledForDescendants
243 // * nsChangeHint_Hints_AlwaysHandledForDescendants
244 // * nsChangeHint_Hints_SometimesHandledForDescendants
246 // and you also may need to handle it in NS_HintsNotHandledForDescendantsIn.
248 // Please also add it to RestyleManager::ChangeHintToString and
249 // modify nsChangeHint_AllHints below accordingly.
252 * Dummy hint value for all hints. It exists for compile time check.
254 nsChangeHint_AllHints = uint32_t((1ull << 29) - 1),
257 // Redefine these operators to return nothing. This will catch any use
258 // of these operators on hints. We should not be using these operators
259 // on nsChangeHints
260 inline void operator<(nsChangeHint s1, nsChangeHint s2) {}
261 inline void operator>(nsChangeHint s1, nsChangeHint s2) {}
262 inline void operator!=(nsChangeHint s1, nsChangeHint s2) {}
263 inline void operator==(nsChangeHint s1, nsChangeHint s2) {}
264 inline void operator<=(nsChangeHint s1, nsChangeHint s2) {}
265 inline void operator>=(nsChangeHint s1, nsChangeHint s2) {}
267 // Operators on nsChangeHints
269 // Returns true iff the second hint contains all the hints of the first hint
270 inline bool NS_IsHintSubset(nsChangeHint aSubset, nsChangeHint aSuperSet) {
271 return (aSubset & aSuperSet) == aSubset;
274 // The functions below need an integral type to cast to to avoid
275 // infinite recursion.
276 typedef decltype(nsChangeHint(0) + nsChangeHint(0)) nsChangeHint_size_t;
278 inline nsChangeHint constexpr operator|(nsChangeHint aLeft,
279 nsChangeHint aRight) {
280 return nsChangeHint(nsChangeHint_size_t(aLeft) | nsChangeHint_size_t(aRight));
283 inline nsChangeHint constexpr operator&(nsChangeHint aLeft,
284 nsChangeHint aRight) {
285 return nsChangeHint(nsChangeHint_size_t(aLeft) & nsChangeHint_size_t(aRight));
288 inline nsChangeHint& operator|=(nsChangeHint& aLeft, nsChangeHint aRight) {
289 return aLeft = aLeft | aRight;
292 inline nsChangeHint& operator&=(nsChangeHint& aLeft, nsChangeHint aRight) {
293 return aLeft = aLeft & aRight;
296 inline nsChangeHint constexpr operator~(nsChangeHint aArg) {
297 return nsChangeHint(~nsChangeHint_size_t(aArg));
300 inline nsChangeHint constexpr operator^(nsChangeHint aLeft,
301 nsChangeHint aRight) {
302 return nsChangeHint(nsChangeHint_size_t(aLeft) ^ nsChangeHint_size_t(aRight));
305 inline nsChangeHint operator^=(nsChangeHint& aLeft, nsChangeHint aRight) {
306 return aLeft = aLeft ^ aRight;
310 * We have an optimization when processing change hints which prevents
311 * us from visiting the descendants of a node when a hint on that node
312 * is being processed. This optimization does not apply in some of the
313 * cases where applying a hint to an element does not necessarily result
314 * in the same hint being handled on the descendants.
317 // The change hints that are always handled for descendants.
318 #define nsChangeHint_Hints_AlwaysHandledForDescendants \
319 (nsChangeHint_ClearDescendantIntrinsics | nsChangeHint_NeedDirtyReflow | \
320 nsChangeHint_NeutralChange | nsChangeHint_ReconstructFrame | \
321 nsChangeHint_RepaintFrame | nsChangeHint_SchedulePaint | \
322 nsChangeHint_UpdateCursor | nsChangeHint_UpdateSubtreeOverflow | \
323 nsChangeHint_VisibilityChange)
325 // The change hints that are never handled for descendants.
326 #define nsChangeHint_Hints_NeverHandledForDescendants \
327 (nsChangeHint_BorderStyleNoneChange | nsChangeHint_ChildrenOnlyTransform | \
328 nsChangeHint_ScrollbarChange | nsChangeHint_InvalidateRenderingObservers | \
329 nsChangeHint_RecomputePosition | nsChangeHint_UpdateBackgroundPosition | \
330 nsChangeHint_UpdateComputedBSize | nsChangeHint_UpdateContainingBlock | \
331 nsChangeHint_UpdateEffects | nsChangeHint_UpdateOpacityLayer | \
332 nsChangeHint_UpdateOverflow | nsChangeHint_UpdateParentOverflow | \
333 nsChangeHint_UpdatePostTransformOverflow | \
334 nsChangeHint_UpdateTableCellSpans | nsChangeHint_UpdateTransformLayer | \
335 nsChangeHint_UpdateUsesOpacity | nsChangeHint_AddOrRemoveTransform)
337 // The change hints that are sometimes considered to be handled for descendants.
338 #define nsChangeHint_Hints_SometimesHandledForDescendants \
339 (nsChangeHint_ClearAncestorIntrinsics | nsChangeHint_NeedReflow | \
340 nsChangeHint_ReflowChangesSizeOrPosition)
342 static_assert(!(nsChangeHint_Hints_AlwaysHandledForDescendants &
343 nsChangeHint_Hints_NeverHandledForDescendants) &&
344 !(nsChangeHint_Hints_AlwaysHandledForDescendants &
345 nsChangeHint_Hints_SometimesHandledForDescendants) &&
346 !(nsChangeHint_Hints_NeverHandledForDescendants &
347 nsChangeHint_Hints_SometimesHandledForDescendants) &&
348 !(nsChangeHint_AllHints ^
349 nsChangeHint_Hints_AlwaysHandledForDescendants ^
350 nsChangeHint_Hints_NeverHandledForDescendants ^
351 nsChangeHint_Hints_SometimesHandledForDescendants),
352 "change hints must be present in exactly one of "
353 "nsChangeHint_Hints_{Always,Never,Sometimes}"
354 "HandledForDescendants");
356 // The most hints that NS_HintsNotHandledForDescendantsIn could possibly return:
357 #define nsChangeHint_Hints_NotHandledForDescendants \
358 (nsChangeHint_Hints_NeverHandledForDescendants | \
359 nsChangeHint_Hints_SometimesHandledForDescendants)
361 // Redefine the old NS_STYLE_HINT constants in terms of the new hint structure
362 #define NS_STYLE_HINT_VISUAL \
363 nsChangeHint(nsChangeHint_RepaintFrame | nsChangeHint_SchedulePaint)
364 #define nsChangeHint_AllReflowHints \
365 nsChangeHint( \
366 nsChangeHint_NeedReflow | nsChangeHint_ReflowChangesSizeOrPosition | \
367 nsChangeHint_ClearAncestorIntrinsics | \
368 nsChangeHint_ClearDescendantIntrinsics | nsChangeHint_NeedDirtyReflow)
370 // Below are the change hints that we send for ISize & BSize changes.
371 // Each is similar to nsChangeHint_AllReflowHints with a few changes.
373 // * For an ISize change, we send nsChangeHint_AllReflowHints, with two bits
374 // excluded: nsChangeHint_ClearDescendantIntrinsics (because an ancestor's
375 // inline-size change can't affect descendant intrinsic sizes), and
376 // nsChangeHint_NeedDirtyReflow (because ISize changes don't need to *force*
377 // all descendants to reflow).
378 #define nsChangeHint_ReflowHintsForISizeChange \
379 nsChangeHint(nsChangeHint_AllReflowHints & \
380 ~(nsChangeHint_ClearDescendantIntrinsics | \
381 nsChangeHint_NeedDirtyReflow))
383 // * For a BSize change, we send almost the same hints as for ISize changes,
384 // with one extra: nsChangeHint_UpdateComputedBSize. We need this hint because
385 // BSize changes CAN affect descendant intrinsic sizes, due to replaced
386 // elements with percentage BSizes in descendants which also have percentage
387 // BSizes. nsChangeHint_UpdateComputedBSize clears intrinsic sizes for frames
388 // that have such replaced elements. (We could instead send
389 // nsChangeHint_ClearDescendantIntrinsics, but that's broader than we need.)
391 // NOTE: You might think that BSize changes could exclude
392 // nsChangeHint_ClearAncestorIntrinsics (which is inline-axis specific), but we
393 // do need to send it, to clear cached results from CSS Flex measuring reflows.
394 #define nsChangeHint_ReflowHintsForBSizeChange \
395 nsChangeHint( \
396 (nsChangeHint_AllReflowHints | nsChangeHint_UpdateComputedBSize) & \
397 ~(nsChangeHint_ClearDescendantIntrinsics | \
398 nsChangeHint_NeedDirtyReflow))
400 // For a change in whether a scrollframe displays or not scrollbars.
402 // When requesting this reflow, we send the exact same change hints that "width"
403 // and "height" would send (since conceptually, adding/removing scrollbars is
404 // like changing the available space).
406 // FIXME(emilio): Seems we could be a bit more efficient here, as adding or
407 // removing scrollbars doesn't change the size of the element itself, so maybe
408 // ClearAncestorIntrinsics or ReflowChangesSizeOrPosition are not needed... I
409 // think this ideally should be just nsChangehint_NeedReflow.
410 #define nsChangeHint_ReflowHintsForScrollbarChange \
411 nsChangeHint(nsChangeHint_ReflowHintsForBSizeChange | \
412 nsChangeHint_ReflowHintsForISizeChange)
414 // * For changes to the float area of an already-floated element, we need all
415 // reflow hints, but not the ones that apply to descendants.
416 // Our descendants aren't impacted when our float area only changes
417 // placement but not size/shape. (e.g. if we change which side we float to).
418 // But our ancestors/siblings are potentially impacted, so we need to send
419 // the non-descendant reflow hints.
420 #define nsChangeHint_ReflowHintsForFloatAreaChange \
421 nsChangeHint(nsChangeHint_AllReflowHints & \
422 ~(nsChangeHint_ClearDescendantIntrinsics | \
423 nsChangeHint_NeedDirtyReflow))
425 #define NS_STYLE_HINT_REFLOW \
426 nsChangeHint(NS_STYLE_HINT_VISUAL | nsChangeHint_AllReflowHints)
428 // Change hints for added or removed transform style.
430 // If we've added or removed the transform property, we need to reconstruct the
431 // frame to add or remove the view object, and also to handle abs-pos and
432 // fixed-pos containers.
434 // We do not need to apply nsChangeHint_UpdateTransformLayer since
435 // nsChangeHint_RepaintFrame will forcibly invalidate the frame area and
436 // ensure layers are rebuilt (or removed).
437 #define nsChangeHint_ComprehensiveAddOrRemoveTransform \
438 nsChangeHint(nsChangeHint_UpdateContainingBlock | \
439 nsChangeHint_AddOrRemoveTransform | \
440 nsChangeHint_UpdateOverflow | nsChangeHint_RepaintFrame)
442 // NB: Once we drop support for the old style system, this logic should be
443 // inlined in the Servo style system to eliminate the FFI call.
444 inline nsChangeHint NS_HintsNotHandledForDescendantsIn(
445 nsChangeHint aChangeHint) {
446 nsChangeHint result =
447 aChangeHint & nsChangeHint_Hints_NeverHandledForDescendants;
449 if (!(aChangeHint & nsChangeHint_NeedDirtyReflow)) {
450 if (aChangeHint & nsChangeHint_NeedReflow) {
451 // If NeedDirtyReflow is *not* set, then NeedReflow is a
452 // non-inherited hint.
453 result |= nsChangeHint_NeedReflow;
456 if (aChangeHint & nsChangeHint_ReflowChangesSizeOrPosition) {
457 // If NeedDirtyReflow is *not* set, then ReflowChangesSizeOrPosition is a
458 // non-inherited hint.
459 result |= nsChangeHint_ReflowChangesSizeOrPosition;
463 if (!(aChangeHint & nsChangeHint_ClearDescendantIntrinsics) &&
464 (aChangeHint & nsChangeHint_ClearAncestorIntrinsics)) {
465 // If ClearDescendantIntrinsics is *not* set, then
466 // ClearAncestorIntrinsics is a non-inherited hint.
467 result |= nsChangeHint_ClearAncestorIntrinsics;
470 MOZ_ASSERT(
471 NS_IsHintSubset(result, nsChangeHint_Hints_NotHandledForDescendants),
472 "something is inconsistent");
474 return result;
477 inline nsChangeHint NS_HintsHandledForDescendantsIn(nsChangeHint aChangeHint) {
478 return aChangeHint & ~NS_HintsNotHandledForDescendantsIn(aChangeHint);
481 // Returns the change hints in aOurChange that are not subsumed by those
482 // in aHintsHandled (which are hints that have been handled by an ancestor).
483 inline nsChangeHint NS_RemoveSubsumedHints(nsChangeHint aOurChange,
484 nsChangeHint aHintsHandled) {
485 nsChangeHint result =
486 aOurChange & ~NS_HintsHandledForDescendantsIn(aHintsHandled);
488 if (result &
489 (nsChangeHint_ClearAncestorIntrinsics |
490 nsChangeHint_ClearDescendantIntrinsics | nsChangeHint_NeedDirtyReflow |
491 nsChangeHint_ReflowChangesSizeOrPosition |
492 nsChangeHint_UpdateComputedBSize)) {
493 result |= nsChangeHint_NeedReflow;
496 if (result & (nsChangeHint_ClearDescendantIntrinsics)) {
497 MOZ_ASSERT(result & nsChangeHint_ClearAncestorIntrinsics);
498 result |= // nsChangeHint_ClearAncestorIntrinsics |
499 nsChangeHint_NeedDirtyReflow;
502 return result;
505 namespace mozilla {
507 struct StyleRestyleHint;
509 using RestyleHint = StyleRestyleHint;
511 } // namespace mozilla
513 #endif /* nsChangeHint_h___ */