diff --git a/colour.c b/colour.c index 88198e96..1cad01f9 100644 --- a/colour.c +++ b/colour.c @@ -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) diff --git a/format.c b/format.c index d977f154..85c83fda 100644 --- a/format.c +++ b/format.c @@ -1020,7 +1020,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))); } @@ -1057,7 +1057,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))); } diff --git a/input.c b/input.c index aa7b0c0c..cd664360 100644 --- a/input.c +++ b/input.c @@ -3055,7 +3055,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 diff --git a/popup.c b/popup.c index 999e4066..733aa3d7 100644 --- a/popup.c +++ b/popup.c @@ -327,6 +327,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) { diff --git a/screen-redraw.c b/screen-redraw.c index 1e41b859..20d3fc09 100644 --- a/screen-redraw.c +++ b/screen-redraw.c @@ -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; diff --git a/screen-write.c b/screen-write.c index 26e4789b..9973039a 100644 --- a/screen-write.c +++ b/screen-write.c @@ -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; diff --git a/style.c b/style.c index 586e9f93..b79d3291 100644 --- a/style.c +++ b/style.c @@ -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. */ diff --git a/tmux.1 b/tmux.1 index e7bf3713..7d9455e2 100644 --- a/tmux.1 +++ b/tmux.1 @@ -7013,6 +7013,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 diff --git a/tmux.h b/tmux.h index 7a62f415..5a3e7176 100644 --- a/tmux.h +++ b/tmux.h @@ -955,6 +955,7 @@ enum style_default_type { struct style { struct grid_cell gc; int ignore; + int dim; int fill; enum style_align align; @@ -1323,6 +1324,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; @@ -1663,6 +1666,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; }; @@ -2765,7 +2769,7 @@ void tty_cmd_sixelimage(struct tty *, const struct tty_ctx *); void tty_draw_images(struct client *, struct window_pane *, struct screen *); #endif 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; @@ -3202,6 +3206,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 *); @@ -3856,7 +3861,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 *); diff --git a/tty.c b/tty.c index f17e5d57..ed3028c4 100644 --- a/tty.c +++ b/tty.c @@ -85,7 +85,7 @@ static void tty_write_one(void (*)(struct tty *, const struct tty_ctx *), #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 @@ -2591,16 +2591,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); @@ -2609,6 +2632,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. */ @@ -2635,9 +2676,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, @@ -3049,6 +3090,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; @@ -3057,16 +3099,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); @@ -3080,6 +3124,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 diff --git a/window.c b/window.c index 33ac6e1f..11410b52 100644 --- a/window.c +++ b/window.c @@ -599,6 +599,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); @@ -1974,7 +1976,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