The branch, master has been updated via e5eee7de0c35e296b92707fdf66ddd5271f4bcfc (commit) from d8261019f1b1fcf58a79b82448e8851e3acfd026 (commit)
- Log ----------------------------------------------------------------- commit e5eee7de0c35e296b92707fdf66ddd5271f4bcfc Author: Nicholas Marriott <nicholas.marri...@gmail.com> Commit: Nicholas Marriott <nicholas.marri...@gmail.com> Support the latest theory for mouse input, this is enabled/disabled with SM/RM 1006 and is similar in style to SGR input: \033[<b;x;yM or \033[b;x;ym. From Egmont Koblinger. --- TODO | 1 - input-keys.c | 17 ++++++- input.c | 6 ++ screen-write.c | 4 +- tmux.h | 10 ++++- tty-keys.c | 146 +++++++++++++++++++++++++++++++++++++++----------------- tty.c | 15 +++++- 7 files changed, 148 insertions(+), 51 deletions(-) diff --git a/TODO b/TODO index 57a45e2..aadc5af 100644 --- a/TODO +++ b/TODO @@ -171,7 +171,6 @@ TERMINAL ISSUES - support for bce - use screen-256color when started on 256 colour terminal?? - if-shell/run-shell should block further command execution in the same command -- possibly support rxvt-unicode extended mouse input (1015) - wrap/no wrap esc seq DEC CSI ? 7 h/l * We need a tmux terminfo entry to document the extensions we are using in upstream terminfo. Must NOT change (only add or remove) anything from diff --git a/input-keys.c b/input-keys.c index 0953ce7..d57926a 100644 --- a/input-keys.c +++ b/input-keys.c @@ -201,12 +201,25 @@ input_key(struct window_pane *wp, int key) void input_mouse(struct window_pane *wp, struct session *s, struct mouse_event *m) { - char buf[10]; + char buf[40]; size_t len; struct paste_buffer *pb; if (wp->screen->mode & ALL_MOUSE_MODES) { - if (wp->screen->mode & MODE_MOUSE_UTF8) { + /* + * Use the SGR (1006) extension only if the application + * requested it and the underlying terminal also sent the event + * in this format (this is because an old style mouse release + * event cannot be converted into the new SGR format, since the + * released button is unknown). Otherwise pretend that tmux + * doesn't speak this extension, and fall back to the UTF-8 + * (1005) extension if the application requested, or to the + * legacy format. + */ + if (m->sgr && (wp->screen->mode & MODE_MOUSE_SGR)) { + len = xsnprintf(buf, sizeof buf, "\033[<%d;%d;%d%c", + m->sgr_xb, m->x + 1, m->y + 1, m->sgr_rel ? 'm' : 'M'); + } else if (wp->screen->mode & MODE_MOUSE_UTF8) { len = xsnprintf(buf, sizeof buf, "\033[M"); len += utf8_split2(m->xb + 32, &buf[len]); len += utf8_split2(m->x + 33, &buf[len]); diff --git a/input.c b/input.c index 8846c1c..c4e19c0 100644 --- a/input.c +++ b/input.c @@ -1260,6 +1260,9 @@ input_csi_dispatch(struct input_ctx *ictx) case 1005: screen_write_mode_clear(&ictx->ctx, MODE_MOUSE_UTF8); break; + case 1006: + screen_write_mode_clear(&ictx->ctx, MODE_MOUSE_SGR); + break; case 47: case 1047: window_pane_alternate_off(wp, &ictx->cell, 0); @@ -1320,6 +1323,9 @@ input_csi_dispatch(struct input_ctx *ictx) case 1005: screen_write_mode_set(&ictx->ctx, MODE_MOUSE_UTF8); break; + case 1006: + screen_write_mode_set(&ictx->ctx, MODE_MOUSE_SGR); + break; case 47: case 1047: window_pane_alternate_on(wp, &ictx->cell, 0); diff --git a/screen-write.c b/screen-write.c index 2cc9850..59d91fd 100644 --- a/screen-write.c +++ b/screen-write.c @@ -55,7 +55,9 @@ screen_write_reset(struct screen_write_ctx *ctx) screen_reset_tabs(s); screen_write_scrollregion(ctx, 0, screen_size_y(s) - 1); - s->mode &= ~(MODE_INSERT|MODE_KCURSOR|MODE_KKEYPAD|ALL_MOUSE_MODES); + + s->mode &= ~(MODE_INSERT|MODE_KCURSOR|MODE_KKEYPAD); + s->mode &= ~(ALL_MOUSE_MODES|MODE_MOUSE_UTF8|MODE_MOUSE_SGR); screen_write_clearscreen(ctx); screen_write_cursormove(ctx, 0, 0); diff --git a/tmux.h b/tmux.h index e10fb62..1efad53 100644 --- a/tmux.h +++ b/tmux.h @@ -661,7 +661,8 @@ struct mode_key_table { #define MODE_MOUSE_BUTTON 0x40 #define MODE_MOUSE_ANY 0x80 #define MODE_MOUSE_UTF8 0x100 -#define MODE_BRACKETPASTE 0x200 +#define MODE_MOUSE_SGR 0x200 +#define MODE_BRACKETPASTE 0x400 #define ALL_MOUSE_MODES (MODE_MOUSE_STANDARD|MODE_MOUSE_BUTTON|MODE_MOUSE_ANY) @@ -1149,6 +1150,9 @@ LIST_HEAD(tty_terms, tty_term); * - bits 3, 4 and 5 are for keys * - bit 6 is set for dragging * - bit 7 for buttons 4 and 5 + * + * With the SGR 1006 extension the released button becomes known. Store these + * in separate fields and store the value converted to the old format in xb. */ struct mouse_event { u_int xb; @@ -1161,6 +1165,10 @@ struct mouse_event { u_int ly; u_int sy; + u_int sgr; /* whether the input arrived in SGR format */ + u_int sgr_xb; /* only for SGR: the unmangled button */ + u_int sgr_rel; /* only for SGR: whether it is a release event */ + u_int button; u_int clicks; diff --git a/tty-keys.c b/tty-keys.c index 5fda2fb..00327bb 100644 --- a/tty-keys.c +++ b/tty-keys.c @@ -587,20 +587,26 @@ tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size) { struct mouse_event *m = &tty->mouse; struct utf8_data utf8data; - u_int i, value, x, y, b; + u_int i, value, x, y, b, sgr, sgr_b, sgr_rel; + unsigned char c; /* * Standard mouse sequences are \033[M followed by three characters - * indicating buttons, X and Y, all based at 32 with 1,1 top-left. + * indicating button, X and Y, all based at 32 with 1,1 top-left. * * UTF-8 mouse sequences are similar but the three are expressed as * UTF-8 characters. + * + * SGR extended mouse sequences are \033[< followed by three numbers in + * decimal and separated by semicolons indicating button, X and Y. A + * trailing 'M' is click or scroll and trailing 'm' release. All are + * based at 0 with 1,1 top-left. */ *size = 0; - x = y = b = 0; + x = y = b = sgr = sgr_b = sgr_rel = 0; - /* First three bytes are always \033[M. */ + /* First two bytes are always \033[. */ if (buf[0] != '\033') return (-1); if (len == 1) @@ -609,50 +615,99 @@ tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size) return (-1); if (len == 2) return (1); - if (buf[2] != 'M') - return (-1); - if (len == 3) - return (1); - /* Read the three inputs. */ - *size = 3; - for (i = 0; i < 3; i++) { - if (len < *size) - return (1); - - if (tty->mode & MODE_MOUSE_UTF8) { - if (utf8_open(&utf8data, buf[*size])) { - if (utf8data.size != 2) - return (-1); + /* + * Third byte is M in old standard and UTF-8 extension, < in SGR + * extension. + */ + if (buf[2] == 'M') { + /* Read the three inputs. */ + *size = 3; + for (i = 0; i < 3; i++) { + if (len <= *size) + return (1); + + if (tty->mode & MODE_MOUSE_UTF8) { + if (utf8_open(&utf8data, buf[*size])) { + if (utf8data.size != 2) + return (-1); + (*size)++; + if (len <= *size) + return (1); + utf8_append(&utf8data, buf[*size]); + value = utf8_combine(&utf8data); + } else + value = (u_char) buf[*size]; (*size)++; - if (len < *size) - return (1); - utf8_append(&utf8data, buf[*size]); - value = utf8_combine(&utf8data); - } else - value = (unsigned char)buf[*size]; - (*size)++; - } else { - value = (unsigned char)buf[*size]; - (*size)++; - } - - if (i == 0) - b = value; - else if (i == 1) - x = value; - else - y = value; - } - log_debug("mouse input: %.*s", (int) *size, buf); + } else { + value = (u_char) buf[*size]; + (*size)++; + } - /* Check and return the mouse input. */ - if (b < 32 || x < 33 || y < 33) + if (i == 0) + b = value; + else if (i == 1) + x = value; + else + y = value; + } + log_debug("mouse input: %.*s", (int) *size, buf); + + /* Check and return the mouse input. */ + if (b < 32 || x < 33 || y < 33) + return (-1); + b -= 32; + x -= 33; + y -= 33; + } else if (buf[2] == '<') { + /* Read the three inputs. */ + *size = 3; + while (1) { + if (len <= *size) + return (1); + c = (u_char)buf[(*size)++]; + if (c == ';') + break; + if (c < '0' || c > '9') + return (-1); + sgr_b = 10 * sgr_b + (c - '0'); + } + while (1) { + if (len <= *size) + return (1); + c = (u_char)buf[(*size)++]; + if (c == ';') + break; + if (c < '0' || c > '9') + return (-1); + x = 10 * x + (c - '0'); + } + while (1) { + if (len <= *size) + return (1); + c = (u_char) buf[(*size)++]; + if (c == 'M' || c == 'm') + break; + if (c < '0' || c > '9') + return (-1); + y = 10 * y + (c - '0'); + } + log_debug("mouse input (sgr): %.*s", (int) *size, buf); + + /* Check and return the mouse input. */ + if (x < 1 || y < 1) + return (-1); + x--; + y--; + sgr = 1; + sgr_rel = (c == 'm'); + + /* Figure out what b would be in old format. */ + b = sgr_b; + if (sgr_rel) + b |= 3; + } else return (-1); - b -= 32; - x -= 33; - y -= 33; - log_debug("mouse position: x=%u y=%u b=%u", x, y, b); /* Fill in mouse structure. */ if (~m->event & MOUSE_EVENT_WHEEL) { @@ -660,6 +715,9 @@ tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size) m->ly = m->y; } m->xb = b; + m->sgr = sgr; + m->sgr_xb = sgr_b; + m->sgr_rel = sgr_rel; if (b & 64) { /* wheel button */ b &= 3; if (b == 0) diff --git a/tty.c b/tty.c index bae97ac..6da63bf 100644 --- a/tty.c +++ b/tty.c @@ -218,7 +218,7 @@ tty_start_tty(struct tty *tty) tty_putcode(tty, TTYC_CNORM); if (tty_term_has(tty->term, TTYC_KMOUS)) - tty_puts(tty, "\033[?1000l"); + tty_puts(tty, "\033[?1000l\033[?1006l\033[?1005l"); if (tty_term_has(tty->term, TTYC_XT)) tty_puts(tty, "\033[c\033[>4;1m"); @@ -281,7 +281,7 @@ tty_stop_tty(struct tty *tty) tty_raw(tty, tty_term_string(tty->term, TTYC_CNORM)); if (tty_term_has(tty->term, TTYC_KMOUS)) - tty_raw(tty, "\033[?1000l"); + tty_raw(tty, "\033[?1000l\033[?1006l\033[?1005l"); if (tty_term_has(tty->term, TTYC_XT)) tty_puts(tty, "\033[>4m"); @@ -491,8 +491,17 @@ tty_update_mode(struct tty *tty, int mode, struct screen *s) } if (changed & ALL_MOUSE_MODES) { if (mode & ALL_MOUSE_MODES) { + /* + * Enable the UTF-8 (1005) extension if configured to. + * Enable the SGR (1006) extension unconditionally, as + * this is safe from misinterpretation. Do it in this + * order, because in some terminals it's the last one + * that takes effect and SGR is the preferred one. + */ if (mode & MODE_MOUSE_UTF8) tty_puts(tty, "\033[?1005h"); + tty_puts(tty, "\033[?1006h"); + if (mode & MODE_MOUSE_ANY) tty_puts(tty, "\033[?1003h"); else if (mode & MODE_MOUSE_BUTTON) @@ -506,6 +515,8 @@ tty_update_mode(struct tty *tty, int mode, struct screen *s) tty_puts(tty, "\033[?1002l"); else if (tty->mode & MODE_MOUSE_STANDARD) tty_puts(tty, "\033[?1000l"); + + tty_puts(tty, "\033[?1006l"); if (tty->mode & MODE_MOUSE_UTF8) tty_puts(tty, "\033[?1005l"); } ----------------------------------------------------------------------- Summary of changes: TODO | 1 - input-keys.c | 17 ++++++- input.c | 6 ++ screen-write.c | 4 +- tmux.h | 10 ++++- tty-keys.c | 146 +++++++++++++++++++++++++++++++++++++++----------------- tty.c | 15 +++++- 7 files changed, 148 insertions(+), 51 deletions(-) hooks/post-receive -- tmux ------------------------------------------------------------------------------ The Go Parallel Website, sponsored by Intel - in partnership with Geeknet, is your hub for all things parallel software development, from weekly thought leadership blogs to news, videos, case studies, tutorials, tech docs, whitepapers, evaluation guides, and opinion stories. Check out the most recent posts - join the conversation now. http://goparallel.sourceforge.net/ _______________________________________________ tmux-cvs mailing list tmux-cvs@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/tmux-cvs