Add a way (refresh-client -r) for control mode clients to provide OSC 10

and 11 responses to tmux so they can set the default foreground and
background colours, from George Nachman in GitHub issue 4014.
This commit is contained in:
nicm 2024-06-24 08:30:50 +00:00
parent db1665868f
commit 093b5a5518
6 changed files with 116 additions and 20 deletions

View File

@ -34,9 +34,10 @@ const struct cmd_entry cmd_refresh_client_entry = {
.name = "refresh-client",
.alias = "refresh",
.args = { "A:B:cC:Df:F:l::LRSt:U", 0, 1, NULL },
.args = { "A:B:cC:Df:r:F:l::LRSt:U", 0, 1, NULL },
.usage = "[-cDlLRSU] [-A pane:state] [-B name:what:format] "
"[-C XxY] [-f flags] " CMD_TARGET_CLIENT_USAGE " [adjustment]",
"[-C XxY] [-f flags] [-r pane:report]" CMD_TARGET_CLIENT_USAGE
" [adjustment]",
.flags = CMD_AFTERHOOK|CMD_CLIENT_TFLAG,
.exec = cmd_refresh_client_exec
@ -193,6 +194,34 @@ cmd_refresh_client_clipboard(struct cmd *self, struct cmdq_item *item)
return (CMD_RETURN_NORMAL);
}
static void
cmd_refresh_report(struct tty *tty, const char *value)
{
struct window_pane *wp;
u_int pane;
size_t size = 0;
char *copy, *split;
if (*value != '%')
return;
copy = xstrdup(value);
if ((split = strchr(copy, ':')) == NULL)
goto out;
*split++ = '\0';
if (sscanf(copy, "%%%u", &pane) != 1)
goto out;
wp = window_pane_find_by_id(pane);
if (wp == NULL)
goto out;
tty_keys_colours(tty, split, strlen(split), &size, &wp->control_fg,
&wp->control_bg);
out:
free(copy);
}
static enum cmd_retval
cmd_refresh_client_exec(struct cmd *self, struct cmdq_item *item)
{
@ -262,6 +291,8 @@ cmd_refresh_client_exec(struct cmd *self, struct cmdq_item *item)
server_client_set_flags(tc, args_get(args, 'F'));
if (args_has(args, 'f'))
server_client_set_flags(tc, args_get(args, 'f'));
if (args_has(args, 'r'))
cmd_refresh_report(tty, args_get(args, 'r'));
if (args_has(args, 'A')) {
if (~tc->flags & CLIENT_CONTROL)

64
input.c
View File

@ -2652,6 +2652,44 @@ input_get_bg_client(struct window_pane *wp)
return (-1);
}
/*
* If any control mode client exists that has provided a bg color, return it.
* Otherwise, return -1.
*/
static int
input_get_bg_control_client(struct window_pane *wp)
{
struct client *c;
if (wp->control_bg == -1)
return (-1);
TAILQ_FOREACH(c, &clients, entry) {
if (c->flags & CLIENT_CONTROL)
return (wp->control_bg);
}
return (-1);
}
/*
* If any control mode client exists that has provided a fg color, return it.
* Otherwise, return -1.
*/
static int
input_get_fg_control_client(struct window_pane *wp)
{
struct client *c;
if (wp->control_fg == -1)
return (-1);
TAILQ_FOREACH(c, &clients, entry) {
if (c->flags & CLIENT_CONTROL)
return (wp->control_fg);
}
return (-1);
}
/* Handle the OSC 10 sequence for setting and querying foreground colour. */
static void
input_osc_10(struct input_ctx *ictx, const char *p)
@ -2663,11 +2701,14 @@ input_osc_10(struct input_ctx *ictx, const char *p)
if (strcmp(p, "?") == 0) {
if (wp == NULL)
return;
tty_default_colours(&defaults, wp);
if (COLOUR_DEFAULT(defaults.fg))
c = input_get_fg_client(wp);
else
c = defaults.fg;
c = input_get_fg_control_client(wp);
if (c == -1) {
tty_default_colours(&defaults, wp);
if (COLOUR_DEFAULT(defaults.fg))
c = input_get_fg_client(wp);
else
c = defaults.fg;
}
input_osc_colour_reply(ictx, 10, c);
return;
}
@ -2711,11 +2752,14 @@ input_osc_11(struct input_ctx *ictx, const char *p)
if (strcmp(p, "?") == 0) {
if (wp == NULL)
return;
tty_default_colours(&defaults, wp);
if (COLOUR_DEFAULT(defaults.bg))
c = input_get_bg_client(wp);
else
c = defaults.bg;
c = input_get_bg_control_client(wp);
if (c == -1) {
tty_default_colours(&defaults, wp);
if (COLOUR_DEFAULT(defaults.bg))
c = input_get_bg_client(wp);
else
c = defaults.bg;
}
input_osc_colour_reply(ictx, 11, c);
return;
}

7
tmux.1
View File

@ -1357,6 +1357,7 @@ specified multiple times.
.Op Fl B Ar name:what:format
.Op Fl C Ar size
.Op Fl f Ar flags
.Op Fl r Ar pane:report
.Op Fl l Op Ar target-pane
.Op Fl t Ar target-client
.Op Ar adjustment
@ -1467,6 +1468,12 @@ for all windows in the attached session.
.Fl f
sets a comma-separated list of client flags, see
.Ic attach-session .
.Fl r
allows a control mode client to provide information about a pane via a report
(such as the response to OSC 10).
The argument is a pane ID (with a leading
.Ql % ) ,
a colon, then a report escape sequence.
.Pp
.Fl l
requests the clipboard from the client using the

5
tmux.h
View File

@ -1100,6 +1100,9 @@ struct window_pane {
int border_gc_set;
struct grid_cell border_gc;
int control_bg;
int control_fg;
TAILQ_ENTRY(window_pane) entry; /* link in list of all panes */
TAILQ_ENTRY(window_pane) sentry; /* link in list of last visited */
RB_ENTRY(window_pane) tree_entry;
@ -2407,6 +2410,8 @@ const struct utf8_data *tty_acs_rounded_borders(int);
void tty_keys_build(struct tty *);
void tty_keys_free(struct tty *);
int tty_keys_next(struct tty *);
int tty_keys_colours(struct tty *, const char *, size_t, size_t *,
int *, int *);
/* arguments.c */
void args_set(struct args *, u_char, struct args_value *, int);

View File

@ -59,7 +59,6 @@ static int tty_keys_device_attributes2(struct tty *, const char *, size_t,
size_t *);
static int tty_keys_extended_device_attributes(struct tty *, const char *,
size_t, size_t *);
static int tty_keys_colours(struct tty *, const char *, size_t, size_t *);
/* A key tree entry. */
struct tty_key {
@ -721,7 +720,7 @@ tty_keys_next(struct tty *tty)
}
/* Is this a colours response? */
switch (tty_keys_colours(tty, buf, len, &size)) {
switch (tty_keys_colours(tty, buf, len, &size, &tty->fg, &tty->bg)) {
case 0: /* yes */
key = KEYC_UNKNOWN;
goto complete_key;
@ -1490,8 +1489,9 @@ tty_keys_extended_device_attributes(struct tty *tty, const char *buf,
* Handle foreground or background input. Returns 0 for success, -1 for
* failure, 1 for partial.
*/
static int
tty_keys_colours(struct tty *tty, const char *buf, size_t len, size_t *size)
int
tty_keys_colours(struct tty *tty, const char *buf, size_t len, size_t *size,
int *fg, int *bg)
{
struct client *c = tty->client;
u_int i;
@ -1542,11 +1542,17 @@ tty_keys_colours(struct tty *tty, const char *buf, size_t len, size_t *size)
n = colour_parseX11(tmp);
if (n != -1 && buf[3] == '0') {
log_debug("%s: foreground is %s", c->name, colour_tostring(n));
tty->fg = n;
if (c != NULL)
log_debug("%s fg is %s", c->name, colour_tostring(n));
else
log_debug("fg is %s", colour_tostring(n));
*fg = n;
} else if (n != -1) {
log_debug("%s: background is %s", c->name, colour_tostring(n));
tty->bg = n;
if (c != NULL)
log_debug("%s bg is %s", c->name, colour_tostring(n));
else
log_debug("bg is %s", colour_tostring(n));
*bg = n;
}
return (0);

View File

@ -937,6 +937,9 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit)
wp->pipe_fd = -1;
wp->control_bg = -1;
wp->control_fg = -1;
colour_palette_init(&wp->palette);
colour_palette_from_option(&wp->palette, wp->options);