mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 00:56:10 +00:00 
			
		
		
		
	Send notifications to control clients. Also don't redraw client when
suspended.
This commit is contained in:
		
				
					committed by
					
						
						Thomas Adam
					
				
			
			
				
	
			
			
			
						parent
						
							0304555184
						
					
				
				
					commit
					41a448193f
				
			
							
								
								
									
										183
									
								
								control-notify.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										183
									
								
								control-notify.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,183 @@
 | 
			
		||||
/* $OpenBSD$ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2012 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
			
		||||
 * Copyright (c) 2012 George Nachman <tmux@georgester.com>
 | 
			
		||||
 *
 | 
			
		||||
 * Permission to use, copy, modify, and distribute this software for any
 | 
			
		||||
 * purpose with or without fee is hereby granted, provided that the above
 | 
			
		||||
 * copyright notice and this permission notice appear in all copies.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
			
		||||
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
			
		||||
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
			
		||||
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
			
		||||
 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
 | 
			
		||||
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
 | 
			
		||||
 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
 | 
			
		||||
#include "tmux.h"
 | 
			
		||||
 | 
			
		||||
#define CONTROL_SHOULD_NOTIFY_CLIENT(c) \
 | 
			
		||||
	((c) != NULL && ((c)->flags & CLIENT_CONTROL))
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
control_notify_window_layout_changed(struct window *w)
 | 
			
		||||
{
 | 
			
		||||
	struct client		*c;
 | 
			
		||||
	struct session		*s;
 | 
			
		||||
	struct format_tree	*ft;
 | 
			
		||||
	struct winlink		*wl;
 | 
			
		||||
	u_int			 i;
 | 
			
		||||
	const char		*template;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
 | 
			
		||||
		c = ARRAY_ITEM(&clients, i);
 | 
			
		||||
		if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
 | 
			
		||||
			continue;
 | 
			
		||||
		s = c->session;
 | 
			
		||||
 | 
			
		||||
		if (winlink_find_by_window_id(&s->windows, w->id) == NULL)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		 * When the last pane in a window is closed it won't have a
 | 
			
		||||
		 * layout root and we don't need to inform the client about the
 | 
			
		||||
		 * layout change because the whole window will go away soon.
 | 
			
		||||
		 */
 | 
			
		||||
		if (w->layout_root == NULL)
 | 
			
		||||
			continue;
 | 
			
		||||
		template = "%layout-change #{window_id} #{window_layout}";
 | 
			
		||||
 | 
			
		||||
		ft = format_create();
 | 
			
		||||
		wl = winlink_find_by_window(&s->windows, w);
 | 
			
		||||
		if (wl != NULL) {
 | 
			
		||||
			format_winlink(ft, c->session, wl);
 | 
			
		||||
			control_write(c, "%s", format_expand(ft, template));
 | 
			
		||||
		}
 | 
			
		||||
		format_free(ft);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
