Merge pull request #9923 from bfredl/floatblend

blending of floating windows, override individual attributes with ":hi Group blend="
This commit is contained in:
Björn Linse 2019-06-25 18:36:07 +02:00 committed by GitHub
commit 788bcbba24
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 366 additions and 36 deletions

View File

@ -4513,6 +4513,13 @@ A jump table for the options with a short description can be found at |Q_op|.
the range of 0 for fully opaque popupmenu (disabled) to 100 for fully the range of 0 for fully opaque popupmenu (disabled) to 100 for fully
transparent background. Values between 0-30 are typically most useful. transparent background. Values between 0-30 are typically most useful.
It is possible to override the level for individual highlights within
the popupmenu using |highlight-blend|. For instance, to enable
transparency but force the current selected element to be fully opaque: >
:set pumblend=15
:hi PmenuSel blend=0
<
UI-dependent. Works best with RGB colors. 'termguicolors' UI-dependent. Works best with RGB colors. 'termguicolors'
*'pyxversion'* *'pyx'* *'pyxversion'* *'pyx'*
@ -6693,6 +6700,15 @@ A jump table for the options with a short description can be found at |Q_op|.
key is never used for the menu. key is never used for the menu.
This option is not used for <F10>; on Win32. This option is not used for <F10>; on Win32.
*'winblend'* *'winbl'*
'winblend' 'winbl' number (default 0)
local to window
Enables pseudo-transparency for a floating window. Valid values are in
the range of 0 for fully opaque window (disabled) to 100 for fully
transparent background. Values between 0-30 are typically most useful.
UI-dependent. Works best with RGB colors. 'termguicolors'
*'window'* *'wi'* *'window'* *'wi'*
'window' 'wi' number (default screen height - 1) 'window' 'wi' number (default screen height - 1)
global global

View File

@ -4879,6 +4879,11 @@ guisp={color-name} *highlight-guisp*
All values are hexadecimal, range from "00" to "ff". Examples: > All values are hexadecimal, range from "00" to "ff". Examples: >
:highlight Comment guifg=#11f0c3 guibg=#ff00ff :highlight Comment guifg=#11f0c3 guibg=#ff00ff
< <
blend={integer} *highlight-blend*
Override the blend level for a highlight group within the popupmenu
or floating windows. Only takes effect if 'pumblend' or 'winblend'
is set for the menu or window. See the help at the respective option.
*highlight-groups* *highlight-default* *highlight-groups* *highlight-default*
These are the builtin highlighting groups. Note that the highlighting depends These are the builtin highlighting groups. Note that the highlighting depends
on the value of 'background'. You can see the current settings with the on the value of 'background'. You can see the current settings with the

View File

