comparison src/terminal.c @ 13851:3edac4cd1c0a v8.0.1797

patch 8.0.1797: terminal window is redrawn too often commit https://github.com/vim/vim/commit/6eddadff13164b98fe8198153cc656897b2cbcb3 Author: Bram Moolenaar <Bram@vim.org> Date: Sun May 6 16:40:16 2018 +0200 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.
author Christian Brabandt <cb@256bit.org>
date Sun, 06 May 2018 16:45:05 +0200
parents 58b6982ca049
children 7f892e37b017
comparison
equal deleted inserted replaced
13850:939759958f27 13851:3edac4cd1c0a
40 * TODO: 40 * TODO:
41 * - Win32: Make terminal used for :!cmd in the GUI work better. Allow for 41 * - Win32: Make terminal used for :!cmd in the GUI work better. Allow for
42 * redirection. Probably in call to channel_set_pipes(). 42 * redirection. Probably in call to channel_set_pipes().
43 * - Win32: Redirecting output does not work, Test_terminal_redir_file() 43 * - Win32: Redirecting output does not work, Test_terminal_redir_file()
44 * is disabled. 44 * is disabled.
45 * - handle_moverect() scrolls one line at a time. Postpone scrolling, count
46 * the number of lines, until a redraw happens. Then if scrolling many lines
47 * a redraw is faster.
48 * - Copy text in the vterm to the Vim buffer once in a while, so that 45 * - Copy text in the vterm to the Vim buffer once in a while, so that
49 * completion works. 46 * completion works.
50 * - When the job only outputs lines, we could handle resizing the terminal 47 * - When the job only outputs lines, we could handle resizing the terminal
51 * better: store lines separated by line breaks, instead of screen lines, 48 * better: store lines separated by line breaks, instead of screen lines,
52 * then when the window is resized redraw those lines. 49 * then when the window is resized redraw those lines.
134 char_u *tl_status_text; /* NULL or allocated */ 131 char_u *tl_status_text; /* NULL or allocated */
135 132
136 /* Range of screen rows to update. Zero based. */ 133 /* Range of screen rows to update. Zero based. */
137 int tl_dirty_row_start; /* MAX_ROW if nothing dirty */ 134 int tl_dirty_row_start; /* MAX_ROW if nothing dirty */
138 int tl_dirty_row_end; /* row below last one to update */ 135 int tl_dirty_row_end; /* row below last one to update */
136
137 int tl_postponed_scroll; /* to be scrolled up */
139 138
140 garray_T tl_scrollback; 139 garray_T tl_scrollback;
141 int tl_scrollback_scrolled; 140 int tl_scrollback_scrolled;
142 cellattr_T tl_default_color; 141 cellattr_T tl_default_color;
143 142
2371 { 2370 {
2372 term_T *term = (term_T *)user; 2371 term_T *term = (term_T *)user;
2373 2372
2374 term->tl_dirty_row_start = MIN(term->tl_dirty_row_start, rect.start_row); 2373 term->tl_dirty_row_start = MIN(term->tl_dirty_row_start, rect.start_row);
2375 term->tl_dirty_row_end = MAX(term->tl_dirty_row_end, rect.end_row); 2374 term->tl_dirty_row_end = MAX(term->tl_dirty_row_end, rect.end_row);
2376 redraw_buf_later(term->tl_buffer, NOT_VALID); 2375 redraw_buf_later(term->tl_buffer, SOME_VALID);
2377 return 1; 2376 return 1;
2377 }
2378
2379 static void
2380 term_scroll_up(term_T *term, int start_row, int count)
2381 {
2382 win_T *wp;
2383 VTermColor fg, bg;
2384 VTermScreenCellAttrs attr;
2385 int clear_attr;
2386
2387 /* Set the color to clear lines with. */
2388 vterm_state_get_default_colors(vterm_obtain_state(term->tl_vterm),
2389 &fg, &bg);
2390 vim_memset(&attr, 0, sizeof(attr));
2391 clear_attr = cell2attr(attr, fg, bg);
2392
2393 FOR_ALL_WINDOWS(wp)
2394 {
2395 if (wp->w_buffer == term->tl_buffer)
2396 win_del_lines(wp, start_row, count, FALSE, FALSE, clear_attr);
2397 }
2378 } 2398 }
2379 2399
2380 static int 2400 static int
2381 handle_moverect(VTermRect dest, VTermRect src, void *user) 2401 handle_moverect(VTermRect dest, VTermRect src, void *user)
2382 { 2402 {
2383 term_T *term = (term_T *)user; 2403 term_T *term = (term_T *)user;
2404 int count = src.start_row - dest.start_row;
2384 2405
2385 /* Scrolling up is done much more efficiently by deleting lines instead of 2406 /* Scrolling up is done much more efficiently by deleting lines instead of
2386 * redrawing the text. */ 2407 * redrawing the text. But avoid doing this multiple times, postpone until
2408 * the redraw happens. */
2387 if (dest.start_col == src.start_col 2409 if (dest.start_col == src.start_col
2388 && dest.end_col == src.end_col 2410 && dest.end_col == src.end_col
2389 && dest.start_row < src.start_row) 2411 && dest.start_row < src.start_row)
2390 { 2412 {
2391 win_T *wp; 2413 if (dest.start_row == 0)
2392 VTermColor fg, bg; 2414 term->tl_postponed_scroll += count;
2393 VTermScreenCellAttrs attr; 2415 else
2394 int clear_attr; 2416 term_scroll_up(term, dest.start_row, count);
2395
2396 /* Set the color to clear lines with. */
2397 vterm_state_get_default_colors(vterm_obtain_state(term->tl_vterm),
2398 &fg, &bg);
2399 vim_memset(&attr, 0, sizeof(attr));
2400 clear_attr = cell2attr(attr, fg, bg);
2401
2402 FOR_ALL_WINDOWS(wp)
2403 {
2404 if (wp->w_buffer == term->tl_buffer)
2405 win_del_lines(wp, dest.start_row,
2406 src.start_row - dest.start_row, FALSE, FALSE,
2407 clear_attr);
2408 }
2409 } 2417 }
2410 2418
2411 term->tl_dirty_row_start = MIN(term->tl_dirty_row_start, dest.start_row); 2419 term->tl_dirty_row_start = MIN(term->tl_dirty_row_start, dest.start_row);
2412 term->tl_dirty_row_end = MIN(term->tl_dirty_row_end, dest.end_row); 2420 term->tl_dirty_row_end = MIN(term->tl_dirty_row_end, dest.end_row);
2413 2421
2422 /* Note sure if the scrolling will work correctly, let's do a complete
2423 * redraw later. */
2414 redraw_buf_later(term->tl_buffer, NOT_VALID); 2424 redraw_buf_later(term->tl_buffer, NOT_VALID);
2415 return 1; 2425 return 1;
2416 } 2426 }
2417 2427
2418 static int 2428 static int
2855 update_cursor(term, TRUE); 2865 update_cursor(term, TRUE);
2856 } 2866 }
2857 #endif 2867 #endif
2858 2868
2859 /* 2869 /*
2870 * Return TRUE if window "wp" is to be redrawn with term_update_window().
2871 * Returns FALSE when there is no terminal running in this window or it is in
2872 * Terminal-Normal mode.
2873 */
2874 int
2875 term_do_update_window(win_T *wp)
2876 {
2877 term_T *term = wp->w_buffer->b_term;
2878
2879 return term != NULL && term->tl_vterm != NULL && !term->tl_normal_mode;
2880 }
2881
2882 /*
2860 * Called to update a window that contains an active terminal. 2883 * Called to update a window that contains an active terminal.
2861 * Returns FAIL when there is no terminal running in this window or in 2884 */
2862 * Terminal-Normal mode. 2885 void
2863 */
2864 int
2865 term_update_window(win_T *wp) 2886 term_update_window(win_T *wp)
2866 { 2887 {
2867 term_T *term = wp->w_buffer->b_term; 2888 term_T *term = wp->w_buffer->b_term;
2868 VTerm *vterm; 2889 VTerm *vterm;
2869 VTermScreen *screen; 2890 VTermScreen *screen;
2872 int rows, cols; 2893 int rows, cols;
2873 int newrows, newcols; 2894 int newrows, newcols;
2874 int minsize; 2895 int minsize;
2875 win_T *twp; 2896 win_T *twp;
2876 2897
2877 if (term == NULL || term->tl_vterm == NULL || term->tl_normal_mode)
2878 return FAIL;
2879
2880 vterm = term->tl_vterm; 2898 vterm = term->tl_vterm;
2881 screen = vterm_obtain_screen(vterm); 2899 screen = vterm_obtain_screen(vterm);
2882 state = vterm_obtain_state(vterm); 2900 state = vterm_obtain_state(vterm);
2883 2901
2884 if (wp->w_redr_type >= SOME_VALID) 2902 /* We use NOT_VALID on a resize or scroll, redraw everything then. With
2903 * SOME_VALID only redraw what was marked dirty. */
2904 if (wp->w_redr_type > SOME_VALID)
2885 { 2905 {
2886 term->tl_dirty_row_start = 0; 2906 term->tl_dirty_row_start = 0;
2887 term->tl_dirty_row_end = MAX_ROW; 2907 term->tl_dirty_row_end = MAX_ROW;
2908
2909 if (term->tl_postponed_scroll > 0
2910 && term->tl_postponed_scroll < term->tl_rows / 3)
2911 /* Scrolling is usually faster than redrawing, when there are only
2912 * a few lines to scroll. */
2913 term_scroll_up(term, 0, term->tl_postponed_scroll);
2914 term->tl_postponed_scroll = 0;
2888 } 2915 }
2889 2916
2890 /* 2917 /*
2891 * If the window was resized a redraw will be triggered and we get here. 2918 * If the window was resized a redraw will be triggered and we get here.
2892 * Adjust the size of the vterm unless 'termwinsize' specifies a fixed size. 2919 * Adjust the size of the vterm unless 'termwinsize' specifies a fixed size.
2941 #endif 2968 #endif
2942 , wp->w_wincol, pos.col, wp->w_width, FALSE); 2969 , wp->w_wincol, pos.col, wp->w_width, FALSE);
2943 } 2970 }
2944 term->tl_dirty_row_start = MAX_ROW; 2971 term->tl_dirty_row_start = MAX_ROW;
2945 term->tl_dirty_row_end = 0; 2972 term->tl_dirty_row_end = 0;
2946
2947 return OK;
2948 } 2973 }
2949 2974
2950 /* 2975 /*
2951 * Return TRUE if "wp" is a terminal window where the job has finished. 2976 * Return TRUE if "wp" is a terminal window where the job has finished.
2952 */ 2977 */