Rework GtkTextView cursor code.

Move the handling of primary/secondary cursors to gtktextdisplay, which
makes code simpler and more consistent to how GtkLabel and GtkEntry
draw cursors, which is useful in preparation to further refactoring.

https://bugzilla.gnome.org/show_bug.cgi?id=640317
This commit is contained in:
Paolo Borelli
2011-11-26 23:48:10 +01:00
parent b3f850e6b9
commit 0bff1af7a2
3 changed files with 49 additions and 100 deletions

View File

@ -822,7 +822,6 @@ gtk_text_layout_draw (GtkTextLayout *layout,
GList **widgets) GList **widgets)
{ {
gint offset_y; gint offset_y;
GSList *cursor_list;
GtkTextRenderer *text_renderer; GtkTextRenderer *text_renderer;
GtkTextIter selection_start, selection_end; GtkTextIter selection_start, selection_end;
gboolean have_selection; gboolean have_selection;
@ -862,8 +861,6 @@ gtk_text_layout_draw (GtkTextLayout *layout,
GtkTextLineDisplay *line_display; GtkTextLineDisplay *line_display;
gint selection_start_index = -1; gint selection_start_index = -1;
gint selection_end_index = -1; gint selection_end_index = -1;
gboolean have_strong;
gboolean have_weak;
GtkTextLine *line = tmp_list->data; GtkTextLine *line = tmp_list->data;
@ -905,47 +902,52 @@ gtk_text_layout_draw (GtkTextLayout *layout,
selection_start_index, selection_end_index); selection_start_index, selection_end_index);
/* We paint the cursors last, because they overlap another chunk /* We paint the cursors last, because they overlap another chunk
and need to appear on top. */ * and need to appear on top.
*/
have_strong = FALSE; if (line_display->cursors != NULL)
have_weak = FALSE;
cursor_list = line_display->cursors;
while (cursor_list)
{
GtkTextCursorDisplay *cursor = cursor_list->data;
if (cursor->is_strong)
have_strong = TRUE;
else
have_weak = TRUE;
cursor_list = cursor_list->next;
}
cursor_list = line_display->cursors;
while (cursor_list)
{ {
GtkTextCursorDisplay *cursor = cursor_list->data; int i;
GtkTextDirection dir;
GdkRectangle cursor_location;
dir = line_display->direction; for (i = 0; i < line_display->cursors->len; i++)
if (have_strong && have_weak) {
{ int index;
if (!cursor->is_strong) PangoRectangle strong_pos, weak_pos;
dir = (dir == GTK_TEXT_DIR_RTL) ? GTK_TEXT_DIR_LTR : GTK_TEXT_DIR_RTL; GdkRectangle cursor_location;
}
cursor_location.x = line_display->x_offset + cursor->x; index = g_array_index(line_display->cursors, int, i);
cursor_location.y = line_display->top_margin + cursor->y; pango_layout_get_cursor_pos (line_display->layout, index, &strong_pos, &weak_pos);
cursor_location.width = 0;
cursor_location.height = cursor->height;
gtk_draw_insertion_cursor (widget, cr, &cursor_location, cursor_location.x = line_display->x_offset + PANGO_PIXELS (strong_pos.x);
cursor->is_strong, cursor_location.y = line_display->top_margin + PANGO_PIXELS (strong_pos.y);
dir, have_strong && have_weak); cursor_location.width = 0;
cursor_location.height = PANGO_PIXELS (strong_pos.height);
cursor_list = cursor_list->next; if (layout->cursor_direction == GTK_TEXT_DIR_NONE ||
line_display->direction == layout->cursor_direction)
{
gtk_draw_insertion_cursor (widget, cr,
&cursor_location, TRUE, line_display->direction,
layout->cursor_direction != GTK_TEXT_DIR_NONE);
}
if ((strong_pos.x != weak_pos.x || strong_pos.y != weak_pos.y) &&
(layout->cursor_direction == GTK_TEXT_DIR_NONE ||
line_display->direction != layout->cursor_direction))
{
GtkTextDirection dir;
dir = (line_display->direction == GTK_TEXT_DIR_RTL) ? GTK_TEXT_DIR_LTR : GTK_TEXT_DIR_RTL;
cursor_location.x = line_display->x_offset + PANGO_PIXELS (weak_pos.x);
cursor_location.y = line_display->top_margin + PANGO_PIXELS (weak_pos.y);
cursor_location.width = 0;
cursor_location.height = PANGO_PIXELS (weak_pos.height);
gtk_draw_insertion_cursor (widget, cr,
&cursor_location, FALSE, dir,
TRUE);
}
}
} }
} /* line_display->height > 0 */ } /* line_display->height > 0 */

View File

