Merge branch 'master' into floating_panes

This commit is contained in:
Dane Jensen
2026-06-18 12:50:47 -07:00
16 changed files with 244 additions and 101 deletions

View File

@@ -120,6 +120,28 @@ colour_force_rgb(int c)
return (-1); 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. */ /* Convert colour to a string. */
const char * const char *
colour_tostring(int c) colour_tostring(int c)

136
format.c
View File

@@ -128,6 +128,9 @@ format_job_cmp(struct format_job *fj1, struct format_job *fj2)
/* Limit on time taken (milliseconds). */ /* Limit on time taken (milliseconds). */
#define FORMAT_TIME_LIMIT 100 #define FORMAT_TIME_LIMIT 100
/* How often to check the time in long loops. */
#define FORMAT_TIME_LOOP_CHECK 10000
/* Format expand flags. */ /* Format expand flags. */
#define FORMAT_EXPAND_TIME 0x1 #define FORMAT_EXPAND_TIME 0x1
#define FORMAT_EXPAND_NOJOBS 0x2 #define FORMAT_EXPAND_NOJOBS 0x2
@@ -573,7 +576,7 @@ format_cb_session_attached_list(struct format_tree *ft)
} }
if ((size = EVBUFFER_LENGTH(buffer)) != 0) if ((size = EVBUFFER_LENGTH(buffer)) != 0)
xasprintf(&value, "%.*s", size, EVBUFFER_DATA(buffer)); value = xmemdup(EVBUFFER_DATA(buffer), size);
evbuffer_free(buffer); evbuffer_free(buffer);
return (value); return (value);
} }
@@ -712,7 +715,7 @@ format_cb_window_linked_sessions_list(struct format_tree *ft)
} }
if ((size = EVBUFFER_LENGTH(buffer)) != 0) if ((size = EVBUFFER_LENGTH(buffer)) != 0)
xasprintf(&value, "%.*s", size, EVBUFFER_DATA(buffer)); value = xmemdup(EVBUFFER_DATA(buffer), size);
evbuffer_free(buffer); evbuffer_free(buffer);
return (value); return (value);
} }
@@ -766,7 +769,7 @@ format_cb_window_active_sessions_list(struct format_tree *ft)
} }
if ((size = EVBUFFER_LENGTH(buffer)) != 0) if ((size = EVBUFFER_LENGTH(buffer)) != 0)
xasprintf(&value, "%.*s", size, EVBUFFER_DATA(buffer)); value = xmemdup(EVBUFFER_DATA(buffer), size);
evbuffer_free(buffer); evbuffer_free(buffer);
return (value); return (value);
} }
@@ -830,7 +833,7 @@ format_cb_window_active_clients_list(struct format_tree *ft)
} }
if ((size = EVBUFFER_LENGTH(buffer)) != 0) if ((size = EVBUFFER_LENGTH(buffer)) != 0)
xasprintf(&value, "%.*s", size, EVBUFFER_DATA(buffer)); value = xmemdup(EVBUFFER_DATA(buffer), size);
evbuffer_free(buffer); evbuffer_free(buffer);
return (value); return (value);
} }
@@ -1005,7 +1008,7 @@ format_cb_pane_tabs(struct format_tree *ft)
evbuffer_add_printf(buffer, "%u", i); evbuffer_add_printf(buffer, "%u", i);
} }
if ((size = EVBUFFER_LENGTH(buffer)) != 0) if ((size = EVBUFFER_LENGTH(buffer)) != 0)
xasprintf(&value, "%.*s", size, EVBUFFER_DATA(buffer)); value = xmemdup(EVBUFFER_DATA(buffer), size);
evbuffer_free(buffer); evbuffer_free(buffer);
return (value); return (value);
} }
@@ -1020,7 +1023,7 @@ format_cb_pane_fg(struct format_tree *ft)
if (wp == NULL) if (wp == NULL)
return (NULL); return (NULL);
tty_default_colours(&gc, wp); tty_default_colours(&gc, wp, NULL);
return (xstrdup(colour_tostring(gc.fg))); return (xstrdup(colour_tostring(gc.fg)));
} }
@@ -1057,7 +1060,7 @@ format_cb_pane_bg(struct format_tree *ft)
if (wp == NULL) if (wp == NULL)
return (NULL); return (NULL);
tty_default_colours(&gc, wp); tty_default_colours(&gc, wp, NULL);
return (xstrdup(colour_tostring(gc.bg))); return (xstrdup(colour_tostring(gc.bg)));
} }
@@ -1089,7 +1092,7 @@ format_cb_session_group_list(struct format_tree *ft)
} }
if ((size = EVBUFFER_LENGTH(buffer)) != 0) if ((size = EVBUFFER_LENGTH(buffer)) != 0)
xasprintf(&value, "%.*s", size, EVBUFFER_DATA(buffer)); value = xmemdup(EVBUFFER_DATA(buffer), size);
evbuffer_free(buffer); evbuffer_free(buffer);
return (value); return (value);
} }
@@ -1129,7 +1132,7 @@ format_cb_session_group_attached_list(struct format_tree *ft)
} }
if ((size = EVBUFFER_LENGTH(buffer)) != 0) if ((size = EVBUFFER_LENGTH(buffer)) != 0)
xasprintf(&value, "%.*s", size, EVBUFFER_DATA(buffer)); value = xmemdup(EVBUFFER_DATA(buffer), size);
evbuffer_free(buffer); evbuffer_free(buffer);
return (value); return (value);
} }
@@ -4254,10 +4257,14 @@ found:
/* Check if format has not taken too long. */ /* Check if format has not taken too long. */
static int static int
format_check_time(struct format_expand_state *es) format_check_time(struct format_expand_state *es, u_int *check)
{ {
uint64_t t = get_timer(); uint64_t t;
if (check != NULL && ++*check % FORMAT_TIME_LOOP_CHECK != 0)
return (1);
t = get_timer();
if (t - es->start_time < FORMAT_TIME_LIMIT) if (t - es->start_time < FORMAT_TIME_LIMIT)
return (1); return (1);
t -= es->start_time; t -= es->start_time;
@@ -4268,21 +4275,24 @@ format_check_time(struct format_expand_state *es)
/* Unescape escaped characters. */ /* Unescape escaped characters. */
static char * static char *
format_unescape(struct format_expand_state *es, const char *s) format_unescape(struct format_expand_state *es, const char *s, size_t n)
{ {
char *out, *cp; const char *end = s + n;
int brackets = 0; char *out, *cp;
int brackets = 0;
u_int check = 0;
cp = out = xmalloc(strlen(s) + 1); cp = out = xmalloc(n + 1);
for (; *s != '\0'; s++) { for (; s != end; s++) {
if (!format_check_time(es)){ if (!format_check_time(es, &check)) {
free(out); free(out);
return (xstrdup("")); return (xstrdup(""));
} }
if (*s == '#' && s[1] == '{') if (*s == '#' && s + 1 != end && s[1] == '{')
brackets++; brackets++;
if (brackets == 0 && if (brackets == 0 &&
*s == '#' && *s == '#' &&
s + 1 != end &&
strchr(",#{}:", s[1]) != NULL) { strchr(",#{}:", s[1]) != NULL) {
*cp++ = *++s; *cp++ = *++s;
continue; continue;
@@ -4301,10 +4311,11 @@ format_strip(struct format_expand_state *es, const char *s)
{ {
char *out, *cp; char *out, *cp;
int brackets = 0; int brackets = 0;
u_int check = 0;
cp = out = xmalloc(strlen(s) + 1); cp = out = xmalloc(strlen(s) + 1);
for (; *s != '\0'; s++) { for (; *s != '\0'; s++) {
if (!format_check_time(es)){ if (!format_check_time(es, &check)) {
free(out); free(out);
return (xstrdup("")); return (xstrdup(""));
} }
@@ -4328,9 +4339,10 @@ static const char *
format_skip1(struct format_expand_state *es, const char *s, const char *end) format_skip1(struct format_expand_state *es, const char *s, const char *end)
{ {
int brackets = 0; int brackets = 0;
u_int check = 0;
for (; *s != '\0'; s++) { for (; *s != '\0'; s++) {
if (es != NULL && !format_check_time(es)) if (es != NULL && !format_check_time(es, &check))
return (NULL); return (NULL);
if (*s == '#' && s[1] == '{') if (*s == '#' && s[1] == '{')
brackets++; brackets++;
@@ -4501,7 +4513,7 @@ format_build_modifiers(struct format_expand_state *es, const char **s,
break; break;
argv = xcalloc(1, sizeof *argv); argv = xcalloc(1, sizeof *argv);
value = xstrndup(cp + 1, end - (cp + 1)); value = format_unescape(es, cp + 1, end - (cp + 1));
argv[0] = format_expand1(es, value); argv[0] = format_expand1(es, value);
free(value); free(value);
argc = 1; argc = 1;
@@ -4525,7 +4537,7 @@ format_build_modifiers(struct format_expand_state *es, const char **s,
cp++; cp++;
argv = xreallocarray(argv, argc + 1, sizeof *argv); argv = xreallocarray(argv, argc + 1, sizeof *argv);
value = xstrndup(cp, end - cp); value = format_unescape(es, cp, end - cp);
argv[argc++] = format_expand1(es, value); argv[argc++] = format_expand1(es, value);
free(value); free(value);
@@ -4688,7 +4700,8 @@ format_loop_sessions(struct format_expand_state *es, const char *fmt)
struct format_tree *nft; struct format_tree *nft;
struct format_expand_state next; struct format_expand_state next;
char *all, *active, *use, *expanded, *value; char *all, *active, *use, *expanded, *value;
size_t valuelen; struct evbuffer *buffer;
size_t size;
struct session *s, **l; struct session *s, **l;
int i, n, last = 0; int i, n, last = 0;
@@ -4697,8 +4710,9 @@ format_loop_sessions(struct format_expand_state *es, const char *fmt)
active = NULL; active = NULL;
} }
value = xcalloc(1, 1); buffer = evbuffer_new();
valuelen = 1; if (buffer == NULL)
fatalx("out of memory");
l = sort_get_sessions(&n, sc); l = sort_get_sessions(&n, sc);
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
@@ -4719,16 +4733,18 @@ format_loop_sessions(struct format_expand_state *es, const char *fmt)
expanded = format_expand1(&next, use); expanded = format_expand1(&next, use);
format_free(next.ft); format_free(next.ft);
valuelen += strlen(expanded); evbuffer_add(buffer, expanded, strlen(expanded));
value = xrealloc(value, valuelen);
strlcat(value, expanded, valuelen);
free(expanded); free(expanded);
} }
free(active); free(active);
free(all); free(all);
if ((size = EVBUFFER_LENGTH(buffer)) != 0)
value = xmemdup(EVBUFFER_DATA(buffer), size);
else
value = xstrdup("");
evbuffer_free(buffer);
return (value); return (value);
} }
@@ -4798,7 +4814,8 @@ format_loop_windows(struct format_expand_state *es, const char *fmt)
struct format_tree *nft; struct format_tree *nft;
struct format_expand_state next; struct format_expand_state next;
char *all, *active, *use, *expanded, *value; char *all, *active, *use, *expanded, *value;
size_t valuelen; struct evbuffer *buffer;
size_t size;
struct winlink *wl, **l; struct winlink *wl, **l;
struct window *w; struct window *w;
int i, n, last = 0; int i, n, last = 0;
@@ -4813,8 +4830,9 @@ format_loop_windows(struct format_expand_state *es, const char *fmt)
active = NULL; active = NULL;
} }
value = xcalloc(1, 1); buffer = evbuffer_new();
valuelen = 1; if (buffer == NULL)
fatalx("out of memory");
l = sort_get_winlinks_session(ft->s, &n, sc); l = sort_get_winlinks_session(ft->s, &n, sc);
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
@@ -4846,16 +4864,18 @@ format_loop_windows(struct format_expand_state *es, const char *fmt)
expanded = format_expand1(&next, use); expanded = format_expand1(&next, use);
format_free(nft); format_free(nft);
valuelen += strlen(expanded); evbuffer_add(buffer, expanded, strlen(expanded));
value = xrealloc(value, valuelen);
strlcat(value, expanded, valuelen);
free(expanded); free(expanded);
} }
free(active); free(active);
free(all); free(all);
if ((size = EVBUFFER_LENGTH(buffer)) != 0)
value = xmemdup(EVBUFFER_DATA(buffer), size);
else
value = xstrdup("");
evbuffer_free(buffer);
return (value); return (value);
} }
@@ -4870,7 +4890,8 @@ format_loop_panes(struct format_expand_state *es, const char *fmt)
struct format_tree *nft; struct format_tree *nft;
struct format_expand_state next; struct format_expand_state next;
char *all, *active, *use, *expanded, *value; char *all, *active, *use, *expanded, *value;
size_t valuelen; struct evbuffer *buffer;
size_t size;
struct window_pane *wp, **l; struct window_pane *wp, **l;
int i, n, last = 0; int i, n, last = 0;
@@ -4884,8 +4905,9 @@ format_loop_panes(struct format_expand_state *es, const char *fmt)
active = NULL; active = NULL;
} }
value = xcalloc(1, 1); buffer = evbuffer_new();
valuelen = 1; if (buffer == NULL)
fatalx("out of memory");
l = sort_get_panes_window(ft->w, &n, sc); l = sort_get_panes_window(ft->w, &n, sc);
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
@@ -4905,16 +4927,18 @@ format_loop_panes(struct format_expand_state *es, const char *fmt)
expanded = format_expand1(&next, use); expanded = format_expand1(&next, use);
format_free(nft); format_free(nft);
valuelen += strlen(expanded); evbuffer_add(buffer, expanded, strlen(expanded));
value = xrealloc(value, valuelen);
strlcat(value, expanded, valuelen);
free(expanded); free(expanded);
} }
free(active); free(active);
free(all); free(all);
if ((size = EVBUFFER_LENGTH(buffer)) != 0)
value = xmemdup(EVBUFFER_DATA(buffer), size);
else
value = xstrdup("");
evbuffer_free(buffer);
return (value); return (value);
} }
@@ -4929,11 +4953,13 @@ format_loop_clients(struct format_expand_state *es, const char *fmt)
struct format_tree *nft; struct format_tree *nft;
struct format_expand_state next; struct format_expand_state next;
char *expanded, *value; char *expanded, *value;
size_t valuelen; struct evbuffer *buffer;
size_t size;
int i, n, last = 0; int i, n, last = 0;
value = xcalloc(1, 1); buffer = evbuffer_new();
valuelen = 1; if (buffer == NULL)
fatalx("out of memory");
l = sort_get_clients(&n, sc); l = sort_get_clients(&n, sc);
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
@@ -4948,13 +4974,15 @@ format_loop_clients(struct format_expand_state *es, const char *fmt)
expanded = format_expand1(&next, fmt); expanded = format_expand1(&next, fmt);
format_free(nft); format_free(nft);
valuelen += strlen(expanded); evbuffer_add(buffer, expanded, strlen(expanded));
value = xrealloc(value, valuelen);
strlcat(value, expanded, valuelen);
free(expanded); free(expanded);
} }
if ((size = EVBUFFER_LENGTH(buffer)) != 0)
value = xmemdup(EVBUFFER_DATA(buffer), size);
else
value = xstrdup("");
evbuffer_free(buffer);
return (value); return (value);
} }
@@ -5120,7 +5148,7 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
struct format_modifier *list, *cmp = NULL, *search = NULL; struct format_modifier *list, *cmp = NULL, *search = NULL;
struct format_modifier **sub = NULL, *mexp = NULL, *fm; struct format_modifier **sub = NULL, *mexp = NULL, *fm;
struct format_modifier *bool_op_n = NULL; struct format_modifier *bool_op_n = NULL;
u_int i, count, nsub = 0, nrep; u_int i, count, nsub = 0, nrep, check = 0;
struct format_expand_state next; struct format_expand_state next;
struct environ_entry *envent; struct environ_entry *envent;
@@ -5377,7 +5405,7 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
/* Is this a literal string? */ /* Is this a literal string? */
if (modifiers & FORMAT_LITERAL) { if (modifiers & FORMAT_LITERAL) {
format_log(es, "literal string is '%s'", copy); format_log(es, "literal string is '%s'", copy);
value = format_unescape(es, copy); value = format_unescape(es, copy, strlen(copy));
goto done; goto done;
} }
@@ -5453,7 +5481,7 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
else { else {
value = xstrdup(""); value = xstrdup("");
for (i = 0; i < nrep; i++) { for (i = 0; i < nrep; i++) {
if (!format_check_time(es)) { if (!format_check_time(es, &check)) {
free(right); free(right);
free(left); free(left);
free(value); free(value);
@@ -5733,7 +5761,7 @@ format_expand1(struct format_expand_state *es, const char *fmt)
int ch, brackets; int ch, brackets;
char expanded[8192]; char expanded[8192];
if (fmt == NULL || *fmt == '\0' || !format_check_time(es)) if (fmt == NULL || *fmt == '\0' || !format_check_time(es, NULL))
return (xstrdup("")); return (xstrdup(""));
if (es->loop == FORMAT_LOOP_LIMIT) { if (es->loop == FORMAT_LOOP_LIMIT) {

View File

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

View File

@@ -624,18 +624,18 @@ layout_resize_set_size(struct window *w, struct layout_cell *lc,
static struct layout_cell * static struct layout_cell *
layout_cell_get_neighbour_direction(struct layout_cell *lc, int direction) layout_cell_get_neighbour_direction(struct layout_cell *lc, int direction)
{ {
struct layout_cell *lcneighbour = lc; struct layout_cell *lcn = lc;
while (1) { while (1) {
if (direction) if (direction)
lcneighbour = TAILQ_NEXT(lcneighbour, entry); lcn = TAILQ_NEXT(lcn, entry);
else else
lcneighbour = TAILQ_PREV(lcneighbour, layout_cells, lcn = TAILQ_PREV(lcn, layout_cells, entry);
entry);
if (lcneighbour == NULL || layout_cell_is_tiled(lcneighbour) || if (lcn == NULL ||
layout_cell_has_tiled_child(lcneighbour)) layout_cell_is_tiled(lcn) ||
return (lcneighbour); layout_cell_has_tiled_child(lcn))
return (lcn);
} }
} }
@@ -660,19 +660,17 @@ layout_cell_get_neighbour(struct layout_cell *lc)
if (lcother == NULL) if (lcother == NULL)
lcother = layout_cell_get_neighbour_direction(lc, !direction); lcother = layout_cell_get_neighbour_direction(lc, !direction);
return lcother; return (lcother);
} }
/*
* Destroy a cell and redistribute the space if the cell was tiled. Assumes /* Destroy a cell and redistribute the space. */
* to be called on a leaf cell.
*/
void void
layout_destroy_cell(struct window *w, struct layout_cell *lc, layout_destroy_cell(struct window *w, struct layout_cell *lc,
struct layout_cell **lcroot) struct layout_cell **lcroot)
{ {
struct layout_cell *lcother, *lcparent; struct layout_cell *lcother = NULL, *lcparent;
int val; int change;
/* /*
* If no parent, this is either a floating pane or the last * If no parent, this is either a floating pane or the last
@@ -696,10 +694,10 @@ layout_destroy_cell(struct window *w, struct layout_cell *lc,
lcother = layout_cell_get_neighbour(lc); lcother = layout_cell_get_neighbour(lc);
if (lcother != NULL) { if (lcother != NULL) {
if (lcparent->type == LAYOUT_LEFTRIGHT) if (lcparent->type == LAYOUT_LEFTRIGHT)
val = lc->sx + 1; change = lc->sx + 1;
else else
val = lc->sy + 1; change = lc->sy + 1;
layout_resize_adjust(w, lcother, lcparent->type, val); layout_resize_adjust(w, lcother, lcparent->type, change);
} else } else
layout_remove_tile(w, lcparent); layout_remove_tile(w, lcparent);
@@ -1694,7 +1692,7 @@ layout_get_floating_cell(struct cmdq_item *item, struct args *args,
} }
/* /*
* Removes a cell from the tiled layout by giving half the cells space to the * Removes a cell from the tiled layout by giving the cell's space to the
* nearest neighbour. * nearest neighbour.
*/ */
int int

View File

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

View File

@@ -67,6 +67,7 @@ $TMUX set @true 1 || exit 1
$TMUX set @false 0 || exit 1 $TMUX set @false 0 || exit 1
$TMUX set @warm Summer || exit 1 $TMUX set @warm Summer || exit 1
$TMUX set @cold Winter || exit 1 $TMUX set @cold Winter || exit 1
$TMUX set @v 'foo:bar' || exit 1
# Plain string without substitutions et al # Plain string without substitutions et al
test_format "abc xyz" "abc xyz" test_format "abc xyz" "abc xyz"
@@ -74,6 +75,8 @@ test_format "abc xyz" "abc xyz"
# Test basic escapes for "#", "{", "#{" "}", "#}", "," # Test basic escapes for "#", "{", "#{" "}", "#}", ","
test_format "##" "#" test_format "##" "#"
test_format "#," "," test_format "#," ","
test_format "#{s/#:/_/:@v}" "foo_bar"
test_format "#{s/o/#:/:@v}" "f:::bar"
test_format "{" "{" test_format "{" "{"
test_format "##{" "#{" test_format "##{" "#{"
test_format "#}" "}" test_format "#}" "}"

View File

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

View File

@@ -255,7 +255,8 @@ screen_write_initctx(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx,
} else { } else {
ttyctx->redraw_cb = screen_write_redraw_cb; ttyctx->redraw_cb = screen_write_redraw_cb;
if (ctx->wp != NULL) { 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->style_ctx.palette = &ctx->wp->palette;
ttyctx->set_client_cb = screen_write_set_client_cb; ttyctx->set_client_cb = screen_write_set_client_cb;
ttyctx->arg = ctx->wp; ttyctx->arg = ctx->wp;

View File

@@ -2014,16 +2014,32 @@ server_client_check_modes(struct client *c)
} }
} }
/* Check if any panes need to be redrawn. */
static int
server_client_any_pane_redraw(struct client *c)
{
struct session *s = c->session;
struct window *w = s->curw->window;
struct window_pane *wp;
if (c->flags & CLIENT_REDRAWWINDOW)
return (1);
TAILQ_FOREACH(wp, &w->panes, entry) {
if (wp->flags & (PANE_REDRAW|PANE_REDRAWSCROLLBAR))
return (1);
}
return (0);
}
/* Check for client redraws. */ /* Check for client redraws. */
static void static void
server_client_check_redraw(struct client *c) server_client_check_redraw(struct client *c)
{ {
struct session *s = c->session; struct session *s = c->session;
struct tty *tty = &c->tty; struct tty *tty = &c->tty;
struct window *w = c->session->curw->window; struct window *w = s->curw->window;
struct window_pane *wp; struct window_pane *wp;
int needed, tflags, mode = tty->mode; int needed, tflags, mode = tty->mode;
uint64_t client_flags = 0;
struct timeval tv = { .tv_usec = 1000 }; struct timeval tv = { .tv_usec = 1000 };
static struct event ev; static struct event ev;
size_t n; size_t n;
@@ -2042,20 +2058,8 @@ server_client_check_redraw(struct client *c)
needed = 0; needed = 0;
if (c->flags & CLIENT_ALLREDRAWFLAGS) if (c->flags & CLIENT_ALLREDRAWFLAGS)
needed = 1; needed = 1;
else { else if (server_client_any_pane_redraw(c))
TAILQ_FOREACH(wp, &w->panes, entry) { needed = 1;
if (wp->flags & PANE_REDRAW) {
needed = 1;
client_flags |= CLIENT_REDRAWWINDOW;
break;
}
if (wp->flags & PANE_REDRAWSCROLLBAR) {
needed = 1;
client_flags |= CLIENT_REDRAWWINDOW;
/* no break - later panes may need redraw */
}
}
}
if (!needed) { if (!needed) {
c->flags &= ~CLIENT_STATUSFORCE; c->flags &= ~CLIENT_STATUSFORCE;
return; return;
@@ -2078,7 +2082,8 @@ server_client_check_redraw(struct client *c)
log_debug("redraw timer started"); log_debug("redraw timer started");
evtimer_add(&ev, &tv); evtimer_add(&ev, &tv);
} }
c->flags |= client_flags; if (server_client_any_pane_redraw(c))
c->flags |= CLIENT_REDRAWWINDOW;
return; return;
} }

16
style.c
View File

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

3
tmux.1
View File

@@ -7140,6 +7140,9 @@ is the terminal alternate character set.
Align text to the left, centre or right of the available space if appropriate. Align text to the left, centre or right of the available space if appropriate.
.It Ic fill=colour .It Ic fill=colour
Fill the available space with a background colour if appropriate. 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 .It Ic width=N
Set the width of the styled area. Set the width of the styled area.
.Ar N .Ar N

9
tmux.h
View File

@@ -955,6 +955,7 @@ enum style_default_type {
struct style { struct style {
struct grid_cell gc; struct grid_cell gc;
int ignore; int ignore;
int dim;
int fill; int fill;
enum style_align align; enum style_align align;
@@ -1330,6 +1331,8 @@ struct window_pane {
struct grid_cell cached_gc; struct grid_cell cached_gc;
struct grid_cell cached_active_gc; struct grid_cell cached_active_gc;
u_int cached_dim;
u_int cached_active_dim;
struct colour_palette palette; struct colour_palette palette;
enum client_theme last_theme; enum client_theme last_theme;
struct style_line_entry border_status_line; struct style_line_entry border_status_line;
@@ -1671,6 +1674,7 @@ LIST_HEAD(tty_terms, tty_term);
struct tty_style_ctx { struct tty_style_ctx {
const struct grid_cell *defaults; const struct grid_cell *defaults;
struct colour_palette *palette; struct colour_palette *palette;
u_int dim;
struct hyperlinks *hyperlinks; struct hyperlinks *hyperlinks;
}; };
@@ -2773,7 +2777,7 @@ void tty_cmd_sixelimage(struct tty *, const struct tty_ctx *);
void tty_draw_images(struct client *, struct window_pane *, struct screen *); void tty_draw_images(struct client *, struct window_pane *, struct screen *);
#endif #endif
void tty_cmd_syncstart(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 */ /* tty-term.c */
extern struct tty_terms tty_terms; extern struct tty_terms tty_terms;
@@ -3210,6 +3214,7 @@ int colour_find_rgb(u_char, u_char, u_char);
int colour_join_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 *); void colour_split_rgb(int, u_char *, u_char *, u_char *);
int colour_force_rgb(int); int colour_force_rgb(int);
int colour_dim(int, u_int);
const char *colour_tostring(int); const char *colour_tostring(int);
enum client_theme colour_totheme(int); enum client_theme colour_totheme(int);
int colour_fromstring(const char *); int colour_fromstring(const char *);
@@ -3878,7 +3883,7 @@ int popup_modify(struct client *, const char *, const char *,
int style_parse(struct style *,const struct grid_cell *, int style_parse(struct style *,const struct grid_cell *,
const char *); const char *);
const char *style_tostring(struct style *); 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 *); const char *, struct format_tree *);
void style_apply(struct grid_cell *, struct options *, void style_apply(struct grid_cell *, struct options *,
const char *, struct format_tree *); const char *, struct format_tree *);

58
tty.c
View File

@@ -85,7 +85,7 @@ static void tty_write_one(void (*)(struct tty *, const struct tty_ctx *),
#define TTY_REQUEST_LIMIT 30 #define TTY_REQUEST_LIMIT 30
static struct tty_style_ctx tty_default_style_ctx = { static struct tty_style_ctx tty_default_style_ctx = {
&grid_default_cell, NULL, NULL &grid_default_cell, NULL, 0, NULL
}; };
void void
@@ -2730,16 +2730,39 @@ tty_hyperlink(struct tty *tty, const struct grid_cell *gc,
tty_putcode_ss(tty, TTYC_HLS, id, uri); 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 void
tty_attributes(struct tty *tty, const struct grid_cell *gc, tty_attributes(struct tty *tty, const struct grid_cell *gc,
const struct tty_style_ctx *style_ctx) const struct tty_style_ctx *style_ctx)
{ {
struct grid_cell *tc = &tty->cell, gc2; struct grid_cell *tc = &tty->cell, gc2;
struct colour_palette *palette;
int changed; int changed;
/* Use default style if not given. */ /* Use default style if not given. */
if (style_ctx == NULL) if (style_ctx == NULL)
style_ctx = &tty_default_style_ctx; style_ctx = &tty_default_style_ctx;
palette = style_ctx->palette;
/* Copy cell and update default colours. */ /* Copy cell and update default colours. */
memcpy(&gc2, gc, sizeof gc2); memcpy(&gc2, gc, sizeof gc2);
@@ -2748,6 +2771,24 @@ tty_attributes(struct tty *tty, const struct grid_cell *gc,
gc2.fg = style_ctx->defaults->fg; gc2.fg = style_ctx->defaults->fg;
if (gc2.bg == 8) if (gc2.bg == 8)
gc2.bg = style_ctx->defaults->bg; 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. */ /* Ignore cell if it is the same as the last one. */
@@ -2774,9 +2815,9 @@ tty_attributes(struct tty *tty, const struct grid_cell *gc,
} }
/* Fix up the colours if necessary. */ /* Fix up the colours if necessary. */
tty_check_fg(tty, style_ctx->palette, &gc2); tty_check_fg(tty, palette, &gc2);
tty_check_bg(tty, style_ctx->palette, &gc2); tty_check_bg(tty, palette, &gc2);
tty_check_us(tty, style_ctx->palette, &gc2); tty_check_us(tty, palette, &gc2);
/* /*
* If any bits are being cleared or the underline colour is now default, * If any bits are being cleared or the underline colour is now default,
@@ -3209,7 +3250,7 @@ tty_style_changed(struct window_pane *wp)
} }
void 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) if (wp->flags & PANE_STYLECHANGED)
tty_style_changed (wp); tty_style_changed (wp);
@@ -3223,6 +3264,13 @@ tty_default_colours(struct grid_cell *gc, struct window_pane *wp)
gc->bg = wp->cached_active_gc.bg; gc->bg = wp->cached_active_gc.bg;
else else
gc->bg = wp->cached_gc.bg; 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 void

View File

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

View File

@@ -105,6 +105,18 @@ xstrndup(const char *str, size_t maxlen)
return cp; return cp;
} }
char *
xmemdup(const void *ptr, size_t len)
{
char *cp;
cp = xmalloc(len + 1);
if (len != 0)
memcpy(cp, ptr, len);
cp[len] = '\0';
return cp;
}
int int
xasprintf(char **ret, const char *fmt, ...) xasprintf(char **ret, const char *fmt, ...)
{ {

View File

@@ -30,6 +30,7 @@ void *xreallocarray(void *, size_t, size_t);
void *xrecallocarray(void *, size_t, size_t, size_t); void *xrecallocarray(void *, size_t, size_t, size_t);
char *xstrdup(const char *); char *xstrdup(const char *);
char *xstrndup(const char *, size_t); char *xstrndup(const char *, size_t);
char *xmemdup(const void *, size_t);
int xasprintf(char **, const char *, ...) int xasprintf(char **, const char *, ...)
__attribute__((__format__ (printf, 2, 3))) __attribute__((__format__ (printf, 2, 3)))
__attribute__((__nonnull__ (2))); __attribute__((__nonnull__ (2)));