patch 8.1.1446: popup window callback not implemented yet
Problem: Popup window callback not implemented yet.
Solution: Implement the callback.
diff --git a/src/evalfunc.c b/src/evalfunc.c
index ccb8b3e..bc60567 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -810,7 +810,7 @@
#endif
#ifdef FEAT_TEXT_PROP
{"popup_atcursor", 2, 2, f_popup_atcursor},
- {"popup_close", 1, 1, f_popup_close},
+ {"popup_close", 1, 2, f_popup_close},
{"popup_create", 2, 2, f_popup_create},
{"popup_getoptions", 1, 1, f_popup_getoptions},
{"popup_getpos", 1, 1, f_popup_getpos},
diff --git a/src/popupwin.c b/src/popupwin.c
index 810987a..dc3b564 100644
--- a/src/popupwin.c
+++ b/src/popupwin.c
@@ -201,6 +201,15 @@
wp->w_p_wrap = nr != 0;
}
+ di = dict_find(dict, (char_u *)"callback", -1);
+ if (di != NULL)
+ {
+ callback_T callback = get_callback(&di->di_tv);
+
+ if (callback.cb_name != NULL)
+ set_callback(&wp->w_close_cb, &callback);
+ }
+
di = dict_find(dict, (char_u *)"filter", -1);
if (di != NULL)
{
@@ -632,14 +641,53 @@
}
/*
+ * Invoke the close callback for window "wp" with value "result".
+ * Careful: The callback may make "wp" invalid!
+ */
+ static void
+invoke_popup_callback(win_T *wp, typval_T *result)
+{
+ typval_T rettv;
+ int dummy;
+ typval_T argv[3];
+
+ argv[0].v_type = VAR_NUMBER;
+ argv[0].vval.v_number = (varnumber_T)wp->w_id;
+
+ if (result != NULL && result->v_type != VAR_UNKNOWN)
+ copy_tv(result, &argv[1]);
+ else
+ {
+ argv[1].v_type = VAR_NUMBER;
+ argv[1].vval.v_number = 0;
+ }
+
+ argv[2].v_type = VAR_UNKNOWN;
+
+ call_callback(&wp->w_close_cb, -1,
+ &rettv, 2, argv, NULL, 0L, 0L, &dummy, TRUE, NULL);
+ if (result != NULL)
+ clear_tv(&argv[1]);
+ clear_tv(&rettv);
+}
+
+/*
* popup_close({id})
*/
void
f_popup_close(typval_T *argvars, typval_T *rettv UNUSED)
{
int id = (int)tv_get_number(argvars);
+ win_T *wp = find_popup_win(id);
- popup_close(id);
+ if (wp != NULL)
+ {
+ if (wp->w_close_cb.cb_name != NULL)
+ // Careful: This may make "wp" invalid.
+ invoke_popup_callback(wp, &argvars[1]);
+
+ popup_close(id);
+ }
}
/*
@@ -688,6 +736,7 @@
/*
* Close a popup window by Window-id.
+ * Does not invoke the callback.
*/
void
popup_close(int id)
diff --git a/src/structs.h b/src/structs.h
index f6db264..2100135 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -2894,6 +2894,7 @@
int w_border_char[8]; // popup border characters
varnumber_T w_popup_last_changedtick; // b:changedtick when position was
// computed
+ callback_T w_close_cb; // popup close callback
callback_T w_filter_cb; // popup filter callback
# if defined(FEAT_TIMERS)
timer_T *w_popup_timer; // timer for closing popup window
diff --git a/src/testdir/test_popupwin.vim b/src/testdir/test_popupwin.vim
index 6a2ef24..6e05919 100644
--- a/src/testdir/test_popupwin.vim
+++ b/src/testdir/test_popupwin.vim
@@ -586,3 +586,13 @@
delfunc MyPopupFilter
popupclear
endfunc
+
+func Test_popup_close_callback()
+ func PopupDone(id, result)
+ let g:result = a:result
+ endfunc
+ let winid = popup_create('something', {'callback': 'PopupDone'})
+ redraw
+ call popup_close(winid, 'done')
+ call assert_equal('done', g:result)
+endfunc
diff --git a/src/version.c b/src/version.c
index 3be4e65..597fb90 100644
--- a/src/version.c
+++ b/src/version.c
@@ -768,6 +768,8 @@
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1446,
+/**/
1445,
/**/
1444,
diff --git a/src/window.c b/src/window.c
index e15b311..f4ef983 100644
--- a/src/window.c
+++ b/src/window.c
@@ -4845,6 +4845,7 @@
remove_winbar(wp);
#endif
#ifdef FEAT_TEXT_PROP
+ free_callback(&wp->w_close_cb);
free_callback(&wp->w_filter_cb);
for (i = 0; i < 4; ++i)
VIM_CLEAR(wp->w_border_highlight[i]);