| File: | src/usr.bin/tmux/resize.c |
| Warning: | line 457, column 20 Access to field 'statuslines' results in a dereference of a null pointer (loaded from variable 's') |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* $OpenBSD: resize.c,v 1.49 2022/01/06 08:20:00 nicm Exp $ */ | |||
| 2 | ||||
| 3 | /* | |||
| 4 | * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> | |||
| 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 | ||||
| 25 | void | |||
| 26 | resize_window(struct window *w, u_int sx, u_int sy, int xpixel, int ypixel) | |||
| 27 | { | |||
| 28 | int zoomed; | |||
| 29 | ||||
| 30 | /* Check size limits. */ | |||
| 31 | if (sx < WINDOW_MINIMUM1) | |||
| 32 | sx = WINDOW_MINIMUM1; | |||
| 33 | if (sx > WINDOW_MAXIMUM10000) | |||
| 34 | sx = WINDOW_MAXIMUM10000; | |||
| 35 | if (sy < WINDOW_MINIMUM1) | |||
| 36 | sy = WINDOW_MINIMUM1; | |||
| 37 | if (sy > WINDOW_MAXIMUM10000) | |||
| 38 | sy = WINDOW_MAXIMUM10000; | |||
| 39 | ||||
| 40 | /* If the window is zoomed, unzoom. */ | |||
| 41 | zoomed = w->flags & WINDOW_ZOOMED0x8; | |||
| 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, xpixel, ypixel); | |||
| 54 | log_debug("%s: @%u resized to %ux%u; layout %ux%u", __func__, w->id, | |||
| 55 | sx, sy, w->layout_root->sx, w->layout_root->sy); | |||
| 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 | w->flags &= ~WINDOW_RESIZE0x20; | |||
| 65 | } | |||
| 66 | ||||
| 67 | static int | |||
| 68 | ignore_client_size(struct client *c) | |||
| 69 | { | |||
| 70 | struct client *loop; | |||
| 71 | ||||
| 72 | if (c->session == NULL((void *)0)) | |||
| 73 | return (1); | |||
| 74 | if (c->flags & CLIENT_NOSIZEFLAGS(0x200| 0x40| 0x4)) | |||
| 75 | return (1); | |||
| 76 | if (c->flags & CLIENT_IGNORESIZE0x20000) { | |||
| 77 | /* | |||
| 78 | * Ignore flagged clients if there are any attached clients | |||
| 79 | * that aren't flagged. | |||
| 80 | */ | |||
| 81 | TAILQ_FOREACH (loop, &clients, entry)for((loop) = ((&clients)->tqh_first); (loop) != ((void *)0); (loop) = ((loop)->entry.tqe_next)) { | |||
| 82 | if (loop->session == NULL((void *)0)) | |||
| 83 | continue; | |||
| 84 | if (loop->flags & CLIENT_NOSIZEFLAGS(0x200| 0x40| 0x4)) | |||
| 85 | continue; | |||
| 86 | if (~loop->flags & CLIENT_IGNORESIZE0x20000) | |||
| 87 | return (1); | |||
| 88 | } | |||
| 89 | } | |||
| 90 | if ((c->flags & CLIENT_CONTROL0x2000) && | |||
| 91 | (~c->flags & CLIENT_SIZECHANGED0x400000) && | |||
| 92 | (~c->flags & CLIENT_WINDOWSIZECHANGED0x400000000ULL)) | |||
| 93 | return (1); | |||
| 94 | return (0); | |||
| 95 | } | |||
| 96 | ||||
| 97 | static u_int | |||
| 98 | clients_with_window(struct window *w) | |||
| 99 | { | |||
| 100 | struct client *loop; | |||
| 101 | u_int n = 0; | |||
| 102 | ||||
| 103 | TAILQ_FOREACH(loop, &clients, entry)for((loop) = ((&clients)->tqh_first); (loop) != ((void *)0); (loop) = ((loop)->entry.tqe_next)) { | |||
| 104 | if (ignore_client_size(loop) || !session_has(loop->session, w)) | |||
| 105 | continue; | |||
| 106 | if (++n > 1) | |||
| 107 | break; | |||
| 108 | } | |||
| 109 | return (n); | |||
| 110 | } | |||
| 111 | ||||
| 112 | static int | |||
| 113 | clients_calculate_size(int type, int current, struct client *c, | |||
| 114 | struct session *s, struct window *w, int (*skip_client)(struct client *, | |||
| 115 | int, int, struct session *, struct window *), u_int *sx, u_int *sy, | |||
| 116 | u_int *xpixel, u_int *ypixel) | |||
| 117 | { | |||
| 118 | struct client *loop; | |||
| 119 | struct client_window *cw; | |||
| 120 | u_int cx, cy, n = 0; | |||
| 121 | ||||
| 122 | /* | |||
| 123 | * Start comparing with 0 for largest and UINT_MAX for smallest or | |||
| 124 | * latest. | |||
| 125 | */ | |||
| 126 | if (type == WINDOW_SIZE_LARGEST0) { | |||
| 127 | *sx = 0; | |||
| 128 | *sy = 0; | |||
| 129 | } else if (type == WINDOW_SIZE_MANUAL2) { | |||
| 130 | *sx = w->manual_sx; | |||
| 131 | *sy = w->manual_sy; | |||
| 132 | log_debug("%s: manual size %ux%u", __func__, *sx, *sy); | |||
| 133 | } else { | |||
| 134 | *sx = UINT_MAX(2147483647 *2U +1U); | |||
| 135 | *sy = UINT_MAX(2147483647 *2U +1U); | |||
| 136 | } | |||
| 137 | *xpixel = *ypixel = 0; | |||
| 138 | ||||
| 139 | /* | |||
| 140 | * For latest, count the number of clients with this window. We only | |||
| 141 | * care if there is more than one. | |||
| 142 | */ | |||
| 143 | if (type == WINDOW_SIZE_LATEST3 && w != NULL((void *)0)) | |||
| 144 | n = clients_with_window(w); | |||
| 145 | ||||
| 146 | /* Skip setting the size if manual */ | |||
| 147 | if (type == WINDOW_SIZE_MANUAL2) | |||
| 148 | goto skip; | |||
| 149 | ||||
| 150 | /* Loop over the clients and work out the size. */ | |||
| 151 | TAILQ_FOREACH(loop, &clients, entry)for((loop) = ((&clients)->tqh_first); (loop) != ((void *)0); (loop) = ((loop)->entry.tqe_next)) { | |||
| 152 | if (loop != c && ignore_client_size(loop)) { | |||
| 153 | log_debug("%s: ignoring %s (1)", __func__, loop->name); | |||
| 154 | continue; | |||
| 155 | } | |||
| 156 | if (loop != c && skip_client(loop, type, current, s, w)) { | |||
| 157 | log_debug("%s: skipping %s (1)", __func__, loop->name); | |||
| 158 | continue; | |||
| 159 | } | |||
| 160 | ||||
| 161 | /* | |||
| 162 | * If there are multiple clients attached, only accept the | |||
| 163 | * latest client; otherwise let the only client be chosen as | |||
| 164 | * for smallest. | |||
| 165 | */ | |||
| 166 | if (type == WINDOW_SIZE_LATEST3 && n > 1 && loop != w->latest) { | |||
| 167 | log_debug("%s: %s is not latest", __func__, loop->name); | |||
| 168 | continue; | |||
| 169 | } | |||
| 170 | ||||
| 171 | /* | |||
| 172 | * If the client has a per-window size, use this instead if it is | |||
| 173 | * smaller. | |||
| 174 | */ | |||
| 175 | if (w != NULL((void *)0)) | |||
| 176 | cw = server_client_get_client_window(loop, w->id); | |||
| 177 | else | |||
| 178 | cw = NULL((void *)0); | |||
| 179 | ||||
| 180 | /* Work out this client's size. */ | |||
| 181 | if (cw != NULL((void *)0) && cw->sx != 0 && cw->sy != 0) { | |||
| 182 | cx = cw->sx; | |||
| 183 | cy = cw->sy; | |||
| 184 | } else { | |||
| 185 | cx = loop->tty.sx; | |||
| 186 | cy = loop->tty.sy - status_line_size(loop); | |||
| 187 | } | |||
| 188 | ||||
| 189 | /* | |||
| 190 | * If it is larger or smaller than the best so far, update the | |||
| 191 | * new size. | |||
| 192 | */ | |||
| 193 | if (type == WINDOW_SIZE_LARGEST0) { | |||
| 194 | if (cx > *sx) | |||
| 195 | *sx = cx; | |||
| 196 | if (cy > *sy) | |||
| 197 | *sy = cy; | |||
| 198 | } else { | |||
| 199 | if (cx < *sx) | |||
| 200 | *sx = cx; | |||
| 201 | if (cy < *sy) | |||
| 202 | *sy = cy; | |||
| 203 | } | |||
| 204 | if (loop->tty.xpixel > *xpixel && loop->tty.ypixel > *ypixel) { | |||
| 205 | *xpixel = loop->tty.xpixel; | |||
| 206 | *ypixel = loop->tty.ypixel; | |||
| 207 | } | |||
| 208 | log_debug("%s: after %s (%ux%u), size is %ux%u", __func__, | |||
| 209 | loop->name, cx, cy, *sx, *sy); | |||
| 210 | } | |||
| 211 | if (*sx != UINT_MAX(2147483647 *2U +1U) && *sy != UINT_MAX(2147483647 *2U +1U)) | |||
| 212 | log_debug("%s: calculated size %ux%u", __func__, *sx, *sy); | |||
| 213 | else | |||
| 214 | log_debug("%s: no calculated size", __func__); | |||
| 215 | ||||
| 216 | skip: | |||
| 217 | /* | |||
| 218 | * Do not allow any size to be larger than the per-client window size | |||
| 219 | * if one exists. | |||
| 220 | */ | |||
| 221 | if (w != NULL((void *)0)) { | |||
| 222 | TAILQ_FOREACH(loop, &clients, entry)for((loop) = ((&clients)->tqh_first); (loop) != ((void *)0); (loop) = ((loop)->entry.tqe_next)) { | |||
| 223 | if (loop != c && ignore_client_size(loop)) | |||
| 224 | continue; | |||
| 225 | if (loop != c && skip_client(loop, type, current, s, w)) | |||
| 226 | continue; | |||
| 227 | ||||
| 228 | /* Look up per-window size if any. */ | |||
| 229 | if (~loop->flags & CLIENT_WINDOWSIZECHANGED0x400000000ULL) | |||
| 230 | continue; | |||
| 231 | cw = server_client_get_client_window(loop, w->id); | |||
| 232 | if (cw == NULL((void *)0)) | |||
| 233 | continue; | |||
| 234 | ||||
| 235 | /* Clamp the size. */ | |||
| 236 | log_debug("%s: %s size for @%u is %ux%u", __func__, | |||
| 237 | loop->name, w->id, cw->sx, cw->sy); | |||
| 238 | if (cw->sx != 0 && *sx > cw->sx) | |||
| 239 | *sx = cw->sx; | |||
| 240 | if (cw->sy != 0 && *sy > cw->sy) | |||
| 241 | *sy = cw->sy; | |||
| 242 | } | |||
| 243 | } | |||
| 244 | if (*sx != UINT_MAX(2147483647 *2U +1U) && *sy != UINT_MAX(2147483647 *2U +1U)) | |||
| 245 | log_debug("%s: calculated size %ux%u", __func__, *sx, *sy); | |||
| 246 | else | |||
| 247 | log_debug("%s: no calculated size", __func__); | |||
| 248 | ||||
| 249 | /* Return whether a suitable size was found. */ | |||
| 250 | if (type == WINDOW_SIZE_MANUAL2) { | |||
| 251 | log_debug("%s: type is manual", __func__); | |||
| 252 | return (1); | |||
| 253 | } | |||
| 254 | if (type == WINDOW_SIZE_LARGEST0) { | |||
| 255 | log_debug("%s: type is largest", __func__); | |||
| 256 | return (*sx != 0 && *sy != 0); | |||
| 257 | } | |||
| 258 | if (type == WINDOW_SIZE_LATEST3) | |||
| 259 | log_debug("%s: type is latest", __func__); | |||
| 260 | else | |||
| 261 | log_debug("%s: type is smallest", __func__); | |||
| 262 | return (*sx != UINT_MAX(2147483647 *2U +1U) && *sy != UINT_MAX(2147483647 *2U +1U)); | |||
| 263 | } | |||
| 264 | ||||
| 265 | static int | |||
| 266 | default_window_size_skip_client(struct client *loop, int type, | |||
| 267 | __unused__attribute__((__unused__)) int current, struct session *s, struct window *w) | |||
| 268 | { | |||
| 269 | /* | |||
| 270 | * Latest checks separately, so do not check here. Otherwise only | |||
| 271 | * include clients where the session contains the window or where the | |||
| 272 | * session is the given session. | |||
| 273 | */ | |||
| 274 | if (type == WINDOW_SIZE_LATEST3) | |||
| 275 | return (0); | |||
| 276 | if (w != NULL((void *)0) && !session_has(loop->session, w)) | |||
| 277 | return (1); | |||
| 278 | if (w == NULL((void *)0) && loop->session != s) | |||
| 279 | return (1); | |||
| 280 | return (0); | |||
| 281 | } | |||
| 282 | ||||
| 283 | void | |||
| 284 | default_window_size(struct client *c, struct session *s, struct window *w, | |||
| 285 | u_int *sx, u_int *sy, u_int *xpixel, u_int *ypixel, int type) | |||
| 286 | { | |||
| 287 | const char *value; | |||
| 288 | ||||
| 289 | /* Get type if not provided. */ | |||
| 290 | if (type == -1) | |||
| 291 | type = options_get_number(global_w_options, "window-size"); | |||
| 292 | ||||
| 293 | /* | |||
| 294 | * Latest clients can use the given client if suitable. If there is no | |||
| 295 | * client and no window, use the default size as for manual type. | |||
| 296 | */ | |||
| 297 | if (type == WINDOW_SIZE_LATEST3 && c != NULL((void *)0) && !ignore_client_size(c)) { | |||
| 298 | *sx = c->tty.sx; | |||
| 299 | *sy = c->tty.sy - status_line_size(c); | |||
| 300 | *xpixel = c->tty.xpixel; | |||
| 301 | *ypixel = c->tty.ypixel; | |||
| 302 | log_debug("%s: using %ux%u from %s", __func__, *sx, *sy, | |||
| 303 | c->name); | |||
| 304 | goto done; | |||
| 305 | } | |||
| 306 | ||||
| 307 | /* | |||
| 308 | * Ignore the given client if it is a control client - the creating | |||
| 309 | * client should only affect the size if it is not a control client. | |||
| 310 | */ | |||
| 311 | if (c != NULL((void *)0) && (c->flags & CLIENT_CONTROL0x2000)) | |||
| 312 | c = NULL((void *)0); | |||
| 313 | ||||
| 314 | /* | |||
| 315 | * Look for a client to base the size on. If none exists (or the type | |||
| 316 | * is manual), use the default-size option. | |||
| 317 | */ | |||
| 318 | if (!clients_calculate_size(type, 0, c, s, w, | |||
| 319 | default_window_size_skip_client, sx, sy, xpixel, ypixel)) { | |||
| 320 | value = options_get_string(s->options, "default-size"); | |||
| 321 | if (sscanf(value, "%ux%u", sx, sy) != 2) { | |||
| 322 | *sx = 80; | |||
| 323 | *sy = 24; | |||
| 324 | } | |||
| 325 | log_debug("%s: using %ux%u from default-size", __func__, *sx, | |||
| 326 | *sy); | |||
| 327 | } | |||
| 328 | ||||
| 329 | done: | |||
| 330 | /* Make sure the limits are enforced. */ | |||
| 331 | if (*sx < WINDOW_MINIMUM1) | |||
| 332 | *sx = WINDOW_MINIMUM1; | |||
| 333 | if (*sx > WINDOW_MAXIMUM10000) | |||
| 334 | *sx = WINDOW_MAXIMUM10000; | |||
| 335 | if (*sy < WINDOW_MINIMUM1) | |||
| 336 | *sy = WINDOW_MINIMUM1; | |||
| 337 | if (*sy > WINDOW_MAXIMUM10000) | |||
| 338 | *sy = WINDOW_MAXIMUM10000; | |||
| 339 | log_debug("%s: resulting size is %ux%u", __func__, *sx, *sy); | |||
| 340 | } | |||
| 341 | ||||
| 342 | static int | |||
| 343 | recalculate_size_skip_client(struct client *loop, __unused__attribute__((__unused__)) int type, | |||
| 344 | int current, __unused__attribute__((__unused__)) struct session *s, struct window *w) | |||
| 345 | { | |||
| 346 | /* | |||
| 347 | * If the current flag is set, then skip any client where this window | |||
| 348 | * is not the current window - this is used for aggressive-resize. | |||
| 349 | * Otherwise skip any session that doesn't contain the window. | |||
| 350 | */ | |||
| 351 | if (loop->session->curw == NULL((void *)0)) | |||
| 352 | return (1); | |||
| 353 | if (current) | |||
| 354 | return (loop->session->curw->window != w); | |||
| 355 | return (session_has(loop->session, w) == 0); | |||
| 356 | } | |||
| 357 | ||||
| 358 | void | |||
| 359 | recalculate_size(struct window *w, int now) | |||
| 360 | { | |||
| 361 | u_int sx, sy, xpixel = 0, ypixel = 0; | |||
| 362 | int type, current, changed; | |||
| 363 | ||||
| 364 | /* | |||
| 365 | * Do not attempt to resize windows which have no pane, they must be on | |||
| 366 | * the way to destruction. | |||
| 367 | */ | |||
| 368 | if (w->active == NULL((void *)0)) | |||
| 369 | return; | |||
| 370 | log_debug("%s: @%u is %ux%u", __func__, w->id, w->sx, w->sy); | |||
| 371 | ||||
| 372 | /* | |||
| 373 | * Type is manual, smallest, largest, latest. Current is the | |||
| 374 | * aggressive-resize option (do not resize based on clients where the | |||
| 375 | * window is not the current window). | |||
| 376 | */ | |||
| 377 | type = options_get_number(w->options, "window-size"); | |||
| 378 | current = options_get_number(w->options, "aggressive-resize"); | |||
| 379 | ||||
| 380 | /* Look for a suitable client and get the new size. */ | |||
| 381 | changed = clients_calculate_size(type, current, NULL((void *)0), NULL((void *)0), w, | |||
| 382 | recalculate_size_skip_client, &sx, &sy, &xpixel, &ypixel); | |||
| 383 | ||||
| 384 | /* | |||
| 385 | * Make sure the size has actually changed. If the window has already | |||
| 386 | * got a resize scheduled, then use the new size; otherwise the old. | |||
| 387 | */ | |||
| 388 | if (w->flags & WINDOW_RESIZE0x20) { | |||
| 389 | if (!now && changed && w->new_sx == sx && w->new_sy == sy) | |||
| 390 | changed = 0; | |||
| 391 | } else { | |||
| 392 | if (!now && changed && w->sx == sx && w->sy == sy) | |||
| 393 | changed = 0; | |||
| 394 | } | |||
| 395 | ||||
| 396 | /* | |||
| 397 | * If the size hasn't changed, update the window offset but not the | |||
| 398 | * size. | |||
| 399 | */ | |||
| 400 | if (!changed) { | |||
| 401 | log_debug("%s: @%u no size change", __func__, w->id); | |||
| 402 | tty_update_window_offset(w); | |||
| 403 | return; | |||
| 404 | } | |||
| 405 | ||||
| 406 | /* | |||
| 407 | * If the now flag is set or if the window is sized manually, change | |||
| 408 | * the size immediately. Otherwise set the flag and it will be done | |||
| 409 | * later. | |||
| 410 | */ | |||
| 411 | log_debug("%s: @%u new size %ux%u", __func__, w->id, sx, sy); | |||
| 412 | if (now || type == WINDOW_SIZE_MANUAL2) | |||
| 413 | resize_window(w, sx, sy, xpixel, ypixel); | |||
| 414 | else { | |||
| 415 | w->new_sx = sx; | |||
| 416 | w->new_sy = sy; | |||
| 417 | w->new_xpixel = xpixel; | |||
| 418 | w->new_ypixel = ypixel; | |||
| 419 | ||||
| 420 | w->flags |= WINDOW_RESIZE0x20; | |||
| 421 | tty_update_window_offset(w); | |||
| 422 | } | |||
| 423 | } | |||
| 424 | ||||
| 425 | void | |||
| 426 | recalculate_sizes(void) | |||
| 427 | { | |||
| 428 | recalculate_sizes_now(0); | |||
| ||||
| 429 | } | |||
| 430 | ||||
| 431 | void | |||
| 432 | recalculate_sizes_now(int now) | |||
| 433 | { | |||
| 434 | struct session *s; | |||
| 435 | struct client *c; | |||
| 436 | struct window *w; | |||
| 437 | ||||
| 438 | /* | |||
| 439 | * Clear attached count and update saved status line information for | |||
| 440 | * each session. | |||
| 441 | */ | |||
| 442 | RB_FOREACH(s, sessions, &sessions)for ((s) = sessions_RB_MINMAX(&sessions, -1); (s) != ((void *)0); (s) = sessions_RB_NEXT(s)) { | |||
| 443 | s->attached = 0; | |||
| 444 | status_update_cache(s); | |||
| 445 | } | |||
| 446 | ||||
| 447 | /* | |||
| 448 | * Increment attached count and check the status line size for each | |||
| 449 | * client. | |||
| 450 | */ | |||
| 451 | TAILQ_FOREACH(c, &clients, entry)for((c) = ((&clients)->tqh_first); (c) != ((void *)0); (c) = ((c)->entry.tqe_next)) { | |||
| 452 | s = c->session; | |||
| 453 | if (s != NULL((void *)0) && !(c->flags & CLIENT_UNATTACHEDFLAGS(0x200| 0x40| 0x4))) | |||
| 454 | s->attached++; | |||
| 455 | if (ignore_client_size(c)) | |||
| 456 | continue; | |||
| 457 | if (c->tty.sy <= s->statuslines || (c->flags & CLIENT_CONTROL0x2000)) | |||
| ||||
| 458 | c->flags |= CLIENT_STATUSOFF0x800000; | |||
| 459 | else | |||
| 460 | c->flags &= ~CLIENT_STATUSOFF0x800000; | |||
| 461 | } | |||
| 462 | ||||
| 463 | /* Walk each window and adjust the size. */ | |||
| 464 | RB_FOREACH(w, windows, &windows)for ((w) = windows_RB_MINMAX(&windows, -1); (w) != ((void *)0); (w) = windows_RB_NEXT(w)) | |||
| 465 | recalculate_size(w, now); | |||
| 466 | } |