From a5442fe19432509eda44901093b45e97f72e04c0 Mon Sep 17 00:00:00 2001
From: Sam Spilsbury <smspillaz@gmail.com>
Date: Thu, 13 Jan 2011 11:59:40 +0800
Subject: [PATCH] Add UXD shadows and borders

---
 src/ui/theme-parser.c                  |  520 ++++++++++++++++++++------------
 src/ui/theme.c                         |   63 ++++
 src/ui/theme.h                         |  112 ++++++--
 3 files changed, 482 insertions(+), 215 deletions(-)
 
diff --git a/src/ui/theme-parser.c b/src/ui/theme-parser.c
index c56e318..aef6cee 100644
--- a/src/ui/theme-parser.c
+++ b/src/ui/theme-parser.c
@@ -67,6 +67,8 @@ typedef enum
   STATE_FRAME_STYLE,
   STATE_PIECE,
   STATE_BUTTON,
+  STATE_SHADOW,
+  STATE_PADDING,
   /* style set */
   STATE_FRAME_STYLE_SET,
   STATE_FRAME,
@@ -173,6 +175,20 @@ static void parse_button_element    (GMarkupParseContext  *context,
                                      ParseInfo            *info,
                                      GError              **error);
 
+static void parse_shadow_element    (GMarkupParseContext  *context,
+                                     const gchar          *element_name,
+                                     const gchar         **attribute_names,
+                                     const gchar         **attribute_values,
+                                     ParseInfo            *info,
+                                     GError              **error);
+
+static void parse_padding_element    (GMarkupParseContext  *context,
+                                      const gchar          *element_name,
+                                      const gchar         **attribute_names,
+                                      const gchar         **attribute_values,
+                                      ParseInfo            *info,
+                                      GError              **error);
+
 static void parse_menu_icon_element (GMarkupParseContext  *context,
                                      const gchar          *element_name,
                                      const gchar         **attribute_names,
@@ -2924,9 +2940,76 @@ parse_style_element (GMarkupParseContext  *context,
           meta_draw_op_list_ref (op_list);
           info->op_list = op_list;
         }
-      
+
       push_state (info, STATE_BUTTON);
     }
