Compare commits

...

29 Commits

Author SHA1 Message Date
Michael Grant
2f7429c556
Merge 76b8ee08ef244537c4050bb99346a550c7d5222d into 7e439539377e272f37d18bb10dbff374b87acee6 2025-07-02 22:29:03 +02:00
Thomas Adam
7e43953937 Merge branch 'obsd-master' 2025-07-02 12:01:08 +01:00
nicm
28481e984b Add sorting to W, P, L operators as well, and add some new session
format variables. From Michael Grant in GitHub issue 4516.
2025-07-02 08:13:09 +00:00
Michael Grant
76b8ee08ef
Merge branch 'tmux:master' into non-blocking-popup-windows 2025-06-16 16:56:26 -04:00
Michael Grant
b9d7771f2a
Merge branch 'tmux:master' into non-blocking-popup-windows 2025-05-15 01:57:02 -04:00
Michael Grant
c22a60e412 Only redraw the whole window if the menu was closed, otherwise the user will see flashing when the mouse moves. 2025-05-06 10:52:48 +02:00
Michael Grant
b9222a6613 A better fix. 2025-05-06 06:56:26 +02:00
Michael Grant
71a7206e8b Merge branch 'non-blocking-popup-windows' of github.com:mgrant0/tmux into non-blocking-popup-windows 2025-05-05 22:19:36 +02:00
Michael Grant
eb3867d02e Fix bug if pane is focused and its menu is open that it does not change focus to the overlay popup if the mouse moves over that rectangle area. 2025-05-05 22:18:27 +02:00
Michael Grant
4ac0c79d8e
Merge branch 'tmux:master' into non-blocking-popup-windows 2025-05-04 07:42:10 -04:00
Michael Grant
2bae40ec7e Move window menu out of overlay into window struct. 2025-04-17 15:10:33 +01:00
Michael Grant
fe3ed1d7a8
Merge branch 'tmux:master' into non-blocking-popup-windows 2025-04-17 08:50:54 -04:00
Michael Grant
f11fa9d7f0 Check for right mouse button if pane is focused, let pane handle it. 2025-04-05 15:48:27 +01:00
Michael Grant
e7bc34df3d fix segv when overlay_check is null 2025-04-05 15:44:22 +01:00
Michael Grant
9327991d8b
Merge branch 'tmux:master' into non-blocking-popup-windows 2025-04-04 05:01:51 -04:00
Michael Grant
5001c8148a To fix a race condition by inhibitting it from calling popup_free_cb twice 2025-04-03 14:12:45 +01:00
Michael Grant
f755a007fa update man page 2025-04-01 17:41:26 +01:00
Michael Grant
4b545ac620
Merge branch 'tmux:master' into non-blocking-popup-windows 2025-03-31 10:52:31 -04:00
Michael Grant
5091236d4d skip foreach loop if done 2025-03-29 23:04:14 +00:00
Michael Grant
7fa11dcd24 -D arg to enable do not block 2025-03-29 22:47:49 +00:00
Michael Grant
6ab507c9ce rename CLIENT_OVERLAYPOPUP_FOCUSED to CLIENT_OVERLAYFOCUSED 2025-03-27 14:34:35 +00:00
Michael Grant
f6818a097f
Merge branch 'tmux:master' into non-blocking-popup-windows 2025-03-26 12:53:30 -04:00
Michael Grant
0a0e9852a2 Add overlay check to scrollbar code to prevent scrollbars obscured by an overlay from flashing while being dragged around. 2025-03-12 15:44:04 -04:00
Michael Grant
c0ff4831fc Add check to check if cursor is behind the overlay popup. 2025-03-12 15:34:48 -04:00
Michael Grant
5327f39134 Try 2. Move popup focus flag into client struct. 2025-03-12 13:52:17 -04:00
Michael Grant
66bf623259
Merge branch 'tmux:master' into non-blocking-popup-windows 2025-03-11 14:29:42 -04:00
Michael Grant
616143ea31
Merge branch 'tmux:master' into non-blocking-popup-windows 2025-03-04 15:20:12 -05:00
Michael Grant
43c947c348
Merge branch 'tmux:master' into non-blocking-popup-windows 2025-02-22 13:47:03 -05:00
Michael Grant
41ef18debb initial commit 2025-01-19 16:20:14 -04:00
10 changed files with 486 additions and 56 deletions

View File

@ -54,7 +54,7 @@ const struct cmd_entry cmd_display_popup_entry = {
.name = "display-popup", .name = "display-popup",
.alias = "popup", .alias = "popup",
.args = { "Bb:Cc:d:e:Eh:s:S:t:T:w:x:y:", 0, -1, NULL }, .args = { "Bb:Cc:Dd:e:Eh:s:S:t:T:w:x:y:", 0, -1, NULL },
.usage = "[-BCE] [-b border-lines] [-c target-client] " .usage = "[-BCE] [-b border-lines] [-c target-client] "
"[-d start-directory] [-e environment] [-h height] " "[-d start-directory] [-e environment] [-h height] "
"[-s style] [-S border-style] " CMD_TARGET_PANE_USAGE "[-s style] [-S border-style] " CMD_TARGET_PANE_USAGE
@ -301,7 +301,7 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item)
struct options_entry *oe; struct options_entry *oe;
if (tc->overlay_draw != NULL) if ((tc->overlay_draw != NULL) && (tc->flags & CLIENT_OVERLAYFOCUSED))
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);
if (args_has(args, 'C')) { if (args_has(args, 'C')) {
@ -484,6 +484,8 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item)
flags |= POPUP_CLOSEEXITZERO; flags |= POPUP_CLOSEEXITZERO;
else if (args_has(args, 'E')) else if (args_has(args, 'E'))
flags |= POPUP_CLOSEEXIT; flags |= POPUP_CLOSEEXIT;
if (args_has(args, 'D'))
item = NULL;
if (popup_display(flags, lines, item, px, py, w, h, env, shellcmd, argc, if (popup_display(flags, lines, item, px, py, w, h, env, shellcmd, argc,
argv, cwd, title, tc, s, style, border_style, NULL, NULL) != 0) { argv, cwd, title, tc, s, style, border_style, NULL, NULL) != 0) {
cmd_free_argv(argc, argv); cmd_free_argv(argc, argv);
@ -498,5 +500,8 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item)
free(cwd); free(cwd);
free(title); free(title);
cmd_free_argv(argc, argv); cmd_free_argv(argc, argv);
return (CMD_RETURN_WAIT); if (args_has(args, 'D'))
return (CMD_RETURN_NORMAL);
else
return (CMD_RETURN_WAIT);
} }

371
format.c
View File

