From 76196b8ffa17659e653840d86229d27448735c84 Mon Sep 17 00:00:00 2001 From: Dane Jensen Date: Sat, 16 May 2026 17:30:30 -0700 Subject: [PATCH] Moved new-pane into split-window. --- cmd-split-window.c | 135 +++++++++++++-------------------------------- spawn.c | 2 +- tmux.h | 12 +++- window.c | 96 +++++++++++++++++++++++++++++--- 4 files changed, 136 insertions(+), 109 deletions(-) diff --git a/cmd-split-window.c b/cmd-split-window.c index 2286d41d..5859983c 100644 --- a/cmd-split-window.c +++ b/cmd-split-window.c @@ -38,13 +38,12 @@ const struct cmd_entry cmd_new_pane_entry = { .name = "new-pane", .alias = "newp", - .args = { "bc:de:fF:hIkl:m:M:p:PR:s:S:t:x:X:y:Y:vZ", 0, -1, NULL }, + .args = { "bc:de:fF:hIkl:Lm:p:PR:s:S:t:vx:X:y:Y:Z", 0, -1, NULL }, .usage = "[-bdefhIklPvZ] [-c start-directory] [-e environment] " - "[-F format] [-l size] [-m message] [-M mode] " - "[-R inactive-border-style] [-s style] " - "[-S active-border-style] [-x width] [-X x-position]" - "[-y height] [-Y y-position]" CMD_TARGET_PANE_USAGE - "[shell-command [argument ...]]", + "[-F format] [-l size] [-m message] [-p percentage] [-s style] " + "[-S active-border-style] [-R inactive-border-style] " + "[-x width] [-y height] [-X x-position] [-Y y-position] " + CMD_TARGET_PANE_USAGE " [shell-command [argument ...]]", .target = { 't', CMD_FIND_PANE, 0 }, @@ -56,13 +55,11 @@ const struct cmd_entry cmd_split_window_entry = { .name = "split-window", .alias = "splitw", - .args = { "bc:de:fF:hIkl:m:M:p:PR:s:S:t:x:X:y:Y:vZ", 0, -1, NULL }, + .args = { "bc:de:fF:hIkl:m:p:PR:s:S:t:vZ", 0, -1, NULL }, .usage = "[-bdefhIklPvZ] [-c start-directory] [-e environment] " - "[-F format] [-l size] [-m message] [-M mode] " - "[-R inactive-border-style] [-s style] " - "[-S active-border-style] [-x width] [-X x-position]" - "[-y height] [-Y y-position]" CMD_TARGET_PANE_USAGE - "[shell-command [argument ...]]", + "[-F format] [-l size] [-m message] [-p percentage] [-s style] " + "[-S active-border-style] [-R inactive-border-style] " + CMD_TARGET_PANE_USAGE " [shell-command [argument ...]]", .target = { 't', CMD_FIND_PANE, 0 }, @@ -72,67 +69,17 @@ const struct cmd_entry cmd_split_window_entry = { static struct layout_cell * cmd_split_window_get_floating_layout_cell(struct cmdq_item *item, - struct args *args, struct window *w) + struct args *args, struct window *w, struct window_pane *wp) { struct layout_cell *lc = NULL; char *cause = NULL; - int x, y; - u_int sx, sy; - static int last_x = 0, last_y = 0; + u_int x, y, sx, sy; - /* Default size. */ - sx = w->sx / 2; - sy = w->sy / 2; - - if (args_has(args, 'x')) { - sx = args_percentage_and_expand(args, 'x', 0, USHRT_MAX, w->sx, - item, &cause); - if (cause != NULL) { - cmdq_error(item, "size %s", cause); - free(cause); - return (NULL); - } - } - if (args_has(args, 'y')) { - sy = args_percentage_and_expand(args, 'y', 0, USHRT_MAX, w->sy, - item, &cause); - if (cause != NULL) { - cmdq_error(item, "size %s", cause); - free(cause); - return (NULL); - } - } - - /* If a position is not defined, it defaults to cascading. */ - if (args_has(args, 'X')) { - x = args_percentage_and_expand(args, 'X', 0, USHRT_MAX, w->sx, - item, &cause); - if (cause != NULL) { - cmdq_error(item, "size %s", cause); - free(cause); - return (NULL); - } - } else if (last_x == 0) - x = 4; - else { - x = (last_x += 4); - if (last_x > (int)w->sx) - x = 4; - } - if (args_has(args, 'Y')) { - y = args_percentage_and_expand(args, 'Y', 0, USHRT_MAX, w->sy, - item, &cause); - if (cause != NULL) { - cmdq_error(item, "size %s", cause); - free(cause); - return (NULL); - } - } else if (last_y == 0) - y = 2; - else { - y = (last_y += 2); - if (last_y > (int)w->sy) - y = 2; + if (window_pane_float_geometry(w, wp, &x, &y, &sx, &sy, item, args, &cause) + != 0) { + cmdq_error(item, "invalid float geometry %s", cause); + free(cause); + return (NULL); } /* Floating panes sit in layout cells which are not in the layout_root @@ -143,8 +90,6 @@ cmd_split_window_get_floating_layout_cell(struct cmdq_item *item, lc->yoff = y; lc->sx = sx; lc->sy = sy; - last_x = x; /* Statically save last xoff & yoff so that new */ - last_y = y; /* floating panes offset so they don't overlap. */ return (lc); } @@ -163,6 +108,11 @@ cmd_split_window_get_tiled_layout_cell(struct cmdq_item *item, return (NULL); } + if (wp->flags & PANE_MINIMISED) { + cmdq_error(item, "can't split a minimised pane"); + return (NULL); + } + if (window_pane_tile_geometry(w, wp, &size, &flags, &type, item, args, &cause) != 0) { cmdq_error(item, "invalid tiled geometry %s", cause); @@ -191,30 +141,20 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item) struct window_pane *wp = target->wp, *new_wp; struct layout_cell *lc = NULL; struct cmd_find_state fs; - int flags, input; + int input, is_floating, flags = 0; const char *template, *style; char *cause = NULL, *cp; struct args_value *av; u_int count = args_count(args); - enum { FLOATING, TILED, NONE } pane_mode; - if (args_has(args, 'M')) { - if (strcasecmp(args_get(args, 'M'), "f") == 0) - pane_mode = FLOATING; - else if (strcasecmp(args_get(args, 'M'), "t") == 0) - pane_mode = TILED; - else - pane_mode = NONE; - } else { - if (cmd_get_entry(self) == &cmd_new_pane_entry) - pane_mode = FLOATING; - else - pane_mode = TILED; - } + if (cmd_get_entry(self) == &cmd_new_pane_entry) + is_floating = !args_has(args, 'L'); + else + is_floating = 0; input = (args_has(args, 'I') && count == 0); - flags = (pane_mode == FLOATING) ? SPAWN_FLOATING : 0; + flags = is_floating ? SPAWN_FLOATING : 0; if (args_has(args, 'b')) flags |= SPAWN_BEFORE; if (args_has(args, 'f')) @@ -222,16 +162,12 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item) if (input || (count == 1 && *args_string(args, 0) == '\0')) flags |= SPAWN_EMPTY; - if (pane_mode == FLOATING) - lc = cmd_split_window_get_floating_layout_cell(item, args, w); - else if (pane_mode == TILED) { + if (is_floating) + lc = cmd_split_window_get_floating_layout_cell(item, args, w, + wp); + else lc = cmd_split_window_get_tiled_layout_cell(item, args, w, wp, flags); - } else { - cmdq_error(item, "unrecognized pane mode '%s'", - args_get(args, 'M')); - return (CMD_RETURN_ERROR); - } if (lc == NULL) return (CMD_RETURN_ERROR); @@ -310,7 +246,7 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item) switch (window_pane_start_input(new_wp, item, &cause)) { case -1: server_client_remove_pane(new_wp); - if (pane_mode == TILED) + if (!is_floating) layout_close_pane(new_wp); window_remove_pane(wp->window, new_wp); cmdq_error(item, "%s", cause); @@ -326,8 +262,11 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item) } if (!args_has(args, 'd')) cmd_find_from_winlink_pane(current, wl, new_wp, 0); - window_pop_zoom(wp->window); - server_redraw_window(wp->window); + + if (!is_floating) { + window_pop_zoom(wp->window); + server_redraw_window(wp->window); + } server_status_session(s); if (args_has(args, 'P')) { diff --git a/spawn.c b/spawn.c index 24617bdd..7219a67a 100644 --- a/spawn.c +++ b/spawn.c @@ -379,7 +379,7 @@ spawn_pane(struct spawn_context *sc, char **cause) goto complete; } - /* Store current working directory and change to new one. */ + /* Store current working directory and change to new one. */ if (getcwd(path, sizeof path) != NULL) { if (chdir(new_wp->cwd) == 0) actual_cwd = new_wp->cwd; diff --git a/tmux.h b/tmux.h index 0150e277..a18defe0 100644 --- a/tmux.h +++ b/tmux.h @@ -1386,6 +1386,9 @@ struct window { u_int xpixel; u_int ypixel; + u_int last_new_pane_x; + u_int last_new_pane_y; + u_int new_sx; u_int new_sy; u_int new_xpixel; @@ -3491,9 +3494,12 @@ enum client_theme window_pane_get_theme(struct window_pane *); void window_pane_send_theme_update(struct window_pane *); struct style_range *window_pane_border_status_get_range(struct window_pane *, u_int, u_int); -int window_pane_tile_geometry(struct window *, - struct window_pane *, int *, int *, enum layout_type *, - struct cmdq_item *, struct args *, char **); +int window_pane_tile_geometry(struct window *, struct window_pane *, + int *, int *, enum layout_type *, struct cmdq_item *, + struct args *, char **); +int window_pane_float_geometry(struct window *, struct window_pane *, + u_int *, u_int *, u_int *, u_int *, struct cmdq_item *, + struct args *, char **); /* layout.c */ u_int layout_count_cells(struct layout_cell *); diff --git a/window.c b/window.c index c183fd37..850793dd 100644 --- a/window.c +++ b/window.c @@ -2128,11 +2128,11 @@ window_pane_border_status_get_range(struct window_pane *wp, u_int x, u_int y) } int -window_pane_tile_geometry(struct window *w, struct window_pane *wp, - int *out_size, int *out_flags, enum layout_type *out_type, - struct cmdq_item *item, struct args *args, char **cause) +window_pane_tile_geometry(struct window *w, 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; + int size, flags = *out_flags; enum layout_type type; u_int curval = 0; @@ -2140,6 +2140,7 @@ window_pane_tile_geometry(struct window *w, struct window_pane *wp, if (args_has(args, 'h')) type = LAYOUT_LEFTRIGHT; + /* If the 'p' flag is dropped then this bit can be moved into 'l'. */ if (args_has(args, 'l') || args_has(args, 'p')) { if (args_has(args, 'f')) { if (type == LAYOUT_TOPBOTTOM) @@ -2154,6 +2155,7 @@ window_pane_tile_geometry(struct window *w, struct window_pane *wp, } } + size = -1; if (args_has(args, 'l')) { size = args_percentage_and_expand(args, 'l', 0, INT_MAX, curval, item, cause); @@ -2161,11 +2163,11 @@ window_pane_tile_geometry(struct window *w, struct window_pane *wp, size = args_strtonum_and_expand(args, 'p', 0, 100, item, cause); if (cause == NULL) - size = curval * size / 100; + size = curval * (size) / 100; } - if (*cause != NULL) + if (*cause != NULL) { return (-1); - + } if (args_has(args, 'b')) flags |= SPAWN_BEFORE; if (args_has(args, 'f')) @@ -2174,5 +2176,85 @@ window_pane_tile_geometry(struct window *w, struct window_pane *wp, *out_size = size; *out_flags = flags; *out_type = type; + + return (0); +} + +int +window_pane_float_geometry(struct window *w, 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, sy; + const u_int cx = 4, cy = 2; + + if ((wp->flags & PANE_SAVED_FLOAT) && + !args_has(args, 'x') && !args_has(args, 'y') && + !args_has(args, 'X') && !args_has(args, 'Y')) { + x = wp->saved_float_xoff; + y = wp->saved_float_yoff; + sx = wp->saved_float_sx; + sy = wp->saved_float_sy; + goto out; + } + + /* Default size */ + sx = w->sx / 2; + sy = w->sy / 2; + + 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); + } + } + + /* Position defaults to cascading when not defined */ + 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 = cx; + else { + x = w->last_new_pane_x + cx; + if (w->last_new_pane_x > w->sx) + x = cx; + } + 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 = cy; + else { + y = w->last_new_pane_y + cy; + if (w->last_new_pane_y > w->sy) + y = cy; + } + w->last_new_pane_y = y; + } + +out: + *out_x = x; + *out_y = y; + *out_sx = sx; + *out_sy = sy; return (0); }