Merge branch 'master' into floating_panes

This commit is contained in:
Nicholas Marriott
2026-06-02 20:36:08 +01:00
15 changed files with 215 additions and 235 deletions

View File

@@ -17,7 +17,7 @@ jobs:
action: action:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: dessant/lock-threads@v5 - uses: dessant/lock-threads@v6
with: with:
github-token: ${{ github.token }} github-token: ${{ github.token }}
issue-inactive-days: '30' issue-inactive-days: '30'

View File

@@ -159,7 +159,7 @@ cmd_resize_pane_mouse_update(__unused struct cmd *self, struct cmdq_item *item)
if (wp == NULL || c == NULL || c->session != s) if (wp == NULL || c == NULL || c->session != s)
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);
if (~wp->flags & PANE_FLOATING) { if (!window_pane_is_floating(wp)) {
c->tty.mouse_drag_update = cmd_resize_pane_mouse_update_tiled; c->tty.mouse_drag_update = cmd_resize_pane_mouse_update_tiled;
cmd_resize_pane_mouse_update_tiled(c, &event->m); cmd_resize_pane_mouse_update_tiled(c, &event->m);
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);

View File

@@ -160,7 +160,7 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
server_redraw_window_borders(markedwp->window); server_redraw_window_borders(markedwp->window);
server_status_window(markedwp->window); server_status_window(markedwp->window);
} }
if (wp->flags & PANE_FLOATING) { if (window_pane_is_floating(wp)) {
window_redraw_active_switch(w, wp); window_redraw_active_switch(w, wp);
window_set_active_pane(w, wp, 1); window_set_active_pane(w, wp, 1);
} }

View File

