| 27 static gboolean dark_mode_cached_value = FALSE; |
27 static gboolean dark_mode_cached_value = FALSE; |
| 28 |
28 |
| 29 /****************************************************************************** |
29 /****************************************************************************** |
| 30 * Public API |
30 * Public API |
| 31 *****************************************************************************/ |
31 *****************************************************************************/ |
| |
32 void |
| |
33 pidgin_style_context_get_background_color(GdkRGBA *color) { |
| |
34 /* This value will leak, we could put a shutdown function in but right now |
| |
35 * that seems like a bit much for a few bytes. |
| |
36 */ |
| |
37 static GdkRGBA *background = NULL; |
| |
38 |
| |
39 if(g_once_init_enter(&background)) { |
| |
40 GdkRGBA *bg = NULL; |
| |
41 GtkStyleContext *context = NULL; |
| |
42 GtkWidget *window = NULL; |
| |
43 |
| |
44 /* We create a window to get its background color from its style |
| |
45 * context. This _is_ doable without creating a window, but you still |
| |
46 * need the window class and about four times as much code, so that's |
| |
47 * why we do it this way. |
| |
48 */ |
| |
49 window = gtk_window_new(GTK_WINDOW_TOPLEVEL); |
| |
50 context = gtk_widget_get_style_context(window); |
| |
51 |
| |
52 gtk_style_context_get(context, GTK_STATE_FLAG_NORMAL, |
| |
53 GTK_STYLE_PROPERTY_BACKGROUND_COLOR, &bg, |
| |
54 NULL); |
| |
55 g_object_unref(G_OBJECT(window)); |
| |
56 |
| |
57 g_once_init_leave(&background, bg); |
| |
58 } |
| |
59 |
| |
60 *color = *background; |
| |
61 } |
| |
62 |
| 32 gboolean |
63 gboolean |
| 33 pidgin_style_context_is_dark(GtkStyleContext *context) { |
64 pidgin_style_context_is_dark(void) { |
| 34 GdkRGBA bg; |
65 GdkRGBA bg; |
| 35 gdouble luminance = 0.0; |
66 gdouble luminance = 0.0; |
| 36 |
67 |
| 37 if(context == NULL) { |
68 if(dark_mode_have_cache) { |
| 38 if(dark_mode_have_cache) { |
69 return dark_mode_cached_value; |
| 39 return dark_mode_cached_value; |
|
| 40 } |
|
| 41 |
|
| 42 context = gtk_style_context_new(); |
|
| 43 } else { |
|
| 44 g_object_ref(G_OBJECT(context)); |
|
| 45 } |
70 } |
| 46 |
71 |
| 47 gtk_style_context_get(context, GTK_STATE_FLAG_NORMAL, |
72 pidgin_style_context_get_background_color(&bg); |
| 48 GTK_STYLE_PROPERTY_BACKGROUND_COLOR, &bg, |
|
| 49 NULL); |
|
| 50 g_object_unref(G_OBJECT(context)); |
|
| 51 |
73 |
| 52 /* magic values are taken from https://en.wikipedia.org/wiki/Luma_(video) |
74 /* 709 coefficients from https://en.wikipedia.org/wiki/Luma_(video) */ |
| 53 * Rec._601_luma_versus_Rec._709_luma_coefficients. |
75 luminance = (0.2126 * bg.red) + (0.7152 * bg.green) + (0.0722 * bg.blue); |
| 54 */ |
|
| 55 luminance = (0.299 * bg.red) + (0.587 * bg.green) + (0.114 * bg.blue); |
|
| 56 |
76 |
| 57 dark_mode_cached_value = (luminance < 0x7FFF); |
77 dark_mode_cached_value = (luminance < 0.5); |
| 58 dark_mode_have_cache = TRUE; |
78 dark_mode_have_cache = TRUE; |
| 59 |
79 |
| 60 return dark_mode_cached_value; |
80 return dark_mode_cached_value; |
| 61 } |
81 } |
| 62 |
|
| 63 void |
|
| 64 pidgin_style_context_adjust_contrast(GtkStyleContext *context, GdkRGBA *rgba) { |
|
| 65 if(pidgin_style_context_is_dark(context)) { |
|
| 66 gdouble h, s, v; |
|
| 67 |
|
| 68 gtk_rgb_to_hsv(rgba->red, rgba->green, rgba->blue, &h, &s, &v); |
|
| 69 |
|
| 70 v += 0.3; |
|
| 71 v = v > 1.0 ? 1.0 : v; |
|
| 72 s = 0.7; |
|
| 73 |
|
| 74 gtk_hsv_to_rgb(h, s, v, &rgba->red, &rgba->green, &rgba->blue); |
|
| 75 } |
|
| 76 } |
|