mirror of
https://github.com/vim/vim.git
synced 2026-05-28 00:21:37 +02:00
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>
This commit is contained in:
committed by
Christian Brabandt
parent
0fe3ca6031
commit
4d0c57e15f
+54
-5
@@ -785,13 +785,19 @@ apply_general_options(win_T *wp, dict_T *dict)
|
||||
if (di != NULL)
|
||||
{
|
||||
nr = dict_get_number(dict, "opacity");
|
||||
if (nr > 0 && nr <= 100)
|
||||
if (nr > 0 && nr < 100)
|
||||
{
|
||||
// opacity: 0-100, where 0=transparent, 100=opaque
|
||||
// opacity: 1-99, partially transparent
|
||||
// Convert to blend (0=opaque, 100=transparent)
|
||||
wp->w_popup_flags |= POPF_OPACITY;
|
||||
wp->w_popup_blend = 100 - nr;
|
||||
}
|
||||
else if (nr == 100)
|
||||
{
|
||||
// Fully opaque, same as no opacity set.
|
||||
wp->w_popup_flags &= ~POPF_OPACITY;
|
||||
wp->w_popup_blend = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
wp->w_popup_flags &= ~POPF_OPACITY;
|
||||
@@ -1098,7 +1104,8 @@ apply_options(win_T *wp, dict_T *dict, int create)
|
||||
wp->w_valid &= ~VALID_BOTLINE;
|
||||
}
|
||||
|
||||
popup_mask_refresh = TRUE;
|
||||
if (create)
|
||||
popup_mask_refresh = TRUE;
|
||||
popup_highlight_curline(wp);
|
||||
|
||||
return OK;
|
||||
@@ -3106,7 +3113,15 @@ f_popup_settext(typval_T *argvars, typval_T *rettv UNUSED)
|
||||
return;
|
||||
|
||||
popup_set_buffer_text(wp->w_buffer, argvars[1]);
|
||||
redraw_win_later(wp, UPD_NOT_VALID);
|
||||
|
||||
// Redraw the popup window without triggering a full screen redraw.
|
||||
// Using redraw_win_later() with UPD_NOT_VALID would set the global
|
||||
// must_redraw, causing may_update_popup_mask() to refresh the mask and
|
||||
// redraw windows behind the popup, resulting in flickering.
|
||||
wp->w_redr_type = UPD_NOT_VALID;
|
||||
wp->w_lines_valid = 0;
|
||||
if (must_redraw < UPD_VALID)
|
||||
must_redraw = UPD_VALID;
|
||||
popup_adjust_position(wp);
|
||||
}
|
||||
|
||||
@@ -3391,6 +3406,7 @@ f_popup_setoptions(typval_T *argvars, typval_T *rettv UNUSED)
|
||||
char_u *old_thumb_highlight;
|
||||
char_u *old_border_highlight[4];
|
||||
int need_redraw = FALSE;
|
||||
int need_reposition = FALSE;
|
||||
int i;
|
||||
|
||||
if (in_vim9script()
|
||||
@@ -3419,13 +3435,25 @@ f_popup_setoptions(typval_T *argvars, typval_T *rettv UNUSED)
|
||||
|
||||
(void)apply_options(wp, dict, FALSE);
|
||||
|
||||
// Keep "firstline" sticky across popup_setoptions(): when it is set, any
|
||||
// property update should reapply it and restore the displayed top line.
|
||||
if (wp->w_firstline > 0
|
||||
&& wp->w_firstline <= wp->w_buffer->b_ml.ml_line_count)
|
||||
wp->w_topline = wp->w_firstline;
|
||||
|
||||
// Check if visual options changed and redraw if needed
|
||||
if (old_firstline != wp->w_firstline)
|
||||
need_redraw = TRUE;
|
||||
if (old_zindex != wp->w_zindex)
|
||||
{
|
||||
need_redraw = TRUE;
|
||||
need_reposition = TRUE;
|
||||
}
|
||||
if (old_popup_flags != wp->w_popup_flags)
|
||||
{
|
||||
need_redraw = TRUE;
|
||||
need_reposition = TRUE;
|
||||
}
|
||||
if (old_scrollbar_highlight != wp->w_scrollbar_highlight)
|
||||
need_redraw = TRUE;
|
||||
if (old_thumb_highlight != wp->w_thumb_highlight)
|
||||
@@ -3437,8 +3465,23 @@ f_popup_setoptions(typval_T *argvars, typval_T *rettv UNUSED)
|
||||
break;
|
||||
}
|
||||
|
||||
if (need_redraw)
|
||||
if (need_reposition)
|
||||
{
|
||||
redraw_win_later(wp, UPD_NOT_VALID);
|
||||
popup_mask_refresh = TRUE;
|
||||
}
|
||||
else if (need_redraw)
|
||||
{
|
||||
// Only content changed (e.g. firstline, highlight): redraw the
|
||||
// popup window without updating the popup mask or triggering a
|
||||
// full screen redraw. This avoids flickering of windows behind
|
||||
// the popup.
|
||||
wp->w_redr_type = UPD_NOT_VALID;
|
||||
wp->w_lines_valid = 0;
|
||||
if (must_redraw < UPD_VALID)
|
||||
must_redraw = UPD_VALID;
|
||||
}
|
||||
|
||||
#ifdef FEAT_PROP_POPUP
|
||||
// Force redraw if opacity value changed
|
||||
if (old_blend != wp->w_popup_blend)
|
||||
@@ -3446,8 +3489,14 @@ f_popup_setoptions(typval_T *argvars, typval_T *rettv UNUSED)
|
||||
redraw_win_later(wp, UPD_NOT_VALID);
|
||||
// Also redraw windows below the popup
|
||||
redraw_all_later(UPD_NOT_VALID);
|
||||
popup_mask_refresh = TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Always recalculate popup position/size: other options like border,
|
||||
// close, padding may have changed without affecting w_popup_flags.
|
||||
// popup_adjust_position() only sets popup_mask_refresh when the
|
||||
// position or size actually changed.
|
||||
popup_adjust_position(wp);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -627,7 +627,7 @@ screen_line(
|
||||
ScreenLines[off_to + 1] = ScreenLines[off_from + 1];
|
||||
ScreenAttrs[off_to + 1] = ScreenAttrs[off_from];
|
||||
}
|
||||
if (enc_dbcs == DBCS_JPNU) // Copilot's suggestion for DBCS_JPNU
|
||||
if (enc_dbcs == DBCS_JPNU)
|
||||
ScreenLines2[off_to] = ScreenLines2[off_from];
|
||||
|
||||
if (enc_dbcs != 0 && char_cells == 2)
|
||||
|
||||
@@ -734,6 +734,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
112,
|
||||
/**/
|
||||
111,
|
||||
/**/
|
||||
|
||||
Reference in New Issue
Block a user