Bug 1404181 - Part 25: Force rebuilding when we detect changes to the displaylist that didn't have invalidations. Also forces rebuilding of the canvas frame every time so that AddExtraBackgroundItems produces a consistent result. r?mstange
MozReview-Commit-ID: KBganOiuRGK
--- a/layout/generic/nsSubDocumentFrame.cpp
+++ b/layout/generic/nsSubDocumentFrame.cpp
@@ -447,16 +447,41 @@ nsSubDocumentFrame::BuildDisplayList(nsD
}
if (!needsOwnLayer && aBuilder->IsBuildingLayerEventRegions() &&
nsLayoutUtils::HasDocumentLevelListenersForApzAwareEvents(presShell))
{
needsOwnLayer = true;
}
+ if (aBuilder->IsRetainingDisplayList()) {
+ // The value of needsOwnLayer can change between builds without
+ // an invalidation recorded for this frame (like if the root
+ // scrollframe becomes active). If this happens,
+ // then we need to notify the builder so that merging can
+ // happen correctly.
+ if (!mPreviouslyNeededLayer ||
+ mPreviouslyNeededLayer.value() != needsOwnLayer) {
+ dirty = visible;
+ aBuilder->MarkFrameModifiedDuringBuilding(this);
+ }
+ mPreviouslyNeededLayer = Some(needsOwnLayer);
+
+ // Caret frame changed, rebuild the entire subdoc.
+ // We could just invalidate the old and new frame
+ // areas and save some work here. RetainedDisplayListBuilder
+ // does this, so we could teach it to find and check all
+ // subdocs in advance.
+ if (mPreviousCaret != aBuilder->GetCaretFrame()) {
+ dirty = visible;
+ aBuilder->MarkFrameModifiedDuringBuilding(this);
+ }
+ mPreviousCaret = aBuilder->GetCaretFrame();
+ }
+
nsDisplayList childItems(aBuilder);
{
DisplayListClipState::AutoSaveRestore nestedClipState(aBuilder);
if (needsOwnLayer) {
// Clear current clip. There's no point in propagating it down, since
// the layer we will construct will be clipped by the current clip.
// In fact for nsDisplayZoom propagating it down would be incorrect since
--- a/layout/generic/nsSubDocumentFrame.h
+++ b/layout/generic/nsSubDocumentFrame.h
@@ -162,15 +162,17 @@ protected:
nsIFrame* ObtainIntrinsicSizeFrame();
nsView* GetViewInternal() const override { return mOuterView; }
void SetViewInternal(nsView* aView) override { mOuterView = aView; }
RefPtr<nsFrameLoader> mFrameLoader;
nsView* mOuterView;
nsView* mInnerView;
+ Maybe<bool> mPreviouslyNeededLayer;
bool mIsInline;
bool mPostedReflowCallback;
bool mDidCreateDoc;
bool mCallingShow;
+ WeakFrame mPreviousCaret;
};
#endif /* NSSUBDOCUMENTFRAME_H_ */
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -1258,16 +1258,30 @@ void
nsDisplayListBuilder::EnterPresShell(nsIFrame* aReferenceFrame,
bool aPointerEventsNoneDoc)
{
PresShellState* state = mPresShellStates.AppendElement();
state->mPresShell = aReferenceFrame->PresContext()->PresShell();
state->mCaretFrame = nullptr;
state->mFirstFrameMarkedForDisplay = mFramesMarkedForDisplay.Length();
+ nsIScrollableFrame* sf = state->mPresShell->GetRootScrollFrameAsScrollable();
+ if (sf) {
+ // We are forcing a rebuild of nsDisplayCanvasBackgroundColor to make sure
+ // that the canvas background color will be set correctly, and that only one
+ // unscrollable item will be created.
+ // This is done to avoid, for example, a case where only scrollbar frames
+ // are invalidated - we would skip creating nsDisplayCanvasBackgroundColor
+ // and possibly end up with an extra nsDisplaySolidColor item.
+ nsCanvasFrame* canvasFrame = do_QueryFrame(sf->GetScrolledFrame());
+ if (canvasFrame) {
+ MarkFrameForDisplayIfVisible(canvasFrame);
+ }
+ }
+
#ifdef DEBUG
state->mAutoLayoutPhase.emplace(aReferenceFrame->PresContext(), eLayoutPhase_DisplayListBuilding);
#endif
state->mPresShell->UpdateCanvasBackground();
bool buildCaret = mBuildCaret;
if (mIgnoreSuppression || !state->mPresShell->IsPaintingSuppressed()) {