Skip to content

Commit

Permalink
fix: read GTK dark theme setting on Linux (#23678)
Browse files Browse the repository at this point in the history
  • Loading branch information
zcbenz authored May 21, 2020
1 parent 8292467 commit fdf40ce
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 5 deletions.
45 changes: 40 additions & 5 deletions shell/browser/electron_browser_main_parts.cc
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
#include "ui/base/x/x11_util.h"
#include "ui/base/x/x11_util_internal.h"
#include "ui/events/devices/x11/touch_factory_x11.h"
#include "ui/gfx/color_utils.h"
#include "ui/gfx/x/x11_types.h"
#include "ui/gtk/gtk_ui.h"
#include "ui/gtk/gtk_ui_delegate.h"
Expand Down Expand Up @@ -210,10 +211,36 @@ int X11EmptyErrorHandler(Display* d, XErrorEvent* error) {
int X11EmptyIOErrorHandler(Display* d) {
return 0;
}

// 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 defined(USE_X11)
class DarkThemeObserver : public ui::NativeThemeObserver {
public:
DarkThemeObserver() = default;

// ui::NativeThemeObserver:
void OnNativeThemeUpdated(ui::NativeTheme* observed_theme) override {
UpdateDarkThemeSetting();
}
};
#endif

// static
ElectronBrowserMainParts* ElectronBrowserMainParts::self_ = nullptr;

Expand Down Expand Up @@ -374,11 +401,19 @@ void ElectronBrowserMainParts::ToolkitInitialized() {
// In Aura/X11, Gtk-based LinuxUI implementation is used.
gtk_ui_delegate_ = std::make_unique<ui::GtkUiDelegateX11>(gfx::GetXDisplay());
ui::GtkUiDelegate::SetInstance(gtk_ui_delegate_.get());
views::LinuxUI::SetInstance(BuildGtkUi(ui::GtkUiDelegate::instance()));
#endif

#if defined(USE_AURA) && defined(USE_X11)
views::LinuxUI::instance()->Initialize();
views::LinuxUI* linux_ui = BuildGtkUi(gtk_ui_delegate_.get());
views::LinuxUI::SetInstance(linux_ui);
linux_ui->Initialize();

// 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 naitve theme when GTK theme changes. The GetNativeTheme
// here returns a NativeThemeGtk, which monitors GTK settings.
dark_theme_observer_.reset(new DarkThemeObserver);
linux_ui->GetNativeTheme(nullptr)->AddObserver(dark_theme_observer_.get());
#endif

#if defined(USE_AURA)
Expand Down
6 changes: 6 additions & 0 deletions shell/browser/electron_browser_main_parts.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ class ViewsDelegate;
class ViewsDelegateMac;
#endif

#if defined(USE_X11)
class DarkThemeObserver;
#endif

class ElectronBrowserMainParts : public content::BrowserMainParts {
public:
explicit ElectronBrowserMainParts(const content::MainFunctionParams& params);
Expand Down Expand Up @@ -129,6 +133,8 @@ class ElectronBrowserMainParts : public content::BrowserMainParts {

#if defined(USE_X11)
std::unique_ptr<ui::GtkUiDelegate> gtk_ui_delegate_;
// Used to notify the native theme of changes to dark mode.
std::unique_ptr<DarkThemeObserver> dark_theme_observer_;
#endif

std::unique_ptr<views::LayoutProvider> layout_provider_;
Expand Down

0 comments on commit fdf40ce

Please sign in to comment.