Bug 1687183 - Fix dark background detection in nsNativeTheme when only root has a background. r=mstange

If we hit the canvas frame, and the root has a background but the body
doesn't, previously we were using the body style. Then
FindNonTransparentBackgroundFrame would return the document element
frame (with the right background), but FindBackgroundFor that failed.

Differential Revision: https://phabricator.services.mozilla.com/D103975
This commit is contained in:
Emilio Cobos Álvarez 2021-02-04 16:54:48 +00:00
parent 6124970be9
commit 6937065186
3 changed files with 34 additions and 28 deletions

View File

@ -2065,7 +2065,7 @@ nscolor nsStyleBackground::BackgroundColor(const nsIFrame* aFrame) const {
return mBackgroundColor.CalcColor(aFrame);
}
nscolor nsStyleBackground::BackgroundColor(ComputedStyle* aStyle) const {
nscolor nsStyleBackground::BackgroundColor(const ComputedStyle* aStyle) const {
return mBackgroundColor.CalcColor(*aStyle);
}

View File

@ -342,7 +342,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleBackground {
// Return the background color as nscolor.
nscolor BackgroundColor(const nsIFrame* aFrame) const;
nscolor BackgroundColor(mozilla::ComputedStyle* aStyle) const;
nscolor BackgroundColor(const mozilla::ComputedStyle* aStyle) const;
// True if this background is completely transparent.
bool IsTransparent(const nsIFrame* aFrame) const;

View File

@ -607,17 +607,39 @@ bool nsNativeTheme::IsRangeHorizontal(nsIFrame* aFrame) {
}
static nsIFrame* GetBodyFrame(nsIFrame* aCanvasFrame) {
nsIContent* content = aCanvasFrame->GetContent();
if (!content) {
return nullptr;
}
nsIContent* body = content->OwnerDoc()->GetBodyElement();
nsIContent* body = aCanvasFrame->PresContext()->Document()->GetBodyElement();
if (!body) {
return nullptr;
}
return body->GetPrimaryFrame();
}
static const ComputedStyle* GetBackgroundStyle(nsIFrame* aFrame) {
if (nsCSSRendering::IsCanvasFrame(aFrame)) {
// For canvas frames, prefer to look at the body first, because the body
// background color is most likely what will be visible as the background
// color of the page, even if the html element has a different background
// color which prevents that of the body frame to propagate to the viewport.
if (nsIFrame* bodyFrame = GetBodyFrame(aFrame)) {
if (!bodyFrame->StyleBackground()->IsTransparent(bodyFrame->Style())) {
return bodyFrame->Style();
}
}
}
ComputedStyle* bgSC = nullptr;
if (nsCSSRendering::FindBackground(aFrame, &bgSC) &&
!bgSC->StyleBackground()->IsTransparent(bgSC)) {
return bgSC;
}
nsIFrame* backgroundFrame =
nsCSSRendering::FindNonTransparentBackgroundFrame(aFrame, true);
if (!backgroundFrame) {
return nullptr;
}
return backgroundFrame->Style();
}
/* static */
bool nsNativeTheme::IsDarkBackground(nsIFrame* aFrame) {
nsIScrollableFrame* scrollFrame = nullptr;
@ -625,28 +647,12 @@ bool nsNativeTheme::IsDarkBackground(nsIFrame* aFrame) {
scrollFrame = aFrame->GetScrollTargetFrame();
aFrame = aFrame->GetParent();
}
if (!scrollFrame) return false;
if (!scrollFrame) {
return false;
}
nsIFrame* frame = scrollFrame->GetScrolledFrame();
if (nsCSSRendering::IsCanvasFrame(frame)) {
// For canvas frames, prefer to look at the body first, because the body
// background color is most likely what will be visible as the background
// color of the page, even if the html element has a different background
// color which prevents that of the body frame to propagate to the viewport.
nsIFrame* bodyFrame = GetBodyFrame(frame);
if (bodyFrame) {
frame = bodyFrame;
}
}
ComputedStyle* bgSC = nullptr;
if (!nsCSSRendering::FindBackground(frame, &bgSC) ||
bgSC->StyleBackground()->IsTransparent(bgSC)) {
nsIFrame* backgroundFrame =
nsCSSRendering::FindNonTransparentBackgroundFrame(frame, true);
nsCSSRendering::FindBackground(backgroundFrame, &bgSC);
}
if (bgSC) {
nscolor bgColor = bgSC->StyleBackground()->BackgroundColor(bgSC);
if (const auto* style = GetBackgroundStyle(scrollFrame->GetScrolledFrame())) {
nscolor bgColor = style->StyleBackground()->BackgroundColor(style);
// Consider the background color dark if the sum of the r, g and b values is
// less than 384 in a semi-transparent document. This heuristic matches
// what WebKit does, and we can improve it later if needed.