Mercurial > vim
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 */ |