summaryrefslogtreecommitdiffstats
path: root/layout/base/nsDisplayList.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'layout/base/nsDisplayList.cpp')
-rw-r--r--layout/base/nsDisplayList.cpp120
1 files changed, 78 insertions, 42 deletions
diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp
index 8a34d108f..f870c6d97 100644
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -721,7 +721,6 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
: mReferenceFrame(aReferenceFrame),
mIgnoreScrollFrame(nullptr),
mLayerEventRegions(nullptr),
- mCurrentTableItem(nullptr),
mCurrentFrame(aReferenceFrame),
mCurrentReferenceFrame(aReferenceFrame),
mCurrentAGR(&mRootAGR),
@@ -731,6 +730,7 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
mGlassDisplayItem(nullptr),
mScrollInfoItemsForHoisting(nullptr),
mMode(aMode),
+ mTableBackgroundSet(nullptr),
mCurrentScrollParentId(FrameMetrics::NULL_SCROLL_ID),
mCurrentScrollbarTarget(FrameMetrics::NULL_SCROLL_ID),
mCurrentScrollbarFlags(0),
@@ -783,7 +783,10 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
"Check nsDisplayItem::TYPE_MAX should not overflow");
}
-static void MarkFrameForDisplay(nsIFrame* aFrame, nsIFrame* aStopAtFrame) {
+void
+nsDisplayListBuilder::MarkFrameForDisplay(nsIFrame* aFrame, nsIFrame* aStopAtFrame)
+{
+ mFramesMarkedForDisplay.AppendElement(aFrame);
for (nsIFrame* f = aFrame; f;
f = nsLayoutUtils::GetParentOrPlaceholderFor(f)) {
if (f->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO)
@@ -796,6 +799,22 @@ static void MarkFrameForDisplay(nsIFrame* aFrame, nsIFrame* aStopAtFrame) {
}
}
+void
+nsDisplayListBuilder::MarkFrameForDisplayIfVisible(nsIFrame* aFrame, nsIFrame* aStopAtFrame)
+{
+ mFramesMarkedForDisplay.AppendElement(aFrame);
+ for (nsIFrame* f = aFrame; f;
+ f = nsLayoutUtils::GetParentOrPlaceholderFor(f)) {
+ if (f->ForceDescendIntoIfVisible())
+ return;
+ f->SetForceDescendIntoIfVisible(true);
+ if (f == aStopAtFrame) {
+ // we've reached a frame that we know will be painted, so we can stop.
+ break;
+ }
+ }
+}
+
bool nsDisplayListBuilder::NeedToForceTransparentSurfaceForItem(nsDisplayItem* aItem)
{
return aItem == mGlassDisplayItem || aItem->ClearsBackground();
@@ -864,10 +883,10 @@ nsDisplayListBuilder::FindAnimatedGeometryRootFor(nsDisplayItem* aItem)
void nsDisplayListBuilder::MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame,
- nsIFrame* aFrame,
- const nsRect& aDirtyRect)
+ nsIFrame* aFrame)
{
- nsRect dirtyRectRelativeToDirtyFrame = aDirtyRect;
+ nsRect visible = GetVisibleRect();
+ nsRect dirtyRectRelativeToDirtyFrame = GetDirtyRect();
if (nsLayoutUtils::IsFixedPosFrameInDisplayPort(aFrame) &&
IsPaintingToWindow()) {
NS_ASSERTION(aDirtyFrame == aFrame->GetParent(), "Dirty frame should be viewport frame");
@@ -881,8 +900,14 @@ void nsDisplayListBuilder::MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame,
} else {
dirtyRectRelativeToDirtyFrame.SizeTo(aDirtyFrame->GetSize());
}
+ // TODO: We probably don't want visible and dirty to be the same here, figure
+ // out what to do.
+ visible = dirtyRectRelativeToDirtyFrame;
}
- nsRect dirty = dirtyRectRelativeToDirtyFrame - aFrame->GetOffsetTo(aDirtyFrame);
+
+ nsPoint offset = aFrame->GetOffsetTo(aDirtyFrame);
+ visible -= offset;
+ nsRect dirty = dirtyRectRelativeToDirtyFrame - offset;
nsRect overflowRect = aFrame->GetVisualOverflowRect();
if (aFrame->IsTransformed() &&
@@ -895,15 +920,18 @@ void nsDisplayListBuilder::MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame,
*/
overflowRect.Inflate(nsPresContext::CSSPixelsToAppUnits(32));
}
-
- if (!dirty.IntersectRect(dirty, overflowRect) &&
- !(aFrame->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO)) {
+ visible.IntersectRect(visible, overflowRect);
+ dirty.IntersectRect(dirty, overflowRect);
+ if (!(aFrame->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO) &&
+ dirty.IsEmpty() &&
+ (!aFrame->ForceDescendIntoIfVisible() ||
+ visible.IsEmpty())) {
return;
}
const DisplayItemClip* oldClip = mClipState.GetClipForContainingBlockDescendants();
const DisplayItemScrollClip* sc = mClipState.GetCurrentInnermostScrollClip();
- OutOfFlowDisplayData* data = new OutOfFlowDisplayData(oldClip, sc, dirty);
+ OutOfFlowDisplayData* data = new OutOfFlowDisplayData(oldClip, sc, visible, dirty);
aFrame->SetProperty(nsDisplayListBuilder::OutOfFlowDisplayDataProperty(), data);
MarkFrameForDisplay(aFrame, aDirtyFrame);
@@ -914,9 +942,11 @@ static void UnmarkFrameForDisplay(nsIFrame* aFrame) {
for (nsIFrame* f = aFrame; f;
f = nsLayoutUtils::GetParentOrPlaceholderFor(f)) {
- if (!(f->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO))
+ if (!(f->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO) &&
+ !f->ForceDescendIntoIfVisible())
return;
f->RemoveStateBits(NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO);
+ f->SetForceDescendIntoIfVisible(false);
}
}
@@ -925,7 +955,6 @@ nsDisplayListBuilder::~nsDisplayListBuilder() {
"All frames should have been unmarked");
NS_ASSERTION(mPresShellStates.Length() == 0,
"All presshells should have been exited");
- NS_ASSERTION(!mCurrentTableItem, "No table item should be active");
nsCSSRendering::EndFrameTreesLocked();
@@ -1008,22 +1037,27 @@ nsDisplayListBuilder::EnterPresShell(nsIFrame* aReferenceFrame,
}
state->mInsidePointerEventsNoneDoc = pointerEventsNone;
+ state->mPresShellIgnoreScrollFrame =
+ state->mPresShell->IgnoringViewportScrolling()
+ ? state->mPresShell->GetRootScrollFrame()
+ : nullptr;
+
+ nsPresContext* pc = aReferenceFrame->PresContext();
+ nsCOMPtr<nsIDocShell> docShell = pc->GetDocShell();
+ if (docShell) {
+ docShell->GetWindowDraggingAllowed(&mWindowDraggingAllowed);
+ }
+
+ mIsInChromePresContext = pc->IsChrome();
+
if (!buildCaret)
return;
RefPtr<nsCaret> caret = state->mPresShell->GetCaret();
state->mCaretFrame = caret->GetPaintGeometry(&state->mCaretRect);
if (state->mCaretFrame) {
- mFramesMarkedForDisplay.AppendElement(state->mCaretFrame);
MarkFrameForDisplay(state->mCaretFrame, nullptr);
}
-
- nsPresContext* pc = aReferenceFrame->PresContext();
- nsCOMPtr<nsIDocShell> docShell = pc->GetDocShell();
- if (docShell) {
- docShell->GetWindowDraggingAllowed(&mWindowDraggingAllowed);
- }
- mIsInChromePresContext = pc->IsChrome();
}
// A non-blank paint is a paint that does not just contain the canvas background.
@@ -1094,8 +1128,7 @@ nsDisplayListBuilder::ResetMarkedFramesForDisplayList()
void
nsDisplayListBuilder::MarkFramesForDisplayList(nsIFrame* aDirtyFrame,
- const nsFrameList& aFrames,
- const nsRect& aDirtyRect) {
+ const nsFrameList& aFrames) {
for (nsIFrame* e : aFrames) {
// Skip the AccessibleCaret frame when building no caret.
if (!IsBuildingCaret()) {
@@ -1108,8 +1141,7 @@ nsDisplayListBuilder::MarkFramesForDisplayList(nsIFrame* aDirtyFrame,
}
}
- mFramesMarkedForDisplay.AppendElement(e);
- MarkOutOfFlowFrameForDisplay(aDirtyFrame, e, aDirtyRect);
+ MarkOutOfFlowFrameForDisplay(aDirtyFrame, e);
}
}
@@ -1132,7 +1164,6 @@ nsDisplayListBuilder::MarkPreserve3DFramesForDisplayList(nsIFrame* aDirtyFrame)
for (; !childFrames.AtEnd(); childFrames.Next()) {
nsIFrame *child = childFrames.get();
if (child->Combines3DTransformWithAncestors()) {
- mFramesMarkedForDisplay.AppendElement(child);
MarkFrameForDisplay(child, aDirtyFrame);
}
}
@@ -2318,11 +2349,11 @@ nsDisplayItem::nsDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
mAnimatedGeometryRoot = aBuilder->FindAnimatedGeometryRootFor(aFrame);
MOZ_ASSERT(nsLayoutUtils::IsAncestorFrameCrossDoc(aBuilder->RootReferenceFrame(),
*mAnimatedGeometryRoot), "Bad");
- NS_ASSERTION(aBuilder->GetDirtyRect().width >= 0 ||
- !aBuilder->IsForPainting(), "dirty rect not set");
- // The dirty rect is for mCurrentFrame, so we have to use
+ NS_ASSERTION(aBuilder->GetVisibleRect().width >= 0 ||
+ !aBuilder->IsForPainting(), "visible rect not set");
+ // The visible rect is for mCurrentFrame, so we have to use
// mCurrentOffsetToReferenceFrame
- mVisibleRect = aBuilder->GetDirtyRect() +
+ mVisibleRect = aBuilder->GetVisibleRect() +
aBuilder->GetCurrentFrameOffsetToReferenceFrame();
}
@@ -2573,8 +2604,7 @@ static nsStyleContext* GetBackgroundStyleContext(nsIFrame* aFrame)
/* static */ void
SetBackgroundClipRegion(DisplayListClipState::AutoSaveRestore& aClipState,
- nsIFrame* aFrame, const nsPoint& aToReferenceFrame,
- const nsStyleImageLayers::Layer& aLayer,
+ nsIFrame* aFrame, const nsStyleImageLayers::Layer& aLayer,
const nsRect& aBackgroundRect,
bool aWillPaintBorder)
{
@@ -2626,7 +2656,6 @@ SpecialCutoutRegionCase(nsDisplayListBuilder* aBuilder,
return true;
}
-
/*static*/ bool
nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame,
@@ -2635,14 +2664,16 @@ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuil
bool aAllowWillPaintBorderOptimization,
nsStyleContext* aStyleContext,
const nsRect& aBackgroundOriginRect,
- nsIFrame* aSecondaryReferenceFrame)
+ nsIFrame* aSecondaryReferenceFrame,
+ Maybe<nsDisplayListBuilder::AutoBuildingDisplayList>*
+ aAutoBuildingDisplayList)
{
nsStyleContext* bgSC = aStyleContext;
const nsStyleBackground* bg = nullptr;
- nsRect bgRect = aBackgroundRect + aBuilder->ToReferenceFrame(aFrame);
+ nsRect bgRect = aBackgroundRect;
nsRect bgOriginRect = bgRect;
if (!aBackgroundOriginRect.IsEmpty()) {
- bgOriginRect = aBackgroundOriginRect + aBuilder->ToReferenceFrame(aFrame);
+ bgOriginRect = aBackgroundOriginRect;
}
nsPresContext* presContext = aFrame->PresContext();
bool isThemed = aFrame->IsThemed();
@@ -2678,8 +2709,6 @@ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuil
!isThemed && !hasInsetShadow &&
borderStyle->HasBorder();
- nsPoint toRef = aBuilder->ToReferenceFrame(aFrame);
-
// An auxiliary list is necessary in case we have background blending; if that
// is the case, background items need to be wrapped by a blend container to
// isolate blending to the background
@@ -2688,6 +2717,9 @@ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuil
// to create an item for hit testing.
if ((drawBackgroundColor && color != NS_RGBA(0,0,0,0)) ||
aBuilder->IsForEventDelivery()) {
+ if (aAutoBuildingDisplayList && !*aAutoBuildingDisplayList) {
+ aAutoBuildingDisplayList->emplace(aBuilder, aFrame);
+ }
DisplayListClipState::AutoSaveRestore clipState(aBuilder);
if (bg && !aBuilder->IsForEventDelivery()) {
// Disable the will-paint-border optimization for background
@@ -2699,7 +2731,7 @@ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuil
// artifacts along the rounded corners.
bool useWillPaintBorderOptimization = willPaintBorder &&
nsLayoutUtils::HasNonZeroCorner(borderStyle->mBorderRadius);
- SetBackgroundClipRegion(clipState, aFrame, toRef,
+ SetBackgroundClipRegion(clipState, aFrame,
bg->BottomLayer(), bgRect,
useWillPaintBorderOptimization);
}
@@ -2752,6 +2784,10 @@ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuil
continue;
}
+ if (aAutoBuildingDisplayList && !*aAutoBuildingDisplayList) {
+ aAutoBuildingDisplayList->emplace(aBuilder, aFrame);
+ }
+
if (bg->mImage.mLayers[i].mBlendMode != NS_STYLE_BLEND_NORMAL) {
needBlendContainer = true;
}
@@ -2759,8 +2795,8 @@ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuil
DisplayListClipState::AutoSaveRestore clipState(aBuilder);
if (!aBuilder->IsForEventDelivery()) {
const nsStyleImageLayers::Layer& layer = bg->mImage.mLayers[i];
- SetBackgroundClipRegion(clipState, aFrame, toRef,
- layer, bgRect, willPaintBorder);
+ SetBackgroundClipRegion(clipState, aFrame, layer, bgRect,
+ willPaintBorder);
}
nsDisplayList thisItemList;
@@ -4342,7 +4378,7 @@ nsDisplayWrapList::nsDisplayWrapList(nsDisplayListBuilder* aBuilder,
mReferenceFrame = i->ReferenceFrame();
mToReferenceFrame = i->ToReferenceFrame();
}
- mVisibleRect = aBuilder->GetDirtyRect() +
+ mVisibleRect = aBuilder->GetVisibleRect() +
aBuilder->GetCurrentFrameOffsetToReferenceFrame();
}
@@ -4368,7 +4404,7 @@ nsDisplayWrapList::nsDisplayWrapList(nsDisplayListBuilder* aBuilder,
mReferenceFrame = aItem->ReferenceFrame();
mToReferenceFrame = aItem->ToReferenceFrame();
}
- mVisibleRect = aBuilder->GetDirtyRect() +
+ mVisibleRect = aBuilder->GetVisibleRect() +
aBuilder->GetCurrentFrameOffsetToReferenceFrame();
}