fix(ui): avoid redundant ext_cmdline events (#32237)

Problem:  `cmdline_show` is emitted unnecessarily each event
          loop iteration, because `cmdline_was_last_drawn` is never set.
Solution: Keep track of whether the cmdline was last drawn to avoid
          unnecessarily emitting cmdline_show. Set `redraw_state` to
          emit `cmdline_pos` when emitting `CursorMovedC`. Only emit
          `cmdline_pos` when cmdline was last drawn.
This commit is contained in:
luukvbaal 2025-01-29 12:07:27 +01:00 committed by GitHub
parent e7ebc5c13d
commit 216ec73972
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 35 additions and 30 deletions

View File

@ -692,8 +692,11 @@ int update_screen(void)
decor_providers_invoke_end();
// either cmdline is cleared, not drawn or mode is last drawn
cmdline_was_last_drawn = false;
// Either cmdline is cleared, not drawn or mode is last drawn.
// This does not (necessarily) overwrite an external cmdline.
if (!ui_has(kUICmdline)) {
cmdline_was_last_drawn = false;
}
return OK;
}

View File

@ -679,6 +679,15 @@ static void init_ccline(int firstc, int indent)
}
}
static void ui_ext_cmdline_hide(bool abort)
{
if (ui_has(kUICmdline)) {
cmdline_was_last_drawn = false;
ccline.redraw_state = kCmdRedrawNone;
ui_call_cmdline_hide(ccline.level, abort);
}
}
/// Internal entry point for cmdline mode.
///
/// @param count only used for incremental search
@ -954,8 +963,7 @@ theend:
char *p = ccline.cmdbuff;
if (ui_has(kUICmdline)) {
ccline.redraw_state = kCmdRedrawNone;
ui_call_cmdline_hide(ccline.level, s->gotesc);
ui_ext_cmdline_hide(s->gotesc);
msg_ext_clear_later();
}
if (!cmd_silent) {
@ -2209,14 +2217,19 @@ end:
return ccline.one_key ? 0 : command_line_changed(s);
}
static int command_line_not_changed(CommandLineState *s)
/// Trigger CursorMovedC autocommands.
static void may_trigger_cursormovedc(CommandLineState *s)
{
// Trigger CursorMovedC autocommands.
if (ccline.cmdpos != s->prev_cmdpos) {
trigger_cmd_autocmd(get_cmdline_type(), EVENT_CURSORMOVEDC);
s->prev_cmdpos = ccline.cmdpos;
ccline.redraw_state = MAX(ccline.redraw_state, kCmdRedrawPos);
}
}
static int command_line_not_changed(CommandLineState *s)
{
may_trigger_cursormovedc(s);
// Incremental searches for "/" and "?":
// Enter command_line_not_changed() when a character has been read but the
// command line did not change. Then we only search and redraw if something
@ -2696,11 +2709,7 @@ static int command_line_changed(CommandLineState *s)
// Trigger CmdlineChanged autocommands.
do_autocmd_cmdlinechanged(s->firstc > 0 ? s->firstc : '-');
// Trigger CursorMovedC autocommands.
if (ccline.cmdpos != s->prev_cmdpos) {
trigger_cmd_autocmd(get_cmdline_type(), EVENT_CURSORMOVEDC);
s->prev_cmdpos = ccline.cmdpos;
}
may_trigger_cursormovedc(s);
const bool prev_cmdpreview = cmdpreview;
if (s->firstc == ':'
@ -2741,7 +2750,6 @@ static int command_line_changed(CommandLineState *s)
static void abandon_cmdline(void)
{
dealloc_cmdbuff();
ccline.redraw_state = kCmdRedrawNone;
if (msg_scrolled == 0) {
compute_cmdrow();
}
@ -3385,7 +3393,7 @@ color_cmdline_error:
// when cmdline_star is true.
static void draw_cmdline(int start, int len)
{
if (!color_cmdline(&ccline)) {
if (ccline.cmdbuff == NULL || !color_cmdline(&ccline)) {
return;
}
@ -3491,8 +3499,7 @@ void ui_ext_cmdline_block_leave(void)
ui_call_cmdline_block_hide();
}
/// Extra redrawing needed for redraw! and on ui_attach
/// assumes "redrawcmdline()" will already be invoked
/// Extra redrawing needed for redraw! and on ui_attach.
void cmdline_screen_cleared(void)
{
if (!ui_has(kUICmdline)) {
@ -3515,6 +3522,7 @@ void cmdline_screen_cleared(void)
}
line = line->prev_ccline;
}
redrawcmd();
}
/// called by ui_flush, do what redraws necessary to keep cmdline updated.
@ -3527,12 +3535,14 @@ void cmdline_ui_flush(void)
CmdlineInfo *line = &ccline;
while (level > 0 && line) {
if (line->level == level) {
if (line->redraw_state == kCmdRedrawAll) {
CmdRedraw redraw_state = line->redraw_state;
line->redraw_state = kCmdRedrawNone;
if (redraw_state == kCmdRedrawAll) {
cmdline_was_last_drawn = true;
ui_ext_cmdline_show(line);
} else if (line->redraw_state == kCmdRedrawPos) {
} else if (redraw_state == kCmdRedrawPos && cmdline_was_last_drawn) {
ui_call_cmdline_pos(line->cmdpos, line->level);
}
line->redraw_state = kCmdRedrawNone;
level--;
}
line = line->prev_ccline;
@ -3900,12 +3910,7 @@ void compute_cmdrow(void)
void cursorcmd(void)
{
if (cmd_silent) {
return;
}
if (ui_has(kUICmdline)) {
ccline.redraw_state = MAX(ccline.redraw_state, kCmdRedrawPos);
if (cmd_silent || ui_has(kUICmdline)) {
return;
}
@ -4507,10 +4512,7 @@ static int open_cmdwin(void)
curwin->w_cursor.col = ccline.cmdpos;
changed_line_abv_curs();
invalidate_botline(curwin);
if (ui_has(kUICmdline)) {
ccline.redraw_state = kCmdRedrawNone;
ui_call_cmdline_hide(ccline.level, false);
}
ui_ext_cmdline_hide(false);
redraw_later(curwin, UPD_SOME_VALID);
// No Ex mode here!

View File

@ -202,7 +202,7 @@ describe('vim.ui_attach', function()
feed([[:call confirm("Save changes?", "&Yes\n&No\n&Cancel")<CR>]])
screen:expect({
grid = [[
^5 |
^4 |
{1:~ }|*4
]],
cmdline = {
@ -224,7 +224,7 @@ describe('vim.ui_attach', function()
feed('n')
screen:expect({
grid = [[
^5 |
^4 |
{1:~ }|*4
]],
cmdline = { { abort = false } },