Bug 1701691 - -moz-toolbar-prefers-color-scheme for dark theme detection r=desktop-theme-reviewers,emilio,harry

This adds a new @media query -moz-toolbar-prefers-color-scheme which works like
prefers-color-scheme but is set based on the browser theme rather than the OS
theme. The background colour of the toolbar is used to determine the theme
dark/light preference. This will be used for in-content common.css pages and
other UI elements that include that stylesheet in the browser-chrome through
shadow DOM.

The end result is that about: pages, infobars, and modals will now "match" the
browser theme (just light/dark mode, not LWT theming support).

Differential Revision: https://phabricator.services.mozilla.com/D111486
This commit is contained in:
Mark Striemer 2021-04-18 22:22:49 +00:00
Родитель 93a6a5e91f
Коммит 209f987106
9 изменённых файлов: 139 добавлений и 1 удалений

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

@ -311,3 +311,5 @@ tags = fullscreen
[browser_ext_contentscript_animate.js]
[browser_ext_contentscript_cross_docGroup_adoption.js]
[browser_ext_contentscript_cross_docGroup_adoption_xhr.js]
[browser_toolbar_prefers_color_scheme.js]
skip-if = os == 'mac'

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

@ -0,0 +1,79 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
add_task(async function testThemeDeterminesToolbarQuery() {
let darkModeQuery = window.matchMedia("(prefers-color-scheme: dark)");
let darkToolbarQuery = window.matchMedia(
"(-moz-toolbar-prefers-color-scheme: dark)"
);
let darkExtension = ExtensionTestUtils.loadExtension({
manifest: {
applications: {
gecko: {
id: "dark@mochi.test",
},
},
theme: {
colors: {
toolbar: "rgba(12, 12, 12, 1)",
},
},
},
});
let lightExtension = ExtensionTestUtils.loadExtension({
manifest: {
applications: {
gecko: {
id: "light@mochi.test",
},
},
theme: {
colors: {
toolbar: "rgba(255, 255, 255, 1)",
},
},
},
});
let initialDarkModeMatches = darkModeQuery.matches;
ok(
initialDarkModeMatches == darkToolbarQuery.matches,
"OS dark mode matches toolbar initially"
);
let testExtensions = darkToolbarQuery.matches
? [lightExtension, darkExtension]
: [darkExtension, lightExtension];
await Promise.all([
BrowserTestUtils.waitForEvent(darkToolbarQuery, "change"),
TestUtils.topicObserved("lightweight-theme-styling-update"),
testExtensions[0].startup(),
]);
is(darkModeQuery.matches, initialDarkModeMatches, "OS dark mode unchanged");
is(
darkToolbarQuery.matches,
!initialDarkModeMatches,
"toolbar query changed"
);
await Promise.all([
BrowserTestUtils.waitForEvent(darkToolbarQuery, "change"),
TestUtils.topicObserved("lightweight-theme-styling-update"),
testExtensions[1].startup(),
]);
is(darkModeQuery.matches, initialDarkModeMatches, "OS dark mode unchanged");
is(
darkToolbarQuery.matches,
initialDarkModeMatches,
"toolbar query matches OS"
);
await lightExtension.unload();
await darkExtension.unload();
});

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

