[metacity] libmetacity: add meta-color-spec.[c/h]



commit 3c382734b75c27a6070cb8273dccb21f0355b5cd
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date:   Wed Jan 27 23:08:32 2016 +0200

    libmetacity: add meta-color-spec.[c/h]

 libmetacity/Makefile.am          |    3 +
 libmetacity/meta-color-private.h |   33 ++
 libmetacity/meta-color-spec.c    |  633 ++++++++++++++++++++++++++++++++++++++
 libmetacity/meta-color-spec.h    |   48 +++
 libmetacity/meta-color.c         |    1 +
 libmetacity/meta-color.h         |    4 -
 po/POTFILES.in                   |    2 +-
 src/ui/theme-private.h           |   69 +----
 src/ui/theme.c                   |  571 ----------------------------------
 9 files changed, 721 insertions(+), 643 deletions(-)
---
diff --git a/libmetacity/Makefile.am b/libmetacity/Makefile.am
index 8f89d6a..f2a3e7f 100644
--- a/libmetacity/Makefile.am
+++ b/libmetacity/Makefile.am
@@ -5,6 +5,9 @@ noinst_LTLIBRARIES = libmetacity.la
 libmetacity_la_SOURCES = \
        meta-color.c \
        meta-color.h \
+       meta-color-private.h \
+       meta-color-spec.c \
+       meta-color-spec.h \
        meta-hsla.c \
        meta-hsla.h \
        meta-theme.c \
