diff --git a/cmd-join-pane.c b/cmd-join-pane.c index 67214fa0..3f144b4b 100644 --- a/cmd-join-pane.c +++ b/cmd-join-pane.c @@ -31,8 +31,6 @@ */ 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", @@ -52,10 +50,10 @@ const struct cmd_entry cmd_move_pane_entry = { .name = "move-pane", .alias = "movep", - .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, + .args = { "D::L::P:R::U::X:Y:bdfhvp:l:s:t:", 0, 0, NULL }, + .usage = "[-bdfhv] [-D lines] [-L columns] [-P position] " + "[-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 }, @@ -65,25 +63,88 @@ const struct cmd_entry cmd_move_pane_entry = { }; static enum cmd_retval -cmd_join_pane_move(struct cmdq_item *item, struct args *args, struct winlink *wl, - struct window_pane *wp) +cmd_join_pane_place(struct cmdq_item *item, struct winlink *wl, + struct window_pane *wp, const char *position) +{ + struct window *w = wl->window; + struct layout_cell *lc = wp->layout_cell; + int wx = w->sx, wy = w->sy, px = lc->sx; + int py = lc->sy, xoff, yoff; + + if (strcmp(position, "top-left") == 0) { + xoff = 1; + yoff = 1; + } else if (strcmp(position, "top-centre") == 0 || + strcmp(position, "top-center") == 0) { + xoff = (wx - px) / 2; + yoff = 1; + } else if (strcmp(position, "top-right") == 0) { + xoff = wx - px - 1; + yoff = 1; + } else if (strcmp(position, "centre-left") == 0 || + strcmp(position, "center-left") == 0) { + xoff = 1; + yoff = (wy - py) / 2; + } else if (strcmp(position, "centre") == 0 || + strcmp(position, "center") == 0) { + xoff = (wx - px) / 2; + yoff = (wy - py) / 2; + } else if (strcmp(position, "centre-right") == 0 || + strcmp(position, "center-right") == 0) { + xoff = wx - px - 1; + yoff = (wy - py) / 2; + } else if (strcmp(position, "bottom-left") == 0) { + xoff = 1; + yoff = wy - py - 1; + } else if (strcmp(position, "bottom-centre") == 0 || + strcmp(position, "bottom-center") == 0) { + xoff = (wx - px) / 2; + yoff = wy - py - 1; + } else if (strcmp(position, "bottom-right") == 0) { + xoff = wx - px - 1; + yoff = wy - py - 1; + } else if (strcmp(position, "top-left-centre") == 0 || + strcmp(position, "top-left-center") == 0) { + xoff = wx / 4 - px / 2; + yoff = wy / 4 - py / 2; + } else if (strcmp(position, "top-right-centre") == 0 || + strcmp(position, "top-right-center") == 0) { + xoff = (3 * wx) / 4 - px / 2; + yoff = wy / 4 - py / 2; + } else if (strcmp(position, "bottom-left-centre") == 0 || + strcmp(position, "bottom-left-center") == 0) { + xoff = wx / 4 - px / 2; + yoff = (3 * wy) / 4 - py / 2; + } else if (strcmp(position, "bottom-right-centre") == 0 || + strcmp(position, "bottom-right-center") == 0) { + xoff = (3 * wx) / 4 - px / 2; + yoff = (3 * wy) / 4 - py / 2; + } else { + cmdq_error(item, "unknown position: %s", position); + return (CMD_RETURN_ERROR); + } + + 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_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; + int xoff = lc->xoff, yoff = lc->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); @@ -127,11 +188,13 @@ cmd_join_pane_move(struct cmdq_item *item, struct args *args, struct winlink *wl xoff += adjust; } - lc->xoff = xoff; - lc->yoff = yoff; - layout_fix_panes(w, NULL); - notify_window("window-layout-changed", w); - server_redraw_window(w); + if (xoff != lc->xoff || yoff != lc->yoff) { + 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); } @@ -147,6 +210,7 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item) struct winlink *src_wl, *dst_wl; struct window *src_w, *dst_w; struct window_pane *src_wp, *dst_wp; + const char *s; char *cause = NULL; int flags = 0, dst_idx; struct layout_cell *lc; @@ -159,6 +223,12 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item) server_unzoom_window(dst_w); if (cmd_get_entry(self) == &cmd_move_pane_entry) { + if (!window_pane_is_floating(dst_wp)) { + cmdq_error(item, "pane is not floating"); + return (CMD_RETURN_ERROR); + } + if ((s = args_get(args, 'P')) != NULL) + return (cmd_join_pane_place(item, dst_wl, dst_wp, s)); if (args_has(args, 'X') || args_has(args, 'Y') || args_has(args, 'U') || diff --git a/key-bindings.c b/key-bindings.c index eee29ae0..95300537 100644 --- a/key-bindings.c +++ b/key-bindings.c @@ -406,8 +406,10 @@ key_bindings_init(void) "bind -N 'Choose a window from a list' w { choose-tree -Zw }", "bind -N 'Kill the active pane' x { confirm-before -p\"kill-pane #P? (y/n)\" kill-pane }", "bind -N 'Zoom the active pane' z { resize-pane -Z }", - "bind -N 'Swap the active pane with the pane above' '{' { swap-pane -U }", - "bind -N 'Swap the active pane with the pane below' '}' { swap-pane -D }", + "bind -N 'Move pane to top-left corner' '{' { move-pane -P top-left }", + "bind -N 'Move pane to top-right corner' '}' { move-pane -P top-right }", + "bind -N 'Move pane to bottom-left corner' 'M-{' { move-pane -P bottom-left }", + "bind -N 'Move pane to bottom-right corner' 'M-}' { move-pane -P bottom-right }", "bind -N 'Show messages' '~' { show-messages }", "bind -N 'Enter copy mode and scroll up' PPage { copy-mode -u }", "bind -N 'Select the pane above the active pane' -r Up { select-pane -U }", diff --git a/tmux.1 b/tmux.1 index e16fbe3b..fbcec34a 100644 --- a/tmux.1 +++ b/tmux.1 @@ -3306,6 +3306,7 @@ reverses the sort order. .Op Fl bdfhv .Op Fl D Op Ar lines .Op Fl L Op Ar columns +.Op Fl P Ar position .Op Fl R Op Ar columns .Op Fl U Op Ar lines .Op Fl X Ar x\-position @@ -3318,20 +3319,52 @@ reverses the sort order. Does the same as .Ic join\-pane , except if given -.Fl U , .Fl D , -.Fl L +.Fl L , +.Fl P , +.Fl R , +.Fl U , +.Fl X or +.Fl Y +in which case move the target floating pane. +.Fl D , +.Fl L , .Fl R -in which case move the target floating pane up, down, left or right by +and +.Fl U +move it down, left, right or up by .Ar lines or .Ar columns (one if omitted); +.Fl P +moves it to +.Ar position , +which may be +.Ql top-left , +.Ql top-centre , +.Ql top-right , +.Ql centre-left , +.Ql centre , +.Ql centre-right , +.Ql bottom-left , +.Ql bottom-centre , +.Ql bottom-right , +.Ql top-left-centre , +.Ql top-right-centre , +.Ql bottom-left-centre +or +.Ql bottom-right-centre ; +for each +.Ql centre +position, +.Ql center +is accepted as an alias. .Fl X and .Fl Y -move to the an absolute position. +move it to an absolute position. .Tg movew .It Xo Ic move\-window .Op Fl abrdk