Skip to content

Commit c79edc0

Browse files
mattnchrisbra
authored andcommitted
patch 9.2.0319: popup: rendering issues with partially transparent popups
Problem: popup: rendering issues with partially transparent popups. Solution: Redraw the area under the old popup position on move or resize. Apply the background blend only to the covered half of a double-width character. (Yasuhiro Matsumoto) closes: #19881 Signed-off-by: Yasuhiro Matsumoto <[email protected]> Signed-off-by: Christian Brabandt <[email protected]>
1 parent 317351c commit c79edc0

2 files changed

Lines changed: 114 additions & 71 deletions

File tree

src/popupwin.c

Lines changed: 112 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ static void may_start_message_win_timer(win_T *wp);
4646
static int popup_on_cmdline = FALSE;
4747

4848
static void popup_adjust_position(win_T *wp);
49+
static void redraw_under_popup_area(int winrow, int wincol, int height,
50+
int width, int leftoff);
4951

5052
/*
5153
* Get option value for "key", which is "line" or "col".
@@ -3107,6 +3109,14 @@ f_popup_settext(typval_T *argvars, typval_T *rettv UNUSED)
31073109
{
31083110
int id;
31093111
win_T *wp;
3112+
#ifdef FEAT_PROP_POPUP
3113+
int old_popup_active;
3114+
#endif
3115+
int old_winrow;
3116+
int old_wincol;
3117+
int old_popup_height;
3118+
int old_popup_width;
3119+
int old_popup_leftoff;
31103120

31113121
if (in_vim9script()
31123122
&& (check_for_number_arg(argvars, 0) == FAIL
@@ -3118,6 +3128,16 @@ f_popup_settext(typval_T *argvars, typval_T *rettv UNUSED)
31183128
if (wp == NULL)
31193129
return;
31203130

3131+
#ifdef FEAT_PROP_POPUP
3132+
old_popup_active = (wp->w_popup_flags & POPF_OPACITY)
3133+
&& wp->w_popup_blend > 0;
3134+
#endif
3135+
old_winrow = wp->w_winrow;
3136+
old_wincol = wp->w_wincol;
3137+
old_popup_height = popup_height(wp);
3138+
old_popup_width = popup_width(wp);
3139+
old_popup_leftoff = wp->w_popup_leftoff;
3140+
31213141
if (check_for_string_or_list_arg(argvars, 1) == FAIL)
31223142
return;
31233143

@@ -3132,6 +3152,17 @@ f_popup_settext(typval_T *argvars, typval_T *rettv UNUSED)
31323152
if (must_redraw < UPD_VALID)
31333153
must_redraw = UPD_VALID;
31343154
popup_adjust_position(wp);
3155+
3156+
#ifdef FEAT_PROP_POPUP
3157+
if (old_popup_active
3158+
&& (old_winrow != wp->w_winrow
3159+
|| old_wincol != wp->w_wincol
3160+
|| old_popup_height != popup_height(wp)
3161+
|| old_popup_width != popup_width(wp)
3162+
|| old_popup_leftoff != wp->w_popup_leftoff))
3163+
redraw_under_popup_area(old_winrow, old_wincol,
3164+
old_popup_height, old_popup_width, old_popup_leftoff);
3165+
#endif
31353166
}
31363167

31373168
/*
@@ -3316,6 +3347,49 @@ close_all_popups(int force)
33163347
return;
33173348
}
33183349

3350+
/*
3351+
* Force windows under a popup area to redraw.
3352+
*/
3353+
static void
3354+
redraw_under_popup_area(int winrow, int wincol, int height, int width, int leftoff)
3355+
{
3356+
int r;
3357+
3358+
for (r = winrow; r < winrow + height && r < screen_Rows; ++r)
3359+
{
3360+
int c;
3361+
win_T *prev_twp = NULL;
3362+
3363+
if (r >= cmdline_row)
3364+
{
3365+
clear_cmdline = TRUE;
3366+
continue;
3367+
}
3368+
3369+
for (c = wincol; c < wincol + width - leftoff && c < screen_Columns; ++c)
3370+
{
3371+
int line_cp = r;
3372+
int col_cp = c;
3373+
win_T *twp;
3374+
3375+
twp = mouse_find_win(&line_cp, &col_cp, IGNORE_POPUP);
3376+
if (twp != NULL && twp != prev_twp)
3377+
{
3378+
prev_twp = twp;
3379+
if (line_cp < twp->w_height)
3380+
{
3381+
linenr_T lnum;
3382+
3383+
(void)mouse_comp_pos(twp, &line_cp, &col_cp, &lnum, NULL);
3384+
redrawWinline(twp, lnum);
3385+
}
3386+
else if (line_cp == twp->w_height)
3387+
twp->w_redr_status = TRUE;
3388+
}
3389+
}
3390+
}
3391+
}
3392+
33193393
/*
33203394
* popup_move({id}, {options})
33213395
*/
@@ -3329,6 +3403,9 @@ f_popup_move(typval_T *argvars, typval_T *rettv UNUSED)
33293403
int old_wincol;
33303404
int old_height;
33313405
int old_width;
3406+
int old_popup_height;
3407+
int old_popup_width;
3408+
int old_popup_leftoff;
33323409

