forked from AuroraMiddleware/gtk
c34f98931e
We have a region for the border here, but the color is defined as transparent black because we don't want to render anything for it. This way, the generated .node file for the listbox demo in gtk4-demo with enabled layout borders is 3.5MB instead of 3.8MB.
190 lines
5.4 KiB
C
190 lines
5.4 KiB
C
|
|
#include "config.h"
|
|
#include "layoutoverlay.h"
|
|
#include "gtkwidgetprivate.h"
|
|
#include "gtkcssstyleprivate.h"
|
|
#include "gtkcssnodeprivate.h"
|
|
#include "gtkcssnumbervalueprivate.h"
|
|
#include "gtknative.h"
|
|
|
|
struct _GtkLayoutOverlay
|
|
{
|
|
GtkInspectorOverlay parent_instance;
|
|
};
|
|
|
|
struct _GtkLayoutOverlayClass
|
|
{
|
|
GtkInspectorOverlayClass parent_class;
|
|
};
|
|
|
|
G_DEFINE_TYPE (GtkLayoutOverlay, gtk_layout_overlay, GTK_TYPE_INSPECTOR_OVERLAY)
|
|
|
|
|
|
static int
|
|
get_number (GtkCssValue *value)
|
|
{
|
|
double d = _gtk_css_number_value_get (value, 100);
|
|
|
|
if (d < 1)
|
|
return ceil (d);
|
|
else
|
|
return floor (d);
|
|
}
|
|
|
|
static void
|
|
get_box_margin (GtkCssStyle *style,
|
|
GtkBorder *margin)
|
|
{
|
|
margin->top = get_number (style->size->margin_top);
|
|
margin->left = get_number (style->size->margin_left);
|
|
margin->bottom = get_number (style->size->margin_bottom);
|
|
margin->right = get_number (style->size->margin_right);
|
|
}
|
|
|
|
static void
|
|
get_box_border (GtkCssStyle *style,
|
|
GtkBorder *border)
|
|
{
|
|
border->top = get_number (style->border->border_top_width);
|
|
border->left = get_number (style->border->border_left_width);
|
|
border->bottom = get_number (style->border->border_bottom_width);
|
|
border->right = get_number (style->border->border_right_width);
|
|
}
|
|
|
|
static void
|
|
get_box_padding (GtkCssStyle *style,
|
|
GtkBorder *border)
|
|
{
|
|
border->top = get_number (style->size->padding_top);
|
|
border->left = get_number (style->size->padding_left);
|
|
border->bottom = get_number (style->size->padding_bottom);
|
|
border->right = get_number (style->size->padding_right);
|
|
}
|
|
|
|
static void
|
|
recurse_child_widgets (GtkWidget *widget,
|
|
GtkSnapshot *snapshot)
|
|
{
|
|
int width = gtk_widget_get_width (widget);
|
|
int height = gtk_widget_get_height (widget);
|
|
gboolean needs_clip;
|
|
GtkCssStyle *style;
|
|
GtkWidget *child;
|
|
GtkBorder boxes[4];
|
|
const GdkRGBA colors[4] = {
|
|
{0.7, 0.0, 0.7, 0.6}, /* Padding */
|
|
{0.0, 0.0, 0.0, 0.0}, /* Border */
|
|
{0.7, 0.7, 0.0, 0.6}, /* CSS Margin */
|
|
{0.7, 0.0, 0.0, 0.6}, /* Widget Margin */
|
|
};
|
|
int i;
|
|
|
|
if (!gtk_widget_get_mapped (widget))
|
|
return;
|
|
|
|
G_STATIC_ASSERT (G_N_ELEMENTS (boxes) == G_N_ELEMENTS (colors));
|
|
|
|
style = gtk_css_node_get_style (gtk_widget_get_css_node (widget));
|
|
get_box_padding (style, &boxes[0]);
|
|
get_box_border (style, &boxes[1]);
|
|
get_box_margin (style, &boxes[2]);
|
|
|
|
/* TODO: Eh, left = start? RTL? */
|
|
boxes[3].left = gtk_widget_get_margin_start (widget);
|
|
boxes[3].top = gtk_widget_get_margin_top (widget);
|
|
boxes[3].right = gtk_widget_get_margin_end (widget);
|
|
boxes[3].bottom = gtk_widget_get_margin_bottom (widget);
|
|
|
|
/* width/height are the content size and we're going to grow that
|
|
* as we're drawing the boxes, as well as offset the origin.
|
|
* Right now we're at the widget's own origin.
|
|
*/
|
|
gtk_snapshot_save (snapshot);
|
|
gtk_snapshot_push_debug (snapshot, "Widget layout debugging");
|
|
|
|
for (i = 0; i < G_N_ELEMENTS (boxes); i ++)
|
|
{
|
|
const GdkRGBA *color = &colors[i];
|
|
const GtkBorder *box = &boxes[i];
|
|
|
|
if (gdk_rgba_is_clear (color))
|
|
goto next;
|
|
|
|
if (box->top > 0)
|
|
gtk_snapshot_append_color (snapshot, color,
|
|
&GRAPHENE_RECT_INIT ( 0, - box->top, width, box->top));
|
|
if (box->right > 0)
|
|
gtk_snapshot_append_color (snapshot, color,
|
|
&GRAPHENE_RECT_INIT (width, 0, box->right, height));
|
|
if (box->bottom > 0)
|
|
gtk_snapshot_append_color (snapshot, color,
|
|
&GRAPHENE_RECT_INIT (0, height, width, box->bottom));
|
|
if (box->left > 0)
|
|
gtk_snapshot_append_color (snapshot, color,
|
|
&GRAPHENE_RECT_INIT (- box->left, 0, box->left, height));
|
|
|
|
next:
|
|
/* Grow box + offset */
|
|
width += box->left + box->right;
|
|
height += box->top + box->bottom;
|
|
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (- box->left, - box->top));
|
|
}
|
|
|
|
gtk_snapshot_pop (snapshot);
|
|
|
|
|
|
needs_clip = gtk_widget_get_overflow (widget) == GTK_OVERFLOW_HIDDEN &&
|
|
gtk_widget_get_first_child (widget) != NULL;
|
|
|
|
if (needs_clip)
|
|
gtk_snapshot_push_clip (snapshot,
|
|
&GRAPHENE_RECT_INIT (0, 0, gtk_widget_get_width (widget), gtk_widget_get_height (widget)));
|
|
|
|
/* Recurse into child widgets */
|
|
for (child = gtk_widget_get_first_child (widget);
|
|
child != NULL;
|
|
child = gtk_widget_get_next_sibling (child))
|
|
{
|
|
gtk_snapshot_save (snapshot);
|
|
gtk_snapshot_transform (snapshot, child->priv->transform);
|
|
|
|
recurse_child_widgets (child, snapshot);
|
|
|
|
gtk_snapshot_restore (snapshot);
|
|
}
|
|
|
|
if (needs_clip)
|
|
gtk_snapshot_pop (snapshot);
|
|
|
|
gtk_snapshot_restore (snapshot);
|
|
}
|
|
|
|
static void
|
|
gtk_layout_overlay_snapshot (GtkInspectorOverlay *overlay,
|
|
GtkSnapshot *snapshot,
|
|
GskRenderNode *node,
|
|
GtkWidget *widget)
|
|
{
|
|
recurse_child_widgets (widget, snapshot);
|
|
}
|
|
|
|
static void
|
|
gtk_layout_overlay_init (GtkLayoutOverlay *self)
|
|
{
|
|
|
|
}
|
|
|
|
static void
|
|
gtk_layout_overlay_class_init (GtkLayoutOverlayClass *klass)
|
|
{
|
|
GtkInspectorOverlayClass *overlay_class = (GtkInspectorOverlayClass *)klass;
|
|
|
|
overlay_class->snapshot = gtk_layout_overlay_snapshot;
|
|
}
|
|
|
|
GtkInspectorOverlay *
|
|
gtk_layout_overlay_new (void)
|
|
{
|
|
return g_object_new (GTK_TYPE_LAYOUT_OVERLAY, NULL);
|
|
}
|