Merge branch 'floating_panes' into floating_panes_staging

This commit is contained in:
Nicholas Marriott
2026-05-20 09:41:43 +01:00
5 changed files with 210 additions and 235 deletions

View File

@@ -63,8 +63,7 @@ cmd_kill_pane_exec(struct cmd *self, struct cmdq_item *item)
} }
if (wp == NULL) { if (wp == NULL) {
/* No active window pane. */ cmdq_error(item, "no active pane to kill");
cmdq_error(item, "No active pane to kill.");
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
server_kill_pane(wp); server_kill_pane(wp);

View File

@@ -79,7 +79,6 @@ control_notify_window_pane_changed(struct window *w)
if (w->active == NULL) if (w->active == NULL)
return; return;
TAILQ_FOREACH(c, &clients, entry) { TAILQ_FOREACH(c, &clients, entry) {
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c)) if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
continue; continue;

View File

@@ -122,13 +122,13 @@ screen_redraw_two_panes(struct window *w, enum layout_type *type)
/* Check if cell is on the border of a pane. */ /* Check if cell is on the border of a pane. */
static enum screen_redraw_border_type static enum screen_redraw_border_type
screen_redraw_pane_border(struct screen_redraw_ctx *ctx, struct window_pane *wp, screen_redraw_pane_border(struct screen_redraw_ctx *ctx, struct window_pane *wp,
u_int px, u_int py) int px, int py)
{ {
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, pane_status = ctx->pane_status;
int pane_scrollbars = ctx->pane_scrollbars, sb_w = 0; int pane_scrollbars = ctx->pane_scrollbars, sb_w = 0;
int sb_pos; int sb_pos, sx = wp->sx, sy = wp->sy;
enum layout_type split_type; enum layout_type split_type;
if (pane_scrollbars != 0) if (pane_scrollbars != 0)
@@ -137,34 +137,32 @@ screen_redraw_pane_border(struct screen_redraw_ctx *ctx, struct window_pane *wp,
sb_pos = 0; sb_pos = 0;
/* Inside pane. */ /* Inside pane. */
if ((int)px >= wp->xoff && (int)px < ex && if (px >= wp->xoff && px < ex && py >= wp->yoff && py < ey)
(int)py >= wp->yoff && (int)py < ey)
return (SCREEN_REDRAW_INSIDE); return (SCREEN_REDRAW_INSIDE);
/* 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;
/* Floating pane borders */ /* Floating pane borders. */
if (wp->flags & PANE_FLOATING) { if (wp->flags & PANE_FLOATING) {
if ((int)py >= wp->yoff - 1 && if (py >= wp->yoff - 1 && py <= wp->yoff + sy) {
(int)py <= wp->yoff + (int)wp->sy) {
if (sb_pos == PANE_SCROLLBARS_LEFT) { if (sb_pos == PANE_SCROLLBARS_LEFT) {
if ((int)px == wp->xoff - 1 - sb_w) if (px == wp->xoff - 1 - sb_w)
return (SCREEN_REDRAW_BORDER_LEFT); return (SCREEN_REDRAW_BORDER_LEFT);
if ((int)px == wp->xoff + (int)wp->sx) if (px == wp->xoff + sx)
return (SCREEN_REDRAW_BORDER_RIGHT); return (SCREEN_REDRAW_BORDER_RIGHT);
} else { /* PANE_SCROLLBARS_RIGHT or none. */ } else { /* PANE_SCROLLBARS_RIGHT or none. */
if ((int)px == wp->xoff - 1) if (px == wp->xoff - 1)
return (SCREEN_REDRAW_BORDER_LEFT); return (SCREEN_REDRAW_BORDER_LEFT);
if ((int)px == wp->xoff + (int)wp->sx + sb_w) if (px == wp->xoff + sx + sb_w)
return (SCREEN_REDRAW_BORDER_RIGHT); return (SCREEN_REDRAW_BORDER_RIGHT);
} }
} }
if ((int)px >= wp->xoff && (int)px <= wp->xoff + (int)wp->sx) { if (px >= wp->xoff && px <= wp->xoff + sx) {
if ((int)py == wp->yoff - 1) if (py == wp->yoff - 1)
return (SCREEN_REDRAW_BORDER_TOP); return (SCREEN_REDRAW_BORDER_TOP);
if ((int)py == wp->yoff + (int)wp->sy) if (py == wp->yoff + sy)
return (SCREEN_REDRAW_BORDER_BOTTOM); return (SCREEN_REDRAW_BORDER_BOTTOM);
} }
return (SCREEN_REDRAW_OUTSIDE); return (SCREEN_REDRAW_OUTSIDE);
@@ -182,31 +180,32 @@ screen_redraw_pane_border(struct screen_redraw_ctx *ctx, struct window_pane *wp,
} }
/* /*
* Left/right borders. The wp->sy / 2 test is to colour only half the * Left/right borders. The sy / 2 test is to colour only half the
* active window's border when there are two panes. * active window's border when there are two panes.
*/ */
if ((wp->yoff == 0 || (int)py >= wp->yoff - 1) && (int)py <= ey) { if ((wp->yoff == 0 || py >= wp->yoff - 1) && py <= ey) {
if (sb_pos == PANE_SCROLLBARS_LEFT) { if (sb_pos == PANE_SCROLLBARS_LEFT) {
if (wp->xoff - sb_w == 0 && px == wp->sx + sb_w) if (wp->xoff - sb_w == 0 && px == sx + sb_w) {
if (!hsplit || (hsplit && py <= wp->sy / 2)) if (!hsplit || (hsplit && py <= sy / 2))
return (SCREEN_REDRAW_BORDER_RIGHT); return (SCREEN_REDRAW_BORDER_RIGHT);
}
if (wp->xoff - sb_w != 0) { if (wp->xoff - sb_w != 0) {
if ((int)px == wp->xoff - sb_w - 1 && if (px == wp->xoff - sb_w - 1 &&
(!hsplit || (hsplit && py > wp->sy / 2))) (!hsplit || (hsplit && py > sy / 2)))
return (SCREEN_REDRAW_BORDER_LEFT); return (SCREEN_REDRAW_BORDER_LEFT);
if ((int)px == wp->xoff + if (px == wp->xoff + sx + sb_w - 1)
(int)wp->sx + sb_w - 1)
return (SCREEN_REDRAW_BORDER_RIGHT); return (SCREEN_REDRAW_BORDER_RIGHT);
} }
} else { /* sb_pos == PANE_SCROLLBARS_RIGHT or disabled */ } else { /* sb_pos == PANE_SCROLLBARS_RIGHT or disabled */
if (wp->xoff == 0 && px == wp->sx + sb_w) if (wp->xoff == 0 && px == sx + sb_w) {
if (!hsplit || (hsplit && py <= wp->sy / 2)) if (!hsplit || (hsplit && py <= sy / 2))
return (SCREEN_REDRAW_BORDER_RIGHT); return (SCREEN_REDRAW_BORDER_RIGHT);
}
if (wp->xoff != 0) { if (wp->xoff != 0) {
if ((int)px == wp->xoff - 1 && if (px == wp->xoff - 1 &&
(!hsplit || (hsplit && py > wp->sy / 2))) (!hsplit || (hsplit && py > sy / 2)))
return (SCREEN_REDRAW_BORDER_LEFT); return (SCREEN_REDRAW_BORDER_LEFT);
if (px == wp->xoff + wp->sx + sb_w) if (px == wp->xoff + sx + sb_w)
return (SCREEN_REDRAW_BORDER_RIGHT); return (SCREEN_REDRAW_BORDER_RIGHT);
} }
} }
@@ -214,31 +213,27 @@ screen_redraw_pane_border(struct screen_redraw_ctx *ctx, struct window_pane *wp,
/* Top/bottom borders. */ /* Top/bottom borders. */
if (vsplit && pane_status == PANE_STATUS_OFF && sb_w == 0) { if (vsplit && pane_status == PANE_STATUS_OFF && sb_w == 0) {
if (wp->yoff == 0 && py == wp->sy && px <= wp->sx / 2) if (wp->yoff == 0 && py == sy && px <= sx / 2)
return (SCREEN_REDRAW_BORDER_BOTTOM); return (SCREEN_REDRAW_BORDER_BOTTOM);
if (wp->yoff != 0 && (int)py == wp->yoff - 1 && px > wp->sx / 2) if (wp->yoff != 0 && py == wp->yoff - 1 && px > sx / 2)
return (SCREEN_REDRAW_BORDER_TOP); return (SCREEN_REDRAW_BORDER_TOP);
} else { } else {
if (sb_pos == PANE_SCROLLBARS_LEFT) { if (sb_pos == PANE_SCROLLBARS_LEFT) {
if ((wp->xoff - sb_w == 0 || if ((wp->xoff - sb_w == 0 || px >= wp->xoff - sb_w) &&
(int)px >= wp->xoff - sb_w) && (px <= ex || (sb_w != 0 && px < ex + sb_w))) {
((int)px <= ex || (sb_w != 0 && if (wp->yoff != 0 && py == wp->yoff - 1)
(int)px < ex + sb_w))) {
if (wp->yoff != 0 && (int)py == wp->yoff - 1)
return (SCREEN_REDRAW_BORDER_TOP); return (SCREEN_REDRAW_BORDER_TOP);
if ((int)py == ey) if (py == ey)
return (SCREEN_REDRAW_BORDER_BOTTOM); return (SCREEN_REDRAW_BORDER_BOTTOM);
} }
} else { /* sb_pos == PANE_SCROLLBARS_RIGHT */ } else { /* sb_pos == PANE_SCROLLBARS_RIGHT */
if ((wp->xoff == 0 || (int)px >= wp->xoff) && if ((wp->xoff == 0 || px >= wp->xoff) &&
((int)px <= ex || (px <= ex || (sb_w != 0 && px < ex + sb_w))) {
(sb_w != 0 && (int)px < ex + sb_w))) {
if (pane_status != PANE_STATUS_BOTTOM && if (pane_status != PANE_STATUS_BOTTOM &&
wp->yoff != 0 && wp->yoff != 0 &&
(int)py == wp->yoff - 1) py == wp->yoff - 1)
return (SCREEN_REDRAW_BORDER_TOP); return (SCREEN_REDRAW_BORDER_TOP);
if (pane_status != PANE_STATUS_TOP && if (pane_status != PANE_STATUS_TOP && py == ey)
(int)py == ey)
return (SCREEN_REDRAW_BORDER_BOTTOM); return (SCREEN_REDRAW_BORDER_BOTTOM);
} }
} }
@@ -251,44 +246,41 @@ screen_redraw_pane_border(struct screen_redraw_ctx *ctx, struct window_pane *wp,
/* Check if a cell is on a border. */ /* Check if a cell is on a border. */
static int static int
screen_redraw_cell_border(struct screen_redraw_ctx *ctx, struct window_pane *wp, screen_redraw_cell_border(struct screen_redraw_ctx *ctx, struct window_pane *wp,
u_int px, u_int py) int px, int py)
{ {
struct client *c = ctx->c; struct client *c = ctx->c;
struct window *w = c->session->curw->window; struct window *w = c->session->curw->window;
struct window_pane *wp2; struct window_pane *wp2;
u_int sy = w->sy; int sx = w->sx, sy = w->sy, sb_w, sb_pos, floating;
int sb_w, sb_pos, floating = 0;
floating = (wp->flags & PANE_FLOATING);
if (ctx->pane_scrollbars != 0) if (ctx->pane_scrollbars != 0)
sb_pos = ctx->pane_scrollbars_pos; sb_pos = ctx->pane_scrollbars_pos;
else else
sb_pos = 0; sb_pos = 0;
sb_w = wp->scrollbar_style.width + wp->scrollbar_style.pad;
sb_w = wp->scrollbar_style.width +
wp->scrollbar_style.pad;
if (ctx->pane_status == PANE_STATUS_BOTTOM) if (ctx->pane_status == PANE_STATUS_BOTTOM)
sy--; sy--;
floating = (wp->flags & PANE_FLOATING);
if (!floating) { if (!floating) {
/* Outside the window? */ /* Outside the window? */
if (px > w->sx || py > sy) if (px > sx || py > sy)
return (0); return (0);
/* On the window border? */ /* On the window border? */
if (px == w->sx || py == sy) if (px == sx || py == sy)
return (1); return (1);
} }
/* If checking a cell from a tiled pane, ignore floating panes /*
* because 2 side-by-side or top-bottom panes share a border * If checking a cell from a tiled pane, ignore floating panes because
* which is used to do split colouring. Essentially treat all * tqo side-by-side or top-bottom panes share a border which is used to
* tiled panes as being in a single z-index. * do split colouring. Essentially, treat all tiled panes as being in a
* single z-index.
* *
* If checking a cell from a floating pane, only check cells * If checking a cell from a floating pane, only check cells from this
* from this floating pane, again, essentially only this z-index. * floating pane, again, essentially only this z-index.
*/ */
/* Check all the panes. */ /* Check all the panes. */
@@ -298,16 +290,16 @@ screen_redraw_cell_border(struct screen_redraw_ctx *ctx, struct window_pane *wp,
(floating && wp2 != wp)) (floating && wp2 != wp))
continue; continue;
if (sb_pos == PANE_SCROLLBARS_LEFT) { if (sb_pos == PANE_SCROLLBARS_LEFT) {
if (((int)px < wp2->xoff - 1 - sb_w || if ((px < wp2->xoff - 1 - sb_w ||
(int)px > wp2->xoff + (int)wp2->sx) && px > wp2->xoff + (int)wp2->sx) &&
((int)py < wp2->yoff - 1 || (py < wp2->yoff - 1 ||
(int)py > wp2->yoff + (int)wp2->sy)) py > wp2->yoff + (int)wp2->sy))
continue; continue;
} else { /* PANE_SCROLLBARS_RIGHT or off. */ } else { /* PANE_SCROLLBARS_RIGHT or off. */
if (((int)px < wp2->xoff - 1 || if ((px < wp2->xoff - 1 ||
(int)px > wp2->xoff + (int)wp2->sx + sb_w) && px > wp2->xoff + (int)wp2->sx + sb_w) &&
((int)py < wp2->yoff - 1 || (py < wp2->yoff - 1 ||
(int)py > wp2->yoff + (int)wp2->sy)) py > wp2->yoff + (int)wp2->sy))
continue; continue;
} }
switch (screen_redraw_pane_border(ctx, wp2, px, py)) { switch (screen_redraw_pane_border(ctx, wp2, px, py)) {
@@ -326,23 +318,19 @@ screen_redraw_cell_border(struct screen_redraw_ctx *ctx, struct window_pane *wp,
/* Work out type of border cell from surrounding cells. */ /* Work out type of border cell from surrounding cells. */
static int static int
screen_redraw_type_of_cell(struct screen_redraw_ctx *ctx, screen_redraw_type_of_cell(struct screen_redraw_ctx *ctx,
struct window_pane *wp, u_int px, u_int py) struct window_pane *wp, int px, int py)
{ {
struct client *c = ctx->c; struct client *c = ctx->c;
int pane_status = ctx->pane_status;
struct window *w = c->session->curw->window; struct window *w = c->session->curw->window;
u_int sx = w->sx, sy = w->sy; int pane_status = ctx->pane_status, borders = 0;
int borders = 0, floating; int sx = w->sx, sy = w->sy;
if (pane_status == PANE_STATUS_BOTTOM)
sy--;
/* Is this outside the window? */ /* Is this outside the window? */
if (pane_status == PANE_STATUS_BOTTOM)
sy--;
if (px > sx || py > sy) if (px > sx || py > sy)
return (CELL_OUTSIDE); return (CELL_OUTSIDE);
floating = (wp->flags & PANE_FLOATING);
/* /*
* Construct a bitmask of whether the cells to the left (bit 8), right, * Construct a bitmask of whether the cells to the left (bit 8), right,
* top, and bottom (bit 1) of this cell are borders. * top, and bottom (bit 1) of this cell are borders.
@@ -351,7 +339,7 @@ screen_redraw_type_of_cell(struct screen_redraw_ctx *ctx,
* 8 + 4 * 8 + 4
* 1 * 1
*/ */
if (! floating) { if (~wp->flags & PANE_FLOATING) {
if (px == 0 || screen_redraw_cell_border(ctx, wp, px - 1, py)) if (px == 0 || screen_redraw_cell_border(ctx, wp, px - 1, py))
borders |= 8; borders |= 8;
if (px <= sx && screen_redraw_cell_border(ctx, wp, px + 1, py)) if (px <= sx && screen_redraw_cell_border(ctx, wp, px + 1, py))
@@ -435,106 +423,102 @@ screen_redraw_type_of_cell(struct screen_redraw_ctx *ctx,
/* Check if cell inside a pane. */ /* Check if cell inside a pane. */
static int static int
screen_redraw_check_cell(struct screen_redraw_ctx *ctx, u_int px, u_int py, screen_redraw_check_cell(struct screen_redraw_ctx *ctx, int px, int py,
struct window_pane **wpp) struct window_pane **wpp)
{ {
struct client *c = ctx->c; struct client *c = ctx->c;
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 pane_status = ctx->pane_status; int pane_status = ctx->pane_status;
u_int sx = w->sx, sy = w->sy;
int border, pane_scrollbars = ctx->pane_scrollbars; int border, pane_scrollbars = ctx->pane_scrollbars;
int pane_status_line; int pane_status_line, tiled_only = 0, left, right;
int sb_pos = ctx->pane_scrollbars_pos; int sb_pos = ctx->pane_scrollbars_pos, sb_w;
int sb_w, left, right, tiled_only=0;
*wpp = NULL; *wpp = NULL;
/* Outside the pane. */
if (px > sx || py > sy) if (px > sx || py > sy)
return (CELL_OUTSIDE); return (CELL_OUTSIDE);
/* Find pane higest in z-index at this point. */ /* Find pane higest in z-index at this point. */
TAILQ_FOREACH(wp, &w->z_index, zentry) { TAILQ_FOREACH(wp, &w->z_index, zentry) {
if (wp->flags & PANE_FLOATING && (px >= sx || py >= sy)) if (wp->flags & PANE_FLOATING && (px >= sx || py >= sy)) {
/* Clip floating panes to window. */ /* Clip floating panes to window. */
continue; continue;
sb_w = wp->scrollbar_style.width + }
wp->scrollbar_style.pad; sb_w = wp->scrollbar_style.width + wp->scrollbar_style.pad;
if (sb_pos == PANE_SCROLLBARS_LEFT) { if (sb_pos == PANE_SCROLLBARS_LEFT) {
if (((int)px >= (int)wp->xoff - 1 - sb_w && if ((px >= wp->xoff - 1 - sb_w &&
(int)px <= wp->xoff + (int)wp->sx) && px <= wp->xoff + (int)wp->sx) &&
((int)py >= (int)wp->yoff - 1 && (py >= wp->yoff - 1 &&
(int)py <= wp->yoff + (int)wp->sy)) py <= wp->yoff + (int)wp->sy))
break; break;
} else { /* PANE_SCROLLBARS_RIGHT or none. */ } else { /* PANE_SCROLLBARS_RIGHT or none. */
if (((int)px >= (int)wp->xoff - 1 && if ((px >= wp->xoff - 1 &&
(int)px <= wp->xoff + (int)wp->sx + sb_w) && px <= wp->xoff + (int)wp->sx + sb_w) &&
((int)py >= (int)wp->yoff - 1 && (py >= wp->yoff - 1 &&
(int)py <= wp->yoff + (int)wp->sy)) py <= wp->yoff + (int)wp->sy))
break; break;
} }
} }
if (wp == NULL) { if (wp != NULL)
start = wp;
else
start = wp = server_client_get_pane(c); start = wp = server_client_get_pane(c);
if (wp == NULL) if (wp == NULL)
return (CELL_OUTSIDE); return (CELL_OUTSIDE);
} else {
start = wp;
}
if (px == sx || py == sy) /* window border */ /* On the window border. */
if (px == sx || py == sy)
return (screen_redraw_type_of_cell(ctx, wp, px, py)); return (screen_redraw_type_of_cell(ctx, wp, px, py));
/* If this is a tiled window, then only check other tiled /*
* windows. This is necessary if there are 2 side-by-side or * If this is a tiled pane, then only check other tiled panes. This is
* top-bottom windows with a shared border and half the shared * necessary if there are two side-by-side or top-bottom panes with a
* border is the active border. * shared border and half the shared border is the active border.
*/ */
if (~wp->flags & PANE_FLOATING) if (~wp->flags & PANE_FLOATING)
tiled_only = 1; tiled_only = 1;
do { /* Loop until back to wp == start.*/ do { /* Loop until back to wp == start.*/
if (!window_pane_visible(wp) || if (!window_pane_visible(wp) ||
(tiled_only && (wp->flags & PANE_FLOATING))) (tiled_only && (wp->flags & PANE_FLOATING)))
goto next; goto next;
*wpp = wp; *wpp = wp;
sb_w = wp->scrollbar_style.width + sb_w = wp->scrollbar_style.width + wp->scrollbar_style.pad;
wp->scrollbar_style.pad;
if (sb_pos == PANE_SCROLLBARS_LEFT) { if (sb_pos == PANE_SCROLLBARS_LEFT) {
if (((int)px < wp->xoff - 1 - sb_w || if ((px < wp->xoff - 1 - sb_w ||
(int)px > wp->xoff + (int)wp->sx) && px > wp->xoff + (int)wp->sx) &&
((int)py < wp->yoff - 1 || (py < wp->yoff - 1 ||
(int)py > wp->yoff + (int)wp->sy)) py > wp->yoff + (int)wp->sy))
goto next; goto next;
} else { /* PANE_SCROLLBARS_RIGHT or none. */ } else { /* PANE_SCROLLBARS_RIGHT or none. */
if (((int)px < wp->xoff - 1 || if ((px < wp->xoff - 1 ||
(int)px > wp->xoff + (int)wp->sx + sb_w) && px > wp->xoff + (int)wp->sx + sb_w) &&
((int)py < wp->yoff - 1 || (py < wp->yoff - 1 ||
(int)py > wp->yoff + (int)wp->sy)) py > wp->yoff + (int)wp->sy))
goto next; goto next;
} }
if (pane_status != PANE_STATUS_OFF) { /*
/* Pane border status inside top/bottom border is * Pane border status inside top/bottom border is CELL_INSIDE
* CELL_INSIDE so it doesn't get overdrawn by a border * so it doesn't get overdrawn by a border line.
* line.
*/ */
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;
else else
pane_status_line = wp->yoff + (int)wp->sy; pane_status_line = wp->yoff + (int)wp->sy;
left = wp->xoff + 2; left = wp->xoff + 2;
right = wp->xoff + 2 + (int)wp->status_size - 1; right = wp->xoff + 2 + (int)wp->status_size - 1;
if (py == pane_status_line + (int)ctx->oy &&
if ((int)py == pane_status_line + (int)ctx->oy && px >= left &&
(int)px >= left && (int)px <= right) px <= right)
return (CELL_INSIDE); return (CELL_INSIDE);
} }
/* Check if CELL_SCROLLBAR */ /* Check if CELL_SCROLLBAR. */
if (window_pane_show_scrollbar(wp, pane_scrollbars)) { if (window_pane_show_scrollbar(wp, pane_scrollbars)) {
/* /*
* Check if py could lie within a scrollbar. If the * Check if py could lie within a scrollbar. If the
@@ -543,16 +527,16 @@ screen_redraw_check_cell(struct screen_redraw_ctx *ctx, u_int px, u_int py,
*/ */
sb_w = wp->scrollbar_style.width + sb_w = wp->scrollbar_style.width +
wp->scrollbar_style.pad; wp->scrollbar_style.pad;
if ((wp->yoff == 0 && py < wp->sy) || if ((wp->yoff == 0 && py < (int)wp->sy) ||
((int)py >= wp->yoff && (py >= wp->yoff &&
(int)py < wp->yoff + (int)wp->sy)) { py < wp->yoff + (int)wp->sy)) {
/* Check if px lies within a scrollbar. */ /* Check if px lies within a scrollbar. */
if ((sb_pos == PANE_SCROLLBARS_RIGHT && if ((sb_pos == PANE_SCROLLBARS_RIGHT &&
(px >= wp->xoff + wp->sx && (px >= wp->xoff + (int)wp->sx &&
px < wp->xoff + wp->sx + sb_w)) || px < wp->xoff + (int)wp->sx + sb_w)) ||
(sb_pos == PANE_SCROLLBARS_LEFT && (sb_pos == PANE_SCROLLBARS_LEFT &&
((int)px >= wp->xoff - sb_w && (px >= wp->xoff - sb_w &&
(int)px < wp->xoff))) px < wp->xoff)))
return (CELL_SCROLLBAR); return (CELL_SCROLLBAR);
} }
} }
@@ -579,7 +563,7 @@ screen_redraw_check_cell(struct screen_redraw_ctx *ctx, u_int px, u_int py,
/* Check if the border of a particular pane. */ /* Check if the border of a particular pane. */
static int static int
screen_redraw_check_is(struct screen_redraw_ctx *ctx, u_int px, u_int py, screen_redraw_check_is(struct screen_redraw_ctx *ctx, int px, int py,
struct window_pane *wp) struct window_pane *wp)
{ {
enum screen_redraw_border_type border; enum screen_redraw_border_type border;
@@ -599,7 +583,7 @@ screen_redraw_make_pane_status(struct client *c, struct window_pane *wp,
{ {
struct window *w = wp->window; struct window *w = wp->window;
struct grid_cell gc; struct grid_cell gc;
const char *fmt, *border_opt; const char *fmt, *border_option;
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;
@@ -616,19 +600,15 @@ screen_redraw_make_pane_status(struct client *c, struct window_pane *wp,
ft = format_create(c, NULL, FORMAT_PANE|wp->id, FORMAT_STATUS); ft = format_create(c, NULL, FORMAT_PANE|wp->id, FORMAT_STATUS);
format_defaults(ft, c, c->session, c->session->curw, wp); format_defaults(ft, c, c->session, c->session->curw, wp);
border_opt = (wp == server_client_get_pane(c)) ? if (wp == server_client_get_pane(c))
"pane-active-border-style" : "pane-border-style"; border_option = "pane-active-border-style";
else
/* Window-level baseline. */ border_option = "pane-border-style";
style_apply(&gc, w->options, border_opt, ft); style_apply(&gc, w->options, border_option, ft);
/* Floating pane window default overrides window baseline. */
if (wp->flags & PANE_FLOATING) if (wp->flags & PANE_FLOATING)
style_add(&gc, w->options, "floating-pane-border-style", ft); style_add(&gc, w->options, "floating-pane-border-style", ft);
if (options_get_only(wp->options, border_option) != NULL)
/* Per-pane override (set via new-pane -S or set-option -p). */ style_add(&gc, wp->options, border_option, ft);
if (options_get_only(wp->options, border_opt) != NULL)
style_add(&gc, wp->options, border_opt, ft);
fmt = options_get_string(wp->options, "pane-border-format"); fmt = options_get_string(wp->options, "pane-border-format");
expanded = format_expand_time(ft, fmt); expanded = format_expand_time(ft, fmt);
@@ -1127,8 +1107,9 @@ screen_redraw_draw_status(struct screen_redraw_ctx *ctx)
} }
} }
/* Check if a single character is within a visible range (not obscured by a /*
* floating window pane). Returns a boolean. * Check if a single character is within a visible range (not obscured by a
* floating pane).
*/ */
int int
screen_redraw_is_visible(struct visible_ranges *r, u_int px) screen_redraw_is_visible(struct visible_ranges *r, u_int px)
@@ -1136,60 +1117,57 @@ screen_redraw_is_visible(struct visible_ranges *r, u_int px)
u_int i; u_int i;
struct visible_range *ri; struct visible_range *ri;
/* No visible_ranges if called from a popup or menu. Always visible. */
if (r == NULL) if (r == NULL)
return (1); return (1);
for (i = 0; i < r->used; i++) { for (i = 0; i < r->used; i++) {
ri = &r->ranges[i]; ri = &r->ranges[i];
if (ri->nx == 0) if (ri->nx != 0 && px >= ri->px && px <= ri->px + ri->nx)
continue;
if ((px >= ri->px) && (px <= ri->px + ri->nx))
return (1); return (1);
} }
return (0); return (0);
} }
/* Construct ranges array for the line at starting at px,py of width /*
cells of base_wp that are unobsructed. */ * Construct ranges array for the line at starting at px,py of width cells of
* base_wp that are unobsructed.
*/
struct visible_ranges * struct visible_ranges *
screen_redraw_get_visible_ranges(struct window_pane *base_wp, u_int px, screen_redraw_get_visible_ranges(struct window_pane *base_wp, u_int px,
u_int py, u_int width, struct visible_ranges *r) { u_int py, u_int width, struct visible_ranges *r)
{
struct window_pane *wp; struct window_pane *wp;
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_w, sb_pos; int found_self, sb, sb_w, sb_pos;
u_int lb, rb, tb, bb; u_int lb, rb, tb, bb;
u_int i, s; u_int i, s;
if (base_wp == NULL) { if (base_wp == NULL) {
if (r != NULL) { if (r != NULL)
return (r); return (r);
} else {
/* Return static range as last resort. */ /* Return static range as last resort. */
if (sr.ranges == NULL) if (sr.ranges == NULL)
sr.ranges = xcalloc(1, sr.ranges = xcalloc(1, sizeof *sr.ranges);
sizeof (struct visible_range));
sr.ranges[0].px = px; sr.ranges[0].px = px;
sr.ranges[0].nx = width; sr.ranges[0].nx = width;
sr.size = 1; sr.size = 1;
sr.used = 1; sr.used = 1;
return (&sr); return (&sr);
} }
}
if (r == NULL) { if (r == NULL) {
/* Start with the entire width of the range. */
server_client_ensure_ranges(&base_wp->r, 1); server_client_ensure_ranges(&base_wp->r, 1);
r = &base_wp->r; r = &base_wp->r;
/* Start with the entire width of the range. */
r->ranges[0].px = px; r->ranges[0].px = px;
r->ranges[0].nx = width; r->ranges[0].nx = width;
r->used = 1; r->used = 1;
} }
w = base_wp->window; w = base_wp->window;
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");
found_self = 0; found_self = 0;
@@ -1199,24 +1177,19 @@ screen_redraw_get_visible_ranges(struct window_pane *base_wp, u_int px,
continue; continue;
} }
tb = (wp->yoff > 0) ? wp->yoff - 1 : 0; tb = wp->yoff > 0 ? wp->yoff - 1 : 0;
bb = wp->yoff + wp->sy; bb = wp->yoff + wp->sy;
if (!found_self || if (!found_self ||
!window_pane_visible(wp) || !window_pane_visible(wp) ||
py < tb || py > bb) py < tb ||
py > bb)
continue; continue;
if (~wp->flags & PANE_FLOATING && py == bb) if (~wp->flags & PANE_FLOATING && py == bb)
continue; continue;
/* Are scrollbars enabled? */ sb_w = wp->scrollbar_style.width + wp->scrollbar_style.pad;
if (window_pane_show_scrollbar(wp, if (!window_pane_show_scrollbar(wp, sb))
options_get_number(w->options, "pane-scrollbars"))) sb_w = sb_pos = 0;
sb_w = wp->scrollbar_style.width +
wp->scrollbar_style.pad;
else {
sb_w = 0;
sb_pos = 0;
}
for (i = 0; i < r->used; i++) { for (i = 0; i < r->used; i++) {
ri = &r->ranges[i]; ri = &r->ranges[i];
@@ -1237,56 +1210,61 @@ screen_redraw_get_visible_ranges(struct window_pane *base_wp, u_int px,
rb = wp->xoff + wp->sx + sb_w; rb = wp->xoff + wp->sx + sb_w;
if (rb > w->sx) if (rb > w->sx)
rb = w->sx - 1; rb = w->sx - 1;
/* If the left edge of floating wp
falls inside this range and right
edge covers up to right of range,
then shrink left edge of range. */
if (lb > ri->px && if (lb > ri->px &&
lb < ri->px + ri->nx && lb < ri->px + ri->nx &&
rb >= ri->px + ri->nx) { rb >= ri->px + ri->nx)
{
/*
* 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; ri->nx = lb - ri->px;
} }
/* Else if the right edge of floating wp
falls inside of this range and left
edge covers the left of range,
then move px forward to right edge of wp. */
else if (rb >= ri->px && else if (rb >= ri->px &&
rb < ri->px + ri->nx && rb < ri->px + ri->nx &&
lb <= ri->px) { lb <= ri->px) {
/*
* 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->nx = ri->nx - (rb + 1 - ri->px);
ri->px = ri->px + (rb + 1 - ri->px); ri->px = ri->px + (rb + 1 - ri->px);
} }
/* Else if wp fully inside range else if (lb > ri->px && rb < ri->px + ri->nx) {
then split range into 2 ranges. */ /*
else if (lb > ri->px && * Else if pane fully inside range then split
rb < ri->px + ri->nx) { * into 2 ranges.
*/
server_client_ensure_ranges(r, r->used + 1); server_client_ensure_ranges(r, r->used + 1);
for (s=r->used; s>i; s--) for (s = r->used; s > i; s--) {
memcpy(&r->ranges[s], &r->ranges[s - 1], memcpy(&r->ranges[s], &r->ranges[s - 1],
sizeof (struct visible_range)); sizeof *r->ranges);
}
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 = ri->px + ri->nx - (rb + 1);
/* ri->px was copied, unchanged. */ /* ri->px was copied, unchanged. */
ri->nx = lb - ri->px; ri->nx = lb - ri->px;
r->used++; r->used++;
} } else if (lb <= ri->px && rb >= ri->px + ri->nx) {
/* If floating wp completely covers this range /*
* then delete it (make it 0 length). */ * If floating pane completely covers this range
else if (lb <= ri->px && * then delete it (make it 0 length).
rb >= ri->px + ri->nx) { */
ri->nx = 0; ri->nx = 0;
} } else {
/* Else the range is already obscured, do nothing. */ /*
* The range is already obscured, do
* nothing.
*/
} }
} }
for (i=0; i<r->used; i++) {
ri = &r->ranges[i];
log_debug("%s: %%%u visible_range py=%u r[%u]: [px=%u nx=%u]",
__func__, base_wp->id, py, i, ri->px, ri->nx);
} }
return (r); return (r);
} }

28
tmux.1
View File

@@ -3042,7 +3042,7 @@ are all omitted and the pane was previously returned to the tiled layout
with with
.Ic tile\-pane , .Ic tile\-pane ,
its last floating position and size are restored. its last floating position and size are restored.
The pane must not already be floating or minimised, and the window must not The pane must not already be floating or hidden, and the window must not
be zoomed. be zoomed.
.Tg joinp .Tg joinp
.It Xo Ic join\-pane .It Xo Ic join\-pane
@@ -3228,23 +3228,23 @@ or
(time). (time).
.Fl r .Fl r
reverses the sort order. reverses the sort order.
.Tg minp .Tg hidep
.It Xo Ic minimise\-pane .It Xo Ic hide\-pane
.Op Fl a .Op Fl a
.Op Fl t Ar target\-pane .Op Fl t Ar target\-pane
.Xc .Xc
.D1 Pq alias: Ic minimize\-pane .D1 Pq alias: Ic hidep
Hide Hide
.Ar target\-pane .Ar target\-pane
from the tiled layout without closing it. from the tiled layout without closing it.
The pane continues to run but is no longer visible and does not occupy any The pane continues to run but is no longer visible and does not occupy any
screen space. screen space.
Minimised panes are shown in the status line and can be restored with Hidden panes are shown in the status line and can be restored with
.Ic unminimise\-pane . .Ic show\-pane .
With With
.Fl a , .Fl a ,
all visible panes in the window are minimised. all visible panes in the window are hidden.
The pane must not already be minimised. The pane must not already be hidden.
.Tg movep .Tg movep
.It Xo Ic move\-pane .It Xo Ic move\-pane
.Op Fl bdfhv .Op Fl bdfhv
@@ -3860,17 +3860,17 @@ a subsequent
.Ic float\-pane .Ic float\-pane
command with no geometry options. command with no geometry options.
The pane must be floating and the window must not be zoomed. The pane must be floating and the window must not be zoomed.
.Tg unminp .Tg showp
.It Xo Ic unminimise\-pane .It Xo Ic show\-pane
.Op Fl t Ar target\-pane .Op Fl t Ar target\-pane
.Xc .Xc
.D1 Pq alias: Ic unminimize\-pane .D1 Pq alias: Ic showp
Restore a minimised Restore a hidden
.Ar target\-pane .Ar target\-pane
to the tiled layout. to the tiled layout.
Space is redistributed equally among all visible panes at the same layout Space is redistributed equally among all visible panes at the same layout
level after the pane is restored. level after the pane is restored.
The pane must be minimised. The pane must be hidden.
.Tg unlinkw .Tg unlinkw
.It Xo Ic unlink\-window .It Xo Ic unlink\-window
.Op Fl k .Op Fl k
@@ -6670,7 +6670,7 @@ The following variables are available, where appropriate:
.It Li "pane_left" Ta "" Ta "Left of pane" .It Li "pane_left" Ta "" Ta "Left of pane"
.It Li "pane_marked" Ta "" Ta "1 if this is the marked pane" .It Li "pane_marked" Ta "" Ta "1 if this is the marked pane"
.It Li "pane_marked_set" Ta "" Ta "1 if a marked pane is set" .It Li "pane_marked_set" Ta "" Ta "1 if a marked pane is set"
.It Li "pane_minimised_flag" Ta "" Ta "1 if pane is minimised" .It Li "pane_hidden_flag" Ta "" Ta "1 if pane is hidden"
.It Li "pane_mode" Ta "" Ta "Name of pane mode, if any" .It Li "pane_mode" Ta "" Ta "Name of pane mode, if any"
.It Li "pane_path" Ta "" Ta "Path of pane (can be set by application)" .It Li "pane_path" Ta "" Ta "Path of pane (can be set by application)"
.It Li "pane_pid" Ta "" Ta "PID of first process in pane" .It Li "pane_pid" Ta "" Ta "PID of first process in pane"

3
tmux.h
View File

@@ -3344,11 +3344,10 @@ void screen_write_alternateoff(struct screen_write_ctx *,
/* screen-redraw.c */ /* screen-redraw.c */
void screen_redraw_screen(struct client *); void screen_redraw_screen(struct client *);
void screen_redraw_pane(struct client *, struct window_pane *, int); void screen_redraw_pane(struct client *, struct window_pane *, int);
int screen_redraw_is_visible(struct visible_ranges *, u_int px); int screen_redraw_is_visible(struct visible_ranges *, u_int);
struct visible_ranges *screen_redraw_get_visible_ranges(struct window_pane *, struct visible_ranges *screen_redraw_get_visible_ranges(struct window_pane *,
u_int, u_int, u_int, struct visible_ranges *); u_int, u_int, u_int, struct visible_ranges *);
/* screen.c */ /* screen.c */
void screen_init(struct screen *, u_int, u_int, u_int); void screen_init(struct screen *, u_int, u_int, u_int);
void screen_reinit(struct screen *); void screen_reinit(struct screen *);