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.
This commit is contained in:
Owen Taylor 2000-09-08 18:33:03 +00:00 committed by Owen Taylor
parent 38a656ab18
commit 2e2272aac1
10 changed files with 259 additions and 75 deletions

View File

@ -1,3 +1,18 @@
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.
Thu Sep 07 20:54:33 2000 George Lebl <jirka@5z.com>
* gtk/gtkmenu.c: in gtk_menu_set_submenu_navigation_region

View File

@ -1,3 +1,18 @@
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.
Thu Sep 07 20:54:33 2000 George Lebl <jirka@5z.com>
* gtk/gtkmenu.c: in gtk_menu_set_submenu_navigation_region

View File

@ -1,3 +1,18 @@
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.
Thu Sep 07 20:54:33 2000 George Lebl <jirka@5z.com>
* gtk/gtkmenu.c: in gtk_menu_set_submenu_navigation_region

View File

@ -1,3 +1,18 @@
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.
Thu Sep 07 20:54:33 2000 George Lebl <jirka@5z.com>
* gtk/gtkmenu.c: in gtk_menu_set_submenu_navigation_region

View File

@ -1,3 +1,18 @@
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.
Thu Sep 07 20:54:33 2000 George Lebl <jirka@5z.com>
* gtk/gtkmenu.c: in gtk_menu_set_submenu_navigation_region

View File

@ -1,3 +1,18 @@
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.
Thu Sep 07 20:54:33 2000 George Lebl <jirka@5z.com>
* gtk/gtkmenu.c: in gtk_menu_set_submenu_navigation_region

View File

@ -1,3 +1,18 @@
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.
Thu Sep 07 20:54:33 2000 George Lebl <jirka@5z.com>
* gtk/gtkmenu.c: in gtk_menu_set_submenu_navigation_region

View File

@ -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

View File

@ -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,

View File

@ -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),