version 1.17, 2016/10/16 19:55:52 |
version 1.18, 2016/10/16 22:06:40 |
|
|
#include <sys/queue.h> |
#include <sys/queue.h> |
|
|
#include <stdlib.h> |
#include <stdlib.h> |
|
#include <string.h> |
|
|
#include "tmux.h" |
#include "tmux.h" |
|
|
enum notify_type { |
|
NOTIFY_WINDOW_LAYOUT_CHANGED, |
|
NOTIFY_WINDOW_UNLINKED, |
|
NOTIFY_WINDOW_LINKED, |
|
NOTIFY_WINDOW_RENAMED, |
|
NOTIFY_ATTACHED_SESSION_CHANGED, |
|
NOTIFY_SESSION_RENAMED, |
|
NOTIFY_SESSION_CREATED, |
|
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", |
|
"session-created", |
|
"session-closed" |
|
}; |
|
|
|
struct notify_entry { |
struct notify_entry { |
enum notify_type type; |
const char *name; |
|
|
struct client *client; |
struct client *client; |
struct session *session; |
struct session *session; |
struct window *window; |
struct window *window; |
|
int pane; |
|
|
|
struct cmd_find_state fs; |
}; |
}; |
|
|
static void |
static void |
notify_hook(struct cmdq_item *item, struct notify_entry *ne) |
notify_hook(struct cmdq_item *item, struct notify_entry *ne) |
{ |
{ |
const char *name; |
|
struct cmd_find_state fs; |
struct cmd_find_state fs; |
struct hook *hook; |
struct hook *hook; |
struct cmdq_item *new_item; |
struct cmdq_item *new_item; |
struct session *s = ne->session; |
struct session *s = ne->session; |
struct window *w = ne->window; |
struct window *w = ne->window; |
|
|
name = notify_hooks[ne->type]; |
|
if (name == NULL) |
|
return; |
|
|
|
cmd_find_clear_state(&fs, NULL, 0); |
cmd_find_clear_state(&fs, NULL, 0); |
if (s != NULL && w != NULL) |
if (cmd_find_empty_state(&ne->fs) || !cmd_find_valid_state(&ne->fs)) |
cmd_find_from_session_window(&fs, s, w); |
|
else if (w != NULL) |
|
cmd_find_from_window(&fs, w); |
|
else if (s != NULL && session_alive(s)) |
|
cmd_find_from_session(&fs, s); |
|
else |
|
cmd_find_current(&fs, item, CMD_FIND_QUIET); |
cmd_find_current(&fs, item, CMD_FIND_QUIET); |
if (cmd_find_empty_state(&fs) || !cmd_find_valid_state(&fs)) |
else |
return; |
cmd_find_copy_state(&fs, &ne->fs); |
|
|
hook = hooks_find(fs.s->hooks, name); |
hook = hooks_find(hooks_get(fs.s), ne->name); |
if (hook == NULL) |
if (hook == NULL) |
return; |
return; |
log_debug("notify hook %s", name); |
log_debug("notify hook %s", ne->name); |
|
|
new_item = cmdq_get_command(hook->cmdlist, &fs, NULL, CMDQ_NOHOOKS); |
new_item = cmdq_get_command(hook->cmdlist, &fs, NULL, CMDQ_NOHOOKS); |
cmdq_format(new_item, "hook", "%s", name); |
cmdq_format(new_item, "hook", "%s", ne->name); |
|
|
if (s != NULL) { |
if (s != NULL) { |
cmdq_format(new_item, "hook_session", "$%u", s->id); |
cmdq_format(new_item, "hook_session", "$%u", s->id); |
|
|
cmdq_format(new_item, "hook_window", "@%u", w->id); |
cmdq_format(new_item, "hook_window", "@%u", w->id); |
cmdq_format(new_item, "hook_window_name", "%s", w->name); |
cmdq_format(new_item, "hook_window_name", "%s", w->name); |
} |
} |
|
if (ne->pane != -1) |
|
cmdq_format(new_item, "hook_pane", "%%%d", ne->pane); |
|
|
cmdq_insert_after(item, new_item); |
cmdq_insert_after(item, new_item); |
} |
} |
|
|
{ |
{ |
struct notify_entry *ne = data; |
struct notify_entry *ne = data; |
|
|
switch (ne->type) { |
if (strcmp(ne->name, "window-layout-changed") == 0) |
case NOTIFY_WINDOW_LAYOUT_CHANGED: |
|
control_notify_window_layout_changed(ne->window); |
control_notify_window_layout_changed(ne->window); |
break; |
if (strcmp(ne->name, "window-unlinked") == 0) |
case NOTIFY_WINDOW_UNLINKED: |
|
control_notify_window_unlinked(ne->session, ne->window); |
control_notify_window_unlinked(ne->session, ne->window); |
break; |
if (strcmp(ne->name, "window-linked") == 0) |
case NOTIFY_WINDOW_LINKED: |
|
control_notify_window_linked(ne->session, ne->window); |
control_notify_window_linked(ne->session, ne->window); |
break; |
if (strcmp(ne->name, "window-renamed") == 0) |
case NOTIFY_WINDOW_RENAMED: |
|
control_notify_window_renamed(ne->window); |
control_notify_window_renamed(ne->window); |
break; |
if (strcmp(ne->name, "client-session-changed") == 0) |
case NOTIFY_ATTACHED_SESSION_CHANGED: |
control_notify_client_session_changed(ne->client); |
control_notify_attached_session_changed(ne->client); |
if (strcmp(ne->name, "session-renamed") == 0) |
break; |
|
case NOTIFY_SESSION_RENAMED: |
|
control_notify_session_renamed(ne->session); |
control_notify_session_renamed(ne->session); |
break; |
if (strcmp(ne->name, "session-created") == 0) |
case NOTIFY_SESSION_CREATED: |
|
control_notify_session_created(ne->session); |
control_notify_session_created(ne->session); |
break; |
if (strcmp(ne->name, "session-closed") == 0) |
case NOTIFY_SESSION_CLOSED: |
|
control_notify_session_closed(ne->session); |
control_notify_session_closed(ne->session); |
break; |
|
} |
|
notify_hook(item, ne); |
notify_hook(item, ne); |
|
|
if (ne->client != NULL) |
if (ne->client != NULL) |
|
|
session_unref(ne->session); |
session_unref(ne->session); |
if (ne->window != NULL) |
if (ne->window != NULL) |
window_remove_ref(ne->window); |
window_remove_ref(ne->window); |
|
|
|
if (ne->fs.s != NULL) |
|
session_unref(ne->fs.s); |
|
|
|
free((void *)ne->name); |
free(ne); |
free(ne); |
|
|
return (CMD_RETURN_NORMAL); |
return (CMD_RETURN_NORMAL); |
} |
} |
|
|
static void |
static void |
notify_add(enum notify_type type, struct client *c, struct session *s, |
notify_add(const char *name, struct client *c, struct session *s, |
struct window *w) |
struct window *w, struct window_pane *wp) |
{ |
{ |
struct notify_entry *ne; |
struct notify_entry *ne; |
struct cmdq_item *new_item; |
struct cmdq_item *new_item; |
|
|
ne = xcalloc(1, sizeof *ne); |
ne = xcalloc(1, sizeof *ne); |
ne->type = type; |
ne->name = xstrdup(name); |
|
|
ne->client = c; |
ne->client = c; |
ne->session = s; |
ne->session = s; |
ne->window = w; |
ne->window = w; |
|
|
|
if (wp != NULL) |
|
ne->pane = wp->id; |
|
else |
|
ne->pane = -1; |
|
|
if (c != NULL) |
if (c != NULL) |
c->references++; |
c->references++; |
if (s != NULL) |
if (s != NULL) |
|
|
if (w != NULL) |
if (w != NULL) |
w->references++; |
w->references++; |
|
|
|
cmd_find_clear_state(&ne->fs, NULL, 0); |
|
if (s != NULL && w != NULL) |
|
cmd_find_from_session_window(&ne->fs, s, w); |
|
else if (w != NULL) |
|
cmd_find_from_window(&ne->fs, w); |
|
else if (s != NULL && session_alive(s)) |
|
cmd_find_from_session(&ne->fs, s); |
|
else if (wp != NULL) |
|
cmd_find_from_pane(&ne->fs, wp); |
|
else |
|
cmd_find_current(&ne->fs, NULL, CMD_FIND_QUIET); |
|
if (ne->fs.s != NULL) |
|
ne->fs.s->references++; /* cmd_find_valid_state need session */ |
|
|
new_item = cmdq_get_callback(notify_callback, ne); |
new_item = cmdq_get_callback(notify_callback, ne); |
cmdq_append(NULL, new_item); |
cmdq_append(NULL, new_item); |
} |
} |
|
|
} |
} |
|
|
void |
void |
notify_window_layout_changed(struct window *w) |
notify_client(const char *name, struct client *c) |
{ |
{ |
notify_add(NOTIFY_WINDOW_LAYOUT_CHANGED, NULL, NULL, w); |
notify_add(name, c, NULL, NULL, NULL); |
} |
} |
|
|
void |
void |
notify_window_unlinked(struct session *s, struct window *w) |
notify_session(const char *name, struct session *s) |
{ |
{ |
notify_add(NOTIFY_WINDOW_UNLINKED, NULL, s, w); |
notify_add(name, NULL, s, NULL, NULL); |
} |
} |
|
|
void |
void |
notify_window_linked(struct session *s, struct window *w) |
notify_session_window(const char *name, struct session *s, struct window *w) |
{ |
{ |
notify_add(NOTIFY_WINDOW_LINKED, NULL, s, w); |
notify_add(name, NULL, s, w, NULL); |
} |
} |
|
|
void |
void |
notify_window_renamed(struct window *w) |
notify_window(const char *name, struct window *w) |
{ |
{ |
notify_add(NOTIFY_WINDOW_RENAMED, NULL, NULL, w); |
notify_add(name, NULL, NULL, w, NULL); |
} |
} |
|
|
void |
void |
notify_attached_session_changed(struct client *c) |
notify_pane(const char *name, struct window_pane *wp) |
{ |
{ |
notify_add(NOTIFY_ATTACHED_SESSION_CHANGED, c, NULL, NULL); |
notify_add(name, NULL, NULL, NULL, wp); |
} |
|
|
|
void |
|
notify_session_renamed(struct session *s) |
|
{ |
|
notify_add(NOTIFY_SESSION_RENAMED, NULL, s, NULL); |
|
} |
|
|
|
void |
|
notify_session_created(struct session *s) |
|
{ |
|
notify_add(NOTIFY_SESSION_CREATED, NULL, s, NULL); |
|
} |
|
|
|
void |
|
notify_session_closed(struct session *s) |
|
{ |
|
notify_add(NOTIFY_SESSION_CLOSED, NULL, s, NULL); |
|
} |
} |