[gtk+/wip/matthiasc/gadget] Redo frame gadgetization



commit 124f69d30e980babf59d7ef99198a5c76a0b1ed0
Author: Matthias Clasen <mclasen redhat com>
Date:   Thu Dec 10 22:45:15 2015 -0500

    Redo frame gadgetization
    
    Use gadget drawing for the frame, but clip out the label
    allocation. Also, rename the decoration node to border
    to avoid inheritance from window decorations.

 gtk/gtkframe.c                           |  175 +++++++++++++++++-------------
 gtk/theme/Adwaita/_common.scss           |    6 +-
 gtk/theme/Adwaita/gtk-contained-dark.css |   12 ++-
 gtk/theme/Adwaita/gtk-contained.css      |   12 ++-
 4 files changed, 118 insertions(+), 87 deletions(-)
---
diff --git a/gtk/gtkframe.c b/gtk/gtkframe.c
index e59a498..0350d37 100644
--- a/gtk/gtkframe.c
+++ b/gtk/gtkframe.c
@@ -37,6 +37,7 @@
 #include "gtkcontainerprivate.h"
 #include "gtkstylecontextprivate.h"
 #include "gtkcssstylepropertyprivate.h"
+#include "gtklabel.h"
 
 #include "a11y/gtkframeaccessible.h"
 
@@ -86,7 +87,7 @@ struct _GtkFramePrivate
   GtkWidget *label_widget;
 
   GtkCssGadget *gadget;
-  GtkCssNode *decoration_node;
+  GtkCssGadget *border_gadget;
 
   gint16 shadow_type;
   gfloat label_xalign;
