diff --git a/cmd-join-pane.c b/cmd-join-pane.c index dee370cc..04cc0676 100644 --- a/cmd-join-pane.c +++ b/cmd-join-pane.c @@ -70,20 +70,24 @@ cmd_join_pane_place(struct cmdq_item *item, struct winlink *wl, struct window_pane *owp; int wx = w->sx, wy = w->sy, px = lc->sx; 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) { - xoff = 1; - yoff = 1; + xoff = border; + yoff = border; } else if (strcmp(position, "top-centre") == 0 || strcmp(position, "top-center") == 0) { xoff = (wx - px) / 2; - yoff = 1; + yoff = border; } else if (strcmp(position, "top-right") == 0) { - xoff = wx - px - 1; - yoff = 1; + xoff = wx - px - border; + yoff = border; } else if (strcmp(position, "centre-left") == 0 || strcmp(position, "center-left") == 0) { - xoff = 1; + xoff = border; yoff = (wy - py) / 2; } else if (strcmp(position, "centre") == 0 || strcmp(position, "center") == 0) { @@ -91,18 +95,18 @@ cmd_join_pane_place(struct cmdq_item *item, struct winlink *wl, yoff = (wy - py) / 2; } else if (strcmp(position, "centre-right") == 0 || strcmp(position, "center-right") == 0) { - xoff = wx - px - 1; + xoff = wx - px - border; yoff = (wy - py) / 2; } else if (strcmp(position, "bottom-left") == 0) { - xoff = 1; - yoff = wy - py - 1; + xoff = border; + yoff = wy - py - border; } else if (strcmp(position, "bottom-centre") == 0 || strcmp(position, "bottom-center") == 0) { xoff = (wx - px) / 2; - yoff = wy - py - 1; + yoff = wy - py - border; } else if (strcmp(position, "bottom-right") == 0) { - xoff = wx - px - 1; - yoff = wy - py - 1; + xoff = wx - px - border; + yoff = wy - py - border; } else if (strcmp(position, "top-left-centre") == 0 || strcmp(position, "top-left-center") == 0) { xoff = wx / 4 - px / 2; diff --git a/cmd-split-window.c b/cmd-split-window.c index 30426144..2b9a4542 100644 --- a/cmd-split-window.c +++ b/cmd-split-window.c @@ -38,9 +38,10 @@ const struct cmd_entry cmd_new_pane_entry = { .name = "new-pane", .alias = "newp", - .args = { "bc: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] " - "[-F format] [-l size] [-m message] [-p percentage] " + .args = { "bB:c:de:EfF:hIkl:Lm:p:PR:s:S:t:T:vWx:X:y:Y:Z", 0, -1, NULL }, + .usage = "[-bdefhIklPvWZ] [-B border-lines] " + "[-c start-directory] [-e environment] " + "[-F format] [-l size] [-m message] [-p percentage] " "[-s style] [-S active-border-style] " "[-R inactive-border-style] [-T title] [-x width] [-y height] " "[-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 cmd_find_state fs; int input, empty, is_floating, flags = 0; - const char *template, *style; + const char *template, *style, *value; char *cause = NULL, *cp, *title; + struct options_entry *oe; struct args_value *av; + enum pane_lines lines; u_int count = args_count(args); 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); } } + 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')) { options_set_number(new_wp->options, "remain-on-exit", 3); if (args_has(args, 'm')) { diff --git a/format.c b/format.c index aa49ceb5..06192962 100644 --- a/format.c +++ b/format.c @@ -1157,15 +1157,13 @@ static void * format_cb_pane_at_top(struct format_tree *ft) { struct window_pane *wp = ft->wp; - struct window *w; int status, flag; char *value; if (wp == NULL) return (NULL); - w = wp->window; - status = window_get_pane_status(w); + status = window_pane_get_pane_status(wp); if (status == PANE_STATUS_TOP) flag = (wp->yoff == 1); else @@ -1187,7 +1185,7 @@ format_cb_pane_at_bottom(struct format_tree *ft) return (NULL); w = wp->window; - status = options_get_number(w->options, "pane-border-status"); + status = window_pane_get_pane_status(wp); if (status == PANE_STATUS_BOTTOM) flag = (wp->yoff + (int)wp->sy == (int)w->sy - 1); else diff --git a/layout.c b/layout.c index 6cb2cad1..a89fee82 100644 --- a/layout.c +++ b/layout.c @@ -853,7 +853,8 @@ layout_resize_floating_pane_to(struct window_pane *wp, enum layout_type type, return; } - if (size >= PANE_MINIMUM + 2) + if (window_pane_get_pane_lines(wp) != PANE_LINES_NONE && + size >= PANE_MINIMUM + 2) size -= 2; if (size < PANE_MINIMUM || size > PANE_MAXIMUM) { *cause = xstrdup("size is too big or too small"); diff --git a/options-table.c b/options-table.c index c3bdca0e..fd4c4f42 100644 --- a/options-table.c +++ b/options-table.c @@ -70,13 +70,13 @@ static const char *options_table_pane_scrollbars_position_list[] = { "right", "left", NULL }; 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[] = { "off", "colour", "arrows", "both", NULL }; 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[] = { "single", "double", "heavy", "simple", "rounded", "padded", "none", NULL @@ -1386,7 +1386,7 @@ const struct options_table_entry options_table[] = { { .name = "pane-border-lines", .type = OPTIONS_TABLE_CHOICE, - .scope = OPTIONS_TABLE_WINDOW, + .scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE, .choices = options_table_pane_border_lines_list, .default_num = PANE_LINES_SINGLE, .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", .type = OPTIONS_TABLE_CHOICE, - .scope = OPTIONS_TABLE_WINDOW, + .scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE, .choices = options_table_pane_status_list, .default_num = PANE_STATUS_OFF, .text = "Position of the pane status lines." diff --git a/screen-redraw.c b/screen-redraw.c index b835e4d5..da183ce5 100644 --- a/screen-redraw.c +++ b/screen-redraw.c @@ -87,6 +87,7 @@ screen_redraw_border_set(struct window *w, struct window_pane *wp, gc->attr &= ~GRID_ATTR_CHARSET; utf8_set(&gc->data, SIMPLE_BORDERS[cell_type]); break; + case PANE_LINES_NONE: case PANE_LINES_SPACES: gc->attr &= ~GRID_ATTR_CHARSET; 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; 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 sb_pos, sx = wp->sx, sy = wp->sy; 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) 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? */ if (window_pane_show_scrollbar(wp, pane_scrollbars)) 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? */ - if (ctx->pane_status == PANE_STATUS_BOTTOM) + if (window_pane_get_pane_status(wp) == PANE_STATUS_BOTTOM) sy--; if (px > sx || py > sy) return (0); @@ -327,7 +333,8 @@ screen_redraw_type_of_cell(struct screen_redraw_ctx *ctx, { struct client *c = ctx->c; 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; /* 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_pane *wp, *start; int sx = w->sx, sy = w->sy; - int pane_status = ctx->pane_status; + int pane_status; int border, pane_scrollbars = ctx->pane_scrollbars; int pane_status_line, tiled_only = 0, left, right; 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 * 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_TOP) 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 style_line_entry *sle = &wp->border_status_line; 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 max_width; u_int width, i, cell_type, px, py; struct screen_write_ctx ctx; struct screen old; + if (pane_status == PANE_STATUS_OFF) { + wp->status_size = 0; + return (0); + } + if (window_pane_show_scrollbar(wp, pane_scrollbars)) 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_range *ri; 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); @@ -685,7 +699,10 @@ screen_redraw_draw_pane_status(struct screen_redraw_ctx *ctx) s = &wp->status_screen; 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; else 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) flags |= CLIENT_REDRAWOVERLAY; - if (ctx->pane_status != PANE_STATUS_OFF) { - lines = ctx->pane_lines; - redraw = 0; - TAILQ_FOREACH(wp, &w->panes, entry) { - if (screen_redraw_make_pane_status(c, wp, ctx, lines)) - redraw = 1; - } - if (redraw) - flags |= CLIENT_REDRAWBORDERS; + lines = ctx->pane_lines; + redraw = 0; + TAILQ_FOREACH(wp, &w->panes, entry) { + if (screen_redraw_make_pane_status(c, wp, ctx, lines)) + redraw = 1; } + if (redraw) + flags |= CLIENT_REDRAWBORDERS; return (flags); } @@ -789,7 +804,6 @@ screen_redraw_set_context(struct client *c, struct screen_redraw_ctx *ctx) ctx->statustop = 1; ctx->statuslines = lines; - ctx->pane_status = window_get_pane_status(w); ctx->pane_lines = options_get_number(w->options, "pane-border-lines"); ctx->pane_scrollbars = options_get_number(w->options, @@ -826,8 +840,7 @@ screen_redraw_screen(struct client *c) if (flags & (CLIENT_REDRAWWINDOW|CLIENT_REDRAWBORDERS)) { log_debug("%s: redrawing borders", c->name); 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); } 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 window_pane *wp, *active = server_client_get_pane(c); struct grid_cell gc; + enum pane_lines pane_lines; u_int cell_type; u_int x = ctx->ox + i, y = ctx->oy + j; 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)) 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 && (c->flags & CLIENT_UTF8) && @@ -1142,8 +1160,8 @@ screen_redraw_get_visible_ranges(struct window_pane *base_wp, int px, struct window *w; struct visible_range *ri; static struct visible_ranges sr = { NULL, 0, 0 }; - int found_self, sb, sb_w, sb_pos; - u_int lb, rb, tb, bb; + int found_self, sb, sb_w, sb_pos, no_border; + int lb, rb, tb, bb, sx, ex; u_int i, s; if (py < 0 || width == 0) @@ -1192,15 +1210,24 @@ screen_redraw_get_visible_ranges(struct window_pane *base_wp, int px, continue; } - tb = wp->yoff > 0 ? wp->yoff - 1 : 0; - bb = wp->yoff + wp->sy; + if (window_pane_is_floating(wp) && + 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 || !window_pane_visible(wp) || - (u_int)py < tb || - (u_int)py > bb) + py < tb || + py > bb) continue; - if (!window_pane_is_floating(wp) && - ((u_int)py == tb || (u_int)py == bb)) + if (!window_pane_is_floating(wp) && (py == tb || py == bb)) continue; 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++) { 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) lb = wp->xoff - 1 - sb_w; else @@ -1220,38 +1250,41 @@ screen_redraw_get_visible_ranges(struct window_pane *base_wp, int px, else lb = 0; } - if (sb_pos == PANE_SCROLLBARS_LEFT) - rb = wp->xoff + wp->sx; - else /* PANE_SCROLLBARS_RIGHT or none. */ - rb = wp->xoff + wp->sx + sb_w; - if (rb > w->sx) + if (!no_border) { + if (sb_pos == PANE_SCROLLBARS_LEFT) + rb = wp->xoff + (int)wp->sx; + else /* PANE_SCROLLBARS_RIGHT or none. */ + 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; - if (lb > ri->px && - lb < ri->px + ri->nx && - rb >= ri->px + ri->nx) - { + sx = ri->px; + ex = sx + ri->nx - 1; + if (lb > sx && lb <= ex && rb > ex) { /* * If the left edge of floating pane falls * inside this range and right edge covers up * to right of range, then shrink left edge of * range. */ - ri->nx = lb - ri->px; - } - else if (rb >= ri->px && - rb < ri->px + ri->nx && - lb <= ri->px) { + ri->nx = lb - sx; + } else if (rb >= sx && rb <= ex && lb <= sx) { /* * Else if the right edge of floating pane falls * inside of this range and left edge covers * the left of range, then move px forward to * right edge of pane. */ - ri->nx = ri->nx - (rb + 1 - ri->px); - ri->px = ri->px + (rb + 1 - ri->px); - } - else if (lb > ri->px && rb < ri->px + ri->nx) { + ri->nx = ex - rb; + ri->px = rb + 1; + } else if (lb > sx && rb <= ex) { /* * Else if pane fully inside range then split * into 2 ranges. @@ -1263,11 +1296,11 @@ screen_redraw_get_visible_ranges(struct window_pane *base_wp, int px, } ri = &r->ranges[i]; 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->nx = lb - ri->px; + ri->nx = lb - sx; 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 * then delete it (make it 0 length). diff --git a/screen-write.c b/screen-write.c index 0b6db4e3..ba1dea86 100644 --- a/screen-write.c +++ b/screen-write.c @@ -1130,6 +1130,25 @@ screen_write_backspace(struct screen_write_ctx *ctx) 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. */ static void 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 screen *s = ctx->s; 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; struct visible_ranges *r; struct visible_range *ri; + if (s->mode & MODE_SYNC) + return; + r = screen_redraw_get_visible_ranges(wp, xoff, yoff + yy, sx, NULL); for (i = 0; i < r->used; i++) { ri = &r->ranges[i]; @@ -1150,20 +1172,34 @@ screen_write_redraw_line(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx, continue; cx = ri->px - xoff; - for (n = 0; n < ri->nx && cx < sx; n++, cx++) { - grid_view_get_cell(s->grid, cx, yy, &gc); - if (~gc.flags & GRID_FLAG_SELECTED) - ttyctx->cell = &gc; - else { - screen_select_cell(s, &ngc, &gc); - ttyctx->cell = &ngc; - } + if (cx >= sx) + continue; + if (cx + ri->nx > sx) + ttyctx->n = sx - cx; + else + ttyctx->n = ri->nx; + if (ttyctx->n == 0) + continue; + ttyctx->ocx = cx; + ttyctx->ocy = yy; - ttyctx->ocx = cx; - ttyctx->ocy = yy; - if (~s->mode & MODE_SYNC) - tty_write(tty_cmd_cell, ttyctx); + if (ttyctx->n != 1) { + tty_write(tty_cmd_redrawline, ttyctx); + continue; } + + 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) continue; 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); } } diff --git a/server-client.c b/server-client.c index 665bcd01..2e7194b5 100644 --- a/server-client.c +++ b/server-client.c @@ -598,6 +598,7 @@ server_client_exec(struct client *c, const char *cmd) free(msg); } +/* 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, 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_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)) { 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 */ return (KEYC_MOUSE_LOCATION_SCROLLBAR_DOWN); } else if (window_pane_is_floating(wp) && + window_pane_get_pane_lines(wp) != PANE_LINES_NONE && (px == wp->xoff - 1 || py == wp->yoff - 1 || 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) && (~fwp->flags & PANE_ZOOMED)) continue; + if (window_pane_is_floating(fwp) && + window_pane_get_pane_lines(fwp) == PANE_LINES_NONE) + continue; bdr_top = fwp->yoff - 1; bdr_bottom = fwp->yoff + fwp->sy; if (sb_pos == PANE_SCROLLBARS_LEFT) @@ -1506,12 +1511,14 @@ server_client_handle_key0(struct client *c, struct key_event *event, return (1); } +/* Handle key and insert at end of queue. */ int server_client_handle_key(struct client *c, struct key_event *event) { return (server_client_handle_key0(c, event, NULL, NULL)); } +/* Handle key and insert after another item. */ int server_client_handle_key_after(struct client *c, struct key_event *event, 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) { - log_debug("%s: redraw deferred (%zu left)", c->name, left); + left = EVBUFFER_LENGTH(tty->out); + 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)) evtimer_set(&ev, server_client_redraw_timer, NULL); if (!evtimer_pending(&ev, NULL)) { diff --git a/tmux.1 b/tmux.1 index c88b9071..5f9b71fd 100644 --- a/tmux.1 +++ b/tmux.1 @@ -3552,6 +3552,7 @@ but a different format may be specified with .Tg newp .It Xo Ic new\-pane .Op Fl bdefhIkPvWZ +.Op Fl B Ar border\-lines .Op Fl c Ar start\-directory .Op Fl e Ar environment .Op Fl F Ar format @@ -3583,6 +3584,9 @@ sets the border style when the pane is inactive (see .Sx STYLES ) . .Fl T sets the pane title. +.Fl B +sets the pane border lines for floating panes; see +.Ic pane\-border\-lines . .Pp .Fl h does a horizontal split and @@ -5758,6 +5762,8 @@ simple ASCII characters the pane number .It spaces space characters +.It none +no border for floating panes .El .Pp .Ql double @@ -5766,9 +5772,14 @@ and will fall back to standard ACS line drawing when UTF\-8 is not supported. .Pp .It Xo Ic pane\-border\-status -.Op Ic off | top | bottom +.Op Ic off | top | bottom | top\-floating | bottom\-floating .Xc 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 .It Ic pane\-border\-style Ar style Set the pane border style for panes aside from the active pane. diff --git a/tmux.h b/tmux.h index b4788b5e..9a90dc0d 100644 --- a/tmux.h +++ b/tmux.h @@ -1091,7 +1091,8 @@ enum pane_lines { PANE_LINES_HEAVY, PANE_LINES_SIMPLE, PANE_LINES_NUMBER, - PANE_LINES_SPACES + PANE_LINES_SPACES, + PANE_LINES_NONE }; /* Pane border indicator option. */ @@ -1112,7 +1113,6 @@ struct screen_redraw_ctx { u_int statuslines; int statustop; - int pane_status; enum pane_lines pane_lines; int pane_scrollbars; @@ -1457,6 +1457,8 @@ TAILQ_HEAD(winlink_stack, winlink); #define PANE_STATUS_OFF 0 #define PANE_STATUS_TOP 1 #define PANE_STATUS_BOTTOM 2 +#define PANE_STATUS_TOP_FLOATING 3 +#define PANE_STATUS_BOTTOM_FLOATING 4 /* Pane scrollbars option. */ #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_cell(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_clearendofscreen(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 *); enum client_theme window_pane_get_theme(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_pane_get_pane_status(struct window_pane *); struct style_range *window_pane_status_get_range(struct window_pane *, u_int, u_int); int window_pane_is_floating(struct window_pane *); diff --git a/tty.c b/tty.c index 1c515d68..b1c2e84c 100644 --- a/tty.c +++ b/tty.c @@ -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. */ const struct grid_cell * tty_check_codeset(struct tty *tty, const struct grid_cell *gc) diff --git a/window.c b/window.c index 6f6f42f9..ff3481c1 100644 --- a/window.c +++ b/window.c @@ -686,11 +686,18 @@ window_get_active_at(struct window *w, u_int x, u_int y) continue; } } else { - /* Floating - include all borders. */ - if ((int)x < xoff - 1 || x > xoff + sx) - continue; - if ((int)y < yoff - 1 || y > yoff + sy) - continue; + if (window_pane_get_pane_lines(wp) == PANE_LINES_NONE) { + if ((int)x < xoff || (int)x >= xoff + (int)sx) + continue; + if ((int)y < yoff || (int)y >= yoff + (int)sy) + 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); } @@ -2168,16 +2175,14 @@ struct style_range * window_pane_status_get_range(struct window_pane *wp, u_int x, u_int y) { struct style_ranges *srs; - struct window *w; u_int line; int pane_status; if (wp == NULL) return (NULL); - w = wp->window; 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) line = wp->yoff - 1; 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)); } +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 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