mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-11 19:30:10 +00:00
style: Draw insertion cursor with Cairo
This commit is contained in:
parent
9bac13b1f5
commit
610e29892e
142
gtk/gtkstyle.c
142
gtk/gtkstyle.c
@ -6058,8 +6058,8 @@ typedef struct _CursorInfo CursorInfo;
|
|||||||
struct _CursorInfo
|
struct _CursorInfo
|
||||||
{
|
{
|
||||||
GType for_type;
|
GType for_type;
|
||||||
GdkGC *primary_gc;
|
GdkColor primary;
|
||||||
GdkGC *secondary_gc;
|
GdkColor secondary;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -6070,54 +6070,23 @@ style_unrealize_cursor_gcs (GtkStyle *style)
|
|||||||
cursor_info = g_object_get_data (G_OBJECT (style), "gtk-style-cursor-info");
|
cursor_info = g_object_get_data (G_OBJECT (style), "gtk-style-cursor-info");
|
||||||
if (cursor_info)
|
if (cursor_info)
|
||||||
{
|
{
|
||||||
if (cursor_info->primary_gc)
|
|
||||||
gtk_gc_release (cursor_info->primary_gc);
|
|
||||||
|
|
||||||
if (cursor_info->secondary_gc)
|
|
||||||
gtk_gc_release (cursor_info->secondary_gc);
|
|
||||||
|
|
||||||
g_free (cursor_info);
|
g_free (cursor_info);
|
||||||
g_object_set_data (G_OBJECT (style), I_("gtk-style-cursor-info"), NULL);
|
g_object_set_data (G_OBJECT (style), I_("gtk-style-cursor-info"), NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static GdkGC *
|
static const GdkColor *
|
||||||
make_cursor_gc (GtkWidget *widget,
|
get_insertion_cursor_color (GtkWidget *widget,
|
||||||
const gchar *property_name,
|
|
||||||
const GdkColor *fallback)
|
|
||||||
{
|
|
||||||
GdkGCValues gc_values;
|
|
||||||
GdkGCValuesMask gc_values_mask;
|
|
||||||
GdkColor *cursor_color;
|
|
||||||
|
|
||||||
gtk_widget_style_get (widget, property_name, &cursor_color, NULL);
|
|
||||||
|
|
||||||
gc_values_mask = GDK_GC_FOREGROUND;
|
|
||||||
if (cursor_color)
|
|
||||||
{
|
|
||||||
gc_values.foreground = *cursor_color;
|
|
||||||
gdk_color_free (cursor_color);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
gc_values.foreground = *fallback;
|
|
||||||
|
|
||||||
gdk_rgb_find_color (widget->style->colormap, &gc_values.foreground);
|
|
||||||
return gtk_gc_get (widget->style->depth, widget->style->colormap, &gc_values, gc_values_mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
static GdkGC *
|
|
||||||
get_insertion_cursor_gc (GtkWidget *widget,
|
|
||||||
gboolean is_primary)
|
gboolean is_primary)
|
||||||
{
|
{
|
||||||
CursorInfo *cursor_info;
|
CursorInfo *cursor_info;
|
||||||
|
GdkColor *cursor_color;
|
||||||
|
|
||||||
cursor_info = g_object_get_data (G_OBJECT (widget->style), "gtk-style-cursor-info");
|
cursor_info = g_object_get_data (G_OBJECT (widget->style), "gtk-style-cursor-info");
|
||||||
if (!cursor_info)
|
if (!cursor_info)
|
||||||
{
|
{
|
||||||
cursor_info = g_new (CursorInfo, 1);
|
cursor_info = g_new0 (CursorInfo, 1);
|
||||||
g_object_set_data (G_OBJECT (widget->style), I_("gtk-style-cursor-info"), cursor_info);
|
g_object_set_data (G_OBJECT (widget->style), I_("gtk-style-cursor-info"), cursor_info);
|
||||||
cursor_info->primary_gc = NULL;
|
|
||||||
cursor_info->secondary_gc = NULL;
|
|
||||||
cursor_info->for_type = G_TYPE_INVALID;
|
cursor_info->for_type = G_TYPE_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6130,42 +6099,40 @@ get_insertion_cursor_gc (GtkWidget *widget,
|
|||||||
if (cursor_info->for_type != G_OBJECT_TYPE (widget))
|
if (cursor_info->for_type != G_OBJECT_TYPE (widget))
|
||||||
{
|
{
|
||||||
cursor_info->for_type = G_OBJECT_TYPE (widget);
|
cursor_info->for_type = G_OBJECT_TYPE (widget);
|
||||||
if (cursor_info->primary_gc)
|
|
||||||
{
|
|
||||||
gtk_gc_release (cursor_info->primary_gc);
|
|
||||||
cursor_info->primary_gc = NULL;
|
|
||||||
}
|
|
||||||
if (cursor_info->secondary_gc)
|
|
||||||
{
|
|
||||||
gtk_gc_release (cursor_info->secondary_gc);
|
|
||||||
cursor_info->secondary_gc = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Cursors in text widgets are drawn only in NORMAL state,
|
/* Cursors in text widgets are drawn only in NORMAL state,
|
||||||
* so we can use text[GTK_STATE_NORMAL] as text color here */
|
* so we can use text[GTK_STATE_NORMAL] as text color here */
|
||||||
if (is_primary)
|
gtk_widget_style_get (widget, "cursor-color", &cursor_color, NULL);
|
||||||
|
if (cursor_color)
|
||||||
{
|
{
|
||||||
if (!cursor_info->primary_gc)
|
cursor_info->primary = *cursor_color;
|
||||||
cursor_info->primary_gc = make_cursor_gc (widget,
|
gdk_color_free (cursor_color);
|
||||||
"cursor-color",
|
}
|
||||||
&widget->style->text[GTK_STATE_NORMAL]);
|
else
|
||||||
|
{
|
||||||
return cursor_info->primary_gc;
|
cursor_info->primary = widget->style->text[GTK_STATE_NORMAL];
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_widget_style_get (widget, "secondary-cursor-color", &cursor_color, NULL);
|
||||||
|
if (cursor_color)
|
||||||
|
{
|
||||||
|
cursor_info->secondary = *cursor_color;
|
||||||
|
gdk_color_free (cursor_color);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!cursor_info->secondary_gc)
|
|
||||||
cursor_info->secondary_gc = make_cursor_gc (widget,
|
|
||||||
"secondary-cursor-color",
|
|
||||||
/* text_aa is the average of text and base colors,
|
/* text_aa is the average of text and base colors,
|
||||||
* in usual black-on-white case it's grey. */
|
* in usual black-on-white case it's grey. */
|
||||||
&widget->style->text_aa[GTK_STATE_NORMAL]);
|
cursor_info->secondary = widget->style->text_aa[GTK_STATE_NORMAL];
|
||||||
|
|
||||||
return cursor_info->secondary_gc;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_primary)
|
||||||
|
return &cursor_info->primary;
|
||||||
|
else
|
||||||
|
return &cursor_info->secondary;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_gtk_widget_get_cursor_color (GtkWidget *widget,
|
_gtk_widget_get_cursor_color (GtkWidget *widget,
|
||||||
GdkColor *color)
|
GdkColor *color)
|
||||||
@ -6188,8 +6155,7 @@ _gtk_widget_get_cursor_color (GtkWidget *widget,
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
draw_insertion_cursor (GtkWidget *widget,
|
draw_insertion_cursor (GtkWidget *widget,
|
||||||
GdkDrawable *drawable,
|
cairo_t *cr,
|
||||||
GdkGC *gc,
|
|
||||||
const GdkRectangle *location,
|
const GdkRectangle *location,
|
||||||
GtkTextDirection direction,
|
GtkTextDirection direction,
|
||||||
gboolean draw_arrow)
|
gboolean draw_arrow)
|
||||||
@ -6216,10 +6182,10 @@ draw_insertion_cursor (GtkWidget *widget,
|
|||||||
else
|
else
|
||||||
offset = stem_width - stem_width / 2;
|
offset = stem_width - stem_width / 2;
|
||||||
|
|
||||||
for (i = 0; i < stem_width; i++)
|
cairo_rectangle (cr,
|
||||||
gdk_draw_line (drawable, gc,
|
location->x - offset, location->y,
|
||||||
location->x + i - offset, location->y,
|
stem_width, location->height);
|
||||||
location->x + i - offset, location->y + location->height - 1);
|
cairo_fill (cr);
|
||||||
|
|
||||||
if (draw_arrow)
|
if (draw_arrow)
|
||||||
{
|
{
|
||||||
@ -6228,26 +6194,20 @@ draw_insertion_cursor (GtkWidget *widget,
|
|||||||
x = location->x - offset - 1;
|
x = location->x - offset - 1;
|
||||||
y = location->y + location->height - arrow_width * 2 - arrow_width + 1;
|
y = location->y + location->height - arrow_width * 2 - arrow_width + 1;
|
||||||
|
|
||||||
for (i = 0; i < arrow_width; i++)
|
cairo_move_to (cr, x, y + 1);
|
||||||
{
|
cairo_line_to (cr, x - arrow_width, y + arrow_width);
|
||||||
gdk_draw_line (drawable, gc,
|
cairo_line_to (cr, x, y + 2 * arrow_width);
|
||||||
x, y + i + 1,
|
cairo_fill (cr);
|
||||||
x, y + 2 * arrow_width - i - 1);
|
|
||||||
x --;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (direction == GTK_TEXT_DIR_LTR)
|
else if (direction == GTK_TEXT_DIR_LTR)
|
||||||
{
|
{
|
||||||
x = location->x + stem_width - offset;
|
x = location->x + stem_width - offset;
|
||||||
y = location->y + location->height - arrow_width * 2 - arrow_width + 1;
|
y = location->y + location->height - arrow_width * 2 - arrow_width + 1;
|
||||||
|
|
||||||
for (i = 0; i < arrow_width; i++)
|
cairo_move_to (cr, x, y + 1);
|
||||||
{
|
cairo_line_to (cr, x + arrow_width, y + arrow_width);
|
||||||
gdk_draw_line (drawable, gc,
|
cairo_line_to (cr, x, y + 2 * arrow_width);
|
||||||
x, y + i + 1,
|
cairo_fill (cr);
|
||||||
x, y + 2 * arrow_width - i - 1);
|
|
||||||
x++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6279,20 +6239,22 @@ gtk_draw_insertion_cursor (GtkWidget *widget,
|
|||||||
GtkTextDirection direction,
|
GtkTextDirection direction,
|
||||||
gboolean draw_arrow)
|
gboolean draw_arrow)
|
||||||
{
|
{
|
||||||
GdkGC *gc;
|
cairo_t *cr;
|
||||||
|
|
||||||
g_return_if_fail (GTK_IS_WIDGET (widget));
|
g_return_if_fail (GTK_IS_WIDGET (widget));
|
||||||
g_return_if_fail (GDK_IS_DRAWABLE (drawable));
|
g_return_if_fail (GDK_IS_DRAWABLE (drawable));
|
||||||
g_return_if_fail (location != NULL);
|
g_return_if_fail (location != NULL);
|
||||||
g_return_if_fail (direction != GTK_TEXT_DIR_NONE);
|
g_return_if_fail (direction != GTK_TEXT_DIR_NONE);
|
||||||
|
|
||||||
gc = get_insertion_cursor_gc (widget, is_primary);
|
cr = gdk_cairo_create (drawable);
|
||||||
if (area)
|
if (area)
|
||||||
gdk_gc_set_clip_rectangle (gc, area);
|
{
|
||||||
|
gdk_cairo_rectangle (cr, area);
|
||||||
draw_insertion_cursor (widget, drawable, gc,
|
cairo_clip (cr);
|
||||||
location, direction, draw_arrow);
|
}
|
||||||
|
|
||||||
if (area)
|
gdk_cairo_set_source_color (cr, get_insertion_cursor_color (widget, is_primary));
|
||||||
gdk_gc_set_clip_rectangle (gc, NULL);
|
draw_insertion_cursor (widget, cr, location, direction, draw_arrow);
|
||||||
|
|
||||||
|
cairo_destroy (cr);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user