@@ -109,6 +110,7 @@ enum {
 
 static GParamSpec *frame_props[LAST_PROP];
 
+static void gtk_frame_finalize     (GObject      *object);
 static void gtk_frame_set_property (GObject      *object,
                                    guint         param_id,
                                    const GValue *value,
@@ -170,6 +172,11 @@ static void     gtk_frame_allocate       (GtkCssGadget        *gadget,
                                           int                  baseline,
                                           GtkAllocation       *out_clip,
                                           gpointer             data);
+static void     gtk_frame_allocate_border (GtkCssGadget        *gadget,
+                                          const GtkAllocation *allocation,
+                                          int                  baseline,
+                                          GtkAllocation       *out_clip,
+                                          gpointer             data);
 static gboolean gtk_frame_render         (GtkCssGadget        *gadget,
                                           cairo_t             *cr,
                                           int                  x,
@@ -195,6 +202,7 @@ gtk_frame_class_init (GtkFrameClass *class)
   widget_class = GTK_WIDGET_CLASS (class);
   container_class = GTK_CONTAINER_CLASS (class);
 
+  gobject_class->finalize = gtk_frame_finalize;
   gobject_class->set_property = gtk_frame_set_property;
   gobject_class->get_property = gtk_frame_get_property;
 
@@ -276,29 +284,6 @@ gtk_frame_buildable_add_child (GtkBuildable *buildable,
 }
 
 static void
-node_style_changed_cb (GtkCssNode  *node,
-                       GtkCssStyle *old_style,
-                       GtkCssStyle *new_style,
-                       GtkWidget   *widget)
-{
-  GtkBitmask *changes;
-  static GtkBitmask *affects_size = NULL;
-
-  if (G_UNLIKELY (affects_size == NULL))
-    affects_size = _gtk_css_style_property_get_mask_affecting (GTK_CSS_AFFECTS_SIZE | GTK_CSS_AFFECTS_CLIP);
-
-  changes = _gtk_bitmask_new ();
-  changes = gtk_css_style_add_difference (changes, old_style, new_style);
-
-  if (_gtk_bitmask_intersects (changes, affects_size))
-    gtk_widget_queue_resize (widget);
-  else
-    gtk_widget_queue_draw (widget);
-
-  _gtk_bitmask_free (changes);
-}
-
-static void
 gtk_frame_init (GtkFrame *frame)
 {
   GtkFramePrivate *priv;
@@ -320,12 +305,27 @@ gtk_frame_init (GtkFrame *frame)
                                                      gtk_frame_render,
                                                      NULL,
                                                      NULL);
-  priv->decoration_node = gtk_css_node_new ();
-  gtk_css_node_set_name (priv->decoration_node, I_("decoration"));
-  gtk_css_node_set_parent (priv->decoration_node, widget_node);
-  gtk_css_node_set_state (priv->decoration_node, gtk_css_node_get_state (widget_node));
-  g_signal_connect_object (priv->decoration_node, "style-changed", G_CALLBACK (node_style_changed_cb), 
frame, 0);
-  g_object_unref (priv->decoration_node);
+  priv->border_gadget = gtk_css_custom_gadget_new ("border",
+                                                       GTK_WIDGET (frame),
+                                                       priv->gadget,
+                                                       NULL,
+                                                       NULL,
+                                                       gtk_frame_allocate_border,
+                                                       NULL,
+                                                       NULL,
+                                                       NULL);
+}
+
+static void
+gtk_frame_finalize (GObject *object)
+{
+  GtkFrame *frame = GTK_FRAME (object);
+  GtkFramePrivate *priv = frame->priv;
+
+  g_clear_object (&priv->border_gadget);
+  g_clear_object (&priv->gadget);
+
+  G_OBJECT_CLASS (gtk_frame_parent_class)->finalize (object);
 }
 
 static void 
@@ -661,9 +661,9 @@ gtk_frame_set_shadow_type (GtkFrame      *frame,
       priv->shadow_type = type;
 
       if (type == GTK_SHADOW_NONE)
-        gtk_css_node_add_class (priv->decoration_node, g_quark_from_static_string (GTK_STYLE_CLASS_FLAT));
+        gtk_css_gadget_add_class (priv->border_gadget, GTK_STYLE_CLASS_FLAT);
       else
-        gtk_css_node_remove_class (priv->decoration_node, g_quark_from_static_string (GTK_STYLE_CLASS_FLAT));
+        gtk_css_gadget_remove_class (priv->border_gadget, GTK_STYLE_CLASS_FLAT);
 
       g_object_notify_by_pspec (G_OBJECT (frame), frame_props[PROP_SHADOW_TYPE]);
     }
@@ -706,54 +706,45 @@ gtk_frame_render (GtkCssGadget *gadget,
 {
   GtkWidget *widget;
   GtkFramePrivate *priv;
-  GtkStyleContext *context;
+  gint xc, yc, w, h;
   GtkAllocation allocation;
 
   widget = gtk_css_gadget_get_owner (gadget);
   priv = GTK_FRAME (widget)->priv;
 
-  context = gtk_widget_get_style_context (widget);
-  gtk_style_context_save_to_node (context, priv->decoration_node);
-
+  cairo_save (cr);
 
   gtk_widget_get_allocation (widget, &allocation);
-  x = priv->child_allocation.x - allocation.x;
-  y = priv->child_allocation.y - allocation.y;
-  width = priv->child_allocation.width;
-  height = priv->child_allocation.height;
-
-  if (priv->label_widget)
-    {
-      gfloat xalign;
-      gint height_extra;
-      gint x2;
-
-      if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
-        xalign = priv->label_xalign;
-      else
-        xalign = 1 - priv->label_xalign;
-
-      height_extra = (1 - priv->label_yalign) * priv->label_allocation.height;
-      y -= height_extra;
-      height += height_extra;
 
-      x2 = (priv->child_allocation.width - priv->label_allocation.width) * xalign;
+  /* We want to use the standard gadget drawing for the border,
+   * so we clip out the label allocation in order to get the
+   * frame gap.
+   */
+  xc = priv->label_allocation.x - allocation.x;
+  yc = y;
+  w = priv->label_allocation.width;
+  h = priv->label_allocation.height;
 
-      /* If the label is completely over or under the frame we can omit the gap */
-      if (priv->label_yalign == 0.0 || priv->label_yalign == 1.0)
-        gtk_render_frame (context, cr, x, y, width, height);
-      else
-        gtk_render_frame_gap (context, cr,
-                              x, y, width, height,
-                              GTK_POS_TOP,
-                              x2, x2 + priv->label_allocation.width);
-    }
-  else
+  if (GTK_IS_LABEL (priv->label_widget))
     {
-      gtk_render_frame (context, cr, x, y, width, height);
+      PangoRectangle ink_rect;
+
+      /* Shrink the clip area for labels, so we get unclipped
+       * frames for the yalign 0.0 and 1.0 cases.
+       */
+      pango_layout_get_pixel_extents (gtk_label_get_layout (GTK_LABEL (priv->label_widget)), &ink_rect, 
NULL);
+      yc += (h - ink_rect.height) / 2;
+      h = ink_rect.height;
     }
 
-  gtk_style_context_restore (context);
+  cairo_rectangle (cr, 0, 0, allocation.width, allocation.height);
+  cairo_rectangle (cr, xc + w, yc, - w, h);
+  cairo_set_fill_rule (cr, CAIRO_FILL_RULE_WINDING);
+  cairo_clip (cr);
+
+  gtk_css_gadget_draw (priv->border_gadget, cr);
+
+  cairo_restore (cr);
 
   GTK_WIDGET_CLASS (gtk_frame_parent_class)->draw (widget, cr);
 
@@ -787,18 +778,15 @@ gtk_frame_allocate (GtkCssGadget        *gadget,
   GtkFrame *frame;
   GtkFramePrivate *priv;
   GtkAllocation new_allocation;
-  GtkWidget *child;
+  GtkAllocation frame_allocation;
+  gint height_extra;
+  GtkAllocation clip;
 
   widget = gtk_css_gadget_get_owner (gadget);
   frame = GTK_FRAME (widget);
   priv = frame->priv;
 
   gtk_frame_compute_child_allocation (frame, &new_allocation);
-
-  child = gtk_bin_get_child (GTK_BIN (widget));
-  if (child && gtk_widget_get_visible (child))
-    gtk_widget_size_allocate (child, &new_allocation);
-
   priv->child_allocation = new_allocation;
 
   if (priv->label_widget && gtk_widget_get_visible (priv->label_widget))
@@ -821,9 +809,41 @@ gtk_frame_allocate (GtkCssGadget        *gadget,
       priv->label_allocation.width = width;
 
       gtk_widget_size_allocate (priv->label_widget, &priv->label_allocation);
+
+      height_extra = (1 - priv->label_yalign) * height;
     }
+  else
+    height_extra = 0;
+
+  frame_allocation.x = priv->child_allocation.x;
+  frame_allocation.y = priv->child_allocation.y - height_extra;
+  frame_allocation.width = priv->child_allocation.width;
+  frame_allocation.height = priv->child_allocation.height + height_extra;
+
+  gtk_css_gadget_allocate (priv->border_gadget,
+                           &frame_allocation,
+                           -1,
+                           &clip);
 
   gtk_container_get_children_clip (GTK_CONTAINER (widget), out_clip);
+  gdk_rectangle_union (out_clip, &clip, out_clip);
+}
+
+static void
+gtk_frame_allocate_border (GtkCssGadget        *gadget,
+                           const GtkAllocation *allocation,
+                           int                  baseline,
+                           GtkAllocation       *out_clip,
+                           gpointer             data)
+{
+  GtkWidget *widget;
+  GtkWidget *child;
+
+  widget = gtk_css_gadget_get_owner (gadget);
+
+  child = gtk_bin_get_child (GTK_BIN (widget));
+  if (child && gtk_widget_get_visible (child))
+    gtk_widget_size_allocate (child, (GtkAllocation *)allocation);
 }
 
 static void
@@ -863,6 +883,8 @@ gtk_frame_real_compute_child_allocation (GtkFrame      *frame,
   child_allocation->y = allocation.y + border_width + height;
   child_allocation->width = MAX (1, allocation.width - 2 * border_width);
   child_allocation->height = MAX (1, allocation.height - 2 * border_width - height);
+
+
 }
 
 static void
@@ -994,7 +1016,10 @@ static void
 gtk_frame_state_flags_changed (GtkWidget     *widget,
                                GtkStateFlags  previous_state)
 {
-  gtk_css_node_set_state (GTK_FRAME (widget)->priv->decoration_node, gtk_widget_get_state_flags (widget));
+  GtkCssNode *border_node;
+
+  border_node = gtk_css_gadget_get_node (GTK_FRAME (widget)->priv->border_gadget);
+  gtk_css_node_set_state (border_node, gtk_widget_get_state_flags (widget));
 
   GTK_WIDGET_CLASS (gtk_frame_parent_class)->state_flags_changed (widget, previous_state);
 }
diff --git a/gtk/theme/Adwaita/_common.scss b/gtk/theme/Adwaita/_common.scss
index 2187070..f6c38e8 100644
--- a/gtk/theme/Adwaita/_common.scss
+++ b/gtk/theme/Adwaita/_common.scss
@@ -2488,13 +2488,15 @@ levelbar {
 /**********
  * Frames *
  **********/
-frame decoration,
+frame border,
 .frame {
+  box-shadow: none;
+  margin: 0;
+  padding: 0;
   border-radius: 0;
   border: 1px solid $borders_color;
   &.flat { border-style: none; }
   &:backdrop { border-color: $backdrop_borders_color; }
-  padding: 0;
 }
 
 paper {
diff --git a/gtk/theme/Adwaita/gtk-contained-dark.css b/gtk/theme/Adwaita/gtk-contained-dark.css
index faee2a5..5ba7547 100644
--- a/gtk/theme/Adwaita/gtk-contained-dark.css
+++ b/gtk/theme/Adwaita/gtk-contained-dark.css
@@ -3429,15 +3429,17 @@ levelbar {
 /**********
  * Frames *
  **********/
-frame decoration,
+frame border,
 .frame {
+  box-shadow: none;
+  margin: 0;
+  padding: 0;
   border-radius: 0;
-  border: 1px solid #1c1f1f;
-  padding: 0; }
-  frame decoration.flat,
+  border: 1px solid #1c1f1f; }
+  frame border.flat,
   .frame.flat {
     border-style: none; }
-  frame decoration:backdrop,
+  frame border:backdrop,
   .frame:backdrop {
     border-color: #1f2222; }
 
diff --git a/gtk/theme/Adwaita/gtk-contained.css b/gtk/theme/Adwaita/gtk-contained.css
index 9669221..9e860d7 100644
--- a/gtk/theme/Adwaita/gtk-contained.css
+++ b/gtk/theme/Adwaita/gtk-contained.css
@@ -3591,15 +3591,17 @@ levelbar {
 /**********
  * Frames *
  **********/
-frame decoration,
+frame border,
 .frame {
+  box-shadow: none;
+  margin: 0;
+  padding: 0;
   border-radius: 0;
-  border: 1px solid #a1a1a1;
-  padding: 0; }
-  frame decoration.flat,
+  border: 1px solid #a1a1a1; }
+  frame border.flat,
   .frame.flat {
     border-style: none; }
-  frame decoration:backdrop,
+  frame border:backdrop,
   .frame:backdrop {
     border-color: darkgray; }
 


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