Merge branch 'master' into floating_panes

This commit is contained in:
Dane Jensen
2026-06-15 13:00:51 -07:00
12 changed files with 281 additions and 104 deletions

View File

@@ -70,20 +70,24 @@ cmd_join_pane_place(struct cmdq_item *item, struct winlink *wl,
struct window_pane *owp; struct window_pane *owp;
int wx = w->sx, wy = w->sy, px = lc->sx; int wx = w->sx, wy = w->sy, px = lc->sx;
int py = lc->sy, xoff = lc->xoff, yoff = lc->yoff; int py = lc->sy, xoff = lc->xoff, yoff = lc->yoff;
int border = 1;
if (window_pane_get_pane_lines(wp) == PANE_LINES_NONE)
border = 0;
if (strcmp(position, "top-left") == 0) { if (strcmp(position, "top-left") == 0) {
xoff = 1; xoff = border;
yoff = 1; yoff = border;
} else if (strcmp(position, "top-centre") == 0 || } else if (strcmp(position, "top-centre") == 0 ||
strcmp(position, "top-center") == 0) { strcmp(position, "top-center") == 0) {
xoff = (wx - px) / 2; xoff = (wx - px) / 2;
yoff = 1; yoff = border;
} else if (strcmp(position, "top-right") == 0) { } else if (strcmp(position, "top-right") == 0) {
xoff = wx - px - 1; xoff = wx - px - border;
yoff = 1; yoff = border;
} else if (strcmp(position, "centre-left") == 0 || } else if (strcmp(position, "centre-left") == 0 ||
strcmp(position, "center-left") == 0) { strcmp(position, "center-left") == 0) {
xoff = 1; xoff = border;
yoff = (wy - py) / 2; yoff = (wy - py) / 2;
} else if (strcmp(position, "centre") == 0 || } else if (strcmp(position, "centre") == 0 ||
strcmp(position, "center") == 0) { strcmp(position, "center") == 0) {
@@ -91,18 +95,18 @@ cmd_join_pane_place(struct cmdq_item *item, struct winlink *wl,
yoff = (wy - py) / 2; yoff = (wy - py) / 2;
} else if (strcmp(position, "centre-right") == 0 || } else if (strcmp(position, "centre-right") == 0 ||
strcmp(position, "center-right") == 0) { strcmp(position, "center-right") == 0) {
xoff = wx - px - 1; xoff = wx - px - border;
yoff = (wy - py) / 2; yoff = (wy - py) / 2;
} else if (strcmp(position, "bottom-left") == 0) { } else if (strcmp(position, "bottom-left") == 0) {
xoff = 1; xoff = border;
yoff = wy - py - 1; yoff = wy - py - border;
} else if (strcmp(position, "bottom-centre") == 0 || } else if (strcmp(position, "bottom-centre") == 0 ||
strcmp(position, "bottom-center") == 0) { strcmp(position, "bottom-center") == 0) {
xoff = (wx - px) / 2; xoff = (wx - px) / 2;
yoff = wy - py - 1; yoff = wy - py - border;
} else if (strcmp(position, "bottom-right") == 0) { } else if (strcmp(position, "bottom-right") == 0) {
xoff = wx - px - 1; xoff = wx - px - border;
yoff = wy - py - 1; yoff = wy - py - border;
} else if (strcmp(position, "top-left-centre") == 0 || } else if (strcmp(position, "top-left-centre") == 0 ||
strcmp(position, "top-left-center") == 0) { strcmp(position, "top-left-center") == 0) {
xoff = wx / 4 - px / 2; xoff = wx / 4 - px / 2;

View File

@@ -38,9 +38,10 @@ const struct cmd_entry cmd_new_pane_entry = {
.name = "new-pane", .name = "new-pane",
.alias = "newp", .alias = "newp",
.args = { "bc:de:EfF:hIkl:Lm:p:PR:s:S:t:T:vWx:X:y:Y:Z", 0, -1, NULL }, .args = { "bB:c:de:EfF:hIkl:Lm:p:PR:s:S:t:T:vWx:X:y:Y:Z", 0, -1, NULL },
.usage = "[-bdefhIklPvWZ] [-c start-directory] [-e environment] " .usage = "[-bdefhIklPvWZ] [-B border-lines] "
"[-F format] [-l size] [-m message] [-p percentage] " "[-c start-directory] [-e environment] "
"[-F format] [-l size] [-m message] [-p percentage] "
"[-s style] [-S active-border-style] " "[-s style] [-S active-border-style] "
"[-R inactive-border-style] [-T title] [-x width] [-y height] " "[-R inactive-border-style] [-T title] [-x width] [-y height] "
"[-X x-position] [-Y y-position] " CMD_TARGET_PANE_USAGE " " "[-X x-position] [-Y y-position] " CMD_TARGET_PANE_USAGE " "
@@ -84,9 +85,11 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
struct layout_cell *lc = NULL; struct layout_cell *lc = NULL;
struct cmd_find_state fs; struct cmd_find_state fs;
int input, empty, is_floating, flags = 0; int input, empty, is_floating, flags = 0;
const char *template, *style; const char *template, *style, *value;
char *cause = NULL, *cp, *title; char *cause = NULL, *cp, *title;
struct options_entry *oe;
struct args_value *av; struct args_value *av;
enum pane_lines lines;
u_int count = args_count(args); u_int count = args_count(args);
if (cmd_get_entry(self) == &cmd_new_pane_entry) if (cmd_get_entry(self) == &cmd_new_pane_entry)
@@ -187,6 +190,19 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
} }
value = args_get(args, 'B');
if (value != NULL) {
oe = options_get(new_wp->options, "pane-border-lines");
lines = options_find_choice(options_table_entry(oe), value,
&cause);
if (cause != NULL) {
cmdq_error(item, "pane-border-lines %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
options_set_number(new_wp->options, "pane-border-lines",
lines);
}
if (args_has(args, 'k') || args_has(args, 'm')) { if (args_has(args, 'k') || args_has(args, 'm')) {
options_set_number(new_wp->options, "remain-on-exit", 3); options_set_number(new_wp->options, "remain-on-exit", 3);
if (args_has(args, 'm')) { if (args_has(args, 'm')) {

View File

@@ -1157,15 +1157,13 @@ static void *
format_cb_pane_at_top(struct format_tree *ft) format_cb_pane_at_top(struct format_tree *ft)
{ {
struct window_pane *wp = ft->wp; struct window_pane *wp = ft->wp;
struct window *w;
int status, flag; int status, flag;
char *value; char *value;
if (wp == NULL) if (wp == NULL)
return (NULL); return (NULL);
w = wp->window;
status = window_get_pane_status(w); status = window_pane_get_pane_status(wp);
if (status == PANE_STATUS_TOP) if (status == PANE_STATUS_TOP)
flag = (wp->yoff == 1); flag = (wp->yoff == 1);
else else
@@ -1187,7 +1185,7 @@ format_cb_pane_at_bottom(struct format_tree *ft)
return (NULL); return (NULL);
w = wp->window; w = wp->window;
status = options_get_number(w->options, "pane-border-status"); status = window_pane_get_pane_status(wp);
if (status == PANE_STATUS_BOTTOM) if (status == PANE_STATUS_BOTTOM)
flag = (wp->yoff + (int)wp->sy == (int)w->sy - 1); flag = (wp->yoff + (int)wp->sy == (int)w->sy - 1);
else else

View File

@@ -853,7 +853,8 @@ layout_resize_floating_pane_to(struct window_pane *wp, enum layout_type type,
return; return;
} }
if (size >= PANE_MINIMUM + 2) if (window_pane_get_pane_lines(wp) != PANE_LINES_NONE &&
size >= PANE_MINIMUM + 2)
size -= 2; size -= 2;
if (size < PANE_MINIMUM || size > PANE_MAXIMUM) { if (size < PANE_MINIMUM || size > PANE_MAXIMUM) {
*cause = xstrdup("size is too big or too small"); *cause = xstrdup("size is too big or too small");

View File

@@ -70,13 +70,13 @@ static const char *options_table_pane_scrollbars_position_list[] = {
"right", "left", NULL "right", "left", NULL
}; };
static const char *options_table_pane_status_list[] = { static const char *options_table_pane_status_list[] = {
"off", "top", "bottom", NULL "off", "top", "bottom", "top-floating", "bottom-floating", NULL
}; };
static const char *options_table_pane_border_indicators_list[] = { static const char *options_table_pane_border_indicators_list[] = {
"off", "colour", "arrows", "both", NULL "off", "colour", "arrows", "both", NULL
}; };
static const char *options_table_pane_border_lines_list[] = { static const char *options_table_pane_border_lines_list[] = {
"single", "double", "heavy", "simple", "number", "spaces", NULL "single", "double", "heavy", "simple", "number", "spaces", "none", NULL
}; };
static const char *options_table_popup_border_lines_list[] = { static const char *options_table_popup_border_lines_list[] = {
"single", "double", "heavy", "simple", "rounded", "padded", "none", NULL "single", "double", "heavy", "simple", "rounded", "padded", "none", NULL
@@ -1386,7 +1386,7 @@ const struct options_table_entry options_table[] = {
{ .name = "pane-border-lines", { .name = "pane-border-lines",
.type = OPTIONS_TABLE_CHOICE, .type = OPTIONS_TABLE_CHOICE,
.scope = OPTIONS_TABLE_WINDOW, .scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE,
.choices = options_table_pane_border_lines_list, .choices = options_table_pane_border_lines_list,
.default_num = PANE_LINES_SINGLE, .default_num = PANE_LINES_SINGLE,
.text = "Type of characters used to draw pane border lines. Some of " .text = "Type of characters used to draw pane border lines. Some of "
@@ -1395,7 +1395,7 @@ const struct options_table_entry options_table[] = {
{ .name = "pane-border-status", { .name = "pane-border-status",
.type = OPTIONS_TABLE_CHOICE, .type = OPTIONS_TABLE_CHOICE,
.scope = OPTIONS_TABLE_WINDOW, .scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE,
.choices = options_table_pane_status_list, .choices = options_table_pane_status_list,
.default_num = PANE_STATUS_OFF, .default_num = PANE_STATUS_OFF,
.text = "Position of the pane status lines." .text = "Position of the pane status lines."

View File

@@ -87,6 +87,7 @@ screen_redraw_border_set(struct window *w, struct window_pane *wp,
gc->attr &= ~GRID_ATTR_CHARSET; gc->attr &= ~GRID_ATTR_CHARSET;
utf8_set(&gc->data, SIMPLE_BORDERS[cell_type]); utf8_set(&gc->data, SIMPLE_BORDERS[cell_type]);
break; break;
case PANE_LINES_NONE:
case PANE_LINES_SPACES: case PANE_LINES_SPACES:
gc->attr &= ~GRID_ATTR_CHARSET; gc->attr &= ~GRID_ATTR_CHARSET;
utf8_set(&gc->data, ' '); utf8_set(&gc->data, ' ');
@@ -125,7 +126,8 @@ screen_redraw_pane_border(struct screen_redraw_ctx *ctx, struct window_pane *wp,
{ {
struct options *oo = wp->window->options; struct options *oo = wp->window->options;
int ex = wp->xoff + wp->sx, ey = wp->yoff + wp->sy; int ex = wp->xoff + wp->sx, ey = wp->yoff + wp->sy;
int hsplit = 0, vsplit = 0, pane_status = ctx->pane_status; int hsplit = 0, vsplit = 0;
int pane_status = window_pane_get_pane_status(wp);
int pane_scrollbars = ctx->pane_scrollbars, sb_w = 0; int pane_scrollbars = ctx->pane_scrollbars, sb_w = 0;
int sb_pos, sx = wp->sx, sy = wp->sy; int sb_pos, sx = wp->sx, sy = wp->sy;
enum layout_type split_type; enum layout_type split_type;
@@ -139,6 +141,10 @@ screen_redraw_pane_border(struct screen_redraw_ctx *ctx, struct window_pane *wp,
if (px >= wp->xoff && px < ex && py >= wp->yoff && py < ey) if (px >= wp->xoff && px < ex && py >= wp->yoff && py < ey)
return (SCREEN_REDRAW_INSIDE); return (SCREEN_REDRAW_INSIDE);
if (window_pane_is_floating(wp) &&
window_pane_get_pane_lines(wp) == PANE_LINES_NONE)
return (SCREEN_REDRAW_OUTSIDE);
/* Are scrollbars enabled? */ /* Are scrollbars enabled? */
if (window_pane_show_scrollbar(wp, pane_scrollbars)) if (window_pane_show_scrollbar(wp, pane_scrollbars))
sb_w = wp->scrollbar_style.width + wp->scrollbar_style.pad; sb_w = wp->scrollbar_style.width + wp->scrollbar_style.pad;
@@ -296,7 +302,7 @@ screen_redraw_cell_border(struct screen_redraw_ctx *ctx, struct window_pane *wp,
} }
/* Outside the window or on the window border? */ /* Outside the window or on the window border? */
if (ctx->pane_status == PANE_STATUS_BOTTOM) if (window_pane_get_pane_status(wp) == PANE_STATUS_BOTTOM)
sy--; sy--;
if (px > sx || py > sy) if (px > sx || py > sy)
return (0); return (0);
@@ -327,7 +333,8 @@ screen_redraw_type_of_cell(struct screen_redraw_ctx *ctx,
{ {
struct client *c = ctx->c; struct client *c = ctx->c;
struct window *w = c->session->curw->window; struct window *w = c->session->curw->window;
int pane_status = ctx->pane_status, borders = 0; int pane_status = window_pane_get_pane_status(wp);
int borders = 0;
int sx = w->sx, sy = w->sy; int sx = w->sx, sy = w->sy;
/* Is this outside the window? */ /* Is this outside the window? */
@@ -435,7 +442,7 @@ screen_redraw_check_cell(struct screen_redraw_ctx *ctx, int px, int py,
struct window *w = c->session->curw->window; struct window *w = c->session->curw->window;
struct window_pane *wp, *start; struct window_pane *wp, *start;
int sx = w->sx, sy = w->sy; int sx = w->sx, sy = w->sy;
int pane_status = ctx->pane_status; int pane_status;
int border, pane_scrollbars = ctx->pane_scrollbars; int border, pane_scrollbars = ctx->pane_scrollbars;
int pane_status_line, tiled_only = 0, left, right; int pane_status_line, tiled_only = 0, left, right;
int sb_pos = ctx->pane_scrollbars_pos, sb_w; int sb_pos = ctx->pane_scrollbars_pos, sb_w;
@@ -511,6 +518,7 @@ screen_redraw_check_cell(struct screen_redraw_ctx *ctx, int px, int py,
* Pane border status inside top/bottom border is CELL_INSIDE * Pane border status inside top/bottom border is CELL_INSIDE
* so it doesn't get overdrawn by a border line. * so it doesn't get overdrawn by a border line.
*/ */
pane_status = window_pane_get_pane_status(wp);
if (pane_status != PANE_STATUS_OFF) { if (pane_status != PANE_STATUS_OFF) {
if (pane_status == PANE_STATUS_TOP) if (pane_status == PANE_STATUS_TOP)
pane_status_line = wp->yoff - 1; pane_status_line = wp->yoff - 1;
@@ -593,13 +601,19 @@ screen_redraw_make_pane_status(struct client *c, struct window_pane *wp,
struct format_tree *ft; struct format_tree *ft;
struct style_line_entry *sle = &wp->border_status_line; struct style_line_entry *sle = &wp->border_status_line;
char *expanded; char *expanded;
int pane_status = rctx->pane_status, sb_w = 0; int pane_status = window_pane_get_pane_status(wp);
int sb_w = 0;
int pane_scrollbars = rctx->pane_scrollbars; int pane_scrollbars = rctx->pane_scrollbars;
int max_width; int max_width;
u_int width, i, cell_type, px, py; u_int width, i, cell_type, px, py;
struct screen_write_ctx ctx; struct screen_write_ctx ctx;
struct screen old; struct screen old;
if (pane_status == PANE_STATUS_OFF) {
wp->status_size = 0;
return (0);
}
if (window_pane_show_scrollbar(wp, pane_scrollbars)) if (window_pane_show_scrollbar(wp, pane_scrollbars))
sb_w = wp->scrollbar_style.width + wp->scrollbar_style.pad; sb_w = wp->scrollbar_style.width + wp->scrollbar_style.pad;
@@ -675,7 +689,7 @@ screen_redraw_draw_pane_status(struct screen_redraw_ctx *ctx)
struct visible_ranges *r; struct visible_ranges *r;
struct visible_range *ri; struct visible_range *ri;
u_int i, l, x, width, size; u_int i, l, x, width, size;
int xoff, yoff; int xoff, yoff, pane_status;
log_debug("%s: %s @%u", __func__, c->name, w->id); log_debug("%s: %s @%u", __func__, c->name, w->id);
@@ -685,7 +699,10 @@ screen_redraw_draw_pane_status(struct screen_redraw_ctx *ctx)
s = &wp->status_screen; s = &wp->status_screen;
size = wp->status_size; size = wp->status_size;
if (ctx->pane_status == PANE_STATUS_TOP) pane_status = window_pane_get_pane_status(wp);
if (pane_status == PANE_STATUS_OFF)
continue;
if (pane_status == PANE_STATUS_TOP)
yoff = wp->yoff - 1; yoff = wp->yoff - 1;
else else
yoff = wp->yoff + wp->sy; yoff = wp->yoff + wp->sy;
@@ -756,16 +773,14 @@ screen_redraw_update(struct screen_redraw_ctx *ctx, uint64_t flags)
if (c->overlay_draw != NULL) if (c->overlay_draw != NULL)
flags |= CLIENT_REDRAWOVERLAY; flags |= CLIENT_REDRAWOVERLAY;
if (ctx->pane_status != PANE_STATUS_OFF) { lines = ctx->pane_lines;
lines = ctx->pane_lines; redraw = 0;
redraw = 0; TAILQ_FOREACH(wp, &w->panes, entry) {
TAILQ_FOREACH(wp, &w->panes, entry) { if (screen_redraw_make_pane_status(c, wp, ctx, lines))
if (screen_redraw_make_pane_status(c, wp, ctx, lines)) redraw = 1;
redraw = 1;
}
if (redraw)
flags |= CLIENT_REDRAWBORDERS;
} }
if (redraw)
flags |= CLIENT_REDRAWBORDERS;
return (flags); return (flags);
} }
@@ -789,7 +804,6 @@ screen_redraw_set_context(struct client *c, struct screen_redraw_ctx *ctx)
ctx->statustop = 1; ctx->statustop = 1;
ctx->statuslines = lines; ctx->statuslines = lines;
ctx->pane_status = window_get_pane_status(w);
ctx->pane_lines = options_get_number(w->options, "pane-border-lines"); ctx->pane_lines = options_get_number(w->options, "pane-border-lines");
ctx->pane_scrollbars = options_get_number(w->options, ctx->pane_scrollbars = options_get_number(w->options,
@@ -826,8 +840,7 @@ screen_redraw_screen(struct client *c)
if (flags & (CLIENT_REDRAWWINDOW|CLIENT_REDRAWBORDERS)) { if (flags & (CLIENT_REDRAWWINDOW|CLIENT_REDRAWBORDERS)) {
log_debug("%s: redrawing borders", c->name); log_debug("%s: redrawing borders", c->name);
screen_redraw_draw_borders(&ctx); screen_redraw_draw_borders(&ctx);
if (ctx.pane_status != PANE_STATUS_OFF) screen_redraw_draw_pane_status(&ctx);
screen_redraw_draw_pane_status(&ctx);
screen_redraw_draw_pane_scrollbars(&ctx); screen_redraw_draw_pane_scrollbars(&ctx);
} }
if (flags & CLIENT_REDRAWWINDOW) { if (flags & CLIENT_REDRAWWINDOW) {
@@ -997,6 +1010,7 @@ screen_redraw_draw_borders_cell(struct screen_redraw_ctx *ctx, u_int i, u_int j)
struct format_tree *ft; struct format_tree *ft;
struct window_pane *wp, *active = server_client_get_pane(c); struct window_pane *wp, *active = server_client_get_pane(c);
struct grid_cell gc; struct grid_cell gc;
enum pane_lines pane_lines;
u_int cell_type; u_int cell_type;
u_int x = ctx->ox + i, y = ctx->oy + j; u_int x = ctx->ox + i, y = ctx->oy + j;
int isolates; int isolates;
@@ -1028,7 +1042,11 @@ screen_redraw_draw_borders_cell(struct screen_redraw_ctx *ctx, u_int i, u_int j)
screen_redraw_check_is(ctx, x, y, marked_pane.wp)) screen_redraw_check_is(ctx, x, y, marked_pane.wp))
gc.attr ^= GRID_ATTR_REVERSE; gc.attr ^= GRID_ATTR_REVERSE;
} }
screen_redraw_border_set(w, wp, ctx->pane_lines, cell_type, &gc); if (wp == NULL)
pane_lines = ctx->pane_lines;
else
pane_lines = window_pane_get_pane_lines(wp);
screen_redraw_border_set(w, wp, pane_lines, cell_type, &gc);
if (cell_type == CELL_TOPBOTTOM && if (cell_type == CELL_TOPBOTTOM &&
(c->flags & CLIENT_UTF8) && (c->flags & CLIENT_UTF8) &&
@@ -1142,8 +1160,8 @@ screen_redraw_get_visible_ranges(struct window_pane *base_wp, int px,
struct window *w; struct window *w;
struct visible_range *ri; struct visible_range *ri;
static struct visible_ranges sr = { NULL, 0, 0 }; static struct visible_ranges sr = { NULL, 0, 0 };
int found_self, sb, sb_w, sb_pos; int found_self, sb, sb_w, sb_pos, no_border;
u_int lb, rb, tb, bb; int lb, rb, tb, bb, sx, ex;
u_int i, s; u_int i, s;
if (py < 0 || width == 0) if (py < 0 || width == 0)
@@ -1192,15 +1210,24 @@ screen_redraw_get_visible_ranges(struct window_pane *base_wp, int px,
continue; continue;
} }
tb = wp->yoff > 0 ? wp->yoff - 1 : 0; if (window_pane_is_floating(wp) &&
bb = wp->yoff + wp->sy; window_pane_get_pane_lines(wp) == PANE_LINES_NONE)
no_border = 1;
else
no_border = 0;
if (no_border) {
tb = wp->yoff;
bb = wp->yoff + (int)wp->sy - 1;
} else {
tb = wp->yoff > 0 ? wp->yoff - 1 : 0;
bb = wp->yoff + (int)wp->sy;
}
if (!found_self || if (!found_self ||
!window_pane_visible(wp) || !window_pane_visible(wp) ||
(u_int)py < tb || py < tb ||
(u_int)py > bb) py > bb)
continue; continue;
if (!window_pane_is_floating(wp) && if (!window_pane_is_floating(wp) && (py == tb || py == bb))
((u_int)py == tb || (u_int)py == bb))
continue; continue;
sb_w = wp->scrollbar_style.width + wp->scrollbar_style.pad; sb_w = wp->scrollbar_style.width + wp->scrollbar_style.pad;
@@ -1209,7 +1236,10 @@ screen_redraw_get_visible_ranges(struct window_pane *base_wp, int px,
for (i = 0; i < r->used; i++) { for (i = 0; i < r->used; i++) {
ri = &r->ranges[i]; ri = &r->ranges[i];
if (sb_pos == PANE_SCROLLBARS_LEFT) { if (no_border) {
lb = wp->xoff;
rb = wp->xoff + (int)wp->sx - 1;
} else if (sb_pos == PANE_SCROLLBARS_LEFT) {
if (wp->xoff > sb_w) if (wp->xoff > sb_w)
lb = wp->xoff - 1 - sb_w; lb = wp->xoff - 1 - sb_w;
else else
@@ -1220,38 +1250,41 @@ screen_redraw_get_visible_ranges(struct window_pane *base_wp, int px,
else else
lb = 0; lb = 0;
} }
if (sb_pos == PANE_SCROLLBARS_LEFT) if (!no_border) {
rb = wp->xoff + wp->sx; if (sb_pos == PANE_SCROLLBARS_LEFT)
else /* PANE_SCROLLBARS_RIGHT or none. */ rb = wp->xoff + (int)wp->sx;
rb = wp->xoff + wp->sx + sb_w; else /* PANE_SCROLLBARS_RIGHT or none. */
if (rb > w->sx) rb = wp->xoff + (int)wp->sx + sb_w;
}
if (lb < 0)
lb = 0;
if (rb < 0)
continue;
if (no_border && rb >= (int)w->sx)
rb = w->sx - 1;
else if (!no_border && rb > (int)w->sx)
rb = w->sx - 1; rb = w->sx - 1;
if (lb > ri->px && sx = ri->px;
lb < ri->px + ri->nx && ex = sx + ri->nx - 1;
rb >= ri->px + ri->nx) if (lb > sx && lb <= ex && rb > ex) {
{
/* /*
* If the left edge of floating pane falls * If the left edge of floating pane falls
* inside this range and right edge covers up * inside this range and right edge covers up
* to right of range, then shrink left edge of * to right of range, then shrink left edge of
* range. * range.
*/ */
ri->nx = lb - ri->px; ri->nx = lb - sx;
} } else if (rb >= sx && rb <= ex && lb <= sx) {
else if (rb >= ri->px &&
rb < ri->px + ri->nx &&
lb <= ri->px) {
/* /*
* Else if the right edge of floating pane falls * Else if the right edge of floating pane falls
* inside of this range and left edge covers * inside of this range and left edge covers
* the left of range, then move px forward to * the left of range, then move px forward to
* right edge of pane. * right edge of pane.
*/ */
ri->nx = ri->nx - (rb + 1 - ri->px); ri->nx = ex - rb;
ri->px = ri->px + (rb + 1 - ri->px); ri->px = rb + 1;
} } else if (lb > sx && rb <= ex) {
else if (lb > ri->px && rb < ri->px + ri->nx) {
/* /*
* Else if pane fully inside range then split * Else if pane fully inside range then split
* into 2 ranges. * into 2 ranges.
@@ -1263,11 +1296,11 @@ screen_redraw_get_visible_ranges(struct window_pane *base_wp, int px,
} }
ri = &r->ranges[i]; ri = &r->ranges[i];
r->ranges[i + 1].px = rb + 1; r->ranges[i + 1].px = rb + 1;
r->ranges[i + 1].nx = ri->px + ri->nx - (rb + 1); r->ranges[i + 1].nx = ex - rb;
/* ri->px was copied, unchanged. */ /* ri->px was copied, unchanged. */
ri->nx = lb - ri->px; ri->nx = lb - sx;
r->used++; r->used++;
} else if (lb <= ri->px && rb >= ri->px + ri->nx) { } else if (lb <= sx && rb > ex) {
/* /*
* If floating pane completely covers this range * If floating pane completely covers this range
* then delete it (make it 0 length). * then delete it (make it 0 length).

View File

@@ -1130,6 +1130,25 @@ screen_write_backspace(struct screen_write_ctx *ctx)
screen_write_set_cursor(ctx, cx, cy); screen_write_set_cursor(ctx, cx, cy);
} }
/* Is this cell a single ASCII character? */
static int
screen_write_cell_is_single(const struct grid_cell *gc)
{
if (gc->data.width != 1)
return (0);
if (gc->data.size != 1)
return (0);
if (*gc->data.data < 0x20 || *gc->data.data == 0x7f)
return (0);
if (gc->flags & GRID_FLAG_CLEARED)
return (0);
if (gc->flags & GRID_FLAG_PADDING)
return (0);
if (gc->flags & GRID_FLAG_TAB)
return (0);
return (1);
}
/* Redraw all visible cells on a line. */ /* Redraw all visible cells on a line. */
static void static void
screen_write_redraw_line(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx, screen_write_redraw_line(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx,
@@ -1138,11 +1157,14 @@ screen_write_redraw_line(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx,
struct window_pane *wp = ctx->wp; struct window_pane *wp = ctx->wp;
struct screen *s = ctx->s; struct screen *s = ctx->s;
struct grid_cell gc, ngc; struct grid_cell gc, ngc;
u_int sx = screen_size_x(s), cx, i, n; u_int sx = screen_size_x(s), cx, i;
int xoff = wp->xoff, yoff = wp->yoff; int xoff = wp->xoff, yoff = wp->yoff;
struct visible_ranges *r; struct visible_ranges *r;
struct visible_range *ri; struct visible_range *ri;
if (s->mode & MODE_SYNC)
return;
r = screen_redraw_get_visible_ranges(wp, xoff, yoff + yy, sx, NULL); r = screen_redraw_get_visible_ranges(wp, xoff, yoff + yy, sx, NULL);
for (i = 0; i < r->used; i++) { for (i = 0; i < r->used; i++) {
ri = &r->ranges[i]; ri = &r->ranges[i];
@@ -1150,20 +1172,34 @@ screen_write_redraw_line(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx,
continue; continue;
cx = ri->px - xoff; cx = ri->px - xoff;
for (n = 0; n < ri->nx && cx < sx; n++, cx++) { if (cx >= sx)
grid_view_get_cell(s->grid, cx, yy, &gc); continue;
if (~gc.flags & GRID_FLAG_SELECTED) if (cx + ri->nx > sx)
ttyctx->cell = &gc; ttyctx->n = sx - cx;
else { else
screen_select_cell(s, &ngc, &gc); ttyctx->n = ri->nx;
ttyctx->cell = &ngc; if (ttyctx->n == 0)
} continue;
ttyctx->ocx = cx;
ttyctx->ocy = yy;
ttyctx->ocx = cx; if (ttyctx->n != 1) {
ttyctx->ocy = yy; tty_write(tty_cmd_redrawline, ttyctx);
if (~s->mode & MODE_SYNC) continue;
tty_write(tty_cmd_cell, ttyctx);
} }
grid_view_get_cell(s->grid, cx, yy, &gc);
if (!screen_write_cell_is_single(&gc)) {
tty_write(tty_cmd_redrawline, ttyctx);
continue;
}
if (~gc.flags & GRID_FLAG_SELECTED)
ttyctx->cell = &gc;
else {
screen_select_cell(s, &ngc, &gc);
ttyctx->cell = &ngc;
}
tty_write(tty_cmd_cell, ttyctx);
} }
} }
@@ -2648,7 +2684,7 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
if (ri->nx == 0) if (ri->nx == 0)
continue; continue;
for (n = 0; n < ri->nx; n++) { for (n = 0; n < ri->nx; n++) {
ttyctx.ocx = ri->px + n; ttyctx.ocx = (int)ri->px - xoff + (int)n;
tty_write(tty_cmd_cell, &ttyctx); tty_write(tty_cmd_cell, &ttyctx);
} }
} }

View File

@@ -598,6 +598,7 @@ server_client_exec(struct client *c, const char *cmd)
free(msg); free(msg);
} }
/* Is the mouse inside a pane? */
static enum key_code_mouse_location static enum key_code_mouse_location
server_client_check_mouse_in_pane(struct window_pane *wp, int px, int py, server_client_check_mouse_in_pane(struct window_pane *wp, int px, int py,
u_int *sl_mpos) u_int *sl_mpos)
@@ -610,7 +611,7 @@ server_client_check_mouse_in_pane(struct window_pane *wp, int px, int py,
sb = options_get_number(w->options, "pane-scrollbars"); sb = options_get_number(w->options, "pane-scrollbars");
sb_pos = options_get_number(w->options, "pane-scrollbars-position"); sb_pos = options_get_number(w->options, "pane-scrollbars-position");
pane_status = window_get_pane_status(w); pane_status = window_pane_get_pane_status(wp);
if (window_pane_show_scrollbar(wp, sb)) { if (window_pane_show_scrollbar(wp, sb)) {
sb_w = wp->scrollbar_style.width; sb_w = wp->scrollbar_style.width;
@@ -655,6 +656,7 @@ server_client_check_mouse_in_pane(struct window_pane *wp, int px, int py,
} else /* py > sl_bottom */ } else /* py > sl_bottom */
return (KEYC_MOUSE_LOCATION_SCROLLBAR_DOWN); return (KEYC_MOUSE_LOCATION_SCROLLBAR_DOWN);
} else if (window_pane_is_floating(wp) && } else if (window_pane_is_floating(wp) &&
window_pane_get_pane_lines(wp) != PANE_LINES_NONE &&
(px == wp->xoff - 1 || (px == wp->xoff - 1 ||
py == wp->yoff - 1 || py == wp->yoff - 1 ||
py == wp->yoff + (int)wp->sy)) { py == wp->yoff + (int)wp->sy)) {
@@ -670,6 +672,9 @@ server_client_check_mouse_in_pane(struct window_pane *wp, int px, int py,
if ((w->flags & WINDOW_ZOOMED) && if ((w->flags & WINDOW_ZOOMED) &&
(~fwp->flags & PANE_ZOOMED)) (~fwp->flags & PANE_ZOOMED))
continue; continue;
if (window_pane_is_floating(fwp) &&
window_pane_get_pane_lines(fwp) == PANE_LINES_NONE)
continue;
bdr_top = fwp->yoff - 1; bdr_top = fwp->yoff - 1;
bdr_bottom = fwp->yoff + fwp->sy; bdr_bottom = fwp->yoff + fwp->sy;
if (sb_pos == PANE_SCROLLBARS_LEFT) if (sb_pos == PANE_SCROLLBARS_LEFT)
@@ -1506,12 +1511,14 @@ server_client_handle_key0(struct client *c, struct key_event *event,
return (1); return (1);
} }
/* Handle key and insert at end of queue. */
int int
server_client_handle_key(struct client *c, struct key_event *event) server_client_handle_key(struct client *c, struct key_event *event)
{ {
return (server_client_handle_key0(c, event, NULL, NULL)); return (server_client_handle_key0(c, event, NULL, NULL));
} }
/* Handle key and insert after another item. */
int int
server_client_handle_key_after(struct client *c, struct key_event *event, server_client_handle_key_after(struct client *c, struct key_event *event,
struct cmdq_item *after, struct cmdq_item **next) struct cmdq_item *after, struct cmdq_item **next)
@@ -2047,8 +2054,13 @@ server_client_check_redraw(struct client *c)
} }
} }
} }
if (needed && (left = EVBUFFER_LENGTH(tty->out)) != 0) { left = EVBUFFER_LENGTH(tty->out);
log_debug("%s: redraw deferred (%zu left)", c->name, left); if (needed && (left != 0 || (tty->flags & TTY_BLOCK))) {
if (left != 0) {
log_debug("%s: redraw deferred (%zu left)", c->name,
left);
} else
log_debug("%s: redraw deferred (blocked)", c->name);
if (!evtimer_initialized(&ev)) if (!evtimer_initialized(&ev))
evtimer_set(&ev, server_client_redraw_timer, NULL); evtimer_set(&ev, server_client_redraw_timer, NULL);
if (!evtimer_pending(&ev, NULL)) { if (!evtimer_pending(&ev, NULL)) {

13
tmux.1
View File

@@ -3552,6 +3552,7 @@ but a different format may be specified with
.Tg newp .Tg newp
.It Xo Ic new\-pane .It Xo Ic new\-pane
.Op Fl bdefhIkPvWZ .Op Fl bdefhIkPvWZ
.Op Fl B Ar border\-lines
.Op Fl c Ar start\-directory .Op Fl c Ar start\-directory
.Op Fl e Ar environment .Op Fl e Ar environment
.Op Fl F Ar format .Op Fl F Ar format
@@ -3583,6 +3584,9 @@ sets the border style when the pane is inactive (see
.Sx STYLES ) . .Sx STYLES ) .
.Fl T .Fl T
sets the pane title. sets the pane title.
.Fl B
sets the pane border lines for floating panes; see
.Ic pane\-border\-lines .
.Pp .Pp
.Fl h .Fl h
does a horizontal split and does a horizontal split and
@@ -5758,6 +5762,8 @@ simple ASCII characters
the pane number the pane number
.It spaces .It spaces
space characters space characters
.It none
no border for floating panes
.El .El
.Pp .Pp
.Ql double .Ql double
@@ -5766,9 +5772,14 @@ and
will fall back to standard ACS line drawing when UTF\-8 is not supported. will fall back to standard ACS line drawing when UTF\-8 is not supported.
.Pp .Pp
.It Xo Ic pane\-border\-status .It Xo Ic pane\-border\-status
.Op Ic off | top | bottom .Op Ic off | top | bottom | top\-floating | bottom\-floating
.Xc .Xc
Turn pane border status lines off or set their position. Turn pane border status lines off or set their position.
If set to
.Ic top\-floating
or
.Ic bottom\-floating ,
status lines are shown only on floating panes.
.Pp .Pp
.It Ic pane\-border\-style Ar style .It Ic pane\-border\-style Ar style
Set the pane border style for panes aside from the active pane. Set the pane border style for panes aside from the active pane.

9
tmux.h
View File

@@ -1091,7 +1091,8 @@ enum pane_lines {
PANE_LINES_HEAVY, PANE_LINES_HEAVY,
PANE_LINES_SIMPLE, PANE_LINES_SIMPLE,
PANE_LINES_NUMBER, PANE_LINES_NUMBER,
PANE_LINES_SPACES PANE_LINES_SPACES,
PANE_LINES_NONE
}; };
/* Pane border indicator option. */ /* Pane border indicator option. */
@@ -1112,7 +1113,6 @@ struct screen_redraw_ctx {
u_int statuslines; u_int statuslines;
int statustop; int statustop;
int pane_status;
enum pane_lines pane_lines; enum pane_lines pane_lines;
int pane_scrollbars; int pane_scrollbars;
@@ -1457,6 +1457,8 @@ TAILQ_HEAD(winlink_stack, winlink);
#define PANE_STATUS_OFF 0 #define PANE_STATUS_OFF 0
#define PANE_STATUS_TOP 1 #define PANE_STATUS_TOP 1
#define PANE_STATUS_BOTTOM 2 #define PANE_STATUS_BOTTOM 2
#define PANE_STATUS_TOP_FLOATING 3
#define PANE_STATUS_BOTTOM_FLOATING 4
/* Pane scrollbars option. */ /* Pane scrollbars option. */
#define PANE_SCROLLBARS_OFF 0 #define PANE_SCROLLBARS_OFF 0
@@ -2746,6 +2748,7 @@ void tty_write(void (*)(struct tty *, const struct tty_ctx *),
void tty_cmd_alignmenttest(struct tty *, const struct tty_ctx *); void tty_cmd_alignmenttest(struct tty *, const struct tty_ctx *);
void tty_cmd_cell(struct tty *, const struct tty_ctx *); void tty_cmd_cell(struct tty *, const struct tty_ctx *);
void tty_cmd_cells(struct tty *, const struct tty_ctx *); void tty_cmd_cells(struct tty *, const struct tty_ctx *);
void tty_cmd_redrawline(struct tty *, const struct tty_ctx *);
void tty_cmd_clearendofline(struct tty *, const struct tty_ctx *); void tty_cmd_clearendofline(struct tty *, const struct tty_ctx *);
void tty_cmd_clearendofscreen(struct tty *, const struct tty_ctx *); void tty_cmd_clearendofscreen(struct tty *, const struct tty_ctx *);
void tty_cmd_clearline(struct tty *, const struct tty_ctx *); void tty_cmd_clearline(struct tty *, const struct tty_ctx *);
@@ -3529,7 +3532,9 @@ int window_pane_get_bg_control_client(struct window_pane *);
int window_get_bg_client(struct window_pane *); int window_get_bg_client(struct window_pane *);
enum client_theme window_pane_get_theme(struct window_pane *); enum client_theme window_pane_get_theme(struct window_pane *);
void window_pane_send_theme_update(struct window_pane *); void window_pane_send_theme_update(struct window_pane *);
enum pane_lines window_pane_get_pane_lines(struct window_pane *);
int window_get_pane_status(struct window *); int window_get_pane_status(struct window *);
int window_pane_get_pane_status(struct window_pane *);
struct style_range *window_pane_status_get_range(struct window_pane *, u_int, struct style_range *window_pane_status_get_range(struct window_pane *, u_int,
u_int); u_int);
int window_pane_is_floating(struct window_pane *); int window_pane_is_floating(struct window_pane *);

20
tty.c
View File

@@ -1435,6 +1435,26 @@ tty_draw_pane(struct tty *tty, const struct tty_ctx *ctx, u_int py)
} }
} }
void
tty_cmd_redrawline(struct tty *tty, const struct tty_ctx *ctx)
{
u_int i, x, rx, ry, j;
struct visible_ranges *r;
struct visible_range *rr;
if (tty_clamp_line(tty, ctx, ctx->ocx, ctx->ocy, ctx->n,
&i, &x, &rx, &ry)) {
r = tty_check_overlay_range(tty, x, ry, rx);
for (j = 0; j < r->used; j++) {
rr = &r->ranges[j];
if (rr->nx == 0)
continue;
tty_draw_line(tty, ctx->s, ctx->ocx + i + rr->px - x,
ctx->ocy, rr->nx, rr->px, ry, &ctx->style_ctx);
}
}
}
/* Check if character needs to be mapped for codeset. */ /* Check if character needs to be mapped for codeset. */
const struct grid_cell * const struct grid_cell *
tty_check_codeset(struct tty *tty, const struct grid_cell *gc) tty_check_codeset(struct tty *tty, const struct grid_cell *gc)

View File

@@ -686,11 +686,18 @@ window_get_active_at(struct window *w, u_int x, u_int y)
continue; continue;
} }
} else { } else {
/* Floating - include all borders. */ if (window_pane_get_pane_lines(wp) == PANE_LINES_NONE) {
if ((int)x < xoff - 1 || x > xoff + sx) if ((int)x < xoff || (int)x >= xoff + (int)sx)
continue; continue;
if ((int)y < yoff - 1 || y > yoff + sy) if ((int)y < yoff || (int)y >= yoff + (int)sy)
continue; continue;
} else {
/* Floating - include all borders. */
if ((int)x < xoff - 1 || x > xoff + sx)
continue;
if ((int)y < yoff - 1 || y > yoff + sy)
continue;
}
} }
return (wp); return (wp);
} }
@@ -2168,16 +2175,14 @@ struct style_range *
window_pane_status_get_range(struct window_pane *wp, u_int x, u_int y) window_pane_status_get_range(struct window_pane *wp, u_int x, u_int y)
{ {
struct style_ranges *srs; struct style_ranges *srs;
struct window *w;
u_int line; u_int line;
int pane_status; int pane_status;
if (wp == NULL) if (wp == NULL)
return (NULL); return (NULL);
w = wp->window;
srs = &wp->border_status_line.ranges; srs = &wp->border_status_line.ranges;
pane_status = window_get_pane_status(w); pane_status = window_pane_get_pane_status(wp);
if (pane_status == PANE_STATUS_TOP) if (pane_status == PANE_STATUS_TOP)
line = wp->yoff - 1; line = wp->yoff - 1;
else if (pane_status == PANE_STATUS_BOTTOM) else if (pane_status == PANE_STATUS_BOTTOM)
@@ -2192,10 +2197,46 @@ window_pane_status_get_range(struct window_pane *wp, u_int x, u_int y)
return (style_ranges_get_range(srs, x - wp->xoff - 2)); return (style_ranges_get_range(srs, x - wp->xoff - 2));
} }
enum pane_lines
window_pane_get_pane_lines(struct window_pane *wp)
{
struct options *oo;
if (!window_pane_is_floating(wp))
oo = wp->window->options;
else
oo = wp->options;
return (options_get_number(oo, "pane-border-lines"));
}
int int
window_get_pane_status(struct window *w) window_get_pane_status(struct window *w)
{ {
return (options_get_number(w->options, "pane-border-status")); int status;
status = options_get_number(w->options, "pane-border-status");
if (status == PANE_STATUS_TOP_FLOATING ||
status == PANE_STATUS_BOTTOM_FLOATING)
return (PANE_STATUS_OFF);
return (status);
}
int
window_pane_get_pane_status(struct window_pane *wp)
{
int status;
if (!window_pane_is_floating(wp))
return (window_get_pane_status(wp->window));
if (window_pane_get_pane_lines(wp) == PANE_LINES_NONE)
return (PANE_STATUS_OFF);
status = options_get_number(wp->options, "pane-border-status");
if (status == PANE_STATUS_TOP_FLOATING)
return (PANE_STATUS_TOP);
if (status == PANE_STATUS_BOTTOM_FLOATING)
return (PANE_STATUS_BOTTOM);
return (status);
} }
int int