Skip to content

Commit 9eaac89

Browse files
committed
patch 8.1.1446: popup window callback not implemented yet
Problem: Popup window callback not implemented yet. Solution: Implement the callback.
1 parent 790498b commit 9eaac89

7 files changed

Lines changed: 79 additions & 8 deletions

File tree

runtime/doc/popup.txt

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ Probably 2. is the best choice.
9090

9191
IMPLEMENTATION:
9292
- Code is in popupwin.c
93+
- Fix positioning with border and padding.
9394
- Why does 'nrformats' leak from the popup window buffer???
9495
- Make redrawing more efficient and avoid flicker.
9596
Store popup info in a mask, use the mask in screen_line()
@@ -133,10 +134,15 @@ popup_create({text}, {options}) *popup_create()*
133134
< In case of failure zero is returned.
134135

135136

136-
popup_close({id}) *popup_close()*
137+
popup_close({id} [, {result}]) *popup_close()*
137138
Close popup {id}. The window and the associated buffer will
138139
be deleted.
139140

141+
If the popup has a callback it will be called just before the
142+
popup window is deleted. If the optional {result} is present
143+
it will be passed as the second argument of the callback.
144+
Otherwise zero is passed to the callback.
145+
140146

141147
popup_dialog({text}, {options}) *popup_dialog()*
142148
{not implemented yet}
@@ -145,6 +151,7 @@ popup_dialog({text}, {options}) *popup_dialog()*
145151
\ 'pos': 'center',
146152
\ 'zindex': 200,
147153
\ 'border': [],
154+
\ 'padding': [],
148155
\})
149156
< Use {options} to change the properties.
150157

@@ -166,6 +173,7 @@ popup_notification({text}, {options}) *popup_notification()*
166173

167174