@ -30,6 +30,7 @@
#include "nvim/memline.h" #include "nvim/memline.h"
#include "nvim/memory.h" #include "nvim/memory.h"
#include "nvim/message.h" #include "nvim/message.h"
#include "nvim/popupmnu.h"
#include "nvim/edit.h" #include "nvim/edit.h"
#include "nvim/eval.h" #include "nvim/eval.h"
#include "nvim/eval/typval.h" #include "nvim/eval/typval.h"
@ -2239,16 +2240,33 @@ void nvim_select_popupmenu_item(Integer item, Boolean insert, Boolean finish,
} }
/// NB: if your UI doesn't use hlstate, this will not return hlstate first time /// NB: if your UI doesn't use hlstate, this will not return hlstate first time
Array nvim__inspect_cell(Integer row, Integer col, Error *err) Array nvim__inspect_cell(Integer grid, Integer row, Integer col, Error *err)
{ {
Array ret = ARRAY_DICT_INIT; Array ret = ARRAY_DICT_INIT;
if (row < 0 || row >= default_grid.Rows
|| col < 0 || col >= default_grid.Columns) { // TODO(bfredl): if grid == 0 we should read from the compositor's buffer.
// The only problem is that it does not yet exist.
ScreenGrid *g = &default_grid;
if (grid == pum_grid.handle) {
g = &pum_grid;
} else if (grid > 1) {
win_T *wp = get_win_by_grid_handle((handle_T)grid);
if (wp != NULL && wp->w_grid.chars != NULL) {
g = &wp->w_grid;
} else {
api_set_error(err, kErrorTypeValidation,
"No grid with the given handle");
return ret; return ret;
} }
size_t off = default_grid.line_offset[(size_t)row] + (size_t)col; }
ADD(ret, STRING_OBJ(cstr_to_string((char *)default_grid.chars[off])));
int attr = default_grid.attrs[off]; if (row < 0 || row >= g->Rows
|| col < 0 || col >= g->Columns) {
return ret;
}
size_t off = g->line_offset[(size_t)row] + (size_t)col;
ADD(ret, STRING_OBJ(cstr_to_string((char *)g->chars[off])));
int attr = g->attrs[off];
ADD(ret, DICTIONARY_OBJ(hl_get_attr_by_id(attr, true, err))); ADD(ret, DICTIONARY_OBJ(hl_get_attr_by_id(attr, true, err)));
// will not work first time // will not work first time
if (!highlight_use_hlstate()) { if (!highlight_use_hlstate()) {

View File

@ -252,6 +252,8 @@ typedef struct {
# define w_p_fcs w_onebuf_opt.wo_fcs // 'fillchars' # define w_p_fcs w_onebuf_opt.wo_fcs // 'fillchars'
char_u *wo_lcs; char_u *wo_lcs;
# define w_p_lcs w_onebuf_opt.wo_lcs // 'listchars' # define w_p_lcs w_onebuf_opt.wo_lcs // 'listchars'
long wo_winbl;
# define w_p_winbl w_onebuf_opt.wo_winbl // 'winblend'
LastSet wo_scriptID[WV_COUNT]; // SIDs for window-local options LastSet wo_scriptID[WV_COUNT]; // SIDs for window-local options
# define w_p_scriptID w_onebuf_opt.wo_scriptID # define w_p_scriptID w_onebuf_opt.wo_scriptID

View File

@ -756,9 +756,11 @@ EXTERN bool KeyTyped; // true if user typed current char
EXTERN int KeyStuffed; // TRUE if current char from stuffbuf EXTERN int KeyStuffed; // TRUE if current char from stuffbuf
EXTERN int maptick INIT(= 0); // tick for each non-mapped char EXTERN int maptick INIT(= 0); // tick for each non-mapped char
EXTERN int must_redraw INIT(= 0); /* type of redraw necessary */ EXTERN int must_redraw INIT(= 0); // type of redraw necessary
EXTERN int skip_redraw INIT(= FALSE); /* skip redraw once */ EXTERN bool skip_redraw INIT(= false); // skip redraw once
EXTERN int do_redraw INIT(= FALSE); /* extra redraw once */ EXTERN bool do_redraw INIT(= false); // extra redraw once
EXTERN bool must_redraw_pum INIT(= false); // redraw pum. NB: must_redraw
// should also be set.
EXTERN int need_highlight_changed INIT(= true); EXTERN int need_highlight_changed INIT(= true);

View File

@ -54,6 +54,9 @@ typedef struct {
int row_offset; int row_offset;
int col_offset; int col_offset;
// whether the compositor should blend the grid with the background grid
bool blending;
// state owned by the compositor. // state owned by the compositor.
int comp_row; int comp_row;
int comp_col; int comp_col;
@ -61,7 +64,7 @@ typedef struct {
bool comp_disabled; bool comp_disabled;
} ScreenGrid; } ScreenGrid;
#define SCREEN_GRID_INIT { 0, NULL, NULL, NULL, NULL, 0, 0, false, 0, 0, 0, \ #define SCREEN_GRID_INIT { 0, NULL, NULL, NULL, NULL, 0, 0, false, 0, 0, \
0, 0, false } false, 0, 0, 0, false }
#endif // NVIM_GRID_DEFS_H #endif // NVIM_GRID_DEFS_H

View File

@ -7,6 +7,7 @@
#include "nvim/highlight.h" #include "nvim/highlight.h"
#include "nvim/highlight_defs.h" #include "nvim/highlight_defs.h"
#include "nvim/map.h" #include "nvim/map.h"
#include "nvim/popupmnu.h"
#include "nvim/screen.h" #include "nvim/screen.h"
#include "nvim/syntax.h" #include "nvim/syntax.h"
#include "nvim/ui.h" #include "nvim/ui.h"
@ -145,6 +146,16 @@ int hl_get_ui_attr(int idx, int final_id, bool optional)
attrs = syn_attr2entry(syn_attr); attrs = syn_attr2entry(syn_attr);
available = true; available = true;
} }
if (HLF_PNI <= idx && idx <= HLF_PST) {
if (attrs.hl_blend == -1 && p_pb > 0) {
attrs.hl_blend = (int)p_pb;
}
if (pum_drawn()) {
must_redraw_pum = true;
}
}
if (optional && !available) { if (optional && !available) {
return 0; return 0;
} }
@ -159,20 +170,35 @@ void update_window_hl(win_T *wp, bool invalid)
} }
wp->w_hl_needs_update = false; wp->w_hl_needs_update = false;
// If a floating window is blending it always have a named
// wp->w_hl_attr_normal group. HL_ATTR(HLF_NFLOAT) is always named.
bool has_blend = wp->w_floating && wp->w_p_winbl != 0;
// determine window specific background set in 'winhighlight' // determine window specific background set in 'winhighlight'
bool float_win = wp->w_floating && !wp->w_float_config.external; bool float_win = wp->w_floating && !wp->w_float_config.external;
if (wp != curwin && wp->w_hl_ids[HLF_INACTIVE] > 0) { if (wp != curwin && wp->w_hl_ids[HLF_INACTIVE] > 0) {
wp->w_hl_attr_normal = hl_get_ui_attr(HLF_INACTIVE, wp->w_hl_attr_normal = hl_get_ui_attr(HLF_INACTIVE,
wp->w_hl_ids[HLF_INACTIVE], true); wp->w_hl_ids[HLF_INACTIVE],
!has_blend);
} else if (float_win && wp->w_hl_ids[HLF_NFLOAT] > 0) { } else if (float_win && wp->w_hl_ids[HLF_NFLOAT] > 0) {
wp->w_hl_attr_normal = hl_get_ui_attr(HLF_NFLOAT, wp->w_hl_attr_normal = hl_get_ui_attr(HLF_NFLOAT,
wp->w_hl_ids[HLF_NFLOAT], true); // 'cursorline'
wp->w_hl_ids[HLF_NFLOAT], !has_blend);
} else if (wp->w_hl_id_normal > 0) { } else if (wp->w_hl_id_normal > 0) {
wp->w_hl_attr_normal = hl_get_ui_attr(-1, wp->w_hl_id_normal, true); wp->w_hl_attr_normal = hl_get_ui_attr(-1, wp->w_hl_id_normal, !has_blend);
} else { } else {
wp->w_hl_attr_normal = float_win ? HL_ATTR(HLF_NFLOAT) : 0; wp->w_hl_attr_normal = float_win ? HL_ATTR(HLF_NFLOAT) : 0;
} }
// if blend= attribute is not set, 'winblend' value overrides it.
if (wp->w_floating && wp->w_p_winbl > 0) {
HlEntry entry = kv_A(attr_entries, wp->w_hl_attr_normal);
if (entry.attr.hl_blend == -1) {
entry.attr.hl_blend = (int)wp->w_p_winbl;
wp->w_hl_attr_normal = get_attr_entry(entry);
}
}
if (wp != curwin) { if (wp != curwin) {
wp->w_hl_attr_normal = hl_combine_attr(HL_ATTR(HLF_INACTIVE), wp->w_hl_attr_normal = hl_combine_attr(HL_ATTR(HLF_INACTIVE),
wp->w_hl_attr_normal); wp->w_hl_attr_normal);
@ -240,6 +266,8 @@ void hl_invalidate_blends(void)
{ {
map_clear(int, int)(blend_attr_entries); map_clear(int, int)(blend_attr_entries);
map_clear(int, int)(blendthrough_attr_entries); map_clear(int, int)(blendthrough_attr_entries);
highlight_changed();
update_window_hl(curwin, true);
} }
// Combine special attributes (e.g., for spelling) with other attributes // Combine special attributes (e.g., for spelling) with other attributes
@ -292,6 +320,10 @@ int hl_combine_attr(int char_attr, int prim_attr)
new_en.rgb_sp_color = spell_aep.rgb_sp_color; new_en.rgb_sp_color = spell_aep.rgb_sp_color;
} }
if (spell_aep.hl_blend >= 0) {
new_en.hl_blend = spell_aep.hl_blend;
}
id = get_attr_entry((HlEntry){ .attr = new_en, .kind = kHlCombine, id = get_attr_entry((HlEntry){ .attr = new_en, .kind = kHlCombine,
.id1 = char_attr, .id2 = prim_attr }); .id1 = char_attr, .id2 = prim_attr });
if (id > 0) { if (id > 0) {
@ -336,50 +368,59 @@ static HlAttrs get_colors_force(int attr)
/// This is called per-cell, so cache the result. /// This is called per-cell, so cache the result.
/// ///
/// @return the resulting attributes. /// @return the resulting attributes.
int hl_blend_attrs(int back_attr, int front_attr, bool through) int hl_blend_attrs(int back_attr, int front_attr, bool *through)
{ {
HlAttrs fattrs = get_colors_force(front_attr);
int ratio = fattrs.hl_blend;
if (ratio <= 0) {
*through = false;
return front_attr;
}
int combine_tag = (back_attr << 16) + front_attr; int combine_tag = (back_attr << 16) + front_attr;
Map(int, int) *map = through ? blendthrough_attr_entries : blend_attr_entries; Map(int, int) *map = (*through
? blendthrough_attr_entries
: blend_attr_entries);
int id = map_get(int, int)(map, combine_tag); int id = map_get(int, int)(map, combine_tag);
if (id > 0) { if (id > 0) {
return id; return id;
} }
HlAttrs battrs = get_colors_force(back_attr); HlAttrs battrs = get_colors_force(back_attr);
HlAttrs fattrs = get_colors_force(front_attr);
HlAttrs cattrs; HlAttrs cattrs;
if (through) {
if (*through) {
cattrs = battrs; cattrs = battrs;
cattrs.rgb_fg_color = rgb_blend((int)p_pb, battrs.rgb_fg_color, cattrs.rgb_fg_color = rgb_blend(ratio, battrs.rgb_fg_color,
fattrs.rgb_bg_color); fattrs.rgb_bg_color);
if (cattrs.rgb_ae_attr & (HL_UNDERLINE|HL_UNDERCURL)) { if (cattrs.rgb_ae_attr & (HL_UNDERLINE|HL_UNDERCURL)) {
cattrs.rgb_sp_color = rgb_blend((int)p_pb, battrs.rgb_sp_color, cattrs.rgb_sp_color = rgb_blend(ratio, battrs.rgb_sp_color,
fattrs.rgb_bg_color); fattrs.rgb_bg_color);
} else { } else {
cattrs.rgb_sp_color = -1; cattrs.rgb_sp_color = -1;
} }
cattrs.cterm_bg_color = fattrs.cterm_bg_color; cattrs.cterm_bg_color = fattrs.cterm_bg_color;
cattrs.cterm_fg_color = cterm_blend((int)p_pb, battrs.cterm_fg_color, cattrs.cterm_fg_color = cterm_blend(ratio, battrs.cterm_fg_color,
fattrs.cterm_bg_color); fattrs.cterm_bg_color);
} else { } else {
cattrs = fattrs; cattrs = fattrs;
if (p_pb >= 50) { if (ratio >= 50) {
cattrs.rgb_ae_attr |= battrs.rgb_ae_attr; cattrs.rgb_ae_attr |= battrs.rgb_ae_attr;
} }
cattrs.rgb_fg_color = rgb_blend((int)p_pb/2, battrs.rgb_fg_color, cattrs.rgb_fg_color = rgb_blend(ratio/2, battrs.rgb_fg_color,
fattrs.rgb_fg_color); fattrs.rgb_fg_color);
if (cattrs.rgb_ae_attr & (HL_UNDERLINE|HL_UNDERCURL)) { if (cattrs.rgb_ae_attr & (HL_UNDERLINE|HL_UNDERCURL)) {
cattrs.rgb_sp_color = rgb_blend((int)p_pb/2, battrs.rgb_bg_color, cattrs.rgb_sp_color = rgb_blend(ratio/2, battrs.rgb_bg_color,
fattrs.rgb_sp_color); fattrs.rgb_sp_color);
} else { } else {
cattrs.rgb_sp_color = -1; cattrs.rgb_sp_color = -1;
} }
} }
cattrs.rgb_bg_color = rgb_blend((int)p_pb, battrs.rgb_bg_color, cattrs.rgb_bg_color = rgb_blend(ratio, battrs.rgb_bg_color,
fattrs.rgb_bg_color); fattrs.rgb_bg_color);
HlKind kind = through ? kHlBlendThrough : kHlBlend; HlKind kind = *through ? kHlBlendThrough : kHlBlend;
id = get_attr_entry((HlEntry){ .attr = cattrs, .kind = kind, id = get_attr_entry((HlEntry){ .attr = cattrs, .kind = kind,
.id1 = back_attr, .id2 = front_attr }); .id1 = back_attr, .id2 = front_attr });
if (id > 0) { if (id > 0) {

View File

@ -25,6 +25,7 @@ typedef struct attr_entry {
int16_t rgb_ae_attr, cterm_ae_attr; ///< HlAttrFlags int16_t rgb_ae_attr, cterm_ae_attr; ///< HlAttrFlags
RgbValue rgb_fg_color, rgb_bg_color, rgb_sp_color; RgbValue rgb_fg_color, rgb_bg_color, rgb_sp_color;
int cterm_fg_color, cterm_bg_color; int cterm_fg_color, cterm_bg_color;
int hl_blend;
} HlAttrs; } HlAttrs;
#define HLATTRS_INIT (HlAttrs) { \ #define HLATTRS_INIT (HlAttrs) { \

View File

@ -74,6 +74,7 @@
#include "nvim/strings.h" #include "nvim/strings.h"
#include "nvim/syntax.h" #include "nvim/syntax.h"
#include "nvim/ui.h" #include "nvim/ui.h"
#include "nvim/ui_compositor.h"
#include "nvim/undo.h" #include "nvim/undo.h"
#include "nvim/window.h" #include "nvim/window.h"
#include "nvim/os/os.h" #include "nvim/os/os.h"
@ -4391,11 +4392,10 @@ static char *set_num_option(int opt_idx, char_u *varp, long value,
} }
} else if (pp == &p_pb) { } else if (pp == &p_pb) {
p_pb = MAX(MIN(p_pb, 100), 0); p_pb = MAX(MIN(p_pb, 100), 0);
if (old_value != 0) {
hl_invalidate_blends(); hl_invalidate_blends();
} pum_grid.blending = (p_pb > 0);
if (pum_drawn()) { if (pum_drawn()) {
pum_recompose(); pum_redraw();
} }
} else if (pp == &p_pyx) { } else if (pp == &p_pyx) {
if (p_pyx != 0 && p_pyx != 2 && p_pyx != 3) { if (p_pyx != 0 && p_pyx != 2 && p_pyx != 3) {
@ -4418,6 +4418,11 @@ static char *set_num_option(int opt_idx, char_u *varp, long value,
} }
} else if (pp == &curwin->w_p_nuw) { } else if (pp == &curwin->w_p_nuw) {
curwin->w_nrwidth_line_count = 0; curwin->w_nrwidth_line_count = 0;
} else if (pp == &curwin->w_p_winbl && value != old_value) {
// 'floatblend'
curwin->w_p_winbl = MAX(MIN(curwin->w_p_winbl, 100), 0);
curwin->w_hl_needs_update = true;
curwin->w_grid.blending = curwin->w_p_winbl > 0;
} }
@ -5713,6 +5718,7 @@ static char_u *get_varp(vimoption_T *p)
case PV_WINHL: return (char_u *)&(curwin->w_p_winhl); case PV_WINHL: return (char_u *)&(curwin->w_p_winhl);
case PV_FCS: return (char_u *)&(curwin->w_p_fcs); case PV_FCS: return (char_u *)&(curwin->w_p_fcs);
case PV_LCS: return (char_u *)&(curwin->w_p_lcs); case PV_LCS: return (char_u *)&(curwin->w_p_lcs);
case PV_WINBL: return (char_u *)&(curwin->w_p_winbl);
default: IEMSG(_("E356: get_varp ERROR")); default: IEMSG(_("E356: get_varp ERROR"));
} }
// always return a valid pointer to avoid a crash! // always return a valid pointer to avoid a crash!
@ -5792,6 +5798,7 @@ void copy_winopt(winopt_T *from, winopt_T *to)
to->wo_winhl = vim_strsave(from->wo_winhl); to->wo_winhl = vim_strsave(from->wo_winhl);
to->wo_fcs = vim_strsave(from->wo_fcs); to->wo_fcs = vim_strsave(from->wo_fcs);
to->wo_lcs = vim_strsave(from->wo_lcs); to->wo_lcs = vim_strsave(from->wo_lcs);
to->wo_winbl = from->wo_winbl;
check_winopt(to); // don't want NULL pointers check_winopt(to); // don't want NULL pointers
} }
@ -5854,7 +5861,8 @@ void didset_window_options(win_T *wp)
briopt_check(wp); briopt_check(wp);
set_chars_option(wp, &wp->w_p_fcs); set_chars_option(wp, &wp->w_p_fcs);
set_chars_option(wp, &wp->w_p_lcs); set_chars_option(wp, &wp->w_p_lcs);
parse_winhl_opt(wp); parse_winhl_opt(wp); // sets w_hl_needs_update also for w_p_winbl
wp->w_grid.blending = wp->w_p_winbl > 0;
} }

