mirror of
https://github.com/tmux/tmux.git
synced 2026-07-26 18:41:53 +00:00
Merge remote-tracking branch 'refs/remotes/tmux-openbsd/master'
* refs/remotes/tmux-openbsd/master: Small section missed from previous. Add modal panes, created currently with new-pane -O. There is one modal pane per window and it must be a floating pane. These are intended to replace popups. Currently a modal pane will unzoom a zoomed window and rezoom it when it is closed (a bit like modes do), but this is planned to change when we get an always-on-top flag.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: cmd-break-pane.c,v 1.73 2026/07/13 13:01:14 nicm Exp $ */
|
||||
/* $OpenBSD: cmd-break-pane.c,v 1.74 2026/07/15 13:02:33 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
@@ -103,6 +103,11 @@ cmd_break_pane_exec(struct cmd *self, struct cmdq_item *item)
|
||||
int idx = target->idx, before, old_idx = wl->idx;
|
||||
const char *template, *name = args_get(args, 'n');
|
||||
|
||||
if (wp == w->modal) {
|
||||
cmdq_error(item, "pane is modal");
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
|
||||
if (args_has(args, 'W'))
|
||||
return (cmd_break_pane_float(item, args, w, wp));
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: cmd-join-pane.c,v 1.71 2026/07/13 13:01:14 nicm Exp $ */
|
||||
/* $OpenBSD: cmd-join-pane.c,v 1.72 2026/07/15 13:02:33 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2011 George Nachman <tmux@georgester.com>
|
||||
@@ -424,7 +424,6 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item)
|
||||
dst_wp = target->wp;
|
||||
dst_w = dst_wl->window;
|
||||
dst_idx = dst_wl->idx;
|
||||
server_unzoom_window(dst_w);
|
||||
|
||||
if (cmd_get_entry(self) == &cmd_move_pane_entry) {
|
||||
if (args_has(args, 'M'))
|
||||
@@ -433,22 +432,35 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item)
|
||||
cmdq_error(item, "pane is not floating");
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
if ((s = args_get(args, 'P')) != NULL)
|
||||
if ((s = args_get(args, 'P')) != NULL) {
|
||||
server_unzoom_window(dst_w);
|
||||
return (cmd_join_pane_place(item, dst_wl, dst_wp, s));
|
||||
if ((s = args_get(args, 'z')) != NULL)
|
||||
}
|
||||
if ((s = args_get(args, 'z')) != NULL) {
|
||||
server_unzoom_window(dst_w);
|
||||
return (cmd_join_pane_zindex(item, dst_wl, dst_wp, s));
|
||||
}
|
||||
if (args_has(args, 'X') ||
|
||||
args_has(args, 'Y') ||
|
||||
args_has(args, 'U') ||
|
||||
args_has(args, 'D') ||
|
||||
args_has(args, 'L') ||
|
||||
args_has(args, 'R'))
|
||||
args_has(args, 'R')) {
|
||||
server_unzoom_window(dst_w);
|
||||
return (cmd_join_pane_move(item, args, dst_wl, dst_wp));
|
||||
}
|
||||
}
|
||||
|
||||
src_wl = source->wl;
|
||||
src_wp = source->wp;
|
||||
src_w = src_wl->window;
|
||||
|
||||
if (src_wp == src_w->modal || dst_wp == dst_w->modal) {
|
||||
cmdq_error(item, "pane is modal");
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
|
||||
server_unzoom_window(dst_w);
|
||||
server_unzoom_window(src_w);
|
||||
|
||||
if (src_wp == dst_wp) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: cmd-split-window.c,v 1.144 2026/07/14 15:06:54 nicm Exp $ */
|
||||
/* $OpenBSD: cmd-split-window.c,v 1.145 2026/07/15 13:02:33 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
@@ -40,8 +40,8 @@ const struct cmd_entry cmd_new_pane_entry = {
|
||||
.name = "new-pane",
|
||||
.alias = "newp",
|
||||
|
||||
.args = { "bB:c:de:EfF:hIkl:LMm:p:PR:s:S:t:T:vWx:X:y:Y:Z", 0, -1, NULL },
|
||||
.usage = "[-bdefhIklMPvWZ] [-B border-lines] "
|
||||
.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] "
|
||||
"[-c start-directory] [-e environment] "
|
||||
"[-F format] [-l size] [-m message] [-p percentage] "
|
||||
"[-s style] [-S active-border-style] "
|
||||
@@ -103,6 +103,17 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
|
||||
flags |= SPAWN_SPLIT;
|
||||
}
|
||||
|
||||
if (args_has(args, 'O')) {
|
||||
if (!is_floating) {
|
||||
cmdq_error(item, "modal pane must be floating");
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
if (w->modal != NULL) {
|
||||
cmdq_error(item, "window already has a modal pane");
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
if (args_has(args, 'M') && is_floating) {
|
||||
if (event == NULL || !event->m.valid || tc == NULL)
|
||||
return (CMD_RETURN_NORMAL);
|
||||
@@ -120,6 +131,8 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
|
||||
flags |= SPAWN_DETACHED;
|
||||
if (args_has(args, 'Z'))
|
||||
flags |= SPAWN_ZOOM;
|
||||
if (args_has(args, 'O'))
|
||||
flags |= SPAWN_MODAL;
|
||||
|
||||
input = args_has(args, 'I');
|
||||
if (input || (count == 1 && *args_string(args, 0) == '\0'))
|
||||
@@ -255,7 +268,7 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
|
||||
if (~flags & SPAWN_DETACHED)
|
||||
cmd_find_from_winlink_pane(current, wl, new_wp, 0);
|
||||
|
||||
if (~flags & SPAWN_FLOATING) {
|
||||
if ((~flags & SPAWN_FLOATING) && !args_has(args, 'O')) {
|
||||
window_pop_zoom(wp->window);
|
||||
server_redraw_window(wp->window);
|
||||
}
|
||||
@@ -306,7 +319,8 @@ fail:
|
||||
if (!is_floating)
|
||||
layout_close_pane(new_wp);
|
||||
window_remove_pane(wp->window, new_wp);
|
||||
}
|
||||
} else if (args_has(args, 'O'))
|
||||
window_pop_modal_zoom(wp->window);
|
||||
if (sc.argv != NULL)
|
||||
cmd_free_argv(sc.argc, sc.argv);
|
||||
environ_free(sc.environ);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: cmd-swap-pane.c,v 1.54 2026/07/13 13:01:14 nicm Exp $ */
|
||||
/* $OpenBSD: cmd-swap-pane.c,v 1.55 2026/07/15 13:02:33 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
@@ -77,6 +77,11 @@ cmd_swap_pane_exec(struct cmd *self, struct cmdq_item *item)
|
||||
src_wp = source->wp;
|
||||
src_idx = source->wl->idx;
|
||||
|
||||
if (src_wp == src_w->modal || dst_wp == dst_w->modal) {
|
||||
cmdq_error(item, "pane is modal");
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
|
||||
if (window_push_zoom(dst_w, 0, args_has(args, 'Z')))
|
||||
server_redraw_window(dst_w);
|
||||
|
||||
|
||||
4
cmd.c
4
cmd.c
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: cmd.c,v 1.187 2026/07/13 09:37:39 nicm Exp $ */
|
||||
/* $OpenBSD: cmd.c,v 1.188 2026/07/15 13:02:33 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
@@ -832,6 +832,8 @@ cmd_mouse_pane(struct mouse_event *m, struct session **sp,
|
||||
if (!window_has_pane(wl->window, wp))
|
||||
return (NULL);
|
||||
}
|
||||
if (wl->window->modal != NULL && wp != wl->window->modal)
|
||||
return (NULL);
|
||||
|
||||
if (wlp != NULL)
|
||||
*wlp = wl;
|
||||
|
||||
31
format.c
31
format.c
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: format.c,v 1.404 2026/07/14 15:06:54 nicm Exp $ */
|
||||
/* $OpenBSD: format.c,v 1.405 2026/07/15 13:02:33 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2011 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
@@ -1088,6 +1088,20 @@ format_cb_pane_floating_flag(struct format_tree *ft)
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Callback for pane_modal_flag. */
|
||||
static void *
|
||||
format_cb_pane_modal_flag(struct format_tree *ft)
|
||||
{
|
||||
struct window_pane *wp = ft->wp;
|
||||
|
||||
if (wp != NULL) {
|
||||
if (wp == wp->window->modal)
|
||||
return (xstrdup("1"));
|
||||
return (xstrdup("0"));
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Callback for pane_bg. */
|
||||
static void *
|
||||
format_cb_pane_bg(struct format_tree *ft)
|
||||
@@ -3102,6 +3116,15 @@ format_cb_window_marked_flag(struct format_tree *ft)
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Callback for window_modal_pane. */
|
||||
static void *
|
||||
format_cb_window_modal_pane(struct format_tree *ft)
|
||||
{
|
||||
if (ft->w != NULL && ft->w->modal != NULL)
|
||||
return (format_printf("%%%u", ft->w->modal->id));
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Callback for window_name. */
|
||||
static void *
|
||||
format_cb_window_name(struct format_tree *ft)
|
||||
@@ -3684,6 +3707,9 @@ static const struct format_table_entry format_table[] = {
|
||||
{ "pane_marked_set", FORMAT_TABLE_STRING,
|
||||
format_cb_pane_marked_set
|
||||
},
|
||||
{ "pane_modal_flag", FORMAT_TABLE_STRING,
|
||||
format_cb_pane_modal_flag
|
||||
},
|
||||
{ "pane_mode", FORMAT_TABLE_STRING,
|
||||
format_cb_pane_mode
|
||||
},
|
||||
@@ -3942,6 +3968,9 @@ static const struct format_table_entry format_table[] = {
|
||||
{ "window_marked_flag", FORMAT_TABLE_STRING,
|
||||
format_cb_window_marked_flag
|
||||
},
|
||||
{ "window_modal_pane", FORMAT_TABLE_STRING,
|
||||
format_cb_window_modal_pane
|
||||
},
|
||||
{ "window_name", FORMAT_TABLE_STRING,
|
||||
format_cb_window_name
|
||||
},
|
||||
|
||||
7
layout.c
7
layout.c
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: layout.c,v 1.95 2026/07/14 17:17:17 nicm Exp $ */
|
||||
/* $OpenBSD: layout.c,v 1.96 2026/07/15 13:02:33 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
@@ -1677,7 +1677,10 @@ layout_get_floating_cell(struct cmdq_item *item, struct args *args,
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
window_push_zoom(wp->window, 1, (flags & SPAWN_ZOOM));
|
||||
if (flags & SPAWN_MODAL)
|
||||
window_push_modal_zoom(w);
|
||||
else
|
||||
window_push_zoom(wp->window, 1, (flags & SPAWN_ZOOM));
|
||||
lcnew = layout_floating_pane(w, wp, &fg);
|
||||
return (lcnew);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: options-table.c,v 1.237 2026/07/14 17:17:17 nicm Exp $ */
|
||||
/* $OpenBSD: options-table.c,v 1.238 2026/07/15 13:02:33 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2011 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
@@ -1530,9 +1530,10 @@ const struct options_table_entry options_table[] = {
|
||||
{ .name = "pane-active-border-style",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE,
|
||||
.default_str = "fg=#{?pane_marked,thememagenta,"
|
||||
.default_str = "fg=#{?pane_modal_flag,themeblue,"
|
||||
"#{?pane_marked,thememagenta,"
|
||||
"#{?synchronize-panes,themered,"
|
||||
"#{?pane_in_mode,themeyellow,themegreen}}}",
|
||||
"#{?pane_in_mode,themeyellow,themegreen}}}}",
|
||||
.flags = OPTIONS_TABLE_IS_STYLE,
|
||||
.separator = ",",
|
||||
.text = "Style of the active pane border."
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: server-client.c,v 1.492 2026/07/15 10:38:31 nicm Exp $ */
|
||||
/* $OpenBSD: server-client.c,v 1.494 2026/07/15 14:14:50 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
@@ -871,6 +871,7 @@ server_client_check_mouse(struct client *c, struct key_event *event)
|
||||
u_int x, y, sx, sy, px, py, n, sl_mpos = 0;
|
||||
u_int b, bn;
|
||||
int ignore = 0;
|
||||
int modal_drag = 0;
|
||||
key_code key;
|
||||
struct timeval tv;
|
||||
struct style_range *sr;
|
||||
@@ -1053,9 +1054,34 @@ have_event:
|
||||
}
|
||||
px = px + m->ox;
|
||||
py = py + m->oy;
|
||||
if (w->modal != NULL &&
|
||||
!window_pane_contains(w->modal, px, py)) {
|
||||
if (lwp == w->modal &&
|
||||
c->tty.mouse_drag_flag != 0 &&
|
||||
(type == KEYC_TYPE_MOUSEDRAG ||
|
||||
type == KEYC_TYPE_MOUSEUP)) {
|
||||
modal_drag = 1;
|
||||
wp = lwp;
|
||||
loc = KEYC_MOUSE_LOCATION_PANE;
|
||||
m->wp = wp->id;
|
||||
m->w = wp->window->id;
|
||||
} else {
|
||||
server_client_update_scrollbar_hover(c, type,
|
||||
-1, -1);
|
||||
c->tty.mouse_drag_update = NULL;
|
||||
c->tty.mouse_drag_release = NULL;
|
||||
c->tty.mouse_drag_flag = 0;
|
||||
c->tty.mouse_scrolling_flag = 0;
|
||||
c->tty.mouse_slider_mpos = -1;
|
||||
c->tty.mouse_last_pane = -1;
|
||||
return (KEYC_UNKNOWN);
|
||||
}
|
||||
}
|
||||
server_client_update_scrollbar_hover(c, type, px, py);
|
||||
|
||||
if (type == KEYC_TYPE_MOUSEDRAG && lwp != NULL) {
|
||||
if (modal_drag) {
|
||||
/* Keep the drag with the modal pane. */
|
||||
} else if (type == KEYC_TYPE_MOUSEDRAG && lwp != NULL) {
|
||||
/* Use pane from last mouse event. */
|
||||
wp = lwp;
|
||||
} else {
|
||||
@@ -1067,8 +1093,10 @@ have_event:
|
||||
m->w = w->id;
|
||||
log_debug("mouse %u,%u on empty area", x, y);
|
||||
} else {
|
||||
loc = server_client_check_mouse_in_pane(wp, px, py,
|
||||
&sl_mpos);
|
||||
if (!modal_drag) {
|
||||
loc = server_client_check_mouse_in_pane(wp, px,
|
||||
py, &sl_mpos);
|
||||
}
|
||||
if (loc == KEYC_MOUSE_LOCATION_PANE) {
|
||||
log_debug("mouse %u,%u on pane %%%u", x, y,
|
||||
wp->id);
|
||||
@@ -3083,16 +3111,20 @@ struct window_pane *
|
||||
server_client_get_pane(struct client *c)
|
||||
{
|
||||
struct session *s = c->session;
|
||||
struct window *w;
|
||||
struct client_window *cw;
|
||||
|
||||
if (s == NULL)
|
||||
return (NULL);
|
||||
|
||||
w = s->curw->window;
|
||||
if (w->modal != NULL)
|
||||
return (w->modal);
|
||||
if (~c->flags & CLIENT_ACTIVEPANE)
|
||||
return (s->curw->window->active);
|
||||
cw = server_client_get_client_window(c, s->curw->window->id);
|
||||
return (w->active);
|
||||
cw = server_client_get_client_window(c, w->id);
|
||||
if (cw == NULL)
|
||||
return (s->curw->window->active);
|
||||
return (w->active);
|
||||
return (cw->pane);
|
||||
}
|
||||
|
||||
@@ -3105,6 +3137,8 @@ server_client_set_pane(struct client *c, struct window_pane *wp)
|
||||
|
||||
if (s == NULL)
|
||||
return;
|
||||
if (wp->window->modal != NULL && wp != wp->window->modal)
|
||||
return;
|
||||
|
||||
cw = server_client_add_client_window(c, s->curw->window->id);
|
||||
cw->pane = wp;
|
||||
|
||||
33
spawn.c
33
spawn.c
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: spawn.c,v 1.48 2026/07/13 13:01:14 nicm Exp $ */
|
||||
/* $OpenBSD: spawn.c,v 1.49 2026/07/15 13:02:33 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
@@ -271,6 +271,17 @@ spawn_pane(struct spawn_context *sc, char **cause)
|
||||
|
||||
spawn_log(__func__, sc);
|
||||
|
||||
if (sc->flags & SPAWN_MODAL) {
|
||||
if (~sc->flags & SPAWN_FLOATING) {
|
||||
xasprintf(cause, "modal pane must be floating");
|
||||
return (NULL);
|
||||
}
|
||||
if (w->modal != NULL) {
|
||||
xasprintf(cause, "window already has a modal pane");
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Work out the current working directory. If respawning, use
|
||||
* the pane's stored one unless specified.
|
||||
@@ -565,7 +576,16 @@ complete:
|
||||
|
||||
if (sc->flags & SPAWN_RESPAWN)
|
||||
return (new_wp);
|
||||
if ((~sc->flags & SPAWN_DETACHED) || w->active == NULL) {
|
||||
if (sc->flags & SPAWN_MODAL) {
|
||||
w->modal_last = w->active;
|
||||
w->modal = new_wp;
|
||||
window_redraw_active_switch(w, new_wp);
|
||||
if (sc->flags & SPAWN_NONOTIFY)
|
||||
window_set_active_pane(w, new_wp, 0);
|
||||
else
|
||||
window_set_active_pane(w, new_wp, 1);
|
||||
} else if (((~sc->flags & SPAWN_DETACHED) || w->active == NULL) &&
|
||||
w->modal == NULL) {
|
||||
if (sc->flags & SPAWN_NONOTIFY)
|
||||
window_set_active_pane(w, new_wp, 0);
|
||||
else
|
||||
@@ -681,6 +701,9 @@ spawn_editor(struct client *c, const char *buf, size_t len,
|
||||
const char *editor;
|
||||
int fd;
|
||||
|
||||
if (w->modal != NULL)
|
||||
return (NULL);
|
||||
|
||||
editor = options_get_string(global_options, "editor");
|
||||
fd = mkstemp(path);
|
||||
if (fd == -1)
|
||||
@@ -707,9 +730,10 @@ spawn_editor(struct client *c, const char *buf, size_t len,
|
||||
lg.sy = w->sy * 9 / 10;
|
||||
lg.xoff = w->sx / 2 - lg.sx / 2;
|
||||
lg.yoff = w->sy / 2 - lg.sy / 2;
|
||||
window_push_zoom(w, 1, 0);
|
||||
window_push_modal_zoom(w);
|
||||
lc = layout_floating_pane(w, NULL, &lg);
|
||||
if (lc == NULL) {
|
||||
window_pop_modal_zoom(w);
|
||||
spawn_editor_free(es);
|
||||
return (NULL);
|
||||
}
|
||||
@@ -726,13 +750,14 @@ spawn_editor(struct client *c, const char *buf, size_t len,
|
||||
sc.environ = env;
|
||||
sc.idx = -1;
|
||||
sc.cwd = _PATH_TMP;
|
||||
sc.flags = SPAWN_FLOATING;
|
||||
sc.flags = SPAWN_FLOATING|SPAWN_MODAL;
|
||||
|
||||
wp = spawn_pane(&sc, &cause);
|
||||
free(cmd);
|
||||
environ_free(env);
|
||||
if (wp == NULL) {
|
||||
free(cause);
|
||||
window_pop_modal_zoom(w);
|
||||
spawn_editor_free(es);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
11
tmux.1
11
tmux.1
@@ -1,4 +1,4 @@
|
||||
.\" $OpenBSD: tmux.1,v 1.1141 2026/07/15 10:38:31 nicm Exp $
|
||||
.\" $OpenBSD: tmux.1,v 1.1142 2026/07/15 13:02:33 nicm Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
.\"
|
||||
@@ -3647,7 +3647,7 @@ but a different format may be specified with
|
||||
.Fl F .
|
||||
.Tg newp
|
||||
.It Xo Ic new\-pane
|
||||
.Op Fl bdefhIkLMPvWZ
|
||||
.Op Fl bdefhIkLMOPvWZ
|
||||
.Op Fl B Ar border\-lines
|
||||
.Op Fl c Ar start\-directory
|
||||
.Op Fl e Ar environment
|
||||
@@ -3698,6 +3698,11 @@ may be used when bound to a mouse drag key; the new floating pane is resized to
|
||||
follow the mouse drag.
|
||||
It has no effect with
|
||||
.Fl L .
|
||||
.Fl O
|
||||
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.
|
||||
.Pp
|
||||
The
|
||||
.Fl L
|
||||
@@ -7320,6 +7325,7 @@ The following variables are available, where appropriate:
|
||||
.It Li "pane_left" Ta "" Ta "Left of pane"
|
||||
.It Li "pane_marked" Ta "" Ta "1 if this is the marked pane"
|
||||
.It Li "pane_marked_set" Ta "" Ta "1 if a marked pane is set"
|
||||
.It Li "pane_modal_flag" Ta "" Ta "1 if pane is modal"
|
||||
.It Li "pane_mode" Ta "" Ta "Name of pane mode, if any"
|
||||
.It Li "pane_path" Ta "" Ta "Path of pane (can be set by application)"
|
||||
.It Li "pane_pid" Ta "" Ta "PID of first process in pane"
|
||||
@@ -7420,6 +7426,7 @@ The following variables are available, where appropriate:
|
||||
.It Li "window_manual_height" Ta "" Ta "Manual height of window, if set"
|
||||
.It Li "window_manual_width" Ta "" Ta "Manual width of window, if set"
|
||||
.It Li "window_marked_flag" Ta "" Ta "1 if window contains the marked pane"
|
||||
.It Li "window_modal_pane" Ta "" Ta "Modal pane in window, if any"
|
||||
.It Li "window_name" Ta "#W" Ta "Name of window"
|
||||
.It Li "window_offset_x" Ta "" Ta "X offset into window if larger than client"
|
||||
.It Li "window_offset_y" Ta "" Ta "Y offset into window if larger than client"
|
||||
|
||||
9
tmux.h
9
tmux.h
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: tmux.h,v 1.1405 2026/07/15 10:38:31 nicm Exp $ */
|
||||
/* $OpenBSD: tmux.h,v 1.1406 2026/07/15 13:02:33 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
@@ -1415,6 +1415,8 @@ struct window {
|
||||
struct timeval creation_time;
|
||||
|
||||
struct window_pane *active;
|
||||
struct window_pane *modal;
|
||||
struct window_pane *modal_last;
|
||||
struct window_panes last_panes;
|
||||
struct window_panes z_index;
|
||||
struct window_panes panes;
|
||||
@@ -1456,6 +1458,7 @@ struct window {
|
||||
#define WINDOW_ZOOMED 0x8
|
||||
#define WINDOW_WASZOOMED 0x10
|
||||
#define WINDOW_RESIZE 0x20
|
||||
#define WINDOW_WASMODALZOOMED 0x40
|
||||
#define WINDOW_ALERTFLAGS (WINDOW_BELL|WINDOW_ACTIVITY|WINDOW_SILENCE)
|
||||
|
||||
int alerts_queued;
|
||||
@@ -2513,6 +2516,7 @@ struct spawn_context {
|
||||
#define SPAWN_FLOATING 0x100
|
||||
#define SPAWN_HORIZONTAL 0x200
|
||||
#define SPAWN_SPLIT 0x400
|
||||
#define SPAWN_MODAL 0x800
|
||||
};
|
||||
|
||||
/* Paste buffer. */
|
||||
@@ -3688,6 +3692,7 @@ struct window_pane *window_get_active_at(struct window *, u_int, u_int);
|
||||
struct window_pane *window_find_string(struct window *, const char *);
|
||||
int window_has_floating_panes(struct window *);
|
||||
int window_has_pane(struct window *, struct window_pane *);
|
||||
int window_pane_contains(struct window_pane *, u_int, u_int);
|
||||
int window_set_active_pane(struct window *, struct window_pane *,
|
||||
int);
|
||||
void window_fire_pane_moved(struct window_pane *, struct window *,
|
||||
@@ -3702,6 +3707,8 @@ void window_resize(struct window *, u_int, u_int, int, int);
|
||||
void window_pane_send_resize(struct window_pane *, u_int, u_int);
|
||||
int window_zoom(struct window_pane *);
|
||||
int window_unzoom(struct window *, int);
|
||||
void window_push_modal_zoom(struct window *);
|
||||
int window_pop_modal_zoom(struct window *);
|
||||
int window_push_zoom(struct window *, int, int);
|
||||
int window_pop_zoom(struct window *);
|
||||
void window_lost_pane(struct window *, struct window_pane *);
|
||||
|
||||
94
window.c
94
window.c
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: window.c,v 1.363 2026/07/14 19:07:03 nicm Exp $ */
|
||||
/* $OpenBSD: window.c,v 1.364 2026/07/15 13:02:33 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
@@ -633,6 +633,35 @@ window_has_pane(struct window *w, struct window_pane *wp)
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
window_pane_contains(struct window_pane *wp, u_int x, u_int y)
|
||||
{
|
||||
int xoff, yoff;
|
||||
u_int sx, sy;
|
||||
|
||||
if (!window_pane_is_visible(wp))
|
||||
return (0);
|
||||
|
||||
window_pane_full_size_offset(wp, &xoff, &yoff, &sx, &sy);
|
||||
if (!window_pane_is_floating(wp)) {
|
||||
if ((int)x < xoff || x > xoff + sx)
|
||||
return (0);
|
||||
if ((int)y < yoff || y > yoff + sy)
|
||||
return (0);
|
||||
} else if (window_pane_get_pane_lines(wp) == PANE_LINES_NONE) {
|
||||
if ((int)x < xoff || (int)x >= xoff + (int)sx)
|
||||
return (0);
|
||||
if ((int)y < yoff || (int)y >= yoff + (int)sy)
|
||||
return (0);
|
||||
} else {
|
||||
if ((int)x < xoff - 1 || x > xoff + sx)
|
||||
return (0);
|
||||
if ((int)y < yoff - 1 || y > yoff + sy)
|
||||
return (0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
void
|
||||
window_update_focus(struct window *w)
|
||||
{
|
||||
@@ -690,6 +719,8 @@ window_set_active_pane(struct window *w, struct window_pane *wp, int notify)
|
||||
|
||||
if (wp == w->active)
|
||||
return (0);
|
||||
if (w->modal != NULL && wp != w->modal)
|
||||
return (0);
|
||||
if (w->flags & WINDOW_ZOOMED)
|
||||
window_unzoom(w, 1);
|
||||
lastwp = w->active;
|
||||
@@ -728,6 +759,8 @@ window_redraw_active_switch(struct window *w, struct window_pane *wp)
|
||||
struct grid_cell *gc1, *gc2;
|
||||
int c1, c2;
|
||||
|
||||
if (w->modal != NULL && wp != w->modal)
|
||||
return;
|
||||
if (wp == w->active)
|
||||
return;
|
||||
|
||||
@@ -780,6 +813,12 @@ window_get_active_at(struct window *w, u_int x, u_int y)
|
||||
|
||||
pane_status = window_get_pane_status(w);
|
||||
|
||||
if (w->modal != NULL) {
|
||||
if (window_pane_contains(w->modal, x, y))
|
||||
return (w->modal);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (pane_status == PANE_STATUS_TOP) {
|
||||
/*
|
||||
* Prefer a pane's top border status line over the pane above's
|
||||
@@ -936,6 +975,29 @@ window_unzoom(struct window *w, int notify)
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
window_push_modal_zoom(struct window *w)
|
||||
{
|
||||
if (w->flags & WINDOW_ZOOMED)
|
||||
w->flags |= WINDOW_WASMODALZOOMED;
|
||||
else
|
||||
w->flags &= ~WINDOW_WASMODALZOOMED;
|
||||
window_unzoom(w, 1);
|
||||
}
|
||||
|
||||
int
|
||||
window_pop_modal_zoom(struct window *w)
|
||||
{
|
||||
struct window_pane *wp = w->active;
|
||||
|
||||
if (~w->flags & WINDOW_WASMODALZOOMED)
|
||||
return (0);
|
||||
w->flags &= ~WINDOW_WASMODALZOOMED;
|
||||
if (wp != NULL && window_has_pane(w, wp))
|
||||
return (window_zoom(wp) == 0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
window_push_zoom(struct window *w, int always, int flag)
|
||||
{
|
||||
@@ -986,6 +1048,8 @@ window_add_pane(struct window *w, struct window_pane *other, u_int hlimit,
|
||||
}
|
||||
if (~flags & SPAWN_FLOATING)
|
||||
TAILQ_INSERT_TAIL(&w->z_index, wp, zentry);
|
||||
else if (w->modal != NULL)
|
||||
TAILQ_INSERT_AFTER(&w->z_index, w->modal, wp, zentry);
|
||||
else {
|
||||
TAILQ_INSERT_HEAD(&w->z_index, wp, zentry);
|
||||
}
|
||||
@@ -996,14 +1060,29 @@ window_add_pane(struct window *w, struct window_pane *other, u_int hlimit,
|
||||
void
|
||||
window_lost_pane(struct window *w, struct window_pane *wp)
|
||||
{
|
||||
struct window_pane *lastwp;
|
||||
|
||||
log_debug("%s: @%u pane %%%u", __func__, w->id, wp->id);
|
||||
|
||||
if (wp == marked_pane.wp)
|
||||
server_clear_marked();
|
||||
if (wp == w->modal_last)
|
||||
w->modal_last = NULL;
|
||||
if (w->modal_last == NULL)
|
||||
w->flags &= ~WINDOW_WASMODALZOOMED;
|
||||
|
||||
window_pane_stack_remove(&w->last_panes, wp);
|
||||
if (wp == w->active) {
|
||||
w->active = TAILQ_FIRST(&w->last_panes);
|
||||
lastwp = NULL;
|
||||
if (wp == w->modal) {
|
||||
lastwp = w->modal_last;
|
||||
w->modal = NULL;
|
||||
w->modal_last = NULL;
|
||||
}
|
||||
if (lastwp != NULL && window_has_pane(w, lastwp))
|
||||
w->active = lastwp;
|
||||
else
|
||||
w->active = TAILQ_FIRST(&w->last_panes);
|
||||
if (w->active == NULL) {
|
||||
w->active = TAILQ_PREV(wp, window_panes, entry);
|
||||
if (w->active == NULL)
|
||||
@@ -1015,6 +1094,9 @@ window_lost_pane(struct window *w, struct window_pane *wp)
|
||||
window_fire_pane_changed(w, w->active, wp);
|
||||
window_update_focus(w);
|
||||
}
|
||||
} else if (wp == w->modal) {
|
||||
w->modal = w->modal_last = NULL;
|
||||
w->flags &= ~WINDOW_WASMODALZOOMED;
|
||||
}
|
||||
redraw_invalidate_scene(w);
|
||||
}
|
||||
@@ -1022,9 +1104,13 @@ window_lost_pane(struct window *w, struct window_pane *wp)
|
||||
void
|
||||
window_remove_pane(struct window *w, struct window_pane *wp)
|
||||
{
|
||||
int pop = (wp == w->modal);
|
||||
|
||||
window_lost_pane(w, wp);
|
||||
TAILQ_REMOVE(&w->panes, wp, entry);
|
||||
TAILQ_REMOVE(&w->z_index, wp, zentry);
|
||||
if (pop && window_pop_modal_zoom(w))
|
||||
server_redraw_window(w);
|
||||
redraw_invalidate_scene(w);
|
||||
window_pane_destroy(wp);
|
||||
}
|
||||
@@ -1157,6 +1243,8 @@ window_printable_flags(struct winlink *wl, int escape)
|
||||
flags[pos++] = '-';
|
||||
if (server_check_marked() && wl == marked_pane.wl)
|
||||
flags[pos++] = 'M';
|
||||
if (wl->window->modal != NULL)
|
||||
flags[pos++] = 'O';
|
||||
if (wl->window->flags & WINDOW_ZOOMED)
|
||||
flags[pos++] = 'Z';
|
||||
flags[pos] = '\0';
|
||||
@@ -1178,6 +1266,8 @@ window_pane_printable_flags(struct window_pane *wp)
|
||||
flags[pos++] = 'Z';
|
||||
if (window_pane_is_floating(wp))
|
||||
flags[pos++] = 'F';
|
||||
if (wp == w->modal)
|
||||
flags[pos++] = 'O';
|
||||
flags[pos] = '\0';
|
||||
return (flags);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user