mirror of
https://github.com/tmux/tmux.git
synced 2025-12-22 07:16:06 +00:00
If tmux receives a palette request (OSC 4) in a pane and the palette
entry has not been set, send a request to the most recently used client and forward any response instead. Based on change from Tim Culverhouse in GitHub issue 4665.
This commit is contained in:
222
input.c
222
input.c
@@ -51,6 +51,20 @@
|
|||||||
* be passed to the underlying terminals.
|
* be passed to the underlying terminals.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Request sent by a pane. */
|
||||||
|
struct input_request {
|
||||||
|
struct client *c;
|
||||||
|
struct input_ctx *ictx;
|
||||||
|
|
||||||
|
enum input_request_type type;
|
||||||
|
int idx;
|
||||||
|
time_t t;
|
||||||
|
|
||||||
|
TAILQ_ENTRY(input_request) entry;
|
||||||
|
TAILQ_ENTRY(input_request) centry;
|
||||||
|
};
|
||||||
|
#define INPUT_REQUEST_TIMEOUT 5
|
||||||
|
|
||||||
/* Input parser cell. */
|
/* Input parser cell. */
|
||||||
struct input_cell {
|
struct input_cell {
|
||||||
struct grid_cell cell;
|
struct grid_cell cell;
|
||||||
@@ -72,6 +86,12 @@ struct input_param {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Type of terminator. */
|
||||||
|
enum input_end_type {
|
||||||
|
INPUT_END_ST,
|
||||||
|
INPUT_END_BEL
|
||||||
|
};
|
||||||
|
|
||||||
/* Input parser context. */
|
/* Input parser context. */
|
||||||
struct input_ctx {
|
struct input_ctx {
|
||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
@@ -80,7 +100,6 @@ struct input_ctx {
|
|||||||
struct colour_palette *palette;
|
struct colour_palette *palette;
|
||||||
|
|
||||||
struct input_cell cell;
|
struct input_cell cell;
|
||||||
|
|
||||||
struct input_cell old_cell;
|
struct input_cell old_cell;
|
||||||
u_int old_cx;
|
u_int old_cx;
|
||||||
u_int old_cy;
|
u_int old_cy;
|
||||||
@@ -96,10 +115,7 @@ struct input_ctx {
|
|||||||
u_char *input_buf;
|
u_char *input_buf;
|
||||||
size_t input_len;
|
size_t input_len;
|
||||||
size_t input_space;
|
size_t input_space;
|
||||||
enum {
|
enum input_end_type input_end;
|
||||||
INPUT_END_ST,
|
|
||||||
INPUT_END_BEL
|
|
||||||
} input_end;
|
|
||||||
|
|
||||||
struct input_param param_list[24];
|
struct input_param param_list[24];
|
||||||
u_int param_list_len;
|
u_int param_list_len;
|
||||||
@@ -110,23 +126,29 @@ struct input_ctx {
|
|||||||
int ch;
|
int ch;
|
||||||
struct utf8_data last;
|
struct utf8_data last;
|
||||||
|
|
||||||
|
const struct input_state *state;
|
||||||
int flags;
|
int flags;
|
||||||
#define INPUT_DISCARD 0x1
|
#define INPUT_DISCARD 0x1
|
||||||
#define INPUT_LAST 0x2
|
#define INPUT_LAST 0x2
|
||||||
|
|
||||||
const struct input_state *state;
|
struct input_requests requests[INPUT_REQUEST_TYPES];
|
||||||
|
u_int request_count;
|
||||||
struct event timer;
|
struct event request_timer;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* All input received since we were last in the ground state. Sent to
|
* All input received since we were last in the ground state. Sent to
|
||||||
* control clients on connection.
|
* control clients on connection.
|
||||||
*/
|
*/
|
||||||
struct evbuffer *since_ground;
|
struct evbuffer *since_ground;
|
||||||
|
struct event ground_timer;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Helper functions. */
|
/* Helper functions. */
|
||||||
struct input_transition;
|
struct input_transition;
|
||||||
|
static void input_request_timer_callback(int, short, void *);
|
||||||
|
static void input_start_request_timer(struct input_ctx *);
|
||||||
|
static int input_add_request(struct input_ctx *, enum input_request_type,
|
||||||
|
int);
|
||||||
static int input_split(struct input_ctx *);
|
static int input_split(struct input_ctx *);
|
||||||
static int input_get(struct input_ctx *, u_int, int, int);
|
static int input_get(struct input_ctx *, u_int, int, int);
|
||||||
static void printflike(2, 3) input_reply(struct input_ctx *, const char *, ...);
|
static void printflike(2, 3) input_reply(struct input_ctx *, const char *, ...);
|
||||||
@@ -766,7 +788,7 @@ input_stop_utf8(struct input_ctx *ictx)
|
|||||||
* long, so reset to ground.
|
* long, so reset to ground.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
input_timer_callback(__unused int fd, __unused short events, void *arg)
|
input_ground_timer_callback(__unused int fd, __unused short events, void *arg)
|
||||||
{
|
{
|
||||||
struct input_ctx *ictx = arg;
|
struct input_ctx *ictx = arg;
|
||||||
|
|
||||||
@@ -776,12 +798,12 @@ input_timer_callback(__unused int fd, __unused short events, void *arg)
|
|||||||
|
|
||||||
/* Start the timer. */
|
/* Start the timer. */
|
||||||
static void
|
static void
|
||||||
input_start_timer(struct input_ctx *ictx)
|
input_start_ground_timer(struct input_ctx *ictx)
|
||||||
{
|
{
|
||||||
struct timeval tv = { .tv_sec = 5, .tv_usec = 0 };
|
struct timeval tv = { .tv_sec = 5, .tv_usec = 0 };
|
||||||
|
|
||||||
event_del(&ictx->timer);
|
event_del(&ictx->ground_timer);
|
||||||
event_add(&ictx->timer, &tv);
|
event_add(&ictx->ground_timer, &tv);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset cell state to default. */
|
/* Reset cell state to default. */
|
||||||
@@ -830,6 +852,7 @@ input_init(struct window_pane *wp, struct bufferevent *bev,
|
|||||||
struct colour_palette *palette)
|
struct colour_palette *palette)
|
||||||
{
|
{
|
||||||
struct input_ctx *ictx;
|
struct input_ctx *ictx;
|
||||||
|
u_int i;
|
||||||
|
|
||||||
ictx = xcalloc(1, sizeof *ictx);
|
ictx = xcalloc(1, sizeof *ictx);
|
||||||
ictx->wp = wp;
|
ictx->wp = wp;
|
||||||
@@ -842,8 +865,11 @@ input_init(struct window_pane *wp, struct bufferevent *bev,
|
|||||||
ictx->since_ground = evbuffer_new();
|
ictx->since_ground = evbuffer_new();
|
||||||
if (ictx->since_ground == NULL)
|
if (ictx->since_ground == NULL)
|
||||||
fatalx("out of memory");
|
fatalx("out of memory");
|
||||||
|
evtimer_set(&ictx->ground_timer, input_ground_timer_callback, ictx);
|
||||||
|
|
||||||
evtimer_set(&ictx->timer, input_timer_callback, ictx);
|
for (i = 0; i < INPUT_REQUEST_TYPES; i++)
|
||||||
|
TAILQ_INIT(&ictx->requests[i]);
|
||||||
|
evtimer_set(&ictx->request_timer, input_request_timer_callback, ictx);
|
||||||
|
|
||||||
input_reset(ictx, 0);
|
input_reset(ictx, 0);
|
||||||
return (ictx);
|
return (ictx);
|
||||||
@@ -853,6 +879,8 @@ input_init(struct window_pane *wp, struct bufferevent *bev,
|
|||||||
void
|
void
|
||||||
input_free(struct input_ctx *ictx)
|
input_free(struct input_ctx *ictx)
|
||||||
{
|
{
|
||||||
|
struct input_request_list *irl;
|
||||||
|
struct input_request *ir, *ir1;
|
||||||
u_int i;
|
u_int i;
|
||||||
|
|
||||||
for (i = 0; i < ictx->param_list_len; i++) {
|
for (i = 0; i < ictx->param_list_len; i++) {
|
||||||
@@ -860,10 +888,21 @@ input_free(struct input_ctx *ictx)
|
|||||||
free(ictx->param_list[i].str);
|
free(ictx->param_list[i].str);
|
||||||
}
|
}
|
||||||
|
|
||||||
event_del(&ictx->timer);
|
for (i = 0; i < INPUT_REQUEST_TYPES; i++) {
|
||||||
|
TAILQ_FOREACH_SAFE(ir, &ictx->requests[i], entry, ir1) {
|
||||||
|
log_debug("%s: req %p: client %s, pane %%%u, type %d",
|
||||||
|
__func__, ir, ir->c->name, ictx->wp->id, i);
|
||||||
|
irl = &ir->c->input_requests[i];
|
||||||
|
TAILQ_REMOVE(&ictx->requests[i], ir, entry);
|
||||||
|
TAILQ_REMOVE(&irl->requests, ir, centry);
|
||||||
|
free(ir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
event_del(&ictx->request_timer);
|
||||||
|
|
||||||
free(ictx->input_buf);
|
free(ictx->input_buf);
|
||||||
evbuffer_free(ictx->since_ground);
|
evbuffer_free(ictx->since_ground);
|
||||||
|
event_del(&ictx->ground_timer);
|
||||||
|
|
||||||
free(ictx);
|
free(ictx);
|
||||||
}
|
}
|
||||||
@@ -1122,7 +1161,7 @@ input_reply(struct input_ctx *ictx, const char *fmt, ...)
|
|||||||
static void
|
static void
|
||||||
input_clear(struct input_ctx *ictx)
|
input_clear(struct input_ctx *ictx)
|
||||||
{
|
{
|
||||||
event_del(&ictx->timer);
|
event_del(&ictx->ground_timer);
|
||||||
|
|
||||||
*ictx->interm_buf = '\0';
|
*ictx->interm_buf = '\0';
|
||||||
ictx->interm_len = 0;
|
ictx->interm_len = 0;
|
||||||
@@ -1142,7 +1181,7 @@ input_clear(struct input_ctx *ictx)
|
|||||||
static void
|
static void
|
||||||
input_ground(struct input_ctx *ictx)
|
input_ground(struct input_ctx *ictx)
|
||||||
{
|
{
|
||||||
event_del(&ictx->timer);
|
event_del(&ictx->ground_timer);
|
||||||
evbuffer_drain(ictx->since_ground, EVBUFFER_LENGTH(ictx->since_ground));
|
evbuffer_drain(ictx->since_ground, EVBUFFER_LENGTH(ictx->since_ground));
|
||||||
|
|
||||||
if (ictx->input_space > INPUT_BUF_START) {
|
if (ictx->input_space > INPUT_BUF_START) {
|
||||||
@@ -2385,7 +2424,7 @@ input_enter_dcs(struct input_ctx *ictx)
|
|||||||
log_debug("%s", __func__);
|
log_debug("%s", __func__);
|
||||||
|
|
||||||
input_clear(ictx);
|
input_clear(ictx);
|
||||||
input_start_timer(ictx);
|
input_start_ground_timer(ictx);
|
||||||
ictx->flags &= ~INPUT_LAST;
|
ictx->flags &= ~INPUT_LAST;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2511,7 +2550,7 @@ input_enter_osc(struct input_ctx *ictx)
|
|||||||
log_debug("%s", __func__);
|
log_debug("%s", __func__);
|
||||||
|
|
||||||
input_clear(ictx);
|
input_clear(ictx);
|
||||||
input_start_timer(ictx);
|
input_start_ground_timer(ictx);
|
||||||
ictx->flags &= ~INPUT_LAST;
|
ictx->flags &= ~INPUT_LAST;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2606,7 +2645,7 @@ input_enter_apc(struct input_ctx *ictx)
|
|||||||
log_debug("%s", __func__);
|
log_debug("%s", __func__);
|
||||||
|
|
||||||
input_clear(ictx);
|
input_clear(ictx);
|
||||||
input_start_timer(ictx);
|
input_start_ground_timer(ictx);
|
||||||
ictx->flags &= ~INPUT_LAST;
|
ictx->flags &= ~INPUT_LAST;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2637,7 +2676,7 @@ input_enter_rename(struct input_ctx *ictx)
|
|||||||
log_debug("%s", __func__);
|
log_debug("%s", __func__);
|
||||||
|
|
||||||
input_clear(ictx);
|
input_clear(ictx);
|
||||||
input_start_timer(ictx);
|
input_start_ground_timer(ictx);
|
||||||
ictx->flags &= ~INPUT_LAST;
|
ictx->flags &= ~INPUT_LAST;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2767,11 +2806,15 @@ input_osc_4(struct input_ctx *ictx, const char *p)
|
|||||||
s = strsep(&next, ";");
|
s = strsep(&next, ";");
|
||||||
if (strcmp(s, "?") == 0) {
|
if (strcmp(s, "?") == 0) {
|
||||||
c = colour_palette_get(palette, idx|COLOUR_FLAG_256);
|
c = colour_palette_get(palette, idx|COLOUR_FLAG_256);
|
||||||
if (c != -1)
|
if (c != -1) {
|
||||||
input_osc_colour_reply(ictx, 4, idx, c);
|
input_osc_colour_reply(ictx, 4, idx, c);
|
||||||
s = next;
|
s = next;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
input_add_request(ictx, INPUT_REQUEST_PALETTE, idx);
|
||||||
|
s = next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if ((c = colour_parseX11(s)) == -1) {
|
if ((c = colour_parseX11(s)) == -1) {
|
||||||
s = next;
|
s = next;
|
||||||
continue;
|
continue;
|
||||||
@@ -3110,6 +3153,143 @@ input_set_buffer_size(size_t buffer_size)
|
|||||||
input_buffer_size = buffer_size;
|
input_buffer_size = buffer_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Request timer. Remove any requests that are too old. */
|
||||||
|
static void
|
||||||
|
input_request_timer_callback(__unused int fd, __unused short events, void *arg)
|
||||||
|
{
|
||||||
|
struct input_ctx *ictx = arg;
|
||||||
|
struct input_request *ir, *ir1;
|
||||||
|
struct input_request_list *irl;
|
||||||
|
u_int i;
|
||||||
|
time_t t = time(NULL);
|
||||||
|
|
||||||
|
for (i = 0; i < INPUT_REQUEST_TYPES; i++) {
|
||||||
|
TAILQ_FOREACH_SAFE(ir, &ictx->requests[i], entry, ir1) {
|
||||||
|
if (ir->t >= t - INPUT_REQUEST_TIMEOUT)
|
||||||
|
continue;
|
||||||
|
log_debug("%s: req %p: client %s, pane %%%u, type %d",
|
||||||
|
__func__, ir, ir->c->name, ictx->wp->id, ir->type);
|
||||||
|
irl = &ir->c->input_requests[i];
|
||||||
|
TAILQ_REMOVE(&ictx->requests[i], ir, entry);
|
||||||
|
TAILQ_REMOVE(&irl->requests, ir, centry);
|
||||||
|
ictx->request_count--;
|
||||||
|
free(ir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ictx->request_count != 0)
|
||||||
|
input_start_request_timer(ictx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Start the request timer. */
|
||||||
|
static void
|
||||||
|
input_start_request_timer(struct input_ctx *ictx)
|
||||||
|
{
|
||||||
|
struct timeval tv = { .tv_sec = 1, .tv_usec = 0 };
|
||||||
|
|
||||||
|
event_del(&ictx->request_timer);
|
||||||
|
event_add(&ictx->request_timer, &tv);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add a request. */
|
||||||
|
static int
|
||||||
|
input_add_request(struct input_ctx *ictx, enum input_request_type type, int idx)
|
||||||
|
{
|
||||||
|
struct window_pane *wp = ictx->wp;
|
||||||
|
struct window *w;
|
||||||
|
struct client *c = NULL, *loop;
|
||||||
|
struct input_request *ir;
|
||||||
|
char s[64];
|
||||||
|
|
||||||
|
if (wp == NULL)
|
||||||
|
return (-1);
|
||||||
|
w = wp->window;
|
||||||
|
|
||||||
|
TAILQ_FOREACH(loop, &clients, entry) {
|
||||||
|
if (loop->flags & CLIENT_UNATTACHEDFLAGS)
|
||||||
|
continue;
|
||||||
|
if (loop->session == NULL || !session_has(loop->session, w))
|
||||||
|
continue;
|
||||||
|
if (~loop->tty.flags & TTY_STARTED)
|
||||||
|
continue;
|
||||||
|
if (c == NULL)
|
||||||
|
c = loop;
|
||||||
|
else if (timercmp(&loop->activity_time, &c->activity_time, >))
|
||||||
|
c = loop;
|
||||||
|
}
|
||||||
|
if (c == NULL)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
ir = xcalloc (1, sizeof *ir);
|
||||||
|
ir->c = c;
|
||||||
|
ir->ictx = ictx;
|
||||||
|
ir->type = type;
|
||||||
|
ir->idx = idx;
|
||||||
|
ir->t = time(NULL);
|
||||||
|
TAILQ_INSERT_TAIL(&ictx->requests[type], ir, entry);
|
||||||
|
TAILQ_INSERT_TAIL(&c->input_requests[type].requests, ir, centry);
|
||||||
|
if (++ictx->request_count == 1)
|
||||||
|
input_start_request_timer(ictx);
|
||||||
|
log_debug("%s: req %p: client %s, pane %%%u, type %d", __func__, ir,
|
||||||
|
c->name, wp->id, type);
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case INPUT_REQUEST_PALETTE:
|
||||||
|
xsnprintf(s, sizeof s, "\033]4;%d;?\033\\", idx);
|
||||||
|
tty_puts(&c->tty, s);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle a reply to a request. */
|
||||||
|
void
|
||||||
|
input_request_reply(struct client *c, enum input_request_type type, void *data)
|
||||||
|
{
|
||||||
|
struct input_request_list *irl = &c->input_requests[type];
|
||||||
|
struct input_request *ir, *ir1;
|
||||||
|
struct input_request_palette_data *pd = data;
|
||||||
|
|
||||||
|
TAILQ_FOREACH_SAFE(ir, &irl->requests, centry, ir1) {
|
||||||
|
log_debug("%s: req %p: client %s, pane %%%u, type %d",
|
||||||
|
__func__, ir, c->name, ir->ictx->wp->id, ir->type);
|
||||||
|
switch (type) {
|
||||||
|
case INPUT_REQUEST_PALETTE:
|
||||||
|
if (pd->idx != ir->idx)
|
||||||
|
continue;
|
||||||
|
input_osc_colour_reply(ir->ictx, 4, pd->idx, pd->c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
TAILQ_REMOVE(&ir->ictx->requests[type], ir, entry);
|
||||||
|
TAILQ_REMOVE(&irl->requests, ir, centry);
|
||||||
|
ir->ictx->request_count--;
|
||||||
|
free(ir);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cancel pending requests for client. */
|
||||||
|
void
|
||||||
|
input_cancel_requests(struct client *c)
|
||||||
|
{
|
||||||
|
struct input_request_list *irl;
|
||||||
|
struct input_request *ir, *ir1;
|
||||||
|
u_int i;
|
||||||
|
|
||||||
|
for (i = 0; i < INPUT_REQUEST_TYPES; i++) {
|
||||||
|
irl = &c->input_requests[i];
|
||||||
|
TAILQ_FOREACH_SAFE(ir, &irl->requests, entry, ir1) {
|
||||||
|
log_debug("%s: req %p: client %s, pane %%%u, type %d",
|
||||||
|
__func__, ir, c->name, ir->ictx->wp->id, ir->type);
|
||||||
|
TAILQ_REMOVE(&ir->ictx->requests[i], ir, entry);
|
||||||
|
TAILQ_REMOVE(&irl->requests, ir, centry);
|
||||||
|
ir->ictx->request_count--;
|
||||||
|
free(ir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Report current theme. */
|
||||||
static void
|
static void
|
||||||
input_report_current_theme(struct input_ctx *ictx)
|
input_report_current_theme(struct input_ctx *ictx)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -282,6 +282,7 @@ struct client *
|
|||||||
server_client_create(int fd)
|
server_client_create(int fd)
|
||||||
{
|
{
|
||||||
struct client *c;
|
struct client *c;
|
||||||
|
u_int i;
|
||||||
|
|
||||||
setblocking(fd, 0);
|
setblocking(fd, 0);
|
||||||
|
|
||||||
@@ -315,6 +316,12 @@ server_client_create(int fd)
|
|||||||
evtimer_set(&c->repeat_timer, server_client_repeat_timer, c);
|
evtimer_set(&c->repeat_timer, server_client_repeat_timer, c);
|
||||||
evtimer_set(&c->click_timer, server_client_click_timer, c);
|
evtimer_set(&c->click_timer, server_client_click_timer, c);
|
||||||
|
|
||||||
|
for (i = 0; i < INPUT_REQUEST_TYPES; i++) {
|
||||||
|
c->input_requests[i].c = c;
|
||||||
|
c->input_requests[i].type = i;
|
||||||
|
TAILQ_INIT(&c->input_requests[i].requests);
|
||||||
|
}
|
||||||
|
|
||||||
TAILQ_INSERT_TAIL(&clients, c, entry);
|
TAILQ_INSERT_TAIL(&clients, c, entry);
|
||||||
log_debug("new client %p", c);
|
log_debug("new client %p", c);
|
||||||
return (c);
|
return (c);
|
||||||
@@ -463,6 +470,7 @@ server_client_lost(struct client *c)
|
|||||||
tty_term_free_list(c->term_caps, c->term_ncaps);
|
tty_term_free_list(c->term_caps, c->term_ncaps);
|
||||||
|
|
||||||
status_free(c);
|
status_free(c);
|
||||||
|
input_cancel_requests(c);
|
||||||
|
|
||||||
free(c->title);
|
free(c->title);
|
||||||
free((void *)c->cwd);
|
free((void *)c->cwd);
|
||||||
|
|||||||
26
tmux.h
26
tmux.h
@@ -53,6 +53,8 @@ struct format_tree;
|
|||||||
struct hyperlinks_uri;
|
struct hyperlinks_uri;
|
||||||
struct hyperlinks;
|
struct hyperlinks;
|
||||||
struct input_ctx;
|
struct input_ctx;
|
||||||
|
struct input_request;
|
||||||
|
struct input_requests;
|
||||||
struct job;
|
struct job;
|
||||||
struct menu_data;
|
struct menu_data;
|
||||||
struct mode_tree_data;
|
struct mode_tree_data;
|
||||||
@@ -1092,6 +1094,26 @@ struct window_mode_entry {
|
|||||||
TAILQ_ENTRY(window_mode_entry) entry;
|
TAILQ_ENTRY(window_mode_entry) entry;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Type of request to client. */
|
||||||
|
enum input_request_type {
|
||||||
|
INPUT_REQUEST_PALETTE
|
||||||
|
};
|
||||||
|
#define INPUT_REQUEST_TYPES (1)
|
||||||
|
|
||||||
|
/* Palette request reply data. */
|
||||||
|
struct input_request_palette_data {
|
||||||
|
int idx;
|
||||||
|
int c;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Request sent to client on behalf of pane. */
|
||||||
|
TAILQ_HEAD(input_requests, input_request);
|
||||||
|
struct input_request_list {
|
||||||
|
struct client *c;
|
||||||
|
enum input_request_type type;
|
||||||
|
struct input_requests requests;
|
||||||
|
};
|
||||||
|
|
||||||
/* Offsets into pane buffer. */
|
/* Offsets into pane buffer. */
|
||||||
struct window_pane_offset {
|
struct window_pane_offset {
|
||||||
size_t used;
|
size_t used;
|
||||||
@@ -1920,6 +1942,8 @@ struct client {
|
|||||||
struct status_line status;
|
struct status_line status;
|
||||||
enum client_theme theme;
|
enum client_theme theme;
|
||||||
|
|
||||||
|
struct input_request_list input_requests[INPUT_REQUEST_TYPES];
|
||||||
|
|
||||||
#define CLIENT_TERMINAL 0x1
|
#define CLIENT_TERMINAL 0x1
|
||||||
#define CLIENT_LOGIN 0x2
|
#define CLIENT_LOGIN 0x2
|
||||||
#define CLIENT_EXIT 0x4
|
#define CLIENT_EXIT 0x4
|
||||||
@@ -2922,6 +2946,8 @@ void input_parse_screen(struct input_ctx *, struct screen *,
|
|||||||
void input_reply_clipboard(struct bufferevent *, const char *, size_t,
|
void input_reply_clipboard(struct bufferevent *, const char *, size_t,
|
||||||
const char *);
|
const char *);
|
||||||
void input_set_buffer_size(size_t);
|
void input_set_buffer_size(size_t);
|
||||||
|
void input_request_reply(struct client *, enum input_request_type, void *);
|
||||||
|
void input_cancel_requests(struct client *);
|
||||||
|
|
||||||
/* input-key.c */
|
/* input-key.c */
|
||||||
void input_key_build(void);
|
void input_key_build(void);
|
||||||
|
|||||||
76
tty-keys.c
76
tty-keys.c
@@ -59,6 +59,7 @@ static int tty_keys_device_attributes2(struct tty *, const char *, size_t,
|
|||||||
size_t *);
|
size_t *);
|
||||||
static int tty_keys_extended_device_attributes(struct tty *, const char *,
|
static int tty_keys_extended_device_attributes(struct tty *, const char *,
|
||||||
size_t, size_t *);
|
size_t, size_t *);
|
||||||
|
static int tty_keys_palette(struct tty *, const char *, size_t, size_t *);
|
||||||
|
|
||||||
/* A key tree entry. */
|
/* A key tree entry. */
|
||||||
struct tty_key {
|
struct tty_key {
|
||||||
@@ -804,6 +805,17 @@ tty_keys_next(struct tty *tty)
|
|||||||
goto partial_key;
|
goto partial_key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Is this a palette response? */
|
||||||
|
switch (tty_keys_palette(tty, buf, len, &size)) {
|
||||||
|
case 0: /* yes */
|
||||||
|
key = KEYC_UNKNOWN;
|
||||||
|
goto complete_key;
|
||||||
|
case -1: /* no, or not valid */
|
||||||
|
break;
|
||||||
|
case 1: /* partial */
|
||||||
|
goto partial_key;
|
||||||
|
}
|
||||||
|
|
||||||
/* Is this a mouse key press? */
|
/* Is this a mouse key press? */
|
||||||
switch (tty_keys_mouse(tty, buf, len, &size, &m)) {
|
switch (tty_keys_mouse(tty, buf, len, &size, &m)) {
|
||||||
case 0: /* yes */
|
case 0: /* yes */
|
||||||
@@ -1699,3 +1711,67 @@ tty_keys_colours(struct tty *tty, const char *buf, size_t len, size_t *size,
|
|||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Handle OSC 4 palette colour responses. */
|
||||||
|
static int
|
||||||
|
tty_keys_palette(struct tty *tty, const char *buf, size_t len, size_t *size)
|
||||||
|
{
|
||||||
|
struct client *c = tty->client;
|
||||||
|
u_int i, start;
|
||||||
|
char tmp[128], *endptr;
|
||||||
|
int idx;
|
||||||
|
struct input_request_palette_data pd;
|
||||||
|
|
||||||
|
*size = 0;
|
||||||
|
|
||||||
|
/* First three bytes are always \033]4. */
|
||||||
|
if (buf[0] != '\033')
|
||||||
|
return (-1);
|
||||||
|
if (len == 1)
|
||||||
|
return (1);
|
||||||
|
if (buf[1] != ']')
|
||||||
|
return (-1);
|
||||||
|
if (len == 2)
|
||||||
|
return (1);
|
||||||
|
if (buf[2] != '4')
|
||||||
|
return (-1);
|
||||||
|
if (len == 3)
|
||||||
|
return (1);
|
||||||
|
if (buf[3] != ';')
|
||||||
|
return (-1);
|
||||||
|
if (len == 4)
|
||||||
|
return (1);
|
||||||
|
|
||||||
|
/* Parse index. */
|
||||||
|
idx = strtol(buf + 4, &endptr, 10);
|
||||||
|
if (endptr == buf + 4 || *endptr != ';')
|
||||||
|
return (-1);
|
||||||
|
if (idx < 0 || idx > 255)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
/* Copy the rest up to \033\ or \007. */
|
||||||
|
start = (endptr - buf) + 1;
|
||||||
|
for (i = start; i < len && i - start < sizeof tmp; i++) {
|
||||||
|
if (buf[i - 1] == '\033' && buf[i] == '\\')
|
||||||
|
break;
|
||||||
|
if (buf[i] == '\007')
|
||||||
|
break;
|
||||||
|
tmp[i - start] = buf[i];
|
||||||
|
}
|
||||||
|
if (i - start == sizeof tmp)
|
||||||
|
return (-1);
|
||||||
|
if (i > 0 && buf[i - 1] == '\033')
|
||||||
|
tmp[i - start - 1] = '\0';
|
||||||
|
else
|
||||||
|
tmp[i - start] = '\0';
|
||||||
|
*size = i + 1;
|
||||||
|
|
||||||
|
/* Work out the colour. */
|
||||||
|
pd.c = colour_parseX11(tmp);
|
||||||
|
if (pd.c == -1)
|
||||||
|
return (0);
|
||||||
|
pd.idx = idx;
|
||||||
|
input_request_reply(c, INPUT_REQUEST_PALETTE, &pd);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|||||||
6
tty.c
6
tty.c
@@ -414,10 +414,12 @@ tty_repeat_requests(struct tty *tty, int force)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (!force && n <= TTY_REQUEST_LIMIT) {
|
if (!force && n <= TTY_REQUEST_LIMIT) {
|
||||||
log_debug("%s: not repeating requests (%u seconds)", c->name, n);
|
log_debug("%s: not repeating requests (%u seconds)", c->name,
|
||||||
|
n);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
log_debug("%s: %srepeating requests (%u seconds)", c->name, force ? "(force) " : "" , n);
|
log_debug("%s: %srepeating requests (%u seconds)", c->name,
|
||||||
|
force ? "(force) " : "" , n);
|
||||||
tty->last_requests = t;
|
tty->last_requests = t;
|
||||||
|
|
||||||
if (tty->term->flags & TERM_VT100LIKE) {
|
if (tty->term->flags & TERM_VT100LIKE) {
|
||||||
|
|||||||
Reference in New Issue
Block a user