From 9b3ae84993d2493ff0761efbcda0b9d188ed6d9e Mon Sep 17 00:00:00 2001 From: nicm Date: Sat, 15 Oct 2016 00:01:01 +0000 Subject: [PATCH 1/3] Drain notifys once at the end of the server loop instead of doing it from the end of every command queue (which could be nested). --- cmd-queue.c | 6 +----- notify.c | 27 +-------------------------- server.c | 1 + tmux.h | 3 +-- 4 files changed, 4 insertions(+), 33 deletions(-) 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/notify.c b/notify.c index a1f69240..3ec41e99 100644 --- a/notify.c +++ b/notify.c @@ -45,25 +45,10 @@ 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) -{ - notify_enabled = 1; - notify_drain(); -} - -void -notify_disable(void) -{ - notify_enabled = 0; -} - static void notify_add(enum notify_type type, struct client *c, struct session *s, struct window *w) @@ -85,14 +70,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: @@ -138,13 +120,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); diff --git a/server.c b/server.c index bcb596b8..e6d1c09f 100644 --- a/server.c +++ b/server.c @@ -192,6 +192,7 @@ server_loop(void) struct client *c; server_client_loop(); + notify_drain(); if (!options_get_number(global_options, "exit-unattached")) { if (!RB_EMPTY(&sessions)) diff --git a/tmux.h b/tmux.h index 3f29f07f..a57ac5b0 100644 --- a/tmux.h +++ b/tmux.h @@ -1577,8 +1577,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 *); From 63b2547a0255c42bff405ca34577de240a99b736 Mon Sep 17 00:00:00 2001 From: nicm Date: Sat, 15 Oct 2016 00:09:30 +0000 Subject: [PATCH 2/3] Fire hooks on the simple notifys (window-renamed and session-renamed), the complicated ones get no hooks for now (more to come). --- cmd-find.c | 18 ++++++++++++++++++ notify.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++-- tmux.1 | 4 ++++ tmux.h | 2 ++ 4 files changed, 74 insertions(+), 2 deletions(-) diff --git a/cmd-find.c b/cmd-find.c index 10f2fd04..21691f67 100644 --- a/cmd-find.c +++ b/cmd-find.c @@ -904,6 +904,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) @@ -915,6 +932,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/notify.c b/notify.c index 3ec41e99..5f4f046e 100644 --- a/notify.c +++ b/notify.c @@ -34,6 +34,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; @@ -49,6 +60,43 @@ static struct notify_queue notify_queue = TAILQ_HEAD_INITIALIZER(notify_queue); static void notify_add(enum notify_type, struct client *, struct session *, struct window *); +static void +notify_hook(struct notify_entry *ne) +{ + const char *name; + struct cmd_find_state fs; + struct hook *hook; + struct cmd_q *hooks_cmdq; + + 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 notify_add(enum notify_type type, struct client *c, struct session *s, struct window *w) @@ -102,6 +150,8 @@ notify_drain(void) control_notify_session_close(ne->session); break; } + TAILQ_REMOVE(¬ify_queue, ne, entry); + notify_hook(ne); if (ne->client != NULL) server_client_unref(ne->client); @@ -109,8 +159,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); } } diff --git a/tmux.1 b/tmux.1 index 79746d01..877318c0 100644 --- a/tmux.1 +++ b/tmux.1 @@ -3244,6 +3244,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: diff --git a/tmux.h b/tmux.h index a57ac5b0..0db6f031 100644 --- a/tmux.h +++ b/tmux.h @@ -1742,6 +1742,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 *); From 3f138dc40c37ddee021b92e5d29676ed96b6cab8 Mon Sep 17 00:00:00 2001 From: nicm Date: Sat, 15 Oct 2016 00:12:58 +0000 Subject: [PATCH 3/3] Rename a function for consistency and some spacing nits. --- control-notify.c | 2 +- notify.c | 2 +- session.c | 6 +++++- tmux.h | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) 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; diff --git a/notify.c b/notify.c index 5f4f046e..416b81f6 100644 --- a/notify.c +++ b/notify.c @@ -147,7 +147,7 @@ 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); diff --git a/session.c b/session.c index 634f89d9..423b7db1 100644 --- a/session.c +++ b/session.c @@ -211,6 +211,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); @@ -385,14 +386,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); diff --git a/tmux.h b/tmux.h index 0db6f031..00d08016 100644 --- a/tmux.h +++ b/tmux.h @@ -2208,7 +2208,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;