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.
pull/1920/head
nicm 2019-09-19 09:02:30 +00:00
parent d018477359
commit 647887b794
10 changed files with 147 additions and 74 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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
View File

@ -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);
}

View File

@ -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();

View File

@ -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
View File

@ -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
View File

@ -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 */