Problem: Popup with opacity fade to black whatever the colorscheme or
background is. When using a light colorscheme or the default
colorscheme with background=light,a lower value of opacity turn the
popup darker and not match the Normal background
Solution: Fade to Normal background by using guibg or ctermbg or finaly black
or white depending on the value of background option
I've tried to set fallback colors, but they are calculated for each call to hl_blend_attr(). I'm sure that can be optimised by calculating them only once after highlight initialisation but, before going any further, I prefer to check if I'm on the right track by proposing this modification.
Before this patch: with termguicolors we can see popup color fading to black for lower value of opacity until 0 where the popup sudently become fully transparent
peachpuff-termguicolor.png (view on web)
Before this patch: with notermguicolors, the same fading to black than previous screenshot occur and at opacity=0 the background of popup text become black, clashing with the transparency of the popup
peachpuff-notermguicolor.png (view on web)
After this patch to color of the popup fade from PMenu color to Normal color. smoothly when termguicolors is set.
peachpuff-termguicolor-after-patch.png (view on web)
The transition is a little bumpy when notermguicolors because there are not enough colors in the 256 palette between PMenu and Normal. It's obvious for peachpuff colorscheme.
peachpuff-notermguicolor-after-patch.png (view on web)
To test it:
open a vim file containing
" DUMB CODE TO HAVE COLORED TEXT UNDER POPUP " █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ " █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ " 0123456789 abcdef TODO highlight grup cterm=underline ctermbg=1 guibg=#00ff00 let s:uvar = &filetype . 'under' + 1 " █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ " █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ " 0123456789 abcdef TODO highlight grup cterm=underline ctermbg=1 guibg=#00ff00 let s:uvar = &filetype . 'under' + 1 " █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ " █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ " 0123456789 abcdef TODO highlight grup cterm=underline ctermbg=1 guibg=#00ff00 let s:uvar = &filetype . 'under' + 1 " █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ " █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ " 0123456789 abcdef TODO highlight grup cterm=underline ctermbg=1 guibg=#00ff00 let s:uvar = &filetype . 'under' + 1 " █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ " █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ " 0123456789 abcdef TODO highlight grup cterm=underline ctermbg=1 guibg=#00ff00 let s:uvar = &filetype . 'under' + 1 " █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ " █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ " 0123456789 abcdef TODO highlight grup cterm=underline ctermbg=1 guibg=#00ff00 let s:uvar = &filetype . 'under' + 1 " █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ " █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ █▓▒░ " 0123456789 abcdef TODO highlight grup cterm=underline ctermbg=1 guibg=#00ff00 let s:uvar = &filetype . 'under' + 1 " ===== END OF DUMB CODE ===== function! Custompopup(opacity, position) abort let popup_content = [ \ '" popup content', \ '" A C E TODO █▓▒░ ', \ 'hi p cterm=nocombine ctermbg=1 guibg=#ccc', \ '', \ 'let s:pvar = &filetype . "popup" + 1', \ ''] if (has('nvim')) let bufnr = nvim_create_buf(v:false, v:true) let opts = { \ 'relative': 'win', \ 'row': a:position['line'] -1, \ 'border': [ '╔', '═' ,'╗', '║', '╝', '═', '╚', '║' ], \ 'width': 40, \ 'height': 7, \ 'fixed': 1, \ 'col': a:position['col'], \ 'title': 'opacity ' . a:opacity, \ } call nvim_buf_set_lines(bufnr, 0, -1, v:true, popup_content) let winid = nvim_open_win(bufnr, 0, opts) let bla = nvim_win_set_option(winid, 'winblend', 100 - a:opacity) let bla = nvim_win_set_option(winid, 'filetype', 'vim') else let opts = { \ 'border': [1, 1, 1, 1], \ 'line': a:position['line'], \ 'close': 'button', \ 'minheight': 7, \ 'minwidth': 40, \ 'opacity': a:opacity, \ 'fixed': 1, \ 'col': a:position['col'], \ 'title': 'opacity ' . a:opacity, \ } let winid = popup_create(popup_content, opts) call setbufvar(winbufnr(winid), '&filetype', 'vim') endif return winid endfunction let popupline = 2 for opacity in [0, 20, 40, 60, 80, 100] let win1 = Custompopup(opacity, {'line': popupline, 'col': 10}) let popupline = popupline + 9 endfor " to compare popup and pum opacity if (has('nvim')) let pumblend=20 else set pumopt=opacity:80 endif
source it:
:sourceand play with
:colorscheme <YOURSCHEME> :set termguicolors :set notermguicolors :set background=dark :set background=light
https://github.com/vim/vim/pull/20285
(1 file)
—
Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications on the go with GitHub Mobile for iOS or Android.
You are receiving this because you are subscribed to this thread.![]()
diff --git a/src/highlight.c b/src/highlight.c index 3b1886be0..2f0ee3387 100644 --- a/src/highlight.c +++ b/src/highlight.c @@ -3242,7 +3242,7 @@ rgb_to_cterm_idx(int r, int g, int b) static bool resolve_color_to_rgb(int cterm_c, guicolor_T rgb UNUSED, int *r, int *g, int *b) { -#ifdef FEAT_TERMGUICOLORS +#if defined(FEAT_TERMGUICOLORS) || defined(FEAT_GUI) if (!COLOR_INVALID(rgb)) { *r = (rgb >> 16) & 0xFF; @@ -3326,12 +3326,26 @@ blend_colors(guicolor_T popup_color, guicolor_T bg_color, int blend_val) 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 - r = r1 * (100 - blend_val) / 100; - g = g1 * (100 - blend_val) / 100; - b = b1 * (100 - blend_val) / 100; - return (r << 16) | (g << 8) | b; + // RGB fallback background color from guibg, ctermbg or deduced form background + guicolor_T fallback_bg_rgb = INVALCOLOR; + int fbr, fbg, fbb; + guicolor_T bgcolor_or_gui_bcolor = INVALCOLOR; +#ifdef FEAT_TERMGUICOLORS + bgcolor_or_gui_bcolor = cterm_normal_bg_gui_color; +#endif +#ifdef FEAT_GUI + if (gui.in_use) + bgcolor_or_gui_bcolor = gui.back_pixel; +#endif + if (!resolve_color_to_rgb(cterm_normal_bg_color, bgcolor_or_gui_bcolor, &fbr, &fbg, &fbb)) { + if (*p_bg == 'l') + fallback_bg_rgb = 0xFFFFFF; + else + fallback_bg_rgb = 0x000000; + } else { + fallback_bg_rgb = (fbr << 16) + (fbg << 8) + fbb; + } + bg_color = fallback_bg_rgb; } r2 = (bg_color >> 16) & 0xFF; @@ -3365,6 +3379,49 @@ hl_blend_attr(int char_attr, int popup_attr, int blend, int blend_fg UNUSED) if (blend >= 100 && blend_fg) return char_attr; // Fully transparent for both fg and bg + // TODO maybe calculate once after initialisation + // RGB fallback foreground color from guifg, ctermrg or deduced form background + guicolor_T fallback_fg_rgb = INVALCOLOR; + // RGB fallback background color from guibg, ctermbg or deduced form background + guicolor_T fallback_bg_rgb = INVALCOLOR; + { + int ffr, ffg, ffb; + guicolor_T fgcolor_or_gui_fgcolor = INVALCOLOR; +#ifdef FEAT_TERMGUICOLORS + fgcolor_or_gui_fgcolor = cterm_normal_fg_gui_color; +#endif +#ifdef FEAT_GUI + if (gui.in_use) + fgcolor_or_gui_fgcolor = gui.norm_pixel; +#endif + if (!resolve_color_to_rgb(cterm_normal_fg_color, fgcolor_or_gui_fgcolor, &ffr, &ffg, &ffb)) { + if (*p_bg == 'l') + fallback_fg_rgb = 0x000000; + else + fallback_fg_rgb = 0xFFFFFF; + } else { + fallback_fg_rgb = (ffr << 16) + (ffg << 8) + ffb; + } + } + { + int fbr, fbg, fbb; + guicolor_T bgcolor_or_gui_bcolor = INVALCOLOR; +#ifdef FEAT_TERMGUICOLORS + bgcolor_or_gui_bcolor = cterm_normal_bg_gui_color; +#endif +#ifdef FEAT_GUI + if (gui.in_use) + bgcolor_or_gui_bcolor = gui.back_pixel; +#endif + if (!resolve_color_to_rgb(cterm_normal_bg_color, bgcolor_or_gui_bcolor, &fbr, &fbg, &fbb)) { + if (*p_bg == 'l') + fallback_bg_rgb = 0xFFFFFF; + else + fallback_bg_rgb = 0x000000; + } else { + fallback_bg_rgb = (fbr << 16) + (fbg << 8) + fbb; + } + } #ifdef FEAT_GUI if (gui.in_use) { @@ -3392,12 +3449,12 @@ hl_blend_attr(int char_attr, int popup_attr, int blend, int blend_fg UNUSED) // blend_fg=TRUE: fade underlying text toward popup bg. if (popup_aep->ae_u.gui.bg_color != INVALCOLOR) { - int base_fg = 0xFFFFFF; + int base_fg = fallback_fg_rgb; if (char_aep != NULL && char_aep->ae_u.gui.fg_color != INVALCOLOR) base_fg = char_aep->ae_u.gui.fg_color; new_en.ae_u.gui.fg_color = blend_colors( - base_fg, popup_aep->ae_u.gui.bg_color, blend); + popup_aep->ae_u.gui.bg_color, base_fg, blend); } } else @@ -3414,7 +3471,7 @@ hl_blend_attr(int char_attr, int popup_attr, int blend, int blend_fg UNUSED) // Blend background color: blend popup bg toward underlying bg if (popup_aep->ae_u.gui.bg_color != INVALCOLOR) { - guicolor_T underlying_bg = INVALCOLOR; + guicolor_T underlying_bg = fallback_bg_rgb; if (char_aep != NULL) underlying_bg = char_aep->ae_u.gui.bg_color; new_en.ae_u.gui.bg_color = blend_colors( @@ -3489,7 +3546,7 @@ hl_blend_attr(int char_attr, int popup_attr, int blend, int blend_fg UNUSED) #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); + under_fg, under_fg_rgb, fallback_fg_rgb, blend); } // Approximate cterm bg by blending with the underlying bg // in the 256-color palette and mapping to the nearest entry. @@ -3505,7 +3562,7 @@ hl_blend_attr(int char_attr, int popup_attr, int blend, int blend_fg UNUSED) #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); + under_bg, under_bg_rgb, fallback_bg_rgb, blend); } #ifdef FEAT_TERMGUICOLORS // Blend RGB colors for termguicolors mode. @@ -3529,7 +3586,7 @@ hl_blend_attr(int char_attr, int popup_attr, int blend, int blend_fg UNUSED) // blend_fg=TRUE: fade underlying text toward popup bg. if (popup_bg != INVALCOLOR) { - int base_fg = 0xFFFFFF; + int base_fg = fallback_fg_rgb; // 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. @@ -3537,7 +3594,7 @@ hl_blend_attr(int char_attr, int popup_attr, int blend, int blend_fg UNUSED) && !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); + popup_bg, base_fg, blend); } } else @@ -3554,12 +3611,12 @@ hl_blend_attr(int char_attr, int popup_attr, int blend, int blend_fg UNUSED) 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; + new_en.ae_u.cterm.fg_rgb = fallback_fg_rgb; } if (popup_bg != INVALCOLOR) { // Blend popup bg toward underlying bg - guicolor_T underlying_bg = INVALCOLOR; + guicolor_T underlying_bg = fallback_bg_rgb; if (char_aep != NULL && !COLOR_INVALID(char_aep->ae_u.cterm.bg_rgb)) underlying_bg = char_aep->ae_u.cterm.bg_rgb;
Looks good to me.
Before
100%
image.png (view on web)
50%
image.png (view on web)
20%
image.png (view on web)
After
100%
image.png (view on web)
both 100% for two popups.
image.png (view on web)
—
Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications on the go with GitHub Mobile for iOS or Android.
You are receiving this because you are subscribed to this thread.![]()