feat: enable dark mode on GTK UIs (#38977)

feat: port DarkModeManagerLinux

This is needed after https://bugs.chromium.org/p/chromium/issues/detail?id=998903
and replaces the previous workaround to detect dark mode on GTK.
Detect system dark theme preference via xdg settings portal:
https://flatpak.github.io/xdg-desktop-portal/#gdbus-org.freedesktop.portal.Settings

Closes: https://github.com/electron/electron/issues/38961
Closes: https://github.com/electron/electron/issues/28838

Signed-off-by: Robert Günzler <r@gnzler.io>
Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
This commit is contained in:
Robert Günzler 2023-09-27 20:17:40 +02:00 committed by GitHub
parent a0ae691a9c
commit 480f48b2fc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 12 additions and 48 deletions

View file

@ -204,6 +204,10 @@ static_library("chrome") {
"//chrome/browser/ui/views/status_icons/status_icon_linux_dbus.cc", "//chrome/browser/ui/views/status_icons/status_icon_linux_dbus.cc",
"//chrome/browser/ui/views/status_icons/status_icon_linux_dbus.h", "//chrome/browser/ui/views/status_icons/status_icon_linux_dbus.h",
] ]
sources += [
"//chrome/browser/ui/views/dark_mode_manager_linux.cc",
"//chrome/browser/ui/views/dark_mode_manager_linux.h",
]
public_deps += [ public_deps += [
"//components/dbus/menu", "//components/dbus/menu",
"//components/dbus/thread_linux", "//components/dbus/thread_linux",

View file

@ -79,12 +79,12 @@
#if BUILDFLAG(IS_LINUX) #if BUILDFLAG(IS_LINUX)
#include "base/environment.h" #include "base/environment.h"
#include "chrome/browser/ui/views/dark_mode_manager_linux.h"
#include "device/bluetooth/bluetooth_adapter_factory.h" #include "device/bluetooth/bluetooth_adapter_factory.h"
#include "device/bluetooth/dbus/dbus_bluez_manager_wrapper_linux.h" #include "device/bluetooth/dbus/dbus_bluez_manager_wrapper_linux.h"
#include "electron/electron_gtk_stubs.h" #include "electron/electron_gtk_stubs.h"
#include "ui/base/cursor/cursor_factory.h" #include "ui/base/cursor/cursor_factory.h"
#include "ui/base/ime/linux/linux_input_method_context_factory.h" #include "ui/base/ime/linux/linux_input_method_context_factory.h"
#include "ui/gfx/color_utils.h"
#include "ui/gtk/gtk_compat.h" // nogncheck #include "ui/gtk/gtk_compat.h" // nogncheck
#include "ui/gtk/gtk_util.h" // nogncheck #include "ui/gtk/gtk_util.h" // nogncheck
#include "ui/linux/linux_ui.h" #include "ui/linux/linux_ui.h"
@ -169,36 +169,8 @@ std::u16string MediaStringProvider(media::MessageId id) {
} }
} }
#if BUILDFLAG(IS_LINUX)
// GTK does not provide a way to check if current theme is dark, so we compare
// the text and background luminosity to get a result.
// This trick comes from FireFox.
void UpdateDarkThemeSetting() {
float bg = color_utils::GetRelativeLuminance(gtk::GetBgColor("GtkLabel"));
float fg = color_utils::GetRelativeLuminance(gtk::GetFgColor("GtkLabel"));
bool is_dark = fg > bg;
// Pass it to NativeUi theme, which is used by the nativeTheme module and most
// places in Electron.
ui::NativeTheme::GetInstanceForNativeUi()->set_use_dark_colors(is_dark);
// Pass it to Web Theme, to make "prefers-color-scheme" media query work.
ui::NativeTheme::GetInstanceForWeb()->set_use_dark_colors(is_dark);
}
#endif
} // namespace } // namespace
#if BUILDFLAG(IS_LINUX)
class DarkThemeObserver : public ui::NativeThemeObserver {
public:
DarkThemeObserver() = default;
// ui::NativeThemeObserver:
void OnNativeThemeUpdated(ui::NativeTheme* observed_theme) override {
UpdateDarkThemeSetting();
}
};
#endif
// static // static
ElectronBrowserMainParts* ElectronBrowserMainParts::self_ = nullptr; ElectronBrowserMainParts* ElectronBrowserMainParts::self_ = nullptr;
@ -435,17 +407,10 @@ void ElectronBrowserMainParts::ToolkitInitialized() {
CHECK(electron::IsElectron_gdk_pixbufInitialized()) CHECK(electron::IsElectron_gdk_pixbufInitialized())
<< "Failed to initialize libgdk_pixbuf-2.0.so.0"; << "Failed to initialize libgdk_pixbuf-2.0.so.0";
// Chromium does not respect GTK dark theme setting, but they may change // source theme changes from system settings, including settings portal:
// in future and this code might be no longer needed. Check the Chromium // https://flatpak.github.io/xdg-desktop-portal/#gdbus-org.freedesktop.portal.Settings
// issue to keep updated: dark_mode_manager_ = std::make_unique<ui::DarkModeManagerLinux>();
// https://bugs.chromium.org/p/chromium/issues/detail?id=998903
UpdateDarkThemeSetting();
// Update the native theme when GTK theme changes. The GetNativeTheme
// here returns a NativeThemeGtk, which monitors GTK settings.
dark_theme_observer_ = std::make_unique<DarkThemeObserver>();
auto* linux_ui_theme = ui::LinuxUiTheme::GetForProfile(nullptr);
CHECK(linux_ui_theme);
linux_ui_theme->GetNativeTheme()->AddObserver(dark_theme_observer_.get());
ui::LinuxUi::SetInstance(linux_ui); ui::LinuxUi::SetInstance(linux_ui);
// Cursor theme changes are tracked by LinuxUI (via a CursorThemeManager // Cursor theme changes are tracked by LinuxUI (via a CursorThemeManager

View file

@ -43,7 +43,8 @@ class Environment;
namespace ui { namespace ui {
class LinuxUiGetter; class LinuxUiGetter;
} class DarkModeManagerLinux;
} // namespace ui
namespace electron { namespace electron {
@ -65,10 +66,6 @@ class ViewsDelegate;
class ViewsDelegateMac; class ViewsDelegateMac;
#endif #endif
#if BUILDFLAG(IS_LINUX)
class DarkThemeObserver;
#endif
class ElectronBrowserMainParts : public content::BrowserMainParts { class ElectronBrowserMainParts : public content::BrowserMainParts {
public: public:
ElectronBrowserMainParts(); ElectronBrowserMainParts();
@ -145,9 +142,7 @@ class ElectronBrowserMainParts : public content::BrowserMainParts {
#endif #endif
#if BUILDFLAG(IS_LINUX) #if BUILDFLAG(IS_LINUX)
// Used to notify the native theme of changes to dark mode. std::unique_ptr<ui::DarkModeManagerLinux> dark_mode_manager_;
std::unique_ptr<DarkThemeObserver> dark_theme_observer_;
std::unique_ptr<ui::LinuxUiGetter> linux_ui_getter_; std::unique_ptr<ui::LinuxUiGetter> linux_ui_getter_;
#endif #endif