Annotation of src/usr.bin/tmux/resize.c, Revision 1.31
1.31 ! nicm 1: /* $OpenBSD: resize.c,v 1.30 2019/03/16 17:14:07 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
153: recalculate_sizes(void)
154: {
155: struct session *s;
156: struct client *c;
157: struct window *w;
158: u_int sx, sy, cx, cy;
1.29 nicm 159: int type, current, has, changed;
1.27 nicm 160:
161: /*
162: * Clear attached count and update saved status line information for
163: * each session.
164: */
165: RB_FOREACH(s, sessions, &sessions) {
166: s->attached = 0;
1.30 nicm 167: status_update_cache(s);
1.27 nicm 168: }
1.9 nicm 169:
1.27 nicm 170: /*
171: * Increment attached count and check the status line size for each
172: * client.
173: */
174: TAILQ_FOREACH(c, &clients, entry) {
1.29 nicm 175: if (ignore_client_size(c))
1.27 nicm 176: continue;
177: if (c->tty.sy <= status_line_size(c))
178: c->flags |= CLIENT_STATUSOFF;
179: else
180: c->flags &= ~CLIENT_STATUSOFF;
1.29 nicm 181: c->session->attached++;
1.1 nicm 182: }
183:
1.27 nicm 184: /* Walk each window and adjust the size. */
1.15 nicm 185: RB_FOREACH(w, windows, &windows) {
186: if (w->active == NULL)
1.1 nicm 187: continue;
1.27 nicm 188: log_debug("%s: @%u is %u,%u", __func__, w->id, w->sx, w->sy);
1.1 nicm 189:
1.27 nicm 190: type = options_get_number(w->options, "window-size");
191: if (type == WINDOW_SIZE_MANUAL)
1.1 nicm 192: continue;
1.28 nicm 193: current = options_get_number(w->options, "aggressive-resize");
1.1 nicm 194:
1.27 nicm 195: changed = 1;
196: if (type == WINDOW_SIZE_LARGEST) {
197: sx = sy = 0;
198: TAILQ_FOREACH(c, &clients, entry) {
1.29 nicm 199: if (ignore_client_size(c))
1.27 nicm 200: continue;
1.29 nicm 201: s = c->session;
202:
1.27 nicm 203: if (current)
204: has = (s->curw->window == w);
205: else
206: has = session_has(s, w);
207: if (!has)
208: continue;
209:
210: cx = c->tty.sx;
211: cy = c->tty.sy - status_line_size(c);
212:
213: if (cx > sx)
214: sx = cx;
215: if (cy > sy)
216: sy = cy;
217: }
218: if (sx == 0 || sy == 0)
219: changed = 0;
220: } else {
221: sx = sy = UINT_MAX;
222: TAILQ_FOREACH(c, &clients, entry) {
1.29 nicm 223: if (ignore_client_size(c))
1.27 nicm 224: continue;
1.29 nicm 225: s = c->session;
226:
1.27 nicm 227: if (current)
228: has = (s->curw->window == w);
229: else
230: has = session_has(s, w);
231: if (!has)
232: continue;
233:
234: cx = c->tty.sx;
235: cy = c->tty.sy - status_line_size(c);
236:
237: if (cx < sx)
238: sx = cx;
239: if (cy < sy)
240: sy = cy;
241: }
242: if (sx == UINT_MAX || sy == UINT_MAX)
243: changed = 0;
1.14 nicm 244: }
1.27 nicm 245: if (w->sx == sx && w->sy == sy)
246: changed = 0;
1.1 nicm 247:
1.27 nicm 248: if (!changed) {
249: tty_update_window_offset(w);
1.1 nicm 250: continue;
1.2 nicm 251: }
1.27 nicm 252: log_debug("%s: @%u changed to %u,%u", __func__, w->id, sx, sy);
253: resize_window(w, sx, sy);
1.1 nicm 254: }
255: }