mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 01:34:18 +00:00 
			
		
		
		
	Show status messages without blocking the server.
This commit is contained in:
		
							
								
								
									
										6
									
								
								TODO
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								TODO
									
									
									
									
									
								
							@@ -37,8 +37,6 @@
 | 
			
		||||
- function groups, bind-key ^W { select-window 0; send-key ^W } etc ***
 | 
			
		||||
- allow fnmatch for -c, so that you can, eg, detach all clients
 | 
			
		||||
- bind non prefix keys
 | 
			
		||||
- stuff like rename would be nice to be able to do in-client like screen, if
 | 
			
		||||
  it could be implemented in a non-icky way
 | 
			
		||||
- there is too much redrawing. use flags?
 | 
			
		||||
- command mode (! + type tmux command)
 | 
			
		||||
- garbage collect window history (100 lines at a time?) if it hasn't been used
 | 
			
		||||
@@ -86,3 +84,7 @@ option to pass through to xterm window when switching window
 | 
			
		||||
  session not being watched?
 | 
			
		||||
- document status-left/status-right/status-interval/set-titles
 | 
			
		||||
- enhance paste buffers. per-session buffers, lots of command love
 | 
			
		||||
- stuff like rename would be nice to be able to do in-client like screen, if
 | 
			
		||||
  it could be implemented in a non-icky way (we have control over the tty fd
 | 
			
		||||
  now in the server so should be easier...)
 | 
			
		||||
- tidy up window modes
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										62
									
								
								server-fn.c
									
									
									
									
									
								
							
							
						
						
									
										62
									
								
								server-fn.c
									
									
									
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
/* $Id: server-fn.c,v 1.42 2008-06-16 17:35:40 nicm Exp $ */
 | 
			
		||||
/* $Id: server-fn.c,v 1.43 2008-06-19 18:27:55 nicm Exp $ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
			
		||||
@@ -23,6 +23,31 @@
 | 
			
		||||
 | 
			
		||||
#include "tmux.h"
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
server_set_client_message(struct client *c, const char *msg)
 | 
			
		||||
{
 | 
			
		||||
	struct timespec	ts = { 0, 750000000L };
 | 
			
		||||
 | 
			
		||||
	c->message_string = xstrdup(msg);
 | 
			
		||||
	if (clock_gettime(CLOCK_REALTIME, &c->message_timer) != 0)
 | 
			
		||||
		fatal("clock_gettime");
 | 
			
		||||
	timespecadd(&c->message_timer, &ts, &c->message_timer);
 | 
			
		||||
 | 
			
		||||
	c->flags |= CLIENT_STATUS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
server_clear_client_message(struct client *c)
 | 
			
		||||
{
 | 
			
		||||
	if (c->message_string == NULL)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	xfree(c->message_string);
 | 
			
		||||
	c->message_string = NULL;
 | 
			
		||||
 | 
			
		||||
	c->flags |= CLIENT_STATUS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
server_write_client(
 | 
			
		||||
    struct client *c, enum hdrtype type, const void *buf, size_t len)
 | 
			
		||||
@@ -150,47 +175,14 @@ server_status_window(struct window *w)
 | 
			
		||||
void printflike2
 | 
			
		||||
server_write_message(struct client *c, const char *fmt, ...)
 | 
			
		||||
{
 | 
			
		||||
	struct screen_redraw_ctx	ctx;
 | 
			
		||||
	va_list	ap;
 | 
			
		||||
	char   *msg;
 | 
			
		||||
	size_t				size;
 | 
			
		||||
	u_int				slines;
 | 
			
		||||
 | 
			
		||||
	slines = options_get_number(&c->session->options, "status-lines");
 | 
			
		||||
 | 
			
		||||
	screen_redraw_start_client(&ctx, c);
 | 
			
		||||
 | 
			
		||||
	va_start(ap, fmt);
 | 
			
		||||
	xvasprintf(&msg, fmt, ap);
 | 
			
		||||
	va_end(ap);
 | 
			
		||||
 | 
			
		||||
	msg = xrealloc(msg, 1, c->sx + 1);
 | 
			
		||||
	msg[c->sx] = '\0';
 | 
			
		||||
 | 
			
		||||
	size = strlen(msg);
 | 
			
		||||
	if (size < c->sx)
 | 
			
		||||
		memset(msg + size, ' ', c->sx - size);
 | 
			
		||||
 | 
			
		||||
	screen_redraw_move_cursor(&ctx, 0, c->sy - 1);
 | 
			
		||||
	screen_redraw_set_attributes(&ctx, ATTR_REVERSE, 0x88);
 | 
			
		||||
	screen_redraw_write_string(&ctx, "%s", msg);
 | 
			
		||||
 | 
			
		||||
	buffer_flush(c->tty.fd, c->tty.in, c->tty.out);
 | 
			
		||||
	usleep(750000);
 | 
			
		||||
 | 
			
		||||
	memset(msg, ' ', c->sx);
 | 
			
		||||
 | 
			
		||||
	screen_redraw_move_cursor(&ctx, 0, c->sy - 1);
 | 
			
		||||
	screen_redraw_set_attributes(&ctx, 0, 0x88);
 | 
			
		||||
	screen_redraw_write_string(&ctx, "%s", msg);
 | 
			
		||||
	server_set_client_message(c, msg);
 | 
			
		||||
 | 
			
		||||
	xfree(msg);
 | 
			
		||||
 | 
			
		||||
	if (slines == 0) {
 | 
			
		||||
		screen_redraw_lines(&ctx, c->sy - 1, 1);
 | 
			
		||||
		screen_redraw_stop(&ctx);
 | 
			
		||||
	} else {
 | 
			
		||||
		screen_redraw_stop(&ctx);
 | 
			
		||||
		server_status_client(c);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										59
									
								
								server.c
									
									
									
									
									
								
							
							
						
						
									
										59
									
								
								server.c
									
									
									
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
/* $Id: server.c,v 1.68 2008-06-18 22:21:51 nicm Exp $ */
 | 
			
		||||