33333410
if (in_vim9script()
33343411
&& (check_for_number_arg(argvars, 0) == FAIL
@@ -3349,6 +3426,9 @@ f_popup_move(typval_T *argvars, typval_T *rettv UNUSED)
33493426
old_wincol = wp->w_wincol;
33503427
old_height = wp->w_height;
33513428
old_width = wp->w_width;
3429+
old_popup_height = popup_height(wp);
3430+
old_popup_width = popup_width(wp);
3431+
old_popup_leftoff = wp->w_popup_leftoff;
33523432

33533433
apply_move_options(wp, dict);
33543434

@@ -3367,39 +3447,8 @@ f_popup_move(typval_T *argvars, typval_T *rettv UNUSED)
33673447
redraw_win_later(wp, UPD_NOT_VALID);
33683448

33693449
if ((wp->w_popup_flags & POPF_OPACITY) && wp->w_popup_blend > 0)
3370-
{
3371-
int total_h = old_height + popup_top_extra(wp)
3372-
+ wp->w_popup_border[2] + wp->w_popup_padding[2];
3373-
int row;
3374-
3375-
for (row = old_winrow;
3376-
row < old_winrow + total_h && row < screen_Rows; ++row)
3377-
{
3378-
if (row >= cmdline_row)
3379-
clear_cmdline = TRUE;
3380-
else
3381-
{
3382-
int line_cp = row;
3383-
int col_cp = old_wincol;
3384-
win_T *twp;
3385-
3386-
twp = mouse_find_win(&line_cp, &col_cp, IGNORE_POPUP);
3387-
if (twp != NULL)
3388-
{
3389-
if (line_cp >= twp->w_height)
3390-
twp->w_redr_status = TRUE;
3391-
else
3392-
{
3393-
linenr_T lnum;
3394-
3395-
(void)mouse_comp_pos(twp, &line_cp, &col_cp,
3396-
&lnum, NULL);
3397-
redrawWinline(twp, lnum);
3398-
}
3399-
}
3400-
}
3401-
}
3402-
}
3450+
redraw_under_popup_area(old_winrow, old_wincol,
3451+
old_popup_height, old_popup_width, old_popup_leftoff);
34033452
}
34043453
}
34053454

@@ -3415,7 +3464,13 @@ f_popup_setoptions(typval_T *argvars, typval_T *rettv UNUSED)
34153464
linenr_T old_firstline;
34163465
#ifdef FEAT_PROP_POPUP
34173466
int old_blend;
3467+
int old_popup_active;
34183468
#endif
3469+
int old_winrow;
3470+
int old_wincol;
3471+
int old_popup_height;
3472+
int old_popup_width;
3473+
int old_popup_leftoff;
34193474
int old_zindex;
34203475
int old_popup_flags;
34213476
char_u *old_scrollbar_highlight;
@@ -3441,7 +3496,14 @@ f_popup_setoptions(typval_T *argvars, typval_T *rettv UNUSED)
34413496
old_firstline = wp->w_firstline;
34423497
#ifdef FEAT_PROP_POPUP
34433498
old_blend = wp->w_popup_blend;
3499+
old_popup_active = (wp->w_popup_flags & POPF_OPACITY)
3500+
&& wp->w_popup_blend > 0;
34443501
#endif
3502+
old_winrow = wp->w_winrow;
3503+
old_wincol = wp->w_wincol;
3504+
old_popup_height = popup_height(wp);
3505+
old_popup_width = popup_width(wp);
3506+
old_popup_leftoff = wp->w_popup_leftoff;
34453507
old_zindex = wp->w_zindex;
34463508
old_popup_flags = wp->w_popup_flags;
34473509
old_scrollbar_highlight = wp->w_scrollbar_highlight;
@@ -3514,6 +3576,17 @@ f_popup_setoptions(typval_T *argvars, typval_T *rettv UNUSED)
35143576
// popup_adjust_position() only sets popup_mask_refresh when the
35153577
// position or size actually changed.
35163578
popup_adjust_position(wp);
3579+
3580+
#ifdef FEAT_PROP_POPUP
3581+
if (old_popup_active
3582+
&& (old_winrow != wp->w_winrow
3583+
|| old_wincol != wp->w_wincol
3584+
|| old_popup_height != popup_height(wp)
3585+
|| old_popup_width != popup_width(wp)
3586+
|| old_popup_leftoff != wp->w_popup_leftoff))
3587+
redraw_under_popup_area(old_winrow, old_wincol,
3588+
old_popup_height, old_popup_width, old_popup_leftoff);
3589+
#endif
35173590
}
35183591

