From 27ee0c9c3bddcc7ab4ccc8b4b85f83a8e186781f Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 26 Feb 2025 07:39:50 +0000 Subject: [PATCH 1/6] Add the width of the scrollbars to the calculation of the width of the window panes when finding the adjacent panes, GitHub issue 4370 from Michael Grant. --- window.c | 94 +++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 70 insertions(+), 24 deletions(-) diff --git a/window.c b/window.c index 35fc370ba..a6354e206 100644 --- a/window.c +++ b/window.c @@ -1349,6 +1349,36 @@ window_pane_choose_best(struct window_pane **list, u_int size) return (best); } +/* + * Get full size and offset of a window pane including the area of the + * scrollbars if they were visible but not including the border(s). + */ +static void +window_pane_full_size_offset(struct window_pane *wp, u_int *xoff, u_int *yoff, + u_int *sx, u_int *sy) +{ + struct window *w = wp->window; + int pane_scrollbars; + u_int sb_w, sb_pos; + + pane_scrollbars = options_get_number(w->options, "pane-scrollbars"); + sb_pos = options_get_number(w->options, "pane-scrollbars-position"); + + if (window_pane_show_scrollbar(wp, pane_scrollbars)) + sb_w = wp->scrollbar_style.width + wp->scrollbar_style.pad; + else + sb_w = 0; + if (sb_pos == PANE_SCROLLBARS_LEFT) { + *xoff = wp->xoff - sb_w; + *sx = wp->sx + sb_w; + } else { /* sb_pos == PANE_SCROLLBARS_RIGHT */ + *xoff = wp->xoff; + *sx = wp->sx + sb_w; + } + *yoff = wp->yoff; + *sy = wp->sy; +} + /* * Find the pane directly above another. We build a list of those adjacent to * top edge and then choose the best. @@ -1360,6 +1390,7 @@ window_pane_find_up(struct window_pane *wp) struct window_pane *next, *best, **list; u_int edge, left, right, end, size; int status, found; + u_int xoff, yoff, sx, sy; if (wp == NULL) return (NULL); @@ -1369,7 +1400,9 @@ window_pane_find_up(struct window_pane *wp) list = NULL; size = 0; - edge = wp->yoff; + window_pane_full_size_offset(wp, &xoff, &yoff, &sx, &sy); + + edge = yoff; if (status == PANE_STATUS_TOP) { if (edge == 1) edge = w->sy + 1; @@ -1381,20 +1414,21 @@ window_pane_find_up(struct window_pane *wp) edge = w->sy + 1; } - left = wp->xoff; - right = wp->xoff + wp->sx; + left = xoff; + right = xoff + sx; TAILQ_FOREACH(next, &w->panes, entry) { + window_pane_full_size_offset(next, &xoff, &yoff, &sx, &sy); if (next == wp) continue; - if (next->yoff + next->sy + 1 != edge) + if (yoff + sy + 1 != edge) continue; - end = next->xoff + next->sx - 1; + end = xoff + sx - 1; found = 0; - if (next->xoff < left && end > right) + if (xoff < left && end > right) found = 1; - else if (next->xoff >= left && next->xoff <= right) + else if (xoff >= left && xoff <= right) found = 1; else if (end >= left && end <= right) found = 1; @@ -1417,6 +1451,7 @@ window_pane_find_down(struct window_pane *wp) struct window_pane *next, *best, **list; u_int edge, left, right, end, size; int status, found; + u_int xoff, yoff, sx, sy; if (wp == NULL) return (NULL); @@ -1426,7 +1461,9 @@ window_pane_find_down(struct window_pane *wp) list = NULL; size = 0; - edge = wp->yoff + wp->sy + 1; + window_pane_full_size_offset(wp, &xoff, &yoff, &sx, &sy); + + edge = yoff + sy + 1; if (status == PANE_STATUS_TOP) { if (edge >= w->sy) edge = 1; @@ -1442,16 +1479,17 @@ window_pane_find_down(struct window_pane *wp) right = wp->xoff + wp->sx; TAILQ_FOREACH(next, &w->panes, entry) { + window_pane_full_size_offset(next, &xoff, &yoff, &sx, &sy); if (next == wp) continue; - if (next->yoff != edge) + if (yoff != edge) continue; - end = next->xoff + next->sx - 1; + end = xoff + sx - 1; found = 0; - if (next->xoff < left && end > right) + if (xoff < left && end > right) found = 1; - else if (next->xoff >= left && next->xoff <= right) + else if (xoff >= left && xoff <= right) found = 1; else if (end >= left && end <= right) found = 1; @@ -1474,6 +1512,7 @@ window_pane_find_left(struct window_pane *wp) struct window_pane *next, *best, **list; u_int edge, top, bottom, end, size; int found; + u_int xoff, yoff, sx, sy; if (wp == NULL) return (NULL); @@ -1482,24 +1521,27 @@ window_pane_find_left(struct window_pane *wp) list = NULL; size = 0; - edge = wp->xoff; + window_pane_full_size_offset(wp, &xoff, &yoff, &sx, &sy); + + edge = xoff; if (edge == 0) edge = w->sx + 1; - top = wp->yoff; - bottom = wp->yoff + wp->sy; + top = yoff; + bottom = yoff + sy; TAILQ_FOREACH(next, &w->panes, entry) { + window_pane_full_size_offset(next, &xoff, &yoff, &sx, &sy); if (next == wp) continue; - if (next->xoff + next->sx + 1 != edge) + if (xoff + sx + 1 != edge) continue; - end = next->yoff + next->sy - 1; + end = yoff + sy - 1; found = 0; - if (next->yoff < top && end > bottom) + if (yoff < top && end > bottom) found = 1; - else if (next->yoff >= top && next->yoff <= bottom) + else if (yoff >= top && yoff <= bottom) found = 1; else if (end >= top && end <= bottom) found = 1; @@ -1522,6 +1564,7 @@ window_pane_find_right(struct window_pane *wp) struct window_pane *next, *best, **list; u_int edge, top, bottom, end, size; int found; + u_int xoff, yoff, sx, sy; if (wp == NULL) return (NULL); @@ -1530,7 +1573,9 @@ window_pane_find_right(struct window_pane *wp) list = NULL; size = 0; - edge = wp->xoff + wp->sx + 1; + window_pane_full_size_offset(wp, &xoff, &yoff, &sx, &sy); + + edge = xoff + sx + 1; if (edge >= w->sx) edge = 0; @@ -1538,16 +1583,17 @@ window_pane_find_right(struct window_pane *wp) bottom = wp->yoff + wp->sy; TAILQ_FOREACH(next, &w->panes, entry) { + window_pane_full_size_offset(next, &xoff, &yoff, &sx, &sy); if (next == wp) continue; - if (next->xoff != edge) + if (xoff != edge) continue; - end = next->yoff + next->sy - 1; + end = yoff + sy - 1; found = 0; - if (next->yoff < top && end > bottom) + if (yoff < top && end > bottom) found = 1; - else if (next->yoff >= top && next->yoff <= bottom) + else if (yoff >= top && yoff <= bottom) found = 1; else if (end >= top && end <= bottom) found = 1; From 9a8f46e554d848c9b1114a98e14fd17d705f5f84 Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 26 Feb 2025 07:42:52 +0000 Subject: [PATCH 2/6] Fix colouring of pane border when scrollbars are enabled, GitHub issue 4378 from Michael Grant. --- screen-redraw.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/screen-redraw.c b/screen-redraw.c index c1e1481c3..fb5300071 100644 --- a/screen-redraw.c +++ b/screen-redraw.c @@ -433,11 +433,15 @@ screen_redraw_make_pane_status(struct client *c, struct window_pane *wp, const char *fmt; struct format_tree *ft; char *expanded; - int pane_status = rctx->pane_status; + int pane_status = rctx->pane_status, sb_w = 0; + int pane_scrollbars = rctx->pane_scrollbars; u_int width, i, cell_type, px, py; struct screen_write_ctx ctx; struct screen old; + if (window_pane_show_scrollbar(wp, pane_scrollbars)) + sb_w = wp->scrollbar_style.width + wp->scrollbar_style.pad; + ft = format_create(c, NULL, FORMAT_PANE|wp->id, FORMAT_STATUS); format_defaults(ft, c, c->session, c->session->curw, wp); @@ -451,7 +455,7 @@ screen_redraw_make_pane_status(struct client *c, struct window_pane *wp, if (wp->sx < 4) wp->status_size = width = 0; else - wp->status_size = width = wp->sx - 4; + wp->status_size = width = wp->sx + sb_w - 2; memcpy(&old, &wp->status_screen, sizeof old); screen_init(&wp->status_screen, width, 1, 0); From d938ab5dd7698e9f4dd92986d5b9746b2cd12834 Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 26 Feb 2025 07:47:46 +0000 Subject: [PATCH 3/6] If command parsing fails in the client, report the error rather than trying to send the command to the server. GitHub issue 4372 from Nikola Tadic. --- client.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/client.c b/client.c index fcc49c395..9d16e1e9e 100644 --- a/client.c +++ b/client.c @@ -267,8 +267,13 @@ client_main(struct event_base *base, int argc, char **argv, uint64_t flags, if (cmd_list_any_have(pr->cmdlist, CMD_STARTSERVER)) flags |= CLIENT_STARTSERVER; cmd_list_free(pr->cmdlist); - } else + } else { + fprintf(stderr, "%s\n", pr->error); + args_free_values(values, argc); + free(values); free(pr->error); + return 1; + } args_free_values(values, argc); free(values); } From f224d61f3781a246a75e48f222755246920adcb9 Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 26 Feb 2025 07:50:36 +0000 Subject: [PATCH 4/6] Document the use of ';' as a modifier separator, from Matt Liggett in GitHub issue 4384. --- tmux.1 | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tmux.1 b/tmux.1 index 5c9797583..e17a92b30 100644 --- a/tmux.1 +++ b/tmux.1 @@ -5867,6 +5867,12 @@ with .Ql bar/ throughout. .Pp +Multiple modifiers may be separated with a semicolon (;) as in +.Ql #{T;=10:status-left} , +which limits the resulting +.Xr strftime 3 -expanded +string to at most 10 characters. +.Pp In addition, the last line of a shell command's output may be inserted using .Ql #() . For example, From 21f7db4c4dbbc1837667a7d813663036f9288ea6 Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 26 Feb 2025 08:55:27 +0000 Subject: [PATCH 5/6] Do not allow meta prefix on paste start and end sequences, GitHub issue 4387. --- server-client.c | 4 ++-- tmux.h | 3 ++- tty-keys.c | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/server-client.c b/server-client.c index 847a85768..7b017697a 100644 --- a/server-client.c +++ b/server-client.c @@ -2247,13 +2247,13 @@ server_client_check_mouse(struct client *c, struct key_event *event) static int server_client_is_bracket_paste(struct client *c, key_code key) { - if (key == KEYC_PASTE_START) { + if ((key & KEYC_MASK_KEY) == KEYC_PASTE_START) { c->flags |= CLIENT_BRACKETPASTING; log_debug("%s: bracket paste on", c->name); return (0); } - if (key == KEYC_PASTE_END) { + if ((key & KEYC_MASK_KEY) == KEYC_PASTE_END) { c->flags &= ~CLIENT_BRACKETPASTING; log_debug("%s: bracket paste off", c->name); return (0); diff --git a/tmux.h b/tmux.h index cd93097e9..52b85cb19 100644 --- a/tmux.h +++ b/tmux.h @@ -167,7 +167,8 @@ struct winlink; /* Is this a paste key? */ #define KEYC_IS_PASTE(key) \ - ((key) == KEYC_PASTE_START || (key) == KEYC_PASTE_END) + (((key) & KEYC_MASK_KEY) == KEYC_PASTE_START || \ + ((key) & KEYC_MASK_KEY) == KEYC_PASTE_END) /* Multiple click timeout. */ #define KEYC_CLICK_TIMEOUT 300 diff --git a/tty-keys.c b/tty-keys.c index 0de31c5d0..77ab4ae1b 100644 --- a/tty-keys.c +++ b/tty-keys.c @@ -208,8 +208,8 @@ static const struct tty_default_key_raw tty_default_raw_keys[] = { { "\033[O", KEYC_FOCUS_OUT }, /* Paste keys. */ - { "\033[200~", KEYC_PASTE_START }, - { "\033[201~", KEYC_PASTE_END }, + { "\033[200~", KEYC_PASTE_START|KEYC_IMPLIED_META }, + { "\033[201~", KEYC_PASTE_END|KEYC_IMPLIED_META }, /* Extended keys. */ { "\033[1;5Z", '\011'|KEYC_CTRL|KEYC_SHIFT }, From 91c0de60b4fb0962699eaf7c1b32ae441767e963 Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 26 Feb 2025 09:02:00 +0000 Subject: [PATCH 6/6] Also need the implied meta paste keys in the list for output. --- input-keys.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/input-keys.c b/input-keys.c index fa4e3f8ea..900dea07d 100644 --- a/input-keys.c +++ b/input-keys.c @@ -54,9 +54,15 @@ static struct input_key_entry input_key_defaults[] = { { .key = KEYC_PASTE_START, .data = "\033[200~" }, + { .key = KEYC_PASTE_START|KEYC_IMPLIED_META, + .data = "\033[200~" + }, { .key = KEYC_PASTE_END, .data = "\033[201~" }, + { .key = KEYC_PASTE_END|KEYC_IMPLIED_META, + .data = "\033[201~" + }, /* Function keys. */ { .key = KEYC_F1,