@ -4,6 +4,8 @@
var EXPORTED_SYMBOLS = ["ThemeVariableMap", "ThemeContentPropertyList"];
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
const ThemeVariableMap = [
[
"--lwt-accent-color-inactive",
@ -55,6 +57,22 @@ const ThemeVariableMap = [
"--toolbar-bgcolor",
{
lwtProperty: "toolbarColor",
processColor(rgbaChannels, element) {
if (!rgbaChannels) {
Services.prefs.setBoolPref(
"browser.theme.dark-toolbar-theme",
element.ownerGlobal.matchMedia("(prefers-color-scheme: dark)")
.matches
);
return null;
}
const { r, g, b, a } = rgbaChannels;
Services.prefs.setBoolPref(
"browser.theme.dark-toolbar-theme",
_isColorDark(r, g, b)
);
return `rgba(${r}, ${g}, ${b}, ${a})`;
},
},
],
[
@ -183,3 +201,8 @@ const ThemeContentPropertyList = [
"sidebar_highlight_text",
"sidebar_text",
];
// This is copied from LightweightThemeConsumer.jsm.
function _isColorDark(r, g, b) {
return 0.2125 * r + 0.7154 * g + 0.0721 * b <= 110;
}

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

@ -39,4 +39,6 @@ const CHROME_ONLY_QUERIES = [
"(-moz-os-version: windows-win7)",
"(-moz-os-version: windows-win8)",
"(-moz-os-version: windows-win10)",
"(-moz-toolbar-prefers-color-scheme: dark)",
"(-moz-toolbar-prefers-color-scheme: light)",
];

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

@ -1144,6 +1144,14 @@
value: false
mirror: always
# Whether the toolbar is dark/light/auto.
# Controls @media -moz-toolbar-prefers-color-scheme.
- name: browser.theme.dark-toolbar-theme
type: RelaxedAtomicBool
value: false
mirror: always
rust: true
# Enable Proton restyle. Requires restart.
- name: browser.proton.enabled
type: RelaxedAtomicBool

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

@ -406,6 +406,21 @@ fn eval_prefers_color_scheme(device: &Device, query_value: Option<PrefersColorSc
}
}
/// The color-scheme of the toolbar in the current Firefox theme. This is based
/// on a pref managed by the front-end.
fn eval_toolbar_prefers_color_scheme(_: &Device, query_value: Option<PrefersColorScheme>) -> bool {
let prefers_color_scheme = if static_prefs::pref!("browser.theme.dark-toolbar-theme") {
PrefersColorScheme::Dark
} else {
PrefersColorScheme::Light
};
match query_value {
Some(v) => prefers_color_scheme == v,
None => true,
}
}
bitflags! {
/// https://drafts.csswg.org/mediaqueries-4/#mf-interaction
struct PointerCapabilities: u8 {
@ -624,7 +639,7 @@ macro_rules! bool_pref_feature {
/// to support new types in these entries and (2) ensuring that either
/// nsPresContext::MediaFeatureValuesChanged is called when the value that
/// would be returned by the evaluator function could change.
pub static MEDIA_FEATURES: [MediaFeatureDescription; 61] = [
pub static MEDIA_FEATURES: [MediaFeatureDescription; 62] = [
feature!(
atom!("width"),
AllowsRanges::Yes,
@ -834,6 +849,12 @@ pub static MEDIA_FEATURES: [MediaFeatureDescription; 61] = [
Evaluator::BoolInteger(eval_moz_non_native_content_theme),
ParsingRequirements::CHROME_AND_UA_ONLY,
),
feature!(
atom!("-moz-toolbar-prefers-color-scheme"),
AllowsRanges::No,
keyword_evaluator!(eval_toolbar_prefers_color_scheme, PrefersColorScheme),
ParsingRequirements::CHROME_AND_UA_ONLY,
),
lnf_int_feature!(atom!("-moz-scrollbar-start-backward"), ScrollArrowStyle, get_scrollbar_start_backward),
lnf_int_feature!(atom!("-moz-scrollbar-start-forward"), ScrollArrowStyle, get_scrollbar_start_forward),

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

@ -478,6 +478,7 @@ function _rgbaToString(parsedColor) {
return `rgba(${r}, ${g}, ${b}, ${a})`;
}
// There is a second copy of this in ThemeVariableMap.jsm.
function _isColorDark(r, g, b) {
return 0.2125 * r + 0.7154 * g + 0.0721 * b <= 110;
}

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

@ -422,6 +422,7 @@ static constexpr nsLiteralCString kBoolMediaQueryPrefs[] = {
"browser.proton.modals.enabled"_ns,
"browser.proton.doorhangers.enabled"_ns,
"browser.proton.places-tooltip.enabled"_ns,
"browser.theme.dark-toolbar-theme"_ns,
};
// Read values from the user's preferences.

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

@ -2223,6 +2223,7 @@ STATIC_ATOMS = [
Atom("_moz_proton_doorhangers", "-moz-proton-doorhangers"),
Atom("_moz_proton_modals", "-moz-proton-modals"),
Atom("_moz_proton_places_tooltip", "-moz-proton-places-tooltip"),
Atom("_moz_toolbar_prefers_color_scheme", "-moz-toolbar-prefers-color-scheme"),
Atom("_moz_system_dark_theme", "-moz-system-dark-theme"),
# application commands
Atom("Back", "Back"),