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:
tmux update bot
2026-07-15 15:53:06 +00:00
13 changed files with 269 additions and 35 deletions

View File

@@ -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));

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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
View File

@@ -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;

View File

@@ -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
},

View File

@@ -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);
}

View File

@@ -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."

View File

@@ -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
View File

@@ -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
View File

@@ -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
View File

@@ -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 *);

View File

@@ -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);
}