Opacity with undefined bg for popup highlight group result a fully transparent popup#20414
Opacity with undefined bg for popup highlight group result a fully transparent popup#20414shadowwa wants to merge 13 commits into
Conversation
Problem: when the Popup highlight group has no guibg/ctermbg the popup
became fully transparent.
Solution: Create an entry if no popup_attr exists (highlight group
cleared for example), and test if popup_attr exists but
without guibg/ctermbg attributes to fallaback to normal bg
color.
previously the blending used guibg and guifg even when termguicolor was not set, here the text color is white now the if the guibg color is still used, for the text color without termguicolor, only a ctermfg will be used and since &background=light the resulting popup text color is black
You can add |
I mean, I've started to add in src/testdir/test_gui.vim a test like func Test_gui_popup_opacity_undefined_popup_highlight()
CheckGui
CheckScreendump
"[…]
call VerifyScreenDump(…to get an error " Verify that Vim running in terminal buffer "buf" matches the screen dump.but did not found a similar function for gui use. |
VerifyScreenDump should work in the GUI, it uses the terminal feature, not the terminal Vim is running in. I think the error you are getting is because test_gui.vim doesn't source src/screendump.vim. However you shouldnt be putting the tests in test_gui, just put them in test_popupwin. The CI will run Vim in the GUI against all the tests anyways, you can test using |
Thanks, I've missed this option when reading the doc. |
h-east
left a comment
There was a problem hiding this comment.
Thanks for the pull request!
By the way, adjusting the columns is easier using {Visual}gq (:h v_gq).
Scope: src/highlight.c, function hl_blend_attr().
1. Removed early-return changes behavior for the both-zero case
The early return
// If both attrs are 0, return 0
if (char_attr == 0 && popup_attr == 0)
return 0;was removed. This is necessary for the fix (a colorless popup must still blend
instead of being skipped), so the direction is correct. However, the removal also
affects the trivial case where both the underlying cell and the popup resolve to
attr 0: it used to return plain 0, and now it synthesizes a popup entry with the
Normal background and produces a blended attribute entry.
hl_blend_attr() is also called from pum opacity and popup border/background paths
(popupwin.c, screen.c), so this is a behavior change for those callers too, not
only for the reported case. In practice get_attr_entry() deduplicates the result,
so the cost is bounded, and the visible result should match (Normal bg equals the
terminal default). Still, it would be good to call out this intentional behavior
change in the commit message / PR description so it is not mistaken for an
accidental side effect.
2. A popup attr in the range 1..HL_ALL loses its raw attribute flags
When popup_attr <= HL_ALL the code now builds a synthetic entry with
CLEAR_FIELD(tmp_en), i.e. ae_attr == 0. If popup_attr is a non-zero raw
attribute (1 <= popup_attr <= HL_ALL, e.g. a highlight that is only "bold" with no
colors), those flags are silently dropped, because for blend_fg == FALSE the code
does new_en.ae_attr = popup_aep->ae_attr; (== 0). The old code skipped the whole
blend block in this case, so the underlying attribute was preserved instead.
This value range is unusual for a popup highlight, so the impact is small, but it is
a real corner that changed. Consider preserving popup_attr into the synthetic
entry (e.g. tmp_en.ae_attr = popup_attr <= HL_ALL ? popup_attr : 0;) if keeping
bold/underline-only popup highlights matters.
3. GUI vs cterm asymmetry for the foreground fallback
In the cterm branch the fix adds a foreground fallback when the popup has no fg and
text is opaque (blend_fg == FALSE): popup fg -> cterm_normal_fg_color ->
(*p_bg == 'l') ? 1 : 16. This is what stops the underlying text color from
bleeding through (the OVERANDABOVE case).
The GUI branch does not do the equivalent: its synthetic entry leaves
fg_color = INVALCOLOR, and for blend_fg == FALSE it assigns
new_en.ae_u.gui.fg_color = popup_aep->ae_u.gui.fg_color; (== INVALCOLOR). GUI
resolves INVALCOLOR to the default foreground, so it usually looks acceptable, but
the "fall back to Normal fg" intent that was added for cterm is not mirrored on the
GUI side. Worth aligning the two paths, or at least confirming the GUI result is
intentional. (The author already notes the GUI path is untested because the
screendump only covers the terminal.)
4. Duplicated fallback snippet (optional)
The pattern
if (COLOR_INVALID(popup_bg_rgb) && popup_aep->ae_u.cterm.bg_color == 0)
popup_bg_rgb = fallback_bg_rgb;appears twice in the cterm (no-termguicolors) block, and a similar
if (COLOR_INVALID(popup_bg)) popup_bg = fallback_bg_rgb; in the termguicolors
block. Each operates on a slightly different field, so this is not required, but a
small helper (or computing the fallback once) would reduce repetition and the chance
of the three copies drifting apart later.
5. Test coverage
The added cterm screendumps cover the core cases well
(Test_popup_opacity_undefined_popup_highlight for the Normal / linked-to-Normal /
cleared / bg=NONE groups, and Test_popup_opacity_only_cterm_or_gui_set). The GUI
rendering path has no test, which the author acknowledges; since the fix is applied
separately in the GUI branch, that untested path is the main coverage gap.
Overall
The approach (synthesize a popup entry with the Normal background when the popup
highlight has no real entry, and fall back for fg) is sound and matches the
before/after screenshots. The points above are mostly clarifications and minor
robustness items rather than blockers.
Co-authored-by: h_east <[email protected]>
…bg was not blended when popup had no bgcolor set
I was planning to do the same modification for the pum in another PR so the behavior should be the same at the end.
Fixed: bold, underline,… attributes are keep even if no colors are set.
The GUI result was ok, I've just added a comment, while testing this I found another asymmetry for the background color that needed a fix for the gui branch.
Fixed: I'm calculating now the fallback_bg_rgb once in the cterm branch. |
Problem: When using popup with a highlight group without background color set, and opacity set between 1 and 99 the blending fail and the popup is completely transparent.
I'm expecting a fadeout toward the underlying background color.
it occurs when popup highlight or highlights option are set to a group:
Moreover in the case ctermfg and guifg are not set, the underlying text color bleed on the popup text if this one does not have a color attribute (see the$${\color{cyan}OV\color{black}E\color{green}RANDABO\color{black}V\color{pink}E}$$ text in the screenshots)
Before this patch:

After this patch:

Since gui and cterm code are separate, I wanted to add similar screendump for gui but it works only for terminal, is there any way to do this kind of test for gvim ?
As the blocs guarded by
if (popup_attr > HL_ALL)are not conditional any more, to ease the review on github, I've removed the bloc brackets and reindent in a separate commit.To test it:
open a vim file containing
source it:
:source