Bug 1404181 - Part 6: Compute and store the frame that contributed the style data for backgrounds so that we can invalidate the display item when either frame changes. r?mstange
MozReview-Commit-ID: 7Q3J6AH0Ipg
--- a/layout/generic/nsCanvasFrame.cpp
+++ b/layout/generic/nsCanvasFrame.cpp
@@ -493,21 +493,24 @@ nsCanvasFrame::BuildDisplayList(nsDispla
// Force a background to be shown. We may have a background propagated to us,
// in which case StyleBackground wouldn't have the right background
// and the code in nsFrame::DisplayBorderBackgroundOutline might not give us
// a background.
// We don't have any border or outline, and our background draws over
// the overflow area, so just add nsDisplayCanvasBackground instead of
// calling DisplayBorderBackgroundOutline.
if (IsVisibleForPainting(aBuilder)) {
- nsStyleContext* bgSC;
const nsStyleBackground* bg = nullptr;
+ nsIFrame* dependentFrame = nullptr;
bool isThemed = IsThemed();
- if (!isThemed && nsCSSRendering::FindBackground(this, &bgSC)) {
- bg = bgSC->StyleBackground();
+ if (!isThemed && nsCSSRendering::FindBackgroundFrame(this, &dependentFrame)) {
+ bg = dependentFrame->StyleContext()->StyleBackground();
+ if (dependentFrame == this) {
+ dependentFrame = nullptr;
+ }
}
aLists.BorderBackground()->AppendNewToTop(
new (aBuilder) nsDisplayCanvasBackgroundColor(aBuilder, this));
if (isThemed) {
aLists.BorderBackground()->AppendNewToTop(
new (aBuilder) nsDisplayCanvasThemedBackground(aBuilder, this));
return;
@@ -560,22 +563,25 @@ nsCanvasFrame::BuildDisplayList(nsDispla
displayData->mContainingBlockActiveScrolledRoot);
thisItemASR = displayData->mContainingBlockActiveScrolledRoot;
}
nsDisplayCanvasBackgroundImage* bgItem = nullptr;
{
DisplayListClipState::AutoSaveRestore bgImageClip(aBuilder);
bgImageClip.Clear();
bgItem = new (aBuilder) nsDisplayCanvasBackgroundImage(bgData);
+ bgItem->SetDependentFrame(aBuilder, dependentFrame);
}
thisItemList.AppendNewToTop(
nsDisplayFixedPosition::CreateForFixedBackground(aBuilder, this, bgItem, i));
} else {
- thisItemList.AppendNewToTop(new (aBuilder) nsDisplayCanvasBackgroundImage(bgData));
+ nsDisplayCanvasBackgroundImage* bgItem = new (aBuilder) nsDisplayCanvasBackgroundImage(bgData);
+ bgItem->SetDependentFrame(aBuilder, dependentFrame);
+ thisItemList.AppendNewToTop(bgItem);
}
if (layers.mLayers[i].mBlendMode != NS_STYLE_BLEND_NORMAL) {
DisplayListClipState::AutoSaveRestore blendClip(aBuilder);
blendClip.ClearUpToASR(thisItemASR);
thisItemList.AppendNewToTop(
new (aBuilder) nsDisplayBlendMode(aBuilder, this, &thisItemList,
layers.mLayers[i].mBlendMode,
--- a/layout/painting/nsCSSRendering.cpp
+++ b/layout/painting/nsCSSRendering.cpp
@@ -1403,26 +1403,23 @@ nsCSSRendering::FindBackgroundStyleFrame
*/
nsStyleContext*
nsCSSRendering::FindRootFrameBackground(nsIFrame* aForFrame)
{
return FindBackgroundStyleFrame(aForFrame)->StyleContext();
}
inline bool
-FindElementBackground(nsIFrame* aForFrame, nsIFrame* aRootElementFrame,
- nsStyleContext** aBackgroundSC)
+FindElementBackground(nsIFrame* aForFrame, nsIFrame* aRootElementFrame)
{
if (aForFrame == aRootElementFrame) {
// We must have propagated our background to the viewport or canvas. Abort.
return false;
}
- *aBackgroundSC = aForFrame->StyleContext();
-
// Return true unless the frame is for a BODY element whose background
// was propagated to the viewport.
nsIContent* content = aForFrame->GetContent();
if (!content || content->NodeInfo()->NameAtom() != nsGkAtoms::body)
return true; // not frame for a "body" element
// It could be a non-HTML "body" element but that's OK, we'd fail the
// bodyContent check below
@@ -1443,29 +1440,42 @@ FindElementBackground(nsIFrame* aForFram
if (!aRootElementFrame)
return true;
const nsStyleBackground* htmlBG = aRootElementFrame->StyleBackground();
return !htmlBG->IsTransparent(aRootElementFrame);
}
bool
-nsCSSRendering::FindBackground(nsIFrame* aForFrame,
- nsStyleContext** aBackgroundSC)
+nsCSSRendering::FindBackgroundFrame(nsIFrame* aForFrame,
+ nsIFrame** aBackgroundFrame)
{
nsIFrame* rootElementFrame =
aForFrame->PresContext()->PresShell()->FrameConstructor()->GetRootElementStyleFrame();
if (IsCanvasFrame(aForFrame)) {
- *aBackgroundSC = FindCanvasBackground(aForFrame, rootElementFrame);
+ *aBackgroundFrame = FindCanvasBackgroundFrame(aForFrame, rootElementFrame);
return true;
} else {
- return FindElementBackground(aForFrame, rootElementFrame, aBackgroundSC);
+ *aBackgroundFrame = aForFrame;
+ return FindElementBackground(aForFrame, rootElementFrame);
}
}
+bool
+nsCSSRendering::FindBackground(nsIFrame* aForFrame,
+ nsStyleContext** aBackgroundSC)
+{
+ nsIFrame *backgroundFrame = nullptr;
+ if (FindBackgroundFrame(aForFrame, &backgroundFrame)) {
+ *aBackgroundSC = backgroundFrame->StyleContext();
+ return true;
+ }
+ return false;
+}
+
void
nsCSSRendering::BeginFrameTreesLocked()
{
++gFrameTreeLockCount;
}
void
nsCSSRendering::EndFrameTreesLocked()
--- a/layout/painting/nsCSSRendering.h
+++ b/layout/painting/nsCSSRendering.h
@@ -282,16 +282,18 @@ struct nsCSSRendering {
/**
* Fill in an aBackgroundSC to be used to paint the background
* for an element. This applies the rules for propagating
* backgrounds between BODY, the root element, and the canvas.
* @return true if there is some meaningful background.
*/
static bool FindBackground(nsIFrame* aForFrame,
nsStyleContext** aBackgroundSC);
+ static bool FindBackgroundFrame(nsIFrame* aForFrame,
+ nsIFrame** aBackgroundFrame);
/**
* As FindBackground, but the passed-in frame is known to be a root frame
* (returned from nsCSSFrameConstructor::GetRootElementStyleFrame())
* and there is always some meaningful background returned.
*/
static nsStyleContext* FindRootFrameBackground(nsIFrame* aForFrame);
@@ -301,27 +303,34 @@ struct nsCSSRendering {
* @param aForFrame
* the frame used to represent the canvas, in the CSS sense (i.e.
* nsCSSRendering::IsCanvasFrame(aForFrame) must be true)
* @param aRootElementFrame
* the frame representing the root element of the document
* @param aBackground
* contains background style information for the canvas on return
*/
- static nsStyleContext*
- FindCanvasBackground(nsIFrame* aForFrame, nsIFrame* aRootElementFrame)
+
+ static nsIFrame*
+ FindCanvasBackgroundFrame(nsIFrame* aForFrame, nsIFrame* aRootElementFrame)
{
MOZ_ASSERT(IsCanvasFrame(aForFrame), "not a canvas frame");
if (aRootElementFrame)
- return FindRootFrameBackground(aRootElementFrame);
+ return FindBackgroundStyleFrame(aRootElementFrame);
// This should always give transparent, so we'll fill it in with the
// default color if needed. This seems to happen a bit while a page is
// being loaded.
- return aForFrame->StyleContext();
+ return aForFrame;
+ }
+
+ static nsStyleContext*
+ FindCanvasBackground(nsIFrame* aForFrame, nsIFrame* aRootElementFrame)
+ {
+ return FindCanvasBackgroundFrame(aForFrame, aRootElementFrame)->StyleContext();
}
/**
* Find a frame which draws a non-transparent background,
* for various table-related and HR-related backwards-compatibility hacks.
* This function will also stop if it finds themed frame which might draw
* background.
*
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -3141,31 +3141,33 @@ nsDisplayBackgroundImage::GetInitData(ns
}
return InitData{
aBuilder, aFrame, aBackgroundStyle, image, aBackgroundRect,
state.mFillArea, state.mDestArea, aLayer, isRasterImage,
shouldFixToViewport
};
}
-nsDisplayBackgroundImage::nsDisplayBackgroundImage(const InitData& aInitData)
+nsDisplayBackgroundImage::nsDisplayBackgroundImage(const InitData& aInitData,
+ nsIFrame* aFrameForBounds)
: nsDisplayImageContainer(aInitData.builder, aInitData.frame)
, mBackgroundStyle(aInitData.backgroundStyle)
, mImage(aInitData.image)
+ , mDependentFrame(nullptr)
, mBackgroundRect(aInitData.backgroundRect)
, mFillRect(aInitData.fillArea)
, mDestRect(aInitData.destArea)
, mLayer(aInitData.layer)
, mIsRasterImage(aInitData.isRasterImage)
, mShouldFixToViewport(aInitData.shouldFixToViewport)
, mImageFlags(0)
{
MOZ_COUNT_CTOR(nsDisplayBackgroundImage);
- mBounds = GetBoundsInternal(aInitData.builder);
+ mBounds = GetBoundsInternal(aInitData.builder, aFrameForBounds);
if (mShouldFixToViewport) {
mAnimatedGeometryRoot = aInitData.builder->FindAnimatedGeometryRootFor(this);
// Expand the item's visible rect to cover the entire bounds, limited to the
// viewport rect. This is necessary because the background's clip can move
// asynchronously.
if (Maybe<nsRect> viewportRect = GetViewportRectRelativeToReferenceFrame(aInitData.builder, mFrame)) {
SetVisibleRect(mBounds.Intersect(*viewportRect), true);
@@ -3173,39 +3175,42 @@ nsDisplayBackgroundImage::nsDisplayBackg
}
}
nsDisplayBackgroundImage::~nsDisplayBackgroundImage()
{
#ifdef NS_BUILD_REFCNT_LOGGING
MOZ_COUNT_DTOR(nsDisplayBackgroundImage);
#endif
-}
-
-static nsStyleContext* GetBackgroundStyleContext(nsIFrame* aFrame)
-{
- nsStyleContext *sc;
- if (!nsCSSRendering::FindBackground(aFrame, &sc)) {
+ if (mDependentFrame) {
+ mDependentFrame->RemoveDisplayItem(this);
+ }
+}
+
+static nsIFrame* GetBackgroundStyleContextFrame(nsIFrame* aFrame)
+{
+ nsIFrame* f;
+ if (!nsCSSRendering::FindBackgroundFrame(aFrame, &f)) {
// We don't want to bail out if moz-appearance is set on a root
// node. If it has a parent content node, bail because it's not
// a root, other wise keep going in order to let the theme stuff
// draw the background. The canvas really should be drawing the
// bg, but there's no way to hook that up via css.
if (!aFrame->StyleDisplay()->mAppearance) {
return nullptr;
}
nsIContent* content = aFrame->GetContent();
if (!content || content->GetParent()) {
return nullptr;
}
- sc = aFrame->StyleContext();
- }
- return sc;
+ f = aFrame;
+ }
+ return f;
}
/* static */ void
SetBackgroundClipRegion(DisplayListClipState::AutoSaveRestore& aClipState,
nsIFrame* aFrame, const nsPoint& aToReferenceFrame,
const nsStyleImageLayers::Layer& aLayer,
const nsRect& aBackgroundRect,
bool aWillPaintBorder)
@@ -3273,19 +3278,26 @@ nsDisplayBackgroundImage::AppendBackgrou
const nsStyleBackground* bg = nullptr;
nsRect bgRect = aBackgroundRect + aBuilder->ToReferenceFrame(aFrame);
nsRect bgOriginRect = bgRect;
if (!aBackgroundOriginRect.IsEmpty()) {
bgOriginRect = aBackgroundOriginRect + aBuilder->ToReferenceFrame(aFrame);
}
nsPresContext* presContext = aFrame->PresContext();
bool isThemed = aFrame->IsThemed();
+ nsIFrame* dependentFrame = nullptr;
if (!isThemed) {
if (!bgSC) {
- bgSC = GetBackgroundStyleContext(aFrame);
+ dependentFrame = GetBackgroundStyleContextFrame(aFrame);
+ if (dependentFrame) {
+ bgSC = dependentFrame->StyleContext();
+ if (dependentFrame == aFrame) {
+ dependentFrame = nullptr;
+ }
+ }
}
if (bgSC) {
bg = bgSC->StyleBackground();
}
}
bool drawBackgroundColor = false;
// Dummy initialisation to keep Valgrind/Memcheck happy.
@@ -3343,26 +3355,29 @@ nsDisplayBackgroundImage::AppendBackgrou
if (clip.mHasAdditionalBGClipArea) {
bgColorRect = bgColorRect.Intersect(clip.mAdditionalBGClipArea);
}
if (clip.mHasRoundedCorners) {
clipState.emplace(aBuilder);
clipState->ClipContentDescendants(clip.mBGClipArea, clip.mRadii);
}
}
+ nsDisplayBackgroundColor *bgItem;
if (aSecondaryReferenceFrame) {
- bgItemList.AppendNewToTop(
+ bgItem =
new (aBuilder) nsDisplayTableBackgroundColor(aBuilder, aSecondaryReferenceFrame, bgColorRect, bg,
drawBackgroundColor ? color : NS_RGBA(0, 0, 0, 0),
- aFrame));
+ aFrame);
} else {
- bgItemList.AppendNewToTop(
+ bgItem =
new (aBuilder) nsDisplayBackgroundColor(aBuilder, aFrame, bgColorRect, bg,
- drawBackgroundColor ? color : NS_RGBA(0, 0, 0, 0)));
- }
+ drawBackgroundColor ? color : NS_RGBA(0, 0, 0, 0));
+ }
+ bgItem->SetDependentFrame(aBuilder, dependentFrame);
+ bgItemList.AppendNewToTop(bgItem);
}
if (isThemed) {
nsITheme* theme = presContext->GetTheme();
if (theme->NeedToClearBackgroundBehindWidget(aFrame, aFrame->StyleDisplay()->mAppearance) &&
aBuilder->IsInChromeDocumentOrPopup() && !aBuilder->IsInTransform()) {
bgItemList.AppendNewToTop(
new (aBuilder) nsDisplayClearBackground(aBuilder, aFrame));
@@ -3433,41 +3448,50 @@ nsDisplayBackgroundImage::AppendBackgrou
}
nsDisplayBackgroundImage* bgItem = nullptr;
{
// The clip is captured by the nsDisplayFixedPosition, so clear the
// clip for the nsDisplayBackgroundImage inside.
DisplayListClipState::AutoSaveRestore bgImageClip(aBuilder);
bgImageClip.Clear();
if (aSecondaryReferenceFrame) {
- bgItem = new (aBuilder) nsDisplayTableBackgroundImage(bgData, aSecondaryReferenceFrame);
+ nsDisplayBackgroundImage::InitData tableData = bgData;
+ nsIFrame* styleFrame = tableData.frame;
+ tableData.frame = aSecondaryReferenceFrame;
+ bgItem = new (aBuilder) nsDisplayTableBackgroundImage(tableData, styleFrame);
} else {
bgItem = new (aBuilder) nsDisplayBackgroundImage(bgData);
}
}
+ bgItem->SetDependentFrame(aBuilder, dependentFrame);
if (aSecondaryReferenceFrame) {
thisItemList.AppendNewToTop(
nsDisplayTableFixedPosition::CreateForFixedBackground(aBuilder,
aSecondaryReferenceFrame,
bgItem,
i,
aFrame));
} else {
thisItemList.AppendNewToTop(
nsDisplayFixedPosition::CreateForFixedBackground(aBuilder, aFrame, bgItem, i));
}
} else {
+ nsDisplayBackgroundImage* bgItem;
if (aSecondaryReferenceFrame) {
- thisItemList.AppendNewToTop(
- new (aBuilder) nsDisplayTableBackgroundImage(bgData,
- aSecondaryReferenceFrame));
+ nsDisplayBackgroundImage::InitData tableData = bgData;
+ nsIFrame* styleFrame = tableData.frame;
+ tableData.frame = aSecondaryReferenceFrame;
+
+ bgItem = new (aBuilder) nsDisplayTableBackgroundImage(tableData, styleFrame);
} else {
- thisItemList.AppendNewToTop(new (aBuilder) nsDisplayBackgroundImage(bgData));
+ bgItem = new (aBuilder) nsDisplayBackgroundImage(bgData);
}
+ bgItem->SetDependentFrame(aBuilder, dependentFrame);
+ thisItemList.AppendNewToTop(bgItem);
}
if (bg->mImage.mLayers[i].mBlendMode != NS_STYLE_BLEND_NORMAL) {
DisplayListClipState::AutoSaveRestore blendClip(aBuilder);
blendClip.ClearUpToASR(asr);
// asr is scrolled. Even if we wrap a fixed background layer, that's
// fine, because the item will have a scrolled clip that limits the
// item with respect to asr.
@@ -3949,41 +3973,46 @@ nsRect
nsDisplayBackgroundImage::GetBounds(nsDisplayListBuilder* aBuilder,
bool* aSnap) const
{
*aSnap = true;
return mBounds;
}
nsRect
-nsDisplayBackgroundImage::GetBoundsInternal(nsDisplayListBuilder* aBuilder) {
- nsPresContext* presContext = mFrame->PresContext();
+nsDisplayBackgroundImage::GetBoundsInternal(nsDisplayListBuilder* aBuilder,
+ nsIFrame* aFrameForBounds)
+{
+ // This allows nsDisplayTableBackgroundImage to change the frame used for
+ // bounds calculation.
+ nsIFrame* frame = aFrameForBounds ? aFrameForBounds : mFrame;
+
+ nsPresContext* presContext = frame->PresContext();
if (!mBackgroundStyle) {
return nsRect();
}
nsRect clipRect = mBackgroundRect;
- if (mFrame->IsCanvasFrame()) {
- nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
- clipRect = frame->CanvasArea() + ToReferenceFrame();
+ if (frame->IsCanvasFrame()) {
+ nsCanvasFrame* canvasFrame = static_cast<nsCanvasFrame*>(frame);
+ clipRect = canvasFrame->CanvasArea() + ToReferenceFrame();
}
const nsStyleImageLayers::Layer& layer = mBackgroundStyle->mImage.mLayers[mLayer];
- return nsCSSRendering::GetBackgroundLayerRect(presContext, mFrame,
+ return nsCSSRendering::GetBackgroundLayerRect(presContext, frame,
mBackgroundRect, clipRect, layer,
aBuilder->GetBackgroundPaintFlags());
}
nsDisplayTableBackgroundImage::nsDisplayTableBackgroundImage(const InitData& aData,
nsIFrame* aCellFrame)
- : nsDisplayBackgroundImage(aData)
- , mStyleFrame(aData.frame)
+ : nsDisplayBackgroundImage(aData, aCellFrame)
+ , mStyleFrame(aCellFrame)
, mTableType(GetTableTypeFromFrame(mStyleFrame))
{
- mFrame = aCellFrame;
}
bool
nsDisplayTableBackgroundImage::IsInvalid(nsRect& aRect) const
{
bool result = mStyleFrame ? mStyleFrame->IsInvalid(aRect) : false;
aRect += ToReferenceFrame();
return result;
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -2474,16 +2474,21 @@ public:
GetClipChain() == aOther->GetClipChain();
}
bool HasSameContent(const nsDisplayItem* aOther) const
{
return mFrame->GetContent() == aOther->Frame()->GetContent();
}
+ virtual nsIFrame* GetDependentFrame()
+ {
+ return nullptr;
+ }
+
protected:
nsDisplayItem() = delete;
typedef bool (*PrefFunc)(void);
bool ShouldUseAdvancedLayer(LayerManager* aManager, PrefFunc aFunc) const;
bool CanUseAdvancedLayer(LayerManager* aManager) const;
nsIFrame* mFrame;
@@ -3470,17 +3475,18 @@ public:
};
static InitData GetInitData(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame,
uint32_t aLayer,
const nsRect& aBackgroundRect,
const nsStyleBackground* aBackgroundStyle,
LayerizeFixed aLayerizeFixed);
- explicit nsDisplayBackgroundImage(const InitData& aInitData);
+ explicit nsDisplayBackgroundImage(const InitData& aInitData,
+ nsIFrame* aFrameForBounds = nullptr);
virtual ~nsDisplayBackgroundImage();
// This will create and append new items for all the layers of the
// background. Returns whether we appended a themed background.
// aAllowWillPaintBorderOptimization should usually be left at true, unless
// aFrame has special border drawing that causes opaque borders to not
// actually be opaque.
static bool AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuilder,
@@ -3560,23 +3566,48 @@ public:
const nsRect& aRect,
const nsRect& aBackgroundRect);
virtual bool ShouldFixToViewport(nsDisplayListBuilder* aBuilder) const override
{
return mShouldFixToViewport;
}
+ virtual nsIFrame* GetDependentFrame() override
+ {
+ return mDependentFrame;
+ }
+
+ void SetDependentFrame(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
+ {
+ if (!aBuilder->IsRetainingDisplayList()) {
+ return;
+ }
+ mDependentFrame = aFrame;
+ if (aFrame) {
+ mDependentFrame->AddDisplayItem(this);
+ }
+ }
+
+ virtual void RemoveFrame(nsIFrame* aFrame) override
+ {
+ if (aFrame == mDependentFrame) {
+ mDependentFrame = nullptr;
+ }
+ nsDisplayItem::RemoveFrame(aFrame);
+ }
+
protected:
typedef class mozilla::layers::ImageContainer ImageContainer;
typedef class mozilla::layers::ImageLayer ImageLayer;
bool CanBuildWebRenderDisplayItems(LayerManager* aManager);
bool TryOptimizeToImageLayer(LayerManager* aManager, nsDisplayListBuilder* aBuilder);
- nsRect GetBoundsInternal(nsDisplayListBuilder* aBuilder);
+ nsRect GetBoundsInternal(nsDisplayListBuilder* aBuilder,
+ nsIFrame* aFrameForBounds = nullptr);
void PaintInternal(nsDisplayListBuilder* aBuilder, gfxContext* aCtx,
const nsRect& aBounds, nsRect* aClipRect);
virtual nsIFrame* StyleFrame() { return mFrame; }
// Determine whether we want to be separated into our own layer, independent
// of whether this item can actually be layerized.
@@ -3587,16 +3618,17 @@ protected:
};
ImageLayerization ShouldCreateOwnLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager);
// Cache the result of nsCSSRendering::FindBackground. Always null if
// mIsThemed is true or if FindBackground returned false.
const nsStyleBackground* mBackgroundStyle;
nsCOMPtr<imgIContainer> mImage;
+ nsIFrame* mDependentFrame;
nsRect mBackgroundRect; // relative to the reference frame
nsRect mFillRect;
nsRect mDestRect;
/* Bounds of this display item */
nsRect mBounds;
uint32_t mLayer;
bool mIsRasterImage;
/* Whether the image should be treated as fixed to the viewport. */
@@ -3720,20 +3752,27 @@ class nsDisplayBackgroundColor : public
public:
nsDisplayBackgroundColor(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
const nsRect& aBackgroundRect,
const nsStyleBackground* aBackgroundStyle,
nscolor aColor)
: nsDisplayItem(aBuilder, aFrame)
, mBackgroundRect(aBackgroundRect)
, mBackgroundStyle(aBackgroundStyle)
+ , mDependentFrame(nullptr)
, mColor(Color::FromABGR(aColor))
{
mState.mColor = mColor;
}
+ virtual ~nsDisplayBackgroundColor()
+ {
+ if (mDependentFrame) {
+ mDependentFrame->RemoveDisplayItem(this);
+ }
+ }
virtual void RestoreState() override
{
nsDisplayItem::RestoreState();
mColor = mState.mColor;
}
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
@@ -3779,23 +3818,49 @@ public:
if (mColor.ToABGR() != geometry->mColor) {
bool dummy;
aInvalidRegion->Or(geometry->mBounds, GetBounds(aBuilder, &dummy));
return;
}
ComputeInvalidationRegionDifference(aBuilder, geometry, aInvalidRegion);
}
+ virtual nsIFrame* GetDependentFrame() override
+ {
+ return mDependentFrame;
+ }
+
+ void SetDependentFrame(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
+ {
+ if (!aBuilder->IsRetainingDisplayList()) {
+ return;
+ }
+ mDependentFrame = aFrame;
+ if (aFrame) {
+ mDependentFrame->AddDisplayItem(this);
+ }
+ }
+
+ virtual void RemoveFrame(nsIFrame* aFrame) override
+ {
+ if (aFrame == mDependentFrame) {
+ mDependentFrame = nullptr;
+ }
+ nsDisplayItem::RemoveFrame(aFrame);
+ }
+
NS_DISPLAY_DECL_NAME("BackgroundColor", TYPE_BACKGROUND_COLOR)
virtual void WriteDebugInfo(std::stringstream& aStream) override;
protected:
const nsRect mBackgroundRect;
const nsStyleBackground* mBackgroundStyle;
+ nsIFrame* mDependentFrame;
mozilla::gfx::Color mColor;
+
struct {
mozilla::gfx::Color mColor;
} mState;
};
class nsDisplayTableBackgroundColor : public nsDisplayBackgroundColor
{
public: