Skip to content

Commit 4d0c57e

Browse files
mattnchrisbra
authored andcommitted
patch 9.2.0112: popup: windows flicker when updating text
Problem: popup: windows flicker when updating text Solution: Only refresh the popup mask if the position or size changed, manually set the window redraw type instead of using redraw_win_later() to avoid triggering a full screen redraw. Handle opacity 100 correctly. Keep "firstline" sticky when setting options (Yasuhiro Matsumoto). related: #19510 closes: #19559 Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
1 parent 0fe3ca6 commit 4d0c57e

File tree

3 files changed

+57
-6
lines changed

3 files changed

+57
-6
lines changed

src/popupwin.c

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -785,13 +785,19 @@ apply_general_options(win_T *wp, dict_T *dict)
785785
if (di != NULL)
786786
{
787787
nr = dict_get_number(dict, "opacity");
788-
if (nr > 0 && nr <= 100)
788+
if (nr > 0 && nr < 100)
789789
{
790-
// opacity: 0-100, where 0=transparent, 100=opaque
790+
// opacity: 1-99, partially transparent
791791
// Convert to blend (0=opaque, 100=transparent)
792792
wp->w_popup_flags |= POPF_OPACITY;
793793
wp->w_popup_blend = 100 - nr;
794794
}
795+
else if (nr == 100)
796+
{
797+
// Fully opaque, same as no opacity set.
798+
wp->w_popup_flags &= ~POPF_OPACITY;
799+
wp->w_popup_blend = 0;
800+
}
795801
else
796802
{
797803
wp->w_popup_flags &= ~POPF_OPACITY;
@@ -1098,7 +1104,8 @@ apply_options(win_T *wp, dict_T *dict, int create)
10981104
wp->w_valid &= ~VALID_BOTLINE;
10991105
}
11001106

1101-
popup_mask_refresh = TRUE;
1107+
if (create)
1108+
popup_mask_refresh = TRUE;
11021109
popup_highlight_curline(wp);
11031110

11041111
return OK;
@@ -3106,7 +3113,15 @@ f_popup_settext(typval_T *argvars, typval_T *rettv UNUSED)
31063113
return;
31073114

31083115
popup_set_buffer_text(wp->w_buffer, argvars[1]);
3109-
redraw_win_later(wp, UPD_NOT_VALID);
3116+
3117+
// Redraw the popup window without triggering a full screen redraw.
3118+
// Using redraw_win_later() with UPD_NOT_VALID would set the global
3119+
// must_redraw, causing may_update_popup_mask() to refresh the mask and
3120+
// redraw windows behind the popup, resulting in flickering.
3121+
wp->w_redr_type = UPD_NOT_VALID;
3122+
wp->w_lines_valid = 0;
3123+
if (must_redraw < UPD_VALID)
3124+
must_redraw = UPD_VALID;
31103125
popup_adjust_position(wp);
31113126
}
31123127

@@ -3391,6 +3406,7 @@ f_popup_setoptions(typval_T *argvars, typval_T *rettv UNUSED)
33913406
char_u *old_thumb_highlight;
33923407
char_u *old_border_highlight[4];
33933408
int need_redraw = FALSE;
3409+
int need_reposition = FALSE;
33943410
int i;
33953411

33963412
if (in_vim9script()
@@ -3419,13 +3435,25 @@ f_popup_setoptions(typval_T *argvars, typval_T *rettv UNUSED)
34193435

34203436
(void)apply_options(wp, dict, FALSE);
34213437

3438+
// Keep "firstline" sticky across popup_setoptions(): when it is set, any
3439+
// property update should reapply it and restore the displayed top line.
3440+
if (wp->w_firstline > 0
3441+
&& wp->w_firstline <= wp->w_buffer->b_ml.ml_line_count)
3442+
wp->w_topline = wp->w_firstline;
3443+
34223444
// Check if visual options changed and redraw if needed
34233445
if (old_firstline != wp->w_firstline)
34243446
need_redraw = TRUE;
34253447
if (old_zindex != wp->w_zindex)
3448+
{
34263449
need_redraw = TRUE;
3450+
need_reposition = TRUE;
3451+
}
34273452
if (old_popup_flags != wp->w_popup_flags)
3453+
{
34283454
need_redraw = TRUE;
3455+
need_reposition = TRUE;
3456+
}
34293457
if (old_scrollbar_highlight != wp->w_scrollbar_highlight)
34303458
need_redraw = TRUE;
34313459
if (old_thumb_highlight != wp->w_thumb_highlight)
@@ -3437,17 +3465,38 @@ f_popup_setoptions(typval_T *argvars, typval_T *rettv UNUSED)
34373465
break;
34383466
}
34393467

3440-
if (need_redraw)
3468+
if (need_reposition)
3469+
{
34413470
redraw_win_later(wp, UPD_NOT_VALID);
3471+
popup_mask_refresh = TRUE;
3472+
}
3473+
else if (need_redraw)
3474+
{
3475+
// Only content changed (e.g. firstline, highlight): redraw the
3476+
// popup window without updating the popup mask or triggering a
3477+
// full screen redraw. This avoids flickering of windows behind
3478+
// the popup.
3479+
wp->w_redr_type = UPD_NOT_VALID;
3480+
wp->w_lines_valid = 0;
3481+
if (must_redraw < UPD_VALID)
3482+
must_redraw = UPD_VALID;
3483+
}
3484+
34423485
#ifdef FEAT_PROP_POPUP
34433486
// Force redraw if opacity value changed
34443487
if (old_blend != wp->w_popup_blend)
34453488
{
34463489
redraw_win_later(wp, UPD_NOT_VALID);
34473490
// Also redraw windows below the popup
34483491
redraw_all_later(UPD_NOT_VALID);
3492+
popup_mask_refresh = TRUE;
34493493
}
34503494
#endif
3495+
3496+
// Always recalculate popup position/size: other options like border,
3497+
// close, padding may have changed without affecting w_popup_flags.
3498+
// popup_adjust_position() only sets popup_mask_refresh when the
3499+
// position or size actually changed.
34513500
popup_adjust_position(wp);
34523501
}
34533502

src/screen.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -627,7 +627,7 @@ screen_line(
627627
ScreenLines[off_to + 1] = ScreenLines[off_from + 1];
628628
ScreenAttrs[off_to + 1] = ScreenAttrs[off_from];
629629
}
630-
if (enc_dbcs == DBCS_JPNU) // Copilot's suggestion for DBCS_JPNU
630+
if (enc_dbcs == DBCS_JPNU)
631631
ScreenLines2[off_to] = ScreenLines2[off_from];
632632

633633
if (enc_dbcs != 0 && char_cells == 2)

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+
112,
737739
/**/
738740
111,
739741
/**/

0 commit comments

Comments
 (0)