diff --git a/libmetacity/meta-color-private.h b/libmetacity/meta-color-private.h
new file mode 100644
index 0000000..0e41116
--- /dev/null
+++ b/libmetacity/meta-color-private.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2001 Havoc Pennington
+ * Copyright (C) 2016 Alberts Muktupāvels
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef META_COLOR_PRIVATE_H
+#define META_COLOR_PRIVATE_H
+
+#include <gdk/gdk.h>
+
+G_BEGIN_DECLS
+
+G_GNUC_INTERNAL
+void meta_color_shade (const GdkRGBA *source,
+                       const gdouble  factor,
+                       GdkRGBA       *destination);
+
+G_END_DECLS
+
+#endif
diff --git a/libmetacity/meta-color-spec.c b/libmetacity/meta-color-spec.c
new file mode 100644
index 0000000..5561f71
--- /dev/null
+++ b/libmetacity/meta-color-spec.c
@@ -0,0 +1,633 @@
+/*
+ * Copyright (C) 2001 Havoc Pennington
+ * Copyright (C) 2016 Alberts Muktupāvels
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n-lib.h>
+
+#include "meta-color.h"
+#include "meta-color-private.h"
+#include "meta-color-spec.h"
+#include "meta-theme.h"
+
+enum _MetaColorSpecType
+{
+  META_COLOR_SPEC_BASIC,
+  META_COLOR_SPEC_GTK,
+  META_COLOR_SPEC_GTK_CUSTOM,
+  META_COLOR_SPEC_BLEND,
+  META_COLOR_SPEC_SHADE
+};
+
+enum _MetaGtkColorComponent
+{
+  META_GTK_COLOR_FG,
+  META_GTK_COLOR_BG,
+  META_GTK_COLOR_LIGHT,
+  META_GTK_COLOR_DARK,
+  META_GTK_COLOR_MID,
+  META_GTK_COLOR_TEXT,
+  META_GTK_COLOR_BASE,
+  META_GTK_COLOR_TEXT_AA,
+  META_GTK_COLOR_LAST
+};
+
+struct _MetaColorSpec
+{
+  MetaColorSpecType type;
+  union
+  {
+    struct {
+      GdkRGBA color;
+    } basic;
+    struct {
+      MetaGtkColorComponent component;
+      GtkStateFlags         state;
+    } gtk;
+    struct {
+      gchar         *color_name;
+      MetaColorSpec *fallback;
+    } gtkcustom;
+    struct {
+      MetaColorSpec *foreground;
+      MetaColorSpec *background;
+      gdouble        alpha;
+
+      GdkRGBA        color;
+    } blend;
+    struct {
+      MetaColorSpec *base;
+      gdouble        factor;
+
+      GdkRGBA        color;
+    } shade;
+  } data;
+};
+
+static void
+set_color_from_style (GdkRGBA               *color,
+                      GtkStyleContext       *context,
+                      GtkStateFlags          state,
+                      MetaGtkColorComponent  component)
+{
+  GdkRGBA other;
+
+  gtk_style_context_set_state (context, state);
+
+  switch (component)
+    {
+      case META_GTK_COLOR_BG:
+      case META_GTK_COLOR_BASE:
+        meta_color_get_background_color (context, state, color);
+        break;
+
+      case META_GTK_COLOR_FG:
+      case META_GTK_COLOR_TEXT:
+        gtk_style_context_get_color (context, state, color);
+        break;
+
+      case META_GTK_COLOR_TEXT_AA:
+        gtk_style_context_get_color (context, state, color);
+        set_color_from_style (&other, context, state, META_GTK_COLOR_BASE);
+
+        color->red = (color->red + other.red) / 2;
+        color->green = (color->green + other.green) / 2;
+        color->blue = (color->blue + other.blue) / 2;
+        break;
+
+      case META_GTK_COLOR_MID:
+        meta_color_get_light_color (context, state, color);
+        meta_color_get_dark_color (context, state, &other);
+
+        color->red = (color->red + other.red) / 2;
+        color->green = (color->green + other.green) / 2;
+        color->blue = (color->blue + other.blue) / 2;
+        break;
+
+      case META_GTK_COLOR_LIGHT:
+        meta_color_get_light_color (context, state, color);
+        break;
+
+      case META_GTK_COLOR_DARK:
+        meta_color_get_dark_color (context, state, color);
+        break;
+
+      case META_GTK_COLOR_LAST:
+      default:
+        g_assert_not_reached ();
+        break;
+    }
+}
+
+static void
+color_composite (const GdkRGBA *bg,
+                 const GdkRGBA *fg,
+                 gdouble        alpha,
+                 GdkRGBA       *color)
+{
+  *color = *bg;
+
+  color->red = color->red + (fg->red - color->red) * alpha;
+  color->green = color->green + (fg->green - color->green) * alpha;
+  color->blue = color->blue + (fg->blue - color->blue) * alpha;
+  color->alpha = color->alpha + (fg->alpha - color->alpha) * alpha;
+}
+
+static void
+set_custom_color_from_style (GdkRGBA         *color,
+                             GtkStyleContext *context,
+                             const gchar     *color_name,
+                             MetaColorSpec   *fallback)
+{
+  if (!gtk_style_context_lookup_color (context, color_name, color))
+    meta_color_spec_render (fallback, context, color);
+}
+
+static MetaGtkColorComponent
+meta_color_component_from_string (const gchar *str)
+{
+  if (strcmp ("fg", str) == 0)
+    return META_GTK_COLOR_FG;
+  else if (strcmp ("bg", str) == 0)
+    return META_GTK_COLOR_BG;
+  else if (strcmp ("light", str) == 0)
+    return META_GTK_COLOR_LIGHT;
+  else if (strcmp ("dark", str) == 0)
+    return META_GTK_COLOR_DARK;
+  else if (strcmp ("mid", str) == 0)
+    return META_GTK_COLOR_MID;
+  else if (strcmp ("text", str) == 0)
+    return META_GTK_COLOR_TEXT;
+  else if (strcmp ("base", str) == 0)
+    return META_GTK_COLOR_BASE;
+  else if (strcmp ("text_aa", str) == 0)
+    return META_GTK_COLOR_TEXT_AA;
+  else
+    return META_GTK_COLOR_LAST;
+}
+
+MetaColorSpec *
+meta_color_spec_new (MetaColorSpecType type)
+{
+  MetaColorSpec *spec;
+  MetaColorSpec dummy;
+  gint size;
+
+  size = G_STRUCT_OFFSET (MetaColorSpec, data);
+
+  switch (type)
+    {
+      case META_COLOR_SPEC_BASIC:
+        size += sizeof (dummy.data.basic);
+        break;
+
+      case META_COLOR_SPEC_GTK:
+        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;
+
+      case META_COLOR_SPEC_SHADE:
+        size += sizeof (dummy.data.shade);
+        break;
+
+      default:
+        break;
+    }
+
+  spec = g_malloc0 (size);
+
+  spec->type = type;
+
+  return spec;
+}
+
+MetaColorSpec *
+meta_color_spec_new_from_string (const gchar  *str,
+                                 GError      **error)
+{
+  MetaColorSpec *spec;
+
+  spec = NULL;
+
+  if (strncmp (str, "gtk:custom", 10) == 0)
+    {
+      MetaColorSpec *fallback;
+      static gboolean debug_set;
+      static gboolean debug;
+      const gchar *color_name_start;
+      const gchar *fallback_str_start;
+      const gchar *end;
+      gchar *color_name;
+
+      fallback = NULL;
+
+      if (!debug_set)
+        {
+          debug = g_getenv ("METACITY_DISABLE_FALLBACK_COLOR") != NULL;
+          debug_set = TRUE;
+        }
+
+      if (str[10] != '(')
+        {
+          g_set_error (error, 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 (error, 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 (error, 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;
+        }
+
+      if (!debug)
+        {
+          gchar *fallback_str;
+          fallback_str = g_strndup (fallback_str_start, end - fallback_str_start);
+          fallback = meta_color_spec_new_from_string (fallback_str, error);
+          g_free (fallback_str);
+        }
+      else
+        {
+          fallback = meta_color_spec_new_from_string ("pink", error);
+        }
+
+      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 (strncmp (str, "gtk:", 4) == 0)
+    {
+      const gchar *bracket;
+      const gchar *end_bracket;
+      gchar *tmp;
+      GtkStateFlags state;
+      MetaGtkColorComponent component;
+
+      bracket = str;
+      while (*bracket && *bracket != '[')
+        ++bracket;
+
+      if (*bracket == '\0')
+        {
+          g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
+                       _("GTK color specification must have the state in brackets, e.g. gtk:fg[NORMAL] where 
NORMAL is the state; could not parse '%s'"),
+                       str);
+          return NULL;
+        }
+
+      end_bracket = bracket;
+      ++end_bracket;
+      while (*end_bracket && *end_bracket != ']')
+        ++end_bracket;
+
+      if (*end_bracket == '\0')
+        {
+          g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
+                       _("GTK color specification must have a close bracket after the state, e.g. 
gtk:fg[NORMAL] where NORMAL is the state; could not parse '%s'"),
+                       str);
+          return NULL;
+        }
+
+      tmp = g_strndup (bracket + 1, end_bracket - bracket - 1);
+      state = meta_gtk_state_from_string (tmp);
+      if (((int) state) == -1)
+        {
+          g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
+                       _("Did not understand state '%s' in color specification"),
+                       tmp);
+          g_free (tmp);
+          return NULL;
+        }
+      g_free (tmp);
+
+      tmp = g_strndup (str + 4, bracket - str - 4);
+      component = meta_color_component_from_string (tmp);
+      if (component == META_GTK_COLOR_LAST)
+        {
+          g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
+                       _("Did not understand color component '%s' in color specification"),
+                       tmp);
+          g_free (tmp);
+          return NULL;
+        }
+      g_free (tmp);
+
+      spec = meta_color_spec_new (META_COLOR_SPEC_GTK);
+      spec->data.gtk.state = state;
+      spec->data.gtk.component = component;
+      g_assert (spec->data.gtk.component < META_GTK_COLOR_LAST);
+    }
+  else if (strncmp (str, "blend/", 6) == 0)
+    {
+      gchar **split;
+      gdouble alpha;
+      gchar *end;
+      MetaColorSpec *fg;
+      MetaColorSpec *bg;
+
+      split = g_strsplit (str, "/", 4);
+
+      if (split[0] == NULL || split[1] == NULL ||
+          split[2] == NULL || split[3] == NULL)
+        {
+          g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
+                       _("Blend format is 'blend/bg_color/fg_color/alpha', '%s' does not fit the format"),
+                       str);
+          g_strfreev (split);
+          return NULL;
+        }
+
+      alpha = g_ascii_strtod (split[3], &end);
+      if (end == split[3])
+        {
+          g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
+                       _("Could not parse alpha value '%s' in blended color"),
+                       split[3]);
+          g_strfreev (split);
+          return NULL;
+        }
+
+      if (alpha < (0.0 - 1e6) || alpha > (1.0 + 1e6))
+        {
+          g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
+                       _("Alpha value '%s' in blended color is not between 0.0 and 1.0"),
+                       split[3]);
+          g_strfreev (split);
+          return NULL;
+        }
+
+      fg = NULL;
+      bg = NULL;
+
+      bg = meta_color_spec_new_from_string (split[1], error);
+      if (bg == NULL)
+        {
+          g_strfreev (split);
+          return NULL;
+        }
+
+      fg = meta_color_spec_new_from_string (split[2], error);
+      if (fg == NULL)
+        {
+          meta_color_spec_free (bg);
+          g_strfreev (split);
+          return NULL;
+        }
+
+      g_strfreev (split);
+
+      spec = meta_color_spec_new (META_COLOR_SPEC_BLEND);
+      spec->data.blend.alpha = alpha;
+      spec->data.blend.background = bg;
+      spec->data.blend.foreground = fg;
+    }
+  else if (strncmp (str, "shade/", 6) == 0)
+    {
+      gchar **split;
+      gdouble factor;
+      gchar *end;
+      MetaColorSpec *base;
+
+      split = g_strsplit (str, "/", 3);
+
+      if (split[0] == NULL || split[1] == NULL || split[2] == NULL)
+        {
+          g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
+                       _("Shade format is 'shade/base_color/factor', '%s' does not fit the format"),
+                       str);
+          g_strfreev (split);
+          return NULL;
+        }
+
+      factor = g_ascii_strtod (split[2], &end);
+      if (end == split[2])
+        {
+          g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
+                       _("Could not parse shade factor '%s' in shaded color"),
+                       split[2]);
+          g_strfreev (split);
+          return NULL;
+        }
+
+      if (factor < (0.0 - 1e6))
+        {
+          g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
+                       _("Shade factor '%s' in shaded color is negative"),
+                       split[2]);
+          g_strfreev (split);
+          return NULL;
+        }
+
+      base = meta_color_spec_new_from_string (split[1], error);
+      if (base == NULL)
+        {
+          g_strfreev (split);
+          return NULL;
+        }
+
+      g_strfreev (split);
+
+      spec = meta_color_spec_new (META_COLOR_SPEC_SHADE);
+      spec->data.shade.factor = factor;
+      spec->data.shade.base = base;
+    }
+  else
+    {
+      spec = meta_color_spec_new (META_COLOR_SPEC_BASIC);
+
+      if (!gdk_rgba_parse (&spec->data.basic.color, str))
+        {
+          g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
+                       _("Could not parse color '%s'"), str);
+          meta_color_spec_free (spec);
+          return NULL;
+        }
+    }
+
+  g_assert (spec);
+
+  return spec;
+}
+
+MetaColorSpec *
+meta_color_spec_new_gtk (MetaGtkColorComponent component,
+                         GtkStateFlags         state)
+{
+  MetaColorSpec *spec;
+
+  spec = meta_color_spec_new (META_COLOR_SPEC_GTK);
+
+  spec->data.gtk.component = component;
+  spec->data.gtk.state = state;
+
+  return spec;
+}
+
+void
+meta_color_spec_free (MetaColorSpec *spec)
+{
+  g_return_if_fail (spec != NULL);
+
+  switch (spec->type)
+    {
+      case META_COLOR_SPEC_BASIC:
+        break;
+
+      case META_COLOR_SPEC_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);
+        break;
+
+      case META_COLOR_SPEC_BLEND:
+        if (spec->data.blend.foreground)
+          meta_color_spec_free (spec->data.blend.foreground);
+        if (spec->data.blend.background)
+          meta_color_spec_free (spec->data.blend.background);
+        break;
+
+      case META_COLOR_SPEC_SHADE:
+        if (spec->data.shade.base)
+          meta_color_spec_free (spec->data.shade.base);
+        break;
+
+      default:
+        break;
+    }
+
+  g_free (spec);
+}
+
+void
+meta_color_spec_render (MetaColorSpec   *spec,
+                        GtkStyleContext *context,
+                        GdkRGBA         *color)
+{
+  g_return_if_fail (spec != NULL);
+  g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
+
+  switch (spec->type)
+    {
+      case META_COLOR_SPEC_BASIC:
+        *color = spec->data.basic.color;
+        break;
+
+      case META_COLOR_SPEC_GTK:
+        set_color_from_style (color, context, spec->data.gtk.state,
+                              spec->data.gtk.component);
+        break;
+
+      case META_COLOR_SPEC_GTK_CUSTOM:
+        set_custom_color_from_style (color, context,
+                                     spec->data.gtkcustom.color_name,
+                                     spec->data.gtkcustom.fallback);
+        break;
+
+      case META_COLOR_SPEC_BLEND:
+        {
+          GdkRGBA bg;
+          GdkRGBA fg;
+
+          meta_color_spec_render (spec->data.blend.background, context, &bg);
+          meta_color_spec_render (spec->data.blend.foreground, context, &fg);
+
+          color_composite (&bg, &fg, spec->data.blend.alpha,
+                           &spec->data.blend.color);
+
+          *color = spec->data.blend.color;
+        }
+        break;
+
+      case META_COLOR_SPEC_SHADE:
+        {
+          meta_color_spec_render (spec->data.shade.base, context,
+                                  &spec->data.shade.color);
+
+          meta_color_shade (&spec->data.shade.color, spec->data.shade.factor,
+                            &spec->data.shade.color);
+
+          *color = spec->data.shade.color;
+        }
+        break;
+
+      default:
+        break;
+    }
+}
+
+GtkStateFlags
+meta_gtk_state_from_string (const gchar *str)
+{
+  if (g_ascii_strcasecmp ("normal", str) == 0)
+    return GTK_STATE_FLAG_NORMAL;
+  else if (g_ascii_strcasecmp ("prelight", str) == 0)
+    return GTK_STATE_FLAG_PRELIGHT;
+  else if (g_ascii_strcasecmp ("active", str) == 0)
+    return GTK_STATE_FLAG_ACTIVE;
+  else if (g_ascii_strcasecmp ("selected", str) == 0)
+    return GTK_STATE_FLAG_SELECTED;
+  else if (g_ascii_strcasecmp ("insensitive", str) == 0)
+    return GTK_STATE_FLAG_INSENSITIVE;
+  else if (g_ascii_strcasecmp ("inconsistent", str) == 0)
+    return GTK_STATE_FLAG_INCONSISTENT;
+  else if (g_ascii_strcasecmp ("focused", str) == 0)
+    return GTK_STATE_FLAG_FOCUSED;
+  else if (g_ascii_strcasecmp ("backdrop", str) == 0)
+    return GTK_STATE_FLAG_BACKDROP;
+  else
+    return -1;
+}
diff --git a/libmetacity/meta-color-spec.h b/libmetacity/meta-color-spec.h
new file mode 100644
index 0000000..fb4d2e5
--- /dev/null
+++ b/libmetacity/meta-color-spec.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2001 Havoc Pennington
+ * Copyright (C) 2016 Alberts Muktupāvels
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef META_COLOR_SPEC_H
+#define META_COLOR_SPEC_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+typedef enum _MetaColorSpecType MetaColorSpecType;
+typedef enum _MetaGtkColorComponent MetaGtkColorComponent;
+typedef struct _MetaColorSpec MetaColorSpec;
+
+MetaColorSpec *meta_color_spec_new             (MetaColorSpecType       type);
+
+MetaColorSpec *meta_color_spec_new_from_string (const gchar            *str,
+                                                GError                **error);
+
+MetaColorSpec *meta_color_spec_new_gtk         (MetaGtkColorComponent   component,
+                                                GtkStateFlags           state);
+
+void           meta_color_spec_free            (MetaColorSpec          *spec);
+
+void           meta_color_spec_render          (MetaColorSpec          *spec,
+                                                GtkStyleContext        *context,
+                                                GdkRGBA                *color);
+
+GtkStateFlags  meta_gtk_state_from_string      (const gchar            *str);
+
+G_END_DECLS
+
+#endif
diff --git a/libmetacity/meta-color.c b/libmetacity/meta-color.c
index 17fe213..ff64ecd 100644
--- a/libmetacity/meta-color.c
+++ b/libmetacity/meta-color.c
@@ -19,6 +19,7 @@
 #include "config.h"
 
 #include "meta-hsla.h"
+#include "meta-color-private.h"
 #include "meta-color.h"
 
 #define LIGHTNESS_MULT 1.3
diff --git a/libmetacity/meta-color.h b/libmetacity/meta-color.h
index effeb18..9b153d1 100644
--- a/libmetacity/meta-color.h
+++ b/libmetacity/meta-color.h
@@ -23,10 +23,6 @@
 
 G_BEGIN_DECLS
 
-void meta_color_shade                (const GdkRGBA   *source,
-                                      const gdouble    factor,
-                                      GdkRGBA         *destination);
-
 void meta_color_get_background_color (GtkStyleContext *context,
                                       GtkStateFlags    state,
                                       GdkRGBA         *color);
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 6e31bc4..d768852 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -1,5 +1,6 @@
 # List of source files containing translatable strings.
 # Please keep this file sorted alphabetically.
+libmetacity/meta-color-spec.c
 src/50-metacity-navigation.xml.in
 src/50-metacity-system.xml.in
 src/50-metacity-windows.xml.in
@@ -28,4 +29,3 @@ src/ui/resizepopup.c
 src/ui/theme.c
 src/ui/theme-parser.c
 src/ui/theme-viewer.c
-
diff --git a/src/ui/theme-private.h b/src/ui/theme-private.h
index 66df5a5..de73200 100644
--- a/src/ui/theme-private.h
+++ b/src/ui/theme-private.h
@@ -18,6 +18,8 @@
 #ifndef META_THEME_PRIVATE_H
 #define META_THEME_PRIVATE_H
 
+#include <libmetacity/meta-color-spec.h>
+
 #include "boxes.h"
 #include "gradient.h"
 #include "theme.h"
@@ -25,7 +27,6 @@
 G_BEGIN_DECLS
 
 typedef struct _MetaAlphaGradientSpec MetaAlphaGradientSpec;
-typedef struct _MetaColorSpec MetaColorSpec;
 typedef struct _MetaDrawInfo MetaDrawInfo;
 typedef struct _MetaDrawOp MetaDrawOp;
 typedef struct _MetaDrawOpList MetaDrawOpList;
@@ -335,60 +336,6 @@ struct _MetaDrawInfo
   const MetaFrameGeometry *fgeom;
 };
 
-typedef enum
-{
-  META_GTK_COLOR_FG,
-  META_GTK_COLOR_BG,
-  META_GTK_COLOR_LIGHT,
-  META_GTK_COLOR_DARK,
-  META_GTK_COLOR_MID,
-  META_GTK_COLOR_TEXT,
-  META_GTK_COLOR_BASE,
-  META_GTK_COLOR_TEXT_AA,
-  META_GTK_COLOR_LAST
-} MetaGtkColorComponent;
-
-typedef enum
-{
-  META_COLOR_SPEC_BASIC,
-  META_COLOR_SPEC_GTK,
-  META_COLOR_SPEC_GTK_CUSTOM,
-  META_COLOR_SPEC_BLEND,
-  META_COLOR_SPEC_SHADE
-} MetaColorSpecType;
-
-struct _MetaColorSpec
-{
-  MetaColorSpecType type;
-  union
-  {
-    struct {
-      GdkRGBA color;
-    } basic;
-    struct {
-      MetaGtkColorComponent component;
-      GtkStateFlags state;
-    } gtk;
-    struct {
-      char *color_name;
-      MetaColorSpec *fallback;
-    } gtkcustom;
-    struct {
-      MetaColorSpec *foreground;
-      MetaColorSpec *background;
-      double alpha;
-
-      GdkRGBA color;
-    } blend;
-    struct {
-      MetaColorSpec *base;
-      double factor;
-
-      GdkRGBA color;
-    } shade;
-  } data;
-};
-
 struct _MetaPositionExprEnv
 {
   MetaRectangle rect;
@@ -741,16 +688,6 @@ void                   meta_frame_layout_unref                 (MetaFrameLayout
 gboolean               meta_frame_layout_validate              (const MetaFrameLayout       *layout,
                                                                 GError                     **error);
 
-MetaColorSpec         *meta_color_spec_new                     (MetaColorSpecType            type);
-MetaColorSpec         *meta_color_spec_new_from_string         (const char                  *str,
-                                                                GError                     **err);
-MetaColorSpec         *meta_color_spec_new_gtk                 (MetaGtkColorComponent        component,
-                                                                GtkStateFlags                state);
-void                   meta_color_spec_free                    (MetaColorSpec               *spec);
-void                   meta_color_spec_render                  (MetaColorSpec               *spec,
-                                                                GtkStyleContext             *style_gtk,
-                                                                GdkRGBA                     *color);
-
 MetaDrawSpec          *meta_draw_spec_new                      (MetaTheme                   *theme,
                                                                 const char                  *expr,
                                                                 GError                     **error);
@@ -854,8 +791,6 @@ gboolean               meta_theme_lookup_color_constant        (MetaTheme
                                                                 const char                  *name,
                                                                 char                       **value);
 
-GtkStateFlags          meta_gtk_state_from_string              (const char                  *str);
-
 PangoFontDescription  *meta_gtk_widget_get_font_desc           (GtkWidget                   *widget,
                                                                 double                       scale,
                                                                 const PangoFontDescription  *override);
diff --git a/src/ui/theme.c b/src/ui/theme.c
index 946e73d..db630ec 100644
--- a/src/ui/theme.c
+++ b/src/ui/theme.c
@@ -162,19 +162,6 @@ colorize_pixbuf (GdkPixbuf *orig,
   return pixbuf;
 }
 
-static void
-color_composite (const GdkRGBA *bg,
-                 const GdkRGBA *fg,
-                 double         alpha,
-                 GdkRGBA       *color)
-{
-  *color = *bg;
-  color->red = color->red + (fg->red - color->red) * alpha;
-  color->green = color->green + (fg->green - color->green) * alpha;
-  color->blue = color->blue + (fg->blue - color->blue) * alpha;
-  color->alpha = color->alpha + (fg->alpha - color->alpha) * alpha;
-}
-
 /**
  * Sets all the fields of a border to dummy values.
  *
@@ -1265,541 +1252,6 @@ meta_alpha_gradient_spec_free (MetaAlphaGradientSpec *spec)
   g_free (spec);
 }
 
-MetaColorSpec*
-meta_color_spec_new (MetaColorSpecType type)
-{
-  MetaColorSpec *spec;
-  MetaColorSpec dummy;
-  int size;
-
-  size = G_STRUCT_OFFSET (MetaColorSpec, data);
-
-  switch (type)
-    {
-    case META_COLOR_SPEC_BASIC:
-      size += sizeof (dummy.data.basic);
-      break;
-
-    case META_COLOR_SPEC_GTK:
-      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;
-
-    case META_COLOR_SPEC_SHADE:
-      size += sizeof (dummy.data.shade);
-      break;
-
-    default:
-      break;
-    }
-
-  spec = g_malloc0 (size);
-
-  spec->type = type;
-
-  return spec;
-}
-
-void
-meta_color_spec_free (MetaColorSpec *spec)
-{
-  g_return_if_fail (spec != NULL);
-
-  switch (spec->type)
-    {
-    case META_COLOR_SPEC_BASIC:
-      DEBUG_FILL_STRUCT (&spec->data.basic);
-      break;
-
-    case META_COLOR_SPEC_GTK:
-      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);
-      if (spec->data.blend.background)
-        meta_color_spec_free (spec->data.blend.background);
-      DEBUG_FILL_STRUCT (&spec->data.blend);
-      break;
-
-    case META_COLOR_SPEC_SHADE:
-      if (spec->data.shade.base)
-        meta_color_spec_free (spec->data.shade.base);
-      DEBUG_FILL_STRUCT (&spec->data.shade);
-      break;
-
-    default:
-      break;
-    }
-
-  g_free (spec);
-}
-
-static MetaGtkColorComponent
-meta_color_component_from_string (const char *str)
-{
-  if (strcmp ("fg", str) == 0)
-    return META_GTK_COLOR_FG;
-  else if (strcmp ("bg", str) == 0)
-    return META_GTK_COLOR_BG;
-  else if (strcmp ("light", str) == 0)
-    return META_GTK_COLOR_LIGHT;
-  else if (strcmp ("dark", str) == 0)
-    return META_GTK_COLOR_DARK;
-  else if (strcmp ("mid", str) == 0)
-    return META_GTK_COLOR_MID;
-  else if (strcmp ("text", str) == 0)
-    return META_GTK_COLOR_TEXT;
-  else if (strcmp ("base", str) == 0)
-    return META_GTK_COLOR_BASE;
-  else if (strcmp ("text_aa", str) == 0)
-    return META_GTK_COLOR_TEXT_AA;
-  else
-    return META_GTK_COLOR_LAST;
-}
-
-MetaColorSpec*
-meta_color_spec_new_from_string (const char *str,
-                                 GError    **err)
-{
-  MetaColorSpec *spec;
-
-  spec = NULL;
-
-  if (strncmp (str, "gtk:custom", 10) == 0)
-    {
-      const char *color_name_start, *fallback_str_start, *end;
-      char *color_name;
-      MetaColorSpec *fallback = NULL;
-      static gboolean debug, debug_set = FALSE;
-
-      if (!debug_set)
-        {
-          debug = g_getenv ("METACITY_DISABLE_FALLBACK_COLOR") != NULL;
-          debug_set = TRUE;
-        }
-
-      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;
-        }
-
-      if (!debug)
-        {
-          char *fallback_str;
-          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);
-        }
-      else
-        {
-          fallback = meta_color_spec_new_from_string ("pink", err);
-        }
-
-      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 (strncmp (str, "gtk:", 4) == 0)
-    {
-      /* GTK color */
-      const char *bracket;
-      const char *end_bracket;
-      char *tmp;
-      GtkStateFlags state;
-      MetaGtkColorComponent component;
-
-      bracket = str;
-      while (*bracket && *bracket != '[')
-        ++bracket;
-
-      if (*bracket == '\0')
-        {
-          g_set_error (err, META_THEME_ERROR,
-                       META_THEME_ERROR_FAILED,
-                       _("GTK color specification must have the state in brackets, e.g. gtk:fg[NORMAL] where 
NORMAL is the state; could not parse \"%s\""),
-                       str);
-          return NULL;
-        }
-
-      end_bracket = bracket;
-      ++end_bracket;
-      while (*end_bracket && *end_bracket != ']')
-        ++end_bracket;
-
-      if (*end_bracket == '\0')
-        {
-          g_set_error (err, META_THEME_ERROR,
-                       META_THEME_ERROR_FAILED,
-                       _("GTK color specification must have a close bracket after the state, e.g. 
gtk:fg[NORMAL] where NORMAL is the state; could not parse \"%s\""),
-                       str);
-          return NULL;
-        }
-
-      tmp = g_strndup (bracket + 1, end_bracket - bracket - 1);
-      state = meta_gtk_state_from_string (tmp);
-      if (((int) state) == -1)
-        {
-          g_set_error (err, META_THEME_ERROR,
-                       META_THEME_ERROR_FAILED,
-                       _("Did not understand state \"%s\" in color specification"),
-                       tmp);
-          g_free (tmp);
-          return NULL;
-        }
-      g_free (tmp);
-
-      tmp = g_strndup (str + 4, bracket - str - 4);
-      component = meta_color_component_from_string (tmp);
-      if (component == META_GTK_COLOR_LAST)
-        {
-          g_set_error (err, META_THEME_ERROR,
-                       META_THEME_ERROR_FAILED,
-                       _("Did not understand color component \"%s\" in color specification"),
-                       tmp);
-          g_free (tmp);
-          return NULL;
-        }
-      g_free (tmp);
-
-      spec = meta_color_spec_new (META_COLOR_SPEC_GTK);
-      spec->data.gtk.state = state;
-      spec->data.gtk.component = component;
-      g_assert (spec->data.gtk.component < META_GTK_COLOR_LAST);
-    }
-  else if (strncmp (str, "blend/", 6) == 0)
-    {
-      /* blend */
-      char **split;
-      double alpha;
-      char *end;
-      MetaColorSpec *fg;
-      MetaColorSpec *bg;
-
-      split = g_strsplit (str, "/", 4);
-
-      if (split[0] == NULL || split[1] == NULL ||
-          split[2] == NULL || split[3] == NULL)
-        {
-          g_set_error (err, META_THEME_ERROR,
-                       META_THEME_ERROR_FAILED,
-                       _("Blend format is \"blend/bg_color/fg_color/alpha\", \"%s\" does not fit the 
format"),
-                       str);
-          g_strfreev (split);
-          return NULL;
-        }
-
-      alpha = g_ascii_strtod (split[3], &end);
-      if (end == split[3])
-        {
-          g_set_error (err, META_THEME_ERROR,
-                       META_THEME_ERROR_FAILED,
-                       _("Could not parse alpha value \"%s\" in blended color"),
-                       split[3]);
-          g_strfreev (split);
-          return NULL;
-        }
-
-      if (alpha < (0.0 - 1e6) || alpha > (1.0 + 1e6))
-        {
-          g_set_error (err, META_THEME_ERROR,
-                       META_THEME_ERROR_FAILED,
-                       _("Alpha value \"%s\" in blended color is not between 0.0 and 1.0"),
-                       split[3]);
-          g_strfreev (split);
-          return NULL;
-        }
-
-      fg = NULL;
-      bg = NULL;
-
-      bg = meta_color_spec_new_from_string (split[1], err);
-      if (bg == NULL)
-        {
-          g_strfreev (split);
-          return NULL;
-        }
-
-      fg = meta_color_spec_new_from_string (split[2], err);
-      if (fg == NULL)
-        {
-          meta_color_spec_free (bg);
-          g_strfreev (split);
-          return NULL;
-        }
-
-      g_strfreev (split);
-
-      spec = meta_color_spec_new (META_COLOR_SPEC_BLEND);
-      spec->data.blend.alpha = alpha;
-      spec->data.blend.background = bg;
-      spec->data.blend.foreground = fg;
-    }
-  else if (strncmp (str, "shade/", 6) == 0)
-    {
-      /* shade */
-      char **split;
-      double factor;
-      char *end;
-      MetaColorSpec *base;
-
-      split = g_strsplit (str, "/", 3);
-
-      if (split[0] == NULL || split[1] == NULL ||
-          split[2] == NULL)
-        {
-          g_set_error (err, META_THEME_ERROR,
-                       META_THEME_ERROR_FAILED,
-                       _("Shade format is \"shade/base_color/factor\", \"%s\" does not fit the format"),
-                       str);
-          g_strfreev (split);
-          return NULL;
-        }
-
-      factor = g_ascii_strtod (split[2], &end);
-      if (end == split[2])
-        {
-          g_set_error (err, META_THEME_ERROR,
-                       META_THEME_ERROR_FAILED,
-                       _("Could not parse shade factor \"%s\" in shaded color"),
-                       split[2]);
-          g_strfreev (split);
-          return NULL;
-        }
-
-      if (factor < (0.0 - 1e6))
-        {
-          g_set_error (err, META_THEME_ERROR,
-                       META_THEME_ERROR_FAILED,
-                       _("Shade factor \"%s\" in shaded color is negative"),
-                       split[2]);
-          g_strfreev (split);
-          return NULL;
-        }
-
-      base = NULL;
-
-      base = meta_color_spec_new_from_string (split[1], err);
-      if (base == NULL)
-        {
-          g_strfreev (split);
-          return NULL;
-        }
-
-      g_strfreev (split);
-
-      spec = meta_color_spec_new (META_COLOR_SPEC_SHADE);
-      spec->data.shade.factor = factor;
-      spec->data.shade.base = base;
-    }
-  else
-    {
-      spec = meta_color_spec_new (META_COLOR_SPEC_BASIC);
-
-      if (!gdk_rgba_parse (&spec->data.basic.color, str))
-        {
-          g_set_error (err, META_THEME_ERROR,
-                       META_THEME_ERROR_FAILED,
-                       _("Could not parse color \"%s\""),
-                       str);
-          meta_color_spec_free (spec);
-          return NULL;
-        }
-    }
-
-  g_assert (spec);
-
-  return spec;
-}
-
-MetaColorSpec*
-meta_color_spec_new_gtk (MetaGtkColorComponent component,
-                         GtkStateFlags         state)
-{
-  MetaColorSpec *spec;
-
-  spec = meta_color_spec_new (META_COLOR_SPEC_GTK);
-
-  spec->data.gtk.component = component;
-  spec->data.gtk.state = state;
-
-  return spec;
-}
-
-static void
-meta_set_color_from_style (GdkRGBA               *color,
-                           GtkStyleContext       *context,
-                           GtkStateFlags          state,
-                           MetaGtkColorComponent  component)
-{
-  GdkRGBA other;
-
-  gtk_style_context_set_state (context, state);
-
-  switch (component)
-    {
-    case META_GTK_COLOR_BG:
-    case META_GTK_COLOR_BASE:
-      meta_color_get_background_color (context, state, color);
-      break;
-    case META_GTK_COLOR_FG:
-    case META_GTK_COLOR_TEXT:
-      gtk_style_context_get_color (context, state, color);
-      break;
-    case META_GTK_COLOR_TEXT_AA:
-      gtk_style_context_get_color (context, state, color);
-      meta_set_color_from_style (&other, context, state, META_GTK_COLOR_BASE);
-
-      color->red = (color->red + other.red) / 2;
-      color->green = (color->green + other.green) / 2;
-      color->blue = (color->blue + other.blue) / 2;
-      break;
-    case META_GTK_COLOR_MID:
-      meta_color_get_light_color (context, state, color);
-      meta_color_get_dark_color (context, state, &other);
-
-      color->red = (color->red + other.red) / 2;
-      color->green = (color->green + other.green) / 2;
-      color->blue = (color->blue + other.blue) / 2;
-      break;
-    case META_GTK_COLOR_LIGHT:
-      meta_color_get_light_color (context, state, color);
-      break;
-    case META_GTK_COLOR_DARK:
-      meta_color_get_dark_color (context, state, color);
-      break;
-    case META_GTK_COLOR_LAST:
-    default:
-      g_assert_not_reached ();
-      break;
-    }
-}
-
-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,
-                        GdkRGBA         *color)
-{
-  g_return_if_fail (spec != NULL);
-  g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
-
-  switch (spec->type)
-    {
-    case META_COLOR_SPEC_BASIC:
-      *color = spec->data.basic.color;
-      break;
-
-    case META_COLOR_SPEC_GTK:
-      meta_set_color_from_style (color,
-                                 context,
-                                 spec->data.gtk.state,
-                                 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;
-
-        meta_color_spec_render (spec->data.blend.background, context, &bg);
-        meta_color_spec_render (spec->data.blend.foreground, context, &fg);
-
-        color_composite (&bg, &fg, spec->data.blend.alpha,
-                         &spec->data.blend.color);
-
-        *color = spec->data.blend.color;
-      }
-      break;
-
-    case META_COLOR_SPEC_SHADE:
-      {
-        meta_color_spec_render (spec->data.shade.base, context,
-                                &spec->data.shade.color);
-
-        meta_color_shade (&spec->data.shade.color, spec->data.shade.factor,
-                          &spec->data.shade.color);
-
-        *color = spec->data.shade.color;
-      }
-      break;
-
-    default:
-      break;
-    }
-}
-
 /**
  * Represents an operation as a string.
  *
@@ -6527,29 +5979,6 @@ meta_frame_type_from_string (const char *str)
     return META_FRAME_TYPE_LAST;
 }
 
-GtkStateFlags
-meta_gtk_state_from_string (const char *str)
-{
-  if (g_ascii_strcasecmp ("normal", str) == 0)
-    return GTK_STATE_FLAG_NORMAL;
-  else if (g_ascii_strcasecmp ("prelight", str) == 0)
-    return GTK_STATE_FLAG_PRELIGHT;
-  else if (g_ascii_strcasecmp ("active", str) == 0)
-    return GTK_STATE_FLAG_ACTIVE;
-  else if (g_ascii_strcasecmp ("selected", str) == 0)
-    return GTK_STATE_FLAG_SELECTED;
-  else if (g_ascii_strcasecmp ("insensitive", str) == 0)
-    return GTK_STATE_FLAG_INSENSITIVE;
-  else if (g_ascii_strcasecmp ("inconsistent", str) == 0)
-    return GTK_STATE_FLAG_INCONSISTENT;
-  else if (g_ascii_strcasecmp ("focused", str) == 0)
-    return GTK_STATE_FLAG_FOCUSED;
-  else if (g_ascii_strcasecmp ("backdrop", str) == 0)
-    return GTK_STATE_FLAG_BACKDROP;
-  else
-    return -1; /* hack */
-}
-
 /**
  * Returns the earliest version of the theme format which required support
  * for a particular button.  (For example, "shade" first appeared in v2, and



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]