diff options
-rw-r--r-- | cmd-find.c | 18 | ||||
-rw-r--r-- | cmd-queue.c | 6 | ||||
-rw-r--r-- | control-notify.c | 2 | ||||
-rw-r--r-- | notify.c | 73 | ||||
-rw-r--r-- | server.c | 1 | ||||
-rw-r--r-- | session.c | 6 | ||||
-rw-r--r-- | tmux.1 | 4 | ||||
-rw-r--r-- | tmux.h | 7 |
8 files changed, 82 insertions, 35 deletions
@@ -903,6 +903,23 @@ cmd_find_from_winlink(struct cmd_find_state *fs, struct session *s, return (0); } +/* Find state from a session and window. */ +int +cmd_find_from_session_window(struct cmd_find_state *fs, struct session *s, + struct window *w) +{ + cmd_find_clear_state(fs, NULL, 0); + + fs->s = s; + fs->w = w; + if (cmd_find_best_winlink_with_window(fs) != 0) + return (-1); + fs->wp = fs->w->active; + + cmd_find_log_state(__func__, fs); + return (0); +} + /* Find state from a window. */ int cmd_find_from_window(struct cmd_find_state *fs, struct window *w) @@ -914,6 +931,7 @@ cmd_find_from_window(struct cmd_find_state *fs, struct window *w) return (-1); if (cmd_find_best_winlink_with_window(fs) != 0) return (-1); + fs->wp = fs->w->active; cmd_find_log_state(__func__, fs); return (0); diff --git a/cmd-queue.c b/cmd-queue.c index bafff1d6..2012e871 100644 --- a/cmd-queue.c +++ b/cmd-queue.c @@ -248,10 +248,8 @@ cmdq_continue(struct cmd_q *cmdq) enum cmd_retval retval; int empty; - cmdq->references++; - notify_disable(); - log_debug("continuing cmdq %p: flags %#x (%p)", cmdq, cmdq->flags, c); + cmdq->references++; empty = TAILQ_EMPTY(&cmdq->queue); if (empty) @@ -296,9 +294,7 @@ empty: empty = 1; out: - notify_enable(); cmdq_free(cmdq); - return (empty); } diff --git a/control-notify.c b/control-notify.c index c28d0fc8..e544139b 100644 --- a/control-notify.c +++ b/control-notify.c @@ -196,7 +196,7 @@ control_notify_session_created(__unused struct session *s) } void -control_notify_session_close(__unused struct session *s) +control_notify_session_closed(__unused struct session *s) { struct client *c; @@ -33,6 +33,17 @@ enum notify_type { NOTIFY_SESSION_CLOSED }; +static const char *notify_hooks[] = { + "window-layout-changed", + NULL, /* "window-unlinked", */ + NULL, /* "window-linked", */ + "window-renamed", + NULL, /* "attached-session-changed", */ + "session-renamed", + NULL, /* "session-created", */ + NULL, /* "session-closed" */ +}; + struct notify_entry { enum notify_type type; @@ -44,23 +55,45 @@ struct notify_entry { }; TAILQ_HEAD(notify_queue, notify_entry); static struct notify_queue notify_queue = TAILQ_HEAD_INITIALIZER(notify_queue); -static int notify_enabled = 1; -static void notify_drain(void); static void notify_add(enum notify_type, struct client *, struct session *, struct window *); -void -notify_enable(void) +static void +notify_hook(struct notify_entry *ne) { - notify_enabled = 1; - notify_drain(); -} + const char *name; + struct cmd_find_state fs; + struct hook *hook; + struct cmd_q *hooks_cmdq; -void -notify_disable(void) -{ - notify_enabled = 0; + name = notify_hooks[ne->type]; + if (name == NULL) + return; + + cmd_find_clear_state(&fs, NULL, 0); + if (ne->session != NULL && ne->window != NULL) + cmd_find_from_session_window(&fs, ne->session, ne->window); + else if (ne->window != NULL) + cmd_find_from_window(&fs, ne->window); + else if (ne->session != NULL) + cmd_find_from_session(&fs, ne->session); + if (cmd_find_empty_state(&fs) || !cmd_find_valid_state(&fs)) + return; + + hook = hooks_find(fs.s->hooks, name); + if (hook == NULL) + return; + log_debug("notify hook %s", name); + + hooks_cmdq = cmdq_new(NULL); + hooks_cmdq->flags |= CMD_Q_NOHOOKS; + + cmd_find_copy_state(&hooks_cmdq->current, &fs); + hooks_cmdq->parent = NULL; + + cmdq_run(hooks_cmdq, hook->cmdlist, NULL); + cmdq_free(hooks_cmdq); } static void @@ -84,14 +117,11 @@ notify_add(enum notify_type type, struct client *c, struct session *s, w->references++; } -static void +void notify_drain(void) { struct notify_entry *ne, *ne1; - if (!notify_enabled) - return; - TAILQ_FOREACH_SAFE(ne, ¬ify_queue, entry, ne1) { switch (ne->type) { case NOTIFY_WINDOW_LAYOUT_CHANGED: @@ -116,9 +146,11 @@ notify_drain(void) control_notify_session_created(ne->session); break; case NOTIFY_SESSION_CLOSED: - control_notify_session_close(ne->session); + control_notify_session_closed(ne->session); break; } + TAILQ_REMOVE(¬ify_queue, ne, entry); + notify_hook(ne); if (ne->client != NULL) server_client_unref(ne->client); @@ -126,8 +158,6 @@ notify_drain(void) session_unref(ne->session); if (ne->window != NULL) window_remove_ref(ne->window); - - TAILQ_REMOVE(¬ify_queue, ne, entry); free(ne); } } @@ -137,13 +167,6 @@ notify_input(struct window_pane *wp, struct evbuffer *input) { struct client *c; - /* - * notify_input() is not queued and only does anything when - * notifications are enabled. - */ - if (!notify_enabled) - return; - TAILQ_FOREACH(c, &clients, entry) { if (c->flags & CLIENT_CONTROL) control_notify_input(c, wp, input); @@ -194,6 +194,7 @@ server_loop(void) struct client *c; server_client_loop(); + notify_drain(); if (!options_get_number(global_options, "exit-unattached")) { if (!RB_EMPTY(&sessions)) @@ -210,6 +210,7 @@ session_destroy(struct session *s) struct winlink *wl; log_debug("session %s destroyed", s->name); + s->curw = NULL; RB_REMOVE(sessions, &sessions, s); notify_session_closed(s); @@ -384,14 +385,17 @@ int session_detach(struct session *s, struct winlink *wl) { if (s->curw == wl && - session_last(s) != 0 && session_previous(s, 0) != 0) + session_last(s) != 0 && + session_previous(s, 0) != 0) session_next(s, 0); wl->flags &= ~WINLINK_ALERTFLAGS; notify_window_unlinked(s, wl->window); winlink_stack_remove(&s->lastw, wl); winlink_remove(&s->windows, wl); + session_group_synchronize_from(s); + if (RB_EMPTY(&s->windows)) { session_destroy(s); return (1); @@ -3248,6 +3248,10 @@ Run when the program running in a pane exits, but is on so the pane has not closed. .It pane-exited Run when the program running in a pane exits. +.It session-renamed +Run when a session is renamed. +.It window-renamed +Run when a window is renamed. .El .Pp Hooks are managed with these commands: @@ -1579,8 +1579,7 @@ void mode_key_init(struct mode_key_data *, struct mode_key_tree *); enum mode_key_cmd mode_key_lookup(struct mode_key_data *, key_code); /* notify.c */ -void notify_enable(void); -void notify_disable(void); +void notify_drain(void); void notify_input(struct window_pane *, struct evbuffer *); void notify_window_layout_changed(struct window *); void notify_window_unlinked(struct session *, struct window *); @@ -1745,6 +1744,8 @@ int cmd_find_from_session(struct cmd_find_state *, struct session *); int cmd_find_from_winlink(struct cmd_find_state *, struct session *, struct winlink *); +int cmd_find_from_session_window(struct cmd_find_state *, + struct session *, struct window *); int cmd_find_from_window(struct cmd_find_state *, struct window *); int cmd_find_from_pane(struct cmd_find_state *, struct window_pane *); @@ -2209,7 +2210,7 @@ void control_notify_window_renamed(struct window *); void control_notify_attached_session_changed(struct client *); void control_notify_session_renamed(struct session *); void control_notify_session_created(struct session *); -void control_notify_session_close(struct session *); +void control_notify_session_closed(struct session *); /* session.c */ extern struct sessions sessions; |