Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/metacity/ChangeLog,v
retrieving revision 1.868
diff -u -p -u -r1.868 ChangeLog
--- ChangeLog	30 Aug 2004 05:27:35 -0000	1.868
+++ ChangeLog	4 Sep 2004 03:30:26 -0000
@@ -1,3 +1,20 @@
+2004-09-03  Havoc Pennington  <hp@redhat.com>
+
+	* src/theme.h (struct _MetaFrameStyle): add
+	window_background_color and window_background_alpha fields
+
+	* src/theme-parser.c (parse_toplevel_element): parse "alpha" and
+	"color" attributes on frame_style
+
+	* src/frames.c (meta_frames_set_window_background): use the
+	color/alpha set in the theme, if any
+
+	* src/theme-parser.c (meta_theme_load): scan for theme format
+	versions in descending order, and tag the parser with the format
+	version we are expecting to parse.
+
+	* doc/theme-format.txt: update to describe version 2 features
+
 2004-08-29  Elijah Newren  <newren@math.utah.edu>
 
 	* NEWS: 2.8.4 release
Index: doc/theme-format.txt
===================================================================
RCS file: /cvs/gnome/metacity/doc/theme-format.txt,v
retrieving revision 1.1
diff -u -p -u -r1.1 theme-format.txt
--- doc/theme-format.txt	20 Nov 2002 04:57:25 -0000	1.1
+++ doc/theme-format.txt	4 Sep 2004 03:30:26 -0000
@@ -1,6 +1,83 @@
-Docs on the theme format
+Themes are in a simple XML-subset format. There are multiple versions
+of the theme format and a given theme can support more than one format:
 
-Themes are in a simple XML-subset format.
+Version 1:           THEMEDIR/metacity-1/metacity-theme-1.xml
+  (original metacity format)
+Version 2:           THEMEDIR/metacity-2/metacity-theme.xml
+  (extensions in GNOME 2.10 that do not require RGBA visuals)
+Version 3:           THEMEDIR/metacity-3/metacity-theme.xml
+  (version 2, plus extensions in 2.10 that require RGBA visuals)
+
+As you might expect, older versions of metacity will not understand
+newer theme formats. However, newer versions will use old themes.
+Metacity will always use the newest theme format it understands that
+the X server supports. Some format versions are only supported if you
+have the right X server features.
+
+Each format *requires* the corresponding filename. If you put version
+2 format features in the metacity-1/metacity-theme-1.xml file, then
+metacity will get angry.
+
+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.
+
+Planned New Format Features
+========================================
+
+Please see the dependencies of bug
+http://bugzilla.gnome.org/show_bug.cgi?id=102547
+
+A hypothetical future on new format versions:
+
+Version 4:           THEMEDIR/metacity-4/metacity-theme.xml
+  (version 2, plus extensions in GNOME 2.12 that do not require RGBA visuals)
+Version 5:           THEMEDIR/metacity-5/metacity-theme.xml
+  (versions 3 and 4, plus extensions in 2.12 that require RGBA visuals)
+Version 6:           THEMEDIR/metacity-6/metacity-theme.xml
+  (version 4, plus extensions in GNOME 2.14 that do not require RGBA visuals)
+Version 7:           THEMEDIR/metacity-7/metacity-theme.xml
+  (versions 5 and 6, plus extensions in 2.14 that require COMPOSITE)
+Version 8:           THEMEDIR/metacity-8/metacity-theme.xml
+  (version 7, plus new extensions in 2.16, requires COMPOSITE)
+Version 9:           THEMEDIR/metacity-9/metacity-theme.xml
+  (version 8, plus new extensions in 2.18, requires COMPOSITE)
+
+Remember that all versions continue to work, so if you never have
+COMPOSITE then metacity works, you just have to use an older theme
+format for that.
+
+I doubt we'll really have this many versions this quickly, and I'm
+sure unexpected stuff will happen, I'm just trying to give a sense of
+the plan.
+
+New Features in Theme Format Version 3
+========================================
+
+Theme format version 3 implies version 2, but also requires newer X
+server features so not all users will be able to use a version 3
+theme.
+
+New attributes on <frame_style>:
+  <frame_style color="#FF0000" alpha="0.5"/> <!-- sets the alpha channel of the frame window 
+                                                 background color -->
+
+  "alpha" attribute requires "color" attribute.
+
+New Features in Theme Format Version 2
+========================================
+
+Theme format version 2 contains extensions to Version 1 format that do
+not require any special X server features.
+
+New attributes on <frame_style>:
+  <frame_style color="#00FF00"/> <!-- any color spec can go here; sets
+                                      the window background for the frame -->
+
+
+
+Overview of Theme Format Version 1
+========================================
 
 <?xml version="1.0"?>
 <metacity_theme>