@ -827,8 +827,8 @@ gtk_text_layout_invalidate_cache (GtkTextLayout *layout,
if (cursors_only) if (cursors_only)
{ {
g_slist_foreach (display->cursors, (GFunc)g_free, NULL); if (display->cursors)
g_slist_free (display->cursors); g_array_free (display->cursors, TRUE);
display->cursors = NULL; display->cursors = NULL;
display->cursors_invalid = TRUE; display->cursors_invalid = TRUE;
display->has_block_cursor = FALSE; display->has_block_cursor = FALSE;
@ -1733,11 +1733,6 @@ add_cursor (GtkTextLayout *layout,
GtkTextLineSegment *seg, GtkTextLineSegment *seg,
gint start) gint start)
{ {
PangoRectangle strong_pos, weak_pos;
GtkTextCursorDisplay *cursor = NULL; /* Quiet GCC */
gboolean add_weak = FALSE;
gboolean add_strong = FALSE;
/* Hide insertion cursor when we have a selection or the layout /* Hide insertion cursor when we have a selection or the layout
* user has hidden the cursor. * user has hidden the cursor.
*/ */
@ -1767,46 +1762,10 @@ add_cursor (GtkTextLayout *layout,
} }
} }
pango_layout_get_cursor_pos (display->layout, start, &strong_pos, &weak_pos); if (!display->cursors)
display->cursors = g_array_new (FALSE, FALSE, sizeof(int));
if (layout->cursor_direction == GTK_TEXT_DIR_NONE) display->cursors = g_array_append_val (display->cursors, start);
{
add_strong = TRUE;
add_weak = TRUE;
}
else if (display->direction == layout->cursor_direction)
add_strong = TRUE;
else
add_weak = TRUE;
if (add_strong)
{
cursor = g_new (GtkTextCursorDisplay, 1);
cursor->x = PANGO_PIXELS (strong_pos.x);
cursor->y = PANGO_PIXELS (strong_pos.y);
cursor->height = PANGO_PIXELS (strong_pos.height);
cursor->is_strong = TRUE;
cursor->is_weak = (layout->cursor_direction == GTK_TEXT_DIR_NONE) ? FALSE : TRUE;
display->cursors = g_slist_prepend (display->cursors, cursor);
}
if (add_weak)
{
if (weak_pos.x == strong_pos.x && add_strong)
cursor->is_weak = TRUE;
else
{
cursor = g_new (GtkTextCursorDisplay, 1);
cursor->x = PANGO_PIXELS (weak_pos.x);
cursor->y = PANGO_PIXELS (weak_pos.y);
cursor->height = PANGO_PIXELS (weak_pos.height);
cursor->is_strong = (layout->cursor_direction == GTK_TEXT_DIR_NONE) ? FALSE : TRUE;
cursor->is_weak = TRUE;
display->cursors = g_slist_prepend (display->cursors, cursor);
}
}
} }
static gboolean static gboolean
@ -2530,10 +2489,7 @@ gtk_text_layout_free_line_display (GtkTextLayout *layout,
g_object_unref (display->layout); g_object_unref (display->layout);
if (display->cursors) if (display->cursors)
{ g_array_free (display->cursors, TRUE);
g_slist_foreach (display->cursors, (GFunc)g_free, NULL);
g_slist_free (display->cursors);
}
if (display->pg_bg_color) if (display->pg_bg_color)
gdk_color_free (display->pg_bg_color); gdk_color_free (display->pg_bg_color);

View File

@ -109,7 +109,6 @@ typedef struct _GtkTextLineData GtkTextLineData;
typedef struct _GtkTextLayout GtkTextLayout; typedef struct _GtkTextLayout GtkTextLayout;
typedef struct _GtkTextLayoutClass GtkTextLayoutClass; typedef struct _GtkTextLayoutClass GtkTextLayoutClass;
typedef struct _GtkTextLineDisplay GtkTextLineDisplay; typedef struct _GtkTextLineDisplay GtkTextLineDisplay;
typedef struct _GtkTextCursorDisplay GtkTextCursorDisplay;
typedef struct _GtkTextAttrAppearance GtkTextAttrAppearance; typedef struct _GtkTextAttrAppearance GtkTextAttrAppearance;
struct _GtkTextLayout struct _GtkTextLayout
@ -225,19 +224,11 @@ struct _GtkTextAttrAppearance
PangoAttribute attr; PangoAttribute attr;
GtkTextAppearance appearance; GtkTextAppearance appearance;
}; };
struct _GtkTextCursorDisplay
{
gint x;
gint y;
gint height;
guint is_strong : 1;
guint is_weak : 1;
};
struct _GtkTextLineDisplay struct _GtkTextLineDisplay
{ {
PangoLayout *layout; PangoLayout *layout;
GSList *cursors; GArray *cursors; /* indexes of cursors in the PangoLayout */
GtkTextDirection direction; GtkTextDirection direction;