diff options
author | Bram Moolenaar <Bram@vim.org> | 2019-06-12 22:42:41 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2019-06-12 22:42:41 +0200 |
commit | 68d48f40a4da79547b53e3164b658812e154d411 (patch) | |
tree | f105df9cab26c0ecb688974635a6bd4fc978e7be /src | |
parent | 7c7f01e2b260c75d9996ca9ab621119eafe13a63 (diff) | |
download | vim-git-68d48f40a4da79547b53e3164b658812e154d411.tar.gz |
patch 8.1.1522: poup_notification() not implemented yetv8.1.1522
Problem: Popup_notification() not implemented yet.
Solution: Implement it.
Diffstat (limited to 'src')
-rw-r--r-- | src/evalfunc.c | 1 | ||||
-rw-r--r-- | src/popupwin.c | 138 | ||||
-rw-r--r-- | src/proto/popupwin.pro | 1 | ||||
-rw-r--r-- | src/structs.h | 5 | ||||
-rw-r--r-- | src/testdir/dumps/Test_popupwin_notify_01.dump | 10 | ||||
-rw-r--r-- | src/testdir/dumps/Test_popupwin_notify_02.dump | 10 | ||||
-rw-r--r-- | src/testdir/test_popupwin.vim | 28 | ||||
-rw-r--r-- | src/version.c | 2 |
8 files changed, 163 insertions, 32 deletions
diff --git a/src/evalfunc.c b/src/evalfunc.c index 134280f6d..0ef76095f 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -819,6 +819,7 @@ static struct fst {"popup_getpos", 1, 1, f_popup_getpos}, {"popup_hide", 1, 1, f_popup_hide}, {"popup_move", 2, 2, f_popup_move}, + {"popup_notification", 2, 2, f_popup_notification}, {"popup_show", 1, 1, f_popup_show}, #endif #ifdef FEAT_FLOAT diff --git a/src/popupwin.c b/src/popupwin.c index adfa46229..d0f106fe6 100644 --- a/src/popupwin.c +++ b/src/popupwin.c @@ -110,7 +110,6 @@ get_padding_border(dict_T *dict, int *array, char *name, int max_val) { dictitem_T *di; - vim_memset(array, 0, sizeof(int) * 4); di = dict_find(dict, (char_u *)name, -1); if (di != NULL) { @@ -165,6 +164,26 @@ set_moved_columns(win_T *wp, int flags) } } + +#if defined(FEAT_TIMERS) + static void +popup_add_timeout(win_T *wp, int time) +{ + 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(time, 0); + wp->w_popup_timer->tr_callback = get_callback(&tv); + clear_tv(&tv); + } +} +#endif + /* * Go through the options in "dict" and apply them to buffer "buf" displayed in * popup window "wp". @@ -184,31 +203,22 @@ apply_options(win_T *wp, buf_T *buf UNUSED, dict_T *dict) get_pos_options(wp, dict); - wp->w_zindex = dict_get_number(dict, (char_u *)"zindex"); - if (wp->w_zindex < 1) - wp->w_zindex = POPUPWIN_DEFAULT_ZINDEX; - if (wp->w_zindex > 32000) - wp->w_zindex = 32000; + di = dict_find(dict, (char_u *)"zindex", -1); + if (di != NULL) + { + wp->w_zindex = dict_get_number(dict, (char_u *)"zindex"); + if (wp->w_zindex < 1) + wp->w_zindex = POPUPWIN_DEFAULT_ZINDEX; + if (wp->w_zindex > 32000) + wp->w_zindex = 32000; + } -# if defined(FEAT_TIMERS) +#if defined(FEAT_TIMERS) // 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 = get_callback(&tv); - clear_tv(&tv); - } - } -# endif + popup_add_timeout(wp, nr); +#endif // Option values resulting in setting an option. str = dict_get_string(dict, (char_u *)"highlight", FALSE); @@ -601,7 +611,8 @@ popup_adjust_position(win_T *wp) typedef enum { TYPE_NORMAL, - TYPE_ATCURSOR + TYPE_ATCURSOR, + TYPE_NOTIFICATION } create_type_T; /* @@ -659,7 +670,13 @@ popup_create(typval_T *argvars, typval_T *rettv, create_type_T type) // Avoid that 'buftype' is reset when this buffer is entered. buf->b_p_initialized = TRUE; - nr = (int)dict_get_number(d, (char_u *)"tab"); + if (dict_find(d, (char_u *)"tab", -1) != NULL) + nr = (int)dict_get_number(d, (char_u *)"tab"); + else if (type == TYPE_NOTIFICATION) + nr = -1; // notifications are global by default + else + nr = 0; + if (nr == 0) { // popup on current tab @@ -668,9 +685,18 @@ popup_create(typval_T *argvars, typval_T *rettv, create_type_T type) } else if (nr < 0) { - // global popup - wp->w_next = first_popupwin; - first_popupwin = wp; + win_T *prev = first_popupwin; + + // Global popup: add at the end, so that it gets displayed on top of + // older ones with the same zindex. Matters for notifications. + if (first_popupwin == NULL) + first_popupwin = wp; + else + { + while (prev->w_next != NULL) + prev = prev->w_next; + prev->w_next = wp; + } } else // TODO: find tab page "nr" @@ -720,9 +746,52 @@ popup_create(typval_T *argvars, typval_T *rettv, create_type_T type) // set default values wp->w_zindex = POPUPWIN_DEFAULT_ZINDEX; + if (type == TYPE_NOTIFICATION) + { + win_T *twp, *nextwin; + int height = buf->b_ml.ml_line_count + 3; + int i; + + // Try to not overlap with another global popup. Guess we need 3 + // more screen lines than buffer lines. + wp->w_wantline = 1; + for (twp = first_popupwin; twp != NULL; twp = nextwin) + { + nextwin = twp->w_next; + if (twp != wp + && twp->w_zindex == POPUPWIN_NOTIFICATION_ZINDEX + && twp->w_winrow <= wp->w_wantline - 1 + height + && twp->w_winrow + popup_height(twp) > wp->w_wantline - 1) + { + // move to below this popup and restart the loop to check for + // overlap with other popups + wp->w_wantline = twp->w_winrow + popup_height(twp) + 1; + nextwin = first_popupwin; + } + } + if (wp->w_wantline + height > Rows) + { + // can't avoid overlap, put on top in the hope that message goes + // away soon. + wp->w_wantline = 1; + } + + wp->w_wantcol = 10; + wp->w_zindex = POPUPWIN_NOTIFICATION_ZINDEX; + for (i = 0; i < 4; ++i) + wp->w_popup_border[i] = 1; + wp->w_popup_padding[1] = 1; + wp->w_popup_padding[3] = 1; + set_string_option_direct_in_win(wp, (char_u *)"wincolor", -1, + (char_u *)"WarningMsg", OPT_FREE|OPT_LOCAL, 0); + } + // Deal with options. apply_options(wp, buf, argvars[1].vval.v_dict); + if (type == TYPE_NOTIFICATION && wp->w_popup_timer == NULL) + popup_add_timeout(wp, 3000); + popup_adjust_position(wp); wp->w_vsep_width = 0; @@ -759,6 +828,15 @@ f_popup_atcursor(typval_T *argvars, typval_T *rettv) } /* + * popup_notification({text}, {options}) + */ + void +f_popup_notification(typval_T *argvars, typval_T *rettv) +{ + popup_create(argvars, rettv, TYPE_NOTIFICATION); +} + +/* * Find the popup window with window-ID "id". * If the popup window does not exist NULL is returned. * If the window is not a popup window, and error message is given. @@ -1017,8 +1095,10 @@ f_popup_getpos(typval_T *argvars, typval_T *rettv) dict_add_number(dict, "line", wp->w_winrow + 1); dict_add_number(dict, "col", wp->w_wincol + 1); - dict_add_number(dict, "width", wp->w_width + left_extra + wp->w_popup_border[1] + wp->w_popup_padding[1]); - dict_add_number(dict, "height", wp->w_height + top_extra + wp->w_popup_border[2] + wp->w_popup_padding[2]); + dict_add_number(dict, "width", wp->w_width + left_extra + + wp->w_popup_border[1] + wp->w_popup_padding[1]); + dict_add_number(dict, "height", wp->w_height + top_extra + + wp->w_popup_border[2] + wp->w_popup_padding[2]); dict_add_number(dict, "core_line", wp->w_winrow + 1 + top_extra); dict_add_number(dict, "core_col", wp->w_wincol + 1 + left_extra); diff --git a/src/proto/popupwin.pro b/src/proto/popupwin.pro index a27444679..03d3729ed 100644 --- a/src/proto/popupwin.pro +++ b/src/proto/popupwin.pro @@ -5,6 +5,7 @@ void popup_adjust_position(win_T *wp); void f_popup_clear(typval_T *argvars, typval_T *rettv); void f_popup_create(typval_T *argvars, typval_T *rettv); void f_popup_atcursor(typval_T *argvars, typval_T *rettv); +void f_popup_notification(typval_T *argvars, typval_T *rettv); int popup_any_visible(void); void f_popup_close(typval_T *argvars, typval_T *rettv); void f_popup_hide(typval_T *argvars, typval_T *rettv); diff --git a/src/structs.h b/src/structs.h index 8e6d93f30..1fd430965 100644 --- a/src/structs.h +++ b/src/structs.h @@ -1992,8 +1992,9 @@ typedef enum { POPPOS_CENTER } poppos_T; -# define POPUPWIN_DEFAULT_ZINDEX 50 -# define POPUPMENU_ZINDEX 100 +# define POPUPWIN_DEFAULT_ZINDEX 50 +# define POPUPMENU_ZINDEX 100 +# define POPUPWIN_NOTIFICATION_ZINDEX 200 #endif /* diff --git a/src/testdir/dumps/Test_popupwin_notify_01.dump b/src/testdir/dumps/Test_popupwin_notify_01.dump new file mode 100644 index 000000000..2ecd5ee1d --- /dev/null +++ b/src/testdir/dumps/Test_popupwin_notify_01.dump @@ -0,0 +1,10 @@ +>1+0&#ffffff0| @7|╔+0#e000002&|═@19|╗| +0#0000000&@43 +|2| @7|║+0#e000002&| |f|i|r|s|t| |n|o|t|i|f|i|c|a|t|i|o|n| |║| +0#0000000&@43 +|3| @7|╚+0#e000002&|═@19|╝| +0#0000000&@43 +|4| @73 +|5| @73 +|6| @73 +|7| @73 +|8| @73 +|9| @73 +@57|1|,|1| @10|T|o|p| diff --git a/src/testdir/dumps/Test_popupwin_notify_02.dump b/src/testdir/dumps/Test_popupwin_notify_02.dump new file mode 100644 index 000000000..10170619a --- /dev/null +++ b/src/testdir/dumps/Test_popupwin_notify_02.dump @@ -0,0 +1,10 @@ +>1+0&#ffffff0| @7|╔+0#e000002&|═@19|╗| +0#0000000&@43 +|2| @7|║+0#e000002&| |f|i|r|s|t| |n|o|t|i|f|i|c|a|t|i|o|n| |║| +0#0000000&@43 +|3| @7|╚+0#e000002&|═@19|╝| +0#0000000&@43 +|4| @7|╔+0fd7ff255|═@31|╗| +0&#ffffff0@31 +|5| @7|║+0fd7ff255| |a|n|o|t|h|e|r| |i|m|p|o|r|t|a|n|t| |n|o|t|i|f|i|c|a|t|i|o|n| |║| +0&#ffffff0@31 +|6| @7|╚+0fd7ff255|═@31|╝| +0&#ffffff0@31 +|7| @73 +|8| @73 +|9| @73 +@57|1|,|1| @10|T|o|p| diff --git a/src/testdir/test_popupwin.vim b/src/testdir/test_popupwin.vim index d100dc993..9afd84033 100644 --- a/src/testdir/test_popupwin.vim +++ b/src/testdir/test_popupwin.vim @@ -428,7 +428,7 @@ endfunc func Test_popup_time() if !has('timers') - return + throw 'Skipped, timer feature not supported' endif topleft vnew call setline(1, 'hello') @@ -1086,3 +1086,29 @@ func Test_popup_moved() bwipe! call test_override('ALL', 0) endfunc + +func Test_notifications() + if !has('timers') + throw 'Skipped, timer feature not supported' + endif + if !CanRunVimInTerminal() + throw 'Skipped: cannot make screendumps' + endif + + call writefile([ + \ "call setline(1, range(1, 20))", + \ "hi Notification ctermbg=lightblue", + \ "call popup_notification('first notification', {})", + \], 'XtestNotifications') + let buf = RunVimInTerminal('-S XtestNotifications', {'rows': 10}) + call VerifyScreenDump(buf, 'Test_popupwin_notify_01', {}) + + " second one goes below the first one + call term_sendkeys(buf, ":call popup_notification('another important notification', {'highlight': 'Notification'})\<CR>") + call VerifyScreenDump(buf, 'Test_popupwin_notify_02', {}) + + + " clean up + call StopVimInTerminal(buf) + call delete('XtestNotifications') +endfunc diff --git a/src/version.c b/src/version.c index 28877cb56..9c4d0688a 100644 --- a/src/version.c +++ b/src/version.c @@ -778,6 +778,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1522, +/**/ 1521, /**/ 1520, |