+  else if (ELEMENT_IS ("shadow"))
+    {
+      const char *shadow_radius = NULL;
+      const char *shadow_opacity = NULL;
+      const char *shadow_color = NULL;
+      const char *shadow_x_offset = NULL;
+      const char *shadow_y_offset = NULL;
+      double shadow_radius_v, shadow_opacity_v;
+      int    shadow_x_offset_v, shadow_y_offset_v;
+      MetaColorSpec *shadow_color_v;
+
+      if (!locate_attributes (context, element_name, attribute_names, attribute_values,
+                              error,
+                              "radius", &shadow_radius,
+                              "opacity", &shadow_opacity,
+                              "color", &shadow_color,
+                              "x_offset", &shadow_x_offset,
+                              "y_offset", &shadow_y_offset,
+                              NULL))
+        return;
+
+      parse_double (shadow_radius, &shadow_radius_v, context, error);
+      parse_double (shadow_opacity, &shadow_opacity_v, context, error);
+      parse_positive_integer (shadow_x_offset, &shadow_x_offset_v, context, info->theme, error);
+      parse_positive_integer (shadow_y_offset, &shadow_y_offset_v, context, info->theme, error);
+      shadow_color_v = parse_color (info->theme, shadow_color, error);
+
+      if (!info->style->shadow_properties)
+        info->style->shadow_properties = meta_shadow_properties_new ();
+
+      info->style->shadow_properties->unity_shadow_radius = shadow_radius_v;
+      info->style->shadow_properties->unity_shadow_opacity = shadow_opacity_v;
+      info->style->shadow_properties->unity_shadow_x_offset = shadow_x_offset_v;
+      info->style->shadow_properties->unity_shadow_y_offset = shadow_y_offset_v;
+      info->style->shadow_properties->unity_shadow_color = shadow_color_v;
+
+      push_state (info, STATE_SHADOW);
+
+    }
+  else if (ELEMENT_IS ("padding"))
+    {
+      const char *left = NULL;
+      const char *bottom = NULL;
+      const char *right = NULL;
+      int        left_v, right_v, bottom_v;
+
+      if (!locate_attributes (context, element_name, attribute_names, attribute_values,
+                              error,
+                              "left", &left,
+                              "right", &right,
+                              "bottom", &bottom,
+                              NULL))
+        return;
+
+      parse_positive_integer (left, &left_v, context, info->theme, error);
+      parse_positive_integer (right, &right_v, context, info->theme, error);
+      parse_positive_integer (bottom, &bottom_v, context, info->theme, error);
+
+      if (!info->style->invisible_grab_area_properties)
+        info->style->invisible_grab_area_properties = meta_invisible_grab_area_properties_new ();
+
+      info->style->invisible_grab_area_properties->left = left_v;
+      info->style->invisible_grab_area_properties->right = right_v;
+      info->style->invisible_grab_area_properties->bottom = bottom_v;
+
+      push_state (info, STATE_PADDING);
+    }
   else
     {
       set_error (error, context,
@@ -3205,6 +3288,38 @@ parse_button_element (GMarkupParseContext  *context,
 }
 
 static void
+parse_shadow_element (GMarkupParseContext  *context,
+                      const gchar          *element_name,
+                      const gchar         **attribute_names,
+                      const gchar         **attribute_values,
+                      ParseInfo            *info,
+                      GError              **error)
+{
+  g_return_if_fail (peek_state (info) == STATE_SHADOW);
+
+  set_error (error, context,
+             G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
+             _("Element <%s> is not allowed below <%s>"),
+             element_name, "shadow");
+}
+
+static void
+parse_padding_element (GMarkupParseContext  *context,
+                      const gchar          *element_name,
+                      const gchar         **attribute_names,
+                      const gchar         **attribute_values,
+                      ParseInfo            *info,
+                      GError              **error)
+{
+  g_return_if_fail (peek_state (info) == STATE_PADDING);
+
+  set_error (error, context,
+             G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
+             _("Element <%s> is not allowed below <%s>"),
+             element_name, "padding");
+}
+
+static void
 parse_menu_icon_element (GMarkupParseContext  *context,
                          const gchar          *element_name,
                          const gchar         **attribute_names,
@@ -3355,6 +3469,16 @@ start_element_handler (GMarkupParseContext *context,
                             attribute_names, attribute_values,
                             info, error);
       break;
+    case STATE_SHADOW:
+       parse_shadow_element (context, element_name,
+                             attribute_names, attribute_values,
+                             info, error);
+       break;
+    case STATE_PADDING:
+       parse_padding_element (context, element_name,
+                              attribute_names, attribute_values,
+                              info, error);
+       break;
     case STATE_MENU_ICON:
       parse_menu_icon_element (context, element_name,
                                attribute_names, attribute_values,
@@ -3624,6 +3748,14 @@ end_element_handler (GMarkupParseContext *context,
         }
       pop_state (info);
       break;
+    case STATE_SHADOW:
+      g_assert (info->style);
+      pop_state (info);
+      break;
+    case STATE_PADDING:
+      g_assert (info->style);
+      pop_state (info);
+      break;
     case STATE_MENU_ICON:
       g_assert (info->theme);
       if (info->op_list != NULL)
@@ -3848,6 +3980,12 @@ text_handler (GMarkupParseContext *context,
     case STATE_BUTTON:
       NO_TEXT ("button");
       break;
+    case STATE_SHADOW:
+      NO_TEXT ("shadow");
+      break;
+    case STATE_PADDING:
+      NO_TEXT ("padding");
+      break;
     case STATE_MENU_ICON:
       NO_TEXT ("menu_icon");
       break;

diff --git a/src/ui/theme.c b/src/ui/theme.c
index 1397fc6..dfa5e9f 100644
--- a/src/ui/theme.c
+++ b/src/ui/theme.c
@@ -1051,6 +1051,51 @@ meta_alpha_gradient_spec_free (MetaAlphaGradientSpec *spec)
   g_free (spec);
 }
 
+MetaShadowProperties*
+meta_shadow_properties_new (void)
+{
+  MetaShadowProperties *properties;
+  
+  properties = g_new0 (MetaShadowProperties, 1);
+
+  if (properties)
+  {
+    properties->unity_shadow_radius = 0.0f;
+    properties->unity_shadow_x_offset = 0;
+    properties->unity_shadow_y_offset = 0;
+    properties->unity_shadow_color = NULL;
+  }
+
+  return properties;
+}
+
+void
+meta_shadow_properties_free (MetaShadowProperties *properties)
+{
+  g_return_if_fail (properties != NULL);
+
+  meta_color_spec_free (properties->unity_shadow_color);
+  g_free (properties);
+}
+
+MetaInvisibleGrabAreaProperties*
+meta_invisible_grab_area_properties_new (void)
+{
+  MetaInvisibleGrabAreaProperties *properties;
+  
+  properties = g_new0 (MetaInvisibleGrabAreaProperties, 1);
+
+  return properties;
+}
+
+void
+meta_invisible_grab_area_properties_free (MetaInvisibleGrabAreaProperties *properties)
+{
+  g_return_if_fail (properties != NULL);
+
+  g_free (properties);
+}
+
 MetaColorSpec*
 meta_color_spec_new (MetaColorSpecType type)
 {
@@ -4149,6 +4194,12 @@ meta_frame_style_unref (MetaFrameStyle *style)
       if (style->parent)
         meta_frame_style_unref (style->parent);
 
+      if (style->shadow_properties)
+        meta_shadow_properties_free (style->shadow_properties);
+
+      if (style->invisible_grab_area_properties)
+        meta_invisible_grab_area_properties_free (style->invisible_grab_area_properties);
+
       DEBUG_FILL_STRUCT (style);
       g_free (style);
     }
@@ -4581,6 +4632,18 @@ meta_frame_style_draw (MetaFrameStyle          *style,
                                     button_states, mini_icon, icon);
 }
 
+MetaShadowProperties *
+meta_frame_style_get_shadow_properties (MetaFrameStyle *style)
+{
+    return style->shadow_properties;
+}
+
+
+MetaInvisibleGrabAreaProperties * meta_frame_style_get_invisible_grab_area_properties (MetaFrameStyle *style)
+{
+    return style->invisible_grab_area_properties;
+}
+
 MetaFrameStyleSet*
 meta_frame_style_set_new (MetaFrameStyleSet *parent)
 {
diff --git a/src/ui/theme.h b/src/ui/theme.h
index ddf777d..88d3bf0 100644
--- a/src/ui/theme.h
+++ b/src/ui/theme.h
@@ -34,7 +34,7 @@ typedef struct _MetaFrameStyleSet MetaFrameStyleSet;
 typedef struct _MetaDrawOp MetaDrawOp;
 typedef struct _MetaDrawOpList MetaDrawOpList;
 typedef struct _MetaGradientSpec MetaGradientSpec;
-typedef struct _MetaAlphaGradientSpec MetaAlphaGradientSpec; 
+typedef struct _MetaAlphaGradientSpec MetaAlphaGradientSpec;
 typedef struct _MetaColorSpec MetaColorSpec;
 typedef struct _MetaFrameLayout MetaFrameLayout;
 typedef struct _MetaButtonSpace MetaButtonSpace;
@@ -42,6 +42,54 @@ typedef struct _MetaFrameGeometry MetaFrameGeometry;
 typedef struct _MetaTheme MetaTheme;
 typedef struct _MetaPositionExprEnv MetaPositionExprEnv;
 typedef struct _MetaDrawInfo MetaDrawInfo;
+typedef struct _MetaShadowProperties MetaShadowProperties;
+typedef struct _MetaInvisibleGrabAreaProperties MetaInvisibleGrabAreaProperties;
+
+struct _MetaShadowProperties
+{
+  /**
+   * Radius of the shadow
+   */
+  double unity_shadow_radius;
+
+  /**
+   * Opacity of the shadow
+   */
+  double unity_shadow_opacity;
+
+  /**
+   * Color of the shadow
+   */
+  MetaColorSpec *unity_shadow_color;
+  /**
+   * Shadow X Offset
+   */
+  guint8 unity_shadow_x_offset;
+  /**
+   * Shadow Y Offset
+   */
+  guint8 unity_shadow_y_offset;
+};
+
+struct _MetaInvisibleGrabAreaProperties
+{
+  /**
+   * Left padding
+   */
+  guint8 left;
+  /**
+   * Right padding
+   */
+  guint8 right;
+  /**
+   * Bottom padding
+   */
+  guint8 bottom;
+  /**
+   * Top padding
+   */
+  guint8 top;
+};
 
 #define META_THEME_ERROR (g_quark_from_static_string ("meta-theme-error"))
 
@@ -693,6 +741,15 @@ struct _MetaFrameStyle
    * Transparency of the window background. 0=transparent; 255=opaque.
    */
   guint8 window_background_alpha;
+  /**
+   * Shadow
+   */
+  MetaShadowProperties *shadow_properties;
+  /**
+   * Padding (eg invisible grab area)
+   */
+  MetaInvisibleGrabAreaProperties *invisible_grab_area_properties;
+
 };
 
 /* Kinds of frame...
@@ -946,6 +1003,11 @@ MetaAlphaGradientSpec* meta_alpha_gradient_spec_new  (MetaGradientType       typ
                                                       int                    n_alphas);
 void                   meta_alpha_gradient_spec_free (MetaAlphaGradientSpec *spec);
 
+MetaShadowProperties* meta_shadow_properties_new (void);
+void                  meta_shadow_properties_free (MetaShadowProperties *);
+
+MetaInvisibleGrabAreaProperties* meta_invisible_grab_area_properties_new (void);
+void                             meta_invisible_grab_area_properties_free (MetaInvisibleGrabAreaProperties *);
 
 MetaFrameStyle* meta_frame_style_new   (MetaFrameStyle *parent);
 void            meta_frame_style_ref   (MetaFrameStyle *style);
@@ -983,6 +1045,8 @@ void meta_frame_style_draw_with_style (MetaFrameStyle          *style,
                                        GdkPixbuf               *mini_icon,
                                        GdkPixbuf               *icon);
 
+MetaShadowProperties * meta_frame_style_get_shadow_properties (MetaFrameStyle *style);
+MetaInvisibleGrabAreaProperties * meta_frame_style_get_invisible_grab_area_properties (MetaFrameStyle *style);
 
 gboolean       meta_frame_style_validate (MetaFrameStyle    *style,
                                           guint              current_theme_version,
-- 
1.7.2.3

