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.
This commit is contained in:
horrifyingHorse
2026-02-05 23:09:57 +05:30
committed by Sean Dewar
parent a33e5fb1bb
commit ba6440c106
2 changed files with 56 additions and 3 deletions

View File

@@ -2210,13 +2210,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);
}
@@ -2287,10 +2298,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;
@@ -2299,6 +2310,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
{5:-- TERMINAL --} |
]])
feed_data(('A'):rep(30))
screen:expect([[
interact $ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA^ |
|*5
{5:-- TERMINAL --} |
]])
command('vnew | wincmd p')
screen:expect([[
interact $ AAAAAAAAAAAAA│ |
AAAAAAAAAAAAAAAAA^ │{100:~ }|
│{100:~ }|*3
{120:1000 }{2:1001 }|
{5:-- 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
{119:1000 }{120:1002 }|
|
]])
end)
end)
describe(':terminal window', function()