diff options
author | Bram Moolenaar <Bram@vim.org> | 2018-06-17 14:47:55 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2018-06-17 14:47:55 +0200 |
commit | 491ac28d5f91505519c623ebc1a9ab08834bf367 (patch) | |
tree | aec1e3ed4ca83039c349734b6079e61f3af374e8 | |
parent | 84a9308511871d9ff94c91a1c6badb92300ded98 (diff) | |
download | vim-git-491ac28d5f91505519c623ebc1a9ab08834bf367.tar.gz |
patch 8.1.0062: popup menu broken if a callback changes the window layoutv8.1.0062
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.
-rw-r--r-- | src/popupmnu.c | 69 | ||||
-rw-r--r-- | src/proto/popupmnu.pro | 1 | ||||
-rw-r--r-- | src/screen.c | 19 | ||||
-rw-r--r-- | src/version.c | 2 |
4 files changed, 71 insertions, 20 deletions
diff --git a/src/popupmnu.c b/src/popupmnu.c index 9bebceb89..66fd6b9c5 100644 --- a/src/popupmnu.c +++ b/src/popupmnu.c @@ -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 @@ -823,6 +834,42 @@ pum_visible(void) } /* + * 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! */ diff --git a/src/proto/popupmnu.pro b/src/proto/popupmnu.pro index d5e1bbd23..f553100bb 100644 --- a/src/proto/popupmnu.pro +++ b/src/proto/popupmnu.pro @@ -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); diff --git a/src/screen.c b/src/screen.c index 5ffc357d7..2fae1805d 100644 --- a/src/screen.c +++ b/src/screen.c @@ -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 diff --git a/src/version.c b/src/version.c index c8c4dd15e..bcbbe4022 100644 --- a/src/version.c +++ b/src/version.c @@ -762,6 +762,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 62, +/**/ 61, /**/ 60, |