Add support for floating panes to resize-pane, from Dane Jensen.

This commit is contained in:
nicm
2026-06-11 10:16:19 +00:00
parent de60750506
commit 3ea458b9dc
4 changed files with 172 additions and 42 deletions

View File

@@ -40,9 +40,9 @@ const struct cmd_entry cmd_resize_pane_entry = {
.name = "resize-pane", .name = "resize-pane",
.alias = "resizep", .alias = "resizep",
.args = { "DLMRTt:Ux:y:Z", 0, 1, NULL }, .args = { "D::L::MR::Tt:U::x:y:Z", 0, 1, NULL },
.usage = "[-DLMRTUZ] [-x width] [-y height] " CMD_TARGET_PANE_USAGE " " .usage = "[-MTZ] [-U lines] [-D lines] [-L columns] [-R columns] "
"[adjustment]", "[-x width] [-y height] " CMD_TARGET_PANE_USAGE,
.target = { 't', CMD_FIND_PANE, 0 }, .target = { 't', CMD_FIND_PANE, 0 },
@@ -58,17 +58,21 @@ cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item)
struct window_pane *wp = target->wp; struct window_pane *wp = target->wp;
struct winlink *wl = target->wl; struct winlink *wl = target->wl;
struct window *w = wl->window; struct window *w = wl->window;
const char *errstr; struct layout_cell *lc = wp->layout_cell;
char *cause; enum layout_type type;
u_int adjust; const char *errstr, *argval;
int x, y, status; const char flags[4] = { 'U', 'D', 'L', 'R' };
char *cause = NULL, flag;
u_int opposite = 0;
int adjust, x, y, status;
long unsigned i;
struct grid *gd = wp->base.grid; struct grid *gd = wp->base.grid;
if (args_has(args, 'T')) { if (args_has(args, 'T')) {
if (!TAILQ_EMPTY(&wp->modes)) if (!TAILQ_EMPTY(&wp->modes))
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);
adjust = screen_size_y(&wp->base) - 1 - wp->base.cy; adjust = screen_size_y(&wp->base) - 1 - wp->base.cy;
if (adjust > gd->hsize) if (adjust > (int)gd->hsize)
adjust = gd->hsize; adjust = gd->hsize;
grid_remove_history(gd, adjust); grid_remove_history(gd, adjust);
wp->base.cy += adjust; wp->base.cy += adjust;
@@ -89,16 +93,6 @@ cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item)
} }
server_unzoom_window(w); server_unzoom_window(w);
if (args_count(args) == 0)
adjust = 1;
else {
adjust = strtonum(args_string(args, 0), 1, INT_MAX, &errstr);
if (errstr != NULL) {
cmdq_error(item, "adjustment %s", errstr);
return (CMD_RETURN_ERROR);
}
}
if (args_has(args, 'x')) { if (args_has(args, 'x')) {
x = args_percentage(args, 'x', 0, INT_MAX, w->sx, &cause); x = args_percentage(args, 'x', 0, INT_MAX, w->sx, &cause);
if (cause != NULL) { if (cause != NULL) {
@@ -106,7 +100,16 @@ cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item)
free(cause); free(cause);
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
layout_resize_pane_to(wp, LAYOUT_LEFTRIGHT, x); if (window_pane_is_floating(wp)) {
layout_resize_floating_pane_to(wp, LAYOUT_LEFTRIGHT, x,
&cause);
if (cause != NULL) {
cmdq_error(item, "size %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
} else
layout_resize_pane_to(wp, LAYOUT_LEFTRIGHT, x);
} }
if (args_has(args, 'y')) { if (args_has(args, 'y')) {
y = args_percentage(args, 'y', 0, INT_MAX, w->sy, &cause); y = args_percentage(args, 'y', 0, INT_MAX, w->sy, &cause);
@@ -126,18 +129,60 @@ cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item)
y++; y++;
break; break;
} }
layout_resize_pane_to(wp, LAYOUT_TOPBOTTOM, y); if (window_pane_is_floating(wp)) {
layout_resize_floating_pane_to(wp, LAYOUT_TOPBOTTOM, y,
&cause);
if (cause != NULL) {
cmdq_error(item, "size %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
} else
layout_resize_pane_to(wp, LAYOUT_TOPBOTTOM, y);
} }
if (args_has(args, 'L')) for (i = 0; i < nitems(flags); i++) {
layout_resize_pane(wp, LAYOUT_LEFTRIGHT, -adjust, 1); flag = flags[i];
else if (args_has(args, 'R')) if (!args_has(args, flag))
layout_resize_pane(wp, LAYOUT_LEFTRIGHT, adjust, 1); continue;
else if (args_has(args, 'U'))
layout_resize_pane(wp, LAYOUT_TOPBOTTOM, -adjust, 1); argval = args_get(args, flag);
else if (args_has(args, 'D')) if (argval == NULL)
layout_resize_pane(wp, LAYOUT_TOPBOTTOM, adjust, 1); argval = "1";
server_redraw_window(wl->window);
adjust = strtonum(argval, INT_MIN, INT_MAX, &errstr);
if (errstr != NULL) {
cmdq_error(item, "adjustment %s", errstr);
return (CMD_RETURN_ERROR);
}
type = LAYOUT_TOPBOTTOM;
if (flag == 'L' || flag == 'R')
type = LAYOUT_LEFTRIGHT;
if (window_pane_is_floating(wp)) {
if (flag == 'L' || flag == 'U')
opposite = 1;
layout_resize_floating_pane(wp, type, adjust, opposite,
&cause);
if (cause != NULL) {
cmdq_error(item, "adjustment %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
} else {
if (flag == 'L' || flag == 'U')
adjust = -adjust;
layout_resize_pane(wp, type, adjust, 1);
}
}
if (lc->parent != NULL)
layout_fix_offsets(w);
layout_fix_panes(w, NULL);
notify_window("window-layout-changed", w);
server_redraw_window(w);
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);
} }

View File

@@ -686,6 +686,63 @@ layout_resize_pane_to(struct window_pane *wp, enum layout_type type,
layout_resize_pane(wp, type, change, 1); layout_resize_pane(wp, type, change, 1);
} }
/* Resize a floating pane to an absolute size. */
void
layout_resize_floating_pane_to(struct window_pane *wp, enum layout_type type,
u_int size, char **cause)
{
struct layout_cell *lc = wp->layout_cell;
if (~lc->flags & LAYOUT_CELL_FLOATING) {
*cause = xstrdup("pane is not floating");
return;
}
if (size < PANE_MINIMUM || size > PANE_MAXIMUM) {
*cause = xstrdup("size is too big or too small");
return;
}
if (type == LAYOUT_TOPBOTTOM)
lc->sy = size;
else
lc->sx = size;
}
/* Resize a floating pane relative to its current size. */
void
layout_resize_floating_pane(struct window_pane *wp, enum layout_type type,
int change, int opposite, char **cause)
{
struct layout_cell *lc = wp->layout_cell;
u_int size;
if (~lc->flags & LAYOUT_CELL_FLOATING) {
*cause = xstrdup("pane is not floating");
return;
}
if (type == LAYOUT_TOPBOTTOM) {
size = lc->sy + change;
if (size < PANE_MINIMUM || size > PANE_MAXIMUM) {
*cause = xstrdup("change is too big or too small");
return;
}
lc->sy = size;
if (opposite)
lc->yoff -= change;
} else {
size = lc->sx + change;
if (size < PANE_MINIMUM || size > PANE_MAXIMUM) {
*cause = xstrdup("change is too big or too small");
return;
}
lc->sx = size;
if (opposite)
lc->xoff -= change;
}
}
void void
layout_resize_layout(struct window *w, struct layout_cell *lc, layout_resize_layout(struct window *w, struct layout_cell *lc,
enum layout_type type, int change, int opposite) enum layout_type type, int change, int opposite)
@@ -719,9 +776,7 @@ void
layout_resize_pane(struct window_pane *wp, enum layout_type type, int change, layout_resize_pane(struct window_pane *wp, enum layout_type type, int change,
int opposite) int opposite)
{ {
struct layout_cell *lc, *lcparent; struct layout_cell *lc = wp->layout_cell, *lcparent;
lc = wp->layout_cell;
/* Find next parent of the same type. */ /* Find next parent of the same type. */
lcparent = lc->parent; lcparent = lc->parent;
@@ -1408,6 +1463,15 @@ layout_get_floating_cell(struct cmdq_item *item, struct args *args,
w->last_new_pane_y = oy; w->last_new_pane_y = oy;
} }
if (sx < PANE_MINIMUM || sx > PANE_MAXIMUM) {
*cause = xstrdup("invalid width");
return (NULL);
}
if (sy < PANE_MINIMUM || sy > PANE_MAXIMUM) {
*cause = xstrdup("invalid height");
return (NULL);
}
lcnew = layout_floating_pane(w, sx, sy, ox, oy); lcnew = layout_floating_pane(w, sx, sy, ox, oy);
return (lcnew); return (lcnew);
} }

