mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 00:56:10 +00:00 
			
		
		
		
	Implement "all event" (1003) mouse mode but in a way that works. The
main issue is that if we have two panes, A with 1002 and B with 1003, we need to set 1003 outside tmux in order to get all the mouse events, but then we need to suppress the ones that pane A doesn't want. This is easy in SGR mouse mode, because buttons == 3 is only used for movement events (for other events the trailing m/M marks a release instead), but in normal mouse mode we can't tell so easily. So for that, look at the previous event instead - if it is drag+release as well, then the current event is a movement event.
This commit is contained in:
		
							
								
								
									
										4
									
								
								format.c
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								format.c
									
									
									
									
									
								
							@@ -1280,11 +1280,13 @@ format_defaults_pane(struct format_tree *ft, struct window_pane *wp)
 | 
			
		||||
	    !!(wp->base.mode & MODE_WRAP));
 | 
			
		||||
 | 
			
		||||
	format_add(ft, "mouse_any_flag", "%d",
 | 
			
		||||
	    !!(wp->base.mode & (MODE_MOUSE_STANDARD|MODE_MOUSE_BUTTON)));
 | 
			
		||||
	    !!(wp->base.mode & ALL_MOUSE_MODES));
 | 
			
		||||
	format_add(ft, "mouse_standard_flag", "%d",
 | 
			
		||||
	    !!(wp->base.mode & MODE_MOUSE_STANDARD));
 | 
			
		||||
	format_add(ft, "mouse_button_flag", "%d",
 | 
			
		||||
	    !!(wp->base.mode & MODE_MOUSE_BUTTON));
 | 
			
		||||
	format_add(ft, "mouse_all_flag", "%d",
 | 
			
		||||
	    !!(wp->base.mode & MODE_MOUSE_ALL));
 | 
			
		||||
 | 
			
		||||
	format_add_cb(ft, "pane_tabs", format_cb_pane_tabs);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										40
									
								
								input-keys.c
									
									
									
									
									
								
							
							
						
						
									
										40
									
								
								input-keys.c
									
									
									
									
									
								
							@@ -235,20 +235,42 @@ input_key(struct window_pane *wp, key_code key, struct mouse_event *m)
 | 
			
		||||
static void
 | 
			
		||||
