4
4
5
5
#include " flutter/shell/platform/linux/fl_settings_plugin.h"
6
6
7
- #include < cstring>
7
+ #include < gmodule.h>
8
+ #include < gtk/gtk.h>
9
+ #include < math.h>
8
10
9
11
#include " flutter/shell/platform/linux/public/flutter_linux/fl_basic_message_channel.h"
10
12
#include " flutter/shell/platform/linux/public/flutter_linux/fl_json_message_codec.h"
@@ -17,11 +19,12 @@ static constexpr char kPlatformBrightnessLight[] = "light";
17
19
static constexpr char kPlatformBrightnessDark [] = " dark" ;
18
20
19
21
static constexpr char kDesktopInterfaceSchema [] = " org.gnome.desktop.interface" ;
20
- static constexpr char kDesktopGtkThemeKey [] = " gtk-theme" ;
21
22
static constexpr char kDesktopTextScalingFactorKey [] = " text-scaling-factor" ;
22
23
static constexpr char kDesktopClockFormatKey [] = " clock-format" ;
23
24
static constexpr char kClockFormat24Hour [] = " 24h" ;
24
25
26
+ enum class Brightness { Light, Dark };
27
+
25
28
struct _FlSettingsPlugin {
26
29
GObject parent_instance;
27
30
@@ -32,6 +35,51 @@ struct _FlSettingsPlugin {
32
35
33
36
G_DEFINE_TYPE (FlSettingsPlugin, fl_settings_plugin, G_TYPE_OBJECT)
34
37
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
+
35
83
// Sends the current settings to the Flutter engine.
36
84
static void update_settings (FlSettingsPlugin* self) {
37
85
gdouble scaling_factor = 1.0 ;
@@ -44,15 +92,10 @@ static void update_settings(FlSettingsPlugin* self) {
44
92
g_autofree gchar* clock_format =
45
93
g_settings_get_string (self->interface_settings , kDesktopClockFormatKey );
46
94
always_use_24hr = g_strcmp0 (clock_format, kClockFormat24Hour ) == 0 ;
95
+ }
47
96
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 ;
56
99
}
57
100
58
101
g_autoptr (FlValue) message = fl_value_new_map ();
0 commit comments