summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--input-keys.c20
-rw-r--r--input.c6
-rw-r--r--options-table.c5
-rw-r--r--screen-write.c12
-rw-r--r--server-client.c15
-rw-r--r--tmux.14
-rw-r--r--tmux.c1
-rw-r--r--tmux.h10
-rw-r--r--tty-keys.c60
-rw-r--r--tty.c4
-rw-r--r--utf8.c13
11 files changed, 128 insertions, 22 deletions
diff --git a/input-keys.c b/input-keys.c
index ac759684..f73ce397 100644
--- a/input-keys.c
+++ b/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);
}
}
diff --git a/input.c b/input.c
index 49224e0e..cb8c4e52 100644
--- a/input.c
+++ b/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;
diff --git a/options-table.c b/options-table.c
index 56cb24e5..4e2b8f61 100644
--- a/options-table.c
+++ b/options-table.c
@@ -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
diff --git a/screen-write.c b/screen-write.c
index c4e873b1..88c183ae 100644
--- a/screen-write.c
+++ b/screen-write.c
@@ -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)
diff --git a/server-client.c b/server-client.c
index 76f8d3a8..24a85b56 100644
--- a/server-client.c
+++ b/server-client.c
@@ -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);
}
diff --git a/tmux.1 b/tmux.1
index 079c8b8c..0f86e195 100644
--- a/tmux.1
+++ b/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
diff --git a/tmux.c b/tmux.c
index 54abf658..007d81fd 100644
--- a/tmux.c
+++ b/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);
}
diff --git a/tmux.h b/tmux.h
index 45bb1a1b..09999b00 100644
--- a/tmux.h
+++ b/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 *);
diff --git a/tty-keys.c b/tty-keys.c
index 19964538..3381aefe 100644
--- a/tty-keys.c
+++ b/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);
+
+ 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)++;
+ }
- log_debug(
- "mouse input: %.6s (%hhu,%hhu/%hhu)", buf, buf[4], buf[5], buf[3]);
+ 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);
- m->b = buf[3];
- m->x = buf[4];
- m->y = buf[5];
+ /* 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);
}
diff --git a/tty.c b/tty.c
index f7698708..80afa2d4 100644
--- a/tty.c
+++ b/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) {
diff --git a/utf8.c b/utf8.c
index 00b1c736..b276d872 100644
--- a/utf8.c
+++ b/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)