diff options
author | Owen Taylor <otaylor@redhat.com> | 2000-09-08 18:33:03 +0000 |
---|---|---|
committer | Owen Taylor <otaylor@src.gnome.org> | 2000-09-08 18:33:03 +0000 |
commit | 2e2272aac14ab669060c107e607611f1f16b6d49 (patch) | |
tree | 1c1f57de2b074ab7d3fff8b74e18e7c73e380432 /gtk | |
parent | 38a656ab1881f9013f3b0bdbb2172840d7685638 (diff) | |
download | gtk+-2e2272aac14ab669060c107e607611f1f16b6d49.tar.gz |
Fix up visibility so that focus, cursor_visible and blink interact
Fri Sep 8 14:28:00 2000 Owen Taylor <otaylor@redhat.com>
* gtk/gtktextview.c: Fix up visibility so that focus,
cursor_visible and blink interact properly. Reenable cursor blink
which had been roughly disabled. Make blink and focus
properly per-view.
* gtk/gtktextlayout.[ch] (gtk_text_layout_set_cursor_visible):
Add a flag for whether to display insertion cursor and
a function to set the flag.
* gtk/gtktextlayout.c (gtk_text_layout_get_line_yrange): Change
get_line_y() to get_line_yrange(), to be a bit more generally
useful.
Diffstat (limited to 'gtk')
-rw-r--r-- | gtk/gtktextlayout.c | 115 | ||||
-rw-r--r-- | gtk/gtktextlayout.h | 33 | ||||
-rw-r--r-- | gtk/gtktextview.c | 81 |
3 files changed, 154 insertions, 75 deletions
diff --git a/gtk/gtktextlayout.c b/gtk/gtktextlayout.c index 09a0ff2a13..a169fe486b 100644 --- a/gtk/gtktextlayout.c +++ b/gtk/gtktextlayout.c @@ -75,6 +75,8 @@ 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_invalidate_cache (GtkTextLayout *layout, + GtkTextLine *line); static void gtk_text_layout_real_free_line_data (GtkTextLayout *layout, GtkTextLine *line, GtkTextLineData *line_data); @@ -177,6 +179,7 @@ gtk_text_layout_class_init (GtkTextLayoutClass *klass) void gtk_text_layout_init (GtkTextLayout *text_layout) { + text_layout->cursor_visible = TRUE; } GtkTextLayout* @@ -329,6 +332,56 @@ gtk_text_layout_set_screen_width (GtkTextLayout *layout, gint width) gtk_text_layout_invalidate_all (layout); } +/** + * gtk_text_layout_set_cursor_visible: + * @layout: a #GtkTextLayout + * @cursor_visible: If %FALSE, then the insertion cursor will not + * be shown, even if the text is editable. + * + * Sets whether the insertion cursor should be shown. Generally, + * widgets using #GtkTextLayout will hide the cursor when the + * widget does not have the input focus. + **/ +void +gtk_text_layout_set_cursor_visible (GtkTextLayout *layout, + gboolean cursor_visible) +{ + cursor_visible = (cursor_visible != FALSE); + + if (layout->cursor_visible != cursor_visible) + { + GtkTextIter iter; + gint y, height; + + layout->cursor_visible = cursor_visible; + + /* Now queue a redraw on the paragraph containing the cursor + */ + gtk_text_buffer_get_iter_at_mark (layout->buffer, &iter, + gtk_text_buffer_get_mark (layout->buffer, "insert")); + + gtk_text_layout_get_line_yrange (layout, &iter, &y, &height); + gtk_text_layout_changed (layout, y, height, height); + + gtk_text_layout_invalidate_cache (layout, gtk_text_iter_get_text_line (&iter)); + } +} + +/** + * gtk_text_layout_get_cursor_visible: + * @layout: a #GtkTextLayout + * + * Returns whether the insertion cursor will be shown. + * + * Return value: if %FALSE, the insertion cursor will not be + shown, even if the text is editable. + **/ +gboolean +gtk_text_layout_get_cursor_visible (GtkTextLayout *layout) +{ + return layout->cursor_visible; +} + void gtk_text_layout_get_size (GtkTextLayout *layout, gint *width, @@ -517,9 +570,18 @@ gtk_text_layout_invalidate_all (GtkTextLayout *layout) gtk_text_layout_invalidate (layout, &start, &end); } -/* FIXME: This is now completely generic, and we could probably be - * moved into gtktextbtree.c. - */ +static void +gtk_text_layout_invalidate_cache (GtkTextLayout *layout, + GtkTextLine *line) +{ + 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); + } +} + static void gtk_text_layout_real_invalidate (GtkTextLayout *layout, const GtkTextIter *start, @@ -546,13 +608,7 @@ gtk_text_layout_real_invalidate (GtkTextLayout *layout, if (line_data && (line != last_line || !gtk_text_iter_starts_line (end))) { - 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); - } + gtk_text_layout_invalidate_cache (layout, line); gtk_text_line_invalidate_wrap (line, line_data); } @@ -1148,11 +1204,12 @@ add_cursor (GtkTextLayout *layout, PangoRectangle strong_pos, weak_pos; GtkTextCursorDisplay *cursor; - /* Hide insertion cursor when we have a selection + /* Hide insertion cursor when we have a selection or the layout + * user has hidden the cursor. */ if (gtk_text_btree_mark_is_insert (_gtk_text_buffer_get_btree (layout->buffer), (GtkTextMark*)seg) && - gtk_text_buffer_get_selection_bounds (layout->buffer, &selection_start, &selection_end)) + (!layout->cursor_visible || gtk_text_buffer_get_selection_bounds (layout->buffer, &selection_start, &selection_end))) return; pango_layout_get_cursor_pos (display->layout, start, &strong_pos, &weak_pos); @@ -1589,27 +1646,41 @@ gtk_text_layout_get_cursor_locations (GtkTextLayout *layout, } /** - * gtk_text_layout_get_line_y: + * gtk_text_layout_get_line_yrange: * @layout: a #GtkTextLayout * @iter: a #GtkTextIter + * @y: location to store the top of the paragraph in pixels, + * or %NULL. + * @height location to store the height of the paragraph in pixels, + * or %NULL. * - * Find the y coordinate of the top of the paragraph containing + * Find the range of y coordinates for the paragraph containing * the given iter. - * - * Return value: the y coordinate, in pixels. **/ -gint -gtk_text_layout_get_line_y (GtkTextLayout *layout, - const GtkTextIter *iter) +void +gtk_text_layout_get_line_yrange (GtkTextLayout *layout, + const GtkTextIter *iter, + gint *y, + gint *height) { GtkTextLine *line; - g_return_val_if_fail (GTK_IS_TEXT_LAYOUT (layout), 0); - g_return_val_if_fail (gtk_text_iter_get_btree (iter) == _gtk_text_buffer_get_btree (layout->buffer), 0); + g_return_if_fail (GTK_IS_TEXT_LAYOUT (layout)); + g_return_if_fail (gtk_text_iter_get_btree (iter) == _gtk_text_buffer_get_btree (layout->buffer)); line = gtk_text_iter_get_text_line (iter); - return gtk_text_btree_find_line_top (_gtk_text_buffer_get_btree (layout->buffer), + + if (y) + *y = gtk_text_btree_find_line_top (_gtk_text_buffer_get_btree (layout->buffer), line, layout); + if (height) + { + GtkTextLineData *line_data = gtk_text_line_get_data (line, layout); + if (line_data) + *height = line_data->height; + else + *height = 0; + } } void diff --git a/gtk/gtktextlayout.h b/gtk/gtktextlayout.h index 79871d3890..048b55d771 100644 --- a/gtk/gtktextlayout.h +++ b/gtk/gtktextlayout.h @@ -67,6 +67,9 @@ struct _GtkTextLayout /* Whether we are allowed to wrap right now */ gint wrap_loop_count; + + /* Whether to show the insertion cursor */ + guint cursor_visible : 1; }; struct _GtkTextLayoutClass @@ -143,16 +146,20 @@ extern PangoAttrType gtk_text_attr_appearance_type; GtkType gtk_text_layout_get_type (void) G_GNUC_CONST; GtkTextLayout *gtk_text_layout_new (void); -void gtk_text_layout_set_buffer (GtkTextLayout *layout, - GtkTextBuffer *buffer); -void gtk_text_layout_set_default_style (GtkTextLayout *layout, - GtkTextAttributes *values); -void gtk_text_layout_set_contexts (GtkTextLayout *layout, - PangoContext *ltr_context, - PangoContext *rtl_context); -void gtk_text_layout_default_style_changed (GtkTextLayout *layout); -void gtk_text_layout_set_screen_width (GtkTextLayout *layout, - gint width); +void gtk_text_layout_set_buffer (GtkTextLayout *layout, + GtkTextBuffer *buffer); +void gtk_text_layout_set_default_style (GtkTextLayout *layout, + GtkTextAttributes *values); +void gtk_text_layout_set_contexts (GtkTextLayout *layout, + PangoContext *ltr_context, + PangoContext *rtl_context); +void gtk_text_layout_default_style_changed (GtkTextLayout *layout); +void gtk_text_layout_set_screen_width (GtkTextLayout *layout, + gint width); + +void gtk_text_layout_set_cursor_visible (GtkTextLayout *layout, + gboolean cursor_visible); +gboolean gtk_text_layout_get_cursor_visible (GtkTextLayout *layout); /* Getting the size or the lines potentially results in a call to * recompute, which is pretty massively expensive. Thus it should @@ -225,8 +232,10 @@ void gtk_text_layout_changed (GtkTextLayout *layout, void gtk_text_layout_get_iter_location (GtkTextLayout *layout, const GtkTextIter *iter, GdkRectangle *rect); -gint gtk_text_layout_get_line_y (GtkTextLayout *layout, - const GtkTextIter *iter); +void gtk_text_layout_get_line_yrange (GtkTextLayout *layout, + const GtkTextIter *iter, + gint *y, + gint *height); void gtk_text_layout_get_cursor_locations (GtkTextLayout *layout, GtkTextIter *iter, GdkRectangle *strong_pos, diff --git a/gtk/gtktextview.c b/gtk/gtktextview.c index 857e7578c4..e97df15f72 100644 --- a/gtk/gtktextview.c +++ b/gtk/gtktextview.c @@ -986,18 +986,24 @@ gtk_text_view_set_cursor_visible (GtkTextView *text_view, { g_return_if_fail (GTK_IS_TEXT_VIEW (text_view)); + setting = (setting != FALSE); + if (text_view->cursor_visible != setting) { text_view->cursor_visible = setting; if (GTK_WIDGET_HAS_FOCUS (text_view)) - { - GtkTextMark *insert; - - insert = gtk_text_buffer_get_mark (text_view->buffer, - "insert"); - gtk_text_mark_set_visible (insert, text_view->cursor_visible); - } + { + if (text_view->layout) + { + gtk_text_layout_set_cursor_visible (text_view->layout, setting); + + if (setting) + gtk_text_view_start_cursor_blink (text_view); + else + gtk_text_view_stop_cursor_blink (text_view); + } + } } } @@ -1039,7 +1045,7 @@ gtk_text_view_destroy (GtkObject *object) gtk_text_view_destroy_layout (text_view); gtk_text_view_set_buffer (text_view, NULL); - + (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); } @@ -1177,7 +1183,9 @@ gtk_text_view_size_allocate (GtkWidget *widget, * the buffer */ gtk_text_view_get_first_para_iter (text_view, &first_para); - y = gtk_text_layout_get_line_y (text_view->layout, &first_para) + text_view->first_para_pixels; + gtk_text_layout_get_line_yrange (text_view->layout, &first_para, &y, NULL); + + y += text_view->first_para_pixels; /* Ensure h/v adj exist */ get_hadjustment (text_view); @@ -1693,15 +1701,15 @@ gtk_text_view_button_release_event (GtkWidget *widget, GdkEventButton *event) static gint gtk_text_view_focus_in_event (GtkWidget *widget, GdkEventFocus *event) { - GtkTextMark *insert; + GtkTextView *text_view = GTK_TEXT_VIEW (widget); GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS); - insert = gtk_text_buffer_get_mark (GTK_TEXT_VIEW (widget)->buffer, - "insert"); - gtk_text_mark_set_visible (insert, GTK_TEXT_VIEW (widget)->cursor_visible); - - gtk_text_view_start_cursor_blink (GTK_TEXT_VIEW (widget)); + if (text_view->cursor_visible && text_view->layout) + { + gtk_text_layout_set_cursor_visible (text_view->layout, TRUE); + gtk_text_view_start_cursor_blink (text_view); + } gtk_im_context_focus_in (GTK_TEXT_VIEW (widget)->im_context); @@ -1711,15 +1719,15 @@ gtk_text_view_focus_in_event (GtkWidget *widget, GdkEventFocus *event) static gint gtk_text_view_focus_out_event (GtkWidget *widget, GdkEventFocus *event) { - GtkTextMark *insert; + GtkTextView *text_view = GTK_TEXT_VIEW (widget); GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS); - insert = gtk_text_buffer_get_mark (GTK_TEXT_VIEW (widget)->buffer, - "insert"); - gtk_text_mark_set_visible (insert, FALSE); - - gtk_text_view_stop_cursor_blink (GTK_TEXT_VIEW (widget)); + if (text_view->cursor_visible && text_view->layout) + { + gtk_text_layout_set_cursor_visible (text_view->layout, FALSE); + gtk_text_view_stop_cursor_blink (text_view); + } gtk_im_context_focus_out (GTK_TEXT_VIEW (widget)->im_context); @@ -1783,33 +1791,19 @@ static gint blink_cb (gpointer data) { GtkTextView *text_view; - GtkTextMark *insert; text_view = GTK_TEXT_VIEW (data); - insert = gtk_text_buffer_get_mark (text_view->buffer, - "insert"); - - if (!GTK_WIDGET_HAS_FOCUS (text_view)) - { - /* paranoia, in case the user somehow mangles our - focus_in/focus_out pairing. */ - gtk_text_mark_set_visible (insert, FALSE); - text_view->blink_timeout = 0; - return FALSE; - } - else - { - gtk_text_mark_set_visible (insert, - !gtk_text_mark_is_visible (insert)); - return TRUE; - } + g_assert (text_view->layout && GTK_WIDGET_HAS_FOCUS (text_view) && text_view->cursor_visible); + + gtk_text_layout_set_cursor_visible (text_view->layout, + !gtk_text_layout_get_cursor_visible (text_view->layout)); + return TRUE; } static void gtk_text_view_start_cursor_blink (GtkTextView *text_view) { - return; if (text_view->blink_timeout != 0) return; @@ -1819,7 +1813,6 @@ gtk_text_view_start_cursor_blink (GtkTextView *text_view) static void gtk_text_view_stop_cursor_blink (GtkTextView *text_view) { - return; if (text_view->blink_timeout == 0) return; @@ -2510,6 +2503,11 @@ gtk_text_view_ensure_layout (GtkTextView *text_view) if (text_view->buffer) gtk_text_layout_set_buffer (text_view->layout, text_view->buffer); + if ((GTK_WIDGET_HAS_FOCUS (text_view) && text_view->cursor_visible)) + gtk_text_view_start_cursor_blink (text_view); + else + gtk_text_layout_set_cursor_visible (text_view->layout, FALSE); + ltr_context = gtk_widget_create_pango_context (GTK_WIDGET (text_view)); pango_context_set_base_dir (ltr_context, PANGO_DIRECTION_LTR); rtl_context = gtk_widget_create_pango_context (GTK_WIDGET (text_view)); @@ -2544,6 +2542,7 @@ gtk_text_view_destroy_layout (GtkTextView *text_view) { if (text_view->layout) { + gtk_text_view_stop_cursor_blink (text_view); gtk_text_view_end_selection_drag (text_view, NULL); gtk_signal_disconnect_by_func (GTK_OBJECT (text_view->layout), |