mirror of
https://github.com/neovim/neovim.git
synced 2026-11-06 05:16:52 +00:00
fix(ui): curs_columns() scrolls a window due for a full redraw #42625
Problem:
After a resize, a decoration provider's "on_start" calling line('w0')
makes curs_columns() scroll a window whose grid offsets are stale: it
shifts cells of another window and sends a wasted grid_scroll.
Solution:
Don't scroll a window that is due for a full redraw.
This commit is contained in:
1 parent
facba8d36b
commit
2b13dfb2a4
3 files changed
+22
-5
No files matched your search
@@ -2571,7 +2571,8 @@ void win_scroll_lines(win_T *wp, int row, int line_count)
|
||||
int checked_width = MIN(grid->cols - col, wp->w_view_width);
|
||||
int checked_height = MIN(grid->rows - row_off, wp->w_view_height);
|
||||
|
||||
// No lines are being moved, just draw over the entire area
|
||||
// No lines are being moved, or the window is not on the grid (stale offsets, see curs_columns()):
|
||||
// just draw over the entire area.
|
||||
if (checked_width <= 0 || row + abs(line_count) >= checked_height) {
|
||||
return;
|
||||
}
|
||||
|
||||
+4
-1
@@ -1143,7 +1143,10 @@ void curs_columns(win_T *wp, int may_scroll)
|
||||
extra = (prev_skipcol - wp->w_skipcol) / width2;
|
||||
// TODO(bfredl): this is very suspicious when not called by win_update()
|
||||
// We should not randomly alter screen state outside of update_screen() :(
|
||||
if (wp->w_grid.target) {
|
||||
if (wp->w_grid.target
|
||||
// A window due for a full redraw is not scrolled: its grid offsets may be stale (e.g. after
|
||||
// a resize, until win_grid_alloc()).
|
||||
&& wp->w_redr_type < UPD_NOT_VALID) {
|
||||
win_scroll_lines(wp, 0, extra);
|
||||
}
|
||||
} else if (!wp->w_p_sms) {
|
||||
|
||||
@@ -1414,20 +1414,33 @@ describe('decoration_providers', function()
|
||||
it('no crash when "start" scrolls a window after the screen shrinks', function()
|
||||
clear()
|
||||
local screen = Screen.new(200, 40)
|
||||
exec_lua(function()
|
||||
local win = exec_lua(function()
|
||||
vim.cmd('rightbelow vnew')
|
||||
local win = vim.api.nvim_get_current_win()
|
||||
vim.api.nvim_buf_set_lines(0, 0, -1, false, { 'title', ('x'):rep(57) })
|
||||
vim.api.nvim_win_set_cursor(win, { 2, 56 })
|
||||
vim.cmd('wincmd p | vertical resize 120')
|
||||
vim.cmd('wincmd p | vertical resize 120 | redraw')
|
||||
vim.api.nvim_set_decoration_provider(vim.api.nvim_create_namespace('ns'), {
|
||||
on_start = function()
|
||||
vim.fn.line('w0', win)
|
||||
end,
|
||||
})
|
||||
return win
|
||||
end)
|
||||
screen:try_resize(100, 40)
|
||||
assert_alive()
|
||||
-- The window shrank to one column, so line('w0') in "on_start" changed its skipcol.
|
||||
eq(
|
||||
{ 1, 19 },
|
||||
exec_lua(function(w)
|
||||
return { vim.api.nvim_win_get_width(w), vim.api.nvim_win_call(w, vim.fn.winsaveview).skipcol }
|
||||
end, win)
|
||||
)
|
||||
screen:expect([[
|
||||
^ │{1:<}|
|
||||
{1:~ }│x|*37
|
||||
{3:[No Name] }{2:<}|
|
||||
|
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
|
||||
|
||||
Reference in new issue
Block a user