@ -140,8 +140,8 @@ enum format_loop_sort_type {
}; };
static struct format_loop_sort_criteria { static struct format_loop_sort_criteria {
u_int field; enum format_loop_sort_type field;
int reversed; int reversed;
} format_loop_sort_criteria; } format_loop_sort_criteria;
struct format_tree { struct format_tree {
@ -554,6 +554,38 @@ format_cb_session_attached_list(struct format_tree *ft)
return (value); return (value);
} }
/* Callback for session_alert. */
static void *
format_cb_session_alert(struct format_tree *ft)
{
struct session *s = ft->s;
struct winlink *wl;
char alerts[1024];
int alerted = 0;
if (s == NULL)
return (NULL);
*alerts = '\0';
RB_FOREACH(wl, winlinks, &s->windows) {
if ((wl->flags & WINLINK_ALERTFLAGS) == 0)
continue;
if (~alerted & wl->flags & WINLINK_ACTIVITY) {
strlcat(alerts, "#", sizeof alerts);
alerted |= WINLINK_ACTIVITY;
}
if (~alerted & wl->flags & WINLINK_BELL) {
strlcat(alerts, "!", sizeof alerts);
alerted |= WINLINK_BELL;
}
if (~alerted & wl->flags & WINLINK_SILENCE) {
strlcat(alerts, "~", sizeof alerts);
alerted |= WINLINK_SILENCE;
}
}
return (xstrdup(alerts));
}
/* Callback for session_alerts. */ /* Callback for session_alerts. */
static void * static void *
format_cb_session_alerts(struct format_tree *ft) format_cb_session_alerts(struct format_tree *ft)
@ -1743,6 +1775,15 @@ format_cb_keypad_flag(struct format_tree *ft)
return (NULL); return (NULL);
} }
/* Callback for loop_last_flag. */
static void *
format_cb_loop_last_flag(struct format_tree *ft)
{
if (ft->flags & FORMAT_LAST)
return (xstrdup("1"));
return (xstrdup("0"));
}
/* Callback for mouse_all_flag. */ /* Callback for mouse_all_flag. */
static void * static void *
format_cb_mouse_all_flag(struct format_tree *ft) format_cb_mouse_all_flag(struct format_tree *ft)
@ -2264,6 +2305,66 @@ format_cb_server_sessions(__unused struct format_tree *ft)
return (format_printf("%u", n)); return (format_printf("%u", n));
} }
/* Callback for session_active. */
static void *
format_cb_session_active(struct format_tree *ft)
{
if (ft->s == NULL || ft->c == NULL)
return (NULL);
if (ft->c->session == ft->s)
return (xstrdup("1"));
return (xstrdup("0"));
}
/* Callback for session_activity_flag. */
static void *
format_cb_session_activity_flag(struct format_tree *ft)
{
struct winlink *wl;
if (ft->s != NULL) {
RB_FOREACH(wl, winlinks, &ft->s->windows) {
if (ft->wl->flags & WINLINK_ACTIVITY)
return (xstrdup("1"));
return (xstrdup("0"));
}
}
return (NULL);
}
/* Callback for session_bell_flag. */
static void *
format_cb_session_bell_flag(struct format_tree *ft)
{
struct winlink *wl;
if (ft->s != NULL) {
RB_FOREACH(wl, winlinks, &ft->s->windows) {
if (wl->flags & WINLINK_BELL)
return (xstrdup("1"));
return (xstrdup("0"));
}
}
return (NULL);
}
/* Callback for session_silence_flag. */
static void *
format_cb_session_silence_flag(struct format_tree *ft)
{
struct winlink *wl;
if (ft->s != NULL) {
RB_FOREACH(wl, winlinks, &ft->s->windows) {
if (ft->wl->flags & WINLINK_SILENCE)
return (xstrdup("1"));
return (xstrdup("0"));
}
}
return (NULL);
}
/* Callback for session_attached. */ /* Callback for session_attached. */
static void * static void *
format_cb_session_attached(struct format_tree *ft) format_cb_session_attached(struct format_tree *ft)
@ -3054,6 +3155,9 @@ static const struct format_table_entry format_table[] = {
{ "last_window_index", FORMAT_TABLE_STRING, { "last_window_index", FORMAT_TABLE_STRING,
format_cb_last_window_index format_cb_last_window_index
}, },
{ "loop_last_flag", FORMAT_TABLE_STRING,
format_cb_loop_last_flag
},
{ "mouse_all_flag", FORMAT_TABLE_STRING, { "mouse_all_flag", FORMAT_TABLE_STRING,
format_cb_mouse_all_flag format_cb_mouse_all_flag
}, },
@ -3234,9 +3338,18 @@ static const struct format_table_entry format_table[] = {
{ "server_sessions", FORMAT_TABLE_STRING, { "server_sessions", FORMAT_TABLE_STRING,
format_cb_server_sessions format_cb_server_sessions
}, },
{ "session_active", FORMAT_TABLE_STRING,
format_cb_session_active
},
{ "session_activity", FORMAT_TABLE_TIME, { "session_activity", FORMAT_TABLE_TIME,
format_cb_session_activity format_cb_session_activity
}, },
{ "session_activity_flag", FORMAT_TABLE_STRING,
format_cb_session_activity_flag
},
{ "session_alert", FORMAT_TABLE_STRING,
format_cb_session_alert
},
{ "session_alerts", FORMAT_TABLE_STRING, { "session_alerts", FORMAT_TABLE_STRING,
format_cb_session_alerts format_cb_session_alerts
}, },
@ -3246,6 +3359,9 @@ static const struct format_table_entry format_table[] = {
{ "session_attached_list", FORMAT_TABLE_STRING, { "session_attached_list", FORMAT_TABLE_STRING,
format_cb_session_attached_list format_cb_session_attached_list
}, },
{ "session_bell_flag", FORMAT_TABLE_STRING,
format_cb_session_bell_flag
},
{ "session_created", FORMAT_TABLE_TIME, { "session_created", FORMAT_TABLE_TIME,
format_cb_session_created format_cb_session_created
}, },
@ -3291,6 +3407,9 @@ static const struct format_table_entry format_table[] = {
{ "session_path", FORMAT_TABLE_STRING, { "session_path", FORMAT_TABLE_STRING,
format_cb_session_path format_cb_session_path
}, },
{ "session_silence_flag", FORMAT_TABLE_STRING,
format_cb_session_silence_flag
},
{ "session_stack", FORMAT_TABLE_STRING, { "session_stack", FORMAT_TABLE_STRING,
format_cb_session_stack format_cb_session_stack
}, },
@ -4044,7 +4163,7 @@ format_build_modifiers(struct format_expand_state *es, const char **s,
} }
/* Now try single character with arguments. */ /* Now try single character with arguments. */
if (strchr("mCNSst=pReq", cp[0]) == NULL) if (strchr("mCLNPSst=pReqW", cp[0]) == NULL)
break; break;
c = cp[0]; c = cp[0];
@ -4243,13 +4362,14 @@ format_session_name(struct format_expand_state *es, const char *fmt)
static int static int
format_cmp_session(const void *a0, const void *b0) format_cmp_session(const void *a0, const void *b0)
{ {
const struct session *const *a = a0; struct format_loop_sort_criteria *sc = &format_loop_sort_criteria;
const struct session *const *b = b0; const struct session *const *a = a0;
const struct session *sa = *a; const struct session *const *b = b0;
const struct session *sb = *b; const struct session *sa = *a;
int result = 0; const struct session *sb = *b;
int result = 0;
switch (format_loop_sort_criteria.field) { switch (sc->field) {
case FORMAT_LOOP_BY_INDEX: case FORMAT_LOOP_BY_INDEX:
result = sa->id - sb->id; result = sa->id - sb->id;
break; break;
@ -4268,7 +4388,7 @@ format_cmp_session(const void *a0, const void *b0)
break; break;
} }
if (format_loop_sort_criteria.reversed) if (sc->reversed)
result = -result; result = -result;
return (result); return (result);
} }
@ -4285,7 +4405,7 @@ format_loop_sessions(struct format_expand_state *es, const char *fmt)
char *all, *active, *use, *expanded, *value; char *all, *active, *use, *expanded, *value;
size_t valuelen; size_t valuelen;
struct session *s; struct session *s;
int i, n; int i, n, last = 0;
static struct session **l = NULL; static struct session **l = NULL;
static int lsz = 0; static int lsz = 0;
@ -4315,7 +4435,9 @@ format_loop_sessions(struct format_expand_state *es, const char *fmt)
use = active; use = active;
else else
use = all; use = all;
nft = format_create(c, item, FORMAT_NONE, ft->flags); if (i == n - 1)
last = FORMAT_LAST;
nft = format_create(c, item, FORMAT_NONE, ft->flags|last);
format_defaults(nft, ft->c, s, NULL, NULL); format_defaults(nft, ft->c, s, NULL, NULL);
format_copy_state(&next, es, 0); format_copy_state(&next, es, 0);
next.ft = nft; next.ft = nft;
@ -4356,6 +4478,40 @@ format_window_name(struct format_expand_state *es, const char *fmt)
return (xstrdup("0")); return (xstrdup("0"));
} }
static int
format_cmp_window(const void *a0, const void *b0)
{
struct format_loop_sort_criteria *sc = &format_loop_sort_criteria;
const struct winlink *const *a = a0;
const struct winlink *const *b = b0;
const struct window *wa = (*a)->window;
const struct window *wb = (*b)->window;
int result = 0;
switch (sc->field) {
case FORMAT_LOOP_BY_INDEX:
result = wa->id - wb->id;
break;
case FORMAT_LOOP_BY_TIME:
if (timercmp(&wa->activity_time, &wb->activity_time, >)) {
result = -1;
break;
}
if (timercmp(&wa->activity_time, &wb->activity_time, <)) {
result = 1;
break;
}
/* FALLTHROUGH */
case FORMAT_LOOP_BY_NAME:
result = strcmp(wa->name, wb->name);
break;
}
if (sc->reversed)
result = -result;
return (result);
}
/* Loop over windows. */ /* Loop over windows. */
static char * static char *
format_loop_windows(struct format_expand_state *es, const char *fmt) format_loop_windows(struct format_expand_state *es, const char *fmt)
@ -4369,6 +4525,9 @@ format_loop_windows(struct format_expand_state *es, const char *fmt)
size_t valuelen; size_t valuelen;
struct winlink *wl; struct winlink *wl;
struct window *w; struct window *w;
int i, n, last = 0;
static struct winlink **l = NULL;
static int lsz = 0;
if (ft->s == NULL) { if (ft->s == NULL) {
format_log(es, "window loop but no session"); format_log(es, "window loop but no session");
@ -4380,17 +4539,32 @@ format_loop_windows(struct format_expand_state *es, const char *fmt)
active = NULL; active = NULL;
} }
n = 0;
RB_FOREACH(wl, winlinks, &ft->s->windows) {
if (lsz <= n) {
lsz += 100;
l = xreallocarray(l, lsz, sizeof *l);
}
l[n++] = wl;
}
qsort(l, n, sizeof *l, format_cmp_window);
value = xcalloc(1, 1); value = xcalloc(1, 1);
valuelen = 1; valuelen = 1;
RB_FOREACH(wl, winlinks, &ft->s->windows) { for (i = 0; i < n; i++) {
wl = l[i];
w = wl->window; w = wl->window;
format_log(es, "window loop: %u @%u", wl->idx, w->id); format_log(es, "window loop: %u @%u", wl->idx, w->id);
if (active != NULL && wl == ft->s->curw) if (active != NULL && wl == ft->s->curw)
use = active; use = active;
else else
use = all; use = all;
nft = format_create(c, item, FORMAT_WINDOW|w->id, ft->flags); if (i == n - 1)
last = FORMAT_LAST;
nft = format_create(c, item, FORMAT_WINDOW|w->id,
ft->flags|last);
format_defaults(nft, ft->c, ft->s, wl, NULL); format_defaults(nft, ft->c, ft->s, wl, NULL);
format_copy_state(&next, es, 0); format_copy_state(&next, es, 0);
next.ft = nft; next.ft = nft;
@ -4410,6 +4584,23 @@ format_loop_windows(struct format_expand_state *es, const char *fmt)
return (value); return (value);
} }
static int
format_cmp_pane(const void *a0, const void *b0)
{
struct format_loop_sort_criteria *sc = &format_loop_sort_criteria;
const struct window_pane *const *a = a0;
const struct window_pane *const *b = b0;
const struct window_pane *wpa = *a;
const struct window_pane *wpb = *b;
int result = 0;
if (sc->reversed)
result = wpb->id - wpa->id;
else
result = wpa->id - wpb->id;
return (result);
}
/* Loop over panes. */ /* Loop over panes. */
static char * static char *
format_loop_panes(struct format_expand_state *es, const char *fmt) format_loop_panes(struct format_expand_state *es, const char *fmt)
@ -4422,6 +4613,9 @@ format_loop_panes(struct format_expand_state *es, const char *fmt)
char *all, *active, *use, *expanded, *value; char *all, *active, *use, *expanded, *value;
size_t valuelen; size_t valuelen;
struct window_pane *wp; struct window_pane *wp;
int i, n, last = 0;
static struct window_pane **l = NULL;
static int lsz = 0;
if (ft->w == NULL) { if (ft->w == NULL) {
format_log(es, "pane loop but no window"); format_log(es, "pane loop but no window");
@ -4433,16 +4627,31 @@ format_loop_panes(struct format_expand_state *es, const char *fmt)
active = NULL; active = NULL;
} }
n = 0;
TAILQ_FOREACH(wp, &ft->w->panes, entry) {
if (lsz <= n) {
lsz += 100;
l = xreallocarray(l, lsz, sizeof *l);
}
l[n++] = wp;
}
qsort(l, n, sizeof *l, format_cmp_pane);
value = xcalloc(1, 1); value = xcalloc(1, 1);
valuelen = 1; valuelen = 1;
TAILQ_FOREACH(wp, &ft->w->panes, entry) { for (i = 0; i < n; i++) {
wp = l[i];
format_log(es, "pane loop: %%%u", wp->id); format_log(es, "pane loop: %%%u", wp->id);
if (active != NULL && wp == ft->w->active) if (active != NULL && wp == ft->w->active)
use = active; use = active;
else else
use = all; use = all;
nft = format_create(c, item, FORMAT_PANE|wp->id, ft->flags); if (i == n - 1)
last = FORMAT_LAST;
nft = format_create(c, item, FORMAT_PANE|wp->id,
ft->flags|last);
format_defaults(nft, ft->c, ft->s, ft->wl, wp); format_defaults(nft, ft->c, ft->s, ft->wl, wp);
format_copy_state(&next, es, 0); format_copy_state(&next, es, 0);
next.ft = nft; next.ft = nft;
@ -4462,24 +4671,86 @@ format_loop_panes(struct format_expand_state *es, const char *fmt)
return (value); return (value);
} }
static int
format_cmp_client(const void *a0, const void *b0)
{
struct format_loop_sort_criteria *sc = &format_loop_sort_criteria;
const struct client *const *a = a0;
const struct client *const *b = b0;
const struct client *ca = *a;
const struct client *cb = *b;
int result = 0;
switch (sc->field) {
case FORMAT_LOOP_BY_INDEX:
break;
case FORMAT_LOOP_BY_TIME:
if (timercmp(&ca->activity_time, &cb->activity_time, >)) {
result = -1;
break;
}
if (timercmp(&ca->activity_time, &cb->activity_time, <)) {
result = 1;
break;
}
/* FALLTHROUGH */
case FORMAT_LOOP_BY_NAME:
result = strcmp(ca->name, cb->name);
break;
}
if (sc->reversed)
result = -result;
return (result);
}
/* Loop over clients. */ /* Loop over clients. */
static char * static char *
format_loop_clients(struct format_expand_state *es, const char *fmt) format_loop_clients(struct format_expand_state *es, const char *fmt)
{ {
struct format_tree *ft = es->ft; struct format_loop_sort_criteria *sc = &format_loop_sort_criteria;
struct client *c; struct format_tree *ft = es->ft;
struct cmdq_item *item = ft->item; struct client *c;
struct format_tree *nft; struct cmdq_item *item = ft->item;
struct format_expand_state next; struct format_tree *nft;
char *expanded, *value; struct format_expand_state next;
size_t valuelen; char *expanded, *value;
size_t valuelen;
int i, n, last = 0;
static struct client **l = NULL;
static int lsz = 0;
value = xcalloc(1, 1); value = xcalloc(1, 1);
valuelen = 1; valuelen = 1;
n = 0;
TAILQ_FOREACH(c, &clients, entry) { TAILQ_FOREACH(c, &clients, entry) {
if (lsz <= n) {
lsz += 100;
l = xreallocarray(l, lsz, sizeof *l);
}
l[n++] = c;
}
if (sc->field != FORMAT_LOOP_BY_INDEX)
qsort(l, n, sizeof *l, format_cmp_client);
else {
/* Use order in the TAILQ as "index" order. */
if (sc->reversed) {
for (i = 0; i < n / 2; i++) {
c = l[i];
l[i] = l[n - 1 - i];
l[n - 1 - i] = c;
}
}
}
for (i = 0; i < n; i++) {
c = l[i];
format_log(es, "client loop: %s", c->name); format_log(es, "client loop: %s", c->name);
nft = format_create(c, item, 0, ft->flags); if (i == n - 1)
last = FORMAT_LAST;
nft = format_create(c, item, 0, ft->flags|last);
format_defaults(nft, c, ft->s, ft->wl, ft->wp); format_defaults(nft, c, ft->s, ft->wl, ft->wp);
format_copy_state(&next, es, 0); format_copy_state(&next, es, 0);
next.ft = nft; next.ft = nft;
@ -4643,6 +4914,7 @@ static int
format_replace(struct format_expand_state *es, const char *key, size_t keylen, format_replace(struct format_expand_state *es, const char *key, size_t keylen,
char **buf, size_t *len, size_t *off) char **buf, size_t *len, size_t *off)
{ {
struct format_loop_sort_criteria *sc = &format_loop_sort_criteria;
struct format_tree *ft = es->ft; struct format_tree *ft = es->ft;
struct window_pane *wp = ft->wp; struct window_pane *wp = ft->wp;
const char *errstr, *copy, *cp, *cp2; const char *errstr, *copy, *cp, *cp2;
@ -4658,7 +4930,6 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
struct format_modifier *bool_op_n = NULL; struct format_modifier *bool_op_n = NULL;
u_int i, count, nsub = 0, nrep; u_int i, count, nsub = 0, nrep;
struct format_expand_state next; struct format_expand_state next;
struct format_loop_sort_criteria *sc = &format_loop_sort_criteria;
/* Make a copy of the key. */ /* Make a copy of the key. */
copy = copy0 = xstrndup(key, keylen); copy = copy0 = xstrndup(key, keylen);
@ -4769,15 +5040,19 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
break; break;
case 'S': case 'S':
modifiers |= FORMAT_SESSIONS; modifiers |= FORMAT_SESSIONS;
if (fm->argc < 1) if (fm->argc < 1) {
sc->field = FORMAT_LOOP_BY_INDEX;
sc->reversed = 0;
break; break;
}
if (strchr(fm->argv[0], 'i') != NULL) if (strchr(fm->argv[0], 'i') != NULL)
sc->field = FORMAT_LOOP_BY_INDEX; sc->field = FORMAT_LOOP_BY_INDEX;
else if (strchr(fm->argv[0], 'n') != NULL) else if (strchr(fm->argv[0], 'n') != NULL)
sc->field = FORMAT_LOOP_BY_NAME; sc->field = FORMAT_LOOP_BY_NAME;
else if (strchr(fm->argv[0], 't') != NULL) else if (strchr(fm->argv[0], 't') != NULL)
sc->field = FORMAT_LOOP_BY_TIME; sc->field = FORMAT_LOOP_BY_TIME;
else sc->field = FORMAT_LOOP_BY_INDEX; else
sc->field = FORMAT_LOOP_BY_INDEX;
if (strchr(fm->argv[0], 'r') != NULL) if (strchr(fm->argv[0], 'r') != NULL)
sc->reversed = 1; sc->reversed = 1;
else else
@ -4785,12 +5060,54 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
break; break;
case 'W': case 'W':
modifiers |= FORMAT_WINDOWS; modifiers |= FORMAT_WINDOWS;
if (fm->argc < 1) {
sc->field = FORMAT_LOOP_BY_INDEX;
sc->reversed = 0;
break;
}
if (strchr(fm->argv[0], 'i') != NULL)
sc->field = FORMAT_LOOP_BY_INDEX;
else if (strchr(fm->argv[0], 'n') != NULL)
sc->field = FORMAT_LOOP_BY_NAME;
else if (strchr(fm->argv[0], 't') != NULL)
sc->field = FORMAT_LOOP_BY_TIME;
else
sc->field = FORMAT_LOOP_BY_INDEX;
if (strchr(fm->argv[0], 'r') != NULL)
sc->reversed = 1;
else
sc->reversed = 0;
break; break;
case 'P': case 'P':
modifiers |= FORMAT_PANES; modifiers |= FORMAT_PANES;
if (fm->argc < 1) {
sc->reversed = 0;
break;
}
if (strchr(fm->argv[0], 'r') != NULL)
sc->reversed = 1;
else
sc->reversed = 0;
break; break;
case 'L': case 'L':
modifiers |= FORMAT_CLIENTS; modifiers |= FORMAT_CLIENTS;
if (fm->argc < 1) {
sc->field = FORMAT_LOOP_BY_INDEX;
sc->reversed = 0;
break;
}
if (strchr(fm->argv[0], 'i') != NULL)
sc->field = FORMAT_LOOP_BY_INDEX;
else if (strchr(fm->argv[0], 'n') != NULL)
sc->field = FORMAT_LOOP_BY_NAME;
else if (strchr(fm->argv[0], 't') != NULL)
sc->field = FORMAT_LOOP_BY_TIME;
else
sc->field = FORMAT_LOOP_BY_INDEX;
if (strchr(fm->argv[0], 'r') != NULL)
sc->reversed = 1;
else
sc->reversed = 0;
break; break;
case 'R': case 'R':
modifiers |= FORMAT_REPEAT; modifiers |= FORMAT_REPEAT;

11
menu.c
View File

@ -421,10 +421,6 @@ chosen:
return (1); return (1);
} }
if (md->item != NULL)
event = cmdq_get_event(md->item);
else
event = NULL;
state = cmdq_new_state(&md->fs, event, 0); state = cmdq_new_state(&md->fs, event, 0);
status = cmd_parse_and_append(item->command, NULL, c, state, &error); status = cmd_parse_and_append(item->command, NULL, c, state, &error);
@ -544,12 +540,17 @@ menu_display(struct menu *menu, int flags, int starting_choice,
void *data) void *data)
{ {
struct menu_data *md; struct menu_data *md;
struct window *w = c->session->curw->window;
md = menu_prepare(menu, flags, starting_choice, item, px, py, c, lines, md = menu_prepare(menu, flags, starting_choice, item, px, py, c, lines,
style, selected_style, border_style, fs, cb, data); style, selected_style, border_style, fs, cb, data);
if (md == NULL) if (md == NULL)
return (-1); return (-1);
w->md = md;
c->flags |= CLIENT_REDRAWWINDOW;
/*
server_client_set_overlay(c, 0, NULL, menu_mode_cb, menu_draw_cb, server_client_set_overlay(c, 0, NULL, menu_mode_cb, menu_draw_cb,
menu_key_cb, menu_free_cb, NULL, md); menu_key_cb, menu_free_cb, NULL, md);
return (0); */
return (1);
} }

View File

@ -138,7 +138,7 @@ static const char *options_table_allow_passthrough_list[] = {
"#{T:window-status-format}" \ "#{T:window-status-format}" \
"#[pop-default]" \ "#[pop-default]" \
"#[norange default]" \ "#[norange default]" \
"#{?window_end_flag,,#{window-status-separator}}" \ "#{?loop_last_flag,,#{window-status-separator}}" \
"," \ "," \
"#[range=window|#{window_index} list=focus " \ "#[range=window|#{window_index} list=focus " \
"#{?#{!=:#{E:window-status-current-style},default}," \ "#{?#{!=:#{E:window-status-current-style},default}," \
@ -165,7 +165,7 @@ static const char *options_table_allow_passthrough_list[] = {
"#{T:window-status-current-format}" \ "#{T:window-status-current-format}" \
"#[pop-default]" \ "#[pop-default]" \
"#[norange list=on default]" \ "#[norange list=on default]" \
"#{?window_end_flag,,#{window-status-separator}}" \ "#{?loop_last_flag,,#{window-status-separator}}" \
"}" \ "}" \
"#[nolist align=right range=right #{E:status-right-style}]" \ "#[nolist align=right range=right #{E:status-right-style}]" \
"#[push-default]" \ "#[push-default]" \

17
popup.c
View File

@ -218,6 +218,7 @@ popup_draw_cb(struct client *c, void *data, struct screen_redraw_ctx *rctx)
u_int i, px = pd->px, py = pd->py; u_int i, px = pd->px, py = pd->py;
struct colour_palette *palette = &pd->palette; struct colour_palette *palette = &pd->palette;
struct grid_cell defaults; struct grid_cell defaults;
struct window *w = c->session->curw->window;
screen_init(&s, pd->sx, pd->sy, 0); screen_init(&s, pd->sx, pd->sy, 0);
screen_write_start(&ctx, &s); screen_write_start(&ctx, &s);
@ -244,6 +245,9 @@ popup_draw_cb(struct client *c, void *data, struct screen_redraw_ctx *rctx)
if (pd->md != NULL) { if (pd->md != NULL) {
c->overlay_check = menu_check_cb; c->overlay_check = menu_check_cb;
c->overlay_data = pd->md; c->overlay_data = pd->md;
} else if (w->md != NULL) {
c->overlay_check = menu_check_cb;
c->overlay_data = w->md;
} else { } else {
c->overlay_check = NULL; c->overlay_check = NULL;
c->overlay_data = NULL; c->overlay_data = NULL;
@ -257,6 +261,10 @@ popup_draw_cb(struct client *c, void *data, struct screen_redraw_ctx *rctx)
c->overlay_check = NULL; c->overlay_check = NULL;
c->overlay_data = NULL; c->overlay_data = NULL;
menu_draw_cb(c, pd->md, rctx); menu_draw_cb(c, pd->md, rctx);
} else if (w->md != NULL) {
c->overlay_check = NULL;
c->overlay_data = NULL;
menu_draw_cb(c, w->md, rctx);
} }
c->overlay_check = popup_check_cb; c->overlay_check = popup_check_cb;
c->overlay_data = pd; c->overlay_data = pd;
@ -511,10 +519,13 @@ popup_key_cb(struct client *c, void *data, struct key_event *event)
m->x > pd->px + pd->sx - 1 || m->x > pd->px + pd->sx - 1 ||
m->y < pd->py || m->y < pd->py ||
m->y > pd->py + pd->sy - 1) { m->y > pd->py + pd->sy - 1) {
if (MOUSE_BUTTONS(m->b) == MOUSE_BUTTON_3) if ((c->flags & CLIENT_OVERLAYFOCUSED) &&
(MOUSE_BUTTONS(m->b) & MOUSE_BUTTON_3))
goto menu; goto menu;
c->flags &= ~CLIENT_OVERLAYFOCUSED;
return (0); return (0);
} }
c->flags |= CLIENT_OVERLAYFOCUSED;
if (pd->border_lines != BOX_LINES_NONE) { if (pd->border_lines != BOX_LINES_NONE) {
if (m->x == pd->px) if (m->x == pd->px)
border = LEFT; border = LEFT;
@ -561,7 +572,8 @@ popup_key_cb(struct client *c, void *data, struct key_event *event)
bufferevent_write(job_get_event(pd->job), buf, len); bufferevent_write(job_get_event(pd->job), buf, len);
return (0); return (0);
} }
input_key(&pd->s, job_get_event(pd->job), event->key); if (c->flags & CLIENT_OVERLAYFOCUSED)
input_key(&pd->s, job_get_event(pd->job), event->key);
} }
return (0); return (0);
@ -725,6 +737,7 @@ popup_display(int flags, enum box_lines lines, struct cmdq_item *item, u_int px,
server_client_set_overlay(c, 0, popup_check_cb, popup_mode_cb, server_client_set_overlay(c, 0, popup_check_cb, popup_mode_cb,
popup_draw_cb, popup_key_cb, popup_free_cb, popup_resize_cb, pd); popup_draw_cb, popup_key_cb, popup_free_cb, popup_resize_cb, pd);
c->flags |= CLIENT_OVERLAYFOCUSED;
return (0); return (0);
} }

View File

@ -857,6 +857,9 @@ screen_redraw_draw_panes(struct screen_redraw_ctx *ctx)
if (window_pane_visible(wp)) if (window_pane_visible(wp))
screen_redraw_draw_pane(ctx, wp); screen_redraw_draw_pane(ctx, wp);
} }
if (w->md != NULL)
w->menu_draw_cb(c, w->md, ctx);
} }
/* Draw the status line. */ /* Draw the status line. */
@ -1018,6 +1021,7 @@ screen_redraw_draw_scrollbar(struct screen_redraw_ctx *ctx,
struct tty *tty = &c->tty; struct tty *tty = &c->tty;
struct grid_cell gc, slgc, *gcp; struct grid_cell gc, slgc, *gcp;
struct style *sb_style = &wp->scrollbar_style; struct style *sb_style = &wp->scrollbar_style;
struct overlay_ranges r;
u_int i, j, imax, jmax; u_int i, j, imax, jmax;
u_int sb_w = sb_style->width, sb_pad = sb_style->pad; u_int sb_w = sb_style->width, sb_pad = sb_style->pad;
int px, py, ox = ctx->ox, oy = ctx->oy; int px, py, ox = ctx->ox, oy = ctx->oy;
@ -1046,6 +1050,16 @@ screen_redraw_draw_scrollbar(struct screen_redraw_ctx *ctx,
py < yoff - oy - 1 || py < yoff - oy - 1 ||
py >= sy || py < 0) py >= sy || py < 0)
continue; continue;
if (c->overlay_check != NULL) {
c->overlay_check(c, c->overlay_data, px, py, 1, &r);
if (r.nx[0] + r.nx[1] == 0)
continue;
}
if (wp->window->md != NULL) {
menu_check_cb(c, wp->window->md, px, py, 1, &r);
if (r.nx[0] + r.nx[1] == 0)
continue;
}
tty_cursor(tty, px, py); tty_cursor(tty, px, py);
if ((sb_pos == PANE_SCROLLBARS_LEFT && if ((sb_pos == PANE_SCROLLBARS_LEFT &&
i >= sb_w && i < sb_w + sb_pad) || i >= sb_w && i < sb_w + sb_pad) ||

View File

@ -2598,6 +2598,7 @@ paste_key:
out: out:
if (s != NULL && key != KEYC_FOCUS_OUT) if (s != NULL && key != KEYC_FOCUS_OUT)
server_client_update_latest(c); server_client_update_latest(c);
free(event->buf); free(event->buf);
free(event); free(event);
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);
@ -2608,7 +2609,10 @@ int
server_client_handle_key(struct client *c, struct key_event *event) server_client_handle_key(struct client *c, struct key_event *event)
{ {
struct session *s = c->session; struct session *s = c->session;
struct window *w = s->curw->window;
struct cmdq_item *item; struct cmdq_item *item;
struct window_pane *wp;
int done;
/* Check the client is good to accept input. */ /* Check the client is good to accept input. */
if (s == NULL || (c->flags & CLIENT_UNATTACHEDFLAGS)) if (s == NULL || (c->flags & CLIENT_UNATTACHEDFLAGS))
@ -2625,17 +2629,27 @@ server_client_handle_key(struct client *c, struct key_event *event)
return (0); return (0);
status_message_clear(c); status_message_clear(c);
} }
if (c->overlay_key != NULL) { if (w->md != NULL) {
switch (c->overlay_key(c, c->overlay_data, event)) { done = w->menu_key_cb(c, w->md, event);
case 0: if (done) {
return (0); w->menu_free_cb(c, w->md);
case 1: w->md = NULL;
server_client_clear_overlay(c); c->flags |= CLIENT_REDRAWWINDOW;
return (0);
} }
} }
server_client_clear_overlay(c); else if (c->overlay_key != NULL) {
if (c->prompt_string != NULL) { done = c->overlay_key(c, c->overlay_data, event);
if (done)
server_client_clear_overlay(c);
else {
TAILQ_FOREACH(wp, &w->panes, entry) {
if (~c->flags & CLIENT_OVERLAYFOCUSED)
goto focused;
}
}
return (0);
}
focused: if (c->prompt_string != NULL) {
if (status_prompt_key(c, event->key) == 0) if (status_prompt_key(c, event->key) == 0)
return (0); return (0);
} }
@ -2885,6 +2899,25 @@ out:
bufferevent_enable(wp->event, EV_READ); bufferevent_enable(wp->event, EV_READ);
} }
static int
server_client_check_overlay(struct client *c, u_int px, u_int py)
{
struct overlay_ranges r;
/*
* A unit width range will always return nx[2] == 0 from a check, even
* with multiple overlays, so it's sufficient to check just the first
* two entries.
*/
if (c->overlay_check == NULL)
return (0);
c->overlay_check(c, c->overlay_data, px, py, 1, &r);
if (r.nx[0] + r.nx[1] == 0)
return (0);
return (1);
}
/* /*
* Update cursor position and mode settings. The scroll region and attributes * Update cursor position and mode settings. The scroll region and attributes
* are cleared when idle (waiting for an event) as this is the most likely time * are cleared when idle (waiting for an event) as this is the most likely time
@ -2894,6 +2927,7 @@ out:
* tty_region/tty_reset/tty_update_mode already take care of not resetting * tty_region/tty_reset/tty_update_mode already take care of not resetting
* things that are already in their default state. * things that are already in their default state.
*/ */
static void static void
server_client_reset_state(struct client *c) server_client_reset_state(struct client *c)
{ {
@ -2913,9 +2947,11 @@ server_client_reset_state(struct client *c)
tty->flags &= ~TTY_BLOCK; tty->flags &= ~TTY_BLOCK;
/* Get mode from overlay if any, else from screen. */ /* Get mode from overlay if any, else from screen. */
if (c->overlay_draw != NULL) { if (c->overlay_draw != NULL && c->flags & CLIENT_OVERLAYFOCUSED) {
if (c->overlay_mode != NULL) if (c->overlay_mode != NULL)
s = c->overlay_mode(c, c->overlay_data, &cx, &cy); s = c->overlay_mode(c, c->overlay_data, &cx, &cy);
} else if (w->md != NULL) {
s = w->menu_mode_cb(c, w->md, &cx, &cy);
} else if (c->prompt_string == NULL) } else if (c->prompt_string == NULL)
s = wp->screen; s = wp->screen;
else else
@ -2944,18 +2980,22 @@ server_client_reset_state(struct client *c)
cy = tty->sy - n; cy = tty->sy - n;
} }
cx = c->prompt_cursor; cx = c->prompt_cursor;
} else if (c->overlay_draw == NULL) { } else if (c->overlay_draw == NULL || ~c->flags & CLIENT_OVERLAYFOCUSED) {
cursor = 0; cursor = 0;
tty_window_offset(tty, &ox, &oy, &sx, &sy); tty_window_offset(tty, &ox, &oy, &sx, &sy);
if (wp->xoff + s->cx >= ox && wp->xoff + s->cx <= ox + sx && if (wp->xoff + s->cx >= ox && wp->xoff + s->cx <= ox + sx &&
wp->yoff + s->cy >= oy && wp->yoff + s->cy <= oy + sy) { wp->yoff + s->cy >= oy && wp->yoff + s->cy <= oy + sy) {
cursor = 1;
cx = wp->xoff + s->cx - ox; cx = wp->xoff + s->cx - ox;
cy = wp->yoff + s->cy - oy; cy = wp->yoff + s->cy - oy;
if (status_at_line(c) == 0) if (status_at_line(c) == 0)
cy += status_line_size(c); cy += status_line_size(c);
if (c->overlay_draw != NULL &&
!server_client_check_overlay(c, cx, cy))
cursor = 0;
else
cursor = 1;
} }
if (!cursor) if (!cursor)
mode &= ~MODE_CURSOR; mode &= ~MODE_CURSOR;

27
tmux.1
View File

@ -5911,14 +5911,21 @@ or
.Ql L:\& .Ql L:\&
will loop over each session, window, pane or client and insert the format once will loop over each session, window, pane or client and insert the format once
for each. for each.
.Ql S:\& , .Ql L:\& ,
.Ql S:\&
and
.Ql W:\&
can take an optional sort argument can take an optional sort argument
.Ql /i\& , .Ql /i\& ,
.Ql /n\& , .Ql /n\& ,
.Ql /t\& .Ql /t\&
to sort by index, name, or time; or to sort by index, name, or last activity time; additionally
.Ql /r\& .Ql /r\&
to sort in reverse order. to sort in reverse order.
.Ql /r\&
can also be used with
.Ql P:\&
to reverse the sort order by pane index.
For example, For example,
.Ql S/nr:\& .Ql S/nr:\&
to sort sessions by name in reverse order. to sort sessions by name in reverse order.
@ -6070,8 +6077,10 @@ The following variables are available, where appropriate:
.It Li "insert_flag" Ta "" Ta "Pane insert flag" .It Li "insert_flag" Ta "" Ta "Pane insert flag"
.It Li "keypad_cursor_flag" Ta "" Ta "Pane keypad cursor flag" .It Li "keypad_cursor_flag" Ta "" Ta "Pane keypad cursor flag"
.It Li "keypad_flag" Ta "" Ta "Pane keypad flag" .It Li "keypad_flag" Ta "" Ta "Pane keypad flag"
.It Li "last_session_index" Ta "" Ta "Index of last session"
.It Li "last_window_index" Ta "" Ta "Index of last window in session" .It Li "last_window_index" Ta "" Ta "Index of last window in session"
.It Li "line" Ta "" Ta "Line number in the list" .It Li "line" Ta "" Ta "Line number in the list"
.It Li "loop_last_flag" Ta "" Ta "1 if last window, pane, session, client in the W:, P:, S:, or L: loop"
.It Li "mouse_all_flag" Ta "" Ta "Pane mouse all flag" .It Li "mouse_all_flag" Ta "" Ta "Pane mouse all flag"
.It Li "mouse_any_flag" Ta "" Ta "Pane mouse any flag" .It Li "mouse_any_flag" Ta "" Ta "Pane mouse any flag"
.It Li "mouse_button_flag" Ta "" Ta "Pane mouse button flag" .It Li "mouse_button_flag" Ta "" Ta "Pane mouse button flag"
@ -6143,10 +6152,13 @@ The following variables are available, where appropriate:
.It Li "selection_start_x" Ta "" Ta "X position of the start of the selection" .It Li "selection_start_x" Ta "" Ta "X position of the start of the selection"
.It Li "selection_start_y" Ta "" Ta "Y position of the start of the selection" .It Li "selection_start_y" Ta "" Ta "Y position of the start of the selection"
.It Li "server_sessions" Ta "" Ta "Number of sessions" .It Li "server_sessions" Ta "" Ta "Number of sessions"
.It Li "session_active" Ta "" Ta "1 if session active"
.It Li "session_activity" Ta "" Ta "Time of session last activity" .It Li "session_activity" Ta "" Ta "Time of session last activity"
.It Li "session_activity_flag" Ta "" Ta "1 if any window in session has activity"
.It Li "session_alerts" Ta "" Ta "List of window indexes with alerts" .It Li "session_alerts" Ta "" Ta "List of window indexes with alerts"
.It Li "session_attached" Ta "" Ta "Number of clients session is attached to" .It Li "session_attached" Ta "" Ta "Number of clients session is attached to"
.It Li "session_attached_list" Ta "" Ta "List of clients session is attached to" .It Li "session_attached_list" Ta "" Ta "List of clients session is attached to"
.It Li "session_bell_flag" Ta "" Ta "1 if any window in session has bell"
.It Li "session_created" Ta "" Ta "Time session created" .It Li "session_created" Ta "" Ta "Time session created"
.It Li "session_format" Ta "" Ta "1 if format is for a session" .It Li "session_format" Ta "" Ta "1 if format is for a session"
.It Li "session_group" Ta "" Ta "Name of session group" .It Li "session_group" Ta "" Ta "Name of session group"
@ -6157,11 +6169,13 @@ The following variables are available, where appropriate:
.It Li "session_group_size" Ta "" Ta "Size of session group" .It Li "session_group_size" Ta "" Ta "Size of session group"
.It Li "session_grouped" Ta "" Ta "1 if session in a group" .It Li "session_grouped" Ta "" Ta "1 if session in a group"
.It Li "session_id" Ta "" Ta "Unique session ID" .It Li "session_id" Ta "" Ta "Unique session ID"
.It Li "session_index" Ta "" Ta "Index of session"
.It Li "session_last_attached" Ta "" Ta "Time session last attached" .It Li "session_last_attached" Ta "" Ta "Time session last attached"
.It Li "session_many_attached" Ta "" Ta "1 if multiple clients attached" .It Li "session_many_attached" Ta "" Ta "1 if multiple clients attached"
.It Li "session_marked" Ta "" Ta "1 if this session contains the marked pane" .It Li "session_marked" Ta "" Ta "1 if this session contains the marked pane"
.It Li "session_name" Ta "#S" Ta "Name of session" .It Li "session_name" Ta "#S" Ta "Name of session"
.It Li "session_path" Ta "" Ta "Working directory of session" .It Li "session_path" Ta "" Ta "Working directory of session"
.It Li "session_silence_flag" Ta "" Ta "1 if any window in session has silence alert"
.It Li "session_stack" Ta "" Ta "Window indexes in most recent order" .It Li "session_stack" Ta "" Ta "Window indexes in most recent order"
.It Li "session_windows" Ta "" Ta "Number of windows in session" .It Li "session_windows" Ta "" Ta "Number of windows in session"
.It Li "socket_path" Ta "" Ta "Server socket path" .It Li "socket_path" Ta "" Ta "Server socket path"
@ -6921,7 +6935,7 @@ forwards any input read from stdin to the empty pane given by
.Ar target-pane . .Ar target-pane .
.Tg popup .Tg popup
.It Xo Ic display-popup .It Xo Ic display-popup
.Op Fl BCE .Op Fl BCDE
.Op Fl b Ar border-lines .Op Fl b Ar border-lines
.Op Fl c Ar target-client .Op Fl c Ar target-client
.Op Fl d Ar start-directory .Op Fl d Ar start-directory
@ -6944,7 +6958,6 @@ Display a popup running
when omitted) on when omitted) on
.Ar target-client . .Ar target-client .
A popup is a rectangular box drawn over the top of any panes. A popup is a rectangular box drawn over the top of any panes.
Panes are not updated while a popup is present.
.Pp .Pp
.Fl E .Fl E
closes the popup automatically when closes the popup automatically when
@ -7003,6 +7016,12 @@ is a format for the popup title (see
The The
.Fl C .Fl C
flag closes any popup on the client. flag closes any popup on the client.
.Pp
The
.Fl D
flag causes the command not to block and wait for the
.Ar shell-command
to exit.
.Tg showphist .Tg showphist
.It Xo Ic show-prompt-history .It Xo Ic show-prompt-history
.Op Fl T Ar prompt-type .Op Fl T Ar prompt-type

15
tmux.h
View File

@ -1225,6 +1225,13 @@ TAILQ_HEAD(window_panes, window_pane);
RB_HEAD(window_pane_tree, window_pane); RB_HEAD(window_pane_tree, window_pane);
/* Window structure. */ /* Window structure. */
struct key_event;
typedef struct screen *(*window_menu_mode_cb)(struct client *, void *, u_int *,
u_int *);
typedef void (*window_menu_draw_cb)(struct client *, void *,
struct screen_redraw_ctx *);
typedef int (*window_menu_key_cb)(struct client *, void *, struct key_event *);
typedef void (*window_menu_free_cb)(struct client *, void *);
struct window { struct window {
u_int id; u_int id;
void *latest; void *latest;
@ -1247,6 +1254,12 @@ struct window {
struct layout_cell *saved_layout_root; struct layout_cell *saved_layout_root;
char *old_layout; char *old_layout;
struct menu_data *md;
window_menu_mode_cb menu_mode_cb;
window_menu_draw_cb menu_draw_cb;
window_menu_key_cb menu_key_cb;
window_menu_free_cb menu_free_cb;
u_int sx; u_int sx;
u_int sy; u_int sy;
u_int manual_sx; u_int manual_sx;
@ -1983,6 +1996,7 @@ struct client {
#define CLIENT_ASSUMEPASTING 0x2000000000ULL #define CLIENT_ASSUMEPASTING 0x2000000000ULL
#define CLIENT_REDRAWSCROLLBARS 0x4000000000ULL #define CLIENT_REDRAWSCROLLBARS 0x4000000000ULL
#define CLIENT_NO_DETACH_ON_DESTROY 0x8000000000ULL #define CLIENT_NO_DETACH_ON_DESTROY 0x8000000000ULL
#define CLIENT_OVERLAYFOCUSED 0x10000000000ULL
#define CLIENT_ALLREDRAWFLAGS \ #define CLIENT_ALLREDRAWFLAGS \
(CLIENT_REDRAWWINDOW| \ (CLIENT_REDRAWWINDOW| \
CLIENT_REDRAWSTATUS| \ CLIENT_REDRAWSTATUS| \
@ -2290,6 +2304,7 @@ char *paste_make_sample(struct paste_buffer *);
#define FORMAT_FORCE 0x2 #define FORMAT_FORCE 0x2
#define FORMAT_NOJOBS 0x4 #define FORMAT_NOJOBS 0x4
#define FORMAT_VERBOSE 0x8 #define FORMAT_VERBOSE 0x8
#define FORMAT_LAST 0x10
#define FORMAT_NONE 0 #define FORMAT_NONE 0
#define FORMAT_PANE 0x80000000U #define FORMAT_PANE 0x80000000U
#define FORMAT_WINDOW 0x40000000U #define FORMAT_WINDOW 0x40000000U

View File

@ -319,6 +319,12 @@ window_create(u_int sx, u_int sy, u_int xpixel, u_int ypixel)
w->xpixel = xpixel; w->xpixel = xpixel;
w->ypixel = ypixel; w->ypixel = ypixel;
w->md = NULL;
w->menu_mode_cb = menu_mode_cb;
w->menu_draw_cb = menu_draw_cb;
w->menu_key_cb = menu_key_cb;
w->menu_free_cb = menu_free_cb;
w->options = options_create(global_w_options); w->options = options_create(global_w_options);
w->references = 0; w->references = 0;