Problem: Updating completions may cause the popup menu to flicker.
Solution: Avoid updating the text below the popup menu before drawing the
popup menu.
if (compl_match_array != NULL)
{
h = curwin->w_cline_height;
- update_screen(0);
+ // Update the screen later, before drawing the popup menu over it.
+ pum_call_update_screen();
if (h != curwin->w_cline_height)
ins_compl_del_pum();
}
do_cmdline_cmd((char_u *)"if exists('g:loaded_matchparen')|3match none|endif");
#endif
- /* Update the screen before drawing the popup menu over it. */
- update_screen(0);
+ // Update the screen later, before drawing the popup menu over it.
+ pum_call_update_screen();
if (compl_match_array == NULL)
{
spell_bad_len = 0; /* need to redetect bad word */
#endif
/*
- * Matches were cleared, need to search for them now. First display
- * the changed text before the cursor. Set "compl_restarting" to
- * avoid that the first match is inserted.
+ * Matches were cleared, need to search for them now. Befor drawing
+ * the popup menu display the changed text before the cursor. Set
+ * "compl_restarting" to avoid that the first match is inserted.
*/
- update_screen(0);
+ pum_call_update_screen();
#ifdef FEAT_GUI
if (gui.in_use)
{
/* may undisplay the popup menu first */
ins_compl_upd_pum();
- /* redraw to show the user what was inserted */
- update_screen(0);
+ // Redraw before showing the popup menu to show the user what was
+ // inserted.
+ pum_call_update_screen();
/* display the updated popup menu */
ins_compl_show_pum();
static int pum_selected; /* index of selected item or -1 */
static int pum_first = 0; /* index of top item */
+static int call_update_screen = FALSE;
+
static int pum_height; /* nr of displayed pum items */
static int pum_width; /* width of displayed pum items */
static int pum_base_width; /* width of pum items base */
static int pum_win_wcol;
static int pum_win_width;
-static int pum_do_redraw = FALSE; /* do redraw anyway */
+static int pum_do_redraw = FALSE; // do redraw anyway
+static int pum_skip_redraw = FALSE; // skip redraw
static int pum_set_selected(int n, int repeat);
} while (pum_set_selected(selected, redo_count) && ++redo_count <= 2);
}
+/*
+ * Set a flag that when pum_redraw() is called it first calls update_screen().
+ * This will avoid clearing and redrawing the popup menu, prevent flicker.
+ */
+ void
+pum_call_update_screen()
+{
+ call_update_screen = TRUE;
+
+ // Update the cursor position to be able to compute the popup menu
+ // position. The cursor line length may have changed because of the
+ // inserted completion.
+ curwin->w_valid &= VALID_CROW|VALID_CHEIGHT;
+ validate_cursor();
+}
+
+/*
+ * Return TRUE if we are going to redraw the popup menu and the screen position
+ * "row"/"col" is under the popup menu.
+ */
+ int
+pum_under_menu(int row, int col)
+{
+ return pum_skip_redraw
+ && row >= pum_row
+ && row < pum_row + pum_height
+ && col >= pum_col - 1
+ && col < pum_col + pum_width;
+}
+
/*
* Redraw the popup menu, using "pum_first" and "pum_selected".
*/
int round;
int n;
- /* Never display more than we have */
+ if (call_update_screen)
+ {
+ call_update_screen = FALSE;
+ pum_skip_redraw = TRUE; // do not redraw in pum_may_redraw().
+ update_screen(0);
+ pum_skip_redraw = FALSE;
+ }
+
+ // never display more than we have
if (pum_first > pum_size - pum_height)
pum_first = pum_size - pum_height;
pum_do_redraw = TRUE;
update_screen(0);
pum_do_redraw = FALSE;
+ call_update_screen = FALSE;
}
}
}
int len = pum_size;
int selected = pum_selected;
- if (!pum_visible())
+ if (!pum_visible() || pum_skip_redraw)
return; // nothing to do
if (pum_window != curwin
/* popupmnu.c */
void pum_display(pumitem_T *array, int size, int selected);
+void pum_call_update_screen(void);
+int pum_under_menu(int row, int col);
void pum_redraw(void);
void pum_undisplay(void);
void pum_clear(void);
/*
* Redraw the current window later, with update_screen(type).
* Set must_redraw only if not already set to a higher value.
- * e.g. if must_redraw is CLEAR, type NOT_VALID will do nothing.
+ * E.g. if must_redraw is CLEAR, type NOT_VALID will do nothing.
*/
void
redraw_later(int type)
if (row >= screen_Rows || col >= screen_Columns)
return;
+#ifdef FEAT_INS_EXPAND
+ if (pum_under_menu(row, col))
+ return;
+#endif
/* Outputting a character in the last cell on the screen may scroll the
* screen up. Only do it when the "xn" termcap property is set, otherwise
* mark the character invalid (update it when scrolled up). */
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 768,
/**/
767,
/**/