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:
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; wp->flags |= PANE_STYLECHANGED;
TAILQ_INSERT_HEAD(&w->panes, wp, entry); TAILQ_INSERT_HEAD(&w->panes, wp, entry);
w->active = wp; w->active = wp;
w->latest = c;
if (!args_has(args, 'n')) { if (!args_has(args, 'n')) {
name = default_window_name(w); 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); memset(&sc, 0, sizeof sc);
sc.item = item; sc.item = item;
sc.s = s; sc.s = s;
sc.c = c;
sc.name = args_get(args, 'n'); sc.name = args_get(args, 'n');
sc.argc = args->argc; 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); memset(&sc, 0, sizeof sc);
sc.item = item; sc.item = item;
sc.s = s; sc.s = s;
sc.c = c;
sc.name = args_get(args, 'n'); sc.name = args_get(args, 'n');
sc.argc = args->argc; 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.item = item;
sc.s = s; sc.s = s;
sc.wl = wl; sc.wl = wl;
sc.c = cmd_find_client(item, NULL, 1);
sc.name = NULL; sc.name = NULL;
sc.argc = args->argc; sc.argc = args->argc;

View File

@ -64,7 +64,7 @@ static const char *options_table_set_clipboard_list[] = {
"off", "external", "on", NULL "off", "external", "on", NULL
}; };
static const char *options_table_window_size_list[] = { static const char *options_table_window_size_list[] = {
"largest", "smallest", "manual", NULL "largest", "smallest", "manual", "latest", NULL
}; };
/* Status line format. */ /* Status line format. */

183
resize.c
View File

@ -149,14 +149,121 @@ done:
*sy = WINDOW_MAXIMUM; *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 void
recalculate_sizes(void) recalculate_sizes(void)
{ {
struct session *s; struct session *s;
struct client *c; struct client *c;
struct window *w; struct window *w;
u_int sx, sy, cx, cy;
int type, current, has, changed;
/* /*
* Clear attached count and update saved status line information for * Clear attached count and update saved status line information for
@ -183,74 +290,6 @@ recalculate_sizes(void)
} }
/* Walk each window and adjust the size. */ /* Walk each window and adjust the size. */
RB_FOREACH(w, windows, &windows) { RB_FOREACH(w, windows, &windows)
if (w->active == NULL) recalculate_size(w);
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);
}
} }

View File

@ -996,6 +996,24 @@ server_client_assume_paste(struct session *s)
return (0); 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 * Handle data key input from client. This owns and can modify the key event it
* is given and is responsible for freeing it. * is given and is responsible for freeing it.
@ -1192,6 +1210,8 @@ forward_key:
window_pane_key(wp, c, s, wl, key, m); window_pane_key(wp, c, s, wl, key, m);
out: out:
if (s != NULL)
server_client_update_latest(c);
free(event); free(event);
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);
} }
@ -1737,6 +1757,7 @@ server_client_dispatch(struct imsg *imsg, void *arg)
if (c->flags & CLIENT_CONTROL) if (c->flags & CLIENT_CONTROL)
break; break;
server_client_update_latest(c);
server_client_clear_overlay(c); server_client_clear_overlay(c);
tty_resize(&c->tty); tty_resize(&c->tty);
recalculate_sizes(); recalculate_sizes();

View File

@ -164,6 +164,7 @@ spawn_window(struct spawn_context *sc, char **cause)
if (s->curw == NULL) if (s->curw == NULL)
s->curw = sc->wl; s->curw = sc->wl;
sc->wl->session = s; sc->wl->session = s;
w->latest = sc->c;
winlink_set_window(sc->wl, w); winlink_set_window(sc->wl, w);
} else } else
w = NULL; w = NULL;

6
tmux.1
View File

@ -3659,7 +3659,7 @@ see the
section. section.
.Pp .Pp
.It Xo Ic window-size .It Xo Ic window-size
.Ar largest | Ar smallest | Ar manual .Ar largest | Ar smallest | Ar manual | Ar latest
.Xc .Xc
Configure how Configure how
.Nm .Nm
@ -3674,6 +3674,10 @@ If
the size of a new window is set from the the size of a new window is set from the
.Ic default-size .Ic default-size
option and windows are resized automatically. 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 See also the
.Ic resize-window .Ic resize-window
command and the command and the

4
tmux.h
View File

@ -905,6 +905,7 @@ RB_HEAD(window_pane_tree, window_pane);
/* Window structure. */ /* Window structure. */
struct window { struct window {
u_int id; u_int id;
void *latest;
char *name; char *name;
struct event name_event; struct event name_event;
@ -970,6 +971,7 @@ TAILQ_HEAD(winlink_stack, winlink);
#define WINDOW_SIZE_LARGEST 0 #define WINDOW_SIZE_LARGEST 0
#define WINDOW_SIZE_SMALLEST 1 #define WINDOW_SIZE_SMALLEST 1
#define WINDOW_SIZE_MANUAL 2 #define WINDOW_SIZE_MANUAL 2
#define WINDOW_SIZE_LATEST 3
/* Pane border status option. */ /* Pane border status option. */
#define PANE_STATUS_OFF 0 #define PANE_STATUS_OFF 0
@ -1670,6 +1672,7 @@ struct spawn_context {
struct session *s; struct session *s;
struct winlink *wl; struct winlink *wl;
struct client *c;
struct window_pane *wp0; struct window_pane *wp0;
struct layout_cell *lc; struct layout_cell *lc;
@ -2195,6 +2198,7 @@ void status_prompt_save_history(void);
void resize_window(struct window *, u_int, u_int); void resize_window(struct window *, u_int, u_int);
void default_window_size(struct session *, struct window *, u_int *, void default_window_size(struct session *, struct window *, u_int *,
u_int *, int); u_int *, int);
void recalculate_size(struct window *);
void recalculate_sizes(void); void recalculate_sizes(void);
/* input.c */ /* input.c */