/* $Id: server.c,v 1.69 2008-06-19 18:27:55 nicm Exp $ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
			
		||||
@@ -54,7 +54,7 @@ void		 server_handle_window(struct window *);
 | 
			
		||||
void		 server_lost_client(struct client *);
 | 
			
		||||
void	 	 server_lost_window(struct window *);
 | 
			
		||||
void		 server_check_redraw(struct client *);
 | 
			
		||||
void		 server_check_status(struct client *);
 | 
			
		||||
void		 server_check_timers(struct client *);
 | 
			
		||||
void		 server_update_socket(const char *);
 | 
			
		||||
 | 
			
		||||
/* Fork new server. */
 | 
			
		||||
@@ -322,7 +322,7 @@ server_check_redraw(struct client *c)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	xx = c->sx;
 | 
			
		||||
	yy = c->sy - options_get_number(&s->options, "status-lines");
 | 
			
		||||
	yy = c->sy - 1; //options_get_number(&s->options, "status-lines");
 | 
			
		||||
	if (c->flags & CLIENT_REDRAW) {
 | 
			
		||||
		sx = screen_size_x(s->curw->window->screen);
 | 
			
		||||
		sy = screen_size_y(s->curw->window->screen);
 | 
			
		||||
@@ -351,33 +351,47 @@ server_check_redraw(struct client *c)
 | 
			
		||||
		screen_redraw_lines(&ctx, 0, screen_size_y(ctx.s));
 | 
			
		||||
		screen_redraw_stop(&ctx);
 | 
			
		||||
 | 
			
		||||
		status_redraw(c);
 | 
			
		||||
	} else if (c->flags & CLIENT_STATUS)
 | 
			
		||||
		status_redraw(c);
 | 
			
		||||
 | 
			
		||||
	c->flags &= ~(CLIENT_CLEAR|CLIENT_REDRAW|CLIENT_STATUS);
 | 
			
		||||
		c->flags |= CLIENT_STATUS;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
