From cf7c11a9479ba7ce775b86c7a846fae48321d260 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 2 Jun 2016 20:05:26 +0200 Subject: [PATCH] patch 7.4.1878 Problem: Whether a job has exited isn't detected until a character is typed. After calling exit_cb the cursor is in the wrong place. Solution: Don't wait forever for a character to be typed when there is a pending job. Update the screen if neede after calling exit_cb. --- src/channel.c | 21 +++++++++++++++++++++ src/os_unix.c | 16 +++++++++++++++- src/proto/channel.pro | 1 + src/version.c | 2 ++ 4 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/channel.c b/src/channel.c index 75cadae7a..5168f7410 100644 --- a/src/channel.c +++ b/src/channel.c @@ -4402,6 +4402,21 @@ job_stop_on_exit() mch_stop_job(job, job->jv_stoponexit); } +/* + * Return TRUE when there is any job that might exit, which means + * job_check_ended() should be called once in a while. + */ + int +has_pending_job() +{ + job_T *job; + + for (job = first_job; job != NULL; job = job->jv_next) + if (job->jv_status == JOB_STARTED && job_still_useful(job)) + return TRUE; + return FALSE; +} + /* * Called once in a while: check if any jobs that seem useful have ended. */ @@ -4425,6 +4440,11 @@ job_check_ended(void) job_status(job); /* may free "job" */ } } + if (channel_need_redraw) + { + channel_need_redraw = FALSE; + redraw_after_callback(); + } } /* @@ -4658,6 +4678,7 @@ job_status(job_T *job) job->jv_exit_partial, NULL); clear_tv(&rettv); --job->jv_refcount; + channel_need_redraw = TRUE; } if (job->jv_status == JOB_ENDED && job->jv_refcount == 0) { diff --git a/src/os_unix.c b/src/os_unix.c index f7b5ae4b1..b4808b5fe 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -438,17 +438,31 @@ mch_inchar( for (;;) /* repeat until we got a character */ { + long wtime_now = -1L; + while (do_resize) /* window changed size */ handle_resize(); #ifdef MESSAGE_QUEUE parse_queued_messages(); + +# ifdef FEAT_JOB_CHANNEL + if (has_pending_job()) + { + /* Don't wait longer than a few seconds, checking for a finished + * job requires polling. */ + if (p_ut > 9000L) + wtime_now = 1000L; + else + wtime_now = 10000L - p_ut; + } +# endif #endif /* * We want to be interrupted by the winch signal * or by an event on the monitored file descriptors. */ - if (!WaitForChar(-1L)) + if (!WaitForChar(wtime_now)) { if (do_resize) /* interrupted by SIGWINCH signal */ handle_resize(); diff --git a/src/proto/channel.pro b/src/proto/channel.pro index 60b68f013..2f2deb4bc 100644 --- a/src/proto/channel.pro +++ b/src/proto/channel.pro @@ -57,6 +57,7 @@ int free_unused_jobs_contents(int copyID, int mask); void free_unused_jobs(int copyID, int mask); void job_set_options(job_T *job, jobopt_T *opt); void job_stop_on_exit(void); +int has_pending_job(void); void job_check_ended(void); job_T *job_start(typval_T *argvars); char *job_status(job_T *job); diff --git a/src/version.c b/src/version.c index aeed59180..f450ba8bb 100644 --- a/src/version.c +++ b/src/version.c @@ -753,6 +753,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1878, /**/ 1877, /**/