View File

@ -816,6 +816,7 @@ enum {
, WV_WINHL , WV_WINHL
, WV_FCS , WV_FCS
, WV_LCS , WV_LCS
, WV_WINBL
, WV_COUNT // must be the last one , WV_COUNT // must be the last one
}; };

View File

@ -2761,6 +2761,13 @@ return {
varname='p_wak', varname='p_wak',
defaults={if_true={vi="menu"}} defaults={if_true={vi="menu"}}
}, },
{
full_name='winblend', abbreviation='winbl',
type='number', scope={'window'},
vi_def=true,
redraw={'current_window'},
defaults={if_true={vi=0}}
},
{ {
full_name='winhighlight', abbreviation='winhl', full_name='winhighlight', abbreviation='winhl',
type='string', scope={'window'}, type='string', scope={'window'},

View File

@ -376,6 +376,7 @@ void pum_redraw(void)
pum_height, grid_width, false, true); pum_height, grid_width, false, true);
bool invalid_grid = moved || pum_invalid; bool invalid_grid = moved || pum_invalid;
pum_invalid = false; pum_invalid = false;
must_redraw_pum = false;
if (!pum_grid.chars if (!pum_grid.chars
|| pum_grid.Rows != pum_height || pum_grid.Columns != grid_width) { || pum_grid.Rows != pum_height || pum_grid.Columns != grid_width) {
@ -790,6 +791,7 @@ void pum_undisplay(bool immediate)
{ {
pum_is_visible = false; pum_is_visible = false;
pum_array = NULL; pum_array = NULL;
must_redraw_pum = false;
if (immediate) { if (immediate) {
pum_check_clear(); pum_check_clear();

View File

@ -482,13 +482,13 @@ void update_screen(int type)
} }
end_search_hl(); end_search_hl();
// May need to redraw the popup menu. // May need to redraw the popup menu.
if (pum_drawn() && redraw_popupmenu) { if (pum_drawn() && must_redraw_pum) {
pum_redraw(); pum_redraw();
} }
send_grid_resize = false; send_grid_resize = false;
redraw_popupmenu = false;
/* Reset b_mod_set flags. Going through all windows is probably faster /* Reset b_mod_set flags. Going through all windows is probably faster
* than going through all buffers (there could be many buffers). */ * than going through all buffers (there could be many buffers). */

View File

@ -75,6 +75,8 @@ struct hl_group {
uint8_t *sg_rgb_fg_name; ///< RGB foreground color name uint8_t *sg_rgb_fg_name; ///< RGB foreground color name
uint8_t *sg_rgb_bg_name; ///< RGB background color name uint8_t *sg_rgb_bg_name; ///< RGB background color name
uint8_t *sg_rgb_sp_name; ///< RGB special color name uint8_t *sg_rgb_sp_name; ///< RGB special color name
int sg_blend; ///< blend level (0-100 inclusive), -1 if unset
}; };
/// \addtogroup SG_SET /// \addtogroup SG_SET
@ -6879,6 +6881,12 @@ void do_highlight(const char *line, const bool forceit, const bool init)
} }
} else if (strcmp(key, "START") == 0 || strcmp(key, "STOP") == 0) { } else if (strcmp(key, "START") == 0 || strcmp(key, "STOP") == 0) {
// Ignored for now // Ignored for now
} else if (strcmp(key, "BLEND") == 0) {
if (strcmp(arg, "NONE") != 0) {
HL_TABLE()[idx].sg_blend = strtol(arg, NULL, 10);
} else {
HL_TABLE()[idx].sg_blend = -1;
}
} else { } else {
emsgf(_("E423: Illegal argument: %s"), key_start); emsgf(_("E423: Illegal argument: %s"), key_start);
error = true; error = true;
@ -6993,6 +7001,7 @@ static void highlight_clear(int idx)
XFREE_CLEAR(HL_TABLE()[idx].sg_rgb_fg_name); XFREE_CLEAR(HL_TABLE()[idx].sg_rgb_fg_name);
XFREE_CLEAR(HL_TABLE()[idx].sg_rgb_bg_name); XFREE_CLEAR(HL_TABLE()[idx].sg_rgb_bg_name);
XFREE_CLEAR(HL_TABLE()[idx].sg_rgb_sp_name); XFREE_CLEAR(HL_TABLE()[idx].sg_rgb_sp_name);
HL_TABLE()[idx].sg_blend = -1;
// Clear the script ID only when there is no link, since that is not // Clear the script ID only when there is no link, since that is not
// cleared. // cleared.
if (HL_TABLE()[idx].sg_link == 0) { if (HL_TABLE()[idx].sg_link == 0) {
@ -7029,6 +7038,9 @@ static void highlight_list_one(const int id)
didh = highlight_list_arg(id, didh, LIST_STRING, didh = highlight_list_arg(id, didh, LIST_STRING,
0, sgp->sg_rgb_sp_name, "guisp"); 0, sgp->sg_rgb_sp_name, "guisp");
didh = highlight_list_arg(id, didh, LIST_INT,
sgp->sg_blend+1, NULL, "blend");
if (sgp->sg_link && !got_int) { if (sgp->sg_link && !got_int) {
(void)syn_list_header(didh, 9999, id); (void)syn_list_header(didh, 9999, id);
didh = true; didh = true;
@ -7252,6 +7264,7 @@ static void set_hl_attr(int idx)
at_en.rgb_fg_color = sgp->sg_rgb_fg_name ? sgp->sg_rgb_fg : -1; at_en.rgb_fg_color = sgp->sg_rgb_fg_name ? sgp->sg_rgb_fg : -1;
at_en.rgb_bg_color = sgp->sg_rgb_bg_name ? sgp->sg_rgb_bg : -1; at_en.rgb_bg_color = sgp->sg_rgb_bg_name ? sgp->sg_rgb_bg : -1;
at_en.rgb_sp_color = sgp->sg_rgb_sp_name ? sgp->sg_rgb_sp : -1; at_en.rgb_sp_color = sgp->sg_rgb_sp_name ? sgp->sg_rgb_sp : -1;
at_en.hl_blend = sgp->sg_blend;
sgp->sg_attr = hl_get_syn_attr(idx+1, at_en); sgp->sg_attr = hl_get_syn_attr(idx+1, at_en);
@ -7377,6 +7390,7 @@ static int syn_add_group(char_u *name)
hlgp->sg_rgb_bg = -1; hlgp->sg_rgb_bg = -1;
hlgp->sg_rgb_fg = -1; hlgp->sg_rgb_fg = -1;
hlgp->sg_rgb_sp = -1; hlgp->sg_rgb_sp = -1;
hlgp->sg_blend = -1;
hlgp->sg_name_u = vim_strsave_up(name); hlgp->sg_name_u = vim_strsave_up(name);
return highlight_ga.ga_len; /* ID is index plus one */ return highlight_ga.ga_len; /* ID is index plus one */

View File

@ -330,10 +330,10 @@ static void compose_line(Integer row, Integer startcol, Integer endcol,
memcpy(attrbuf+(col-startcol), grid->attrs+off, n * sizeof(*attrbuf)); memcpy(attrbuf+(col-startcol), grid->attrs+off, n * sizeof(*attrbuf));
// 'pumblend' // 'pumblend'
if (grid == &pum_grid && p_pb) { if (grid->blending) {
for (int i = col-(int)startcol; i < until-startcol; i++) { for (int i = col-(int)startcol; i < until-startcol; i++) {
bool thru = strequal((char *)linebuf[i], " "); // negative space bool thru = strequal((char *)linebuf[i], " "); // negative space
attrbuf[i] = (sattr_T)hl_blend_attrs(bg_attrs[i], attrbuf[i], thru); attrbuf[i] = (sattr_T)hl_blend_attrs(bg_attrs[i], attrbuf[i], &thru);
if (thru) { if (thru) {
memcpy(linebuf[i], bg_line[i], sizeof(linebuf[i])); memcpy(linebuf[i], bg_line[i], sizeof(linebuf[i]));
} }
@ -419,7 +419,7 @@ static void ui_comp_raw_line(UI *ui, Integer grid, Integer row,
assert(clearcol <= default_grid.Columns); assert(clearcol <= default_grid.Columns);
if (flags & kLineFlagInvalid if (flags & kLineFlagInvalid
|| kv_size(layers) > curgrid->comp_index+1 || kv_size(layers) > curgrid->comp_index+1
|| (p_pb && curgrid == &pum_grid)) { || curgrid->blending) {
compose_line(row, startcol, clearcol, flags); compose_line(row, startcol, clearcol, flags);
} else { } else {
ui_composed_call_raw_line(1, row, startcol, endcol, clearcol, clearattr, ui_composed_call_raw_line(1, row, startcol, endcol, clearcol, clearattr,

View File

@ -3764,6 +3764,196 @@ describe('floating windows', function()
end end
end) end)
end) end)
it("'winblend' option", function()
screen:try_resize(50,9)
screen:set_default_attr_ids({
[1] = {background = Screen.colors.LightMagenta},
[2] = {foreground = Screen.colors.Grey0, background = tonumber('0xffcfff')},
[3] = {foreground = tonumber('0xb282b2'), background = tonumber('0xffcfff')},
[4] = {foreground = Screen.colors.Red, background = Screen.colors.LightMagenta},
[5] = {foreground = tonumber('0x990000'), background = tonumber('0xfff1ff')},
[6] = {foreground = tonumber('0x332533'), background = tonumber('0xfff1ff')},
})
insert([[
Lorem ipsum dolor sit amet, consectetur
adipisicing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud
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
occaecat cupidatat non proident, sunt in culpa
qui officia deserunt mollit anim id est
laborum.]])
local buf = meths.create_buf(false,false)
meths.buf_set_lines(buf, 0, -1, true, {"test", "", "popup text"})
local win = meths.open_win(buf, false, {relative='editor', width=15, height=3, row=2, col=5})
if multigrid then
screen:expect{grid=[[
## grid 1
[2:--------------------------------------------------]|
[2:--------------------------------------------------]|
[2:--------------------------------------------------]|
[2:--------------------------------------------------]|
[2:--------------------------------------------------]|
[2:--------------------------------------------------]|
[2:--------------------------------------------------]|
[2:--------------------------------------------------]|
|
## grid 2
Ut enim ad minim veniam, quis nostrud |
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 |
occaecat cupidatat non proident, sunt in culpa |
qui officia deserunt mollit anim id est |
laborum^. |
## grid 4
{1:test }|
{1: }|
{1:popup text }|
]], float_pos={[4] = {{id = 1002}, "NW", 1, 2, 5, true}}}
else
screen:expect([[
Ut enim ad minim veniam, quis nostrud |
exercitation ullamco laboris nisi ut aliquip ex |
ea co{1:test }. Duis aute irure dolor in |
repre{1: }uptate velit esse cillum |
dolor{1:popup text }la pariatur. Excepteur sint |
occaecat cupidatat non proident, sunt in culpa |
qui officia deserunt mollit anim id est |
laborum^. |
|
]])
end
meths.win_set_option(win, "winblend", 30)
if multigrid then
screen:expect{grid=[[
## grid 1
[2:--------------------------------------------------]|
[2:--------------------------------------------------]|
[2:--------------------------------------------------]|
[2:--------------------------------------------------]|
[2:--------------------------------------------------]|
[2:--------------------------------------------------]|
[2:--------------------------------------------------]|
[2:--------------------------------------------------]|
|
## grid 2
Ut enim ad minim veniam, quis nostrud |
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 |
occaecat cupidatat non proident, sunt in culpa |
qui officia deserunt mollit anim id est |
laborum^. |
## grid 4
{1:test }|
{1: }|
{1:popup text }|
]], float_pos={[4] = {{id = 1002}, "NW", 1, 2, 5, true}}, unchanged=true}
else
screen:expect([[
Ut enim ad minim veniam, quis nostrud |
exercitation ullamco laboris nisi ut aliquip ex |
ea co{2:test}{3:o consequat}. Duis aute irure dolor in |
repre{3:henderit in vol}uptate velit esse cillum |
dolor{2:popup}{3:fugi}{2:text}{3:ul}la pariatur. Excepteur sint |
occaecat cupidatat non proident, sunt in culpa |
qui officia deserunt mollit anim id est |
laborum^. |
|
]])
end
command('hi SpecialRegion guifg=Red blend=0')
meths.buf_add_highlight(buf, -1, "SpecialRegion", 2, 0, -1)
if multigrid then
screen:expect{grid=[[
## grid 1
[2:--------------------------------------------------]|
[2:--------------------------------------------------]|
[2:--------------------------------------------------]|
[2:--------------------------------------------------]|
[2:--------------------------------------------------]|
[2:--------------------------------------------------]|
[2:--------------------------------------------------]|
[2:--------------------------------------------------]|
|
## grid 2
Ut enim ad minim veniam, quis nostrud |
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 |
occaecat cupidatat non proident, sunt in culpa |
qui officia deserunt mollit anim id est |
laborum^. |
## grid 4
{1:test }|
{1: }|
{4:popup text}{1: }|
]], float_pos={[4] = {{id = 1002}, "NW", 1, 2, 5, true}}}
else
screen:expect([[
Ut enim ad minim veniam, quis nostrud |
exercitation ullamco laboris nisi ut aliquip ex |
ea co{2:test}{3:o consequat}. Duis aute irure dolor in |
repre{3:henderit in vol}uptate velit esse cillum |
dolor{4:popup text}{3:ul}la pariatur. Excepteur sint |
occaecat cupidatat non proident, sunt in culpa |
qui officia deserunt mollit anim id est |
laborum^. |
|
]])
end
command('hi SpecialRegion guifg=Red blend=80')
if multigrid then
screen:expect{grid=[[
## grid 1
[2:--------------------------------------------------]|
[2:--------------------------------------------------]|
[2:--------------------------------------------------]|
[2:--------------------------------------------------]|
[2:--------------------------------------------------]|
[2:--------------------------------------------------]|
[2:--------------------------------------------------]|
[2:--------------------------------------------------]|
|
## grid 2
Ut enim ad minim veniam, quis nostrud |
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 |
occaecat cupidatat non proident, sunt in culpa |
qui officia deserunt mollit anim id est |
laborum^. |
## grid 4
{1:test }|
{1: }|
{4:popup text}{1: }|
]], float_pos={[4] = {{id = 1002}, "NW", 1, 2, 5, true}}, unchanged=true}
else
screen:expect([[
Ut enim ad minim veniam, quis nostrud |
exercitation ullamco laboris nisi ut aliquip ex |
ea co{2:test}{3:o consequat}. Duis aute irure dolor in |
repre{3:henderit in vol}uptate velit esse cillum |
dolor{5:popup}{6:fugi}{5:text}{3:ul}la pariatur. Excepteur sint |
occaecat cupidatat non proident, sunt in culpa |
qui officia deserunt mollit anim id est |
laborum^. |
|
]])
end
end)
end end
describe('with ext_multigrid', function() describe('with ext_multigrid', function()

View File

@ -1662,6 +1662,26 @@ describe('builtin popupmenu', function()
{20:-- Keyword Local completion (^N^P) }{21:match 1 of 65} | {20:-- Keyword Local completion (^N^P) }{21:match 1 of 65} |
]]) ]])
-- can disable blending for indiviual attribute. For instance current
-- selected item. (also tests that `hi Pmenu*` take immediate effect)
command('hi PMenuSel blend=0')
screen:expect([[
Lorem ipsum d{1:ol}or sit amet, consectetur |
adipisicing elit, sed do eiusmod tempor |
bla bla incididunt^ |
incidid{22: incididunt }{27: }d{1:ol}ore magna aliqua. |
Ut enim{28: }{29:ut}{28: minim veniam}{25:,} quis nostrud |
exercit{28:a}{29:labore}{28:llamco la}{25:b}oris nisi ut aliquip ex |
{2:[No Nam}{30:e}{43:et}{30:[+] }{32: }{2: }|
incidid{28:u}{29:dol}{41:or}{29:e}{28:labore et}{25: }d{1:ol}ore magna aliqua. |
Ut enim{28: }{29:magna}{28:nim veniam}{25:,} quis nostrud |
exercit{28:a}{29:aliqua}{28:llamco la}{25:b}oris nisi {4:ut} aliquip ex |
ea comm{28:o}{29:Ut}{28: consequat. D}{25:u}is a{4:ut}e irure d{1:ol}or in |
reprehe{28:n}{29:enim}{28:t in v}{34:ol}{28:upt}{25:a}te v{3:el}it esse cillum |
{5:[No Nam}{38:e}{44:ad}{38:[+] }{40: }{5: }|
{20:-- Keyword Local completion (^N^P) }{21:match 1 of 65} |
]])
feed('<c-e>') feed('<c-e>')
screen:expect([[ screen:expect([[
Lorem ipsum d{1:ol}or sit amet, consectetur | Lorem ipsum d{1:ol}or sit amet, consectetur |