Bug 1535507 - Assume that we have an empty display list building override rect for frames that support it, even if an explicit one isn't present. r=miko

If the frame supports it (stacking context + containing block for fixed), and a descendant was
modified, we would have created an override dirty region with just the area of that descendant.
In the case where no descendants are modified, we should use an empty rect, rather than
the area inherited from our parent.

This fixes the case where we forcibly build position:fixed frames (since they might async
scroll differently to the rest of the page), but we only need to build the container item,
not the whole frame subtree within it.

Added a test that shows us building the non-intersecting position:fixed, but not items within it.

Differential Revision: https://phabricator.services.mozilla.com/D23610

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Matt Woodrow 2019-03-18 21:11:20 +00:00
Родитель 266099eaea
Коммит 43b084c81c
4 изменённых файлов: 65 добавлений и 9 удалений

Просмотреть файл

@ -2964,15 +2964,21 @@ void nsIFrame::BuildDisplayListForStackingContext(
}
bool hasOverrideDirtyRect = false;
// If we have an override dirty region, and neither us nor our ancestors are
// modified, then use it.
if (HasOverrideDirtyRegion() && !aBuilder->InInvalidSubtree() &&
!IsFrameModified()) {
nsDisplayListBuilder::DisplayListBuildingData* data =
GetProperty(nsDisplayListBuilder::DisplayListBuildingRect());
if (data) {
dirtyRect = data->mDirtyRect.Intersect(visibleRect);
hasOverrideDirtyRect = true;
// If we're doing a partial build, we're not invalid and we're capable
// of having an override building rect (stacking context and fixed pos
// containing block), then we should assume we have one.
// Either we have an explicit one, or nothing in our subtree changed and
// we have an implicit empty rect.
if (aBuilder->IsPartialUpdate() && !aBuilder->InInvalidSubtree() &&
!IsFrameModified() && IsFixedPosContainingBlock()) {
dirtyRect = nsRect();
if (HasOverrideDirtyRegion()) {
nsDisplayListBuilder::DisplayListBuildingData* data =
GetProperty(nsDisplayListBuilder::DisplayListBuildingRect());
if (data) {
dirtyRect = data->mDirtyRect.Intersect(visibleRect);
hasOverrideDirtyRect = true;
}
}
}

Просмотреть файл

@ -3,6 +3,7 @@ skip-if(!retainedDisplayList) == retained-dl-frame-deleted-1.html retained-dl-st
skip-if(!retainedDisplayList) == retained-dl-frame-created-1.html retained-dl-style-change-1-ref.html
skip-if(!retainedDisplayList) == retained-dl-style-change-stacking-context-1.html retained-dl-style-change-stacking-context-1-ref.html
skip-if(!retainedDisplayList) == retained-dl-style-change-stacking-context-2.html retained-dl-style-change-stacking-context-2-ref.html
skip-if(!retainedDisplayList) == retained-dl-style-change-stacking-context-3.html retained-dl-style-change-stacking-context-3-ref.html
skip-if(!retainedDisplayList||!asyncPan) == retained-dl-async-scrolled-1.html retained-dl-async-scrolled-1-ref.html
skip-if(!retainedDisplayList) == retained-dl-remove-for-ancestor-change-1.html retained-dl-remove-for-ancestor-change-1-ref.html
skip-if(!retainedDisplayList) == retained-dl-scroll-out-of-view-1.html retained-dl-scroll-out-of-view-1-ref.html

Просмотреть файл

@ -0,0 +1,20 @@
<html>
<head>
<style>
body {
margin: 0px;
}
div {
width:100px;
height:100px;
display: inline-block;
position:absolute;
background-color: green;
}
</style>
</head>
<body>
<div></div>
<div style="top: 110px;"></div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,29 @@
<html class="reftest-wait">
<head>
<style>
body {
margin: 0px;
}
div {
width:100px;
height:100px;
display: inline-block;
position:absolute;
}
</style>
</head>
<body>
<div style="position:fixed;" class="reftest-display-list">
<div style="background-color:green;" class="reftest-no-display-list">
</div>
<div id="second" style="background-color:red; top: 110px;"></div>
</body>
<script>
function doTest() {
document.getElementById("second").style.backgroundColor = "green";
document.documentElement.removeAttribute("class");
}
window.addEventListener("MozReftestInvalidate", doTest);
</script>
</html>