Make mouse event structure clearer by defining events (up, click, drag)

and simplifying how buttons and wheels are represented, from Ailin
Nemui. Should be no functional changes.
This commit is contained in:
Nicholas Marriott 2012-10-26 14:35:42 +00:00
parent 2a609b332f
commit d210d99cce
8 changed files with 155 additions and 108 deletions

View File

@ -200,7 +200,7 @@ input_key(struct window_pane *wp, int key)
/* Translate mouse and output. */
void
input_mouse(struct window_pane *wp, struct mouse_event *m)
input_mouse(struct window_pane *wp, struct session *s, struct mouse_event *m)
{
char buf[10];
size_t len;
@ -208,14 +208,14 @@ input_mouse(struct window_pane *wp, struct mouse_event *m)
if (wp->screen->mode & ALL_MOUSE_MODES) {
if (wp->screen->mode & MODE_MOUSE_UTF8) {
len = xsnprintf(buf, sizeof buf, "\033[M");
len += utf8_split2(m->b + 32, &buf[len]);
len += utf8_split2(m->xb + 32, &buf[len]);
len += utf8_split2(m->x + 33, &buf[len]);
len += utf8_split2(m->y + 33, &buf[len]);
} else {
if (m->b > 223 || m->x >= 222 || m->y > 222)
if (m->xb > 223 || m->x >= 222 || m->y > 222)
return;
len = xsnprintf(buf, sizeof buf, "\033[M");
buf[len++] = m->b + 32;
buf[len++] = m->xb + 32;
buf[len++] = m->x + 33;
buf[len++] = m->y + 33;
}
@ -223,12 +223,12 @@ input_mouse(struct window_pane *wp, struct mouse_event *m)
return;
}
if ((m->b & 3) != 1 &&
if ((m->xb & 3) != 1 &&
options_get_number(&wp->window->options, "mode-mouse") == 1) {
if (window_pane_set_mode(wp, &window_copy_mode) == 0) {
window_copy_init_from_pane(wp);
if (wp->mode->mouse != NULL)
wp->mode->mouse(wp, NULL, m);
wp->mode->mouse(wp, s, m);
}
return;
}

View File

@ -488,50 +488,51 @@ layout_resize_pane(struct window_pane *wp, enum layout_type type, int change)
}
void
layout_resize_pane_mouse(struct client *c, struct mouse_event *mouse)
layout_resize_pane_mouse(struct client *c)
{
struct window *w;
struct window_pane *wp;
struct mouse_event *m = &c->tty.mouse;
int pane_border;
w = c->session->curw->window;
pane_border = 0;
if ((c->last_mouse.b & MOUSE_BUTTON) != MOUSE_UP &&
(c->last_mouse.b & MOUSE_RESIZE_PANE)) {
if (m->event & MOUSE_EVENT_DRAG && m->flags & MOUSE_RESIZE_PANE) {
TAILQ_FOREACH(wp, &w->panes, entry) {
if (wp->xoff + wp->sx == c->last_mouse.x &&
wp->yoff <= 1 + c->last_mouse.y &&
wp->yoff + wp->sy >= c->last_mouse.y) {
if (wp->xoff + wp->sx == m->lx &&
wp->yoff <= 1 + m->ly &&
wp->yoff + wp->sy >= m->ly) {
layout_resize_pane(wp, LAYOUT_LEFTRIGHT,
mouse->x - c->last_mouse.x);
m->x - m->lx);
pane_border = 1;
}
if (wp->yoff + wp->sy == c->last_mouse.y &&
wp->xoff <= 1 + c->last_mouse.x &&
wp->xoff + wp->sx >= c->last_mouse.x) {
if (wp->yoff + wp->sy == m->ly &&
wp->xoff <= 1 + m->lx &&
wp->xoff + wp->sx >= m->lx) {
layout_resize_pane(wp, LAYOUT_TOPBOTTOM,
mouse->y - c->last_mouse.y);
m->y - m->ly);
pane_border = 1;
}
}
if (pane_border)
server_redraw_window(w);
} else if (mouse->b != MOUSE_UP &&
mouse->b == (mouse->b & MOUSE_BUTTON)) {
} else if (~m->event & MOUSE_EVENT_UP) {
TAILQ_FOREACH(wp, &w->panes, entry) {
if ((wp->xoff + wp->sx == mouse->x &&
wp->yoff <= 1 + mouse->y &&
wp->yoff + wp->sy >= mouse->y) ||
(wp->yoff + wp->sy == mouse->y &&
wp->xoff <= 1 + mouse->x &&
wp->xoff + wp->sx >= mouse->x)) {
if ((wp->xoff + wp->sx == m->x &&
wp->yoff <= 1 + m->y &&
wp->yoff + wp->sy >= m->y) ||
(wp->yoff + wp->sy == m->y &&
wp->xoff <= 1 + m->x &&
wp->xoff + wp->sx >= m->x)) {
pane_border = 1;
}
}
}
if (pane_border)
mouse->b |= MOUSE_RESIZE_PANE;
m->flags |= MOUSE_RESIZE_PANE;
else
m->flags &= ~MOUSE_RESIZE_PANE;
}
int

View File

@ -28,8 +28,7 @@
#include "tmux.h"
void server_client_check_mouse(struct client *, struct window_pane *,
struct mouse_event *);
void server_client_check_mouse(struct client *, struct window_pane *);
void server_client_repeat_timer(int, short, void *);
void server_client_check_exit(struct client *);
void server_client_check_redraw(struct client *);
@ -87,8 +86,12 @@ server_client_create(int fd)
c->prompt_buffer = NULL;
c->prompt_index = 0;
c->last_mouse.b = MOUSE_UP;
c->last_mouse.x = c->last_mouse.y = -1;
c->tty.mouse.xb = c->tty.mouse.button = 3;
c->tty.mouse.x = c->tty.mouse.y = -1;
c->tty.mouse.lx = c->tty.mouse.ly = -1;
c->tty.mouse.sx = c->tty.mouse.sy = -1;
c->tty.mouse.event = MOUSE_EVENT_UP;
c->tty.mouse.flags = 0;
evtimer_set(&c->repeat_timer, server_client_repeat_timer, c);
@ -271,37 +274,28 @@ server_client_status_timer(void)
/* Check for mouse keys. */
void
server_client_check_mouse(
struct client *c, struct window_pane *wp, struct mouse_event *mouse)
server_client_check_mouse(struct client *c, struct window_pane *wp)
{
struct session *s = c->session;
struct options *oo = &s->options;
int statusat;
struct session *s = c->session;
struct options *oo = &s->options;
struct mouse_event *m = &c->tty.mouse;
int statusat;
statusat = status_at_line(c);
/* Is this a window selection click on the status line? */
if (statusat != -1 && mouse->y == (u_int)statusat &&
if (statusat != -1 && m->y == (u_int)statusat &&
options_get_number(oo, "mouse-select-window")) {
if (mouse->b == MOUSE_UP && c->last_mouse.b != MOUSE_UP) {
status_set_window_at(c, mouse->x);
recalculate_sizes();
return;
}
if (mouse->b & MOUSE_45) {
if ((mouse->b & MOUSE_BUTTON) == MOUSE_1) {
if (m->event & MOUSE_EVENT_CLICK) {
status_set_window_at(c, m->x);
} else if (m->event == MOUSE_EVENT_WHEEL) {
if (m->wheel == MOUSE_WHEEL_UP)
session_previous(c->session, 0);
server_redraw_session(s);
recalculate_sizes();
}
if ((mouse->b & MOUSE_BUTTON) == MOUSE_2) {
else if (m->wheel == MOUSE_WHEEL_DOWN)
session_next(c->session, 0);
server_redraw_session(s);
recalculate_sizes();
}
return;
server_redraw_session(s);
}
memcpy(&c->last_mouse, mouse, sizeof c->last_mouse);
recalculate_sizes();
return;
}
@ -310,27 +304,25 @@ server_client_check_mouse(
* top and limit if at the bottom. From here on a struct mouse
* represents the offset onto the window itself.
*/
if (statusat == 0 &&mouse->y > 0)
mouse->y--;
else if (statusat > 0 && mouse->y >= (u_int)statusat)
mouse->y = statusat - 1;
if (statusat == 0 && m->y > 0)
m->y--;
else if (statusat > 0 && m->y >= (u_int)statusat)
m->y = statusat - 1;
/* Is this a pane selection? Allow down only in copy mode. */
if (options_get_number(oo, "mouse-select-pane") &&
((!(mouse->b & MOUSE_DRAG) && mouse->b != MOUSE_UP) ||
wp->mode != &window_copy_mode)) {
window_set_active_at(wp->window, mouse->x, mouse->y);
(m->event == MOUSE_EVENT_DOWN || wp->mode != &window_copy_mode)) {
window_set_active_at(wp->window, m->x, m->y);
server_redraw_window_borders(wp->window);
wp = wp->window->active; /* may have changed */
}
/* Check if trying to resize pane. */
if (options_get_number(oo, "mouse-resize-pane"))
layout_resize_pane_mouse(c, mouse);
layout_resize_pane_mouse(c);
/* Update last and pass through to client. */
memcpy(&c->last_mouse, mouse, sizeof c->last_mouse);
window_pane_mouse(wp, c->session, mouse);
window_pane_mouse(wp, c->session, m);
}
/* Handle data key input from client. */
@ -385,7 +377,7 @@ server_client_handle_key(struct client *c, int key)
if (key == KEYC_MOUSE) {
if (c->flags & CLIENT_READONLY)
return;
server_client_check_mouse(c, wp, &c->tty.mouse);
server_client_check_mouse(c, wp);
return;
}
@ -524,7 +516,7 @@ server_client_reset_state(struct client *c)
* a smooth appearance.
*/
mode = s->mode;
if ((c->last_mouse.b & MOUSE_RESIZE_PANE) &&
if ((c->tty.mouse.flags & MOUSE_RESIZE_PANE) &&
!(mode & (MODE_MOUSE_BUTTON|MODE_MOUSE_ANY)))
mode |= MODE_MOUSE_BUTTON;

72
tmux.h
View File

@ -1119,29 +1119,6 @@ struct session {
RB_HEAD(sessions, session);
ARRAY_DECL(sessionslist, struct session *);
/*
* Mouse input. 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. Bits
* 3, 4 and 5 are for keys. Bit 6 is set for dragging and 7 for mouse buttons 4
* and 5.
*/
struct mouse_event {
u_int b;
#define MOUSE_1 0
#define MOUSE_2 1
#define MOUSE_3 2
#define MOUSE_UP 3
#define MOUSE_BUTTON 3
#define MOUSE_SHIFT 4
#define MOUSE_ESCAPE 8
#define MOUSE_CTRL 16
#define MOUSE_DRAG 32
#define MOUSE_45 64
#define MOUSE_RESIZE_PANE 128 /* marker for resizing */
u_int x;
u_int y;
};
/* TTY information. */
struct tty_key {
char ch;
@ -1170,6 +1147,47 @@ struct tty_term {
};
LIST_HEAD(tty_terms, tty_term);
/* Mouse wheel states. */
#define MOUSE_WHEEL_UP 0
#define MOUSE_WHEEL_DOWN 1
/* Mouse events. */
#define MOUSE_EVENT_DOWN (1 << 0)
#define MOUSE_EVENT_DRAG (1 << 1)
#define MOUSE_EVENT_UP (1 << 2)
#define MOUSE_EVENT_CLICK (1 << 3)
#define MOUSE_EVENT_WHEEL (1 << 4)
/* Mouse flags. */
#define MOUSE_RESIZE_PANE (1 << 0)
/*
* Mouse input. When sent by xterm:
*
* - buttons are in the bottom two bits: 0 = b1; 1 = b2; 2 = b3; 3 = released
* - bits 3, 4 and 5 are for keys
* - bit 6 is set for dragging
* - bit 7 for buttons 4 and 5
*/
struct mouse_event {
u_int xb;
u_int x;
u_int lx;
u_int sx;
u_int y;
u_int ly;
u_int sy;
u_int button;
u_int clicks;
int wheel;
int event;
int flags;
};
struct tty {
struct client *client;
@ -1330,8 +1348,6 @@ struct client {
struct session *session;
struct session *last_session;
struct mouse_event last_mouse;
int wlmouse;
int references;
@ -1926,7 +1942,8 @@ void input_parse(struct window_pane *);
/* input-key.c */
void input_key(struct window_pane *, int);
void input_mouse(struct window_pane *, struct mouse_event *);
void input_mouse(struct window_pane *, struct session *,
struct mouse_event *);
/* xterm-keys.c */
char *xterm_keys_lookup(int);
@ -2170,8 +2187,7 @@ void layout_free(struct window *);
void layout_resize(struct window *, u_int, u_int);
void layout_resize_pane(
struct window_pane *, enum layout_type, int);
void layout_resize_pane_mouse(
struct client *c, struct mouse_event *mouse);
void layout_resize_pane_mouse(struct client *c);
void layout_assign_pane(struct layout_cell *, struct window_pane *);
struct layout_cell *layout_split_pane(
struct window_pane *, enum layout_type, int, int);

View File

@ -611,7 +611,7 @@ 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;
u_int i, value, x, y, b;
/*
* Standard mouse sequences are \033[M followed by three characters
@ -622,6 +622,7 @@ tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size)
*/
*size = 0;
x = y = b = 0;
/* First three bytes are always \033[M. */
if (buf[0] != '\033')
@ -661,21 +662,58 @@ tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size)
}
if (i == 0)
m->b = value;
b = value;
else if (i == 1)
m->x = value;
x = value;
else
m->y = value;
y = value;
}
log_debug("mouse input: %.*s", (int) *size, buf);
/* Check and return the mouse input. */
if (m->b < 32 || m->x < 33 || m->y < 33)
if (b < 32 || x < 33 || y < 33)
return (-1);
m->b -= 32;
m->x -= 33;
m->y -= 33;
log_debug("mouse position: x=%u y=%u b=%u", m->x, m->y, m->b);
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) {
m->lx = m->x;
m->ly = m->y;
}
m->xb = b;
if (b & 64) { /* wheel button */
b &= 3;
if (b == 0)
m->wheel = MOUSE_WHEEL_UP;
else if (b == 1)
m->wheel = MOUSE_WHEEL_DOWN;
m->event = MOUSE_EVENT_WHEEL;
} else if ((b & 3) == 3) {
if (~m->event & MOUSE_EVENT_DRAG && x == m->x && y == m->y) {
m->event = MOUSE_EVENT_CLICK;
} else
m->event = MOUSE_EVENT_DRAG;
m->event |= MOUSE_EVENT_UP;
} else {
if (b & 32) /* drag motion */
m->event = MOUSE_EVENT_DRAG;
else {
if (m->event & MOUSE_EVENT_UP && x == m->x && y == m->y)
m->clicks = (m->clicks + 1) % 3;
else
m->clicks = 0;
m->sx = x;
m->sy = y;
m->event = MOUSE_EVENT_DOWN;
}
m->button = (b & 3);
}
m->x = x;
m->y = y;
return (0);
}

View File

@ -623,7 +623,7 @@ window_choose_mouse(
struct window_choose_mode_item *item;
u_int idx;
if ((m->b & 3) == 3)
if (~m->event & MOUSE_EVENT_CLICK)
return;
if (m->x >= screen_size_x(s))
return;

View File

@ -829,11 +829,11 @@ window_copy_mouse(
return;
/* If mouse wheel (buttons 4 and 5), scroll. */
if ((m->b & MOUSE_45)) {
if ((m->b & MOUSE_BUTTON) == MOUSE_1) {
if (m->event == MOUSE_EVENT_WHEEL) {
if (m->wheel == MOUSE_WHEEL_UP) {
for (i = 0; i < 5; i++)
window_copy_cursor_up(wp, 0);
} else if ((m->b & MOUSE_BUTTON) == MOUSE_2) {
} else if (m->wheel == MOUSE_WHEEL_DOWN) {
for (i = 0; i < 5; i++)
window_copy_cursor_down(wp, 0);
if (data->oy == 0)
@ -847,7 +847,7 @@ window_copy_mouse(
* pressed, or stop the selection on their release.
*/
if (s->mode & MODE_MOUSE_BUTTON) {
if ((m->b & MOUSE_BUTTON) != MOUSE_UP) {
if (~m->event & MOUSE_EVENT_UP) {
window_copy_update_cursor(wp, m->x, m->y);
if (window_copy_update_selection(wp))
window_copy_redraw_screen(wp);
@ -857,7 +857,7 @@ window_copy_mouse(
}
/* Otherwise if other buttons pressed, start selection and motion. */
if ((m->b & MOUSE_BUTTON) != MOUSE_UP) {
if (~m->event & MOUSE_EVENT_UP) {
s->mode &= ~MODE_MOUSE_STANDARD;
s->mode |= MODE_MOUSE_BUTTON;

View File

@ -1011,7 +1011,7 @@ window_pane_mouse(
options_get_number(&wp->window->options, "mode-mouse"))
wp->mode->mouse(wp, sess, m);
} else if (wp->fd != -1)
input_mouse(wp, m);
input_mouse(wp, sess, m);
}
int