Bug 1710324 - Tweak dark background detection so that it works for XUL use cases. r=mstange

Two changes:

 * Make it work across document boundaries, so that it works on e.g., the
   bookmarks sidebar.

 * Don't bail out if there's no scrollable frame, as XUL <tree>s use raw
   <scrollbar> elements without any scrollframe (gnarly). In that case, just
   use the target frame, but make sure to skip over themed elements (like the
   scrollbars themselves) so that we can find the right background.

The logic to check the canvas frame background etcetera was simpler in
FindNonTransparentBackgroundFrame. The only caller other than the
scrollbar darkening code is nsTextFrame, which should find a non-canvas frame
before anyways, but it doesn't hurt there.

Differential Revision: https://phabricator.services.mozilla.com/D114697
This commit is contained in:
Emilio Cobos Álvarez 2021-05-10 23:33:33 +00:00
Родитель 147c187bac
Коммит d420cf322f
4 изменённых файлов: 68 добавлений и 69 удалений

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

@ -4038,10 +4038,10 @@ void nsTextPaintStyle::InitCommonColors() {
return; return;
} }
nsIFrame* bgFrame = nsCSSRendering::FindNonTransparentBackgroundFrame(mFrame); auto bgFrame = nsCSSRendering::FindNonTransparentBackgroundFrame(mFrame);
NS_ASSERTION(bgFrame, "Cannot find NonTransparentBackgroundFrame."); NS_ASSERTION(bgFrame.mFrame, "Cannot find NonTransparentBackgroundFrame.");
nscolor bgColor = nscolor bgColor = bgFrame.mFrame->GetVisitedDependentColor(
bgFrame->GetVisitedDependentColor(&nsStyleBackground::mBackgroundColor); &nsStyleBackground::mBackgroundColor);
nscolor defaultBgColor = mPresContext->DefaultBackgroundColor(); nscolor defaultBgColor = mPresContext->DefaultBackgroundColor();
mFrameBackgroundColor = NS_ComposeColors(defaultBgColor, bgColor); mFrameBackgroundColor = NS_ComposeColors(defaultBgColor, bgColor);
@ -4051,7 +4051,7 @@ void nsTextPaintStyle::InitCommonColors() {
mSystemFieldBackgroundColor = mSystemFieldBackgroundColor =
LookAndFeel::Color(LookAndFeel::ColorID::Field, mFrame); LookAndFeel::Color(LookAndFeel::ColorID::Field, mFrame);
if (bgFrame->IsThemed()) { if (bgFrame.mIsThemed) {
// Assume a native widget has sufficient contrast always // Assume a native widget has sufficient contrast always
mSufficientContrast = 0; mSufficientContrast = 0;
mInitCommonColors = true; mInitCommonColors = true;

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

@ -1123,38 +1123,34 @@ void nsImageRenderer::ComputeObjectAnchorPoint(const Position& aPos,
aImageSize.height, &aTopLeft->y, &aAnchorPoint->y); aImageSize.height, &aTopLeft->y, &aAnchorPoint->y);
} }
nsIFrame* nsCSSRendering::FindNonTransparentBackgroundFrame( auto nsCSSRendering::FindNonTransparentBackgroundFrame(nsIFrame* aFrame,
nsIFrame* aFrame, bool aStartAtParent /*= false*/) { bool aStopAtThemed)
-> NonTransparentBackgroundFrame {
NS_ASSERTION(aFrame, NS_ASSERTION(aFrame,
"Cannot find NonTransparentBackgroundFrame in a null frame"); "Cannot find NonTransparentBackgroundFrame in a null frame");
nsIFrame* frame = nullptr; for (nsIFrame* frame = aFrame; frame;
if (aStartAtParent) { frame = nsLayoutUtils::GetParentOrPlaceholderForCrossDoc(frame)) {
frame = nsLayoutUtils::GetParentOrPlaceholderFor(aFrame); // No need to call GetVisitedDependentColor because it always uses this
} // alpha component anyway.
if (!frame) { if (NS_GET_A(frame->StyleBackground()->BackgroundColor(frame))) {
frame = aFrame; return {frame, false, false};
} }
while (frame) { if (aStopAtThemed && frame->IsThemed()) {
// No need to call GetVisitedDependentColor because it always uses return {frame, true, false};
// this alpha component anyway.
if (NS_GET_A(frame->StyleBackground()->BackgroundColor(frame)) > 0) {
break;
} }
if (frame->IsThemed()) { if (IsCanvasFrame(frame)) {
break; nsIFrame* bgFrame = nullptr;
if (FindBackgroundFrame(frame, &bgFrame) &&
NS_GET_A(bgFrame->StyleBackground()->BackgroundColor(bgFrame))) {
return {bgFrame, false, true};
}
}
} }
nsIFrame* parent = nsLayoutUtils::GetParentOrPlaceholderFor(frame); return {};
if (!parent) {
break;
}
frame = parent;
}
return frame;
} }
// Returns true if aFrame is a canvas frame. // Returns true if aFrame is a canvas frame.

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

