# HG changeset patch # User Bram Moolenaar # Date 1580653804 -3600 # Node ID 2142fb62465897aa87515b5107dc155d121fcab9 # Parent ca1f1b78a0b48ec12d98e145bbb7e704ed802b93 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 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. diff --git a/src/popupwin.c b/src/popupwin.c --- 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; diff --git a/src/proto/terminal.pro b/src/proto/terminal.pro --- 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); diff --git a/src/terminal.c b/src/terminal.c --- 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. 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 @@ -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("\:quit\", "xt")', 'E948:') + call feedkeys("exit\", 'xt') + " Wait for shell to exit + sleep 100m + call feedkeys(":quit\", 'xt') + call assert_equal(origwin, win_getid()) endfunc func Test_popupwin_with_buffer_and_filter() diff --git a/src/version.c b/src/version.c --- 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, diff --git a/src/window.c b/src/window.c --- 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;