[gtk+] window: rework the CSD theming layer



commit 7bbbb01ff521065c10d41185cc64f2823a5a6c9c
Author: Cosimo Cecchi <cosimoc gnome org>
Date:   Mon Apr 22 17:28:23 2013 -0400

    window: rework the CSD theming layer
    
    Instead of having three different boxes and style classes, we can just
    get away with the regular background box, plus a window-frame, which
    contains the external frame, together with the window drop shadows.
    
    GtkWindow now has special code to ensure the backing actual window is
    allocated big enough to accomodate the shadows (using the shadow size
    calculations introduced in the previous commit). We also use the margin
    value to determine the size of the invisible borders (which can then be
    different than the shadow).

 gtk/gtkwindow.c | 255 +++++++++++++++++++++++++++++---------------------------
 1 file changed, 133 insertions(+), 122 deletions(-)
---
diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c
index c4086e7..fe00a5c 100644
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -35,6 +35,7 @@
 #include "gtkwindowprivate.h"
 #include "gtkaccelgroupprivate.h"
 #include "gtkbindings.h"
+#include "gtkcssshadowsvalueprivate.h"
 #include "gtkkeyhash.h"
 #include "gtkmain.h"
 #include "gtkmnemonichash.h"
@@ -6067,68 +6068,65 @@ set_grip_position (GtkWindow *window)
 }
 
 static void
-get_decoration_borders (GtkWidget *widget,
-                        GtkBorder *window_border,
-                        GtkBorder *outer_border)
+sum_borders (GtkBorder *one,
+             GtkBorder *two)
 {
+  one->top += two->top;
+  one->right += two->right;
+  one->bottom += two->bottom;
+  one->left += two->left;
+}
+
+static void
+get_decoration_size (GtkWidget *widget,
+                     GtkBorder *decorations)
+{
+  GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
+  GtkBorder border = { 0 };
+  GtkBorder margin;
   GtkStyleContext *context;
   GtkStateFlags state;
-  GdkWindow *window;
-  gboolean maximized = FALSE;
-  const GtkBorder empty = { 0 };
-  GtkBorder outer;
+  GtkCssValue *shadows;
+
+  *decorations = border;
 
+  if (!priv->client_decorated)
+    return;
+
+  if (gtk_window_get_maximized (GTK_WINDOW (widget)))
+    return;
+
+  state = gtk_widget_get_state_flags (widget);
   context = gtk_widget_get_style_context (widget);
-  state = gtk_style_context_get_state (context);
-  window = gtk_widget_get_window (widget);
-  if (window != NULL)
-    maximized = gdk_window_get_state (window) & GDK_WINDOW_STATE_MAXIMIZED;
 
-  if (window_border != NULL)
-    {
-      if (maximized)
-        {
-          *window_border = empty;
-        }
-      else
-        {
-          gtk_style_context_save (context);
-          gtk_style_context_add_class (context, "window-border");
-          gtk_style_context_get_border (context, state, window_border);
-          gtk_style_context_restore (context);
-        }
-    }
+  gtk_style_context_save (context);
+  gtk_style_context_remove_class (context, GTK_STYLE_CLASS_BACKGROUND);
+  gtk_style_context_add_class (context, "window-frame");
 
-  if (window_border != NULL || outer_border != NULL)
-    {
-      if (maximized)
-        {
-          outer = empty;
-        }
-      else
-        {
-          gtk_style_context_save (context);
-          gtk_style_context_add_class (context, "window-outer-border");
-          gtk_style_context_get_border (context, state, &outer);
-          gtk_style_context_restore (context);
-        }
+  /* Always sum border + padding */
+  gtk_style_context_get_border (context, state, decorations);
+  gtk_style_context_get_padding (context, state, &border);
+  sum_borders (decorations, &border);
 
-      if (outer_border != NULL)
-        {
-          *outer_border = outer;
-        }
-      else
-        {
-          window_border->left += outer.left;
-          window_border->right += outer.right;
-          window_border->top += outer.top;
-          window_border->bottom += outer.bottom;
-        }
-    }
+  /* Calculate the size of the drop shadows ... */
+  shadows = _gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BOX_SHADOW);
+  _gtk_css_shadows_value_get_extents (shadows, &border);
+
+  /* ... and compare it to the margin size, which we use for resize grips */
+  gtk_style_context_get_margin (context, state, &margin);
+
+  border.top = MAX (border.top, margin.top);
+  border.right = MAX (border.right, margin.right);
+  border.bottom = MAX (border.bottom, margin.bottom);
+  border.left = MAX (border.left, margin.left);
+
+  sum_borders (decorations, &border);
+
+  gtk_style_context_restore (context);
 }
 
 static void
