patch 9.2.0440: MS-Windows: cursor flicker during update_screen()
Commit:
https://github.com/vim/vim/commit/0c998003bc6ae20e10a6a7362edf52da2eb12019
Author: Yasuhiro Matsumoto <
matt...@gmail.com>
Date: Mon May 4 19:58:27 2026 +0000
patch 9.2.0440: MS-Windows: cursor flicker during update_screen()
Problem: MS-Windows: cursor flicker during update_screen()
Solution: Hide the cursor during update_screen() to avoid Windows ConPTY
flicker (Yasuhiro Matsumoto).
On terminals that do not honor synchronized output mode (e.g. Windows
ConPTY), update_screen() emits cell positioning and content as multiple
Win32 console writes through mch_write(), which the terminal renders as
separate frames. This shows up as the cursor briefly jumping to column
1 of rows being redrawn, especially during async redraws around the
popup completion menu.
Disable the cursor with cursor_off() at the start of update_screen()
and restore it with cursor_on() at the end, but only when synchronized
output mode is not active. When it is, the redraw is already atomic
from the terminal's view and hiding the cursor would only add visible
blink with no benefit.
closes: #20121
Signed-off-by: Yasuhiro Matsumoto <
matt...@gmail.com>
Signed-off-by: Christian Brabandt <
c...@256bit.org>
diff --git a/src/drawscreen.c b/src/drawscreen.c
index 702d686ab..cecfcccb6 100644
--- a/src/drawscreen.c
+++ b/src/drawscreen.c
@@ -160,6 +160,11 @@ update_screen(int type_arg)
}
updating_screen = TRUE;
+ // Hide the cursor while redrawing when sync output is not active, to
+ // avoid visible cursor flicker on terminals like Windows ConPTY.
+ int hid_cursor = !sync_output_active();
+ if (hid_cursor)
+ cursor_off();
term_set_sync_output(TERM_SYNC_OUTPUT_ENABLE);
#ifdef FEAT_PROP_POPUP
@@ -447,6 +452,8 @@ update_screen(int type_arg)
#endif
term_set_sync_output(TERM_SYNC_OUTPUT_DISABLE);
+ if (hid_cursor)
+ cursor_on();
return OK;
}
diff --git a/src/proto/
term.pro b/src/proto/
term.pro
index 9653a35af..3f099338b 100644
--- a/src/proto/
term.pro
+++ b/src/proto/
term.pro
@@ -98,5 +98,6 @@ void cterm_color2rgb(int nr, char_u *r, char_u *g, char_u *b, char_u *ansi_idx);
int term_replace_keycodes(char_u *ta_buf, int ta_len, int len_arg);
void term_disable_dec(void);
void term_set_win_resize(bool state);
+int sync_output_active(void);
void term_set_sync_output(int flags);
/* vim: set ft=c : */
diff --git a/src/term.c b/src/term.c
index 07eb5974b..37f05ed01 100644
--- a/src/term.c
+++ b/src/term.c
@@ -8094,6 +8094,17 @@ term_set_win_resize(bool state)
}
#endif
+ int
+sync_output_active(void)
+{
+#ifdef FEAT_GUI
+ if (gui.in_use)
+ return TRUE;
+#endif
+ return p_tsy && (sync_output_setting == 1 || sync_output_setting == 2)
+ && *T_BSU != NUL && *T_ESU != NUL;
+}
+
/*
* Enable or disable synchronized output if possible. Specification can be found
* here:
diff --git a/src/version.c b/src/version.c
index 81809c9ea..34f3dd850 100644
--- a/src/version.c
+++ b/src/version.c
@@ -729,6 +729,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 440,
/**/
439,
/**/