xref: /minix/external/bsd/tmux/dist/notify.c (revision 0a6a1f1d)
1 /* Id */
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 
19 #include <sys/types.h>
20 
21 #include <stdlib.h>
22 
23 #include "tmux.h"
24 
25 enum notify_type {
26 	NOTIFY_WINDOW_LAYOUT_CHANGED,
27 	NOTIFY_WINDOW_UNLINKED,
28 	NOTIFY_WINDOW_LINKED,
29 	NOTIFY_WINDOW_RENAMED,
30 	NOTIFY_ATTACHED_SESSION_CHANGED,
31 	NOTIFY_SESSION_RENAMED,
32 	NOTIFY_SESSION_CREATED,
33 	NOTIFY_SESSION_CLOSED
34 };
35 
36 struct notify_entry {
37 	enum notify_type	 type;
38 
39 	struct client		*client;
40 	struct session		*session;
41 	struct window		*window;
42 
43 	TAILQ_ENTRY(notify_entry) entry;
44 };
45 TAILQ_HEAD(, notify_entry) notify_queue = TAILQ_HEAD_INITIALIZER(notify_queue);
46 int	notify_enabled = 1;
47 
48 void	notify_drain(void);
49 void	notify_add(enum notify_type, struct client *, struct session *,
50 	    struct window *);
51 
52 void
notify_enable(void)53 notify_enable(void)
54 {
55 	notify_enabled = 1;
56 	notify_drain();
57 }
58 
59 void
notify_disable(void)60 notify_disable(void)
61 {
62 	notify_enabled = 0;
63 }
64 
65 void
notify_add(enum notify_type type,struct client * c,struct session * s,struct window * w)66 notify_add(enum notify_type type, struct client *c, struct session *s,
67     struct window *w)
68 {
69 	struct notify_entry	*ne;
70 
71 	ne = xcalloc(1, sizeof *ne);
72 	ne->type = type;
73 	ne->client = c;
74 	ne->session = s;
75 	ne->window = w;
76 	TAILQ_INSERT_TAIL(&notify_queue, ne, entry);
77 
78 	if (c != NULL)
79 		c->references++;
80 	if (s != NULL)
81 		s->references++;
82 	if (w != NULL)
83 		w->references++;
84 }
85 
86 void
notify_drain(void)87 notify_drain(void)
88 {
89 	struct notify_entry	*ne, *ne1;
90 
91 	if (!notify_enabled)
92 		return;
93 
94 	TAILQ_FOREACH_SAFE(ne, &notify_queue, entry, ne1) {
95 		switch (ne->type) {
96 		case NOTIFY_WINDOW_LAYOUT_CHANGED:
97 			control_notify_window_layout_changed(ne->window);
98 			break;
99 		case NOTIFY_WINDOW_UNLINKED:
100 			control_notify_window_unlinked(ne->session, ne->window);
101 			break;
102 		case NOTIFY_WINDOW_LINKED:
103 			control_notify_window_linked(ne->session, ne->window);
104 			break;
105 		case NOTIFY_WINDOW_RENAMED:
106 			control_notify_window_renamed(ne->window);
107 			break;
108 		case NOTIFY_ATTACHED_SESSION_CHANGED:
109 			control_notify_attached_session_changed(ne->client);
110 			break;
111 		case NOTIFY_SESSION_RENAMED:
112 			control_notify_session_renamed(ne->session);
113 			break;
114 		case NOTIFY_SESSION_CREATED:
115 			control_notify_session_created(ne->session);
116 			break;
117 		case NOTIFY_SESSION_CLOSED:
118 			control_notify_session_close(ne->session);
119 			break;
120 		}
121 
122 		if (ne->client != NULL)
123 			ne->client->references--;
124 		if (ne->session != NULL)
125 			ne->session->references--;
126 		if (ne->window != NULL)
127 			window_remove_ref(ne->window);
128 
129 		TAILQ_REMOVE(&notify_queue, ne, entry);
130 		free(ne);
131 	}
132 }
133 
134 void
notify_input(struct window_pane * wp,struct evbuffer * input)135 notify_input(struct window_pane *wp, struct evbuffer *input)
136 {
137 	struct client	*c;
138 	u_int		 i;
139 
140 	/*
141 	 * notify_input() is not queued and only does anything when
142 	 * notifications are enabled.
143 	 */
144 	if (!notify_enabled)
145 		return;
146 
147 	for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
148 		c = ARRAY_ITEM(&clients, i);
149 		if (c != NULL && (c->flags & CLIENT_CONTROL))
150 			control_notify_input(c, wp, input);
151 	}
152 }
153 
154 void
notify_window_layout_changed(struct window * w)155 notify_window_layout_changed(struct window *w)
156 {
157 	notify_add(NOTIFY_WINDOW_LAYOUT_CHANGED, NULL, NULL, w);
158 	notify_drain();
159 }
160 
161 void
notify_window_unlinked(struct session * s,struct window * w)162 notify_window_unlinked(struct session *s, struct window *w)
163 {
164 	notify_add(NOTIFY_WINDOW_UNLINKED, NULL, s, w);
165 	notify_drain();
166 }
167 
168 void
notify_window_linked(struct session * s,struct window * w)169 notify_window_linked(struct session *s, struct window *w)
170 {
171 	notify_add(NOTIFY_WINDOW_LINKED, NULL, s, w);
172 	notify_drain();
173 }
174 
175 void
notify_window_renamed(struct window * w)176 notify_window_renamed(struct window *w)
177 {
178 	notify_add(NOTIFY_WINDOW_RENAMED, NULL, NULL, w);
179 	notify_drain();
180 }
181 
182 void
notify_attached_session_changed(struct client * c)183 notify_attached_session_changed(struct client *c)
184 {
185 	notify_add(NOTIFY_ATTACHED_SESSION_CHANGED, c, NULL, NULL);
186 	notify_drain();
187 }
188 
189 void
notify_session_renamed(struct session * s)190 notify_session_renamed(struct session *s)
191 {
192 	notify_add(NOTIFY_SESSION_RENAMED, NULL, s, NULL);
193 	notify_drain();
194 }
195 
196 void
notify_session_created(struct session * s)197 notify_session_created(struct session *s)
198 {
199 	notify_add(NOTIFY_SESSION_CREATED, NULL, s, NULL);
200 	notify_drain();
201 }
202 
203 void
notify_session_closed(struct session * s)204 notify_session_closed(struct session *s)
205 {
206 	notify_add(NOTIFY_SESSION_CLOSED, NULL, s, NULL);
207 	notify_drain();
208 }
209