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:
parent
a0ae691a9c
commit
480f48b2fc
3 changed files with 12 additions and 48 deletions
|
@ -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",
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue