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