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";
1719static constexpr char kPlatformBrightnessDark [] = " dark" ;
1820
1921static constexpr char kDesktopInterfaceSchema [] = " org.gnome.desktop.interface" ;
20- static constexpr char kDesktopGtkThemeKey [] = " gtk-theme" ;
2122static constexpr char kDesktopTextScalingFactorKey [] = " text-scaling-factor" ;
2223static constexpr char kDesktopClockFormatKey [] = " clock-format" ;
2324static constexpr char kClockFormat24Hour [] = " 24h" ;
2425
26+ enum class Brightness { Light, Dark };
27+
2528struct _FlSettingsPlugin {
2629 GObject parent_instance;
2730
@@ -32,6 +35,51 @@ struct _FlSettingsPlugin {
3235
3336G_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.
3684static 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