control_notify_window_unlinked(unused struct session *s, struct window *w)
 | 
			
		||||
{
 | 
			
		||||
	struct client	*c;
 | 
			
		||||
	struct session	*cs;
 | 
			
		||||
	u_int		 i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
 | 
			
		||||
		c = ARRAY_ITEM(&clients, i);
 | 
			
		||||
		if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
 | 
			
		||||
			continue;
 | 
			
		||||
		cs = c->session;
 | 
			
		||||
 | 
			
		||||
		if (winlink_find_by_window_id(&cs->windows, w->id) != NULL)
 | 
			
		||||
			control_write(c, "%%window-close %u", w->id);
 | 
			
		||||
		else
 | 
			
		||||
			control_write(c, "%%unlinked-window-close %u", w->id);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
control_notify_window_linked(unused struct session *s, struct window *w)
 | 
			
		||||
{
 | 
			
		||||
	struct client	*c;
 | 
			
		||||
	struct session	*cs;
 | 
			
		||||
	u_int		 i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
 | 
			
		||||
		c = ARRAY_ITEM(&clients, i);
 | 
			
		||||
		if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
 | 
			
		||||
			continue;
 | 
			
		||||
		cs = c->session;
 | 
			
		||||
 | 
			
		||||
		if (winlink_find_by_window_id(&cs->windows, w->id) != NULL)
 | 
			
		||||
			control_write(c, "%%window-add %u", w->id);
 | 
			
		||||
		else
 | 
			
		||||
			control_write(c, "%%unlinked-window-add %u", w->id);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
control_notify_window_renamed(struct window *w)
 | 
			
		||||
{
 | 
			
		||||
	struct client	*c;
 | 
			
		||||
	struct session	*s;
 | 
			
		||||
	u_int		 i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
 | 
			
		||||
		c = ARRAY_ITEM(&clients, i);
 | 
			
		||||
		if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
 | 
			
		||||
			continue;
 | 
			
		||||
		s = c->session;
 | 
			
		||||
 | 
			
		||||
		if (winlink_find_by_window_id(&s->windows, w->id) != NULL) {
 | 
			
		||||
			control_write(c, "%%window-renamed %u %s",
 | 
			
		||||
			    w->id, w->name);
 | 
			
		||||
		} else {
 | 
			
		||||
			control_write(c, "%%unlinked-window-renamed %u %s",
 | 
			
		||||
			    w->id, w->name);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
control_notify_attached_session_changed(struct client *c)
 | 
			
		||||
{
 | 
			
		||||
	struct session	*s;
 | 
			
		||||
 | 
			
		||||
	if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
 | 
			
		||||
		return;
 | 
			
		||||
	s = c->session;
 | 
			
		||||
 | 
			
		||||
	control_write(c, "%%session-changed %d %s", s->idx, s->name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
control_notify_session_renamed(struct session *s)
 | 
			
		||||
{
 | 
			
		||||
	struct client	*c;
 | 
			
		||||
	u_int		 i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
 | 
			
		||||
		c = ARRAY_ITEM(&clients, i);
 | 
			
		||||
		if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session != s)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		control_write(c, "%%session-renamed %s", s->name);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
control_notify_session_created(unused struct session *s)
 | 
			
		||||
{
 | 
			
		||||
	struct client	*c;
 | 
			
		||||
	u_int		 i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
 | 
			
		||||
		c = ARRAY_ITEM(&clients, i);
 | 
			
		||||
		if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		control_write(c, "%%sessions-changed");
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
control_notify_session_close(unused struct session *s)
 | 
			
		||||
{
 | 
			
		||||
	struct client	*c;
 | 
			
		||||
	u_int		 i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
 | 
			
		||||
		c = ARRAY_ITEM(&clients, i);
 | 
			
		||||
		if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		control_write(c, "%%sessions-changed");
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -28,7 +28,6 @@
 | 
			
		||||
void printflike2 control_msg_error(struct cmd_ctx *, const char *, ...);
 | 
			
		||||
void printflike2 control_msg_print(struct cmd_ctx *, const char *, ...);
 | 
			
		||||
void printflike2 control_msg_info(struct cmd_ctx *, const char *, ...);
 | 
			
		||||
void printflike2 control_write(struct client *, const char *, ...);
 | 
			
		||||
 | 
			
		||||
/* Command error callback. */
 | 
			
		||||
void printflike2
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										16
									
								
								notify.c
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								notify.c
									
									
									
									
									
								
							@@ -94,28 +94,28 @@ notify_drain(void)
 | 
			
		||||
	TAILQ_FOREACH_SAFE(ne, ¬ify_queue, entry, ne1) {
 | 
			
		||||
		switch (ne->type) {
 | 
			
		||||
		case NOTIFY_WINDOW_LAYOUT_CHANGED:
 | 
			
		||||
			/* control_notify_window_layout_changed(ne->window); */
 | 
			
		||||
			control_notify_window_layout_changed(ne->window);
 | 
			
		||||
			break;
 | 
			
		||||
		case NOTIFY_WINDOW_UNLINKED:
 | 
			
		||||
			/* control_notify_window_unlinked(ne->session, ne->window); */
 | 
			
		||||
			control_notify_window_unlinked(ne->session, ne->window);
 | 
			
		||||
			break;
 | 
			
		||||
		case NOTIFY_WINDOW_LINKED:
 | 
			
		||||
			/* control_notify_window_linked(ne->session, ne->window); */
 | 
			
		||||
			control_notify_window_linked(ne->session, ne->window);
 | 
			
		||||
			break;
 | 
			
		||||
		case NOTIFY_WINDOW_RENAMED:
 | 
			
		||||
			/* control_notify_window_renamed(ne->window); */
 | 
			
		||||
			control_notify_window_renamed(ne->window);
 | 
			
		||||
			break;
 | 
			
		||||
		case NOTIFY_ATTACHED_SESSION_CHANGED:
 | 
			
		||||
			/* control_notify_attached_session_changed(ne->client, ne->session); */
 | 
			
		||||
			control_notify_attached_session_changed(ne->client);
 | 
			
		||||
			break;
 | 
			
		||||
		case NOTIFY_SESSION_RENAMED:
 | 
			
		||||
			/* control_notify_session_renamed(ne->session); */
 | 
			
		||||
			control_notify_session_renamed(ne->session);
 | 
			
		||||
			break;
 | 
			
		||||
		case NOTIFY_SESSION_CREATED:
 | 
			
		||||
			/* control_notify_session_created(ne->session); */
 | 
			
		||||
			control_notify_session_created(ne->session);
 | 
			
		||||
			break;
 | 
			
		||||
		case NOTIFY_SESSION_CLOSED:
 | 
			
		||||
			/* control_notify_session_close(ne->session); */
 | 
			
		||||
			control_notify_session_close(ne->session);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -602,6 +602,9 @@ server_client_check_redraw(struct client *c)
 | 
			
		||||
	struct window_pane	*wp;
 | 
			
		||||
	int		 	 flags, redraw;
 | 
			
		||||
 | 
			
		||||
	if (c->flags & CLIENT_SUSPENDED)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	flags = c->tty.flags & TTY_FREEZE;
 | 
			
		||||
	c->tty.flags &= ~TTY_FREEZE;
 | 
			
		||||
 | 
			
		||||
@@ -899,6 +902,7 @@ server_client_msg_identify(
 | 
			
		||||
	if (data->flags & IDENTIFY_CONTROL) {
 | 
			
		||||
		c->stdin_callback = control_callback;
 | 
			
		||||
		c->flags |= (CLIENT_CONTROL|CLIENT_SUSPENDED);
 | 
			
		||||
		server_write_client(c, MSG_STDIN, NULL, 0);
 | 
			
		||||
 | 
			
		||||
		c->tty.fd = -1;
 | 
			
		||||
		c->tty.log_fd = -1;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										11
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								tmux.h
									
									
									
									
									
								
							@@ -2211,6 +2211,17 @@ void	clear_signals(int);
 | 
			
		||||
 | 
			
		||||
/* control.c */
 | 
			
		||||
void	control_callback(struct client *, int, void*);
 | 
			
		||||
void printflike2 control_write(struct client *, const char *, ...);
 | 
			
		||||
 | 
			
		||||
/* control-notify.c */
 | 
			
		||||
void	control_notify_window_layout_changed(struct window *);
 | 
			
		||||
void	control_notify_window_unlinked(struct session *, struct window *);
 | 
			
		||||
void	control_notify_window_linked(struct session *, struct window *);
 | 
			
		||||
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 *);
 | 
			
		||||
 | 
			
		||||
/* session.c */
 | 
			
		||||
extern struct sessions sessions;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user