mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 00:56:10 +00:00 
			
		
		
		
	Add a "latest" window-size option which tries to size windows based on
the most recently used client. From Tommie Gannert in GitHub issue 1869 based on earlier changes from me.
This commit is contained in:
		@@ -81,6 +81,7 @@ cmd_break_pane_exec(struct cmd *self, struct cmdq_item *item)
 | 
			
		||||
	wp->flags |= PANE_STYLECHANGED;
 | 
			
		||||
	TAILQ_INSERT_HEAD(&w->panes, wp, entry);
 | 
			
		||||
	w->active = wp;
 | 
			
		||||
	w->latest = c;
 | 
			
		||||
 | 
			
		||||
	if (!args_has(args, 'n')) {
 | 
			
		||||
		name = default_window_name(w);
 | 
			
		||||
 
 | 
			
		||||
@@ -259,6 +259,7 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
 | 
			
		||||
	memset(&sc, 0, sizeof sc);
 | 
			
		||||
	sc.item = item;
 | 
			
		||||
	sc.s = s;
 | 
			
		||||
	sc.c = c;
 | 
			
		||||
 | 
			
		||||
	sc.name = args_get(args, 'n');
 | 
			
		||||
	sc.argc = args->argc;
 | 
			
		||||
 
 | 
			
		||||
@@ -72,6 +72,7 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item)
 | 
			
		||||
	memset(&sc, 0, sizeof sc);
 | 
			
		||||
	sc.item = item;
 | 
			
		||||
	sc.s = s;
 | 
			
		||||
	sc.c = c;
 | 
			
		||||
 | 
			
		||||
	sc.name = args_get(args, 'n');
 | 
			
		||||
	sc.argc = args->argc;
 | 
			
		||||
 
 | 
			
		||||
@@ -59,6 +59,7 @@ cmd_respawn_window_exec(struct cmd *self, struct cmdq_item *item)
 | 
			
		||||
	sc.item = item;
 | 
			
		||||
	sc.s = s;
 | 
			
		||||
	sc.wl = wl;
 | 
			
		||||
	sc.c = cmd_find_client(item, NULL, 1);
 | 
			
		||||
 | 
			
		||||
	sc.name = NULL;
 | 
			
		||||
	sc.argc = args->argc;
 | 
			
		||||
 
 | 
			
		||||
@@ -64,7 +64,7 @@ static const char *options_table_set_clipboard_list[] = {
 | 
			
		||||
	"off", "external", "on", NULL
 | 
			
		||||
};
 | 
			
		||||
