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

Reply via email to