Add a dim= style attribute to dim the colours (as best as tmux is able

to). GitHub issue 4842.
This commit is contained in:
nicm
2026-06-18 09:59:55 +00:00
parent b1b184cdb8
commit d92a479d2f
11 changed files with 115 additions and 16 deletions

View File

@@ -120,6 +120,28 @@ colour_force_rgb(int c)
return (-1);
}
/* Dim colour by a percentage. */
int
colour_dim(int c, u_int dim)
{
u_char r, g, b;
if (dim == 0 || COLOUR_DEFAULT(c))
return (c);
if (dim >= 100)
return (colour_join_rgb(0, 0, 0));
c = colour_force_rgb(c);
if (c == -1)
return (-1);
colour_split_rgb(c, &r, &g, &b);
r = (r * (100 - dim)) / 100;
g = (g * (100 - dim)) / 100;
b = (b * (100 - dim)) / 100;
return (colour_join_rgb(r, g, b));
}
/* Convert colour to a string. */
const char *
colour_tostring(int c)

View File

@@ -1006,7 +1006,7 @@ format_cb_pane_fg(struct format_tree *ft)
if (wp == NULL)
return (NULL);
tty_default_colours(&gc, wp);
tty_default_colours(&gc, wp, NULL);
return (xstrdup(colour_tostring(gc.fg)));
}
@@ -1043,7 +1043,7 @@ format_cb_pane_bg(struct format_tree *ft)
if (wp == NULL)
return (NULL);
tty_default_colours(&gc, wp);
tty_default_colours(&gc, wp, NULL);
return (xstrdup(colour_tostring(gc.bg)));
}

View File