input_key_mouse(struct window_pane *wp, struct mouse_event *m)
 | 
			
		||||
{
 | 
			
		||||
	char	buf[40];
 | 
			
		||||
	size_t	len;
 | 
			
		||||
	u_int	x, y;
 | 
			
		||||
	struct screen	*s = wp->screen;
 | 
			
		||||
	int		 mode = s->mode;
 | 
			
		||||
	char		 buf[40];
 | 
			
		||||
	size_t		 len;
 | 
			
		||||
	u_int		 x, y;
 | 
			
		||||
 | 
			
		||||
	if ((wp->screen->mode & ALL_MOUSE_MODES) == 0)
 | 
			
		||||
	if ((mode & ALL_MOUSE_MODES) == 0)
 | 
			
		||||
		return;
 | 
			
		||||
	if (!window_pane_visible(wp))
 | 
			
		||||
		return;
 | 
			
		||||
	if (cmd_mouse_at(wp, m, &x, &y, 0) != 0)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	/* If this pane is not in button mode, discard motion events. */
 | 
			
		||||
	if (!(wp->screen->mode & MODE_MOUSE_BUTTON) && (m->b & MOUSE_MASK_DRAG))
 | 
			
		||||
		return;
 | 
			
		||||
	/* If this pane is not in button or all mode, discard motion events. */
 | 
			
		||||
	if (MOUSE_DRAG(m->b) &&
 | 
			
		||||
	    (mode & (MODE_MOUSE_BUTTON|MODE_MOUSE_ALL)) == 0)
 | 
			
		||||
	    return;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * If this event is a release event and not in all mode, discard it.
 | 
			
		||||
	 * In SGR mode we can tell absolutely because a release is normally
 | 
			
		||||
	 * shown by the last character. Without SGR, we check if the last
 | 
			
		||||
	 * buttons was also a release.
 | 
			
		||||
	 */
 | 
			
		||||
	if (m->sgr_type != ' ') {
 | 
			
		||||
		if (MOUSE_DRAG(m->sgr_b) &&
 | 
			
		||||
		    MOUSE_BUTTONS(m->sgr_b) == 3 &&
 | 
			
		||||
		    (~mode & MODE_MOUSE_ALL))
 | 
			
		||||
			return;
 | 
			
		||||
	} else {
 | 
			
		||||
		if (MOUSE_DRAG(m->b) &&
 | 
			
		||||
		    MOUSE_BUTTONS(m->b) == 3 &&
 | 
			
		||||
		    MOUSE_BUTTONS(m->lb) == 3 &&
 | 
			
		||||
		    (~mode & MODE_MOUSE_ALL))
 | 
			
		||||
			return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Use the SGR (1006) extension only if the application requested it
 | 
			
		||||
@@ -259,10 +281,10 @@ input_key_mouse(struct window_pane *wp, struct mouse_event *m)
 | 
			
		||||
	 * UTF-8 (1005) extension if the application requested, or to the
 | 
			
		||||
	 * legacy format.
 | 
			
		||||
	 */
 | 
			
		||||
	if (m->sgr_type != ' ' && (wp->screen->mode & MODE_MOUSE_SGR)) {
 | 
			
		||||
	if (m->sgr_type != ' ' && (s->mode & MODE_MOUSE_SGR)) {
 | 
			
		||||
		len = xsnprintf(buf, sizeof buf, "\033[<%u;%u;%u%c",
 | 
			
		||||
		    m->sgr_b, x + 1, y + 1, m->sgr_type);
 | 
			
		||||
	} else if (wp->screen->mode & MODE_MOUSE_UTF8) {
 | 
			
		||||
	} else if (s->mode & MODE_MOUSE_UTF8) {
 | 
			
		||||
		if (m->b > 0x7ff - 32 || x > 0x7ff - 33 || y > 0x7ff - 33)
 | 
			
		||||
			return;
 | 
			
		||||
		len = xsnprintf(buf, sizeof buf, "\033[M");
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										5
									
								
								input.c
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								input.c
									
									
									
									
									
								
							@@ -1477,6 +1477,7 @@ input_csi_dispatch_rm_private(struct input_ctx *ictx)
 | 
			
		||||
		case 1000:
 | 
			
		||||
		case 1001:
 | 
			
		||||
		case 1002:
 | 
			
		||||
		case 1003:
 | 
			
		||||
			screen_write_mode_clear(&ictx->ctx, ALL_MOUSE_MODES);
 | 
			
		||||
			break;
 | 
			
		||||
		case 1004:
 | 
			
		||||
@@ -1560,6 +1561,10 @@ input_csi_dispatch_sm_private(struct input_ctx *ictx)
 | 
			
		||||
			screen_write_mode_clear(&ictx->ctx, ALL_MOUSE_MODES);
 | 
			
		||||
			screen_write_mode_set(&ictx->ctx, MODE_MOUSE_BUTTON);
 | 
			
		||||
			break;
 | 
			
		||||
		case 1003:
 | 
			
		||||
			screen_write_mode_clear(&ictx->ctx, ALL_MOUSE_MODES);
 | 
			
		||||
			screen_write_mode_set(&ictx->ctx, MODE_MOUSE_ALL);
 | 
			
		||||
			break;
 | 
			
		||||
		case 1004:
 | 
			
		||||
			if (ictx->ctx.s->mode & MODE_FOCUSON)
 | 
			
		||||
				break;
 | 
			
		||||
 
 | 
			
		||||
@@ -255,6 +255,12 @@ key_string_lookup_key(key_code key)
 | 
			
		||||
		return ("Mouse");
 | 
			
		||||
	if (key == KEYC_DRAGGING)
 | 
			
		||||
		return ("Dragging");
 | 
			
		||||
	if (key == KEYC_MOUSEMOVE_PANE)
 | 
			
		||||
		return ("MouseMovePane");
 | 
			
		||||
	if (key == KEYC_MOUSEMOVE_STATUS)
 | 
			
		||||
		return ("MouseMoveStatus");
 | 
			
		||||
	if (key == KEYC_MOUSEMOVE_BORDER)
 | 
			
		||||
		return ("MouseMoveBorder");
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Special case: display C-@ as C-Space. Could do this below in
 | 
			
		||||
 
 | 
			
		||||
@@ -335,14 +335,27 @@ server_client_check_mouse(struct client *c)
 | 
			
		||||
	int			 flag;
 | 
			
		||||
	key_code		 key;
 | 
			
		||||
	struct timeval		 tv;
 | 
			
		||||
	enum { NOTYPE, DOWN, UP, DRAG, WHEEL, DOUBLE, TRIPLE } type = NOTYPE;
 | 
			
		||||
	enum { NOWHERE, PANE, STATUS, BORDER } where = NOWHERE;
 | 
			
		||||
	enum { NOTYPE, MOVE, DOWN, UP, DRAG, WHEEL, DOUBLE, TRIPLE } type;
 | 
			
		||||
	enum { NOWHERE, PANE, STATUS, BORDER } where;
 | 
			
		||||
 | 
			
		||||
	type = NOTYPE;
 | 
			
		||||
	where = NOWHERE;
 | 
			
		||||
 | 
			
		||||
	log_debug("mouse %02x at %u,%u (last %u,%u) (%d)", m->b, m->x, m->y,
 | 
			
		||||
	    m->lx, m->ly, c->tty.mouse_drag_flag);
 | 
			
		||||
 | 
			
		||||
	/* What type of event is this? */
 | 
			
		||||
	if (MOUSE_DRAG(m->b)) {
 | 
			
		||||
	if ((m->sgr_type != ' ' &&
 | 
			
		||||
	    MOUSE_DRAG(m->sgr_b) &&
 | 
			
		||||
	    MOUSE_BUTTONS(m->sgr_b) == 3) ||
 | 
			
		||||
	    (m->sgr_type == ' ' &&
 | 
			
		||||
	    MOUSE_DRAG(m->b) &&
 | 
			
		||||
	    MOUSE_BUTTONS(m->b) == 3 &&
 | 
			
		||||
	    MOUSE_BUTTONS(m->lb) == 3)) {
 | 
			
		||||
		type = MOVE;
 | 
			
		||||
		x = m->x, y = m->y, b = 0;
 | 
			
		||||
		log_debug("move at %u,%u", x, y);
 | 
			
		||||
	} else if (MOUSE_DRAG(m->b)) {
 | 
			
		||||
		type = DRAG;
 | 
			
		||||
		if (c->tty.mouse_drag_flag) {
 | 
			
		||||
			x = m->x, y = m->y, b = m->b;
 | 
			
		||||
@@ -500,6 +513,14 @@ have_event:
 | 
			
		||||
	switch (type) {
 | 
			
		||||
	case NOTYPE:
 | 
			
		||||
		break;
 | 
			
		||||
	case MOVE:
 | 
			
		||||
		if (where == PANE)
 | 
			
		||||
			key = KEYC_MOUSEMOVE_PANE;
 | 
			
		||||
		if (where == STATUS)
 | 
			
		||||
			key = KEYC_MOUSEMOVE_STATUS;
 | 
			
		||||
		if (where == BORDER)
 | 
			
		||||
			key = KEYC_MOUSEMOVE_BORDER;
 | 
			
		||||
		break;
 | 
			
		||||
	case DRAG:
 | 
			
		||||
		if (c->tty.mouse_drag_update != NULL)
 | 
			
		||||
			key = KEYC_DRAGGING;
 | 
			
		||||
@@ -1055,7 +1076,7 @@ static void
 | 
			
		||||
server_client_reset_state(struct client *c)
 | 
			
		||||
{
 | 
			
		||||
	struct window		*w = c->session->curw->window;
 | 
			
		||||
	struct window_pane	*wp = w->active;
 | 
			
		||||
	struct window_pane	*wp = w->active, *loop;
 | 
			
		||||
	struct screen		*s = wp->screen;
 | 
			
		||||
	struct options		*oo = c->session->options;
 | 
			
		||||
	int			 status, mode, o;
 | 
			
		||||
@@ -1079,8 +1100,15 @@ server_client_reset_state(struct client *c)
 | 
			
		||||
	 * mode.
 | 
			
		||||
	 */
 | 
			
		||||
	mode = s->mode;
 | 
			
		||||
	if (options_get_number(oo, "mouse"))
 | 
			
		||||
		mode = (mode & ~ALL_MOUSE_MODES) | MODE_MOUSE_BUTTON;
 | 
			
		||||
	if (options_get_number(oo, "mouse")) {
 | 
			
		||||
		mode &= ~ALL_MOUSE_MODES;
 | 
			
		||||
		TAILQ_FOREACH(loop, &w->panes, entry) {
 | 
			
		||||
			if (loop->screen->mode & MODE_MOUSE_ALL)
 | 
			
		||||
				mode |= MODE_MOUSE_ALL;
 | 
			
		||||
		}
 | 
			
		||||
		if (~mode & MODE_MOUSE_ALL)
 | 
			
		||||
			mode |= MODE_MOUSE_BUTTON;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Set the terminal mode and reset attributes. */
 | 
			
		||||
	tty_update_mode(&c->tty, mode, s);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								tmux.1
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								tmux.1
									
									
									
									
									
								
							@@ -3528,6 +3528,7 @@ The following variables are available, where appropriate:
 | 
			
		||||
.It Li "mouse_any_flag" Ta "" Ta "Pane mouse any flag"
 | 
			
		||||
.It Li "mouse_button_flag" Ta "" Ta "Pane mouse button flag"
 | 
			
		||||
.It Li "mouse_standard_flag" Ta "" Ta "Pane mouse standard flag"
 | 
			
		||||
.It Li "mouse_all_flag" Ta "" Ta "Pane mouse all flag"
 | 
			
		||||
.It Li "pane_active" Ta "" Ta "1 if active pane"
 | 
			
		||||
.It Li "pane_bottom" Ta "" Ta "Bottom of pane"
 | 
			
		||||
.It Li "pane_current_command" Ta "" Ta "Current command if available"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								tmux.h
									
									
									
									
									
								
							@@ -137,6 +137,7 @@ enum {
 | 
			
		||||
	/* Mouse keys. */
 | 
			
		||||
	KEYC_MOUSE, /* unclassified mouse event */
 | 
			
		||||
	KEYC_DRAGGING, /* dragging in progress */
 | 
			
		||||
	KEYC_MOUSE_KEY(MOUSEMOVE),
 | 
			
		||||
	KEYC_MOUSE_KEY(MOUSEDOWN1),
 | 
			
		||||
	KEYC_MOUSE_KEY(MOUSEDOWN2),
 | 
			
		||||
	KEYC_MOUSE_KEY(MOUSEDOWN3),
 | 
			
		||||
@@ -488,8 +489,9 @@ struct msg_stderr_data {
 | 
			
		||||
#define MODE_MOUSE_SGR 0x200
 | 
			
		||||
#define MODE_BRACKETPASTE 0x400
 | 
			
		||||
#define MODE_FOCUSON 0x800
 | 
			
		||||
#define MODE_MOUSE_ALL 0x1000
 | 
			
		||||
 | 
			
		||||
#define ALL_MOUSE_MODES (MODE_MOUSE_STANDARD|MODE_MOUSE_BUTTON)
 | 
			
		||||
#define ALL_MOUSE_MODES (MODE_MOUSE_STANDARD|MODE_MOUSE_BUTTON|MODE_MOUSE_ALL)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * A single UTF-8 character. UTF8_SIZE must be big enough to hold at least one
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										8
									
								
								tty.c
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								tty.c
									
									
									
									
									
								
							@@ -568,12 +568,16 @@ tty_update_mode(struct tty *tty, int mode, struct screen *s)
 | 
			
		||||
			 * it is safe from misinterpretation.
 | 
			
		||||
			 */
 | 
			
		||||
			tty_puts(tty, "\033[?1006h");
 | 
			
		||||
			if (mode & MODE_MOUSE_BUTTON)
 | 
			
		||||
			if (mode & MODE_MOUSE_ALL)
 | 
			
		||||
				tty_puts(tty, "\033[?1003h");
 | 
			
		||||
			else if (mode & MODE_MOUSE_BUTTON)
 | 
			
		||||
				tty_puts(tty, "\033[?1002h");
 | 
			
		||||
			else if (mode & MODE_MOUSE_STANDARD)
 | 
			
		||||
				tty_puts(tty, "\033[?1000h");
 | 
			
		||||
		} else {
 | 
			
		||||
			if (tty->mode & MODE_MOUSE_BUTTON)
 | 
			
		||||
			if (tty->mode & MODE_MOUSE_ALL)
 | 
			
		||||
				tty_puts(tty, "\033[?1003l");
 | 
			
		||||
			else if (tty->mode & MODE_MOUSE_BUTTON)
 | 
			
		||||
				tty_puts(tty, "\033[?1002l");
 | 
			
		||||
			else if (tty->mode & MODE_MOUSE_STANDARD)
 | 
			
		||||
				tty_puts(tty, "\033[?1000l");
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user