forked from aniani/vim
patch 8.1.2300: redraw breaks going through list of popup windows
Problem: Redraw breaks going through list of popup windows. Solution: Use different flags for popup_reset_handled(). (closes #5216)
This commit is contained in:
parent
36e7a823c6
commit
afe45b68a6
@ -2921,8 +2921,8 @@ mouse_find_win(int *rowp, int *colp, mouse_find_T popup UNUSED)
|
|||||||
|
|
||||||
if (popup != IGNORE_POPUP)
|
if (popup != IGNORE_POPUP)
|
||||||
{
|
{
|
||||||
popup_reset_handled();
|
popup_reset_handled(POPUP_HANDLED_1);
|
||||||
while ((wp = find_next_popup(TRUE)) != NULL)
|
while ((wp = find_next_popup(TRUE, POPUP_HANDLED_1)) != NULL)
|
||||||
{
|
{
|
||||||
if (*rowp >= wp->w_winrow && *rowp < wp->w_winrow + popup_height(wp)
|
if (*rowp >= wp->w_winrow && *rowp < wp->w_winrow + popup_height(wp)
|
||||||
&& *colp >= wp->w_wincol
|
&& *colp >= wp->w_wincol
|
||||||
|
@ -2815,28 +2815,30 @@ error_if_popup_window()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reset all the POPF_HANDLED flags in global popup windows and popup windows
|
* Reset all the "handled_flag" flags in global popup windows and popup windows
|
||||||
* in the current tab page.
|
* in the current tab page.
|
||||||
|
* Each calling function should use a different flag, see the list at
|
||||||
|
* POPUP_HANDLED_1. This won't work with recursive calls though.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
popup_reset_handled()
|
popup_reset_handled(int handled_flag)
|
||||||
{
|
{
|
||||||
win_T *wp;
|
win_T *wp;
|
||||||
|
|
||||||
for (wp = first_popupwin; wp != NULL; wp = wp->w_next)
|
for (wp = first_popupwin; wp != NULL; wp = wp->w_next)
|
||||||
wp->w_popup_flags &= ~POPF_HANDLED;
|
wp->w_popup_handled &= ~handled_flag;
|
||||||
for (wp = curtab->tp_first_popupwin; wp != NULL; wp = wp->w_next)
|
for (wp = curtab->tp_first_popupwin; wp != NULL; wp = wp->w_next)
|
||||||
wp->w_popup_flags &= ~POPF_HANDLED;
|
wp->w_popup_handled &= ~handled_flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find the next visible popup where POPF_HANDLED is not set.
|
* Find the next visible popup where "handled_flag" is not set.
|
||||||
* Must have called popup_reset_handled() first.
|
* Must have called popup_reset_handled() first.
|
||||||
* When "lowest" is TRUE find the popup with the lowest zindex, otherwise the
|
* When "lowest" is TRUE find the popup with the lowest zindex, otherwise the
|
||||||
* popup with the highest zindex.
|
* popup with the highest zindex.
|
||||||
*/
|
*/
|
||||||
win_T *
|
win_T *
|
||||||
find_next_popup(int lowest)
|
find_next_popup(int lowest, int handled_flag)
|
||||||
{
|
{
|
||||||
win_T *wp;
|
win_T *wp;
|
||||||
win_T *found_wp;
|
win_T *found_wp;
|
||||||
@ -2845,24 +2847,26 @@ find_next_popup(int lowest)
|
|||||||
found_zindex = lowest ? INT_MAX : 0;
|
found_zindex = lowest ? INT_MAX : 0;
|
||||||
found_wp = NULL;
|
found_wp = NULL;
|
||||||
for (wp = first_popupwin; wp != NULL; wp = wp->w_next)
|
for (wp = first_popupwin; wp != NULL; wp = wp->w_next)
|
||||||
if ((wp->w_popup_flags & (POPF_HANDLED|POPF_HIDDEN)) == 0
|
if ((wp->w_popup_handled & handled_flag) == 0
|
||||||
|
&& (wp->w_popup_flags & POPF_HIDDEN) == 0
|
||||||
&& (lowest ? wp->w_zindex < found_zindex
|
&& (lowest ? wp->w_zindex < found_zindex
|
||||||
: wp->w_zindex > found_zindex))
|
: wp->w_zindex > found_zindex))
|
||||||
{
|
{
|
||||||
found_zindex = wp->w_zindex;
|
found_zindex = wp->w_zindex;
|
||||||
found_wp = wp;
|
found_wp = wp;
|
||||||
}
|
}
|
||||||
for (wp = curtab->tp_first_popupwin; wp != NULL; wp = wp->w_next)
|
for (wp = curtab->tp_first_popupwin; wp != NULL; wp = wp->w_next)
|
||||||
if ((wp->w_popup_flags & (POPF_HANDLED|POPF_HIDDEN)) == 0
|
if ((wp->w_popup_handled & handled_flag) == 0
|
||||||
|
&& (wp->w_popup_flags & POPF_HIDDEN) == 0
|
||||||
&& (lowest ? wp->w_zindex < found_zindex
|
&& (lowest ? wp->w_zindex < found_zindex
|
||||||
: wp->w_zindex > found_zindex))
|
: wp->w_zindex > found_zindex))
|
||||||
{
|
{
|
||||||
found_zindex = wp->w_zindex;
|
found_zindex = wp->w_zindex;
|
||||||
found_wp = wp;
|
found_wp = wp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (found_wp != NULL)
|
if (found_wp != NULL)
|
||||||
found_wp->w_popup_flags |= POPF_HANDLED;
|
found_wp->w_popup_handled |= handled_flag;
|
||||||
return found_wp;
|
return found_wp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2929,6 +2933,7 @@ invoke_popup_filter(win_T *wp, int c)
|
|||||||
{
|
{
|
||||||
set_vim_var_nr(VV_MOUSE_LNUM, 0);
|
set_vim_var_nr(VV_MOUSE_LNUM, 0);
|
||||||
set_vim_var_nr(VV_MOUSE_COL, 0);
|
set_vim_var_nr(VV_MOUSE_COL, 0);
|
||||||
|
set_vim_var_nr(VV_MOUSE_WINID, wp->w_id);
|
||||||
}
|
}
|
||||||
vim_free(argv[1].vval.v_string);
|
vim_free(argv[1].vval.v_string);
|
||||||
clear_tv(&rettv);
|
clear_tv(&rettv);
|
||||||
@ -2963,9 +2968,9 @@ popup_do_filter(int c)
|
|||||||
res = TRUE;
|
res = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
popup_reset_handled();
|
popup_reset_handled(POPUP_HANDLED_2);
|
||||||
state = get_real_state();
|
state = get_real_state();
|
||||||
while (!res && (wp = find_next_popup(FALSE)) != NULL)
|
while (!res && (wp = find_next_popup(FALSE, POPUP_HANDLED_2)) != NULL)
|
||||||
if (wp->w_filter_cb.cb_name != NULL
|
if (wp->w_filter_cb.cb_name != NULL
|
||||||
&& (wp->w_filter_mode & state) != 0)
|
&& (wp->w_filter_mode & state) != 0)
|
||||||
res = invoke_popup_filter(wp, c);
|
res = invoke_popup_filter(wp, c);
|
||||||
@ -3005,8 +3010,8 @@ popup_check_cursor_pos()
|
|||||||
{
|
{
|
||||||
win_T *wp;
|
win_T *wp;
|
||||||
|
|
||||||
popup_reset_handled();
|
popup_reset_handled(POPUP_HANDLED_3);
|
||||||
while ((wp = find_next_popup(TRUE)) != NULL)
|
while ((wp = find_next_popup(TRUE, POPUP_HANDLED_3)) != NULL)
|
||||||
if (wp->w_popup_curwin != NULL
|
if (wp->w_popup_curwin != NULL
|
||||||
&& (curwin != wp->w_popup_curwin
|
&& (curwin != wp->w_popup_curwin
|
||||||
|| curwin->w_cursor.lnum != wp->w_popup_lnum
|
|| curwin->w_cursor.lnum != wp->w_popup_lnum
|
||||||
@ -3242,8 +3247,8 @@ may_update_popup_mask(int type)
|
|||||||
// Find the window with the lowest zindex that hasn't been handled yet,
|
// Find the window with the lowest zindex that hasn't been handled yet,
|
||||||
// so that the window with a higher zindex overwrites the value in
|
// so that the window with a higher zindex overwrites the value in
|
||||||
// popup_mask.
|
// popup_mask.
|
||||||
popup_reset_handled();
|
popup_reset_handled(POPUP_HANDLED_4);
|
||||||
while ((wp = find_next_popup(TRUE)) != NULL)
|
while ((wp = find_next_popup(TRUE, POPUP_HANDLED_4)) != NULL)
|
||||||
{
|
{
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
@ -3383,8 +3388,8 @@ update_popups(void (*win_update)(win_T *wp))
|
|||||||
// Find the window with the lowest zindex that hasn't been updated yet,
|
// Find the window with the lowest zindex that hasn't been updated yet,
|
||||||
// so that the window with a higher zindex is drawn later, thus goes on
|
// so that the window with a higher zindex is drawn later, thus goes on
|
||||||
// top.
|
// top.
|
||||||
popup_reset_handled();
|
popup_reset_handled(POPUP_HANDLED_5);
|
||||||
while ((wp = find_next_popup(TRUE)) != NULL)
|
while ((wp = find_next_popup(TRUE, POPUP_HANDLED_5)) != NULL)
|
||||||
{
|
{
|
||||||
// This drawing uses the zindex of the popup window, so that it's on
|
// This drawing uses the zindex of the popup window, so that it's on
|
||||||
// top of the text but doesn't draw when another popup with higher
|
// top of the text but doesn't draw when another popup with higher
|
||||||
|
@ -40,8 +40,8 @@ void f_popup_getpos(typval_T *argvars, typval_T *rettv);
|
|||||||
void f_popup_locate(typval_T *argvars, typval_T *rettv);
|
void f_popup_locate(typval_T *argvars, typval_T *rettv);
|
||||||
void f_popup_getoptions(typval_T *argvars, typval_T *rettv);
|
void f_popup_getoptions(typval_T *argvars, typval_T *rettv);
|
||||||
int error_if_popup_window(void);
|
int error_if_popup_window(void);
|
||||||
void popup_reset_handled(void);
|
void popup_reset_handled(int handled_flag);
|
||||||
win_T *find_next_popup(int lowest);
|
win_T *find_next_popup(int lowest, int handled_flag);
|
||||||
int popup_do_filter(int c);
|
int popup_do_filter(int c);
|
||||||
int popup_no_mapping(void);
|
int popup_no_mapping(void);
|
||||||
void popup_check_cursor_pos(void);
|
void popup_check_cursor_pos(void);
|
||||||
|
@ -3015,6 +3015,7 @@ struct window_S
|
|||||||
pos_save_T w_save_cursor; // backup of cursor pos and topline
|
pos_save_T w_save_cursor; // backup of cursor pos and topline
|
||||||
#ifdef FEAT_TEXT_PROP
|
#ifdef FEAT_TEXT_PROP
|
||||||
int w_popup_flags; // POPF_ values
|
int w_popup_flags; // POPF_ values
|
||||||
|
int w_popup_handled; // POPUP_HANDLE[0-9] flags
|
||||||
char_u *w_popup_title;
|
char_u *w_popup_title;
|
||||||
poppos_T w_popup_pos;
|
poppos_T w_popup_pos;
|
||||||
int w_popup_fixed; // do not shift popup to fit on screen
|
int w_popup_fixed; // do not shift popup to fit on screen
|
||||||
|
@ -2949,4 +2949,38 @@ func Test_popupwin_cancel()
|
|||||||
call assert_equal({}, popup_getpos(win3))
|
call assert_equal({}, popup_getpos(win3))
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_popupwin_filter_redraw()
|
||||||
|
" Create two popups with a filter that closes the popup when typing "0".
|
||||||
|
" Both popups should close, even though the redraw also calls
|
||||||
|
" popup_reset_handled()
|
||||||
|
|
||||||
|
func CloseFilter(winid, key)
|
||||||
|
if a:key == '0'
|
||||||
|
call popup_close(a:winid)
|
||||||
|
redraw
|
||||||
|
endif
|
||||||
|
return 0 " pass the key
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
let id1 = popup_create('first one', #{
|
||||||
|
\ line: 1,
|
||||||
|
\ col: 1,
|
||||||
|
\ filter: 'CloseFilter',
|
||||||
|
\ })
|
||||||
|
let id2 = popup_create('second one', #{
|
||||||
|
\ line: 9,
|
||||||
|
\ col: 1,
|
||||||
|
\ filter: 'CloseFilter',
|
||||||
|
\ })
|
||||||
|
call assert_equal(1, popup_getpos(id1).line)
|
||||||
|
call assert_equal(9, popup_getpos(id2).line)
|
||||||
|
|
||||||
|
call feedkeys('0', 'xt')
|
||||||
|
call assert_equal({}, popup_getpos(id1))
|
||||||
|
call assert_equal({}, popup_getpos(id2))
|
||||||
|
|
||||||
|
call popup_clear()
|
||||||
|
delfunc CloseFilter
|
||||||
|
endfunc
|
||||||
|
|
||||||
" vim: shiftwidth=2 sts=2
|
" vim: shiftwidth=2 sts=2
|
||||||
|
@ -741,6 +741,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
2300,
|
||||||
/**/
|
/**/
|
||||||
2299,
|
2299,
|
||||||
/**/
|
/**/
|
||||||
|
24
src/vim.h
24
src/vim.h
@ -624,15 +624,21 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring);
|
|||||||
// Values for w_popup_flags.
|
// Values for w_popup_flags.
|
||||||
#define POPF_IS_POPUP 0x01 // this is a popup window
|
#define POPF_IS_POPUP 0x01 // this is a popup window
|
||||||
#define POPF_HIDDEN 0x02 // popup is not displayed
|
#define POPF_HIDDEN 0x02 // popup is not displayed
|
||||||
#define POPF_HANDLED 0x04 // popup was just redrawn or filtered
|
#define POPF_CURSORLINE 0x04 // popup is highlighting at the cursorline
|
||||||
#define POPF_CURSORLINE 0x08 // popup is highlighting at the cursorline
|
#define POPF_ON_CMDLINE 0x08 // popup overlaps command line
|
||||||
#define POPF_ON_CMDLINE 0x10 // popup overlaps command line
|
#define POPF_DRAG 0x10 // popup can be moved by dragging
|
||||||
#define POPF_DRAG 0x20 // popup can be moved by dragging
|
#define POPF_RESIZE 0x20 // popup can be resized by dragging
|
||||||
#define POPF_RESIZE 0x40 // popup can be resized by dragging
|
#define POPF_MAPPING 0x40 // mapping keys
|
||||||
#define POPF_MAPPING 0x80 // mapping keys
|
#define POPF_INFO 0x80 // used for info of popup menu
|
||||||
#define POPF_INFO 0x100 // used for info of popup menu
|
#define POPF_INFO_MENU 0x100 // align info popup with popup menu
|
||||||
#define POPF_INFO_MENU 0x200 // align info popup with popup menu
|
#define POPF_POSINVERT 0x200 // vertical position can be inverted
|
||||||
#define POPF_POSINVERT 0x400 // vertical position can be inverted
|
|
||||||
|
// flags used in w_popup_handled
|
||||||
|
#define POPUP_HANDLED_1 0x01 // used by mouse_find_win()
|
||||||
|
#define POPUP_HANDLED_2 0x02 // used by popup_do_filter()
|
||||||
|
#define POPUP_HANDLED_3 0x04 // used by popup_check_cursor_pos()
|
||||||
|
#define POPUP_HANDLED_4 0x08 // used by may_update_popup_mask()
|
||||||
|
#define POPUP_HANDLED_5 0x10 // used by update_popups()
|
||||||
|
|
||||||
#ifdef FEAT_TEXT_PROP
|
#ifdef FEAT_TEXT_PROP
|
||||||
# define WIN_IS_POPUP(wp) ((wp)->w_popup_flags != 0)
|
# define WIN_IS_POPUP(wp) ((wp)->w_popup_flags != 0)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user