mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-05 22:20:24 -08:00
Add new commands 'merge-frames' and 'split-frame'
* lisp/window-x.el (merge-frames, split-frame): New commands. * etc/NEWS: Announce new commands 'merge-frame' and 'split-frame'.
This commit is contained in:
parent
5822759d47
commit
18a346da6a
2 changed files with 103 additions and 0 deletions
5
etc/NEWS
5
etc/NEWS
|
|
@ -454,6 +454,11 @@ either resize the frame and change the fullscreen status accordingly or
|
|||
keep the frame size unchanged. The value t means to first reset the
|
||||
fullscreen status and then resize the frame.
|
||||
|
||||
*** New commands 'split-frame' and 'merge-frames'.
|
||||
'split-frame' moves a specified number of windows from an existing frame
|
||||
to a newly-created frame. 'merge-frames' merges all windows from two
|
||||
frames into one of these frames and deletes the other one.
|
||||
|
||||
---
|
||||
*** Frames can now be renamed to "F<number>" on text terminals.
|
||||
Unlike with other frame names, an attempt to rename to "F<number>" throws
|
||||
|
|
|
|||
|
|
@ -315,5 +315,103 @@ ones in `window--transpose'."
|
|||
(if is-atom '(nil . t) conf)
|
||||
no-resize atom-windows)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun merge-frames (&optional frame1 frame2 vertical)
|
||||
"Merge the main window of FRAME2 into FRAME1.
|
||||
Split the main window of FRAME1 and make the new window display the main
|
||||
window of FRAME2. Both FRAME1 and FRAME2 must be live frames. If
|
||||
VERTICAL is non-nil, make the new window below the old main window of
|
||||
FRAME1. Otherwise, make the new window on the right of FRAME1's main
|
||||
window. Interactively, VERTICAL is the prefix argument, FRAME1 is the
|
||||
selected frame and FRAME2 is the frame following FRAME1 in the frame
|
||||
list. Delete FRAME2 if the merge completed successfully and return
|
||||
FRAME1."
|
||||
(interactive "i\ni\nP")
|
||||
(let* ((frame1 (window-normalize-frame frame1))
|
||||
(frame2 (or (if frame2
|
||||
(window-normalize-frame frame2)
|
||||
(next-frame frame1))
|
||||
(user-error "Cannot find frame to merge"))))
|
||||
(window-state-put
|
||||
;; Source window on frame2.
|
||||
(window-state-get (window-main-window frame2))
|
||||
;; Make new window on frame1.
|
||||
(split-window (window-main-window frame1) nil (not vertical)))
|
||||
(delete-frame frame2)
|
||||
frame1))
|
||||
|
||||
;;;###autoload
|
||||
(defun split-frame (&optional frame arg)
|
||||
"Split windows of specified FRAME into two separate frames.
|
||||
FRAME must be a live frame and defaults to the selected frame. ARG
|
||||
specifies the number of windows to consider for splitting and defaults
|
||||
to 1. Interactively, ARG is the prefix argument.
|
||||
|
||||
First divide the child windows of FRAME's main window into two parts.
|
||||
The first part includes the first ARG child windows if ARG is positive,
|
||||
or -ARG last windows if it's negative. The second part includes the
|
||||
remaining child windows of FRAME's main window. Then clone into a
|
||||
newly-created frame each of the windows of the part which does not
|
||||
include FRAME's selected window and delete those windows from FRAME.
|
||||
|
||||
Signal an error if ARG is either zero or not a number, if FRAME's main
|
||||
window is live or does not have more child windows than specified by the
|
||||
absolute value of ARG. Return the new frame."
|
||||
(interactive "i\nP")
|
||||
(let* ((frame (window-normalize-frame frame))
|
||||
;; MAIN is FRAME'S main window.
|
||||
(main (window-main-window frame))
|
||||
(total-window-count (window-child-count main))
|
||||
(arg (or arg 1)))
|
||||
(cond
|
||||
((window-live-p main)
|
||||
(user-error "Cannot split frame with only one window"))
|
||||
((or (not (numberp arg)) (zerop arg))
|
||||
(user-error "Invalid ARG %s for splitting frame" arg))
|
||||
((>= (abs arg) total-window-count)
|
||||
(user-error "ARG %s exceeds number of windows %s that can be split off"
|
||||
(abs arg) (1- total-window-count)))
|
||||
(t (let* ((reverse (< arg 0))
|
||||
;; This is where the pivot window is.
|
||||
(pivot-window-pos (- (if reverse
|
||||
(+ total-window-count arg)
|
||||
arg)
|
||||
1))
|
||||
(pivot-window (window-child main))
|
||||
(active-window (frame-selected-window frame))
|
||||
;; If FRAME's selected window is on the left side of the
|
||||
;; pivot window.
|
||||
(active-window-on-left (eq pivot-window active-window)))
|
||||
;; We want the 2nd level window that the active window is a
|
||||
;; part of.
|
||||
(while (not (eq (window-parent active-window) main))
|
||||
(setq active-window (window-parent active-window)))
|
||||
|
||||
;; Now we need to find the pivot window
|
||||
(dotimes (_ pivot-window-pos)
|
||||
(setq pivot-window (window-next-sibling pivot-window))
|
||||
(when (eq active-window pivot-window)
|
||||
(setq active-window-on-left t)))
|
||||
|
||||
;; Now we have pivot-window set, and we just need to
|
||||
;; combine. We want to split away all windows from the
|
||||
;; side of the pivot that doesn't contain the active
|
||||
;; window.
|
||||
(let* ((first (window-child main))
|
||||
(last (window-last-child main))
|
||||
(next-pivot-sib (window-next-sibling pivot-window))
|
||||
(right-comb (if (eq next-pivot-sib last)
|
||||
last
|
||||
(combine-windows next-pivot-sib last)))
|
||||
(left-comb (if (eq first pivot-window)
|
||||
first
|
||||
(combine-windows first pivot-window)))
|
||||
;; comb-win is the combination that will be
|
||||
;; split off.
|
||||
(comb-win (if active-window-on-left right-comb left-comb)))
|
||||
(window-state-put (window-state-get comb-win)
|
||||
(window-main-window (make-frame)))
|
||||
(delete-window comb-win)))))))
|
||||
|
||||
(provide 'window-x)
|
||||
;;; window-x.el ends here
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue