diff options
| author | Martin Rudalics | 2012-08-22 11:22:08 +0200 |
|---|---|---|
| committer | Martin Rudalics | 2012-08-22 11:22:08 +0200 |
| commit | caceae2529106eef4b5cc2b56c0cc6319ea7fcdf (patch) | |
| tree | 245e4ba036063c23dc33b886d61346b47e114e5a | |
| parent | 842e3a93aa3a0826cb4148376e54cd1527d10901 (diff) | |
| download | emacs-caceae2529106eef4b5cc2b56c0cc6319ea7fcdf.tar.gz emacs-caceae2529106eef4b5cc2b56c0cc6319ea7fcdf.zip | |
Rewrite handling of side and atomic windows.
* window.el (display-buffer-in-atom-window, window--major-non-side-window)
(window--major-side-window, display-buffer-in-major-side-window)
(delete-side-window, display-buffer-in-side-window): New
functions.
(window--side-check, window-deletable-p, delete-window)
(delete-other-windows, split-window): Handle side windows and
atomic windows appropriately.
(window--display-buffer): Call display-buffer-record-window also
when the window buffer did not change.
| -rw-r--r-- | lisp/ChangeLog | 9 | ||||
| -rw-r--r-- | lisp/window.el | 485 |
2 files changed, 409 insertions, 85 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 4296280b22e..f8ed5ce15fd 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -7,6 +7,15 @@ | |||
| 7 | (window-in-direction): Simplify and rewrite doc-string. | 7 | (window-in-direction): Simplify and rewrite doc-string. |
| 8 | (window--size-ignore): Rename to window--size-ignore-p. Update | 8 | (window--size-ignore): Rename to window--size-ignore-p. Update |
| 9 | callers. | 9 | callers. |
| 10 | (display-buffer-in-atom-window, window--major-non-side-window) | ||
| 11 | (window--major-side-window, display-buffer-in-major-side-window) | ||
| 12 | (delete-side-window, display-buffer-in-side-window): New | ||
| 13 | functions. | ||
| 14 | (window--side-check, window-deletable-p, delete-window) | ||
| 15 | (delete-other-windows, split-window): Handle side windows and | ||
| 16 | atomic windows appropriately. | ||
| 17 | (window--display-buffer): Call display-buffer-record-window also | ||
| 18 | when the window buffer did not change. | ||
| 10 | 19 | ||
| 11 | 2012-08-22 Christopher Schmidt <christopher@ch.ristopher.com> | 20 | 2012-08-22 Christopher Schmidt <christopher@ch.ristopher.com> |
| 12 | 21 | ||
diff --git a/lisp/window.el b/lisp/window.el index ab90d8a4bde..8f402f0c2b9 100644 --- a/lisp/window.el +++ b/lisp/window.el | |||
| @@ -357,6 +357,45 @@ WINDOW must be an internal window. Return WINDOW." | |||
| 357 | window t) | 357 | window t) |
| 358 | window)) | 358 | window)) |
| 359 | 359 | ||
| 360 | (defun display-buffer-in-atom-window (buffer alist) | ||
| 361 | "Display BUFFER in an atomic window. | ||
| 362 | This function displays BUFFER in a new window that will be | ||
| 363 | combined with an existing window to form an atomic window. If | ||
| 364 | the existing window is already part of an atomic window, add the | ||
| 365 | new window to that atomic window. Operations like `split-window' | ||
| 366 | or `delete-window', when applied to a constituent of an atomic | ||
| 367 | window, are applied atomically to the root of that atomic window. | ||
| 368 | |||
| 369 | ALIST is an association list of symbols and values. The | ||
| 370 | following symbols can be used. | ||
| 371 | |||
| 372 | `window' specifies the existing window the new window shall be | ||
| 373 | combined with. Use `window-atom-root' to make the new window a | ||
| 374 | sibling of an atomic window's root. If an internal window is | ||
| 375 | specified here, all children of that window become part of the | ||
| 376 | atomic window too. If no window is specified, the new window | ||
| 377 | becomes a sibling of the selected window. | ||
| 378 | |||
| 379 | `side' denotes the side of the existing window where the new | ||
| 380 | window shall be located. Valid values are `below', `right', | ||
| 381 | `above' and `left'. The default is `below'. | ||
| 382 | |||
| 383 | The return value is the new window, nil when creating that window | ||
| 384 | failed." | ||
| 385 | (let ((ignore-window-parameters t) | ||
| 386 | (window-combination-limit t) | ||
| 387 | (window (cdr (assq 'window alist))) | ||
| 388 | (side (cdr (assq 'side alist))) | ||
| 389 | new) | ||
| 390 | (setq window (window-normalize-window window)) | ||
| 391 | ;; Split off new window | ||
| 392 | (when (setq new (split-window window nil side)) | ||
| 393 | ;; Make sure we have a valid atomic window. | ||
| 394 | (window-make-atom (window-parent window)) | ||
| 395 | ;; Display BUFFER in NEW and return NEW. | ||
| 396 | (window--display-buffer | ||
| 397 | buffer new 'window display-buffer-mark-dedicated)))) | ||
| 398 | |||
| 360 | (defun window--atom-check-1 (window) | 399 | (defun window--atom-check-1 (window) |
| 361 | "Subroutine of `window--atom-check'." | 400 | "Subroutine of `window--atom-check'." |
| 362 | (when window | 401 | (when window |
| @@ -446,23 +485,273 @@ number of slots on that side." | |||
| 446 | (integer :tag "Number" :value 3 :size 5))) | 485 | (integer :tag "Number" :value 3 :size 5))) |
| 447 | :group 'windows) | 486 | :group 'windows) |
| 448 | 487 | ||
| 488 | (defun window--major-non-side-window (&optional frame) | ||
| 489 | "Return the major non-side window of frame FRAME. | ||
| 490 | The optional argument FRAME must be a live frame and defaults to | ||
| 491 | the selected one. | ||
| 492 | |||
| 493 | If FRAME has at least one side window, the major non-side window | ||
| 494 | is either an internal non-side window such that all other | ||
| 495 | non-side windows on FRAME descend from it, or the single live | ||
| 496 | non-side window of FRAME. If FRAME has no side windows, return | ||
| 497 | its root window." | ||
| 498 | (let ((frame (window-normalize-frame frame)) | ||
| 499 | major sibling) | ||
| 500 | ;; Set major to the _last_ window found by `walk-window-tree' that | ||
| 501 | ;; is not a side window but has a side window as its sibling. | ||
| 502 | (walk-window-tree | ||
| 503 | (lambda (window) | ||
| 504 | (and (not (window-parameter window 'window-side)) | ||
| 505 | (or (and (setq sibling (window-prev-sibling window)) | ||
| 506 | (window-parameter sibling 'window-side)) | ||
| 507 | (and (setq sibling (window-next-sibling window)) | ||
| 508 | (window-parameter sibling 'window-side))) | ||
| 509 | (setq major window))) | ||
| 510 | frame t) | ||
| 511 | (or major (frame-root-window frame)))) | ||
| 512 | |||
| 513 | (defun window--major-side-window (side) | ||
| 514 | "Return major side window on SIDE. | ||
| 515 | SIDE must be one of the symbols `left', `top', `right' or | ||
| 516 | `bottom'. Return nil if no such window exists." | ||
| 517 | (let ((root (frame-root-window)) | ||
| 518 | window) | ||
| 519 | ;; (1) If a window on the opposite side exists, return that window's | ||
| 520 | ;; sibling. | ||
| 521 | ;; (2) If the new window shall span the entire side, return the | ||
| 522 | ;; frame's root window. | ||
| 523 | ;; (3) If a window on an orthogonal side exists, return that | ||
| 524 | ;; window's sibling. | ||
| 525 | ;; (4) Otherwise return the frame's root window. | ||
| 526 | (cond | ||
| 527 | ((or (and (eq side 'left) | ||
| 528 | (setq window (window-with-parameter 'window-side 'right nil t))) | ||
| 529 | (and (eq side 'top) | ||
| 530 | (setq window (window-with-parameter 'window-side 'bottom nil t)))) | ||
| 531 | (window-prev-sibling window)) | ||
| 532 | ((or (and (eq side 'right) | ||
| 533 | (setq window (window-with-parameter 'window-side 'left nil t))) | ||
| 534 | (and (eq side 'bottom) | ||
| 535 | (setq window (window-with-parameter 'window-side 'top nil t)))) | ||
| 536 | (window-next-sibling window)) | ||
| 537 | ((memq side '(left right)) | ||
| 538 | (cond | ||
| 539 | (window-sides-vertical | ||
| 540 | root) | ||
| 541 | ((setq window (window-with-parameter 'window-side 'top nil t)) | ||
| 542 | (window-next-sibling window)) | ||
| 543 | ((setq window (window-with-parameter 'window-side 'bottom nil t)) | ||
| 544 | (window-prev-sibling window)) | ||
| 545 | (t root))) | ||
| 546 | ((memq side '(top bottom)) | ||
| 547 | (cond | ||
| 548 | ((not window-sides-vertical) | ||
| 549 | root) | ||
| 550 | ((setq window (window-with-parameter 'window-side 'left nil t)) | ||
| 551 | (window-next-sibling window)) | ||
| 552 | ((setq window (window-with-parameter 'window-side 'right nil t)) | ||
| 553 | (window-prev-sibling window)) | ||
| 554 | (t root)))))) | ||
| 555 | |||
| 556 | (defun display-buffer-in-major-side-window (buffer side slot &optional alist) | ||
| 557 | "Display BUFFER in a new window on SIDE of the selected frame. | ||
| 558 | SIDE must be one of `left', `top', `right' or `bottom'. SLOT | ||
| 559 | specifies the slot to use. ALIST is an association list of | ||
| 560 | symbols and values as passed to `display-buffer-in-side-window'. | ||
| 561 | This function may be called only if no window on SIDE exists yet. | ||
| 562 | The new window automatically becomes the \"major\" side window on | ||
| 563 | SIDE. Return the new window, nil if its creation window failed." | ||
| 564 | (let* ((root (frame-root-window)) | ||
| 565 | (left-or-right (memq side '(left right))) | ||
| 566 | (size (or (assq 'size alist) | ||
| 567 | (/ (window-total-size (frame-root-window) left-or-right) | ||
| 568 | ;; By default use a fourth of the size of the | ||
| 569 | ;; frame's root window. This has to be made | ||
| 570 | ;; customizable via ALIST. | ||
| 571 | 4))) | ||
| 572 | (major (window--major-side-window side)) | ||
| 573 | (selected-window (selected-window)) | ||
| 574 | (on-side (cond | ||
| 575 | ((eq side 'top) 'above) | ||
| 576 | ((eq side 'bottom) 'below) | ||
| 577 | (t side))) | ||
| 578 | ;; The following two bindings will tell `split-window' to take | ||
| 579 | ;; the space for the new window from `major' and not make a new | ||
| 580 | ;; parent window unless needed. | ||
| 581 | (window-combination-resize 'side) | ||
| 582 | (window-combination-limit nil) | ||
| 583 | (new (split-window major (- size) on-side)) | ||
| 584 | fun) | ||
| 585 | (when new | ||
| 586 | ;; Initialize `window-side' parameter of new window to SIDE. | ||
| 587 | (set-window-parameter new 'window-side side) | ||
| 588 | ;; Install `window-slot' parameter of new window. | ||
| 589 | (set-window-parameter new 'window-slot slot) | ||
| 590 | ;; Install `delete-window' parameter thus making sure that when | ||
| 591 | ;; the new window is deleted, a side window on the opposite side | ||
| 592 | ;; does not get resized. | ||
| 593 | (set-window-parameter new 'delete-window 'delete-side-window) | ||
| 594 | ;; Install BUFFER in new window and return NEW. | ||
| 595 | (window--display-buffer buffer new 'window 'side)))) | ||
| 596 | |||
| 597 | (defun delete-side-window (window) | ||
| 598 | "Delete side window WINDOW." | ||
| 599 | (let ((window-combination-resize | ||
| 600 | (window-parameter (window-parent window) 'window-side)) | ||
| 601 | (ignore-window-parameters t)) | ||
| 602 | (delete-window window))) | ||
| 603 | |||
| 604 | (defun display-buffer-in-side-window (buffer alist) | ||
| 605 | "Display BUFFER in a window on side SIDE of the selected frame. | ||
| 606 | ALIST is an association list of symbols and values. The | ||
| 607 | following symbols can be used: | ||
| 608 | |||
| 609 | `side' denotes the side of the existing window where the new | ||
| 610 | window shall be located. Valid values are `bottom', `right', | ||
| 611 | `top' and `left'. The default is `bottom'. | ||
| 612 | |||
| 613 | `slot' if non-nil, specifies the window slot where to display | ||
| 614 | BUFFER. A value of zero or nil means use the middle slot on | ||
| 615 | the specified side. A negative value means use a slot | ||
| 616 | preceding (that is, above or on the left of) the middle slot. | ||
| 617 | A positive value means use a slot following (that is, below or | ||
| 618 | on the right of) the middle slot. The default is zero." | ||
| 619 | (let ((side (or (cdr (assq 'side alist)) 'bottom)) | ||
| 620 | (slot (or (cdr (assq 'slot alist)) 0)) | ||
| 621 | new) | ||
| 622 | (cond | ||
| 623 | ((not (memq side '(top bottom left right))) | ||
| 624 | (error "Invalid side %s specified" side)) | ||
| 625 | ((not (numberp slot)) | ||
| 626 | (error "Invalid slot %s specified" slot))) | ||
| 627 | |||
| 628 | (let* ((major (window-with-parameter 'window-side side nil t)) | ||
| 629 | ;; `major' is the major window on SIDE, `windows' the list of | ||
| 630 | ;; life windows on SIDE. | ||
| 631 | (windows | ||
| 632 | (when major | ||
| 633 | (let (windows) | ||
| 634 | (walk-window-tree | ||
| 635 | (lambda (window) | ||
| 636 | (when (eq (window-parameter window 'window-side) side) | ||
| 637 | (setq windows (cons window windows))))) | ||
| 638 | (nreverse windows)))) | ||
| 639 | (slots (when major (max 1 (window-child-count major)))) | ||
| 640 | (max-slots | ||
| 641 | (nth (cond | ||
| 642 | ((eq side 'left) 0) | ||
| 643 | ((eq side 'top) 1) | ||
| 644 | ((eq side 'right) 2) | ||
| 645 | ((eq side 'bottom) 3)) | ||
| 646 | window-sides-slots)) | ||
| 647 | (selected-window (selected-window)) | ||
| 648 | window this-window this-slot prev-window next-window | ||
| 649 | best-window best-slot abs-slot new-window) | ||
| 650 | |||
| 651 | (cond | ||
| 652 | ((and (numberp max-slots) (<= max-slots 0)) | ||
| 653 | ;; No side-slots available on this side. Don't create an error, | ||
| 654 | ;; just return nil. | ||
| 655 | nil) | ||
| 656 | ((not windows) | ||
| 657 | ;; No major window exists on this side, make one. | ||
| 658 | (display-buffer-in-major-side-window buffer side slot alist)) | ||
| 659 | (t | ||
| 660 | ;; Scan windows on SIDE. | ||
| 661 | (catch 'found | ||
| 662 | (dolist (window windows) | ||
| 663 | (setq this-slot (window-parameter window 'window-slot)) | ||
| 664 | (cond | ||
| 665 | ;; The following should not happen and probably be checked | ||
| 666 | ;; by window--side-check. | ||
| 667 | ((not (numberp this-slot))) | ||
| 668 | ((= this-slot slot) | ||
| 669 | ;; A window with a matching slot has been found. | ||
| 670 | (setq this-window window) | ||
| 671 | (throw 'found t)) | ||
| 672 | (t | ||
| 673 | ;; Check if this window has a better slot value wrt the | ||
| 674 | ;; slot of the window we want. | ||
| 675 | (setq abs-slot | ||
| 676 | (if (or (and (> this-slot 0) (> slot 0)) | ||
| 677 | (and (< this-slot 0) (< slot 0))) | ||
| 678 | (abs (- slot this-slot)) | ||
| 679 | (+ (abs slot) (abs this-slot)))) | ||
| 680 | (unless (and best-slot (<= best-slot abs-slot)) | ||
| 681 | (setq best-window window) | ||
| 682 | (setq best-slot abs-slot)) | ||
| 683 | (cond | ||
| 684 | ((<= this-slot slot) | ||
| 685 | (setq prev-window window)) | ||
| 686 | ((not next-window) | ||
| 687 | (setq next-window window))))))) | ||
| 688 | |||
| 689 | ;; `this-window' is the first window with the same SLOT. | ||
| 690 | ;; `prev-window' is the window with the largest slot < SLOT. A new | ||
| 691 | ;; window will be created after it. | ||
| 692 | ;; `next-window' is the window with the smallest slot > SLOT. A new | ||
| 693 | ;; window will be created before it. | ||
| 694 | ;; `best-window' is the window with the smallest absolute difference | ||
| 695 | ;; of its slot and SLOT. | ||
| 696 | |||
| 697 | ;; Note: We dedicate the window used softly to its buffer to | ||
| 698 | ;; avoid that "other" (non-side) buffer display functions steal | ||
| 699 | ;; it from us. This must eventually become customizable via | ||
| 700 | ;; ALIST (or, better, avoided in the "other" functions). | ||
| 701 | (or (and this-window | ||
| 702 | ;; Reuse `this-window'. | ||
| 703 | (window--display-buffer buffer this-window 'reuse 'side)) | ||
| 704 | (and (or (not max-slots) (< slots max-slots)) | ||
| 705 | (or (and next-window | ||
| 706 | ;; Make new window before `next-window'. | ||
| 707 | (let ((next-side | ||
| 708 | (if (memq side '(left right)) 'above 'left)) | ||
| 709 | (window-combination-resize 'side)) | ||
| 710 | (setq window (split-window next-window nil next-side)) | ||
| 711 | ;; When the new window is deleted, its space | ||
| 712 | ;; is returned to other side windows. | ||
| 713 | (set-window-parameter | ||
| 714 | window 'delete-window 'delete-side-window) | ||
| 715 | window)) | ||
| 716 | (and prev-window | ||
| 717 | ;; Make new window after `prev-window'. | ||
| 718 | (let ((prev-side | ||
| 719 | (if (memq side '(left right)) 'below 'right)) | ||
| 720 | (window-combination-resize 'side)) | ||
| 721 | (setq window (split-window prev-window nil prev-side)) | ||
| 722 | ;; When the new window is deleted, its space | ||
| 723 | ;; is returned to other side windows. | ||
| 724 | (set-window-parameter | ||
| 725 | window 'delete-window 'delete-side-window) | ||
| 726 | window))) | ||
| 727 | (set-window-parameter window 'window-slot slot) | ||
| 728 | (window--display-buffer buffer window 'window 'side)) | ||
| 729 | (and best-window | ||
| 730 | ;; Reuse `best-window'. | ||
| 731 | (progn | ||
| 732 | ;; Give best-window the new slot value. | ||
| 733 | (set-window-parameter best-window 'window-slot slot) | ||
| 734 | (window--display-buffer buffer best-window 'reuse 'side))))))))) | ||
| 735 | |||
| 449 | (defun window--side-check (&optional frame) | 736 | (defun window--side-check (&optional frame) |
| 450 | "Check the window-side parameter of all windows on FRAME. | 737 | "Check the side window configuration of FRAME. |
| 451 | FRAME defaults to the selected frame. If the configuration is | 738 | FRAME defaults to the selected frame. |
| 452 | invalid, reset all window-side parameters to nil. | 739 | |
| 453 | 740 | A valid side window configuration preserves the following two | |
| 454 | A valid configuration has to preserve the following invariant: | 741 | invariants: |
| 455 | 742 | ||
| 456 | - If a window has a non-nil window-side parameter, it must have a | 743 | - If there exists a window whose window-side parameter is |
| 457 | parent window and the parent window's window-side parameter | 744 | non-nil, there must exist at least one live window whose |
| 458 | must be either nil or the same as for window. | 745 | window-side parameter is nil. |
| 459 | 746 | ||
| 460 | - If windows with non-nil window-side parameters exist, there | 747 | - If a window W has a non-nil window-side parameter (i) it must |
| 461 | must be at most one window of each side and non-side with a | 748 | have a parent window and that parent's window-side parameter |
| 462 | parent whose window-side parameter is nil and there must be no | 749 | must be either nil or the same as for W, and (ii) any child |
| 463 | leaf window whose window-side parameter is nil." | 750 | window of W must have the same window-side parameter as W. |
| 464 | (let (normal none left top right bottom | 751 | |
| 465 | side parent parent-side) | 752 | If the configuration is invalid, reset the window-side parameters |
| 753 | of all windows on FRAME to nil." | ||
| 754 | (let (left top right bottom none side parent parent-side) | ||
| 466 | (when (or (catch 'reset | 755 | (when (or (catch 'reset |
| 467 | (walk-window-tree | 756 | (walk-window-tree |
| 468 | (lambda (window) | 757 | (lambda (window) |
| @@ -478,40 +767,34 @@ A valid configuration has to preserve the following invariant: | |||
| 478 | ;; A parent whose window-side is non-nil must | 767 | ;; A parent whose window-side is non-nil must |
| 479 | ;; have a child with the same window-side. | 768 | ;; have a child with the same window-side. |
| 480 | (throw 'reset t))) | 769 | (throw 'reset t))) |
| 481 | ;; Now check that there's more than one main window | 770 | ((not side) |
| 482 | ;; for any of none, left, top, right and bottom. | 771 | (when (window-buffer window) |
| 483 | ((eq side 'none) | 772 | ;; Record that we have at least one non-side, |
| 484 | (if none | 773 | ;; live window. |
| 485 | (throw 'reset t) | ||
| 486 | (setq none t))) | 774 | (setq none t))) |
| 775 | ((if (memq side '(left top)) | ||
| 776 | (window-prev-sibling window) | ||
| 777 | (window-next-sibling window)) | ||
| 778 | ;; Left and top major side windows must not have a | ||
| 779 | ;; previous sibling, right and bottom major side | ||
| 780 | ;; windows must not have a next sibling. | ||
| 781 | (throw 'reset t)) | ||
| 782 | ;; Now check that there's no more than one major | ||
| 783 | ;; window for any of left, top, right and bottom. | ||
| 487 | ((eq side 'left) | 784 | ((eq side 'left) |
| 488 | (if left | 785 | (if left (throw 'reset t) (setq left t))) |
| 489 | (throw 'reset t) | ||
| 490 | (setq left t))) | ||
| 491 | ((eq side 'top) | 786 | ((eq side 'top) |
| 492 | (if top | 787 | (if top (throw 'reset t) (setq top t))) |
| 493 | (throw 'reset t) | ||
| 494 | (setq top t))) | ||
| 495 | ((eq side 'right) | 788 | ((eq side 'right) |
| 496 | (if right | 789 | (if right (throw 'reset t) (setq right t))) |
| 497 | (throw 'reset t) | ||
| 498 | (setq right t))) | ||
| 499 | ((eq side 'bottom) | 790 | ((eq side 'bottom) |
| 500 | (if bottom | 791 | (if bottom (throw 'reset t) (setq bottom t))) |
| 501 | (throw 'reset t) | 792 | (t |
| 502 | (setq bottom t))) | 793 | (throw 'reset t)))) |
| 503 | ((window-buffer window) | ||
| 504 | ;; A leaf window without window-side parameter, | ||
| 505 | ;; record its existence. | ||
| 506 | (setq normal t)))) | ||
| 507 | frame t)) | 794 | frame t)) |
| 508 | (if none | 795 | ;; If there's a side window, there must be at least one |
| 509 | ;; At least one non-side window exists, so there must | 796 | ;; non-side window. |
| 510 | ;; be at least one side-window and no normal window. | 797 | (and (or left top right bottom) (not none))) |
| 511 | (or (not (or left top right bottom)) normal) | ||
| 512 | ;; No non-side window exists, so there must be no side | ||
| 513 | ;; window either. | ||
| 514 | (or left top right bottom))) | ||
| 515 | (walk-window-tree | 798 | (walk-window-tree |
| 516 | (lambda (window) | 799 | (lambda (window) |
| 517 | (set-window-parameter window 'window-side nil)) | 800 | (set-window-parameter window 'window-side nil)) |
| @@ -2393,8 +2676,7 @@ Return `frame' if deleting WINDOW should also delete its frame." | |||
| 2393 | (when (window-parameter window 'window-atom) | 2676 | (when (window-parameter window 'window-atom) |
| 2394 | (setq window (window-atom-root window)))) | 2677 | (setq window (window-atom-root window)))) |
| 2395 | 2678 | ||
| 2396 | (let ((parent (window-parent window)) | 2679 | (let ((frame (window-frame window))) |
| 2397 | (frame (window-frame window))) | ||
| 2398 | (cond | 2680 | (cond |
| 2399 | ((frame-root-window-p window) | 2681 | ((frame-root-window-p window) |
| 2400 | ;; WINDOW's frame can be deleted only if there are other frames | 2682 | ;; WINDOW's frame can be deleted only if there are other frames |
| @@ -2405,10 +2687,9 @@ Return `frame' if deleting WINDOW should also delete its frame." | |||
| 2405 | (and minibuf (eq frame (window-frame minibuf))))) | 2687 | (and minibuf (eq frame (window-frame minibuf))))) |
| 2406 | 'frame)) | 2688 | 'frame)) |
| 2407 | ((or ignore-window-parameters | 2689 | ((or ignore-window-parameters |
| 2408 | (not (eq (window-parameter window 'window-side) 'none)) | 2690 | (not (eq window (window--major-non-side-window frame)))) |
| 2409 | (and parent (eq (window-parameter parent 'window-side) 'none))) | 2691 | ;; WINDOW can be deleted unless it is the major non-side window of |
| 2410 | ;; WINDOW can be deleted unless it is the main window of its | 2692 | ;; its frame. |
| 2411 | ;; frame. | ||
| 2412 | t)))) | 2693 | t)))) |
| 2413 | 2694 | ||
| 2414 | (defun window--in-subtree-p (window root) | 2695 | (defun window--in-subtree-p (window root) |
| @@ -2459,13 +2740,13 @@ that is its frame's root window." | |||
| 2459 | ((and (window-parameter window 'window-atom) | 2740 | ((and (window-parameter window 'window-atom) |
| 2460 | (setq atom-root (window-atom-root window)) | 2741 | (setq atom-root (window-atom-root window)) |
| 2461 | (not (eq atom-root window))) | 2742 | (not (eq atom-root window))) |
| 2462 | (throw 'done (delete-window atom-root))) | 2743 | (if (eq atom-root (frame-root-window frame)) |
| 2463 | ((and (eq (window-parameter window 'window-side) 'none) | 2744 | (error "Root of atomic window is root window of its frame") |
| 2464 | (or (not parent) | 2745 | (throw 'done (delete-window atom-root)))) |
| 2465 | (not (eq (window-parameter parent 'window-side) 'none)))) | ||
| 2466 | (error "Attempt to delete last non-side window")) | ||
| 2467 | ((not parent) | 2746 | ((not parent) |
| 2468 | (error "Attempt to delete minibuffer or sole ordinary window"))) | 2747 | (error "Attempt to delete minibuffer or sole ordinary window")) |
| 2748 | ((eq window (window--major-non-side-window frame)) | ||
| 2749 | (error "Attempt to delete last non-side window"))) | ||
| 2469 | 2750 | ||
| 2470 | (let* ((horizontal (window-left-child parent)) | 2751 | (let* ((horizontal (window-left-child parent)) |
| 2471 | (size (window-total-size window horizontal)) | 2752 | (size (window-total-size window horizontal)) |
| @@ -2539,13 +2820,19 @@ window signal an error." | |||
| 2539 | ((and (window-parameter window 'window-atom) | 2820 | ((and (window-parameter window 'window-atom) |
| 2540 | (setq atom-root (window-atom-root window)) | 2821 | (setq atom-root (window-atom-root window)) |
| 2541 | (not (eq atom-root window))) | 2822 | (not (eq atom-root window))) |
| 2542 | (throw 'done (delete-other-windows atom-root))) | 2823 | (if (eq atom-root (frame-root-window frame)) |
| 2543 | ((eq window-side 'none) | 2824 | (error "Root of atomic window is root window of its frame") |
| 2544 | ;; Set side-main to the major non-side window. | 2825 | (throw 'done (delete-other-windows atom-root)))) |
| 2545 | (setq side-main (window-with-parameter 'window-side 'none frame t))) | ||
| 2546 | ((memq window-side window-sides) | 2826 | ((memq window-side window-sides) |
| 2547 | (error "Cannot make side window the only window"))) | 2827 | (error "Cannot make side window the only window")) |
| 2548 | ;; If WINDOW is the main non-side window, do nothing. | 2828 | ((and (window-minibuffer-p window) |
| 2829 | (not (eq window (frame-root-window window)))) | ||
| 2830 | (error "Can't expand minibuffer to full frame"))) | ||
| 2831 | |||
| 2832 | ;; If WINDOW is the major non-side window, do nothing. | ||
| 2833 | (if (window-with-parameter 'window-side) | ||
| 2834 | (setq side-main (window--major-non-side-window frame)) | ||
| 2835 | (setq side-main (frame-root-window frame))) | ||
| 2549 | (unless (eq window side-main) | 2836 | (unless (eq window side-main) |
| 2550 | (delete-other-windows-internal window side-main) | 2837 | (delete-other-windows-internal window side-main) |
| 2551 | (run-window-configuration-change-hook frame) | 2838 | (run-window-configuration-change-hook frame) |
| @@ -3204,14 +3491,16 @@ frame. The selected window is not changed by this function." | |||
| 3204 | ((not side) 'below) | 3491 | ((not side) 'below) |
| 3205 | ((memq side '(below above right left)) side) | 3492 | ((memq side '(below above right left)) side) |
| 3206 | (t 'right))) | 3493 | (t 'right))) |
| 3207 | (horizontal (not (memq side '(nil below above)))) | 3494 | (horizontal (not (memq side '(below above)))) |
| 3208 | (frame (window-frame window)) | 3495 | (frame (window-frame window)) |
| 3209 | (parent (window-parent window)) | 3496 | (parent (window-parent window)) |
| 3210 | (function (window-parameter window 'split-window)) | 3497 | (function (window-parameter window 'split-window)) |
| 3211 | (window-side (window-parameter window 'window-side)) | 3498 | (window-side (window-parameter window 'window-side)) |
| 3212 | ;; Rebind `window-combination-limit' since in some cases we may | 3499 | ;; Rebind `window-combination-limit' and |
| 3213 | ;; have to override its value. | 3500 | ;; `window-combination-resize' since in some cases we may have |
| 3501 | ;; to override their value. | ||
| 3214 | (window-combination-limit window-combination-limit) | 3502 | (window-combination-limit window-combination-limit) |
| 3503 | (window-combination-resize window-combination-resize) | ||
| 3215 | atom-root) | 3504 | atom-root) |
| 3216 | 3505 | ||
| 3217 | (window--check frame) | 3506 | (window--check frame) |
| @@ -3229,20 +3518,32 @@ frame. The selected window is not changed by this function." | |||
| 3229 | ((and (window-parameter window 'window-atom) | 3518 | ((and (window-parameter window 'window-atom) |
| 3230 | (setq atom-root (window-atom-root window)) | 3519 | (setq atom-root (window-atom-root window)) |
| 3231 | (not (eq atom-root window))) | 3520 | (not (eq atom-root window))) |
| 3232 | (throw 'done (split-window atom-root size side)))) | 3521 | (throw 'done (split-window atom-root size side))) |
| 3233 | 3522 | ;; If WINDOW is a side window or its first or last child is a | |
| 3234 | (when (and window-side | 3523 | ;; side window, throw an error unless `window-combination-resize' |
| 3235 | (or (not parent) | 3524 | ;; equals 'side. |
| 3236 | (not (window-parameter parent 'window-side)))) | 3525 | ((and (not (eq window-combination-resize 'side)) |
| 3237 | ;; WINDOW is a side root window. To make sure that a new parent | 3526 | (or (window-parameter window 'window-side) |
| 3238 | ;; window gets created set `window-combination-limit' to t. | 3527 | (and (window-child window) |
| 3239 | (setq window-combination-limit t)) | 3528 | (or (window-parameter |
| 3240 | 3529 | (window-child window) 'window-side) | |
| 3241 | (when (and window-combination-resize size (> size 0)) | 3530 | (window-parameter |
| 3242 | ;; If `window-combination-resize' is non-nil and SIZE is a | 3531 | (window-last-child window) 'window-side))))) |
| 3243 | ;; non-negative integer, we cannot reasonably resize other | 3532 | (error "Cannot split side window or parent of side window")) |
| 3244 | ;; windows. Rather bind `window-combination-limit' to t to make | 3533 | ;; If `window-combination-resize' is 'side and window has a side |
| 3245 | ;; sure that subsequent window deletions are handled correctly. | 3534 | ;; window sibling, bind `window-combination-limit' to t. |
| 3535 | ((and (not (eq window-combination-resize 'side)) | ||
| 3536 | (or (and (window-prev-sibling window) | ||
| 3537 | (window-parameter | ||
| 3538 | (window-prev-sibling window) 'window-side)) | ||
| 3539 | (and (window-next-sibling window) | ||
| 3540 | (window-parameter | ||
| 3541 | (window-next-sibling window) 'window-side)))) | ||
| 3542 | (setq window-combination-limit t))) | ||
| 3543 | |||
| 3544 | ;; If `window-combination-resize' is t and SIZE is non-negative, | ||
| 3545 | ;; bind `window-combination-limit' to t. | ||
| 3546 | (when (and (eq window-combination-resize t) size (> size 0)) | ||
| 3246 | (setq window-combination-limit t)) | 3547 | (setq window-combination-limit t)) |
| 3247 | 3548 | ||
| 3248 | (let* ((parent-size | 3549 | (let* ((parent-size |
| @@ -3252,7 +3553,10 @@ frame. The selected window is not changed by this function." | |||
| 3252 | ;; `resize' non-nil means we are supposed to resize other | 3553 | ;; `resize' non-nil means we are supposed to resize other |
| 3253 | ;; windows in WINDOW's combination. | 3554 | ;; windows in WINDOW's combination. |
| 3254 | (resize | 3555 | (resize |
| 3255 | (and window-combination-resize (not window-combination-limit) | 3556 | (and window-combination-resize |
| 3557 | (or (window-parameter window 'window-side) | ||
| 3558 | (not (eq window-combination-resize 'side))) | ||
| 3559 | (not window-combination-limit) | ||
| 3256 | ;; Resize makes sense in iso-combinations only. | 3560 | ;; Resize makes sense in iso-combinations only. |
| 3257 | (window-combined-p window horizontal))) | 3561 | (window-combined-p window horizontal))) |
| 3258 | ;; `old-size' is the current size of WINDOW. | 3562 | ;; `old-size' is the current size of WINDOW. |
| @@ -3363,10 +3667,21 @@ frame. The selected window is not changed by this function." | |||
| 3363 | new-normal))) | 3667 | new-normal))) |
| 3364 | 3668 | ||
| 3365 | (let* ((new (split-window-internal window new-size side new-normal))) | 3669 | (let* ((new (split-window-internal window new-size side new-normal))) |
| 3366 | ;; Inherit window-side parameters, if any. | 3670 | ;; Assign window-side parameters, if any. |
| 3367 | (when (and window-side new-parent) | 3671 | (when (eq window-combination-resize 'side) |
| 3368 | (set-window-parameter (window-parent new) 'window-side window-side) | 3672 | (let ((window-side |
| 3369 | (set-window-parameter new 'window-side window-side)) | 3673 | (cond |
| 3674 | (window-side window-side) | ||
| 3675 | ((eq side 'above) 'top) | ||
| 3676 | ((eq side 'below) 'bottom) | ||
| 3677 | (t side)))) | ||
| 3678 | ;; We made a new side window. | ||
| 3679 | (set-window-parameter new 'window-side window-side) | ||
| 3680 | (when (and new-parent (window-parameter window 'window-side)) | ||
| 3681 | ;; We've been splitting a side root window. Give the | ||
| 3682 | ;; new parent the same window-side parameter. | ||
| 3683 | (set-window-parameter | ||
| 3684 | (window-parent new) 'window-side window-side)))) | ||
| 3370 | 3685 | ||
| 3371 | (run-window-configuration-change-hook frame) | 3686 | (run-window-configuration-change-hook frame) |
| 3372 | (window--check frame) | 3687 | (window--check frame) |
| @@ -4621,9 +4936,9 @@ is passed unaltered to `display-buffer-record-window'. Set | |||
| 4621 | `window-dedicated-p' to DEDICATED if non-nil. Return WINDOW if | 4936 | `window-dedicated-p' to DEDICATED if non-nil. Return WINDOW if |
| 4622 | BUFFER and WINDOW are live." | 4937 | BUFFER and WINDOW are live." |
| 4623 | (when (and (buffer-live-p buffer) (window-live-p window)) | 4938 | (when (and (buffer-live-p buffer) (window-live-p window)) |
| 4939 | (display-buffer-record-window type window buffer) | ||
| 4624 | (unless (eq buffer (window-buffer window)) | 4940 | (unless (eq buffer (window-buffer window)) |
| 4625 | (set-window-dedicated-p window nil) | 4941 | (set-window-dedicated-p window nil) |
| 4626 | (display-buffer-record-window type window buffer) | ||
| 4627 | (set-window-buffer window buffer) | 4942 | (set-window-buffer window buffer) |
| 4628 | (when dedicated | 4943 | (when dedicated |
| 4629 | (set-window-dedicated-p window dedicated)) | 4944 | (set-window-dedicated-p window dedicated)) |