From 749126de087db45bb0ee31c6785dbdb1d30336c9 Mon Sep 17 00:00:00 2001 From: glepnir Date: Tue, 16 Jun 2026 19:39:32 +0800 Subject: [PATCH] fix(highlight): keep guisp underline color in float with 'winblend' #40283 Problem: A colored (guisp) underline showing through a 'winblend' float lost its special color and followed the foreground instead. Solution: In the blend-through case, blend the underline's special color only when the cell below sets sp explicitly; otherwise clear it. (cherry picked from commit 823517ad1d5df03914c55ec7ca5daa504734530d) --- src/nvim/highlight.c | 4 ++-- test/functional/ui/float_spec.lua | 20 +++++++++++--------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index 99f0d8d56c..7f4fdb5df6 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -737,8 +737,8 @@ int hl_blend_attrs(int back_attr, int front_attr, bool *through) if (*through) { cattrs = battrs; cattrs.rgb_fg_color = rgb_blend(ratio, battrs.rgb_fg_color, fattrs.rgb_bg_color); - // Only apply special colors when the foreground attribute has an underline style. - if (fattrs_raw.rgb_ae_attr & HL_UNDERLINE_MASK) { + // Blend the special color only when the cell below sets one explicitly, else clear it. + if ((cattrs.rgb_ae_attr & HL_UNDERLINE_MASK) && battrs_raw.rgb_sp_color != -1) { cattrs.rgb_sp_color = rgb_blend(ratio, battrs.rgb_sp_color, fattrs.rgb_bg_color); } else { cattrs.rgb_sp_color = -1; diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua index 1d467d17ec..32915086a7 100644 --- a/test/functional/ui/float_spec.lua +++ b/test/functional/ui/float_spec.lua @@ -8933,6 +8933,8 @@ describe('float window', function() [32] = { foreground = Screen.colors.Blue1, blend = 100, bold = true }, [33] = { foreground = Screen.colors.Gray0, underline = true }, [34] = { underline = true }, + [35] = { foreground = Screen.colors.Black, underline = true, special = Screen.colors.Red }, + [36] = { special = Screen.colors.Red, underline = true }, }) insert([[ Lorem ipsum dolor sit amet, consectetur @@ -9292,12 +9294,12 @@ describe('float window', function() ]]) end - -- winblend highlight with underline (but without guisp) in a floatwin. #14453 - command('fclose | hi TestUnderLine gui=underline') + -- winblend underline: without guisp follows the fg (#14453), with guisp keeps its sp (#34614). + command('fclose | hi TestUnderLine gui=underline | hi TestUnderLineSp gui=underline guisp=Red') api.nvim_buf_add_highlight(curbufnr, -1, 'TestUnderLine', 3, 0, -1) - api.nvim_buf_add_highlight(curbufnr, -1, 'TestUnderLine', 4, 0, -1) - api.nvim_buf_set_lines(buf, 0, -1, false, {}) - api.nvim_open_win(buf, false, { relative = 'win', row = 0, col = 0, width = 50, height = 1 }) + api.nvim_buf_add_highlight(curbufnr, -1, 'TestUnderLineSp', 4, 0, -1) + api.nvim_buf_set_lines(buf, 0, -1, false, { '', '' }) + api.nvim_open_win(buf, false, { relative = 'win', row = 0, col = 0, width = 50, height = 2 }) if multigrid then screen:expect({ grid = [[ @@ -9306,7 +9308,7 @@ describe('float window', function() [3:--------------------------------------------------]| ## grid 2 {34:Ut enim ad minim veniam, quis nostrud} | - {34:exercitation ullamco laboris nisi ut aliquip ex} | + {36:exercitation ullamco laboris nisi ut aliquip ex} | ea commodo consequat. Duis aute irure dolor in | reprehenderit in voluptate velit esse cillum | dolore eu fugiat nulla pariatur. Excepteur sint | @@ -9316,13 +9318,13 @@ describe('float window', function() ## grid 3 | ## grid 5 - {17: }| + {17: }|*2 ]], win_pos = { [2] = { height = 8, startcol = 0, startrow = 0, width = 50, win = 1000 } }, float_pos = { [5] = { 1002, 'NW', 2, 0, 0, true, 50, 1, 0, 0 } }, win_viewport = { [2] = { win = 1000, topline = 3, botline = 11, curline = 9, curcol = 0, linecount = 11, sum_scroll_delta = 3 }, - [5] = { win = 1002, topline = 0, botline = 1, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0 }, + [5] = { win = 1002, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0 }, }, win_viewport_margins = { [2] = { bottom = 0, left = 0, right = 0, top = 0, win = 1000 }, @@ -9332,7 +9334,7 @@ describe('float window', function() else screen:expect([[ {33:Ut enim ad minim veniam, quis nostrud}{26: }| - {34:exercitation ullamco laboris nisi ut aliquip ex} | + {35:exercitation ullamco laboris nisi ut aliquip ex}{26: }| ea commodo consequat. Duis aute irure dolor in | reprehenderit in voluptate velit esse cillum | dolore eu fugiat nulla pariatur. Excepteur sint |