fix(tui): attribute TermResponse to source channel #40330

Problem: Attach-time terminal probes cannot distinguish responses from
different attached UIs.

Solution: Identify the UI by RPC channel id in `TermResponse` and make
`vim.tty.request()` filter responses by channel.
This commit is contained in:
Barrett Ruth
2026-06-23 05:19:56 -05:00
committed by GitHub
parent e4fbe162c1
commit db30608058
8 changed files with 139 additions and 78 deletions

View File

@@ -922,7 +922,7 @@ do
--- @param sync boolean When true (a TTY is present at startup), also send a
--- DSR probe and synchronously wait so 'background' is set before user config,
--- warning (E1568) if the terminal never answers the DSR.
local function detect_background(sync)
local function detect_background(sync, chan)
-- Re-create (clear) the handler's augroup on each call so only the
-- most-recently-attached TUI's handler remains.
local bg_group = vim.api.nvim_create_augroup('nvim.tty.background', {})
@@ -938,36 +938,40 @@ do
-- also reacts to runtime theme changes; the per-response bg_user_set() guard
-- stops it once the user pins 'background'.
local did_dsr_response = false
vim.tty.request(osc11 .. (sync and dsr or ''), { group = bg_group, timeout = 0 }, function(resp)
-- DSR response that should come after the OSC 11 response if the terminal
-- supports it.
if sync and string.match(resp, '^\027%[0n$') then
did_dsr_response = true
-- Don't stop listening: the bg response may come after the DSR response
-- if the terminal handles requests out of sequence. In that case, the bg
-- will simply be set later in the startup sequence.
return
end
vim.tty.request(
osc11 .. (sync and dsr or ''),
{ group = bg_group, timeout = 0, chan = chan },
function(resp)
-- DSR response that should come after the OSC 11 response if the terminal
-- supports it.
if sync and string.match(resp, '^\027%[0n$') then
did_dsr_response = true
-- Don't stop listening: the bg response may come after the DSR response
-- if the terminal handles requests out of sequence. In that case, the bg
-- will simply be set later in the startup sequence.
return
end
-- Never override an explicit user value: stop once the user pins it.
if bg_user_set() then
return true
end
-- Never override an explicit user value: stop once the user pins it.
if bg_user_set() then
return true
end
local r, g, b = parseosc11(resp)
if r and g and b then
local rr = parsecolor(r)
local gg = parsecolor(g)
local bb = parsecolor(b)
local r, g, b = parseosc11(resp)
if r and g and b then
local rr = parsecolor(r)
local gg = parsecolor(g)
local bb = parsecolor(b)
if rr and gg and bb then
local luminance = (0.299 * rr) + (0.587 * gg) + (0.114 * bb)
local bg = luminance < 0.5 and 'dark' or 'light'
-- Use :noautocmd to suppress OptionSet event; OSC11 response may arrive after VimEnter.
vim.cmd('noautocmd set background=' .. bg)
if rr and gg and bb then
local luminance = (0.299 * rr) + (0.587 * gg) + (0.114 * bb)
local bg = luminance < 0.5 and 'dark' or 'light'
-- Use :noautocmd to suppress OptionSet event; OSC11 response may arrive after VimEnter.
vim.cmd('noautocmd set background=' .. bg)
end
end
end
end)
)
if not sync then
return
@@ -1133,7 +1137,7 @@ do
-- runtime theme changes (mode 2031 -> TUI re-queries -> |TermResponse|);
-- the per-response bg_user_set() guard preserves an explicit user value.
if vim.o.ttyfast then
detect_background(false)
detect_background(false, ui.chan)
end
end)
end