]> granicus.if.org Git - vim/commitdiff
patch 8.1.0768: updating completions may cause the popup menu to flicker v8.1.0768
authorBram Moolenaar <Bram@vim.org>
Thu, 17 Jan 2019 20:09:05 +0000 (21:09 +0100)
committerBram Moolenaar <Bram@vim.org>
Thu, 17 Jan 2019 20:09:05 +0000 (21:09 +0100)
Problem:    Updating completions may cause the popup menu to flicker.
Solution:   Avoid updating the text below the popup menu before drawing the
            popup menu.

src/edit.c
src/popupmnu.c
src/proto/popupmnu.pro
src/screen.c
src/version.c

index effc524d3037eedd55f1c0d1acb7242d5b93363d..ea50e801842f0dad44e201b193ffb0c1166f8c0e 100644 (file)
@@ -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();
index c0191c407f818a403ef0998f2f996bcfd57a7e45..2f2bde0bb5ed4f5e435e4c959cb0a7b1687cf8be 100644 (file)
@@ -19,6 +19,8 @@ static int pum_size;                  /* nr of items in "pum_array" */
 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);
 
@@ -353,6 +356,36 @@ pum_display(
     } 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".
  */
@@ -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
index f553100bb1df5448262c844f1e7d3b1f6f71e7f7..e2ae92ae8f2118413abc7c04fadee00906b2b72f 100644 (file)
@@ -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);
index cd146fd6c1299b717dacaa0dff19ad8f3985baa4..1b53ae2cd2d2988669b98e92481aa95d30b2ddf9 100644 (file)
@@ -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 col)
     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). */
index 719fd074150af010ff87625151f76c4d7ec65078..c6fe19d0e2acfe406c204944d657f90e153d52cb 100644 (file)
@@ -791,6 +791,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    768,
 /**/
     767,
 /**/