mirror of
https://github.com/vim/vim.git
synced 2025-09-26 04:04:07 -04:00
patch 8.1.0062: popup menu broken if a callback changes the window layout
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.
This commit is contained in:
@@ -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!
|
||||
|
@@ -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);
|
||||
|
19
src/screen.c
19
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
|
||||
|
||||
|
@@ -761,6 +761,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
62,
|
||||
/**/
|
||||
61,
|
||||
/**/
|
||||
|
Reference in New Issue
Block a user