fix(terminal): reset w_leftcol after resizing terminal

Problem: windows may scroll horizontally upon resize using the old terminal
size, which may be unnecessary and cause the content to be partially out-of-view.

Solution: reset the horizontal scroll after resizing.

Adjust expected highlights, as commit e946951f6a isn't backported.

(cherry picked from commit ba6440c106)
This commit is contained in:
horrifyingHorse
2026-02-05 23:09:57 +05:30
committed by github-actions[bot]
parent 03e68ad5d3
commit 37738d5ae0
2 changed files with 56 additions and 3 deletions

View File

@@ -2150,13 +2150,24 @@ static void refresh_terminal(Terminal *term)
}
linenr_T ml_before = buf->b_ml.ml_line_count;
refresh_size(term, buf);
bool resized = refresh_size(term, buf);
refresh_scrollback(term, buf);
refresh_screen(term, buf);
int ml_added = buf->b_ml.ml_line_count - ml_before;
adjust_topline_cursor(term, buf, ml_added);
// Resized window may have scrolled horizontally to keep its cursor in-view using the old terminal
// size. Reset the scroll, and let curs_columns correct it if that sends the cursor out-of-view.
if (resized) {
FOR_ALL_TAB_WINDOWS(tp, wp) {
if (wp->w_buffer == buf && wp->w_leftcol != 0) {
wp->w_leftcol = 0;
curs_columns(wp, true);
}
}
}
// Copy pending events back to the main event queue
multiqueue_move_events(main_loop.events, term->pending.events);
}
@@ -2227,10 +2238,10 @@ static void refresh_timer_cb(TimeWatcher *watcher, void *data)
unblock_autocmds();
}
static void refresh_size(Terminal *term, buf_T *buf)
static bool refresh_size(Terminal *term, buf_T *buf)
{
if (!term->pending.resize || term->closed) {
return;
return false;
}
term->pending.resize = false;
@@ -2239,6 +2250,7 @@ static void refresh_size(Terminal *term, buf_T *buf)
term->invalid_start = 0;
term->invalid_end = height;
term->opts.resize_cb((uint16_t)width, (uint16_t)height, term->opts.data);
return true;
}
void on_scrollback_option_changed(Terminal *term)

View File

@@ -14,6 +14,7 @@ local eq = t.eq
local eval = n.eval
local skip = t.skip
local is_os = t.is_os
local testprg = n.testprg
describe(':terminal window', function()
before_each(clear)
@@ -33,6 +34,46 @@ describe(':terminal window', function()
eq({ 1, 1, 1 }, eval('[&l:wrap, &wrap, &g:wrap]'))
eq({ 1, 1, 1 }, eval('[&l:list, &list, &g:list]'))
end)
it('resets horizontal scroll on resize #35331', function()
local screen = tt.setup_screen(0, { testprg('shell-test'), 'INTERACT' })
command('set statusline=%{win_getid()} splitright')
screen:expect([[
interact $ ^ |
|*5
{3:-- TERMINAL --} |
]])
feed_data(('A'):rep(30))
screen:expect([[
interact $ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA^ |
|*5
{3:-- TERMINAL --} |
]])
command('vnew | wincmd p')
screen:expect([[
interact $ AAAAAAAAAAAAA│ |
AAAAAAAAAAAAAAAAA^ │{4:~ }|
│{4:~ }|*3
{17:1000 }{1:1001 }|
{3:-- TERMINAL --} |
]])
feed([[<C-\><C-N><C-W>o]])
screen:expect([[
interact $ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA |
^ |
|*5
]])
-- Window with less room scrolls anyway to keep its cursor in-view.
feed('gg$20<C-W>v')
screen:expect([[
interact $ AAAAAAAAAAAAAAAAAA│$ AAAAAAAAAAAAAAAAA^A|
AAAAAAAAAAAA │AAA |
│ |*3
{18:1000 }{17:1002 }|
|
]])
end)
end)
describe(':terminal window', function()