From 8bf2a4e807a092970dabfac89936d6e887389ecd Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 21 Jul 2026 12:28:43 +0000 Subject: [PATCH 1/3] Add a -C flag to new-pane to have a modal pane close when the mouse is clicked outside it, GitHub issue 5400. --- cmd-split-window.c | 8 +++++--- server-client.c | 7 ++++++- tmux.1 | 7 +++++-- tmux.h | 3 ++- 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/cmd-split-window.c b/cmd-split-window.c index bcda1d97f..8cefba937 100644 --- a/cmd-split-window.c +++ b/cmd-split-window.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-split-window.c,v 1.145 2026/07/15 13:02:33 nicm Exp $ */ +/* $OpenBSD: cmd-split-window.c,v 1.146 2026/07/21 12:28:43 nicm Exp $ */ /* * Copyright (c) 2009 Nicholas Marriott @@ -41,8 +41,8 @@ const struct cmd_entry cmd_new_pane_entry = { .name = "new-pane", .alias = "newp", - .args = { "bB:c:de:EfF:hIkl:LMm:Op:PR:s:S:t:T:vWx:X:y:Y:Z", 0, -1, NULL }, - .usage = "[-bdefhIklMOPvWZ] [-B border-lines] " + .args = { "bB:Cc:de:EfF:hIkl:LMm:Op:PR:s:S:t:T:vWx:X:y:Y:Z", 0, -1, NULL }, + .usage = "[-bCdefhIklMOPvWZ] [-B border-lines] " "[-c start-directory] [-e environment] " "[-F format] [-l size] [-m message] [-p percentage] " "[-s style] [-S active-border-style] " @@ -202,6 +202,8 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item) */ goto fail; } + if (args_has(args, 'C') && args_has(args, 'O')) + new_wp->flags |= PANE_CLOSEONCLICK; style = args_get(args, 's'); if (style != NULL) { diff --git a/server-client.c b/server-client.c index c64c57d2e..a010c9f16 100644 --- a/server-client.c +++ b/server-client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: server-client.c,v 1.497 2026/07/17 12:42:51 nicm Exp $ */ +/* $OpenBSD: server-client.c,v 1.498 2026/07/21 12:28:43 nicm Exp $ */ /* * Copyright (c) 2009 Nicholas Marriott @@ -1062,6 +1062,11 @@ have_event: c->tty.mouse_scrolling_flag = 0; c->tty.mouse_slider_mpos = -1; c->tty.mouse_last_pane = -1; + if ((w->modal->flags & PANE_CLOSEONCLICK) && + (type == KEYC_TYPE_MOUSEDOWN || + type == KEYC_TYPE_SECONDCLICK || + type == KEYC_TYPE_TRIPLECLICK)) + server_kill_pane(w->modal); return (KEYC_UNKNOWN); } } diff --git a/tmux.1 b/tmux.1 index 4565a1d94..5fb22d413 100644 --- a/tmux.1 +++ b/tmux.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: tmux.1,v 1.1145 2026/07/21 11:52:13 nicm Exp $ +.\" $OpenBSD: tmux.1,v 1.1146 2026/07/21 12:28:43 nicm Exp $ .\" .\" Copyright (c) 2007 Nicholas Marriott .\" @@ -3636,7 +3636,7 @@ but a different format may be specified with .Fl F . .Tg newp .It Xo Ic new\-pane -.Op Fl bdefhIkLMOPvWZ +.Op Fl bCdefhIkLMOPvWZ .Op Fl B Ar border\-lines .Op Fl c Ar start\-directory .Op Fl e Ar environment @@ -3692,6 +3692,9 @@ creates a modal pane. A modal pane is always the active pane and prevents interaction with any other panes while it is active. A window can only have one modal pane and it must be a floating pane. +With +.Fl C , +the modal pane is closed when the mouse is clicked outside it. .Pp The .Fl L diff --git a/tmux.h b/tmux.h index 597d169b7..217e5e55e 100644 --- a/tmux.h +++ b/tmux.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tmux.h,v 1.1411 2026/07/20 11:16:33 nicm Exp $ */ +/* $OpenBSD: tmux.h,v 1.1412 2026/07/21 12:28:43 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -1298,6 +1298,7 @@ struct window_pane { #define PANE_DESTROYED 0x10000 #define PANE_CMDRUNNING 0x20000 #define PANE_ACTIVITY 0x40000 +#define PANE_CLOSEONCLICK 0x80000 bitstr_t *sync_dirty; u_int sync_dirty_size; From c59db2d007351f0da953334b81f5394508204df9 Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 21 Jul 2026 13:04:01 +0000 Subject: [PATCH 2/3] Invalidate scene when window is resized. --- window.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/window.c b/window.c index 5f06c1a14..f5bf6870b 100644 --- a/window.c +++ b/window.c @@ -1,4 +1,4 @@ -/* $OpenBSD: window.c,v 1.366 2026/07/19 19:53:11 nicm Exp $ */ +/* $OpenBSD: window.c,v 1.367 2026/07/21 13:04:01 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -573,13 +573,13 @@ window_resize(struct window *w, u_int sx, u_int sy, int xpixel, int ypixel) w->sy = sy; if (w->menu != NULL) { menu_resize(w->menu, w); - redraw_invalidate_scene(w); server_redraw_window(w); } if (xpixel != -1) w->xpixel = xpixel; if (ypixel != -1) w->ypixel = ypixel; + redraw_invalidate_scene(w); } void From a57b0f1282129231d3e0934062991feb11381976 Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 21 Jul 2026 13:27:41 +0000 Subject: [PATCH 3/3] Clip floating panes exactly at window edge, don't let the border creep into the first outside column. --- screen-redraw.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/screen-redraw.c b/screen-redraw.c index a82d0566e..ea4af99bf 100644 --- a/screen-redraw.c +++ b/screen-redraw.c @@ -1,4 +1,4 @@ -/* $OpenBSD: screen-redraw.c,v 1.154 2026/07/21 11:53:41 nicm Exp $ */ +/* $OpenBSD: screen-redraw.c,v 1.155 2026/07/21 13:27:41 nicm Exp $ */ /* * Copyright (c) 2026 Nicholas Marriott @@ -696,20 +696,22 @@ redraw_mark_pane_borders(struct redraw_build_ctx *bctx, struct window_pane *wp, bottom = wp->yoff + wp->sy; mark_left = (left >= 0); - mark_right = (right <= (int)bctx->w->sx); mark_top = (top >= 0); - mark_bottom = (bottom <= (int)bctx->w->sy); if (floating) { + mark_right = (right < (int)bctx->w->sx); + mark_bottom = (bottom < (int)bctx->w->sy); if (left < 0) left = 0; - if (right > (int)bctx->w->sx) + if (right >= (int)bctx->w->sx) right = (int)bctx->w->sx - 1; if (top < 0) top = 0; - if (bottom > (int)bctx->w->sy) + if (bottom >= (int)bctx->w->sy) bottom = (int)bctx->w->sy - 1; } else { + mark_right = (right <= (int)bctx->w->sx); + mark_bottom = (bottom <= (int)bctx->w->sy); if (pane_status == PANE_STATUS_TOP) mark_bottom = 0; else if (pane_status == PANE_STATUS_BOTTOM)