Skip to content

Commit

Permalink
theme: Allow using custom colors from the GTK+ theme
Browse files Browse the repository at this point in the history
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

NOTE: Patch copied from mutter and adapted for metacity.
  • Loading branch information
fmuellner authored and vkareh committed Aug 28, 2018
1 parent ed5eff6 commit 18bfff3
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 2 deletions.
12 changes: 12 additions & 0 deletions doc/theme-format.txt
Expand Up @@ -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 <name> refers to a custom color defined with @define-color in
the GTK+ theme, and <fallback> provides an alternative color definition
in case the color referenced by <name> is not found.

New Features in Theme Format Version 3.3
========================================

Expand Down
2 changes: 1 addition & 1 deletion src/ui/theme-parser.c
Expand Up @@ -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 MARCO_THEME_FILENAME_FORMAT "metacity-theme-%d.xml"
Expand Down
91 changes: 90 additions & 1 deletion src/ui/theme.c
Expand Up @@ -1096,6 +1096,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;
Expand Down Expand Up @@ -1127,6 +1131,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);
Expand All @@ -1153,7 +1165,67 @@ 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;
Expand Down Expand Up @@ -1497,6 +1569,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 *style,
Expand All @@ -1519,6 +1601,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,
style,
spec->data.gtkcustom.color_name,
spec->data.gtkcustom.fallback);
break;

case META_COLOR_SPEC_BLEND:
{
GdkRGBA bg, fg;
Expand Down
5 changes: 5 additions & 0 deletions src/ui/theme.h
Expand Up @@ -232,6 +232,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;
Expand Down Expand Up @@ -261,6 +262,10 @@ struct _MetaColorSpec
MetaGtkColorComponent component;
GtkStateFlags state;
} gtk;
struct {
char *color_name;
MetaColorSpec *fallback;
} gtkcustom;
struct {
MetaColorSpec *foreground;
MetaColorSpec *background;
Expand Down

0 comments on commit 18bfff3

Please sign in to comment.