From 34933f5926bf1cf58cfa9853582b0cbc23dae3c3 Mon Sep 17 00:00:00 2001 From: nicm Date: Sat, 13 Jun 2026 16:16:18 +0000 Subject: [PATCH] Add flags to move-pane to move floating panes around (-U, -D, -L, -R similar to resize-pane; -X, -Y similar to new-pane). --- usr.bin/tmux/cmd-join-pane.c | 92 ++++++++++++++++++++++++++++++++-- usr.bin/tmux/cmd-resize-pane.c | 4 +- usr.bin/tmux/tmux.1 | 35 ++++++++++--- 3 files changed, 118 insertions(+), 13 deletions(-) diff --git a/usr.bin/tmux/cmd-join-pane.c b/usr.bin/tmux/cmd-join-pane.c index 7b1c9644c07..06a3b11045b 100644 --- a/usr.bin/tmux/cmd-join-pane.c +++ b/usr.bin/tmux/cmd-join-pane.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-join-pane.c,v 1.58 2026/06/07 09:54:25 nicm Exp $ */ +/* $OpenBSD: cmd-join-pane.c,v 1.59 2026/06/13 16:16:18 nicm Exp $ */ /* * Copyright (c) 2011 George Nachman @@ -31,6 +31,8 @@ */ static enum cmd_retval cmd_join_pane_exec(struct cmd *, struct cmdq_item *); +static enum cmd_retval cmd_join_pane_move(struct cmdq_item *, struct args *, + struct winlink *, struct window_pane *); const struct cmd_entry cmd_join_pane_entry = { .name = "join-pane", @@ -50,8 +52,10 @@ const struct cmd_entry cmd_move_pane_entry = { .name = "move-pane", .alias = "movep", - .args = { "bdfhvp:l:s:t:", 0, 0, NULL }, - .usage = "[-bdfhv] [-l size] " CMD_SRCDST_PANE_USAGE, + .args = { "D::L::R::U::X:Y:bdfhvp:l:s:t:", 0, 0, NULL }, + .usage = "[-bdfhv] [-D lines] [-L columns] [-R columns] " + "[-U lines] [-X x-position] [-Y y-position] [-l size] " + CMD_SRCDST_PANE_USAGE, .source = { 's', CMD_FIND_PANE, CMD_FIND_DEFAULT_MARKED }, .target = { 't', CMD_FIND_PANE, 0 }, @@ -60,6 +64,78 @@ const struct cmd_entry cmd_move_pane_entry = { .exec = cmd_join_pane_exec }; +static enum cmd_retval +cmd_join_pane_move(struct cmdq_item *item, struct args *args, struct winlink *wl, + struct window_pane *wp) +{ + struct window *w = wl->window; + struct layout_cell *lc = wp->layout_cell; + const char *errstr, *argval; + const char flags[] = { 'U', 'D', 'L', 'R' }; + char *cause = NULL, flag; + int xoff, yoff, adjust; + u_int i; + + if (!window_pane_is_floating(wp)) { + cmdq_error(item, "pane is not floating"); + return (CMD_RETURN_ERROR); + } + + xoff = lc->xoff; + yoff = lc->yoff; + + if (args_has(args, 'X')) { + xoff = args_percentage_and_expand(args, 'X', -(int)lc->sx, + w->sx, w->sx, item, &cause); + if (cause != NULL) { + cmdq_error(item, "position %s", cause); + free(cause); + return (CMD_RETURN_ERROR); + } + } + if (args_has(args, 'Y')) { + yoff = args_percentage_and_expand(args, 'Y', -(int)lc->sy, + w->sy, w->sy, item, &cause); + if (cause != NULL) { + cmdq_error(item, "position %s", cause); + free(cause); + return (CMD_RETURN_ERROR); + } + } + + for (i = 0; i < nitems(flags); i++) { + flag = flags[i]; + if (!args_has(args, flag)) + continue; + + argval = args_get(args, flag); + if (argval == NULL) + argval = "1"; + adjust = strtonum(argval, INT_MIN, INT_MAX, &errstr); + if (errstr != NULL) { + cmdq_error(item, "offset %s", errstr); + return (CMD_RETURN_ERROR); + } + + if (flag == 'U') + yoff -= adjust; + else if (flag == 'D') + yoff += adjust; + else if (flag == 'L') + xoff -= adjust; + else + xoff += adjust; + } + + lc->xoff = xoff; + lc->yoff = yoff; + layout_fix_panes(w, NULL); + notify_window("window-layout-changed", w); + server_redraw_window(w); + + return (CMD_RETURN_NORMAL); +} + static enum cmd_retval cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item) { @@ -82,6 +158,16 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item) dst_idx = dst_wl->idx; server_unzoom_window(dst_w); + if (cmd_get_entry(self) == &cmd_move_pane_entry) { + if (args_has(args, 'X') || + args_has(args, 'Y') || + args_has(args, 'U') || + args_has(args, 'D') || + args_has(args, 'L') || + args_has(args, 'R')) + return (cmd_join_pane_move(item, args, dst_wl, dst_wp)); + } + src_wl = source->wl; src_wp = source->wp; src_w = src_wl->window; diff --git a/usr.bin/tmux/cmd-resize-pane.c b/usr.bin/tmux/cmd-resize-pane.c index 80545ed7abe..5858d5c2f30 100644 --- a/usr.bin/tmux/cmd-resize-pane.c +++ b/usr.bin/tmux/cmd-resize-pane.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-resize-pane.c,v 1.56 2026/06/11 10:16:19 nicm Exp $ */ +/* $OpenBSD: cmd-resize-pane.c,v 1.57 2026/06/13 16:16:18 nicm Exp $ */ /* * Copyright (c) 2009 Nicholas Marriott @@ -41,7 +41,7 @@ const struct cmd_entry cmd_resize_pane_entry = { .alias = "resizep", .args = { "D::L::MR::Tt:U::x:y:Z", 0, 1, NULL }, - .usage = "[-MTZ] [-U lines] [-D lines] [-L columns] [-R columns] " + .usage = "[-MTZ] [-D lines] [-L columns] [-R columns] [-U lines] " "[-x width] [-y height] " CMD_TARGET_PANE_USAGE, .target = { 't', CMD_FIND_PANE, 0 }, diff --git a/usr.bin/tmux/tmux.1 b/usr.bin/tmux/tmux.1 index 81302af6d74..fa70014ac6f 100644 --- a/usr.bin/tmux/tmux.1 +++ b/usr.bin/tmux/tmux.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: tmux.1,v 1.1083 2026/06/13 10:32:54 nicm Exp $ +.\" $OpenBSD: tmux.1,v 1.1084 2026/06/13 16:16:18 nicm Exp $ .\" .\" Copyright (c) 2007 Nicholas Marriott .\" @@ -3304,13 +3304,34 @@ reverses the sort order. .Tg movep .It Xo Ic move\-pane .Op Fl bdfhv +.Op Fl D Op Ar lines +.Op Fl L Op Ar columns +.Op Fl R Op Ar columns +.Op Fl U Op Ar lines +.Op Fl X Ar x\-position +.Op Fl Y Ar y\-position .Op Fl l Ar size .Op Fl s Ar src\-pane .Op Fl t Ar dst\-pane .Xc .D1 Pq alias: Ic movep Does the same as -.Ic join\-pane . +.Ic join\-pane , +except if given +.Fl U , +.Fl D , +.Fl L +or +.Fl R +in which case move the target floating pane up, down, left or right by +.Ar lines +or +.Ar columns +(one if omitted); +.Fl X +and +.Fl Y +move to the an absolute position. .Tg movew .It Xo Ic move\-window .Op Fl abrdk @@ -3612,13 +3633,13 @@ if specified, to .Tg resizep .It Xo Ic resize\-pane .Op Fl MTZ -.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 U Ar lines .Op Fl x Ar width .Op Fl y Ar height +.Op Fl t Ar target\-pane .Xc .D1 Pq alias: Ic resizep Resize a pane, up, down, left or right by a specified adjustment with @@ -3626,10 +3647,8 @@ Resize a pane, up, down, left or right by a specified adjustment with .Fl D , .Fl L or -.Fl R , -or -to an absolute size -with +.Fl R ; +or to an absolute size with .Fl x or .Fl y .