1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-05 22:20:24 -08:00

New commands to split and merge frames

* lisp/window-x.el (merge-frames, split-frame): New commands.
This commit is contained in:
Pranshu Sharma 2025-10-23 10:04:39 +02:00 committed by Martin Rudalics
parent 8fc068a15d
commit db6ac3c5f4
2 changed files with 109 additions and 2 deletions

View file

@ -313,7 +313,114 @@ ones in `window--transpose'."
(let ((is-atom (memq (cadr (cadr (cddddr subtree))) atom-windows)))
(window--transpose-1 (car (cddddr subtree)) cwin
(if is-atom '(nil . t) conf)
no-resize atom-windows)))))
no-resize atom-windows)))))
;;;###autoload
(defun merge-frames (&optional vertical frame1 frame2)
"Merge FRAME2 into FRAME1.
Split the root window of FRAME1 and make the new window display the root
window of FRAME2. Both FRAME1 and FRAME2 must be live frames. If
VERTICAL is non-nil, make the new window below the old root window of
FRAME1. Otherwise, make the new window on the right of FRAME1's root
window. Interactively, VERTICAL is the prefix argument, FRAME1 is the
selected frame and FRAME2 is the frame following FRAME1 in the frame
list."
(interactive "P")
(let* ((frame1 (window-normalize-frame frame1))
(frame2 (if frame2
(window-normalize-frame frame2)
(next-frame frame1))))
(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 (null vertical)))
(delete-frame frame2)
frame1))
;;;###autoload
(defun split-frame (&optional arg frame)
"Split FRAME.
FRAME must be a live frame and defaults to the selected one.
Interactively, ARG is the prefix argument. If ARG is a number, make ARG
- 1 new frames and put any child window of the main window of FRAME into
one of these frames. As a special case, if ARG equals 1, make one new
frame containing all children but the first of the root window of FRAME.
With a non-numeric prefix ARG, try to put all children of FRAME's main
window but the first into a new frame. In either case, any window put
on a new frame is a clone of the original window and the original window
is deleted."
(interactive "P")
(let* ((mw (window-main-window frame))
(first-child (window-child mw))
(nwindows (window-child-count mw)))
(cond
((or (<= nwindows 1))
(error "Cannot split a one-window frame"))
;; One frame for each window.
((or (eq nwindows 2) (and arg (not (numberp arg))))
(let ((sib (window-next-sibling first-child))
frames)
(while sib
(let* ((state (window-state-get sib))
(frame (make-frame))
(next-sib (window-next-sibling sib)))
(push frame frames)
(window-state-put state (window-main-window frame))
(delete-window sib)
(setq sib next-sib)))
frames))
;; Two windows.
((eq 1 arg)
(let* ((snd-sib (window-next-sibling first-child))
(sib (combine-windows snd-sib (window-last-child mw)))
(state (window-state-get sib))
(frame (make-frame)))
(window-state-put state (window-main-window frame))
(delete-window sib)
frame))
;; Smart window splitting.
(t
(let ((nframes (or arg 2)))
(when (< nwindows nframes)
(error "%i frames cannot be made from %i windows" arg nwindows))
(let* ((horizontal (window-combined-p first-child t))
(ideal (/ (window-size mw horizontal) nframes))
(current-window first-child)
(sum (window-size current-window horizontal))
(windows (list (list first-child)))
frames)
;; Need to come up with the inital windows split using sliding
;; sum technique.
(while (setq current-window (window-next-sibling current-window))
(setq sum (seq-reduce '+ (mapcar
(lambda (w)
(window-size w horizontal))
(car (last windows)))
0))
(let ((remaining-frames (- nframes (length windows)))
(remaining-windows
(- nwindows (seq-reduce '+ (mapcar 'length windows) 0))))
(if (or (= remaining-windows remaining-frames)
;; HACK ALERT!
(>= sum (* ideal 0.85)))
(progn
(setq sum 0)
(nconc windows (list (list current-window))))
(nconc (car (last windows)) (list current-window)))))
(when (cdar windows)
(combine-windows (caar windows) (car (last (car windows)))))
(dolist (wls (cdr windows) frames)
(let* ((cwin (if (cdr wls)
(combine-windows (car wls) (car (last wls)))
(car wls)))
(state (window-state-get cwin))
(frame (make-frame)))
(push frame frames)
(delete-window cwin)
(window-state-put state (window-main-window frame))))))))))
(provide 'window-x)
;;; window-x.el ends here

View file

@ -2072,7 +2072,7 @@ dump_interval_tree (struct dump_context *ctx,
static dump_off
dump_string (struct dump_context *ctx, const struct Lisp_String *string)
{
#if CHECK_STRUCTS && !defined (HASH_Lisp_String_03B2DF1C8E)
#if CHECK_STRUCTS && !defined (HASH_Lisp_String_B71C8876EB)
# error "Lisp_String changed. See CHECK_STRUCTS comment in config.h."
#endif
/* If we have text properties, write them _after_ the string so that