static const char *options_table_window_size_list[] = {
 | 
			
		||||
	"largest", "smallest", "manual", NULL
 | 
			
		||||
	"largest", "smallest", "manual", "latest", NULL
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Status line format. */
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										183
									
								
								resize.c
									
									
									
									
									
								
							
							
						
						
									
										183
									
								
								resize.c
									
									
									
									
									
								
							@@ -149,14 +149,121 @@ done:
 | 
			
		||||
		*sy = WINDOW_MAXIMUM;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
recalculate_size(struct window *w)
 | 
			
		||||
{
 | 
			
		||||
	struct session	*s;
 | 
			
		||||
	struct client	*c;
 | 
			
		||||
	u_int		 sx, sy, cx, cy;
 | 
			
		||||
	int		 type, current, has, changed;
 | 
			
		||||
 | 
			
		||||
	if (w->active == NULL)
 | 
			
		||||
		return;
 | 
			
		||||
	log_debug("%s: @%u is %u,%u", __func__, w->id, w->sx, w->sy);
 | 
			
		||||
 | 
			
		||||
	type = options_get_number(w->options, "window-size");
 | 
			
		||||
	current = options_get_number(w->options, "aggressive-resize");
 | 
			
		||||
 | 
			
		||||
	changed = 1;
 | 
			
		||||
	switch (type) {
 | 
			
		||||
	case WINDOW_SIZE_LARGEST:
 | 
			
		||||
		sx = sy = 0;
 | 
			
		||||
		TAILQ_FOREACH(c, &clients, entry) {
 | 
			
		||||
			if (ignore_client_size(c))
 | 
			
		||||
				continue;
 | 
			
		||||
			s = c->session;
 | 
			
		||||
 | 
			
		||||
			if (current)
 | 
			
		||||
				has = (s->curw->window == w);
 | 
			
		||||
			else
 | 
			
		||||
				has = session_has(s, w);
 | 
			
		||||
			if (!has)
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			cx = c->tty.sx;
 | 
			
		||||
			cy = c->tty.sy - status_line_size(c);
 | 
			
		||||
 | 
			
		||||
			if (cx > sx)
 | 
			
		||||
				sx = cx;
 | 
			
		||||
			if (cy > sy)
 | 
			
		||||
				sy = cy;
 | 
			
		||||
		}
 | 
			
		||||
		if (sx == 0 || sy == 0)
 | 
			
		||||
			changed = 0;
 | 
			
		||||
		break;
 | 
			
		||||
	case WINDOW_SIZE_SMALLEST:
 | 
			
		||||
		sx = sy = UINT_MAX;
 | 
			
		||||
		TAILQ_FOREACH(c, &clients, entry) {
 | 
			
		||||
			if (ignore_client_size(c))
 | 
			
		||||
				continue;
 | 
			
		||||
			s = c->session;
 | 
			
		||||
 | 
			
		||||
			if (current)
 | 
			
		||||
				has = (s->curw->window == w);
 | 
			
		||||
			else
 | 
			
		||||
				has = session_has(s, w);
 | 
			
		||||
			if (!has)
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			cx = c->tty.sx;
 | 
			
		||||
			cy = c->tty.sy - status_line_size(c);
 | 
			
		||||
 | 
			
		||||
			if (cx < sx)
 | 
			
		||||
				sx = cx;
 | 
			
		||||
			if (cy < sy)
 | 
			
		||||
				sy = cy;
 | 
			
		||||
		}
 | 
			
		||||
		if (sx == UINT_MAX || sy == UINT_MAX)
 | 
			
		||||
			changed = 0;
 | 
			
		||||
		break;
 | 
			
		||||
	case WINDOW_SIZE_LATEST:
 | 
			
		||||
		sx = sy = UINT_MAX;
 | 
			
		||||
		TAILQ_FOREACH(c, &clients, entry) {
 | 
			
		||||
			if (ignore_client_size(c))
 | 
			
		||||
				continue;
 | 
			
		||||
			if (c != w->latest)
 | 
			
		||||
				continue;
 | 
			
		||||
			s = c->session;
 | 
			
		||||
 | 
			
		||||
			if (current)
 | 
			
		||||
				has = (s->curw->window == w);
 | 
			
		||||
			else
 | 
			
		||||
				has = session_has(s, w);
 | 
			
		||||
			if (!has)
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			cx = c->tty.sx;
 | 
			
		||||
			cy = c->tty.sy - status_line_size(c);
 | 
			
		||||
 | 
			
		||||
			if (cx < sx)
 | 
			
		||||
				sx = cx;
 | 
			
		||||
			if (cy < sy)
 | 
			
		||||
				sy = cy;
 | 
			
		||||
		}
 | 
			
		||||
		if (sx == UINT_MAX || sy == UINT_MAX)
 | 
			
		||||
			changed = 0;
 | 
			
		||||
		break;
 | 
			
		||||
	case WINDOW_SIZE_MANUAL:
 | 
			
		||||
		changed = 0;
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	if (changed && w->sx == sx && w->sy == sy)
 | 
			
		||||
		changed = 0;
 | 
			
		||||
 | 
			
		||||
	if (!changed) {
 | 
			
		||||
		tty_update_window_offset(w);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	log_debug("%s: @%u changed to %u,%u", __func__, w->id, sx, sy);
 | 
			
		||||
	resize_window(w, sx, sy);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
recalculate_sizes(void)
 | 
			
		||||
{
 | 
			
		||||
	struct session	*s;
 | 
			
		||||
	struct client	*c;
 | 
			
		||||
	struct window	*w;
 | 
			
		||||
	u_int		 sx, sy, cx, cy;
 | 
			
		||||
	int		 type, current, has, changed;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Clear attached count and update saved status line information for
 | 
			
		||||
@@ -183,74 +290,6 @@ recalculate_sizes(void)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Walk each window and adjust the size. */
 | 
			
		||||
	RB_FOREACH(w, windows, &windows) {
 | 
			
		||||
		if (w->active == NULL)
 | 
			
		||||
			continue;
 | 
			
		||||
		log_debug("%s: @%u is %u,%u", __func__, w->id, w->sx, w->sy);
 | 
			
		||||
 | 
			
		||||
		type = options_get_number(w->options, "window-size");
 | 
			
		||||
		if (type == WINDOW_SIZE_MANUAL)
 | 
			
		||||
			continue;
 | 
			
		||||
		current = options_get_number(w->options, "aggressive-resize");
 | 
			
		||||
 | 
			
		||||
		changed = 1;
 | 
			
		||||
		if (type == WINDOW_SIZE_LARGEST) {
 | 
			
		||||
			sx = sy = 0;
 | 
			
		||||
			TAILQ_FOREACH(c, &clients, entry) {
 | 
			
		||||
				if (ignore_client_size(c))
 | 
			
		||||
					continue;
 | 
			
		||||
				s = c->session;
 | 
			
		||||
 | 
			
		||||
				if (current)
 | 
			
		||||
					has = (s->curw->window == w);
 | 
			
		||||
				else
 | 
			
		||||
					has = session_has(s, w);
 | 
			
		||||
				if (!has)
 | 
			
		||||
					continue;
 | 
			
		||||
 | 
			
		||||
				cx = c->tty.sx;
 | 
			
		||||
				cy = c->tty.sy - status_line_size(c);
 | 
			
		||||
 | 
			
		||||
				if (cx > sx)
 | 
			
		||||
					sx = cx;
 | 
			
		||||
				if (cy > sy)
 | 
			
		||||
					sy = cy;
 | 
			
		||||
			}
 | 
			
		||||
			if (sx == 0 || sy == 0)
 | 
			
		||||
				changed = 0;
 | 
			
		||||
		} else {
 | 
			
		||||
			sx = sy = UINT_MAX;
 | 
			
		||||
			TAILQ_FOREACH(c, &clients, entry) {
 | 
			
		||||
				if (ignore_client_size(c))
 | 
			
		||||
					continue;
 | 
			
		||||
				s = c->session;
 | 
			
		||||
 | 
			
		||||
				if (current)
 | 
			
		||||
					has = (s->curw->window == w);
 | 
			
		||||
				else
 | 
			
		||||
					has = session_has(s, w);
 | 
			
		||||
				if (!has)
 | 
			
		||||
					continue;
 | 
			
		||||
 | 
			
		||||
				cx = c->tty.sx;
 | 
			
		||||
				cy = c->tty.sy - status_line_size(c);
 | 
			
		||||
 | 
			
		||||
				if (cx < sx)
 | 
			
		||||
					sx = cx;
 | 
			
		||||
				if (cy < sy)
 | 
			
		||||
					sy = cy;
 | 
			
		||||
			}
 | 
			
		||||
			if (sx == UINT_MAX || sy == UINT_MAX)
 | 
			
		||||
				changed = 0;
 | 
			
		||||
		}
 | 
			
		||||
		if (w->sx == sx && w->sy == sy)
 | 
			
		||||
			changed = 0;
 | 
			
		||||
 | 
			
		||||
		if (!changed) {
 | 
			
		||||
			tty_update_window_offset(w);
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		log_debug("%s: @%u changed to %u,%u", __func__, w->id, sx, sy);
 | 
			
		||||
		resize_window(w, sx, sy);
 | 
			
		||||
	}
 | 
			
		||||
	RB_FOREACH(w, windows, &windows)
 | 
			
		||||
		recalculate_size(w);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -996,6 +996,24 @@ server_client_assume_paste(struct session *s)
 | 
			
		||||
	return (0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Has the latest client changed? */
 | 
			
		||||
static void
 | 
			
		||||
server_client_update_latest(struct client *c)
 | 
			
		||||
{
 | 
			
		||||
	struct window	*w;
 | 
			
		||||
 | 
			
		||||
	if (c->session == NULL)
 | 
			
		||||
		return;
 | 
			
		||||
	w = c->session->curw->window;
 | 
			
		||||
 | 
			
		||||
	if (w->latest == c)
 | 
			
		||||
		return;
 | 
			
		||||
	w->latest = c;
 | 
			
		||||
 | 
			
		||||
	if (options_get_number(w->options, "window-size") == WINDOW_SIZE_LATEST)
 | 
			
		||||
		recalculate_size(w);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Handle data key input from client. This owns and can modify the key event it
 | 
			
		||||
 * is given and is responsible for freeing it.
 | 
			
		||||
@@ -1192,6 +1210,8 @@ forward_key:
 | 
			
		||||
		window_pane_key(wp, c, s, wl, key, m);
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
	if (s != NULL)
 | 
			
		||||
		server_client_update_latest(c);
 | 
			
		||||
	free(event);
 | 
			
		||||
	return (CMD_RETURN_NORMAL);
 | 
			
		||||
}
 | 
			
		||||
@@ -1737,6 +1757,7 @@ server_client_dispatch(struct imsg *imsg, void *arg)
 | 
			
		||||
 | 
			
		||||
		if (c->flags & CLIENT_CONTROL)
 | 
			
		||||
			break;
 | 
			
		||||
		server_client_update_latest(c);
 | 
			
		||||
		server_client_clear_overlay(c);
 | 
			
		||||
		tty_resize(&c->tty);
 | 
			
		||||
		recalculate_sizes();
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								spawn.c
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								spawn.c
									
									
									
									
									
								
							@@ -164,6 +164,7 @@ spawn_window(struct spawn_context *sc, char **cause)
 | 
			
		||||
		if (s->curw == NULL)
 | 
			
		||||
			s->curw = sc->wl;
 | 
			
		||||
		sc->wl->session = s;
 | 
			
		||||
		w->latest = sc->c;
 | 
			
		||||
		winlink_set_window(sc->wl, w);
 | 
			
		||||
	} else
 | 
			
		||||
		w = NULL;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										6
									
								
								tmux.1
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								tmux.1
									
									
									
									
									
								
							@@ -3659,7 +3659,7 @@ see the
 | 
			
		||||
section.
 | 
			
		||||
.Pp
 | 
			
		||||
.It Xo Ic window-size
 | 
			
		||||
.Ar largest | Ar smallest | Ar manual
 | 
			
		||||
.Ar largest | Ar smallest | Ar manual | Ar latest
 | 
			
		||||
.Xc
 | 
			
		||||
Configure how
 | 
			
		||||
.Nm
 | 
			
		||||
@@ -3674,6 +3674,10 @@ If
 | 
			
		||||
the size of a new window is set from the
 | 
			
		||||
.Ic default-size
 | 
			
		||||
option and windows are resized automatically.
 | 
			
		||||
With
 | 
			
		||||
.Ar latest ,
 | 
			
		||||
.Nm
 | 
			
		||||
uses the size of the client that had the most recent activity.
 | 
			
		||||
See also the
 | 
			
		||||
.Ic resize-window
 | 
			
		||||
command and the
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								tmux.h
									
									
									
									
									
								
							@@ -905,6 +905,7 @@ RB_HEAD(window_pane_tree, window_pane);
 | 
			
		||||
/* Window structure. */
 | 
			
		||||
struct window {
 | 
			
		||||
	u_int		 id;
 | 
			
		||||
	void		*latest;
 | 
			
		||||
 | 
			
		||||
	char		*name;
 | 
			
		||||
	struct event	 name_event;
 | 
			
		||||
@@ -970,6 +971,7 @@ TAILQ_HEAD(winlink_stack, winlink);
 | 
			
		||||
#define WINDOW_SIZE_LARGEST 0
 | 
			
		||||
#define WINDOW_SIZE_SMALLEST 1
 | 
			
		||||
#define WINDOW_SIZE_MANUAL 2
 | 
			
		||||
#define WINDOW_SIZE_LATEST 3
 | 
			
		||||
 | 
			
		||||
/* Pane border status option. */
 | 
			
		||||
#define PANE_STATUS_OFF 0
 | 
			
		||||
@@ -1670,6 +1672,7 @@ struct spawn_context {
 | 
			
		||||
 | 
			
		||||
	struct session		 *s;
 | 
			
		||||
	struct winlink		 *wl;
 | 
			
		||||
	struct client		 *c;
 | 
			
		||||
 | 
			
		||||
	struct window_pane	 *wp0;
 | 
			
		||||
	struct layout_cell	 *lc;
 | 
			
		||||
@@ -2195,6 +2198,7 @@ void	 status_prompt_save_history(void);
 | 
			
		||||
void	 resize_window(struct window *, u_int, u_int);
 | 
			
		||||
void	 default_window_size(struct session *, struct window *, u_int *,
 | 
			
		||||
	     u_int *, int);
 | 
			
		||||
void	 recalculate_size(struct window *);
 | 
			
		||||
void	 recalculate_sizes(void);
 | 
			
		||||
 | 
			
		||||
/* input.c */
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user