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.
This commit is contained in:
glepnir
2026-07-13 00:30:40 +08:00
committed by GitHub
parent 17f13ab338
commit 58b6310adc
3 changed files with 59 additions and 8 deletions

View File

@@ -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;

View File

@@ -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()

View File

@@ -778,7 +778,7 @@ describe('TUI :restart', function()
feed_data(':restart! echo "restarted"\r')
screen:expect([[
^ │0000;<control>;Cc;0;BN;;;;;N|
^0000;<control>;Cc;0;BN;;;;;N|
~ │0001;<control>;Cc;0;BN;;;;;N|
~ │0002;<control>;Cc;0;BN;;;;;N|
~ │0003;<control>;Cc;0;BN;;;;;N|
@@ -789,11 +789,11 @@ describe('TUI :restart', function()
feed_data(':set sessionoptions-=winsize | restart!\r')
screen:expect([[
^ │0000;<control>;Cc;0;BN;;|
~ │0001;<control>;Cc;0;BN;;|
~ │0002;<control>;Cc;0;BN;;|
~ │0003;<control>;Cc;0;BN;;|
~ │0004;<control>;Cc;0;BN;;|
^0000;<control>;Cc;0;BN;;;|
~ │0001;<control>;Cc;0;BN;;;|
~ │0002;<control>;Cc;0;BN;;;|
~ │0003;<control>;Cc;0;BN;;;|
~ │0004;<control>;Cc;0;BN;;;|
|
{5:-- TERMINAL --} |
]])