From 54b2fab849dee46c55314edaaae048886a5d335c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Wed, 4 May 2011 16:13:55 +0200 Subject: [PATCH] theme: Allow using custom colors from the GTK+ theme Add an additional color type to pick up colors defined with @define-color in the GTK+ theme's CSS: gtk:custom(name,fallback) (where "name" refers to the name defined in GTK+'s CSS, and fallback refers to an alternative color spec which is used when the color referenced by "name" is not found) The main intent of the change is to allow designers to improve Adwaita's dark theme variant without having to compromise on colors which work in the light variant as well. https://bugzilla.gnome.org/show_bug.cgi?id=648709 --- doc/theme-format.txt | 12 ++++++ src/ui/theme-parser.c | 2 +- src/ui/theme-private.h | 5 +++ src/ui/theme.c | 92 +++++++++++++++++++++++++++++++++++++++++- 4 files changed, 109 insertions(+), 2 deletions(-) diff --git a/doc/theme-format.txt b/doc/theme-format.txt index 52e409988..2a58e3550 100644 --- a/doc/theme-format.txt +++ b/doc/theme-format.txt @@ -22,6 +22,18 @@ This document has separate sections for each format version. You may want to read the document in reverse order, since the base features are discussed under version 1. +New Features in Theme Format Version 3.4 +======================================== + +An additional color type is added to pick up custom colors defined +in the GTK+ theme's CSS: + + gtk:custom(name,fallback) + +where refers to a custom color defined with @define-color in +the GTK+ theme, and provides an alternative color definition +in case the color referenced by is not found. + New Features in Theme Format Version 3.3 ======================================== diff --git a/src/ui/theme-parser.c b/src/ui/theme-parser.c index 36056acdb..906354122 100644 --- a/src/ui/theme-parser.c +++ b/src/ui/theme-parser.c @@ -38,7 +38,7 @@ * look out for. */ #define THEME_MAJOR_VERSION 3 -#define THEME_MINOR_VERSION 3 +#define THEME_MINOR_VERSION 4 #define THEME_VERSION (1000 * THEME_MAJOR_VERSION + THEME_MINOR_VERSION) #define METACITY_THEME_FILENAME_FORMAT "metacity-theme-%d.xml" diff --git a/src/ui/theme-private.h b/src/ui/theme-private.h index 015a88919..73f6fcd3e 100644 --- a/src/ui/theme-private.h +++ b/src/ui/theme-private.h @@ -281,6 +281,7 @@ typedef enum { META_COLOR_SPEC_BASIC, META_COLOR_SPEC_GTK, + META_COLOR_SPEC_GTK_CUSTOM, META_COLOR_SPEC_BLEND, META_COLOR_SPEC_SHADE } MetaColorSpecType; @@ -310,6 +311,10 @@ struct _MetaColorSpec MetaGtkColorComponent component; GtkStateFlags state; } gtk; + struct { + char *color_name; + MetaColorSpec *fallback; + } gtkcustom; struct { MetaColorSpec *foreground; MetaColorSpec *background; diff --git a/src/ui/theme.c b/src/ui/theme.c index 10889984b..7dedc6b22 100644 --- a/src/ui/theme.c +++ b/src/ui/theme.c @@ -1118,6 +1118,10 @@ meta_color_spec_new (MetaColorSpecType type) size += sizeof (dummy.data.gtk); break; + case META_COLOR_SPEC_GTK_CUSTOM: + size += sizeof (dummy.data.gtkcustom); + break; + case META_COLOR_SPEC_BLEND: size += sizeof (dummy.data.blend); break; @@ -1149,6 +1153,14 @@ meta_color_spec_free (MetaColorSpec *spec) DEBUG_FILL_STRUCT (&spec->data.gtk); break; + case META_COLOR_SPEC_GTK_CUSTOM: + if (spec->data.gtkcustom.color_name) + g_free (spec->data.gtkcustom.color_name); + if (spec->data.gtkcustom.fallback) + meta_color_spec_free (spec->data.gtkcustom.fallback); + DEBUG_FILL_STRUCT (&spec->data.gtkcustom); + break; + case META_COLOR_SPEC_BLEND: if (spec->data.blend.foreground) meta_color_spec_free (spec->data.blend.foreground); @@ -1179,7 +1191,68 @@ meta_color_spec_new_from_string (const char *str, spec = NULL; - if (str[0] == 'g' && str[1] == 't' && str[2] == 'k' && str[3] == ':') + if (str[0] == 'g' && str[1] == 't' && str[2] == 'k' && str[3] == ':' && + str[4] == 'c' && str[5] == 'u' && str[6] == 's' && str[7] == 't' && + str[8] == 'o' && str[9] == 'm') + { + const char *color_name_start, *fallback_str_start, *end; + char *color_name, *fallback_str; + MetaColorSpec *fallback = NULL; + + if (str[10] != '(') + { + g_set_error (err, META_THEME_ERROR, + META_THEME_ERROR_FAILED, + _("GTK custom color specification must have color name and fallback in parentheses, e.g. gtk:custom(foo,bar); could not parse \"%s\""), + str); + return NULL; + } + + color_name_start = str + 11; + + fallback_str_start = color_name_start; + while (*fallback_str_start && *fallback_str_start != ',') + { + if (!(g_ascii_isalnum (*fallback_str_start) + || *fallback_str_start == '-' + || *fallback_str_start == '_')) + { + g_set_error (err, META_THEME_ERROR, + META_THEME_ERROR_FAILED, + _("Invalid character '%c' in color_name parameter of gtk:custom, only A-Za-z0-9-_ are valid"), + *fallback_str_start); + return NULL; + } + fallback_str_start++; + } + fallback_str_start++; + + end = strrchr (str, ')'); + + if (color_name_start == NULL || fallback_str_start == NULL || end == NULL) + { + g_set_error (err, META_THEME_ERROR, + META_THEME_ERROR_FAILED, + _("Gtk:custom format is \"gtk:custom(color_name,fallback)\", \"%s\" does not fit the format"), + str); + return NULL; + } + + fallback_str = g_strndup (fallback_str_start, end - fallback_str_start); + fallback = meta_color_spec_new_from_string (fallback_str, err); + g_free (fallback_str); + + if (fallback == NULL) + return NULL; + + color_name = g_strndup (color_name_start, + fallback_str_start - color_name_start - 1); + + spec = meta_color_spec_new (META_COLOR_SPEC_GTK_CUSTOM); + spec->data.gtkcustom.color_name = color_name; + spec->data.gtkcustom.fallback = fallback; + } + else if (str[0] == 'g' && str[1] == 't' && str[2] == 'k' && str[3] == ':') { /* GTK color */ const char *bracket; @@ -1479,6 +1552,16 @@ meta_set_color_from_style (GdkRGBA *color, } } +static void +meta_set_custom_color_from_style (GdkRGBA *color, + GtkStyleContext *context, + char *color_name, + MetaColorSpec *fallback) +{ + if (!gtk_style_context_lookup_color (context, color_name, color)) + meta_color_spec_render (fallback, context, color); +} + void meta_color_spec_render (MetaColorSpec *spec, GtkStyleContext *context, @@ -1500,6 +1583,13 @@ meta_color_spec_render (MetaColorSpec *spec, spec->data.gtk.component); break; + case META_COLOR_SPEC_GTK_CUSTOM: + meta_set_custom_color_from_style (color, + context, + spec->data.gtkcustom.color_name, + spec->data.gtkcustom.fallback); + break; + case META_COLOR_SPEC_BLEND: { GdkRGBA bg, fg;