34
tmux.1
View File

@@ -3608,16 +3608,17 @@ if specified, to
.Ar new\-name . .Ar new\-name .
.Tg resizep .Tg resizep
.It Xo Ic resize\-pane .It Xo Ic resize\-pane
.Op Fl DLMRTUZ .Op Fl MTZ
.Op Fl t Ar target\-pane .Op Fl t Ar target\-pane
.Op Fl U Ar lines
.Op Fl D Ar lines
.Op Fl L Ar columns
.Op Fl R Ar columns
.Op Fl x Ar width .Op Fl x Ar width
.Op Fl y Ar height .Op Fl y Ar height
.Op Ar adjustment
.Xc .Xc
.D1 Pq alias: Ic resizep .D1 Pq alias: Ic resizep
Resize a pane, up, down, left or right by Resize a pane, up, down, left or right by a specified adjustment with
.Ar adjustment
with
.Fl U , .Fl U ,
.Fl D , .Fl D ,
.Fl L .Fl L
@@ -3629,16 +3630,31 @@ with
.Fl x .Fl x
or or
.Fl y . .Fl y .
The The adjustment is given in
.Ar adjustment .Ar lines
is given in lines or columns (the default is 1); or
.Ar columns
(the default is 1);
.Fl x .Fl x
and and
.Fl y .Fl y
may be a given as a number of lines or columns or followed by may be a given as a number of
.Ar lines
or
.Ar columns
or followed by
.Ql % .Ql %
for a percentage of the window size (for example for a percentage of the window size (for example
.Ql \-x 10% ) . .Ql \-x 10% ) .
If
.Ar target\-pane
is floating,
.Fl U ,
.Fl D ,
.Fl L ,
and
.Fl R
target their respective borders, and negative values may be given.
With With
.Fl Z , .Fl Z ,
the active pane is toggled between zoomed (occupying the whole of the window) the active pane is toggled between zoomed (occupying the whole of the window)

