[vte/wip/bug746690: 2/2] widget: Implement smooth scrolling
- From: Christian Persch <chpe src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vte/wip/bug746690: 2/2] widget: Implement smooth scrolling
- Date: Thu, 8 Oct 2015 12:53:38 +0000 (UTC)
commit 0a6759923178d4bfb431e9038c6ee729e7346732
Author: Egmont Koblinger <egmont gmail com>
Date: Thu Oct 8 14:49:37 2015 +0200
widget: Implement smooth scrolling
WIP
https://bugzilla.gnome.org/show_bug.cgi?id=746690
src/vte-private.h | 5 -
src/vte.cc | 583 +++++++++++++++++++++++++++++-----------------------
src/vteaccess.cc | 5 +-
src/vteinternal.hh | 3 +-
4 files changed, 330 insertions(+), 266 deletions(-)
---
diff --git a/src/vte-private.h b/src/vte-private.h
index b6867f1..9b389fc 100644
--- a/src/vte-private.h
+++ b/src/vte-private.h
@@ -112,11 +112,6 @@ void _vte_terminal_handle_sequence(VteTerminal *terminal,
const char *match,
GValueArray *params);
-gboolean _vte_terminal_xy_to_grid(VteTerminal *terminal,
- long x,
- long y,
- long *col,
- long *row);
gboolean _vte_terminal_size_to_grid_size(VteTerminal *terminal,
long w,
long h,
diff --git a/src/vte.cc b/src/vte.cc
index 224d895..26590a7 100644
--- a/src/vte.cc
+++ b/src/vte.cc
@@ -383,6 +383,79 @@ _vte_terminal_set_default_attributes(VteTerminal *terminal)
terminal->pvt->fill_defaults = terminal->pvt->defaults;
}
+static inline glong
+_vte_terminal_scroll_delta_pixel (VteTerminal *terminal)
+{
+ return round(terminal->pvt->screen->scroll_delta * terminal->pvt->char_height);
+}
+
+/* Pixel is relative to viewport, top padding excluded.
+ * Row is relative to the beginning of the terminal history, like {insert,scroll}_delta. */
+static inline glong
+_vte_terminal_pixel_to_row (VteTerminal *terminal,
+ glong y)
+{
+ return (_vte_terminal_scroll_delta_pixel(terminal) + y) / terminal->pvt->char_height;
+}
+
+/* Row is relative to the beginning of the terminal history, like {insert,scroll}_delta.
+ * Pixel is relative to viewport, top padding excluded. */
+static inline glong
+_vte_terminal_row_to_pixel (VteTerminal *terminal,
+ glong row)
+{
+ return row * terminal->pvt->char_height - (glong) round(terminal->pvt->screen->scroll_delta *
terminal->pvt->char_height);
+}
+
+static inline glong
+_vte_terminal_first_displayed_row (VteTerminal *terminal)
+{
+ return _vte_terminal_pixel_to_row (terminal, 0);
+}
+
+static inline glong
+_vte_terminal_last_displayed_row (VteTerminal *terminal)
+{
+ GtkAllocation allocation;
+
+ gtk_widget_get_allocation (&terminal->widget, &allocation);
+ return _vte_terminal_pixel_to_row (terminal,
+ allocation.height - terminal->pvt->padding.top -
terminal->pvt->padding.bottom - 1);
+}
+
+/* x, y are coordinates excluding the padding.
+ * col, row are in 0..width-1, 0..height-1.
+ * Returns FALSE if clicked over scrollback content; output values are unchanged then.
+ */
+static gboolean
+_vte_terminal_mouse_pixels_to_grid (VteTerminal *terminal,
+ long x, long y,
+ long *col, long *row)
+{
+ VteTerminalPrivate *pvt = terminal->pvt;
+ long c, r;
+
+ /* Vertical is tricky: combine smooth scrolling, extra area near the bottom,
+ * and scrollbar being dragged back a bit. */
+ /* Confine top padding clicks while still in pixels. */
+ y = MAX(y, 0);
+ r = _vte_terminal_pixel_to_row(terminal, y);
+ /* Clicking on scrollback area. */
+ if (r < terminal->pvt->screen->insert_delta)
+ return FALSE;
+ r -= terminal->pvt->screen->insert_delta;
+ /* Handle bottom padding now. */
+ r = MIN(r, terminal->pvt->row_count - 1);
+
+ /* After these, horizontal is piece of cake. */
+ c = x / pvt->char_width;
+ c = CLAMP (c, 0, pvt->column_count - 1);
+
+ *col = c;
+ *row = r;
+ return TRUE;
+}
+
/* Cause certain cells to be repainted. */
void
_vte_invalidate_cells(VteTerminal *terminal,
@@ -390,7 +463,7 @@ _vte_invalidate_cells(VteTerminal *terminal,
glong row_start, gint row_count)
{
cairo_rectangle_int_t rect;
- glong i;
+ GtkAllocation allocation;
if (G_UNLIKELY (!gtk_widget_get_realized(&terminal->widget)))
return;
@@ -404,64 +477,51 @@ _vte_invalidate_cells(VteTerminal *terminal,
}
_vte_debug_print (VTE_DEBUG_UPDATES,
- "Invalidating cells at (%ld,%ld+%ld)x(%d,%d).\n",
+ "Invalidating cells at (%ld,%ld)x(%d,%d).\n",
column_start, row_start,
- (long)terminal->pvt->screen->scroll_delta,
column_count, row_count);
_vte_debug_print (VTE_DEBUG_WORK, "?");
- /* Subtract the scrolling offset from the row start so that the
- * resulting rectangle is relative to the visible portion of the
- * buffer. */
- row_start -= terminal->pvt->screen->scroll_delta;
-
- /* Ensure the start of region is on screen */
- if (column_start > terminal->pvt->column_count ||
- row_start > terminal->pvt->row_count) {
- return;
- }
-
- /* Clamp the start values to reasonable numbers. */
- i = row_start + row_count;
- row_start = MAX (0, row_start);
- row_count = CLAMP (i - row_start, 0, terminal->pvt->row_count);
-
- i = column_start + column_count;
- column_start = MAX (0, column_start);
- column_count = CLAMP (i - column_start, 0 , terminal->pvt->column_count);
-
if (!column_count || !row_count) {
return;
}
if (column_count == terminal->pvt->column_count &&
- row_count == terminal->pvt->row_count) {
+ row_count == terminal->pvt->row_count &&
+ terminal->pvt->screen->scroll_delta == terminal->pvt->screen->insert_delta) {
_vte_invalidate_all (terminal);
return;
}
+ gtk_widget_get_allocation (&terminal->widget, &allocation);
+
/* Convert the column and row start and end to pixel values
* by multiplying by the size of a character cell.
* Always include the extra pixel border and overlap pixel.
*/
- rect.x = column_start * terminal->pvt->char_width - 1;
- if (column_start != 0) {
- rect.x += terminal->pvt->padding.left;
- }
- rect.width = (column_start + column_count) * terminal->pvt->char_width + 3 +
terminal->pvt->padding.left;
- if (column_start + column_count == terminal->pvt->column_count) {
- rect.width += terminal->pvt->padding.right;
- }
+ rect.x = terminal->pvt->padding.left + column_start * terminal->pvt->char_width - 1;
+ if (rect.x <= 0 /* TODOegmont if artifacts remain on the screen then: terminal->pvt->padding.left */)
+ rect.x = 0;
+ /* Temporarily misuse rect.width for the end x coordinate... */
+ rect.width = terminal->pvt->padding.left + (column_start + column_count) * terminal->pvt->char_width
+ 2; /* TODO why 2 and not 1? */
+ if (rect.width >= allocation.width /* TODOegmont if artifacts remain on the screen then:
terminal->pvt->padding.left + terminal->pvt->column_count * terminal->pvt->char_width */)
+ rect.width = allocation.width;
+ /* ... fix that here */
rect.width -= rect.x;
- rect.y = row_start * terminal->pvt->char_height - 1;
- if (row_start != 0) {
- rect.y += terminal->pvt->padding.top;
- }
- rect.height = (row_start + row_count) * terminal->pvt->char_height + 2 + terminal->pvt->padding.top;
- if (row_start + row_count == terminal->pvt->row_count) {
- rect.height += terminal->pvt->padding.bottom;
- }
- rect.height -= rect.y;
+ rect.y = terminal->pvt->padding.top + _vte_terminal_row_to_pixel(terminal, row_start) - 1;
+ if (rect.y <= 0 /* TODOegmont if artifacts remain on the screen then: terminal->pvt->padding.top */)
+ rect.y = 0;
+
+ /* Temporarily misuse rect.height for the end y coordinate... */
+ rect.height = terminal->pvt->padding.top + _vte_terminal_row_to_pixel(terminal, row_start +
row_count) + 1;
+ if (rect.height >= allocation.height /* TODOegmont if artifacts remain on the screen then:
terminal->pvt->padding.top + terminal->pvt->row_count * terminal->pvt->char_height */)
+ rect.height = allocation.height;
+ /* ... fix that here */
+ rect.height -= rect.y;
+
+ /* Ensure the values make sense */
+ if (rect.width <= 0 || rect.height <= 0)
+ return;
_vte_debug_print (VTE_DEBUG_UPDATES,
"Invalidating pixels at (%d,%d)x(%d,%d).\n",
@@ -1134,12 +1194,21 @@ static void
vte_terminal_match_contents_refresh(VteTerminal *terminal)
{
GArray *array;
+ long start_row, start_col, end_row, end_col;
+
+ start_row = _vte_terminal_first_displayed_row (terminal);
+ start_col = 0;
+ end_row = _vte_terminal_last_displayed_row (terminal);
+ end_col = terminal->pvt->column_count - 1;
+
vte_terminal_match_contents_clear(terminal);
array = g_array_new(FALSE, TRUE, sizeof(struct _VteCharAttributes));
- terminal->pvt->match_contents = vte_terminal_get_text(terminal,
- always_selected,
- NULL,
- array);
+ terminal->pvt->match_contents = vte_terminal_get_text_range(terminal,
+ start_row, start_col,
+ end_row, end_col,
+ always_selected,
+ NULL,
+ array);
terminal->pvt->match_attributes = array;
}
@@ -2127,6 +2196,35 @@ vte_terminal_match_check(VteTerminal *terminal, glong column, glong row,
return ret;
}
+static gboolean
+rowcol_from_event(VteTerminal *terminal,
+ GdkEvent *event,
+ long *column,
+ long *row)
+{
+ double x, y;
+ GtkAllocation allocation;
+
+ if (event == NULL)
+ return FALSE;
+ if (((GdkEventAny*)event)->window != gtk_widget_get_window(&terminal->widget))
+ return FALSE;
+ if (!gdk_event_get_coords(event, &x, &y))
+ return FALSE;
+
+ gtk_widget_get_allocation (&terminal->widget, &allocation);
+
+ x -= terminal->pvt->padding.left;
+ y -= terminal->pvt->padding.top;
+ if (x < 0 || x >= terminal->pvt->column_count * terminal->pvt->char_width ||
+ y < 0 || y >= allocation.height - terminal->pvt->padding.top - terminal->pvt->padding.bottom)
+ return FALSE;
+ *column = x / terminal->pvt->char_width;
+ *row = _vte_terminal_pixel_to_row(terminal, y);
+
+ return TRUE;
+}
+
/**
* vte_terminal_match_check_event:
* @terminal: a #VteTerminal
@@ -2150,21 +2248,15 @@ vte_terminal_match_check_event(VteTerminal *terminal,
GdkEvent *event,
int *tag)
{
- double x, y;
long col, row;
g_return_val_if_fail(VTE_IS_TERMINAL(terminal), FALSE);
- if (event == NULL)
- return FALSE;
- if (((GdkEventAny*)event)->window != gtk_widget_get_window(&terminal->widget))
- return FALSE;
- if (!gdk_event_get_coords(event, &x, &y))
- return FALSE;
- if (!_vte_terminal_xy_to_grid(terminal, x, y, &col, &row))
+ if (!rowcol_from_event(terminal, event, &col, &row))
return FALSE;
- return vte_terminal_match_check(terminal, col, row, tag);
+ /* FIXME Shouldn't rely on a deprecated, not sub-row aware method. */
+ return vte_terminal_match_check(terminal, col, row - (long) terminal->pvt->screen->scroll_delta,
tag);
}
/**
@@ -2199,7 +2291,6 @@ vte_terminal_event_check_regex_simple(VteTerminal *terminal,
pcre2_match_data_8 *match_data;
pcre2_match_context_8 *match_context;
gboolean any_matches = FALSE;
- double x, y;
long col, row;
guint i;
@@ -2208,11 +2299,7 @@ vte_terminal_event_check_regex_simple(VteTerminal *terminal,
g_return_val_if_fail(regexes != NULL || n_regexes == 0, FALSE);
g_return_val_if_fail(matches != NULL, FALSE);
- if (((GdkEventAny*)event)->window != gtk_widget_get_window(&terminal->widget))
- return FALSE;
- if (!gdk_event_get_coords(event, &x, &y))
- return FALSE;
- if (!_vte_terminal_xy_to_grid(terminal, x, y, &col, &row))
+ if (!rowcol_from_event(terminal, event, &col, &row))
return FALSE;
if (pvt->match_contents == NULL) {
@@ -2285,7 +2372,6 @@ vte_terminal_event_check_gregex_simple(VteTerminal *terminal,
VteTerminalPrivate *pvt = terminal->pvt;
gsize offset, sattr, eattr;
gboolean any_matches = FALSE;
- double x, y;
long col, row;
guint i;
@@ -2294,11 +2380,7 @@ vte_terminal_event_check_gregex_simple(VteTerminal *terminal,
g_return_val_if_fail(regexes != NULL || n_regexes == 0, FALSE);
g_return_val_if_fail(matches != NULL, FALSE);
- if (((GdkEventAny*)event)->window != gtk_widget_get_window(&terminal->widget))
- return FALSE;
- if (!gdk_event_get_coords(event, &x, &y))
- return FALSE;
- if (!_vte_terminal_xy_to_grid(terminal, x, y, &col, &row))
+ if (!rowcol_from_event(terminal, event, &col, &row))
return FALSE;
if (pvt->match_contents == NULL) {
@@ -2374,11 +2456,11 @@ vte_terminal_emit_adjustment_changed(VteTerminal *terminal)
terminal->pvt->adjustment_changed_pending = FALSE;
}
if (terminal->pvt->adjustment_value_changed_pending) {
- glong v, delta;
+ double v, delta;
_vte_debug_print(VTE_DEBUG_SIGNALS,
"Emitting adjustment_value_changed.\n");
terminal->pvt->adjustment_value_changed_pending = FALSE;
- v = round (gtk_adjustment_get_value(terminal->pvt->vadjustment));
+ v = gtk_adjustment_get_value(terminal->pvt->vadjustment);
if (v != terminal->pvt->screen->scroll_delta) {
/* this little dance is so that the scroll_delta is
* updated immediately, but we still handled scrolling
@@ -2401,9 +2483,12 @@ vte_terminal_queue_adjustment_changed(VteTerminal *terminal)
}
static void
-vte_terminal_queue_adjustment_value_changed(VteTerminal *terminal, glong v)
+vte_terminal_queue_adjustment_value_changed(VteTerminal *terminal, double v)
{
if (v != terminal->pvt->screen->scroll_delta) {
+ _vte_debug_print(VTE_DEBUG_ADJ,
+ "Adjustment value changed to %f\n",
+ v);
terminal->pvt->screen->scroll_delta = v;
terminal->pvt->adjustment_value_changed_pending = TRUE;
add_update_timeout (terminal);
@@ -2411,7 +2496,7 @@ vte_terminal_queue_adjustment_value_changed(VteTerminal *terminal, glong v)
}
static void
-vte_terminal_queue_adjustment_value_changed_clamped(VteTerminal *terminal, glong v)
+vte_terminal_queue_adjustment_value_changed_clamped(VteTerminal *terminal, double v)
{
gdouble lower, upper;
@@ -2512,10 +2597,15 @@ _vte_terminal_adjust_adjustments_full (VteTerminal *terminal)
static void
vte_terminal_scroll_lines(VteTerminal *terminal, gint lines)
{
- glong destination;
+ double destination;
_vte_debug_print(VTE_DEBUG_ADJ, "Scrolling %d lines.\n", lines);
/* Calculate the ideal position where we want to be before clamping. */
destination = terminal->pvt->screen->scroll_delta;
+ /* Snap to whole cell offset. */
+ if (lines > 0)
+ destination = floor(destination);
+ else if (lines < 0)
+ destination = ceil(destination);
destination += lines;
/* Tell the scrollbar to adjust itself. */
vte_terminal_queue_adjustment_value_changed_clamped (terminal, destination);
@@ -4311,7 +4401,8 @@ vte_terminal_process_incoming(VteTerminal *terminal)
gboolean cursor_visible;
GdkPoint bbox_topleft, bbox_bottomright;
gunichar *wbuf, c;
- long wcount, start, delta;
+ long wcount, start;
+ long top_row, bottom_row;
gboolean leftovers, modified, bottom, again;
gboolean invalidated_text;
gboolean in_scroll_region;
@@ -4327,8 +4418,10 @@ vte_terminal_process_incoming(VteTerminal *terminal)
screen = terminal->pvt->screen;
- delta = screen->scroll_delta;
- bottom = screen->insert_delta == delta;
+ bottom = screen->insert_delta == (long) screen->scroll_delta;
+
+ top_row = _vte_terminal_first_displayed_row(terminal);
+ bottom_row = _vte_terminal_last_displayed_row(terminal);
/* Save the current cursor position. */
cursor = terminal->pvt->cursor;
@@ -4449,7 +4542,9 @@ skip_chunk:
&& (terminal->pvt->cursor.row >= (screen->insert_delta +
terminal->pvt->scrolling_region.start))
&& (terminal->pvt->cursor.row <= (screen->insert_delta +
terminal->pvt->scrolling_region.end));
- delta = screen->scroll_delta; /* delta may have changed from sequence. */
+ /* delta may have changed from sequence. */
+ top_row = _vte_terminal_first_displayed_row(terminal);
+ bottom_row = _vte_terminal_last_displayed_row(terminal);
/* if we have moved greatly during the sequence handler, or moved
* into a scroll_region from outside it, restart the bbox.
@@ -4462,12 +4557,12 @@ skip_chunk:
terminal->pvt->cursor.row < bbox_topleft.y -
VTE_CELL_BBOX_SLACK))) {
/* Clip off any part of the box which isn't already on-screen. */
bbox_topleft.x = MAX(bbox_topleft.x, 0);
- bbox_topleft.y = MAX(bbox_topleft.y, delta);
+ bbox_topleft.y = MAX(bbox_topleft.y, top_row);
bbox_bottomright.x = MIN(bbox_bottomright.x,
terminal->pvt->column_count);
/* lazily apply the +1 to the cursor_row */
bbox_bottomright.y = MIN(bbox_bottomright.y + 1,
- delta + terminal->pvt->row_count);
+ bottom_row + 1);
_vte_invalidate_cells(terminal,
bbox_topleft.x,
@@ -4554,12 +4649,12 @@ skip_chunk:
terminal->pvt->cursor.row < bbox_topleft.y -
VTE_CELL_BBOX_SLACK)) {
/* Clip off any part of the box which isn't already on-screen. */
bbox_topleft.x = MAX(bbox_topleft.x, 0);
- bbox_topleft.y = MAX(bbox_topleft.y, delta);
+ bbox_topleft.y = MAX(bbox_topleft.y, top_row);
bbox_bottomright.x = MIN(bbox_bottomright.x,
terminal->pvt->column_count);
/* lazily apply the +1 to the cursor_row */
bbox_bottomright.y = MIN(bbox_bottomright.y + 1,
- delta + terminal->pvt->row_count);
+ bottom_row + 1);
_vte_invalidate_cells(terminal,
bbox_topleft.x,
@@ -4674,12 +4769,12 @@ next_match:
if (invalidated_text) {
/* Clip off any part of the box which isn't already on-screen. */
bbox_topleft.x = MAX(bbox_topleft.x, 0);
- bbox_topleft.y = MAX(bbox_topleft.y, delta);
+ bbox_topleft.y = MAX(bbox_topleft.y, top_row);
bbox_bottomright.x = MIN(bbox_bottomright.x,
terminal->pvt->column_count);
/* lazily apply the +1 to the cursor_row */
bbox_bottomright.y = MIN(bbox_bottomright.y + 1,
- delta + terminal->pvt->row_count);
+ bottom_row + 1);
_vte_invalidate_cells(terminal,
bbox_topleft.x,
@@ -4709,8 +4804,7 @@ next_match:
rect.x = terminal->pvt->cursor.col *
terminal->pvt->char_width + terminal->pvt->padding.left;
rect.width = terminal->pvt->char_width;
- rect.y = (terminal->pvt->cursor.row - delta) *
- terminal->pvt->char_height + terminal->pvt->padding.top;
+ rect.y = _vte_terminal_row_to_pixel(terminal, terminal->pvt->cursor.row) +
terminal->pvt->padding.top;
rect.height = terminal->pvt->char_height;
gtk_im_context_set_cursor_location(terminal->pvt->im_context,
&rect);
@@ -6099,40 +6193,6 @@ vte_terminal_paste_cb(GtkClipboard *clipboard, const gchar *text, gpointer data)
}
}
-/**
- * _vte_terminal_xy_to_grid:
- * @x: the X coordinate
- * @y: the Y coordinate
- * @col: return location to store the column
- * @row: return location to store the row
- *
- * Translates from widget coordinates to grid coordinates.
- *
- * If the coordinates are outside the grid, returns %FALSE.
- */
-gboolean
-_vte_terminal_xy_to_grid(VteTerminal *terminal,
- long x,
- long y,
- long *col,
- long *row)
-{
- VteTerminalPrivate *pvt = terminal->pvt;
- long c, r;
-
- /* FIXMEchpe: is this correct for RTL? */
- c = (x - pvt->padding.left) / pvt->char_width;
- r = (y - pvt->padding.top) / pvt->char_height;
-
- if ((c < 0 || c >= pvt->column_count) ||
- (r < 0 || r >= pvt->row_count))
- return FALSE;
-
- *col = c;
- *row = r;
- return TRUE;
-}
-
/*
* _vte_terminal_size_to_grid_size:
* @w: the width in px
@@ -6223,11 +6283,9 @@ vte_terminal_feed_mouse_event(VteTerminal *terminal,
cb |= 32;
}
- /* Clamp the cursor coordinates. Make them 1-based. */
- cx = CLAMP(1 + col,
- 1, terminal->pvt->column_count);
- cy = CLAMP(1 + row,
- 1, terminal->pvt->row_count);
+ /* Make coordinates 1-based. */
+ cx = col + 1;
+ cy = row + 1;
/* Check the extensions in decreasing order of preference. Encoding the release event above assumes
that 1006 comes first. */
if (terminal->pvt->mouse_xterm_extension) {
@@ -6252,13 +6310,12 @@ vte_terminal_send_mouse_button_internal(VteTerminal *terminal,
long x,
long y)
{
- int width = terminal->pvt->char_width;
- int height = terminal->pvt->char_height;
- long col = (x - terminal->pvt->padding.left) / width;
- long row = (y - terminal->pvt->padding.top) / height -
- (terminal->pvt->screen->insert_delta - terminal->pvt->screen->scroll_delta);
+ long col, row;
- if (row < 0)
+ if (!_vte_terminal_mouse_pixels_to_grid (terminal,
+ x - terminal->pvt->padding.left,
+ y - terminal->pvt->padding.top,
+ &col, &row))
return;
vte_terminal_feed_mouse_event(terminal, button, FALSE /* not drag */, is_release, col, row);
@@ -6336,14 +6393,13 @@ vte_terminal_maybe_send_mouse_button(VteTerminal *terminal,
static gboolean
vte_terminal_maybe_send_mouse_drag(VteTerminal *terminal, GdkEventMotion *event)
{
- int width = terminal->pvt->char_width;
- int height = terminal->pvt->char_height;
- long col = ((long) event->x - terminal->pvt->padding.left) / width;
- long row = ((long) event->y - terminal->pvt->padding.top) / height -
- (terminal->pvt->screen->insert_delta - terminal->pvt->screen->scroll_delta);
+ long col, row;
int button;
- if (row < 0)
+ if (!_vte_terminal_mouse_pixels_to_grid (terminal,
+ (long) event->x - terminal->pvt->padding.left,
+ (long) event->y - terminal->pvt->padding.top,
+ &col, &row))
return FALSE;
/* First determine if we even want to send notification. */
@@ -6359,8 +6415,8 @@ vte_terminal_maybe_send_mouse_drag(VteTerminal *terminal, GdkEventMotion *event)
}
/* the xterm doc is not clear as to whether
* all-tracking also sends degenerate same-cell events */
- if (col == terminal->pvt->mouse_last_x / width &&
- row == terminal->pvt->mouse_last_y / height)
+ if (col == terminal->pvt->mouse_last_col &&
+ row == terminal->pvt->mouse_last_row)
return FALSE;
}
break;
@@ -6415,10 +6471,8 @@ vte_terminal_match_hilite_clear(VteTerminal *terminal)
static gboolean
cursor_inside_match (VteTerminal *terminal, long x, long y)
{
- gint width = terminal->pvt->char_width;
- gint height = terminal->pvt->char_height;
- glong col = x / width;
- glong row = y / height + terminal->pvt->screen->scroll_delta;
+ glong col = x / terminal->pvt->char_width;
+ glong row = _vte_terminal_pixel_to_row(terminal, y);
if (terminal->pvt->match_start.row == terminal->pvt->match_end.row) {
return row == terminal->pvt->match_start.row &&
col >= terminal->pvt->match_start.col &&
@@ -6472,28 +6526,20 @@ static void
vte_terminal_match_hilite_update(VteTerminal *terminal, long x, long y)
{
gsize start, end;
- int width, height;
char *match;
struct _VteCharAttributes *attr;
- VteScreen *screen;
- long delta;
-
- width = terminal->pvt->char_width;
- height = terminal->pvt->char_height;
/* Check for matches. */
- screen = terminal->pvt->screen;
- delta = screen->scroll_delta;
_vte_debug_print(VTE_DEBUG_EVENTS,
"Match hilite update (%ld, %ld) -> %ld, %ld\n",
x, y,
- x / width,
- y / height + delta);
+ x / terminal->pvt->char_width,
+ _vte_terminal_pixel_to_row(terminal, y));
match = vte_terminal_match_check_internal(terminal,
- x / width,
- y / height + delta,
+ x / terminal->pvt->char_width,
+ _vte_terminal_pixel_to_row(terminal, y),
&terminal->pvt->match_tag,
&start,
&end);
@@ -6566,12 +6612,8 @@ vte_terminal_match_hilite_update(VteTerminal *terminal, long x, long y)
static void
vte_terminal_match_hilite(VteTerminal *terminal, long x, long y)
{
- int width, height;
GtkAllocation allocation;
- width = terminal->pvt->char_width;
- height = terminal->pvt->char_height;
-
gtk_widget_get_allocation (&terminal->widget, &allocation);
/* if the cursor is not above a cell, skip */
@@ -6582,8 +6624,8 @@ vte_terminal_match_hilite(VteTerminal *terminal, long x, long y)
/* If the pointer hasn't moved to another character cell, then we
* need do nothing. */
- if (x / width == terminal->pvt->mouse_last_x / width &&
- y / height == terminal->pvt->mouse_last_y / height) {
+ if (x / terminal->pvt->char_width == terminal->pvt->mouse_last_x / terminal->pvt->char_width &&
+ _vte_terminal_pixel_to_row(terminal, y) == _vte_terminal_pixel_to_row(terminal,
terminal->pvt->mouse_last_y)) {
terminal->pvt->show_match = terminal->pvt->match != NULL;
return;
}
@@ -7284,13 +7326,19 @@ vte_terminal_confine_coordinates (VteTerminal *terminal, long *xp, long *yp)
{
long x = *xp;
long y = *yp;
+ long y_stop;
+
+ /* Allow to use the bottom extra padding only if there's content there. */
+ y_stop = _vte_terminal_last_displayed_row (terminal) + 1;
+ y_stop = MIN(y_stop, _vte_terminal_row_to_pixel(terminal,
_vte_ring_next(terminal->pvt->screen->row_data)));
+ y_stop = MAX(y_stop, terminal->pvt->row_count * terminal->pvt->char_height);
if (y < 0) {
y = 0;
if (!terminal->pvt->selection_block_mode)
x = 0;
- } else if (y >= terminal->pvt->row_count * terminal->pvt->char_height) {
- y = terminal->pvt->row_count * terminal->pvt->char_height - 1;
+ } else if (y >= y_stop) {
+ y = y_stop - 1;
if (!terminal->pvt->selection_block_mode)
x = terminal->pvt->column_count * terminal->pvt->char_width - 1;
}
@@ -7309,8 +7357,6 @@ static void
vte_terminal_start_selection(VteTerminal *terminal, long x, long y,
enum vte_selection_type selection_type)
{
- long delta;
-
if (terminal->pvt->selection_block_mode)
selection_type = selection_type_char;
@@ -7318,10 +7364,9 @@ vte_terminal_start_selection(VteTerminal *terminal, long x, long y,
vte_terminal_confine_coordinates(terminal, &x, &y);
/* Record that we have the selection, and where it started. */
- delta = terminal->pvt->screen->scroll_delta;
terminal->pvt->has_selection = TRUE;
terminal->pvt->selection_last.x = x;
- terminal->pvt->selection_last.y = y + (terminal->pvt->char_height * delta);
+ terminal->pvt->selection_last.y = _vte_terminal_scroll_delta_pixel(terminal) + y;
/* Decide whether or not to restart on the next drag. */
switch (selection_type) {
@@ -7601,9 +7646,8 @@ static void
vte_terminal_extend_selection(VteTerminal *terminal, long x, long y,
gboolean always_grow, gboolean force)
{
- VteScreen *screen;
int width, height;
- long delta, residual;
+ long residual;
struct selection_event_coords *origin, *last, *start, *end;
VteVisualPosition old_start, old_end, *sc, *ec, *so, *eo;
gboolean invalidate_selected = FALSE;
@@ -7615,15 +7659,11 @@ vte_terminal_extend_selection(VteTerminal *terminal, long x, long y,
/* Confine coordinates into the visible area. (#563024, #722635c7) */
vte_terminal_confine_coordinates(terminal, &x, &y);
- screen = terminal->pvt->screen;
old_start = terminal->pvt->selection_start;
old_end = terminal->pvt->selection_end;
so = &old_start;
eo = &old_end;
- /* Convert the event coordinates to cell coordinates. */
- delta = screen->scroll_delta;
-
/* If we're restarting on a drag, then mark this as the start of
* the selected block. */
if (terminal->pvt->selecting_restart) {
@@ -7649,7 +7689,7 @@ vte_terminal_extend_selection(VteTerminal *terminal, long x, long y,
origin = &terminal->pvt->selection_origin;
if (terminal->pvt->selection_block_mode) {
last->x = x;
- last->y = y + height * delta;
+ last->y = _vte_terminal_scroll_delta_pixel(terminal) + y;
/* We don't support always_grow in block mode */
if (always_grow)
@@ -7667,7 +7707,7 @@ vte_terminal_extend_selection(VteTerminal *terminal, long x, long y,
} else {
if (!always_grow) {
last->x = x;
- last->y = y + height * delta;
+ last->y = _vte_terminal_scroll_delta_pixel(terminal) + y;
}
if ((origin->y / height < last->y / height) ||
@@ -7686,15 +7726,15 @@ vte_terminal_extend_selection(VteTerminal *terminal, long x, long y,
* closer to the new point. */
if (always_grow) {
/* New endpoint is before existing selection. */
- if ((y / height < ((start->y / height) - delta)) ||
- ((y / height == ((start->y / height) - delta)) &&
+ if (_vte_terminal_pixel_to_row(terminal, y) < start->y / height ||
+ ((_vte_terminal_pixel_to_row(terminal, y) == start->y / height) &&
(x / width < start->x / width))) {
start->x = x;
- start->y = y + height * delta;
+ start->y = _vte_terminal_scroll_delta_pixel(terminal) + y;
} else {
/* New endpoint is after existing selection. */
end->x = x;
- end->y = y + height * delta;
+ end->y = _vte_terminal_scroll_delta_pixel(terminal) + y;
}
}
}
@@ -7880,6 +7920,9 @@ vte_terminal_autoscroll(VteTerminal *terminal)
gboolean extend = FALSE;
long x, y, xmax, ymax;
glong adj;
+ GtkAllocation allocation;
+
+ gtk_widget_get_allocation (&terminal->widget, &allocation);
/* Provide an immediate effect for mouse wigglers. */
if (terminal->pvt->mouse_last_y < 0) {
@@ -7892,7 +7935,7 @@ vte_terminal_autoscroll(VteTerminal *terminal)
_vte_debug_print(VTE_DEBUG_EVENTS, "Autoscrolling down.\n");
}
if (terminal->pvt->mouse_last_y >=
- terminal->pvt->row_count * terminal->pvt->char_height) {
+ allocation.height - terminal->pvt->padding.top - terminal->pvt->padding.bottom) {
if (terminal->pvt->vadjustment) {
/* Try to scroll up by one line. */
adj = terminal->pvt->screen->scroll_delta + 1;
@@ -7970,7 +8013,8 @@ vte_terminal_motion_notify(GtkWidget *widget, GdkEventMotion *event)
_vte_debug_print(VTE_DEBUG_EVENTS,
"Motion notify (%ld,%ld) [%ld, %ld].\n",
x, y,
- x / width, y / height + terminal->pvt->screen->scroll_delta);
+ x / width,
+ _vte_terminal_pixel_to_row(terminal, y));
vte_terminal_read_modifiers (terminal, (GdkEvent*) event);
@@ -8029,6 +8073,10 @@ vte_terminal_motion_notify(GtkWidget *widget, GdkEventMotion *event)
/* Save the pointer coordinates for later use. */
terminal->pvt->mouse_last_x = x;
terminal->pvt->mouse_last_y = y;
+ _vte_terminal_mouse_pixels_to_grid (terminal,
+ x, y,
+ &terminal->pvt->mouse_last_col,
+ &terminal->pvt->mouse_last_row);
return handled;
}
@@ -8038,7 +8086,6 @@ static gint
vte_terminal_button_press(GtkWidget *widget, GdkEventButton *event)
{
VteTerminal *terminal;
- long height, width, delta;
gboolean handled = FALSE;
gboolean start_selecting = FALSE, extend_selecting = FALSE;
long cellx, celly;
@@ -8049,10 +8096,6 @@ vte_terminal_button_press(GtkWidget *widget, GdkEventButton *event)
x = event->x - terminal->pvt->padding.left;
y = event->y - terminal->pvt->padding.top;
- height = terminal->pvt->char_height;
- width = terminal->pvt->char_width;
- delta = terminal->pvt->screen->scroll_delta;
-
vte_terminal_match_hilite(terminal, x, y);
_vte_terminal_set_pointer_visible(terminal, TRUE);
@@ -8060,15 +8103,15 @@ vte_terminal_button_press(GtkWidget *widget, GdkEventButton *event)
vte_terminal_read_modifiers (terminal, (GdkEvent*) event);
/* Convert the event coordinates to cell coordinates. */
- cellx = x / width;
- celly = y / height + delta;
+ cellx = x / terminal->pvt->char_width;
+ celly = _vte_terminal_pixel_to_row(terminal, y);
switch (event->type) {
case GDK_BUTTON_PRESS:
_vte_debug_print(VTE_DEBUG_EVENTS,
"Button %d single-click at (%ld,%ld)\n",
event->button,
- x, y + terminal->pvt->char_height * delta);
+ x, _vte_terminal_scroll_delta_pixel(terminal) + y);
/* Handle this event ourselves. */
switch (event->button) {
case 1:
@@ -8152,7 +8195,7 @@ vte_terminal_button_press(GtkWidget *widget, GdkEventButton *event)
_vte_debug_print(VTE_DEBUG_EVENTS,
"Button %d double-click at (%ld,%ld)\n",
event->button,
- x, y + (terminal->pvt->char_height * delta));
+ x, _vte_terminal_scroll_delta_pixel(terminal) + y);
switch (event->button) {
case 1:
if (terminal->pvt->selecting_after_threshold) {
@@ -8178,7 +8221,7 @@ vte_terminal_button_press(GtkWidget *widget, GdkEventButton *event)
_vte_debug_print(VTE_DEBUG_EVENTS,
"Button %d triple-click at (%ld,%ld).\n",
event->button,
- x, y + (terminal->pvt->char_height * delta));
+ x, _vte_terminal_scroll_delta_pixel(terminal) + y);
switch (event->button) {
case 1:
if ((terminal->pvt->mouse_handled_buttons & 1) != 0) {
@@ -8202,6 +8245,10 @@ vte_terminal_button_press(GtkWidget *widget, GdkEventButton *event)
terminal->pvt->mouse_pressed_buttons |= (1 << (event->button - 1));
terminal->pvt->mouse_last_x = x;
terminal->pvt->mouse_last_y = y;
+ _vte_terminal_mouse_pixels_to_grid (terminal,
+ x, y,
+ &terminal->pvt->mouse_last_col,
+ &terminal->pvt->mouse_last_row);
return handled;
}
@@ -8258,6 +8305,10 @@ vte_terminal_button_release(GtkWidget *widget, GdkEventButton *event)
terminal->pvt->mouse_pressed_buttons &= ~(1 << (event->button - 1));
terminal->pvt->mouse_last_x = x;
terminal->pvt->mouse_last_y = y;
+ _vte_terminal_mouse_pixels_to_grid (terminal,
+ x, y,
+ &terminal->pvt->mouse_last_col,
+ &terminal->pvt->mouse_last_row);
terminal->pvt->selecting_after_threshold = FALSE;
return handled;
@@ -8685,22 +8736,22 @@ vte_terminal_screen_set_size(VteTerminal *terminal, VteScreen *screen, glong old
VteVisualPosition below_viewport;
VteVisualPosition below_current_paragraph;
VteVisualPosition *markers[7];
- gboolean was_scrolled_to_top = (screen->scroll_delta == _vte_ring_delta(ring));
- gboolean was_scrolled_to_bottom = (screen->scroll_delta == screen->insert_delta);
+ gboolean was_scrolled_to_top = ((long) ceil(screen->scroll_delta) == _vte_ring_delta(ring));
+ gboolean was_scrolled_to_bottom = ((long) screen->scroll_delta == screen->insert_delta);
glong old_top_lines;
- glong new_scroll_delta;
+ double new_scroll_delta;
if (terminal->pvt->selection_block_mode && do_rewrap && old_columns != terminal->pvt->column_count)
vte_terminal_deselect_all(terminal);
_vte_debug_print(VTE_DEBUG_RESIZE,
"Resizing %s screen\n"
- "Old insert_delta=%ld scroll_delta=%ld\n"
- " cursor (absolute) row=%ld (visual line %ld) col=%ld\n"
+ "Old insert_delta=%ld scroll_delta=%f\n"
+ " cursor (absolute) row=%ld col=%ld\n"
" cursor_saved (relative to insert_delta) row=%ld col=%ld\n",
screen == &terminal->pvt->normal_screen ? "normal" : "alternate",
screen->insert_delta, screen->scroll_delta,
- terminal->pvt->cursor.row, terminal->pvt->cursor.row - screen->scroll_delta + 1,
terminal->pvt->cursor.col,
+ terminal->pvt->cursor.row, terminal->pvt->cursor.col,
screen->saved.cursor.row, screen->saved.cursor.col);
cursor_saved_absolute.row = screen->saved.cursor.row + screen->insert_delta;
@@ -8786,6 +8837,8 @@ vte_terminal_screen_set_size(VteTerminal *terminal, VteScreen *screen, glong old
TODO: What would be the best behavior if the bottom of the screen is a
soft line break, i.e. only a partial line is visible at the bottom? */
new_scroll_delta = below_viewport.row - terminal->pvt->row_count;
+ /* Keep the old fractional part. */
+ new_scroll_delta += screen->scroll_delta - floor(screen->scroll_delta);
_vte_debug_print(VTE_DEBUG_RESIZE,
"Scroll so bottom row stays\n");
}
@@ -8797,11 +8850,11 @@ vte_terminal_screen_set_size(VteTerminal *terminal, VteScreen *screen, glong old
screen->saved.cursor.col = cursor_saved_absolute.col;
_vte_debug_print(VTE_DEBUG_RESIZE,
- "New insert_delta=%ld scroll_delta=%ld\n"
- " cursor (absolute) row=%ld (visual line %ld) col=%ld\n"
+ "New insert_delta=%ld scroll_delta=%f\n"
+ " cursor (absolute) row=%ld col=%ld\n"
" cursor_saved (relative to insert_delta) row=%ld col=%ld\n\n",
screen->insert_delta, new_scroll_delta,
- terminal->pvt->cursor.row, terminal->pvt->cursor.row - new_scroll_delta + 1,
terminal->pvt->cursor.col,
+ terminal->pvt->cursor.row, terminal->pvt->cursor.col,
screen->saved.cursor.row, screen->saved.cursor.col);
if (screen == terminal->pvt->screen)
@@ -8882,13 +8935,13 @@ vte_terminal_set_size(VteTerminal *terminal, glong columns, glong rows)
static void
vte_terminal_handle_scroll(VteTerminal *terminal)
{
- long dy, adj;
+ double dy, adj;
VteScreen *screen;
screen = terminal->pvt->screen;
/* Read the new adjustment value and save the difference. */
- adj = round (gtk_adjustment_get_value(terminal->pvt->vadjustment));
+ adj = gtk_adjustment_get_value(terminal->pvt->vadjustment);
dy = adj - screen->scroll_delta;
screen->scroll_delta = adj;
@@ -8901,9 +8954,8 @@ vte_terminal_handle_scroll(VteTerminal *terminal)
if (dy != 0) {
_vte_debug_print(VTE_DEBUG_ADJ,
- "Scrolling by %ld\n", dy);
- _vte_terminal_scroll_region(terminal, screen->scroll_delta,
- terminal->pvt->row_count, -dy);
+ "Scrolling by %f\n", dy);
+ _vte_invalidate_all(terminal);
vte_terminal_emit_text_scrolled(terminal, dy);
_vte_terminal_queue_contents_changed(terminal);
} else {
@@ -10502,15 +10554,21 @@ vte_terminal_expand_region (VteTerminal *terminal, cairo_region_t *region, const
int width, height;
int row, col, row_stop, col_stop;
cairo_rectangle_int_t rect;
+ GtkAllocation allocation;
width = terminal->pvt->char_width;
height = terminal->pvt->char_height;
+ gtk_widget_get_allocation (&terminal->widget, &allocation);
+
/* increase the paint by one pixel on all sides to force the
* inclusion of neighbouring cells */
- row = MAX(0, (area->y - terminal->pvt->padding.top - 1) / height);
- row_stop = MIN(howmany(area->height + area->y - terminal->pvt->padding.top + 1, height),
- terminal->pvt->row_count);
+ row = _vte_terminal_pixel_to_row(terminal, MAX(0, area->y - terminal->pvt->padding.top - 1));
+ /* Both the value given by MIN() and row_stop are exclusive.
+ * _vte_terminal_pixel_to_row expects an actual value corresponding
+ * to the bottom visible pixel, hence the - 1 + 1 magic. */
+ row_stop = _vte_terminal_pixel_to_row(terminal, MIN(area->height + area->y -
terminal->pvt->padding.top + 1,
+ allocation.height -
terminal->pvt->padding.bottom) - 1) + 1;
if (row_stop <= row) {
return;
}
@@ -10524,7 +10582,7 @@ vte_terminal_expand_region (VteTerminal *terminal, cairo_region_t *region, const
rect.x = col*width + terminal->pvt->padding.left;
rect.width = (col_stop - col) * width;
- rect.y = row*height + terminal->pvt->padding.top;
+ rect.y = _vte_terminal_row_to_pixel(terminal, row) + terminal->pvt->padding.top;
rect.height = (row_stop - row)*height;
/* the rect must be cell aligned to avoid overlapping XY bands */
@@ -10544,17 +10602,23 @@ static void
vte_terminal_paint_area (VteTerminal *terminal, const GdkRectangle *area)
{
VteScreen *screen;
- int width, height, delta;
+ int width, height;
int row, col, row_stop, col_stop;
+ GtkAllocation allocation;
screen = terminal->pvt->screen;
width = terminal->pvt->char_width;
height = terminal->pvt->char_height;
- row = MAX(0, (area->y - terminal->pvt->padding.top) / height);
- row_stop = MIN((area->height + area->y - terminal->pvt->padding.top) / height,
- terminal->pvt->row_count);
+ gtk_widget_get_allocation (&terminal->widget, &allocation);
+
+ row = _vte_terminal_pixel_to_row(terminal, MAX(0, area->y - terminal->pvt->padding.top));
+ /* Both the value given by MIN() and row_stop are exclusive.
+ * _vte_terminal_pixel_to_row expects an actual value corresponding
+ * to the bottom visible pixel, hence the - 1 + 1 magic. */
+ row_stop = _vte_terminal_pixel_to_row(terminal, MIN(area->height + area->y -
terminal->pvt->padding.top,
+ allocation.height -
terminal->pvt->padding.bottom) - 1) + 1;
if (row_stop <= row) {
return;
}
@@ -10578,13 +10642,12 @@ vte_terminal_paint_area (VteTerminal *terminal, const GdkRectangle *area)
/* Now we're ready to draw the text. Iterate over the rows we
* need to draw. */
- delta = screen->scroll_delta;
vte_terminal_draw_rows(terminal,
screen,
- row + delta, row_stop - row,
+ row, row_stop - row,
col, col_stop - col,
col * width,
- row * height,
+ _vte_terminal_row_to_pixel(terminal, row),
width,
height);
}
@@ -10592,11 +10655,10 @@ vte_terminal_paint_area (VteTerminal *terminal, const GdkRectangle *area)
static void
vte_terminal_paint_cursor(VteTerminal *terminal)
{
- VteScreen *screen;
const VteCell *cell;
struct _vte_draw_text_request item;
- int row, drow, col;
- long width, height, delta, cursor_width;
+ int drow, col;
+ long width, height, cursor_width;
guint fore, back;
PangoColor bg;
int x, y;
@@ -10605,16 +10667,16 @@ vte_terminal_paint_cursor(VteTerminal *terminal)
if (!terminal->pvt->cursor_visible)
return;
- screen = terminal->pvt->screen;
- delta = screen->scroll_delta;
+ if (terminal->pvt->im_preedit_active)
+ return;
+
col = terminal->pvt->cursor.col;
drow = terminal->pvt->cursor.row;
- row = drow - delta;
width = terminal->pvt->char_width;
height = terminal->pvt->char_height;
- if ((CLAMP(col, 0, terminal->pvt->column_count - 1) != col) ||
- (CLAMP(row, 0, terminal->pvt->row_count - 1) != row))
+ /* TODOegmont: clamp on rows? tricky... */
+ if (CLAMP(col, 0, terminal->pvt->column_count - 1) != col)
return;
focus = terminal->pvt->has_focus;
@@ -10635,7 +10697,7 @@ vte_terminal_paint_cursor(VteTerminal *terminal)
item.c = (cell && cell->c) ? cell->c : ' ';
item.columns = item.c == '\t' ? 1 : cell ? cell->attr.columns : 1;
item.x = col * width;
- item.y = row * height;
+ item.y = _vte_terminal_row_to_pixel(terminal, drow);
cursor_width = item.columns * width;
if (cell && cell->c != 0) {
guint style;
@@ -10684,22 +10746,12 @@ vte_terminal_paint_cursor(VteTerminal *terminal)
case VTE_CURSOR_SHAPE_BLOCK:
if (focus) {
- gboolean hilite = FALSE;
-
/* just reverse the character under the cursor */
vte_terminal_fill_rectangle (terminal,
&bg,
x, y,
cursor_width, height);
- if (cell && terminal->pvt->show_match) {
- hilite = vte_cell_is_between(col, row,
- terminal->pvt->match_start.col,
- terminal->pvt->match_start.row,
- terminal->pvt->match_end.col,
- terminal->pvt->match_end.row,
- TRUE);
- }
if (cell && cell->c != 0 && cell->c != ' ') {
vte_terminal_draw_cells(terminal,
&item, 1,
@@ -10708,7 +10760,7 @@ vte_terminal_paint_cursor(VteTerminal *terminal)
cell->attr.italic,
cell->attr.underline,
cell->attr.strikethrough,
- hilite,
+ FALSE,
FALSE,
width,
height);
@@ -10731,24 +10783,17 @@ vte_terminal_paint_cursor(VteTerminal *terminal)
static void
vte_terminal_paint_im_preedit_string(VteTerminal *terminal)
{
- VteScreen *screen;
- int row, col, columns;
- long width, height, delta;
+ int col, columns;
+ long width, height;
int i, len;
guint fore, back;
if (!terminal->pvt->im_preedit)
return;
- /* Get going. */
- screen = terminal->pvt->screen;
-
/* Keep local copies of rendering information. */
width = terminal->pvt->char_width;
height = terminal->pvt->char_height;
- delta = screen->scroll_delta;
-
- row = terminal->pvt->cursor.row - delta;
/* Find out how many columns the pre-edit string takes up. */
columns = vte_terminal_preedit_width(terminal, FALSE);
@@ -10773,13 +10818,13 @@ vte_terminal_paint_im_preedit_string(VteTerminal *terminal)
items[i].columns = _vte_unichar_width(items[i].c,
terminal->pvt->utf8_ambiguous_width);
items[i].x = (col + columns) * width;
- items[i].y = row * height;
+ items[i].y = _vte_terminal_row_to_pixel(terminal, terminal->pvt->cursor.row);
columns += items[i].columns;
preedit = g_utf8_next_char(preedit);
}
_vte_draw_clear(terminal->pvt->draw,
col * width + terminal->pvt->padding.left,
- row * height + terminal->pvt->padding.top,
+ _vte_terminal_row_to_pixel(terminal, terminal->pvt->cursor.row) +
terminal->pvt->padding.top,
width * columns,
height);
fore = terminal->pvt->color_defaults.attr.fore;
@@ -10815,6 +10860,7 @@ vte_terminal_draw(GtkWidget *widget,
cairo_rectangle_int_t clip_rect;
cairo_region_t *region;
int allocated_width, allocated_height;
+ int extra_area_for_cursor;
if (!gdk_cairo_get_clip_rectangle (cr, &clip_rect))
return FALSE;
@@ -10838,6 +10884,12 @@ vte_terminal_draw(GtkWidget *widget,
_vte_draw_clear (terminal->pvt->draw, 0, 0,
allocated_width, allocated_height);
+ /* Clip vertically, for the sake of smooth scrolling. We want the top and bottom paddings to be
unused.
+ * Don't clip horizontally so that antialiasing can legally overflow to the right padding. */
+ cairo_save(cr);
+ cairo_rectangle(cr, 0, terminal->pvt->padding.top, allocated_width, allocated_height -
terminal->pvt->padding.top - terminal->pvt->padding.bottom);
+ cairo_clip(cr);
+
/* Calculate the bounding rectangle. */
{
cairo_rectangle_int_t *rectangles;
@@ -10874,9 +10926,20 @@ vte_terminal_draw(GtkWidget *widget,
g_free (rectangles);
}
+ vte_terminal_paint_im_preedit_string(terminal);
+
+ cairo_restore(cr);
+
+ /* Re-clip, allowing 1 more pixel row for the outline cursor. */
+ /* TODOegmont: It's really ugly to do it here. */
+ cairo_save(cr);
+ extra_area_for_cursor = (_vte_terminal_decscusr_cursor_shape(terminal) == VTE_CURSOR_SHAPE_BLOCK &&
!terminal->pvt->has_focus) ? 1 : 0;
+ cairo_rectangle(cr, 0, terminal->pvt->padding.top - extra_area_for_cursor, allocated_width,
allocated_height - terminal->pvt->padding.top - terminal->pvt->padding.bottom + 2 * extra_area_for_cursor);
+ cairo_clip(cr);
+
vte_terminal_paint_cursor(terminal);
- vte_terminal_paint_im_preedit_string(terminal);
+ cairo_restore(cr);
/* Done with various structures. */
_vte_draw_set_cairo(terminal->pvt->draw, NULL);
@@ -10994,19 +11057,19 @@ vte_terminal_scroll(GtkWidget *widget, GdkEventScroll *event)
_vte_debug_print(VTE_DEBUG_EVENTS,
"Scroll speed is %d lines per non-smooth scroll unit\n",
(int) v);
- cnt = v * terminal->pvt->mouse_smooth_scroll_delta;
- if (cnt == 0)
- return TRUE;
- terminal->pvt->mouse_smooth_scroll_delta -= cnt / v;
- _vte_debug_print(VTE_DEBUG_EVENTS,
- "Scroll by %d lines, smooth scroll delta set back to %f\n",
- cnt, terminal->pvt->mouse_smooth_scroll_delta);
-
if (terminal->pvt->screen == &terminal->pvt->alternate_screen &&
terminal->pvt->alternate_screen_scroll) {
char *normal;
gssize normal_length;
+ cnt = v * terminal->pvt->mouse_smooth_scroll_delta;
+ if (cnt == 0)
+ return TRUE;
+ terminal->pvt->mouse_smooth_scroll_delta -= cnt / v;
+ _vte_debug_print(VTE_DEBUG_EVENTS,
+ "Scroll by %d lines, smooth scroll delta set back to %f\n",
+ cnt, terminal->pvt->mouse_smooth_scroll_delta);
+
/* In the alternate screen there is no scrolling,
* so fake a few cursor keystrokes. */
@@ -11026,8 +11089,9 @@ vte_terminal_scroll(GtkWidget *widget, GdkEventScroll *event)
g_free (normal);
} else {
/* Perform a history scroll. */
- cnt += terminal->pvt->screen->scroll_delta;
- vte_terminal_queue_adjustment_value_changed_clamped (terminal, cnt);
+ double dcnt = terminal->pvt->screen->scroll_delta + v *
terminal->pvt->mouse_smooth_scroll_delta;
+ vte_terminal_queue_adjustment_value_changed_clamped (terminal, dcnt);
+ terminal->pvt->mouse_smooth_scroll_delta = 0;
}
return TRUE;
@@ -12652,7 +12716,8 @@ vte_terminal_set_scrollback_lines(VteTerminal *terminal, glong lines)
{
VteTerminalPrivate *pvt;
GObject *object;
- glong scroll_delta, low, high, next;
+ glong low, high, next;
+ double scroll_delta;
VteScreen *screen;
g_return_if_fail(VTE_IS_TERMINAL(terminal));
@@ -12940,6 +13005,8 @@ vte_terminal_reset(VteTerminal *terminal,
pvt->mouse_handled_buttons = 0;
pvt->mouse_last_x = 0;
pvt->mouse_last_y = 0;
+ pvt->mouse_last_col = 0;
+ pvt->mouse_last_row = 0;
pvt->mouse_xterm_extension = FALSE;
pvt->mouse_urxvt_extension = FALSE;
pvt->mouse_smooth_scroll_delta = 0.;
@@ -14115,10 +14182,10 @@ vte_terminal_search_rows(VteTerminal *terminal,
value = gtk_adjustment_get_value(terminal->pvt->vadjustment);
page_size = gtk_adjustment_get_page_size(terminal->pvt->vadjustment);
if (backward) {
- if (end_row < value || end_row >= value + page_size)
+ if (end_row < value || end_row > value + page_size - 1)
vte_terminal_queue_adjustment_value_changed_clamped (terminal, end_row - page_size +
1);
} else {
- if (start_row < value || start_row >= value + page_size)
+ if (start_row < value || start_row > value + page_size - 1)
vte_terminal_queue_adjustment_value_changed_clamped (terminal, start_row);
}
diff --git a/src/vteaccess.cc b/src/vteaccess.cc
index c5c6414..6eea312 100644
--- a/src/vteaccess.cc
+++ b/src/vteaccess.cc
@@ -511,7 +511,9 @@ vte_terminal_accessible_text_scrolled(VteTerminal *terminal,
long delta, row_count;
guint i, len;
- g_assert(howmuch != 0);
+// FIXME!
+// g_assert(howmuch != 0);
+ if (howmuch == 0) return;
row_count = vte_terminal_get_row_count(terminal);
if (((howmuch < 0) && (howmuch <= -row_count)) ||
@@ -1381,7 +1383,6 @@ vte_terminal_accessible_get_offset_at_point(AtkText *text,
terminal = VTE_TERMINAL (gtk_accessible_get_widget (GTK_ACCESSIBLE (text)));
atk_component_get_extents (ATK_COMPONENT (text), &base_x, &base_y, &w, &h, coords);
- /* FIXME: use _vte_terminal_xy_to_grid */
char_width = vte_terminal_get_char_width (terminal);
char_height = vte_terminal_get_char_height (terminal);
x -= base_x;
diff --git a/src/vteinternal.hh b/src/vteinternal.hh
index 9175b8f..7573ada 100644
--- a/src/vteinternal.hh
+++ b/src/vteinternal.hh
@@ -121,7 +121,7 @@ struct _vte_incoming_chunk{
typedef struct _VteScreen VteScreen;
struct _VteScreen {
VteRing row_data[1]; /* buffer contents */
- long scroll_delta; /* scroll offset */
+ double scroll_delta; /* scroll offset */
long insert_delta; /* insertion offset */
/* Stuff saved along with the cursor */
@@ -324,6 +324,7 @@ public:
guint mouse_pressed_buttons; /* bits 0, 1, 2 resp. for buttons 1, 2, 3 */
guint mouse_handled_buttons; /* similar bitmap for buttons we handled ourselves */
long mouse_last_x, mouse_last_y;
+ long mouse_last_col, mouse_last_row;
gboolean mouse_autohide;
guint mouse_autoscroll_tag;
gboolean mouse_xterm_extension;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]