/* Check for status line redraw on client. */
 | 
			
		||||
	if (c->flags & CLIENT_STATUS) {
 | 
			
		||||
		if (c->message_string != NULL)
 | 
			
		||||
			status_message_redraw(c);
 | 
			
		||||
		else
 | 
			
		||||
			status_redraw(c);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	c->flags &= ~(CLIENT_REDRAW|CLIENT_STATUS);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Check for timers on client. */
 | 
			
		||||
void
 | 
			
		||||
server_check_status(struct client *c)
 | 
			
		||||
server_check_timers(struct client *c)
 | 
			
		||||
{
 | 
			
		||||
	struct timespec	 ts;
 | 
			
		||||
	struct session	*s;
 | 
			
		||||
	struct timespec	 ts, ts2;
 | 
			
		||||
	u_int		 nlines, interval;
 | 
			
		||||
 | 
			
		||||
	if (c == NULL || c->session == NULL)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	nlines = options_get_number(&c->session->options, "status-lines");
 | 
			
		||||
	interval = options_get_number(&c->session->options, "status-interval");
 | 
			
		||||
	if (nlines == 0 || interval == 0)
 | 
			
		||||
		return;
 | 
			
		||||
	s = c->session;
 | 
			
		||||
 | 
			
		||||
	if (clock_gettime(CLOCK_REALTIME, &ts) != 0)
 | 
			
		||||
		fatal("clock_gettime");
 | 
			
		||||
	ts.tv_sec -= interval;
 | 
			
		||||
	
 | 
			
		||||
	if (timespeccmp(&c->status_ts, &ts, <))
 | 
			
		||||
	if (c->message_string != NULL && timespeccmp(&ts, &c->message_timer, >))
 | 
			
		||||
		server_clear_client_message(c);
 | 
			
		||||
 | 
			
		||||
	nlines = options_get_number(&s->options, "status-lines");
 | 
			
		||||
	if (nlines == 0)
 | 
			
		||||
		return;
 | 
			
		||||
	interval = options_get_number(&s->options, "status-interval");
 | 
			
		||||
	if (interval == 0)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	memcpy(&ts2, &ts, sizeof ts2);
 | 
			
		||||
	ts2.tv_sec -= interval;
 | 
			
		||||
	if (timespeccmp(&c->status_timer, &ts2, <))
 | 
			
		||||
		c->flags |= CLIENT_STATUS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -391,8 +405,8 @@ server_fill_clients(struct pollfd **pfd)
 | 
			
		||||
	for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
 | 
			
		||||
		c = ARRAY_ITEM(&clients, i);
 | 
			
		||||
 | 
			
		||||
		server_check_timers(c);
 | 
			
		||||
		server_check_redraw(c);
 | 
			
		||||
		server_check_status(c);
 | 
			
		||||
 | 
			
		||||
		if (c == NULL)
 | 
			
		||||
			(*pfd)->fd = -1;
 | 
			
		||||
@@ -483,6 +497,12 @@ server_accept_client(int srv_fd)
 | 
			
		||||
	c->sx = 80;
 | 
			
		||||
	c->sy = 25;
 | 
			
		||||
 | 
			
		||||
	c->message_string = NULL;
 | 
			
		||||
 | 
			
		||||
	c->prompt_string = NULL;
 | 
			
		||||
	c->prompt_buffer = NULL;
 | 
			
		||||
	c->prompt_size = 0;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
 | 
			
		||||
		if (ARRAY_ITEM(&clients, i) == NULL) {
 | 
			
		||||
			ARRAY_SET(&clients, i, c);
 | 
			
		||||
@@ -502,6 +522,7 @@ server_handle_client(struct client *c)
 | 
			
		||||
 | 
			
		||||
	prefix = options_get_key(&c->session->options, "prefix-key");
 | 
			
		||||
	while (tty_keys_next(&c->tty, &key) == 0) {
 | 
			
		||||
		server_clear_client_message(c);
 | 
			
		||||
		if (c->flags & CLIENT_PREFIX) {
 | 
			
		||||
			key_bindings_dispatch(key, c);
 | 
			
		||||
			c->flags &= ~CLIENT_PREFIX;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										60
									
								
								status.c
									
									
									
									
									
								
							
							
						
						
									
										60
									
								
								status.c
									
									
									
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
/* $Id: status.c,v 1.30 2008-06-18 22:21:51 nicm Exp $ */
 | 
			
		||||
/* $Id: status.c,v 1.31 2008-06-19 18:27:55 nicm Exp $ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
			
		||||
@@ -39,14 +39,15 @@ status_redraw(struct client *c)
 | 
			
		||||
	size_t				llen, rlen, offset, xx, yy;
 | 
			
		||||
	size_t				size, start, width;
 | 
			
		||||
	u_char		 		attr, colr;
 | 
			
		||||
	struct tm		       *tm;
 | 
			
		||||
	int				larrow, rarrow;
 | 
			
		||||
 | 
			
		||||
	yy = options_get_number(&s->options, "status-lines");
 | 
			
		||||
	if (c->sy == 0 || yy == 0)
 | 
			
		||||
		return;
 | 
			
		||||
		goto off;
 | 
			
		||||
	larrow = rarrow = 0;
 | 
			
		||||
 | 
			
		||||
	if (clock_gettime(CLOCK_REALTIME, &c->status_ts) != 0)
 | 
			
		||||
	if (clock_gettime(CLOCK_REALTIME, &c->status_timer) != 0)
 | 
			
		||||
		fatal("clock_gettime failed");
 | 
			
		||||
	colr = options_get_colours(&s->options, "status-colour");
 | 
			
		||||
 | 
			
		||||
@@ -54,11 +55,12 @@ status_redraw(struct client *c)
 | 
			
		||||
	if (yy == 0)
 | 
			
		||||
		goto blank;
 | 
			
		||||
 | 
			
		||||
	tm = localtime(&(c->status_timer.tv_sec));
 | 
			
		||||
	left = options_get_string(&s->options, "status-left");
 | 
			
		||||
	strftime(lbuf, sizeof lbuf, left, localtime(&(c->status_ts.tv_sec)));
 | 
			
		||||
	strftime(lbuf, sizeof lbuf, left, tm);
 | 
			
		||||
	llen = strlen(lbuf);
 | 
			
		||||
	right = options_get_string(&s->options, "status-right");
 | 
			
		||||
	strftime(rbuf, sizeof rbuf, right, localtime(&(c->status_ts.tv_sec)));
 | 
			
		||||
	strftime(rbuf, sizeof rbuf, right, tm);
 | 
			
		||||
	rlen = strlen(rbuf);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
@@ -229,6 +231,26 @@ blank:
 | 
			
		||||
	for (offset = 0; offset < c->sx; offset++)
 | 
			
		||||
		ctx.write(ctx.data, TTY_CHARACTER, ' ');
 | 
			
		||||
	screen_redraw_stop(&ctx);
 | 
			
		||||
 | 
			
		||||
	return;
 | 
			
		||||
 | 
			
		||||
off:
 | 
			
		||||
	/*
 | 
			
		||||
	 * Draw the real window last line. Necessary to wipe over message if
 | 
			
		||||
	 * status is off. Not sure this is the right place for this.
 | 
			
		||||
	 */
 | 
			
		||||
	screen_redraw_start_client(&ctx, c);
 | 
			
		||||
	/* If the screen is too small, use blank. */
 | 
			
		||||
	if (screen_size_y(c->session->curw->window->screen) < c->sy) {
 | 
			
		||||
		screen_redraw_move_cursor(&ctx, 0, c->sy - 1);
 | 
			
		||||
		screen_redraw_set_attributes(&ctx, 0, 0x88);
 | 
			
		||||
		for (offset = 0; offset < c->sx; offset++)
 | 
			
		||||
			ctx.write(ctx.data, TTY_CHARACTER, ' ');
 | 
			
		||||
	} else
 | 
			
		||||
		screen_redraw_lines(&ctx, c->sy - 1, 1);
 | 
			
		||||
	screen_redraw_stop(&ctx);
 | 
			
		||||
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
size_t
 | 
			
		||||
@@ -261,3 +283,31 @@ status_print(struct session *s, struct winlink *wl, u_char *attr)
 | 
			
		||||
	xasprintf(&text, "%d:%s%c", wl->idx, wl->window->name, flag);
 | 
			
		||||
	return (text);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Draw client message on status line of present else on last line. */
 | 
			
		||||
void
 | 
			
		||||
status_message_redraw(struct client *c)
 | 
			
		||||
{
 | 
			
		||||
	struct screen_redraw_ctx	ctx;
 | 
			
		||||
	size_t			        xx, yy;
 | 
			
		||||
 | 
			
		||||
	if (c->sx == 0 || c->sy == 0)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	xx = strlen(c->message_string);
 | 
			
		||||
	if (xx > c->sx)
 | 
			
		||||
		xx = c->sx;
 | 
			
		||||
	yy = c->sy - 1;		
 | 
			
		||||
 | 
			
		||||
	screen_redraw_start_client(&ctx, c);
 | 
			
		||||
	screen_redraw_set_attributes(&ctx, ATTR_REVERSE, 0x88);
 | 
			
		||||
 | 
			
		||||
	screen_redraw_move_cursor(&ctx, 0, yy);
 | 
			
		||||
	screen_redraw_write_string(&ctx, "%.*s", (int) xx, c->message_string);
 | 
			
		||||
	for (; xx < c->sx; xx++)
 | 
			
		||||
		ctx.write(ctx.data, TTY_CHARACTER, ' ');
 | 
			
		||||
	screen_redraw_stop(&ctx);
 | 
			
		||||
 | 
			
		||||
	/* Force cursor off. */
 | 
			
		||||
	tty_write_client(c, TTY_CURSOROFF);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										15
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								tmux.h
									
									
									
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
/* $Id: tmux.h,v 1.151 2008-06-18 20:58:03 nicm Exp $ */
 | 
			
		||||
/* $Id: tmux.h,v 1.152 2008-06-19 18:27:55 nicm Exp $ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
			
		||||
@@ -664,7 +664,7 @@ struct client {
 | 
			
		||||
	char		*title;
 | 
			
		||||
 | 
			
		||||
	struct tty 	 tty;
 | 
			
		||||
	struct timespec	 status_ts;
 | 
			
		||||
	struct timespec	 status_timer;
 | 
			
		||||
 | 
			
		||||
	u_int		 sx;
 | 
			
		||||
	u_int		 sy;
 | 
			
		||||
@@ -674,9 +674,15 @@ struct client {
 | 
			
		||||
#define CLIENT_MOUSE 0x4
 | 
			
		||||
#define CLIENT_REDRAW 0x8
 | 
			
		||||
#define CLIENT_STATUS 0x10
 | 
			
		||||
#define CLIENT_CLEAR 0x20
 | 
			
		||||
	int		 flags;
 | 
			
		||||
 | 
			
		||||
	char		*message_string;
 | 
			
		||||
	struct timespec	 message_timer;
 | 
			
		||||
 | 
			
		||||
	char		*prompt_string;
 | 
			
		||||
	char		*prompt_buffer;
 | 
			
		||||
	size_t		 prompt_size;
 | 
			
		||||
 | 
			
		||||
	struct session	*session;
 | 
			
		||||
};
 | 
			
		||||
ARRAY_DECL(clients, struct client *);
 | 
			
		||||
@@ -949,6 +955,8 @@ int	 server_start(const char *);
 | 
			
		||||
int	 server_msg_dispatch(struct client *);
 | 
			
		||||
 | 
			
		||||
/* server-fn.c */
 | 
			
		||||
void	 server_set_client_message(struct client *, const char *);
 | 
			
		||||
void	 server_clear_client_message(struct client *);
 | 
			
		||||
struct session *server_extract_session(
 | 
			
		||||
    	     struct msg_command_data *, char *, char **);
 | 
			
		||||
void	 server_write_client(
 | 
			
		||||
@@ -967,6 +975,7 @@ void printflike2 server_write_message(struct client *, const char *, ...);
 | 
			
		||||
 | 
			
		||||
/* status.c */
 | 
			
		||||
void	 status_redraw(struct client *c);
 | 
			
		||||
void	 status_message_redraw(struct client *c);
 | 
			
		||||
 | 
			
		||||
/* resize.c */
 | 
			
		||||
void	 recalculate_sizes(void);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user