]> granicus.if.org Git - vim/commitdiff
patch 8.1.0062: popup menu broken if a callback changes the window layout v8.1.0062
authorBram Moolenaar <Bram@vim.org>
Sun, 17 Jun 2018 12:47:55 +0000 (14:47 +0200)
committerBram Moolenaar <Bram@vim.org>
Sun, 17 Jun 2018 12:47:55 +0000 (14:47 +0200)
Problem:    Popup menu broken if a callback changes the window layout. (Qiming
            Zhao)
Solution:   Recompute the popup menu position if needed.  Redraw the ruler
            even when the popup menu is displayed.

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

index 9bebceb894391cc38e2ddf431fc77fc05c90a9b5..66fd6b9c5353de9a7c0a79fbf710d7ed718c8edc 100644 (file)
@@ -29,6 +29,12 @@ static int pum_scrollbar;            /* TRUE when scrollbar present */
 static int pum_row;                    /* top row of pum */
 static int pum_col;                    /* left column of pum */
 
+static int pum_win_row;
+static int pum_win_height;
+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_set_selected(int n, int repeat);
@@ -81,7 +87,6 @@ pum_display(
 {
     int                def_width;
     int                max_width;
-    int                row;
     int                context_lines;
     int                cursor_col;
     int                above_row;
@@ -103,7 +108,13 @@ pum_display(
        validate_cursor_col();
        pum_array = NULL;
 
-       row = curwin->w_wrow + W_WINROW(curwin);
+       // Remember the essential parts of the window position and size, so we
+       // can decide when to reposition the popup menu.
+       pum_win_row = curwin->w_wrow + W_WINROW(curwin);
+       pum_win_height = curwin->w_height;
+       pum_win_col = curwin->w_wincol;
+       pum_win_wcol = curwin->w_wcol;
+       pum_win_width = curwin->w_width;
 
 #if defined(FEAT_QUICKFIX)
        FOR_ALL_WINDOWS(pvwin)
@@ -128,12 +139,12 @@ pum_display(
        if (p_ph > 0 && pum_height > p_ph)
            pum_height = p_ph;
 
-       /* Put the pum below "row" if possible.  If there are few lines decide
+       /* Put the pum below "pum_win_row" if possible.  If there are few lines decide
         * on where there is more room. */
-       if (row + 2 >= below_row - pum_height
-                             && row - above_row > (below_row - above_row) / 2)
+       if (pum_win_row + 2 >= below_row - pum_height
+                     && pum_win_row - above_row > (below_row - above_row) / 2)
        {
-           /* pum above "row" */
+           /* pum above "pum_win_row" */
 
            /* Leave two lines of context if possible */
            if (curwin->w_wrow - curwin->w_cline_row >= 2)
@@ -141,15 +152,15 @@ pum_display(
            else
                context_lines = curwin->w_wrow - curwin->w_cline_row;
 
-           if (row >= size + context_lines)
+           if (pum_win_row >= size + context_lines)
            {
-               pum_row = row - size - context_lines;
+               pum_row = pum_win_row - size - context_lines;
                pum_height = size;
            }
            else
            {
                pum_row = 0;
-               pum_height = row - context_lines;
+               pum_height = pum_win_row - context_lines;
            }
            if (p_ph > 0 && pum_height > p_ph)
            {
@@ -159,7 +170,7 @@ pum_display(
        }
        else
        {
-           /* pum below "row" */
+           /* pum below "pum_win_row" */
 
            /* Leave two lines of context if possible */
            if (curwin->w_cline_row
@@ -169,7 +180,7 @@ pum_display(
                context_lines = curwin->w_cline_row
                                    + curwin->w_cline_height - curwin->w_wrow;
 
-           pum_row = row + context_lines;
+           pum_row = pum_win_row + context_lines;
            if (size > below_row - pum_row)
                pum_height = below_row - pum_row;
            else
@@ -822,6 +833,42 @@ pum_visible(void)
     return !pum_do_redraw && pum_array != NULL;
 }
 
+/*
+ * Reposition the popup menu to adjust for window layout changes.
+ */
+    void
+pum_may_redraw(void)
+{
+    pumitem_T  *array = pum_array;
+    int                len = pum_size;
+    int                selected = pum_selected;
+
+    if (!pum_visible())
+       return;  // nothing to do
+
+    if (pum_win_row == curwin->w_wrow + W_WINROW(curwin)
+           && pum_win_height == curwin->w_height
+           && pum_win_col == curwin->w_wincol
+           && pum_win_width == curwin->w_width)
+    {
+       // window position didn't change, redraw in the same position
+       pum_redraw();
+    }
+    else
+    {
+       int wcol = curwin->w_wcol;
+
+       // Window layout changed, recompute the position.
+       // Use the remembered w_wcol value, the cursor may have moved when a
+       // completion was inserted, but we want the menu in the same position.
+       pum_undisplay();
+       curwin->w_wcol = pum_win_wcol;
+       curwin->w_valid |= VALID_WCOL;
+       pum_display(array, len, selected);
+       curwin->w_wcol = wcol;
+    }
+}
+
 /*
  * Return the height of the popup menu, the number of entries visible.
  * Only valid when pum_visible() returns TRUE!
index d5e1bbd2353f99cec0b7c4147689478b1507d9d4..f553100bb1df5448262c844f1e7d3b1f6f71e7f7 100644 (file)
@@ -4,6 +4,7 @@ void pum_redraw(void);
 void pum_undisplay(void);
 void pum_clear(void);
 int pum_visible(void);
+void pum_may_redraw(void);
 int pum_get_height(void);
 int split_message(char_u *mesg, pumitem_T **array);
 void ui_remove_balloon(void);
index 5ffc357d7d0d2fea531b0fcb1919c4138933771b..2fae1805d3bb50ea7a8b0c1310066bb5dbc8eb14 100644 (file)
@@ -171,7 +171,7 @@ static void redraw_win_toolbar(win_T *wp);
 static void win_redr_custom(win_T *wp, int draw_ruler);
 #endif
 #ifdef FEAT_CMDL_INFO
-static void win_redr_ruler(win_T *wp, int always);
+static void win_redr_ruler(win_T *wp, int always, int ignore_pum);
 #endif
 
 /* Ugly global: overrule attribute used by screen_char() */
@@ -783,8 +783,7 @@ update_screen(int type_arg)
 #endif
 #ifdef FEAT_INS_EXPAND
     /* May need to redraw the popup menu. */
-    if (pum_visible())
-       pum_redraw();
+    pum_may_redraw();
 #endif
 
     /* Reset b_mod_set flags.  Going through all windows is probably faster
@@ -7002,7 +7001,7 @@ win_redr_status(win_T *wp, int ignore_pum)
                                                   - 1 + wp->w_wincol), attr);
 
 #ifdef FEAT_CMDL_INFO
-       win_redr_ruler(wp, TRUE);
+       win_redr_ruler(wp, TRUE, ignore_pum);
 #endif
     }
 
@@ -10455,7 +10454,7 @@ showmode(void)
     /* If the last window has no status line, the ruler is after the mode
      * message and must be redrawn */
     if (redrawing() && lastwin->w_status_height == 0)
-       win_redr_ruler(lastwin, TRUE);
+       win_redr_ruler(lastwin, TRUE, FALSE);
 #endif
     redraw_cmdline = FALSE;
     clear_cmdline = FALSE;
@@ -10874,6 +10873,7 @@ redraw_win_toolbar(win_T *wp)
                                                     (int)wp->w_width, FALSE);
 }
 #endif
+
 /*
  * Show current status info in ruler and various other places
  * If always is FALSE, only show ruler if position has changed.
@@ -10899,7 +10899,7 @@ showruler(int always)
     else
 #endif
 #ifdef FEAT_CMDL_INFO
-       win_redr_ruler(curwin, always);
+       win_redr_ruler(curwin, always, FALSE);
 #endif
 
 #ifdef FEAT_TITLE
@@ -10918,7 +10918,7 @@ showruler(int always)
 
 #ifdef FEAT_CMDL_INFO
     static void
-win_redr_ruler(win_T *wp, int always)
+win_redr_ruler(win_T *wp, int always, int ignore_pum)
 {
 #define RULER_BUF_LEN 70
     char_u     buffer[RULER_BUF_LEN];
@@ -10951,8 +10951,9 @@ win_redr_ruler(win_T *wp, int always)
     if (wp == lastwin && lastwin->w_status_height == 0)
        if (edit_submode != NULL)
            return;
-    /* Don't draw the ruler when the popup menu is visible, it may overlap. */
-    if (pum_visible())
+    // Don't draw the ruler when the popup menu is visible, it may overlap.
+    // Except when the popup menu will be redrawn anyway.
+    if (!ignore_pum && pum_visible())
        return;
 #endif
 
index c8c4dd15e1104819e93a772b3b471103cc7cba4f..bcbbe40221b3044705d3e69235124579ec49867c 100644 (file)
@@ -761,6 +761,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    62,
 /**/
     61,
 /**/