{
}
+static cairo_region_t *
+create_offset_region (const cairo_region_t *region,
+ int dx,
+ int dy)
+{
+ cairo_region_t *result;
+
+ if (region == NULL)
+ return NULL;
+
+ result = cairo_region_copy (region);
+ cairo_region_translate (result, -dx, -dy);
+
+ return result;
+}
+
static GskRenderNode *
-gtk_snapshot_collect_default (GtkSnapshot *snapshot,
- GtkSnapshotState *state,
- GskRenderNode **nodes,
- guint n_nodes,
- const char *name)
+gtk_snapshot_collect_default (GtkSnapshot *snapshot,
+ GtkSnapshotState *state,
+ GskRenderNode **nodes,
+ guint n_nodes,
+ const char *name)
{
GskRenderNode *node;
g_clear_pointer (&state->name, g_free);
}
+static GtkSnapshot *
+gtk_snapshot_new_internal (gboolean record_names,
+ cairo_region_t *clip,
+ char *name)
+{
+ GtkSnapshot *snapshot;
+
+ snapshot = g_object_new (GTK_TYPE_SNAPSHOT, NULL);
+
+ snapshot->record_names = record_names;
+ snapshot->state_stack = g_array_new (FALSE, TRUE, sizeof (GtkSnapshotState));
+ g_array_set_clear_func (snapshot->state_stack, (GDestroyNotify)gtk_snapshot_state_clear);
+ snapshot->nodes = g_ptr_array_new_with_free_func ((GDestroyNotify)gsk_render_node_unref);
+
+ gtk_snapshot_push_state (snapshot,
+ name,
+ clip,
+ 0, 0,
+ gtk_snapshot_collect_default);
+
+ return snapshot;
+}
+
/**
* gtk_snapshot_new:
* @record_names: whether to keep node names (for debugging purposes)
const char *name,
...)
{
- GtkSnapshot *snapshot;
char *str;
if (name && record_names)
else
str = NULL;
- snapshot = g_object_new (GTK_TYPE_SNAPSHOT, NULL);
+ return gtk_snapshot_new_internal (record_names,
+ (cairo_region_t *) clip,
+ str);
+}
- snapshot->record_names = record_names;
- snapshot->state_stack = g_array_new (FALSE, TRUE, sizeof (GtkSnapshotState));
- g_array_set_clear_func (snapshot->state_stack, (GDestroyNotify)gtk_snapshot_state_clear);
- snapshot->nodes = g_ptr_array_new_with_free_func ((GDestroyNotify)gsk_render_node_unref);
+GtkSnapshot *
+gtk_snapshot_new_child (GtkSnapshot *parent,
+ const char *name,
+ ...)
+{
+ GtkSnapshotState *parent_state;
+ GtkSnapshot *snapshot;
+ cairo_region_t *clip;
+ char *str;
- gtk_snapshot_push_state (snapshot,
- str,
- (cairo_region_t *) clip,
- 0, 0,
- gtk_snapshot_collect_default);
+ if (name && parent->record_names)
+ {
+ va_list args;
+
+ va_start (args, name);
+ str = g_strdup_vprintf (name, args);
+ va_end (args);
+ }
+ else
+ str = NULL;
+
+ parent_state = gtk_snapshot_get_current_state (parent);
+ clip = create_offset_region (parent_state->clip_region,
+ parent_state->translate_x,
+ parent_state->translate_y);
+
+ snapshot = gtk_snapshot_new_internal (parent->record_names,
+ clip,
+ str);
+
+ if (clip)
+ cairo_region_destroy (clip);
return snapshot;
}
else
str = NULL;
- if (state->clip_region)
- {
- offset_clip = cairo_region_copy (state->clip_region);
- if (state->translate_x != floor (state->translate_x))
- {
- cairo_region_translate (offset_clip, -1, 0);
- cairo_region_union (offset_clip, state->clip_region);
- if (state->translate_y != floor (state->translate_y))
- {
- cairo_region_t *tmp = cairo_region_copy (offset_clip);
- cairo_region_translate (offset_clip, 0, -1);
- cairo_region_union (offset_clip, tmp);
- cairo_region_destroy (tmp);
- }
- }
- else if (state->translate_y != floor (state->translate_y))
- {
- cairo_region_translate (offset_clip, 0, -1);
- cairo_region_union (offset_clip, state->clip_region);
- }
- cairo_region_translate (offset_clip,
- - floor (state->translate_x),
- - floor (state->translate_y));
+ offset_clip = create_offset_region (state->clip_region,
+ state->translate_x,
+ state->translate_y);
- }
- else
- {
- offset_clip = NULL;
- }
state = gtk_snapshot_push_state (snapshot,
str,
offset_clip,
#include "gtkselection.h"
#include "gtksettingsprivate.h"
#include "gtksizegroup-private.h"
-#include "gtksnapshot.h"
+#include "gtksnapshotprivate.h"
#include "gtkstylecontextprivate.h"
#include "gtktooltipprivate.h"
#include "gtktypebuiltins.h"
priv->sensitive = TRUE;
priv->alloc_needed = TRUE;
priv->alloc_needed_on_child = TRUE;
+ priv->draw_needed = TRUE;
priv->focus_on_click = TRUE;
#ifdef G_ENABLE_DEBUG
priv->highlight_resize = FALSE;
g_object_ref (widget);
gtk_widget_push_verify_invariants (widget);
- if (!_gtk_widget_get_has_surface (widget))
- gtk_widget_queue_draw (widget);
+ gtk_widget_queue_draw (widget);
_gtk_tooltip_hide (widget);
g_signal_emit (widget, widget_signals[UNMAP], 0);
cairo_region_destroy (region);
}
+static void
+gtk_widget_real_queue_draw (GtkWidget *widget)
+{
+ for (; widget; widget = _gtk_widget_get_parent (widget))
+ {
+ GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
+
+ if (priv->draw_needed)
+ break;
+
+ priv->draw_needed = TRUE;
+ g_clear_pointer (&priv->render_node, gsk_render_node_unref);
+ }
+}
+
/**
* gtk_widget_queue_draw:
* @widget: a #GtkWidget
g_return_if_fail (GTK_IS_WIDGET (widget));
+ gtk_widget_real_queue_draw (widget);
+
parent = _gtk_widget_get_parent (widget);
rect = &widget->priv->clip;
if (!_gtk_widget_get_mapped (widget))
return;
+ gtk_widget_real_queue_draw (widget);
+
if (!_gtk_widget_get_parent (widget))
{
g_assert (_gtk_widget_get_has_surface (widget));
* are relative to */
gtk_widget_queue_draw_region (parent ? parent : widget, invalidate);
cairo_region_destroy (invalidate);
+ gtk_widget_real_queue_draw (widget);
}
}
#endif
}
-void
-gtk_widget_snapshot (GtkWidget *widget,
- GtkSnapshot *snapshot)
+static GskRenderNode *
+gtk_widget_create_render_node (GtkWidget *widget,
+ GtkSnapshot *parent_snapshot)
{
GtkWidgetClass *klass = GTK_WIDGET_GET_CLASS (widget);
- GtkWidgetPrivate *priv;
+ GtkWidgetPrivate *priv = widget->priv;
GtkCssValue *filter_value;
RenderMode mode;
double opacity;
- cairo_rectangle_int_t offset_clip;
GtkCssStyle *style;
GtkAllocation allocation;
GtkBorder margin, border, padding;
+ GtkSnapshot *snapshot;
- if (!_gtk_widget_is_drawable (widget))
- return;
-
- if (_gtk_widget_get_alloc_needed (widget))
- {
- g_warning ("Trying to snapshot %s %p without a current allocation", G_OBJECT_TYPE_NAME (widget), widget);
- return;
- }
-
- priv = widget->priv;
- offset_clip = priv->clip;
- offset_clip.x -= priv->allocation.x;
- offset_clip.y -= priv->allocation.y;
-
- if (gtk_snapshot_clips_rect (snapshot, &offset_clip))
- return;
-
- opacity = widget->priv->alpha / 255.0;
- if (opacity <= 0.0)
- return;
+ snapshot = gtk_snapshot_new_child (parent_snapshot, "%s<%p>", gtk_widget_get_name (widget), widget);
/* Compatibility mode: if the widget does not have a render node, we draw
* using gtk_widget_draw() on a temporary node
*/
mode = get_render_mode (klass);
- if (GTK_DEBUG_CHECK (SNAPSHOT))
- gtk_snapshot_push (snapshot, TRUE, "%s<%p>", gtk_widget_get_name (widget), widget);
-
filter_value = _gtk_style_context_peek_property (_gtk_widget_get_style_context (widget), GTK_CSS_PROPERTY_FILTER);
gtk_css_filter_value_push_snapshot (filter_value, snapshot);
get_box_margin (style, &margin);
get_box_border (style, &border);
get_box_padding (style, &padding);
+ opacity = widget->priv->alpha / 255.0;
_gtk_widget_get_allocation (widget, &allocation);
{
cairo_t *cr;
graphene_rect_t bounds;
+ cairo_rectangle_int_t offset_clip;
+
+ offset_clip = priv->clip;
+ offset_clip.x -= priv->allocation.x;
+ offset_clip.y -= priv->allocation.y;
graphene_rect_init (&bounds,
offset_clip.x,
gboolean result;
cairo_t *cr;
graphene_rect_t bounds;
+ cairo_rectangle_int_t offset_clip;
+
+ offset_clip = priv->clip;
+ offset_clip.x -= priv->allocation.x;
+ offset_clip.y -= priv->allocation.y;
graphene_rect_init (&bounds,
offset_clip.x,
gtk_snapshot_pop (snapshot);
}
-
gtk_css_filter_value_pop_snapshot (filter_value, snapshot);
#ifdef G_ENABLE_DEBUG
gtk_widget_maybe_add_debug_render_nodes (widget, snapshot);
#endif
+ return gtk_snapshot_free_to_node (snapshot);
+}
+
+void
+gtk_widget_snapshot (GtkWidget *widget,
+ GtkSnapshot *snapshot)
+{
+ GtkWidgetPrivate *priv = widget->priv;
+ cairo_rectangle_int_t offset_clip;
+ double opacity;
+
+ if (!_gtk_widget_is_drawable (widget))
+ return;
+
+ if (_gtk_widget_get_alloc_needed (widget))
+ {
+ g_warning ("Trying to snapshot %s %p without a current allocation", G_OBJECT_TYPE_NAME (widget), widget);
+ return;
+ }
+
+ priv = widget->priv;
+ offset_clip = priv->clip;
+ offset_clip.x -= priv->allocation.x;
+ offset_clip.y -= priv->allocation.y;
+
+ if (gtk_snapshot_clips_rect (snapshot, &offset_clip))
+ return;
+
+ opacity = widget->priv->alpha / 255.0;
+ if (opacity <= 0.0)
+ return;
+
+ if (priv->draw_needed)
+ {
+ g_assert (priv->render_node == NULL);
+ priv->render_node = gtk_widget_create_render_node (widget, snapshot);
+ priv->draw_needed = FALSE;
+ }
- if (GTK_DEBUG_CHECK (SNAPSHOT))
- gtk_snapshot_pop (snapshot);
+ if (priv->render_node)
+ gtk_snapshot_append_node (snapshot, priv->render_node);
}
static gboolean
GtkSnapshot *snapshot;
GskRenderer *renderer;
GskRenderNode *root;
- cairo_region_t *clip;
/* We only render double buffered on native windows */
if (!gdk_surface_has_native (surface))
return;
context = gsk_renderer_begin_draw_frame (renderer, region);
- clip = gdk_drawing_context_get_clip (context);
snapshot = gtk_snapshot_new (should_record_names (widget, renderer),
- clip,
+ NULL,
"Render<%s>", G_OBJECT_TYPE_NAME (widget));
- cairo_region_destroy (clip);
gtk_widget_snapshot (widget, snapshot);
root = gtk_snapshot_free_to_node (snapshot);
if (root != NULL)