Annotation of src/usr.bin/tmux/resize.c, Revision 1.33
1.33 ! nicm 1: /* $OpenBSD: resize.c,v 1.32 2019/05/11 06:34:56 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);
1.31 nicm 54: log_debug("%s: @%u resized to %u,%u; layout %u,%u", __func__, w->id,
55: sx, sy, w->layout_root->sx, w->layout_root->sy);
1.27 nicm 56:
57: /* Restore the window zoom state. */
58: if (zoomed)
59: window_zoom(w->active);
60:
61: tty_update_window_offset(w);
62: server_redraw_window(w);
63: notify_window("window-layout-changed", w);
64: }
1.1 nicm 65:
1.29 nicm 66: static int
67: ignore_client_size(struct client *c)
68: {
69: if (c->session == NULL)
70: return (1);
71: if (c->flags & CLIENT_NOSIZEFLAGS)
72: return (1);
73: if ((c->flags & CLIENT_CONTROL) && (~c->flags & CLIENT_SIZECHANGED))
74: return (1);
75: return (0);
76: }
77:
1.1 nicm 78: void
1.27 nicm 79: default_window_size(struct session *s, struct window *w, u_int *sx, u_int *sy,
80: int type)
1.1 nicm 81: {
1.27 nicm 82: struct client *c;
83: u_int cx, cy;
84: const char *value;
85:
86: if (type == -1)
87: type = options_get_number(global_w_options, "window-size");
88: if (type == WINDOW_SIZE_MANUAL)
89: goto manual;
1.1 nicm 90:
1.27 nicm 91: if (type == WINDOW_SIZE_LARGEST) {
92: *sx = *sy = 0;
93: TAILQ_FOREACH(c, &clients, entry) {
1.29 nicm 94: if (ignore_client_size(c))
1.27 nicm 95: continue;
96: if (w != NULL && !session_has(c->session, w))
97: continue;
98: if (w == NULL && c->session != s)
99: continue;
100:
101: cx = c->tty.sx;
102: cy = c->tty.sy - status_line_size(c);
1.9 nicm 103:
1.27 nicm 104: if (cx > *sx)
105: *sx = cx;
106: if (cy > *sy)
107: *sy = cy;
108: }
109: if (*sx == 0 || *sy == 0)
110: goto manual;
111: } else {
112: *sx = *sy = UINT_MAX;
1.17 nicm 113: TAILQ_FOREACH(c, &clients, entry) {
1.29 nicm 114: if (ignore_client_size(c))
1.1 nicm 115: continue;
1.27 nicm 116: if (w != NULL && !session_has(c->session, w))
117: continue;
118: if (w == NULL && c->session != s)
119: continue;
120:
121: cx = c->tty.sx;
122: cy = c->tty.sy - status_line_size(c);
123:
124: if (cx < *sx)
125: *sx = cx;
126: if (cy < *sy)
127: *sy = cy;
1.1 nicm 128: }
1.27 nicm 129: if (*sx == UINT_MAX || *sy == UINT_MAX)
130: goto manual;
131: }
132: goto done;
133:
134: manual:
135: value = options_get_string(s->options, "default-size");
136: if (sscanf(value, "%ux%u", sx, sy) != 2) {
137: *sx = 80;
138: *sy = 24;
139: }
140:
141: done:
142: if (*sx < WINDOW_MINIMUM)
143: *sx = WINDOW_MINIMUM;
144: if (*sx > WINDOW_MAXIMUM)
145: *sx = WINDOW_MAXIMUM;
146: if (*sy < WINDOW_MINIMUM)
147: *sy = WINDOW_MINIMUM;
148: if (*sy > WINDOW_MAXIMUM)
149: *sy = WINDOW_MAXIMUM;
150: }
1.1 nicm 151:
1.27 nicm 152: void
1.33 ! nicm 153: recalculate_size(struct window *w)
! 154: {
! 155: struct session *s;
! 156: struct client *c;
! 157: u_int sx, sy, cx, cy;
! 158: int type, current, has, changed;
! 159:
! 160: if (w->active == NULL)
! 161: return;
! 162: log_debug("%s: @%u is %u,%u", __func__, w->id, w->sx, w->sy);
! 163:
! 164: type = options_get_number(w->options, "window-size");
! 165: current = options_get_number(w->options, "aggressive-resize");
! 166:
! 167: changed = 1;
! 168: switch (type) {
! 169: case WINDOW_SIZE_LARGEST:
! 170: sx = sy = 0;
! 171: TAILQ_FOREACH(c, &clients, entry) {
! 172: if (ignore_client_size(c))
! 173: continue;
! 174: s = c->session;
! 175:
! 176: if (current)
! 177: has = (s->curw->window == w);
! 178: else
! 179: has = session_has(s, w);
! 180: if (!has)
! 181: continue;
! 182:
! 183: cx = c->tty.sx;
! 184: cy = c->tty.sy - status_line_size(c);
! 185:
! 186: if (cx > sx)
! 187: sx = cx;
! 188: if (cy > sy)
! 189: sy = cy;
! 190: }
! 191: if (sx == 0 || sy == 0)
! 192: changed = 0;
! 193: break;
! 194: case WINDOW_SIZE_SMALLEST:
! 195: sx = sy = UINT_MAX;
! 196: TAILQ_FOREACH(c, &clients, entry) {
! 197: if (ignore_client_size(c))
! 198: continue;
! 199: s = c->session;
! 200:
! 201: if (current)
! 202: has = (s->curw->window == w);
! 203: else
! 204: has = session_has(s, w);
! 205: if (!has)
! 206: continue;
! 207:
! 208: cx = c->tty.sx;
! 209: cy = c->tty.sy - status_line_size(c);
! 210:
! 211: if (cx < sx)
! 212: sx = cx;
! 213: if (cy < sy)
! 214: sy = cy;
! 215: }
! 216: if (sx == UINT_MAX || sy == UINT_MAX)
! 217: changed = 0;
! 218: break;
! 219: case WINDOW_SIZE_LATEST:
! 220: sx = sy = UINT_MAX;
! 221: TAILQ_FOREACH(c, &clients, entry) {
! 222: if (ignore_client_size(c))
! 223: continue;
! 224: if (c != w->latest)
! 225: continue;
! 226: s = c->session;
! 227:
! 228: if (current)
! 229: has = (s->curw->window == w);
! 230: else
! 231: has = session_has(s, w);
! 232: if (!has)
! 233: continue;
! 234:
! 235: cx = c->tty.sx;
! 236: cy = c->tty.sy - status_line_size(c);
! 237:
! 238: if (cx < sx)
! 239: sx = cx;
! 240: if (cy < sy)
! 241: sy = cy;
! 242: }
! 243: if (sx == UINT_MAX || sy == UINT_MAX)
! 244: changed = 0;
! 245: break;
! 246: case WINDOW_SIZE_MANUAL:
! 247: changed = 0;
! 248: break;
! 249: }
! 250: if (changed && w->sx == sx && w->sy == sy)
! 251: changed = 0;
! 252:
! 253: if (!changed) {
! 254: tty_update_window_offset(w);
! 255: return;
! 256: }
! 257: log_debug("%s: @%u changed to %u,%u", __func__, w->id, sx, sy);
! 258: resize_window(w, sx, sy);
! 259: }
! 260:
! 261: void
1.27 nicm 262: recalculate_sizes(void)
263: {
264: struct session *s;
265: struct client *c;
266: struct window *w;
267:
268: /*
269: * Clear attached count and update saved status line information for
270: * each session.
271: */
272: RB_FOREACH(s, sessions, &sessions) {
273: s->attached = 0;
1.30 nicm 274: status_update_cache(s);
1.27 nicm 275: }
1.9 nicm 276:
1.27 nicm 277: /*
278: * Increment attached count and check the status line size for each
279: * client.
280: */
281: TAILQ_FOREACH(c, &clients, entry) {
1.29 nicm 282: if (ignore_client_size(c))
1.27 nicm 283: continue;
1.32 nicm 284: s = c->session;
285: if (c->tty.sy <= s->statuslines || (c->flags & CLIENT_CONTROL))
1.27 nicm 286: c->flags |= CLIENT_STATUSOFF;
287: else
288: c->flags &= ~CLIENT_STATUSOFF;
1.32 nicm 289: s->attached++;
1.1 nicm 290: }
291:
1.27 nicm 292: /* Walk each window and adjust the size. */
1.33 ! nicm 293: RB_FOREACH(w, windows, &windows)
! 294: recalculate_size(w);
1.1 nicm 295: }