mirror of
https://github.com/tmux/tmux.git
synced 2024-12-24 18:21:33 +00:00
Merge branch 'obsd-master' into master
This commit is contained in:
commit
54773d23b5
@ -124,17 +124,9 @@ cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag,
|
||||
if (!Eflag)
|
||||
environ_update(s->options, c->environ, s->environ);
|
||||
|
||||
c->session = s;
|
||||
server_client_set_session(c, s);
|
||||
if (~cmdq_get_flags(item) & CMDQ_STATE_REPEAT)
|
||||
server_client_set_key_table(c, NULL);
|
||||
tty_update_client_offset(c);
|
||||
status_timer_start(c);
|
||||
notify_client("client-session-changed", c);
|
||||
session_update_activity(s, NULL);
|
||||
gettimeofday(&s->last_attached_time, NULL);
|
||||
server_redraw_client(c);
|
||||
s->curw->flags &= ~WINLINK_ALERTFLAGS;
|
||||
s->curw->window->latest = c;
|
||||
} else {
|
||||
if (server_client_open(c, &cause) != 0) {
|
||||
cmdq_error(item, "open terminal failed: %s", cause);
|
||||
@ -156,25 +148,14 @@ cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag,
|
||||
if (!Eflag)
|
||||
environ_update(s->options, c->environ, s->environ);
|
||||
|
||||
c->session = s;
|
||||
server_client_set_session(c, s);
|
||||
server_client_set_key_table(c, NULL);
|
||||
tty_update_client_offset(c);
|
||||
status_timer_start(c);
|
||||
notify_client("client-session-changed", c);
|
||||
session_update_activity(s, NULL);
|
||||
gettimeofday(&s->last_attached_time, NULL);
|
||||
server_redraw_client(c);
|
||||
s->curw->flags &= ~WINLINK_ALERTFLAGS;
|
||||
s->curw->window->latest = c;
|
||||
|
||||
if (~c->flags & CLIENT_CONTROL)
|
||||
proc_send(c->peer, MSG_READY, -1, NULL, 0);
|
||||
notify_client("client-attached", c);
|
||||
c->flags |= CLIENT_ATTACHED;
|
||||
}
|
||||
recalculate_sizes();
|
||||
alerts_check_session(s);
|
||||
server_update_socket();
|
||||
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
@ -40,8 +40,8 @@ const struct cmd_entry cmd_command_prompt_entry = {
|
||||
.name = "command-prompt",
|
||||
.alias = NULL,
|
||||
|
||||
.args = { "1FkiI:Np:t:T:", 0, 1 },
|
||||
.usage = "[-1FkiN] [-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE
|
||||
.args = { "1bFkiI:Np:t:T:", 0, 1 },
|
||||
.usage = "[-1bFkiN] [-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE
|
||||
" [-T type] [template]",
|
||||
|
||||
.flags = CMD_CLIENT_TFLAG,
|
||||
@ -49,17 +49,20 @@ const struct cmd_entry cmd_command_prompt_entry = {
|
||||
};
|
||||
|
||||
struct cmd_command_prompt_cdata {
|
||||
int flags;
|
||||
enum prompt_type prompt_type;
|
||||
struct cmdq_item *item;
|
||||
struct cmd_parse_input pi;
|
||||
|
||||
char *inputs;
|
||||
char *next_input;
|
||||
int flags;
|
||||
enum prompt_type prompt_type;
|
||||
|
||||
char *prompts;
|
||||
char *next_prompt;
|
||||
char *inputs;
|
||||
char *next_input;
|
||||
|
||||
char *template;
|
||||
int idx;
|
||||
char *prompts;
|
||||
char *next_prompt;
|
||||
|
||||
char *template;
|
||||
int idx;
|
||||
};
|
||||
|
||||
static enum cmd_retval
|
||||
@ -72,21 +75,23 @@ cmd_command_prompt_exec(struct cmd *self, struct cmdq_item *item)
|
||||
struct cmd_command_prompt_cdata *cdata;
|
||||
char *prompt, *ptr, *input = NULL;
|
||||
size_t n;
|
||||
int wait = !args_has(args, 'b');
|
||||
|
||||
if (tc->prompt_string != NULL)
|
||||
return (CMD_RETURN_NORMAL);
|
||||
|
||||
cdata = xcalloc(1, sizeof *cdata);
|
||||
|
||||
cdata->inputs = NULL;
|
||||
cdata->next_input = NULL;
|
||||
|
||||
cdata->prompts = NULL;
|
||||
cdata->next_prompt = NULL;
|
||||
|
||||
cdata->template = NULL;
|
||||
cdata->idx = 1;
|
||||
|
||||
cmd_get_source(self, &cdata->pi.file, &cdata->pi.line);
|
||||
if (wait)
|
||||
cdata->pi.item = item;
|
||||
cdata->pi.c = tc;
|
||||
cmd_find_copy_state(&cdata->pi.fs, target);
|
||||
|
||||
if (wait)
|
||||
cdata->item = item;
|
||||
|
||||
if (args->argc != 0 && args_has(args, 'F'))
|
||||
cdata->template = format_single_from_target(item, args->argv[0]);
|
||||
else if (args->argc != 0)
|
||||
@ -140,7 +145,9 @@ cmd_command_prompt_exec(struct cmd *self, struct cmdq_item *item)
|
||||
cdata->flags, cdata->prompt_type);
|
||||
free(prompt);
|
||||
|
||||
return (CMD_RETURN_NORMAL);
|
||||
if (!wait)
|
||||
return (CMD_RETURN_NORMAL);
|
||||
return (CMD_RETURN_WAIT);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -150,12 +157,13 @@ cmd_command_prompt_callback(struct client *c, void *data, const char *s,
|
||||
struct cmd_command_prompt_cdata *cdata = data;
|
||||
char *new_template, *prompt, *ptr, *error;
|
||||
char *input = NULL;
|
||||
struct cmdq_item *item = cdata->item;
|
||||
enum cmd_parse_status status;
|
||||
|
||||
if (s == NULL)
|
||||
return (0);
|
||||
goto out;
|
||||
if (done && (cdata->flags & PROMPT_INCREMENTAL))
|
||||
return (0);
|
||||
goto out;
|
||||
|
||||
new_template = cmd_template_replace(cdata->template, s, cdata->idx);
|
||||
if (done) {
|
||||
@ -177,7 +185,13 @@ cmd_command_prompt_callback(struct client *c, void *data, const char *s,
|
||||
return (1);
|
||||
}
|
||||
|
||||
status = cmd_parse_and_append(new_template, NULL, c, NULL, &error);
|
||||
if (item != NULL) {
|
||||
status = cmd_parse_and_insert(new_template, &cdata->pi, item,
|
||||
cmdq_get_state(item), &error);
|
||||
} else {
|
||||
status = cmd_parse_and_append(new_template, &cdata->pi, c, NULL,
|
||||
&error);
|
||||
}
|
||||
if (status == CMD_PARSE_ERROR) {
|
||||
cmdq_append(c, cmdq_get_error(error));
|
||||
free(error);
|
||||
@ -187,6 +201,10 @@ cmd_command_prompt_callback(struct client *c, void *data, const char *s,
|
||||
free(new_template);
|
||||
if (c->prompt_inputcb != cmd_command_prompt_callback)
|
||||
return (1);
|
||||
|
||||
out:
|
||||
if (item != NULL)
|
||||
cmdq_continue(item);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -75,7 +75,6 @@ cmd_confirm_before_exec(struct cmd *self, struct cmdq_item *item)
|
||||
cdata = xmalloc(sizeof *cdata);
|
||||
cdata->cmd = xstrdup(args->argv[0]);
|
||||
|
||||
memset(&cdata->pi, 0, sizeof cdata->pi);
|
||||
cmd_get_source(self, &cdata->pi.file, &cdata->pi.line);
|
||||
if (wait)
|
||||
cdata->pi.item = item;
|
||||
@ -88,8 +87,8 @@ cmd_confirm_before_exec(struct cmd *self, struct cmdq_item *item)
|
||||
status_prompt_set(tc, target, new_prompt, NULL,
|
||||
cmd_confirm_before_callback, cmd_confirm_before_free, cdata,
|
||||
PROMPT_SINGLE, PROMPT_TYPE_COMMAND);
|
||||
|
||||
free(new_prompt);
|
||||
|
||||
if (!wait)
|
||||
return (CMD_RETURN_NORMAL);
|
||||
return (CMD_RETURN_WAIT);
|
||||
@ -104,14 +103,16 @@ cmd_confirm_before_callback(struct client *c, void *data, const char *s,
|
||||
char *error;
|
||||
struct cmdq_item *item = cdata->item;
|
||||
enum cmd_parse_status status;
|
||||
int retcode = 1;
|
||||
|
||||
if (c->flags & CLIENT_DEAD)
|
||||
return (0);
|
||||
goto out;
|
||||
|
||||
if (s == NULL || *s == '\0')
|
||||
goto out;
|
||||
if (tolower((u_char)s[0]) != 'y' || s[1] != '\0')
|
||||
goto out;
|
||||
retcode = 0;
|
||||
|
||||
if (item != NULL) {
|
||||
status = cmd_parse_and_insert(cmd, &cdata->pi, item,
|
||||
@ -124,8 +125,12 @@ cmd_confirm_before_callback(struct client *c, void *data, const char *s,
|
||||
}
|
||||
|
||||
out:
|
||||
if (item != NULL)
|
||||
cmdq_continue(item);
|
||||
if (item != NULL) {
|
||||
if (cmdq_get_client(item) != NULL &&
|
||||
cmdq_get_client(item)->session == NULL)
|
||||
cmdq_get_client(item)->retval = retcode;
|
||||
cmdq_continue(item);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -50,8 +50,8 @@ const struct cmd_entry cmd_display_popup_entry = {
|
||||
.name = "display-popup",
|
||||
.alias = "popup",
|
||||
|
||||
.args = { "Cc:d:Eh:t:w:x:y:", 0, -1 },
|
||||
.usage = "[-CE] [-c target-client] [-d start-directory] [-h height] "
|
||||
.args = { "BCc:d:Eh:t:w:x:y:", 0, -1 },
|
||||
.usage = "[-BCE] [-c target-client] [-d start-directory] [-h height] "
|
||||
CMD_TARGET_PANE_USAGE " [-w width] "
|
||||
"[-x position] [-y position] [command]",
|
||||
|
||||
@ -390,6 +390,8 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item)
|
||||
flags |= POPUP_CLOSEEXITZERO;
|
||||
else if (args_has(args, 'E'))
|
||||
flags |= POPUP_CLOSEEXIT;
|
||||
if (args_has(args, 'B'))
|
||||
flags |= POPUP_NOBORDER;
|
||||
if (popup_display(flags, item, px, py, w, h, shellcmd, argc, argv, cwd,
|
||||
tc, s, NULL, NULL) != 0)
|
||||
return (CMD_RETURN_NORMAL);
|
||||
|
@ -186,7 +186,8 @@ out:
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_display_panes_draw(struct client *c, struct screen_redraw_ctx *ctx)
|
||||
cmd_display_panes_draw(struct client *c, __unused void *data,
|
||||
struct screen_redraw_ctx *ctx)
|
||||
{
|
||||
struct window *w = c->session->curw->window;
|
||||
struct window_pane *wp;
|
||||
@ -200,9 +201,9 @@ cmd_display_panes_draw(struct client *c, struct screen_redraw_ctx *ctx)
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_display_panes_free(struct client *c)
|
||||
cmd_display_panes_free(__unused struct client *c, void *data)
|
||||
{
|
||||
struct cmd_display_panes_data *cdata = c->overlay_data;
|
||||
struct cmd_display_panes_data *cdata = data;
|
||||
|
||||
if (cdata->item != NULL)
|
||||
cmdq_continue(cdata->item);
|
||||
@ -211,9 +212,9 @@ cmd_display_panes_free(struct client *c)
|
||||
}
|
||||
|
||||
static int
|
||||
cmd_display_panes_key(struct client *c, struct key_event *event)
|
||||
cmd_display_panes_key(struct client *c, void *data, struct key_event *event)
|
||||
{
|
||||
struct cmd_display_panes_data *cdata = c->overlay_data;
|
||||
struct cmd_display_panes_data *cdata = data;
|
||||
char *cmd, *expanded, *error;
|
||||
struct window *w = c->session->curw->window;
|
||||
struct window_pane *wp;
|
||||
|
@ -104,8 +104,6 @@ cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item)
|
||||
cdata->cmd_if = xstrdup(args->argv[1]);
|
||||
if (args->argc == 3)
|
||||
cdata->cmd_else = xstrdup(args->argv[2]);
|
||||
else
|
||||
cdata->cmd_else = NULL;
|
||||
|
||||
if (!args_has(args, 'b'))
|
||||
cdata->client = cmdq_get_client(item);
|
||||
@ -116,10 +114,7 @@ cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item)
|
||||
|
||||
if (!args_has(args, 'b'))
|
||||
cdata->item = item;
|
||||
else
|
||||
cdata->item = NULL;
|
||||
|
||||
memset(&cdata->input, 0, sizeof cdata->input);
|
||||
cmd_get_source(self, &file, &cdata->input.line);
|
||||
if (file != NULL)
|
||||
cdata->input.file = xstrdup(file);
|
||||
|
@ -329,18 +329,10 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
|
||||
proc_send(c->peer, MSG_READY, -1, NULL, 0);
|
||||
} else if (c->session != NULL)
|
||||
c->last_session = c->session;
|
||||
c->session = s;
|
||||
server_client_set_session(c, s);
|
||||
if (~cmdq_get_flags(item) & CMDQ_STATE_REPEAT)
|
||||
server_client_set_key_table(c, NULL);
|
||||
tty_update_client_offset(c);
|
||||
status_timer_start(c);
|
||||
notify_client("client-session-changed", c);
|
||||
session_update_activity(s, NULL);
|
||||
gettimeofday(&s->last_attached_time, NULL);
|
||||
server_redraw_client(c);
|
||||
}
|
||||
recalculate_sizes();
|
||||
server_update_socket();
|
||||
|
||||
/*
|
||||
* If there are still configuration file errors to display, put the new
|
||||
|
@ -121,7 +121,6 @@ cmd_run_shell_exec(struct cmd *self, struct cmdq_item *item)
|
||||
|
||||
cdata->shell = !args_has(args, 'C');
|
||||
if (!cdata->shell) {
|
||||
memset(&cdata->pi, 0, sizeof cdata->pi);
|
||||
cmd_get_source(self, &cdata->pi.file, &cdata->pi.line);
|
||||
if (wait)
|
||||
cdata->pi.item = item;
|
||||
|
@ -134,23 +134,9 @@ cmd_switch_client_exec(struct cmd *self, struct cmdq_item *item)
|
||||
if (!args_has(args, 'E'))
|
||||
environ_update(s->options, tc->environ, s->environ);
|
||||
|
||||
if (tc->session != NULL && tc->session != s)
|
||||
tc->last_session = tc->session;
|
||||
tc->session = s;
|
||||
server_client_set_session(tc, s);
|
||||
if (~cmdq_get_flags(item) & CMDQ_STATE_REPEAT)
|
||||
server_client_set_key_table(tc, NULL);
|
||||
tty_update_client_offset(tc);
|
||||
status_timer_start(tc);
|
||||
notify_client("client-session-changed", tc);
|
||||
session_update_activity(s, NULL);
|
||||
gettimeofday(&s->last_attached_time, NULL);
|
||||
|
||||
server_check_unattached();
|
||||
server_redraw_client(tc);
|
||||
s->curw->flags &= ~WINLINK_ALERTFLAGS;
|
||||
s->curw->window->latest = tc;
|
||||
recalculate_sizes();
|
||||
alerts_check_session(s);
|
||||
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
8
input.c
8
input.c
@ -1792,8 +1792,12 @@ input_csi_dispatch_sm_private(struct input_ctx *ictx)
|
||||
if (sctx->s->mode & MODE_FOCUSON)
|
||||
break;
|
||||
screen_write_mode_set(sctx, MODE_FOCUSON);
|
||||
if (wp != NULL)
|
||||
wp->flags |= PANE_FOCUSPUSH; /* force update */
|
||||
if (wp == NULL)
|
||||
break;
|
||||
if (wp->flags & PANE_FOCUSED)
|
||||
bufferevent_write(wp->event, "\033[I", 3);
|
||||
else
|
||||
bufferevent_write(wp->event, "\033[O", 3);
|
||||
break;
|
||||
case 1005:
|
||||
screen_write_mode_set(sctx, MODE_MOUSE_UTF8);
|
||||
|
32
job.c
32
job.c
@ -50,6 +50,7 @@ struct job {
|
||||
|
||||
char *cmd;
|
||||
pid_t pid;
|
||||
char tty[TTY_NAME_MAX];
|
||||
int status;
|
||||
|
||||
int fd;
|
||||
@ -79,7 +80,7 @@ job_run(const char *cmd, int argc, char **argv, struct session *s,
|
||||
const char *home;
|
||||
sigset_t set, oldset;
|
||||
struct winsize ws;
|
||||
char **argvp;
|
||||
char **argvp, tty[TTY_NAME_MAX];
|
||||
|
||||
/*
|
||||
* Do not set TERM during .tmux.conf, it is nice to be able to use
|
||||
@ -94,7 +95,7 @@ job_run(const char *cmd, int argc, char **argv, struct session *s,
|
||||
memset(&ws, 0, sizeof ws);
|
||||
ws.ws_col = sx;
|
||||
ws.ws_row = sy;
|
||||
pid = fdforkpty(ptm_fd, &master, NULL, NULL, &ws);
|
||||
pid = fdforkpty(ptm_fd, &master, tty, NULL, &ws);
|
||||
} else {
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, out) != 0)
|
||||
goto fail;
|
||||
@ -168,6 +169,7 @@ job_run(const char *cmd, int argc, char **argv, struct session *s,
|
||||
else
|
||||
job->cmd = cmd_stringify_argv(argc, argv);
|
||||
job->pid = pid;
|
||||
strlcpy(job->tty, tty, sizeof job->tty);
|
||||
job->status = 0;
|
||||
|
||||
LIST_INSERT_HEAD(&all_jobs, job, entry);
|
||||
@ -199,6 +201,32 @@ fail:
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Take job's file descriptor and free the job. */
|
||||
int
|
||||
job_transfer(struct job *job, pid_t *pid, char *tty, size_t ttylen)
|
||||
{
|
||||
int fd = job->fd;
|
||||
|
||||
log_debug("transfer job %p: %s", job, job->cmd);
|
||||
|
||||
if (pid != NULL)
|
||||
*pid = job->pid;
|
||||
if (tty != NULL)
|
||||
strlcpy(tty, job->tty, ttylen);
|
||||
|
||||
LIST_REMOVE(job, entry);
|
||||
free(job->cmd);
|
||||
|
||||
if (job->freecb != NULL && job->data != NULL)
|
||||
job->freecb(job->data);
|
||||
|
||||
if (job->event != NULL)
|
||||
bufferevent_free(job->event);
|
||||
|
||||
free(job);
|
||||
return (fd);
|
||||
}
|
||||
|
||||
/* Kill and free an individual job. */
|
||||
void
|
||||
job_free(struct job *job)
|
||||
|
57
menu.c
57
menu.c
@ -131,18 +131,33 @@ menu_free(struct menu *menu)
|
||||
free(menu);
|
||||
}
|
||||
|
||||
static struct screen *
|
||||
menu_mode_cb(struct client *c, __unused u_int *cx, __unused u_int *cy)
|
||||
struct screen *
|
||||
menu_mode_cb(__unused struct client *c, void *data, __unused u_int *cx,
|
||||
__unused u_int *cy)
|
||||
{
|
||||
struct menu_data *md = c->overlay_data;
|
||||
struct menu_data *md = data;
|
||||
|
||||
return (&md->s);
|
||||
}
|
||||
|
||||
static void
|
||||
menu_draw_cb(struct client *c, __unused struct screen_redraw_ctx *ctx0)
|
||||
int
|
||||
menu_check_cb(__unused struct client *c, void *data, u_int px, u_int py)
|
||||
{
|
||||
struct menu_data *md = c->overlay_data;
|
||||
struct menu_data *md = data;
|
||||
struct menu *menu = md->menu;
|
||||
|
||||
if (px < md->px || px > md->px + menu->width + 3)
|
||||
return (1);
|
||||
if (py < md->py || py > md->py + menu->count + 1)
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
menu_draw_cb(struct client *c, void *data,
|
||||
__unused struct screen_redraw_ctx *rctx)
|
||||
{
|
||||
struct menu_data *md = data;
|
||||
struct tty *tty = &c->tty;
|
||||
struct screen *s = &md->s;
|
||||
struct menu *menu = md->menu;
|
||||
@ -163,10 +178,10 @@ menu_draw_cb(struct client *c, __unused struct screen_redraw_ctx *ctx0)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
menu_free_cb(struct client *c)
|
||||
void
|
||||
menu_free_cb(__unused struct client *c, void *data)
|
||||
{
|
||||
struct menu_data *md = c->overlay_data;
|
||||
struct menu_data *md = data;
|
||||
|
||||
if (md->item != NULL)
|
||||
cmdq_continue(md->item);
|
||||
@ -179,10 +194,10 @@ menu_free_cb(struct client *c)
|
||||
free(md);
|
||||
}
|
||||
|
||||
static int
|
||||
menu_key_cb(struct client *c, struct key_event *event)
|
||||
int
|
||||
menu_key_cb(struct client *c, void *data, struct key_event *event)
|
||||
{
|
||||
struct menu_data *md = c->overlay_data;
|
||||
struct menu_data *md = data;
|
||||
struct menu *menu = md->menu;
|
||||
struct mouse_event *m = &event->m;
|
||||
u_int i;
|
||||
@ -342,8 +357,8 @@ chosen:
|
||||
return (1);
|
||||
}
|
||||
|
||||
int
|
||||
menu_display(struct menu *menu, int flags, struct cmdq_item *item, u_int px,
|
||||
struct menu_data *
|
||||
menu_prepare(struct menu *menu, int flags, struct cmdq_item *item, u_int px,
|
||||
u_int py, struct client *c, struct cmd_find_state *fs, menu_choice_cb cb,
|
||||
void *data)
|
||||
{
|
||||
@ -352,7 +367,7 @@ menu_display(struct menu *menu, int flags, struct cmdq_item *item, u_int px,
|
||||
const char *name;
|
||||
|
||||
if (c->tty.sx < menu->width + 4 || c->tty.sy < menu->count + 2)
|
||||
return (-1);
|
||||
return (NULL);
|
||||
if (px + menu->width + 4 > c->tty.sx)
|
||||
px = c->tty.sx - menu->width - 4;
|
||||
if (py + menu->count + 2 > c->tty.sy)
|
||||
@ -388,7 +403,19 @@ menu_display(struct menu *menu, int flags, struct cmdq_item *item, u_int px,
|
||||
|
||||
md->cb = cb;
|
||||
md->data = data;
|
||||
return (md);
|
||||
}
|
||||
|
||||
int
|
||||
menu_display(struct menu *menu, int flags, struct cmdq_item *item, u_int px,
|
||||
u_int py, struct client *c, struct cmd_find_state *fs, menu_choice_cb cb,
|
||||
void *data)
|
||||
{
|
||||
struct menu_data *md;
|
||||
|
||||
md = menu_prepare(menu, flags, item, px, py, c, fs, cb, data);
|
||||
if (md == NULL)
|
||||
return (-1);
|
||||
server_client_set_overlay(c, 0, NULL, menu_mode_cb, menu_draw_cb,
|
||||
menu_key_cb, menu_free_cb, NULL, md);
|
||||
return (0);
|
||||
|
305
popup.c
305
popup.c
@ -39,6 +39,10 @@ struct popup_data {
|
||||
popup_close_cb cb;
|
||||
void *arg;
|
||||
|
||||
struct menu *menu;
|
||||
struct menu_data *md;
|
||||
int close;
|
||||
|
||||
/* Current position and size. */
|
||||
u_int px;
|
||||
u_int py;
|
||||
@ -66,6 +70,28 @@ struct popup_editor {
|
||||
void *arg;
|
||||
};
|
||||
|
||||
static const struct menu_item popup_menu_items[] = {
|
||||
{ "Close", 'q', NULL },
|
||||
{ "#{?buffer_name,Paste #[underscore]#{buffer_name},}", 'p', NULL },
|
||||
{ "", KEYC_NONE, NULL },
|
||||
{ "Fill Space", 'F', NULL },
|
||||
{ "Centre", 'C', NULL },
|
||||
{ "", KEYC_NONE, NULL },
|
||||
{ "To Horizontal Pane", 'h', NULL },
|
||||
{ "To Vertical Pane", 'v', NULL },
|
||||
|
||||
{ NULL, KEYC_NONE, NULL }
|
||||
};
|
||||
|
||||
static const struct menu_item popup_internal_menu_items[] = {
|
||||
{ "Close", 'q', NULL },
|
||||
{ "", KEYC_NONE, NULL },
|
||||
{ "Fill Space", 'F', NULL },
|
||||
{ "Centre", 'C', NULL },
|
||||
|
||||
{ NULL, KEYC_NONE, NULL }
|
||||
};
|
||||
|
||||
static void
|
||||
popup_redraw_cb(const struct tty_ctx *ttyctx)
|
||||
{
|
||||
@ -90,8 +116,13 @@ popup_set_client_cb(struct tty_ctx *ttyctx, struct client *c)
|
||||
ttyctx->wsx = c->tty.sx;
|
||||
ttyctx->wsy = c->tty.sy;
|
||||
|
||||
ttyctx->xoff = ttyctx->rxoff = pd->px + 1;
|
||||
ttyctx->yoff = ttyctx->ryoff = pd->py + 1;
|
||||
if (pd->flags & POPUP_NOBORDER) {
|
||||
ttyctx->xoff = ttyctx->rxoff = pd->px;
|
||||
ttyctx->yoff = ttyctx->ryoff = pd->py;
|
||||
} else {
|
||||
ttyctx->xoff = ttyctx->rxoff = pd->px + 1;
|
||||
ttyctx->yoff = ttyctx->ryoff = pd->py + 1;
|
||||
}
|
||||
|
||||
return (1);
|
||||
}
|
||||
@ -108,20 +139,30 @@ popup_init_ctx_cb(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx)
|
||||
}
|
||||
|
||||
static struct screen *
|
||||
popup_mode_cb(struct client *c, u_int *cx, u_int *cy)
|
||||
popup_mode_cb(__unused struct client *c, void *data, u_int *cx, u_int *cy)
|
||||
{
|
||||
struct popup_data *pd = c->overlay_data;
|
||||
struct popup_data *pd = data;
|
||||
|
||||
*cx = pd->px + 1 + pd->s.cx;
|
||||
*cy = pd->py + 1 + pd->s.cy;
|
||||
if (pd->md != NULL)
|
||||
return (menu_mode_cb(c, pd->md, cx, cy));
|
||||
|
||||
if (pd->flags & POPUP_NOBORDER) {
|
||||
*cx = pd->px + pd->s.cx;
|
||||
*cy = pd->py + pd->s.cy;
|
||||
} else {
|
||||
*cx = pd->px + 1 + pd->s.cx;
|
||||
*cy = pd->py + 1 + pd->s.cy;
|
||||
}
|
||||
return (&pd->s);
|
||||
}
|
||||
|
||||
static int
|
||||
popup_check_cb(struct client *c, u_int px, u_int py)
|
||||
popup_check_cb(struct client *c, void *data, u_int px, u_int py)
|
||||
{
|
||||
struct popup_data *pd = c->overlay_data;
|
||||
struct popup_data *pd = data;
|
||||
|
||||
if (pd->md != NULL && menu_check_cb(c, pd->md, px, py) == 0)
|
||||
return (0);
|
||||
if (px < pd->px || px > pd->px + pd->sx - 1)
|
||||
return (1);
|
||||
if (py < pd->py || py > pd->py + pd->sy - 1)
|
||||
@ -130,9 +171,9 @@ popup_check_cb(struct client *c, u_int px, u_int py)
|
||||
}
|
||||
|
||||
static void
|
||||
popup_draw_cb(struct client *c, __unused struct screen_redraw_ctx *ctx0)
|
||||
popup_draw_cb(struct client *c, void *data, struct screen_redraw_ctx *rctx)
|
||||
{
|
||||
struct popup_data *pd = c->overlay_data;
|
||||
struct popup_data *pd = data;
|
||||
struct tty *tty = &c->tty;
|
||||
struct screen s;
|
||||
struct screen_write_ctx ctx;
|
||||
@ -144,8 +185,10 @@ popup_draw_cb(struct client *c, __unused struct screen_redraw_ctx *ctx0)
|
||||
screen_write_start(&ctx, &s);
|
||||
screen_write_clearscreen(&ctx, 8);
|
||||
|
||||
/* Skip drawing popup if the terminal is too small. */
|
||||
if (pd->sx > 2 && pd->sy > 2) {
|
||||
if (pd->flags & POPUP_NOBORDER) {
|
||||
screen_write_cursormove(&ctx, 0, 0, 0);
|
||||
screen_write_fast_copy(&ctx, &pd->s, 0, 0, pd->sx, pd->sy);
|
||||
} else if (pd->sx > 2 && pd->sy > 2) {
|
||||
screen_write_box(&ctx, pd->sx, pd->sy);
|
||||
screen_write_cursormove(&ctx, 1, 1, 0);
|
||||
screen_write_fast_copy(&ctx, &pd->s, 0, 0, pd->sx - 2,
|
||||
@ -157,18 +200,33 @@ popup_draw_cb(struct client *c, __unused struct screen_redraw_ctx *ctx0)
|
||||
gc.fg = pd->palette.fg;
|
||||
gc.bg = pd->palette.bg;
|
||||
|
||||
c->overlay_check = NULL;
|
||||
if (pd->md != NULL) {
|
||||
c->overlay_check = menu_check_cb;
|
||||
c->overlay_data = pd->md;
|
||||
} else {
|
||||
c->overlay_check = NULL;
|
||||
c->overlay_data = NULL;
|
||||
}
|
||||
for (i = 0; i < pd->sy; i++)
|
||||
tty_draw_line(tty, &s, 0, i, pd->sx, px, py + i, &gc, palette);
|
||||
if (pd->md != NULL) {
|
||||
c->overlay_check = NULL;
|
||||
c->overlay_data = NULL;
|
||||
menu_draw_cb(c, pd->md, rctx);
|
||||
}
|
||||
c->overlay_check = popup_check_cb;
|
||||
c->overlay_data = pd;
|
||||
}
|
||||
|
||||
static void
|
||||
popup_free_cb(struct client *c)
|
||||
popup_free_cb(struct client *c, void *data)
|
||||
{
|
||||
struct popup_data *pd = c->overlay_data;
|
||||
struct popup_data *pd = data;
|
||||
struct cmdq_item *item = pd->item;
|
||||
|
||||
if (pd->md != NULL)
|
||||
menu_free_cb(c, pd->md);
|
||||
|
||||
if (pd->cb != NULL)
|
||||
pd->cb(pd->status, pd->arg);
|
||||
|
||||
@ -186,17 +244,20 @@ popup_free_cb(struct client *c)
|
||||
|
||||
screen_free(&pd->s);
|
||||
colour_palette_free(&pd->palette);
|
||||
|
||||
free(pd);
|
||||
}
|
||||
|
||||
static void
|
||||
popup_resize_cb(struct client *c)
|
||||
popup_resize_cb(__unused struct client *c, void *data)
|
||||
{
|
||||
struct popup_data *pd = c->overlay_data;
|
||||
struct popup_data *pd = data;
|
||||
struct tty *tty = &c->tty;
|
||||
|
||||
if (pd == NULL)
|
||||
return;
|
||||
if (pd->md != NULL)
|
||||
menu_free_cb(c, pd->md);
|
||||
|
||||
/* Adjust position and size. */
|
||||
if (pd->psy > tty->sy)
|
||||
@ -217,13 +278,103 @@ popup_resize_cb(struct client *c)
|
||||
pd->px = pd->ppx;
|
||||
|
||||
/* Avoid zero size screens. */
|
||||
if (pd->sx > 2 && pd->sy > 2) {
|
||||
if (pd->flags & POPUP_NOBORDER) {
|
||||
screen_resize(&pd->s, pd->sx, pd->sy, 0);
|
||||
if (pd->job != NULL)
|
||||
job_resize(pd->job, pd->sx, pd->sy );
|
||||
} else if (pd->sx > 2 && pd->sy > 2) {
|
||||
screen_resize(&pd->s, pd->sx - 2, pd->sy - 2, 0);
|
||||
if (pd->job != NULL)
|
||||
job_resize(pd->job, pd->sx - 2, pd->sy - 2);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
popup_make_pane(struct popup_data *pd, enum layout_type type)
|
||||
{
|
||||
struct client *c = pd->c;
|
||||
struct session *s = c->session;
|
||||
struct window *w = s->curw->window;
|
||||
struct layout_cell *lc;
|
||||
struct window_pane *wp = w->active, *new_wp;
|
||||
u_int hlimit;
|
||||
const char *shell;
|
||||
|
||||
window_unzoom(w);
|
||||
|
||||
lc = layout_split_pane(wp, type, -1, 0);
|
||||
hlimit = options_get_number(s->options, "history-limit");
|
||||
new_wp = window_add_pane(wp->window, NULL, hlimit, 0);
|
||||
layout_assign_pane(lc, new_wp, 0);
|
||||
|
||||
new_wp->fd = job_transfer(pd->job, &new_wp->pid, new_wp->tty,
|
||||
sizeof new_wp->tty);
|
||||
pd->job = NULL;
|
||||
|
||||
screen_set_title(&pd->s, new_wp->base.title);
|
||||
screen_free(&new_wp->base);
|
||||
memcpy(&new_wp->base, &pd->s, sizeof wp->base);
|
||||
screen_resize(&new_wp->base, new_wp->sx, new_wp->sy, 1);
|
||||
screen_init(&pd->s, 1, 1, 0);
|
||||
|
||||
shell = options_get_string(s->options, "default-shell");
|
||||
if (!checkshell(shell))
|
||||
shell = _PATH_BSHELL;
|
||||
new_wp->shell = xstrdup(shell);
|
||||
|
||||
window_pane_set_event(new_wp);
|
||||
window_set_active_pane(w, new_wp, 1);
|
||||
new_wp->flags |= PANE_CHANGED;
|
||||
|
||||
pd->close = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
popup_menu_done(__unused struct menu *menu, __unused u_int choice,
|
||||
key_code key, void *data)
|
||||
{
|
||||
struct popup_data *pd = data;
|
||||
struct client *c = pd->c;
|
||||
struct paste_buffer *pb;
|
||||
const char *buf;
|
||||
size_t len;
|
||||
|
||||
pd->md = NULL;
|
||||
pd->menu = NULL;
|
||||
server_redraw_client(pd->c);
|
||||
|
||||
switch (key) {
|
||||
case 'p':
|
||||
pb = paste_get_top(NULL);
|
||||
if (pb != NULL) {
|
||||
buf = paste_buffer_data(pb, &len);
|
||||
bufferevent_write(job_get_event(pd->job), buf, len);
|
||||
}
|
||||
break;
|
||||
case 'F':
|
||||
pd->sx = c->tty.sx;
|
||||
pd->sy = c->tty.sy;
|
||||
pd->px = 0;
|
||||
pd->py = 0;
|
||||
server_redraw_client(c);
|
||||
break;
|
||||
case 'C':
|
||||
pd->px = c->tty.sx / 2 - pd->sx / 2;
|
||||
pd->py = c->tty.sy / 2 - pd->sy / 2;
|
||||
server_redraw_client(c);
|
||||
break;
|
||||
case 'h':
|
||||
popup_make_pane(pd, LAYOUT_LEFTRIGHT);
|
||||
break;
|
||||
case 'v':
|
||||
popup_make_pane(pd, LAYOUT_TOPBOTTOM);
|
||||
break;
|
||||
case 'q':
|
||||
pd->close = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
popup_handle_drag(struct client *c, struct popup_data *pd,
|
||||
struct mouse_event *m)
|
||||
@ -253,29 +404,55 @@ popup_handle_drag(struct client *c, struct popup_data *pd,
|
||||
pd->ppy = py;
|
||||
server_redraw_client(c);
|
||||
} else if (pd->dragging == SIZE) {
|
||||
if (m->x < pd->px + 3)
|
||||
return;
|
||||
if (m->y < pd->py + 3)
|
||||
return;
|
||||
if (pd->flags & POPUP_NOBORDER) {
|
||||
if (m->x < pd->px + 1)
|
||||
return;
|
||||
if (m->y < pd->py + 1)
|
||||
return;
|
||||
} else {
|
||||
if (m->x < pd->px + 3)
|
||||
return;
|
||||
if (m->y < pd->py + 3)
|
||||
return;
|
||||
}
|
||||
pd->sx = m->x - pd->px;
|
||||
pd->sy = m->y - pd->py;
|
||||
pd->psx = pd->sx;
|
||||
pd->psy = pd->sy;
|
||||
|
||||
screen_resize(&pd->s, pd->sx - 2, pd->sy - 2, 0);
|
||||
if (pd->job != NULL)
|
||||
job_resize(pd->job, pd->sx - 2, pd->sy - 2);
|
||||
if (pd->flags & POPUP_NOBORDER) {
|
||||
screen_resize(&pd->s, pd->sx, pd->sy, 0);
|
||||
if (pd->job != NULL)
|
||||
job_resize(pd->job, pd->sx, pd->sy);
|
||||
} else {
|
||||
screen_resize(&pd->s, pd->sx - 2, pd->sy - 2, 0);
|
||||
if (pd->job != NULL)
|
||||
job_resize(pd->job, pd->sx - 2, pd->sy - 2);
|
||||
}
|
||||
server_redraw_client(c);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
popup_key_cb(struct client *c, struct key_event *event)
|
||||
popup_key_cb(struct client *c, void *data, struct key_event *event)
|
||||
{
|
||||
struct popup_data *pd = c->overlay_data;
|
||||
struct popup_data *pd = data;
|
||||
struct mouse_event *m = &event->m;
|
||||
const char *buf;
|
||||
size_t len;
|
||||
u_int px, py, x;
|
||||
|
||||
if (pd->md != NULL) {
|
||||
if (menu_key_cb(c, pd->md, event) == 1) {
|
||||
pd->md = NULL;
|
||||
pd->menu = NULL;
|
||||
if (pd->close)
|
||||
server_client_clear_overlay(c);
|
||||
else
|
||||
server_redraw_client(c);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (KEYC_IS_MOUSE(event->key)) {
|
||||
if (pd->dragging != OFF) {
|
||||
@ -286,15 +463,24 @@ popup_key_cb(struct client *c, struct key_event *event)
|
||||
m->x > pd->px + pd->sx - 1 ||
|
||||
m->y < pd->py ||
|
||||
m->y > pd->py + pd->sy - 1) {
|
||||
if (MOUSE_BUTTONS (m->b) == 1)
|
||||
return (1);
|
||||
if (MOUSE_BUTTONS(m->b) == 2)
|
||||
goto menu;
|
||||
return (0);
|
||||
}
|
||||
if ((m->b & MOUSE_MASK_META) ||
|
||||
m->x == pd->px ||
|
||||
if ((~pd->flags & POPUP_NOBORDER) &&
|
||||
(~m->b & MOUSE_MASK_META) &&
|
||||
MOUSE_BUTTONS(m->b) == 2 &&
|
||||
(m->x == pd->px ||
|
||||
m->x == pd->px + pd->sx - 1 ||
|
||||
m->y == pd->py ||
|
||||
m->y == pd->py + pd->sy - 1) {
|
||||
m->y == pd->py + pd->sy - 1))
|
||||
goto menu;
|
||||
if ((m->b & MOUSE_MASK_META) ||
|
||||
((~pd->flags & POPUP_NOBORDER) &&
|
||||
(m->x == pd->px ||
|
||||
m->x == pd->px + pd->sx - 1 ||
|
||||
m->y == pd->py ||
|
||||
m->y == pd->py + pd->sy - 1))) {
|
||||
if (!MOUSE_DRAG(m->b))
|
||||
goto out;
|
||||
if (MOUSE_BUTTONS(m->lb) == 0)
|
||||
@ -306,7 +492,6 @@ popup_key_cb(struct client *c, struct key_event *event)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if ((((pd->flags & (POPUP_CLOSEEXIT|POPUP_CLOSEEXITZERO)) == 0) ||
|
||||
pd->job == NULL) &&
|
||||
(event->key == '\033' || event->key == '\003'))
|
||||
@ -314,8 +499,14 @@ popup_key_cb(struct client *c, struct key_event *event)
|
||||
if (pd->job != NULL) {
|
||||
if (KEYC_IS_MOUSE(event->key)) {
|
||||
/* Must be inside, checked already. */
|
||||
if (!input_key_get_mouse(&pd->s, m, m->x - pd->px - 1,
|
||||
m->y - pd->py - 1, &buf, &len))
|
||||
if (pd->flags & POPUP_NOBORDER) {
|
||||
px = m->x - pd->px;
|
||||
py = m->y - pd->py;
|
||||
} else {
|
||||
px = m->x - pd->px - 1;
|
||||
py = m->y - pd->py - 1;
|
||||
}
|
||||
if (!input_key_get_mouse(&pd->s, m, px, py, &buf, &len))
|
||||
return (0);
|
||||
bufferevent_write(job_get_event(pd->job), buf, len);
|
||||
return (0);
|
||||
@ -324,6 +515,21 @@ popup_key_cb(struct client *c, struct key_event *event)
|
||||
}
|
||||
return (0);
|
||||
|
||||
menu:
|
||||
pd->menu = menu_create("");
|
||||
if (pd->flags & POPUP_INTERNAL) {
|
||||
menu_add_items(pd->menu, popup_internal_menu_items, NULL, NULL,
|
||||
NULL);
|
||||
} else
|
||||
menu_add_items(pd->menu, popup_menu_items, NULL, NULL, NULL);
|
||||
if (m->x >= (pd->menu->width + 4) / 2)
|
||||
x = m->x - (pd->menu->width + 4) / 2;
|
||||
else
|
||||
x = 0;
|
||||
pd->md = menu_prepare(pd->menu, 0, NULL, x, m->y, c, NULL,
|
||||
popup_menu_done, pd);
|
||||
c->flags |= CLIENT_REDRAWOVERLAY;
|
||||
|
||||
out:
|
||||
pd->lx = m->x;
|
||||
pd->ly = m->y;
|
||||
@ -344,9 +550,16 @@ popup_job_update_cb(struct job *job)
|
||||
if (size == 0)
|
||||
return;
|
||||
|
||||
c->overlay_check = NULL;
|
||||
if (pd->md != NULL) {
|
||||
c->overlay_check = menu_check_cb;
|
||||
c->overlay_data = pd->md;
|
||||
} else {
|
||||
c->overlay_check = NULL;
|
||||
c->overlay_data = NULL;
|
||||
}
|
||||
input_parse_screen(pd->ictx, s, popup_init_ctx_cb, pd, data, size);
|
||||
c->overlay_check = popup_check_cb;
|
||||
c->overlay_data = pd;
|
||||
|
||||
evbuffer_drain(evb, size);
|
||||
}
|
||||
@ -377,9 +590,19 @@ popup_display(int flags, struct cmdq_item *item, u_int px, u_int py, u_int sx,
|
||||
struct client *c, struct session *s, popup_close_cb cb, void *arg)
|
||||
{
|
||||
struct popup_data *pd;
|
||||
u_int jx, jy;
|
||||
|
||||
if (sx < 3 || sy < 3)
|
||||
return (-1);
|
||||
if (flags & POPUP_NOBORDER) {
|
||||
if (sx < 1 || sy < 1)
|
||||
return (-1);
|
||||
jx = sx;
|
||||
jy = sy;
|
||||
} else {
|
||||
if (sx < 3 || sy < 3)
|
||||
return (-1);
|
||||
jx = sx - 2;
|
||||
jy = sy - 2;
|
||||
}
|
||||
if (c->tty.sx < sx || c->tty.sy < sy)
|
||||
return (-1);
|
||||
|
||||
@ -410,7 +633,7 @@ popup_display(int flags, struct cmdq_item *item, u_int px, u_int py, u_int sx,
|
||||
|
||||
pd->job = job_run(shellcmd, argc, argv, s, cwd,
|
||||
popup_job_update_cb, popup_job_complete_cb, NULL, pd,
|
||||
JOB_NOWAIT|JOB_PTY|JOB_KEEPWRITE, pd->sx - 2, pd->sy - 2);
|
||||
JOB_NOWAIT|JOB_PTY|JOB_KEEPWRITE, jx, jy);
|
||||
pd->ictx = input_init(NULL, job_get_event(pd->job), &pd->palette);
|
||||
|
||||
server_client_set_overlay(c, 0, popup_check_cb, popup_mode_cb,
|
||||
@ -497,8 +720,8 @@ popup_editor(struct client *c, const char *buf, size_t len,
|
||||
py = (c->tty.sy / 2) - (sy / 2);
|
||||
|
||||
xasprintf(&cmd, "%s %s", editor, path);
|
||||
if (popup_display(POPUP_CLOSEEXIT, NULL, px, py, sx, sy, cmd, 0, NULL,
|
||||
_PATH_TMP, c, NULL, popup_editor_close_cb, pe) != 0) {
|
||||
if (popup_display(POPUP_INTERNAL|POPUP_CLOSEEXIT, NULL, px, py, sx, sy,
|
||||
cmd, 0, NULL, _PATH_TMP, c, NULL, popup_editor_close_cb, pe) != 0) {
|
||||
popup_editor_free(pe);
|
||||
free(cmd);
|
||||
return (-1);
|
||||
|
@ -624,7 +624,7 @@ screen_redraw_screen(struct client *c)
|
||||
}
|
||||
if (c->overlay_draw != NULL && (flags & CLIENT_REDRAWOVERLAY)) {
|
||||
log_debug("%s: redrawing overlay", c->name);
|
||||
c->overlay_draw(c, &ctx);
|
||||
c->overlay_draw(c, c->overlay_data, &ctx);
|
||||
}
|
||||
|
||||
tty_reset(&c->tty);
|
||||
@ -690,7 +690,8 @@ screen_redraw_draw_borders_cell(struct screen_redraw_ctx *ctx, u_int i, u_int j)
|
||||
struct grid_cell gc;
|
||||
const struct grid_cell *tmp;
|
||||
|
||||
if (c->overlay_check != NULL && !c->overlay_check(c, x, y))
|
||||
if (c->overlay_check != NULL &&
|
||||
!c->overlay_check(c, c->overlay_data, x, y))
|
||||
return;
|
||||
|
||||
cell_type = screen_redraw_check_cell(c, x, y, pane_status, &wp);
|
||||
|
104
server-client.c
104
server-client.c
@ -30,7 +30,6 @@
|
||||
#include "tmux.h"
|
||||
|
||||
static void server_client_free(int, short, void *);
|
||||
static void server_client_check_pane_focus(struct window_pane *);
|
||||
static void server_client_check_pane_resize(struct window_pane *);
|
||||
static void server_client_check_pane_buffer(struct window_pane *);
|
||||
static void server_client_check_window_resize(struct window *);
|
||||
@ -132,7 +131,7 @@ server_client_clear_overlay(struct client *c)
|
||||
evtimer_del(&c->overlay_timer);
|
||||
|
||||
if (c->overlay_free != NULL)
|
||||
c->overlay_free(c);
|
||||
c->overlay_free(c, c->overlay_data);
|
||||
|
||||
c->overlay_check = NULL;
|
||||
c->overlay_mode = NULL;
|
||||
@ -298,9 +297,8 @@ server_client_attached_lost(struct client *c)
|
||||
s = loop->session;
|
||||
if (loop == c || s == NULL || s->curw->window != w)
|
||||
continue;
|
||||
if (found == NULL ||
|
||||
timercmp(&loop->activity_time, &found->activity_time,
|
||||
>))
|
||||
if (found == NULL || timercmp(&loop->activity_time,
|
||||
&found->activity_time, >))
|
||||
found = loop;
|
||||
}
|
||||
if (found != NULL)
|
||||
@ -308,6 +306,40 @@ server_client_attached_lost(struct client *c)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Set client session. */
|
||||
void
|
||||
server_client_set_session(struct client *c, struct session *s)
|
||||
{
|
||||
struct session *old = c->session;
|
||||
|
||||
if (s != NULL && c->session != NULL && c->session != s)
|
||||
c->last_session = c->session;
|
||||
else if (s == NULL)
|
||||
c->last_session = NULL;
|
||||
c->session = s;
|
||||
c->flags |= CLIENT_FOCUSED;
|
||||
recalculate_sizes();
|
||||
|
||||
if (old != NULL && old->curw != NULL)
|
||||
window_update_focus(old->curw->window);
|
||||
if (s != NULL) {
|
||||
window_update_focus(s->curw->window);
|
||||
session_update_activity(s, NULL);
|
||||
gettimeofday(&s->last_attached_time, NULL);
|
||||
s->curw->flags &= ~WINLINK_ALERTFLAGS;
|
||||
s->curw->window->latest = c;
|
||||
alerts_check_session(s);
|
||||
tty_update_client_offset(c);
|
||||
status_timer_start(c);
|
||||
notify_client("client-session-changed", c);
|
||||
server_redraw_client(c);
|
||||
}
|
||||
|
||||
server_check_unattached();
|
||||
server_update_socket();
|
||||
}
|
||||
|
||||
/* Lost a client. */
|
||||
void
|
||||
server_client_lost(struct client *c)
|
||||
@ -1355,7 +1387,7 @@ server_client_handle_key(struct client *c, struct key_event *event)
|
||||
status_message_clear(c);
|
||||
}
|
||||
if (c->overlay_key != NULL) {
|
||||
switch (c->overlay_key(c, event)) {
|
||||
switch (c->overlay_key(c, c->overlay_data, event)) {
|
||||
case 0:
|
||||
return (0);
|
||||
case 1:
|
||||
@ -1386,7 +1418,6 @@ server_client_loop(void)
|
||||
struct client *c;
|
||||
struct window *w;
|
||||
struct window_pane *wp;
|
||||
int focus;
|
||||
|
||||
/* Check for window resize. This is done before redrawing. */
|
||||
RB_FOREACH(w, windows, &windows)
|
||||
@ -1404,14 +1435,11 @@ server_client_loop(void)
|
||||
|
||||
/*
|
||||
* Any windows will have been redrawn as part of clients, so clear
|
||||
* their flags now. Also check pane focus and resize.
|
||||
* their flags now.
|
||||
*/
|
||||
focus = options_get_number(global_options, "focus-events");
|
||||
RB_FOREACH(w, windows, &windows) {
|
||||
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||
if (wp->fd != -1) {
|
||||
if (focus)
|
||||
server_client_check_pane_focus(wp);
|
||||
server_client_check_pane_resize(wp);
|
||||
server_client_check_pane_buffer(wp);
|
||||
}
|
||||
@ -1612,54 +1640,6 @@ out:
|
||||
bufferevent_enable(wp->event, EV_READ);
|
||||
}
|
||||
|
||||
/* Check whether pane should be focused. */
|
||||
static void
|
||||
server_client_check_pane_focus(struct window_pane *wp)
|
||||
{
|
||||
struct client *c;
|
||||
int push;
|
||||
|
||||
/* Do we need to push the focus state? */
|
||||
push = wp->flags & PANE_FOCUSPUSH;
|
||||
wp->flags &= ~PANE_FOCUSPUSH;
|
||||
|
||||
/* If we're not the active pane in our window, we're not focused. */
|
||||
if (wp->window->active != wp)
|
||||
goto not_focused;
|
||||
|
||||
/*
|
||||
* If our window is the current window in any focused clients with an
|
||||
* attached session, we're focused.
|
||||
*/
|
||||
TAILQ_FOREACH(c, &clients, entry) {
|
||||
if (c->session == NULL || !(c->flags & CLIENT_FOCUSED))
|
||||
continue;
|
||||
if (c->session->attached == 0)
|
||||
continue;
|
||||
|
||||
if (c->session->curw->window == wp->window)
|
||||
goto focused;
|
||||
}
|
||||
|
||||
not_focused:
|
||||
if (push || (wp->flags & PANE_FOCUSED)) {
|
||||
if (wp->base.mode & MODE_FOCUSON)
|
||||
bufferevent_write(wp->event, "\033[O", 3);
|
||||
notify_pane("pane-focus-out", wp);
|
||||
}
|
||||
wp->flags &= ~PANE_FOCUSED;
|
||||
return;
|
||||
|
||||
focused:
|
||||
if (push || !(wp->flags & PANE_FOCUSED)) {
|
||||
if (wp->base.mode & MODE_FOCUSON)
|
||||
bufferevent_write(wp->event, "\033[I", 3);
|
||||
notify_pane("pane-focus-in", wp);
|
||||
session_update_activity(c->session, NULL);
|
||||
}
|
||||
wp->flags |= PANE_FOCUSED;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
@ -1690,7 +1670,7 @@ server_client_reset_state(struct client *c)
|
||||
/* Get mode from overlay if any, else from screen. */
|
||||
if (c->overlay_draw != NULL) {
|
||||
if (c->overlay_mode != NULL)
|
||||
s = c->overlay_mode(c, &cx, &cy);
|
||||
s = c->overlay_mode(c, c->overlay_data, &cx, &cy);
|
||||
} else
|
||||
s = wp->screen;
|
||||
if (s != NULL)
|
||||
@ -2067,7 +2047,7 @@ server_client_dispatch(struct imsg *imsg, void *arg)
|
||||
if (c->overlay_resize == NULL)
|
||||
server_client_clear_overlay(c);
|
||||
else
|
||||
c->overlay_resize(c);
|
||||
c->overlay_resize(c, c->overlay_data);
|
||||
server_redraw_client(c);
|
||||
if (c->session != NULL)
|
||||
notify_client("client-resized", c);
|
||||
@ -2075,7 +2055,7 @@ server_client_dispatch(struct imsg *imsg, void *arg)
|
||||
case MSG_EXITING:
|
||||
if (datalen != 0)
|
||||
fatalx("bad MSG_EXITING size");
|
||||
c->session = NULL;
|
||||
server_client_set_session(c, NULL);
|
||||
tty_close(&c->tty);
|
||||
proc_send(c->peer, MSG_EXITED, -1, NULL, 0);
|
||||
break;
|
||||
|
16
server-fn.c
16
server-fn.c
@ -446,21 +446,9 @@ server_destroy_session(struct session *s)
|
||||
TAILQ_FOREACH(c, &clients, entry) {
|
||||
if (c->session != s)
|
||||
continue;
|
||||
if (s_new == NULL) {
|
||||
c->session = NULL;
|
||||
server_client_set_session(c, NULL);
|
||||
if (s_new == NULL)
|
||||
c->flags |= CLIENT_EXIT;
|
||||
} else {
|
||||
c->last_session = NULL;
|
||||
c->session = s_new;
|
||||
server_client_set_key_table(c, NULL);
|
||||
tty_update_client_offset(c);
|
||||
status_timer_start(c);
|
||||
notify_client("client-session-changed", c);
|
||||
session_update_activity(s_new, NULL);
|
||||
gettimeofday(&s_new->last_attached_time, NULL);
|
||||
server_redraw_client(c);
|
||||
alerts_check_session(s_new);
|
||||
}
|
||||
}
|
||||
recalculate_sizes();
|
||||
}
|
||||
|
@ -487,6 +487,8 @@ session_last(struct session *s)
|
||||
int
|
||||
session_set_current(struct session *s, struct winlink *wl)
|
||||
{
|
||||
struct winlink *old = s->curw;
|
||||
|
||||
if (wl == NULL)
|
||||
return (-1);
|
||||
if (wl == s->curw)
|
||||
@ -495,6 +497,10 @@ session_set_current(struct session *s, struct winlink *wl)
|
||||
winlink_stack_remove(&s->lastw, wl);
|
||||
winlink_stack_push(&s->lastw, s->curw);
|
||||
s->curw = wl;
|
||||
if (options_get_number(global_options, "focus-events")) {
|
||||
window_update_focus(old->window);
|
||||
window_update_focus(wl->window);
|
||||
}
|
||||
winlink_clear_flags(wl);
|
||||
window_update_activity(wl->window);
|
||||
tty_update_window_offset(wl->window);
|
||||
|
114
tmux-protocol.h
Normal file
114
tmux-protocol.h
Normal file
@ -0,0 +1,114 @@
|
||||
/* $OpenBSD$ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2021 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef TMUX_PROTOCOL_H
|
||||
#define TMUX_PROTOCOL_H
|
||||
|
||||
/* Protocol version. */
|
||||
#define PROTOCOL_VERSION 8
|
||||
|
||||
/* Message types. */
|
||||
enum msgtype {
|
||||
MSG_VERSION = 12,
|
||||
|
||||
MSG_IDENTIFY_FLAGS = 100,
|
||||
MSG_IDENTIFY_TERM,
|
||||
MSG_IDENTIFY_TTYNAME,
|
||||
MSG_IDENTIFY_OLDCWD, /* unused */
|
||||
MSG_IDENTIFY_STDIN,
|
||||
MSG_IDENTIFY_ENVIRON,
|
||||
MSG_IDENTIFY_DONE,
|
||||
MSG_IDENTIFY_CLIENTPID,
|
||||
MSG_IDENTIFY_CWD,
|
||||
MSG_IDENTIFY_FEATURES,
|
||||
MSG_IDENTIFY_STDOUT,
|
||||
MSG_IDENTIFY_LONGFLAGS,
|
||||
MSG_IDENTIFY_TERMINFO,
|
||||
|
||||
MSG_COMMAND = 200,
|
||||
MSG_DETACH,
|
||||
MSG_DETACHKILL,
|
||||
MSG_EXIT,
|
||||
MSG_EXITED,
|
||||
MSG_EXITING,
|
||||
MSG_LOCK,
|
||||
MSG_READY,
|
||||
MSG_RESIZE,
|
||||
MSG_SHELL,
|
||||
MSG_SHUTDOWN,
|
||||
MSG_OLDSTDERR, /* unused */
|
||||
MSG_OLDSTDIN, /* unused */
|
||||
MSG_OLDSTDOUT, /* unused */
|
||||
MSG_SUSPEND,
|
||||
MSG_UNLOCK,
|
||||
MSG_WAKEUP,
|
||||
MSG_EXEC,
|
||||
MSG_FLAGS,
|
||||
|
||||
MSG_READ_OPEN = 300,
|
||||
MSG_READ,
|
||||
MSG_READ_DONE,
|
||||
MSG_WRITE_OPEN,
|
||||
MSG_WRITE,
|
||||
MSG_WRITE_READY,
|
||||
MSG_WRITE_CLOSE
|
||||
};
|
||||
|
||||
/*
|
||||
* Message data.
|
||||
*
|
||||
* Don't forget to bump PROTOCOL_VERSION if any of these change!
|
||||
*/
|
||||
struct msg_command {
|
||||
int argc;
|
||||
}; /* followed by packed argv */
|
||||
|
||||
struct msg_read_open {
|
||||
int stream;
|
||||
int fd;
|
||||
}; /* followed by path */
|
||||
|
||||
struct msg_read_data {
|
||||
int stream;
|
||||
};
|
||||
|
||||
struct msg_read_done {
|
||||
int stream;
|
||||
int error;
|
||||
};
|
||||
|
||||
struct msg_write_open {
|
||||
int stream;
|
||||
int fd;
|
||||
int flags;
|
||||
}; /* followed by path */
|
||||
|
||||
struct msg_write_data {
|
||||
int stream;
|
||||
}; /* followed by data */
|
||||
|
||||
struct msg_write_ready {
|
||||
int stream;
|
||||
int error;
|
||||
};
|
||||
|
||||
struct msg_write_close {
|
||||
int stream;
|
||||
};
|
||||
|
||||
#endif /* TMUX_PROTOCOL_H */
|
14
tmux.1
14
tmux.1
@ -5414,7 +5414,7 @@ See
|
||||
for possible values for
|
||||
.Ar prompt-type .
|
||||
.It Xo Ic command-prompt
|
||||
.Op Fl 1FikN
|
||||
.Op Fl 1bFikN
|
||||
.Op Fl I Ar inputs
|
||||
.Op Fl p Ar prompts
|
||||
.Op Fl t Ar target-client
|
||||
@ -5517,6 +5517,11 @@ option:
|
||||
.It Li "Move cursor to start" Ta "0" Ta "C-a"
|
||||
.It Li "Transpose characters" Ta "" Ta "C-t"
|
||||
.El
|
||||
.Pp
|
||||
With
|
||||
.Fl b ,
|
||||
the prompt is shown in the background and the invoking client does not exit
|
||||
until it is dismissed.
|
||||
.It Xo Ic confirm-before
|
||||
.Op Fl b
|
||||
.Op Fl p Ar prompt
|
||||
@ -5537,7 +5542,8 @@ It may contain the special character sequences supported by the
|
||||
option.
|
||||
With
|
||||
.Fl b ,
|
||||
the prompt is shown in the background and the client.
|
||||
the prompt is shown in the background and the invoking client does not exit
|
||||
until it is dismissed.
|
||||
.It Xo Ic display-menu
|
||||
.Op Fl O
|
||||
.Op Fl c Ar target-client
|
||||
@ -5671,7 +5677,7 @@ lists the format variables and their values.
|
||||
forwards any input read from stdin to the empty pane given by
|
||||
.Ar target-pane .
|
||||
.It Xo Ic display-popup
|
||||
.Op Fl CE
|
||||
.Op Fl BCE
|
||||
.Op Fl c Ar target-client
|
||||
.Op Fl d Ar start-directory
|
||||
.Op Fl h Ar height
|
||||
@ -5711,6 +5717,8 @@ and
|
||||
give the width and height - both may be a percentage (followed by
|
||||
.Ql % ) .
|
||||
If omitted, half of the terminal size is used.
|
||||
.Fl B
|
||||
does not surround the popup by a border.
|
||||
.Pp
|
||||
The
|
||||
.Fl C
|
||||
|
143
tmux.h
143
tmux.h
@ -32,6 +32,7 @@
|
||||
#endif
|
||||
|
||||
#include "compat.h"
|
||||
#include "tmux-protocol.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
extern char **environ;
|
||||
@ -51,6 +52,7 @@ struct format_job_tree;
|
||||
struct format_tree;
|
||||
struct input_ctx;
|
||||
struct job;
|
||||
struct menu_data;
|
||||
struct mode_tree_data;
|
||||
struct mouse_event;
|
||||
struct options;
|
||||
@ -61,13 +63,12 @@ struct screen_write_cline;
|
||||
struct screen_write_ctx;
|
||||
struct session;
|
||||
struct tty_ctx;
|
||||
struct tty_code;
|
||||
struct tty_key;
|
||||
struct tmuxpeer;
|
||||
struct tmuxproc;
|
||||
struct winlink;
|
||||
|
||||
/* Client-server protocol version. */
|
||||
#define PROTOCOL_VERSION 8
|
||||
|
||||
/* Default configuration files and socket paths. */
|
||||
#ifndef TMUX_CONF
|
||||
#define TMUX_CONF "/etc/tmux.conf:~/.tmux.conf"
|
||||
@ -505,95 +506,6 @@ enum tty_code_code {
|
||||
TTYC_XT
|
||||
};
|
||||
|
||||
/* Message codes. */
|
||||
enum msgtype {
|
||||
MSG_VERSION = 12,
|
||||
|
||||
MSG_IDENTIFY_FLAGS = 100,
|
||||
MSG_IDENTIFY_TERM,
|
||||
MSG_IDENTIFY_TTYNAME,
|
||||
MSG_IDENTIFY_OLDCWD, /* unused */
|
||||
MSG_IDENTIFY_STDIN,
|
||||
MSG_IDENTIFY_ENVIRON,
|
||||
MSG_IDENTIFY_DONE,
|
||||
MSG_IDENTIFY_CLIENTPID,
|
||||
MSG_IDENTIFY_CWD,
|
||||
MSG_IDENTIFY_FEATURES,
|
||||
MSG_IDENTIFY_STDOUT,
|
||||
MSG_IDENTIFY_LONGFLAGS,
|
||||
MSG_IDENTIFY_TERMINFO,
|
||||
|
||||
MSG_COMMAND = 200,
|
||||
MSG_DETACH,
|
||||
MSG_DETACHKILL,
|
||||
MSG_EXIT,
|
||||
MSG_EXITED,
|
||||
MSG_EXITING,
|
||||
MSG_LOCK,
|
||||
MSG_READY,
|
||||
MSG_RESIZE,
|
||||
MSG_SHELL,
|
||||
MSG_SHUTDOWN,
|
||||
MSG_OLDSTDERR, /* unused */
|
||||
MSG_OLDSTDIN, /* unused */
|
||||
MSG_OLDSTDOUT, /* unused */
|
||||
MSG_SUSPEND,
|
||||
MSG_UNLOCK,
|
||||
MSG_WAKEUP,
|
||||
MSG_EXEC,
|
||||
MSG_FLAGS,
|
||||
|
||||
MSG_READ_OPEN = 300,
|
||||
MSG_READ,
|
||||
MSG_READ_DONE,
|
||||
MSG_WRITE_OPEN,
|
||||
MSG_WRITE,
|
||||
MSG_WRITE_READY,
|
||||
MSG_WRITE_CLOSE
|
||||
};
|
||||
|
||||
/*
|
||||
* Message data.
|
||||
*
|
||||
* Don't forget to bump PROTOCOL_VERSION if any of these change!
|
||||
*/
|
||||
struct msg_command {
|
||||
int argc;
|
||||
}; /* followed by packed argv */
|
||||
|
||||
struct msg_read_open {
|
||||
int stream;
|
||||
int fd;
|
||||
}; /* followed by path */
|
||||
|
||||
struct msg_read_data {
|
||||
int stream;
|
||||
};
|
||||
|
||||
struct msg_read_done {
|
||||
int stream;
|
||||
int error;
|
||||
};
|
||||
|
||||
struct msg_write_open {
|
||||
int stream;
|
||||
int fd;
|
||||
int flags;
|
||||
}; /* followed by path */
|
||||
|
||||
struct msg_write_data {
|
||||
int stream;
|
||||
}; /* followed by data */
|
||||
|
||||
struct msg_write_ready {
|
||||
int stream;
|
||||
int error;
|
||||
};
|
||||
|
||||
struct msg_write_close {
|
||||
int stream;
|
||||
};
|
||||
|
||||
/* Character classes. */
|
||||
#define WHITESPACE " "
|
||||
|
||||
@ -1005,7 +917,7 @@ struct window_pane {
|
||||
#define PANE_FOCUSED 0x4
|
||||
/* 0x8 unused */
|
||||
/* 0x10 unused */
|
||||
#define PANE_FOCUSPUSH 0x20
|
||||
/* 0x20 unused */
|
||||
#define PANE_INPUTOFF 0x40
|
||||
#define PANE_CHANGED 0x80
|
||||
#define PANE_EXITED 0x100
|
||||
@ -1293,18 +1205,7 @@ struct key_event {
|
||||
struct mouse_event m;
|
||||
};
|
||||
|
||||
/* TTY information. */
|
||||
struct tty_key {
|
||||
char ch;
|
||||
key_code key;
|
||||
|
||||
struct tty_key *left;
|
||||
struct tty_key *right;
|
||||
|
||||
struct tty_key *next;
|
||||
};
|
||||
|
||||
struct tty_code;
|
||||
/* Terminal definition. */
|
||||
struct tty_term {
|
||||
char *name;
|
||||
struct tty *tty;
|
||||
@ -1326,6 +1227,7 @@ struct tty_term {
|
||||
};
|
||||
LIST_HEAD(tty_terms, tty_term);
|
||||
|
||||
/* Client terminal. */
|
||||
struct tty {
|
||||
struct client *client;
|
||||
struct event start_timer;
|
||||
@ -1394,7 +1296,7 @@ struct tty {
|
||||
struct tty_key *key_tree;
|
||||
};
|
||||
|
||||
/* TTY command context. */
|
||||
/* Terminal command context. */
|
||||
typedef void (*tty_ctx_redraw_cb)(const struct tty_ctx *);
|
||||
typedef int (*tty_ctx_set_client_cb)(struct tty_ctx *, struct client *);
|
||||
struct tty_ctx {
|
||||
@ -1635,12 +1537,14 @@ RB_HEAD(client_windows, client_window);
|
||||
/* Client connection. */
|
||||
typedef int (*prompt_input_cb)(struct client *, void *, const char *, int);
|
||||
typedef void (*prompt_free_cb)(void *);
|
||||
typedef int (*overlay_check_cb)(struct client *, u_int, u_int);
|
||||
typedef struct screen *(*overlay_mode_cb)(struct client *, u_int *, u_int *);
|
||||
typedef void (*overlay_draw_cb)(struct client *, struct screen_redraw_ctx *);
|
||||
typedef int (*overlay_key_cb)(struct client *, struct key_event *);
|
||||
typedef void (*overlay_free_cb)(struct client *);
|
||||
typedef void (*overlay_resize_cb)(struct client *);
|
||||
typedef int (*overlay_check_cb)(struct client *, void *, u_int, u_int);
|
||||
typedef struct screen *(*overlay_mode_cb)(struct client *, void *, u_int *,
|
||||
u_int *);
|
||||
typedef void (*overlay_draw_cb)(struct client *, void *,
|
||||
struct screen_redraw_ctx *);
|
||||
typedef int (*overlay_key_cb)(struct client *, void *, struct key_event *);
|
||||
typedef void (*overlay_free_cb)(struct client *, void *);
|
||||
typedef void (*overlay_resize_cb)(struct client *, void *);
|
||||
struct client {
|
||||
const char *name;
|
||||
struct tmuxpeer *peer;
|
||||
@ -2139,6 +2043,7 @@ struct job *job_run(const char *, int, char **, struct session *,
|
||||
const char *, job_update_cb, job_complete_cb, job_free_cb,
|
||||
void *, int, int, int);
|
||||
void job_free(struct job *);
|
||||
int job_transfer(struct job *, pid_t *, char *, size_t);
|
||||
void job_resize(struct job *, u_int, u_int);
|
||||
void job_check_died(pid_t, int);
|
||||
int job_get_status(struct job *);
|
||||
@ -2507,6 +2412,7 @@ int server_client_handle_key(struct client *, struct key_event *);
|
||||
struct client *server_client_create(int);
|
||||
int server_client_open(struct client *, char **);
|
||||
void server_client_unref(struct client *);
|
||||
void server_client_set_session(struct client *, struct session *);
|
||||
void server_client_lost(struct client *);
|
||||
void server_client_suspend(struct client *);
|
||||
void server_client_detach(struct client *, enum msgtype);
|
||||
@ -2827,6 +2733,8 @@ struct window_pane *window_find_string(struct window *, const char *);
|
||||
int window_has_pane(struct window *, struct window_pane *);
|
||||
int window_set_active_pane(struct window *, struct window_pane *,
|
||||
int);
|
||||
void window_update_focus(struct window *);
|
||||
void window_pane_update_focus(struct window_pane *);
|
||||
void window_redraw_active_switch(struct window *,
|
||||
struct window_pane *);
|
||||
struct window_pane *window_add_pane(struct window *, struct window_pane *,
|
||||
@ -3116,13 +3024,24 @@ void menu_add_item(struct menu *, const struct menu_item *,
|
||||
struct cmdq_item *, struct client *,
|
||||
struct cmd_find_state *);
|
||||
void menu_free(struct menu *);
|
||||
struct menu_data *menu_prepare(struct menu *, int, struct cmdq_item *, u_int,
|
||||
u_int, struct client *, struct cmd_find_state *,
|
||||
menu_choice_cb, void *);
|
||||
int menu_display(struct menu *, int, struct cmdq_item *, u_int,
|
||||
u_int, struct client *, struct cmd_find_state *,
|
||||
menu_choice_cb, void *);
|
||||
struct screen *menu_mode_cb(struct client *, void *, u_int *, u_int *);
|
||||
int menu_check_cb(struct client *, void *, u_int, u_int);
|
||||
void menu_draw_cb(struct client *, void *,
|
||||
struct screen_redraw_ctx *);
|
||||
void menu_free_cb(struct client *, void *);
|
||||
int menu_key_cb(struct client *, void *, struct key_event *);
|
||||
|
||||
/* popup.c */
|
||||
#define POPUP_CLOSEEXIT 0x1
|
||||
#define POPUP_CLOSEEXITZERO 0x2
|
||||
#define POPUP_NOBORDER 0x4
|
||||
#define POPUP_INTERNAL 0x8
|
||||
typedef void (*popup_close_cb)(int, void *);
|
||||
typedef void (*popup_finish_edit_cb)(char *, size_t, void *);
|
||||
int popup_display(int, struct cmdq_item *, u_int, u_int, u_int,
|
||||
|
17
tty-keys.c
17
tty-keys.c
@ -58,6 +58,17 @@ static int tty_keys_device_attributes(struct tty *, const char *, size_t,
|
||||
static int tty_keys_extended_device_attributes(struct tty *, const char *,
|
||||
size_t, size_t *);
|
||||
|
||||
/* A key tree entry. */
|
||||
struct tty_key {
|
||||
char ch;
|
||||
key_code key;
|
||||
|
||||
struct tty_key *left;
|
||||
struct tty_key *right;
|
||||
|
||||
struct tty_key *next;
|
||||
};
|
||||
|
||||
/* Default raw keys. */
|
||||
struct tty_default_key_raw {
|
||||
const char *string;
|
||||
@ -821,11 +832,13 @@ complete_key:
|
||||
|
||||
/* Check for focus events. */
|
||||
if (key == KEYC_FOCUS_OUT) {
|
||||
tty->client->flags &= ~CLIENT_FOCUSED;
|
||||
c->flags &= ~CLIENT_FOCUSED;
|
||||
window_update_focus(c->session->curw->window);
|
||||
notify_client("client-focus-out", c);
|
||||
} else if (key == KEYC_FOCUS_IN) {
|
||||
tty->client->flags |= CLIENT_FOCUSED;
|
||||
c->flags |= CLIENT_FOCUSED;
|
||||
notify_client("client-focus-in", c);
|
||||
window_update_focus(c->session->curw->window);
|
||||
}
|
||||
|
||||
/* Fire the key. */
|
||||
|
2
tty.c
2
tty.c
@ -1318,7 +1318,7 @@ tty_check_overlay(struct tty *tty, u_int px, u_int py)
|
||||
|
||||
if (c->overlay_check == NULL)
|
||||
return (1);
|
||||
return (c->overlay_check(c, px, py));
|
||||
return (c->overlay_check(c, c->overlay_data, px, py));
|
||||
}
|
||||
|
||||
void
|
||||
|
51
window.c
51
window.c
@ -465,6 +465,52 @@ window_has_pane(struct window *w, struct window_pane *wp)
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
window_update_focus(struct window *w)
|
||||
{
|
||||
if (w != NULL) {
|
||||
log_debug("%s: @%u", __func__, w->id);
|
||||
window_pane_update_focus(w->active);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
window_pane_update_focus(struct window_pane *wp)
|
||||
{
|
||||
struct client *c;
|
||||
int focused = 0;
|
||||
|
||||
if (wp != NULL) {
|
||||
if (wp != wp->window->active)
|
||||
focused = 0;
|
||||
else {
|
||||
TAILQ_FOREACH(c, &clients, entry) {
|
||||
if (c->session != NULL &&
|
||||
c->session->attached != 0 &&
|
||||
(c->flags & CLIENT_FOCUSED) &&
|
||||
c->session->curw->window == wp->window) {
|
||||
focused = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!focused && (wp->flags & PANE_FOCUSED)) {
|
||||
log_debug("%s: %%%u focus out", __func__, wp->id);
|
||||
if (wp->base.mode & MODE_FOCUSON)
|
||||
bufferevent_write(wp->event, "\033[O", 3);
|
||||
notify_pane("pane-focus-out", wp);
|
||||
wp->flags &= ~PANE_FOCUSED;
|
||||
} else if (focused && (~wp->flags & PANE_FOCUSED)) {
|
||||
log_debug("%s: %%%u focus in", __func__, wp->id);
|
||||
if (wp->base.mode & MODE_FOCUSON)
|
||||
bufferevent_write(wp->event, "\033[I", 3);
|
||||
notify_pane("pane-focus-in", wp);
|
||||
wp->flags |= PANE_FOCUSED;
|
||||
} else
|
||||
log_debug("%s: %%%u focus unchanged", __func__, wp->id);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
window_set_active_pane(struct window *w, struct window_pane *wp, int notify)
|
||||
{
|
||||
@ -478,6 +524,11 @@ window_set_active_pane(struct window *w, struct window_pane *wp, int notify)
|
||||
w->active->active_point = next_active_point++;
|
||||
w->active->flags |= PANE_CHANGED;
|
||||
|
||||
if (options_get_number(global_options, "focus-events")) {
|
||||
window_pane_update_focus(w->last);
|
||||
window_pane_update_focus(w->active);
|
||||
}
|
||||
|
||||
tty_update_window_offset(w);
|
||||
|
||||
if (notify)
|
||||
|
Loading…
Reference in New Issue
Block a user