changeset 15521:6d949e552e99 v8.1.0768

patch 8.1.0768: updating completions may cause the popup menu to flicker commit https://github.com/vim/vim/commit/ae654385dfb2ae4c1d70789d1dce3676dba4dfbc Author: Bram Moolenaar <Bram@vim.org> Date: Thu Jan 17 21:09:05 2019 +0100 patch 8.1.0768: updating completions may cause the popup menu to flicker Problem: Updating completions may cause the popup menu to flicker. Solution: Avoid updating the text below the popup menu before drawing the popup menu.
author Bram Moolenaar <Bram@vim.org>
date Thu, 17 Jan 2019 21:15:06 +0100
parents f356d2eb8202
children 6c1acefc5d98
files src/edit.c src/popupmnu.c src/proto/popupmnu.pro src/screen.c src/version.c
diffstat 5 files changed, 65 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/src/edit.c
+++ b/src/edit.c
@@ -3020,7 +3020,8 @@ ins_compl_upd_pum(void)
     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();
     }
@@ -3110,8 +3111,8 @@ ins_compl_show_pum(void)
     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)
     {
@@ -3668,11 +3669,11 @@ ins_compl_new_leader(void)
 	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)
 	{
@@ -5077,8 +5078,9 @@ ins_compl_next(
 	/* 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();
--- a/src/popupmnu.c
+++ b/src/popupmnu.c
@@ -19,6 +19,8 @@ static int pum_size;			/* nr of items in
 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 */
@@ -36,7 +38,8 @@ static int pum_win_col;
 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);
 
@@ -354,6 +357,36 @@ pum_display(
 }
 
 /*
+ * 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".
  */
     void
@@ -376,7 +409,15 @@ pum_redraw(void)
     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;
 
@@ -789,6 +830,7 @@ pum_set_selected(int n, int repeat)
 			pum_do_redraw = TRUE;
 			update_screen(0);
 			pum_do_redraw = FALSE;
+			call_update_screen = FALSE;
 		    }
 		}
 	    }
@@ -844,7 +886,7 @@ pum_may_redraw(void)
     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
--- a/src/proto/popupmnu.pro
+++ b/src/proto/popupmnu.pro
@@ -1,5 +1,7 @@
 /* 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);
--- a/src/screen.c
+++ b/src/screen.c
@@ -183,7 +183,7 @@ static int screen_char_attr = 0;
 /*
  * 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)
@@ -8475,6 +8475,10 @@ screen_char(unsigned off, int row, int c
     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). */
--- a/src/version.c
+++ b/src/version.c
@@ -792,6 +792,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    768,
+/**/
     767,
 /**/
     766,