1 /* $OpenBSD: layout-set.c,v 1.31 2024/08/21 05:03:13 nicm Exp $ */ 2 3 /* 4 * Copyright (c) 2009 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 <stdlib.h> 22 #include <string.h> 23 24 #include "tmux.h" 25 26 /* 27 * Set window layouts - predefined methods to arrange windows. These are 28 * one-off and generate a layout tree. 29 */ 30 31 static void layout_set_even_h(struct window *); 32 static void layout_set_even_v(struct window *); 33 static void layout_set_main_h(struct window *); 34 static void layout_set_main_h_mirrored(struct window *); 35 static void layout_set_main_v(struct window *); 36 static void layout_set_main_v_mirrored(struct window *); 37 static void layout_set_tiled(struct window *); 38 39 static const struct { 40 const char *name; 41 void (*arrange)(struct window *); 42 } layout_sets[] = { 43 { "even-horizontal", layout_set_even_h }, 44 { "even-vertical", layout_set_even_v }, 45 { "main-horizontal", layout_set_main_h }, 46 { "main-horizontal-mirrored", layout_set_main_h_mirrored }, 47 { "main-vertical", layout_set_main_v }, 48 { "main-vertical-mirrored", layout_set_main_v_mirrored }, 49 { "tiled", layout_set_tiled }, 50 }; 51 52 int 53 layout_set_lookup(const char *name) 54 { 55 u_int i; 56 int matched = -1; 57 58 for (i = 0; i < nitems(layout_sets); i++) { 59 if (strncmp(layout_sets[i].name, name, strlen(name)) == 0) { 60 if (matched != -1) /* ambiguous */ 61 return (-1); 62 matched = i; 63 } 64 } 65 66 return (matched); 67 } 68 69 u_int 70 layout_set_select(struct window *w, u_int layout) 71 { 72 if (layout > nitems(layout_sets) - 1) 73 layout = nitems(layout_sets) - 1; 74 75 if (layout_sets[layout].arrange != NULL) 76 layout_sets[layout].arrange(w); 77 78 w->lastlayout = layout; 79 return (layout); 80 } 81 82 u_int 83 layout_set_next(struct window *w) 84 { 85 u_int layout; 86 87 if (w->lastlayout == -1) 88 layout = 0; 89 else { 90 layout = w->lastlayout + 1; 91 if (layout > nitems(layout_sets) - 1) 92 layout = 0; 93 } 94 95 if (layout_sets[layout].arrange != NULL) 96 layout_sets[layout].arrange(w); 97 w->lastlayout = layout; 98 return (layout); 99 } 100 101 u_int 102 layout_set_previous(struct window *w) 103 { 104 u_int layout; 105 106 if (w->lastlayout == -1) 107 layout = nitems(layout_sets) - 1; 108 else { 109 layout = w->lastlayout; 110 if (layout == 0) 111 layout = nitems(layout_sets) - 1; 112 else 113 layout--; 114 } 115 116 if (layout_sets[layout].arrange != NULL) 117 layout_sets[layout].arrange(w); 118 w->lastlayout = layout; 119 return (layout); 120 } 121 122 static void 123 layout_set_even(struct window *w, enum layout_type type) 124 { 125 struct window_pane *wp; 126 struct layout_cell *lc, *lcnew; 127 u_int n, sx, sy; 128 129 layout_print_cell(w->layout_root, __func__, 1); 130 131 /* Get number of panes. */ 132 n = window_count_panes(w); 133 if (n <= 1) 134 return; 135 136 /* Free the old root and construct a new. */ 137 layout_free(w); 138 lc = w->layout_root = layout_create_cell(NULL); 139 if (type == LAYOUT_LEFTRIGHT) { 140 sx = (n * (PANE_MINIMUM + 1)) - 1; 141 if (sx < w->sx) 142 sx = w->sx; 143 sy = w->sy; 144 } else { 145 sy = (n * (PANE_MINIMUM + 1)) - 1; 146 if (sy < w->sy) 147 sy = w->sy; 148 sx = w->sx; 149 } 150 layout_set_size(lc, sx, sy, 0, 0); 151 layout_make_node(lc, type); 152 153 /* Build new leaf cells. */ 154 TAILQ_FOREACH(wp, &w->panes, entry) { 155 lcnew = layout_create_cell(lc); 156 layout_make_leaf(lcnew, wp); 157 lcnew->sx = w->sx; 158 lcnew->sy = w->sy; 159 TAILQ_INSERT_TAIL(&lc->cells, lcnew, entry); 160 } 161 162 /* Spread out cells. */ 163 layout_spread_cell(w, lc); 164 165 /* Fix cell offsets. */ 166 layout_fix_offsets(w); 167 layout_fix_panes(w, NULL); 168 169 layout_print_cell(w->layout_root, __func__, 1); 170 171 window_resize(w, lc->sx, lc->sy, -1, -1); 172 notify_window("window-layout-changed", w); 173 server_redraw_window(w); 174 } 175 176 static void 177 layout_set_even_h(struct window *w) 178 { 179 layout_set_even(w, LAYOUT_LEFTRIGHT); 180 } 181 182 static void 183 layout_set_even_v(struct window *w) 184 { 185 layout_set_even(w, LAYOUT_TOPBOTTOM); 186 } 187 188 static void 189 layout_set_main_h(struct window *w) 190 { 191 struct window_pane *wp; 192 struct layout_cell *lc, *lcmain, *lcother, *lcchild; 193 u_int n, mainh, otherh, sx, sy; 194 char *cause; 195 const char *s; 196 197 layout_print_cell(w->layout_root, __func__, 1); 198 199 /* Get number of panes. */ 200 n = window_count_panes(w); 201 if (n <= 1) 202 return; 203 n--; /* take off main pane */ 204 205 /* Find available height - take off one line for the border. */ 206 sy = w->sy - 1; 207 208 /* Get the main pane height. */ 209 s = options_get_string(w->options, "main-pane-height"); 210 mainh = args_string_percentage(s, 0, sy, sy, &cause); 211 if (cause != NULL) { 212 mainh = 24; 213 free(cause); 214 } 215 216 /* Work out the other pane height. */ 217 if (mainh + PANE_MINIMUM >= sy) { 218 if (sy <= PANE_MINIMUM + PANE_MINIMUM) 219 mainh = PANE_MINIMUM; 220 else 221 mainh = sy - PANE_MINIMUM; 222 otherh = PANE_MINIMUM; 223 } else { 224 s = options_get_string(w->options, "other-pane-height"); 225 otherh = args_string_percentage(s, 0, sy, sy, &cause); 226 if (cause != NULL || otherh == 0) { 227 otherh = sy - mainh; 228 free(cause); 229 } else if (otherh > sy || sy - otherh < mainh) 230 otherh = sy - mainh; 231 else 232 mainh = sy - otherh; 233 } 234 235 /* Work out what width is needed. */ 236 sx = (n * (PANE_MINIMUM + 1)) - 1; 237 if (sx < w->sx) 238 sx = w->sx; 239 240 /* Free old tree and create a new root. */ 241 layout_free(w); 242 lc = w->layout_root = layout_create_cell(NULL); 243 layout_set_size(lc, sx, mainh + otherh + 1, 0, 0); 244 layout_make_node(lc, LAYOUT_TOPBOTTOM); 245 246 /* Create the main pane. */ 247 lcmain = layout_create_cell(lc); 248 layout_set_size(lcmain, sx, mainh, 0, 0); 249 layout_make_leaf(lcmain, TAILQ_FIRST(&w->panes)); 250 TAILQ_INSERT_TAIL(&lc->cells, lcmain, entry); 251 252 /* Create the other pane. */ 253 lcother = layout_create_cell(lc); 254 layout_set_size(lcother, sx, otherh, 0, 0); 255 if (n == 1) { 256 wp = TAILQ_NEXT(TAILQ_FIRST(&w->panes), entry); 257 layout_make_leaf(lcother, wp); 258 TAILQ_INSERT_TAIL(&lc->cells, lcother, entry); 259 } else { 260 layout_make_node(lcother, LAYOUT_LEFTRIGHT); 261 TAILQ_INSERT_TAIL(&lc->cells, lcother, entry); 262 263 /* Add the remaining panes as children. */ 264 TAILQ_FOREACH(wp, &w->panes, entry) { 265 if (wp == TAILQ_FIRST(&w->panes)) 266 continue; 267 lcchild = layout_create_cell(lcother); 268 layout_set_size(lcchild, PANE_MINIMUM, otherh, 0, 0); 269 layout_make_leaf(lcchild, wp); 270 TAILQ_INSERT_TAIL(&lcother->cells, lcchild, entry); 271 } 272 layout_spread_cell(w, lcother); 273 } 274 275 /* Fix cell offsets. */ 276 layout_fix_offsets(w); 277 layout_fix_panes(w, NULL); 278 279 layout_print_cell(w->layout_root, __func__, 1); 280 281 window_resize(w, lc->sx, lc->sy, -1, -1); 282 notify_window("window-layout-changed", w); 283 server_redraw_window(w); 284 } 285 286 static void 287 layout_set_main_h_mirrored(struct window *w) 288 { 289 struct window_pane *wp; 290 struct layout_cell *lc, *lcmain, *lcother, *lcchild; 291 u_int n, mainh, otherh, sx, sy; 292 char *cause; 293 const char *s; 294 295 layout_print_cell(w->layout_root, __func__, 1); 296 297 /* Get number of panes. */ 298 n = window_count_panes(w); 299 if (n <= 1) 300 return; 301 n--; /* take off main pane */ 302 303 /* Find available height - take off one line for the border. */ 304 sy = w->sy - 1; 305 306 /* Get the main pane height. */ 307 s = options_get_string(w->options, "main-pane-height"); 308 mainh = args_string_percentage(s, 0, sy, sy, &cause); 309 if (cause != NULL) { 310 mainh = 24; 311 free(cause); 312 } 313 314 /* Work out the other pane height. */ 315 if (mainh + PANE_MINIMUM >= sy) { 316 if (sy <= PANE_MINIMUM + PANE_MINIMUM) 317 mainh = PANE_MINIMUM; 318 else 319 mainh = sy - PANE_MINIMUM; 320 otherh = PANE_MINIMUM; 321 } else { 322 s = options_get_string(w->options, "other-pane-height"); 323 otherh = args_string_percentage(s, 0, sy, sy, &cause); 324 if (cause != NULL || otherh == 0) { 325 otherh = sy - mainh; 326 free(cause); 327 } else if (otherh > sy || sy - otherh < mainh) 328 otherh = sy - mainh; 329 else 330 mainh = sy - otherh; 331 } 332 333 /* Work out what width is needed. */ 334 sx = (n * (PANE_MINIMUM + 1)) - 1; 335 if (sx < w->sx) 336 sx = w->sx; 337 338 /* Free old tree and create a new root. */ 339 layout_free(w); 340 lc = w->layout_root = layout_create_cell(NULL); 341 layout_set_size(lc, sx, mainh + otherh + 1, 0, 0); 342 layout_make_node(lc, LAYOUT_TOPBOTTOM); 343 344 /* Create the other pane. */ 345 lcother = layout_create_cell(lc); 346 layout_set_size(lcother, sx, otherh, 0, 0); 347 if (n == 1) { 348 wp = TAILQ_NEXT(TAILQ_FIRST(&w->panes), entry); 349 layout_make_leaf(lcother, wp); 350 TAILQ_INSERT_TAIL(&lc->cells, lcother, entry); 351 } else { 352 layout_make_node(lcother, LAYOUT_LEFTRIGHT); 353 TAILQ_INSERT_TAIL(&lc->cells, lcother, entry); 354 355 /* Add the remaining panes as children. */ 356 TAILQ_FOREACH(wp, &w->panes, entry) { 357 if (wp == TAILQ_FIRST(&w->panes)) 358 continue; 359 lcchild = layout_create_cell(lcother); 360 layout_set_size(lcchild, PANE_MINIMUM, otherh, 0, 0); 361 layout_make_leaf(lcchild, wp); 362 TAILQ_INSERT_TAIL(&lcother->cells, lcchild, entry); 363 } 364 layout_spread_cell(w, lcother); 365 } 366 367 /* Create the main pane. */ 368 lcmain = layout_create_cell(lc); 369 layout_set_size(lcmain, sx, mainh, 0, 0); 370 layout_make_leaf(lcmain, TAILQ_FIRST(&w->panes)); 371 TAILQ_INSERT_TAIL(&lc->cells, lcmain, entry); 372 373 /* Fix cell offsets. */ 374 layout_fix_offsets(w); 375 layout_fix_panes(w, NULL); 376 377 layout_print_cell(w->layout_root, __func__, 1); 378 379 window_resize(w, lc->sx, lc->sy, -1, -1); 380 notify_window("window-layout-changed", w); 381 server_redraw_window(w); 382 } 383 384 static void 385 layout_set_main_v(struct window *w) 386 { 387 struct window_pane *wp; 388 struct layout_cell *lc, *lcmain, *lcother, *lcchild; 389 u_int n, mainw, otherw, sx, sy; 390 char *cause; 391 const char *s; 392 393 layout_print_cell(w->layout_root, __func__, 1); 394 395 /* Get number of panes. */ 396 n = window_count_panes(w); 397 if (n <= 1) 398 return; 399 n--; /* take off main pane */ 400 401 /* Find available width - take off one line for the border. */ 402 sx = w->sx - 1; 403 404 /* Get the main pane width. */ 405 s = options_get_string(w->options, "main-pane-width"); 406 mainw = args_string_percentage(s, 0, sx, sx, &cause); 407 if (cause != NULL) { 408 mainw = 80; 409 free(cause); 410 } 411 412 /* Work out the other pane width. */ 413 if (mainw + PANE_MINIMUM >= sx) { 414 if (sx <= PANE_MINIMUM + PANE_MINIMUM) 415 mainw = PANE_MINIMUM; 416 else 417 mainw = sx - PANE_MINIMUM; 418 otherw = PANE_MINIMUM; 419 } else { 420 s = options_get_string(w->options, "other-pane-width"); 421 otherw = args_string_percentage(s, 0, sx, sx, &cause); 422 if (cause != NULL || otherw == 0) { 423 otherw = sx - mainw; 424 free(cause); 425 } else if (otherw > sx || sx - otherw < mainw) 426 otherw = sx - mainw; 427 else 428 mainw = sx - otherw; 429 } 430 431 /* Work out what height is needed. */ 432 sy = (n * (PANE_MINIMUM + 1)) - 1; 433 if (sy < w->sy) 434 sy = w->sy; 435 436 /* Free old tree and create a new root. */ 437 layout_free(w); 438 lc = w->layout_root = layout_create_cell(NULL); 439 layout_set_size(lc, mainw + otherw + 1, sy, 0, 0); 440 layout_make_node(lc, LAYOUT_LEFTRIGHT); 441 442 /* Create the main pane. */ 443 lcmain = layout_create_cell(lc); 444 layout_set_size(lcmain, mainw, sy, 0, 0); 445 layout_make_leaf(lcmain, TAILQ_FIRST(&w->panes)); 446 TAILQ_INSERT_TAIL(&lc->cells, lcmain, entry); 447 448 /* Create the other pane. */ 449 lcother = layout_create_cell(lc); 450 layout_set_size(lcother, otherw, sy, 0, 0); 451 if (n == 1) { 452 wp = TAILQ_NEXT(TAILQ_FIRST(&w->panes), entry); 453 layout_make_leaf(lcother, wp); 454 TAILQ_INSERT_TAIL(&lc->cells, lcother, entry); 455 } else { 456 layout_make_node(lcother, LAYOUT_TOPBOTTOM); 457 TAILQ_INSERT_TAIL(&lc->cells, lcother, entry); 458 459 /* Add the remaining panes as children. */ 460 TAILQ_FOREACH(wp, &w->panes, entry) { 461 if (wp == TAILQ_FIRST(&w->panes)) 462 continue; 463 lcchild = layout_create_cell(lcother); 464 layout_set_size(lcchild, otherw, PANE_MINIMUM, 0, 0); 465 layout_make_leaf(lcchild, wp); 466 TAILQ_INSERT_TAIL(&lcother->cells, lcchild, entry); 467 } 468 layout_spread_cell(w, lcother); 469 } 470 471 /* Fix cell offsets. */ 472 layout_fix_offsets(w); 473 layout_fix_panes(w, NULL); 474 475 layout_print_cell(w->layout_root, __func__, 1); 476 477 window_resize(w, lc->sx, lc->sy, -1, -1); 478 notify_window("window-layout-changed", w); 479 server_redraw_window(w); 480 } 481 482 static void 483 layout_set_main_v_mirrored(struct window *w) 484 { 485 struct window_pane *wp; 486 struct layout_cell *lc, *lcmain, *lcother, *lcchild; 487 u_int n, mainw, otherw, sx, sy; 488 char *cause; 489 const char *s; 490 491 layout_print_cell(w->layout_root, __func__, 1); 492 493 /* Get number of panes. */ 494 n = window_count_panes(w); 495 if (n <= 1) 496 return; 497 n--; /* take off main pane */ 498 499 /* Find available width - take off one line for the border. */ 500 sx = w->sx - 1; 501 502 /* Get the main pane width. */ 503 s = options_get_string(w->options, "main-pane-width"); 504 mainw = args_string_percentage(s, 0, sx, sx, &cause); 505 if (cause != NULL) { 506 mainw = 80; 507 free(cause); 508 } 509 510 /* Work out the other pane width. */ 511 if (mainw + PANE_MINIMUM >= sx) { 512 if (sx <= PANE_MINIMUM + PANE_MINIMUM) 513 mainw = PANE_MINIMUM; 514 else 515 mainw = sx - PANE_MINIMUM; 516 otherw = PANE_MINIMUM; 517 } else { 518 s = options_get_string(w->options, "other-pane-width"); 519 otherw = args_string_percentage(s, 0, sx, sx, &cause); 520 if (cause != NULL || otherw == 0) { 521 otherw = sx - mainw; 522 free(cause); 523 } else if (otherw > sx || sx - otherw < mainw) 524 otherw = sx - mainw; 525 else 526 mainw = sx - otherw; 527 } 528 529 /* Work out what height is needed. */ 530 sy = (n * (PANE_MINIMUM + 1)) - 1; 531 if (sy < w->sy) 532 sy = w->sy; 533 534 /* Free old tree and create a new root. */ 535 layout_free(w); 536 lc = w->layout_root = layout_create_cell(NULL); 537 layout_set_size(lc, mainw + otherw + 1, sy, 0, 0); 538 layout_make_node(lc, LAYOUT_LEFTRIGHT); 539 540 /* Create the other pane. */ 541 lcother = layout_create_cell(lc); 542 layout_set_size(lcother, otherw, sy, 0, 0); 543 if (n == 1) { 544 wp = TAILQ_NEXT(TAILQ_FIRST(&w->panes), entry); 545 layout_make_leaf(lcother, wp); 546 TAILQ_INSERT_TAIL(&lc->cells, lcother, entry); 547 } else { 548 layout_make_node(lcother, LAYOUT_TOPBOTTOM); 549 TAILQ_INSERT_TAIL(&lc->cells, lcother, entry); 550 551 /* Add the remaining panes as children. */ 552 TAILQ_FOREACH(wp, &w->panes, entry) { 553 if (wp == TAILQ_FIRST(&w->panes)) 554 continue; 555 lcchild = layout_create_cell(lcother); 556 layout_set_size(lcchild, otherw, PANE_MINIMUM, 0, 0); 557 layout_make_leaf(lcchild, wp); 558 TAILQ_INSERT_TAIL(&lcother->cells, lcchild, entry); 559 } 560 layout_spread_cell(w, lcother); 561 } 562 563 /* Create the main pane. */ 564 lcmain = layout_create_cell(lc); 565 layout_set_size(lcmain, mainw, sy, 0, 0); 566 layout_make_leaf(lcmain, TAILQ_FIRST(&w->panes)); 567 TAILQ_INSERT_TAIL(&lc->cells, lcmain, entry); 568 569 /* Fix cell offsets. */ 570 layout_fix_offsets(w); 571 layout_fix_panes(w, NULL); 572 573 layout_print_cell(w->layout_root, __func__, 1); 574 575 window_resize(w, lc->sx, lc->sy, -1, -1); 576 notify_window("window-layout-changed", w); 577 server_redraw_window(w); 578 } 579 580 void 581 layout_set_tiled(struct window *w) 582 { 583 struct window_pane *wp; 584 struct layout_cell *lc, *lcrow, *lcchild; 585 u_int n, width, height, used, sx, sy; 586 u_int i, j, columns, rows; 587 588 layout_print_cell(w->layout_root, __func__, 1); 589 590 /* Get number of panes. */ 591 n = window_count_panes(w); 592 if (n <= 1) 593 return; 594 595 /* How many rows and columns are wanted? */ 596 rows = columns = 1; 597 while (rows * columns < n) { 598 rows++; 599 if (rows * columns < n) 600 columns++; 601 } 602 603 /* What width and height should they be? */ 604 width = (w->sx - (columns - 1)) / columns; 605 if (width < PANE_MINIMUM) 606 width = PANE_MINIMUM; 607 height = (w->sy - (rows - 1)) / rows; 608 if (height < PANE_MINIMUM) 609 height = PANE_MINIMUM; 610 611 /* Free old tree and create a new root. */ 612 layout_free(w); 613 lc = w->layout_root = layout_create_cell(NULL); 614 sx = ((width + 1) * columns) - 1; 615 if (sx < w->sx) 616 sx = w->sx; 617 sy = ((height + 1) * rows) - 1; 618 if (sy < w->sy) 619 sy = w->sy; 620 layout_set_size(lc, sx, sy, 0, 0); 621 layout_make_node(lc, LAYOUT_TOPBOTTOM); 622 623 /* Create a grid of the cells. */ 624 wp = TAILQ_FIRST(&w->panes); 625 for (j = 0; j < rows; j++) { 626 /* If this is the last cell, all done. */ 627 if (wp == NULL) 628 break; 629 630 /* Create the new row. */ 631 lcrow = layout_create_cell(lc); 632 layout_set_size(lcrow, w->sx, height, 0, 0); 633 TAILQ_INSERT_TAIL(&lc->cells, lcrow, entry); 634 635 /* If only one column, just use the row directly. */ 636 if (n - (j * columns) == 1 || columns == 1) { 637 layout_make_leaf(lcrow, wp); 638 wp = TAILQ_NEXT(wp, entry); 639 continue; 640 } 641 642 /* Add in the columns. */ 643 layout_make_node(lcrow, LAYOUT_LEFTRIGHT); 644 for (i = 0; i < columns; i++) { 645 /* Create and add a pane cell. */ 646 lcchild = layout_create_cell(lcrow); 647 layout_set_size(lcchild, width, height, 0, 0); 648 layout_make_leaf(lcchild, wp); 649 TAILQ_INSERT_TAIL(&lcrow->cells, lcchild, entry); 650 651 /* Move to the next cell. */ 652 if ((wp = TAILQ_NEXT(wp, entry)) == NULL) 653 break; 654 } 655 656 /* 657 * Adjust the row and columns to fit the full width if 658 * necessary. 659 */ 660 if (i == columns) 661 i--; 662 used = ((i + 1) * (width + 1)) - 1; 663 if (w->sx <= used) 664 continue; 665 lcchild = TAILQ_LAST(&lcrow->cells, layout_cells); 666 layout_resize_adjust(w, lcchild, LAYOUT_LEFTRIGHT, 667 w->sx - used); 668 } 669 670 /* Adjust the last row height to fit if necessary. */ 671 used = (rows * height) + rows - 1; 672 if (w->sy > used) { 673 lcrow = TAILQ_LAST(&lc->cells, layout_cells); 674 layout_resize_adjust(w, lcrow, LAYOUT_TOPBOTTOM, 675 w->sy - used); 676 } 677 678 /* Fix cell offsets. */ 679 layout_fix_offsets(w); 680 layout_fix_panes(w, NULL); 681 682 layout_print_cell(w->layout_root, __func__, 1); 683 684 window_resize(w, lc->sx, lc->sy, -1, -1); 685 notify_window("window-layout-changed", w); 686 server_redraw_window(w); 687 } 688