Commit: patch 9.2.0035: syntax highlighting lost in popup with opacity

1 view
Skip to first unread message

Christian Brabandt

unread,
Feb 21, 2026, 5:01:48 AM (yesterday) Feb 21
to vim...@googlegroups.com
patch 9.2.0035: syntax highlighting lost in popup with opacity

Commit: https://github.com/vim/vim/commit/782345c9e6d4539c462d8e51b8eb82c28fa1232a
Author: Yasuhiro Matsumoto <matt...@gmail.com>
Date: Sat Feb 21 09:55:18 2026 +0000

patch 9.2.0035: syntax highlighting lost in popup with opacity

Problem: syntax highlighting lost in popup with opacity lower than 100
(after v9.2.0017)
Solution: Before blending, combine the popup's window color attribute
with the character's own attribute using hl_combine_attr()
(Yasuhiro Matsumoto).

related: #19272
closes: #19478

Signed-off-by: Yasuhiro Matsumoto <matt...@gmail.com>
Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/src/screen.c b/src/screen.c
index 74e4a40e3..6e6f11b70 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -666,10 +666,15 @@ screen_line(
opacity_blank = TRUE;
// Keep the underlying character and blend its foreground color
// from popup background color to original color.
+ // Combine the popup window color with the character's own
+ // attribute (e.g. match highlight) so that its background
+ // color is preserved on blank cells.
+ int char_attr = ScreenAttrs[off_from];
int popup_attr = get_wcr_attr(screen_opacity_popup);
+ int combined = hl_combine_attr(popup_attr, char_attr);
int blend = screen_opacity_popup->w_popup_blend;
ScreenAttrs[off_to] = hl_blend_attr(ScreenAttrs[off_to],
- popup_attr, blend, TRUE);
+ combined, blend, TRUE);
screen_char(off_to, row, col + coloff);
// For wide background character, also update the second cell.
if (bg_char_cells == 2)
@@ -818,11 +823,14 @@ skip_opacity:
&& (flags & SLF_POPUP)
&& screen_opacity_popup->w_popup_blend > 0)
{
+ int char_attr = ScreenAttrs[off_from];
int popup_attr = get_wcr_attr(screen_opacity_popup);
int blend = screen_opacity_popup->w_popup_blend;
- // Blend popup attr with default background (0)
- // FALSE = keep popup foreground color, blend background only
- ScreenAttrs[off_to] = hl_blend_attr(0, popup_attr, blend, FALSE);
+ // Combine popup window color with the character's own
+ // attribute (e.g. syntax highlighting) so that the
+ // character's foreground color is preserved.
+ int combined = hl_combine_attr(popup_attr, char_attr);
+ ScreenAttrs[off_to] = hl_blend_attr(0, combined, blend, FALSE);
}
#endif

diff --git a/src/testdir/dumps/Test_popupwin_opacity_hl_100.dump b/src/testdir/dumps/Test_popupwin_opacity_hl_100.dump
new file mode 100644
index 000000000..f087349e4
--- /dev/null
+++ b/src/testdir/dumps/Test_popupwin_opacity_hl_100.dump
@@ -0,0 +1,10 @@
+>1+0&#ffffff0| @73
+|2| @73
+|3| @7|f+0#ff404010#5fd7ff255|o@1| @1|b+0#0000000&|a|r| +0&#ffffff0@57
+|4| @7|b+0&#5fd7ff255|a|z| @4| +0&#ffffff0@57
+|5| @73
+|6| @73
+|7| @73
+|8| @73
+|9| @73
+@57|1|,|1| @10|T|o|p|
diff --git a/src/testdir/dumps/Test_popupwin_opacity_hl_80.dump b/src/testdir/dumps/Test_popupwin_opacity_hl_80.dump
new file mode 100644
index 000000000..89700f9c4
--- /dev/null
+++ b/src/testdir/dumps/Test_popupwin_opacity_hl_80.dump
@@ -0,0 +1,10 @@
+>1+0&#ffffff0| @73
+|2| @73
+|3| @7|f+0#ff404010#5fd7ff255|o@1| @1|b+0#0000000&|a|r| +0&#ffffff0@57
+|4| @7|b+0&#5fd7ff255|a|z| @4| +0&#ffffff0@57
+|5| @73
+|6| @73
+|7| @73
+|8| @73
+|9| @73
+|:| @55|1|,|1| @10|T|o|p|
diff --git a/src/testdir/test_popupwin.vim b/src/testdir/test_popupwin.vim
index a608fbaf5..c00ac29a7 100644
--- a/src/testdir/test_popupwin.vim
+++ b/src/testdir/test_popupwin.vim
@@ -4653,6 +4653,40 @@ func Test_popupwin_bottom_position_without_decoration()
call StopVimInTerminal(buf)
endfunc

+func Test_popup_opacity_highlight()
+ CheckScreendump
+
+ " Verify that match highlighting is preserved when opacity < 100,
+ " both for non-blank characters and trailing blank cells.
+ let lines =<< trim END
+ call setline(1, range(1, 100))
+ hi PopupColor ctermbg=lightblue
+ hi MyHl ctermfg=red
+
+ " 'foo ' includes trailing spaces to test the opacity blank path.
+ let winid = popup_create(['foo bar', 'baz'],
+ \ #{line: 3, col: 10, highlight: 'PopupColor', opacity: 100})
+ call win_execute(winid, "call matchadd('MyHl', 'foo ')")
+ END
+ call writefile(lines, 'XtestPopupOpacity', 'D')
+ let buf = RunVimInTerminal('-S XtestPopupOpacity', #{rows: 10})
+ call VerifyScreenDump(buf, 'Test_popupwin_opacity_hl_100', {})
+
+ " opacity=80: highlighted text should still be visible
+ call term_sendkeys(buf, ":call popup_clear()\<CR>")
+ call TermWait(buf)
+ call term_sendkeys(buf, ":let winid = popup_create(['foo bar', 'baz'],"
+ \ .. " #{line: 3, col: 10, highlight: 'PopupColor', opacity: 80})\<CR>")
+ call TermWait(buf)
+ call term_sendkeys(buf, ":call win_execute(winid,"
+ \ .. " \"call matchadd('MyHl', 'foo ')\")\<CR>")
+ call TermWait(buf)
+ call term_sendkeys(buf, ":\<CR>")
+ call VerifyScreenDump(buf, 'Test_popupwin_opacity_hl_80', {})
+
+ call StopVimInTerminal(buf)
+endfunc
+
func Test_popup_getwininfo_tabnr()
tab split
let winid1 = popup_create('sup', #{tabpage: 1})
diff --git a/src/version.c b/src/version.c
index b7510a5e9..9e140b13f 100644
--- a/src/version.c
+++ b/src/version.c
@@ -734,6 +734,8 @@ static char *(features[]) =

static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 35,
/**/
34,
/**/
Reply all
Reply to author
Forward
0 new messages