diff --git a/gtk/gtkaccellabel.c b/gtk/gtkaccellabel.c index 93b660af96..954b1d3939 100644 --- a/gtk/gtkaccellabel.c +++ b/gtk/gtkaccellabel.c @@ -139,8 +139,8 @@ static void gtk_accel_label_get_property (GObject *object, GParamSpec *pspec); static void gtk_accel_label_destroy (GtkWidget *widget); static void gtk_accel_label_finalize (GObject *object); -static GskRenderNode *gtk_accel_label_get_render_node (GtkWidget *widget, - GskRenderer *renderer); +static void gtk_accel_label_snapshot (GtkWidget *widget, + GtkSnapshot *snapshot); static const gchar *gtk_accel_label_get_string (GtkAccelLabel *accel_label); static void gtk_accel_label_measure (GtkWidget *widget, GtkOrientation orientation, @@ -163,7 +163,7 @@ gtk_accel_label_class_init (GtkAccelLabelClass *class) gobject_class->set_property = gtk_accel_label_set_property; gobject_class->get_property = gtk_accel_label_get_property; - widget_class->get_render_node = gtk_accel_label_get_render_node; + widget_class->snapshot = gtk_accel_label_snapshot; widget_class->measure = gtk_accel_label_measure; widget_class->destroy = gtk_accel_label_destroy; @@ -457,20 +457,26 @@ get_first_baseline (PangoLayout *layout) return PANGO_PIXELS (result); } -static GskRenderNode * -gtk_accel_label_get_render_node (GtkWidget *widget, - GskRenderer *renderer) +static void +gtk_accel_label_snapshot (GtkWidget *widget, + GtkSnapshot *snapshot) { GtkAccelLabel *accel_label = GTK_ACCEL_LABEL (widget); guint ac_width; - GtkAllocation allocation; + GtkAllocation allocation, clip; GtkRequisition requisition; - GskRenderNode *res; + graphene_rect_t bounds; - res = GTK_WIDGET_CLASS (gtk_accel_label_parent_class)->get_render_node (widget, renderer); + gtk_widget_get_clip (widget, &clip); + gtk_widget_get_allocation (widget, &allocation); + graphene_rect_init (&bounds, + clip.x - allocation.x, clip.y - allocation.y, + clip.width, clip.height); + gtk_snapshot_push (snapshot, &bounds, "AccelLabel"); + + GTK_WIDGET_CLASS (gtk_accel_label_parent_class)->snapshot (widget, snapshot); ac_width = gtk_accel_label_get_accel_width (accel_label); - gtk_widget_get_allocation (widget, &allocation); gtk_widget_get_preferred_size (widget, NULL, &requisition); if (allocation.width >= requisition.width + ac_width) @@ -480,17 +486,6 @@ gtk_accel_label_get_render_node (GtkWidget *widget, PangoLayout *accel_layout; gint x; gint y; - GtkAllocation alloc, clip; - GskRenderNode *node; - cairo_t *cr; - - node = gtk_widget_create_render_node (widget, renderer, "AccelLabel Content"); - - gtk_widget_get_clip (widget, &clip); - _gtk_widget_get_allocation (widget, &alloc); - - cr = gsk_render_node_get_draw_context (node, renderer); - cairo_translate (cr, alloc.x - clip.x, alloc.y - clip.y); context = gtk_widget_get_style_context (widget); @@ -507,18 +502,13 @@ gtk_accel_label_get_render_node (GtkWidget *widget, y += get_first_baseline (label_layout) - get_first_baseline (accel_layout) - allocation.y; gtk_style_context_save_to_node (context, accel_label->priv->accel_node); - gtk_render_layout (context, cr, x, y, accel_layout); + gtk_snapshot_render_layout (snapshot, context, x, y, accel_layout); gtk_style_context_restore (context); g_object_unref (accel_layout); - - cairo_destroy (cr); - - gsk_render_node_append_child (res, node); - gsk_render_node_unref (node); } - return res; + gtk_snapshot_pop (snapshot); } static void diff --git a/gtk/gtklabel.c b/gtk/gtklabel.c index 5461d3fa71..e9e6a69bf6 100644 --- a/gtk/gtklabel.c +++ b/gtk/gtklabel.c @@ -414,12 +414,11 @@ static void gtk_label_size_allocate (GtkWidget *widget, static void gtk_label_state_flags_changed (GtkWidget *widget, GtkStateFlags prev_state); static void gtk_label_style_updated (GtkWidget *widget); +static void gtk_label_snapshot (GtkWidget *widget, + GtkSnapshot *snapshot); static gboolean gtk_label_focus (GtkWidget *widget, GtkDirectionType direction); -static GskRenderNode *gtk_label_get_render_node (GtkWidget *label, - GskRenderer *renderer); - static void gtk_label_realize (GtkWidget *widget); static void gtk_label_unrealize (GtkWidget *widget); static void gtk_label_map (GtkWidget *widget); @@ -565,6 +564,13 @@ static void gtk_label_measure (GtkCssGadget *gadget, int *minimum_baseline, int *natural_baseline, gpointer unused); +static gboolean gtk_label_render (GtkCssGadget *gadget, + GtkSnapshot *snapshot, + int x, + int y, + int width, + int height, + gpointer data); static GtkBuildableIface *buildable_parent_iface = NULL; @@ -612,7 +618,7 @@ gtk_label_class_init (GtkLabelClass *class) widget_class->state_flags_changed = gtk_label_state_flags_changed; widget_class->style_updated = gtk_label_style_updated; widget_class->query_tooltip = gtk_label_query_tooltip; - widget_class->get_render_node = gtk_label_get_render_node; + widget_class->snapshot = gtk_label_snapshot; widget_class->realize = gtk_label_realize; widget_class->unrealize = gtk_label_unrealize; widget_class->map = gtk_label_map; @@ -1371,7 +1377,7 @@ gtk_label_init (GtkLabel *label) gtk_label_measure, NULL, NULL, - NULL, + gtk_label_render, NULL, NULL); } @@ -4153,41 +4159,38 @@ gtk_label_get_focus_link (GtkLabel *label) return NULL; } +static void +gtk_label_snapshot (GtkWidget *widget, + GtkSnapshot *snapshot) +{ + gtk_css_gadget_snapshot (GTK_LABEL (widget)->priv->gadget, snapshot); +} + static void layout_to_window_coords (GtkLabel *label, gint *x, gint *y); +#define GRAPHENE_RECT_FROM_RECT(_r) ((graphene_rect_t) GRAPHENE_RECT_INIT ((_r)->x, (_r)->y, (_r)->width, (_r)->height)) -static GskRenderNode * -gtk_label_get_render_node (GtkWidget *widget, - GskRenderer *renderer) +static gboolean +gtk_label_render (GtkCssGadget *gadget, + GtkSnapshot *snapshot, + int x, + int y, + int width, + int height, + gpointer data) { - GtkLabel *label = GTK_LABEL (widget); - GtkLabelPrivate *priv = label->priv; - GtkLabelSelectionInfo *info = priv->select_info; + GtkWidget *widget; + GtkLabel *label; + GtkLabelPrivate *priv; + GtkLabelSelectionInfo *info; GtkStyleContext *context; - gint x, y, width, height; gint lx, ly; - cairo_t *cr; - GtkAllocation alloc, clip; - GskRenderNode *node; - GskRenderNode *res; - res = gtk_css_gadget_get_render_node (priv->gadget, renderer, FALSE); - - if (res == NULL) - return NULL; - - node = gtk_widget_create_render_node (widget, renderer, "Label Content"); - - gtk_widget_get_clip (widget, &clip); - _gtk_widget_get_allocation (widget, &alloc); - - cr = gsk_render_node_get_draw_context (node, renderer); - cairo_translate (cr, alloc.x - clip.x, alloc.y - clip.y); - x = 0; - y = 0; - width = alloc.width; - height = alloc.height; + widget = gtk_css_gadget_get_owner (gadget); + label = GTK_LABEL (widget); + priv = label->priv; + info = priv->select_info; gtk_label_ensure_layout (label); @@ -4206,12 +4209,14 @@ gtk_label_get_render_node (GtkWidget *widget, lx = ly = 0; layout_to_window_coords (label, &lx, &ly); - gtk_render_layout (context, cr, lx, ly, priv->layout); + gtk_snapshot_render_layout (snapshot, context, lx, ly, priv->layout); if (info && (info->selection_anchor != info->selection_end)) { gint range[2]; cairo_region_t *range_clip; + cairo_rectangle_int_t clip_extents; + cairo_t *cr; range[0] = info->selection_anchor; range[1] = info->selection_end; @@ -4224,8 +4229,10 @@ gtk_label_get_render_node (GtkWidget *widget, } range_clip = gdk_pango_layout_get_clip_region (priv->layout, lx, ly, range, 1); - - cairo_save (cr); + cairo_region_get_extents (range_clip, &clip_extents); + cr = gtk_snapshot_append_cairo_node (snapshot, + &GRAPHENE_RECT_FROM_RECT(&clip_extents), + "Selected Text"); gtk_style_context_save_to_node (context, info->selection_node); gdk_cairo_region (cr, range_clip); @@ -4235,7 +4242,7 @@ gtk_label_get_render_node (GtkWidget *widget, gtk_render_layout (context, cr, lx, ly, priv->layout); gtk_style_context_restore (context); - cairo_restore (cr); + cairo_destroy (cr); cairo_region_destroy (range_clip); } else if (info) @@ -4244,7 +4251,9 @@ gtk_label_get_render_node (GtkWidget *widget, GtkLabelLink *active_link; gint range[2]; cairo_region_t *range_clip; + cairo_rectangle_int_t clip_extents; GdkRectangle rect; + cairo_t *cr; if (info->selectable && gtk_widget_has_focus (widget) && @@ -4253,10 +4262,10 @@ gtk_label_get_render_node (GtkWidget *widget, PangoDirection cursor_direction; cursor_direction = get_cursor_direction (label); - gtk_render_insertion_cursor (context, cr, - lx, ly, - priv->layout, priv->select_info->selection_end, - cursor_direction); + gtk_snapshot_render_insertion_cursor (snapshot, context, + lx, ly, + priv->layout, priv->select_info->selection_end, + cursor_direction); } focus_link = gtk_label_get_focus_link (label); @@ -4267,11 +4276,13 @@ gtk_label_get_render_node (GtkWidget *widget, range[0] = active_link->start; range[1] = active_link->end; - cairo_save (cr); gtk_style_context_save_to_node (context, active_link->cssnode); range_clip = gdk_pango_layout_get_clip_region (priv->layout, lx, ly, range, 1); - + cairo_region_get_extents (range_clip, &clip_extents); + cr = gtk_snapshot_append_cairo_node (snapshot, + &GRAPHENE_RECT_FROM_RECT(&clip_extents), + "Active Link"); gdk_cairo_region (cr, range_clip); cairo_clip (cr); cairo_region_destroy (range_clip); @@ -4291,19 +4302,14 @@ gtk_label_get_render_node (GtkWidget *widget, range_clip = gdk_pango_layout_get_clip_region (priv->layout, lx, ly, range, 1); cairo_region_get_extents (range_clip, &rect); - gtk_render_focus (context, cr, rect.x, rect.y, rect.width, rect.height); + gtk_snapshot_render_focus (snapshot, context, rect.x, rect.y, rect.width, rect.height); cairo_region_destroy (range_clip); } } } - cairo_destroy (cr); - - gsk_render_node_append_child (res, node); - gsk_render_node_unref (node); - - return res; + return FALSE; } static gboolean diff --git a/gtk/gtksnapshot.c b/gtk/gtksnapshot.c index 110cdb5847..62defef2b7 100644 --- a/gtk/gtksnapshot.c +++ b/gtk/gtksnapshot.c @@ -298,6 +298,24 @@ gtk_snapshot_render_frame (GtkSnapshot *state, gtk_snapshot_translate_2d (state, -x, -y); } +void +gtk_snapshot_render_focus (GtkSnapshot *state, + GtkStyleContext *context, + gdouble x, + gdouble y, + gdouble width, + gdouble height) +{ + g_return_if_fail (state != NULL); + g_return_if_fail (GTK_IS_STYLE_CONTEXT (context)); + + gtk_snapshot_translate_2d (state, x, y); + gtk_css_style_snapshot_outline (gtk_style_context_lookup_style (context), + state, + width, height); + gtk_snapshot_translate_2d (state, -x, -y); +} + void gtk_snapshot_render_layout (GtkSnapshot *state, GtkStyleContext *context, diff --git a/gtk/gtksnapshot.h b/gtk/gtksnapshot.h index 948e22c02e..74be2c134b 100644 --- a/gtk/gtksnapshot.h +++ b/gtk/gtksnapshot.h @@ -97,11 +97,26 @@ void gtk_snapshot_render_frame (GtkSnapshot gdouble width, gdouble height); GDK_AVAILABLE_IN_3_90 +void gtk_snapshot_render_focus (GtkSnapshot *state, + GtkStyleContext *context, + gdouble x, + gdouble y, + gdouble width, + gdouble height); +GDK_AVAILABLE_IN_3_90 void gtk_snapshot_render_layout (GtkSnapshot *state, GtkStyleContext *context, gdouble x, gdouble y, PangoLayout *layout); +GDK_AVAILABLE_IN_3_90 /* in gtkstylecontext.c */ +void gtk_snapshot_render_insertion_cursor (GtkSnapshot *snapshot, + GtkStyleContext *context, + gdouble x, + gdouble y, + PangoLayout *layout, + int index, + PangoDirection direction); G_END_DECLS diff --git a/gtk/gtkstylecontext.c b/gtk/gtkstylecontext.c index 64641f8bb4..df934e0529 100644 --- a/gtk/gtkstylecontext.c +++ b/gtk/gtkstylecontext.c @@ -2060,7 +2060,6 @@ draw_insertion_cursor (GtkStyleContext *context, gboolean is_primary, PangoDirection direction, gboolean draw_arrow) - { GdkRGBA primary_color; GdkRGBA secondary_color; @@ -2122,6 +2121,65 @@ draw_insertion_cursor (GtkStyleContext *context, cairo_restore (cr); } +static void +get_insertion_cursor_bounds (gdouble height, + PangoDirection direction, + gboolean draw_arrow, + graphene_rect_t *bounds) +{ + gint stem_width; + gint offset; + + stem_width = height * CURSOR_ASPECT_RATIO + 1; + if (direction == PANGO_DIRECTION_LTR) + offset = stem_width / 2; + else + offset = stem_width - stem_width / 2; + + if (draw_arrow) + { + if (direction == PANGO_DIRECTION_LTR) + { + graphene_rect_init (bounds, + - offset, 0, + 2 * stem_width + 1, height); + } + else + { + graphene_rect_init (bounds, + - offset - stem_width - 2, 0, + 2 * stem_width + 2, height); + } + } + else + { + graphene_rect_init (bounds, + - offset, 0, + stem_width, height); + } +} + +static void +snapshot_insertion_cursor (GtkSnapshot *snapshot, + GtkStyleContext *context, + gdouble height, + gboolean is_primary, + PangoDirection direction, + gboolean draw_arrow) +{ + graphene_rect_t bounds; + cairo_t *cr; + + get_insertion_cursor_bounds (height, direction, draw_arrow, &bounds); + cr = gtk_snapshot_append_cairo_node (snapshot, + &bounds, + "%s Cursor", is_primary ? "Primary" : "Secondary"); + + draw_insertion_cursor (context, cr, 0, 0, height, is_primary, direction, draw_arrow); + + cairo_destroy (cr); +} + /** * gtk_render_insertion_cursor: * @context: a #GtkStyleContext @@ -2209,6 +2267,93 @@ gtk_render_insertion_cursor (GtkStyleContext *context, } } +/** + * gtk_snapshot_render_insertion_cursor: + * @snapshot: snapshot to render to + * @context: a #GtkStyleContext + * @x: X origin + * @y: Y origin + * @layout: the #PangoLayout of the text + * @index: the index in the #PangoLayout + * @direction: the #PangoDirection of the text + * + * Draws a text caret on @cr at the specified index of @layout. + * + * Since: 3.90 + **/ +void +gtk_snapshot_render_insertion_cursor (GtkSnapshot *snapshot, + GtkStyleContext *context, + gdouble x, + gdouble y, + PangoLayout *layout, + int index, + PangoDirection direction) +{ + GtkStyleContextPrivate *priv; + gboolean split_cursor; + PangoRectangle strong_pos, weak_pos; + PangoRectangle *cursor1, *cursor2; + PangoDirection keymap_direction; + PangoDirection direction2; + + g_return_if_fail (snapshot != NULL); + g_return_if_fail (GTK_IS_STYLE_CONTEXT (context)); + g_return_if_fail (PANGO_IS_LAYOUT (layout)); + g_return_if_fail (index >= 0); + + priv = context->priv; + + g_object_get (gtk_settings_get_for_screen (priv->screen), + "gtk-split-cursor", &split_cursor, + NULL); + + keymap_direction = gdk_keymap_get_direction (gdk_keymap_get_for_display (gdk_screen_get_display (priv->screen))); + + pango_layout_get_cursor_pos (layout, index, &strong_pos, &weak_pos); + + direction2 = PANGO_DIRECTION_NEUTRAL; + + if (split_cursor) + { + cursor1 = &strong_pos; + + if (strong_pos.x != weak_pos.x || strong_pos.y != weak_pos.y) + { + direction2 = (direction == PANGO_DIRECTION_LTR) ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR; + cursor2 = &weak_pos; + } + } + else + { + if (keymap_direction == direction) + cursor1 = &strong_pos; + else + cursor1 = &weak_pos; + } + + gtk_snapshot_translate_2d (snapshot, x + PANGO_PIXELS (cursor1->x), y + PANGO_PIXELS (cursor1->y)); + snapshot_insertion_cursor (snapshot, + context, + PANGO_PIXELS (cursor1->height), + TRUE, + direction, + direction2 != PANGO_DIRECTION_NEUTRAL); + gtk_snapshot_translate_2d (snapshot, - x - PANGO_PIXELS (cursor1->x), - y - PANGO_PIXELS (cursor1->y)); + + if (direction2 != PANGO_DIRECTION_NEUTRAL) + { + gtk_snapshot_translate_2d (snapshot, x + PANGO_PIXELS (cursor2->x), y + PANGO_PIXELS (cursor2->y)); + snapshot_insertion_cursor (snapshot, + context, + PANGO_PIXELS (cursor2->height), + FALSE, + direction2, + TRUE); + gtk_snapshot_translate_2d (snapshot, - x - PANGO_PIXELS (cursor2->x), - y - PANGO_PIXELS (cursor2->y)); + } +} + /** * gtk_style_context_get_change: * @context: the context to query