Index: src/frames.c
===================================================================
RCS file: /cvs/gnome/metacity/src/frames.c,v
retrieving revision 1.77
diff -u -p -u -r1.77 frames.c
--- src/frames.c	27 Aug 2004 22:09:13 -0000	1.77
+++ src/frames.c	4 Sep 2004 03:30:29 -0000
@@ -2,7 +2,7 @@
 
 /* 
  * Copyright (C) 2001 Havoc Pennington
- * Copyright (C) 2003 Red Hat, Inc.
+ * Copyright (C) 2003, 2004 Red Hat, Inc.
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -472,7 +472,6 @@ meta_frames_manage_window (MetaFrames *f
 			   GdkWindow  *window)
 {
   MetaUIFrame *frame;
-  GdkColor col;
 
   g_assert (window);
 
@@ -1902,16 +1901,44 @@ static void
 meta_frames_set_window_background (MetaFrames   *frames,
                                    MetaUIFrame  *frame)
 {
-  gtk_style_set_background (GTK_WIDGET (frames)->style,
-                            frame->window, GTK_STATE_NORMAL);
+  MetaFrameFlags flags;
+  MetaFrameType type;
+  MetaFrameStyle *style;
+  
+  flags = meta_core_get_frame_flags (gdk_display, frame->xwindow);
+  type = meta_core_get_frame_type (gdk_display, frame->xwindow);
 
-#if 0
-  /* This is what we want for transparent background */
-  {
-    col.pixel = 0;
-    gdk_window_set_background (window, &col);
-  }
-#endif
+  style = meta_theme_get_frame_style (meta_theme_get_current (),
+                                      type, flags);
+
+  if (style->window_background_color == NULL)
+    {
+      gtk_style_set_background (GTK_WIDGET (frames)->style,
+                                frame->window, GTK_STATE_NORMAL);
+    }
+  else
+    {
+      GdkColor color;
+      GdkVisual *visual;
+      
+      meta_color_spec_render (style->window_background_color,
+                              GTK_WIDGET (frames),
+                              &color);
+
+      /* Fill in color.pixel */
+      gdk_rgb_find_color (gtk_widget_get_colormap (GTK_WIDGET (frames)),
+                          &color);
+      
+      /* Set A in ARGB to window_background_alpha, if we have ARGB */
+      visual = gtk_widget_get_visual (GTK_WIDGET (frames));
+      if (visual->depth == 32)
+        {
+          color.pixel = (color.pixel & 0xffffff) &
+            style->window_background_alpha << 24;
+        }
+
+      gdk_window_set_background (frame->window, &color);   
+    }
 }
 
 static gboolean
