1
0
mirror of https://github.com/tmux/tmux.git synced 2025-03-26 15:58:47 +00:00

Merge branch 'obsd-master'

This commit is contained in:
Thomas Adam 2025-03-04 10:01:15 +00:00
commit 882fb4d295
17 changed files with 382 additions and 107 deletions

View File

@ -99,7 +99,7 @@ cmd_break_pane_exec(struct cmd *self, struct cmdq_item *item)
w = wp->window = window_create(w->sx, w->sy, w->xpixel, w->ypixel);
options_set_parent(wp->options, w->options);
wp->flags |= PANE_STYLECHANGED;
wp->flags |= (PANE_STYLECHANGED|PANE_THEMECHANGED);
TAILQ_INSERT_HEAD(&w->panes, wp, entry);
w->active = wp;
w->latest = tc;

View File

@ -149,7 +149,7 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item)
src_wp->window = dst_w;
options_set_parent(src_wp->options, dst_w->options);
src_wp->flags |= PANE_STYLECHANGED;
src_wp->flags |= (PANE_STYLECHANGED|PANE_THEMECHANGED);
if (flags & SPAWN_BEFORE)
TAILQ_INSERT_BEFORE(dst_wp, src_wp, entry);
else

View File

@ -149,12 +149,14 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
markedwp = marked_pane.wp;
if (lastwp != NULL) {
lastwp->flags |= (PANE_REDRAW|PANE_STYLECHANGED);
lastwp->flags |= (PANE_REDRAW|PANE_STYLECHANGED|
PANE_THEMECHANGED);
server_redraw_window_borders(lastwp->window);
server_status_window(lastwp->window);
}
if (markedwp != NULL) {
markedwp->flags |= (PANE_REDRAW|PANE_STYLECHANGED);
markedwp->flags |= (PANE_REDRAW|PANE_STYLECHANGED|
PANE_THEMECHANGED);
server_redraw_window_borders(markedwp->window);
server_status_window(markedwp->window);
}
@ -169,7 +171,7 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
return (CMD_RETURN_ERROR);
}
options_set_string(oo, "window-active-style", 0, "%s", style);
wp->flags |= (PANE_REDRAW|PANE_STYLECHANGED);
wp->flags |= (PANE_REDRAW|PANE_STYLECHANGED|PANE_THEMECHANGED);
}
if (args_has(args, 'g')) {
cmdq_print(item, "%s", options_get_string(oo, "window-style"));

View File

@ -217,7 +217,7 @@ cmd_send_keys_exec(struct cmd *self, struct cmdq_item *item)
if (args_has(args, 'R')) {
colour_palette_clear(&wp->palette);
input_reset(wp->ictx, 1);
wp->flags |= (PANE_STYLECHANGED|PANE_REDRAW);
wp->flags |= (PANE_STYLECHANGED|PANE_THEMECHANGED|PANE_REDRAW);
}
if (count == 0) {

View File

@ -101,10 +101,10 @@ cmd_swap_pane_exec(struct cmd *self, struct cmdq_item *item)
src_wp->window = dst_w;
options_set_parent(src_wp->options, dst_w->options);
src_wp->flags |= PANE_STYLECHANGED;
src_wp->flags |= (PANE_STYLECHANGED|PANE_THEMECHANGED);
dst_wp->window = src_w;
options_set_parent(dst_wp->options, src_w->options);
dst_wp->flags |= PANE_STYLECHANGED;
dst_wp->flags |= (PANE_STYLECHANGED|PANE_THEMECHANGED);
sx = src_wp->sx; sy = src_wp->sy;
xoff = src_wp->xoff; yoff = src_wp->yoff;

View File

@ -182,6 +182,46 @@ colour_tostring(int c)
return ("invalid");
}
/* Convert background colour to theme. */
enum client_theme
colour_totheme(int c)
{
int r, g, b, brightness;
if (c == -1)
return (THEME_UNKNOWN);
if (c & COLOUR_FLAG_RGB) {
r = (c >> 16) & 0xff;
g = (c >> 8) & 0xff;
b = (c >> 0) & 0xff;
brightness = r + g + b;
if (brightness > 382)
return (THEME_LIGHT);
return (THEME_DARK);
}
if (c & COLOUR_FLAG_256)
return (colour_totheme(colour_256toRGB(c)));
switch (c) {
case 0:
case 90:
return (THEME_DARK);
case 7:
case 97:
return (THEME_LIGHT);
default:
if (c >= 0 && c <= 7)
return (colour_totheme(colour_256toRGB(c)));
if (c >= 90 && c <= 97)
return (colour_totheme(colour_256toRGB(8 + c - 90)));
break;
}
return (THEME_UNKNOWN);
}
/* Convert colour from string. */
int
colour_fromstring(const char *s)

View File

@ -1544,6 +1544,23 @@ format_cb_client_written(struct format_tree *ft)
return (NULL);
}
/* Callback for client_theme. */
static void *
format_cb_client_theme(struct format_tree *ft)
{
if (ft->c != NULL) {
switch (ft->c->theme) {
case THEME_DARK:
return (xstrdup("dark"));
case THEME_LIGHT:
return (xstrdup("light"));
case THEME_UNKNOWN:
return (NULL);
}
}
return (NULL);
}
/* Callback for config_files. */
static void *
format_cb_config_files(__unused struct format_tree *ft)
@ -2881,6 +2898,9 @@ static const struct format_table_entry format_table[] = {
{ "client_termtype", FORMAT_TABLE_STRING,
format_cb_client_termtype
},
{ "client_theme", FORMAT_TABLE_STRING,
format_cb_client_theme
},
{ "client_tty", FORMAT_TABLE_STRING,
format_cb_client_tty
},

View File

@ -313,6 +313,12 @@ static struct input_key_entry input_key_defaults[] = {
{ .key = KEYC_DC|KEYC_BUILD_MODIFIERS,
.data = "\033[3;_~"
},
{ .key = KEYC_REPORT_DARK_THEME,
.data = "\033[?997;1n"
},
{ .key = KEYC_REPORT_LIGHT_THEME,
.data = "\033[?997;2n"
},
};
static const key_code input_key_modifiers[] = {
0,

139
input.c
View File

@ -133,7 +133,7 @@ static void printflike(2, 3) input_reply(struct input_ctx *, const char *, ...);
static void input_set_state(struct input_ctx *,
const struct input_transition *);
static void input_reset_cell(struct input_ctx *);
static void input_report_current_theme(struct input_ctx *);
static void input_osc_4(struct input_ctx *, const char *);
static void input_osc_8(struct input_ctx *, const char *);
static void input_osc_10(struct input_ctx *, const char *);
@ -243,6 +243,7 @@ enum input_csi_type {
INPUT_CSI_DECSTBM,
INPUT_CSI_DL,
INPUT_CSI_DSR,
INPUT_CSI_DSR_PRIVATE,
INPUT_CSI_ECH,
INPUT_CSI_ED,
INPUT_CSI_EL,
@ -251,6 +252,7 @@ enum input_csi_type {
INPUT_CSI_IL,
INPUT_CSI_MODOFF,
INPUT_CSI_MODSET,
INPUT_CSI_QUERY_PRIVATE,
INPUT_CSI_RCP,
INPUT_CSI_REP,
INPUT_CSI_RM,
@ -259,8 +261,8 @@ enum input_csi_type {
INPUT_CSI_SD,
INPUT_CSI_SGR,
INPUT_CSI_SM,
INPUT_CSI_SM_PRIVATE,
INPUT_CSI_SM_GRAPHICS,
INPUT_CSI_SM_PRIVATE,
INPUT_CSI_SU,
INPUT_CSI_TBC,
INPUT_CSI_VPA,
@ -304,6 +306,8 @@ static const struct input_table_entry input_csi_table[] = {
{ 'm', ">", INPUT_CSI_MODSET },
{ 'n', "", INPUT_CSI_DSR },
{ 'n', ">", INPUT_CSI_MODOFF },
{ 'n', "?", INPUT_CSI_DSR_PRIVATE },
{ 'p', "?$", INPUT_CSI_QUERY_PRIVATE },
{ 'q', " ", INPUT_CSI_DECSCUSR },
{ 'q', ">", INPUT_CSI_XDA },
{ 'r', "", INPUT_CSI_DECSTBM },
@ -1531,6 +1535,20 @@ input_csi_dispatch(struct input_ctx *ictx)
if (n != -1)
screen_write_deleteline(sctx, n, bg);
break;
case INPUT_CSI_DSR_PRIVATE:
switch (input_get(ictx, 0, 0, 0)) {
case 996:
input_report_current_theme(ictx);
break;
}
break;
case INPUT_CSI_QUERY_PRIVATE:
switch (input_get(ictx, 0, 0, 0)) {
case 2031:
input_reply(ictx, "\033[?2031;2$y");
break;
}
break;
case INPUT_CSI_DSR:
switch (input_get(ictx, 0, 0, 0)) {
case -1:
@ -1781,6 +1799,9 @@ input_csi_dispatch_rm_private(struct input_ctx *ictx)
case 2004:
screen_write_mode_clear(sctx, MODE_BRACKETPASTE);
break;
case 2031:
screen_write_mode_clear(sctx, MODE_THEME_UPDATES);
break;
default:
log_debug("%s: unknown '%c'", __func__, ictx->ch);
break;
@ -1876,6 +1897,9 @@ input_csi_dispatch_sm_private(struct input_ctx *ictx)
case 2004:
screen_write_mode_set(sctx, MODE_BRACKETPASTE);
break;
case 2031:
screen_write_mode_set(sctx, MODE_THEME_UPDATES);
break;
default:
log_debug("%s: unknown '%c'", __func__, ictx->ch);
break;
@ -2697,84 +2721,6 @@ bad:
free(id);
}
/*
* Get a client with a foreground for the pane. There isn't much to choose
* between them so just use the first.
*/
static int
input_get_fg_client(struct window_pane *wp)
{
struct window *w = wp->window;
struct client *loop;
TAILQ_FOREACH(loop, &clients, entry) {
if (loop->flags & CLIENT_UNATTACHEDFLAGS)
continue;
if (loop->session == NULL || !session_has(loop->session, w))
continue;
if (loop->tty.fg == -1)
continue;
return (loop->tty.fg);
}
return (-1);
}
/* Get a client with a background for the pane. */
static int
input_get_bg_client(struct window_pane *wp)
{
struct window *w = wp->window;
struct client *loop;
TAILQ_FOREACH(loop, &clients, entry) {
if (loop->flags & CLIENT_UNATTACHEDFLAGS)
continue;
if (loop->session == NULL || !session_has(loop->session, w))
continue;
if (loop->tty.bg == -1)
continue;
return (loop->tty.bg);
}
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
@ -2787,11 +2733,11 @@ input_osc_10(struct input_ctx *ictx, const char *p)
if (strcmp(p, "?") == 0) {
if (wp == NULL)
return;
c = input_get_fg_control_client(wp);
c = window_pane_get_fg_control_client(wp);
if (c == -1) {
tty_default_colours(&defaults, wp);
if (COLOUR_DEFAULT(defaults.fg))
c = input_get_fg_client(wp);
c = window_pane_get_fg(wp);
else
c = defaults.fg;
}
@ -2832,20 +2778,12 @@ static void
input_osc_11(struct input_ctx *ictx, const char *p)
{
struct window_pane *wp = ictx->wp;
struct grid_cell defaults;
int c;
if (strcmp(p, "?") == 0) {
if (wp == NULL)
return;
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;
}
c = window_pane_get_bg(wp);
input_osc_colour_reply(ictx, 11, c);
return;
}
@ -2857,7 +2795,7 @@ input_osc_11(struct input_ctx *ictx, const char *p)
if (ictx->palette != NULL) {
ictx->palette->bg = c;
if (wp != NULL)
wp->flags |= PANE_STYLECHANGED;
wp->flags |= (PANE_STYLECHANGED|PANE_THEMECHANGED);
screen_write_fullredraw(&ictx->ctx);
}
}
@ -2873,7 +2811,7 @@ input_osc_111(struct input_ctx *ictx, const char *p)
if (ictx->palette != NULL) {
ictx->palette->bg = 8;
if (wp != NULL)
wp->flags |= PANE_STYLECHANGED;
wp->flags |= (PANE_STYLECHANGED|PANE_THEMECHANGED);
screen_write_fullredraw(&ictx->ctx);
}
}
@ -3064,3 +3002,18 @@ input_set_buffer_size(size_t buffer_size)
log_debug("%s: %lu -> %lu", __func__, input_buffer_size, buffer_size);
input_buffer_size = buffer_size;
}
static void
input_report_current_theme(struct input_ctx *ictx)
{
switch (window_pane_get_theme(ictx->wp)) {
case THEME_DARK:
input_reply(ictx, "\033[?997;1n");
break;
case THEME_LIGHT:
input_reply(ictx, "\033[?997;2n");
break;
case THEME_UNKNOWN:
break;
}
}

View File

@ -1454,6 +1454,8 @@ const struct options_table_entry options_table[] = {
OPTIONS_TABLE_HOOK("client-focus-out", ""),
OPTIONS_TABLE_HOOK("client-resized", ""),
OPTIONS_TABLE_HOOK("client-session-changed", ""),
OPTIONS_TABLE_HOOK("client-light-theme", ""),
OPTIONS_TABLE_HOOK("client-dark-theme", ""),
OPTIONS_TABLE_HOOK("command-error", ""),
OPTIONS_TABLE_PANE_HOOK("pane-died", ""),
OPTIONS_TABLE_PANE_HOOK("pane-exited", ""),

View File

@ -1165,7 +1165,7 @@ options_push_changes(const char *name)
if (strcmp(name, "window-style") == 0 ||
strcmp(name, "window-active-style") == 0) {
RB_FOREACH(wp, window_pane_tree, &all_window_panes)
wp->flags |= PANE_STYLECHANGED;
wp->flags |= (PANE_STYLECHANGED|PANE_THEMECHANGED);
}
if (strcmp(name, "pane-colours") == 0) {
RB_FOREACH(wp, window_pane_tree, &all_window_panes)

View File

@ -56,11 +56,11 @@ static void server_client_set_title(struct client *);
static void server_client_set_path(struct client *);
static void server_client_reset_state(struct client *);
static void server_client_update_latest(struct client *);
static void server_client_dispatch(struct imsg *, void *);
static void server_client_dispatch_command(struct client *, struct imsg *);
static void server_client_dispatch_identify(struct client *, struct imsg *);
static void server_client_dispatch_shell(struct client *);
static void server_client_report_theme(struct client *, enum client_theme);
/* Compare client windows. */
static int
@ -300,6 +300,7 @@ server_client_create(int fd)
c->tty.sx = 80;
c->tty.sy = 24;
c->theme = THEME_UNKNOWN;
status_init(c);
c->flags |= CLIENT_FOCUSED;
@ -401,6 +402,7 @@ server_client_set_session(struct client *c, struct session *s)
recalculate_sizes();
window_update_focus(s->curw->window);
session_update_activity(s, NULL);
session_theme_changed(s);
gettimeofday(&s->last_attached_time, NULL);
s->curw->flags &= ~WINLINK_ALERTFLAGS;
s->curw->window->latest = c;
@ -2384,6 +2386,16 @@ server_client_key_callback(struct cmdq_item *item, void *data)
event->key = key;
}
/* Handle theme reporting keys. */
if (key == KEYC_REPORT_LIGHT_THEME) {
server_client_report_theme(c, THEME_LIGHT);
goto out;
}
if (key == KEYC_REPORT_DARK_THEME) {
server_client_report_theme(c, THEME_DARK);
goto out;
}
/* Find affected pane. */
if (!KEYC_IS_MOUSE(key) || cmd_find_from_mouse(&fs, m, 0) != 0)
cmd_find_from_client(&fs, c, 0);
@ -2674,6 +2686,12 @@ server_client_loop(void)
}
check_window_name(w);
}
/* Send theme updates. */
RB_FOREACH(w, windows, &windows) {
TAILQ_FOREACH(wp, &w->panes, entry)
window_pane_send_theme_update(wp);
}
}
/* Check if window needs to be resized. */
@ -3910,3 +3928,21 @@ out:
if (!parse)
free(msg);
}
static void
server_client_report_theme(struct client *c, enum client_theme theme)
{
if (theme == THEME_LIGHT) {
c->theme = THEME_LIGHT;
notify_client("client-light-theme", c);
} else {
c->theme = THEME_DARK;
notify_client("client-dark-theme", c);
}
/*
* Request foreground and background colour again. Don't forward 2031 to
* panes until a response is received.
*/
tty_puts(&c->tty, "\033]10;?\033\\\033]11;?\033\\");
}

View File

@ -751,3 +751,16 @@ session_renumber_windows(struct session *s)
RB_FOREACH_SAFE(wl, winlinks, &old_wins, wl1)
winlink_remove(&old_wins, wl);
}
/* Set the PANE_THEMECHANGED flag for every pane in this session. */
void
session_theme_changed(struct session *s)
{
struct window_pane *wp;
struct winlink *wl;
RB_FOREACH(wl, winlinks, &s->windows) {
TAILQ_FOREACH(wp, &wl->window->panes, entry)
wp->flags |= PANE_THEMECHANGED;
}
}

34
tmux.h
View File

@ -378,6 +378,10 @@ enum {
KEYC_KP_ZERO,
KEYC_KP_PERIOD,
/* Theme reporting. */
KEYC_REPORT_DARK_THEME,
KEYC_REPORT_LIGHT_THEME,
/* End of special keys. */
KEYC_BASE_END
};
@ -645,6 +649,7 @@ enum tty_code_code {
#define MODE_CURSOR_VERY_VISIBLE 0x10000
#define MODE_CURSOR_BLINKING_SET 0x20000
#define MODE_KEYS_EXTENDED_2 0x40000
#define MODE_THEME_UPDATES 0x80000
#define ALL_MODES 0xffffff
#define ALL_MOUSE_MODES (MODE_MOUSE_STANDARD|MODE_MOUSE_BUTTON|MODE_MOUSE_ALL)
@ -1156,8 +1161,9 @@ struct window_pane {
#define PANE_STATUSDRAWN 0x400
#define PANE_EMPTY 0x800
#define PANE_STYLECHANGED 0x1000
#define PANE_UNSEENCHANGES 0x2000
#define PANE_REDRAWSCROLLBAR 0x4000
#define PANE_THEMECHANGED 0x2000
#define PANE_UNSEENCHANGES 0x4000
#define PANE_REDRAWSCROLLBAR 0x8000
u_int sb_slider_y;
u_int sb_slider_h;
@ -1865,6 +1871,16 @@ struct overlay_ranges {
u_int nx[OVERLAY_MAX_RANGES];
};
/*
* Client theme, this is worked out from the background colour if not reported
* by terminal.
*/
enum client_theme {
THEME_UNKNOWN,
THEME_LIGHT,
THEME_DARK
};
/* Client connection. */
typedef int (*prompt_input_cb)(struct client *, void *, const char *, int);
typedef void (*prompt_free_cb)(void *);
@ -1924,6 +1940,7 @@ struct client {
struct mouse_event click_event;
struct status_line status;
enum client_theme theme;
#define CLIENT_TERMINAL 0x1
#define CLIENT_LOGIN 0x2
@ -2931,6 +2948,8 @@ void input_parse_screen(struct input_ctx *, struct screen *,
void input_reply_clipboard(struct bufferevent *, const char *, size_t,
const char *);
void input_set_buffer_size(size_t);
int input_get_bg_client(struct window_pane *);
int input_get_bg_control_client(struct window_pane *);
/* input-key.c */
void input_key_build(void);
@ -2945,7 +2964,8 @@ int colour_join_rgb(u_char, u_char, u_char);
void colour_split_rgb(int, u_char *, u_char *, u_char *);
int colour_force_rgb(int);
const char *colour_tostring(int);
int colour_fromstring(const char *s);
enum client_theme colour_totheme(int);
int colour_fromstring(const char *);
int colour_256toRGB(int);
int colour_256to16(int);
int colour_byname(const char *);
@ -3246,6 +3266,13 @@ void window_set_fill_character(struct window *);
void window_pane_default_cursor(struct window_pane *);
int window_pane_mode(struct window_pane *);
int window_pane_show_scrollbar(struct window_pane *, int);
int window_pane_get_bg(struct window_pane *);
int window_pane_get_fg(struct window_pane *);
int window_pane_get_fg_control_client(struct window_pane *);
int window_pane_get_bg_control_client(struct window_pane *);
int window_get_bg_client(struct window_pane *);
enum client_theme window_pane_get_theme(struct window_pane *);
void window_pane_send_theme_update(struct window_pane *);
/* layout.c */
u_int layout_count_cells(struct layout_cell *);
@ -3443,6 +3470,7 @@ void session_group_synchronize_from(struct session *);
u_int session_group_count(struct session_group *);
u_int session_group_attached_count(struct session_group *);
void session_renumber_windows(struct session *);
void session_theme_changed(struct session *);
/* utf8.c */
enum utf8_state utf8_towc (const struct utf8_data *, wchar_t *);

View File

@ -213,6 +213,10 @@ static const struct tty_default_key_raw tty_default_raw_keys[] = {
/* Extended keys. */
{ "\033[1;5Z", '\011'|KEYC_CTRL|KEYC_SHIFT },
/* Theme reporting. */
{ "\033[?997;1n", KEYC_REPORT_DARK_THEME },
{ "\033[?997;2n", KEYC_REPORT_LIGHT_THEME },
};
/* Default xterm keys. */
@ -791,10 +795,12 @@ tty_keys_next(struct tty *tty)
switch (tty_keys_colours(tty, buf, len, &size, &tty->fg, &tty->bg)) {
case 0: /* yes */
key = KEYC_UNKNOWN;
session_theme_changed(tty->client->session);
goto complete_key;
case -1: /* no, or not valid */
break;
case 1: /* partial */
session_theme_changed(tty->client->session);
goto partial_key;
}

8
tty.c
View File

@ -356,6 +356,11 @@ tty_start_tty(struct tty *tty)
if (tty_term_has(tty->term, TTYC_ENBP))
tty_putcode(tty, TTYC_ENBP);
if (tty->term->flags & TERM_VT100LIKE) {
/* Subscribe to theme changes and request theme now. */
tty_puts(tty, "\033[?2031h\033[?996n");
}
evtimer_set(&tty->start_timer, tty_start_timer_callback, tty);
evtimer_add(&tty->start_timer, &tv);
@ -468,6 +473,9 @@ tty_stop_tty(struct tty *tty)
tty_raw(tty, tty_term_string(tty->term, TTYC_DSMG));
tty_raw(tty, tty_term_string(tty->term, TTYC_RMCUP));
if (tty->term->flags & TERM_VT100LIKE)
tty_raw(tty, "\033[?2031l");
setblocking(c->fd, 1);
}

163
window.c
View File

@ -950,7 +950,7 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit)
wp = xcalloc(1, sizeof *wp);
wp->window = w;
wp->options = options_create(w->options);
wp->flags = PANE_STYLECHANGED;
wp->flags = (PANE_STYLECHANGED|PANE_THEMECHANGED);
wp->id = next_window_pane_id++;
RB_INSERT(window_pane_tree, &all_window_panes, wp);
@ -1769,6 +1769,8 @@ window_set_fill_character(struct window *w)
ud = utf8_fromcstr(value);
if (ud != NULL && ud[0].width == 1)
w->fill_character = ud;
else
free(ud);
}
}
@ -1802,3 +1804,162 @@ window_pane_show_scrollbar(struct window_pane *wp, int sb_option)
return (1);
return (0);
}
int
window_pane_get_bg(struct window_pane *wp)
{
int c;
struct grid_cell defaults;
c = window_pane_get_bg_control_client(wp);
if (c == -1) {
tty_default_colours(&defaults, wp);
if (COLOUR_DEFAULT(defaults.bg))
c = window_get_bg_client(wp);
else
c = defaults.bg;
}
return (c);
}
/* Get a client with a background for the pane. */
int
window_get_bg_client(struct window_pane *wp)
{
struct window *w = wp->window;
struct client *loop;
TAILQ_FOREACH(loop, &clients, entry) {
if (loop->flags & CLIENT_UNATTACHEDFLAGS)
continue;
if (loop->session == NULL || !session_has(loop->session, w))
continue;
if (loop->tty.bg == -1)
continue;
return (loop->tty.bg);
}
return (-1);
}
/*
* If any control mode client exists that has provided a bg color, return it.
* Otherwise, return -1.
*/
int
window_pane_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);
}
/*
* Get a client with a foreground for the pane. There isn't much to choose
* between them so just use the first.
*/
int
window_pane_get_fg(struct window_pane *wp)
{
struct window *w = wp->window;
struct client *loop;
TAILQ_FOREACH(loop, &clients, entry) {
if (loop->flags & CLIENT_UNATTACHEDFLAGS)
continue;
if (loop->session == NULL || !session_has(loop->session, w))
continue;
if (loop->tty.fg == -1)
continue;
return (loop->tty.fg);
}
return (-1);
}
/*
* If any control mode client exists that has provided a fg color, return it.
* Otherwise, return -1.
*/
int
window_pane_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);
}
enum client_theme
window_pane_get_theme(struct window_pane *wp)
{
struct window *w = wp->window;
struct client *loop;
enum client_theme theme;
int found_light = 0, found_dark = 0;
/*
* Derive theme from pane background color, if it's not the default
* colour.
*/
theme = colour_totheme(window_pane_get_bg(wp));
if (theme != THEME_UNKNOWN)
return (theme);
/* Try to find a client that has a theme. */
TAILQ_FOREACH(loop, &clients, entry) {
if (loop->flags & CLIENT_UNATTACHEDFLAGS)
continue;
if (loop->session == NULL || !session_has(loop->session, w))
continue;
switch (loop->theme) {
case THEME_LIGHT:
found_light = 1;
break;
case THEME_DARK:
found_dark = 1;
break;
case THEME_UNKNOWN:
break;
}
}
if (found_dark && !found_light)
return (THEME_DARK);
if (found_light && !found_dark)
return (THEME_LIGHT);
return (THEME_UNKNOWN);
}
void
window_pane_send_theme_update(struct window_pane *wp)
{
if (~wp->flags & PANE_THEMECHANGED)
return;
if (~wp->screen->mode & MODE_THEME_UPDATES)
return;
switch (window_pane_get_theme(wp)) {
case THEME_LIGHT:
input_key_pane(wp, KEYC_REPORT_LIGHT_THEME, NULL);
break;
case THEME_DARK:
input_key_pane(wp, KEYC_REPORT_DARK_THEME, NULL);
break;
case THEME_UNKNOWN:
break;
}
wp->flags &= ~PANE_THEMECHANGED;
}