summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2017-07-22 22:32:56 +0200
committerBram Moolenaar <Bram@vim.org>2017-07-22 22:32:56 +0200
commitb13501f7dada4154fc7633d79989d1dab98ae99d (patch)
tree097de64eb33e7c336cd83b15491316256181950e
parentd7d3cbedb3dc5c843724430539ad52ddafcefc93 (diff)
patch 8.0.0753: no size reports to a job running in a terminalv8.0.0753
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.
-rw-r--r--src/os_unix.c42
-rw-r--r--src/proto/os_unix.pro1
-rw-r--r--src/terminal.c36
-rw-r--r--src/version.c2
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
@@ -770,6 +770,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 753,
+/**/
752,
/**/
751,