@ -331,16 +331,18 @@ struct nsCSSRendering {
} }
/** /**
* Find a frame which draws a non-transparent background, * Find a frame which draws a non-transparent background, for various contrast
* for various table-related and HR-related backwards-compatibility hacks. * checks. Note that this only accounts for background-color and might stop at
* This function will also stop if it finds themed frame which might draw * themed frames (depending on the argument), so it might not be what you
* background. * want.
*
* Be very hesitant if you're considering calling this function -- it's
* usually not what you want.
*/ */
static nsIFrame* FindNonTransparentBackgroundFrame( struct NonTransparentBackgroundFrame {
nsIFrame* aFrame, bool aStartAtParent = false); nsIFrame* mFrame = nullptr;
bool mIsThemed = false;
bool mIsForCanvas = false;
};
static NonTransparentBackgroundFrame FindNonTransparentBackgroundFrame(
nsIFrame* aFrame, bool aStopAtThemed = true);
/** /**
* Determine the background color to draw taking into account print settings. * Determine the background color to draw taking into account print settings.

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

@ -612,47 +612,48 @@ static nsIFrame* GetBodyFrame(nsIFrame* aCanvasFrame) {
return body->GetPrimaryFrame(); return body->GetPrimaryFrame();
} }
static const ComputedStyle* GetBackgroundStyle(nsIFrame* aFrame) { /* static */
if (nsCSSRendering::IsCanvasFrame(aFrame)) { bool nsNativeTheme::IsDarkBackground(nsIFrame* aFrame) {
// Try to find the scrolled frame. Note that for stuff like xul <tree> there
// might be none.
{
nsIFrame* frame = aFrame;
nsIScrollableFrame* scrollFrame = nullptr;
while (!scrollFrame && frame) {
scrollFrame = frame->GetScrollTargetFrame();
frame = frame->GetParent();
}
if (scrollFrame) {
aFrame = scrollFrame->GetScrolledFrame();
} else {
// Leave aFrame untouched.
}
}
auto backgroundFrame = nsCSSRendering::FindNonTransparentBackgroundFrame(
aFrame, /* aStopAtThemed = */ false);
if (!backgroundFrame.mFrame) {
return false;
}
nscolor color = backgroundFrame.mFrame->StyleBackground()->BackgroundColor(
backgroundFrame.mFrame);
if (backgroundFrame.mIsForCanvas) {
// For canvas frames, prefer to look at the body first, because the body // 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 // 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 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. // color which prevents that of the body frame to propagate to the viewport.
if (nsIFrame* bodyFrame = GetBodyFrame(aFrame)) { if (nsIFrame* bodyFrame = GetBodyFrame(aFrame)) {
if (!bodyFrame->StyleBackground()->IsTransparent(bodyFrame->Style())) { nscolor bodyColor =
return bodyFrame->Style(); bodyFrame->StyleBackground()->BackgroundColor(bodyFrame);
if (NS_GET_A(bodyColor)) {
color = bodyColor;
} }
} }
} }
ComputedStyle* bgSC = nullptr;
if (nsCSSRendering::FindBackground(aFrame, &bgSC) &&
!bgSC->StyleBackground()->IsTransparent(bgSC)) {
return bgSC;
}
nsIFrame* backgroundFrame = return IsDarkColor(color);
nsCSSRendering::FindNonTransparentBackgroundFrame(aFrame, true);
if (!backgroundFrame) {
return nullptr;
}
return backgroundFrame->Style();
}
/* static */
bool nsNativeTheme::IsDarkBackground(nsIFrame* aFrame) {
nsIScrollableFrame* scrollFrame = nullptr;
while (!scrollFrame && aFrame) {
scrollFrame = aFrame->GetScrollTargetFrame();
aFrame = aFrame->GetParent();
}
if (!scrollFrame) {
return false;
}
if (const auto* style = GetBackgroundStyle(scrollFrame->GetScrolledFrame())) {
return IsDarkColor(style->StyleBackground()->BackgroundColor(style));
}
return false;
} }
/*static*/ /*static*/