=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/tmux/resize.c,v retrieving revision 1.26 retrieving revision 1.27 diff -c -r1.26 -r1.27 *** src/usr.bin/tmux/resize.c 2018/08/18 20:08:52 1.26 --- src/usr.bin/tmux/resize.c 2018/10/18 08:38:01 1.27 *************** *** 1,4 **** ! /* $OpenBSD: resize.c,v 1.26 2018/08/18 20:08:52 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott --- 1,4 ---- ! /* $OpenBSD: resize.c,v 1.27 2018/10/18 08:38:01 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott *************** *** 22,165 **** #include "tmux.h" ! /* ! * Recalculate window and session sizes. ! * ! * Every session has the size of the smallest client it is attached to and ! * every window the size of the smallest session it is attached to. ! * ! * So, when a client is resized or a session attached to or detached from a ! * client, the window sizes must be recalculated. For each session, find the ! * smallest client it is attached to, and resize it to that size. Then for ! * every window, find the smallest session it is attached to, resize it to that ! * size and clear and redraw every client with it as the current window. ! * ! * This is quite inefficient - better/additional data structures are needed ! * to make it better. ! */ void ! recalculate_sizes(void) { ! struct session *s; ! struct client *c; ! struct window *w; ! struct window_pane *wp; ! u_int ssx, ssy, has, limit, lines; ! int flag, is_zoomed, forced; ! RB_FOREACH(s, sessions, &sessions) { ! lines = status_line_size(s); ! s->attached = 0; ! ssx = ssy = UINT_MAX; TAILQ_FOREACH(c, &clients, entry) { ! if (c->flags & CLIENT_SUSPENDED) continue; ! if ((c->flags & (CLIENT_CONTROL|CLIENT_SIZECHANGED)) == ! CLIENT_CONTROL) continue; ! if (c->session == s) { ! if (c->tty.sx < ssx) ! ssx = c->tty.sx; ! c->flags &= ~CLIENT_STATUSOFF; ! if (lines != 0 && lines + PANE_MINIMUM > c->tty.sy) ! c->flags |= CLIENT_STATUSOFF; ! if ((~c->flags & CLIENT_STATUSOFF) && ! !(c->flags & CLIENT_CONTROL) && ! c->tty.sy > lines && ! c->tty.sy - lines < ssy) ! ssy = c->tty.sy - lines; ! else if (c->tty.sy < ssy) ! ssy = c->tty.sy; ! s->attached++; ! } } ! if (ssx == UINT_MAX || ssy == UINT_MAX) ! continue; ! if (lines != 0 && ssy == 0) ! ssy = lines; ! if (s->sx == ssx && s->sy == ssy) ! continue; ! log_debug("session $%u size %u,%u (was %u,%u)", s->id, ssx, ssy, ! s->sx, s->sy); ! s->sx = ssx; ! s->sy = ssy; status_update_saved(s); } RB_FOREACH(w, windows, &windows) { if (w->active == NULL) continue; ! flag = options_get_number(w->options, "aggressive-resize"); ! ssx = ssy = UINT_MAX; ! RB_FOREACH(s, sessions, &sessions) { ! if (s->attached == 0) ! continue; ! if (flag) ! has = s->curw->window == w; ! else ! has = session_has(s, w); ! if (has) { ! if (s->sx < ssx) ! ssx = s->sx; ! if (s->sy < ssy) ! ssy = s->sy; ! } ! } ! if (ssx == UINT_MAX || ssy == UINT_MAX) continue; ! forced = 0; ! limit = options_get_number(w->options, "force-width"); ! if (limit >= PANE_MINIMUM && ssx > limit) { ! ssx = limit; ! forced |= WINDOW_FORCEWIDTH; ! } ! limit = options_get_number(w->options, "force-height"); ! if (limit >= PANE_MINIMUM && ssy > limit) { ! ssy = limit; ! forced |= WINDOW_FORCEHEIGHT; ! } ! if (w->sx == ssx && w->sy == ssy) ! continue; ! log_debug("window @%u size %u,%u (was %u,%u)", w->id, ssx, ssy, ! w->sx, w->sy); ! w->flags &= ~(WINDOW_FORCEWIDTH|WINDOW_FORCEHEIGHT); ! w->flags |= forced; ! is_zoomed = w->flags & WINDOW_ZOOMED; ! if (is_zoomed) ! window_unzoom(w); ! layout_resize(w, ssx, ssy); ! window_resize(w, ssx, ssy); ! if (is_zoomed && window_pane_visible(w->active)) ! window_zoom(w->active); ! /* ! * If the current pane is now not visible, move to the next ! * that is. ! */ ! wp = w->active; ! while (!window_pane_visible(w->active)) { ! w->active = TAILQ_PREV(w->active, window_panes, entry); ! if (w->active == NULL) ! w->active = TAILQ_LAST(&w->panes, window_panes); ! if (w->active == wp) ! break; } ! if (w->active == w->last) ! w->last = NULL; ! server_redraw_window(w); ! notify_window("window-layout-changed", w); } } --- 22,249 ---- #include "tmux.h" ! void ! resize_window(struct window *w, u_int sx, u_int sy) ! { ! int zoomed; + /* Check size limits. */ + if (sx < WINDOW_MINIMUM) + sx = WINDOW_MINIMUM; + if (sx > WINDOW_MAXIMUM) + sx = WINDOW_MAXIMUM; + if (sy < WINDOW_MINIMUM) + sy = WINDOW_MINIMUM; + if (sy > WINDOW_MAXIMUM) + sy = WINDOW_MAXIMUM; + + /* If the window is zoomed, unzoom. */ + zoomed = w->flags & WINDOW_ZOOMED; + if (zoomed) + window_unzoom(w); + + /* Resize the layout first. */ + layout_resize(w, sx, sy); + + /* Resize the window, it can be no smaller than the layout. */ + if (sx < w->layout_root->sx) + sx = w->layout_root->sx; + if (sy < w->layout_root->sy) + sy = w->layout_root->sy; + window_resize(w, sx, sy); + + /* Restore the window zoom state. */ + if (zoomed) + window_zoom(w->active); + + tty_update_window_offset(w); + server_redraw_window(w); + notify_window("window-layout-changed", w); + } + void ! default_window_size(struct session *s, struct window *w, u_int *sx, u_int *sy, ! int type) { ! struct client *c; ! u_int cx, cy; ! const char *value; ! if (type == -1) ! type = options_get_number(global_w_options, "window-size"); ! if (type == WINDOW_SIZE_MANUAL) ! goto manual; ! if (type == WINDOW_SIZE_LARGEST) { ! *sx = *sy = 0; TAILQ_FOREACH(c, &clients, entry) { ! if (c->session == NULL) continue; ! if (c->flags & CLIENT_NOSIZEFLAGS) continue; ! if (w != NULL && !session_has(c->session, w)) ! continue; ! if (w == NULL && c->session != s) ! 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) ! goto manual; ! } else { ! *sx = *sy = UINT_MAX; ! TAILQ_FOREACH(c, &clients, entry) { ! if (c->session == NULL) ! continue; ! if (c->flags & CLIENT_NOSIZEFLAGS) ! continue; ! if (w != NULL && !session_has(c->session, w)) ! continue; ! if (w == NULL && c->session != s) ! 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) ! goto manual; ! } ! goto done; ! manual: ! value = options_get_string(s->options, "default-size"); ! if (sscanf(value, "%ux%u", sx, sy) != 2) { ! *sx = 80; ! *sy = 24; ! } ! done: ! if (*sx < WINDOW_MINIMUM) ! *sx = WINDOW_MINIMUM; ! if (*sx > WINDOW_MAXIMUM) ! *sx = WINDOW_MAXIMUM; ! if (*sy < WINDOW_MINIMUM) ! *sy = WINDOW_MINIMUM; ! if (*sy > WINDOW_MAXIMUM) ! *sy = WINDOW_MAXIMUM; ! } + void + recalculate_sizes(void) + { + struct session *s; + struct client *c; + struct window *w; + u_int sx, sy, cx, cy; + int flags, type, current, has, changed; + + /* + * Clear attached count and update saved status line information for + * each session. + */ + RB_FOREACH(s, sessions, &sessions) { + s->attached = 0; status_update_saved(s); } + /* + * Increment attached count and check the status line size for each + * client. + */ + TAILQ_FOREACH(c, &clients, entry) { + if ((s = c->session) == NULL) + continue; + + flags = c->flags; + if (flags & CLIENT_SUSPENDED) + continue; + if ((flags & CLIENT_CONTROL) && (~flags & CLIENT_SIZECHANGED)) + continue; + + if (c->tty.sy <= status_line_size(c)) + c->flags |= CLIENT_STATUSOFF; + else + c->flags &= ~CLIENT_STATUSOFF; + + s->attached++; + } + + /* 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 ((s = c->session) == NULL) ! continue; ! 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 ((s = c->session) == NULL) ! continue; ! 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); } }