fix(ui): superfluous showmode / excessive grid_cursor_goto #29089

Problem:  Unsetting global variables earlier in #28578 to avoid
          recursiveness, caused superfluous or even unlimited
          showmode().
Solution: Partly revert #28578 so that the globals are unset at the end
          of showmode(), and avoid recursiveness for ext UI by adding a
          recursive function guard to each generated UI call that may
          call a Lua callback.
This commit is contained in:
luukvbaal
2024-06-04 15:09:12 +02:00
committed by GitHub
parent 8cbb1f20e5
commit b66106a46c
4 changed files with 35 additions and 16 deletions

View File

@ -931,13 +931,7 @@ int showmode(void)
msg_ext_clear(true);
}
// Don't make non-flushed message part of the showmode and reset global
// variables before flushing to to avoid recursiveness.
bool draw_mode = redraw_mode;
bool clear_cmd = clear_cmdline;
redraw_cmdline = false;
redraw_mode = false;
clear_cmdline = false;
// Don't make non-flushed message part of the showmode.
msg_ext_ui_flush();
msg_grid_validate();
@ -960,8 +954,8 @@ int showmode(void)
msg_check_for_delay(false);
// if the cmdline is more than one line high, erase top lines
bool need_clear = clear_cmd;
if (clear_cmd && cmdline_row < Rows - 1) {
bool need_clear = clear_cmdline;
if (clear_cmdline && cmdline_row < Rows - 1) {
msg_clr_cmdline(); // will reset clear_cmdline
}
@ -1083,7 +1077,7 @@ int showmode(void)
}
mode_displayed = true;
if (need_clear || clear_cmd || draw_mode) {
if (need_clear || clear_cmdline || redraw_mode) {
msg_clr_eos();
}
msg_didout = false; // overwrite this message
@ -1092,10 +1086,10 @@ int showmode(void)
msg_no_more = false;
lines_left = save_lines_left;
need_wait_return = nwr_save; // never ask for hit-return for this
} else if (clear_cmd && msg_silent == 0) {
} else if (clear_cmdline && msg_silent == 0) {
// Clear the whole command line. Will reset "clear_cmdline".
msg_clr_cmdline();
} else if (draw_mode) {
} else if (redraw_mode) {
msg_pos_mode();
msg_clr_eos();
}
@ -1118,6 +1112,10 @@ int showmode(void)
grid_line_flush();
}
redraw_cmdline = false;
redraw_mode = false;
clear_cmdline = false;
return length;
}

View File

@ -3455,11 +3455,9 @@ void cmdline_screen_cleared(void)
/// called by ui_flush, do what redraws necessary to keep cmdline updated.
void cmdline_ui_flush(void)
{
static bool flushing = false;
if (!ui_has(kUICmdline) || flushing) {
if (!ui_has(kUICmdline)) {
return;
}
flushing = true;
int level = ccline.level;
CmdlineInfo *line = &ccline;
while (level > 0 && line) {
@ -3474,7 +3472,6 @@ void cmdline_ui_flush(void)
}
line = line->prev_ccline;
}
flushing = false;
}
// Put a character on the command line. Shifts the following text to the

View File

@ -128,8 +128,16 @@ for i = 1, #events do
write_signature(call_output, ev, '')
call_output:write('\n{\n')
if ev.remote_only then
-- Lua callbacks may emit other events or the same event again. Avoid the latter
-- by adding a recursion guard to each generated function that may call a Lua callback.
call_output:write(' static bool entered = false;\n')
call_output:write(' if (entered) {\n')
call_output:write(' return;\n')
call_output:write(' }\n')
call_output:write(' entered = true;\n')
write_arglist(call_output, ev)
call_output:write(' ui_call_event("' .. ev.name .. '", ' .. args .. ');\n')
call_output:write(' entered = false;\n')
elseif ev.compositor_impl then
call_output:write(' ui_comp_' .. ev.name)
write_signature(call_output, ev, '', true)

View File

@ -1081,6 +1081,22 @@ stack traceback:
},
})
end)
it('does not do showmode unnecessarily #29086', function()
local screen_showmode = screen._handle_msg_showmode
local showmode = 0
screen._handle_msg_showmode = function(...)
screen_showmode(...)
showmode = showmode + 1
end
screen:expect({
grid = [[
^ |
{1:~ }|*4
]],
})
eq(showmode, 1)
end)
end)
describe('ui/builtin messages', function()