mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 21:01:08 +00:00
Bug 1777135 - Part 2: Improve nsNativeTheme::IsDarkBackground by accounting for default bg color. r=dholbert
Since callers want just an effective color to compute whether it's dark, we simplify the API a bit too. This makes sure we find the dark background in plain text documents. Differential Revision: https://phabricator.services.mozilla.com/D151018
This commit is contained in:
parent
b8d58c68d0
commit
482d8239cb
@ -4169,29 +4169,21 @@ void nsTextPaintStyle::InitCommonColors() {
|
||||
return;
|
||||
}
|
||||
|
||||
auto bgFrame = nsCSSRendering::FindNonTransparentBackgroundFrame(mFrame);
|
||||
nscolor defaultBgColor = mPresContext->DefaultBackgroundColor();
|
||||
nscolor bgColor = bgFrame.mFrame ? bgFrame.mFrame->GetVisitedDependentColor(
|
||||
&nsStyleBackground::mBackgroundColor)
|
||||
: defaultBgColor;
|
||||
|
||||
mFrameBackgroundColor = NS_ComposeColors(defaultBgColor, bgColor);
|
||||
auto bgColor = nsCSSRendering::FindEffectiveBackgroundColor(mFrame);
|
||||
mFrameBackgroundColor = bgColor.mColor;
|
||||
|
||||
mSystemFieldForegroundColor =
|
||||
LookAndFeel::Color(LookAndFeel::ColorID::Fieldtext, mFrame);
|
||||
mSystemFieldBackgroundColor =
|
||||
LookAndFeel::Color(LookAndFeel::ColorID::Field, mFrame);
|
||||
|
||||
if (bgFrame.mIsThemed) {
|
||||
if (bgColor.mIsThemed) {
|
||||
// Assume a native widget has sufficient contrast always
|
||||
mSufficientContrast = 0;
|
||||
mInitCommonColors = true;
|
||||
return;
|
||||
}
|
||||
|
||||
NS_ASSERTION(NS_GET_A(defaultBgColor) == 255,
|
||||
"default background color is not opaque");
|
||||
|
||||
nscolor defaultWindowBackgroundColor =
|
||||
LookAndFeel::Color(LookAndFeel::ColorID::Window, mFrame);
|
||||
nscolor selectionTextColor =
|
||||
|
@ -1119,34 +1119,58 @@ void nsImageRenderer::ComputeObjectAnchorPoint(const Position& aPos,
|
||||
aImageSize.height, &aTopLeft->y, &aAnchorPoint->y);
|
||||
}
|
||||
|
||||
auto nsCSSRendering::FindNonTransparentBackgroundFrame(nsIFrame* aFrame,
|
||||
bool aStopAtThemed)
|
||||
-> NonTransparentBackgroundFrame {
|
||||
NS_ASSERTION(aFrame,
|
||||
"Cannot find NonTransparentBackgroundFrame in a null frame");
|
||||
auto nsCSSRendering::FindEffectiveBackgroundColor(nsIFrame* aFrame,
|
||||
bool aStopAtThemed,
|
||||
bool aPreferBodyToCanvas)
|
||||
-> EffectiveBackgroundColor {
|
||||
MOZ_ASSERT(aFrame);
|
||||
|
||||
auto BgColorIfNotTransparent = [](nsIFrame* aFrame) -> Maybe<nscolor> {
|
||||
nscolor c =
|
||||
aFrame->GetVisitedDependentColor(&nsStyleBackground::mBackgroundColor);
|
||||
if (NS_GET_A(c) == 255) {
|
||||
return Some(c);
|
||||
}
|
||||
if (NS_GET_A(c)) {
|
||||
// TODO(emilio): We should maybe just blend with ancestor bg colors and
|
||||
// such, but this is probably good enough for now, matches pre-existing
|
||||
// behavior.
|
||||
const nscolor defaultBg = aFrame->PresContext()->DefaultBackgroundColor();
|
||||
MOZ_ASSERT(NS_GET_A(defaultBg) == 255, "PreferenceSheet guarantees this");
|
||||
return Some(NS_ComposeColors(defaultBg, c));
|
||||
}
|
||||
return Nothing();
|
||||
};
|
||||
|
||||
for (nsIFrame* frame = aFrame; frame;
|
||||
frame = nsLayoutUtils::GetParentOrPlaceholderForCrossDoc(frame)) {
|
||||
// No need to call GetVisitedDependentColor because it always uses this
|
||||
// alpha component anyway.
|
||||
if (NS_GET_A(frame->StyleBackground()->BackgroundColor(frame))) {
|
||||
return {frame, false, false};
|
||||
if (auto bg = BgColorIfNotTransparent(frame)) {
|
||||
return {*bg};
|
||||
}
|
||||
|
||||
if (aStopAtThemed && frame->IsThemed()) {
|
||||
return {frame, true, false};
|
||||
return {NS_TRANSPARENT, true};
|
||||
}
|
||||
|
||||
if (IsCanvasFrame(frame)) {
|
||||
nsIFrame* bgFrame = FindBackgroundFrame(frame);
|
||||
if (bgFrame &&
|
||||
NS_GET_A(bgFrame->StyleBackground()->BackgroundColor(bgFrame))) {
|
||||
return {bgFrame, false, true};
|
||||
if (aPreferBodyToCanvas) {
|
||||
if (auto* body = frame->PresContext()->Document()->GetBodyElement()) {
|
||||
if (nsIFrame* f = body->GetPrimaryFrame()) {
|
||||
if (auto bg = BgColorIfNotTransparent(f)) {
|
||||
return {*bg};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nsIFrame* bgFrame = FindBackgroundFrame(frame)) {
|
||||
if (auto bg = BgColorIfNotTransparent(bgFrame)) {
|
||||
return {*bg};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
return {aFrame->PresContext()->DefaultBackgroundColor()};
|
||||
}
|
||||
|
||||
// Returns true if aFrame is a canvas frame.
|
||||
|
@ -332,18 +332,28 @@ struct nsCSSRendering {
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a frame which draws a non-transparent background, for various contrast
|
||||
* checks. Note that this only accounts for background-color and might stop at
|
||||
* themed frames (depending on the argument), so it might not be what you
|
||||
* want.
|
||||
* Find a non-transparent background color on an ancestor, for various
|
||||
* contrast checks. Note that this only accounts for background-color and
|
||||
* might stop at themed frames (depending on the argument), so it might not be
|
||||
* what you want. Note that if we stop at themed frames we might, in fact, end
|
||||
* up returning a transparent color (but then mIsThemed will be set to true).
|
||||
*
|
||||
* For semi-transparent colors, right now we blend with the default
|
||||
* background-color rather than with all ancestor backgrounds.
|
||||
*
|
||||
* If aPreferBodyToCanvas is true, we prefer the background color of the
|
||||
* <body> frame, even though we found a canvas background, 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.
|
||||
*/
|
||||
struct NonTransparentBackgroundFrame {
|
||||
nsIFrame* mFrame = nullptr;
|
||||
struct EffectiveBackgroundColor {
|
||||
nscolor mColor = 0;
|
||||
bool mIsThemed = false;
|
||||
bool mIsForCanvas = false;
|
||||
};
|
||||
static NonTransparentBackgroundFrame FindNonTransparentBackgroundFrame(
|
||||
nsIFrame* aFrame, bool aStopAtThemed = true);
|
||||
static EffectiveBackgroundColor FindEffectiveBackgroundColor(
|
||||
nsIFrame* aFrame, bool aStopAtThemed = true,
|
||||
bool aPreferBodyToCanvas = false);
|
||||
|
||||
/**
|
||||
* Determine the background color to draw taking into account print settings.
|
||||
|
8
layout/reftests/bugs/1777135-ref.html
Normal file
8
layout/reftests/bugs/1777135-ref.html
Normal file
@ -0,0 +1,8 @@
|
||||
<!doctype html>
|
||||
<style>
|
||||
:root {
|
||||
color-scheme: dark;
|
||||
}
|
||||
</style>
|
||||
Here's a tall div, to generate a scrollbar:
|
||||
<div style="height:200vh"></div>
|
9
layout/reftests/bugs/1777135.html
Normal file
9
layout/reftests/bugs/1777135.html
Normal file
@ -0,0 +1,9 @@
|
||||
<!doctype html>
|
||||
<style>
|
||||
:root {
|
||||
color-scheme: dark;
|
||||
background-color: Canvas;
|
||||
}
|
||||
</style>
|
||||
Here's a tall div, to generate a scrollbar:
|
||||
<div style="height:200vh"></div>
|
@ -2129,4 +2129,5 @@ skip-if(Android) test-pref(ui.textScaleFactor,150) test-pref(browser.display.os-
|
||||
# test-pref(ui.textScaleFactor,50) test-pref(browser.display.os-zoom-behavior,1) == 1773633.html 1773633-full-zoom.html
|
||||
# This works (but not on macOS for some reason).
|
||||
skip-if(Android) test-pref(ui.textScaleFactor,50) test-pref(browser.display.os-zoom-behavior,1) != 1773633.html 1773633.html
|
||||
pref(widget.disable-dark-scrollbar,false) == 1777135.html 1777135-ref.html
|
||||
test-pref(widget.non-native-theme.use-theme-accent,false) == 1778834.html 1778834-ref.html
|
||||
|
@ -547,14 +547,6 @@ bool nsNativeTheme::IsRangeHorizontal(nsIFrame* aFrame) {
|
||||
return aFrame->GetSize().width >= aFrame->GetSize().height;
|
||||
}
|
||||
|
||||
static nsIFrame* GetBodyFrame(nsIFrame* aCanvasFrame) {
|
||||
nsIContent* body = aCanvasFrame->PresContext()->Document()->GetBodyElement();
|
||||
if (!body) {
|
||||
return nullptr;
|
||||
}
|
||||
return body->GetPrimaryFrame();
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool nsNativeTheme::IsDarkBackground(nsIFrame* aFrame) {
|
||||
// Try to find the scrolled frame. Note that for stuff like xul <tree> there
|
||||
@ -573,29 +565,10 @@ bool nsNativeTheme::IsDarkBackground(nsIFrame* aFrame) {
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
// 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)) {
|
||||
nscolor bodyColor =
|
||||
bodyFrame->StyleBackground()->BackgroundColor(bodyFrame);
|
||||
if (NS_GET_A(bodyColor)) {
|
||||
color = bodyColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto color =
|
||||
nsCSSRendering::FindEffectiveBackgroundColor(
|
||||
aFrame, /* aStopAtThemed = */ false, /* aPreferBodyToCanvas = */ true)
|
||||
.mColor;
|
||||
return LookAndFeel::IsDarkColor(color);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user