Index: src/theme-parser.c
===================================================================
RCS file: /cvs/gnome/metacity/src/theme-parser.c,v
retrieving revision 1.19
diff -u -p -u -r1.19 theme-parser.c
--- src/theme-parser.c	30 May 2003 04:52:12 -0000	1.19
+++ src/theme-parser.c	4 Sep 2004 03:30:34 -0000
@@ -2,6 +2,7 @@
 
 /*
  * Copyright (C) 2001 Havoc Pennington
+ * Copyright (C) 2004 Red Hat, Inc.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -27,6 +28,39 @@
 
 typedef enum
 {
+  META_THEME_FEATURE_ARGB_VISUALS = 1 << 0,
+  META_THEME_FEATURE_COMPOSITE    = 1 << 1
+} MetaThemeFeature;
+
+
+/* We change the filename when we break the format,
+ * so themes can work with various metacity versions.
+ * We need to know the format version we loaded, so we
+ * can enforce validity of that version (if you try to
+ * name a version 2 theme as a version 1 theme, we want that
+ * to fail so theme authors won't screw up when only testing
+ * with new metacity)
+ */
+typedef struct
+{
+  int version;
+  const char *subdir;
+  const char *filename;
+  unsigned int requirements;
+} ThemeFormatInfo;
+
+static ThemeFormatInfo known_formats[] = {
+  { 1, "metacity-1", "metacity-theme-1.xml", 0 },
+#define META_THEME_FORMAT_INTRODUCES_FRAME_STYLE_COLOR 2
+  { 2, "metacity-2", "metacity-theme.xml", 0 },
+  /* Format 3 introduces "alpha" attribute on frame_style,
+   * which exits for all formats that require ARGB visuals
+   */
+  { 3, "metacity-3", "metacity-theme.xml", META_THEME_FEATURE_ARGB_VISUALS }
+};
+
+typedef enum
+{
   STATE_START,
   STATE_THEME,
   /* info section */
@@ -81,6 +115,7 @@ typedef struct
   const char *theme_name;       /* name of theme (directory it's in) */
   char *theme_file;             /* theme filename */
   char *theme_dir;              /* dir the theme is inside */
+  ThemeFormatInfo *format;      /* version of the theme file format */
   MetaTheme *theme;             /* theme being parsed */
   char *name;                   /* name of named thing being parsed */
   MetaFrameLayout *layout;      /* layout being parsed if any */
@@ -260,6 +295,7 @@ parse_info_init (ParseInfo *info)
   info->piece = META_FRAME_PIECE_LAST;
   info->button_type = META_BUTTON_TYPE_LAST;
   info->button_state = META_BUTTON_STATE_LAST;
+  info->format = NULL;
 }
 
 static void
@@ -579,10 +615,41 @@ parse_angle (const char          *str,
 
 static gboolean
 parse_alpha (const char             *str,
-             MetaAlphaGradientSpec **spec_ret,
+             unsigned char          *alpha_p,
              GMarkupParseContext    *context,
              GError                **error)
 {
+  double v;
+  
+  if (!parse_double (str, &v, context, error))
+    {
+      set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
+                 _("Could not parse \"%s\" as a floating point number"),
+                 str);
+      
+      return FALSE;
+    }
+
+  if (v < (0.0 - 1e6) || v > (1.0 + 1e6))
+    {
+      set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
+                 _("Alpha must be between 0.0 (invisible) and 1.0 (fully opaque), was %g\n"),
+                 v);
+      
+      return FALSE;
+    }
+
+  *alpha_p = (unsigned char) (v * 255);
+  
+  return TRUE;
+}
+
+static gboolean
+parse_alpha_gradient (const char             *str,
+                      MetaAlphaGradientSpec **spec_ret,
+                      GMarkupParseContext    *context,
+                      GError                **error)
+{
   char **split;
   int i;
   int n_alphas;
@@ -618,34 +685,16 @@ parse_alpha (const char             *str
   i = 0;
   while (i < n_alphas)
     {
-      double v;
-      
-      if (!parse_double (split[i], &v, context, error))
+      if (!parse_alpha (split[i],
+                        &spec->alphas[i],
+                        context, error))
         {
-          set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
-                     _("Could not parse \"%s\" as a floating point number"),
-                     split[i]);
-          
           g_strfreev (split);
           meta_alpha_gradient_spec_free (spec);
           
           return FALSE;
         }
 
-      if (v < (0.0 - 1e6) || v > (1.0 + 1e6))
-        {
-          set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
-                     _("Alpha must be between 0.0 (invisible) and 1.0 (fully opaque), was %g\n"),
-                     v);
-
-          g_strfreev (split);
-          meta_alpha_gradient_spec_free (spec);          
-          
-          return FALSE;
-        }
-
-      spec->alphas[i] = (unsigned char) (v * 255);
-      
       ++i;
     }  
 
@@ -919,6 +968,8 @@ parse_toplevel_element (GMarkupParseCont
       const char *name = NULL;
       const char *parent = NULL;
       const char *geometry = NULL;
+      const char *color = NULL;
+      const char *alpha = NULL;
       MetaFrameStyle *parent_style;
       MetaFrameLayout *layout;
 
@@ -926,6 +977,8 @@ parse_toplevel_element (GMarkupParseCont
                               error,
                               "name", &name, "parent", &parent,
                               "geometry", &geometry,
+                              "color", &color,
+                              "alpha", &alpha,
                               NULL))
         return;
 
