[gtk+/wip/matthiasc/gadget] Redo frame gadgetization
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/matthiasc/gadget] Redo frame gadgetization
- Date: Fri, 11 Dec 2015 04:13:39 +0000 (UTC)
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]