-update_border_windows (GtkWindow *window, GtkBorder *border)
+update_border_windows (GtkWindow *window)
 {
   GtkWidget *widget = (GtkWidget *)window;
   GtkWindowPrivate *priv = window->priv;
@@ -6137,10 +6135,20 @@ update_border_windows (GtkWindow *window, GtkBorder *border)
   cairo_region_t *region;
   cairo_rectangle_int_t rect;
   gint width, height;
+  GtkBorder border;
+  GtkStyleContext *context;
 
   if (priv->border_window[0] == NULL)
     return;
 
+  context = gtk_widget_get_style_context (widget);
+  gtk_style_context_save (context);
+  gtk_style_context_add_class (context, "window-frame");
+  gtk_style_context_get_margin (context,
+                                gtk_widget_get_state_flags (widget),
+                                &border);
+  gtk_style_context_restore (context);
+
   if (!priv->resizable || gtk_window_get_maximized (window))
     {
       resize_h = resize_v = FALSE;
@@ -6165,31 +6173,31 @@ update_border_windows (GtkWindow *window, GtkBorder *border)
                         "decoration-resize-handle", &handle,
                         NULL);
 
-  width = gtk_widget_get_allocated_width (widget) - (border->left + border->right);
-  height = gtk_widget_get_allocated_height (widget) - (border->top + border->bottom);
+  width = gtk_widget_get_allocated_width (widget) - (border.left + border.right);
+  height = gtk_widget_get_allocated_height (widget) - (border.top + border.bottom);
 
   if (resize_h && resize_v)
     {
       gdk_window_move_resize (priv->border_window[GDK_WINDOW_EDGE_NORTH_WEST],
                               0, 0,
-                              border->left + handle, border->top + handle);
+                              border.left + handle, border.top + handle);
       gdk_window_move_resize (priv->border_window[GDK_WINDOW_EDGE_NORTH_EAST],
-                              border->left + width - handle, 0,
-                              border->right + handle, border->top + handle);
+                              border.left + width - handle, 0,
+                              border.right + handle, border.top + handle);
       gdk_window_move_resize (priv->border_window[GDK_WINDOW_EDGE_SOUTH_WEST],
-                              0, border->top + height - handle,
-                              border->left + handle, border->bottom + handle);
+                              0, border.top + height - handle,
+                              border.left + handle, border.bottom + handle);
       gdk_window_move_resize (priv->border_window[GDK_WINDOW_EDGE_SOUTH_EAST],
-                              border->left + width - handle, border->top + height - handle,
-                              border->right + handle, border->bottom + handle);
+                              border.left + width - handle, border.top + height - handle,
+                              border.right + handle, border.bottom + handle);
 
       rect.x = 0;
       rect.y = 0;
-      rect.width = border->left + handle;
-      rect.height = border->top + handle;
+      rect.width = border.left + handle;
+      rect.height = border.top + handle;
       region = cairo_region_create_rectangle (&rect);
-      rect.x = border->left;
-      rect.y = border->top;
+      rect.x = border.left;
+      rect.y = border.top;
       rect.width = handle;
       rect.height = handle;
       cairo_region_subtract_rectangle (region, &rect);
@@ -6199,11 +6207,11 @@ update_border_windows (GtkWindow *window, GtkBorder *border)
 
       rect.x = 0;
       rect.y = 0;
-      rect.width = border->right + handle;
-      rect.height = border->top + handle;
+      rect.width = border.right + handle;
+      rect.height = border.top + handle;
       region = cairo_region_create_rectangle (&rect);
       rect.x = 0;
-      rect.y = border->top;
+      rect.y = border.top;
       rect.width = handle;
       rect.height = handle;
       cairo_region_subtract_rectangle (region, &rect);
@@ -6213,10 +6221,10 @@ update_border_windows (GtkWindow *window, GtkBorder *border)
 
       rect.x = 0;
       rect.y = 0;
-      rect.width = border->left + handle;
-      rect.height = border->bottom + handle;
+      rect.width = border.left + handle;
+      rect.height = border.bottom + handle;
       region = cairo_region_create_rectangle (&rect);
-      rect.x = border->left;
+      rect.x = border.left;
       rect.y = 0;
       rect.width = handle;
       rect.height = handle;
@@ -6227,8 +6235,8 @@ update_border_windows (GtkWindow *window, GtkBorder *border)
 
       rect.x = 0;
       rect.y = 0;
