mirror of
https://github.com/tmate-io/tmate.git
synced 2024-11-07 16:54:01 +01:00
Support for UTF-8 mouse input (\033[1005h). This was added in xterm 262
and supports larger terminals than the older way. If the new mouse-utf8 option is on, UTF-8 mouse input is enabled for all UTF-8 terminals. The option defaults to on if LANG etc are set in the same manner as the utf8 option. With help and based on code from hsim at gmx.li.
This commit is contained in:
parent
5158dd9a8d
commit
ac3b78a841
20
input-keys.c
20
input-keys.c
@ -202,11 +202,23 @@ input_key(struct window_pane *wp, int key)
|
||||
void
|
||||
input_mouse(struct window_pane *wp, struct mouse_event *m)
|
||||
{
|
||||
char out[8];
|
||||
char buf[10];
|
||||
size_t len;
|
||||
|
||||
if (wp->screen->mode & ALL_MOUSE_MODES) {
|
||||
xsnprintf(out, sizeof out,
|
||||
"\033[M%c%c%c", m->b + 32, m->x + 33, m->y + 33);
|
||||
bufferevent_write(wp->event, out, strlen(out));
|
||||
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->x + 33, &buf[len]);
|
||||
len += utf8_split2(m->y + 33, &buf[len]);
|
||||
} else {
|
||||
if (m->b > 223 || m->x >= 222 || m->y > 222)
|
||||
return;
|
||||
len = xsnprintf(buf, sizeof buf, "\033[M");
|
||||
buf[len++] = m->b + 32;
|
||||
buf[len++] = m->x + 33;
|
||||
buf[len++] = m->y + 33;
|
||||
}
|
||||
bufferevent_write(wp->event, buf, len);
|
||||
}
|
||||
}
|
||||
|
6
input.c
6
input.c
@ -1161,6 +1161,9 @@ input_csi_dispatch(struct input_ctx *ictx)
|
||||
case 1003:
|
||||
screen_write_mousemode_off(&ictx->ctx);
|
||||
break;
|
||||
case 1005:
|
||||
screen_write_utf8mousemode(&ictx->ctx, 0);
|
||||
break;
|
||||
case 1049:
|
||||
window_pane_alternate_off(wp, &ictx->cell);
|
||||
break;
|
||||
@ -1209,6 +1212,9 @@ input_csi_dispatch(struct input_ctx *ictx)
|
||||
case 1003:
|
||||
screen_write_mousemode_on(&ictx->ctx, MODE_MOUSE_ANY);
|
||||
break;
|
||||
case 1005:
|
||||
screen_write_utf8mousemode(&ictx->ctx, 1);
|
||||
break;
|
||||
case 1049:
|
||||
window_pane_alternate_on(wp, &ictx->cell);
|
||||
break;
|
||||
|
@ -198,6 +198,11 @@ const struct options_table_entry session_options_table[] = {
|
||||
.default_num = 0
|
||||
},
|
||||
|
||||
{ .name = "mouse-utf8",
|
||||
.type = OPTIONS_TABLE_FLAG,
|
||||
.default_num = 0
|
||||
},
|
||||
|
||||
{ .name = "pane-active-border-bg",
|
||||
.type = OPTIONS_TABLE_COLOUR,
|
||||
.default_num = 8
|
||||
|
@ -829,6 +829,18 @@ screen_write_insertmode(struct screen_write_ctx *ctx, int state)
|
||||
s->mode &= ~MODE_INSERT;
|
||||
}
|
||||
|
||||
/* Set UTF-8 mouse mode. */
|
||||
void
|
||||
screen_write_utf8mousemode(struct screen_write_ctx *ctx, int state)
|
||||
{
|
||||
struct screen *s = ctx->s;
|
||||
|
||||
if (state)
|
||||
s->mode |= MODE_MOUSE_UTF8;
|
||||
else
|
||||
s->mode &= ~MODE_MOUSE_UTF8;
|
||||
}
|
||||
|
||||
/* Set mouse mode off. */
|
||||
void
|
||||
screen_write_mousemode_off(struct screen_write_ctx *ctx)
|
||||
|
@ -451,6 +451,21 @@ server_client_reset_state(struct client *c)
|
||||
if (TAILQ_NEXT(TAILQ_FIRST(&w->panes), entry) != NULL &&
|
||||
options_get_number(oo, "mouse-select-pane"))
|
||||
mode |= MODE_MOUSE_STANDARD;
|
||||
|
||||
/*
|
||||
* Set UTF-8 mouse input if required. If the terminal is UTF-8, the
|
||||
* user has set mouse-utf8 and any mouse mode is in effect, turn on
|
||||
* UTF-8 mouse input. If the receiving terminal hasn't requested it
|
||||
* (that is, it isn't in s->mode), then it'll be converted in
|
||||
* input_mouse.
|
||||
*/
|
||||
if ((c->tty.flags & TTY_UTF8) &&
|
||||
(mode & ALL_MOUSE_MODES) && options_get_number(oo, "mouse-utf8"))
|
||||
mode |= MODE_MOUSE_UTF8;
|
||||
else
|
||||
mode &= ~MODE_MOUSE_UTF8;
|
||||
|
||||
/* Set the terminal mode and reset attributes. */
|
||||
tty_update_mode(&c->tty, mode);
|
||||
tty_reset(&c->tty);
|
||||
}
|
||||
|
4
tmux.1
4
tmux.1
@ -1806,6 +1806,10 @@ flag to
|
||||
Repeat is enabled for the default keys bound to the
|
||||
.Ic resize-pane
|
||||
command.
|
||||
.It Xo Ic mouse-utf8
|
||||
.Op Ic on | off
|
||||
.Xc
|
||||
If enabled, request mouse input as UTF-8 on UTF-8 terminals.
|
||||
.It Xo Ic set-remain-on-exit
|
||||
.Op Ic on | off
|
||||
.Xc
|
||||
|
1
tmux.c
1
tmux.c
@ -334,6 +334,7 @@ main(int argc, char **argv)
|
||||
/* Enable UTF-8 if the first client is on UTF-8 terminal. */
|
||||
if (flags & IDENTIFY_UTF8) {
|
||||
options_set_number(&global_s_options, "status-utf8", 1);
|
||||
options_set_number(&global_s_options, "mouse-utf8", 1);
|
||||
options_set_number(&global_w_options, "utf8", 1);
|
||||
}
|
||||
|
||||
|
10
tmux.h
10
tmux.h
@ -550,6 +550,7 @@ struct mode_key_table {
|
||||
#define MODE_MOUSE_HIGHLIGHT 0x40
|
||||
#define MODE_MOUSE_BUTTON 0x80
|
||||
#define MODE_MOUSE_ANY 0x100
|
||||
#define MODE_MOUSE_UTF8 0x200
|
||||
|
||||
#define ALL_MOUSE_MODES (MODE_MOUSE_STANDARD| \
|
||||
MODE_MOUSE_HIGHLIGHT|MODE_MOUSE_BUTTON|MODE_MOUSE_ANY)
|
||||
@ -1075,15 +1076,15 @@ struct tty_ctx {
|
||||
*/
|
||||
/* Mouse input. */
|
||||
struct mouse_event {
|
||||
u_char b;
|
||||
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_45 64
|
||||
u_char x;
|
||||
u_char y;
|
||||
u_int x;
|
||||
u_int y;
|
||||
};
|
||||
|
||||
/* Saved message entry. */
|
||||
@ -1817,6 +1818,7 @@ void screen_write_cursormode(struct screen_write_ctx *, int);
|
||||
void screen_write_reverseindex(struct screen_write_ctx *);
|
||||
void screen_write_scrollregion(struct screen_write_ctx *, u_int, u_int);
|
||||
void screen_write_insertmode(struct screen_write_ctx *, int);
|
||||
void screen_write_utf8mousemode(struct screen_write_ctx *, int);
|
||||
void screen_write_mousemode_on(struct screen_write_ctx *, int);
|
||||
void screen_write_mousemode_off(struct screen_write_ctx *);
|
||||
void screen_write_linefeed(struct screen_write_ctx *, int);
|
||||
@ -2017,6 +2019,8 @@ void session_group_synchronize1(struct session *, struct session *);
|
||||
void utf8_build(void);
|
||||
int utf8_open(struct utf8_data *, u_char);
|
||||
int utf8_append(struct utf8_data *, u_char);
|
||||
u_int utf8_combine(const struct utf8_data *);
|
||||
u_int utf8_split2(u_int, u_char *);
|
||||
|
||||
/* procname.c */
|
||||
char *get_proc_name(int, char *);
|
||||
|
60
tty-keys.c
60
tty-keys.c
@ -38,7 +38,7 @@ struct tty_key *tty_keys_find1(
|
||||
struct tty_key *, const char *, size_t, size_t *);
|
||||
struct tty_key *tty_keys_find(struct tty *, const char *, size_t, size_t *);
|
||||
void tty_keys_callback(int, short, void *);
|
||||
int tty_keys_mouse(
|
||||
int tty_keys_mouse(struct tty *,
|
||||
const char *, size_t, size_t *, struct mouse_event *);
|
||||
|
||||
struct tty_key_ent {
|
||||
@ -462,7 +462,7 @@ tty_keys_next(struct tty *tty)
|
||||
}
|
||||
|
||||
/* Is this a mouse key press? */
|
||||
switch (tty_keys_mouse(buf, len, &size, &mouse)) {
|
||||
switch (tty_keys_mouse(tty, buf, len, &size, &mouse)) {
|
||||
case 0: /* yes */
|
||||
evbuffer_drain(tty->event->input, size);
|
||||
key = KEYC_MOUSE;
|
||||
@ -584,44 +584,74 @@ tty_keys_callback(unused int fd, unused short events, void *data)
|
||||
* (probably a mouse sequence but need more data).
|
||||
*/
|
||||
int
|
||||
tty_keys_mouse(const char *buf, size_t len, size_t *size, struct mouse_event *m)
|
||||
tty_keys_mouse(struct tty *tty,
|
||||
const char *buf, size_t len, size_t *size, struct mouse_event *m)
|
||||
{
|
||||
struct utf8_data utf8data;
|
||||
u_int i, value;
|
||||
|
||||
/*
|
||||
* Mouse sequences are \033[M followed by three characters indicating
|
||||
* buttons, X and Y, all based at 32 with 1,1 top-left.
|
||||
* Standard mouse sequences are \033[M followed by three characters
|
||||
* indicating buttons, 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.
|
||||
*/
|
||||
|
||||
*size = 0;
|
||||
|
||||
/* First three bytes are always \033[M. */
|
||||
if (buf[0] != '\033')
|
||||
return (-1);
|
||||
if (len == 1)
|
||||
return (1);
|
||||
|
||||
if (buf[1] != '[')
|
||||
return (-1);
|
||||
if (len == 2)
|
||||
return (1);
|
||||
|
||||
if (buf[2] != 'M')
|
||||
return (-1);
|
||||
if (len == 3)
|
||||
return (1);
|
||||
|
||||
if (len < 6)
|
||||
return (1);
|
||||
*size = 6;
|
||||
/* Read the three inputs. */
|
||||
*size = 3;
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (len < *size)
|
||||
return (1);
|
||||
|
||||
log_debug(
|
||||
"mouse input: %.6s (%hhu,%hhu/%hhu)", buf, buf[4], buf[5], buf[3]);
|
||||
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 = buf[*size];
|
||||
(*size)++;
|
||||
} else {
|
||||
value = buf[*size];
|
||||
(*size)++;
|
||||
}
|
||||
|
||||
m->b = buf[3];
|
||||
m->x = buf[4];
|
||||
m->y = buf[5];
|
||||
if (i == 0)
|
||||
m->b = value;
|
||||
else if (i == 1)
|
||||
m->x = value;
|
||||
else
|
||||
m->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)
|
||||
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);
|
||||
return (0);
|
||||
}
|
||||
|
4
tty.c
4
tty.c
@ -405,6 +405,8 @@ tty_update_mode(struct tty *tty, int mode)
|
||||
}
|
||||
if (changed & ALL_MOUSE_MODES) {
|
||||
if (mode & ALL_MOUSE_MODES) {
|
||||
if (mode & MODE_MOUSE_UTF8)
|
||||
tty_puts(tty, "\033[?1005h");
|
||||
if (mode & MODE_MOUSE_STANDARD)
|
||||
tty_puts(tty, "\033[?1000h");
|
||||
else if (mode & MODE_MOUSE_HIGHLIGHT)
|
||||
@ -422,6 +424,8 @@ tty_update_mode(struct tty *tty, int mode)
|
||||
tty_puts(tty, "\033[?1002l");
|
||||
else if (tty->mode & MODE_MOUSE_ANY)
|
||||
tty_puts(tty, "\033[?1003l");
|
||||
if (tty->mode & MODE_MOUSE_UTF8)
|
||||
tty_puts(tty, "\033[?1005l");
|
||||
}
|
||||
}
|
||||
if (changed & MODE_KKEYPAD) {
|
||||
|
13
utf8.c
13
utf8.c
@ -318,6 +318,19 @@ utf8_combine(const struct utf8_data *utf8data)
|
||||
return (value);
|
||||
}
|
||||
|
||||
/* Split a two-byte UTF-8 character. */
|
||||
u_int
|
||||
utf8_split2(u_int uc, u_char *ptr)
|
||||
{
|
||||
if (uc > 0x7f) {
|
||||
ptr[0] = (uc >> 6) | 0xc0;
|
||||
ptr[1] = (uc & 0x3f) | 0x80;
|
||||
return (2);
|
||||
}
|
||||
ptr[0] = uc;
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* Lookup width of UTF-8 data in tree. */
|
||||
u_int
|
||||
utf8_width(const struct utf8_data *utf8data)
|
||||
|
Loading…
Reference in New Issue
Block a user