Browse Source

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

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

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Robert Günzler <[email protected]>
trop[bot] 1 year ago
parent
commit
13bdefa549

+ 4 - 0
chromium_src/BUILD.gn

@@ -177,6 +177,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.h",
     ]
+    sources += [
+      "//chrome/browser/ui/views/dark_mode_manager_linux.cc",
+      "//chrome/browser/ui/views/dark_mode_manager_linux.h",
+    ]
     public_deps += [
       "//components/dbus/menu",
       "//components/dbus/thread_linux",

+ 5 - 40
shell/browser/electron_browser_main_parts.cc

@@ -78,12 +78,12 @@
 
 #if BUILDFLAG(IS_LINUX)
 #include "base/environment.h"
+#include "chrome/browser/ui/views/dark_mode_manager_linux.h"
 #include "device/bluetooth/bluetooth_adapter_factory.h"
 #include "device/bluetooth/dbus/dbus_bluez_manager_wrapper_linux.h"
 #include "electron/electron_gtk_stubs.h"
 #include "ui/base/cursor/cursor_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_util.h"    // nogncheck
 #include "ui/linux/linux_ui.h"
@@ -176,36 +176,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
 
-#if BUILDFLAG(IS_LINUX)
-class DarkThemeObserver : public ui::NativeThemeObserver {
- public:
-  DarkThemeObserver() = default;
-
-  // ui::NativeThemeObserver:
-  void OnNativeThemeUpdated(ui::NativeTheme* observed_theme) override {
-    UpdateDarkThemeSetting();
-  }
-};
-#endif
-
 // static
 ElectronBrowserMainParts* ElectronBrowserMainParts::self_ = nullptr;
 
@@ -440,17 +412,10 @@ void ElectronBrowserMainParts::ToolkitInitialized() {
   CHECK(electron::IsElectron_gdk_pixbufInitialized())
       << "Failed to initialize libgdk_pixbuf-2.0.so.0";
 
-  // Chromium does not respect GTK dark theme setting, but they may change
-  // in future and this code might be no longer needed. Check the Chromium
-  // issue to keep updated:
-  // 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());
+  // source theme changes from system settings, including settings portal:
+  // https://flatpak.github.io/xdg-desktop-portal/#gdbus-org.freedesktop.portal.Settings
+  dark_mode_manager_ = std::make_unique<ui::DarkModeManagerLinux>();
+
   ui::LinuxUi::SetInstance(linux_ui);
 
   // Cursor theme changes are tracked by LinuxUI (via a CursorThemeManager

+ 3 - 8
shell/browser/electron_browser_main_parts.h

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