# HG changeset patch # User Christian Brabandt # Date 1518126305 -3600 # Node ID 53f0c469dfc6a968ada683149410befe79ff76b7 # Parent fb5de9f2a96aaf81f6af939af669aa1e5a018446 patch 8.0.1477: redraw flicker when moving the mouse outside of terminal window commit https://github.com/vim/vim/commit/d317b38a4dbcdbd4cf587cf78cc1f4289374214e Author: Bram Moolenaar Date: Thu Feb 8 22:33:31 2018 +0100 patch 8.0.1477: redraw flicker when moving the mouse outside of terminal window Problem: Redraw flicker when moving the mouse outside of terminal window. Solution: Instead of updating the cursor color and shape every time leaving and entering a terminal window, only update when different from the previously used cursor. diff --git a/src/terminal.c b/src/terminal.c --- a/src/terminal.c +++ b/src/terminal.c @@ -193,6 +193,16 @@ static int term_backspace_char = BS; static int term_default_cterm_fg = -1; static int term_default_cterm_bg = -1; +/* Store the last set and the desired cursor properties, so that we only update + * them when needed. Doing it unnecessary may result in flicker. */ +static char_u *last_set_cursor_color = (char_u *)""; +static char_u *desired_cursor_color = (char_u *)""; +static int last_set_cursor_shape = -1; +static int desired_cursor_shape = -1; +static int last_set_cursor_blink = -1; +static int desired_cursor_blink = -1; + + /************************************** * 1. Generic code for all systems. */ @@ -630,7 +640,7 @@ free_terminal(buf_T *buf) { if (term->tl_job->jv_status != JOB_ENDED && term->tl_job->jv_status != JOB_FINISHED - && term->tl_job->jv_status != JOB_FAILED) + && term->tl_job->jv_status != JOB_FAILED) job_stop(term->tl_job, NULL, "kill"); job_unref(term->tl_job); } @@ -642,6 +652,8 @@ free_terminal(buf_T *buf) vim_free(term->tl_status_text); vim_free(term->tl_opencmd); vim_free(term->tl_eof_chars); + if (desired_cursor_color == term->tl_cursor_color) + desired_cursor_color = (char_u *)""; vim_free(term->tl_cursor_color); vim_free(term); buf->b_term = NULL; @@ -1472,8 +1484,28 @@ term_get_cursor_shape(guicolor_T *fg, gu } #endif -static int did_change_cursor = FALSE; - + static void +may_output_cursor_props(void) +{ + if (STRCMP(last_set_cursor_color, desired_cursor_color) != 0 + || last_set_cursor_shape != desired_cursor_shape + || last_set_cursor_blink != desired_cursor_blink) + { + last_set_cursor_color = desired_cursor_color; + last_set_cursor_shape = desired_cursor_shape; + last_set_cursor_blink = desired_cursor_blink; + term_cursor_color(desired_cursor_color); + if (desired_cursor_shape == -1 || desired_cursor_blink == -1) + /* this will restore the initial cursor style, if possible */ + ui_cursor_shape_forced(TRUE); + else + term_cursor_shape(desired_cursor_shape, desired_cursor_blink); + } +} + +/* + * Set the cursor color and shape, if not last set to these. + */ static void may_set_cursor_props(term_T *term) { @@ -1485,29 +1517,30 @@ may_set_cursor_props(term_T *term) #endif if (in_terminal_loop == term) { - did_change_cursor = TRUE; if (term->tl_cursor_color != NULL) - term_cursor_color(term->tl_cursor_color); + desired_cursor_color = term->tl_cursor_color; else - term_cursor_color((char_u *)""); - term_cursor_shape(term->tl_cursor_shape, term->tl_cursor_blink); + desired_cursor_color = (char_u *)""; + desired_cursor_shape = term->tl_cursor_shape; + desired_cursor_blink = term->tl_cursor_blink; + may_output_cursor_props(); } } +/* + * Reset the desired cursor properties and restore them when needed. + */ static void -may_restore_cursor_props(void) +prepare_restore_cursor_props(void) { #ifdef FEAT_GUI if (gui.in_use) return; #endif - if (did_change_cursor) - { - did_change_cursor = FALSE; - term_cursor_color((char_u *)""); - /* this will restore the initial cursor style, if possible */ - ui_cursor_shape_forced(TRUE); - } + desired_cursor_color = (char_u *)""; + desired_cursor_shape = -1; + desired_cursor_blink = -1; + may_output_cursor_props(); } /* @@ -1544,6 +1577,7 @@ terminal_loop(int blocking) int tty_fd = curbuf->b_term->tl_job->jv_channel ->ch_part[get_tty_part(curbuf->b_term)].ch_fd; #endif + int restore_cursor; /* Remember the terminal we are sending keys to. However, the terminal * might be closed while waiting for a character, e.g. typing "exit" in a @@ -1564,6 +1598,7 @@ terminal_loop(int blocking) if (update_screen(0) == FAIL) break; update_cursor(curbuf->b_term, FALSE); + restore_cursor = TRUE; c = term_vgetc(); if (!term_use_loop()) @@ -1672,6 +1707,11 @@ terminal_loop(int blocking) # endif if (send_keys_to_term(curbuf->b_term, c, TRUE) != OK) { + if (c == K_MOUSEMOVE) + /* We are sure to come back here, don't reset the cursor color + * and shape to avoid flickering. */ + restore_cursor = FALSE; + ret = OK; goto theend; } @@ -1680,7 +1720,8 @@ terminal_loop(int blocking) theend: in_terminal_loop = NULL; - may_restore_cursor_props(); + if (restore_cursor) + prepare_restore_cursor_props(); return ret; } @@ -2005,6 +2046,8 @@ handle_settermprop( break; case VTERM_PROP_CURSORCOLOR: + if (desired_cursor_color == term->tl_cursor_color) + desired_cursor_color = (char_u *)""; vim_free(term->tl_cursor_color); if (*value->string == NUL) term->tl_cursor_color = NULL; @@ -3292,7 +3335,7 @@ term_send_eof(channel_T *ch) #define WINPTY_SPAWN_FLAG_AUTO_SHUTDOWN 1ul #define WINPTY_SPAWN_FLAG_EXIT_AFTER_SHUTDOWN 2ull -#define WINPTY_MOUSE_MODE_FORCE 2 +#define WINPTY_MOUSE_MODE_FORCE 2 void* (*winpty_config_new)(UINT64, void*); void* (*winpty_open)(void*, void*); diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -772,6 +772,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1477, +/**/ 1476, /**/ 1475,