Merge branch 'obsd-master'

This commit is contained in:
Thomas Adam
2026-06-29 09:00:09 +01:00
14 changed files with 379 additions and 53 deletions

View File

@@ -251,10 +251,10 @@ cmd_resize_pane_mouse_resize_move_floating(struct client *c,
sb_pos = options_get_number(w->options, "pane-scrollbars-position");
left = wp->xoff - 1;
right = wp->xoff + sx;
if (window_pane_show_scrollbar(wp, scrollbars) &&
if (window_pane_scrollbar_reserve(wp, scrollbars) &&
sb_pos == PANE_SCROLLBARS_LEFT) {
left -= wp->scrollbar_style.width + wp->scrollbar_style.pad;
} else if (window_pane_show_scrollbar(wp, scrollbars) &&
} else if (window_pane_scrollbar_reserve(wp, scrollbars) &&
sb_pos == PANE_SCROLLBARS_RIGHT) {
right += wp->scrollbar_style.width + wp->scrollbar_style.pad;
}

View File

@@ -462,7 +462,7 @@ layout_fix_panes(struct window *w, struct window_pane *skip)
sy--;
}
if (window_pane_show_scrollbar(wp, scrollbars)) {
if (window_pane_scrollbar_reserve(wp, scrollbars)) {
sb_w = wp->scrollbar_style.width;
sb_pad = wp->scrollbar_style.pad;
if (sb_w < 1)
@@ -535,7 +535,7 @@ layout_resize_check(struct window *w, struct layout_cell *lc,
/* Space available in this cell only. */
if (type == LAYOUT_LEFTRIGHT) {
available = lc->sx;
if (scrollbars)
if (scrollbars == PANE_SCROLLBARS_ALWAYS)
minimum = PANE_MINIMUM + sb_style->width +
sb_style->pad;
else
@@ -1263,7 +1263,7 @@ layout_split_check_space(struct window_pane *wp, struct layout_cell *lc,
switch (type) {
case LAYOUT_LEFTRIGHT:
if (scrollbars) {
if (scrollbars == PANE_SCROLLBARS_ALWAYS) {
minimum = PANE_MINIMUM * 2 + sb_style->width +
sb_style->pad;
} else

View File

@@ -64,7 +64,7 @@ static const char *options_table_cursor_style_list[] = {
"blinking-bar", "bar", NULL
};
static const char *options_table_pane_scrollbars_list[] = {
"off", "modal", "on", NULL
"off", "modal", "on", "auto-hide", NULL
};
static const char *options_table_pane_scrollbars_position_list[] = {
"right", "left", NULL
@@ -1594,7 +1594,17 @@ const struct options_table_entry options_table[] = {
.scope = OPTIONS_TABLE_WINDOW,
.choices = options_table_pane_scrollbars_list,
.default_num = PANE_SCROLLBARS_OFF,
.text = "Pane scrollbar state."
.text = "Pane scrollbar state: off, on, modal, or auto-hide."
},
{ .name = "pane-scrollbars-timeout",
.type = OPTIONS_TABLE_NUMBER,
.scope = OPTIONS_TABLE_WINDOW,
.minimum = 0,
.maximum = INT_MAX,
.default_num = 500,
.unit = "milliseconds",
.text = "Time before modal and auto-hide pane scrollbars disappear."
},
{ .name = "pane-scrollbars-style",

View File

@@ -1264,6 +1264,7 @@ options_push_changes(const char *name)
strcmp(name, "pane-border-lines") == 0 ||
strcmp(name, "pane-border-status") == 0 ||
strcmp(name, "pane-scrollbars") == 0 ||
strcmp(name, "pane-scrollbars-timeout") == 0 ||
strcmp(name, "pane-scrollbars-position") == 0 ||
strcmp(name, "pane-scrollbars-style") == 0)
redraw_invalidate_all_scenes();
@@ -1288,6 +1289,10 @@ options_push_changes(const char *name)
RB_FOREACH(w, windows, &windows)
layout_fix_panes(w, NULL);
}
if (strcmp(name, "pane-scrollbars") == 0) {
RB_FOREACH(wp, window_pane_tree, &all_window_panes)
window_pane_scrollbar_hide(wp);
}
if (strcmp(name, "pane-scrollbars-style") == 0) {
RB_FOREACH(wp, window_pane_tree, &all_window_panes) {
style_set_scrollbar_style_from_option(

View File

@@ -24,7 +24,8 @@
#include "tmux.h"
static void
regsub_copy(char **buf, ssize_t *len, const char *text, size_t start, size_t end)
regsub_copy(char **buf, ssize_t *len, const char *text, size_t start,
size_t end)
{
size_t add = end - start;

View File

@@ -81,6 +81,7 @@ enum redraw_span_type {
#define REDRAW_BORDER_IS_ARROW 0x1
#define REDRAW_SCROLLBAR_LEFT 0x2
#define REDRAW_SCROLLBAR_RIGHT 0x4
#define REDRAW_SCROLLBAR_OVERLAY 0x8
/* Draw operations. */
#define REDRAW_PANE 0x1
@@ -447,7 +448,7 @@ redraw_mark_pane_inside(struct redraw_build_ctx *bctx, struct window_pane *wp)
/* Mark scrollbar data. */
static void
redraw_mark_pane_scrollbar(struct redraw_build_ctx *bctx,
struct window_pane *wp, int sb_w, int sb_left)
struct window_pane *wp, int sb_w, int sb_left, int overlay)
{
struct redraw_build_cell *bc;
u_int x, y;
@@ -457,7 +458,13 @@ redraw_mark_pane_scrollbar(struct redraw_build_ctx *bctx,
if (sb_w == 0)
return;
if (sb_left) {
if (overlay && sb_left) {
sx = wp->xoff;
ex = sx + sb_w - 1;
} else if (overlay) {
ex = wp->xoff + (int)wp->sx - 1;
sx = ex - sb_w + 1;
} else if (sb_left) {
sx = wp->xoff - sb_w;
ex = wp->xoff - 1;
} else {
@@ -481,6 +488,8 @@ redraw_mark_pane_scrollbar(struct redraw_build_ctx *bctx,
bc->data.sb.flags |= REDRAW_SCROLLBAR_LEFT;
else
bc->data.sb.flags |= REDRAW_SCROLLBAR_RIGHT;
if (overlay)
bc->data.sb.flags |= REDRAW_SCROLLBAR_OVERLAY;
}
}
}
@@ -755,19 +764,30 @@ redraw_mark_pane_borders(struct redraw_build_ctx *bctx, struct window_pane *wp,
static void
redraw_mark_pane(struct redraw_build_ctx *bctx, struct window_pane *wp)
{
int sb_w = 0, sb_left = 0;
int sb_w = 0, sb_left = 0, overlay = 0;
if (!window_pane_is_visible(wp))
return;
if (window_pane_show_scrollbar(wp, bctx->sb))
sb_w = wp->scrollbar_style.width + wp->scrollbar_style.pad;
if (window_pane_scrollbar_visible(wp, bctx->sb)) {
overlay = window_pane_scrollbar_overlay(wp, bctx->sb);
if (overlay) {
sb_w = wp->scrollbar_style.width +
wp->scrollbar_style.pad;
if (sb_w > (int)wp->sx) {
sb_w = wp->scrollbar_style.width;
if (sb_w > (int)wp->sx)
sb_w = wp->sx;
}
} else
sb_w = wp->scrollbar_style.width + wp->scrollbar_style.pad;
}
if (sb_w != 0 && bctx->sbp == PANE_SCROLLBARS_LEFT)
sb_left = 1;
redraw_mark_pane_inside(bctx, wp);
redraw_mark_pane_borders(bctx, wp, sb_w, sb_left);
redraw_mark_pane_scrollbar(bctx, wp, sb_w, sb_left);
redraw_mark_pane_borders(bctx, wp, overlay ? 0 : sb_w, sb_left);
redraw_mark_pane_scrollbar(bctx, wp, sb_w, sb_left, overlay);
}
/* Choose the pane that will provide the border style for two-pane layouts. */
@@ -1220,7 +1240,7 @@ redraw_draw_scrollbar_span(struct redraw_draw_ctx *dctx,
struct screen *s = wp->screen;
struct tty *tty = &scene->c->tty;
struct style *sb_style = &wp->scrollbar_style;
struct grid_cell gc, slgc, *gcp;
struct grid_cell gc, slgc, pad_gc, *gcp;
double pct_view;
u_int total_height, slider_h, slider_y;
u_int sb_h = span->data.sb.height;
@@ -1260,6 +1280,7 @@ redraw_draw_scrollbar_span(struct redraw_draw_ctx *dctx,
memcpy(&slgc, &gc, sizeof slgc);
slgc.fg = gc.bg;
slgc.bg = gc.fg;
tty_default_colours(&pad_gc, wp, NULL);
sb_w = sb_style->width;
sb_pad = sb_style->pad;
@@ -1269,12 +1290,12 @@ redraw_draw_scrollbar_span(struct redraw_draw_ctx *dctx,
for (i = 0; i < n; i++) {
if (span->data.sb.flags & REDRAW_SCROLLBAR_LEFT) {
if (off + i >= sb_w && off + i < sb_w + sb_pad) {
tty_cell(tty, &grid_default_cell, NULL);
tty_cell(tty, &pad_gc, NULL);
continue;
}
} else {
if (off + i < sb_pad) {
tty_cell(tty, &grid_default_cell, NULL);
tty_cell(tty, &pad_gc, NULL);
continue;
}
}

View File

@@ -2182,6 +2182,10 @@ screen_write_collect_flush_scrolled(struct screen_write_ctx *ctx)
screen_write_redraw_pane(ctx, &ttyctx);
return 0;
}
if (wp != NULL && window_pane_scrollbar_overlay_visible(wp)) {
wp->flags |= PANE_REDRAW;
return 0;
}
log_debug("%s: scrolled %u (region %u-%u)", __func__, ctx->scrolled,
s->rupper, s->rlower);
@@ -2195,7 +2199,7 @@ screen_write_collect_flush_scrolled(struct screen_write_ctx *ctx)
tty_write(tty_cmd_scrollup, &ttyctx);
if (wp != NULL)
wp->flags |= PANE_REDRAWSCROLLBAR;
window_pane_scrollbar_redraw(wp);
return 1;
}

View File

@@ -48,6 +48,8 @@ static void server_client_dispatch(struct imsg *, void *);
static int server_client_dispatch_command(struct client *, struct imsg *);
static int server_client_dispatch_identify(struct client *, struct imsg *);
static int server_client_dispatch_shell(struct client *);
static void server_client_update_scrollbar_hover(struct client *, int, int,
int);
static void server_client_report_theme(struct client *, enum client_theme);
/* Compare client windows. */
@@ -601,6 +603,60 @@ server_client_exec(struct client *c, const char *cmd)
free(msg);
}
/* Is this point inside the auto-hide scrollbar interaction area? */
static int
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;
sb = options_get_number(w->options, "pane-scrollbars");
if (!window_pane_scrollbar_overlay(wp, sb))
return (0);
if (py < wp->yoff || py >= wp->yoff + (int)wp->sy)
return (0);
width = wp->scrollbar_style.width;
pad = wp->scrollbar_style.pad;
total = width + pad;
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) {
start = wp->xoff;
end = wp->xoff + (int)total - 1;
} else {
end = wp->xoff + (int)wp->sx - 1;
start = end - (int)total + 1;
}
return (px >= start && px <= end);
}
/* Update auto-hide scrollbars for a mouse movement. */
static void
server_client_update_scrollbar_hover(struct client *c, int type, int px, int py)
{
struct window *w = c->session->curw->window;
struct window_pane *wp;
if (type != KEYC_TYPE_MOUSEMOVE)
return;
TAILQ_FOREACH(wp, &w->panes, entry) {
if (!window_pane_is_visible(wp))
continue;
if (server_client_in_scrollbar_area(wp, px, py)) {
wp->sb_auto_hover = 1;
window_pane_scrollbar_show(wp, 1);
} else {
wp->sb_auto_hover = 0;
window_pane_scrollbar_start_timer(wp);
}
}
}
/* Is the mouse inside a pane? */
static enum key_code_mouse_location
server_client_check_mouse_in_pane(struct window_pane *wp, int px, int py,
@@ -611,14 +667,18 @@ server_client_check_mouse_in_pane(struct window_pane *wp, int px, int py,
int pane_status, sb, sb_pos, 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);
if (window_pane_show_scrollbar(wp, sb)) {
if (window_pane_scrollbar_visible(wp, sb)) {
sb_w = wp->scrollbar_style.width;
sb_pad = wp->scrollbar_style.pad;
if (sb_overlay && sb_w > (int)wp->sx)
sb_w = wp->sx;
} else {
sb_w = 0;
sb_pad = 0;
@@ -631,9 +691,34 @@ 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_pos == PANE_SCROLLBARS_LEFT)
if (!sb_overlay && 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) {
sb_start = wp->xoff;
sb_end = sb_start + sb_w - 1;
} else {
sb_end = wp->xoff + (int)wp->sx - 1;
sb_start = sb_end - sb_w + 1;
}
if (px >= sb_start && px <= sb_end) {
sl_top = wp->yoff + wp->sb_slider_y;
sl_bottom = (wp->yoff + wp->sb_slider_y +
wp->sb_slider_h - 1);
if (py < sl_top)
return (KEYC_MOUSE_LOCATION_SCROLLBAR_UP);
else if (py >= sl_top && py <= sl_bottom) {
*sl_mpos = (py - wp->sb_slider_y - wp->yoff);
return (KEYC_MOUSE_LOCATION_SCROLLBAR_SLIDER);
} else
return (KEYC_MOUSE_LOCATION_SCROLLBAR_DOWN);
}
return (KEYC_MOUSE_LOCATION_PANE);
}
/* Check if point is within the pane or scrollbar. */
if (((pane_status != PANE_STATUS_OFF &&
py != pane_status_line && py != wp->yoff + (int)wp->sy) ||
@@ -681,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_show_scrollbar(fwp, sb)) {
if (window_pane_scrollbar_reserve(fwp, sb)) {
sb_w = fwp->scrollbar_style.width;
sb_pad = fwp->scrollbar_style.pad;
} else {
@@ -911,10 +996,14 @@ have_event:
tty_window_offset(&c->tty, &m->ox, &m->oy, &sx, &sy);
log_debug("mouse window @%u at %u,%u (%ux%u)",
w->id, m->ox, m->oy, sx, sy);
if (px > sx || py > sy)
if (px > sx || py > sy) {
server_client_update_scrollbar_hover(c, type,
-1, -1);
return (KEYC_UNKNOWN);
}
px = px + m->ox;
py = py + m->oy;
server_client_update_scrollbar_hover(c, type, px, py);
if (type == KEYC_TYPE_MOUSEDRAG && lwp != NULL) {
/* Use pane from last mouse event. */
@@ -947,7 +1036,8 @@ have_event:
m->wp = wp->id;
m->w = wp->window->id;
}
}
} else
server_client_update_scrollbar_hover(c, type, -1, -1);
/* Reset click type or add a click timer if needed. */
if (type == KEYC_TYPE_MOUSEDOWN ||
@@ -1907,8 +1997,9 @@ 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;
int mode = 0, cursor, flags, pane_mode = 0, sb;
u_int cx = 0, cy = 0, ox, oy, sx, sy, prompt = 0;
u_int sb_w;
struct visible_ranges *r;
if (c->flags & (CLIENT_CONTROL|CLIENT_SUSPENDED))
@@ -1961,6 +2052,21 @@ server_client_reset_state(struct client *c)
if (!window_position_is_visible(r, cx))
cursor = 0;
if (window_pane_scrollbar_overlay_visible(wp)) {
sb_w = wp->scrollbar_style.width;
if (sb_w > wp->sx)
sb_w = wp->sx;
if (sb_w != 0 &&
options_get_number(w->options,
"pane-scrollbars-position") ==
PANE_SCROLLBARS_LEFT) {
if (s->cx < sb_w)
cursor = 0;
} else if (sb_w != 0 &&
s->cx >= wp->sx - sb_w)
cursor = 0;
}
if (status_at_line(c) == 0)
cy += status_line_size(c);
}
@@ -1988,7 +2094,10 @@ server_client_reset_state(struct client *c)
mode |= MODE_MOUSE_ALL;
}
}
if (options_get_number(oo, "focus-follows-mouse"))
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;
else if (~mode & MODE_MOUSE_ALL)
mode |= MODE_MOUSE_BUTTON;

4
sort.c
View File

@@ -26,8 +26,8 @@
static struct sort_criteria *sort_criteria;
static void
sort_qsort(void *l, u_int len, u_int size, int (*cmp)(const void *, const void *),
struct sort_criteria *sort_crit)
sort_qsort(void *l, u_int len, u_int size, int (*cmp)(const void *,
const void *), struct sort_criteria *sort_crit)
{
u_int i;
void *tmp, **ll;

35
tmux.1
View File

@@ -5895,7 +5895,7 @@ and
will fall back to standard ACS line drawing when UTF\-8 is not supported.
.Pp
.It Xo Ic pane\-scrollbars
.Op Ic off | modal | on
.Op Ic off | modal | on | auto\-hide
.Xc
When enabled, a character based scrollbar appears on the left or right
of each pane.
@@ -5905,19 +5905,29 @@ represents the position and size of the visible part of the pane content.
.Pp
If set to
.Ic on
the scrollbar is visible all the time.
the scrollbar is visible all the time and the pane is narrowed by the width of
the scrollbar.
If set to
.Ic modal
the scrollbar only appears when the pane is in copy mode or view mode.
When the scrollbar is visible, the pane is narrowed by the width of the
scrollbar and the text in the pane is reflowed.
the scrollbar only appears when the pane is in copy mode or view mode and
auto-hides when not in use.
If set to
.Ic modal ,
the pane is narrowed only when the scrollbar is visible.
.Ic auto\-hide
the scrollbar is available all the time but auto-hides when not in use.
With
.Ic modal
and
.Ic auto\-hide ,
the scrollbar overlays the pane and does not narrow or reflow the pane.
.Pp
See also
.Ic pane\-scrollbars\-style .
.Pp
.It Xo Ic pane\-scrollbars\-position
.Op Ic left | right
.Xc
Sets which side of the pane to display pane scrollbars on.
.Pp
.It Ic pane\-scrollbars\-style Ar style
Set the scrollbars style.
For how to specify
@@ -5934,10 +5944,13 @@ attribute sets the width of the scrollbar and the
attribute the padding between the scrollbar and the pane.
Other attributes are ignored.
.Pp
.It Xo Ic pane\-scrollbars\-position
.Op Ic left | right
.Xc
Sets which side of the pane to display pane scrollbars on.
.It Ic pane\-scrollbars\-timeout Ar time
Set the time in milliseconds before scrollbars are hidden when
.Ic pane\-scrollbars
is
.Ic modal
or
.Ic auto\-hide .
.Pp
.It Ic pane\-status\-current\-style Ar style
Set status line style for the currently active pane.

12
tmux.h
View File

@@ -1300,6 +1300,9 @@ struct window_pane {
u_int sb_slider_y;
u_int sb_slider_h;
int sb_auto_visible;
int sb_auto_hover;
struct event sb_auto_timer;
int argc;
char **argv;
@@ -1474,6 +1477,7 @@ TAILQ_HEAD(winlink_stack, winlink);
#define PANE_SCROLLBARS_OFF 0
#define PANE_SCROLLBARS_MODAL 1
#define PANE_SCROLLBARS_ALWAYS 2
#define PANE_SCROLLBARS_AUTOHIDE 3
/* Pane scrollbars position option. */
#define PANE_SCROLLBARS_RIGHT 0
@@ -3630,6 +3634,14 @@ 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_scrollbar_overlay_visible(struct window_pane *);
void window_pane_scrollbar_show(struct window_pane *, int);
void window_pane_scrollbar_hide(struct window_pane *);
void window_pane_scrollbar_start_timer(struct window_pane *);
void window_pane_scrollbar_redraw(struct window_pane *);
int window_pane_get_bg(struct window_pane *);
int window_pane_get_fg(struct window_pane *);
int window_pane_get_fg_control_client(struct window_pane *);

View File

@@ -61,8 +61,10 @@ static int window_copy_line_number_mode(struct window_mode_entry *);
static int window_copy_line_number_is_absolute(struct window_mode_entry *);
static int window_copy_line_numbers_active(struct window_mode_entry *);
static u_int window_copy_line_number_width(struct window_mode_entry *);
static u_int window_copy_cursor_offset(struct window_mode_entry *, u_int, u_int);
static u_int window_copy_cursor_unoffset(struct window_mode_entry *, u_int, u_int);
static u_int window_copy_cursor_offset(struct window_mode_entry *, u_int,
u_int);
static u_int window_copy_cursor_unoffset(struct window_mode_entry *, u_int,
u_int);
static void window_copy_write_line(struct window_mode_entry *,
struct screen_write_ctx *, u_int);
static void window_copy_write_lines(struct window_mode_entry *,
@@ -860,6 +862,7 @@ window_copy_scroll1(struct window_mode_entry *wme, struct window_pane *wp,
if (data->searchmark != NULL && !data->timeout)
window_copy_search_marks(wme, NULL, data->searchregex, 1);
window_copy_update_selection(wme, 1, 0);
window_pane_scrollbar_show(wp, 1);
window_copy_redraw_screen(wme);
}
@@ -913,6 +916,7 @@ window_copy_pageup1(struct window_mode_entry *wme, int half_page)
if (data->searchmark != NULL && !data->timeout)
window_copy_search_marks(wme, NULL, data->searchregex, 1);
window_copy_update_selection(wme, 1, 0);
window_pane_scrollbar_show(wme->wp, 1);
window_copy_redraw_screen(wme);
}
@@ -973,6 +977,7 @@ window_copy_pagedown1(struct window_mode_entry *wme, int half_page,
if (data->searchmark != NULL && !data->timeout)
window_copy_search_marks(wme, NULL, data->searchregex, 1);
window_copy_update_selection(wme, 1, 0);
window_pane_scrollbar_show(wme->wp, 1);
window_copy_redraw_screen(wme);
return (0);
}
@@ -1789,7 +1794,7 @@ window_copy_cmd_history_bottom(struct window_copy_cmd_state *cs)
struct window_mode_entry *wme = cs->wme;
struct window_copy_mode_data *data = wme->data;
struct screen *s = data->backing;
u_int oy;
u_int oy, old_oy = data->oy;
oy = screen_hsize(s) + data->cy - data->oy;
if (data->lineflag == LINE_SEL_RIGHT_LEFT && oy == data->endsely)
@@ -1802,6 +1807,8 @@ window_copy_cmd_history_bottom(struct window_copy_cmd_state *cs)
if (data->searchmark != NULL && !data->timeout)
window_copy_search_marks(wme, NULL, data->searchregex, 1);
window_copy_update_selection(wme, 1, 0);
if (data->oy != old_oy)
window_pane_scrollbar_show(wme->wp, 1);
return (WINDOW_COPY_CMD_REDRAW);
}
@@ -1810,7 +1817,7 @@ window_copy_cmd_history_top(struct window_copy_cmd_state *cs)
{
struct window_mode_entry *wme = cs->wme;
struct window_copy_mode_data *data = wme->data;
u_int oy;
u_int oy, old_oy = data->oy;
oy = screen_hsize(data->backing) + data->cy - data->oy;
if (data->lineflag == LINE_SEL_LEFT_RIGHT && oy == data->sely)
@@ -1823,6 +1830,8 @@ window_copy_cmd_history_top(struct window_copy_cmd_state *cs)
if (data->searchmark != NULL && !data->timeout)
window_copy_search_marks(wme, NULL, data->searchregex, 1);
window_copy_update_selection(wme, 1, 0);
if (data->oy != old_oy)
window_pane_scrollbar_show(wme->wp, 1);
return (WINDOW_COPY_CMD_REDRAW);
}
@@ -3772,7 +3781,7 @@ window_copy_scroll_to(struct window_mode_entry *wme, u_int px, u_int py,
{
struct window_copy_mode_data *data = wme->data;
struct grid *gd = data->backing->grid;
u_int offset, gap;
u_int offset, gap, old_oy = data->oy;
data->cx = px;
@@ -3796,6 +3805,8 @@ window_copy_scroll_to(struct window_mode_entry *wme, u_int px, u_int py,
if (!no_redraw && data->searchmark != NULL && !data->timeout)
window_copy_search_marks(wme, NULL, data->searchregex, 1);
window_copy_update_selection(wme, 1, 0);
if (data->oy != old_oy)
window_pane_scrollbar_show(wme->wp, 1);
if (!no_redraw)
window_copy_redraw_screen(wme);
}
@@ -5278,7 +5289,10 @@ window_copy_redraw_lines(struct window_mode_entry *wme, u_int py, u_int ny)
return;
}
screen_write_start_pane(&ctx, wp, NULL);
if (window_pane_scrollbar_overlay_visible(wp))
screen_write_start(&ctx, &data->screen);
else
screen_write_start_pane(&ctx, wp, NULL);
for (i = py; i < py + ny; i++)
window_copy_write_line(wme, &ctx, i);
screen_write_cursormove(&ctx,
@@ -5286,7 +5300,7 @@ window_copy_redraw_lines(struct window_mode_entry *wme, u_int py, u_int ny)
0);
screen_write_stop(&ctx);
wp->flags |= PANE_REDRAWSCROLLBAR;
window_pane_scrollbar_redraw(wp);
}
static void
@@ -6542,6 +6556,7 @@ window_copy_scroll_up(struct window_mode_entry *wme, u_int ny)
if (ny == 0)
return;
data->oy -= ny;
window_pane_scrollbar_show(wp, 1);
if (data->searchmark != NULL && !data->timeout)
window_copy_search_marks(wme, NULL, data->searchregex, 1);
@@ -6573,7 +6588,10 @@ window_copy_scroll_up(struct window_mode_entry *wme, u_int ny)
return;
}
screen_write_start_pane(&ctx, wp, NULL);
if (window_pane_scrollbar_overlay_visible(wp))
screen_write_start(&ctx, &data->screen);
else
screen_write_start_pane(&ctx, wp, NULL);
screen_write_cursormove(&ctx, 0, 0, 0);
screen_write_deleteline(&ctx, ny, 8);
window_copy_write_lines(wme, &ctx, screen_size_y(s) - ny, ny);
@@ -6588,7 +6606,7 @@ window_copy_scroll_up(struct window_mode_entry *wme, u_int ny)
window_copy_cursor_offset(wme, data->cx, screen_size_x(s)), data->cy,
0);
screen_write_stop(&ctx);
wp->flags |= PANE_REDRAWSCROLLBAR;
window_pane_scrollbar_redraw(wp);
}
static void
@@ -6607,6 +6625,7 @@ window_copy_scroll_down(struct window_mode_entry *wme, u_int ny)
if (ny == 0)
return;
data->oy += ny;
window_pane_scrollbar_show(wp, 1);
if (data->searchmark != NULL && !data->timeout)
window_copy_search_marks(wme, NULL, data->searchregex, 1);
@@ -6633,7 +6652,10 @@ window_copy_scroll_down(struct window_mode_entry *wme, u_int ny)
return;
}
screen_write_start_pane(&ctx, wp, NULL);
if (window_pane_scrollbar_overlay_visible(wp))
screen_write_start(&ctx, &data->screen);
else
screen_write_start_pane(&ctx, wp, NULL);
screen_write_cursormove(&ctx, 0, 0, 0);
screen_write_insertline(&ctx, ny, 8);
window_copy_write_lines(wme, &ctx, 0, ny);
@@ -6644,7 +6666,7 @@ window_copy_scroll_down(struct window_mode_entry *wme, u_int ny)
screen_write_cursormove(&ctx, window_copy_cursor_offset(wme, data->cx,
screen_size_x(s)), data->cy, 0);
screen_write_stop(&ctx);
wp->flags |= PANE_REDRAWSCROLLBAR;
window_pane_scrollbar_redraw(wp);
}
static void

View File

@@ -126,7 +126,7 @@ 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_show_scrollbar(wp, sb))
if (!window_pane_scrollbar_reserve(wp, sb))
sb_w = sb_pos = 0;
for (i = 0; i < r->used; i++) {

133
window.c
View File

@@ -71,6 +71,7 @@ struct window_pane_input_data {
static struct window_pane *window_pane_create(struct window *, u_int, u_int,
u_int);
static void window_pane_destroy(struct window_pane *);
static void window_pane_scrollbar_timer(int, short, void *);
static void window_pane_full_size_offset(struct window_pane *wp,
int *xoff, int *yoff, u_int *sx, u_int *sy);
@@ -1112,6 +1113,7 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit)
screen_init(&wp->status_screen, 1, 1, 0);
style_ranges_init(&wp->border_status_line.ranges);
evtimer_set(&wp->sb_auto_timer, window_pane_scrollbar_timer, wp);
if (gethostname(host, sizeof host) == 0)
screen_set_title(&wp->base, host, 0);
@@ -1158,6 +1160,52 @@ window_pane_free_modes(struct window_pane *wp)
wp->screen = &wp->base;
}
static void
window_pane_scrollbar_timer(__unused int fd, __unused short events, void *arg)
{
struct window_pane *wp = arg;
wp->sb_auto_hover = 0;
window_pane_scrollbar_hide(wp);
}
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);
}
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));
}
void
window_pane_scrollbar_redraw(struct window_pane *wp)
{
if (window_pane_scrollbar_overlay_visible(wp)) {
wp->flags |= PANE_REDRAW;
return;
}
wp->flags |= PANE_REDRAWSCROLLBAR;
}
static void
window_pane_scrollbar_redraw_visibility(struct window_pane *wp)
{
redraw_invalidate_scene(wp->window);
wp->flags |= PANE_REDRAW;
server_redraw_window(wp->window);
}
static void
window_pane_destroy(struct window_pane *wp)
{
@@ -1193,6 +1241,8 @@ window_pane_destroy(struct window_pane *wp)
event_del(&wp->resize_timer);
if (event_initialized(&wp->sync_timer))
event_del(&wp->sync_timer);
if (event_initialized(&wp->sb_auto_timer))
event_del(&wp->sb_auto_timer);
window_pane_clear_resizes(wp, NULL);
RB_REMOVE(window_pane_tree, &all_window_panes, wp);
@@ -1262,7 +1312,8 @@ window_pane_set_event(struct window_pane *wp)
}
void
window_pane_clear_resizes(struct window_pane *wp, struct window_pane_resize *except)
window_pane_clear_resizes(struct window_pane *wp,
struct window_pane_resize *except)
{
struct window_pane_resize *r, *r1;
@@ -1735,7 +1786,7 @@ window_pane_full_size_offset(struct window_pane *wp, int *xoff, int *yoff,
pane_scrollbars = options_get_number(w->options, "pane-scrollbars");
sb_pos = options_get_number(w->options, "pane-scrollbars-position");
if (window_pane_show_scrollbar(wp, pane_scrollbars))
if (window_pane_scrollbar_reserve(wp, pane_scrollbars))
sb_w = wp->scrollbar_style.width + wp->scrollbar_style.pad;
else
sb_w = 0;
@@ -2162,12 +2213,90 @@ window_pane_show_scrollbar(struct window_pane *wp, int sb_option)
if (SCREEN_IS_ALTERNATE(&wp->base))
return (0);
if (sb_option == PANE_SCROLLBARS_ALWAYS ||
sb_option == PANE_SCROLLBARS_AUTOHIDE ||
(sb_option == 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)
{
if (!window_pane_show_scrollbar(wp, sb_option))
return (0);
return (sb_option == PANE_SCROLLBARS_ALWAYS);
}
int
window_pane_scrollbar_overlay(struct window_pane *wp, int sb_option)
{
if (!window_pane_show_scrollbar(wp, sb_option))
return (0);
return (window_pane_scrollbar_auto_hide(wp));
}
int
window_pane_scrollbar_visible(struct window_pane *wp, int sb_option)
{
if (!window_pane_show_scrollbar(wp, sb_option))
return (0);
if (!window_pane_scrollbar_auto_hide(wp))
return (1);
return (wp->sb_auto_visible);
}
void
window_pane_scrollbar_start_timer(struct window_pane *wp)
{
struct timeval tv;
u_int delay;
if (!window_pane_scrollbar_auto_hide(wp) || !wp->sb_auto_visible)
return;
delay = options_get_number(wp->window->options,
"pane-scrollbars-timeout");
tv.tv_sec = delay / 1000;
tv.tv_usec = (delay % 1000) * 1000L;
evtimer_del(&wp->sb_auto_timer);
evtimer_add(&wp->sb_auto_timer, &tv);
}
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))
return;
if (!wp->sb_auto_visible) {
wp->sb_auto_visible = 1;
changed = 1;
}
evtimer_del(&wp->sb_auto_timer);
if (start_timer)
window_pane_scrollbar_start_timer(wp);
if (changed)
window_pane_scrollbar_redraw_visibility(wp);
}
void
window_pane_scrollbar_hide(struct window_pane *wp)
{
if (event_initialized(&wp->sb_auto_timer))
evtimer_del(&wp->sb_auto_timer);
wp->sb_auto_hover = 0;
if (!wp->sb_auto_visible)
return;
wp->sb_auto_visible = 0;
window_pane_scrollbar_redraw_visibility(wp);
}
int
window_pane_get_bg(struct window_pane *wp)
{