зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1683204 - Include content theme configuration details in FullLookAndFeel. r=spohl
And re-enable the RemoteLookAndFeel by default with Gtk. When the RemoteLookAndFeel is enabled and the non-native theme is not enabled, we still need to configure the Gtk theme in content processes, since we're still using Gtk to paint widget backgrounds etc. Without this, we can end up using LookAndFeel colors from a light theme but painting widget backgrounds from a dark theme. Other platforms don't configure themes for content processes differently, so on those platforms LookAndFeelTheme is an empty struct and we skip the ConfigureTheme call. Differential Revision: https://phabricator.services.mozilla.com/D100223
This commit is contained in:
Родитель
4932b4f870
Коммит
eefbb537b9
|
@ -10424,7 +10424,7 @@
|
|||
- name: widget.remote-look-and-feel
|
||||
type: bool
|
||||
#ifdef MOZ_WIDGET_GTK
|
||||
value: false
|
||||
value: true
|
||||
#else
|
||||
value: false
|
||||
#endif
|
||||
|
|
|
@ -36,8 +36,6 @@ struct LookAndFeelCache {
|
|||
};
|
||||
|
||||
/**
|
||||
* Stores the entirety of a LookAndFeel's data.
|
||||
*
|
||||
* The format allows for some compression compared with having fixed
|
||||
* length arrays for each value type and some indication of whether
|
||||
* a value is present. This is because not all values are present on
|
||||
|
@ -55,7 +53,7 @@ struct LookAndFeelCache {
|
|||
* LookAndFeel::FontID value minus 1, as 1 is the minimum value of that
|
||||
* enum.)
|
||||
*/
|
||||
struct FullLookAndFeel {
|
||||
struct LookAndFeelTables {
|
||||
int32_t[] ints;
|
||||
float[] floats;
|
||||
nscolor[] colors;
|
||||
|
@ -70,6 +68,23 @@ struct FullLookAndFeel {
|
|||
bool passwordEcho;
|
||||
};
|
||||
|
||||
struct LookAndFeelTheme {
|
||||
#ifdef MOZ_WIDGET_GTK
|
||||
nsCString themeName;
|
||||
bool preferDarkTheme;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* Stores the entirety of a LookAndFeel's data.
|
||||
*/
|
||||
struct FullLookAndFeel {
|
||||
LookAndFeelTables tables;
|
||||
#ifdef MOZ_WIDGET_GTK
|
||||
LookAndFeelTheme theme;
|
||||
#endif
|
||||
};
|
||||
|
||||
union LookAndFeelData {
|
||||
LookAndFeelCache;
|
||||
FullLookAndFeel;
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Result.h"
|
||||
#include "mozilla/ResultExtensions.h"
|
||||
#include "mozilla/StaticPrefs_widget.h"
|
||||
#include "nsLookAndFeel.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
|
||||
#include <limits>
|
||||
|
@ -20,19 +22,35 @@
|
|||
|
||||
namespace mozilla::widget {
|
||||
|
||||
RemoteLookAndFeel::RemoteLookAndFeel(FullLookAndFeel&& aTables)
|
||||
: mTables(std::move(aTables)) {
|
||||
RemoteLookAndFeel::RemoteLookAndFeel(FullLookAndFeel&& aData)
|
||||
: mTables(std::move(aData.tables())) {
|
||||
MOZ_ASSERT(XRE_IsContentProcess(),
|
||||
"Only content processes should be using a RemoteLookAndFeel");
|
||||
|
||||
#ifdef MOZ_WIDGET_GTK
|
||||
if (!StaticPrefs::widget_disable_native_theme_for_content()) {
|
||||
// Configure the theme in this content process with the Gtk theme that was
|
||||
// chosen by WithThemeConfiguredForContent in the parent process.
|
||||
nsLookAndFeel::ConfigureTheme(aData.theme());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
RemoteLookAndFeel::~RemoteLookAndFeel() = default;
|
||||
|
||||
void RemoteLookAndFeel::SetDataImpl(FullLookAndFeel&& aTables) {
|
||||
void RemoteLookAndFeel::SetDataImpl(FullLookAndFeel&& aData) {
|
||||
MOZ_ASSERT(XRE_IsContentProcess(),
|
||||
"Only content processes should be using a RemoteLookAndFeel");
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mTables = std::move(aTables);
|
||||
mTables = std::move(aData.tables());
|
||||
|
||||
#ifdef MOZ_WIDGET_GTK
|
||||
if (!StaticPrefs::widget_disable_native_theme_for_content()) {
|
||||
// Configure the theme in this content process with the Gtk theme that was
|
||||
// chosen by WithThemeConfiguredForContent in the parent process.
|
||||
nsLookAndFeel::ConfigureTheme(aData.theme());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -130,14 +148,14 @@ const FullLookAndFeel* RemoteLookAndFeel::ExtractData() {
|
|||
MOZ_ASSERT(XRE_IsParentProcess(),
|
||||
"Only parent processes should be extracting LookAndFeel data");
|
||||
|
||||
if (sCachedTables) {
|
||||
return sCachedTables;
|
||||
if (sCachedLookAndFeelData) {
|
||||
return sCachedLookAndFeelData;
|
||||
}
|
||||
|
||||
static bool sInitialized = false;
|
||||
if (!sInitialized) {
|
||||
sInitialized = true;
|
||||
ClearOnShutdown(&sCachedTables);
|
||||
ClearOnShutdown(&sCachedLookAndFeelData);
|
||||
}
|
||||
|
||||
FullLookAndFeel* lf = new FullLookAndFeel{};
|
||||
|
@ -148,7 +166,7 @@ const FullLookAndFeel* RemoteLookAndFeel::ExtractData() {
|
|||
impl->NativeGetInt(IntID::SystemUsesDarkTheme, darkTheme);
|
||||
impl->NativeGetInt(IntID::UseAccessibilityTheme, accessibilityTheme);
|
||||
|
||||
impl->WithThemeConfiguredForContent([&]() {
|
||||
impl->WithThemeConfiguredForContent([&](const LookAndFeelTheme& aTheme) {
|
||||
for (auto id : MakeEnumeratedRange(IntID::End)) {
|
||||
int32_t theInt;
|
||||
nsresult rv;
|
||||
|
@ -172,21 +190,21 @@ const FullLookAndFeel* RemoteLookAndFeel::ExtractData() {
|
|||
rv = impl->NativeGetInt(id, theInt);
|
||||
break;
|
||||
}
|
||||
AddToMap(&lf->ints(), &lf->intMap(),
|
||||
AddToMap(&lf->tables().ints(), &lf->tables().intMap(),
|
||||
NS_SUCCEEDED(rv) ? Some(theInt) : Nothing{});
|
||||
}
|
||||
|
||||
for (auto id : MakeEnumeratedRange(FloatID::End)) {
|
||||
float theFloat;
|
||||
nsresult rv = impl->NativeGetFloat(id, theFloat);
|
||||
AddToMap(&lf->floats(), &lf->floatMap(),
|
||||
AddToMap(&lf->tables().floats(), &lf->tables().floatMap(),
|
||||
NS_SUCCEEDED(rv) ? Some(theFloat) : Nothing{});
|
||||
}
|
||||
|
||||
for (auto id : MakeEnumeratedRange(ColorID::End)) {
|
||||
nscolor theColor;
|
||||
nsresult rv = impl->NativeGetColor(id, theColor);
|
||||
AddToMap(&lf->colors(), &lf->colorMap(),
|
||||
AddToMap(&lf->tables().colors(), &lf->tables().colorMap(),
|
||||
NS_SUCCEEDED(rv) ? Some(theColor) : Nothing{});
|
||||
}
|
||||
|
||||
|
@ -219,25 +237,29 @@ const FullLookAndFeel* RemoteLookAndFeel::ExtractData() {
|
|||
#endif
|
||||
maybeFont = Some(std::move(font));
|
||||
}
|
||||
AddToMap(&lf->fonts(), &lf->fontMap(), std::move(maybeFont));
|
||||
AddToMap(&lf->tables().fonts(), &lf->tables().fontMap(),
|
||||
std::move(maybeFont));
|
||||
}
|
||||
|
||||
lf->passwordChar() = impl->GetPasswordCharacterImpl();
|
||||
lf->passwordEcho() = impl->GetEchoPasswordImpl();
|
||||
lf->tables().passwordChar() = impl->GetPasswordCharacterImpl();
|
||||
lf->tables().passwordEcho() = impl->GetEchoPasswordImpl();
|
||||
#ifdef MOZ_WIDGET_GTK
|
||||
lf->theme() = aTheme;
|
||||
#endif
|
||||
});
|
||||
|
||||
// This assignment to sCachedTables must be done after the
|
||||
// This assignment to sCachedLookAndFeelData must be done after the
|
||||
// WithThemeConfiguredForContent call, since it can end up calling RefreshImpl
|
||||
// on the LookAndFeel, which will clear out sCachedTables.
|
||||
sCachedTables = lf;
|
||||
return sCachedTables;
|
||||
sCachedLookAndFeelData = lf;
|
||||
return sCachedLookAndFeelData;
|
||||
}
|
||||
|
||||
void RemoteLookAndFeel::ClearCachedData() {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
sCachedTables = nullptr;
|
||||
sCachedLookAndFeelData = nullptr;
|
||||
}
|
||||
|
||||
StaticAutoPtr<FullLookAndFeel> RemoteLookAndFeel::sCachedTables;
|
||||
StaticAutoPtr<FullLookAndFeel> RemoteLookAndFeel::sCachedLookAndFeelData;
|
||||
|
||||
} // namespace mozilla::widget
|
||||
|
|
|
@ -51,11 +51,11 @@ class RemoteLookAndFeel final : public nsXPLookAndFeel {
|
|||
// implementation.
|
||||
//
|
||||
// This is called in the parent process when the default LookAndFeel is
|
||||
// refreshed, to invalidate sCachedTables.
|
||||
// refreshed, to invalidate sCachedLookAndFeelData.
|
||||
static void ClearCachedData();
|
||||
|
||||
private:
|
||||
FullLookAndFeel mTables;
|
||||
LookAndFeelTables mTables;
|
||||
|
||||
// A cached copy of the data extracted by ExtractData.
|
||||
//
|
||||
|
@ -63,7 +63,7 @@ class RemoteLookAndFeel final : public nsXPLookAndFeel {
|
|||
// time we create a new content process.
|
||||
//
|
||||
// Only used in the parent process.
|
||||
static StaticAutoPtr<FullLookAndFeel> sCachedTables;
|
||||
static StaticAutoPtr<FullLookAndFeel> sCachedLookAndFeelData;
|
||||
};
|
||||
|
||||
} // namespace mozilla::widget
|
||||
|
|
|
@ -975,18 +975,32 @@ static nsCString GetGtkTheme() {
|
|||
return ret;
|
||||
}
|
||||
|
||||
static bool GetPreferDarkTheme() {
|
||||
GtkSettings* settings = gtk_settings_get_default();
|
||||
gboolean preferDarkTheme = FALSE;
|
||||
g_object_get(settings, "gtk-application-prefer-dark-theme", &preferDarkTheme,
|
||||
nullptr);
|
||||
return preferDarkTheme == TRUE;
|
||||
}
|
||||
|
||||
void nsLookAndFeel::ConfigureTheme(const LookAndFeelTheme& aTheme) {
|
||||
MOZ_ASSERT(XRE_IsContentProcess());
|
||||
GtkSettings* settings = gtk_settings_get_default();
|
||||
g_object_set(settings, "gtk-theme-name", aTheme.themeName().get(),
|
||||
"gtk-application-prefer-dark-theme",
|
||||
aTheme.preferDarkTheme() ? TRUE : FALSE, nullptr);
|
||||
}
|
||||
|
||||
void nsLookAndFeel::WithThemeConfiguredForContent(
|
||||
const std::function<void()>& aFn) {
|
||||
const std::function<void(const LookAndFeelTheme& aTheme)>& aFn) {
|
||||
nsWindow::WithSettingsChangesIgnored([&]() {
|
||||
// Available on Gtk 3.20+.
|
||||
static auto sGtkSettingsResetProperty =
|
||||
(void (*)(GtkSettings*, const gchar*))dlsym(
|
||||
RTLD_DEFAULT, "gtk_settings_reset_property");
|
||||
|
||||
GtkSettings* settings = gtk_settings_get_default();
|
||||
|
||||
nsCString themeName;
|
||||
gboolean preferDarkTheme = FALSE;
|
||||
bool preferDarkTheme = false;
|
||||
|
||||
if (!sGtkSettingsResetProperty) {
|
||||
// When gtk_settings_reset_property is not available, we instead
|
||||
|
@ -996,8 +1010,7 @@ void nsLookAndFeel::WithThemeConfiguredForContent(
|
|||
// could listen to xsettings changes and update the GtkSettings object
|
||||
// ourselves in response, if we wanted to fix this.)
|
||||
themeName = GetGtkTheme();
|
||||
g_object_get(settings, "gtk-application-prefer-dark-theme",
|
||||
&preferDarkTheme, nullptr);
|
||||
preferDarkTheme = GetPreferDarkTheme();
|
||||
}
|
||||
|
||||
bool changed = ConfigureContentGtkTheme();
|
||||
|
@ -1005,17 +1018,22 @@ void nsLookAndFeel::WithThemeConfiguredForContent(
|
|||
RefreshImpl();
|
||||
}
|
||||
|
||||
aFn();
|
||||
LookAndFeelTheme theme;
|
||||
theme.themeName() = GetGtkTheme();
|
||||
theme.preferDarkTheme() = GetPreferDarkTheme();
|
||||
|
||||
aFn(theme);
|
||||
|
||||
if (changed) {
|
||||
GtkSettings* settings = gtk_settings_get_default();
|
||||
if (sGtkSettingsResetProperty) {
|
||||
sGtkSettingsResetProperty(settings, "gtk-theme-name");
|
||||
sGtkSettingsResetProperty(settings,
|
||||
"gtk-application-prefer-dark-theme");
|
||||
} else {
|
||||
g_object_set(settings, "gtk-theme-name", themeName.get(),
|
||||
"gtk-application-prefer-dark-theme", preferDarkTheme,
|
||||
nullptr);
|
||||
"gtk-application-prefer-dark-theme",
|
||||
preferDarkTheme ? TRUE : FALSE, nullptr);
|
||||
}
|
||||
RefreshImpl();
|
||||
}
|
||||
|
@ -1047,10 +1065,7 @@ bool nsLookAndFeel::ConfigureContentGtkTheme() {
|
|||
}
|
||||
|
||||
// Try to select the light variant of the current theme first...
|
||||
gboolean preferDarkTheme;
|
||||
g_object_get(settings, "gtk-application-prefer-dark-theme", &preferDarkTheme,
|
||||
nullptr);
|
||||
if (preferDarkTheme) {
|
||||
if (GetPreferDarkTheme()) {
|
||||
LOG((" disabling gtk-application-prefer-dark-theme\n"));
|
||||
g_object_set(settings, "gtk-application-prefer-dark-theme", FALSE, nullptr);
|
||||
changed = true;
|
||||
|
|
|
@ -35,7 +35,9 @@ class nsLookAndFeel final : public nsXPLookAndFeel {
|
|||
LookAndFeelCache GetCacheImpl() override;
|
||||
void SetCacheImpl(const LookAndFeelCache& aCache) override;
|
||||
|
||||
void WithThemeConfiguredForContent(const std::function<void()>& aFn) override;
|
||||
void WithThemeConfiguredForContent(
|
||||
const std::function<void(const LookAndFeelTheme& aTheme)>& aFn) override;
|
||||
static void ConfigureTheme(const LookAndFeelTheme& aTheme);
|
||||
|
||||
bool IsCSDAvailable() const { return mCSDAvailable; }
|
||||
|
||||
|
|
|
@ -346,7 +346,7 @@ else:
|
|||
"headless/HeadlessWidgetTypes.ipdlh",
|
||||
]
|
||||
|
||||
IPDL_SOURCES += [
|
||||
PREPROCESSED_IPDL_SOURCES += [
|
||||
"LookAndFeelTypes.ipdlh",
|
||||
]
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "mozilla/StaticPrefs_editor.h"
|
||||
#include "mozilla/StaticPrefs_findbar.h"
|
||||
#include "mozilla/StaticPrefs_ui.h"
|
||||
#include "mozilla/StaticPrefs_widget.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/widget/WidgetMessageUtils.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
|
|
|
@ -84,6 +84,7 @@ class nsXPLookAndFeel : public mozilla::LookAndFeel {
|
|||
using LookAndFeelInt = mozilla::widget::LookAndFeelInt;
|
||||
using LookAndFeelFont = mozilla::widget::LookAndFeelFont;
|
||||
using LookAndFeelColor = mozilla::widget::LookAndFeelColor;
|
||||
using LookAndFeelTheme = mozilla::widget::LookAndFeelTheme;
|
||||
|
||||
virtual LookAndFeelCache GetCacheImpl();
|
||||
virtual void SetCacheImpl(const LookAndFeelCache& aCache) {}
|
||||
|
@ -91,8 +92,9 @@ class nsXPLookAndFeel : public mozilla::LookAndFeel {
|
|||
|
||||
virtual void NativeInit() = 0;
|
||||
|
||||
virtual void WithThemeConfiguredForContent(const std::function<void()>& aFn) {
|
||||
aFn();
|
||||
virtual void WithThemeConfiguredForContent(
|
||||
const std::function<void(const LookAndFeelTheme& aTheme)>& aFn) {
|
||||
aFn(LookAndFeelTheme{});
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
Загрузка…
Ссылка в новой задаче