From 390207cdf1511f1839b3cb19141c4c3a339f5672 Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 2 Jun 2026 19:31:36 +0000 Subject: [PATCH 1/4] Use new layout functions for join-pane also, from Dane Jensen. --- cmd-join-pane.c | 49 +++------------------------------------------- cmd-split-window.c | 3 ++- 2 files changed, 5 insertions(+), 47 deletions(-) diff --git a/cmd-join-pane.c b/cmd-join-pane.c index 59a947f9e..f154a18bf 100644 --- a/cmd-join-pane.c +++ b/cmd-join-pane.c @@ -72,11 +72,8 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item) struct window *src_w, *dst_w; struct window_pane *src_wp, *dst_wp; char *cause = NULL; - int size, dst_idx; - int flags; - enum layout_type type; + int flags = 0, dst_idx; struct layout_cell *lc; - u_int curval = 0; dst_s = target->s; dst_wl = target->wl; @@ -95,53 +92,13 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item) return (CMD_RETURN_ERROR); } - type = LAYOUT_TOPBOTTOM; - 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) - curval = dst_w->sy; - else - curval = dst_w->sx; - } else { - if (type == LAYOUT_TOPBOTTOM) - curval = dst_wp->sy; - else - curval = dst_wp->sx; - } - } - - size = -1; - 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; - } + lc = layout_get_tiled_cell(item, args, dst_w, dst_wp, flags, &cause); if (cause != NULL) { - cmdq_error(item, "size %s", cause); + cmdq_error(item, "%s", cause); free(cause); return (CMD_RETURN_ERROR); } - flags = 0; - if (args_has(args, 'b')) - flags |= SPAWN_BEFORE; - if (args_has(args, 'f')) - flags |= SPAWN_FULLSIZE; - - lc = layout_split_pane(dst_wp, type, size, flags); - if (lc == NULL) { - cmdq_error(item, "create pane failed: pane too small"); - return (CMD_RETURN_ERROR); - } - layout_close_pane(src_wp); server_client_remove_pane(src_wp); diff --git a/cmd-split-window.c b/cmd-split-window.c index 4527a7505..1d8fa08d2 100644 --- a/cmd-split-window.c +++ b/cmd-split-window.c @@ -109,7 +109,8 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item) else lc = layout_get_tiled_cell(item, args, w, wp, flags, &cause); if (cause != NULL) { - cmdq_error(item, "could not create cell: %s", cause); + cmdq_error(item, "%s", cause); + free(cause); return (CMD_RETURN_ERROR); } From 642cc15b9946b0281f34e889cde80b810f4fb130 Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 3 Jun 2026 20:16:14 +0000 Subject: [PATCH 2/4] Change so panes scroll when the cursor is at the top instead of halfway down, from Michael Grant. --- tty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tty.c b/tty.c index 2d1ea01df..e3c620be3 100644 --- a/tty.c +++ b/tty.c @@ -999,7 +999,7 @@ tty_window_offset1(struct tty *tty, u_int *ox, u_int *oy, u_int *sx, u_int *sy) else if (cy > w->sy - *sy) *oy = w->sy - *sy; else - *oy = cy - *sy / 2; + *oy = cy - *sy + 1; } c->pan_window = NULL; From 580f9ced08a4960692cd0ef813ae4fdbd89c8743 Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 3 Jun 2026 20:18:49 +0000 Subject: [PATCH 3/4] Change run-shell expansion to just be #{1} etc not #1 which interferes with colours. --- format.c | 9 +-------- tmux.1 | 3 --- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/format.c b/format.c index a5afd282c..75771630b 100644 --- a/format.c +++ b/format.c @@ -5598,7 +5598,7 @@ format_expand1(struct format_expand_state *es, const char *fmt) const char *ptr, *s, *style_end = NULL; size_t off, len, n, outlen; int ch, brackets; - char expanded[8192], number[2] = { 0 }; + char expanded[8192]; if (fmt == NULL || *fmt == '\0' || !format_check_time(es)) return (xstrdup("")); @@ -5727,13 +5727,6 @@ format_expand1(struct format_expand_state *es, const char *fmt) continue; default: s = NULL; - if (ch >= '1' && ch <= '9') { - number[0] = ch; - if (format_replace(es, number, 1, &buf, &len, - &off) != 0) - break; - continue; - } if (fmt > style_end) { /* skip inside #[] */ if (ch >= 'A' && ch <= 'Z') s = format_upper[ch - 'A']; diff --git a/tmux.1 b/tmux.1 index c8c7dd417..9c9b38de0 100644 --- a/tmux.1 +++ b/tmux.1 @@ -7868,9 +7868,6 @@ section. If .Ar argument values are given, they are available as -.Ql #1 , -.Ql #2 -or .Ql #{1} , .Ql #{2} and so on. From 6beebbe0747bec57d017aafe18d73b8647b0fe29 Mon Sep 17 00:00:00 2001 From: nicm Date: Thu, 4 Jun 2026 09:24:03 +0000 Subject: [PATCH 4/4] Fix scrollbar drag position when window is taller than tty, from Michael Grant. --- cmd-copy-mode.c | 4 +++- tmux.h | 2 +- window-copy.c | 29 ++++++++++++++++++++--------- 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/cmd-copy-mode.c b/cmd-copy-mode.c index eae7698fd..fce6d3fbd 100644 --- a/cmd-copy-mode.c +++ b/cmd-copy-mode.c @@ -63,6 +63,7 @@ cmd_copy_mode_exec(struct cmd *self, struct cmdq_item *item) struct client *c = cmdq_get_client(item); struct session *s; struct window_pane *wp = target->wp, *swp; + u_int tty_ox, tty_oy, tty_sx, tty_sy; int line_numbers; if (args_has(args, 'q')) { @@ -100,8 +101,9 @@ cmd_copy_mode_exec(struct cmd *self, struct cmdq_item *item) if (args_has(args, 'd')) window_copy_pagedown(wp, 0, args_has(args, 'e')); if (args_has(args, 'S')) { + tty_window_offset(&c->tty, &tty_ox, &tty_oy, &tty_sx, &tty_sy); window_copy_scroll(wp, c->tty.mouse_slider_mpos, event->m.y, - args_has(args, 'e')); + tty_oy, args_has(args, 'e')); return (CMD_RETURN_NORMAL); } diff --git a/tmux.h b/tmux.h index 612d70084..524748ae6 100644 --- a/tmux.h +++ b/tmux.h @@ -3566,7 +3566,7 @@ void printflike(3, 4) window_copy_add(struct window_pane *, int, const char *, ...); void printflike(3, 0) window_copy_vadd(struct window_pane *, int, const char *, va_list); -void window_copy_scroll(struct window_pane *, int, u_int, int); +void window_copy_scroll(struct window_pane *, int, u_int, u_int, int); void window_copy_pageup(struct window_pane *, int); void window_copy_pagedown(struct window_pane *, int, int); void window_copy_start_drag(struct client *, struct mouse_event *); diff --git a/window-copy.c b/window-copy.c index a02c99c1b..39ae18816 100644 --- a/window-copy.c +++ b/window-copy.c @@ -42,7 +42,7 @@ static void window_copy_formats(struct window_mode_entry *, struct format_tree *); static struct screen *window_copy_get_screen(struct window_mode_entry *); static void window_copy_scroll1(struct window_mode_entry *, - struct window_pane *wp, int, u_int, int); + struct window_pane *, int, u_int, u_int, int); static void window_copy_pageup1(struct window_mode_entry *, int); static int window_copy_pagedown1(struct window_mode_entry *, int, int); static void window_copy_next_paragraph(struct window_mode_entry *); @@ -629,19 +629,19 @@ window_copy_vadd(struct window_pane *wp, int parse, const char *fmt, va_list ap) void window_copy_scroll(struct window_pane *wp, int sl_mpos, u_int my, - int scroll_exit) + u_int tty_oy, int scroll_exit) { struct window_mode_entry *wme = TAILQ_FIRST(&wp->modes); if (wme != NULL) { window_set_active_pane(wp->window, wp, 0); - window_copy_scroll1(wme, wp, sl_mpos, my, scroll_exit); + window_copy_scroll1(wme, wp, sl_mpos, my, tty_oy, scroll_exit); } } static void window_copy_scroll1(struct window_mode_entry *wme, struct window_pane *wp, - int sl_mpos, u_int my, int scroll_exit) + int sl_mpos, u_int my, u_int tty_oy, int scroll_exit) { struct window_copy_mode_data *data = wme->data; u_int ox, oy, px, py, n, offset, size; @@ -649,21 +649,29 @@ window_copy_scroll1(struct window_mode_entry *wme, struct window_pane *wp, u_int slider_height = wp->sb_slider_h; u_int sb_height = wp->sy, sb_top = wp->yoff; u_int sy = screen_size_y(data->backing); + u_int my_w; int new_slider_y, delta; /* * sl_mpos is where in the slider the user is dragging, mouse is * dragging this y point relative to top of slider. + * + * my is a raw tty y coordinate; sb_top (= wp->yoff) is a window + * coordinate. Convert my to window coordinates by adding tty_oy (the + * window pan offset). sl_mpos already has the status lines adjustment + * baked in (see server_client_check_mouse), so no further status lines + * correction is needed here. */ - if (my <= sb_top + sl_mpos) { + my_w = my + tty_oy; + if (my_w <= sb_top + (u_int)sl_mpos) { /* Slider banged into top. */ new_slider_y = sb_top - wp->yoff; - } else if (my - sl_mpos > sb_top + sb_height - slider_height) { + } else if (my_w - sl_mpos > sb_top + sb_height - slider_height) { /* Slider banged into bottom. */ new_slider_y = sb_top - wp->yoff + (sb_height - slider_height); } else { /* Slider is somewhere in the middle. */ - new_slider_y = my - wp->yoff - sl_mpos; + new_slider_y = my_w - wp->yoff - sl_mpos; } if (TAILQ_FIRST(&wp->modes) == NULL || @@ -1548,8 +1556,11 @@ window_copy_cmd_scroll_to_mouse(struct window_copy_cmd_state *cs) struct client *c = cs->c; struct mouse_event *m = cs->m; int scroll_exit = args_has(cs->wargs, 'e'); + u_int tty_ox, tty_oy, tty_sx, tty_sy; - window_copy_scroll(wp, c->tty.mouse_slider_mpos, m->y, scroll_exit); + tty_window_offset(&c->tty, &tty_ox, &tty_oy, &tty_sx, &tty_sy); + window_copy_scroll(wp, c->tty.mouse_slider_mpos, m->y, tty_oy, + scroll_exit); return (WINDOW_COPY_CMD_NOTHING); } @@ -4981,7 +4992,7 @@ window_copy_write_lines(struct window_mode_entry *wme, u_int yy; for (yy = py; yy < py + ny; yy++) - window_copy_write_line(wme, ctx, py); + window_copy_write_line(wme, ctx, yy); } static void