From 75ed7b27c6ad347c7300edc6d25e61938aeec182 Mon Sep 17 00:00:00 2001 From: Michael Grant Date: Tue, 24 Mar 2026 17:49:55 +0000 Subject: [PATCH] Add -S and -s options to style floating panes. --- cmd-new-pane.c | 29 +++++++++++++++++++++++++---- options-table.c | 26 ++++++++++++++++++++++++-- screen-redraw.c | 41 ++++++++++++++++++++++++++++++----------- tmux.1 | 44 ++++++++++++++++++++++++++++++++++++++++++++ tty.c | 27 ++++++++++++++++++++++++--- 5 files changed, 147 insertions(+), 20 deletions(-) diff --git a/cmd-new-pane.c b/cmd-new-pane.c index 02c2cdc4..1a7911e8 100644 --- a/cmd-new-pane.c +++ b/cmd-new-pane.c @@ -35,10 +35,10 @@ const struct cmd_entry cmd_new_pane_entry = { .name = "new-pane", .alias = "newp", - .args = { "bc:de:fF:h:Iklm:p:Pt:w:x:y:Z", 0, -1, NULL }, + .args = { "bc:de:fF:h:Iklm:p:Ps:S:t:w:x:y:Z", 0, -1, NULL }, .usage = "[-bdefhIklPvZ] [-c start-directory] [-e environment] " - "[-F format] [-l size] [-m message] " CMD_TARGET_PANE_USAGE - " [shell-command [argument ...]]", + "[-F format] [-l size] [-m message] [-s style] [-S border-style] " + CMD_TARGET_PANE_USAGE " [shell-command [argument ...]]", .target = { 't', CMD_FIND_PANE, 0 }, @@ -62,7 +62,7 @@ cmd_new_pane_exec(struct cmd *self, struct cmdq_item *item) struct layout_cell *lc; struct cmd_find_state fs; int flags, input; - const char *template; + const char *template, *style; char *cause = NULL, *cp; struct args_value *av; u_int count = args_count(args); @@ -204,6 +204,27 @@ cmd_new_pane_exec(struct cmd *self, struct cmdq_item *item) environ_free(sc.environ); return (CMD_RETURN_ERROR); } + style = args_get(args, 's'); + if (style != NULL) { + if (options_set_string(new_wp->options, "window-style", 0, + "%s", style) == NULL) { + cmdq_error(item, "bad style: %s", style); + return (CMD_RETURN_ERROR); + } + options_set_string(new_wp->options, "window-active-style", 0, + "%s", style); + new_wp->flags |= (PANE_REDRAW|PANE_STYLECHANGED|PANE_THEMECHANGED); + } + style = args_get(args, 'S'); + if (style != NULL) { + if (options_set_string(new_wp->options, "pane-border-style", 0, + "%s", style) == NULL) { + cmdq_error(item, "bad border style: %s", style); + return (CMD_RETURN_ERROR); + } + options_set_string(new_wp->options, "pane-active-border-style", + 0, "%s", style); + } if (args_has(args, 'k') || args_has(args, 'm')) { options_set_number(new_wp->options, "remain-on-exit", 3); if (args_has(args, 'm')) diff --git a/options-table.c b/options-table.c index 6c9615f5..4125275c 100644 --- a/options-table.c +++ b/options-table.c @@ -1207,6 +1207,28 @@ const struct options_table_entry options_table[] = { .text = "Character used to fill unused parts of window." }, + { .name = "floating-pane-border-style", + .type = OPTIONS_TABLE_STRING, + .scope = OPTIONS_TABLE_WINDOW, + .default_str = "default", + .flags = OPTIONS_TABLE_IS_STYLE, + .separator = ",", + .text = "Default border style for floating panes. " + "Overrides pane-border-style for floating panes unless " + "a per-pane style is set." + }, + + { .name = "floating-pane-style", + .type = OPTIONS_TABLE_STRING, + .scope = OPTIONS_TABLE_WINDOW, + .default_str = "default", + .flags = OPTIONS_TABLE_IS_STYLE, + .separator = ",", + .text = "Default content style for floating panes. " + "Overrides window-style for floating panes unless " + "a per-pane style is set." + }, + { .name = "main-pane-height", .type = OPTIONS_TABLE_STRING, .scope = OPTIONS_TABLE_WINDOW, @@ -1283,7 +1305,7 @@ const struct options_table_entry options_table[] = { { .name = "pane-active-border-style", .type = OPTIONS_TABLE_STRING, - .scope = OPTIONS_TABLE_WINDOW, + .scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE, .default_str = "#{?pane_in_mode,fg=yellow,#{?synchronize-panes,fg=red,fg=green}}", .flags = OPTIONS_TABLE_IS_STYLE, .separator = ",", @@ -1335,7 +1357,7 @@ const struct options_table_entry options_table[] = { { .name = "pane-border-style", .type = OPTIONS_TABLE_STRING, - .scope = OPTIONS_TABLE_WINDOW, + .scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE, .default_str = "default", .flags = OPTIONS_TABLE_IS_STYLE, .separator = ",", diff --git a/screen-redraw.c b/screen-redraw.c index 259fc173..539fa159 100644 --- a/screen-redraw.c +++ b/screen-redraw.c @@ -600,7 +600,7 @@ screen_redraw_make_pane_status(struct client *c, struct window_pane *wp, { struct window *w = wp->window; struct grid_cell gc; - const char *fmt; + const char *fmt, *border_opt; struct format_tree *ft; char *expanded; int pane_status = rctx->pane_status, sb_w = 0; @@ -616,10 +616,19 @@ screen_redraw_make_pane_status(struct client *c, struct window_pane *wp, ft = format_create(c, NULL, FORMAT_PANE|wp->id, FORMAT_STATUS); format_defaults(ft, c, c->session, c->session->curw, wp); - if (wp == server_client_get_pane(c)) - style_apply(&gc, w->options, "pane-active-border-style", ft); - else - style_apply(&gc, w->options, "pane-border-style", ft); + border_opt = (wp == server_client_get_pane(c)) ? + "pane-active-border-style" : "pane-border-style"; + + /* Window-level baseline. */ + style_apply(&gc, w->options, border_opt, ft); + + /* Floating pane window default overrides window baseline. */ + if (wp->flags & PANE_FLOATING) + style_add(&gc, w->options, "floating-pane-border-style", ft); + + /* Per-pane override (set via new-pane -S or set-option -p). */ + if (options_get_only(wp->options, border_opt) != NULL) + style_add(&gc, wp->options, border_opt, ft); fmt = options_get_string(wp->options, "pane-border-format"); expanded = format_expand_time(ft, fmt); @@ -885,7 +894,8 @@ screen_redraw_draw_borders_style(struct screen_redraw_ctx *ctx, u_int x, struct session *s = c->session; struct window *w = s->curw->window; struct window_pane *active = server_client_get_pane(c); - struct options *oo = w->options; + struct options *wo = w->options; + const char *border_opt; struct format_tree *ft; if (wp->border_gc_set) @@ -894,12 +904,21 @@ screen_redraw_draw_borders_style(struct screen_redraw_ctx *ctx, u_int x, ft = format_create_defaults(NULL, c, s, s->curw, wp); - if (screen_redraw_check_is(ctx, x, y, active)) - style_apply(&wp->border_gc, oo, "pane-active-border-style", ft); - else - style_apply(&wp->border_gc, oo, "pane-border-style", ft); - format_free(ft); + border_opt = screen_redraw_check_is(ctx, x, y, active) ? + "pane-active-border-style" : "pane-border-style"; + /* Window-level baseline. */ + style_apply(&wp->border_gc, wo, border_opt, ft); + + /* Floating pane window default overrides window baseline. */ + if (wp->flags & PANE_FLOATING) + style_add(&wp->border_gc, wo, "floating-pane-border-style", ft); + + /* Per-pane override (set via new-pane -S or set-option -p). */ + if (options_get_only(wp->options, border_opt) != NULL) + style_add(&wp->border_gc, wp->options, border_opt, ft); + + format_free(ft); return (&wp->border_gc); } diff --git a/tmux.1 b/tmux.1 index 68e4fd88..0b52fd93 100644 --- a/tmux.1 +++ b/tmux.1 @@ -3278,6 +3278,8 @@ but a different format may be specified with .Op Fl l Ar size .Op Fl m Ar message .Op Fl p Ar percentage +.Op Fl s Ar style +.Op Fl S Ar border-style .Op Fl t Ar target-pane .Op Fl w Ar width .Op Fl x Ar x-position @@ -3334,6 +3336,12 @@ flag (if is not specified or empty) will create an empty pane and forward any output from stdin to it. .Pp +.Fl s +sets the style for the pane and +.Fl S +sets the style for the pane border (see +.Sx STYLES ) . +.Pp All other options have the same meaning as for the .Ic new-window command. @@ -5178,6 +5186,42 @@ Set clock hour format. .It Ic fill-character Ar character Set the character used to fill areas of the terminal unused by a window. .Pp +.It Ic floating-pane-border-style Ar style +Set the default border style for all floating panes in the window. +This overrides +.Ic pane-border-style +for floating panes. +A per-pane style set with +.Fl S +on the +.Ic new-pane +command or with +.Ic set-option Fl p +takes priority over this option. +For how to specify +.Ar style , +see the +.Sx STYLES +section. +.Pp +.It Ic floating-pane-style Ar style +Set the default content style for all floating panes in the window. +This overrides +.Ic window-style +for floating panes. +A per-pane style set with +.Fl s +on the +.Ic new-pane +command or with +.Ic select-pane Fl P +takes priority over this option. +For how to specify +.Ar style , +see the +.Sx STYLES +section. +.Pp .It Ic main-pane-height Ar height .It Ic main-pane-width Ar width Set the width or height of the main (left or top) pane in the diff --git a/tty.c b/tty.c index cdf9f49f..0804a743 100644 --- a/tty.c +++ b/tty.c @@ -3221,7 +3221,8 @@ tty_window_default_style(struct grid_cell *gc, struct window_pane *wp) void tty_default_colours(struct grid_cell *gc, struct window_pane *wp) { - struct options *oo = wp->options; + struct window *w = wp->window; + struct options *wo = w->options; struct format_tree *ft; memcpy(gc, &grid_default_cell, sizeof *gc); @@ -3233,10 +3234,30 @@ tty_default_colours(struct grid_cell *gc, struct window_pane *wp) ft = format_create(NULL, NULL, FORMAT_PANE|wp->id, FORMAT_NOJOBS); format_defaults(ft, NULL, NULL, NULL, wp); + + /* Window-level baseline. */ tty_window_default_style(&wp->cached_active_gc, wp); - style_add(&wp->cached_active_gc, oo, "window-active-style", ft); + style_add(&wp->cached_active_gc, wo, "window-active-style", ft); + /* Floating pane window default overrides window baseline. */ + if (wp->flags & PANE_FLOATING) + style_add(&wp->cached_active_gc, wo, + "floating-pane-style", ft); + /* Per-pane override (set via new-pane -s or select-pane -P). */ + if (options_get_only(wp->options, "window-active-style") != NULL) + style_add(&wp->cached_active_gc, wp->options, + "window-active-style", ft); + + /* Window-level baseline. */ tty_window_default_style(&wp->cached_gc, wp); - style_add(&wp->cached_gc, oo, "window-style", ft); + style_add(&wp->cached_gc, wo, "window-style", ft); + /* Floating pane window default overrides window baseline. */ + if (wp->flags & PANE_FLOATING) + style_add(&wp->cached_gc, wo, "floating-pane-style", ft); + /* Per-pane override (set via new-pane -s or select-pane -P). */ + if (options_get_only(wp->options, "window-style") != NULL) + style_add(&wp->cached_gc, wp->options, + "window-style", ft); + format_free(ft); }