@@ -69,68 +69,6 @@ const struct cmd_entry cmd_split_window_entry = {
.exec = cmd_split_window_exec .exec = cmd_split_window_exec
}; };
static struct layout_cell *
cmd_split_window_get_floating_cell(struct cmdq_item *item, struct args *args,
struct window *w, struct window_pane *wp)
{
struct layout_cell *lc = NULL;
char *cause = NULL;
u_int x, y, sx, sy;
if (window_pane_floating_geometry(w, wp, &x, &y, &sx, &sy, item, args,
&cause) != 0) {
cmdq_error(item, "invalid floating pane geometry %s", cause);
free(cause);
return (NULL);
}
/*
* Floating panes sit in layout cells which are not in the layout_root
* tree so we call it with parent == NULL.
*/
lc = layout_create_cell(NULL);
lc->xoff = x;
lc->yoff = y;
lc->sx = sx;
lc->sy = sy;
return (lc);
}
static struct layout_cell *
cmd_split_window_get_tiled_cell(struct cmdq_item *item, struct args *args,
struct window *w, struct window_pane *wp, int flags)
{
enum layout_type type;
struct layout_cell *lc = NULL;
char *cause = NULL;
int size;
if (wp->flags & PANE_FLOATING) {
cmdq_error(item, "can't split a floating pane");
return (NULL);
}
if (wp->flags & PANE_HIDDEN) {
cmdq_error(item, "can't split a hidden pane");
return (NULL);
}
if (window_pane_tiled_geometry(w, wp, &size, &flags, &type, item, args,
&cause) != 0) {
cmdq_error(item, "invalid tiled geometry %s", cause);
free(cause);
return (NULL);
}
window_push_zoom(wp->window, 1, args_has(args, 'Z'));
lc = layout_split_pane(wp, type, size, flags);
if (lc == NULL)
cmdq_error(item, "no space for new pane");
return (lc);
}
static enum cmd_retval static enum cmd_retval
cmd_split_window_exec(struct cmd *self, struct cmdq_item *item) cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
{ {
@@ -166,11 +104,13 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
flags |= SPAWN_EMPTY; flags |= SPAWN_EMPTY;
if (is_floating) if (is_floating)
lc = cmd_split_window_get_floating_cell(item, args, w, wp); lc = layout_get_floating_cell(item, args, w, wp, lc, &cause);
else else
lc = cmd_split_window_get_tiled_cell(item, args, w, wp, flags); lc = layout_get_tiled_cell(item, args, w, wp, flags, &cause);
if (lc == NULL) if (cause != NULL) {
cmdq_error(item, "could not create cell: %s", cause);
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
}
sc.item = item; sc.item = item;
sc.s = s; sc.s = s;

View File

@@ -79,8 +79,8 @@ cmd_swap_pane_exec(struct cmd *self, struct cmdq_item *item)
if (src_wp == dst_wp) if (src_wp == dst_wp)
goto out; goto out;
if ((src_wp->flags & PANE_FLOATING) && if (window_pane_is_floating(src_wp) &&
(dst_wp->flags & PANE_FLOATING)) { window_pane_is_floating(dst_wp)) {
cmdq_error(item, "cannot swap floating panes"); cmdq_error(item, "cannot swap floating panes");
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
@@ -114,9 +114,9 @@ cmd_swap_pane_exec(struct cmd *self, struct cmdq_item *item)
dst_wp->layout_cell = src_lc; dst_wp->layout_cell = src_lc;
dst_lc->wp = src_wp; dst_lc->wp = src_wp;
src_wp->layout_cell = dst_lc; src_wp->layout_cell = dst_lc;
if ((src_wp->flags ^ dst_wp->flags) & PANE_FLOATING) { if (window_pane_is_floating(src_wp) != window_pane_is_floating(dst_wp)) {
src_wp->flags ^= PANE_FLOATING; src_wp->layout_cell->flags ^= LAYOUT_CELL_FLOATING;
dst_wp->flags ^= PANE_FLOATING; dst_wp->layout_cell->flags ^= LAYOUT_CELL_FLOATING;
} }
src_wp->window = dst_w; src_wp->window = dst_w;

View File

@@ -1035,7 +1035,7 @@ format_cb_pane_floating_flag(struct format_tree *ft)
struct window_pane *wp = ft->wp; struct window_pane *wp = ft->wp;
if (wp != NULL) { if (wp != NULL) {
if (wp->flags & PANE_FLOATING) if (window_pane_is_floating(wp))
return (xstrdup("1")); return (xstrdup("1"));
return (xstrdup("0")); return (xstrdup("0"));
} }

View File

@@ -69,7 +69,7 @@ layout_dump(struct window *w, struct layout_cell *root)
return (NULL); return (NULL);
TAILQ_FOREACH(wp, &w->z_index, zentry) { TAILQ_FOREACH(wp, &w->z_index, zentry) {
if (~wp->flags & PANE_FLOATING) if (!window_pane_is_floating(wp))
break; break;
if (!bracket) { if (!bracket) {
strlcat(layout, "<", sizeof layout); strlcat(layout, "<", sizeof layout);
@@ -307,7 +307,7 @@ layout_assign(struct window_pane **wp, struct layout_cell *lc, int flags)
switch (lc->type) { switch (lc->type) {
case LAYOUT_WINDOWPANE: case LAYOUT_WINDOWPANE:
layout_make_leaf(lc, *wp); layout_make_leaf(lc, *wp);
(*wp)->flags |= flags; lc->flags |= flags;
*wp = TAILQ_NEXT(*wp, entry); *wp = TAILQ_NEXT(*wp, entry);
return; return;
case LAYOUT_LEFTRIGHT: case LAYOUT_LEFTRIGHT:

View File

@@ -129,7 +129,7 @@ layout_first_tiled(struct window *w)
struct window_pane *wp; struct window_pane *wp;
TAILQ_FOREACH(wp, &w->panes, entry) { TAILQ_FOREACH(wp, &w->panes, entry) {
if (~wp->flags & PANE_FLOATING) if (!window_pane_is_floating(wp))
return (wp); return (wp);
} }
return (NULL); return (NULL);
@@ -168,7 +168,7 @@ layout_set_even(struct window *w, enum layout_type type)
/* Build new leaf cells. */ /* Build new leaf cells. */
TAILQ_FOREACH(wp, &w->panes, entry) { TAILQ_FOREACH(wp, &w->panes, entry) {
if (wp->flags & PANE_FLOATING) if (window_pane_is_floating(wp))
continue; continue;
lcnew = layout_create_cell(lc); lcnew = layout_create_cell(lc);
layout_make_leaf(lcnew, wp); layout_make_leaf(lcnew, wp);
@@ -272,7 +272,7 @@ layout_set_main_h(struct window *w)
layout_set_size(lcother, sx, otherh, 0, 0); layout_set_size(lcother, sx, otherh, 0, 0);
if (n == 1) { if (n == 1) {
wp = TAILQ_NEXT(layout_first_tiled(w), entry); wp = TAILQ_NEXT(layout_first_tiled(w), entry);
while (wp != NULL && (wp->flags & PANE_FLOATING)) while (wp != NULL && window_pane_is_floating(wp))
wp = TAILQ_NEXT(wp, entry); wp = TAILQ_NEXT(wp, entry);
layout_make_leaf(lcother, wp); layout_make_leaf(lcother, wp);
TAILQ_INSERT_TAIL(&lc->cells, lcother, entry); TAILQ_INSERT_TAIL(&lc->cells, lcother, entry);
@@ -282,7 +282,7 @@ layout_set_main_h(struct window *w)
/* Add the remaining panes as children. */ /* Add the remaining panes as children. */
TAILQ_FOREACH(wp, &w->panes, entry) { TAILQ_FOREACH(wp, &w->panes, entry) {
if (wp->flags & PANE_FLOATING) if (window_pane_is_floating(wp))
continue; continue;
if (wp == layout_first_tiled(w)) if (wp == layout_first_tiled(w))
continue; continue;
@@ -368,7 +368,7 @@ layout_set_main_h_mirrored(struct window *w)
layout_set_size(lcother, sx, otherh, 0, 0); layout_set_size(lcother, sx, otherh, 0, 0);
if (n == 1) { if (n == 1) {
wp = TAILQ_NEXT(layout_first_tiled(w), entry); wp = TAILQ_NEXT(layout_first_tiled(w), entry);
while (wp != NULL && (wp->flags & PANE_FLOATING)) while (wp != NULL && window_pane_is_floating(wp))
wp = TAILQ_NEXT(wp, entry); wp = TAILQ_NEXT(wp, entry);
layout_make_leaf(lcother, wp); layout_make_leaf(lcother, wp);
TAILQ_INSERT_TAIL(&lc->cells, lcother, entry); TAILQ_INSERT_TAIL(&lc->cells, lcother, entry);
@@ -378,7 +378,7 @@ layout_set_main_h_mirrored(struct window *w)
/* Add the remaining panes as children. */ /* Add the remaining panes as children. */
TAILQ_FOREACH(wp, &w->panes, entry) { TAILQ_FOREACH(wp, &w->panes, entry) {
if (wp->flags & PANE_FLOATING) if (window_pane_is_floating(wp))
continue; continue;
if (wp == layout_first_tiled(w)) if (wp == layout_first_tiled(w))
continue; continue;
@@ -476,7 +476,7 @@ layout_set_main_v(struct window *w)
layout_set_size(lcother, otherw, sy, 0, 0); layout_set_size(lcother, otherw, sy, 0, 0);
if (n == 1) { if (n == 1) {
wp = TAILQ_NEXT(layout_first_tiled(w), entry); wp = TAILQ_NEXT(layout_first_tiled(w), entry);
while (wp != NULL && (wp->flags & PANE_FLOATING)) while (wp != NULL && window_pane_is_floating(wp))
wp = TAILQ_NEXT(wp, entry); wp = TAILQ_NEXT(wp, entry);
layout_make_leaf(lcother, wp); layout_make_leaf(lcother, wp);
TAILQ_INSERT_TAIL(&lc->cells, lcother, entry); TAILQ_INSERT_TAIL(&lc->cells, lcother, entry);
@@ -486,7 +486,7 @@ layout_set_main_v(struct window *w)
/* Add the remaining panes as children. */ /* Add the remaining panes as children. */
TAILQ_FOREACH(wp, &w->panes, entry) { TAILQ_FOREACH(wp, &w->panes, entry) {
if (wp->flags & PANE_FLOATING) if (window_pane_is_floating(wp))
continue; continue;
if (wp == layout_first_tiled(w)) if (wp == layout_first_tiled(w))
continue; continue;
@@ -572,7 +572,7 @@ layout_set_main_v_mirrored(struct window *w)
layout_set_size(lcother, otherw, sy, 0, 0); layout_set_size(lcother, otherw, sy, 0, 0);
if (n == 1) { if (n == 1) {
wp = TAILQ_NEXT(layout_first_tiled(w), entry); wp = TAILQ_NEXT(layout_first_tiled(w), entry);
while (wp != NULL && (wp->flags & PANE_FLOATING)) while (wp != NULL && window_pane_is_floating(wp))
wp = TAILQ_NEXT(wp, entry); wp = TAILQ_NEXT(wp, entry);
layout_make_leaf(lcother, wp); layout_make_leaf(lcother, wp);
TAILQ_INSERT_TAIL(&lc->cells, lcother, entry); TAILQ_INSERT_TAIL(&lc->cells, lcother, entry);
@@ -582,7 +582,7 @@ layout_set_main_v_mirrored(struct window *w)
/* Add the remaining panes as children. */ /* Add the remaining panes as children. */
TAILQ_FOREACH(wp, &w->panes, entry) { TAILQ_FOREACH(wp, &w->panes, entry) {
if (wp->flags & PANE_FLOATING) if (window_pane_is_floating(wp))
continue; continue;
if (wp == layout_first_tiled(w)) if (wp == layout_first_tiled(w))
continue; continue;
@@ -661,7 +661,7 @@ layout_set_tiled(struct window *w)
/* Create a grid of the cells, skipping any floating panes. */ /* Create a grid of the cells, skipping any floating panes. */
wp = TAILQ_FIRST(&w->panes); wp = TAILQ_FIRST(&w->panes);
while (wp != NULL && (wp->flags & PANE_FLOATING)) while (wp != NULL && window_pane_is_floating(wp))
wp = TAILQ_NEXT(wp, entry); wp = TAILQ_NEXT(wp, entry);
for (j = 0; j < rows; j++) { for (j = 0; j < rows; j++) {
/* If this is the last cell, all done. */ /* If this is the last cell, all done. */
@@ -677,7 +677,7 @@ layout_set_tiled(struct window *w)
if (n - (j * columns) == 1 || columns == 1) { if (n - (j * columns) == 1 || columns == 1) {
layout_make_leaf(lcrow, wp); layout_make_leaf(lcrow, wp);
wp = TAILQ_NEXT(wp, entry); wp = TAILQ_NEXT(wp, entry);
while (wp != NULL && (wp->flags & PANE_FLOATING)) while (wp != NULL && window_pane_is_floating(wp))
wp = TAILQ_NEXT(wp, entry); wp = TAILQ_NEXT(wp, entry);
continue; continue;
} }
@@ -693,7 +693,7 @@ layout_set_tiled(struct window *w)
/* Move to the next non-floating cell. */ /* Move to the next non-floating cell. */
wp = TAILQ_NEXT(wp, entry); wp = TAILQ_NEXT(wp, entry);
while (wp != NULL && (wp->flags & PANE_FLOATING)) while (wp != NULL && window_pane_is_floating(wp))
wp = TAILQ_NEXT(wp, entry); wp = TAILQ_NEXT(wp, entry);
if (wp == NULL) if (wp == NULL)
break; break;

145
layout.c
View File

@@ -58,6 +58,7 @@ layout_create_cell(struct layout_cell *lcparent)
lc = xmalloc(sizeof *lc); lc = xmalloc(sizeof *lc);
lc->type = LAYOUT_WINDOWPANE; lc->type = LAYOUT_WINDOWPANE;
lc->flags = 0;
lc->parent = lcparent; lc->parent = lcparent;
TAILQ_INIT(&lc->cells); TAILQ_INIT(&lc->cells);
@@ -363,7 +364,7 @@ layout_fix_panes(struct window *w, struct window_pane *skip)
sx = lc->sx; sx = lc->sx;
sy = lc->sy; sy = lc->sy;
if ((~wp->flags & PANE_FLOATING) && if (!window_pane_is_floating(wp) &&
layout_add_horizontal_border(w, lc, status)) { layout_add_horizontal_border(w, lc, status)) {
if (status == PANE_STATUS_TOP) if (status == PANE_STATUS_TOP)
wp->yoff++; wp->yoff++;
@@ -620,7 +621,7 @@ layout_destroy_cell(struct window *w, struct layout_cell *lc,
*/ */
lcparent = lc->parent; lcparent = lc->parent;
if (lcparent == NULL) { if (lcparent == NULL) {
if (lc->wp != NULL && ~lc->wp->flags & PANE_FLOATING) if (lc->wp != NULL && !window_pane_is_floating(lc->wp))
*lcroot = NULL; *lcroot = NULL;
layout_free_cell(lc); layout_free_cell(lc);
return; return;
@@ -1329,6 +1330,7 @@ layout_close_pane(struct window_pane *wp)
notify_window("window-layout-changed", w); notify_window("window-layout-changed", w);
} }
/* Spread out cells inside a parent cell. */
int int
layout_spread_cell(struct window *w, struct layout_cell *parent) layout_spread_cell(struct window *w, struct layout_cell *parent)
{ {
@@ -1357,6 +1359,7 @@ layout_spread_cell(struct window *w, struct layout_cell *parent)
each = (size - (number - 1)) / number; each = (size - (number - 1)) / number;
if (each == 0) if (each == 0)
return (0); return (0);
/* /*
* Remaining space after assigning that which can be evenly * Remaining space after assigning that which can be evenly
* distributed. * distributed.
@@ -1391,6 +1394,7 @@ layout_spread_cell(struct window *w, struct layout_cell *parent)
return (changed); return (changed);
} }
/* Spread out cells evenly. */
void void
layout_spread_out(struct window_pane *wp) layout_spread_out(struct window_pane *wp)
{ {
@@ -1409,3 +1413,140 @@ layout_spread_out(struct window_pane *wp)
} }
} while ((parent = parent->parent) != NULL); } while ((parent = parent->parent) != NULL);
} }
/* Get a new tiled cell. */
struct layout_cell *
layout_get_tiled_cell(struct cmdq_item *item, struct args *args,
struct window *w, struct window_pane *wp, int flags, char **cause)
{
struct layout_cell *lc;
enum layout_type type;
u_int curval;
int size = -1;
if (window_pane_is_floating(wp)) {
*cause = xstrdup("can't split a floating pane");
return (NULL);
}
type = LAYOUT_TOPBOTTOM;
if (args_has(args, 'h'))
type = LAYOUT_LEFTRIGHT;
if (args_has(args, 'l') || args_has(args, 'p')) {
if (args_has(args, 'f')) {
if (type == LAYOUT_TOPBOTTOM)
curval = w->sy;
else
curval = w->sx;
} else {
if (type == LAYOUT_TOPBOTTOM)
curval = wp->sy;
else
curval = wp->sx;
}
}
if (args_has(args, 'l')) {
size = args_percentage_and_expand(args, 'l', 0, INT_MAX, curval,
item, cause);
} else if (args_has(args, 'p')) {
size = args_strtonum_and_expand(args, 'p', 0, 100, item,
cause);
if (*cause == NULL)
size = curval * size / 100;
}
if (*cause != NULL) {
*cause = xstrdup("invalid tiled geometry");
return (NULL);
}
if (args_has(args, 'b'))
flags |= SPAWN_BEFORE;
if (args_has(args, 'f'))
flags |= SPAWN_FULLSIZE;
window_push_zoom(wp->window, 1, args_has(args, 'Z'));
lc = layout_split_pane(wp, type, size, flags);
if (lc == NULL)
*cause = xstrdup("no space for a new pane");
return (lc);
}
/* Get a new floating cell. */
struct layout_cell *
layout_get_floating_cell(struct cmdq_item *item, struct args *args,
struct window *w, __unused struct window_pane *wp, struct layout_cell *lc,
char **cause)
{
u_int sx, sy, ox, oy;
int new = 0;
if (lc == NULL) {
lc = layout_create_cell(NULL);
new = 1;
}
sx = lc->sx; sy = lc->sy;
ox = lc->xoff; oy = lc->yoff;
if (args_has(args, 'x')) {
sx = args_percentage_and_expand(args, 'x', 0, USHRT_MAX, w->sx,
item, cause);
if (*cause != NULL)
goto error;
}
if (args_has(args, 'y')) {
sy = args_percentage_and_expand(args, 'y', 0, USHRT_MAX, w->sy,
item, cause);
if (*cause != NULL)
goto error;
}
if (args_has(args, 'X')) {
ox = args_percentage_and_expand(args, 'X', 0, USHRT_MAX, w->sx,
item, cause);
if (*cause != NULL)
goto error;
}
if (args_has(args, 'Y')) {
oy = args_percentage_and_expand(args, 'Y', 0, USHRT_MAX, w->sy,
item, cause);
if (*cause != NULL)
goto error;
}
if (sx == UINT_MAX)
sx = w->sx / 2;
if (sy == UINT_MAX)
sy = w->sy / 4;
if (ox == INT_MAX) {
if (w->last_new_pane_x == 0)
ox = 4;
else {
ox = w->last_new_pane_x + 4;
if (w->last_new_pane_x > w->sx)
ox = 4;
}
w->last_new_pane_x = ox;
}
if (oy == INT_MAX) {
if (w->last_new_pane_y == 0)
oy = 2;
else {
oy = w->last_new_pane_y + 2;
if (w->last_new_pane_y > w->sy)
oy = 2;
}
w->last_new_pane_y = oy;
}
layout_set_size(lc, sx, sy, ox, oy);
lc->flags |= LAYOUT_CELL_FLOATING;
return (lc);
error:
if (new)
layout_destroy_cell(w, lc, &w->layout_root);
return (NULL);
}

View File

@@ -106,7 +106,7 @@ screen_redraw_two_panes(struct window *w, enum layout_type *type)
u_int count = 0; u_int count = 0;
TAILQ_FOREACH(wp, &w->panes, entry) { TAILQ_FOREACH(wp, &w->panes, entry) {
if (wp->flags & PANE_FLOATING || wp->layout_cell == NULL) if (window_pane_is_floating(wp) || wp->layout_cell == NULL)
continue; continue;
count++; count++;
if (count > 2 || wp->layout_cell->parent == NULL) if (count > 2 || wp->layout_cell->parent == NULL)
@@ -144,7 +144,7 @@ screen_redraw_pane_border(struct screen_redraw_ctx *ctx, struct window_pane *wp,
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 (window_pane_is_floating(wp)) {
if (py >= wp->yoff - 1 && py <= wp->yoff + sy) { if (py >= wp->yoff - 1 && py <= wp->yoff + sy) {
if (sb_pos == PANE_SCROLLBARS_LEFT) { if (sb_pos == PANE_SCROLLBARS_LEFT) {
if (px == wp->xoff - 1 - sb_w) if (px == wp->xoff - 1 - sb_w)
@@ -287,7 +287,7 @@ screen_redraw_cell_border(struct screen_redraw_ctx *ctx, struct window_pane *wp,
sb_w = wp->scrollbar_style.width + wp->scrollbar_style.pad; sb_w = wp->scrollbar_style.width + wp->scrollbar_style.pad;
/* For floating panes, only check the pane itself. */ /* For floating panes, only check the pane itself. */
if (wp->flags & PANE_FLOATING) { if (window_pane_is_floating(wp)) {
n = screen_redraw_cell_border1(ctx, sb_pos, sb_w, wp, px, py); n = screen_redraw_cell_border1(ctx, sb_pos, sb_w, wp, px, py);
if (n == -1) if (n == -1)
return (0); return (0);
@@ -309,7 +309,7 @@ screen_redraw_cell_border(struct screen_redraw_ctx *ctx, struct window_pane *wp,
* single z-index. * single z-index.
*/ */
TAILQ_FOREACH(wp2, &w->z_index, zentry) { TAILQ_FOREACH(wp2, &w->z_index, zentry) {
if (!window_pane_visible(wp2) || wp2->flags & PANE_FLOATING) if (!window_pane_visible(wp2) || window_pane_is_floating(wp2))
continue; continue;
n = screen_redraw_cell_border1(ctx, sb_pos, sb_w, wp2, px, py); n = screen_redraw_cell_border1(ctx, sb_pos, sb_w, wp2, px, py);
if (n != -1) if (n != -1)
@@ -343,7 +343,7 @@ screen_redraw_type_of_cell(struct screen_redraw_ctx *ctx,
* 8 + 4 * 8 + 4
* 1 * 1
*/ */
if (~wp->flags & PANE_FLOATING) { if (!window_pane_is_floating(wp)) {
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))
@@ -447,7 +447,7 @@ screen_redraw_check_cell(struct screen_redraw_ctx *ctx, int px, int py,
/* Find pane highest in z-index at this point. */ /* Find pane highest 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 (window_pane_is_floating(wp) && (px >= sx || py >= sy)) {
/* Clip floating panes to window. */ /* Clip floating panes to window. */
continue; continue;
} }
@@ -482,12 +482,12 @@ screen_redraw_check_cell(struct screen_redraw_ctx *ctx, int px, int py,
* necessary if there are two side-by-side or top-bottom panes with a * necessary if there are two side-by-side or top-bottom panes with a
* shared border and half the shared border is the active border. * shared border and half the shared border is the active border.
*/ */
if (~wp->flags & PANE_FLOATING) if (!window_pane_is_floating(wp))
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))
goto next; goto next;
if (tiled_only && (wp->flags & PANE_FLOATING)) if (tiled_only && window_pane_is_floating(wp))
goto next; goto next;
*wpp = wp; *wpp = wp;
@@ -884,7 +884,9 @@ screen_redraw_draw_borders_style(struct screen_redraw_ctx *ctx, u_int x,
struct format_tree *ft; struct format_tree *ft;
int *flag; int *flag;
if (screen_redraw_check_is(ctx, x, y, active)) { if ((window_pane_is_floating(wp) && wp == active) ||
(!window_pane_is_floating(wp) &&
screen_redraw_check_is(ctx, x, y, active))) {
flag = &wp->active_border_gc_set; flag = &wp->active_border_gc_set;
gc = &wp->active_border_gc; gc = &wp->active_border_gc;
border_option = "pane-active-border-style"; border_option = "pane-active-border-style";
@@ -923,9 +925,9 @@ screen_redraw_draw_border_arrows(struct screen_redraw_ctx *ctx, int i,
return; return;
if (wp != active) { if (wp != active) {
if (active->flags & PANE_FLOATING) if (window_pane_is_floating(active))
return; return;
if (wp->flags & PANE_FLOATING) if (window_pane_is_floating(wp))
return; return;
} }
@@ -1197,7 +1199,7 @@ screen_redraw_get_visible_ranges(struct window_pane *base_wp, int px,
(u_int)py < tb || (u_int)py < tb ||
(u_int)py > bb) (u_int)py > bb)
continue; continue;
if (~wp->flags & PANE_FLOATING && (u_int)py == bb) if (!window_pane_is_floating(wp) && (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;

View File

@@ -201,7 +201,7 @@ screen_write_pane_is_obscured(struct screen_write_ctx *ctx)
} }
while ((wp = TAILQ_PREV(wp, window_panes, zentry)) != NULL) { while ((wp = TAILQ_PREV(wp, window_panes, zentry)) != NULL) {
if ((wp->flags & PANE_FLOATING) && if (window_pane_is_floating(wp) &&
((wp->yoff >= ctx->wp->yoff && ((wp->yoff >= ctx->wp->yoff &&
wp->yoff <= ctx->wp->yoff + (int)ctx->wp->sy) || wp->yoff <= ctx->wp->yoff + (int)ctx->wp->sy) ||
(wp->yoff + (int)wp->sy >= ctx->wp->yoff && (wp->yoff + (int)wp->sy >= ctx->wp->yoff &&

View File

@@ -655,7 +655,7 @@ server_client_check_mouse_in_pane(struct window_pane *wp, int px, int py,
return (KEYC_MOUSE_LOCATION_SCROLLBAR_SLIDER); return (KEYC_MOUSE_LOCATION_SCROLLBAR_SLIDER);
} else /* py > sl_bottom */ } else /* py > sl_bottom */
return (KEYC_MOUSE_LOCATION_SCROLLBAR_DOWN); return (KEYC_MOUSE_LOCATION_SCROLLBAR_DOWN);
} else if (wp->flags & PANE_FLOATING && } else if (window_pane_is_floating(wp) &&
(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)) {
@@ -683,7 +683,7 @@ server_client_check_mouse_in_pane(struct window_pane *wp, int px, int py,
py <= fwp->yoff + (int)fwp->sy) { py <= fwp->yoff + (int)fwp->sy) {
if (px == bdr_right) if (px == bdr_right)
break; break;
if (wp->flags & PANE_FLOATING) { if (window_pane_is_floating(wp)) {
/* Floating pane, check left border. */ /* Floating pane, check left border. */
bdr_left = fwp->xoff - 1; bdr_left = fwp->xoff - 1;
if (px == bdr_left) if (px == bdr_left)
@@ -695,7 +695,7 @@ server_client_check_mouse_in_pane(struct window_pane *wp, int px, int py,
bdr_bottom = fwp->yoff + fwp->sy; bdr_bottom = fwp->yoff + fwp->sy;
if (py == bdr_bottom) if (py == bdr_bottom)
break; break;
if (wp->flags & PANE_FLOATING) { if (window_pane_is_floating(wp)) {
/* Floating pane, check top border. */ /* Floating pane, check top border. */
bdr_top = fwp->yoff - 1; bdr_top = fwp->yoff - 1;
if (py == bdr_top) if (py == bdr_top)

View File

@@ -280,6 +280,8 @@ spawn_pane(struct spawn_context *sc, char **cause)
else else
layout_assign_pane(sc->lc, new_wp, 0); layout_assign_pane(sc->lc, new_wp, 0);
} }
if (sc->flags & SPAWN_FLOATING)
new_wp->layout_cell->flags |= LAYOUT_CELL_FLOATING;
/* /*
* If window currently zoomed, window_set_active_pane calls * If window currently zoomed, window_set_active_pane calls

18
tmux.h
View File

@@ -1270,7 +1270,7 @@ struct window_pane {
#define PANE_FOCUSED 0x4 #define PANE_FOCUSED 0x4
#define PANE_VISITED 0x8 #define PANE_VISITED 0x8
#define PANE_ZOOMED 0x10 #define PANE_ZOOMED 0x10
#define PANE_FLOATING 0x20 /* unused 0x20 */
#define PANE_INPUTOFF 0x40 #define PANE_INPUTOFF 0x40
#define PANE_CHANGED 0x80 #define PANE_CHANGED 0x80
#define PANE_EXITED 0x100 #define PANE_EXITED 0x100
@@ -1482,6 +1482,10 @@ TAILQ_HEAD(layout_cells, layout_cell);
struct layout_cell { struct layout_cell {
enum layout_type type; enum layout_type type;
/* unused 0x1 */
#define LAYOUT_CELL_FLOATING 0x2
int flags;
struct layout_cell *parent; struct layout_cell *parent;
u_int sx; u_int sx;
@@ -3508,12 +3512,7 @@ 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 *);
struct style_range *window_pane_border_status_get_range(struct window_pane *, struct style_range *window_pane_border_status_get_range(struct window_pane *,
u_int, u_int); u_int, u_int);
int window_pane_tiled_geometry(struct window *, int window_pane_is_floating(struct window_pane *);
struct window_pane *, int *, int *, enum layout_type *,
struct cmdq_item *, struct args *, char **);
int window_pane_floating_geometry(struct window *,
struct window_pane *, u_int *, u_int *, u_int *, u_int *,
struct cmdq_item *, struct args *, char **);
/* layout.c */ /* layout.c */
u_int layout_count_cells(struct layout_cell *); u_int layout_count_cells(struct layout_cell *);
@@ -3551,6 +3550,11 @@ struct layout_cell *layout_split_pane(struct window_pane *, enum layout_type,
void layout_close_pane(struct window_pane *); void layout_close_pane(struct window_pane *);
int layout_spread_cell(struct window *, struct layout_cell *); int layout_spread_cell(struct window *, struct layout_cell *);
void layout_spread_out(struct window_pane *); void layout_spread_out(struct window_pane *);
struct layout_cell *layout_get_floating_cell(struct cmdq_item *, struct args *,
struct window *, struct window_pane *, struct layout_cell *,
char **);
struct layout_cell *layout_get_tiled_cell(struct cmdq_item *, struct args *,
struct window *, struct window_pane *, int, char **);
/* layout-custom.c */ /* layout-custom.c */
char *layout_dump(struct window *, struct layout_cell *); char *layout_dump(struct window *, struct layout_cell *);

131
window.c
View File

@@ -467,7 +467,7 @@ window_has_floating_panes(struct window *w)
struct window_pane *wp; struct window_pane *wp;
TAILQ_FOREACH(wp, &w->panes, entry) { TAILQ_FOREACH(wp, &w->panes, entry) {
if (wp->flags & PANE_FLOATING) if (window_pane_is_floating(wp))
return (1); return (1);
} }
return (0); return (0);
@@ -621,7 +621,7 @@ window_redraw_active_switch(struct window *w, struct window_pane *wp)
break; break;
/* If the pane is floating, move to the front. */ /* If the pane is floating, move to the front. */
if (wp->flags & PANE_FLOATING) { if (window_pane_is_floating(wp)) {
TAILQ_REMOVE(&w->z_index, wp, zentry); TAILQ_REMOVE(&w->z_index, wp, zentry);
TAILQ_INSERT_HEAD(&w->z_index, wp, zentry); TAILQ_INSERT_HEAD(&w->z_index, wp, zentry);
wp->flags |= PANE_REDRAW; wp->flags |= PANE_REDRAW;
@@ -646,7 +646,7 @@ window_get_active_at(struct window *w, u_int x, u_int y)
if (!window_pane_visible(wp)) if (!window_pane_visible(wp))
continue; continue;
window_pane_full_size_offset(wp, &xoff, &yoff, &sx, &sy); window_pane_full_size_offset(wp, &xoff, &yoff, &sx, &sy);
if (~wp->flags & PANE_FLOATING) { if (!window_pane_is_floating(wp)) {
/* Tiled - to and including bottom or right border. */ /* Tiled - to and including bottom or right border. */
if ((int)x < xoff || x > xoff + sx) if ((int)x < xoff || x > xoff + sx)
continue; continue;
@@ -839,7 +839,6 @@ window_add_pane(struct window *w, struct window_pane *other, u_int hlimit,
if (~flags & SPAWN_FLOATING) if (~flags & SPAWN_FLOATING)
TAILQ_INSERT_TAIL(&w->z_index, wp, zentry); TAILQ_INSERT_TAIL(&w->z_index, wp, zentry);
else { else {
wp->flags |= PANE_FLOATING;
TAILQ_INSERT_HEAD(&w->z_index, wp, zentry); TAILQ_INSERT_HEAD(&w->z_index, wp, zentry);
} }
return (wp); return (wp);
@@ -958,11 +957,11 @@ window_pane_zindex(struct window_pane *wp, u_int *i)
*i = 0; *i = 0;
TAILQ_FOREACH(wq, &w->z_index, zentry) { TAILQ_FOREACH(wq, &w->z_index, zentry) {
if (wq == wp) { if (wq == wp) {
if (~wp->flags & PANE_FLOATING) if (!window_pane_is_floating(wp))
(*i)++; (*i)++;
return (0); return (0);
} }
if (wq->flags & PANE_FLOATING) if (window_pane_is_floating(wq))
(*i)++; (*i)++;
} }
@@ -976,7 +975,7 @@ window_count_panes(struct window *w, int with_floating)
u_int n = 0; u_int n = 0;
TAILQ_FOREACH(wp, &w->panes, entry) { TAILQ_FOREACH(wp, &w->panes, entry) {
if (with_floating || ~wp->flags & PANE_FLOATING) if (with_floating || !window_pane_is_floating(wp))
n++; n++;
} }
return (n); return (n);
@@ -1041,7 +1040,7 @@ window_pane_printable_flags(struct window_pane *wp)
flags[pos++] = '-'; flags[pos++] = '-';
if (wp->flags & PANE_ZOOMED) if (wp->flags & PANE_ZOOMED)
flags[pos++] = 'Z'; flags[pos++] = 'Z';
if (wp->flags & PANE_FLOATING) if (window_pane_is_floating(wp))
flags[pos++] = 'F'; flags[pos++] = 'F';
if (wp->flags & PANE_HIDDEN) if (wp->flags & PANE_HIDDEN)
flags[pos++] = 'm'; flags[pos++] = 'm';
@@ -2153,120 +2152,12 @@ window_pane_border_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));
} }
/* Work out geometry for tiled panes. */
int int
window_pane_tiled_geometry(struct window *w, struct window_pane *wp, window_pane_is_floating(struct window_pane *wp)
int *out_size, int *out_flags, enum layout_type *out_type,
struct cmdq_item *item, struct args *args, char **cause)
{ {
int size = -1, flags = *out_flags; struct layout_cell *lc = wp->layout_cell;
enum layout_type type;
u_int curval = 0;
type = LAYOUT_TOPBOTTOM; if (lc == NULL || (lc->flags & LAYOUT_CELL_FLOATING) == 0)
if (args_has(args, 'h'))
type = LAYOUT_LEFTRIGHT;
if (args_has(args, 'l') || args_has(args, 'p')) {
if (args_has(args, 'f')) {
if (type == LAYOUT_TOPBOTTOM)
curval = w->sy;
else
curval = w->sx;
} else {
if (type == LAYOUT_TOPBOTTOM)
curval = wp->sy;
else
curval = wp->sx;
}
}
if (args_has(args, 'l')) {
size = args_percentage_and_expand(args, 'l', 0, INT_MAX, curval,
item, cause);
} else if (args_has(args, 'p')) {
size = args_strtonum_and_expand(args, 'p', 0, 100, item,
cause);
if (*cause == NULL)
size = curval * size / 100;
}
if (*cause != NULL)
return (-1);
if (args_has(args, 'b'))
flags |= SPAWN_BEFORE;
if (args_has(args, 'f'))
flags |= SPAWN_FULLSIZE;
*out_size = size;
*out_flags = flags;
*out_type = type;
return (0);
}
/* Work out geometry for floating panes. */
int
window_pane_floating_geometry(struct window *w, __unused struct window_pane *wp,
u_int *out_x, u_int *out_y, u_int *out_sx, u_int *out_sy,
struct cmdq_item *item, struct args *args, char **cause)
{
u_int x, y, sx = w->sx / 2, sy = w->sy / 4;
if (args_has(args, 'x')) {
sx = args_percentage_and_expand(args, 'x', 0, USHRT_MAX, w->sx,
item, cause);
if (*cause != NULL)
return (-1);
}
if (args_has(args, 'y')) {
sy = args_percentage_and_expand(args, 'y', 0, USHRT_MAX, w->sy,
item, cause);
if (*cause != NULL)
return (-1);
}
if (args_has(args, 'X')) {
x = args_percentage_and_expand(args, 'X', 0, USHRT_MAX, w->sx,
item, cause);
if (*cause != NULL)
return (-1);
} else {
if (w->last_new_pane_x == 0)
x = 4;
else {
x = w->last_new_pane_x + 4;
if (x + sx >= w->sx) {
w->last_new_pane_x = 0;
w->last_new_pane_y = 0;
x = 4;
y = 2;
}
}
w->last_new_pane_x = x;
}
if (args_has(args, 'Y')) {
y = args_percentage_and_expand(args, 'Y', 0, USHRT_MAX, w->sy,
item, cause);
if (*cause != NULL)
return (-1);
} else {
if (w->last_new_pane_y == 0)
y = 2;
else {
y = w->last_new_pane_y + 2;
if (y + sy >= w->sy) {
w->last_new_pane_x = 0;
w->last_new_pane_y = 0;
x = 4;
y = 2;
}
}
w->last_new_pane_y = y;
}
*out_x = x;
*out_y = y;
*out_sx = sx;
*out_sy = sy;
return (0); return (0);
return (1);
} }