# HG changeset patch # User Bram Moolenaar # Date 1558894505 -7200 # Node ID 12e3a3afdb6aefc0befb49ab351911210fd7f4a2 # Parent 3c72f9c278b5f442baaa9c78e24c2bde13233a69 patch 8.1.1402: "timer" option of popup windows not supported commit https://github.com/vim/vim/commit/51fe3b14f63da2b985bcd7b4c50fbe34ae84ea48 Author: Bram Moolenaar Date: Sun May 26 20:10:06 2019 +0200 patch 8.1.1402: "timer" option of popup windows not supported Problem: "timer" option of popup windows not supported. Solution: Implement the "timer" option. (Yasuhiro Matsumoto, closes https://github.com/vim/vim/issues/4439) diff --git a/runtime/doc/popup.txt b/runtime/doc/popup.txt --- a/runtime/doc/popup.txt +++ b/runtime/doc/popup.txt @@ -142,7 +142,7 @@ popup_notification({text}, {options}) \ 'tab': -1, \ 'zindex': 200, \ 'highlight': 'WarningMsg', - \ 'border: [], + \ 'border': [], \ }) < Use {options} to change the properties. @@ -339,7 +339,6 @@ The second argument of |popup_create()| zindex priority for the popup, default 50 time time in milliseconds after which the popup will close; when omitted |popup_close()| must be used. - {not implemented yet} moved "cell": close the popup if the cursor moved at least one screen cell; "word" allows for moving within ||, "WORD" allows for moving within ||, diff --git a/src/popupwin.c b/src/popupwin.c --- a/src/popupwin.c +++ b/src/popupwin.c @@ -22,11 +22,34 @@ static void apply_options(win_T *wp, buf_T *buf UNUSED, dict_T *dict) { + int nr; + wp->w_maxwidth = dict_get_number(dict, (char_u *)"maxwidth"); wp->w_maxheight = dict_get_number(dict, (char_u *)"maxheight"); wp->w_winrow = dict_get_number(dict, (char_u *)"line"); wp->w_wincol = dict_get_number(dict, (char_u *)"col"); wp->w_zindex = dict_get_number(dict, (char_u *)"zindex"); + + // Add timer to close the popup after some time. + nr = dict_get_number(dict, (char_u *)"time"); + if (nr > 0) + { + char_u cbbuf[50]; + char_u *ptr = cbbuf; + typval_T tv; + + vim_snprintf((char *)cbbuf, sizeof(cbbuf), + "{_ -> popup_close(%d)}", wp->w_id); + if (get_lambda_tv(&ptr, &tv, TRUE) == OK) + { + wp->w_popup_timer = create_timer(nr, 0); + wp->w_popup_timer->tr_callback = + vim_strsave(partial_name(tv.vval.v_partial)); + func_ref(wp->w_popup_timer->tr_callback); + wp->w_popup_timer->tr_partial = tv.vval.v_partial; + } + } + } /* @@ -177,6 +200,15 @@ f_popup_close(typval_T *argvars, typval_ popup_close(nr); } + static void +popup_undisplay(win_T *wp) +{ + if (wp->w_winrow + wp->w_height >= cmdline_row) + clear_cmdline = TRUE; + win_free_popup(wp); + redraw_all_later(NOT_VALID); +} + /* * Close a popup window by Window-id. */ @@ -195,8 +227,7 @@ popup_close(int id) first_popupwin = wp->w_next; else prev->w_next = wp->w_next; - win_free_popup(wp); - redraw_all_later(NOT_VALID); + popup_undisplay(wp); return; } @@ -222,8 +253,7 @@ popup_close_tabpage(tabpage_T *tp, int i *root = wp->w_next; else prev->w_next = wp->w_next; - win_free_popup(wp); - redraw_all_later(NOT_VALID); + popup_undisplay(wp); return; } } diff --git a/src/structs.h b/src/structs.h --- a/src/structs.h +++ b/src/structs.h @@ -1941,6 +1941,24 @@ typedef struct { } syn_time_T; #endif +typedef struct timer_S timer_T; +struct timer_S +{ + long tr_id; +#ifdef FEAT_TIMERS + timer_T *tr_next; + timer_T *tr_prev; + proftime_T tr_due; /* when the callback is to be invoked */ + char tr_firing; /* when TRUE callback is being called */ + char tr_paused; /* when TRUE callback is not invoked */ + int tr_repeat; /* number of times to repeat, -1 forever */ + long tr_interval; /* msec */ + char_u *tr_callback; /* allocated */ + partial_T *tr_partial; + int tr_emsg_count; +#endif +}; + #ifdef FEAT_CRYPT /* * Structure to hold the type of encryption and the state of encryption or @@ -2856,6 +2874,7 @@ struct window_S int w_zindex; int w_maxheight; // "maxheight" for popup window int w_maxwidth; // "maxwidth" for popup window + timer_T *w_popup_timer; // timer for closing popup window #endif @@ -3434,24 +3453,6 @@ struct js_reader }; typedef struct js_reader js_read_T; -typedef struct timer_S timer_T; -struct timer_S -{ - long tr_id; -#ifdef FEAT_TIMERS - timer_T *tr_next; - timer_T *tr_prev; - proftime_T tr_due; /* when the callback is to be invoked */ - char tr_firing; /* when TRUE callback is being called */ - char tr_paused; /* when TRUE callback is not invoked */ - int tr_repeat; /* number of times to repeat, -1 forever */ - long tr_interval; /* msec */ - char_u *tr_callback; /* allocated */ - partial_T *tr_partial; - int tr_emsg_count; -#endif -}; - /* Maximum number of commands from + or -c arguments. */ #define MAX_ARG_CMDS 10 diff --git a/src/testdir/test_popupwin.vim b/src/testdir/test_popupwin.vim --- a/src/testdir/test_popupwin.vim +++ b/src/testdir/test_popupwin.vim @@ -37,3 +37,37 @@ func Test_simple_popup() call StopVimInTerminal(buf) call delete('XtestPopup') endfunc + +func Test_popup_time() + topleft vnew + call setline(1, 'hello') + + call popup_create('world', { + \ 'line': 1, + \ 'col': 1, + \ 'time': 500, + \}) + redraw + let line = join(map(range(1, 5), 'screenstring(1, v:val)'), '') + call assert_equal('world', line) + + sleep 700m + let line = join(map(range(1, 5), 'screenstring(1, v:val)'), '') + call assert_equal('hello', line) + + call popup_create('on the command line', { + \ 'line': &lines, + \ 'col': 10, + \ 'time': 500, + \}) + redraw + let line = join(map(range(1, 30), 'screenstring(&lines, v:val)'), '') + call assert_match('.*on the command line.*', line) + + sleep 700m + redraw + let line = join(map(range(1, 30), 'screenstring(&lines, v:val)'), '') + call assert_notmatch('.*on the command line.*', line) + + bwipe! +endfunc diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -768,6 +768,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1402, +/**/ 1401, /**/ 1400, diff --git a/src/window.c b/src/window.c --- a/src/window.c +++ b/src/window.c @@ -3670,12 +3670,8 @@ free_tabpage(tabpage_T *tp) diff_clear(tp); # endif # ifdef FEAT_TEXT_PROP - { - win_T *wp; - - while (tp->tp_first_popupwin != NULL) - popup_close_tabpage(tp, tp->tp_first_popupwin->w_id); - } + while (tp->tp_first_popupwin != NULL) + popup_close_tabpage(tp, tp->tp_first_popupwin->w_id); #endif for (idx = 0; idx < SNAP_COUNT; ++idx) clear_snapshot(tp, idx); @@ -4871,6 +4867,8 @@ win_unlisted(win_T *wp) win_free_popup(win_T *win) { win_close_buffer(win, TRUE, FALSE); + if (win->w_popup_timer != NULL) + stop_timer(win->w_popup_timer); vim_free(win->w_frame); win_free(win, NULL); }