changeset 19275:2142fb624658 v8.2.0196

patch 8.2.0196: blocking commands for a finished job in a popup window Commit: https://github.com/vim/vim/commit/d98c0b63abd7b0e61a383669474abe96044615af Author: Bram Moolenaar <Bram@vim.org> Date: Sun Feb 2 15:25:16 2020 +0100 patch 8.2.0196: blocking commands for a finished job in a popup window Problem: Blocking commands for a finished job in a popup window. Solution: Do not block commands if the job has finished. Adjust test.
author Bram Moolenaar <Bram@vim.org>
date Sun, 02 Feb 2020 15:30:04 +0100
parents ca1f1b78a0b4
children c062923a350f
files src/popupwin.c src/proto/terminal.pro src/terminal.c src/testdir/test_popupwin.vim src/version.c src/window.c
diffstat 6 files changed, 56 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/src/popupwin.c
+++ b/src/popupwin.c
@@ -2863,10 +2863,15 @@ error_if_popup_window(int also_with_term
 }
 
 # if defined(FEAT_TERMINAL) || defined(PROTO)
+/*
+ * Return TRUE if the current window is running a terminal in a popup window.
+ * Return FALSE when the job has ended.
+ */
     int
 error_if_term_popup_window()
 {
-    if (WIN_IS_POPUP(curwin) && curbuf->b_term != NULL)
+    if (WIN_IS_POPUP(curwin) && curbuf->b_term != NULL
+					   && term_job_running(curbuf->b_term))
     {
 	emsg(_("E899: Not allowed for a terminal in a popup window"));
 	return TRUE;
--- a/src/proto/terminal.pro
+++ b/src/proto/terminal.pro
@@ -19,6 +19,7 @@ cursorentry_T *term_get_cursor_shape(gui
 int term_use_loop(void);
 void term_win_entered(void);
 int terminal_loop(int blocking);
+int may_close_term_popup(void);
 void term_channel_closed(channel_T *ch);
 void term_check_channel_closed_recently(void);
 int term_do_update_window(win_T *wp);
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -3260,6 +3260,29 @@ term_after_channel_closed(term_T *term)
     return FALSE;
 }
 
+#if defined(FEAT_PROP_POPUP) || defined(PROTO)
+/*
+ * If the current window is a terminal in a popup window and the job has
+ * finished, close the popup window and to back to the previous window.
+ * Otherwise return FAIL.
+ */
+    int
+may_close_term_popup(void)
+{
+    if (popup_is_popup(curwin) && curbuf->b_term != NULL
+					  && !term_job_running(curbuf->b_term))
+    {
+	win_T *pwin = curwin;
+
+	if (win_valid(prevwin))
+	    win_enter(prevwin, FALSE);
+	popup_close_with_retval(pwin, 0);
+	return OK;
+    }
+    return FAIL;
+}
+#endif
+
 /*
  * Called when a channel has been closed.
  * If this was a channel for a terminal window then finish it up.
--- a/src/testdir/test_popupwin.vim
+++ b/src/testdir/test_popupwin.vim
@@ -2396,10 +2396,20 @@ endfunc
 
 func Test_popupwin_terminal_buffer()
   CheckFeature terminal
-
+  CheckUnix
+
+  let origwin = win_getid()
   let ptybuf = term_start(&shell, #{hidden: 1})
-  call assert_fails('let winnr = popup_create(ptybuf, #{})', 'E278:')
-  exe 'bwipe! ' .. ptybuf
+  let winnr = popup_create(ptybuf, #{minwidth: 40, minheight: 10})
+  " Wait for shell to start
+  sleep 200m
+  " Cannot quit while job is running
+  call assert_fails('call feedkeys("\<C-W>:quit\<CR>", "xt")', 'E948:')
+  call feedkeys("exit\<CR>", 'xt')
+  " Wait for shell to exit
+  sleep 100m
+  call feedkeys(":quit\<CR>", 'xt')
+  call assert_equal(origwin, win_getid())
 endfunc
 
 func Test_popupwin_with_buffer_and_filter()
--- a/src/version.c
+++ b/src/version.c
@@ -743,6 +743,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    196,
+/**/
     195,
 /**/
     194,
--- a/src/window.c
+++ b/src/window.c
@@ -2441,6 +2441,11 @@ win_close(win_T *win, int free_buf)
     int		had_diffmode = win->w_p_diff;
 #endif
 
+#if defined(FEAT_TERMINAL) && defined(FEAT_PROP_POPUP)
+    // Can close a popup window with a terminal if the job has finished.
+    if (may_close_term_popup() == OK)
+	return OK;
+#endif
     if (ERROR_IF_ANY_POPUP_WINDOW)
 	return FAIL;
 
@@ -6439,6 +6444,12 @@ only_one_window(void)
     int		count = 0;
     win_T	*wp;
 
+#if defined(FEAT_PROP_POPUP)
+    // If the current window is a popup then there always is another window.
+    if (popup_is_popup(curwin))
+	return FALSE;
+#endif
+
     // If there is another tab page there always is another window.
     if (first_tabpage->tp_next != NULL)
 	return FALSE;