@@ -3018,7 +3018,7 @@ input_osc_10(struct input_ctx *ictx, const char *p)
return;
c = window_pane_get_fg_control_client(wp);
if (c == -1) {
tty_default_colours(&defaults, wp);
tty_default_colours(&defaults, wp, NULL);
if (COLOUR_DEFAULT(defaults.fg))
c = window_pane_get_fg(wp);
else

View File

@@ -328,6 +328,7 @@ popup_draw_cb(struct client *c, void *data, struct screen_redraw_ctx *rctx)
defaults.bg = pd->palette.bg;
style_ctx.defaults = &defaults;
style_ctx.palette = &pd->palette;
style_ctx.dim = 0;
style_ctx.hyperlinks = s.hyperlinks;
if (pd->md != NULL) {

View File

@@ -1212,7 +1212,7 @@ screen_redraw_draw_pane(struct screen_redraw_ctx *ctx, struct window_pane *wp)
}
/* Set up the default style. */
tty_default_colours(&defaults, wp);
tty_default_colours(&defaults, wp, &style_ctx.dim);
style_ctx.defaults = &defaults;
style_ctx.palette = palette;
style_ctx.hyperlinks = s->hyperlinks;

View File

@@ -252,7 +252,8 @@ screen_write_initctx(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx,
} else {
ttyctx->redraw_cb = screen_write_redraw_cb;
if (ctx->wp != NULL) {
tty_default_colours(&ttyctx->defaults, ctx->wp);
tty_default_colours(&ttyctx->defaults, ctx->wp,
&ttyctx->style_ctx.dim);
ttyctx->style_ctx.palette = &ctx->wp->palette;
ttyctx->set_client_cb = screen_write_set_client_cb;
ttyctx->arg = ctx->wp;

16
style.c
View File

@@ -32,6 +32,7 @@
static struct style style_default = {
{ { { ' ' }, 0, 1, 1 }, 0, 0, 8, 8, 0, 0 },
0,
0,
8,
STYLE_ALIGN_DEFAULT,
@@ -201,6 +202,13 @@ style_parse(struct style *sy, const struct grid_cell *base, const char *in)
if ((value = colour_fromstring(tmp + 5)) == -1)
goto error;
sy->fill = value;
} else if (end > 4 && strncasecmp(tmp, "dim=", 4) == 0) {
if (tmp[end - 1] == '%')
tmp[end - 1] = '\0';
n = strtonum(tmp + 4, 0, 100, &errstr);
if (errstr != NULL)
goto error;
sy->dim = n;
} else if (end > 3 && strncasecmp(tmp + 1, "g=", 2) == 0) {
if ((value = colour_fromstring(tmp + 3)) == -1)
goto error;
@@ -346,6 +354,11 @@ style_tostring(struct style *sy)
colour_tostring(sy->fill));
comma = ",";
}
if (sy->dim != 0) {
off += xsnprintf(s + off, sizeof s - off, "%sdim=%d%%", comma,
sy->dim);
comma = ",";
}
if (gc->fg != 8) {
off += xsnprintf(s + off, sizeof s - off, "%sfg=%s", comma,
colour_tostring(gc->fg));
@@ -386,7 +399,7 @@ style_tostring(struct style *sy)
}
/* Apply a style on top of the given style. */
void
struct style *
style_add(struct grid_cell *gc, struct options *oo, const char *name,
struct format_tree *ft)
{
@@ -409,6 +422,7 @@ style_add(struct grid_cell *gc, struct options *oo, const char *name,
if (ft0 != NULL)
format_free(ft0);
return (sy);
}
/* Apply a style on top of the default style. */

3
tmux.1
View File

@@ -7011,6 +7011,9 @@ is the terminal alternate character set.
Align text to the left, centre or right of the available space if appropriate.
.It Ic fill=colour
Fill the available space with a background colour if appropriate.
.It Ic dim=percentage
Dim foreground and background colours by
.Ar percentage .
.It Ic width=N
Set the width of the styled area.
.Ar N

9
tmux.h
View File

@@ -946,6 +946,7 @@ enum style_default_type {
struct style {
struct grid_cell gc;
int ignore;
int dim;
int fill;
enum style_align align;
@@ -1289,6 +1290,8 @@ struct window_pane {
struct grid_cell cached_gc;
struct grid_cell cached_active_gc;
u_int cached_dim;
u_int cached_active_dim;
struct colour_palette palette;
enum client_theme last_theme;
struct style_line_entry border_status_line;
@@ -1629,6 +1632,7 @@ LIST_HEAD(tty_terms, tty_term);
struct tty_style_ctx {
const struct grid_cell *defaults;
struct colour_palette *palette;
u_int dim;
struct hyperlinks *hyperlinks;
};
@@ -2720,7 +2724,7 @@ void tty_cmd_reverseindex(struct tty *, const struct tty_ctx *);
void tty_cmd_setselection(struct tty *, const struct tty_ctx *);
void tty_cmd_rawstring(struct tty *, const struct tty_ctx *);
void tty_cmd_syncstart(struct tty *, const struct tty_ctx *);
void tty_default_colours(struct grid_cell *, struct window_pane *);
void tty_default_colours(struct grid_cell *, struct window_pane *, u_int *);
/* tty-term.c */
extern struct tty_terms tty_terms;
@@ -3157,6 +3161,7 @@ int colour_find_rgb(u_char, u_char, u_char);
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);
int colour_dim(int, u_int);
const char *colour_tostring(int);
enum client_theme colour_totheme(int);
int colour_fromstring(const char *);
@@ -3806,7 +3811,7 @@ int popup_modify(struct client *, const char *, const char *,
int style_parse(struct style *,const struct grid_cell *,
const char *);
const char *style_tostring(struct style *);
void style_add(struct grid_cell *, struct options *,
struct style *style_add(struct grid_cell *, struct options *,
const char *, struct format_tree *);
void style_apply(struct grid_cell *, struct options *,
const char *, struct format_tree *);

65
tty.c
View File

@@ -80,7 +80,7 @@ static int tty_check_overlay(struct tty *, u_int, u_int);
#define TTY_REQUEST_LIMIT 30
static struct tty_style_ctx tty_default_style_ctx = {
&grid_default_cell, NULL, NULL
&grid_default_cell, NULL, 0, NULL
};
void
@@ -2467,16 +2467,39 @@ tty_hyperlink(struct tty *tty, const struct grid_cell *gc,
tty_putcode_ss(tty, TTYC_HLS, id, uri);
}
static int
tty_dim_default_colour(struct tty *tty, int c, int foreground)
{
enum client_theme theme;
if (!COLOUR_DEFAULT(c))
return (c);
if (foreground && tty->fg != -1)
return (tty->fg);
if (!foreground && tty->bg != -1)
return (tty->bg);
theme = tty->client->theme;
if (theme == THEME_DARK)
return (foreground ? 7 : 0);
if (theme == THEME_LIGHT)
return (foreground ? 0 : 7);
return (c);
}
void
tty_attributes(struct tty *tty, const struct grid_cell *gc,
const struct tty_style_ctx *style_ctx)
{
struct grid_cell *tc = &tty->cell, gc2;
struct colour_palette *palette;
int changed;
/* Use default style if not given. */
if (style_ctx == NULL)
style_ctx = &tty_default_style_ctx;
palette = style_ctx->palette;
/* Copy cell and update default colours. */
memcpy(&gc2, gc, sizeof gc2);
@@ -2485,6 +2508,24 @@ tty_attributes(struct tty *tty, const struct grid_cell *gc,
gc2.fg = style_ctx->defaults->fg;
if (gc2.bg == 8)
gc2.bg = style_ctx->defaults->bg;
if (palette != NULL) {
changed = colour_palette_get(palette, gc2.fg);
if (changed != -1)
gc2.fg = changed;
changed = colour_palette_get(palette, gc2.bg);
if (changed != -1)
gc2.bg = changed;
}
}
if (style_ctx->dim != 0) {
gc2.fg = tty_dim_default_colour(tty, gc2.fg, 1);
gc2.bg = tty_dim_default_colour(tty, gc2.bg, 0);
changed = colour_dim(gc2.fg, style_ctx->dim);
if (changed != -1)
gc2.fg = changed;
changed = colour_dim(gc2.bg, style_ctx->dim);
if (changed != -1)
gc2.bg = changed;
}
/* Ignore cell if it is the same as the last one. */
@@ -2511,9 +2552,9 @@ tty_attributes(struct tty *tty, const struct grid_cell *gc,
}
/* Fix up the colours if necessary. */
tty_check_fg(tty, style_ctx->palette, &gc2);
tty_check_bg(tty, style_ctx->palette, &gc2);
tty_check_us(tty, style_ctx->palette, &gc2);
tty_check_fg(tty, palette, &gc2);
tty_check_bg(tty, palette, &gc2);
tty_check_us(tty, palette, &gc2);
/*
* If any bits are being cleared or the underline colour is now default,
@@ -2925,6 +2966,7 @@ tty_style_changed(struct window_pane *wp)
{
struct options *oo = wp->options;
struct format_tree *ft;
struct style *sy;
log_debug("%%%u: style changed", wp->id);
wp->flags &= ~PANE_STYLECHANGED;
@@ -2933,16 +2975,18 @@ tty_style_changed(struct window_pane *wp)
format_defaults(ft, NULL, NULL, NULL, wp);
tty_window_default_style(&wp->cached_active_gc, wp);
style_add(&wp->cached_active_gc, oo, "window-active-style", ft);
sy = style_add(&wp->cached_active_gc, oo, "window-active-style", ft);
wp->cached_active_dim = sy->dim;
tty_window_default_style(&wp->cached_gc, wp);
style_add(&wp->cached_gc, oo, "window-style", ft);
sy = style_add(&wp->cached_gc, oo, "window-style", ft);
wp->cached_dim = sy->dim;
format_free(ft);
}
void
tty_default_colours(struct grid_cell *gc, struct window_pane *wp)
tty_default_colours(struct grid_cell *gc, struct window_pane *wp, u_int *dim)
{
if (wp->flags & PANE_STYLECHANGED)
tty_style_changed (wp);
@@ -2956,6 +3000,13 @@ tty_default_colours(struct grid_cell *gc, struct window_pane *wp)
gc->bg = wp->cached_active_gc.bg;
else
gc->bg = wp->cached_gc.bg;
if (dim != NULL) {
if (wp == wp->window->active)
*dim = wp->cached_active_dim;
else
*dim = wp->cached_dim;
}
}
void

View File

@@ -592,6 +592,8 @@ window_redraw_active_switch(struct window *w, struct window_pane *wp)
gc2 = &wp->cached_active_gc;
if (!grid_cells_look_equal(gc1, gc2))
wp->flags |= PANE_REDRAW;
else if (wp->cached_dim != wp->cached_active_dim)
wp->flags |= PANE_REDRAW;
else {
c1 = window_pane_get_palette(wp, gc1->fg);
c2 = window_pane_get_palette(wp, gc2->fg);
@@ -1963,7 +1965,7 @@ window_pane_get_bg(struct window_pane *wp)
c = window_pane_get_bg_control_client(wp);
if (c == -1) {
tty_default_colours(&defaults, wp);
tty_default_colours(&defaults, wp, NULL);
if (COLOUR_DEFAULT(defaults.bg))
c = window_get_bg_client(wp);
else