35193592
/*
@@ -4755,10 +4828,15 @@ draw_opacity_padding_cell(
47554828
&& utf_char2cells(ScreenLinesUC[base_off]) == 2)
47564829
{
47574830
// The left half still has the wide char on screen.
4758-
// Clear it to a space.
4831+
// Clear it to an unblended space: only the right half is
4832+
// covered by the popup background.
47594833
ScreenLines[base_off] = ' ';
47604834
ScreenLinesUC[base_off] = 0;
47614835
ScreenAttrs[base_off] = saved_screenattrs[base_save_off];
4836+
popup_set_base_screen_cell(row, base_col,
4837+
ScreenLines[base_off],
4838+
ScreenAttrs[base_off],
4839+
ScreenLinesUC[base_off]);
47624840
screen_char(base_off, row, base_col);
47634841

47644842
// Draw padding in the right half.
@@ -4778,43 +4856,6 @@ draw_opacity_padding_cell(
47784856
return;
47794857
}
47804858

4781-
// screen_line() already cleared the base cell (popup
4782-
// content was a space). Restore the full wide char from
4783-
// saved background so it shows through with opacity.
4784-
if (base_save_off >= 0
4785-
&& saved_screenlinesuc != NULL
4786-
&& saved_screenlinesuc[base_save_off] != 0
4787-
&& utf_char2cells(
4788-
saved_screenlinesuc[base_save_off]) == 2)
4789-
{
4790-
ScreenLines[base_off] =
4791-
saved_screenlines[base_save_off];
4792-
ScreenLinesUC[base_off] =
4793-
saved_screenlinesuc[base_save_off];
4794-
ScreenLines[off] = saved_screenlines[save_off];
4795-
ScreenLinesUC[off] = saved_screenlinesuc[save_off];
4796-
ScreenAttrs[base_off] =
4797-
saved_screenattrs[base_save_off];
4798-
ScreenAttrs[off] = saved_screenattrs[save_off];
4799-
4800-
int popup_attr_val =
4801-
get_win_attr(screen_opacity_popup);
4802-
int blend = screen_opacity_popup->w_popup_blend;
4803-
ScreenAttrs[base_off] = hl_blend_attr(
4804-
ScreenAttrs[base_off],
4805-
popup_attr_val, blend, TRUE);
4806-
ScreenAttrs[off] = ScreenAttrs[base_off];
4807-
popup_set_base_screen_cell(row, base_col,
4808-
ScreenLines[base_off],
4809-
ScreenAttrs[base_off],
4810-
ScreenLinesUC[base_off]);
4811-
popup_set_base_screen_cell(row, col,
4812-
ScreenLines[off], ScreenAttrs[off],
4813-
ScreenLinesUC[off]);
4814-
screen_char(base_off, row, base_col);
4815-
return;
4816-
}
4817-
48184859
// Draw padding in the right half.
48194860
ScreenLines[off] = ' ';
48204861
ScreenAttrs[off] = saved_screenattrs[save_off];

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,8 @@ static char *(features[]) =
734734

735735
static int included_patches[] =
736736
{ /* Add new patch number below this line */
737+
/**/
738+
319,
737739
/**/
738740
318,
739741
/**/

0 commit comments

Comments
 (0)