@@ -936,7 +989,33 @@ parse_toplevel_element (GMarkupParseCont
                      "name", element_name);
           return;
         }
+      
+      if (color != NULL &&
+          info->format->version < META_THEME_FORMAT_INTRODUCES_FRAME_STYLE_COLOR)
+        {
+          set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
+                     _("\"%s\" attribute on <%s> element can only be used with theme format version %d or greater"),
+                     "color", element_name, META_THEME_FORMAT_INTRODUCES_FRAME_STYLE_COLOR);
+          return;
+        }
+      
+      if (alpha != NULL &&
+          !(info->format->requirements & META_THEME_FEATURE_ARGB_VISUALS))
+        {
+          set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
+                     _("\"%s\" attribute on <%s> element can only be used with theme format versions that support ARGB visuals"),
+                     "alpha", element_name);
+          return;
+        }
 
+      if (alpha != NULL && color == NULL)
+        {
+          set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
+                     _("\"%s\" attribute on <%s> element requires \"%s\" attribute"),
+                     "alpha", element_name, "color");
+          return;
+        }
+      
       if (meta_theme_lookup_style (info->theme, name))
         {
           set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
@@ -982,7 +1061,7 @@ parse_toplevel_element (GMarkupParseCont
                      element_name);
           return;
         }
-
+      
       g_assert (info->style == NULL);
 
       info->style = meta_frame_style_new (parent_style);
