}
/*
- * 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.
+ * Each calling function should use a different flag, see the list at
+ * POPUP_HANDLED_1. This won't work with recursive calls though.
*/
void
-popup_reset_handled()
+popup_reset_handled(int handled_flag)
{
win_T *wp;
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)
- 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.
* When "lowest" is TRUE find the popup with the lowest zindex, otherwise the
* popup with the highest zindex.
*/
win_T *
-find_next_popup(int lowest)
+find_next_popup(int lowest, int handled_flag)
{
win_T *wp;
win_T *found_wp;
found_zindex = lowest ? INT_MAX : 0;
found_wp = NULL;
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
- : wp->w_zindex > found_zindex))
+ : wp->w_zindex > found_zindex))
{
found_zindex = wp->w_zindex;
found_wp = wp;
}
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
- : wp->w_zindex > found_zindex))
+ : wp->w_zindex > found_zindex))
{
found_zindex = wp->w_zindex;
found_wp = wp;
}
if (found_wp != NULL)
- found_wp->w_popup_flags |= POPF_HANDLED;
+ found_wp->w_popup_handled |= handled_flag;
return found_wp;
}
{
set_vim_var_nr(VV_MOUSE_LNUM, 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);
clear_tv(&rettv);
res = TRUE;
}
- popup_reset_handled();
+ popup_reset_handled(POPUP_HANDLED_2);
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
&& (wp->w_filter_mode & state) != 0)
res = invoke_popup_filter(wp, c);
{
win_T *wp;
- popup_reset_handled();
- while ((wp = find_next_popup(TRUE)) != NULL)
+ popup_reset_handled(POPUP_HANDLED_3);
+ while ((wp = find_next_popup(TRUE, POPUP_HANDLED_3)) != NULL)
if (wp->w_popup_curwin != NULL
&& (curwin != wp->w_popup_curwin
|| curwin->w_cursor.lnum != wp->w_popup_lnum
// 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
// popup_mask.
- popup_reset_handled();
- while ((wp = find_next_popup(TRUE)) != NULL)
+ popup_reset_handled(POPUP_HANDLED_4);
+ while ((wp = find_next_popup(TRUE, POPUP_HANDLED_4)) != NULL)
{
int width;
int height;
// 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
// top.
- popup_reset_handled();
- while ((wp = find_next_popup(TRUE)) != NULL)
+ popup_reset_handled(POPUP_HANDLED_5);
+ while ((wp = find_next_popup(TRUE, POPUP_HANDLED_5)) != NULL)
{
// 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
call assert_equal({}, popup_getpos(win3))
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
// Values for w_popup_flags.
#define POPF_IS_POPUP 0x01 // this is a popup window
#define POPF_HIDDEN 0x02 // popup is not displayed
-#define POPF_HANDLED 0x04 // popup was just redrawn or filtered
-#define POPF_CURSORLINE 0x08 // popup is highlighting at the cursorline
-#define POPF_ON_CMDLINE 0x10 // popup overlaps command line
-#define POPF_DRAG 0x20 // popup can be moved by dragging
-#define POPF_RESIZE 0x40 // popup can be resized by dragging
-#define POPF_MAPPING 0x80 // mapping keys
-#define POPF_INFO 0x100 // used for info of popup menu
-#define POPF_INFO_MENU 0x200 // align info popup with popup menu
-#define POPF_POSINVERT 0x400 // vertical position can be inverted
+#define POPF_CURSORLINE 0x04 // popup is highlighting at the cursorline
+#define POPF_ON_CMDLINE 0x08 // popup overlaps command line
+#define POPF_DRAG 0x10 // popup can be moved by dragging
+#define POPF_RESIZE 0x20 // popup can be resized by dragging
+#define POPF_MAPPING 0x40 // mapping keys
+#define POPF_INFO 0x80 // used for info of popup menu
+#define POPF_INFO_MENU 0x100 // align info popup with popup menu
+#define POPF_POSINVERT 0x200 // 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
# define WIN_IS_POPUP(wp) ((wp)->w_popup_flags != 0)