Merge branch 'obsd-master'

This commit is contained in:
Thomas Adam 2024-11-15 16:01:11 +00:00
commit be594ff8a4
10 changed files with 190 additions and 66 deletions

View File

@ -291,7 +291,7 @@ layout_fix_panes(struct window *w, struct window_pane *skip)
{
struct window_pane *wp;
struct layout_cell *lc;
int status, scrollbars, sb_pos;
int status, scrollbars, sb_pos, sb_w, sb_pad;
u_int sx, sy;
status = options_get_number(w->options, "pane-border-status");
@ -314,11 +314,26 @@ layout_fix_panes(struct window *w, struct window_pane *skip)
}
if (window_pane_show_scrollbar(wp, scrollbars)) {
sb_w = wp->scrollbar_style.width;
sb_pad = wp->scrollbar_style.pad;
if (sb_w < 1)
sb_w = 1;
if (sb_pad < 0)
sb_pad = 0;
if (sb_pos == PANE_SCROLLBARS_LEFT) {
sx = sx - PANE_SCROLLBARS_WIDTH;
wp->xoff = wp->xoff + PANE_SCROLLBARS_WIDTH;
if ((int)sx - sb_w < PANE_MINIMUM) {
wp->xoff = wp->xoff +
(int)sx - PANE_MINIMUM;
sx = PANE_MINIMUM;
} else {
sx = sx - sb_w - sb_pad;
wp->xoff = wp->xoff + sb_w + sb_pad;
}
} else /* sb_pos == PANE_SCROLLBARS_RIGHT */
sx = sx - PANE_SCROLLBARS_WIDTH;
if ((int)sx - sb_w - sb_pad < PANE_MINIMUM)
sx = PANE_MINIMUM;
else
sx = sx - sb_w - sb_pad;
wp->flags |= PANE_REDRAWSCROLLBAR;
}
@ -353,6 +368,7 @@ layout_resize_check(struct window *w, struct layout_cell *lc,
enum layout_type type)
{
struct layout_cell *lcchild;
struct style *sb_style = &w->active->scrollbar_style;
u_int available, minimum;
int status, scrollbars;
@ -364,7 +380,8 @@ layout_resize_check(struct window *w, struct layout_cell *lc,
if (type == LAYOUT_LEFTRIGHT) {
available = lc->sx;
if (scrollbars)
minimum = PANE_MINIMUM + PANE_SCROLLBARS_WIDTH;
minimum = PANE_MINIMUM + sb_style->width +
sb_style->pad;
else
minimum = PANE_MINIMUM;
} else {
@ -891,11 +908,12 @@ struct layout_cell *
layout_split_pane(struct window_pane *wp, enum layout_type type, int size,
int flags)
{
struct layout_cell *lc, *lcparent, *lcnew, *lc1, *lc2;
u_int sx, sy, xoff, yoff, size1, size2, minimum;
u_int new_size, saved_size, resize_first = 0;
int full_size = (flags & SPAWN_FULLSIZE), status;
int scrollbars;
struct layout_cell *lc, *lcparent, *lcnew, *lc1, *lc2;
struct style *sb_style = &wp->scrollbar_style;
u_int sx, sy, xoff, yoff, size1, size2, minimum;
u_int new_size, saved_size, resize_first = 0;
int full_size = (flags & SPAWN_FULLSIZE), status;
int scrollbars;
/*
* If full_size is specified, add a new cell at the top of the window
@ -917,9 +935,10 @@ layout_split_pane(struct window_pane *wp, enum layout_type type, int size,
/* Check there is enough space for the two new panes. */
switch (type) {
case LAYOUT_LEFTRIGHT:
if (scrollbars)
minimum = PANE_MINIMUM * 2 + PANE_SCROLLBARS_WIDTH;
else
if (scrollbars) {
minimum = PANE_MINIMUM * 2 + sb_style->width +
sb_style->pad;
} else
minimum = PANE_MINIMUM * 2 + 1;
if (sx < minimum)
return (NULL);
@ -1081,6 +1100,7 @@ int
layout_spread_cell(struct window *w, struct layout_cell *parent)
{
struct layout_cell *lc;
struct style *sb_style = &w->active->scrollbar_style;
u_int number, each, size, this;
int change, changed, status, scrollbars;
@ -1094,7 +1114,7 @@ layout_spread_cell(struct window *w, struct layout_cell *parent)
if (parent->type == LAYOUT_LEFTRIGHT) {
if (scrollbars)
size = parent->sx - PANE_SCROLLBARS_WIDTH;
size = parent->sx - sb_style->width + sb_style->pad;
else
size = parent->sx;
}

View File

@ -1186,7 +1186,7 @@ const struct options_table_entry options_table[] = {
{ .name = "pane-scrollbars-style",
.type = OPTIONS_TABLE_STRING,
.scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE,
.default_str = "bg=black,fg=white",
.default_str = "bg=black,fg=white,width=1,pad=0",
.flags = OPTIONS_TABLE_IS_STYLE,
.separator = ",",
.text = "Style of the pane scrollbar."

View File

@ -1177,6 +1177,15 @@ options_push_changes(const char *name)
RB_FOREACH(w, windows, &windows)
layout_fix_panes(w, NULL);
}
if (strcmp(name, "pane-scrollbars-style") == 0) {
RB_FOREACH(wp, window_pane_tree, &all_window_panes) {
style_set_scrollbar_style_from_option(
&wp->scrollbar_style, wp->options);
}
RB_FOREACH(w, windows, &windows)
layout_fix_panes(w, NULL);
}
if (strcmp(name, "input-buffer-size") == 0)
input_set_buffer_size(options_get_number(global_options, name));
RB_FOREACH(s, sessions, &sessions)

View File

@ -138,7 +138,7 @@ screen_redraw_pane_border(struct screen_redraw_ctx *ctx, struct window_pane *wp,
/* Are scrollbars enabled? */
if (window_pane_show_scrollbar(wp, pane_scrollbars))
sb_w = PANE_SCROLLBARS_WIDTH;
sb_w = wp->scrollbar_style.width + wp->scrollbar_style.pad;
/*
* Left/right borders. The wp->sy / 2 test is to colour only half the
@ -171,7 +171,7 @@ screen_redraw_pane_border(struct screen_redraw_ctx *ctx, struct window_pane *wp,
} else {
if (sb_pos == PANE_SCROLLBARS_LEFT) {
if ((wp->xoff - sb_w == 0 || px >= wp->xoff - sb_w) &&
(px <= ex || (sb_w != 0 && px - 1 == ex))) {
(px <= ex || (sb_w != 0 && px < ex + sb_w))) {
if (wp->yoff != 0 && py == wp->yoff - 1)
return (SCREEN_REDRAW_BORDER_TOP);
if (py == ey)
@ -179,7 +179,7 @@ screen_redraw_pane_border(struct screen_redraw_ctx *ctx, struct window_pane *wp,
}
} else { /* sb_pos == PANE_SCROLLBARS_RIGHT */
if ((wp->xoff == 0 || px >= wp->xoff) &&
(px <= ex || (sb_w != 0 && px - 1 == ex))) {
(px <= ex || (sb_w != 0 && px < ex + sb_w))) {
if (wp->yoff != 0 && py == wp->yoff - 1)
return (SCREEN_REDRAW_BORDER_TOP);
if (py == ey)
@ -324,7 +324,7 @@ screen_redraw_check_cell(struct screen_redraw_ctx *ctx, u_int px, u_int py,
int border, pane_scrollbars = ctx->pane_scrollbars;
u_int right, line;
int sb_pos = ctx->pane_scrollbars_pos;
int sb_w = PANE_SCROLLBARS_WIDTH;
int sb_w;
*wpp = NULL;
@ -374,6 +374,8 @@ screen_redraw_check_cell(struct screen_redraw_ctx *ctx, u_int px, u_int py,
* pane is at the top then py == 0 to sy; if the pane
* is not at the top, then yoff to yoff + sy.
*/
sb_w = wp->scrollbar_style.width +
wp->scrollbar_style.pad;
if ((pane_status && py != line) ||
(wp->yoff == 0 && py < wp->sy) ||
(py >= wp->yoff && py < wp->yoff + wp->sy)) {
@ -948,7 +950,9 @@ screen_redraw_draw_pane_scrollbar(struct screen_redraw_ctx *ctx,
double percent_view;
u_int sb = ctx->pane_scrollbars, total_height, sb_h = wp->sy;
u_int sb_pos = ctx->pane_scrollbars_pos, slider_h, slider_y;
u_int sb_w = PANE_SCROLLBARS_WIDTH, cm_y, cm_size;
int sb_w = wp->scrollbar_style.width;
int sb_pad = wp->scrollbar_style.pad;
int cm_y, cm_size, xoff = wp->xoff, ox = ctx->ox;
int sb_x, sb_y = (int)(wp->yoff - ctx->oy); /* sb top */
if (window_pane_mode(wp) == WINDOW_PANE_NO_MODE) {
@ -971,9 +975,9 @@ screen_redraw_draw_pane_scrollbar(struct screen_redraw_ctx *ctx,
}
if (sb_pos == PANE_SCROLLBARS_LEFT)
sb_x = (int)wp->xoff - sb_w - ctx->ox;
sb_x = xoff - sb_w - sb_pad - ox;
else
sb_x = (int)wp->xoff + wp->sx - ctx->ox;
sb_x = xoff + wp->sx - ox;
if (slider_h < 1)
slider_h = 1;
@ -994,39 +998,42 @@ screen_redraw_draw_scrollbar(struct screen_redraw_ctx *ctx,
u_int slider_h, u_int slider_y)
{
struct client *c = ctx->c;
struct window *w = wp->window;
struct tty *tty = &c->tty;
struct grid_cell gc, slgc, *gcp;
u_int i, j, sb_w = PANE_SCROLLBARS_WIDTH;
u_int pad_col = 0;
struct style *sb_style = &wp->scrollbar_style;
u_int i, j, imax, jmax;
u_int sb_w = sb_style->width, sb_pad = sb_style->pad;
int px, py, ox = ctx->ox, oy = ctx->oy;
int sb_pad = PANE_SCROLLBARS_PADDING, sx = ctx->sx;
int sy = ctx->sy, xoff = wp->xoff, yoff = wp->yoff;
/* Set up default style. */
style_apply(&gc, w->options, "pane-scrollbars-style", NULL);
utf8_set(&gc.data, ' ');
int sx = ctx->sx, sy = ctx->sy, xoff = wp->xoff;
int yoff = wp->yoff;
/* Set up style for slider. */
gc = sb_style->gc;
memcpy(&slgc, &gc, sizeof slgc);
slgc.fg = gc.bg;
slgc.bg = gc.fg;
if (sb_pad != 0) {
if (sb_pos == PANE_SCROLLBARS_RIGHT)
pad_col = 0;
else
pad_col = sb_w - 1;
}
imax = sb_w + sb_pad;
if ((int)imax + sb_x > sx)
imax = sx - sb_x;
jmax = sb_h;
if ((int)jmax + sb_y > sy)
jmax = sy - sb_y;
for (i = 0; i < sb_w; i++) {
for (j = 0; j < sb_h; j++) {
for (j = 0; j < jmax; j++) {
py = sb_y + j;
for (i = 0; i < imax; i++) {
px = sb_x + i;
py = sb_y + j;
if (px < xoff - ox - 1 || px >= sx || px < 0 ||
py < yoff - oy - 1 || py >= sy || py < 0)
if (px < xoff - ox - (int)sb_w - (int)sb_pad ||
px >= sx || px < 0 ||
py < yoff - oy - 1 ||
py >= sy || py < 0)
continue;
tty_cursor(tty, px, py);
if (sb_pad && i == pad_col) {
if ((sb_pos == PANE_SCROLLBARS_LEFT &&
i >= sb_w && i < sb_w + sb_pad) ||
(sb_pos == PANE_SCROLLBARS_RIGHT &&
i < sb_pad)) {
tty_cell(tty, &grid_default_cell,
&grid_default_cell, NULL, NULL);
} else {

View File

@ -577,7 +577,7 @@ server_client_check_mouse(struct client *c, struct key_event *event)
struct window_pane *wp, *fwp;
u_int x, y, b, sx, sy, px, py, line = 0, sb_pos;
u_int sl_top, sl_bottom, sl_mpos = 0;
int ignore = 0, sb, sb_w, pane_status;
int ignore = 0, sb, sb_w, sb_pad, pane_status;
key_code key;
struct timeval tv;
struct style_range *sr;
@ -779,10 +779,15 @@ have_event:
/* Try the scrollbar next to a pane. */
sb = options_get_number(wo, "pane-scrollbars");
if (window_pane_show_scrollbar(wp, sb))
sb_w = PANE_SCROLLBARS_WIDTH;
else
sb_pos = options_get_number(wo,
"pane-scrollbars-position");
if (window_pane_show_scrollbar(wp, sb)) {
sb_w = wp->scrollbar_style.width;
sb_pad = wp->scrollbar_style.pad;
} else {
sb_w = 0;
sb_pad = 0;
}
pane_status = options_get_number(wo,
"pane-border-status");
if (pane_status == PANE_STATUS_TOP)
@ -791,8 +796,9 @@ have_event:
line = wp->yoff + wp->sy;
/*
* Check if py could lie within a scrollbar. If the
* pane is at the top, then py is 0; if not then the
* Check if py could lie within a scrollbar
* (but not within the padding). If the pane is
* at the top, then py is 0; if not then the
* top, then yoff to yoff + sy.
*/
if ((pane_status != PANE_STATUS_OFF && py != line) ||
@ -801,11 +807,11 @@ have_event:
sb_pos = options_get_number(wo,
"pane-scrollbars-position");
if ((sb_pos == PANE_SCROLLBARS_RIGHT &&
(px >= wp->xoff + wp->sx &&
px < wp->xoff + wp->sx + sb_w)) ||
(px >= wp->xoff + wp->sx + sb_pad &&
px < wp->xoff + wp->sx + sb_pad + sb_w)) ||
(sb_pos == PANE_SCROLLBARS_LEFT &&
(px >= wp->xoff - sb_w &&
px < wp->xoff))) {
(px >= wp->xoff - sb_pad - sb_w &&
px < wp->xoff - sb_pad))) {
sl_top = wp->yoff + wp->sb_slider_y;
sl_bottom = (wp->yoff +
wp->sb_slider_y +
@ -3678,6 +3684,8 @@ server_client_set_flags(struct client *c, const char *flags)
flag = CLIENT_IGNORESIZE;
else if (strcmp(next, "active-pane") == 0)
flag = CLIENT_ACTIVEPANE;
else if (strcmp(next, "no-detach-on-destroy") == 0)
flag = CLIENT_NO_DETACH_ON_DESTROY;
if (flag == 0)
continue;
@ -3711,6 +3719,8 @@ server_client_get_flags(struct client *c)
strlcat(s, "control-mode,", sizeof s);
if (c->flags & CLIENT_IGNORESIZE)
strlcat(s, "ignore-size,", sizeof s);
if (c->flags & CLIENT_NO_DETACH_ON_DESTROY)
strlcat(s, "no-detach-on-destroy,", sizeof s);
if (c->flags & CLIENT_CONTROL_NOOUTPUT)
strlcat(s, "no-output,", sizeof s);
if (c->flags & CLIENT_CONTROL_WAITEXIT)

View File

@ -426,7 +426,7 @@ void
server_destroy_session(struct session *s)
{
struct client *c;
struct session *s_new = NULL;
struct session *s_new = NULL, *cs_new, *use_s;
int detach_on_destroy;
detach_on_destroy = options_get_number(s->options, "detach-on-destroy");
@ -438,15 +438,26 @@ server_destroy_session(struct session *s)
s_new = session_previous_session(s);
else if (detach_on_destroy == 4)
s_new = session_next_session(s);
if (s_new == s)
s_new = NULL;
/*
* If no suitable new session was found above, then look for any
* session as an alternative in case a client needs it.
*/
if (s_new == NULL &&
(detach_on_destroy == 1 || detach_on_destroy == 2))
cs_new = server_find_session(s, server_newer_session);
TAILQ_FOREACH(c, &clients, entry) {
if (c->session != s)
continue;
use_s = s_new;
if (use_s == NULL && (c->flags & CLIENT_NO_DETACH_ON_DESTROY))
use_s = cs_new;
c->session = NULL;
c->last_session = NULL;
server_client_set_session(c, s_new);
if (s_new == NULL)
server_client_set_session(c, use_s);
if (use_s == NULL)
c->flags |= CLIENT_EXIT;
}
recalculate_sizes();

44
style.c
View File

@ -39,6 +39,8 @@ static struct style style_default = {
STYLE_RANGE_NONE, 0, "",
STYLE_WIDTH_DEFAULT, STYLE_PAD_DEFAULT,
STYLE_DEFAULT_BASE
};
@ -216,6 +218,16 @@ style_parse(struct style *sy, const struct grid_cell *base, const char *in)
if ((value = attributes_fromstring(tmp + 2)) == -1)
goto error;
sy->gc.attr &= ~value;
} else if (end > 6 && strncasecmp(tmp, "width=", 6) == 0) {
n = strtonum(tmp + 6, 0, UINT_MAX, &errstr);
if (errstr != NULL)
goto error;
sy->width = (int)n;
} else if (end > 4 && strncasecmp(tmp, "pad=", 4) == 0) {
n = strtonum(tmp + 4, 0, UINT_MAX, &errstr);
if (errstr != NULL)
goto error;
sy->pad = (int)n;
} else {
if ((value = attributes_fromstring(tmp)) == -1)
goto error;
@ -326,7 +338,16 @@ style_tostring(struct style *sy)
attributes_tostring(gc->attr));
comma = ",";
}
if (sy->width >= 0) {
xsnprintf(s + off, sizeof s - off, "%swidth=%u", comma,
sy->width);
comma = ",";
}
if (sy->pad >= 0) {
xsnprintf(s + off, sizeof s - off, "%spad=%u", comma,
sy->pad);
comma = ",";
}
if (*s == '\0')
return ("default");
return (s);
@ -381,3 +402,24 @@ style_copy(struct style *dst, struct style *src)
{
memcpy(dst, src, sizeof *dst);
}
void
style_set_scrollbar_style_from_option(struct style *sb_style, struct options *oo)
{
struct style *sy;
sy = options_string_to_style(oo, "pane-scrollbars-style", NULL);
if (sy == NULL) {
style_set(sb_style, &grid_default_cell);
sb_style->width = PANE_SCROLLBARS_DEFAULT_WIDTH;
sb_style->pad = PANE_SCROLLBARS_DEFAULT_PADDING;
utf8_set(&sb_style->gc.data, PANE_SCROLLBARS_CHARACTER);
} else {
style_copy(sb_style, sy);
if (sb_style->width < 1)
sb_style->width = PANE_SCROLLBARS_DEFAULT_WIDTH;
if (sb_style->pad < 0)
sb_style->pad = PANE_SCROLLBARS_DEFAULT_PADDING;
utf8_set(&sb_style->gc.data, PANE_SCROLLBARS_CHARACTER);
}
}

10
tmux.1
View File

@ -1068,6 +1068,9 @@ The flags are:
the client has an independent active pane
.It ignore-size
the client does not affect the size of other clients
.It no-detach-on-destroy
do not detach the client when the session it is attached to is destroyed if
there are any other sessions
.It no-output
the client does not receive pane output in control mode
.It pause-after=seconds
@ -5073,7 +5076,12 @@ see the
section.
The foreground colour is used for the slider, the background for the rest of the
scrollbar.
Attributes are ignored.
The
.Ar width
attribute sets the width of the scrollbar and the
.Ar pad
attribute the padding between the scrollbar and the pane.
Other attributes are ignored.
.Pp
.It Xo Ic pane-scrollbars-position
.Op Ic left | right

19
tmux.h
View File

@ -872,6 +872,10 @@ struct style_range {
};
TAILQ_HEAD(style_ranges, style_range);
/* Default style width and pad. */
#define STYLE_WIDTH_DEFAULT -1
#define STYLE_PAD_DEFAULT -1
/* Style default. */
enum style_default_type {
STYLE_DEFAULT_BASE,
@ -892,6 +896,9 @@ struct style {
u_int range_argument;
char range_string[16];
int width;
int pad;
enum style_default_type default_type;
};
@ -1195,6 +1202,8 @@ struct window_pane {
int control_bg;
int control_fg;
struct style scrollbar_style;
TAILQ_ENTRY(window_pane) entry; /* link in list of all panes */
TAILQ_ENTRY(window_pane) sentry; /* link in list of last visited */
RB_ENTRY(window_pane) tree_entry;
@ -1299,9 +1308,10 @@ TAILQ_HEAD(winlink_stack, winlink);
#define PANE_SCROLLBARS_RIGHT 0
#define PANE_SCROLLBARS_LEFT 1
/* Pane scrollbars width and padding. */
#define PANE_SCROLLBARS_WIDTH 1
#define PANE_SCROLLBARS_PADDING 0
/* Pane scrollbars width, padding and fill character. */
#define PANE_SCROLLBARS_DEFAULT_PADDING 0
#define PANE_SCROLLBARS_DEFAULT_WIDTH 1
#define PANE_SCROLLBARS_CHARACTER ' '
/* True if screen in alternate screen. */
#define SCREEN_IS_ALTERNATE(s) ((s)->saved_grid != NULL)
@ -1948,6 +1958,7 @@ struct client {
#define CLIENT_BRACKETPASTING 0x1000000000ULL
#define CLIENT_ASSUMEPASTING 0x2000000000ULL
#define CLIENT_REDRAWSCROLLBARS 0x4000000000ULL
#define CLIENT_NO_DETACH_ON_DESTROY 0x8000000000ULL
#define CLIENT_ALLREDRAWFLAGS \
(CLIENT_REDRAWWINDOW| \
CLIENT_REDRAWSTATUS| \
@ -3522,6 +3533,8 @@ void style_apply(struct grid_cell *, struct options *,
const char *, struct format_tree *);
void style_set(struct style *, const struct grid_cell *);
void style_copy(struct style *, struct style *);
void style_set_scrollbar_style_from_option(struct style *,
struct options *);
/* spawn.c */
struct winlink *spawn_window(struct spawn_context *, char **);

View File

@ -603,9 +603,10 @@ window_get_active_at(struct window *w, u_int x, u_int y)
if (pane_scrollbars == PANE_SCROLLBARS_ALWAYS ||
(pane_scrollbars == PANE_SCROLLBARS_MODAL &&
window_pane_mode(wp) != WINDOW_PANE_NO_MODE))
sb_w = PANE_SCROLLBARS_WIDTH;
else
window_pane_mode(wp) != WINDOW_PANE_NO_MODE)) {
sb_w = wp->scrollbar_style.width +
wp->scrollbar_style.pad;
} else
sb_w = 0;
if (sb_pos == PANE_SCROLLBARS_LEFT) {
@ -968,6 +969,9 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit)
wp->control_bg = -1;
wp->control_fg = -1;
style_set_scrollbar_style_from_option(&wp->scrollbar_style,
wp->options);
colour_palette_init(&wp->palette);
colour_palette_from_option(&wp->palette, wp->options);