mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-27 12:50:09 +00:00
Bug 691651. When an element changes between having a transform and not having one, don't reframe if we don't need to. r=dbaron
--HG-- extra : rebase_source : ed990c17d2501ea5f4d09dea56baeada41cd3f35
This commit is contained in:
parent
65cf9f8b41
commit
d2d218e577
@ -7976,6 +7976,31 @@ nsCSSFrameConstructor::CharacterDataChanged(nsIContent* aContent,
|
||||
|
||||
NS_DECLARE_FRAME_PROPERTY(ChangeListProperty, nullptr)
|
||||
|
||||
/**
|
||||
* Return true if aFrame's subtree has placeholders for abs-pos or fixed-pos
|
||||
* content.
|
||||
*/
|
||||
static bool
|
||||
FrameHasAbsPosPlaceholderDescendants(nsIFrame* aFrame)
|
||||
{
|
||||
const nsIFrame::ChildListIDs skip(nsIFrame::kAbsoluteList |
|
||||
nsIFrame::kFixedList);
|
||||
for (nsIFrame::ChildListIterator lists(aFrame); !lists.IsDone(); lists.Next()) {
|
||||
if (!skip.Contains(lists.CurrentID())) {
|
||||
for (nsFrameList::Enumerator childFrames(lists.CurrentList());
|
||||
!childFrames.AtEnd(); childFrames.Next()) {
|
||||
nsIFrame* f = childFrames.get();
|
||||
if ((f->GetType() == nsGkAtoms::placeholderFrame &&
|
||||
nsPlaceholderFrame::GetRealFrameForPlaceholder(f)->IsAbsolutelyPositioned()) ||
|
||||
FrameHasAbsPosPlaceholderDescendants(f)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsCSSFrameConstructor::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
|
||||
{
|
||||
@ -8036,6 +8061,20 @@ nsCSSFrameConstructor::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((hint & nsChangeHint_AddOrRemoveTransform) && frame &&
|
||||
!(hint & nsChangeHint_ReconstructFrame)) {
|
||||
if (FrameHasAbsPosPlaceholderDescendants(frame)) {
|
||||
NS_UpdateHint(hint, nsChangeHint_ReconstructFrame);
|
||||
} else {
|
||||
// We can just add this state bit unconditionally, since it's
|
||||
// conservative. Normally frame construction would set this if needed,
|
||||
// but we're not going to reconstruct the frame so we need to set it.
|
||||
// It's because we need to set this bit on each affected frame
|
||||
// that we can't coalesce nsChangeHint_AddOrRemoveTransform hints up
|
||||
// to ancestors (i.e. it can't be an inherited change hint).
|
||||
frame->AddStateBits(NS_FRAME_MAY_BE_TRANSFORMED);
|
||||
}
|
||||
}
|
||||
if (hint & nsChangeHint_ReconstructFrame) {
|
||||
// If we ever start passing true here, be careful of restyles
|
||||
// that involve a reframe and animations. In particular, if the
|
||||
|
@ -101,6 +101,14 @@ enum nsChangeHint {
|
||||
*/
|
||||
nsChangeHint_RecomputePosition = 0x2000,
|
||||
|
||||
/**
|
||||
* Behaves like ReconstructFrame, but only if the frame has descendants
|
||||
* that are absolutely or fixed position. Use this hint when a style change
|
||||
* has changed whether the frame is a container for fixed-pos or abs-pos
|
||||
* elements, but reframing is otherwise not needed.
|
||||
*/
|
||||
nsChangeHint_AddOrRemoveTransform = 0x4000,
|
||||
|
||||
/**
|
||||
* We have an optimization when processing change hints which prevents
|
||||
* us from visiting the descendants of a node when a hint on that node
|
||||
@ -116,7 +124,8 @@ enum nsChangeHint {
|
||||
nsChangeHint_UpdateOpacityLayer |
|
||||
nsChangeHint_UpdateOverflow |
|
||||
nsChangeHint_ChildrenOnlyTransform |
|
||||
nsChangeHint_RecomputePosition
|
||||
nsChangeHint_RecomputePosition |
|
||||
nsChangeHint_AddOrRemoveTransform
|
||||
};
|
||||
|
||||
// Redefine these operators to return nothing. This will catch any use
|
||||
|
8
layout/reftests/transform/dynamic-addremove-1-ref.html
Normal file
8
layout/reftests/transform/dynamic-addremove-1-ref.html
Normal file
@ -0,0 +1,8 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<body>
|
||||
<div style="position:absolute; left:80px; top:20px; width:100px; height:100px; background:yellow">
|
||||
<div style="position:absolute; left:50px; top:50px; width:100px; height:100px; background:orange"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
15
layout/reftests/transform/dynamic-addremove-1a.html
Normal file
15
layout/reftests/transform/dynamic-addremove-1a.html
Normal file
@ -0,0 +1,15 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html class="reftest-wait">
|
||||
<body style="margin:0;">
|
||||
<div id="t" style="width:100px; height:100px; background:yellow;">
|
||||
<div style="position:absolute; left:50px; top:50px; width:100px; height:100px; background:orange;"></div>
|
||||
</div>
|
||||
<script>
|
||||
function doTest() {
|
||||
document.getElementById("t").style.transform = "translate(80px,20px)";
|
||||
document.documentElement.removeAttribute("class");
|
||||
}
|
||||
window.addEventListener("MozReftestInvalidate", doTest, false);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
15
layout/reftests/transform/dynamic-addremove-1b.html
Normal file
15
layout/reftests/transform/dynamic-addremove-1b.html
Normal file
@ -0,0 +1,15 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html class="reftest-wait">
|
||||
<body style="margin:0;">
|
||||
<div id="t" style="width:100px; height:100px; background:yellow;">
|
||||
<div style="position:fixed; left:50px; top:50px; width:100px; height:100px; background:orange;"></div>
|
||||
</div>
|
||||
<script>
|
||||
function doTest() {
|
||||
document.getElementById("t").style.transform = "translate(80px,20px)";
|
||||
document.documentElement.removeAttribute("class");
|
||||
}
|
||||
window.addEventListener("MozReftestInvalidate", doTest, false);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
17
layout/reftests/transform/dynamic-addremove-1c.html
Normal file
17
layout/reftests/transform/dynamic-addremove-1c.html
Normal file
@ -0,0 +1,17 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html class="reftest-wait">
|
||||
<body style="margin:0;">
|
||||
<div id="t" style="width:100px; height:100px; background:yellow;">
|
||||
<div style="float:left;">
|
||||
<div style="position:fixed; left:50px; top:50px; width:100px; height:100px; background:orange;"></div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
function doTest() {
|
||||
document.getElementById("t").style.transform = "translate(80px,20px)";
|
||||
document.documentElement.removeAttribute("class");
|
||||
}
|
||||
window.addEventListener("MozReftestInvalidate", doTest, false);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -6,6 +6,9 @@
|
||||
== compound-1a.html compound-1-ref.html
|
||||
!= compound-1a.html compound-1-fail.html
|
||||
== dynamic-inherit-1.html dynamic-inherit-1-ref.html
|
||||
== dynamic-addremove-1a.html dynamic-addremove-1-ref.html
|
||||
== dynamic-addremove-1b.html dynamic-addremove-1-ref.html
|
||||
== dynamic-addremove-1c.html dynamic-addremove-1-ref.html
|
||||
# translatex should act like position: relative
|
||||
== translatex-1a.html translatex-1-ref.html
|
||||
== translatex-1b.html translatex-1-ref.html
|
||||
|
@ -415,7 +415,7 @@ nsStyleContext::CalcStyleDifference(nsStyleContext* aOther)
|
||||
// Visibility, Outline, TableBorder, Table, Text, UIReset, Quotes
|
||||
nsChangeHint maxHint = nsChangeHint(NS_STYLE_HINT_FRAMECHANGE |
|
||||
nsChangeHint_UpdateTransformLayer | nsChangeHint_UpdateOpacityLayer |
|
||||
nsChangeHint_UpdateOverflow);
|
||||
nsChangeHint_UpdateOverflow | nsChangeHint_AddOrRemoveTransform);
|
||||
DO_STRUCT_DIFFERENCE(Display);
|
||||
|
||||
maxHint = nsChangeHint(NS_STYLE_HINT_FRAMECHANGE |
|
||||
|
@ -2276,7 +2276,12 @@ nsChangeHint nsStyleDisplay::CalcDifference(const nsStyleDisplay& aOther) const
|
||||
* or remove the view object, and also to handle abs-pos and fixed-pos containers.
|
||||
*/
|
||||
if (HasTransform() != aOther.HasTransform()) {
|
||||
NS_UpdateHint(hint, nsChangeHint_ReconstructFrame);
|
||||
// We do not need to apply nsChangeHint_UpdateTransformLayer since
|
||||
// nsChangeHint_RepaintFrame will forcibly invalidate the frame area and
|
||||
// ensure layers are rebuilt (or removed).
|
||||
NS_UpdateHint(hint, NS_CombineHint(nsChangeHint_AddOrRemoveTransform,
|
||||
NS_CombineHint(nsChangeHint_UpdateOverflow,
|
||||
nsChangeHint_RepaintFrame)));
|
||||
}
|
||||
else if (HasTransform()) {
|
||||
/* Otherwise, if we've kept the property lying around and we already had a
|
||||
@ -2339,7 +2344,8 @@ nsChangeHint nsStyleDisplay::MaxDifference()
|
||||
return nsChangeHint(NS_STYLE_HINT_FRAMECHANGE |
|
||||
nsChangeHint_UpdateOpacityLayer |
|
||||
nsChangeHint_UpdateTransformLayer |
|
||||
nsChangeHint_UpdateOverflow);
|
||||
nsChangeHint_UpdateOverflow |
|
||||
nsChangeHint_AddOrRemoveTransform);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user