@@ -990,6 +1069,34 @@ parse_toplevel_element (GMarkupParseCont
       meta_frame_layout_ref (layout);
       info->style->layout = layout;
 
+      /* If we return past this point, info->style should get freed
+       * with the ParseInfo
+       */
+      
+      if (color != NULL)
+        {
+          MetaColorSpec *color_spec;
+          
+          color_spec = meta_color_spec_new_from_string (color, error);
+          if (color_spec == NULL)
+            {
+              add_context_to_error (error, context);
+              return;
+            }
+          info->style->window_background_color = color_spec;
+        }
+
+      if (alpha != NULL)
+        {
+          if (!parse_alpha (alpha,
+                            &info->style->window_background_alpha,
+                            context, error))
+            {
+              add_context_to_error (error, context);
+              return;
+            }
+        }
+      
       meta_theme_insert_style (info->theme, name, info->style);
 
       push_state (info, STATE_FRAME_STYLE);
@@ -2104,7 +2211,7 @@ parse_draw_op_element (GMarkupParseConte
         return;
 
       alpha_spec = NULL;
-      if (!parse_alpha (alpha, &alpha_spec, context, error))
+      if (!parse_alpha_gradient (alpha, &alpha_spec, context, error))
         return;
       
       /* Check last so we don't have to free it when other
@@ -2212,7 +2319,7 @@ parse_draw_op_element (GMarkupParseConte
         }
 
       alpha_spec = NULL;
-      if (alpha && !parse_alpha (alpha, &alpha_spec, context, error))
+      if (alpha && !parse_alpha_gradient (alpha, &alpha_spec, context, error))
         return;
       
       g_assert (info->op == NULL);
@@ -2345,7 +2452,7 @@ parse_draw_op_element (GMarkupParseConte
         }
 
       alpha_spec = NULL;
-      if (alpha && !parse_alpha (alpha, &alpha_spec, context, error))
+      if (alpha && !parse_alpha_gradient (alpha, &alpha_spec, context, error))
         {
           g_object_unref (G_OBJECT (pixbuf));
           return;
@@ -2830,7 +2937,7 @@ parse_draw_op_element (GMarkupParseConte
         }
       
       alpha_spec = NULL;
-      if (alpha && !parse_alpha (alpha, &alpha_spec, context, error))
+      if (alpha && !parse_alpha_gradient (alpha, &alpha_spec, context, error))
         return;
       
       op = meta_draw_op_new (META_DRAW_ICON);
@@ -4243,15 +4350,80 @@ text_handler (GMarkupParseContext *conte
     }
 }
 
-/* We change the filename when we break the format,
- * so themes can work with various metacity versions
- * (note, this is obsolete now because we are versioning
- * the directory this file is inside, so oh well)
- */
-#define THEME_FILENAME "metacity-theme-1.xml"
+static gboolean
+meta_theme_load_text_from_directory (const char *directory,
+                                     const char *theme_name,
+                                     char      **theme_file_p,
+                                     int        *format_version_p,
+                                     char      **text,
+                                     gsize      *length,
+                                     GError    **err)
+{
+  int i;
+
+  *text = NULL;
+  *length = 0;
+  *theme_file_p = NULL;
+  
+  i = G_N_ELEMENTS (known_formats) - 1;
+  while (i >= 0)
+    {
+      GError *error;
+      char *theme_file;
+
+      g_assert (*text == NULL);
+      g_assert (*format_version_p == 0);
+      g_assert (*theme_file_p == NULL);
+
+      g_assert (known_formats[i].version == i + 1);
+      
+      theme_file = g_build_filename (directory,
+                                     theme_name,
+                                     known_formats[i].subdir,
+                                     known_formats[i].filename,
+                                     NULL);
 
-/* now this is versioned, /usr/share/themes/NAME/THEME_SUBDIR/THEME_FILENAME */
-#define THEME_SUBDIR "metacity-1"
+      error = NULL;
+      if (!g_file_get_contents (theme_file,
+                                text,
+                                length,
+                                &error))
+        {
+          meta_topic (META_DEBUG_THEMES, "Failed to read theme from file %s: %s\n",
+                      theme_file, error->message);
+
+          /* On last failure, print the error and bail out */
+          if ((i + 1) == (int) G_N_ELEMENTS (known_formats))
+            {
+              meta_warning (_("Failed to read theme from file %s: %s\n"),
+                            theme_file, error->message);
+              
+              g_propagate_error (err, error);
+            }
+          else
+            g_error_free (error);
+
+          g_free (theme_file);
+        }
+      else
+        {
+          /* Success! */
+          
+          *theme_file_p = theme_file; /* pass ownership of theme_file */
+          *format_version_p = known_formats[i].version;
+
+          meta_topic (META_DEBUG_THEMES, "Read theme from file %s format version %d\n",
+                      *theme_file_p, *format_version_p);
+          break;
+        }
+
+      --i;
+    }
+
+  g_assert (*text != NULL || (err == NULL || *err != NULL));
+
+  return *text != NULL;
+}
 
 MetaTheme*
 meta_theme_load (const char *theme_name,
@@ -4262,104 +4434,102 @@ meta_theme_load (const char *theme_name,
   ParseInfo info;
   char *text;
   gsize length;
-  char *theme_file;
-  char *theme_dir;
   MetaTheme *retval;
+  char *theme_dir;
+  char *theme_file;
+  int format_version;
 
   text = NULL;
   length = 0;
   retval = NULL;
   context = NULL;
-  
   theme_dir = NULL;
   theme_file = NULL;
+  format_version = 0;
   
+  /* If debugging, start search path with source tree */
   if (meta_is_debugging ())
     {
-      /* Try in themes in our source tree */
-      theme_dir = g_build_filename ("./themes", theme_name, NULL);
-      
-      theme_file = g_build_filename (theme_dir,
-                                     THEME_FILENAME,
-                                     NULL);
+      char *s;
+
+      s = g_get_current_dir ();
+      theme_dir = g_build_filename (s, "themes", NULL);
+      g_free (s);
       
       error = NULL;
-      if (!g_file_get_contents (theme_file,
-                                &text,
-                                &length,
-                                &error))
+      if (!meta_theme_load_text_from_directory (theme_dir,
+                                                theme_name, &theme_file,
+                                                &format_version,
+                                                &text, &length, &error))
         {
-          meta_topic (META_DEBUG_THEMES, "Failed to read theme from file %s: %s\n",
-                      theme_file, error->message);
-          g_error_free (error);
           g_free (theme_dir);
-          g_free (theme_file);
-          theme_file = NULL;
+          theme_dir = NULL;
+          g_error_free (error);
         }
     }
   
-  /* We try in home dir, then system dir for themes */
-  
+  /* Search home directory */
   if (text == NULL)
     {
+      g_assert (theme_dir == NULL);
+      g_assert (theme_file == NULL);
+      
       theme_dir = g_build_filename (g_get_home_dir (),
                                     ".themes",
-                                    theme_name,
-                                    THEME_SUBDIR,
                                     NULL);
-      
-      theme_file = g_build_filename (theme_dir,
-                                     THEME_FILENAME,
-                                     NULL);
-
       error = NULL;
-      if (!g_file_get_contents (theme_file,
-                                &text,
-                                &length,
-                                &error))
+      if (!meta_theme_load_text_from_directory (theme_dir,
+                                                theme_name, &theme_file,
+                                                &format_version,
+                                                &text, &length, &error))
         {
-          meta_topic (META_DEBUG_THEMES, "Failed to read theme from file %s: %s\n",
-                      theme_file, error->message);
-          g_error_free (error);
           g_free (theme_dir);
-          g_free (theme_file);
-          theme_file = NULL;
+          theme_dir = NULL;
+          g_error_free (error);
         }
     }
 
+  /* Search system themes */
   if (text == NULL)
     {
+      g_assert (theme_dir == NULL);
+      g_assert (theme_file == NULL);
+
       theme_dir = g_build_filename (METACITY_DATADIR,
                                     "themes",
-                                    theme_name,
-                                    THEME_SUBDIR,
                                     NULL);
-      
-      theme_file = g_build_filename (theme_dir,
-                                     THEME_FILENAME,
-                                     NULL);
-
       error = NULL;
-      if (!g_file_get_contents (theme_file,
-                                &text,
-                                &length,
-                                &error))
+      if (!meta_theme_load_text_from_directory (theme_dir,
+                                                theme_name, &theme_file,
+                                                &format_version,
+                                                &text, &length, &error))
         {
-          meta_warning (_("Failed to read theme from file %s: %s\n"),
-                        theme_file, error->message);
-          g_propagate_error (err, error);
-          g_free (theme_file);
+
+          /* If no file found systemwide, we have to give up and
+           * return failure
+           */
           g_free (theme_dir);
-          return FALSE; /* all fallbacks failed */
+          theme_dir = NULL;
+          g_propagate_error (err, error);
+          return FALSE;
         }
     }
 
+  /* If we did not bail out due to failure to load system theme, we
+   * now parse the theme...
+   */
+
   g_assert (text);
+  g_assert (theme_dir);
+  g_assert (theme_file);
+  g_assert (format_version > 0);
 
   meta_topic (META_DEBUG_THEMES, "Parsing theme file %s\n", theme_file);
 
   parse_info_init (&info);
   info.theme_name = theme_name;
+
+  info.format = &known_formats[format_version - 1];
   
   /* pass ownership to info so we free it with the info */
   info.theme_file = theme_file;
Index: src/theme.c
===================================================================
RCS file: /cvs/gnome/metacity/src/theme.c,v
retrieving revision 1.72
diff -u -p -u -r1.72 theme.c
--- src/theme.c	27 Aug 2004 02:24:48 -0000	1.72
+++ src/theme.c	4 Sep 2004 03:30:39 -0000
@@ -3779,10 +3779,12 @@ meta_frame_style_new (MetaFrameStyle *pa
 
   style->refcount = 1;
 
+  style->window_background_alpha = 255;
+  
   style->parent = parent;
   if (parent)
-    meta_frame_style_ref (parent);
-
+    meta_frame_style_ref (parent);  
+  
   return style;
 }
 
@@ -3841,6 +3843,9 @@ meta_frame_style_unref (MetaFrameStyle *
       if (style->layout)
         meta_frame_layout_unref (style->layout);
 
+      if (style->window_background_color)
+        meta_color_spec_free (style->window_background_color);
+      
       /* we hold a reference to any parent style */
       if (style->parent)
         meta_frame_style_unref (style->parent);
Index: src/theme.h
===================================================================
RCS file: /cvs/gnome/metacity/src/theme.h,v
retrieving revision 1.37
diff -u -p -u -r1.37 theme.h
--- src/theme.h	10 Jan 2004 17:16:07 -0000	1.37
+++ src/theme.h	4 Sep 2004 03:30:40 -0000
@@ -488,6 +488,8 @@ struct _MetaFrameStyle
   MetaDrawOpList *buttons[META_BUTTON_TYPE_LAST][META_BUTTON_STATE_LAST];
   MetaDrawOpList *pieces[META_FRAME_PIECE_LAST];
   MetaFrameLayout *layout;
+  MetaColorSpec *window_background_color; /* can be NULL to use the standard gtk theme engine */
+  guint8 window_background_alpha;         /* 0 transparent 255 opaque */
 };
 
 /* Kinds of frame...
