From 8f4aa8c6d7dd2e8ebc60683088aec23ed2806625 Mon Sep 17 00:00:00 2001 From: Yevgen Muntyan Date: Fri, 1 Jun 2007 06:25:43 +0000 Subject: [PATCH] Avoid recreating pangolayouts in GtkTextView on cursor movement (#435405, 2007-06-01 Yevgen Muntyan Avoid recreating pangolayouts in GtkTextView on cursor movement (#435405, Behdad Esfahbod). * gtk/gtktextlayout.c: * gtk/gtktextlayout.h: new GtkTextLayout method invalidate_cursors(), and functions gtk_text_layout_invalidate_cursors() and gtk_text_layout_cursors_changed(), to use when invalidation is due to moved marks or changed selection. * gtk/gtktextbtree.c: * gtk/gtktextbtree.h: use what's appropriate when invalidating layout. * gtk/gtk.symbols: add new functions. * README.in: added a note about changed GtkTextLayout API. svn path=/trunk/; revision=18000 --- ChangeLog | 18 ++++ README.in | 10 ++ gtk/gtk.symbols | 2 + gtk/gtktextbtree.c | 76 ++++++++------ gtk/gtktextbtree.h | 3 +- gtk/gtktextlayout.c | 247 +++++++++++++++++++++++++++++++++++++++----- gtk/gtktextlayout.h | 14 ++- 7 files changed, 316 insertions(+), 54 deletions(-) diff --git a/ChangeLog b/ChangeLog index c5d98c9e52..088009f29a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2007-06-01 Yevgen Muntyan + + Avoid recreating pangolayouts in GtkTextView on cursor movement + (#435405, Behdad Esfahbod). + + * gtk/gtktextlayout.c: + * gtk/gtktextlayout.h: new GtkTextLayout method invalidate_cursors(), + and functions gtk_text_layout_invalidate_cursors() and + gtk_text_layout_cursors_changed(), to use when invalidation is due + to moved marks or changed selection. + + * gtk/gtktextbtree.c: + * gtk/gtktextbtree.h: use what's appropriate when invalidating layout. + + * gtk/gtk.symbols: add new functions. + + * README.in: added a note about changed GtkTextLayout API. + 2007-06-01 Alp Toker * gdk/gdkcairo.c (gdk_cairo_set_source_pixmap): Fix doc typos. diff --git a/README.in b/README.in index 3dc5ef8f8b..ff62e5efe9 100644 --- a/README.in +++ b/README.in @@ -48,6 +48,16 @@ Release notes for 2.12 GDK for drawing decorations. In particular, metacity <= 2.18.0 is affected by this. The problem has been fixed in metacity 2.18.1. +* Semi-private GtkTextLayout api has changed: new GtkTextLayout method + invalidate_cursors(), and new functions gtk_text_layout_invalidate_cursors() + and gtk_text_layout_cursors_changed(), which should be used in place of + gtk_text_layout_invalidate() and gtk_text_layout_changed() if invalidation + is due to marks moved or changed selection; new GtkTextLineDisplay structure + member. Source compatibility is preserved; binary compatibility may break + only if GtkTextLineDisplay structure was created on stack or as a part + of another structure (in particular GnomeCanvas and its clones do not need + recompiling). + Release notes for 2.10 ====================== diff --git a/gtk/gtk.symbols b/gtk/gtk.symbols index 5b28f13185..2c7963580d 100644 --- a/gtk/gtk.symbols +++ b/gtk/gtk.symbols @@ -3715,6 +3715,7 @@ gtk_text_iter_toggles_tag #if IN_HEADER(__GTK_TEXT_LAYOUT_H__) #if IN_FILE(__GTK_TEXT_LAYOUT_C__) gtk_text_layout_changed +gtk_text_layout_cursors_changed gtk_text_layout_clamp_iter_to_vrange gtk_text_layout_default_style_changed gtk_text_layout_free_line_data @@ -3733,6 +3734,7 @@ gtk_text_layout_get_line_yrange gtk_text_layout_get_size gtk_text_layout_get_type G_GNUC_CONST gtk_text_layout_invalidate +gtk_text_layout_invalidate_cursors gtk_text_layout_is_valid gtk_text_layout_iter_starts_line gtk_text_layout_move_iter_to_line_end diff --git a/gtk/gtktextbtree.c b/gtk/gtktextbtree.c index 93f6b4b3d9..111bd48ff4 100644 --- a/gtk/gtktextbtree.c +++ b/gtk/gtktextbtree.c @@ -340,7 +340,8 @@ static void gtk_text_btree_remove_tag_info (GtkTextBTree *tre static void redisplay_region (GtkTextBTree *tree, const GtkTextIter *start, - const GtkTextIter *end); + const GtkTextIter *end, + gboolean cursors_only); /* Inline thingies */ @@ -663,7 +664,7 @@ gtk_text_btree_resolve_bidi (GtkTextIter *start, */ line = _gtk_text_line_previous (line); _gtk_text_btree_get_iter_at_line (tree, &end_propagate, line, 0); - _gtk_text_btree_invalidate_region (tree, end, &end_propagate); + _gtk_text_btree_invalidate_region (tree, end, &end_propagate, FALSE); } /* Sweep backward */ @@ -719,7 +720,7 @@ gtk_text_btree_resolve_bidi (GtkTextIter *start, if (line && line->dir_propagated_forward == PANGO_DIRECTION_NEUTRAL) { _gtk_text_btree_get_iter_at_line (tree, &start_propagate, line, 0); - _gtk_text_btree_invalidate_region(tree, &start_propagate, start); + _gtk_text_btree_invalidate_region (tree, &start_propagate, start, FALSE); } } } @@ -756,7 +757,7 @@ _gtk_text_btree_delete (GtkTextIter *start, /* Broadcast the need for redisplay before we break the iterators */ DV (g_print ("invalidating due to deleting some text (%s)\n", G_STRLOC)); - _gtk_text_btree_invalidate_region (tree, start, end); + _gtk_text_btree_invalidate_region (tree, start, end, FALSE); /* Save the byte offset so we can reset the iterators */ start_byte_offset = gtk_text_iter_get_line_index (start); @@ -1241,8 +1242,7 @@ _gtk_text_btree_insert (GtkTextIter *iter, gtk_text_iter_forward_chars (&end, char_count_delta); DV (g_print ("invalidating due to inserting some text (%s)\n", G_STRLOC)); - _gtk_text_btree_invalidate_region (tree, - &start, &end); + _gtk_text_btree_invalidate_region (tree, &start, &end, FALSE); /* Convenience for the user */ @@ -1292,7 +1292,7 @@ insert_pixbuf_or_widget_segment (GtkTextIter *iter, gtk_text_iter_forward_char (iter); /* skip forward past the segment */ DV (g_print ("invalidating due to inserting pixbuf/widget (%s)\n", G_STRLOC)); - _gtk_text_btree_invalidate_region (tree, &start, iter); + _gtk_text_btree_invalidate_region (tree, &start, iter, FALSE); } void @@ -1627,7 +1627,8 @@ _gtk_text_btree_remove_view (GtkTextBTree *tree, void _gtk_text_btree_invalidate_region (GtkTextBTree *tree, const GtkTextIter *start, - const GtkTextIter *end) + const GtkTextIter *end, + gboolean cursors_only) { BTreeView *view; @@ -1635,7 +1636,10 @@ _gtk_text_btree_invalidate_region (GtkTextBTree *tree, while (view != NULL) { - gtk_text_layout_invalidate (view->layout, start, end); + if (cursors_only) + gtk_text_layout_invalidate_cursors (view->layout, start, end); + else + gtk_text_layout_invalidate (view->layout, start, end); view = view->next; } @@ -1740,12 +1744,12 @@ queue_tag_redisplay (GtkTextBTree *tree, if (_gtk_text_tag_affects_size (tag)) { DV (g_print ("invalidating due to size-affecting tag (%s)\n", G_STRLOC)); - _gtk_text_btree_invalidate_region (tree, start, end); + _gtk_text_btree_invalidate_region (tree, start, end, FALSE); } else if (_gtk_text_tag_affects_nonsize_appearance (tag)) { /* We only need to queue a redraw, not a relayout */ - redisplay_region (tree, start, end); + redisplay_region (tree, start, end, FALSE); } /* We don't need to do anything if the tag doesn't affect display */ @@ -2599,7 +2603,8 @@ _gtk_text_btree_char_is_invisible (const GtkTextIter *iter) static void redisplay_region (GtkTextBTree *tree, const GtkTextIter *start, - const GtkTextIter *end) + const GtkTextIter *end, + gboolean cursors_only) { BTreeView *view; GtkTextLine *start_line, *end_line; @@ -2631,9 +2636,14 @@ redisplay_region (GtkTextBTree *tree, if (ld) end_y += ld->height; - gtk_text_layout_changed (view->layout, start_y, - end_y - start_y, - end_y - start_y); + if (cursors_only) + gtk_text_layout_cursors_changed (view->layout, start_y, + end_y - start_y, + end_y - start_y); + else + gtk_text_layout_changed (view->layout, start_y, + end_y - start_y, + end_y - start_y); view = view->next; } @@ -2653,8 +2663,7 @@ redisplay_mark (GtkTextLineSegment *mark) gtk_text_iter_forward_char (&end); DV (g_print ("invalidating due to moving visible mark (%s)\n", G_STRLOC)); - _gtk_text_btree_invalidate_region (mark->body.mark.tree, - &iter, &end); + _gtk_text_btree_invalidate_region (mark->body.mark.tree, &iter, &end, TRUE); } static void @@ -2729,7 +2738,7 @@ real_set_mark (GtkTextBTree *tree, _gtk_text_btree_get_iter_at_mark (tree, &old_pos, mark->body.mark.obj); - redisplay_region (tree, &old_pos, where); + redisplay_region (tree, &old_pos, where, TRUE); } /* @@ -2863,18 +2872,28 @@ _gtk_text_btree_select_range (GtkTextBTree *tree, const GtkTextIter *ins, const GtkTextIter *bound) { - GtkTextIter start, end; + GtkTextIter old_ins, old_bound; - if (_gtk_text_btree_get_selection_bounds (tree, &start, &end)) - redisplay_region (tree, &start, &end); + _gtk_text_btree_get_iter_at_mark (tree, &old_ins, + tree->insert_mark); + _gtk_text_btree_get_iter_at_mark (tree, &old_bound, + tree->selection_bound_mark); - /* Move insert AND selection_bound before we redisplay */ - real_set_mark (tree, tree->insert_mark, - "insert", FALSE, ins, TRUE, FALSE); - real_set_mark (tree, tree->selection_bound_mark, - "selection_bound", FALSE, bound, TRUE, FALSE); + /* Check if it's no-op since gtk_text_buffer_place_cursor() + * also calls this, and this will redraw the cursor line. */ + if (!gtk_text_iter_equal (&old_ins, ins) || + !gtk_text_iter_equal (&old_bound, bound)) + { + redisplay_region (tree, &old_ins, &old_bound, TRUE); - redisplay_region (tree, ins, bound); + /* Move insert AND selection_bound before we redisplay */ + real_set_mark (tree, tree->insert_mark, + "insert", FALSE, ins, TRUE, FALSE); + real_set_mark (tree, tree->selection_bound_mark, + "selection_bound", FALSE, bound, TRUE, FALSE); + + redisplay_region (tree, ins, bound, TRUE); + } } @@ -5619,8 +5638,7 @@ tag_changed_cb (GtkTextTagTable *table, /* Must be a last toggle if there was a first one. */ _gtk_text_btree_get_iter_at_last_toggle (tree, &end, tag); DV (g_print ("invalidating due to tag change (%s)\n", G_STRLOC)); - _gtk_text_btree_invalidate_region (tree, - &start, &end); + _gtk_text_btree_invalidate_region (tree, &start, &end, FALSE); } } diff --git a/gtk/gtktextbtree.h b/gtk/gtktextbtree.h index 2b2d17cba1..053d9e1a20 100644 --- a/gtk/gtktextbtree.h +++ b/gtk/gtktextbtree.h @@ -92,7 +92,8 @@ void _gtk_text_btree_remove_view (GtkTextBTree *tree, gpointer view_id); void _gtk_text_btree_invalidate_region (GtkTextBTree *tree, const GtkTextIter *start, - const GtkTextIter *end); + const GtkTextIter *end, + gboolean cursors_only); void _gtk_text_btree_get_view_size (GtkTextBTree *tree, gpointer view_id, gint *width, diff --git a/gtk/gtktextlayout.c b/gtk/gtktextlayout.c index 553434a076..2cb2981f7e 100644 --- a/gtk/gtktextlayout.c +++ b/gtk/gtktextlayout.c @@ -110,9 +110,14 @@ static void gtk_text_layout_invalidated (GtkTextLayout *layout); static void gtk_text_layout_real_invalidate (GtkTextLayout *layout, const GtkTextIter *start, const GtkTextIter *end); +static void gtk_text_layout_real_invalidate_cursors(GtkTextLayout *layout, + const GtkTextIter *start, + const GtkTextIter *end); static void gtk_text_layout_invalidate_cache (GtkTextLayout *layout, - GtkTextLine *line); -static void gtk_text_layout_invalidate_cursor_line (GtkTextLayout *layout); + GtkTextLine *line, + gboolean cursors_only); +static void gtk_text_layout_invalidate_cursor_line (GtkTextLayout *layout, + gboolean cursors_only); static void gtk_text_layout_real_free_line_data (GtkTextLayout *layout, GtkTextLine *line, GtkTextLineData *line_data); @@ -172,6 +177,7 @@ gtk_text_layout_class_init (GtkTextLayoutClass *klass) klass->wrap = gtk_text_layout_real_wrap; klass->invalidate = gtk_text_layout_real_invalidate; + klass->invalidate_cursors = gtk_text_layout_real_invalidate_cursors; klass->free_line_data = gtk_text_layout_real_free_line_data; signals[INVALIDATED] = @@ -411,7 +417,7 @@ gtk_text_layout_set_cursor_direction (GtkTextLayout *layout, if (direction != layout->cursor_direction) { layout->cursor_direction = direction; - gtk_text_layout_invalidate_cursor_line (layout); + gtk_text_layout_invalidate_cursor_line (layout, TRUE); } } @@ -430,7 +436,7 @@ gtk_text_layout_set_keyboard_direction (GtkTextLayout *layout, if (keyboard_dir != layout->keyboard_direction) { layout->keyboard_direction = keyboard_dir; - gtk_text_layout_invalidate_cursor_line (layout); + gtk_text_layout_invalidate_cursor_line (layout, TRUE); } } @@ -498,7 +504,7 @@ gtk_text_layout_set_cursor_visible (GtkTextLayout *layout, gtk_text_layout_get_line_yrange (layout, &iter, &y, &height); gtk_text_layout_emit_changed (layout, y, height, height); - gtk_text_layout_invalidate_cache (layout, _gtk_text_iter_get_text_line (&iter)); + gtk_text_layout_invalidate_cache (layout, _gtk_text_iter_get_text_line (&iter), TRUE); } } @@ -560,7 +566,7 @@ gtk_text_layout_set_preedit_string (GtkTextLayout *layout, layout->preedit_cursor = 0; } - gtk_text_layout_invalidate_cursor_line (layout); + gtk_text_layout_invalidate_cursor_line (layout, FALSE); } void @@ -592,11 +598,12 @@ gtk_text_layout_emit_changed (GtkTextLayout *layout, g_signal_emit (layout, signals[CHANGED], 0, y, old_height, new_height); } -void -gtk_text_layout_changed (GtkTextLayout *layout, - gint y, - gint old_height, - gint new_height) +static void +text_layout_changed (GtkTextLayout *layout, + gint y, + gint old_height, + gint new_height, + gboolean cursors_only) { /* Check if the range intersects our cached line display, * and invalidate the cached line if so. @@ -609,12 +616,30 @@ gtk_text_layout_changed (GtkTextLayout *layout, gint cache_height = layout->one_display_cache->height; if (cache_y + cache_height > y && cache_y < y + old_height) - gtk_text_layout_invalidate_cache (layout, line); + gtk_text_layout_invalidate_cache (layout, line, cursors_only); } - + gtk_text_layout_emit_changed (layout, y, old_height, new_height); } +void +gtk_text_layout_changed (GtkTextLayout *layout, + gint y, + gint old_height, + gint new_height) +{ + text_layout_changed (layout, y, old_height, new_height, FALSE); +} + +void +gtk_text_layout_cursors_changed (GtkTextLayout *layout, + gint y, + gint old_height, + gint new_height) +{ + text_layout_changed (layout, y, old_height, new_height, TRUE); +} + void gtk_text_layout_free_line_data (GtkTextLayout *layout, GtkTextLine *line, @@ -633,6 +658,15 @@ gtk_text_layout_invalidate (GtkTextLayout *layout, (layout, start_index, end_index); } +void +gtk_text_layout_invalidate_cursors (GtkTextLayout *layout, + const GtkTextIter *start_index, + const GtkTextIter *end_index) +{ + (* GTK_TEXT_LAYOUT_GET_CLASS (layout)->invalidate_cursors) + (layout, start_index, end_index); +} + GtkTextLineData* gtk_text_layout_wrap (GtkTextLayout *layout, GtkTextLine *line, @@ -748,20 +782,33 @@ gtk_text_layout_invalidate_all (GtkTextLayout *layout) static void gtk_text_layout_invalidate_cache (GtkTextLayout *layout, - GtkTextLine *line) + GtkTextLine *line, + gboolean cursors_only) { if (layout->one_display_cache && line == layout->one_display_cache->line) { - GtkTextLineDisplay *tmp_display = layout->one_display_cache; - layout->one_display_cache = NULL; - gtk_text_layout_free_line_display (layout, tmp_display); + GtkTextLineDisplay *display = layout->one_display_cache; + + if (cursors_only) + { + g_slist_foreach (display->cursors, (GFunc)g_free, NULL); + g_slist_free (display->cursors); + display->cursors = NULL; + display->cursors_invalid = TRUE; + } + else + { + layout->one_display_cache = NULL; + gtk_text_layout_free_line_display (layout, display); + } } } /* Now invalidate the paragraph containing the cursor */ static void -gtk_text_layout_invalidate_cursor_line (GtkTextLayout *layout) +gtk_text_layout_invalidate_cursor_line (GtkTextLayout *layout, + gboolean cursors_only) { GtkTextLayoutPrivate *priv = GTK_TEXT_LAYOUT_GET_PRIVATE (layout); GtkTextLineData *line_data; @@ -772,8 +819,14 @@ gtk_text_layout_invalidate_cursor_line (GtkTextLayout *layout) line_data = _gtk_text_line_get_data (priv->cursor_line, layout); if (line_data) { - gtk_text_layout_invalidate_cache (layout, priv->cursor_line); - _gtk_text_line_invalidate_wrap (priv->cursor_line, line_data); + if (cursors_only) + gtk_text_layout_invalidate_cache (layout, priv->cursor_line, TRUE); + else + { + gtk_text_layout_invalidate_cache (layout, priv->cursor_line, FALSE); + _gtk_text_line_invalidate_wrap (priv->cursor_line, line_data); + } + gtk_text_layout_invalidated (layout); } } @@ -820,7 +873,7 @@ gtk_text_layout_real_invalidate (GtkTextLayout *layout, { GtkTextLineData *line_data = _gtk_text_line_get_data (line, layout); - gtk_text_layout_invalidate_cache (layout, line); + gtk_text_layout_invalidate_cache (layout, line, FALSE); if (line_data) _gtk_text_line_invalidate_wrap (line, line_data); @@ -834,12 +887,48 @@ gtk_text_layout_real_invalidate (GtkTextLayout *layout, gtk_text_layout_invalidated (layout); } +static void +gtk_text_layout_real_invalidate_cursors (GtkTextLayout *layout, + const GtkTextIter *start, + const GtkTextIter *end) +{ + /* Check if the range intersects our cached line display, + * and invalidate the cached line if so. + */ + if (layout->one_display_cache) + { + GtkTextIter line_start, line_end; + GtkTextLine *line = layout->one_display_cache->line; + + _gtk_text_btree_get_iter_at_line (_gtk_text_buffer_get_btree (layout->buffer), + &line_start, line, 0); + line_end = line_start; + if (!gtk_text_iter_ends_line (&line_end)) + gtk_text_iter_forward_to_line_end (&line_end); + + if (gtk_text_iter_compare (start, end) > 0) + { + const GtkTextIter *tmp = start; + start = end; + end = tmp; + } + + if (gtk_text_iter_compare (&line_start, end) <= 0 && + gtk_text_iter_compare (start, &line_end) <= 0) + { + gtk_text_layout_invalidate_cache (layout, line, TRUE); + } + } + + gtk_text_layout_invalidated (layout); +} + static void gtk_text_layout_real_free_line_data (GtkTextLayout *layout, GtkTextLine *line, GtkTextLineData *line_data) { - gtk_text_layout_invalidate_cache (layout, line); + gtk_text_layout_invalidate_cache (layout, line, FALSE); g_free (line_data); } @@ -1789,6 +1878,112 @@ add_preedit_attrs (GtkTextLayout *layout, pango_attr_iterator_destroy (iter); } +/* Iterate over the line and fill in display->cursors. + * It's a stripped copy of gtk_text_layout_get_line_display() */ +static void +update_text_display_cursors (GtkTextLayout *layout, + GtkTextLine *line, + GtkTextLineDisplay *display) +{ + GtkTextLineSegment *seg; + GtkTextIter iter; + gint layout_byte_offset, buffer_byte_offset; + GSList *cursor_byte_offsets = NULL; + GSList *cursor_segs = NULL; + GSList *tmp_list1, *tmp_list2; + + if (!display->cursors_invalid) + return; + + display->cursors_invalid = FALSE; + + _gtk_text_btree_get_iter_at_line (_gtk_text_buffer_get_btree (layout->buffer), + &iter, line, 0); + + /* Special-case optimization for completely + * invisible lines; makes it faster to deal + * with sequences of invisible lines. + */ + if (totally_invisible_line (layout, line, &iter)) + return; + + /* Iterate over segments */ + layout_byte_offset = 0; /* position in the layout text (includes preedit, does not include invisible text) */ + buffer_byte_offset = 0; /* position in the buffer line */ + seg = _gtk_text_iter_get_any_segment (&iter); + while (seg != NULL) + { + /* Displayable segments */ + if (seg->type == >k_text_char_type || + seg->type == >k_text_pixbuf_type || + seg->type == >k_text_child_type) + { + _gtk_text_btree_get_iter_at_line (_gtk_text_buffer_get_btree (layout->buffer), + &iter, line, + buffer_byte_offset); + + if (!_gtk_text_btree_char_is_invisible (&iter)) + layout_byte_offset += seg->byte_count; + + buffer_byte_offset += seg->byte_count; + } + + /* Marks */ + else if (seg->type == >k_text_right_mark_type || + seg->type == >k_text_left_mark_type) + { + gint cursor_offset = 0; + + /* At the insertion point, add the preedit string, if any */ + + if (_gtk_text_btree_mark_is_insert (_gtk_text_buffer_get_btree (layout->buffer), + seg->body.mark.obj)) + { + display->insert_index = layout_byte_offset; + + if (layout->preedit_len > 0) + { + layout_byte_offset += layout->preedit_len; + /* DO NOT increment the buffer byte offset for preedit */ + cursor_offset = layout->preedit_cursor - layout->preedit_len; + } + } + + /* Display visible marks */ + + if (seg->body.mark.visible) + { + cursor_byte_offsets = g_slist_prepend (cursor_byte_offsets, + GINT_TO_POINTER (layout_byte_offset + cursor_offset)); + cursor_segs = g_slist_prepend (cursor_segs, seg); + } + } + + /* Toggles */ + else if (seg->type == >k_text_toggle_on_type || + seg->type == >k_text_toggle_off_type) + { + } + + else + g_error ("Unknown segment type: %s", seg->type->name); + + seg = seg->next; + } + + tmp_list1 = cursor_byte_offsets; + tmp_list2 = cursor_segs; + while (tmp_list1) + { + add_cursor (layout, display, tmp_list2->data, + GPOINTER_TO_INT (tmp_list1->data)); + tmp_list1 = tmp_list1->next; + tmp_list2 = tmp_list2->next; + } + g_slist_free (cursor_byte_offsets); + g_slist_free (cursor_segs); +} + GtkTextLineDisplay * gtk_text_layout_get_line_display (GtkTextLayout *layout, GtkTextLine *line, @@ -1816,7 +2011,11 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout, { if (line == layout->one_display_cache->line && (size_only || !layout->one_display_cache->size_only)) - return layout->one_display_cache; + { + if (!size_only) + update_text_display_cursors (layout, line, layout->one_display_cache); + return layout->one_display_cache; + } else { GtkTextLineDisplay *tmp_display = layout->one_display_cache; @@ -1825,6 +2024,8 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout, } } + DV (g_print ("creating one line display cache (%s)\n", G_STRLOC)); + display = g_new0 (GtkTextLineDisplay, 1); display->size_only = size_only; diff --git a/gtk/gtktextlayout.h b/gtk/gtktextlayout.h index 21e3d53e12..ffc889f711 100644 --- a/gtk/gtktextlayout.h +++ b/gtk/gtktextlayout.h @@ -209,11 +209,14 @@ struct _GtkTextLayoutClass gint x, gint y); + void (*invalidate_cursors) (GtkTextLayout *layout, + const GtkTextIter *start, + const GtkTextIter *end); + /* Padding for future expansion */ void (*_gtk_reserved1) (void); void (*_gtk_reserved2) (void); void (*_gtk_reserved3) (void); - void (*_gtk_reserved4) (void); }; struct _GtkTextAttrAppearance @@ -254,6 +257,8 @@ struct _GtkTextLineDisplay GtkTextLine *line; GdkColor *pg_bg_color; + + guint cursors_invalid : 1; }; extern PangoAttrType gtk_text_attr_appearance_type; @@ -327,6 +332,9 @@ void gtk_text_layout_get_iter_at_position (GtkTextLayout *layout, void gtk_text_layout_invalidate (GtkTextLayout *layout, const GtkTextIter *start, const GtkTextIter *end); +void gtk_text_layout_invalidate_cursors(GtkTextLayout *layout, + const GtkTextIter *start, + const GtkTextIter *end); void gtk_text_layout_free_line_data (GtkTextLayout *layout, GtkTextLine *line, GtkTextLineData *line_data); @@ -353,6 +361,10 @@ void gtk_text_layout_changed (GtkTextLayout *layout, gint y, gint old_height, gint new_height); +void gtk_text_layout_cursors_changed (GtkTextLayout *layout, + gint y, + gint old_height, + gint new_height); void gtk_text_layout_get_iter_location (GtkTextLayout *layout, const GtkTextIter *iter, GdkRectangle *rect);