Document 'split-frame' and 'merge-frames' in Elisp manual

* doc/lispref/frames.texi (Splitting and Merging Frames): New
section.
* doc/lispref/elisp.texi (Top): Add new section.
* doc/lispref/windows.texi (Basic Windows): Explain terms
'layout' and 'identity' of windows.
(Window Configurations): Explain that window identities are
preserved by window configurations and get lost with window
states.
This commit is contained in:
Martin Rudalics 2026-06-23 16:37:37 +02:00
parent 0d67e76b94
commit f0bfa33039
3 changed files with 98 additions and 7 deletions

View file

@ -1137,6 +1137,7 @@ Frames
* Frame Titles:: Automatic updating of frame titles.
* Deleting Frames:: Frames last until explicitly deleted.
* Finding All Frames:: How to examine all existing frames.
* Splitting and Merging Frames:: Transferring window layouts between frames.
* Minibuffers and Frames:: How a frame finds the minibuffer to use.
* Input Focus:: Specifying the selected frame.
* Visibility of Frames:: Frames may be visible or invisible, or icons.

View file

@ -151,6 +151,7 @@ unique id.
* Frame Titles:: Automatic updating of frame titles.
* Deleting Frames:: Frames last until explicitly deleted.
* Finding All Frames:: How to examine all existing frames.
* Splitting and Merging Frames:: Transferring window layouts between frames.
* Minibuffers and Frames:: How a frame finds the minibuffer to use.
* Input Focus:: Specifying the selected frame.
* Visibility of Frames:: Frames may be visible or invisible, or icons.
@ -3076,6 +3077,85 @@ criteria, and should return non-@code{nil} if the frame satisfies the
criteria.
@end defun
@node Splitting and Merging Frames
@section Splitting and Merging Frames
@cindex splitting a frame
@cindex merging two frames
@cindex Transferring window layouts
The following two functions are useful to transfer parts of the window
layout (@pxref{Basic Windows}) of one frame to two separate frames and
to merge the window layouts of two separate frames into one frame.
@deffn Command split-frame &optional frame arg
This command transfers some windows of the specified @var{frame} to a
new frame and subsequently deletes them on @var{frame}. @var{frame}
must be a live frame and defaults to the selected frame. @var{arg}
specifies the number of windows to transfer and defaults to 1.
Interactively, @var{arg} is the prefix argument.
In a first step, it divides the child windows (@pxref{Windows and
Frames}) of @var{frame}'s main window (@pxref{Side Windows}) into two
parts. The first part includes the first @var{arg} child windows if
@var{arg} is positive, and the -@var{arg} last child windows if
@var{arg} is negative. The second part includes the remaining child
windows of @var{frame}'s main window.
In a second step, it clones (@pxref{Window Configurations}) into a newly
created frame each of the windows of the part which does not include
@var{frame}'s selected window (@pxref{Selecting Windows}) and removes
those windows from @var{frame}. Note that the original identity
(@pxref{Basic Windows}) of the cloned windows is lost in this step. The
identity of the windows retained on @var{frame} is preserved, however.
In a final step, it deletes the windows that have been cloned from
@var{frame} and returns the newly created frame.
This function signals an error if @var{arg} is either zero or not a
number, or if @var{frame}'s main window is either live or does not have
more child windows than specified by the absolute value of @var{arg}.
@end deffn
@deffn Command merge-frames &optional frame1 frame2 vertical
This command transfers the main window (@pxref{Side Windows}) of
@var{frame2} to @var{frame1}. Both @var{frame1} and @var{frame2} must
specify live frames.
In a first step it splits the main window of @var{frame1}. If
@var{vertical} is non-@code{nil}, it makes the new window below the old
main window of @var{frame1}. Otherwise, it makes the new window on the
right of @var{frame1}'s main window.
In a second step it makes the new window a clone (@pxref{Window
Configurations}) of the main window of @var{frame2}. The original
identity (@pxref{Basic Windows}) of the cloned windows is lost in that
step. In a final step, it deletes @var{frame2} if the merge completed
successfully and returns @var{frame1}.
Interactively, @var{vertical} is the prefix argument, @var{frame1} is
the selected frame and @var{frame2} is the frame following @var{frame1}
in the list of all frames (@pxref{Finding All Frames}).
@end deffn
In general you cannot ``undo'' a @code{split-frame} call with a
subsequent @code{merge-frames} call for the following reasons: In its
second step @code{merge-frame} puts the main window of @var{frame2} into
an internal window split off in the first step. No such window was
present in the configuration of @var{frame1} before calling
@code{split-frame}. Also, after merging is complete, the window cloned
from the main window of @var{frame2} will occupy as much space as the
main window of @var{frame1} before merging. This might not match the
space distribution of the original layout.
Hence, if your preferred workflow is to temporarily split off windows
for working on them in a separate frame and later continue with the
original layout of the original frame, you should proceed as follows:
Save the configuration (@pxref{Window Configurations}) of the original
frame, call @code{split-frame} to create the separate frame and finally
restore the saved configuration of the original frame and delete the
separate frame.
@node Minibuffers and Frames
@section Minibuffers and Frames

View file

@ -78,14 +78,19 @@ disambiguation, we use the term @dfn{window-system window} when we mean
the window-system window corresponding to an Emacs frame.
@cindex tiled windows
@cindex window layout
Unlike X windows, Emacs windows are @dfn{tiled}; they never overlap
within the area of their frame. When a window is created, resized, or
deleted, the change in window space is taken from or given to other
windows on the same frame, so that the total area of the frame is
unchanged.
unchanged. The @dfn{window layout} of a frame is the result of all
tiling operations for that frame.
@cindex window object
@cindex window identity
In Emacs Lisp, windows are represented by a special Lisp object type
(@pxref{Window Type}).
(@pxref{Window Type}). Two windows are identic if and only if they are
represented by the same Lisp object.
@defun windowp object
This function returns @code{t} if @var{object} is a window (whether or
@ -7263,11 +7268,16 @@ and/or two columns.
In the context of window states, the @dfn{clone of a window} is a window
that has the same decorations and contents as the window whose state was
used to produce it, but is actually represented by another window
object. Operating on the original or the clone of a window does not
affect the other in any way. Note that while @code{window-state-get}
clones existing windows, these clones are not yet valid windows. They
become valid only after @code{window-state-put} has put them into a live
frame.
object. Hence it does not have the same identity as the original
window. Operating on the original or the clone of a window does not
affect the other in any way.
Note that while @code{set-window-configuration} always restores the
identity of the windows it puts back into their frame,
@code{window-state-put} never does that. Note also that while
@code{window-state-get} clones existing windows, these clones are not
yet valid windows. They become valid only after @code{window-state-put}
has put them into a live frame.
By default, @code{set-window-configuration} and @code{window-state-put}
may delete a window from the restored configuration or state when they