summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2019-06-12 22:42:41 +0200
committerBram Moolenaar <Bram@vim.org>2019-06-12 22:42:41 +0200
commit68d48f40a4da79547b53e3164b658812e154d411 (patch)
treef105df9cab26c0ecb688974635a6bd4fc978e7be /src
parent7c7f01e2b260c75d9996ca9ab621119eafe13a63 (diff)
downloadvim-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.c1
-rw-r--r--src/popupwin.c138
-rw-r--r--src/proto/popupwin.pro1
-rw-r--r--src/structs.h5
-rw-r--r--src/testdir/dumps/Test_popupwin_notify_01.dump10
-rw-r--r--src/testdir/dumps/Test_popupwin_notify_02.dump10
-rw-r--r--src/testdir/test_popupwin.vim28
-rw-r--r--src/version.c2
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|╔+0&#5fd7ff255|═@31|╗| +0&#ffffff0@31
+|5| @7|║+0&#5fd7ff255| |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|╚+0&#5fd7ff255|═@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,