From b13501f7dada4154fc7633d79989d1dab98ae99d Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 22 Jul 2017 22:32:56 +0200 Subject: patch 8.0.0753: no size reports to a job running in a terminal Problem: A job running in a terminal does not get notified of changes in the terminal size. Solution: Use ioctl() and SIGWINCH to report the terminal size. --- src/os_unix.c | 42 ++++++++++++++++++++++++++++++++++++++++++ src/proto/os_unix.pro | 1 + src/terminal.c | 36 +++++++++++++++++++++++++++++------- src/version.c | 2 ++ 4 files changed, 74 insertions(+), 7 deletions(-) diff --git a/src/os_unix.c b/src/os_unix.c index 4caf38bb40..f2ab7b15e2 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -3918,6 +3918,44 @@ mch_get_shellsize(void) return OK; } +#if defined(FEAT_TERMINAL) || defined(PROTO) +/* + * Report the windows size "rows" and "cols" to tty "fd". + */ + int +mch_report_winsize(int fd, int rows, int cols) +{ +# ifdef TIOCSWINSZ + struct winsize ws; + + ws.ws_col = cols; + ws.ws_row = rows; + ws.ws_xpixel = cols * 5; + ws.ws_ypixel = rows * 10; + if (ioctl(fd, TIOCSWINSZ, &ws) == 0) + { + ch_log(NULL, "ioctl(TIOCSWINSZ) success"); + return OK; + } + ch_log(NULL, "ioctl(TIOCSWINSZ) failed"); +# else +# ifdef TIOCSSIZE + struct ttysize ts; + + ts.ts_cols = cols; + ts.ts_lines = rows; + if (ioctl(fd, TIOCSSIZE, &ws) == 0) + { + ch_log(NULL, "ioctl(TIOCSSIZE) success"); + return OK; + } + ch_log(NULL, "ioctl(TIOCSSIZE) failed"); +# endif +# endif + return FAIL; +} +#endif + /* * Try to set the window size to Rows and Columns. */ @@ -5473,6 +5511,10 @@ mch_stop_job(job_T *job, char_u *how) sig = SIGINT; else if (STRCMP(how, "kill") == 0) sig = SIGKILL; +#ifdef SIGWINCH + else if (STRCMP(how, "winch") == 0) + sig = SIGWINCH; +#endif else if (isdigit(*how)) sig = atoi((char *)how); else diff --git a/src/proto/os_unix.pro b/src/proto/os_unix.pro index 11191c95b6..cfdf0ed0d7 100644 --- a/src/proto/os_unix.pro +++ b/src/proto/os_unix.pro @@ -53,6 +53,7 @@ void mch_setmouse(int on); void check_mouse_termcode(void); int mch_screenmode(char_u *arg); int mch_get_shellsize(void); +int mch_report_winsize(int fd, int rows, int cols); void mch_set_shellsize(void); void mch_new_shellsize(void); int mch_parse_cmd(char_u *cmd, int use_shcf, char ***argv, int *argc); diff --git a/src/terminal.c b/src/terminal.c index 212b4000d1..f3cb124280 100644 --- a/src/terminal.c +++ b/src/terminal.c @@ -12,10 +12,11 @@ * * There are three parts: * 1. Generic code for all systems. + * Uses libvterm for the terminal emulator. * 2. The MS-Windows implementation. - * Uses a hidden console for the terminal emulator. + * Uses winpty. * 3. The Unix-like implementation. - * Uses libvterm for the terminal emulator directly. + * Uses pseudo-tty's (pty's). * * For each terminal one VTerm is constructed. This uses libvterm. A copy of * that library is in the libvterm directory. @@ -32,8 +33,6 @@ * while, if the terminal window is visible, the screen contents is drawn. * * TODO: - * - When 'termsize' is set and dragging the separator the terminal gets messed - * up. * - set buffer options to be scratch, hidden, nomodifiable, etc. * - set buffer name to command, add (1) to avoid duplicates. * - Add a scrollback buffer (contains lines to scroll off the top). @@ -605,9 +604,32 @@ term_update_window(win_T *wp) */ if ((!term->tl_rows_fixed && term->tl_rows != wp->w_height) || (!term->tl_cols_fixed && term->tl_cols != wp->w_width)) - vterm_set_size(vterm, - term->tl_rows_fixed ? term->tl_rows : wp->w_height, - term->tl_cols_fixed ? term->tl_cols : wp->w_width); + { + int rows = term->tl_rows_fixed ? term->tl_rows : wp->w_height; + int cols = term->tl_cols_fixed ? term->tl_cols : wp->w_width; + + vterm_set_size(vterm, rows, cols); + ch_logn(term->tl_job->jv_channel, "Resizing terminal to %d lines", + rows); + +#if defined(UNIX) + /* Use an ioctl() to report the new window size to the job. */ + if (term->tl_job != NULL && term->tl_job->jv_channel != NULL) + { + int fd = -1; + int part; + + for (part = PART_OUT; part < PART_COUNT; ++part) + { + fd = term->tl_job->jv_channel->ch_part[part].ch_fd; + if (isatty(fd)) + break; + } + if (part < PART_COUNT && mch_report_winsize(fd, rows, cols) == OK) + mch_stop_job(term->tl_job, (char_u *)"winch"); + } +#endif + } /* The cursor may have been moved when resizing. */ vterm_state_get_cursorpos(state, &pos); diff --git a/src/version.c b/src/version.c index 9ea3d819e2..724e7c3e91 100644 --- a/src/version.c +++ b/src/version.c @@ -769,6 +769,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 753, /**/ 752, /**/ -- cgit v1.2.3