7
tmux.h
View File

@@ -87,8 +87,9 @@ struct winlink;
#define TMUX_TERM "screen" #define TMUX_TERM "screen"
#endif #endif
/* Minimum layout cell size, NOT including border lines. */ /* Minimum and maximum layout cell size, NOT including border lines. */
#define PANE_MINIMUM 1 #define PANE_MINIMUM 1
#define PANE_MAXIMUM 10000
/* Minimum and maximum window size. */ /* Minimum and maximum window size. */
#define WINDOW_MINIMUM PANE_MINIMUM #define WINDOW_MINIMUM PANE_MINIMUM
@@ -3492,6 +3493,10 @@ void layout_resize_pane(struct window_pane *, enum layout_type,
int, int); int, int);
void layout_resize_pane_to(struct window_pane *, enum layout_type, void layout_resize_pane_to(struct window_pane *, enum layout_type,
u_int); u_int);
void layout_resize_floating_pane(struct window_pane *,
enum layout_type, int, int, char **);
void layout_resize_floating_pane_to(struct window_pane *,
enum layout_type, u_int, char **);
void layout_assign_pane(struct layout_cell *, struct window_pane *, void layout_assign_pane(struct layout_cell *, struct window_pane *,
int); int);
struct layout_cell *layout_split_pane(struct window_pane *, enum layout_type, struct layout_cell *layout_split_pane(struct window_pane *, enum layout_type,