diff --git a/tmux.1 b/tmux.1 index 9b565dd1..94e60758 100644 --- a/tmux.1 +++ b/tmux.1 @@ -2078,10 +2078,8 @@ Key bindings default to emacs. .Op Ic on | off .Xc Mouse state in modes. -If on, -.Nm -will respond to mouse clicks by moving the cursor in copy mode or selecting an -option in choice mode. +If on, the mouse may be used to copy a selection by dragging in copy mode, or +to select an option in choice mode. .Pp .It Xo Ic monitor-activity .Op Ic on | off diff --git a/tmux.h b/tmux.h index 961019d8..3069f89b 100644 --- a/tmux.h +++ b/tmux.h @@ -541,7 +541,8 @@ struct mode_key_table { #define MODE_KCURSOR 0x4 #define MODE_KKEYPAD 0x8 /* set = application, clear = number */ #define MODE_MOUSE 0x10 -#define MODE_WRAP 0x20 /* whether lines wrap */ +#define MODE_MOUSEMOTION 0x20 +#define MODE_WRAP 0x40 /* whether lines wrap */ /* * A single UTF-8 character. @@ -1086,7 +1087,7 @@ struct client { #define CLIENT_TERMINAL 0x1 #define CLIENT_PREFIX 0x2 -#define CLIENT_MOUSE 0x4 +/* 0x4 unused */ #define CLIENT_REDRAW 0x8 #define CLIENT_STATUS 0x10 #define CLIENT_REPEAT 0x20 /* allow command to repeat within repeat time */ diff --git a/tty-keys.c b/tty-keys.c index 27107bb8..59002fb2 100644 --- a/tty-keys.c +++ b/tty-keys.c @@ -612,7 +612,8 @@ tty_keys_mouse(const char *buf, size_t len, size_t *size, struct mouse_event *m) return (1); *size = 6; - log_debug("mouse input is: %.6s", buf); + log_debug( + "mouse input: %.6s (%hhu,%hhu/%hhu)", buf, buf[4], buf[5], buf[3]); m->b = buf[3]; m->x = buf[4]; diff --git a/tty.c b/tty.c index 72be2c84..92ddf41f 100644 --- a/tty.c +++ b/tty.c @@ -402,11 +402,18 @@ tty_update_mode(struct tty *tty, int mode) else tty_putcode(tty, TTYC_CIVIS); } - if (changed & MODE_MOUSE) { - if (mode & MODE_MOUSE) - tty_puts(tty, "\033[?1000h"); - else - tty_puts(tty, "\033[?1000l"); + if (changed & (MODE_MOUSE|MODE_MOUSEMOTION)) { + if (mode & MODE_MOUSE) { + if (mode & MODE_MOUSEMOTION) + tty_puts(tty, "\033[?1003h"); + else + tty_puts(tty, "\033[?1000h"); + } else { + if (mode & MODE_MOUSEMOTION) + tty_puts(tty, "\033[?1003l"); + else + tty_puts(tty, "\033[?1000l"); + } } if (changed & MODE_KKEYPAD) { if (mode & MODE_KKEYPAD) diff --git a/window-copy.c b/window-copy.c index 3b42c456..66402eca 100644 --- a/window-copy.c +++ b/window-copy.c @@ -760,17 +760,61 @@ window_copy_mouse( { struct window_copy_mode_data *data = wp->modedata; struct screen *s = &data->screen; + u_int i; + + /* + * xterm mouse mode is fairly silly. Buttons are in the bottom two + * bits: 0 button 1; 1 button 2; 2 button 3; 3 buttons released. + * + * Bit 3 is shift; bit 4 is meta; bit 5 control. + * + * Bit 6 is added for mouse buttons 4 and 5. + */ - if ((m->b & 3) == 3) - return; if (m->x >= screen_size_x(s)) return; if (m->y >= screen_size_y(s)) return; - window_copy_update_cursor(wp, m->x, m->y); - if (window_copy_update_selection(wp)) + /* If mouse wheel (buttons 4 and 5), scroll. */ + if ((m->b & 64) == 64) { + if ((m->b & 3) == 0) { + for (i = 0; i < 5; i++) + window_copy_cursor_up(wp, 0); + } else if ((m->b & 3) == 1) { + for (i = 0; i < 5; i++) + window_copy_cursor_down(wp, 0); + } + return; + } + + /* + * If already reading motion, move the cursor while buttons are still + * pressed, or stop the selection on their release. + */ + if (s->mode & MODE_MOUSEMOTION) { + if ((m->b & 3) != 3) { + window_copy_update_cursor(wp, m->x, m->y); + if (window_copy_update_selection(wp)) + window_copy_redraw_screen(wp); + } else { + s->mode &= ~MODE_MOUSEMOTION; + if (sess != NULL) { + window_copy_copy_selection(wp, sess); + window_pane_reset_mode(wp); + } + } + return; + } + + /* Otherwise i other buttons pressed, start selection and motion. */ + if ((m->b & 3) != 3) { + s->mode |= MODE_MOUSEMOTION; + + window_copy_update_cursor(wp, m->x, m->y); + window_copy_start_selection(wp); window_copy_redraw_screen(wp); + } } void