Bug 1237454 - Add VisibilityChange change hint. r?emilio
This new change hint doesn't influence layout so that it can be regarded
as nsChangeHint_Hints_CanIgnoreIfNotVisible. Note that if visibility changed
from collapse or to collapse, we set NS_STYLE_HINT_REFLOW separetely.
MozReview-Commit-ID: AirDWeBYVKG
--- a/dom/animation/test/mozilla/file_restyles.html
+++ b/dom/animation/test/mozilla/file_restyles.html
@@ -653,17 +653,17 @@ waitForAllPaints(() => {
is(markers.length, 5,
'Animations running on the main-thread which were in nested scrolled ' +
'out elements should update restyle soon after the element moved ' +
'in view by scrolling');
await ensureElementRemoval(grandParent);
});
- add_task_if_omta_enabled(async function no_restyling_compositor_animations_in_visiblily_hidden_element() {
+ add_task_if_omta_enabled(async function no_restyling_compositor_animations_in_visibility_hidden_element() {
var div = addDiv(null,
{ style: 'animation: opacity 100s; visibility: hidden' });
var animation = div.getAnimations()[0];
await animation.ready;
ok(!SpecialPowers.wrap(animation).isRunningOnCompositor);
var markers = await observeStyling(5);
@@ -722,17 +722,17 @@ waitForAllPaints(() => {
is(markers.length, 1,
'Animations running on the main-thread which was in scrolled out ' +
'elements should update restyling soon after the element moved in ' +
'view by resizing');
await ensureElementRemoval(parentElement);
});
- add_task(async function no_restyling_main_thread_animations_in_visiblily_hidden_element() {
+ add_task(async function no_restyling_main_thread_animations_in_visibility_hidden_element() {
var div = addDiv(null,
{ style: 'animation: background-color 100s; visibility: hidden' });
var animation = div.getAnimations()[0];
await animation.ready;
var markers = await observeStyling(5);
todo_is(markers.length, 0,
--- a/layout/base/RestyleManager.cpp
+++ b/layout/base/RestyleManager.cpp
@@ -433,37 +433,39 @@ RestyleManager::ChangeHintToString(nsCha
"UpdateSubtreeOverflow", "UpdatePostTransformOverflow",
"UpdateParentOverflow",
"ChildrenOnlyTransform", "RecomputePosition", "UpdateContainingBlock",
"BorderStyleNoneChange", "UpdateTextPath", "SchedulePaint",
"NeutralChange", "InvalidateRenderingObservers",
"ReflowChangesSizeOrPosition", "UpdateComputedBSize",
"UpdateUsesOpacity", "UpdateBackgroundPosition",
"AddOrRemoveTransform", "CSSOverflowChange",
- "UpdateWidgetProperties", "UpdateTableCellSpans"
+ "UpdateWidgetProperties", "UpdateTableCellSpans",
+ "VisibilityChange"
};
- static_assert(nsChangeHint_AllHints == (1u << ArrayLength(names)) - 1,
+ static_assert(nsChangeHint_AllHints ==
+ static_cast<uint32_t>((1ull << ArrayLength(names)) - 1),
"Name list doesn't match change hints.");
- uint32_t hint = aHint & ((1u << ArrayLength(names)) - 1);
- uint32_t rest = aHint & ~((1u << ArrayLength(names)) - 1);
+ uint32_t hint = aHint & static_cast<uint32_t>((1ull << ArrayLength(names)) - 1);
+ uint32_t rest = aHint & ~static_cast<uint32_t>((1ull << ArrayLength(names)) - 1);
if ((hint & NS_STYLE_HINT_REFLOW) == NS_STYLE_HINT_REFLOW) {
result.AppendLiteral("NS_STYLE_HINT_REFLOW");
hint = hint & ~NS_STYLE_HINT_REFLOW;
any = true;
} else if ((hint & nsChangeHint_AllReflowHints) == nsChangeHint_AllReflowHints) {
result.AppendLiteral("nsChangeHint_AllReflowHints");
hint = hint & ~nsChangeHint_AllReflowHints;
any = true;
} else if ((hint & NS_STYLE_HINT_VISUAL) == NS_STYLE_HINT_VISUAL) {
result.AppendLiteral("NS_STYLE_HINT_VISUAL");
hint = hint & ~NS_STYLE_HINT_VISUAL;
any = true;
}
for (uint32_t i = 0; i < ArrayLength(names); i++) {
- if (hint & (1 << i)) {
+ if (hint & (1u << i)) {
if (any) {
result.AppendLiteral(" | ");
}
result.AppendPrintf("nsChangeHint_%s", names[i]);
any = true;
}
}
if (rest) {
--- a/layout/base/nsChangeHint.h
+++ b/layout/base/nsChangeHint.h
@@ -240,32 +240,40 @@ enum nsChangeHint : uint32_t {
nsChangeHint_UpdateWidgetProperties = 1 << 29,
/**
* Indicates that there has been a colspan or rowspan attribute change
* on the cells of a table.
*/
nsChangeHint_UpdateTableCellSpans = 1 << 30,
+ /**
+ * Indicates that the visiblity property changed.
+ * This change hint is used for skip restyling for animations on
+ * visibility:hidden elements in the case where the elements have no visible
+ * descendants.
+ */
+ nsChangeHint_VisibilityChange = 1u << 31,
+
// IMPORTANT NOTE: When adding a new hint, you will need to add it to
// one of:
//
// * nsChangeHint_Hints_NeverHandledForDescendants
// * nsChangeHint_Hints_AlwaysHandledForDescendants
// * nsChangeHint_Hints_SometimesHandledForDescendants
//
// and you also may need to handle it in NS_HintsNotHandledForDescendantsIn.
//
// Please also add it to RestyleManager::ChangeHintToString and
// modify nsChangeHint_AllHints below accordingly.
/**
* Dummy hint value for all hints. It exists for compile time check.
*/
- nsChangeHint_AllHints = (1u << 31) - 1,
+ nsChangeHint_AllHints = uint32_t((1ull << 32) - 1),
};
// Redefine these operators to return nothing. This will catch any use
// of these operators on hints. We should not be using these operators
// on nsChangeHints
inline void operator<(nsChangeHint s1, nsChangeHint s2) {}
inline void operator>(nsChangeHint s1, nsChangeHint s2) {}
inline void operator!=(nsChangeHint s1, nsChangeHint s2) {}
@@ -337,17 +345,18 @@ inline nsChangeHint operator^=(nsChangeH
nsChangeHint_NeedDirtyReflow | \
nsChangeHint_NeutralChange | \
nsChangeHint_ReconstructFrame | \
nsChangeHint_RepaintFrame | \
nsChangeHint_SchedulePaint | \
nsChangeHint_SyncFrameView | \
nsChangeHint_UpdateCursor | \
nsChangeHint_UpdateSubtreeOverflow | \
- nsChangeHint_UpdateTextPath \
+ nsChangeHint_UpdateTextPath | \
+ nsChangeHint_VisibilityChange \
)
// The change hints that are never handled for descendants.
#define nsChangeHint_Hints_NeverHandledForDescendants ( \
nsChangeHint_BorderStyleNoneChange | \
nsChangeHint_ChildrenOnlyTransform | \
nsChangeHint_CSSOverflowChange | \
nsChangeHint_InvalidateRenderingObservers | \
@@ -451,17 +460,18 @@ static_assert(!(nsChangeHint_Hints_Alway
#define nsChangeHint_Hints_CanIgnoreIfNotVisible \
nsChangeHint(NS_STYLE_HINT_VISUAL | \
nsChangeHint_NeutralChange | \
nsChangeHint_UpdateOpacityLayer | \
nsChangeHint_AddOrRemoveTransform | \
nsChangeHint_UpdatePostTransformOverflow | \
nsChangeHint_UpdateTransformLayer | \
- nsChangeHint_UpdateUsesOpacity)
+ nsChangeHint_UpdateUsesOpacity | \
+ nsChangeHint_VisibilityChange)
// NB: Once we drop support for the old style system, this logic should be
// inlined in the Servo style system to eliminate the FFI call.
inline nsChangeHint NS_HintsNotHandledForDescendantsIn(nsChangeHint aChangeHint) {
nsChangeHint result =
aChangeHint & nsChangeHint_Hints_NeverHandledForDescendants;
if (!NS_IsHintSubset(nsChangeHint_NeedDirtyReflow, aChangeHint)) {
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -4106,16 +4106,20 @@ nsStyleVisibility::CalcDifference(const
// classes (e.g. table rows/cells) copy their value from an ancestor.
hint |= nsChangeHint_ReconstructFrame;
} else {
if ((mImageOrientation != aNewData.mImageOrientation)) {
hint |= nsChangeHint_AllReflowHints |
nsChangeHint_RepaintFrame;
}
if (mVisible != aNewData.mVisible) {
+ if (mVisible == NS_STYLE_VISIBILITY_VISIBLE ||
+ aNewData.mVisible == NS_STYLE_VISIBILITY_VISIBLE) {
+ hint |= nsChangeHint_VisibilityChange;
+ }
if ((NS_STYLE_VISIBILITY_COLLAPSE == mVisible) ||
(NS_STYLE_VISIBILITY_COLLAPSE == aNewData.mVisible)) {
hint |= NS_STYLE_HINT_REFLOW;
} else {
hint |= NS_STYLE_HINT_VISUAL;
}
}
if (mTextOrientation != aNewData.mTextOrientation) {