From f2268041490fefabc1f8930c2c8492d4fc37444f Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 6 Jan 2026 20:05:57 +0000 Subject: [PATCH] Do not send theme unless it has changed, and do not send immediately when updates are enabled. GitHub issue 5787. --- input-keys.c | 6 ------ input.c | 15 ++++++++++++--- tmux.h | 21 +++++++++++---------- window.c | 18 +++++++++++++----- 4 files changed, 36 insertions(+), 24 deletions(-) diff --git a/input-keys.c b/input-keys.c index 7d7263fb..6a872731 100644 --- a/input-keys.c +++ b/input-keys.c @@ -314,12 +314,6 @@ 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, diff --git a/input.c b/input.c index 4f5bd38f..43d5e9a7 100644 --- a/input.c +++ b/input.c @@ -1898,6 +1898,8 @@ input_csi_dispatch_rm_private(struct input_ctx *ictx) break; case 2031: screen_write_mode_clear(sctx, MODE_THEME_UPDATES); + if (ictx->wp != NULL) + ictx->wp->flags &= ~PANE_THEMECHANGED; break; case 2026: /* synchronized output */ screen_write_stop_sync(ictx->wp); @@ -2001,6 +2003,10 @@ input_csi_dispatch_sm_private(struct input_ctx *ictx) break; case 2031: screen_write_mode_set(sctx, MODE_THEME_UPDATES); + if (ictx->wp != NULL) { + ictx->wp->last_theme = window_pane_get_theme(ictx->wp); + ictx->wp->flags &= ~PANE_THEMECHANGED; + } break; case 2026: /* synchronized output */ screen_write_start_sync(ictx->wp); @@ -3397,9 +3403,11 @@ input_report_current_theme(struct input_ctx *ictx) { struct window_pane *wp = ictx->wp; - if (wp == NULL) - return; - switch (window_pane_get_theme(wp)) { + if (wp != NULL) { + wp->last_theme = window_pane_get_theme(wp); + wp->flags &= ~PANE_THEMECHANGED; + + switch (wp->last_theme) { case THEME_DARK: log_debug("%s: %%%u dark theme", __func__, wp->id); input_reply(ictx, 0, "\033[?997;1n"); @@ -3411,5 +3419,6 @@ input_report_current_theme(struct input_ctx *ictx) case THEME_UNKNOWN: log_debug("%s: %%%u unknown theme", __func__, wp->id); break; + } } } diff --git a/tmux.h b/tmux.h index c738fb67..de7421f5 100644 --- a/tmux.h +++ b/tmux.h @@ -1135,6 +1135,16 @@ struct window_pane_resize { }; TAILQ_HEAD(window_pane_resizes, window_pane_resize); +/* + * Client theme, this is worked out from the background colour if not reported + * by terminal. + */ +enum client_theme { + THEME_UNKNOWN, + THEME_LIGHT, + THEME_DARK +}; + /* Child window structure. */ struct window_pane { u_int id; @@ -1198,6 +1208,7 @@ struct window_pane { struct grid_cell cached_gc; struct grid_cell cached_active_gc; struct colour_palette palette; + enum client_theme last_theme; int pipe_fd; struct bufferevent *pipe_event; @@ -1876,16 +1887,6 @@ 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 *); diff --git a/window.c b/window.c index f3b8b8a8..9581c64f 100644 --- a/window.c +++ b/window.c @@ -926,7 +926,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|PANE_THEMECHANGED); + wp->flags = PANE_STYLECHANGED; wp->id = next_window_pane_id++; RB_INSERT(window_pane_tree, &all_window_panes, wp); @@ -1926,24 +1926,32 @@ window_pane_get_theme(struct window_pane *wp) void window_pane_send_theme_update(struct window_pane *wp) { + enum client_theme theme; + if (wp == NULL || window_pane_exited(wp)) return; if (~wp->flags & PANE_THEMECHANGED) return; if (~wp->screen->mode & MODE_THEME_UPDATES) return; - switch (window_pane_get_theme(wp)) { + + theme = window_pane_get_theme(wp); + if (theme == wp->last_theme) + return; + wp->last_theme = theme; + wp->flags &= ~PANE_THEMECHANGED; + + switch (theme) { case THEME_LIGHT: log_debug("%s: %%%u light theme", __func__, wp->id); - input_key_pane(wp, KEYC_REPORT_LIGHT_THEME, NULL); + bufferevent_write(wp->event, "\033[?997;2n", 9); break; case THEME_DARK: log_debug("%s: %%%u dark theme", __func__, wp->id); - input_key_pane(wp, KEYC_REPORT_DARK_THEME, NULL); + bufferevent_write(wp->event, "\033[?997;1n", 9); break; case THEME_UNKNOWN: log_debug("%s: %%%u unknown theme", __func__, wp->id); break; } - wp->flags &= ~PANE_THEMECHANGED; }