mirror of
https://github.com/vim/vim.git
synced 2025-09-28 04:24:06 -04:00
patch 8.0.1797: terminal window is redrawn too often
Problem: Terminal window is redrawn too often and scrolling is repeated. Solution: Don't scroll immediately but only when redrawing. Avoid redrawing the whole terminal window on every change.
This commit is contained in:
@@ -14,12 +14,13 @@ void term_enter_job_mode(void);
|
|||||||
int send_keys_to_term(term_T *term, int c, int typed);
|
int send_keys_to_term(term_T *term, int c, int typed);
|
||||||
int terminal_is_active(void);
|
int terminal_is_active(void);
|
||||||
cursorentry_T *term_get_cursor_shape(guicolor_T *fg, guicolor_T *bg);
|
cursorentry_T *term_get_cursor_shape(guicolor_T *fg, guicolor_T *bg);
|
||||||
void term_win_entered(void);
|
|
||||||
int term_use_loop(void);
|
int term_use_loop(void);
|
||||||
|
void term_win_entered(void);
|
||||||
int terminal_loop(int blocking);
|
int terminal_loop(int blocking);
|
||||||
void term_job_ended(job_T *job);
|
void term_job_ended(job_T *job);
|
||||||
void term_channel_closed(channel_T *ch);
|
void term_channel_closed(channel_T *ch);
|
||||||
int term_update_window(win_T *wp);
|
int term_do_update_window(win_T *wp);
|
||||||
|
void term_update_window(win_T *wp);
|
||||||
int term_is_finished(buf_T *buf);
|
int term_is_finished(buf_T *buf);
|
||||||
int term_show_buffer(buf_T *buf);
|
int term_show_buffer(buf_T *buf);
|
||||||
void term_change_in_curbuf(void);
|
void term_change_in_curbuf(void);
|
||||||
|
14
src/screen.c
14
src/screen.c
@@ -567,8 +567,12 @@ update_screen(int type_arg)
|
|||||||
must_redraw = 0;
|
must_redraw = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Need to update w_lines[]. */
|
/* May need to update w_lines[]. */
|
||||||
if (curwin->w_lines_valid == 0 && type < NOT_VALID)
|
if (curwin->w_lines_valid == 0 && type < NOT_VALID
|
||||||
|
#ifdef FEAT_TERMINAL
|
||||||
|
&& !term_do_update_window(curwin)
|
||||||
|
#endif
|
||||||
|
)
|
||||||
type = NOT_VALID;
|
type = NOT_VALID;
|
||||||
|
|
||||||
/* Postpone the redrawing when it's not needed and when being called
|
/* Postpone the redrawing when it's not needed and when being called
|
||||||
@@ -1172,10 +1176,10 @@ win_update(win_T *wp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FEAT_TERMINAL
|
#ifdef FEAT_TERMINAL
|
||||||
/* If this window contains a terminal, redraw works completely differently.
|
// If this window contains a terminal, redraw works completely differently.
|
||||||
*/
|
if (term_do_update_window(wp))
|
||||||
if (term_update_window(wp) == OK)
|
|
||||||
{
|
{
|
||||||
|
term_update_window(wp);
|
||||||
# ifdef FEAT_MENU
|
# ifdef FEAT_MENU
|
||||||
/* Draw the window toolbar, if there is one. */
|
/* Draw the window toolbar, if there is one. */
|
||||||
if (winbar_height(wp) > 0)
|
if (winbar_height(wp) > 0)
|
||||||
|
@@ -42,9 +42,6 @@
|
|||||||
* redirection. Probably in call to channel_set_pipes().
|
* redirection. Probably in call to channel_set_pipes().
|
||||||
* - Win32: Redirecting output does not work, Test_terminal_redir_file()
|
* - Win32: Redirecting output does not work, Test_terminal_redir_file()
|
||||||
* is disabled.
|
* is disabled.
|
||||||
* - handle_moverect() scrolls one line at a time. Postpone scrolling, count
|
|
||||||
* the number of lines, until a redraw happens. Then if scrolling many lines
|
|
||||||
* a redraw is faster.
|
|
||||||
* - Copy text in the vterm to the Vim buffer once in a while, so that
|
* - Copy text in the vterm to the Vim buffer once in a while, so that
|
||||||
* completion works.
|
* completion works.
|
||||||
* - When the job only outputs lines, we could handle resizing the terminal
|
* - When the job only outputs lines, we could handle resizing the terminal
|
||||||
@@ -137,6 +134,8 @@ struct terminal_S {
|
|||||||
int tl_dirty_row_start; /* MAX_ROW if nothing dirty */
|
int tl_dirty_row_start; /* MAX_ROW if nothing dirty */
|
||||||
int tl_dirty_row_end; /* row below last one to update */
|
int tl_dirty_row_end; /* row below last one to update */
|
||||||
|
|
||||||
|
int tl_postponed_scroll; /* to be scrolled up */
|
||||||
|
|
||||||
garray_T tl_scrollback;
|
garray_T tl_scrollback;
|
||||||
int tl_scrollback_scrolled;
|
int tl_scrollback_scrolled;
|
||||||
cellattr_T tl_default_color;
|
cellattr_T tl_default_color;
|
||||||
@@ -2373,44 +2372,55 @@ handle_damage(VTermRect rect, void *user)
|
|||||||
|
|
||||||
term->tl_dirty_row_start = MIN(term->tl_dirty_row_start, rect.start_row);
|
term->tl_dirty_row_start = MIN(term->tl_dirty_row_start, rect.start_row);
|
||||||
term->tl_dirty_row_end = MAX(term->tl_dirty_row_end, rect.end_row);
|
term->tl_dirty_row_end = MAX(term->tl_dirty_row_end, rect.end_row);
|
||||||
redraw_buf_later(term->tl_buffer, NOT_VALID);
|
redraw_buf_later(term->tl_buffer, SOME_VALID);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
term_scroll_up(term_T *term, int start_row, int count)
|
||||||
|
{
|
||||||
|
win_T *wp;
|
||||||
|
VTermColor fg, bg;
|
||||||
|
VTermScreenCellAttrs attr;
|
||||||
|
int clear_attr;
|
||||||
|
|
||||||
|
/* Set the color to clear lines with. */
|
||||||
|
vterm_state_get_default_colors(vterm_obtain_state(term->tl_vterm),
|
||||||
|
&fg, &bg);
|
||||||
|
vim_memset(&attr, 0, sizeof(attr));
|
||||||
|
clear_attr = cell2attr(attr, fg, bg);
|
||||||
|
|
||||||
|
FOR_ALL_WINDOWS(wp)
|
||||||
|
{
|
||||||
|
if (wp->w_buffer == term->tl_buffer)
|
||||||
|
win_del_lines(wp, start_row, count, FALSE, FALSE, clear_attr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
handle_moverect(VTermRect dest, VTermRect src, void *user)
|
handle_moverect(VTermRect dest, VTermRect src, void *user)
|
||||||
{
|
{
|
||||||
term_T *term = (term_T *)user;
|
term_T *term = (term_T *)user;
|
||||||
|
int count = src.start_row - dest.start_row;
|
||||||
|
|
||||||
/* Scrolling up is done much more efficiently by deleting lines instead of
|
/* Scrolling up is done much more efficiently by deleting lines instead of
|
||||||
* redrawing the text. */
|
* redrawing the text. But avoid doing this multiple times, postpone until
|
||||||
|
* the redraw happens. */
|
||||||
if (dest.start_col == src.start_col
|
if (dest.start_col == src.start_col
|
||||||
&& dest.end_col == src.end_col
|
&& dest.end_col == src.end_col
|
||||||
&& dest.start_row < src.start_row)
|
&& dest.start_row < src.start_row)
|
||||||
{
|
{
|
||||||
win_T *wp;
|
if (dest.start_row == 0)
|
||||||
VTermColor fg, bg;
|
term->tl_postponed_scroll += count;
|
||||||
VTermScreenCellAttrs attr;
|
else
|
||||||
int clear_attr;
|
term_scroll_up(term, dest.start_row, count);
|
||||||
|
|
||||||
/* Set the color to clear lines with. */
|
|
||||||
vterm_state_get_default_colors(vterm_obtain_state(term->tl_vterm),
|
|
||||||
&fg, &bg);
|
|
||||||
vim_memset(&attr, 0, sizeof(attr));
|
|
||||||
clear_attr = cell2attr(attr, fg, bg);
|
|
||||||
|
|
||||||
FOR_ALL_WINDOWS(wp)
|
|
||||||
{
|
|
||||||
if (wp->w_buffer == term->tl_buffer)
|
|
||||||
win_del_lines(wp, dest.start_row,
|
|
||||||
src.start_row - dest.start_row, FALSE, FALSE,
|
|
||||||
clear_attr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
term->tl_dirty_row_start = MIN(term->tl_dirty_row_start, dest.start_row);
|
term->tl_dirty_row_start = MIN(term->tl_dirty_row_start, dest.start_row);
|
||||||
term->tl_dirty_row_end = MIN(term->tl_dirty_row_end, dest.end_row);
|
term->tl_dirty_row_end = MIN(term->tl_dirty_row_end, dest.end_row);
|
||||||
|
|
||||||
|
/* Note sure if the scrolling will work correctly, let's do a complete
|
||||||
|
* redraw later. */
|
||||||
redraw_buf_later(term->tl_buffer, NOT_VALID);
|
redraw_buf_later(term->tl_buffer, NOT_VALID);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -2857,11 +2867,22 @@ update_system_term(term_T *term)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called to update a window that contains an active terminal.
|
* Return TRUE if window "wp" is to be redrawn with term_update_window().
|
||||||
* Returns FAIL when there is no terminal running in this window or in
|
* Returns FALSE when there is no terminal running in this window or it is in
|
||||||
* Terminal-Normal mode.
|
* Terminal-Normal mode.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
|
term_do_update_window(win_T *wp)
|
||||||
|
{
|
||||||
|
term_T *term = wp->w_buffer->b_term;
|
||||||
|
|
||||||
|
return term != NULL && term->tl_vterm != NULL && !term->tl_normal_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called to update a window that contains an active terminal.
|
||||||
|
*/
|
||||||
|
void
|
||||||
term_update_window(win_T *wp)
|
term_update_window(win_T *wp)
|
||||||
{
|
{
|
||||||
term_T *term = wp->w_buffer->b_term;
|
term_T *term = wp->w_buffer->b_term;
|
||||||
@@ -2874,17 +2895,23 @@ term_update_window(win_T *wp)
|
|||||||
int minsize;
|
int minsize;
|
||||||
win_T *twp;
|
win_T *twp;
|
||||||
|
|
||||||
if (term == NULL || term->tl_vterm == NULL || term->tl_normal_mode)
|
|
||||||
return FAIL;
|
|
||||||
|
|
||||||
vterm = term->tl_vterm;
|
vterm = term->tl_vterm;
|
||||||
screen = vterm_obtain_screen(vterm);
|
screen = vterm_obtain_screen(vterm);
|
||||||
state = vterm_obtain_state(vterm);
|
state = vterm_obtain_state(vterm);
|
||||||
|
|
||||||
if (wp->w_redr_type >= SOME_VALID)
|
/* We use NOT_VALID on a resize or scroll, redraw everything then. With
|
||||||
|
* SOME_VALID only redraw what was marked dirty. */
|
||||||
|
if (wp->w_redr_type > SOME_VALID)
|
||||||
{
|
{
|
||||||
term->tl_dirty_row_start = 0;
|
term->tl_dirty_row_start = 0;
|
||||||
term->tl_dirty_row_end = MAX_ROW;
|
term->tl_dirty_row_end = MAX_ROW;
|
||||||
|
|
||||||
|
if (term->tl_postponed_scroll > 0
|
||||||
|
&& term->tl_postponed_scroll < term->tl_rows / 3)
|
||||||
|
/* Scrolling is usually faster than redrawing, when there are only
|
||||||
|
* a few lines to scroll. */
|
||||||
|
term_scroll_up(term, 0, term->tl_postponed_scroll);
|
||||||
|
term->tl_postponed_scroll = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2943,8 +2970,6 @@ term_update_window(win_T *wp)
|
|||||||
}
|
}
|
||||||
term->tl_dirty_row_start = MAX_ROW;
|
term->tl_dirty_row_start = MAX_ROW;
|
||||||
term->tl_dirty_row_end = 0;
|
term->tl_dirty_row_end = 0;
|
||||||
|
|
||||||
return OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -761,6 +761,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1797,
|
||||||
/**/
|
/**/
|
||||||
1796,
|
1796,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user