Annotation of src/usr.bin/tmux/resize.c, Revision 1.27
1.27 ! nicm 1: /* $OpenBSD: resize.c,v 1.26 2018/08/18 20:08:52 nicm Exp $ */
1.1 nicm 2:
3: /*
1.19 nicm 4: * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
1.1 nicm 5: *
6: * Permission to use, copy, modify, and distribute this software for any
7: * purpose with or without fee is hereby granted, provided that the above
8: * copyright notice and this permission notice appear in all copies.
9: *
10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14: * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15: * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16: * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17: */
18:
19: #include <sys/types.h>
20:
21: #include <string.h>
22:
23: #include "tmux.h"
24:
1.27 ! nicm 25: void
! 26: resize_window(struct window *w, u_int sx, u_int sy)
! 27: {
! 28: int zoomed;
! 29:
! 30: /* Check size limits. */
! 31: if (sx < WINDOW_MINIMUM)
! 32: sx = WINDOW_MINIMUM;
! 33: if (sx > WINDOW_MAXIMUM)
! 34: sx = WINDOW_MAXIMUM;
! 35: if (sy < WINDOW_MINIMUM)
! 36: sy = WINDOW_MINIMUM;
! 37: if (sy > WINDOW_MAXIMUM)
! 38: sy = WINDOW_MAXIMUM;
! 39:
! 40: /* If the window is zoomed, unzoom. */
! 41: zoomed = w->flags & WINDOW_ZOOMED;
! 42: if (zoomed)
! 43: window_unzoom(w);
! 44:
! 45: /* Resize the layout first. */
! 46: layout_resize(w, sx, sy);
! 47:
! 48: /* Resize the window, it can be no smaller than the layout. */
! 49: if (sx < w->layout_root->sx)
! 50: sx = w->layout_root->sx;
! 51: if (sy < w->layout_root->sy)
! 52: sy = w->layout_root->sy;
! 53: window_resize(w, sx, sy);
! 54:
! 55: /* Restore the window zoom state. */
! 56: if (zoomed)
! 57: window_zoom(w->active);
! 58:
! 59: tty_update_window_offset(w);
! 60: server_redraw_window(w);
! 61: notify_window("window-layout-changed", w);
! 62: }
1.1 nicm 63:
64: void
1.27 ! nicm 65: default_window_size(struct session *s, struct window *w, u_int *sx, u_int *sy,
! 66: int type)
1.1 nicm 67: {
1.27 ! nicm 68: struct client *c;
! 69: u_int cx, cy;
! 70: const char *value;
! 71:
! 72: if (type == -1)
! 73: type = options_get_number(global_w_options, "window-size");
! 74: if (type == WINDOW_SIZE_MANUAL)
! 75: goto manual;
1.1 nicm 76:
1.27 ! nicm 77: if (type == WINDOW_SIZE_LARGEST) {
! 78: *sx = *sy = 0;
! 79: TAILQ_FOREACH(c, &clients, entry) {
! 80: if (c->session == NULL)
! 81: continue;
! 82: if (c->flags & CLIENT_NOSIZEFLAGS)
! 83: continue;
! 84: if (w != NULL && !session_has(c->session, w))
! 85: continue;
! 86: if (w == NULL && c->session != s)
! 87: continue;
! 88:
! 89: cx = c->tty.sx;
! 90: cy = c->tty.sy - status_line_size(c);
1.9 nicm 91:
1.27 ! nicm 92: if (cx > *sx)
! 93: *sx = cx;
! 94: if (cy > *sy)
! 95: *sy = cy;
! 96: }
! 97: if (*sx == 0 || *sy == 0)
! 98: goto manual;
! 99: } else {
! 100: *sx = *sy = UINT_MAX;
1.17 nicm 101: TAILQ_FOREACH(c, &clients, entry) {
1.27 ! nicm 102: if (c->session == NULL)
1.23 nicm 103: continue;
1.27 ! nicm 104: if (c->flags & CLIENT_NOSIZEFLAGS)
1.1 nicm 105: continue;
1.27 ! nicm 106: if (w != NULL && !session_has(c->session, w))
! 107: continue;
! 108: if (w == NULL && c->session != s)
! 109: continue;
! 110:
! 111: cx = c->tty.sx;
! 112: cy = c->tty.sy - status_line_size(c);
! 113:
! 114: if (cx < *sx)
! 115: *sx = cx;
! 116: if (cy < *sy)
! 117: *sy = cy;
1.1 nicm 118: }
1.27 ! nicm 119: if (*sx == UINT_MAX || *sy == UINT_MAX)
! 120: goto manual;
! 121: }
! 122: goto done;
! 123:
! 124: manual:
! 125: value = options_get_string(s->options, "default-size");
! 126: if (sscanf(value, "%ux%u", sx, sy) != 2) {
! 127: *sx = 80;
! 128: *sy = 24;
! 129: }
! 130:
! 131: done:
! 132: if (*sx < WINDOW_MINIMUM)
! 133: *sx = WINDOW_MINIMUM;
! 134: if (*sx > WINDOW_MAXIMUM)
! 135: *sx = WINDOW_MAXIMUM;
! 136: if (*sy < WINDOW_MINIMUM)
! 137: *sy = WINDOW_MINIMUM;
! 138: if (*sy > WINDOW_MAXIMUM)
! 139: *sy = WINDOW_MAXIMUM;
! 140: }
1.1 nicm 141:
1.27 ! nicm 142: void
! 143: recalculate_sizes(void)
! 144: {
! 145: struct session *s;
! 146: struct client *c;
! 147: struct window *w;
! 148: u_int sx, sy, cx, cy;
! 149: int flags, type, current, has, changed;
! 150:
! 151: /*
! 152: * Clear attached count and update saved status line information for
! 153: * each session.
! 154: */
! 155: RB_FOREACH(s, sessions, &sessions) {
! 156: s->attached = 0;
! 157: status_update_saved(s);
! 158: }
1.9 nicm 159:
1.27 ! nicm 160: /*
! 161: * Increment attached count and check the status line size for each
! 162: * client.
! 163: */
! 164: TAILQ_FOREACH(c, &clients, entry) {
! 165: if ((s = c->session) == NULL)
1.1 nicm 166: continue;
167:
1.27 ! nicm 168: flags = c->flags;
! 169: if (flags & CLIENT_SUSPENDED)
! 170: continue;
! 171: if ((flags & CLIENT_CONTROL) && (~flags & CLIENT_SIZECHANGED))
! 172: continue;
1.1 nicm 173:
1.27 ! nicm 174: if (c->tty.sy <= status_line_size(c))
! 175: c->flags |= CLIENT_STATUSOFF;
! 176: else
! 177: c->flags &= ~CLIENT_STATUSOFF;
1.21 nicm 178:
1.27 ! nicm 179: s->attached++;
1.1 nicm 180: }
181:
1.27 ! nicm 182: /* Walk each window and adjust the size. */
1.15 nicm 183: RB_FOREACH(w, windows, &windows) {
184: if (w->active == NULL)
1.1 nicm 185: continue;
1.27 ! nicm 186: log_debug("%s: @%u is %u,%u", __func__, w->id, w->sx, w->sy);
1.1 nicm 187:
1.27 ! nicm 188: type = options_get_number(w->options, "window-size");
! 189: if (type == WINDOW_SIZE_MANUAL)
1.1 nicm 190: continue;
1.27 ! nicm 191: current = !options_get_number(w->options, "aggressive-resize");
1.1 nicm 192:
1.27 ! nicm 193: changed = 1;
! 194: if (type == WINDOW_SIZE_LARGEST) {
! 195: sx = sy = 0;
! 196: TAILQ_FOREACH(c, &clients, entry) {
! 197: if ((s = c->session) == NULL)
! 198: continue;
! 199: if (current)
! 200: has = (s->curw->window == w);
! 201: else
! 202: has = session_has(s, w);
! 203: if (!has)
! 204: continue;
! 205:
! 206: cx = c->tty.sx;
! 207: cy = c->tty.sy - status_line_size(c);
! 208:
! 209: if (cx > sx)
! 210: sx = cx;
! 211: if (cy > sy)
! 212: sy = cy;
! 213: }
! 214: if (sx == 0 || sy == 0)
! 215: changed = 0;
! 216: } else {
! 217: sx = sy = UINT_MAX;
! 218: TAILQ_FOREACH(c, &clients, entry) {
! 219: if ((s = c->session) == NULL)
! 220: continue;
! 221: if (current)
! 222: has = (s->curw->window == w);
! 223: else
! 224: has = session_has(s, w);
! 225: if (!has)
! 226: continue;
! 227:
! 228: cx = c->tty.sx;
! 229: cy = c->tty.sy - status_line_size(c);
! 230:
! 231: if (cx < sx)
! 232: sx = cx;
! 233: if (cy < sy)
! 234: sy = cy;
! 235: }
! 236: if (sx == UINT_MAX || sy == UINT_MAX)
! 237: changed = 0;
1.14 nicm 238: }
1.27 ! nicm 239: if (w->sx == sx && w->sy == sy)
! 240: changed = 0;
1.1 nicm 241:
1.27 ! nicm 242: if (!changed) {
! 243: tty_update_window_offset(w);
1.1 nicm 244: continue;
1.2 nicm 245: }
1.27 ! nicm 246: log_debug("%s: @%u changed to %u,%u", __func__, w->id, sx, sy);
! 247: resize_window(w, sx, sy);
1.1 nicm 248: }
249: }