From 58b6310adc938f49ea85e6ab4839616f8af28ecd Mon Sep 17 00:00:00 2001 From: glepnir Date: Mon, 13 Jul 2026 00:30:40 +0800 Subject: [PATCH] fix(startup): respect enter for windows created in startup scripts #37287 Problem: When a split window is created from the init script using nvim_open_win() with enter=false, the current window focus is not preserved. The cursor incorrectly moves into the newly created split during startup. Solution: Save curwin before the iteration loop in create_windows(), and restore it after the loop. also update edit_buffers() to use curwin instead of firstwin. --- src/nvim/main.c | 9 ++++-- test/functional/api/window_spec.lua | 46 +++++++++++++++++++++++++++ test/functional/terminal/tui_spec.lua | 12 +++---- 3 files changed, 59 insertions(+), 8 deletions(-) diff --git a/src/nvim/main.c b/src/nvim/main.c index 16465cd359..2c66f6e8f8 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -1781,6 +1781,8 @@ static void create_windows(mparm_T *parmp) // Don't execute Win/Buf Enter/Leave autocommands here autocmd_no_enter++; autocmd_no_leave++; + // Save the window selection made by startup scripts. + win_T *startup_curwin = curwin; bool dorewind = true; while (done++ < 1000) { if (dorewind) { @@ -1840,8 +1842,11 @@ static void create_windows(mparm_T *parmp) } if (parmp->window_layout == WIN_TABS) { goto_tabpage(1); - } else { + } else if (parmp->window_count > 1 || !win_valid(startup_curwin)) { + // Multiple windows mode (-o/-O), or startup_curwin was closed: use firstwin. curwin = firstwin; + } else { + curwin = startup_curwin; } curbuf = curwin->w_buffer; autocmd_no_enter--; @@ -1947,7 +1952,7 @@ static void edit_buffers(mparm_T *parmp) autocmd_no_enter--; // make the first window the current window - win = firstwin; + win = (parmp->window_count > 1) ? firstwin : curwin; // Avoid making a preview window the current window. while (win->w_p_pvw) { win = win->w_next; diff --git a/test/functional/api/window_spec.lua b/test/functional/api/window_spec.lua index 13a50b502a..876911621d 100644 --- a/test/functional/api/window_spec.lua +++ b/test/functional/api/window_spec.lua @@ -1,6 +1,7 @@ local t = require('test.testutil') local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') +local tt = require('test.functional.testterm') local clear, curbuf, curbuf_contents, curwin, eq, neq, matches, ok, feed, insert, eval = n.clear, @@ -2303,6 +2304,51 @@ describe('API/win', function() | ]]) end) + + it('keep focus when creating split window with enter=false in init script', function() + local script_file = 'Xstartup.lua' + t.write_file( + script_file, + [[ + vim.o.laststatus = 0 + local enter = vim.g.test_enter + local win = vim.api.nvim_open_win(vim.api.nvim_create_buf(false, true), enter, { + split = 'left', + win = 0, + }) + ]] + ) + finally(function() + os.remove(script_file) + end) + local screen = tt.setup_child_nvim({ + '--clean', + '--cmd', + 'let g:test_enter = v:false', + '-u', + script_file, + }) + screen:expect([[ + │^ | + ~ │~ |*4 + 0,0-1 All | + {5:-- TERMINAL --} | + ]]) + screen:detach() + screen = tt.setup_child_nvim({ + '--clean', + '--cmd', + 'let g:test_enter = v:true', + '-u', + script_file, + }) + screen:expect([[ + ^ │ | + ~ │~ |*4 + 0,0-1 All | + {5:-- TERMINAL --} | + ]]) + end) end) describe('set_config', function() diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua index 34e7b12bc6..1e81a8cf11 100644 --- a/test/functional/terminal/tui_spec.lua +++ b/test/functional/terminal/tui_spec.lua @@ -778,7 +778,7 @@ describe('TUI :restart', function() feed_data(':restart! echo "restarted"\r') screen:expect([[ - ^ │0000;;Cc;0;BN;;;;;N| + │^0000;;Cc;0;BN;;;;;N| ~ │0001;;Cc;0;BN;;;;;N| ~ │0002;;Cc;0;BN;;;;;N| ~ │0003;;Cc;0;BN;;;;;N| @@ -789,11 +789,11 @@ describe('TUI :restart', function() feed_data(':set sessionoptions-=winsize | restart!\r') screen:expect([[ - ^ │0000;;Cc;0;BN;;| - ~ │0001;;Cc;0;BN;;| - ~ │0002;;Cc;0;BN;;| - ~ │0003;;Cc;0;BN;;| - ~ │0004;;Cc;0;BN;;| + │^0000;;Cc;0;BN;;;| + ~ │0001;;Cc;0;BN;;;| + ~ │0002;;Cc;0;BN;;;| + ~ │0003;;Cc;0;BN;;;| + ~ │0004;;Cc;0;BN;;;| | {5:-- TERMINAL --} | ]])