-      rect.width = border->right + handle;
-      rect.height = border->bottom + handle;
+      rect.width = border.right + handle;
+      rect.height = border.bottom + handle;
       region = cairo_region_create_rectangle (&rect);
       rect.x = 0;
       rect.y = 0;
@@ -6258,21 +6266,21 @@ update_border_windows (GtkWindow *window, GtkBorder *border)
 
       if (resize_h)
         {
-          x = border->left + handle;
+          x = border.left + handle;
           w = width - 2 * handle;
         }
       else
         {
           x = 0;
-          w = width + border->left + border->right;
+          w = width + border.left + border.right;
         }
 
       gdk_window_move_resize (priv->border_window[GDK_WINDOW_EDGE_NORTH],
                               x, 0,
-                              w, border->top);
+                              w, border.top);
       gdk_window_move_resize (priv->border_window[GDK_WINDOW_EDGE_SOUTH],
-                              x, border->top + height,
-                              w, border->bottom);
+                              x, border.top + height,
+                              w, border.bottom);
 
       gdk_window_show (priv->border_window[GDK_WINDOW_EDGE_NORTH]);
       gdk_window_show (priv->border_window[GDK_WINDOW_EDGE_SOUTH]);
@@ -6289,22 +6297,22 @@ update_border_windows (GtkWindow *window, GtkBorder *border)
 
       if (resize_v)
         {
-          y = border->top + handle;
+          y = border.top + handle;
           h = height - 2 * handle;
         }
       else
         {
           y = 0;
-          h = height + border->top + border->bottom;
+          h = height + border.top + border.bottom;
         }
 
       gdk_window_move_resize (priv->border_window[GDK_WINDOW_EDGE_WEST],
                               0, y,
-                              border->left, h);
+                              border.left, h);
 
       gdk_window_move_resize (priv->border_window[GDK_WINDOW_EDGE_EAST],
-                              border->left + width, y,
-                              border->right, h);
+                              border.left + width, y,
+                              border.right, h);
 
       gdk_window_show (priv->border_window[GDK_WINDOW_EDGE_WEST]);
       gdk_window_show (priv->border_window[GDK_WINDOW_EDGE_EAST]);
@@ -6352,7 +6360,7 @@ _gtk_window_set_allocation (GtkWindow           *window,
 
   gtk_widget_set_allocation (widget, allocation);
 
-  get_decoration_borders (widget, &window_border, NULL);
+  get_decoration_size (widget, &window_border);
   border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
 
   child_allocation.x = 0;
@@ -6407,7 +6415,7 @@ _gtk_window_set_allocation (GtkWindow           *window,
         {
           update_grip_visibility (window);
           set_grip_position (window);
-          update_border_windows (window, &window_border);
+          update_border_windows (window);
         }
     }
 
@@ -6554,6 +6562,7 @@ gtk_window_style_updated (GtkWidget *widget)
 {
   GtkWindow *window = GTK_WINDOW (widget);
   GtkWindowPrivate *priv = window->priv;
+  GdkRGBA transparent = { 0.0, 0.0, 0.0, 0.0 };
   GdkRectangle rect;
 
   GTK_WIDGET_CLASS (gtk_window_parent_class)->style_updated (widget);
@@ -6566,6 +6575,13 @@ gtk_window_style_updated (GtkWidget *widget)
 
       set_grip_shape (window);
     }
+
+  if (gtk_widget_get_realized (widget))
+    {
+      gdk_window_set_background_rgba (gtk_widget_get_window (widget),
+                                      &transparent);
+      gtk_widget_queue_resize (widget);
+    }
 }
 
 static void
