diff options
author | luukvbaal <luukvbaal@gmail.com> | 2024-06-04 15:09:12 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-04 06:09:12 -0700 |
commit | b66106a46c5c6180c7f80852a8c822b400e73100 (patch) | |
tree | 3ea46b835fbbd014a719fdab42487385843b5225 | |
parent | 8cbb1f20e557461c8417583a7f69d53aaaef920b (diff) | |
download | rneovim-b66106a46c5c6180c7f80852a8c822b400e73100.tar.gz rneovim-b66106a46c5c6180c7f80852a8c822b400e73100.tar.bz2 rneovim-b66106a46c5c6180c7f80852a8c822b400e73100.zip |
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.
-rw-r--r-- | src/nvim/drawscreen.c | 22 | ||||
-rw-r--r-- | src/nvim/ex_getln.c | 5 | ||||
-rw-r--r-- | src/nvim/generators/gen_api_ui_events.lua | 8 | ||||
-rw-r--r-- | test/functional/ui/messages_spec.lua | 16 |
4 files changed, 35 insertions, 16 deletions
diff --git a/src/nvim/drawscreen.c b/src/nvim/drawscreen.c index bd9a834869..88e1f302da 100644 --- a/src/nvim/drawscreen.c +++ b/src/nvim/drawscreen.c @@ -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; } diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 4323a9d221..cef1868fc8 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -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 diff --git a/src/nvim/generators/gen_api_ui_events.lua b/src/nvim/generators/gen_api_ui_events.lua index 516b5ad5ae..c5b37672bf 100644 --- a/src/nvim/generators/gen_api_ui_events.lua +++ b/src/nvim/generators/gen_api_ui_events.lua @@ -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) diff --git a/test/functional/ui/messages_spec.lua b/test/functional/ui/messages_spec.lua index ca52a265fa..07192800e5 100644 --- a/test/functional/ui/messages_spec.lua +++ b/test/functional/ui/messages_spec.lua @@ -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() |