mirror of
https://github.com/tmux/tmux.git
synced 2025-01-08 08:58:47 +00:00
Break new window and pane creation common code from various commands and
window.c into a separate file spawn.c.
This commit is contained in:
parent
7653328ce7
commit
5ece386cdf
@ -162,6 +162,7 @@ dist_tmux_SOURCES = \
|
|||||||
session.c \
|
session.c \
|
||||||
status.c \
|
status.c \
|
||||||
style.c \
|
style.c \
|
||||||
|
spawn.c \
|
||||||
tmux.c \
|
tmux.c \
|
||||||
tmux.h \
|
tmux.h \
|
||||||
tty-acs.c \
|
tty-acs.c \
|
||||||
|
@ -87,7 +87,7 @@ cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag,
|
|||||||
|
|
||||||
if (wl != NULL) {
|
if (wl != NULL) {
|
||||||
if (wp != NULL)
|
if (wp != NULL)
|
||||||
window_set_active_pane(wp->window, wp);
|
window_set_active_pane(wp->window, wp, 1);
|
||||||
session_set_current(s, wl);
|
session_set_current(s, wl);
|
||||||
if (wp != NULL)
|
if (wp != NULL)
|
||||||
cmd_find_from_winlink_pane(current, wl, wp, 0);
|
cmd_find_from_winlink_pane(current, wl, wp, 0);
|
||||||
|
@ -71,7 +71,7 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
int size, percentage, dst_idx;
|
int size, percentage, dst_idx;
|
||||||
enum layout_type type;
|
enum layout_type type;
|
||||||
struct layout_cell *lc;
|
struct layout_cell *lc;
|
||||||
int not_same_window;
|
int not_same_window, flags;
|
||||||
|
|
||||||
if (self->entry == &cmd_join_pane_entry)
|
if (self->entry == &cmd_join_pane_entry)
|
||||||
not_same_window = 1;
|
not_same_window = 1;
|
||||||
@ -123,7 +123,11 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
else
|
else
|
||||||
size = (dst_wp->sx * percentage) / 100;
|
size = (dst_wp->sx * percentage) / 100;
|
||||||
}
|
}
|
||||||
lc = layout_split_pane(dst_wp, type, size, args_has(args, 'b'), 0);
|
if (args_has(args, 'b'))
|
||||||
|
flags = SPAWN_BEFORE;
|
||||||
|
else
|
||||||
|
flags = 0;
|
||||||
|
lc = layout_split_pane(dst_wp, type, size, flags);
|
||||||
if (lc == NULL) {
|
if (lc == NULL) {
|
||||||
cmdq_error(item, "create pane failed: pane too small");
|
cmdq_error(item, "create pane failed: pane too small");
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
@ -144,7 +148,7 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
server_redraw_window(dst_w);
|
server_redraw_window(dst_w);
|
||||||
|
|
||||||
if (!args_has(args, 'd')) {
|
if (!args_has(args, 'd')) {
|
||||||
window_set_active_pane(dst_w, src_wp);
|
window_set_active_pane(dst_w, src_wp, 1);
|
||||||
session_select(dst_s, dst_idx);
|
session_select(dst_s, dst_idx);
|
||||||
cmd_find_from_session(current, dst_s, 0);
|
cmd_find_from_session(current, dst_s, 0);
|
||||||
server_redraw_session(dst_s);
|
server_redraw_session(dst_s);
|
||||||
|
@ -61,12 +61,12 @@ cmd_kill_session_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
RB_FOREACH_SAFE(sloop, sessions, &sessions, stmp) {
|
RB_FOREACH_SAFE(sloop, sessions, &sessions, stmp) {
|
||||||
if (sloop != s) {
|
if (sloop != s) {
|
||||||
server_destroy_session(sloop);
|
server_destroy_session(sloop);
|
||||||
session_destroy(sloop, __func__);
|
session_destroy(sloop, 1, __func__);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
server_destroy_session(s);
|
server_destroy_session(s);
|
||||||
session_destroy(s, __func__);
|
session_destroy(s, 1, __func__);
|
||||||
}
|
}
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
@ -69,20 +69,17 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
struct client *c = item->client;
|
struct client *c = item->client;
|
||||||
struct session *s, *as, *groupwith;
|
struct session *s, *as, *groupwith;
|
||||||
struct window *w;
|
|
||||||
struct environ *env;
|
struct environ *env;
|
||||||
struct options *oo;
|
struct options *oo;
|
||||||
struct termios tio, *tiop;
|
struct termios tio, *tiop;
|
||||||
struct session_group *sg;
|
struct session_group *sg;
|
||||||
const char *errstr, *template, *group, *prefix;
|
const char *errstr, *template, *group, *prefix, *tmp;
|
||||||
const char *path, *cmd, *tmp, *value;
|
char *cause, *cwd = NULL, *cp, *newname = NULL;
|
||||||
char **argv, *cause, *cp, *newname, *cwd = NULL;
|
int detached, already_attached, is_control = 0;
|
||||||
int detached, already_attached, idx, argc;
|
u_int sx, sy, dsx, dsy;
|
||||||
int is_control = 0;
|
struct spawn_context sc;
|
||||||
u_int sx, sy, dsx = 80, dsy = 24;
|
|
||||||
struct environ_entry *envent;
|
|
||||||
struct cmd_find_state fs;
|
|
||||||
enum cmd_retval retval;
|
enum cmd_retval retval;
|
||||||
|
struct cmd_find_state fs;
|
||||||
|
|
||||||
if (self->entry == &cmd_has_session_entry) {
|
if (self->entry == &cmd_has_session_entry) {
|
||||||
/*
|
/*
|
||||||
@ -97,13 +94,12 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
newname = NULL;
|
|
||||||
if (args_has(args, 's')) {
|
if (args_has(args, 's')) {
|
||||||
newname = format_single(item, args_get(args, 's'), c, NULL,
|
newname = format_single(item, args_get(args, 's'), c, NULL,
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
if (!session_check_name(newname)) {
|
if (!session_check_name(newname)) {
|
||||||
cmdq_error(item, "bad session name: %s", newname);
|
cmdq_error(item, "bad session name: %s", newname);
|
||||||
goto error;
|
goto fail;
|
||||||
}
|
}
|
||||||
if ((as = session_find(newname)) != NULL) {
|
if ((as = session_find(newname)) != NULL) {
|
||||||
if (args_has(args, 'A')) {
|
if (args_has(args, 'A')) {
|
||||||
@ -114,7 +110,7 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
return (retval);
|
return (retval);
|
||||||
}
|
}
|
||||||
cmdq_error(item, "duplicate session: %s", newname);
|
cmdq_error(item, "duplicate session: %s", newname);
|
||||||
goto error;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,7 +121,7 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (groupwith == NULL) {
|
if (groupwith == NULL) {
|
||||||
if (!session_check_name(group)) {
|
if (!session_check_name(group)) {
|
||||||
cmdq_error(item, "bad group name: %s", group);
|
cmdq_error(item, "bad group name: %s", group);
|
||||||
goto error;
|
goto fail;
|
||||||
}
|
}
|
||||||
sg = session_group_find(group);
|
sg = session_group_find(group);
|
||||||
} else
|
} else
|
||||||
@ -173,7 +169,7 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (server_client_check_nested(item->client)) {
|
if (server_client_check_nested(item->client)) {
|
||||||
cmdq_error(item, "sessions should be nested with care, "
|
cmdq_error(item, "sessions should be nested with care, "
|
||||||
"unset $TMUX to force");
|
"unset $TMUX to force");
|
||||||
return (CMD_RETURN_ERROR);
|
goto fail;
|
||||||
}
|
}
|
||||||
if (tcgetattr(c->tty.fd, &tio) != 0)
|
if (tcgetattr(c->tty.fd, &tio) != 0)
|
||||||
fatal("tcgetattr failed");
|
fatal("tcgetattr failed");
|
||||||
@ -186,7 +182,7 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (server_client_open(c, &cause) != 0) {
|
if (server_client_open(c, &cause) != 0) {
|
||||||
cmdq_error(item, "open terminal failed: %s", cause);
|
cmdq_error(item, "open terminal failed: %s", cause);
|
||||||
free(cause);
|
free(cause);
|
||||||
goto error;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,7 +196,7 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
dsx = strtonum(tmp, 1, USHRT_MAX, &errstr);
|
dsx = strtonum(tmp, 1, USHRT_MAX, &errstr);
|
||||||
if (errstr != NULL) {
|
if (errstr != NULL) {
|
||||||
cmdq_error(item, "width %s", errstr);
|
cmdq_error(item, "width %s", errstr);
|
||||||
goto error;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -213,7 +209,7 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
dsy = strtonum(tmp, 1, USHRT_MAX, &errstr);
|
dsy = strtonum(tmp, 1, USHRT_MAX, &errstr);
|
||||||
if (errstr != NULL) {
|
if (errstr != NULL) {
|
||||||
cmdq_error(item, "height %s", errstr);
|
cmdq_error(item, "height %s", errstr);
|
||||||
goto error;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -225,8 +221,8 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (sy > 0 && options_get_number(global_s_options, "status"))
|
if (sy > 0 && options_get_number(global_s_options, "status"))
|
||||||
sy--;
|
sy--;
|
||||||
} else {
|
} else {
|
||||||
value = options_get_string(global_s_options, "default-size");
|
tmp = options_get_string(global_s_options, "default-size");
|
||||||
if (sscanf(value, "%ux%u", &sx, &sy) != 2) {
|
if (sscanf(tmp, "%ux%u", &sx, &sy) != 2) {
|
||||||
sx = 80;
|
sx = 80;
|
||||||
sy = 24;
|
sy = 24;
|
||||||
}
|
}
|
||||||
@ -240,59 +236,34 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (sy == 0)
|
if (sy == 0)
|
||||||
sy = 1;
|
sy = 1;
|
||||||
|
|
||||||
/* Figure out the command for the new window. */
|
/* Create the new session. */
|
||||||
argc = -1;
|
|
||||||
argv = NULL;
|
|
||||||
if (!args_has(args, 't') && args->argc != 0) {
|
|
||||||
argc = args->argc;
|
|
||||||
argv = args->argv;
|
|
||||||
} else if (sg == NULL && groupwith == NULL) {
|
|
||||||
cmd = options_get_string(global_s_options, "default-command");
|
|
||||||
if (cmd != NULL && *cmd != '\0') {
|
|
||||||
argc = 1;
|
|
||||||
argv = (char **)&cmd;
|
|
||||||
} else {
|
|
||||||
argc = 0;
|
|
||||||
argv = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
path = NULL;
|
|
||||||
if (c != NULL && c->session == NULL)
|
|
||||||
envent = environ_find(c->environ, "PATH");
|
|
||||||
else
|
|
||||||
envent = environ_find(global_environ, "PATH");
|
|
||||||
if (envent != NULL)
|
|
||||||
path = envent->value;
|
|
||||||
|
|
||||||
/* Construct the environment. */
|
|
||||||
env = environ_create();
|
|
||||||
if (c != NULL && !args_has(args, 'E'))
|
|
||||||
environ_update(global_s_options, c->environ, env);
|
|
||||||
|
|
||||||
/* Set up the options. */
|
|
||||||
oo = options_create(global_s_options);
|
oo = options_create(global_s_options);
|
||||||
if (args_has(args, 'x') || args_has(args, 'y'))
|
if (args_has(args, 'x') || args_has(args, 'y'))
|
||||||
options_set_string(oo, "default-size", 0, "%ux%u", dsx, dsy);
|
options_set_string(oo, "default-size", 0, "%ux%u", dsx, dsy);
|
||||||
|
env = environ_create();
|
||||||
|
if (c != NULL && !args_has(args, 'E'))
|
||||||
|
environ_update(global_s_options, c->environ, env);
|
||||||
|
s = session_create(prefix, newname, cwd, env, oo, tiop);
|
||||||
|
|
||||||
/* Create the new session. */
|
/* Spawn the initial window. */
|
||||||
idx = -1 - options_get_number(global_s_options, "base-index");
|
memset(&sc, 0, sizeof sc);
|
||||||
s = session_create(prefix, newname, argc, argv, path, cwd, env, oo,
|
sc.item = item;
|
||||||
tiop, idx, &cause);
|
sc.s = s;
|
||||||
environ_free(env);
|
|
||||||
if (s == NULL) {
|
sc.name = args_get(args, 'n');
|
||||||
cmdq_error(item, "create session failed: %s", cause);
|
sc.argc = args->argc;
|
||||||
|
sc.argv = args->argv;
|
||||||
|
|
||||||
|
sc.idx = -1;
|
||||||
|
sc.cwd = args_get(args, 'c');
|
||||||
|
|
||||||
|
sc.flags = 0;
|
||||||
|
|
||||||
|
if (spawn_window(&sc, &cause) == NULL) {
|
||||||
|
session_destroy(s, 0, __func__);
|
||||||
|
cmdq_error(item, "create window failed: %s", cause);
|
||||||
free(cause);
|
free(cause);
|
||||||
goto error;
|
goto fail;
|
||||||
}
|
|
||||||
|
|
||||||
/* Set the initial window name if one given. */
|
|
||||||
if (argc >= 0 && (tmp = args_get(args, 'n')) != NULL) {
|
|
||||||
cp = format_single(item, tmp, c, s, NULL, NULL);
|
|
||||||
w = s->curw->window;
|
|
||||||
window_set_name(w, cp);
|
|
||||||
options_set_number(w->options, "automatic-rename", 0);
|
|
||||||
free(cp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -364,7 +335,7 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
free(newname);
|
free(newname);
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
|
|
||||||
error:
|
fail:
|
||||||
free(cwd);
|
free(cwd);
|
||||||
free(newname);
|
free(newname);
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
|
101
cmd-new-window.c
101
cmd-new-window.c
@ -53,87 +53,45 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
{
|
{
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
struct cmd_find_state *current = &item->shared->current;
|
struct cmd_find_state *current = &item->shared->current;
|
||||||
|
struct spawn_context sc;
|
||||||
|
struct client *c = cmd_find_client(item, NULL, 1);
|
||||||
struct session *s = item->target.s;
|
struct session *s = item->target.s;
|
||||||
struct winlink *wl = item->target.wl;
|
struct winlink *wl = item->target.wl;
|
||||||
struct client *c = cmd_find_client(item, NULL, 1);
|
|
||||||
int idx = item->target.idx;
|
int idx = item->target.idx;
|
||||||
const char *cmd, *path, *template, *tmp;
|
struct winlink *new_wl;
|
||||||
char **argv, *cause, *cp, *cwd, *name;
|
char *cause = NULL, *cp;
|
||||||
int argc, detached;
|
const char *template;
|
||||||
struct environ_entry *envent;
|
|
||||||
struct cmd_find_state fs;
|
struct cmd_find_state fs;
|
||||||
|
|
||||||
if (args_has(args, 'a') && wl != NULL) {
|
if (args_has(args, 'a') && (idx = winlink_shuffle_up(s, wl)) == -1) {
|
||||||
if ((idx = winlink_shuffle_up(s, wl)) == -1) {
|
cmdq_error(item, "couldn't get a window index");
|
||||||
cmdq_error(item, "no free window indexes");
|
return (CMD_RETURN_ERROR);
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
detached = args_has(args, 'd');
|
|
||||||
|
|
||||||
if (args->argc == 0) {
|
|
||||||
cmd = options_get_string(s->options, "default-command");
|
|
||||||
if (cmd != NULL && *cmd != '\0') {
|
|
||||||
argc = 1;
|
|
||||||
argv = (char **)&cmd;
|
|
||||||
} else {
|
|
||||||
argc = 0;
|
|
||||||
argv = NULL;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
argc = args->argc;
|
|
||||||
argv = args->argv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
path = NULL;
|
memset(&sc, 0, sizeof sc);
|
||||||
if (item->client != NULL && item->client->session == NULL)
|
sc.item = item;
|
||||||
envent = environ_find(item->client->environ, "PATH");
|
sc.s = s;
|
||||||
else
|
|
||||||
envent = environ_find(s->environ, "PATH");
|
|
||||||
if (envent != NULL)
|
|
||||||
path = envent->value;
|
|
||||||
|
|
||||||
if ((tmp = args_get(args, 'c')) != NULL)
|
sc.name = args_get(args, 'n');
|
||||||
cwd = format_single(item, tmp, c, s, NULL, NULL);
|
sc.argc = args->argc;
|
||||||
else
|
sc.argv = args->argv;
|
||||||
cwd = xstrdup(server_client_get_cwd(item->client, s));
|
|
||||||
|
|
||||||
if ((tmp = args_get(args, 'n')) != NULL)
|
sc.idx = idx;
|
||||||
name = format_single(item, tmp, c, s, NULL, NULL);
|
sc.cwd = args_get(args, 'c');
|
||||||
else
|
|
||||||
name = NULL;
|
|
||||||
|
|
||||||
if (idx != -1)
|
sc.flags = 0;
|
||||||
wl = winlink_find_by_index(&s->windows, idx);
|
if (args_has(args, 'd'))
|
||||||
if (wl != NULL && args_has(args, 'k')) {
|
sc.flags |= SPAWN_DETACHED;
|
||||||
/*
|
if (args_has(args, 'k'))
|
||||||
* Can't use session_detach as it will destroy session if this
|
sc.flags |= SPAWN_KILL;
|
||||||
* makes it empty.
|
|
||||||
*/
|
|
||||||
notify_session_window("window-unlinked", s, wl->window);
|
|
||||||
wl->flags &= ~WINLINK_ALERTFLAGS;
|
|
||||||
winlink_stack_remove(&s->lastw, wl);
|
|
||||||
winlink_remove(&s->windows, wl);
|
|
||||||
|
|
||||||
/* Force select/redraw if current. */
|
if ((new_wl = spawn_window(&sc, &cause)) == NULL) {
|
||||||
if (wl == s->curw) {
|
|
||||||
detached = 0;
|
|
||||||
s->curw = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (idx == -1)
|
|
||||||
idx = -1 - options_get_number(s->options, "base-index");
|
|
||||||
wl = session_new(s, name, argc, argv, path, cwd, idx,
|
|
||||||
&cause);
|
|
||||||
if (wl == NULL) {
|
|
||||||
cmdq_error(item, "create window failed: %s", cause);
|
cmdq_error(item, "create window failed: %s", cause);
|
||||||
free(cause);
|
free(cause);
|
||||||
goto error;
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
if (!detached) {
|
if (!args_has(args, 'd') || new_wl == s->curw) {
|
||||||
session_select(s, wl->idx);
|
cmd_find_from_winlink(current, new_wl, 0);
|
||||||
cmd_find_from_winlink(current, wl, 0);
|
|
||||||
server_redraw_session_group(s);
|
server_redraw_session_group(s);
|
||||||
} else
|
} else
|
||||||
server_status_session_group(s);
|
server_status_session_group(s);
|
||||||
@ -141,7 +99,7 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (args_has(args, 'P')) {
|
if (args_has(args, 'P')) {
|
||||||
if ((template = args_get(args, 'F')) == NULL)
|
if ((template = args_get(args, 'F')) == NULL)
|
||||||
template = NEW_WINDOW_TEMPLATE;
|
template = NEW_WINDOW_TEMPLATE;
|
||||||
cp = format_single(item, template, c, s, wl, NULL);
|
cp = format_single(item, template, c, s, new_wl, NULL);
|
||||||
cmdq_print(item, "%s", cp);
|
cmdq_print(item, "%s", cp);
|
||||||
free(cp);
|
free(cp);
|
||||||
}
|
}
|
||||||
@ -149,12 +107,5 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
cmd_find_from_winlink(&fs, wl, 0);
|
cmd_find_from_winlink(&fs, wl, 0);
|
||||||
hooks_insert(s->hooks, item, &fs, "after-new-window");
|
hooks_insert(s->hooks, item, &fs, "after-new-window");
|
||||||
|
|
||||||
free(name);
|
|
||||||
free(cwd);
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
|
|
||||||
error:
|
|
||||||
free(name);
|
|
||||||
free(cwd);
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
}
|
||||||
|
@ -111,7 +111,7 @@ cmdq_remove(struct cmdq_item *item)
|
|||||||
if (item->client != NULL)
|
if (item->client != NULL)
|
||||||
server_client_unref(item->client);
|
server_client_unref(item->client);
|
||||||
|
|
||||||
if (item->type == CMDQ_COMMAND)
|
if (item->cmdlist != NULL)
|
||||||
cmd_list_free(item->cmdlist);
|
cmd_list_free(item->cmdlist);
|
||||||
|
|
||||||
TAILQ_REMOVE(item->queue, item, entry);
|
TAILQ_REMOVE(item->queue, item, entry);
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ const struct cmd_entry cmd_respawn_pane_entry = {
|
|||||||
|
|
||||||
.args = { "c:kt:", 0, -1 },
|
.args = { "c:kt:", 0, -1 },
|
||||||
.usage = "[-c start-directory] [-k] " CMD_TARGET_PANE_USAGE
|
.usage = "[-c start-directory] [-k] " CMD_TARGET_PANE_USAGE
|
||||||
" [command]",
|
" [command]",
|
||||||
|
|
||||||
.target = { 't', CMD_FIND_PANE, 0 },
|
.target = { 't', CMD_FIND_PANE, 0 },
|
||||||
|
|
||||||
@ -48,53 +48,40 @@ static enum cmd_retval
|
|||||||
cmd_respawn_pane_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_respawn_pane_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
struct winlink *wl = item->target.wl;
|
struct spawn_context sc;
|
||||||
struct window *w = wl->window;
|
|
||||||
struct window_pane *wp = item->target.wp;
|
|
||||||
struct client *c = cmd_find_client(item, NULL, 1);
|
|
||||||
struct session *s = item->target.s;
|
struct session *s = item->target.s;
|
||||||
struct environ *env;
|
struct winlink *wl = item->target.wl;
|
||||||
const char *path = NULL, *cp;
|
struct window_pane *wp = item->target.wp;
|
||||||
char *cause, *cwd = NULL;
|
struct client *c = cmd_find_client(item, NULL, 1);
|
||||||
u_int idx;
|
char *cause = NULL;
|
||||||
struct environ_entry *envent;
|
|
||||||
|
|
||||||
if (!args_has(self->args, 'k') && wp->fd != -1) {
|
memset(&sc, 0, sizeof sc);
|
||||||
if (window_pane_index(wp, &idx) != 0)
|
sc.item = item;
|
||||||
fatalx("index not found");
|
sc.s = s;
|
||||||
cmdq_error(item, "pane still active: %s:%d.%u",
|
sc.wl = wl;
|
||||||
s->name, wl->idx, idx);
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
window_pane_reset_mode_all(wp);
|
sc.wp0 = wp;
|
||||||
screen_reinit(&wp->base);
|
sc.lc = NULL;
|
||||||
input_init(wp);
|
|
||||||
|
|
||||||
if (item->client != NULL && item->client->session == NULL)
|
sc.name = NULL;
|
||||||
envent = environ_find(item->client->environ, "PATH");
|
sc.argc = args->argc;
|
||||||
else
|
sc.argv = args->argv;
|
||||||
envent = environ_find(s->environ, "PATH");
|
|
||||||
if (envent != NULL)
|
|
||||||
path = envent->value;
|
|
||||||
|
|
||||||
if ((cp = args_get(args, 'c')) != NULL)
|
sc.idx = -1;
|
||||||
cwd = format_single(item, cp, c, s, NULL, NULL);
|
sc.cwd = args_get(args, 'c');
|
||||||
|
|
||||||
env = environ_for_session(s, 0);
|
sc.flags = SPAWN_RESPAWN;
|
||||||
if (window_pane_spawn(wp, args->argc, args->argv, path, NULL, cwd, env,
|
if (args_has(args, 'k'))
|
||||||
s->tio, &cause) != 0) {
|
sc.flags |= SPAWN_KILL;
|
||||||
|
|
||||||
|
if (spawn_pane(&sc, &cause) == NULL) {
|
||||||
cmdq_error(item, "respawn pane failed: %s", cause);
|
cmdq_error(item, "respawn pane failed: %s", cause);
|
||||||
free(cause);
|
free(cause);
|
||||||
environ_free(env);
|
|
||||||
free(cwd);
|
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
environ_free(env);
|
|
||||||
free(cwd);
|
|
||||||
|
|
||||||
wp->flags |= PANE_REDRAW;
|
wp->flags |= PANE_REDRAW;
|
||||||
server_status_window(w);
|
server_status_window(wp->window);
|
||||||
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
@ -48,64 +48,34 @@ static enum cmd_retval
|
|||||||
cmd_respawn_window_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_respawn_window_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
|
struct spawn_context sc;
|
||||||
struct session *s = item->target.s;
|
struct session *s = item->target.s;
|
||||||
struct winlink *wl = item->target.wl;
|
struct winlink *wl = item->target.wl;
|
||||||
struct window *w = wl->window;
|
char *cause = NULL;
|
||||||
struct window_pane *wp;
|
|
||||||
struct client *c = cmd_find_client(item, NULL, 1);
|
|
||||||
struct environ *env;
|
|
||||||
const char *path = NULL, *cp;
|
|
||||||
char *cause, *cwd = NULL;
|
|
||||||
struct environ_entry *envent;
|
|
||||||
|
|
||||||
if (!args_has(self->args, 'k')) {
|
memset(&sc, 0, sizeof sc);
|
||||||
TAILQ_FOREACH(wp, &w->panes, entry) {
|
sc.item = item;
|
||||||
if (wp->fd == -1)
|
sc.s = s;
|
||||||
continue;
|
sc.wl = wl;
|
||||||
cmdq_error(item, "window still active: %s:%d", s->name,
|
|
||||||
wl->idx);
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
wp = TAILQ_FIRST(&w->panes);
|
sc.name = NULL;
|
||||||
TAILQ_REMOVE(&w->panes, wp, entry);
|
sc.argc = args->argc;
|
||||||
layout_free(w);
|
sc.argv = args->argv;
|
||||||
window_destroy_panes(w);
|
|
||||||
TAILQ_INSERT_HEAD(&w->panes, wp, entry);
|
|
||||||
window_pane_resize(wp, w->sx, w->sy);
|
|
||||||
|
|
||||||
if (item->client != NULL && item->client->session == NULL)
|
sc.idx = -1;
|
||||||
envent = environ_find(item->client->environ, "PATH");
|
sc.cwd = args_get(args, 'c');
|
||||||
else
|
|
||||||
envent = environ_find(s->environ, "PATH");
|
|
||||||
if (envent != NULL)
|
|
||||||
path = envent->value;
|
|
||||||
|
|
||||||
if ((cp = args_get(args, 'c')) != NULL)
|
sc.flags = SPAWN_RESPAWN;
|
||||||
cwd = format_single(item, cp, c, s, NULL, NULL);
|
if (args_has(args, 'k'))
|
||||||
|
sc.flags |= SPAWN_KILL;
|
||||||
|
|
||||||
env = environ_for_session(s, 0);
|
if (spawn_window(&sc, &cause) == NULL) {
|
||||||
if (window_pane_spawn(wp, args->argc, args->argv, path, NULL, cwd, env,
|
|
||||||
s->tio, &cause) != 0) {
|
|
||||||
cmdq_error(item, "respawn window failed: %s", cause);
|
cmdq_error(item, "respawn window failed: %s", cause);
|
||||||
free(cause);
|
free(cause);
|
||||||
environ_free(env);
|
|
||||||
free(cwd);
|
|
||||||
server_destroy_pane(wp, 0);
|
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
environ_free(env);
|
|
||||||
free(cwd);
|
|
||||||
|
|
||||||
layout_init(w, wp);
|
server_redraw_window(wl->window);
|
||||||
window_pane_reset_mode_all(wp);
|
|
||||||
screen_reinit(&wp->base);
|
|
||||||
input_init(wp);
|
|
||||||
window_set_active_pane(w, wp);
|
|
||||||
|
|
||||||
recalculate_sizes();
|
|
||||||
server_redraw_window(w);
|
|
||||||
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
@ -77,7 +77,7 @@ cmd_rotate_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
|
|
||||||
if ((wp = TAILQ_PREV(w->active, window_panes, entry)) == NULL)
|
if ((wp = TAILQ_PREV(w->active, window_panes, entry)) == NULL)
|
||||||
wp = TAILQ_LAST(&w->panes, window_panes);
|
wp = TAILQ_LAST(&w->panes, window_panes);
|
||||||
window_set_active_pane(w, wp);
|
window_set_active_pane(w, wp, 1);
|
||||||
cmd_find_from_winlink_pane(current, wl, wp, 0);
|
cmd_find_from_winlink_pane(current, wl, wp, 0);
|
||||||
server_redraw_window(w);
|
server_redraw_window(w);
|
||||||
} else {
|
} else {
|
||||||
@ -105,7 +105,7 @@ cmd_rotate_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
|
|
||||||
if ((wp = TAILQ_NEXT(w->active, entry)) == NULL)
|
if ((wp = TAILQ_NEXT(w->active, entry)) == NULL)
|
||||||
wp = TAILQ_FIRST(&w->panes);
|
wp = TAILQ_FIRST(&w->panes);
|
||||||
window_set_active_pane(w, wp);
|
window_set_active_pane(w, wp, 1);
|
||||||
cmd_find_from_winlink_pane(current, wl, wp, 0);
|
cmd_find_from_winlink_pane(current, wl, wp, 0);
|
||||||
server_redraw_window(w);
|
server_redraw_window(w);
|
||||||
}
|
}
|
||||||
|
@ -112,7 +112,7 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
else {
|
else {
|
||||||
server_unzoom_window(w);
|
server_unzoom_window(w);
|
||||||
window_redraw_active_switch(w, lastwp);
|
window_redraw_active_switch(w, lastwp);
|
||||||
if (window_set_active_pane(w, lastwp)) {
|
if (window_set_active_pane(w, lastwp, 1)) {
|
||||||
cmd_find_from_winlink(current, wl, 0);
|
cmd_find_from_winlink(current, wl, 0);
|
||||||
cmd_select_pane_redraw(w);
|
cmd_select_pane_redraw(w);
|
||||||
}
|
}
|
||||||
@ -194,7 +194,7 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
server_unzoom_window(wp->window);
|
server_unzoom_window(wp->window);
|
||||||
window_redraw_active_switch(w, wp);
|
window_redraw_active_switch(w, wp);
|
||||||
if (window_set_active_pane(w, wp)) {
|
if (window_set_active_pane(w, wp, 1)) {
|
||||||
cmd_find_from_winlink_pane(current, wl, wp, 0);
|
cmd_find_from_winlink_pane(current, wl, wp, 0);
|
||||||
hooks_insert(s->hooks, item, current, "after-select-pane");
|
hooks_insert(s->hooks, item, current, "after-select-pane");
|
||||||
cmd_select_pane_redraw(w);
|
cmd_select_pane_redraw(w);
|
||||||
|
@ -52,111 +52,87 @@ const struct cmd_entry cmd_split_window_entry = {
|
|||||||
static enum cmd_retval
|
static enum cmd_retval
|
||||||
cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct cmd_find_state *current = &item->shared->current;
|
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
|
struct cmd_find_state *current = &item->shared->current;
|
||||||
|
struct spawn_context sc;
|
||||||
struct client *c = cmd_find_client(item, NULL, 1);
|
struct client *c = cmd_find_client(item, NULL, 1);
|
||||||
struct session *s = item->target.s;
|
struct session *s = item->target.s;
|
||||||
struct winlink *wl = item->target.wl;
|
struct winlink *wl = item->target.wl;
|
||||||
struct window *w = wl->window;
|
struct window_pane *wp = item->target.wp, *new_wp;
|
||||||
struct window_pane *wp = item->target.wp, *new_wp = NULL;
|
|
||||||
struct environ *env;
|
|
||||||
const char *cmd, *path, *shell, *template, *tmp;
|
|
||||||
char **argv, *cause, *new_cause, *cp, *cwd;
|
|
||||||
u_int hlimit;
|
|
||||||
int argc, size, percentage, before;
|
|
||||||
enum layout_type type;
|
enum layout_type type;
|
||||||
struct layout_cell *lc;
|
struct layout_cell *lc;
|
||||||
struct environ_entry *envent;
|
struct cmd_find_state fs;
|
||||||
struct cmd_find_state fs;
|
int size, percentage, flags;
|
||||||
|
const char *template;
|
||||||
|
char *cause, *cp;
|
||||||
|
|
||||||
server_unzoom_window(w);
|
|
||||||
|
|
||||||
if (args->argc == 0) {
|
|
||||||
cmd = options_get_string(s->options, "default-command");
|
|
||||||
if (cmd != NULL && *cmd != '\0') {
|
|
||||||
argc = 1;
|
|
||||||
argv = (char **)&cmd;
|
|
||||||
} else {
|
|
||||||
argc = 0;
|
|
||||||
argv = NULL;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
argc = args->argc;
|
|
||||||
argv = args->argv;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((tmp = args_get(args, 'c')) != NULL)
|
|
||||||
cwd = format_single(item, tmp, c, s, NULL, NULL);
|
|
||||||
else
|
|
||||||
cwd = xstrdup(server_client_get_cwd(item->client, s));
|
|
||||||
|
|
||||||
type = LAYOUT_TOPBOTTOM;
|
|
||||||
if (args_has(args, 'h'))
|
if (args_has(args, 'h'))
|
||||||
type = LAYOUT_LEFTRIGHT;
|
type = LAYOUT_LEFTRIGHT;
|
||||||
before = args_has(args, 'b');
|
else
|
||||||
|
type = LAYOUT_TOPBOTTOM;
|
||||||
size = -1;
|
|
||||||
if (args_has(args, 'l')) {
|
if (args_has(args, 'l')) {
|
||||||
size = args_strtonum(args, 'l', 0, INT_MAX, &cause);
|
size = args_strtonum(args, 'l', 0, INT_MAX, &cause);
|
||||||
if (cause != NULL) {
|
if (cause != NULL) {
|
||||||
xasprintf(&new_cause, "size %s", cause);
|
cmdq_error(item, "create pane failed: -l %s", cause);
|
||||||
free(cause);
|
free(cause);
|
||||||
cause = new_cause;
|
return (CMD_RETURN_ERROR);
|
||||||
goto error;
|
|
||||||
}
|
}
|
||||||
} else if (args_has(args, 'p')) {
|
} else if (args_has(args, 'p')) {
|
||||||
percentage = args_strtonum(args, 'p', 0, INT_MAX, &cause);
|
percentage = args_strtonum(args, 'p', 0, INT_MAX, &cause);
|
||||||
if (cause != NULL) {
|
if (cause != NULL) {
|
||||||
xasprintf(&new_cause, "percentage %s", cause);
|
cmdq_error(item, "create pane failed: -p %s", cause);
|
||||||
free(cause);
|
free(cause);
|
||||||
cause = new_cause;
|
return (CMD_RETURN_ERROR);
|
||||||
goto error;
|
|
||||||
}
|
}
|
||||||
if (type == LAYOUT_TOPBOTTOM)
|
if (type == LAYOUT_TOPBOTTOM)
|
||||||
size = (wp->sy * percentage) / 100;
|
size = (wp->sy * percentage) / 100;
|
||||||
else
|
else
|
||||||
size = (wp->sx * percentage) / 100;
|
size = (wp->sx * percentage) / 100;
|
||||||
}
|
|
||||||
hlimit = options_get_number(s->options, "history-limit");
|
|
||||||
|
|
||||||
shell = options_get_string(s->options, "default-shell");
|
|
||||||
if (*shell == '\0' || areshell(shell))
|
|
||||||
shell = _PATH_BSHELL;
|
|
||||||
|
|
||||||
lc = layout_split_pane(wp, type, size, before, args_has(args, 'f'));
|
|
||||||
if (lc == NULL) {
|
|
||||||
cause = xstrdup("pane too small");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
new_wp = window_add_pane(w, wp, before, args_has(args, 'f'), hlimit);
|
|
||||||
layout_make_leaf(lc, new_wp);
|
|
||||||
|
|
||||||
path = NULL;
|
|
||||||
if (item->client != NULL && item->client->session == NULL)
|
|
||||||
envent = environ_find(item->client->environ, "PATH");
|
|
||||||
else
|
|
||||||
envent = environ_find(s->environ, "PATH");
|
|
||||||
if (envent != NULL)
|
|
||||||
path = envent->value;
|
|
||||||
|
|
||||||
env = environ_for_session(s, 0);
|
|
||||||
if (window_pane_spawn(new_wp, argc, argv, path, shell, cwd, env,
|
|
||||||
s->tio, &cause) != 0) {
|
|
||||||
environ_free(env);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
environ_free(env);
|
|
||||||
|
|
||||||
layout_fix_panes(w);
|
|
||||||
server_redraw_window(w);
|
|
||||||
|
|
||||||
if (!args_has(args, 'd')) {
|
|
||||||
window_set_active_pane(w, new_wp);
|
|
||||||
session_select(s, wl->idx);
|
|
||||||
cmd_find_from_session(current, s, 0);
|
|
||||||
server_redraw_session(s);
|
|
||||||
} else
|
} else
|
||||||
server_status_session(s);
|
size = -1;
|
||||||
|
|
||||||
|
server_unzoom_window(wp->window);
|
||||||
|
|
||||||
|
flags = 0;
|
||||||
|
if (args_has(args, 'b'))
|
||||||
|
flags |= SPAWN_BEFORE;
|
||||||
|
if (args_has(args, 'f'))
|
||||||
|
flags |= SPAWN_FULLSIZE;
|
||||||
|
|
||||||
|
lc = layout_split_pane(wp, type, size, flags);
|
||||||
|
if (lc == NULL) {
|
||||||
|
cmdq_error(item, "no space for new pane");
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&sc, 0, sizeof sc);
|
||||||
|
sc.item = item;
|
||||||
|
sc.s = s;
|
||||||
|
sc.wl = wl;
|
||||||
|
|
||||||
|
sc.wp0 = wp;
|
||||||
|
sc.lc = lc;
|
||||||
|
|
||||||
|
sc.name = NULL;
|
||||||
|
sc.argc = args->argc;
|
||||||
|
sc.argv = args->argv;
|
||||||
|
|
||||||
|
sc.idx = -1;
|
||||||
|
sc.cwd = args_get(args, 'c');
|
||||||
|
|
||||||
|
sc.flags = flags;
|
||||||
|
if (args_has(args, 'd'))
|
||||||
|
sc.flags |= SPAWN_DETACHED;
|
||||||
|
|
||||||
|
if ((new_wp = spawn_pane(&sc, &cause)) == NULL) {
|
||||||
|
cmdq_error(item, "create pane failed: %s", cause);
|
||||||
|
free(cause);
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
}
|
||||||
|
if (!args_has(args, 'd'))
|
||||||
|
cmd_find_from_winlink_pane(current, wl, new_wp, 0);
|
||||||
|
server_redraw_window(wp->window);
|
||||||
|
server_status_session(s);
|
||||||
|
|
||||||
if (args_has(args, 'P')) {
|
if (args_has(args, 'P')) {
|
||||||
if ((template = args_get(args, 'F')) == NULL)
|
if ((template = args_get(args, 'F')) == NULL)
|
||||||
@ -165,22 +141,9 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
cmdq_print(item, "%s", cp);
|
cmdq_print(item, "%s", cp);
|
||||||
free(cp);
|
free(cp);
|
||||||
}
|
}
|
||||||
notify_window("window-layout-changed", w);
|
|
||||||
|
|
||||||
cmd_find_from_winlink_pane(&fs, wl, new_wp, 0);
|
cmd_find_from_winlink_pane(&fs, wl, new_wp, 0);
|
||||||
hooks_insert(s->hooks, item, &fs, "after-split-window");
|
hooks_insert(s->hooks, item, &fs, "after-split-window");
|
||||||
|
|
||||||
free(cwd);
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
|
|
||||||
error:
|
|
||||||
if (new_wp != NULL) {
|
|
||||||
layout_close_pane(new_wp);
|
|
||||||
window_remove_pane(w, new_wp);
|
|
||||||
}
|
|
||||||
cmdq_error(item, "create pane failed: %s", cause);
|
|
||||||
free(cause);
|
|
||||||
|
|
||||||
free(cwd);
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
}
|
||||||
|
@ -101,17 +101,17 @@ cmd_swap_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
|
|
||||||
if (!args_has(self->args, 'd')) {
|
if (!args_has(self->args, 'd')) {
|
||||||
if (src_w != dst_w) {
|
if (src_w != dst_w) {
|
||||||
window_set_active_pane(src_w, dst_wp);
|
window_set_active_pane(src_w, dst_wp, 1);
|
||||||
window_set_active_pane(dst_w, src_wp);
|
window_set_active_pane(dst_w, src_wp, 1);
|
||||||
} else {
|
} else {
|
||||||
tmp_wp = dst_wp;
|
tmp_wp = dst_wp;
|
||||||
window_set_active_pane(src_w, tmp_wp);
|
window_set_active_pane(src_w, tmp_wp, 1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (src_w->active == src_wp)
|
if (src_w->active == src_wp)
|
||||||
window_set_active_pane(src_w, dst_wp);
|
window_set_active_pane(src_w, dst_wp, 1);
|
||||||
if (dst_w->active == dst_wp)
|
if (dst_w->active == dst_wp)
|
||||||
window_set_active_pane(dst_w, src_wp);
|
window_set_active_pane(dst_w, src_wp, 1);
|
||||||
}
|
}
|
||||||
if (src_w != dst_w) {
|
if (src_w != dst_w) {
|
||||||
if (src_w->last == src_wp)
|
if (src_w->last == src_wp)
|
||||||
|
@ -116,7 +116,7 @@ cmd_switch_client_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
server_unzoom_window(wl->window);
|
server_unzoom_window(wl->window);
|
||||||
if (wp != NULL) {
|
if (wp != NULL) {
|
||||||
window_redraw_active_switch(wp->window, wp);
|
window_redraw_active_switch(wp->window, wp);
|
||||||
window_set_active_pane(wp->window, wp);
|
window_set_active_pane(wp->window, wp, 1);
|
||||||
}
|
}
|
||||||
session_set_current(s, wl);
|
session_set_current(s, wl);
|
||||||
cmd_find_from_session(&item->shared->current, s, 0);
|
cmd_find_from_session(&item->shared->current, s, 0);
|
||||||
|
15
layout.c
15
layout.c
@ -831,11 +831,12 @@ layout_resize_child_cells(struct window *w, struct layout_cell *lc)
|
|||||||
*/
|
*/
|
||||||
struct layout_cell *
|
struct layout_cell *
|
||||||
layout_split_pane(struct window_pane *wp, enum layout_type type, int size,
|
layout_split_pane(struct window_pane *wp, enum layout_type type, int size,
|
||||||
int insert_before, int full_size)
|
int flags)
|
||||||
{
|
{
|
||||||
struct layout_cell *lc, *lcparent, *lcnew, *lc1, *lc2;
|
struct layout_cell *lc, *lcparent, *lcnew, *lc1, *lc2;
|
||||||
u_int sx, sy, xoff, yoff, size1, size2;
|
u_int sx, sy, xoff, yoff, size1, size2;
|
||||||
u_int new_size, saved_size, resize_first = 0;
|
u_int new_size, saved_size, resize_first = 0;
|
||||||
|
int full_size = (flags & SPAWN_FULLSIZE);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If full_size is specified, add a new cell at the top of the window
|
* If full_size is specified, add a new cell at the top of the window
|
||||||
@ -876,7 +877,7 @@ layout_split_pane(struct window_pane *wp, enum layout_type type, int size,
|
|||||||
saved_size = sy;
|
saved_size = sy;
|
||||||
if (size < 0)
|
if (size < 0)
|
||||||
size2 = ((saved_size + 1) / 2) - 1;
|
size2 = ((saved_size + 1) / 2) - 1;
|
||||||
else if (insert_before)
|
else if (flags & SPAWN_BEFORE)
|
||||||
size2 = saved_size - size - 1;
|
size2 = saved_size - size - 1;
|
||||||
else
|
else
|
||||||
size2 = size;
|
size2 = size;
|
||||||
@ -887,7 +888,7 @@ layout_split_pane(struct window_pane *wp, enum layout_type type, int size,
|
|||||||
size1 = saved_size - 1 - size2;
|
size1 = saved_size - 1 - size2;
|
||||||
|
|
||||||
/* Which size are we using? */
|
/* Which size are we using? */
|
||||||
if (insert_before)
|
if (flags & SPAWN_BEFORE)
|
||||||
new_size = size2;
|
new_size = size2;
|
||||||
else
|
else
|
||||||
new_size = size1;
|
new_size = size1;
|
||||||
@ -903,7 +904,7 @@ layout_split_pane(struct window_pane *wp, enum layout_type type, int size,
|
|||||||
*/
|
*/
|
||||||
lcparent = lc->parent;
|
lcparent = lc->parent;
|
||||||
lcnew = layout_create_cell(lcparent);
|
lcnew = layout_create_cell(lcparent);
|
||||||
if (insert_before)
|
if (flags & SPAWN_BEFORE)
|
||||||
TAILQ_INSERT_BEFORE(lc, lcnew, entry);
|
TAILQ_INSERT_BEFORE(lc, lcnew, entry);
|
||||||
else
|
else
|
||||||
TAILQ_INSERT_AFTER(&lcparent->cells, lc, lcnew, entry);
|
TAILQ_INSERT_AFTER(&lcparent->cells, lc, lcnew, entry);
|
||||||
@ -932,7 +933,7 @@ layout_split_pane(struct window_pane *wp, enum layout_type type, int size,
|
|||||||
layout_set_size(lcnew, size, sy, 0, 0);
|
layout_set_size(lcnew, size, sy, 0, 0);
|
||||||
else if (lc->type == LAYOUT_TOPBOTTOM)
|
else if (lc->type == LAYOUT_TOPBOTTOM)
|
||||||
layout_set_size(lcnew, sx, size, 0, 0);
|
layout_set_size(lcnew, sx, size, 0, 0);
|
||||||
if (insert_before)
|
if (flags & SPAWN_BEFORE)
|
||||||
TAILQ_INSERT_HEAD(&lc->cells, lcnew, entry);
|
TAILQ_INSERT_HEAD(&lc->cells, lcnew, entry);
|
||||||
else
|
else
|
||||||
TAILQ_INSERT_TAIL(&lc->cells, lcnew, entry);
|
TAILQ_INSERT_TAIL(&lc->cells, lcnew, entry);
|
||||||
@ -956,12 +957,12 @@ layout_split_pane(struct window_pane *wp, enum layout_type type, int size,
|
|||||||
|
|
||||||
/* Create the new child cell. */
|
/* Create the new child cell. */
|
||||||
lcnew = layout_create_cell(lcparent);
|
lcnew = layout_create_cell(lcparent);
|
||||||
if (insert_before)
|
if (flags & SPAWN_BEFORE)
|
||||||
TAILQ_INSERT_HEAD(&lcparent->cells, lcnew, entry);
|
TAILQ_INSERT_HEAD(&lcparent->cells, lcnew, entry);
|
||||||
else
|
else
|
||||||
TAILQ_INSERT_TAIL(&lcparent->cells, lcnew, entry);
|
TAILQ_INSERT_TAIL(&lcparent->cells, lcnew, entry);
|
||||||
}
|
}
|
||||||
if (insert_before) {
|
if (flags & SPAWN_BEFORE) {
|
||||||
lc1 = lcnew;
|
lc1 = lcnew;
|
||||||
lc2 = lc;
|
lc2 = lc;
|
||||||
} else {
|
} else {
|
||||||
|
@ -369,7 +369,7 @@ server_destroy_session_group(struct session *s)
|
|||||||
else {
|
else {
|
||||||
TAILQ_FOREACH_SAFE(s, &sg->sessions, gentry, s1) {
|
TAILQ_FOREACH_SAFE(s, &sg->sessions, gentry, s1) {
|
||||||
server_destroy_session(s);
|
server_destroy_session(s);
|
||||||
session_destroy(s, __func__);
|
session_destroy(s, 1, __func__);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -436,7 +436,7 @@ server_check_unattached(void)
|
|||||||
if (s->attached != 0)
|
if (s->attached != 0)
|
||||||
continue;
|
continue;
|
||||||
if (options_get_number (s->options, "destroy-unattached"))
|
if (options_get_number (s->options, "destroy-unattached"))
|
||||||
session_destroy(s, __func__);
|
session_destroy(s, 1, __func__);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
server.c
2
server.c
@ -296,7 +296,7 @@ server_send_exit(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
RB_FOREACH_SAFE(s, sessions, &sessions, s1)
|
RB_FOREACH_SAFE(s, sessions, &sessions, s1)
|
||||||
session_destroy(s, __func__);
|
session_destroy(s, 1, __func__);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update socket execute permissions based on whether sessions are attached. */
|
/* Update socket execute permissions based on whether sessions are attached. */
|
||||||
|
68
session.c
68
session.c
@ -111,12 +111,10 @@ session_find_by_id(u_int id)
|
|||||||
|
|
||||||
/* Create a new session. */
|
/* Create a new session. */
|
||||||
struct session *
|
struct session *
|
||||||
session_create(const char *prefix, const char *name, int argc, char **argv,
|
session_create(const char *prefix, const char *name, const char *cwd,
|
||||||
const char *path, const char *cwd, struct environ *env, struct options *oo,
|
struct environ *env, struct options *oo, struct termios *tio)
|
||||||
struct termios *tio, int idx, char **cause)
|
|
||||||
{
|
{
|
||||||
struct session *s;
|
struct session *s;
|
||||||
struct winlink *wl;
|
|
||||||
|
|
||||||
s = xcalloc(1, sizeof *s);
|
s = xcalloc(1, sizeof *s);
|
||||||
s->references = 1;
|
s->references = 1;
|
||||||
@ -128,10 +126,7 @@ session_create(const char *prefix, const char *name, int argc, char **argv,
|
|||||||
TAILQ_INIT(&s->lastw);
|
TAILQ_INIT(&s->lastw);
|
||||||
RB_INIT(&s->windows);
|
RB_INIT(&s->windows);
|
||||||
|
|
||||||
s->environ = environ_create();
|
s->environ = env;
|
||||||
if (env != NULL)
|
|
||||||
environ_copy(env, s->environ);
|
|
||||||
|
|
||||||
s->options = oo;
|
s->options = oo;
|
||||||
s->hooks = hooks_create(global_hooks);
|
s->hooks = hooks_create(global_hooks);
|
||||||
|
|
||||||
@ -165,17 +160,6 @@ session_create(const char *prefix, const char *name, int argc, char **argv,
|
|||||||
fatal("gettimeofday failed");
|
fatal("gettimeofday failed");
|
||||||
session_update_activity(s, &s->creation_time);
|
session_update_activity(s, &s->creation_time);
|
||||||
|
|
||||||
if (argc >= 0) {
|
|
||||||
wl = session_new(s, NULL, argc, argv, path, cwd, idx, cause);
|
|
||||||
if (wl == NULL) {
|
|
||||||
session_destroy(s, __func__);
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
session_select(s, RB_ROOT(&s->windows)->idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
log_debug("session %s created", s->name);
|
|
||||||
|
|
||||||
return (s);
|
return (s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,7 +203,7 @@ session_free(__unused int fd, __unused short events, void *arg)
|
|||||||
|
|
||||||
/* Destroy a session. */
|
/* Destroy a session. */
|
||||||
void
|
void
|
||||||
session_destroy(struct session *s, const char *from)
|
session_destroy(struct session *s, int notify, const char *from)
|
||||||
{
|
{
|
||||||
struct winlink *wl;
|
struct winlink *wl;
|
||||||
|
|
||||||
@ -227,7 +211,8 @@ session_destroy(struct session *s, const char *from)
|
|||||||
s->curw = NULL;
|
s->curw = NULL;
|
||||||
|
|
||||||
RB_REMOVE(sessions, &sessions, s);
|
RB_REMOVE(sessions, &sessions, s);
|
||||||
notify_session("session-closed", s);
|
if (notify)
|
||||||
|
notify_session("session-closed", s);
|
||||||
|
|
||||||
free(s->tio);
|
free(s->tio);
|
||||||
|
|
||||||
@ -337,45 +322,6 @@ session_previous_session(struct session *s)
|
|||||||
return (s2);
|
return (s2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create a new window on a session. */
|
|
||||||
struct winlink *
|
|
||||||
session_new(struct session *s, const char *name, int argc, char **argv,
|
|
||||||
const char *path, const char *cwd, int idx, char **cause)
|
|
||||||
{
|
|
||||||
struct window *w;
|
|
||||||
struct winlink *wl;
|
|
||||||
struct environ *env;
|
|
||||||
const char *shell;
|
|
||||||
u_int hlimit, sx, sy;
|
|
||||||
|
|
||||||
if ((wl = winlink_add(&s->windows, idx)) == NULL) {
|
|
||||||
xasprintf(cause, "index in use: %d", idx);
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
wl->session = s;
|
|
||||||
|
|
||||||
shell = options_get_string(s->options, "default-shell");
|
|
||||||
if (*shell == '\0' || areshell(shell))
|
|
||||||
shell = _PATH_BSHELL;
|
|
||||||
|
|
||||||
default_window_size(s, NULL, &sx, &sy, -1);
|
|
||||||
hlimit = options_get_number(s->options, "history-limit");
|
|
||||||
env = environ_for_session(s, 0);
|
|
||||||
w = window_create_spawn(name, argc, argv, path, shell, cwd, env, s->tio,
|
|
||||||
sx, sy, hlimit, cause);
|
|
||||||
if (w == NULL) {
|
|
||||||
winlink_remove(&s->windows, wl);
|
|
||||||
environ_free(env);
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
winlink_set_window(wl, w);
|
|
||||||
environ_free(env);
|
|
||||||
notify_session_window("window-linked", s, w);
|
|
||||||
|
|
||||||
session_group_synchronize_from(s);
|
|
||||||
return (wl);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Attach a window to a session. */
|
/* Attach a window to a session. */
|
||||||
struct winlink *
|
struct winlink *
|
||||||
session_attach(struct session *s, struct window *w, int idx, char **cause)
|
session_attach(struct session *s, struct window *w, int idx, char **cause)
|
||||||
@ -411,7 +357,7 @@ session_detach(struct session *s, struct winlink *wl)
|
|||||||
session_group_synchronize_from(s);
|
session_group_synchronize_from(s);
|
||||||
|
|
||||||
if (RB_EMPTY(&s->windows)) {
|
if (RB_EMPTY(&s->windows)) {
|
||||||
session_destroy(s, __func__);
|
session_destroy(s, 1, __func__);
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
return (0);
|
return (0);
|
||||||
|
58
tmux.h
58
tmux.h
@ -235,8 +235,8 @@ enum {
|
|||||||
|
|
||||||
/* Termcap codes. */
|
/* Termcap codes. */
|
||||||
enum tty_code_code {
|
enum tty_code_code {
|
||||||
TTYC_AX = 0,
|
|
||||||
TTYC_ACSC,
|
TTYC_ACSC,
|
||||||
|
TTYC_AX,
|
||||||
TTYC_BCE,
|
TTYC_BCE,
|
||||||
TTYC_BEL,
|
TTYC_BEL,
|
||||||
TTYC_BLINK,
|
TTYC_BLINK,
|
||||||
@ -816,7 +816,7 @@ struct window_pane {
|
|||||||
int argc;
|
int argc;
|
||||||
char **argv;
|
char **argv;
|
||||||
char *shell;
|
char *shell;
|
||||||
const char *cwd;
|
char *cwd;
|
||||||
|
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
char tty[TTY_NAME_MAX];
|
char tty[TTY_NAME_MAX];
|
||||||
@ -1563,6 +1563,32 @@ struct options_table_entry {
|
|||||||
#define CMD_SRCDST_CLIENT_USAGE "[-s src-client] [-t dst-client]"
|
#define CMD_SRCDST_CLIENT_USAGE "[-s src-client] [-t dst-client]"
|
||||||
#define CMD_BUFFER_USAGE "[-b buffer-name]"
|
#define CMD_BUFFER_USAGE "[-b buffer-name]"
|
||||||
|
|
||||||
|
/* Spawn common context. */
|
||||||
|
struct spawn_context {
|
||||||
|
struct cmdq_item *item;
|
||||||
|
|
||||||
|
struct session *s;
|
||||||
|
struct winlink *wl;
|
||||||
|
|
||||||
|
struct window_pane *wp0;
|
||||||
|
struct layout_cell *lc;
|
||||||
|
|
||||||
|
const char *name;
|
||||||
|
char **argv;
|
||||||
|
int argc;
|
||||||
|
|
||||||
|
int idx;
|
||||||
|
const char *cwd;
|
||||||
|
|
||||||
|
int flags;
|
||||||
|
#define SPAWN_KILL 0x1
|
||||||
|
#define SPAWN_DETACHED 0x2
|
||||||
|
#define SPAWN_RESPAWN 0x4
|
||||||
|
#define SPAWN_BEFORE 0x8
|
||||||
|
#define SPAWN_NONOTIFY 0x10
|
||||||
|
#define SPAWN_FULLSIZE 0x20
|
||||||
|
};
|
||||||
|
|
||||||
/* tmux.c */
|
/* tmux.c */
|
||||||
extern struct hooks *global_hooks;
|
extern struct hooks *global_hooks;
|
||||||
extern struct options *global_options;
|
extern struct options *global_options;
|
||||||
@ -2234,17 +2260,17 @@ struct window *window_find_by_id_str(const char *);
|
|||||||
struct window *window_find_by_id(u_int);
|
struct window *window_find_by_id(u_int);
|
||||||
void window_update_activity(struct window *);
|
void window_update_activity(struct window *);
|
||||||
struct window *window_create(u_int, u_int);
|
struct window *window_create(u_int, u_int);
|
||||||
struct window *window_create_spawn(const char *, int, char **, const char *,
|
void window_destroy(struct window *);
|
||||||
const char *, const char *, struct environ *,
|
void window_pane_set_event(struct window_pane *);
|
||||||
struct termios *, u_int, u_int, u_int, char **);
|
|
||||||
struct window_pane *window_get_active_at(struct window *, u_int, u_int);
|
struct window_pane *window_get_active_at(struct window *, u_int, u_int);
|
||||||
struct window_pane *window_find_string(struct window *, const char *);
|
struct window_pane *window_find_string(struct window *, const char *);
|
||||||
int window_has_pane(struct window *, struct window_pane *);
|
int window_has_pane(struct window *, struct window_pane *);
|
||||||
int window_set_active_pane(struct window *, struct window_pane *);
|
int window_set_active_pane(struct window *, struct window_pane *,
|
||||||
|
int);
|
||||||
void window_redraw_active_switch(struct window *,
|
void window_redraw_active_switch(struct window *,
|
||||||
struct window_pane *);
|
struct window_pane *);
|
||||||
struct window_pane *window_add_pane(struct window *, struct window_pane *, int,
|
struct window_pane *window_add_pane(struct window *, struct window_pane *,
|
||||||
int, u_int);
|
u_int, int);
|
||||||
void window_resize(struct window *, u_int, u_int);
|
void window_resize(struct window *, u_int, u_int);
|
||||||
int window_zoom(struct window_pane *);
|
int window_zoom(struct window_pane *);
|
||||||
int window_unzoom(struct window *);
|
int window_unzoom(struct window *);
|
||||||
@ -2261,9 +2287,6 @@ void window_destroy_panes(struct window *);
|
|||||||
struct window_pane *window_pane_find_by_id_str(const char *);
|
struct window_pane *window_pane_find_by_id_str(const char *);
|
||||||
struct window_pane *window_pane_find_by_id(u_int);
|
struct window_pane *window_pane_find_by_id(u_int);
|
||||||
int window_pane_destroy_ready(struct window_pane *);
|
int window_pane_destroy_ready(struct window_pane *);
|
||||||
int window_pane_spawn(struct window_pane *, int, char **,
|
|
||||||
const char *, const char *, const char *, struct environ *,
|
|
||||||
struct termios *, char **);
|
|
||||||
void window_pane_resize(struct window_pane *, u_int, u_int);
|
void window_pane_resize(struct window_pane *, u_int, u_int);
|
||||||
void window_pane_alternate_on(struct window_pane *,
|
void window_pane_alternate_on(struct window_pane *,
|
||||||
struct grid_cell *, int);
|
struct grid_cell *, int);
|
||||||
@ -2321,7 +2344,7 @@ void layout_resize_pane_to(struct window_pane *, enum layout_type,
|
|||||||
u_int);
|
u_int);
|
||||||
void layout_assign_pane(struct layout_cell *, struct window_pane *);
|
void layout_assign_pane(struct layout_cell *, struct window_pane *);
|
||||||
struct layout_cell *layout_split_pane(struct window_pane *, enum layout_type,
|
struct layout_cell *layout_split_pane(struct window_pane *, enum layout_type,
|
||||||
int, int, int);
|
int, int);
|
||||||
void layout_close_pane(struct window_pane *);
|
void layout_close_pane(struct window_pane *);
|
||||||
int layout_spread_cell(struct window *, struct layout_cell *);
|
int layout_spread_cell(struct window *, struct layout_cell *);
|
||||||
void layout_spread_out(struct window_pane *);
|
void layout_spread_out(struct window_pane *);
|
||||||
@ -2420,10 +2443,9 @@ int session_alive(struct session *);
|
|||||||
struct session *session_find(const char *);
|
struct session *session_find(const char *);
|
||||||
struct session *session_find_by_id_str(const char *);
|
struct session *session_find_by_id_str(const char *);
|
||||||
struct session *session_find_by_id(u_int);
|
struct session *session_find_by_id(u_int);
|
||||||
struct session *session_create(const char *, const char *, int, char **,
|
struct session *session_create(const char *, const char *, const char *,
|
||||||
const char *, const char *, struct environ *,
|
struct environ *, struct options *, struct termios *);
|
||||||
struct options *, struct termios *, int, char **);
|
void session_destroy(struct session *, int, const char *);
|
||||||
void session_destroy(struct session *, const char *);
|
|
||||||
void session_add_ref(struct session *, const char *);
|
void session_add_ref(struct session *, const char *);
|
||||||
void session_remove_ref(struct session *, const char *);
|
void session_remove_ref(struct session *, const char *);
|
||||||
int session_check_name(const char *);
|
int session_check_name(const char *);
|
||||||
@ -2497,4 +2519,8 @@ void style_set(struct style *, const struct grid_cell *);
|
|||||||
void style_copy(struct style *, struct style *);
|
void style_copy(struct style *, struct style *);
|
||||||
int style_is_default(struct style *);
|
int style_is_default(struct style *);
|
||||||
|
|
||||||
|
/* spawn.c */
|
||||||
|
struct winlink *spawn_window(struct spawn_context *, char **);
|
||||||
|
struct window_pane *spawn_pane(struct spawn_context *, char **);
|
||||||
|
|
||||||
#endif /* TMUX_H */
|
#endif /* TMUX_H */
|
||||||
|
@ -1006,7 +1006,7 @@ window_tree_kill_each(__unused void* modedata, void* itemdata,
|
|||||||
case WINDOW_TREE_SESSION:
|
case WINDOW_TREE_SESSION:
|
||||||
if (s != NULL) {
|
if (s != NULL) {
|
||||||
server_destroy_session(s);
|
server_destroy_session(s);
|
||||||
session_destroy(s, __func__);
|
session_destroy(s, 1, __func__);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case WINDOW_TREE_WINDOW:
|
case WINDOW_TREE_WINDOW:
|
||||||
|
227
window.c
227
window.c
@ -26,7 +26,6 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <termios.h>
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
@ -71,20 +70,10 @@ const struct window_mode *all_window_modes[] = {
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
static void window_destroy(struct window *);
|
|
||||||
|
|
||||||
static struct window_pane *window_pane_create(struct window *, u_int, u_int,
|
static struct window_pane *window_pane_create(struct window *, u_int, u_int,
|
||||||
u_int);
|
u_int);
|
||||||
static void window_pane_destroy(struct window_pane *);
|
static void window_pane_destroy(struct window_pane *);
|
||||||
|
|
||||||
static void window_pane_read_callback(struct bufferevent *, void *);
|
|
||||||
static void window_pane_error_callback(struct bufferevent *, short, void *);
|
|
||||||
|
|
||||||
static int winlink_next_index(struct winlinks *, int);
|
|
||||||
|
|
||||||
static struct window_pane *window_pane_choose_best(struct window_pane **,
|
|
||||||
u_int);
|
|
||||||
|
|
||||||
RB_GENERATE(windows, window, entry, window_cmp);
|
RB_GENERATE(windows, window, entry, window_cmp);
|
||||||
RB_GENERATE(winlinks, winlink, entry, winlink_cmp);
|
RB_GENERATE(winlinks, winlink, entry, winlink_cmp);
|
||||||
RB_GENERATE(window_pane_tree, window_pane, tree_entry, window_pane_cmp);
|
RB_GENERATE(window_pane_tree, window_pane, tree_entry, window_pane_cmp);
|
||||||
@ -340,37 +329,7 @@ window_create(u_int sx, u_int sy)
|
|||||||
return (w);
|
return (w);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct window *
|
void
|
||||||
window_create_spawn(const char *name, int argc, char **argv, const char *path,
|
|
||||||
const char *shell, const char *cwd, struct environ *env,
|
|
||||||
struct termios *tio, u_int sx, u_int sy, u_int hlimit, char **cause)
|
|
||||||
{
|
|
||||||
struct window *w;
|
|
||||||
struct window_pane *wp;
|
|
||||||
|
|
||||||
w = window_create(sx, sy);
|
|
||||||
wp = window_add_pane(w, NULL, 0, 0, hlimit);
|
|
||||||
layout_init(w, wp);
|
|
||||||
|
|
||||||
if (window_pane_spawn(wp, argc, argv, path, shell, cwd,
|
|
||||||
env, tio, cause) != 0) {
|
|
||||||
window_destroy(w);
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
w->active = TAILQ_FIRST(&w->panes);
|
|
||||||
if (name != NULL) {
|
|
||||||
w->name = xstrdup(name);
|
|
||||||
options_set_number(w->options, "automatic-rename", 0);
|
|
||||||
} else
|
|
||||||
w->name = default_window_name(w);
|
|
||||||
|
|
||||||
notify_window("window-pane-changed", w);
|
|
||||||
|
|
||||||
return (w);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
window_destroy(struct window *w)
|
window_destroy(struct window *w)
|
||||||
{
|
{
|
||||||
log_debug("window @%u destroyed (%d references)", w->id, w->references);
|
log_debug("window @%u destroyed (%d references)", w->id, w->references);
|
||||||
@ -461,17 +420,22 @@ window_has_pane(struct window *w, struct window_pane *wp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
window_set_active_pane(struct window *w, struct window_pane *wp)
|
window_set_active_pane(struct window *w, struct window_pane *wp, int notify)
|
||||||
{
|
{
|
||||||
log_debug("%s: pane %%%u (was %%%u)", __func__, wp->id, w->active->id);
|
log_debug("%s: pane %%%u", __func__, wp->id);
|
||||||
|
|
||||||
if (wp == w->active)
|
if (wp == w->active)
|
||||||
return (0);
|
return (0);
|
||||||
w->last = w->active;
|
w->last = w->active;
|
||||||
|
|
||||||
w->active = wp;
|
w->active = wp;
|
||||||
w->active->active_point = next_active_point++;
|
w->active->active_point = next_active_point++;
|
||||||
w->active->flags |= PANE_CHANGED;
|
w->active->flags |= PANE_CHANGED;
|
||||||
|
|
||||||
tty_update_window_offset(w);
|
tty_update_window_offset(w);
|
||||||
notify_window("window-pane-changed", w);
|
|
||||||
|
if (notify)
|
||||||
|
notify_window("window-pane-changed", w);
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -569,7 +533,7 @@ window_zoom(struct window_pane *wp)
|
|||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
if (w->active != wp)
|
if (w->active != wp)
|
||||||
window_set_active_pane(w, wp);
|
window_set_active_pane(w, wp, 1);
|
||||||
|
|
||||||
TAILQ_FOREACH(wp1, &w->panes, entry) {
|
TAILQ_FOREACH(wp1, &w->panes, entry) {
|
||||||
wp1->saved_layout_cell = wp1->layout_cell;
|
wp1->saved_layout_cell = wp1->layout_cell;
|
||||||
@ -608,8 +572,8 @@ window_unzoom(struct window *w)
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct window_pane *
|
struct window_pane *
|
||||||
window_add_pane(struct window *w, struct window_pane *other, int before,
|
window_add_pane(struct window *w, struct window_pane *other, u_int hlimit,
|
||||||
int full_size, u_int hlimit)
|
int flags)
|
||||||
{
|
{
|
||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
|
|
||||||
@ -620,15 +584,15 @@ window_add_pane(struct window *w, struct window_pane *other, int before,
|
|||||||
if (TAILQ_EMPTY(&w->panes)) {
|
if (TAILQ_EMPTY(&w->panes)) {
|
||||||
log_debug("%s: @%u at start", __func__, w->id);
|
log_debug("%s: @%u at start", __func__, w->id);
|
||||||
TAILQ_INSERT_HEAD(&w->panes, wp, entry);
|
TAILQ_INSERT_HEAD(&w->panes, wp, entry);
|
||||||
} else if (before) {
|
} else if (flags & SPAWN_BEFORE) {
|
||||||
log_debug("%s: @%u before %%%u", __func__, w->id, wp->id);
|
log_debug("%s: @%u before %%%u", __func__, w->id, wp->id);
|
||||||
if (full_size)
|
if (flags & SPAWN_FULLSIZE)
|
||||||
TAILQ_INSERT_HEAD(&w->panes, wp, entry);
|
TAILQ_INSERT_HEAD(&w->panes, wp, entry);
|
||||||
else
|
else
|
||||||
TAILQ_INSERT_BEFORE(other, wp, entry);
|
TAILQ_INSERT_BEFORE(other, wp, entry);
|
||||||
} else {
|
} else {
|
||||||
log_debug("%s: @%u after %%%u", __func__, w->id, wp->id);
|
log_debug("%s: @%u after %%%u", __func__, w->id, wp->id);
|
||||||
if (full_size)
|
if (flags & SPAWN_FULLSIZE)
|
||||||
TAILQ_INSERT_TAIL(&w->panes, wp, entry);
|
TAILQ_INSERT_TAIL(&w->panes, wp, entry);
|
||||||
else
|
else
|
||||||
TAILQ_INSERT_AFTER(&w->panes, other, wp, entry);
|
TAILQ_INSERT_AFTER(&w->panes, other, wp, entry);
|
||||||
@ -888,153 +852,6 @@ window_pane_destroy(struct window_pane *wp)
|
|||||||
free(wp);
|
free(wp);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
window_pane_spawn(struct window_pane *wp, int argc, char **argv,
|
|
||||||
const char *path, const char *shell, const char *cwd, struct environ *env,
|
|
||||||
struct termios *tio, char **cause)
|
|
||||||
{
|
|
||||||
struct winsize ws;
|
|
||||||
char *argv0, *cmd, **argvp;
|
|
||||||
const char *ptr, *first, *home;
|
|
||||||
struct termios tio2;
|
|
||||||
#ifdef HAVE_UTEMPTER
|
|
||||||
char s[32];
|
|
||||||
#endif
|
|
||||||
sigset_t set, oldset;
|
|
||||||
|
|
||||||
if (wp->fd != -1) {
|
|
||||||
bufferevent_free(wp->event);
|
|
||||||
close(wp->fd);
|
|
||||||
}
|
|
||||||
if (argc > 0) {
|
|
||||||
cmd_free_argv(wp->argc, wp->argv);
|
|
||||||
wp->argc = argc;
|
|
||||||
wp->argv = cmd_copy_argv(argc, argv);
|
|
||||||
}
|
|
||||||
if (shell != NULL) {
|
|
||||||
free(wp->shell);
|
|
||||||
wp->shell = xstrdup(shell);
|
|
||||||
}
|
|
||||||
if (cwd != NULL) {
|
|
||||||
free((void *)wp->cwd);
|
|
||||||
wp->cwd = xstrdup(cwd);
|
|
||||||
}
|
|
||||||
wp->flags &= ~(PANE_STATUSREADY|PANE_STATUSDRAWN);
|
|
||||||
|
|
||||||
cmd = cmd_stringify_argv(wp->argc, wp->argv);
|
|
||||||
log_debug("%s: shell=%s", __func__, wp->shell);
|
|
||||||
log_debug("%s: cmd=%s", __func__, cmd);
|
|
||||||
log_debug("%s: cwd=%s", __func__, cwd);
|
|
||||||
cmd_log_argv(wp->argc, wp->argv, __func__);
|
|
||||||
environ_log(env, "%s: environment ", __func__);
|
|
||||||
|
|
||||||
memset(&ws, 0, sizeof ws);
|
|
||||||
ws.ws_col = screen_size_x(&wp->base);
|
|
||||||
ws.ws_row = screen_size_y(&wp->base);
|
|
||||||
|
|
||||||
sigfillset(&set);
|
|
||||||
sigprocmask(SIG_BLOCK, &set, &oldset);
|
|
||||||
switch (wp->pid = fdforkpty(ptm_fd, &wp->fd, wp->tty, NULL, &ws)) {
|
|
||||||
case -1:
|
|
||||||
wp->event = NULL;
|
|
||||||
wp->fd = -1;
|
|
||||||
|
|
||||||
xasprintf(cause, "%s: %s", cmd, strerror(errno));
|
|
||||||
free(cmd);
|
|
||||||
|
|
||||||
sigprocmask(SIG_SETMASK, &oldset, NULL);
|
|
||||||
return (-1);
|
|
||||||
case 0:
|
|
||||||
proc_clear_signals(server_proc, 1);
|
|
||||||
sigprocmask(SIG_SETMASK, &oldset, NULL);
|
|
||||||
|
|
||||||
cwd = NULL;
|
|
||||||
if (chdir(wp->cwd) == 0)
|
|
||||||
cwd = wp->cwd;
|
|
||||||
else if ((home = find_home()) != NULL && chdir(home) == 0)
|
|
||||||
cwd = home;
|
|
||||||
else
|
|
||||||
chdir("/");
|
|
||||||
|
|
||||||
if (tcgetattr(STDIN_FILENO, &tio2) != 0)
|
|
||||||
fatal("tcgetattr failed");
|
|
||||||
if (tio != NULL)
|
|
||||||
memcpy(tio2.c_cc, tio->c_cc, sizeof tio2.c_cc);
|
|
||||||
tio2.c_cc[VERASE] = '\177';
|
|
||||||
#ifdef IUTF8
|
|
||||||
tio2.c_iflag |= IUTF8;
|
|
||||||
#endif
|
|
||||||
if (tcsetattr(STDIN_FILENO, TCSANOW, &tio2) != 0)
|
|
||||||
fatal("tcgetattr failed");
|
|
||||||
|
|
||||||
log_close();
|
|
||||||
closefrom(STDERR_FILENO + 1);
|
|
||||||
|
|
||||||
if (path != NULL)
|
|
||||||
environ_set(env, "PATH", "%s", path);
|
|
||||||
if (cwd != NULL)
|
|
||||||
environ_set(env, "PWD", "%s", cwd);
|
|
||||||
environ_set(env, "TMUX_PANE", "%%%u", wp->id);
|
|
||||||
environ_push(env);
|
|
||||||
|
|
||||||
setenv("SHELL", wp->shell, 1);
|
|
||||||
ptr = strrchr(wp->shell, '/');
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If given one argument, assume it should be passed to sh -c;
|
|
||||||
* with more than one argument, use execvp(). If there is no
|
|
||||||
* arguments, create a login shell.
|
|
||||||
*/
|
|
||||||
if (wp->argc > 0) {
|
|
||||||
if (wp->argc != 1) {
|
|
||||||
/* Copy to ensure argv ends in NULL. */
|
|
||||||
argvp = cmd_copy_argv(wp->argc, wp->argv);
|
|
||||||
execvp(argvp[0], argvp);
|
|
||||||
fatal("execvp failed");
|
|
||||||
}
|
|
||||||
first = wp->argv[0];
|
|
||||||
|
|
||||||
if (ptr != NULL && *(ptr + 1) != '\0')
|
|
||||||
xasprintf(&argv0, "%s", ptr + 1);
|
|
||||||
else
|
|
||||||
xasprintf(&argv0, "%s", wp->shell);
|
|
||||||
execl(wp->shell, argv0, "-c", first, (char *)NULL);
|
|
||||||
fatal("execl failed");
|
|
||||||
}
|
|
||||||
if (ptr != NULL && *(ptr + 1) != '\0')
|
|
||||||
xasprintf(&argv0, "-%s", ptr + 1);
|
|
||||||
else
|
|
||||||
xasprintf(&argv0, "-%s", wp->shell);
|
|
||||||
execl(wp->shell, argv0, (char *)NULL);
|
|
||||||
fatal("execl failed");
|
|
||||||
}
|
|
||||||
log_debug("%s: master=%s", __func__, ttyname(wp->fd));
|
|
||||||
log_debug("%s: slave=%s", __func__, wp->tty);
|
|
||||||
|
|
||||||
#ifdef HAVE_UTEMPTER
|
|
||||||
xsnprintf(s, sizeof s, "tmux(%lu).%%%u", (long) getpid(), wp->id);
|
|
||||||
utempter_add_record(wp->fd, s);
|
|
||||||
kill(getpid(), SIGCHLD);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
sigprocmask(SIG_SETMASK, &oldset, NULL);
|
|
||||||
setblocking(wp->fd, 0);
|
|
||||||
|
|
||||||
wp->event = bufferevent_new(wp->fd, window_pane_read_callback, NULL,
|
|
||||||
window_pane_error_callback, wp);
|
|
||||||
if (wp->event == NULL)
|
|
||||||
fatalx("out of memory");
|
|
||||||
|
|
||||||
wp->pipe_off = 0;
|
|
||||||
wp->flags &= ~PANE_EXITED;
|
|
||||||
|
|
||||||
bufferevent_setwatermark(wp->event, EV_READ, 0, READ_SIZE);
|
|
||||||
bufferevent_enable(wp->event, EV_READ|EV_WRITE);
|
|
||||||
|
|
||||||
free(cmd);
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
window_pane_read_callback(__unused struct bufferevent *bufev, void *data)
|
window_pane_read_callback(__unused struct bufferevent *bufev, void *data)
|
||||||
{
|
{
|
||||||
@ -1069,6 +886,18 @@ window_pane_error_callback(__unused struct bufferevent *bufev,
|
|||||||
server_destroy_pane(wp, 1);
|
server_destroy_pane(wp, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
window_pane_set_event(struct window_pane *wp)
|
||||||
|
{
|
||||||
|
setblocking(wp->fd, 0);
|
||||||
|
|
||||||
|
wp->event = bufferevent_new(wp->fd, window_pane_read_callback,
|
||||||
|
NULL, window_pane_error_callback, wp);
|
||||||
|
|
||||||
|
bufferevent_setwatermark(wp->event, EV_READ, 0, READ_SIZE);
|
||||||
|
bufferevent_enable(wp->event, EV_READ|EV_WRITE);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
window_pane_resize(struct window_pane *wp, u_int sx, u_int sy)
|
window_pane_resize(struct window_pane *wp, u_int sx, u_int sy)
|
||||||
{
|
{
|
||||||
@ -1617,6 +1446,8 @@ winlink_shuffle_up(struct session *s, struct winlink *wl)
|
|||||||
{
|
{
|
||||||
int idx, last;
|
int idx, last;
|
||||||
|
|
||||||
|
if (wl == NULL)
|
||||||
|
return (-1);
|
||||||
idx = wl->idx + 1;
|
idx = wl->idx + 1;
|
||||||
|
|
||||||
/* Find the next free index. */
|
/* Find the next free index. */
|
||||||
|
Loading…
Reference in New Issue
Block a user