Bug 1665461: reflect the correct colors for default themes in the skeleton UI. r=dthayer

This patch supports a skeleton UI for default, light, and dark themes.
It is not enabled for apenglow or any custom themes.

This also takes into account the system theme. If the user has the default
theme selected and is in dark mode, we override the theme and present the
dark theme skeleton UI.

Differential Revision: https://phabricator.services.mozilla.com/D96230
This commit is contained in:
Emma Malysz 2020-11-12 23:56:44 +00:00
Родитель dbc30ace84
Коммит bf453ef8eb
4 изменённых файлов: 166 добавлений и 30 удалений

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

@ -88,6 +88,7 @@ add_task(async function testWritesSizeValuesOnChange() {
"CssToDevPixelScaling",
"SpringsCSSSpan",
"SearchbarCSSSpan",
"Theme",
];
// Remove all of the registry values to ensure old tests aren't giving us false

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

@ -86,9 +86,11 @@ static int sNonClientHorizontalMargins = 0;
static uint32_t sDpi = 0;
// Color values needed by the animation loop
static uint32_t sBackgroundColor;
static uint32_t sAnimationColor;
static uint32_t sToolbarForegroundColor;
static ThemeMode sTheme = ThemeMode::Invalid;
typedef BOOL(WINAPI* EnableNonClientDpiScalingProc)(HWND);
static EnableNonClientDpiScalingProc sEnableNonClientDpiScaling = NULL;
typedef int(WINAPI* GetSystemMetricsForDpiProc)(int, UINT);
@ -147,6 +149,7 @@ static const wchar_t* sUrlbarCSSRegSuffix = L"|UrlbarCSSSpan";
static const wchar_t* sCssToDevPixelScalingRegSuffix = L"|CssToDevPixelScaling";
static const wchar_t* sSearchbarRegSuffix = L"|SearchbarCSSSpan";
static const wchar_t* sSpringsCSSRegSuffix = L"|SpringsCSSSpan";
static const wchar_t* sThemeRegSuffix = L"|Theme";
std::wstring GetRegValueName(const wchar_t* prefix, const wchar_t* suffix) {
std::wstring result(prefix);
@ -201,7 +204,8 @@ int CSSToDevPixels(int cssPixels, double scaling) {
void DrawSkeletonUI(HWND hWnd, CSSPixelSpan urlbarCSSSpan,
CSSPixelSpan searchbarCSSSpan,
const Vector<CSSPixelSpan>& springs) {
const Vector<CSSPixelSpan>& springs,
const ThemeColors& currentTheme) {
// NOTE: we opt here to paint a pixel buffer for the application chrome by
// hand, without using native UI library methods. Why do we do this?
//
@ -223,22 +227,8 @@ void DrawSkeletonUI(HWND hWnd, CSSPixelSpan urlbarCSSSpan,
// manipulating raw pixels should not be *too* hard to maintain and
// understand so long as it is only painting such simple shapes.
// NOTE: these could be constants, but eventually they won't be, and they will
// need to be set here.
// --toolbar-non-lwt-bgcolor in browser.css
sBackgroundColor = 0xf9f9fa;
// We define this, but it will need to differ based on theme
sToolbarForegroundColor = 0xe5e5e5;
// found in browser-aero.css ":root[tabsintitlebar]:not(:-moz-lwtheme)"
// (set to "hsl(235,33%,19%)")
uint32_t tabBarColor = 0x202340;
// --chrome-content-separator-color in browser.css
uint32_t chromeContentDividerColor = 0xe2e1e3;
// controlled by css variable --tab-line-color
uint32_t tabLineColor = 0x0a75d3;
// controlled by css variable --toolbar-color
uint32_t urlbarColor = 0xffffff;
sAnimationColor = currentTheme.animationColor;
sToolbarForegroundColor = currentTheme.toolbarForegroundColor;
int chromeHorMargin = CSSToDevPixels(2, sCSSToDevPixelScaling);
int verticalOffset = sMaximized ? sNonClientVerticalMargins : 0;
@ -308,7 +298,7 @@ void DrawSkeletonUI(HWND hWnd, CSSPixelSpan urlbarCSSSpan,
// The (traditionally dark blue on Windows) background of the tab bar.
ColorRect tabBar = {};
tabBar.color = tabBarColor;
tabBar.color = currentTheme.tabBarColor;
tabBar.x = 0;
tabBar.y = topBorder.height;
tabBar.width = sWindowWidth;
@ -319,7 +309,7 @@ void DrawSkeletonUI(HWND hWnd, CSSPixelSpan urlbarCSSSpan,
// The blue highlight at the top of the initial selected tab
ColorRect tabLine = {};
tabLine.color = tabLineColor;
tabLine.color = currentTheme.tabLineColor;
tabLine.x = titlebarSpacerWidth;
tabLine.y = topBorder.height;
tabLine.width = selectedTabWidth;
@ -330,7 +320,7 @@ void DrawSkeletonUI(HWND hWnd, CSSPixelSpan urlbarCSSSpan,
// The initial selected tab
ColorRect selectedTab = {};
selectedTab.color = sBackgroundColor;
selectedTab.color = currentTheme.backgroundColor;
selectedTab.x = titlebarSpacerWidth;
selectedTab.y = tabLine.y + tabLineHeight;
selectedTab.width = selectedTabWidth;
@ -352,7 +342,7 @@ void DrawSkeletonUI(HWND hWnd, CSSPixelSpan urlbarCSSSpan,
// The toolbar background
ColorRect toolbar = {};
toolbar.color = sBackgroundColor;
toolbar.color = currentTheme.backgroundColor;
toolbar.x = 0;
toolbar.y = tabBar.y + tabBarHeight;
toolbar.width = sWindowWidth;
@ -363,7 +353,7 @@ void DrawSkeletonUI(HWND hWnd, CSSPixelSpan urlbarCSSSpan,
// The single-pixel divider line below the toolbar
ColorRect chromeContentDivider = {};
chromeContentDivider.color = chromeContentDividerColor;
chromeContentDivider.color = currentTheme.chromeContentDividerColor;
chromeContentDivider.x = 0;
chromeContentDivider.y = toolbar.y + toolbar.height;
chromeContentDivider.width = sWindowWidth;
@ -374,7 +364,7 @@ void DrawSkeletonUI(HWND hWnd, CSSPixelSpan urlbarCSSSpan,
// The urlbar
ColorRect urlbar = {};
urlbar.color = urlbarColor;
urlbar.color = currentTheme.urlbarColor;
urlbar.x = CSSToDevPixels(urlbarCSSSpan.start, sCSSToDevPixelScaling) +
horizontalOffset;
urlbar.y = tabBar.y + tabBarHeight + urlbarTopOffset;
@ -401,7 +391,7 @@ void DrawSkeletonUI(HWND hWnd, CSSPixelSpan urlbarCSSSpan,
bool hasSearchbar = searchbarCSSSpan.start != 0 && searchbarCSSSpan.end != 0;
ColorRect searchbarRect = {};
if (hasSearchbar == true) {
searchbarRect.color = urlbarColor;
searchbarRect.color = currentTheme.urlbarColor;
searchbarRect.x =
CSSToDevPixels(searchbarCSSSpan.start, sCSSToDevPixelScaling) +
horizontalOffset;
@ -550,7 +540,7 @@ void DrawSkeletonUI(HWND hWnd, CSSPixelSpan urlbarCSSSpan,
// Then, we just fill the rest with FillRect
RECT rect = {0, sTotalChromeHeight, (LONG)sWindowWidth, (LONG)sWindowHeight};
HBRUSH brush = sCreateSolidBrush(sBackgroundColor);
HBRUSH brush = sCreateSolidBrush(currentTheme.backgroundColor);
sFillRect(hdc, &rect, brush);
scopeExit.release();
@ -584,7 +574,7 @@ DWORD WINAPI AnimateSkeletonUI(void* aUnused) {
int animationWidth = CSSToDevPixels(80, sCSSToDevPixelScaling);
UniquePtr<uint32_t[]> animationLookup =
MakeUnique<uint32_t[]>(animationWidth);
uint32_t animationColor = sBackgroundColor;
uint32_t animationColor = sAnimationColor;
NormalizedRGB rgbBlend = UintToRGB(animationColor);
// Build the first half of the lookup table
@ -762,6 +752,86 @@ LRESULT WINAPI PreXULSkeletonUIProc(HWND hWnd, UINT msg, WPARAM wParam,
return ::DefWindowProcW(hWnd, msg, wParam, lParam);
}
bool IsSystemDarkThemeEnabled() {
DWORD result;
HKEY themeKey;
DWORD dataLen = sizeof(uint32_t);
LPCWSTR keyName =
L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize";
result = ::RegOpenKeyExW(HKEY_CURRENT_USER, keyName, 0, KEY_READ, &themeKey);
if (result != ERROR_SUCCESS) {
return false;
}
AutoCloseRegKey closeKey(themeKey);
uint32_t lightThemeEnabled;
result = ::RegGetValueW(
themeKey, nullptr, L"AppsUseLightTheme", RRF_RT_REG_DWORD, nullptr,
reinterpret_cast<PBYTE>(&lightThemeEnabled), &dataLen);
if (result != ERROR_SUCCESS) {
return false;
}
return !lightThemeEnabled;
}
ThemeColors GetTheme(ThemeMode themeId) {
ThemeColors theme = {};
switch (themeId) {
case ThemeMode::Dark:
// Dark theme or default theme when in dark mode
// controlled by css variable --toolbar-bgcolor
theme.backgroundColor = 0x323234;
theme.toolbarForegroundColor = 0x6a6a6b;
// controlled by css variable --lwt-accent-color
theme.tabBarColor = 0x0c0c0d;
// controlled by --toolbar-non-lwt-textcolor in browser.css
theme.chromeContentDividerColor = 0x0c0c0d;
// controlled by css variable --tab-line-color
theme.tabLineColor = 0x0a84ff;
// controlled by css variable --lwt-toolbar-field-background-colo
theme.urlbarColor = 0x474749;
theme.animationColor = theme.urlbarColor;
return theme;
case ThemeMode::Light:
// Light theme
// controlled by --toolbar-bgcolor
theme.backgroundColor = 0xf5f6f7;
theme.toolbarForegroundColor = 0xd9dadb;
// controlled by css variable --lwt-accent-color
theme.tabBarColor = 0xe3e4e6;
// --chrome-content-separator-color in browser.css
theme.chromeContentDividerColor = 0x9e9fa1;
// controlled by css variable --tab-line-color
theme.tabLineColor = 0x0a84ff;
// by css variable --lwt-toolbar-field-background-color
theme.urlbarColor = 0xffffff;
theme.animationColor = theme.backgroundColor;
return theme;
case ThemeMode::Default:
default:
// Default theme when not in dark mode
MOZ_ASSERT(themeId == ThemeMode::Default);
// --toolbar-non-lwt-bgcolor in browser.css
theme.backgroundColor = 0xf9f9fa;
theme.toolbarForegroundColor = 0xe5e5e5;
// found in browser-aero.css ":root[tabsintitlebar]:not(:-moz-lwtheme)"
// (set to "hsl(235,33%,19%)")
theme.tabBarColor = 0x202340;
// --chrome-content-separator-color in browser.css
theme.chromeContentDividerColor = 0xe2e1e3;
// controlled by css variable --tab-line-color
theme.tabLineColor = 0x0a84ff;
// controlled by css variable --toolbar-color
theme.urlbarColor = 0xffffff;
theme.animationColor = theme.backgroundColor;
return theme;
}
}
bool OpenPreXULSkeletonUIRegKey(HKEY& key) {
DWORD disposition;
LSTATUS result =
@ -1221,6 +1291,23 @@ void CreateAndStorePreXULSkeletonUI(HINSTANCE hInstance, int argc,
}
}
dataLen = sizeof(uint32_t);
uint32_t theme;
result = ::RegGetValueW(
regKey, nullptr, GetRegValueName(binPath.get(), sThemeRegSuffix).c_str(),
RRF_RT_REG_DWORD, nullptr, reinterpret_cast<PBYTE>(&theme), &dataLen);
if (result != ERROR_SUCCESS) {
printf_stderr("Error reading theme %lu\n", GetLastError());
return;
}
ThemeMode themeMode = static_cast<ThemeMode>(theme);
if (themeMode == ThemeMode::Default) {
if (IsSystemDarkThemeEnabled() == true) {
themeMode = ThemeMode::Dark;
}
}
ThemeColors currentTheme = GetTheme(themeMode);
sPreXULSkeletonUIWindow =
sCreateWindowExW(kPreXULSkeletonUIWindowStyleEx, L"MozillaWindowClass",
L"", windowStyle, screenX, screenY, windowWidth,
@ -1261,8 +1348,8 @@ void CreateAndStorePreXULSkeletonUI(HINSTANCE hInstance, int argc,
sSetWindowPos(sPreXULSkeletonUIWindow, 0, 0, 0, 0, 0,
SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE |
SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_NOZORDER);
DrawSkeletonUI(sPreXULSkeletonUIWindow, urlbar, searchbar, springs);
DrawSkeletonUI(sPreXULSkeletonUIWindow, urlbar, searchbar, springs,
currentTheme);
if (sAnimatedRects) {
sPreXULSKeletonUIAnimationThread = ::CreateThread(
nullptr, 256 * 1024, AnimateSkeletonUI, nullptr, 0, nullptr);
@ -1450,6 +1537,31 @@ MFBT_API void SetPreXULSkeletonUIEnabledIfAllowed(bool value) {
sPreXULSkeletonUIEnabled = value;
}
MFBT_API void SetPreXULSkeletonUIThemeId(ThemeMode theme) {
if (theme == sTheme) {
return;
}
HKEY regKey;
if (!OpenPreXULSkeletonUIRegKey(regKey)) {
return;
}
AutoCloseRegKey closeKey(regKey);
UniquePtr<wchar_t[]> binPath = GetBinaryPath();
uint32_t themeId = (uint32_t)theme;
LSTATUS result;
result = ::RegSetValueExW(
regKey, GetRegValueName(binPath.get(), sThemeRegSuffix).c_str(), 0,
REG_DWORD, reinterpret_cast<PBYTE>(&themeId), sizeof(themeId));
if (result != ERROR_SUCCESS) {
printf_stderr("Failed persisting theme to Windows registry\n");
sTheme = ThemeMode::Invalid;
return;
}
sTheme = static_cast<ThemeMode>(themeId);
}
MFBT_API void PollPreXULSkeletonUIEvents() {
if (sPreXULSkeletonUIEnabled && sPreXULSkeletonUIWindow) {
MSG outMsg = {};

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

@ -32,6 +32,18 @@ struct DevPixelSpan {
int end;
};
enum class ThemeMode : uint32_t { Invalid, Default, Dark, Light };
struct ThemeColors {
uint32_t backgroundColor;
uint32_t toolbarForegroundColor;
uint32_t tabBarColor;
uint32_t chromeContentDividerColor;
uint32_t tabLineColor;
uint32_t urlbarColor;
uint32_t animationColor;
};
MFBT_API void CreateAndStorePreXULSkeletonUI(HINSTANCE hInstance, int argc,
char** argv);
MFBT_API HWND ConsumePreXULSkeletonUIHandle();
@ -45,6 +57,7 @@ MFBT_API void PersistPreXULSkeletonUIValues(int screenX, int screenY, int width,
MFBT_API bool GetPreXULSkeletonUIEnabled();
MFBT_API void SetPreXULSkeletonUIEnabledIfAllowed(bool value);
MFBT_API void PollPreXULSkeletonUIEvents();
MFBT_API void SetPreXULSkeletonUIThemeId(ThemeMode theme);
} // namespace mozilla

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

@ -1958,7 +1958,17 @@ static void ReflectSkeletonUIPrefToRegistry(const char* aPref, void* aData) {
if (shouldBeEnabled && Preferences::HasUserValue(kPrefThemeId)) {
nsCString themeId;
Preferences::GetCString(kPrefThemeId, themeId);
shouldBeEnabled = themeId.EqualsLiteral("default-theme@mozilla.org");
if (themeId.EqualsLiteral("default-theme@mozilla.org")) {
SetPreXULSkeletonUIThemeId(ThemeMode::Default);
} else if (themeId.EqualsLiteral("firefox-compact-dark@mozilla.org")) {
SetPreXULSkeletonUIThemeId(ThemeMode::Dark);
} else if (themeId.EqualsLiteral("firefox-compact-light@mozilla.org")) {
SetPreXULSkeletonUIThemeId(ThemeMode::Light);
} else {
shouldBeEnabled = false;
}
} else if (shouldBeEnabled) {
SetPreXULSkeletonUIThemeId(ThemeMode::Default);
}
if (GetPreXULSkeletonUIEnabled() != shouldBeEnabled) {