@@ -6783,12 +6799,10 @@ gtk_window_get_resize_grip_area (GtkWindow    *window,
 
   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
 
-  if (!window->priv->has_resize_grip)
+  if (!priv->has_resize_grip)
     return FALSE;
 
-  if (priv->client_decorated)
-    get_decoration_borders (widget, &window_border, NULL);
-
+  get_decoration_size (widget, &window_border);
   gtk_widget_get_allocation (widget, &allocation);
 
   gtk_widget_style_get (widget,
@@ -7449,7 +7463,7 @@ gtk_window_get_preferred_width (GtkWidget *widget,
   if (priv->decorated &&
       !priv->fullscreen)
     {
-      get_decoration_borders (widget, &window_border, NULL);
+      get_decoration_size (widget, &window_border);
 
       if (priv->title_box != NULL)
         gtk_widget_get_preferred_width (priv->title_box,
@@ -7498,7 +7512,7 @@ gtk_window_get_preferred_width_for_height (GtkWidget *widget,
   if (priv->decorated &&
       !priv->fullscreen)
     {
-      get_decoration_borders (widget, &window_border, NULL);
+      get_decoration_size (widget, &window_border);
 
       if (priv->title_box != NULL)
         gtk_widget_get_preferred_width_for_height (priv->title_box,
@@ -7551,7 +7565,7 @@ gtk_window_get_preferred_height (GtkWidget *widget,
   if (priv->decorated &&
       !priv->fullscreen)
     {
-      get_decoration_borders (widget, &window_border, NULL);
+      get_decoration_size (widget, &window_border);
 
       if (priv->title_box != NULL)
         gtk_widget_get_preferred_height (priv->title_box,
@@ -7602,7 +7616,7 @@ gtk_window_get_preferred_height_for_width (GtkWidget *widget,
   if (priv->decorated &&
       !priv->fullscreen)
     {
-      get_decoration_borders (widget, &window_border, NULL);
+      get_decoration_size (widget, &window_border);
 
       if (priv->title_box != NULL)
         gtk_widget_get_preferred_height_for_width (priv->title_box,
@@ -8827,17 +8841,14 @@ gtk_window_draw (GtkWidget *widget,
   GtkStyleContext *context;
   gboolean ret = FALSE;
   GtkAllocation allocation;
-  GtkBorder inner_border = { 0 };
-  GtkBorder outer_border = { 0 };
+  GtkBorder window_border;
   gint title_height;
 
   context = gtk_widget_get_style_context (widget);
 
+  get_decoration_size (widget, &window_border);
   gtk_widget_get_allocation (widget, &allocation);
 
-  if (priv->client_decorated)
-    get_decoration_borders (widget, &inner_border, &outer_border);
-
   if (!gtk_widget_get_app_paintable (widget) &&
       gtk_cairo_should_draw_window (cr, gtk_widget_get_window (widget)))
     {
@@ -8848,25 +8859,22 @@ gtk_window_draw (GtkWidget *widget,
         {
           gtk_style_context_save (context);
 
-          gtk_style_context_add_class (context, "window-border");
+          gtk_style_context_remove_class (context, GTK_STYLE_CLASS_BACKGROUND);
+          gtk_style_context_add_class (context, "window-frame");
+
           gtk_render_background (context, cr,
-                                 inner_border.left + outer_border.left,
-                                 inner_border.top + outer_border.top,
+                                 window_border.left, window_border.top,
                                  allocation.width -
-                                 (inner_border.left + inner_border.right +
-                                  outer_border.left + outer_border.right),
+                                 (window_border.left + window_border.right),
                                  allocation.height -
-                                 (inner_border.top + inner_border.bottom +
-                                  outer_border.top + outer_border.bottom));
+                                 (window_border.top + window_border.bottom));
           gtk_render_frame (context, cr,
-                            outer_border.left,
-                            outer_border.top,
-                            allocation.width - (outer_border.left + outer_border.right),
-                            allocation.height - (outer_border.top + outer_border.bottom));
-          gtk_style_context_remove_class (context, "window-border");
-          gtk_style_context_add_class (context, "window-outer-border");
-          gtk_render_frame (context, cr,
-                            0, 0, allocation.width, allocation.height);
+                            window_border.left, window_border.top,
+                            allocation.width -
+                            (window_border.left + window_border.right),
+                            allocation.height -
+                            (window_border.top + window_border.bottom));
+
           gtk_style_context_restore (context);
         }
 
@@ -8874,20 +8882,23 @@ gtk_window_draw (GtkWidget *widget,
         title_height = gtk_widget_get_allocated_height (priv->title_box);
       else
         title_height = 0;
-      gtk_style_context_save (context);
-      gtk_style_context_add_class (context, "window-content");
+
       gtk_render_background (context, cr,
-                             inner_border.left + outer_border.left,
-                             inner_border.top + outer_border.top +
-                             title_height,
+                             window_border.left,
+                             window_border.top + title_height,
                              allocation.width -
-                             (inner_border.left + inner_border.right +
-                              outer_border.left + outer_border.right),
+                             (window_border.left + window_border.right),
                              allocation.height -
-                             (inner_border.top + inner_border.bottom +
-                              outer_border.top + outer_border.bottom +
+                             (window_border.top + window_border.bottom +
                               title_height));
-      gtk_style_context_restore (context);
+      gtk_render_frame (context, cr,
+                        window_border.left,
+                        window_border.top + title_height,
+                        allocation.width -
+                        (window_border.left + window_border.right),
+                        allocation.height -
+                        (window_border.top + window_border.bottom +
+                         title_height));
     }
 
   if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)


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