Annotation of src/usr.bin/tmux/notify.c, Revision 1.38
1.38 ! nicm 1: /* $OpenBSD: notify.c,v 1.37 2021/03/16 09:14:58 nicm Exp $ */
1.1 nicm 2:
3: /*
4: * Copyright (c) 2012 George Nachman <tmux@georgester.com>
5: *
6: * Permission to use, copy, modify, and distribute this software for any
7: * purpose with or without fee is hereby granted, provided that the above
8: * copyright notice and this permission notice appear in all copies.
9: *
10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14: * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15: * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16: * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17: */
18:
1.2 nicm 19: #include <sys/types.h>
20: #include <sys/queue.h>
21:
22: #include <stdlib.h>
1.18 nicm 23: #include <string.h>
1.2 nicm 24:
1.1 nicm 25: #include "tmux.h"
26:
1.2 nicm 27: struct notify_entry {
1.18 nicm 28: const char *name;
1.38 ! nicm 29: struct cmd_find_state fs;
! 30: struct format_tree *formats;
1.2 nicm 31:
32: struct client *client;
33: struct session *session;
34: struct window *window;
1.18 nicm 35: int pane;
1.2 nicm 36: };
37:
1.9 nicm 38: static void
1.27 nicm 39: notify_insert_hook(struct cmdq_item *item, struct notify_entry *ne)
40: {
41: struct cmd_find_state fs;
42: struct options *oo;
43: struct cmdq_item *new_item;
1.34 nicm 44: struct cmdq_state *new_state;
1.27 nicm 45: struct options_entry *o;
46: struct options_array_item *a;
47: struct cmd_list *cmdlist;
48:
49: log_debug("%s: %s", __func__, ne->name);
1.11 nicm 50:
1.22 nicm 51: cmd_find_clear_state(&fs, 0);
1.18 nicm 52: if (cmd_find_empty_state(&ne->fs) || !cmd_find_valid_state(&ne->fs))
1.25 nicm 53: cmd_find_from_nothing(&fs, 0);
1.15 nicm 54: else
1.18 nicm 55: cmd_find_copy_state(&fs, &ne->fs);
1.11 nicm 56:
1.27 nicm 57: if (fs.s == NULL)
58: oo = global_s_options;
59: else
60: oo = fs.s->options;
61: o = options_get(oo, ne->name);
1.30 nicm 62: if (o == NULL && fs.wp != NULL) {
63: oo = fs.wp->options;
64: o = options_get(oo, ne->name);
65: }
66: if (o == NULL && fs.wl != NULL) {
67: oo = fs.wl->window->options;
68: o = options_get(oo, ne->name);
69: }
1.27 nicm 70: if (o == NULL)
1.11 nicm 71: return;
72:
1.34 nicm 73: new_state = cmdq_new_state(&fs, NULL, CMDQ_STATE_NOHOOKS);
1.38 ! nicm 74: cmdq_add_formats(new_state, ne->formats);
1.34 nicm 75:
1.27 nicm 76: a = options_array_first(o);
77: while (a != NULL) {
78: cmdlist = options_array_item_value(a)->cmdlist;
1.34 nicm 79: if (cmdlist != NULL) {
80: new_item = cmdq_get_command(cmdlist, new_state);
81: item = cmdq_insert_after(item, new_item);
1.27 nicm 82: }
83: a = options_array_next(a);
1.17 nicm 84: }
1.34 nicm 85:
86: cmdq_free_state(new_state);
1.15 nicm 87: }
88:
89: static enum cmd_retval
90: notify_callback(struct cmdq_item *item, void *data)
91: {
92: struct notify_entry *ne = data;
1.20 nicm 93:
94: log_debug("%s: %s", __func__, ne->name);
1.15 nicm 95:
1.24 nicm 96: if (strcmp(ne->name, "pane-mode-changed") == 0)
97: control_notify_pane_mode_changed(ne->pane);
1.18 nicm 98: if (strcmp(ne->name, "window-layout-changed") == 0)
1.15 nicm 99: control_notify_window_layout_changed(ne->window);
1.24 nicm 100: if (strcmp(ne->name, "window-pane-changed") == 0)
101: control_notify_window_pane_changed(ne->window);
1.18 nicm 102: if (strcmp(ne->name, "window-unlinked") == 0)
1.15 nicm 103: control_notify_window_unlinked(ne->session, ne->window);
1.18 nicm 104: if (strcmp(ne->name, "window-linked") == 0)
1.15 nicm 105: control_notify_window_linked(ne->session, ne->window);
1.18 nicm 106: if (strcmp(ne->name, "window-renamed") == 0)
1.15 nicm 107: control_notify_window_renamed(ne->window);
1.18 nicm 108: if (strcmp(ne->name, "client-session-changed") == 0)
109: control_notify_client_session_changed(ne->client);
1.37 nicm 110: if (strcmp(ne->name, "client-detached") == 0)
111: control_notify_client_detached(ne->client);
1.18 nicm 112: if (strcmp(ne->name, "session-renamed") == 0)
1.15 nicm 113: control_notify_session_renamed(ne->session);
1.18 nicm 114: if (strcmp(ne->name, "session-created") == 0)
1.15 nicm 115: control_notify_session_created(ne->session);
1.18 nicm 116: if (strcmp(ne->name, "session-closed") == 0)
1.15 nicm 117: control_notify_session_closed(ne->session);
1.24 nicm 118: if (strcmp(ne->name, "session-window-changed") == 0)
119: control_notify_session_window_changed(ne->session);
1.18 nicm 120:
1.27 nicm 121: notify_insert_hook(item, ne);
1.15 nicm 122:
123: if (ne->client != NULL)
124: server_client_unref(ne->client);
125: if (ne->session != NULL)
1.23 nicm 126: session_remove_ref(ne->session, __func__);
1.15 nicm 127: if (ne->window != NULL)
1.23 nicm 128: window_remove_ref(ne->window, __func__);
1.18 nicm 129:
130: if (ne->fs.s != NULL)
1.23 nicm 131: session_remove_ref(ne->fs.s, __func__);
1.18 nicm 132:
1.38 ! nicm 133: format_free(ne->formats);
1.18 nicm 134: free((void *)ne->name);
1.15 nicm 135: free(ne);
136:
137: return (CMD_RETURN_NORMAL);
1.11 nicm 138: }
139:
140: static void
1.19 nicm 141: notify_add(const char *name, struct cmd_find_state *fs, struct client *c,
142: struct session *s, struct window *w, struct window_pane *wp)
1.2 nicm 143: {
144: struct notify_entry *ne;
1.35 nicm 145: struct cmdq_item *item;
146:
147: item = cmdq_running(NULL);
148: if (item != NULL && (cmdq_get_flags(item) & CMDQ_STATE_NOHOOKS))
149: return;
1.2 nicm 150:
151: ne = xcalloc(1, sizeof *ne);
1.18 nicm 152: ne->name = xstrdup(name);
153:
1.2 nicm 154: ne->client = c;
155: ne->session = s;
156: ne->window = w;
1.38 ! nicm 157: ne->pane = (wp != NULL ? wp->id : -1);
1.2 nicm 158:
1.38 ! nicm 159: ne->formats = format_create(NULL, NULL, 0, FORMAT_NOJOBS);
! 160: format_add(ne->formats, "hook", "%s", name);
! 161: if (c != NULL)
! 162: format_add(ne->formats, "hook_client", "%s", c->name);
! 163: if (s != NULL) {
! 164: format_add(ne->formats, "hook_session", "$%u", s->id);
! 165: format_add(ne->formats, "hook_session_name", "%s", s->name);
! 166: }
! 167: if (w != NULL) {
! 168: format_add(ne->formats, "hook_window", "@%u", w->id);
! 169: format_add(ne->formats, "hook_window_name", "%s", w->name);
! 170: }
1.18 nicm 171: if (wp != NULL)
1.38 ! nicm 172: format_add(ne->formats, "hook_pane", "%%%d", wp->id);
! 173: format_log_debug(ne->formats, __func__);
1.18 nicm 174:
1.2 nicm 175: if (c != NULL)
176: c->references++;
177: if (s != NULL)
1.23 nicm 178: session_add_ref(s, __func__);
1.2 nicm 179: if (w != NULL)
1.23 nicm 180: window_add_ref(w, __func__);
1.2 nicm 181:
1.19 nicm 182: cmd_find_copy_state(&ne->fs, fs);
1.23 nicm 183: if (ne->fs.s != NULL) /* cmd_find_valid_state needs session */
184: session_add_ref(ne->fs.s, __func__);
1.18 nicm 185:
1.35 nicm 186: cmdq_append(NULL, cmdq_get_callback(notify_callback, ne));
1.26 nicm 187: }
188:
189: void
190: notify_hook(struct cmdq_item *item, const char *name)
191: {
1.31 nicm 192: struct cmd_find_state *target = cmdq_get_target(item);
193: struct notify_entry ne;
1.26 nicm 194:
195: memset(&ne, 0, sizeof ne);
196:
197: ne.name = name;
1.31 nicm 198: cmd_find_copy_state(&ne.fs, target);
1.26 nicm 199:
1.31 nicm 200: ne.client = cmdq_get_client(item);
201: ne.session = target->s;
202: ne.window = target->w;
203: ne.pane = target->wp->id;
1.26 nicm 204:
1.38 ! nicm 205: ne.formats = format_create(NULL, NULL, 0, FORMAT_NOJOBS);
! 206: format_add(ne.formats, "hook", "%s", name);
! 207: format_log_debug(ne.formats, __func__);
! 208:
1.27 nicm 209: notify_insert_hook(item, &ne);
1.38 ! nicm 210: format_free(ne.formats);
1.2 nicm 211: }
212:
1.1 nicm 213: void
1.18 nicm 214: notify_client(const char *name, struct client *c)
1.1 nicm 215: {
1.19 nicm 216: struct cmd_find_state fs;
217:
1.25 nicm 218: cmd_find_from_client(&fs, c, 0);
1.19 nicm 219: notify_add(name, &fs, c, NULL, NULL, NULL);
1.1 nicm 220: }
221:
222: void
1.18 nicm 223: notify_session(const char *name, struct session *s)
1.1 nicm 224: {
1.19 nicm 225: struct cmd_find_state fs;
226:
227: if (session_alive(s))
1.25 nicm 228: cmd_find_from_session(&fs, s, 0);
1.19 nicm 229: else
1.25 nicm 230: cmd_find_from_nothing(&fs, 0);
1.19 nicm 231: notify_add(name, &fs, NULL, s, NULL, NULL);
232: }
233:
234: void
1.21 nicm 235: notify_winlink(const char *name, struct winlink *wl)
1.19 nicm 236: {
237: struct cmd_find_state fs;
238:
1.25 nicm 239: cmd_find_from_winlink(&fs, wl, 0);
1.21 nicm 240: notify_add(name, &fs, NULL, wl->session, wl->window, NULL);
1.1 nicm 241: }
242:
243: void
1.18 nicm 244: notify_session_window(const char *name, struct session *s, struct window *w)
1.1 nicm 245: {
1.19 nicm 246: struct cmd_find_state fs;
247:
1.25 nicm 248: cmd_find_from_session_window(&fs, s, w, 0);
1.19 nicm 249: notify_add(name, &fs, NULL, s, w, NULL);
1.1 nicm 250: }
251:
252: void
1.18 nicm 253: notify_window(const char *name, struct window *w)
1.1 nicm 254: {
1.19 nicm 255: struct cmd_find_state fs;
256:
1.25 nicm 257: cmd_find_from_window(&fs, w, 0);
1.19 nicm 258: notify_add(name, &fs, NULL, NULL, w, NULL);
1.1 nicm 259: }
260:
261: void
1.18 nicm 262: notify_pane(const char *name, struct window_pane *wp)
1.1 nicm 263: {
1.19 nicm 264: struct cmd_find_state fs;
265:
1.25 nicm 266: cmd_find_from_pane(&fs, wp, 0);
1.19 nicm 267: notify_add(name, &fs, NULL, NULL, NULL, wp);
1.1 nicm 268: }