Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 1c22286

Browse files
authored
[Linux] revise dark theme detection (#25535)
1 parent 2e3a7f8 commit 1c22286

File tree

1 file changed

+53
-10
lines changed

1 file changed

+53
-10
lines changed

shell/platform/linux/fl_settings_plugin.cc

Lines changed: 53 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44

55
#include "flutter/shell/platform/linux/fl_settings_plugin.h"
66

7-
#include <cstring>
7+
#include <gmodule.h>
8+
#include <gtk/gtk.h>
9+
#include <math.h>
810

911
#include "flutter/shell/platform/linux/public/flutter_linux/fl_basic_message_channel.h"
1012
#include "flutter/shell/platform/linux/public/flutter_linux/fl_json_message_codec.h"
@@ -17,11 +19,12 @@ static constexpr char kPlatformBrightnessLight[] = "light";
1719
static constexpr char kPlatformBrightnessDark[] = "dark";
1820

1921
static constexpr char kDesktopInterfaceSchema[] = "org.gnome.desktop.interface";
20-
static constexpr char kDesktopGtkThemeKey[] = "gtk-theme";
2122
static constexpr char kDesktopTextScalingFactorKey[] = "text-scaling-factor";
2223
static constexpr char kDesktopClockFormatKey[] = "clock-format";
2324
static constexpr char kClockFormat24Hour[] = "24h";
2425

26+
enum class Brightness { Light, Dark };
27+
2528
struct _FlSettingsPlugin {
2629
GObject parent_instance;
2730

@@ -32,6 +35,51 @@ struct _FlSettingsPlugin {
3235

3336
G_DEFINE_TYPE(FlSettingsPlugin, fl_settings_plugin, G_TYPE_OBJECT)
3437

38+
// The color brightness calculation has been adapted from theme_data.dart:
39+
// https://github.com/flutter/flutter/blob/8fe4cc79648a952f9c7e49a5248756c2ff98fa3b/packages/flutter/lib/src/material/theme_data.dart#L1470-L1488
40+
41+
// See <https://www.w3.org/TR/WCAG20/#relativeluminancedef>.
42+
static gdouble linearize_color_component(gdouble component) {
43+
if (component <= 0.03928)
44+
return component / 12.92;
45+
return pow((component + 0.055) / 1.055, 2.4);
46+
}
47+
48+
// See <https://en.wikipedia.org/wiki/Relative_luminance>.
49+
gdouble compute_luminance(GdkRGBA* color) {
50+
gdouble r = linearize_color_component(color->red);
51+
gdouble g = linearize_color_component(color->green);
52+
gdouble b = linearize_color_component(color->blue);
53+
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
54+
}
55+
56+
static Brightness estimate_brightness_for_color(GdkRGBA* color) {
57+
gdouble relative_luminance = compute_luminance(color);
58+
59+
// See <https://www.w3.org/TR/WCAG20/#contrast-ratiodef> and
60+
// <https://material.io/go/design-theming#color-color-palette>.
61+
const gdouble kThreshold = 0.15;
62+
if ((relative_luminance + 0.05) * (relative_luminance + 0.05) > kThreshold)
63+
return Brightness::Light;
64+
return Brightness::Dark;
65+
}
66+
67+
static bool is_dark_theme() {
68+
// GTK doesn't have a specific flag for dark themes, so we check if the
69+
// style text color is light or dark
70+
GList* windows = gtk_window_list_toplevels();
71+
if (windows == nullptr)
72+
return false;
73+
74+
GtkWidget* window = GTK_WIDGET(windows->data);
75+
g_list_free(windows);
76+
77+
GdkRGBA text_color;
78+
GtkStyleContext* style = gtk_widget_get_style_context(window);
79+
gtk_style_context_get_color(style, GTK_STATE_FLAG_NORMAL, &text_color);
80+
return estimate_brightness_for_color(&text_color) == Brightness::Light;
81+
}
82+
3583
// Sends the current settings to the Flutter engine.
3684
static void update_settings(FlSettingsPlugin* self) {
3785
gdouble scaling_factor = 1.0;
@@ -44,15 +92,10 @@ static void update_settings(FlSettingsPlugin* self) {
4492
g_autofree gchar* clock_format =
4593
g_settings_get_string(self->interface_settings, kDesktopClockFormatKey);
4694
always_use_24hr = g_strcmp0(clock_format, kClockFormat24Hour) == 0;
95+
}
4796

48-
// GTK doesn't have a specific flag for dark themes, so we have some
49-
// hard-coded themes for Ubuntu (Yaru) and GNOME (Adwaita).
50-
g_autofree gchar* gtk_theme =
51-
g_settings_get_string(self->interface_settings, kDesktopGtkThemeKey);
52-
if (g_strcmp0(gtk_theme, "Yaru-dark") == 0 ||
53-
g_strcmp0(gtk_theme, "Adwaita-dark") == 0) {
54-
platform_brightness = kPlatformBrightnessDark;
55-
}
97+
if (is_dark_theme()) {
98+
platform_brightness = kPlatformBrightnessDark;
5699
}
57100

58101
g_autoptr(FlValue) message = fl_value_new_map();

0 commit comments

Comments
 (0)