168175
popup_atcursor({text}, {options}) *popup_atcursor()*
176+
{not implemented yet: close when cursor moves}
169177
Show the {text} above the cursor, and close it when the cursor
170178
moves. This works like: >
171179
call popup_create({text}, {
@@ -394,7 +402,6 @@ The second argument of |popup_create()| is a dictionary with options:
394402
|popup-filter|
395403
callback a callback to be used when the popup closes, e.g. when
396404
using |popup_filter_menu()|, see |popup-callback|.
397-
{not implemented yet}
398405

399406
Depending on the "zindex" the popup goes under or above other popups. The
400407
completion menu (|popup-menu|) has zindex 100. For messages that occur for a
@@ -477,11 +484,12 @@ Vim recognizes the Esc key. If you do use Esc, it is reecommended to set the
477484

478485
POPUP CALLBACK *popup-callback*
479486

480-
{not implemented yet}
481487
A callback that is invoked when the popup closes. Used by
482-
|popup_filter_menu()|. Invoked with two arguments: the ID of the popup and
483-
the result, which would usually be an index in the popup lines, or whatever
484-
the filter wants to pass.
488+
|popup_filter_menu()|.
489+
490+
The callback is invoked with two arguments: the ID of the popup window and the
491+
result, which could be an index in the popup lines, or whatever was passed as
492+
the second argument of `popup_close()`.
485493

486494
==============================================================================
487495
3. Examples *popup-examples*

src/evalfunc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -810,7 +810,7 @@ static struct fst
810810
#endif
811811
#ifdef FEAT_TEXT_PROP
812812
{"popup_atcursor", 2, 2, f_popup_atcursor},
813-
{"popup_close", 1, 1, f_popup_close},
813+
{"popup_close", 1, 2, f_popup_close},
814814
{"popup_create", 2, 2, f_popup_create},
815815
{"popup_getoptions", 1, 1, f_popup_getoptions},
816816
{"popup_getpos", 1, 1, f_popup_getpos},

src/popupwin.c

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,15 @@ apply_options(win_T *wp, buf_T *buf UNUSED, dict_T *dict, int atcursor)
201201
wp->w_p_wrap = nr != 0;
202202
}
203203

204+
di = dict_find(dict, (char_u *)"callback", -1);
205+
if (di != NULL)
206+
{
207+
callback_T callback = get_callback(&di->di_tv);
208+
209+
if (callback.cb_name != NULL)
210+
set_callback(&wp->w_close_cb, &callback);
211+
}
212+
204213
di = dict_find(dict, (char_u *)"filter", -1);
205214
if (di != NULL)
206215
{
@@ -631,15 +640,54 @@ popup_any_visible(void)
631640
return FALSE;
632641
}
633642

643+
/*
644+
* Invoke the close callback for window "wp" with value "result".
645+
* Careful: The callback may make "wp" invalid!
646+
*/
647+
static void
648+
invoke_popup_callback(win_T *wp, typval_T *result)
649+
{
650+
typval_T rettv;
651+
int dummy;
652+
typval_T argv[3];
653+
654+
argv[0].v_type = VAR_NUMBER;
655+
argv[0].vval.v_number = (varnumber_T)wp->w_id;
656+
657+
if (result != NULL && result->v_type != VAR_UNKNOWN)
658+
copy_tv(result, &argv[1]);
659+
else
660+
{
661+
argv[1].v_type = VAR_NUMBER;
662+
argv[1].vval.v_number = 0;
663+
}
664+
665+
argv[2].v_type = VAR_UNKNOWN;
666+
667+
call_callback(&wp->w_close_cb, -1,
668+
&rettv, 2, argv, NULL, 0L, 0L, &dummy, TRUE, NULL);
669+
if (result != NULL)
670+
clear_tv(&argv[1]);
671+
clear_tv(&rettv);
672+
}
673+
634674
/*
635675
* popup_close({id})
636676
*/
637677
void
638678
f_popup_close(typval_T *argvars, typval_T *rettv UNUSED)
639679
{
640680
int id = (int)tv_get_number(argvars);
681+
win_T *wp = find_popup_win(id);
682+
683+
if (wp != NULL)
684+
{
685+
if (wp->w_close_cb.cb_name != NULL)
686+
// Careful: This may make "wp" invalid.
687+
invoke_popup_callback(wp, &argvars[1]);
641688

642-
popup_close(id);
689+
popup_close(id);
690+
}
643691
}
644692

645693
/*
@@ -688,6 +736,7 @@ popup_free(win_T *wp)
688736

689737
/*
690738
* Close a popup window by Window-id.
739+
* Does not invoke the callback.
691740
*/
692741
void
693742
popup_close(int id)

src/structs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2894,6 +2894,7 @@ struct window_S
28942894
int w_border_char[8]; // popup border characters
28952895
varnumber_T w_popup_last_changedtick; // b:changedtick when position was
28962896
// computed
2897+
callback_T w_close_cb; // popup close callback
28972898
callback_T w_filter_cb; // popup filter callback
28982899
# if defined(FEAT_TIMERS)
28992900
timer_T *w_popup_timer; // timer for closing popup window

src/testdir/test_popupwin.vim

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,3 +586,13 @@ func Test_popup_filter()
586586
delfunc MyPopupFilter
587587
popupclear
588588
endfunc
589+
590+
func Test_popup_close_callback()
591+
func PopupDone(id, result)
592+
let g:result = a:result
593+
endfunc
594+
let winid = popup_create('something', {'callback': 'PopupDone'})
595+
redraw
596+
call popup_close(winid, 'done')
597+
call assert_equal('done', g:result)
598+
endfunc

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -767,6 +767,8 @@ static char *(features[]) =
767767

768768
static int included_patches[] =
769769
{ /* Add new patch number below this line */
770+
/**/
771+
1446,
770772
/**/
771773
1445,
772774
/**/

src/window.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4845,6 +4845,7 @@ win_free(
48454845
remove_winbar(wp);
48464846
#endif
48474847
#ifdef FEAT_TEXT_PROP
4848+
free_callback(&wp->w_close_cb);
48484849
free_callback(&wp->w_filter_cb);
48494850
for (i = 0; i < 4; ++i)
48504851
VIM_CLEAR(wp->w_border_highlight[i]);

0 commit comments

Comments
 (0)