Annotation of src/usr.bin/tmux/resize.c, Revision 1.35
1.35 ! nicm 1: /* $OpenBSD: resize.c,v 1.34 2019/09/23 15:41:11 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
1.35 ! nicm 26: resize_window(struct window *w, u_int sx, u_int sy, int xpixel, int ypixel)
1.27 nicm 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;
1.35 ! nicm 53: window_resize(w, sx, sy, xpixel, ypixel);
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.34 nicm 79: default_window_size(struct client *c, struct session *s, struct window *w,
1.35 ! nicm 80: u_int *sx, u_int *sy, u_int *xpixel, u_int *ypixel, int type)
1.1 nicm 81: {
1.34 nicm 82: struct client *loop;
1.27 nicm 83: u_int cx, cy;
84: const char *value;
85:
86: if (type == -1)
87: type = options_get_number(global_w_options, "window-size");
1.34 nicm 88: switch (type) {
89: case WINDOW_SIZE_LARGEST:
1.27 nicm 90: *sx = *sy = 0;
1.35 ! nicm 91: *xpixel = *ypixel = 0;
1.34 nicm 92: TAILQ_FOREACH(loop, &clients, entry) {
93: if (ignore_client_size(loop))
1.27 nicm 94: continue;
1.34 nicm 95: if (w != NULL && !session_has(loop->session, w))
1.27 nicm 96: continue;
1.34 nicm 97: if (w == NULL && loop->session != s)
1.27 nicm 98: continue;
99:
1.34 nicm 100: cx = loop->tty.sx;
101: cy = loop->tty.sy - status_line_size(loop);
1.9 nicm 102:
1.27 nicm 103: if (cx > *sx)
104: *sx = cx;
105: if (cy > *sy)
106: *sy = cy;
1.35 ! nicm 107:
! 108: if (loop->tty.xpixel > *xpixel &&
! 109: loop->tty.ypixel > *ypixel) {
! 110: *xpixel = loop->tty.xpixel;
! 111: *ypixel = loop->tty.ypixel;
! 112: }
1.27 nicm 113: }
114: if (*sx == 0 || *sy == 0)
115: goto manual;
1.34 nicm 116: break;
117: case WINDOW_SIZE_SMALLEST:
1.27 nicm 118: *sx = *sy = UINT_MAX;
1.35 ! nicm 119: *xpixel = *ypixel = 0;
1.34 nicm 120: TAILQ_FOREACH(loop, &clients, entry) {
121: if (ignore_client_size(loop))
1.1 nicm 122: continue;
1.34 nicm 123: if (w != NULL && !session_has(loop->session, w))
1.27 nicm 124: continue;
1.34 nicm 125: if (w == NULL && loop->session != s)
1.27 nicm 126: continue;
127:
1.34 nicm 128: cx = loop->tty.sx;
129: cy = loop->tty.sy - status_line_size(loop);
1.27 nicm 130:
131: if (cx < *sx)
132: *sx = cx;
133: if (cy < *sy)
134: *sy = cy;
1.35 ! nicm 135:
! 136: if (loop->tty.xpixel > *xpixel &&
! 137: loop->tty.ypixel > *ypixel) {
! 138: *xpixel = loop->tty.xpixel;
! 139: *ypixel = loop->tty.ypixel;
! 140: }
1.1 nicm 141: }
1.27 nicm 142: if (*sx == UINT_MAX || *sy == UINT_MAX)
143: goto manual;
1.34 nicm 144: break;
145: case WINDOW_SIZE_LATEST:
146: if (c != NULL && !ignore_client_size(c)) {
147: *sx = c->tty.sx;
148: *sy = c->tty.sy - status_line_size(c);
1.35 ! nicm 149: *xpixel = c->tty.xpixel;
! 150: *ypixel = c->tty.ypixel;
1.34 nicm 151: } else {
152: *sx = *sy = UINT_MAX;
1.35 ! nicm 153: *xpixel = *ypixel = 0;
1.34 nicm 154: TAILQ_FOREACH(loop, &clients, entry) {
155: if (ignore_client_size(loop))
156: continue;
157: if (w != NULL && loop != w->latest)
158: continue;
159: s = loop->session;
160:
161: cx = loop->tty.sx;
162: cy = loop->tty.sy - status_line_size(loop);
163:
164: if (cx < *sx)
165: *sx = cx;
166: if (cy < *sy)
167: *sy = cy;
1.35 ! nicm 168:
! 169: if (loop->tty.xpixel > *xpixel &&
! 170: loop->tty.ypixel > *ypixel) {
! 171: *xpixel = loop->tty.xpixel;
! 172: *ypixel = loop->tty.ypixel;
! 173: }
1.34 nicm 174: }
175: if (*sx == UINT_MAX || *sy == UINT_MAX)
176: goto manual;
177: }
178: break;
179: case WINDOW_SIZE_MANUAL:
180: goto manual;
1.27 nicm 181: }
182: goto done;
183:
184: manual:
185: value = options_get_string(s->options, "default-size");
186: if (sscanf(value, "%ux%u", sx, sy) != 2) {
187: *sx = 80;
188: *sy = 24;
189: }
190:
191: done:
192: if (*sx < WINDOW_MINIMUM)
193: *sx = WINDOW_MINIMUM;
194: if (*sx > WINDOW_MAXIMUM)
195: *sx = WINDOW_MAXIMUM;
196: if (*sy < WINDOW_MINIMUM)
197: *sy = WINDOW_MINIMUM;
198: if (*sy > WINDOW_MAXIMUM)
199: *sy = WINDOW_MAXIMUM;
200: }
1.1 nicm 201:
1.27 nicm 202: void
1.33 nicm 203: recalculate_size(struct window *w)
204: {
205: struct session *s;
206: struct client *c;
1.35 ! nicm 207: u_int sx, sy, cx, cy, xpixel = 0, ypixel = 0;
1.33 nicm 208: int type, current, has, changed;
209:
210: if (w->active == NULL)
211: return;
212: log_debug("%s: @%u is %u,%u", __func__, w->id, w->sx, w->sy);
213:
214: type = options_get_number(w->options, "window-size");
215: current = options_get_number(w->options, "aggressive-resize");
216:
217: changed = 1;
218: switch (type) {
219: case WINDOW_SIZE_LARGEST:
220: sx = sy = 0;
221: TAILQ_FOREACH(c, &clients, entry) {
222: if (ignore_client_size(c))
223: continue;
224: s = c->session;
225:
226: if (current)
227: has = (s->curw->window == w);
228: else
229: has = session_has(s, w);
230: if (!has)
231: continue;
232:
233: cx = c->tty.sx;
234: cy = c->tty.sy - status_line_size(c);
235:
236: if (cx > sx)
237: sx = cx;
238: if (cy > sy)
239: sy = cy;
1.35 ! nicm 240:
! 241: if (c->tty.xpixel > xpixel && c->tty.ypixel > ypixel) {
! 242: xpixel = c->tty.xpixel;
! 243: ypixel = c->tty.ypixel;
! 244: }
1.33 nicm 245: }
246: if (sx == 0 || sy == 0)
247: changed = 0;
248: break;
249: case WINDOW_SIZE_SMALLEST:
250: sx = sy = UINT_MAX;
251: TAILQ_FOREACH(c, &clients, entry) {
252: if (ignore_client_size(c))
253: continue;
254: s = c->session;
255:
256: if (current)
257: has = (s->curw->window == w);
258: else
259: has = session_has(s, w);
260: if (!has)
261: continue;
262:
263: cx = c->tty.sx;
264: cy = c->tty.sy - status_line_size(c);
265:
266: if (cx < sx)
267: sx = cx;
268: if (cy < sy)
269: sy = cy;
1.35 ! nicm 270:
! 271: if (c->tty.xpixel > xpixel && c->tty.ypixel > ypixel) {
! 272: xpixel = c->tty.xpixel;
! 273: ypixel = c->tty.ypixel;
! 274: }
1.33 nicm 275: }
276: if (sx == UINT_MAX || sy == UINT_MAX)
277: changed = 0;
278: break;
279: case WINDOW_SIZE_LATEST:
280: sx = sy = UINT_MAX;
281: TAILQ_FOREACH(c, &clients, entry) {
282: if (ignore_client_size(c))
283: continue;
284: if (c != w->latest)
285: continue;
286: s = c->session;
287:
288: if (current)
289: has = (s->curw->window == w);
290: else
291: has = session_has(s, w);
292: if (!has)
293: continue;
294:
295: cx = c->tty.sx;
296: cy = c->tty.sy - status_line_size(c);
297:
298: if (cx < sx)
299: sx = cx;
300: if (cy < sy)
301: sy = cy;
1.35 ! nicm 302:
! 303: if (c->tty.xpixel > xpixel && c->tty.ypixel > ypixel) {
! 304: xpixel = c->tty.xpixel;
! 305: ypixel = c->tty.ypixel;
! 306: }
1.33 nicm 307: }
308: if (sx == UINT_MAX || sy == UINT_MAX)
309: changed = 0;
310: break;
311: case WINDOW_SIZE_MANUAL:
312: changed = 0;
313: break;
314: }
315: if (changed && w->sx == sx && w->sy == sy)
316: changed = 0;
317:
318: if (!changed) {
319: tty_update_window_offset(w);
320: return;
321: }
1.35 ! nicm 322: log_debug("%s: @%u changed to %u,%u (%ux%u)", __func__, w->id, sx, sy,
! 323: xpixel, ypixel);
! 324: resize_window(w, sx, sy, xpixel, ypixel);
1.33 nicm 325: }
326:
327: void
1.27 nicm 328: recalculate_sizes(void)
329: {
330: struct session *s;
331: struct client *c;
332: struct window *w;
333:
334: /*
335: * Clear attached count and update saved status line information for
336: * each session.
337: */
338: RB_FOREACH(s, sessions, &sessions) {
339: s->attached = 0;
1.30 nicm 340: status_update_cache(s);
1.27 nicm 341: }
1.9 nicm 342:
1.27 nicm 343: /*
344: * Increment attached count and check the status line size for each
345: * client.
346: */
347: TAILQ_FOREACH(c, &clients, entry) {
1.29 nicm 348: if (ignore_client_size(c))
1.27 nicm 349: continue;
1.32 nicm 350: s = c->session;
351: if (c->tty.sy <= s->statuslines || (c->flags & CLIENT_CONTROL))
1.27 nicm 352: c->flags |= CLIENT_STATUSOFF;
353: else
354: c->flags &= ~CLIENT_STATUSOFF;
1.32 nicm 355: s->attached++;
1.1 nicm 356: }
357:
1.27 nicm 358: /* Walk each window and adjust the size. */
1.33 nicm 359: RB_FOREACH(w, windows, &windows)
360: recalculate_size(w);
1.1 nicm 361: }