From 79030bf19618f56e8304e5e27af72390e61650d8 Mon Sep 17 00:00:00 2001 From: fredizzimo Date: Thu, 3 Oct 2024 12:31:17 +0300 Subject: [PATCH] fix(ui): ensure screen update before waiting for input #30576 Ensure the screen is fully updated before blocking for input. This did not always happen before, for example when setting `cursorline scrolloff=9999`, which lead to jerky movement when using some GUI applications. Because of the duality of redraw_later, this can't be done in command-line or when waiting for "Press ENTER". In many of those cases the redraw is expected AFTER the key press, while normally it should update the screen immediately. So, those special cases are excluded. (cherry picked from commit 7eba016c86818c5f6fa1542500b19d27bb7ab15c) --- src/nvim/state.c | 8 +- test/functional/ui/multigrid_spec.lua | 253 ++++++++++++++++++++++++++ 2 files changed, 258 insertions(+), 3 deletions(-) diff --git a/src/nvim/state.c b/src/nvim/state.c index 993db255de..07638bfa2f 100644 --- a/src/nvim/state.c +++ b/src/nvim/state.c @@ -66,9 +66,11 @@ getkey: // Event was made available after the last multiqueue_process_events call key = K_EVENT; } else { - // Duplicate display updating logic in vgetorpeek() - if (((State & MODE_INSERT) != 0 || p_lz) && (State & MODE_CMDLINE) == 0 - && must_redraw != 0 && !need_wait_return) { + // Ensure the screen is fully updated before blocking for input. Because of the duality of + // redraw_later, this can't be done in command-line or when waiting for "Press ENTER". + // In many of those cases the redraw is expected AFTER the key press, while normally it should + // update the screen immediately. + if (must_redraw != 0 && !need_wait_return && (State & MODE_CMDLINE) == 0) { update_screen(); setcursor(); // put cursor back where it belongs } diff --git a/test/functional/ui/multigrid_spec.lua b/test/functional/ui/multigrid_spec.lua index dc48061a6c..06d6f818e3 100644 --- a/test/functional/ui/multigrid_spec.lua +++ b/test/functional/ui/multigrid_spec.lua @@ -2598,4 +2598,257 @@ describe('ext_multigrid', function() ]]) eq(1, api.nvim_get_option_value('cmdheight', {})) end) + + describe('centered cursorline', function() + before_each(function() + -- Force a centered cursorline, this caused some redrawing problems described in #30576. + -- Most importantly, win_viewport was not received in time, and sum_scroll_delta did not refresh. + command('set cursorline scrolloff=9999') + end) + it('insert line scrolls correctly', function() + for i = 1, 11 do + insert('line' .. i .. '\n') + end + screen:expect({ + grid = [[ + ## grid 1 + [2:-----------------------------------------------------]|*12 + {11:[No Name] [+] }| + [3:-----------------------------------------------------]| + ## grid 2 + line1 | + line2 | + line3 | + line4 | + line5 | + line6 | + line7 | + line8 | + line9 | + line10 | + line11 | + {23:^ }| + ## grid 3 + | + ]], win_viewport={ + [2] = {win = 1000, topline = 0, botline = 12, curline = 11, curcol = 0, linecount = 12, sum_scroll_delta = 0}; + }, win_viewport_margins={ + [2] = { + bottom = 0, + left = 0, + right = 0, + top = 0, + win = 1000 + } + }}) + insert('line12\n') + screen:expect({ + grid = [[ + ## grid 1 + [2:-----------------------------------------------------]|*12 + {11:[No Name] [+] }| + [3:-----------------------------------------------------]| + ## grid 2 + line2 | + line3 | + line4 | + line5 | + line6 | + line7 | + line8 | + line9 | + line10 | + line11 | + line12 | + {23:^ }| + ## grid 3 + | + ]], win_viewport={ + [2] = {win = 1000, topline = 1, botline = 13, curline = 12, curcol = 0, linecount = 13, sum_scroll_delta = 1}; + }, win_viewport_margins={ + [2] = { + bottom = 0, + left = 0, + right = 0, + top = 0, + win = 1000 + } + }}) + end) + + it('got to top scrolls correctly', function() + for i = 1, 20 do + insert('line' .. i .. '\n') + end + screen:expect({ + grid = [[ + ## grid 1 + [2:-----------------------------------------------------]|*12 + {11:[No Name] [+] }| + [3:-----------------------------------------------------]| + ## grid 2 + line10 | + line11 | + line12 | + line13 | + line14 | + line15 | + line16 | + line17 | + line18 | + line19 | + line20 | + {23:^ }| + ## grid 3 + | + ]], win_viewport={ + [2] = {win = 1000, topline = 9, botline = 21, curline = 20, curcol = 0, linecount = 21, sum_scroll_delta = 9}; + }, win_viewport_margins={ + [2] = { + bottom = 0, + left = 0, + right = 0, + top = 0, + win = 1000 + } + }}) + feed('gg') + screen:expect({ + grid = [[ + ## grid 1 + [2:-----------------------------------------------------]|*12 + {11:[No Name] [+] }| + [3:-----------------------------------------------------]| + ## grid 2 + {23:^line1 }| + line2 | + line3 | + line4 | + line5 | + line6 | + line7 | + line8 | + line9 | + line10 | + line11 | + line12 | + ## grid 3 + | + ]], win_viewport={ + [2] = {win = 1000, topline = 0, botline = 13, curline = 0, curcol = 0, linecount = 21, sum_scroll_delta = 0}; + }, win_viewport_margins={ + [2] = { + bottom = 0, + left = 0, + right = 0, + top = 0, + win = 1000 + } + }}) + end) + + it('scrolls in the middle', function() + for i = 1, 20 do + insert('line' .. i .. '\n') + end + screen:expect({ + grid = [[ + ## grid 1 + [2:-----------------------------------------------------]|*12 + {11:[No Name] [+] }| + [3:-----------------------------------------------------]| + ## grid 2 + line10 | + line11 | + line12 | + line13 | + line14 | + line15 | + line16 | + line17 | + line18 | + line19 | + line20 | + {23:^ }| + ## grid 3 + | + ]], win_viewport={ + [2] = {win = 1000, topline = 9, botline = 21, curline = 20, curcol = 0, linecount = 21, sum_scroll_delta = 9}; + }, win_viewport_margins={ + [2] = { + bottom = 0, + left = 0, + right = 0, + top = 0, + win = 1000 + } + }}) + feed('M') + screen:expect({ + grid = [[ + ## grid 1 + [2:-----------------------------------------------------]|*12 + {11:[No Name] [+] }| + [3:-----------------------------------------------------]| + ## grid 2 + line10 | + line11 | + line12 | + line13 | + line14 | + {23:^line15 }| + line16 | + line17 | + line18 | + line19 | + line20 | + | + ## grid 3 + | + ]], win_viewport={ + [2] = {win = 1000, topline = 9, botline = 21, curline = 14, curcol = 0, linecount = 21, sum_scroll_delta = 9}; + }, win_viewport_margins={ + [2] = { + bottom = 0, + left = 0, + right = 0, + top = 0, + win = 1000 + } + }}) + feed('k') + screen:expect({ + grid = [[ + ## grid 1 + [2:-----------------------------------------------------]|*12 + {11:[No Name] [+] }| + [3:-----------------------------------------------------]| + ## grid 2 + line9 | + line10 | + line11 | + line12 | + line13 | + {23:^line14 }| + line15 | + line16 | + line17 | + line18 | + line19 | + line20 | + ## grid 3 + | + ]], win_viewport={ + [2] = {win = 1000, topline = 8, botline = 21, curline = 13, curcol = 0, linecount = 21, sum_scroll_delta = 8}; + }, win_viewport_margins={ + [2] = { + bottom = 0, + left = 0, + right = 0, + top = 0, + win = 1000 + } + }}) + end) + end) end)