text view: Improve tag pointer tracking

A problem that has been observed in polari is that links in tags
are clickable all the way into the margin. This problem is caused
by gtk_text_view_get_iter_at_position ignoring the return value
of pango_layout_xy_to_index. Instead, pass it back as a boolean
return value. This is technically an API break, but we've allowed
ourselves to change return types from void to gboolean before.
This commit is contained in:
Matthias Clasen 2016-02-10 00:01:54 -05:00
parent 019dab7c38
commit a3a5cf1087
4 changed files with 60 additions and 49 deletions

View File

@ -362,7 +362,7 @@ gtk_text_layout_default_style_changed (GtkTextLayout *layout)
} }
void void
gtk_text_layout_set_default_style (GtkTextLayout *layout, gtk_text_layout_set_default_style (GtkTextLayout *layout,
GtkTextAttributes *values) GtkTextAttributes *values)
{ {
g_return_if_fail (GTK_IS_TEXT_LAYOUT (layout)); g_return_if_fail (GTK_IS_TEXT_LAYOUT (layout));
@ -2736,32 +2736,37 @@ gtk_text_layout_get_line_at_y (GtkTextLayout *layout,
gtk_text_layout_get_iter_at_line (layout, target_iter, line, 0); gtk_text_layout_get_iter_at_line (layout, target_iter, line, 0);
} }
void gboolean
gtk_text_layout_get_iter_at_pixel (GtkTextLayout *layout, gtk_text_layout_get_iter_at_pixel (GtkTextLayout *layout,
GtkTextIter *target_iter, GtkTextIter *target_iter,
gint x, gint x,
gint y) gint y)
{ {
gint trailing; gint trailing;
gboolean inside;
gtk_text_layout_get_iter_at_position (layout, target_iter, &trailing, x, y); inside = gtk_text_layout_get_iter_at_position (layout, target_iter, &trailing, x, y);
gtk_text_iter_forward_chars (target_iter, trailing); gtk_text_iter_forward_chars (target_iter, trailing);
return inside;
} }
void gtk_text_layout_get_iter_at_position (GtkTextLayout *layout, gboolean
GtkTextIter *target_iter, gtk_text_layout_get_iter_at_position (GtkTextLayout *layout,
gint *trailing, GtkTextIter *target_iter,
gint x, gint *trailing,
gint y) gint x,
gint y)
{ {
GtkTextLine *line; GtkTextLine *line;
gint byte_index; gint byte_index;
gint line_top; gint line_top;
GtkTextLineDisplay *display; GtkTextLineDisplay *display;
gboolean inside;
g_return_if_fail (GTK_IS_TEXT_LAYOUT (layout)); g_return_val_if_fail (GTK_IS_TEXT_LAYOUT (layout), FALSE);
g_return_if_fail (target_iter != NULL); g_return_val_if_fail (target_iter != NULL, FALSE);
get_line_at_y (layout, y, &line, &line_top); get_line_at_y (layout, y, &line, &line_top);
@ -2778,6 +2783,8 @@ void gtk_text_layout_get_iter_at_position (GtkTextLayout *layout,
byte_index = _gtk_text_line_byte_count (line); byte_index = _gtk_text_line_byte_count (line);
if (trailing) if (trailing)
*trailing = 0; *trailing = 0;
inside = FALSE;
} }
else else
{ {
@ -2785,13 +2792,15 @@ void gtk_text_layout_get_iter_at_position (GtkTextLayout *layout,
* the right thing even if we are outside the layout in the * the right thing even if we are outside the layout in the
* x-direction. * x-direction.
*/ */
pango_layout_xy_to_index (display->layout, x * PANGO_SCALE, y * PANGO_SCALE, inside = pango_layout_xy_to_index (display->layout, x * PANGO_SCALE, y * PANGO_SCALE,
&byte_index, trailing); &byte_index, trailing);
} }
line_display_index_to_iter (layout, display, target_iter, byte_index, 0); line_display_index_to_iter (layout, display, target_iter, byte_index, 0);
gtk_text_layout_free_line_display (layout, display); gtk_text_layout_free_line_display (layout, display);
return inside;
} }

View File

@ -345,16 +345,16 @@ void gtk_text_layout_get_line_at_y (GtkTextLayout *layout,
gint y, gint y,
gint *line_top); gint *line_top);
GDK_AVAILABLE_IN_ALL GDK_AVAILABLE_IN_ALL
void gtk_text_layout_get_iter_at_pixel (GtkTextLayout *layout, gboolean gtk_text_layout_get_iter_at_pixel (GtkTextLayout *layout,
GtkTextIter *iter, GtkTextIter *iter,
gint x, gint x,
gint y); gint y);
GDK_AVAILABLE_IN_ALL GDK_AVAILABLE_IN_ALL
void gtk_text_layout_get_iter_at_position (GtkTextLayout *layout, gboolean gtk_text_layout_get_iter_at_position (GtkTextLayout *layout,
GtkTextIter *iter, GtkTextIter *iter,
gint *trailing, gint *trailing,
gint x, gint x,
gint y); gint y);
GDK_AVAILABLE_IN_ALL GDK_AVAILABLE_IN_ALL
void gtk_text_layout_invalidate (GtkTextLayout *layout, void gtk_text_layout_invalidate (GtkTextLayout *layout,
const GtkTextIter *start, const GtkTextIter *start,

View File

@ -2091,20 +2091,21 @@ gtk_text_view_get_cursor_locations (GtkTextView *text_view,
* currently-displayed portion. If you have coordinates from an * currently-displayed portion. If you have coordinates from an
* event, you have to convert those to buffer coordinates with * event, you have to convert those to buffer coordinates with
* gtk_text_view_window_to_buffer_coords(). * gtk_text_view_window_to_buffer_coords().
**/ *
void * Returns: %TRUE if the position is over text
*/
gboolean
gtk_text_view_get_iter_at_location (GtkTextView *text_view, gtk_text_view_get_iter_at_location (GtkTextView *text_view,
GtkTextIter *iter, GtkTextIter *iter,
gint x, gint x,
gint y) gint y)
{ {
g_return_if_fail (GTK_IS_TEXT_VIEW (text_view)); g_return_val_if_fail (GTK_IS_TEXT_VIEW (text_view), FALSE);
g_return_if_fail (iter != NULL); g_return_val_if_fail (iter != NULL, FALSE);
gtk_text_view_ensure_layout (text_view); gtk_text_view_ensure_layout (text_view);
gtk_text_layout_get_iter_at_pixel (text_view->priv->layout, return gtk_text_layout_get_iter_at_pixel (text_view->priv->layout, iter, x, y);
iter, x, y);
} }
/** /**
@ -2113,38 +2114,39 @@ gtk_text_view_get_iter_at_location (GtkTextView *text_view,
* @iter: (out): a #GtkTextIter * @iter: (out): a #GtkTextIter
* @trailing: (out) (allow-none): if non-%NULL, location to store an integer indicating where * @trailing: (out) (allow-none): if non-%NULL, location to store an integer indicating where
* in the grapheme the user clicked. It will either be * in the grapheme the user clicked. It will either be
* zero, or the number of characters in the grapheme. * zero, or the number of characters in the grapheme.
* 0 represents the trailing edge of the grapheme. * 0 represents the trailing edge of the grapheme.
* @x: x position, in buffer coordinates * @x: x position, in buffer coordinates
* @y: y position, in buffer coordinates * @y: y position, in buffer coordinates
* *
* Retrieves the iterator pointing to the character at buffer * Retrieves the iterator pointing to the character at buffer
* coordinates @x and @y. Buffer coordinates are coordinates for * coordinates @x and @y. Buffer coordinates are coordinates for
* the entire buffer, not just the currently-displayed portion. * the entire buffer, not just the currently-displayed portion.
* If you have coordinates from an event, you have to convert * If you have coordinates from an event, you have to convert
* those to buffer coordinates with * those to buffer coordinates with
* gtk_text_view_window_to_buffer_coords(). * gtk_text_view_window_to_buffer_coords().
* *
* Note that this is different from gtk_text_view_get_iter_at_location(), * Note that this is different from gtk_text_view_get_iter_at_location(),
* which returns cursor locations, i.e. positions between * which returns cursor locations, i.e. positions between
* characters. * characters.
* *
* Returns: %TRUE if the position is over text
*
* Since: 2.6 * Since: 2.6
**/ **/
void gboolean
gtk_text_view_get_iter_at_position (GtkTextView *text_view, gtk_text_view_get_iter_at_position (GtkTextView *text_view,
GtkTextIter *iter, GtkTextIter *iter,
gint *trailing, gint *trailing,
gint x, gint x,
gint y) gint y)
{ {
g_return_if_fail (GTK_IS_TEXT_VIEW (text_view)); g_return_val_if_fail (GTK_IS_TEXT_VIEW (text_view), FALSE);
g_return_if_fail (iter != NULL); g_return_val_if_fail (iter != NULL, FALSE);
gtk_text_view_ensure_layout (text_view); gtk_text_view_ensure_layout (text_view);
gtk_text_layout_get_iter_at_position (text_view->priv->layout, return gtk_text_layout_get_iter_at_position (text_view->priv->layout, iter, trailing, x, y);
iter, trailing, x, y);
} }
/** /**

View File

@ -259,12 +259,12 @@ void gtk_text_view_get_iter_location (GtkTextView *text_view,
const GtkTextIter *iter, const GtkTextIter *iter,
GdkRectangle *location); GdkRectangle *location);
GDK_AVAILABLE_IN_ALL GDK_AVAILABLE_IN_ALL
void gtk_text_view_get_iter_at_location (GtkTextView *text_view, gboolean gtk_text_view_get_iter_at_location (GtkTextView *text_view,
GtkTextIter *iter, GtkTextIter *iter,
gint x, gint x,
gint y); gint y);
GDK_AVAILABLE_IN_ALL GDK_AVAILABLE_IN_ALL
void gtk_text_view_get_iter_at_position (GtkTextView *text_view, gboolean gtk_text_view_get_iter_at_position (GtkTextView *text_view,
GtkTextIter *iter, GtkTextIter *iter,
gint *trailing, gint *trailing,
gint x, gint x,