patch 9.2.0427: popup: opacity blend may leaks white bg color

Problem:  popup: opacity blend may leaks white bg color
Solution: Add cterm color blending for 256 color terminals, use
          COLOR_INVALID() macro to check for invalid color
          (Yasuhiro Matsumoto)

When a textprop highlight only set gui=undercurl/guisp (no fg/bg), the
CTERMCOLOR sentinel was treated by hl_blend_attr() as a real near-white
color, leaking white bg onto textprop-covered cells under an opacity
popup or pum.  Add a cterm color blending path that approximates blends
in the xterm 256-color palette using the gui RGB when available, so
opacity now has a visible effect even without 'termguicolors' (in
256-color terminals).  Below 256 colors the blend is skipped.

Also document the requirement (GUI, 'termguicolors', or 256-color
terminal) and update existing pumopt/popupwin opacity screendumps to
reflect the new blended output.

closes: #20095

Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
Yasuhiro Matsumoto
2026-05-01 16:10:21 +00:00
committed by Christian Brabandt
parent cf5d7102b9
commit 7b218ae98c
15 changed files with 398 additions and 65 deletions
+2 -1
View File
@@ -7007,7 +7007,8 @@ A jump table for the options with a short description can be found at |Q_op|.
of 'fillchars' option.
opacity:{n} opacity percentage 0-100 (default 100).
When less than 100, background content shows
through the popup menu.
through the popup menu. Requires the GUI,
'termguicolors', or a 256-color terminal.
Flags (no value):
margin adds one-cell spacing inside the left and
+4 -3
View File
@@ -1,4 +1,4 @@
*popup.txt* For Vim version 9.2. Last change: 2026 Apr 06
*popup.txt* For Vim version 9.2. Last change: 2026 May 01
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -1067,8 +1067,9 @@ The opacity value ranges from 0 to 100:
1-99 Partially transparent - the popup background is blended with
the underlying text, making both partially visible.
The transparency effect requires using the GUI or having 'termguicolors'
enabled in the terminal. Without it, the opacity setting has no effect.
The transparency effect requires using the GUI, having 'termguicolors'
enabled, or running in a 256-color terminal. On terminals with fewer
than 256 colors the opacity setting has no effect.
When a popup is transparent:
- The popup's background color is blended with the background text
+277 -44
View File
@@ -3126,9 +3126,19 @@ hl_combine_attr(int char_attr, int prim_attr)
return get_attr_entry(&term_attr_table, &new_en);
}
#if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
// ANSI color order: Black, Red, Green, Yellow, Blue, Magenta,
// Cyan, White, then bright variants. Approximate RGB values used when
// only a cterm color number is known (no guifg/guibg). Real terminal
// palettes may differ if the user reconfigured their emulator, but
// these are reasonable xterm-ish defaults.
static const long_u cterm_color_16[16] = {
0x000000, 0xc00000, 0x008000, 0x808000,
0x0000c0, 0xc000c0, 0x004080, 0xc0c0c0,
0x808080, 0xff8080, 0x00ff00, 0xffff00,
0x6060ff, 0xff40ff, 0x00ffff, 0xffffff
};
# ifdef FEAT_TERMGUICOLORS
#ifdef FEAT_TERMGUICOLORS
/*
* Convert a cterm color number (1-16) to an RGB value.
* Used as a fallback when 'termguicolors' is set but only cterm colors are
@@ -3138,21 +3148,156 @@ hl_combine_attr(int char_attr, int prim_attr)
static guicolor_T
cterm_color_to_rgb(int color_nr)
{
// ANSI color order: Black, Red, Green, Yellow, Blue, Magenta,
// Cyan, White, then bright variants.
static const guicolor_T cterm_color_16[16] = {
0x000000, 0xc00000, 0x008000, 0x808000,
0x0000c0, 0xc000c0, 0x004080, 0xc0c0c0,
0x808080, 0xff8080, 0x00ff00, 0xffff00,
0x6060ff, 0xff40ff, 0x00ffff, 0xffffff
};
if (color_nr < 1 || color_nr > 16)
return INVALCOLOR;
return cterm_color_16[color_nr - 1];
return (guicolor_T)cterm_color_16[color_nr - 1];
}
# endif
#endif
/*
* Convert an xterm 256-color index (0-255) to an approximate RGB triple.
* Uses the standard xterm palette: 0-15 ANSI (cterm_color_16), 16-231
* 6x6x6 cube, 232-255 grayscale ramp.
*/
static void
cterm_idx_to_rgb(int idx, int *r, int *g, int *b)
{
static const int cube[] = { 0x00, 0x5F, 0x87, 0xAF, 0xD7, 0xFF };
if (idx < 0 || idx > 255)
{
*r = *g = *b = 0;
return;
}
if (idx < 16)
{
long_u rgb = cterm_color_16[idx];
*r = (rgb >> 16) & 0xFF;
*g = (rgb >> 8) & 0xFF;
*b = rgb & 0xFF;
}
else if (idx < 232)
{
int n = idx - 16;
*r = cube[n / 36 % 6];
*g = cube[n / 6 % 6];
*b = cube[n % 6];
}
else
{
int v = 8 + (idx - 232) * 10;
*r = *g = *b = v;
}
}
/*
* Approximate an RGB triple to the nearest xterm 256-color index.
* Searches the 6x6x6 cube and the grayscale ramp; returns 0-255.
*/
static int
rgb_to_cterm_idx(int r, int g, int b)
{
static const int cube[] = { 0x00, 0x5F, 0x87, 0xAF, 0xD7, 0xFF };
int best = 0;
long best_d = -1;
int i;
// Search the 6x6x6 cube.
for (i = 16; i < 232; ++i)
{
int n = i - 16;
int cr = cube[n / 36 % 6];
int cg = cube[n / 6 % 6];
int cb = cube[n % 6];
long d = (cr - r) * (cr - r) + (cg - g) * (cg - g) + (cb - b) * (cb - b);
if (best_d < 0 || d < best_d)
{
best_d = d;
best = i;
}
}
// Search the grayscale ramp.
for (i = 232; i < 256; ++i)
{
int v = 8 + (i - 232) * 10;
long d = (v - r) * (v - r) + (v - g) * (v - g) + (v - b) * (v - b);
if (d < best_d)
{
best_d = d;
best = i;
}
}
return best;
}
/*
* Resolve a color to an RGB triple. Prefer the gui RGB value (set by
* guifg/guibg) when valid, otherwise convert the cterm 256-color index.
* Returns true on success; false when no color is defined.
* cterm_c is 1-based (0 means "no color").
*/
static bool
resolve_color_to_rgb(int cterm_c, guicolor_T rgb UNUSED, int *r, int *g, int *b)
{
#ifdef FEAT_TERMGUICOLORS
if (!COLOR_INVALID(rgb))
{
*r = (rgb >> 16) & 0xFF;
*g = (rgb >> 8) & 0xFF;
*b = rgb & 0xFF;
return true;
}
#endif
if (cterm_c > 0)
{
cterm_idx_to_rgb(cterm_c - 1, r, g, b);
return true;
}
return false;
}
/*
* Blend two colors expressed as (cterm 256 index, gui RGB) pairs and
* return the nearest 1-based cterm 256-color index. Prefers the gui
* RGB so highlight definitions like "guibg=#2D2A3D" without ctermbg
* still produce a meaningful blend in 256-color terminals.
*
* "default_rgb" is used as the underlying color when neither under_c
* nor under_rgb is set; pass 0xFFFFFF for fg-style blends (so text
* fades toward white) or 0x000000 for bg-style blends (so the popup
* fades toward terminal default dark).
*
* Requires t_colors >= 256; otherwise returns popup_c unchanged.
*/
static int
blend_cterm_colors(int popup_c, guicolor_T popup_rgb,
int under_c, guicolor_T under_rgb,
int default_rgb,
int blend_val)
{
int pr, pg, pb, ur, ug, ub, r, g, b;
if (t_colors < 256)
return popup_c;
if (!resolve_color_to_rgb(popup_c, popup_rgb, &pr, &pg, &pb))
return under_c;
if (blend_val <= 0)
return rgb_to_cterm_idx(pr, pg, pb) + 1;
if (!resolve_color_to_rgb(under_c, under_rgb, &ur, &ug, &ub))
{
ur = (default_rgb >> 16) & 0xFF;
ug = (default_rgb >> 8) & 0xFF;
ub = default_rgb & 0xFF;
}
if (blend_val >= 100)
return rgb_to_cterm_idx(ur, ug, ub) + 1;
r = pr + (ur - pr) * blend_val / 100;
g = pg + (ug - pg) * blend_val / 100;
b = pb + (ub - pb) * blend_val / 100;
return rgb_to_cterm_idx(r, g, b) + 1;
}
#if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
/*
* Blend two RGB colors based on blend value (0-100).
* blend: 0=use popup color, 100=use background color
@@ -3163,7 +3308,9 @@ blend_colors(guicolor_T popup_color, guicolor_T bg_color, int blend_val)
{
int r1, g1, b1, r2, g2, b2, r, g, b;
if (popup_color == INVALCOLOR)
// CTERMCOLOR is a sentinel meaning "use the cterm color"; for blending
// it has no real RGB so treat it like INVALCOLOR.
if (COLOR_INVALID(popup_color))
return INVALCOLOR;
// Fully transparent: use underlying color as-is.
@@ -3174,7 +3321,7 @@ blend_colors(guicolor_T popup_color, guicolor_T bg_color, int blend_val)
g1 = (popup_color >> 8) & 0xFF;
b1 = popup_color & 0xFF;
if (bg_color == INVALCOLOR)
if (COLOR_INVALID(bg_color))
{
// Background color unknown: fade popup color to black as blend increases
// This makes background text more visible at high blend values
@@ -3253,11 +3400,13 @@ hl_blend_attr(int char_attr, int popup_attr, int blend, int blend_fg UNUSED)
else
{
// blend_fg=FALSE: popup text is opaque. Replace the
// underlying cell's attribute flags and fg with the
// popup's, so the underlying syntax highlighting does
// not bleed through.
// underlying cell's attribute flags, fg and special
// color with the popup's, so the underlying syntax
// highlighting and any decoration (textprop undercurl,
// ...) do not bleed through.
new_en.ae_attr = popup_aep->ae_attr;
new_en.ae_u.gui.fg_color = popup_aep->ae_u.gui.fg_color;
new_en.ae_u.gui.sp_color = popup_aep->ae_u.gui.sp_color;
}
// Blend background color: blend popup bg toward underlying bg
if (popup_aep->ae_u.gui.bg_color != INVALCOLOR)
@@ -3301,18 +3450,60 @@ hl_blend_attr(int char_attr, int popup_attr, int blend, int blend_fg UNUSED)
if (!blend_fg)
{
// blend_fg=FALSE: popup text is opaque. Replace the
// underlying cell's attribute flags and fg with the
// popup's, so the underlying syntax highlighting does
// not bleed through.
// underlying cell's attribute flags, fg and underline
// color with the popup's, so the underlying syntax
// highlighting and any decoration (textprop undercurl,
// ...) do not bleed through. When the popup has no fg
// (e.g. "guifg=NONE") fall back to Normal's fg so the
// text is still readable instead of taking on whatever
// the underlying cell happened to have.
new_en.ae_attr = popup_aep->ae_attr;
new_en.ae_u.cterm.fg_color = popup_aep->ae_u.cterm.fg_color;
if (popup_aep->ae_u.cterm.fg_color > 0)
new_en.ae_u.cterm.fg_color =
popup_aep->ae_u.cterm.fg_color;
else if (cterm_normal_fg_color > 0)
new_en.ae_u.cterm.fg_color = cterm_normal_fg_color;
else
new_en.ae_u.cterm.fg_color = 16; // white-ish
new_en.ae_u.cterm.ul_color = popup_aep->ae_u.cterm.ul_color;
#ifdef FEAT_TERMGUICOLORS
new_en.ae_u.cterm.ul_rgb = popup_aep->ae_u.cterm.ul_rgb;
#endif
}
else
{
// blend_fg=TRUE: fade underlying fg toward popup bg in
// the 256-color palette. Used when the popup is over a
// cell rendered with cterm colors (no termguicolors RGB).
int under_fg = (char_aep != NULL)
? char_aep->ae_u.cterm.fg_color : 0;
guicolor_T under_fg_rgb = INVALCOLOR;
guicolor_T popup_bg_rgb = INVALCOLOR;
#ifdef FEAT_TERMGUICOLORS
if (char_aep != NULL)
under_fg_rgb = char_aep->ae_u.cterm.fg_rgb;
popup_bg_rgb = popup_aep->ae_u.cterm.bg_rgb;
#endif
new_en.ae_u.cterm.fg_color = blend_cterm_colors(
popup_aep->ae_u.cterm.bg_color, popup_bg_rgb,
under_fg, under_fg_rgb, 0xFFFFFF, blend);
}
// Approximate cterm bg by blending with the underlying bg
// in the 256-color palette and mapping to the nearest entry.
{
int under_bg = (char_aep != NULL)
? char_aep->ae_u.cterm.bg_color : 0;
guicolor_T under_bg_rgb = INVALCOLOR;
guicolor_T popup_bg_rgb = INVALCOLOR;
#ifdef FEAT_TERMGUICOLORS
if (char_aep != NULL)
under_bg_rgb = char_aep->ae_u.cterm.bg_rgb;
popup_bg_rgb = popup_aep->ae_u.cterm.bg_rgb;
#endif
new_en.ae_u.cterm.bg_color = blend_cterm_colors(
popup_aep->ae_u.cterm.bg_color, popup_bg_rgb,
under_bg, under_bg_rgb, 0x000000, blend);
}
else if (popup_aep->ae_u.cterm.fg_color > 0)
// Blend foreground color
new_en.ae_u.cterm.fg_color = popup_aep->ae_u.cterm.fg_color;
// Use popup background color (cterm colors don't support blending)
if (popup_aep->ae_u.cterm.bg_color > 0)
new_en.ae_u.cterm.bg_color = popup_aep->ae_u.cterm.bg_color;
#ifdef FEAT_TERMGUICOLORS
// Blend RGB colors for termguicolors mode.
// Fall back to cterm color converted to RGB when
@@ -3336,24 +3527,38 @@ hl_blend_attr(int char_attr, int popup_attr, int blend, int blend_fg UNUSED)
if (popup_bg != INVALCOLOR)
{
int base_fg = 0xFFFFFF;
// CTERMCOLOR is a sentinel meaning "use the cterm
// color"; treat it as no underlying color so it is
// not blended in as a real near-white pixel.
if (char_aep != NULL
&& char_aep->ae_u.cterm.fg_rgb != INVALCOLOR)
&& !COLOR_INVALID(char_aep->ae_u.cterm.fg_rgb))
base_fg = char_aep->ae_u.cterm.fg_rgb;
new_en.ae_u.cterm.fg_rgb = blend_colors(
base_fg, popup_bg, blend);
}
}
else
{
// blend_fg=FALSE: popup text is opaque. Replace fg
// with popup's (even INVALCOLOR) so the underlying
// syntax highlighting fg does not bleed. ae_attr
// was already set above for this branch.
new_en.ae_u.cterm.fg_rgb = popup_fg;
// with popup's so the underlying syntax highlighting
// fg does not bleed. ae_attr was already set above
// for this branch. When the popup has no fg fall
// back to Normal's fg, then to white, so the text
// stays readable instead of rendering as default
// (which can be black on dark themes).
if (!COLOR_INVALID(popup_fg))
new_en.ae_u.cterm.fg_rgb = popup_fg;
else if (!COLOR_INVALID(cterm_normal_fg_gui_color))
new_en.ae_u.cterm.fg_rgb = cterm_normal_fg_gui_color;
else
new_en.ae_u.cterm.fg_rgb = 0xFFFFFF;
}
if (popup_bg != INVALCOLOR)
{
// Blend popup bg toward underlying bg
guicolor_T underlying_bg = INVALCOLOR;
if (char_aep != NULL)
if (char_aep != NULL
&& !COLOR_INVALID(char_aep->ae_u.cterm.bg_rgb))
underlying_bg = char_aep->ae_u.cterm.bg_rgb;
new_en.ae_u.cterm.bg_rgb = blend_colors(
popup_bg, underlying_bg, blend);
@@ -3463,21 +3668,48 @@ hl_pum_blend_attr(int char_attr, int popup_attr, int blend UNUSED)
popup_aep = syn_cterm_attr2entry(popup_attr);
if (popup_aep != NULL)
{
// Blend cterm fg: use popup bg (hides text when opaque)
if (popup_aep->ae_u.cterm.fg_color > 0)
new_en.ae_u.cterm.fg_color =
popup_aep->ae_u.cterm.fg_color;
// Use popup cterm bg.
if (popup_aep->ae_u.cterm.bg_color > 0)
new_en.ae_u.cterm.bg_color =
popup_aep->ae_u.cterm.bg_color;
// Blend cterm fg: pum_bg toward underlying_fg in the
// 256-color palette (mirrors the fg_rgb blend below).
{
int under_fg = (char_aep != NULL)
? char_aep->ae_u.cterm.fg_color : 0;
guicolor_T under_fg_rgb = INVALCOLOR;
guicolor_T popup_bg_rgb = INVALCOLOR;
#ifdef FEAT_TERMGUICOLORS
if (char_aep != NULL)
under_fg_rgb = char_aep->ae_u.cterm.fg_rgb;
popup_bg_rgb = popup_aep->ae_u.cterm.bg_rgb;
#endif
new_en.ae_u.cterm.fg_color = blend_cterm_colors(
popup_aep->ae_u.cterm.bg_color, popup_bg_rgb,
under_fg, under_fg_rgb, 0xFFFFFF, blend);
}
// Approximate cterm bg by blending with the underlying bg
// in the 256-color palette and mapping to the nearest entry.
{
int under_bg = (char_aep != NULL)
? char_aep->ae_u.cterm.bg_color : 0;
guicolor_T under_bg_rgb = INVALCOLOR;
guicolor_T popup_bg_rgb = INVALCOLOR;
#ifdef FEAT_TERMGUICOLORS
if (char_aep != NULL)
under_bg_rgb = char_aep->ae_u.cterm.bg_rgb;
popup_bg_rgb = popup_aep->ae_u.cterm.bg_rgb;
#endif
new_en.ae_u.cterm.bg_color = blend_cterm_colors(
popup_aep->ae_u.cterm.bg_color, popup_bg_rgb,
under_bg, under_bg_rgb, 0x000000, blend);
}
#ifdef FEAT_TERMGUICOLORS
// Blend fg_rgb: pum_bg toward underlying_fg.
// CTERMCOLOR is a sentinel meaning "use the cterm color";
// treat it as no underlying color so it is not blended in
// as a real near-white pixel.
if (popup_aep->ae_u.cterm.bg_rgb != INVALCOLOR)
{
int base_fg = 0xFFFFFF;
if (char_aep != NULL
&& char_aep->ae_u.cterm.fg_rgb != INVALCOLOR)
&& !COLOR_INVALID(char_aep->ae_u.cterm.fg_rgb))
base_fg = char_aep->ae_u.cterm.fg_rgb;
new_en.ae_u.cterm.fg_rgb = blend_colors(
popup_aep->ae_u.cterm.bg_rgb, base_fg, blend);
@@ -3486,7 +3718,8 @@ hl_pum_blend_attr(int char_attr, int popup_attr, int blend UNUSED)
if (popup_aep->ae_u.cterm.bg_rgb != INVALCOLOR)
{
guicolor_T underlying_bg = INVALCOLOR;
if (char_aep != NULL)
if (char_aep != NULL
&& !COLOR_INVALID(char_aep->ae_u.cterm.bg_rgb))
underlying_bg = char_aep->ae_u.cterm.bg_rgb;
new_en.ae_u.cterm.bg_rgb = blend_colors(
popup_aep->ae_u.cterm.bg_rgb,
+2 -2
View File
@@ -1,7 +1,7 @@
>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
|3| @7|f+0#ff404010#5fafd7255|o@1| +0#87d7ff255&@1|b+0#ffffff16&|a|r| +0#0000000#ffffff0@57
|4| @7|b+0#ffffff16#5fafd7255|a|z| +0#87d7ff255&@4| +0#0000000#ffffff0@57
|5| @73
|6| @73
|7| @73
@@ -0,0 +1,8 @@
>a+0&#ffffff0@2| |b@2| |c|P+0#e5e9f0255#03050b255|O|P|U|P|d+0#61646f255&|C+0#e5e9f0255&|O|N|T|E|N|T|f+0#61646f255&| |g@2| |h@2| @7| +0#0000000#ffffff0@10
|i@2| |j@2| |k|k+0#61646f255#03050b255@1| |l@2| |m@2| |n@2| |o@2| |p@2| @7| +0#0000000#ffffff0@10
|q@2| |r@2| |s|s+0#61646f255#03050b255@1| |m+0#e5e9f0255&|i|d@1|l|e|u+0#61646f255&| |v@2| |w@2| |x@2| @7| +0#0000000#ffffff0@10
|y@2| |z@2| |1@2| |2@2| |3@2| |4@2| |5@2| |6@2| @18
|~+0#0000ff255&| @48
|~| @48
|~| @48
| +0#0000000&@31|1|,|1| @10|A|l@1|
+2 -2
View File
@@ -1,7 +1,7 @@
>b+0&#ffffff0|a|c|k|g|r|o|u|n|d| |t|e|x|t| |h|e|r|e| @54
|b|a|c|k|g|r|o|u|n|d| |t|e|x|t| |h|e|r|e| @54
|b|a|c|k|b|l|u|e|n|p|o|p|u|p|t| |h|e|r|e| @54
|b|a|c|k|g|r|o|r|e|d| |p|o|p|u|p|h|e|r|e| @54
|b|a|c|k|b+0#ffffff16#00005f255|l|u|e|n+0#8787d7255&|p+0#ffffff16&|o|p|u|p|t+0#0000000#ffffff0| |h|e|r|e| @54
|b|a|c|k|g|r|o|r+0#ffffff16#000000255|e|d| +0#0000000#ffffff0|p+0#ffffff16#000000255|o|p|u|p|h+0#0000000#ffffff0|e|r|e| @54
|b|a|c|k|g|r|o|u|n|d| |t|e|x|t| |h|e|r|e| @54
|b|a|c|k|g|r|o|u|n|d| |t|e|x|t| |h|e|r|e| @54
|b|a|c|k|g|r|o|u|n|d| |t|e|x|t| |h|e|r|e| @54
+2 -2
View File
@@ -1,7 +1,7 @@
>b+0&#ffffff0|a|c|k|g|r|o|u|n|d| |t|e|x|t| |h|e|r|e| @54
|b|a|c|k|g|r|o|u|n|d| |t|e|x|t| |h|e|r|e| @54
|b|a|c|k|b|l|u|e|n|p|o|p|u|p|t| |h|e|r|e| @54
|b|a|c|k|g|r|o|r|e|d| |p|o|p|u|p|h|e|r|e| @54
|b|a|c|k|b+0#ffffff16#00005f255|l|u|e|n+0#8787d7255&|p+0#ffffff16&|o|p|u|p|t+0#0000000#ffffff0| |h|e|r|e| @54
|b|a|c|k|g|r|o|r+0#ffffff16#000000255|e|d| +0#0000000#ffffff0|p+0#ffffff16#000000255|o|p|u|p|h+0#0000000#ffffff0|e|r|e| @54
|b|a|c|k|g|r|o|u|n|d| |t|e|x|t| |h|e|r|e| @54
|b|a|c|k|g|r|o|u|n|d| |t|e|x|t| |h|e|r|e| @54
|b|a|c|k|g|r|o|u|n|d| |t|e|x|t| |h|e|r|e| @54
+2 -2
View File
@@ -13,8 +13,8 @@
|B|A|C|K|G|R|O|U|N|D|B|A|C|K|G|R|O|U|N|D|B|A|C|K|G|R|O|U|N|D|B|A|C|K|G|R|O|U|N|D|B|A|C|K|G|R|O|U|N|D|B|A|C|K|G|R|O|U|N|D|B|A|C|K|G|R|O|U|N|D|B|A|C|K|G
|R|O|U|N|D| @69
|h|e|l@1|o> @69
|h+0#0000001#e0e0e08|e|l@1|o| @9| +0#4040ff13#ffffff0@59
|h+0#0000001#ffd7ff255|e|l|p| @10| +0#4040ff13#ffffff0@59
|h+0#0000001#5f5f5f255|e|l@1|o| +0#5f5fd7255&@9| +0#4040ff13#ffffff0@59
|h+0#0000001#875f87255|e|l|p| +0#875fff255&@10| +0#4040ff13#ffffff0@59
|~| @73
|~| @73
|-+2#0000000&@1| |K|e|y|w|o|r|d| |c|o|m|p|l|e|t|i|o|n| |(|^|N|^|P|)| |m+0#00e0003&|a|t|c|h| |1| |o|f| |2| +0#0000000&@33
+3 -3
View File
@@ -1,7 +1,7 @@
|ほ*0&#ffffff0|げ> +&@70
|ほ*0#0000001#ffff4012|げ|ほ|げ|ほ|げ|漢*4&&| +&| +4#e000e06#ffffff0|テ*&|ス|ト|あ*0#0000000&|い|う|え|お|カ|タ|カ|ナ| +&@34
|ふ*0#ffffff16#0000e05|が|漢|字|ほ|げ|漢*4&&| +&| +4#e000e06#ffffff0|テ*&|ス|ト|あ*0#0000000&|い|う|え|お|カ|タ|カ|ナ| +&@34
|カ*0#ffffff16#0000e05|タ|カ|ナ|候|補|漢*4&&| +&| +4#e000e06#ffffff0|テ*&|ス|ト|あ*0#0000000&|い|う|え|お|カ|タ|カ|ナ| +&@34
|ほ*0#0000001#875f00255|げ|ほ*0#ffd787255&|げ|ほ|げ|漢*4#ff875f255&| +&| +4#e000e06#ffffff0|テ*&|ス|ト|あ*0#0000000&|い|う|え|お|カ|タ|カ|ナ| +&@34
|ふ*0#ffffff16#00005f255|が|漢|字|ほ*0#87afaf255&|げ|漢*4#875faf255&| +&| +4#e000e06#ffffff0|テ*&|ス|ト|あ*0#0000000&|い|う|え|お|カ|タ|カ|ナ| +&@34
|カ*0#ffffff16#00005f255|タ|カ|ナ|候|補|漢*4#875faf255&| +&| +4#e000e06#ffffff0|テ*&|ス|ト|あ*0#0000000&|い|う|え|お|カ|タ|カ|ナ| +&@34
|ほ*&|げ|ほ|げ|ほ|げ|漢*4#e000e06&|字|テ|ス|ト|あ*0#0000000&|い|う|え|お|カ|タ|カ|ナ| +&@34
|ほ*&|げ|ほ|げ|ほ|げ|漢*4#e000e06&|字|テ|ス|ト|あ*0#0000000&|い|う|え|お|カ|タ|カ|ナ| +&@34
|ほ*&|げ|ほ|げ|ほ|げ|漢*4#e000e06&|字|テ|ス|ト|あ*0#0000000&|い|う|え|お|カ|タ|カ|ナ| +&@34
@@ -0,0 +1,20 @@
|p+0&#ffffff0|o|p|u|p|-|i|t|e|m|-|1> @62
|p+0#000000255#5f5f5f255|o|p|u|p|-|i|t|e|m|-|1|d+0#dedede255&@2| +0#0000000#ffffff0|e@2| |f@2| |g@2| |h@2| @43
|p+0#000000255#7f457f255|o|p|u|p|-|i|t|e|m|-|2|d+0#ffc5ff255&@2| +0#0000000#ffffff0|e@2| |f@2| |g@2| |h@2| @43
|p+0#000000255#7f457f255|o|p|u|p|-|i|t|e|m|-|3|d+0#ffc5ff255&@2| +0#0000000#ffffff0|e@2| |f@2| |g@2| |h@2| @43
|a@2| |b@2| |c@2| |d@2| |e@2| |f@2| |g@2| |h@2| @43
|a@2| |b@2| |c@2| |d@2| |e@2| |f@2| |g@2| |h@2| @43
|a@2| |b@2| |c@2| |d@2| |e@2| |f@2| |g@2| |h@2| @43
|a@2| |b@2| |c@2| |d@2| |e@2| |f@2| |g@2| |h@2| @43
|a@2| |b@2| |c@2| |d@2| |e@2| |f@2| |g@2| |h@2| @43
|~+0#0000ff255&| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|-+2#0000000&@1| |I|N|S|E|R|T| |-@1| +0&&@44|1|,|1| @10|A|l@1|
+3 -3
View File
@@ -1,8 +1,8 @@
|ほ*0&#ffffff0|げ> +&@70
|╭+0#0000001#ffd7ff255|─@15|╮|ス*0#0000000#ffffff0|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@34
|│+0#0000001#ffd7ff255| +0&#e0e0e08|ほ*&|げ@1|ほ|げ|漢|字| +&|│+0&#ffd7ff255|ス*0#0000000#ffffff0|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@34
|│+0#0000001#ffd7ff255| |ふ*&|が|漢|字|げ|漢|字| +&|│|ス*0#0000000#ffffff0|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@34
|│+0#0000001#ffd7ff255| |カ*&|タ|カ|ナ|候|補|字| +&|│|ス*0#0000000#ffffff0|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@34
|│+0#0000001#ffd7ff255| +0&#5f5f5f255|ほ*&|げ|げ*0#dadada255&|ほ|げ|漢|字| +&|│+0#0000001#ffd7ff255|ス*0#0000000#ffffff0|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@34
|│+0#0000001#ffd7ff255| +0&#875f87255|ふ*&|が|漢|字|げ*0#ffd7ff255&|漢|字| +&|│+0#0000001#ffd7ff255|ス*0#0000000#ffffff0|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@34
|│+0#0000001#ffd7ff255| +0&#875f87255|カ*&|タ|カ|ナ|候|補|字*0#ffd7ff255&| +&|│+0#0000001#ffd7ff255|ス*0#0000000#ffffff0|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@34
|╰+0#0000001#ffd7ff255|─@15|╯|ス*0#0000000#ffffff0|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@34
|ほ*&|げ|ほ|げ|ほ|げ|漢|字|テ|ス|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@34
|ほ*&|げ|ほ|げ|ほ|げ|漢|字|テ|ス|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@34
+3 -3
View File
@@ -1,8 +1,8 @@
|ほ*0&#ffffff0|げ> +&@70
|╭+0#0000001#ffd7ff255|─@15|╮|ス*0#0000000#ffffff0|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@34
|│+0#0000001#ffd7ff255| +0&#e0e0e08|ほ*&|げ| +&|げ*&|ほ|げ|漢|字|│+0&#ffd7ff255| +0#0000000#ffffff0|ス*&|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@33
|│+0#0000001#ffd7ff255| |ふ*&|が|漢|字|げ|漢|字| +&|│|ス*0#0000000#ffffff0|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@34
|│+0#0000001#ffd7ff255| |カ*&|タ|カ|ナ|候|補| +&|字*&|│+&| +0#0000000#ffffff0|ス*&|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@33
|│+0#0000001#ffd7ff255| +0&#5f5f5f255|ほ*&|げ| +0#dadada255&|げ*&|ほ|げ|漢|字|│+0#0000001#ffd7ff255| +0#0000000#ffffff0|ス*&|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@33
|│+0#0000001#ffd7ff255| +0&#875f87255|ふ*&|が|漢|字|げ*0#ffd7ff255&|漢|字| +&|│+0#0000001#ffd7ff255|ス*0#0000000#ffffff0|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@34
|│+0#0000001#ffd7ff255| +0&#875f87255|カ*&|タ|カ|ナ|候|補| +0#ffd7ff255&|字*&|│+0#0000001#ffd7ff255| +0#0000000#ffffff0|ス*&|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@33
|╰+0#0000001#ffd7ff255|─@15|╯|ス*0#0000000#ffffff0|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@34
|a|ほ*&|げ|ほ|げ|ほ|げ|漢|字|テ|ス|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@33
|ほ*&|げ|ほ|げ|ほ|げ|漢|字|テ|ス|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@34
+34
View File
@@ -2474,6 +2474,40 @@ func Test_pumopt_opacity_wide_bg()
call StopVimInTerminal(buf)
endfunc
" hl_pum_blend_attr() treated the CTERMCOLOR sentinel as a real near-white
" color, leaking white bg onto textprop-covered cells under pum opacity.
" Triggered by a textprop hl that only sets guisp.
func Test_pumopt_opacity_textprop_undercurl()
CheckScreendump
let lines =<< trim END
set termguicolors
set t_Cs= t_Ce=
set pumopt=opacity:50
set completeopt=menu
call setline(1, '')
for i in range(8)
call append(line('$'), 'aaa bbb ccc ddd eee fff ggg hhh')
endfor
hi MyError guisp=#ec7279
call prop_type_add('mytype', #{highlight: 'MyError', combine: 1})
for s:l in range(2, 8)
call prop_add(s:l, 5, #{type: 'mytype', length: 20})
endfor
normal gg
inoremap <F5> <Cmd>call complete(col('.'),
\ ['popup-item-1', 'popup-item-2', 'popup-item-3'])<CR>
END
call writefile(lines, 'Xpumoptopacitytextprop', 'D')
let buf = RunVimInTerminal('-S Xpumoptopacitytextprop', {})
call TermWait(buf)
call term_sendkeys(buf, "i\<F5>")
call TermWait(buf, 100)
call VerifyScreenDump(buf, 'Test_pumopt_opacity_textprop_undercurl', {})
call term_sendkeys(buf, "\<C-E>\<Esc>u")
call TermWait(buf)
call StopVimInTerminal(buf)
endfunc
" Test pumopt opacity when every other background line is shifted by one
" narrow cell, so the background's wide-character boundaries do not align
" with the popup's wide-character grid. Exercises the blend path when:
+34
View File
@@ -5120,6 +5120,40 @@ func Test_popup_opacity_vsplit()
call StopVimInTerminal(buf)
endfunc
func Test_popup_opacity_textprop_undercurl()
CheckScreendump
" hl_blend_attr() treated the CTERMCOLOR sentinel as a real near-white
" color, leaking white bg onto textprop-covered cells under an opacity
" popup. Triggered by a textprop hl that only sets guisp.
let lines =<< trim END
set termguicolors
set t_Cs= t_Ce=
call setline(1, ['aaa bbb ccc ddd eee fff ggg hhh',
\ 'iii jjj kkk lll mmm nnn ooo ppp',
\ 'qqq rrr sss ttt uuu vvv www xxx',
\ 'yyy zzz 111 222 333 444 555 666'])
hi MyError guisp=#ec7279
call prop_type_add('mytype', #{highlight: 'MyError', combine: 1})
for s:l in range(1, line('$'))
call prop_add(s:l, 5, #{type: 'mytype', length: 20})
endfor
hi PanelBg guibg=#0b1021 guifg=#e5e9f0
call popup_create(['POPUP CONTENT', ' ', ' middle '], #{
\ line: 1, col: 10,
\ minwidth: 30, minheight: 3,
\ opacity: 35,
\ highlight: 'PanelBg',
\ zindex: 200,
\ })
END
call writefile(lines, 'XtestPopupOpacityTextprop', 'D')
let buf = RunVimInTerminal('-S XtestPopupOpacityTextprop', #{rows: 8, cols: 50})
call VerifyScreenDump(buf, 'Test_popupwin_opacity_textprop_undercurl', {})
call StopVimInTerminal(buf)
endfunc
func Test_popup_close_b_nwindows()
edit Xfoo
setlocal bufhidden=wipe
+2
View File
@@ -729,6 +729,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
427,
/**/
426,
/**/