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