Cache scrollbar options in window to avoid a slow lookup when working

out visible ranges.
This commit is contained in:
nicm
2026-06-29 19:03:34 +00:00
parent 65a032b205
commit e06207c914
8 changed files with 73 additions and 95 deletions

View File

@@ -235,7 +235,7 @@ cmd_resize_pane_mouse_resize_move_floating(struct client *c,
struct window_pane *wp;
struct layout_cell *lc;
int y, ly, x, lx, sx, sy, new_sx, new_sy;
int scrollbars, sb_pos, left, right;
int left, right;
int new_xoff, new_yoff, resizes = 0;
wp = cmd_mouse_pane(m, NULL, &wl);
@@ -247,15 +247,13 @@ cmd_resize_pane_mouse_resize_move_floating(struct client *c,
lc = wp->layout_cell;
sx = wp->sx;
sy = wp->sy;
scrollbars = options_get_number(w->options, "pane-scrollbars");
sb_pos = options_get_number(w->options, "pane-scrollbars-position");
left = wp->xoff - 1;
right = wp->xoff + sx;
if (window_pane_scrollbar_reserve(wp, scrollbars) &&
sb_pos == PANE_SCROLLBARS_LEFT) {
if (window_pane_scrollbar_reserve(wp) &&
w->sb_pos == PANE_SCROLLBARS_LEFT) {
left -= wp->scrollbar_style.width + wp->scrollbar_style.pad;
} else if (window_pane_scrollbar_reserve(wp, scrollbars) &&
sb_pos == PANE_SCROLLBARS_RIGHT) {
} else if (window_pane_scrollbar_reserve(wp) &&
w->sb_pos == PANE_SCROLLBARS_RIGHT) {
right += wp->scrollbar_style.width + wp->scrollbar_style.pad;
}

View File

@@ -433,13 +433,11 @@ layout_fix_panes(struct window *w, struct window_pane *skip)
{
struct window_pane *wp;
struct layout_cell *lc;
int status, scrollbars, sb_pos, sb_w, sb_pad;
int status, sb_w, sb_pad;
int old_xoff, old_yoff, changed = 0;
u_int sx, sy, old_sx, old_sy;
status = window_get_pane_status(w);
scrollbars = options_get_number(w->options, "pane-scrollbars");
sb_pos = options_get_number(w->options, "pane-scrollbars-position");
TAILQ_FOREACH(wp, &w->panes, entry) {
if ((lc = wp->layout_cell) == NULL || wp == skip)
@@ -462,14 +460,14 @@ layout_fix_panes(struct window *w, struct window_pane *skip)
sy--;
}
if (window_pane_scrollbar_reserve(wp, scrollbars)) {
if (window_pane_scrollbar_reserve(wp)) {
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) {
if (w->sb_pos == PANE_SCROLLBARS_LEFT) {
if ((int)sx - sb_w - sb_pad < PANE_MINIMUM) {
wp->xoff = wp->xoff +
(int)sx - PANE_MINIMUM;
@@ -526,16 +524,15 @@ layout_resize_check(struct window *w, struct layout_cell *lc,
struct layout_cell *lcchild;
struct style *sb_style = &w->active->scrollbar_style;
u_int available, minimum;
int status, scrollbars;
int status;
status = window_get_pane_status(w);
scrollbars = options_get_number(w->options, "pane-scrollbars");
if (lc->type == LAYOUT_WINDOWPANE) {
/* Space available in this cell only. */
if (type == LAYOUT_LEFTRIGHT) {
available = lc->sx;
if (scrollbars == PANE_SCROLLBARS_ALWAYS)
if (w->sb == PANE_SCROLLBARS_ALWAYS)
minimum = PANE_MINIMUM + sb_style->width +
sb_style->pad;
else
@@ -1253,17 +1250,16 @@ layout_split_check_space(struct window_pane *wp, struct layout_cell *lc,
{
struct style *sb_style = &wp->scrollbar_style;
u_int minimum, sx = lc->sx, sy = lc->sy;
int scrollbars, status;
int status;
if (lc->flags & LAYOUT_CELL_FLOATING)
fatalx("floating cells cannot be split");
status = window_get_pane_status(wp->window);
scrollbars = options_get_number(wp->window->options, "pane-scrollbars");
switch (type) {
case LAYOUT_LEFTRIGHT:
if (scrollbars == PANE_SCROLLBARS_ALWAYS) {
if (wp->window->sb == PANE_SCROLLBARS_ALWAYS) {
minimum = PANE_MINIMUM * 2 + sb_style->width +
sb_style->pad;
} else

View File

@@ -1286,8 +1286,13 @@ options_push_changes(const char *name)
if (strcmp(name, "pane-border-status") == 0 ||
strcmp(name, "pane-scrollbars") == 0 ||
strcmp(name, "pane-scrollbars-position") == 0) {
RB_FOREACH(w, windows, &windows)
RB_FOREACH(w, windows, &windows) {
w->sb = options_get_number(w->options,
"pane-scrollbars");
w->sb_pos = options_get_number(w->options,
"pane-scrollbars-position");
layout_fix_panes(w, NULL);
}
}
if (strcmp(name, "pane-scrollbars") == 0) {
RB_FOREACH(wp, window_pane_tree, &all_window_panes)

View File

@@ -212,8 +212,6 @@ struct redraw_build_ctx {
u_int sx;
u_int sy;
int sb;
int sbp;
int ind;
struct redraw_build_cell *cells;
@@ -285,16 +283,13 @@ redraw_set_context(struct client *c, struct redraw_build_ctx *bctx)
{
struct session *s = c->session;
struct window *w = s->curw->window;
struct options *oo = w->options;
memset(bctx, 0, sizeof *bctx);
bctx->c = c;
bctx->w = w;
redraw_get_window_offset(c, &bctx->ox, &bctx->oy, &bctx->sx, &bctx->sy);
bctx->sb = options_get_number(oo, "pane-scrollbars");
bctx->sbp = options_get_number(oo, "pane-scrollbars-position");
bctx->ind = options_get_number(oo, "pane-border-indicators");
bctx->ind = options_get_number(w->options, "pane-border-indicators");
}
/* Return a cell. */
@@ -769,8 +764,8 @@ redraw_mark_pane(struct redraw_build_ctx *bctx, struct window_pane *wp)
if (!window_pane_is_visible(wp))
return;
if (window_pane_scrollbar_visible(wp, bctx->sb)) {
overlay = window_pane_scrollbar_overlay(wp, bctx->sb);
if (window_pane_scrollbar_visible(wp)) {
overlay = window_pane_scrollbar_overlay(wp);
if (overlay) {
sb_w = wp->scrollbar_style.width +
wp->scrollbar_style.pad;
@@ -782,7 +777,7 @@ redraw_mark_pane(struct redraw_build_ctx *bctx, struct window_pane *wp)
} else
sb_w = wp->scrollbar_style.width + wp->scrollbar_style.pad;
}
if (sb_w != 0 && bctx->sbp == PANE_SCROLLBARS_LEFT)
if (sb_w != 0 && bctx->w->sb_pos == PANE_SCROLLBARS_LEFT)
sb_left = 1;
redraw_mark_pane_inside(bctx, wp);

View File

@@ -613,10 +613,9 @@ server_client_in_scrollbar_area(struct window_pane *wp, int px, int py)
{
struct window *w = wp->window;
u_int width, pad, total;
int sb, sb_pos, start, end;
int start, end;
sb = options_get_number(w->options, "pane-scrollbars");
if (!window_pane_scrollbar_overlay(wp, sb))
if (!window_pane_scrollbar_overlay(wp))
return (0);
if (py < wp->yoff || py >= wp->yoff + (int)wp->sy)
return (0);
@@ -627,8 +626,7 @@ server_client_in_scrollbar_area(struct window_pane *wp, int px, int py)
if (total == 0 || total > wp->sx)
total = wp->sx;
sb_pos = options_get_number(w->options, "pane-scrollbars-position");
if (sb_pos == PANE_SCROLLBARS_LEFT) {
if (w->sb_pos == PANE_SCROLLBARS_LEFT) {
start = wp->xoff;
end = wp->xoff + (int)total - 1;
} else {
@@ -668,17 +666,15 @@ server_client_check_mouse_in_pane(struct window_pane *wp, int px, int py,
{
struct window *w = wp->window;
struct window_pane *fwp;
int pane_status, sb, sb_pos, sb_w, sb_pad;
int pane_status, sb_w, sb_pad;
int pane_status_line, sl_top, sl_bottom;
int bdr_bottom, bdr_top, bdr_left, bdr_right;
int sb_start, sb_end, sb_overlay;
sb = options_get_number(w->options, "pane-scrollbars");
sb_pos = options_get_number(w->options, "pane-scrollbars-position");
pane_status = window_pane_get_pane_status(wp);
sb_overlay = window_pane_scrollbar_overlay(wp, sb);
sb_overlay = window_pane_scrollbar_overlay(wp);
if (window_pane_scrollbar_visible(wp, sb)) {
if (window_pane_scrollbar_visible(wp)) {
sb_w = wp->scrollbar_style.width;
sb_pad = wp->scrollbar_style.pad;
if (sb_overlay && sb_w > (int)wp->sx)
@@ -695,13 +691,13 @@ server_client_check_mouse_in_pane(struct window_pane *wp, int px, int py,
else
pane_status_line = -1; /* not used */
bdr_left = wp->xoff - 1;
if (!sb_overlay && sb_pos == PANE_SCROLLBARS_LEFT)
if (!sb_overlay && w->sb_pos == PANE_SCROLLBARS_LEFT)
bdr_left -= sb_pad + sb_w;
if (sb_overlay && sb_w != 0 &&
py >= wp->yoff && py < wp->yoff + (int)wp->sy &&
px >= wp->xoff && px < wp->xoff + (int)wp->sx) {
if (sb_pos == PANE_SCROLLBARS_LEFT) {
if (w->sb_pos == PANE_SCROLLBARS_LEFT) {
sb_start = wp->xoff;
sb_end = sb_start + sb_w - 1;
} else {
@@ -728,15 +724,15 @@ server_client_check_mouse_in_pane(struct window_pane *wp, int px, int py,
py != pane_status_line && py != wp->yoff + (int)wp->sy) ||
(wp->yoff == 0 && py < (int)wp->sy) ||
(py >= wp->yoff && py < wp->yoff + (int)wp->sy)) &&
((sb_pos == PANE_SCROLLBARS_RIGHT &&
((w->sb_pos == PANE_SCROLLBARS_RIGHT &&
px < wp->xoff + (int)wp->sx + sb_pad + sb_w) ||
(sb_pos == PANE_SCROLLBARS_LEFT &&
(w->sb_pos == PANE_SCROLLBARS_LEFT &&
px < wp->xoff + (int)wp->sx - sb_pad - sb_w))) {
/* Check if in the scrollbar. */
if ((sb_pos == PANE_SCROLLBARS_RIGHT &&
if ((w->sb_pos == PANE_SCROLLBARS_RIGHT &&
(px >= wp->xoff + (int)wp->sx + sb_pad &&
px < wp->xoff + (int)wp->sx + sb_pad + sb_w)) ||
(sb_pos == PANE_SCROLLBARS_LEFT &&
(w->sb_pos == PANE_SCROLLBARS_LEFT &&
(px >= wp->xoff - sb_pad - sb_w &&
px < wp->xoff - sb_pad))) {
/* Check where inside the scrollbar. */
@@ -770,7 +766,7 @@ server_client_check_mouse_in_pane(struct window_pane *wp, int px, int py,
if (window_pane_is_floating(fwp) &&
window_pane_get_pane_lines(fwp) == PANE_LINES_NONE)
continue;
if (window_pane_scrollbar_reserve(fwp, sb)) {
if (window_pane_scrollbar_reserve(fwp)) {
sb_w = fwp->scrollbar_style.width;
sb_pad = fwp->scrollbar_style.pad;
} else {
@@ -780,7 +776,7 @@ server_client_check_mouse_in_pane(struct window_pane *wp, int px, int py,
bdr_top = fwp->yoff - 1;
bdr_bottom = fwp->yoff + fwp->sy;
bdr_left = fwp->xoff - 1;
if (sb_pos == PANE_SCROLLBARS_LEFT) {
if (w->sb_pos == PANE_SCROLLBARS_LEFT) {
bdr_left -= sb_pad + sb_w;
bdr_right = fwp->xoff + fwp->sx;
} else {
@@ -2001,7 +1997,7 @@ server_client_reset_state(struct client *c)
struct window_pane *wp = server_client_get_pane(c), *loop;
struct screen *s = NULL;
struct options *oo = c->session->options;
int mode = 0, cursor, flags, pane_mode = 0, sb;
int mode = 0, cursor, flags, pane_mode = 0;
u_int cx = 0, cy = 0, ox, oy, sx, sy, prompt = 0;
u_int sb_w;
struct visible_ranges *r;
@@ -2061,9 +2057,8 @@ server_client_reset_state(struct client *c)
if (sb_w > wp->sx)
sb_w = wp->sx;
if (sb_w != 0 &&
options_get_number(w->options,
"pane-scrollbars-position") ==
PANE_SCROLLBARS_LEFT) {
w->sb_pos ==
PANE_SCROLLBARS_LEFT) {
if (s->cx < sb_w)
cursor = 0;
} else if (sb_w != 0 &&
@@ -2098,11 +2093,10 @@ server_client_reset_state(struct client *c)
mode |= MODE_MOUSE_ALL;
}
}
sb = options_get_number(w->options, "pane-scrollbars");
if (options_get_number(oo, "focus-follows-mouse") ||
sb == PANE_SCROLLBARS_MODAL ||
sb == PANE_SCROLLBARS_AUTOHIDE)
mode |= MODE_MOUSE_ALL;
if (options_get_number(oo, "focus-follows-mouse") ||
w->sb == PANE_SCROLLBARS_MODAL ||
w->sb == PANE_SCROLLBARS_AUTOHIDE)
mode |= MODE_MOUSE_ALL;
else if (~mode & MODE_MOUSE_ALL)
mode |= MODE_MOUSE_BUTTON;
}

11
tmux.h
View File

@@ -1380,6 +1380,9 @@ struct window {
u_int last_new_pane_x;
u_int last_new_pane_y;
int sb;
int sb_pos;
struct utf8_data *fill_character;
int flags;
#define WINDOW_BELL 0x1
@@ -3580,10 +3583,10 @@ void window_pane_update_used_data(struct window_pane *,
void window_set_fill_character(struct window *);
void window_pane_default_cursor(struct window_pane *);
int window_pane_mode(struct window_pane *);
int window_pane_show_scrollbar(struct window_pane *, int);
int window_pane_scrollbar_reserve(struct window_pane *, int);
int window_pane_scrollbar_visible(struct window_pane *, int);
int window_pane_scrollbar_overlay(struct window_pane *, int);
int window_pane_show_scrollbar(struct window_pane *);
int window_pane_scrollbar_reserve(struct window_pane *);
int window_pane_scrollbar_visible(struct window_pane *);
int window_pane_scrollbar_overlay(struct window_pane *);
int window_pane_scrollbar_overlay_visible(struct window_pane *);
void window_pane_scrollbar_show(struct window_pane *, int);
void window_pane_scrollbar_hide(struct window_pane *);

View File

@@ -55,7 +55,7 @@ window_visible_ranges(struct window_pane *base_wp, int px, int py, u_int width,
struct window *w;
struct visible_range *ri;
static struct visible_ranges sr = { NULL, 0, 0 };
int found_self, sb, sb_w, sb_pos;
int found_self, sb_w, sb_pos;
int lb, rb, tb, bb, sx, ex, no_border;
u_int i, s;
@@ -95,8 +95,6 @@ window_visible_ranges(struct window_pane *base_wp, int px, int py, u_int width,
r->used = 1;
}
sb = options_get_number(w->options, "pane-scrollbars");
sb_pos = options_get_number(w->options, "pane-scrollbars-position");
found_self = 0;
TAILQ_FOREACH_REVERSE(wp, &w->z_index, window_panes_zindex, zentry) {
@@ -126,7 +124,9 @@ window_visible_ranges(struct window_pane *base_wp, int px, int py, u_int width,
continue;
sb_w = wp->scrollbar_style.width + wp->scrollbar_style.pad;
if (!window_pane_scrollbar_reserve(wp, sb))
if (window_pane_scrollbar_reserve(wp))
sb_pos = w->sb_pos;
else
sb_w = sb_pos = 0;
for (i = 0; i < r->used; i++) {

View File

@@ -1165,20 +1165,15 @@ window_pane_scrollbar_timer(__unused int fd, __unused short events, void *arg)
static int
window_pane_scrollbar_auto_hide(struct window_pane *wp)
{
int sb;
sb = options_get_number(wp->window->options, "pane-scrollbars");
return (sb == PANE_SCROLLBARS_MODAL || sb == PANE_SCROLLBARS_AUTOHIDE);
return (wp->window->sb == PANE_SCROLLBARS_MODAL ||
wp->window->sb == PANE_SCROLLBARS_AUTOHIDE);
}
int
window_pane_scrollbar_overlay_visible(struct window_pane *wp)
{
int sb;
sb = options_get_number(wp->window->options, "pane-scrollbars");
return (window_pane_scrollbar_overlay(wp, sb) &&
window_pane_scrollbar_visible(wp, sb));
return (window_pane_scrollbar_overlay(wp) &&
window_pane_scrollbar_visible(wp));
}
void
@@ -1769,17 +1764,13 @@ window_pane_full_size_offset(struct window_pane *wp, int *xoff, int *yoff,
u_int *sx, u_int *sy)
{
struct window *w = wp->window;
int pane_scrollbars;
u_int sb_w, sb_pos;
u_int sb_w;
pane_scrollbars = options_get_number(w->options, "pane-scrollbars");
sb_pos = options_get_number(w->options, "pane-scrollbars-position");
if (window_pane_scrollbar_reserve(wp, pane_scrollbars))
if (window_pane_scrollbar_reserve(wp))
sb_w = wp->scrollbar_style.width + wp->scrollbar_style.pad;
else
sb_w = 0;
if (sb_pos == PANE_SCROLLBARS_LEFT) {
if (w->sb_pos == PANE_SCROLLBARS_LEFT) {
*xoff = wp->xoff - sb_w;
*sx = wp->sx + sb_w;
} else { /* sb_pos == PANE_SCROLLBARS_RIGHT */
@@ -2195,40 +2186,39 @@ window_pane_mode(struct window_pane *wp)
return (WINDOW_PANE_NO_MODE);
}
/* Return 1 if scrollbar is or should be displayed. */
int
window_pane_show_scrollbar(struct window_pane *wp, int sb_option)
window_pane_show_scrollbar(struct window_pane *wp)
{
if (SCREEN_IS_ALTERNATE(&wp->base))
return (0);
if (sb_option == PANE_SCROLLBARS_ALWAYS ||
sb_option == PANE_SCROLLBARS_AUTOHIDE ||
(sb_option == PANE_SCROLLBARS_MODAL &&
if (wp->window->sb == PANE_SCROLLBARS_ALWAYS ||
wp->window->sb == PANE_SCROLLBARS_AUTOHIDE ||
(wp->window->sb == PANE_SCROLLBARS_MODAL &&
window_pane_mode(wp) != WINDOW_PANE_NO_MODE))
return (1);
return (0);
}
int
window_pane_scrollbar_reserve(struct window_pane *wp, int sb_option)
window_pane_scrollbar_reserve(struct window_pane *wp)
{
if (!window_pane_show_scrollbar(wp, sb_option))
if (!window_pane_show_scrollbar(wp))
return (0);
return (sb_option == PANE_SCROLLBARS_ALWAYS);
return (wp->window->sb == PANE_SCROLLBARS_ALWAYS);
}
int
window_pane_scrollbar_overlay(struct window_pane *wp, int sb_option)
window_pane_scrollbar_overlay(struct window_pane *wp)
{
if (!window_pane_show_scrollbar(wp, sb_option))
if (!window_pane_show_scrollbar(wp))
return (0);
return (window_pane_scrollbar_auto_hide(wp));
}
int
window_pane_scrollbar_visible(struct window_pane *wp, int sb_option)
window_pane_scrollbar_visible(struct window_pane *wp)
{
if (!window_pane_show_scrollbar(wp, sb_option))
if (!window_pane_show_scrollbar(wp))
return (0);
if (!window_pane_scrollbar_auto_hide(wp))
return (1);
@@ -2256,12 +2246,9 @@ void
window_pane_scrollbar_show(struct window_pane *wp, int start_timer)
{
int changed = 0;
int sb;
if (!window_pane_scrollbar_auto_hide(wp))
return;
sb = options_get_number(wp->window->options, "pane-scrollbars");
if (!window_pane_show_scrollbar(wp, sb))
if (!window_pane_show_scrollbar(wp))
return;
if (!wp->sb_auto_visible) {
wp->sb_auto_visible = 1;