зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
dbc30ace84
Коммит
bf453ef8eb
|
@ -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) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче