Further amendments of child frame handling and documentation
* src/frame.c (frame_subsumes_p): New static function (delete_frame): On ttys refuse to delete a frame that could be used as surrogate minibuffer frame by surviving frames. (store_frame_param): Make sure 'minibuffer' parameter does not reference a deleted window. If on a tty it references a live window, make sure its frame has the same root frame as the frame where the parameter shall be installed. Also on ttys make sure that storing the 'parent-frame' parameter does not assign a surrogate minibuffer frame a different root frame than that of any of its client frames. Further on ttys assert that making a child a new root frame gives it the dimensions of the terminal. (Fmouse_position_in_root_frame): Don't use XFRAME before it's clear that FRAME is a frame. * doc/lispref/elisp.texi (Top): Add menu for Child Frames section. * doc/lispref/frames.texi (Buffer Parameters): Mention that value 'child-frame' is not special for 'minibuffer' parameter on text terminals. (Visibility of Frames): Fix description of 'iconify-frame'. (Raising and Lowering): 'minibuffer-auto-raise' is an option. (Child Frames): Major rewrite using subsections. Explain new and deviant features on text terminals - menu bar access, reparenting, deleting, visibility and minibuffer-only child frames. * etc/NEWS: Remove remark that child frames cannot be arbitrarily reparented on ttys.
This commit is contained in:
parent
2d278a0f2e
commit
001359ce76
4 changed files with 273 additions and 99 deletions
|
@ -1187,6 +1187,12 @@ Window Frame Parameters
|
|||
* Cursor Parameters:: Controlling the cursor appearance.
|
||||
* Font and Color Parameters:: Fonts and colors for the frame text.
|
||||
|
||||
Child Frames
|
||||
|
||||
* Child Frame Operations:: Making and investigating child frames.
|
||||
* Child Frame Properties:: Special properties of child frames.
|
||||
* Child Frame Peculiarities:: Deviant behaviors of child frames.
|
||||
|
||||
Positions
|
||||
|
||||
* Point:: The special position where editing takes place.
|
||||
|
|
|
@ -2071,7 +2071,9 @@ The special value @code{child-frame} means to make a minibuffer-only
|
|||
child frame (@pxref{Child Frames}) whose parent becomes the frame
|
||||
created. As if specified as @code{nil}, Emacs will set this parameter
|
||||
to the minibuffer window of the child frame but will not select the
|
||||
child frame after its creation.
|
||||
child frame after its creation. The value @code{child-frame} has no
|
||||
effect on text terminals where you have to create a minibuffer-only
|
||||
frame manually (@pxref{Child Frame Peculiarities}).
|
||||
|
||||
@vindex buffer-predicate@r{, a frame parameter}
|
||||
@item buffer-predicate
|
||||
|
@ -3311,11 +3313,12 @@ be seen even if they are considered visible by this function.
|
|||
|
||||
@deffn Command iconify-frame &optional frame
|
||||
This function iconifies frame @var{frame}. If you omit @var{frame}, it
|
||||
iconifies the selected frame. This will also remove any child frames
|
||||
(@pxref{Child Frames}) of @var{frame} from display. On the top frame of
|
||||
a text terminal this function has no effect. visible. If @var{frame} is
|
||||
a child frame, the behavior depends on the value of the variable
|
||||
@code{iconify-child-frame} (@pxref{Child Frames}).
|
||||
iconifies the selected frame. This function also removes any child
|
||||
frames (@pxref{Child Frames}) of @var{frame} and their descendants from
|
||||
display. If @var{frame} is a child frame itself, the behavior depends
|
||||
on the value of the variable @code{iconify-child-frame}. If @var{frame}
|
||||
is the top frame of a text terminal (@pxref{Frames}), this function has
|
||||
no effect.
|
||||
@end deffn
|
||||
|
||||
@deffn Command make-frame-visible &optional frame
|
||||
|
@ -3438,7 +3441,7 @@ function @code{frame-list-z-order} (@pxref{Finding All Frames}).
|
|||
|
||||
@defopt minibuffer-auto-raise
|
||||
If this is non-@code{nil}, activation of the minibuffer raises the frame
|
||||
that the minibuffer window is in. This function has no effect on text
|
||||
that the minibuffer window is in. This variable has no effect on text
|
||||
terminals.
|
||||
@end defopt
|
||||
|
||||
|
@ -3474,7 +3477,6 @@ unwanted frames are iconified instead.
|
|||
@node Child Frames
|
||||
@section Child Frames
|
||||
@cindex child frames
|
||||
@cindex parent frames
|
||||
|
||||
Child frames are objects halfway between windows (@pxref{Windows}) and
|
||||
``normal'' frames. Like windows, they are attached to an owning frame.
|
||||
|
@ -3487,26 +3489,39 @@ with the help of frame parameters (@pxref{Frame Parameters}) without any
|
|||
specialized functions or customizable variables. Child frames
|
||||
are meaningful on graphical and text terminals.
|
||||
|
||||
To create a new child frame or to convert a normal frame into a child
|
||||
@menu
|
||||
* Child Frame Operations:: Making and investigating child frames.
|
||||
* Child Frame Properties:: Special properties of child frames.
|
||||
* Child Frame Peculiarities:: Deviant behaviors of child frames.
|
||||
@end menu
|
||||
|
||||
@node Child Frame Operations
|
||||
@subsection Child Frame Operations
|
||||
|
||||
To create a new child frame or to convert a normal frame into a child
|
||||
frame, set that frame's @code{parent-frame} parameter (@pxref{Frame
|
||||
Interaction Parameters}) to that of an already existing frame. The
|
||||
frame specified by that parameter will then be the frame's parent frame
|
||||
as long as the parameter is not changed or reset. Technically, this
|
||||
makes the child frame's window-system window a child window of the
|
||||
parent frame's window-system window.
|
||||
as long as the parameter is not changed or reset. Technically, on a GUI
|
||||
this makes the child frame's window-system window a child window of the
|
||||
parent frame's window-system window. On a text terminal, this makes the
|
||||
frame usually appear on the same terminal as its parent frame, obscuring
|
||||
some part of it.
|
||||
|
||||
@cindex reparent frame
|
||||
@cindex nest frame
|
||||
The @code{parent-frame} parameter can be changed at any time.
|
||||
Setting it to another frame @dfn{reparents} the child frame. Setting
|
||||
it to another child frame makes the frame a @dfn{nested} child frame.
|
||||
Setting it to @code{nil} restores the frame's status as a top-level
|
||||
frame---a frame whose window-system window is a child of its display's
|
||||
root window.@footnote{On Haiku, child frames are only visible when a
|
||||
parent frame is active, owing to a limitation of the Haiku windowing
|
||||
system. Owing to the same limitation, child frames are only
|
||||
guaranteed to appear above their top-level parent; that is to say, the
|
||||
top-most frame in the hierarchy, which does not have a parent frame.}
|
||||
@cindex reparenting frames
|
||||
@cindex nesting frames
|
||||
@cindex top-level frame
|
||||
The @code{parent-frame} parameter can be changed at any time. Setting
|
||||
it to another frame @dfn{reparents} the child frame. Setting it to
|
||||
another child frame makes the frame a @dfn{nested} child frame. Setting
|
||||
it to @code{nil} restores the frame's status as a top-level frame---a
|
||||
frame whose window-system window is a child of its display's root
|
||||
window.@footnote{On Haiku, child frames are only visible when a parent
|
||||
frame is active, owing to a limitation of the Haiku windowing system.
|
||||
Owing to the same limitation, child frames are only guaranteed to appear
|
||||
above their top-level parent; that is to say, the top-most frame in the
|
||||
hierarchy, which does not have a parent frame.} On text terminals,
|
||||
top-level frames are called root frames (see below).
|
||||
|
||||
Since child frames can be arbitrarily nested, a frame can be both a
|
||||
child and a parent frame. Also, the relative roles of child and parent
|
||||
|
@ -3515,16 +3530,69 @@ keep the size of a child frame sufficiently smaller than that of its
|
|||
parent). An error will be signaled for the attempt to make a frame an
|
||||
ancestor of itself.
|
||||
|
||||
Most window-systems clip a child frame at the native edges
|
||||
(@pxref{Frame Geometry}) of its parent frame---everything outside these
|
||||
edges is usually invisible. A child frame's @code{left} and @code{top}
|
||||
When a parent frame is about to be deleted (@pxref{Deleting Frames}),
|
||||
its child frames are recursively deleted before it. There is one
|
||||
exception to this rule: When the child frame serves as a surrogate
|
||||
minibuffer frame (@pxref{Minibuffers and Frames}) for another frame, it
|
||||
is retained until the parent frame has been deleted. If, at this time,
|
||||
no remaining frame uses the child frame as its minibuffer frame, Emacs
|
||||
will try to delete the child frame too. If that deletion fails for
|
||||
whatever reason, the child frame is made a top-level frame. Since on
|
||||
text terminals no such conversion is possible, deleting a frame may
|
||||
throw an error if a surrogate minibuffer frame to be deleted is used by
|
||||
a frame that will not be deleted too.
|
||||
|
||||
The following three functions help to understand how parent and child
|
||||
frames related to each other.
|
||||
|
||||
@defun frame-parent &optional frame
|
||||
This function returns the parent frame of @var{frame}. It returns
|
||||
@code{nil} if @var{frame} has no parent frame.
|
||||
@end defun
|
||||
|
||||
@cindex ancestor frame
|
||||
@cindex descendant frame
|
||||
@defun frame-ancestor-p ancestor descendant
|
||||
This functions returns non-@code{nil} if @var{ancestor} is an ancestor
|
||||
of @var{descendant}. @var{ancestor} is an ancestor of @var{descendant}
|
||||
when it is either @var{descendant}'s parent frame or it is an ancestor
|
||||
of @var{descendant}'s parent frame. Both, @var{ancestor} and
|
||||
@var{descendant} must specify live frames.
|
||||
@end defun
|
||||
|
||||
@cindex root frame
|
||||
@defun frame-root-frame &optional frame
|
||||
This function returns the root frame of the specified @var{frame}.
|
||||
@var{frame} must be a live frame and defaults to the selected one. The
|
||||
root frame of @var{frame} is the frame obtained by following the chain
|
||||
of parent frames starting with @var{frame} until a frame is reached that
|
||||
has no parent. If @var{frame} has no parent, its root frame is
|
||||
@var{frame} itself.
|
||||
@end defun
|
||||
|
||||
On a text terminal, a root frame is always positioned at the top left
|
||||
edge of its terminal and always occupies the full size of its terminal.
|
||||
|
||||
|
||||
@node Child Frame Properties
|
||||
@subsection Child Frame Properties
|
||||
|
||||
Most window-systems clip child frames at the native edges (@pxref{Frame
|
||||
Geometry}) of their parent frame---everything outside these edges is
|
||||
usually invisible. A child frame's @code{left} and @code{top}
|
||||
parameters specify a position relative to the top-left corner of its
|
||||
parent's native frame. When the parent frame is resized, this position
|
||||
remains conceptually unaltered.
|
||||
|
||||
NS builds do not clip child frames at the parent frame's edges,
|
||||
allowing them to be positioned so they do not obscure the parent frame
|
||||
while still being visible themselves.
|
||||
NS builds and text terminals do not clip child frames at the parent
|
||||
frame's edges, allowing them to be positioned so they do not obscure the
|
||||
parent frame while still being visible themselves.
|
||||
|
||||
Note also the function @code{window-largest-empty-rectangle}
|
||||
(@pxref{Coordinates and Windows}) which can be used to inscribe a child
|
||||
frame in the largest empty area of an existing window. This can be
|
||||
useful to avoid that a child frame obscures any text shown in that
|
||||
window.
|
||||
|
||||
Usually, moving a parent frame moves along all its child frames and
|
||||
their descendants as well, keeping their relative positions unaltered.
|
||||
|
@ -3546,24 +3614,21 @@ obscuring parts of it, except on NS builds where it may be positioned
|
|||
beneath the parent. This is comparable to the window-system window of a
|
||||
top-level frame which also always appears on top of its parent
|
||||
window---the desktop's root window. When a parent frame is iconified or
|
||||
made invisible (@pxref{Visibility of Frames}), its child frames are made
|
||||
invisible. When a parent frame is deiconified or made visible, its
|
||||
child frames are made visible.
|
||||
|
||||
When a parent frame is about to be deleted (@pxref{Deleting
|
||||
Frames}), its child frames are recursively deleted before it. There
|
||||
is one exception to this rule: When the child frame serves as a
|
||||
surrogate minibuffer frame (@pxref{Minibuffers and Frames}) for
|
||||
another frame, it is retained until the parent frame has been deleted.
|
||||
If, at this time, no remaining frame uses the child frame as its
|
||||
minibuffer frame, Emacs will try to delete the child frame too. If
|
||||
that deletion fails for whatever reason, the child frame is made a
|
||||
top-level frame.
|
||||
made invisible (@pxref{Visibility of Frames}), any child frames
|
||||
descending from it will not be shown either even if
|
||||
@code{frame-visible-p} returns @code{t} for them. When a parent frame
|
||||
is deiconified or made visible, any child frames descending from it will
|
||||
be shown again (provided they and all their ancestor frames are visible
|
||||
too). If a child frame is used as surrogate minibuffer frame
|
||||
(@pxref{Minibuffers and Frames}), it's up to the application to
|
||||
guarantee the frame's visibility whenever the minibuffer is activated.
|
||||
|
||||
Whether a child frame can have a menu or tool bar is window-system or
|
||||
window manager dependent. Most window-systems explicitly disallow menu
|
||||
bars for child frames. It seems advisable to disable both, menu and
|
||||
tool bars, via the frame's initial parameters settings.
|
||||
tool bars, via the frame's initial parameters settings. On a text
|
||||
terminal, child frames use the menu bar of their root frame (provided it
|
||||
has one).
|
||||
|
||||
Usually, child frames do not exhibit window manager decorations like a
|
||||
title bar or external borders (@pxref{Frame Geometry}). When the child
|
||||
|
@ -3575,15 +3640,18 @@ outer border can be used. On MS-Windows, specifying a non-zero outer
|
|||
border width will show a one-pixel wide external border. Under all
|
||||
window-systems, the internal border can be used. In either case, it's
|
||||
advisable to disable a child frame's window manager decorations with the
|
||||
@code{undecorated} frame parameter (@pxref{Management Parameters}).
|
||||
@code{undecorated} frame parameter (@pxref{Management Parameters}). On
|
||||
a text terminal, on the other hand, it's better to leave that parameter
|
||||
alone so your child frame will be drawn with an outer border.
|
||||
|
||||
To resize or move an undecorated child frame with the mouse, special
|
||||
To resize or move a border-less child frame with the mouse, special
|
||||
frame parameters (@pxref{Mouse Dragging Parameters}) have to be used.
|
||||
The internal border of a child frame, if present, can be used to resize
|
||||
the frame with the mouse, provided that frame has a non-@code{nil}
|
||||
@code{drag-internal-border} parameter. If set, the @code{snap-width}
|
||||
parameter indicates the number of pixels where the frame @dfn{snaps} at
|
||||
the respective edge or corner of its parent frame.
|
||||
the respective edge or corner of its parent frame. On a text terminal,
|
||||
the outer border can used for resizing.
|
||||
|
||||
There are two ways to drag an entire child frame with the mouse: The
|
||||
@code{drag-with-mode-line} parameter, if non-@code{nil}, enables
|
||||
|
@ -3627,8 +3695,12 @@ to display completions in a separate window, the @code{minibuffer-exit}
|
|||
parameter (@pxref{Frame Interaction Parameters}) is useful in order to
|
||||
deal with the frame when the minibuffer is exited.
|
||||
|
||||
The behavior of child frames deviates from that of top-level frames in
|
||||
a number of other ways as well. Here we sketch a few of them:
|
||||
|
||||
@node Child Frame Peculiarities
|
||||
@subsection Child Frame Peculiarities
|
||||
|
||||
The behavior of child frames deviates from that of normal frames in a
|
||||
number of peculiar ways. Here we sketch a few of them:
|
||||
|
||||
@itemize @bullet
|
||||
@item
|
||||
|
@ -3644,7 +3716,7 @@ described below.
|
|||
Raising, lowering and restacking child frames (@pxref{Raising and
|
||||
Lowering}) or changing the @code{z-group} (@pxref{Position Parameters})
|
||||
of a child frame changes only the stacking order of child frames with
|
||||
the same parent.
|
||||
the same parent. Restacking has not been implemented on text terminals.
|
||||
|
||||
@item
|
||||
Many window-systems are not able to change the opacity (@pxref{Font and
|
||||
|
@ -3667,43 +3739,6 @@ work on all window-systems. Some will drop the object on the parent
|
|||
frame or on some ancestor instead.
|
||||
@end itemize
|
||||
|
||||
The following three functions can be useful when working with child and
|
||||
parent frames:
|
||||
|
||||
@defun frame-parent &optional frame
|
||||
This function returns the parent frame of @var{frame}. The parent frame
|
||||
of @var{frame} is the Emacs frame whose window-system window is the
|
||||
parent window of @var{frame}'s window-system window. If such a frame
|
||||
exists, @var{frame} is considered a child frame of that frame.
|
||||
|
||||
This function returns @code{nil} if @var{frame} has no parent frame.
|
||||
@end defun
|
||||
|
||||
@cindex ancestor frame
|
||||
@defun frame-ancestor-p ancestor descendant
|
||||
This functions returns non-@code{nil} if @var{ancestor} is an ancestor
|
||||
of @var{descendant}. @var{ancestor} is an ancestor of @var{descendant}
|
||||
when it is either @var{descendant}'s parent frame or it is an ancestor
|
||||
of @var{descendant}'s parent frame. Both, @var{ancestor} and
|
||||
@var{descendant} must specify live frames.
|
||||
@end defun
|
||||
|
||||
@cindex root frame
|
||||
@defun frame-root-frame &optional frame
|
||||
This function returns the root frame of the specified @var{frame}.
|
||||
@var{frame} must be a live frame and defaults to the selected one. The
|
||||
root frame of @var{frame} is the frame obtained by following the chain
|
||||
of parent frames starting with @var{frame} until a frame is reached that
|
||||
has no parent. If @var{frame} has no parent, its root frame is
|
||||
@var{frame} itself.
|
||||
@end defun
|
||||
|
||||
Note also the function @code{window-largest-empty-rectangle}
|
||||
(@pxref{Coordinates and Windows}) which can be used to inscribe a child
|
||||
frame in the largest empty area of an existing window. This can be
|
||||
useful to avoid that a child frame obscures any text shown in that
|
||||
window.
|
||||
|
||||
Customizing the following option can be useful to tweak the behavior of
|
||||
@code{iconify-frame} for child frames.
|
||||
|
||||
|
@ -3724,6 +3759,68 @@ On a text terminal the only feasible values are @code{nil} and
|
|||
@code{make-invisible}.
|
||||
@end defopt
|
||||
|
||||
On text terminals exist a few restrictions with respect to reparenting:
|
||||
One is that a top frame (@pxref{Frames}) cannot be directly made a child
|
||||
frame---you first have to make another root frame the new top frame of
|
||||
its terminal. If, on the other hand, you want a child frame to become
|
||||
the new top frame of its terminal, you have to make it a root frame
|
||||
first.
|
||||
|
||||
Also, the surrogate minibuffer window of any frame on a text terminal
|
||||
must reside on a frame with the same root frame. Reparenting will throw
|
||||
an error whenever it violates this restriction. It also means that it's
|
||||
more tricky to make a minibuffer-less frame whose minibuffer window
|
||||
resides on a minibuffer-only child frame. On a GUI, Emacs proceeds as
|
||||
follows when a user has specified the value @code{child-frame} for the
|
||||
@code{minibuffer} parameter in @code{initial-frame-alist}
|
||||
(@pxref{Initial Parameters}):
|
||||
|
||||
@enumerate
|
||||
@item
|
||||
Create a minibuffer-only frame.
|
||||
|
||||
@item
|
||||
Create a minibuffer-less frame with its @code{minibuffer} parameter set
|
||||
to the window of the minibuffer-only frame.
|
||||
|
||||
@item
|
||||
Make the minibuffer-less frame the parent frame of the minibuffer-only
|
||||
frame.
|
||||
|
||||
@item
|
||||
Delete the originally selected frame.
|
||||
@end enumerate
|
||||
|
||||
On a text terminal you have to perform these operations manually as
|
||||
sketched in the following snippet:
|
||||
|
||||
@example
|
||||
@group
|
||||
(let* ((selected (selected-frame))
|
||||
(mini-only
|
||||
(make-frame
|
||||
`((parent-frame . ,selected)
|
||||
(minibuffer . only)
|
||||
(left . 1) (top . -1) (width . 20) (height . 1))))
|
||||
(mini-less
|
||||
(make-frame
|
||||
(append `((parent-frame . ,selected)
|
||||
(minibuffer . ,(minibuffer-window mini-only)))))))
|
||||
(set-frame-parameter mini-only 'parent-frame mini-less)
|
||||
(set-frame-parameter mini-less 'parent-frame nil)
|
||||
(select-frame mini-less)
|
||||
(delete-frame selected))
|
||||
@end group
|
||||
@end example
|
||||
|
||||
This means that you first have to install the minibuffer-less and the
|
||||
minibuffer-only frames both as child frames of the selected frame with
|
||||
the @code{minibuffer} parameter of the minibuffer-less frame set to the
|
||||
minibuffer window of the minibuffer-only frame. Then make the
|
||||
minibuffer-only frame a child frame of the minibuffer-less frame and
|
||||
make the minibuffer-less frame a new root frame. Finally, select the
|
||||
minibuffer-less frame and delete the originally selected frame.
|
||||
|
||||
|
||||
@node Mouse Tracking
|
||||
@section Mouse Tracking
|
||||
|
|
5
etc/NEWS
5
etc/NEWS
|
@ -75,11 +75,10 @@ the 'standard-display-table's extra slots with Unicode characters.
|
|||
Please see the documentation of that function to see which slots of the
|
||||
display table it changes.
|
||||
|
||||
+++
|
||||
** Child frames are now supported on TTY frames.
|
||||
This supports use-cases like Posframe, Corfu, and child frames acting
|
||||
like tooltips. Other use-cases of child frames are not supported yet.
|
||||
In particular, a TTY child frame cannot be converted to a root frame or
|
||||
vice-versa.
|
||||
like tooltips.
|
||||
|
||||
To enable tooltips on TTY frames, call 'tty-tip-mode'.
|
||||
|
||||
|
|
90
src/frame.c
90
src/frame.c
|
@ -2070,6 +2070,7 @@ parent window is the window-system's root window) or an embedded window
|
|||
return Qnil;
|
||||
}
|
||||
|
||||
/* Return true if frame AF is an ancestor of frame DF. */
|
||||
bool
|
||||
frame_ancestor_p (struct frame *af, struct frame *df)
|
||||
{
|
||||
|
@ -2086,6 +2087,22 @@ frame_ancestor_p (struct frame *af, struct frame *df)
|
|||
return false;
|
||||
}
|
||||
|
||||
/* A frame AF subsumes a frame DF if AF and DF are the same or AF is an
|
||||
ancestor of DF. */
|
||||
static bool
|
||||
frame_subsumes_p (struct frame *af, struct frame *df)
|
||||
{
|
||||
while (df)
|
||||
{
|
||||
if (df == af)
|
||||
return true;
|
||||
else
|
||||
df = FRAME_PARENT_FRAME (df);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
DEFUN ("frame-ancestor-p", Fframe_ancestor_p, Sframe_ancestor_p,
|
||||
2, 2, 0,
|
||||
doc: /* Return non-nil if ANCESTOR is an ancestor of DESCENDANT.
|
||||
|
@ -2100,7 +2117,6 @@ frame. */)
|
|||
return frame_ancestor_p (af, df) ? Qt : Qnil;
|
||||
}
|
||||
|
||||
|
||||
/* Return the root frame of frame F. Follow the parent_frame chain
|
||||
until we reach a frame that has no parent. That is the root frame.
|
||||
Note that the root of a root frame is itself. */
|
||||
|
@ -2448,6 +2464,18 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
|
|||
|
||||
XSETFRAME (frame, f);
|
||||
|
||||
if (is_tty_frame (f) && NILP (force))
|
||||
/* If F is a tty frame, check for surrogate minibuffer frames F
|
||||
subsumes used by a frame that is not subsumed by F. */
|
||||
FOR_EACH_FRAME (frames, frame1)
|
||||
{
|
||||
struct frame *f1 = XFRAME (frame1);
|
||||
|
||||
if (frame_subsumes_p (f, WINDOW_XFRAME (XWINDOW (f1->minibuffer_window)))
|
||||
&& !frame_subsumes_p (f, f1))
|
||||
error ("Cannot delete surrogate minibuffer frame");
|
||||
}
|
||||
|
||||
/* Softly delete all frames with this frame as their parent frame or
|
||||
as their `delete-before' frame parameter value. */
|
||||
FOR_EACH_FRAME (frames, frame1)
|
||||
|
@ -3625,7 +3653,7 @@ store_frame_param (struct frame *f, Lisp_Object prop, Lisp_Object val)
|
|||
{
|
||||
if (WINDOWP (val))
|
||||
{
|
||||
if (!MINI_WINDOW_P (XWINDOW (val)))
|
||||
if (!WINDOW_LIVE_P (val) || !MINI_WINDOW_P (XWINDOW (val)))
|
||||
error ("The `minibuffer' parameter does not specify a valid minibuffer window");
|
||||
else if (FRAME_MINIBUF_ONLY_P (f))
|
||||
{
|
||||
|
@ -3641,6 +3669,10 @@ store_frame_param (struct frame *f, Lisp_Object prop, Lisp_Object val)
|
|||
else
|
||||
error ("Can't change the minibuffer window of a frame with its own minibuffer");
|
||||
}
|
||||
else if (is_tty_frame (f)
|
||||
&& (root_frame (WINDOW_XFRAME (XWINDOW (val)))
|
||||
!= root_frame (f)))
|
||||
error ("A frame and its surrogate minibuffer frame must have the same roots");
|
||||
else
|
||||
/* Store the chosen minibuffer window. */
|
||||
fset_minibuffer_window (f, val);
|
||||
|
@ -3719,12 +3751,51 @@ store_frame_param (struct frame *f, Lisp_Object prop, Lisp_Object val)
|
|||
val = old_val;
|
||||
}
|
||||
|
||||
/* Re-parenting is currently not implemented when changing a root
|
||||
frame to a child frame or vice versa. */
|
||||
/* The parent frame parameter for ttys must be handled specially. */
|
||||
if (is_tty_frame (f) && EQ (prop, Qparent_frame))
|
||||
{
|
||||
if (NILP (f->parent_frame) != NILP (val))
|
||||
error ("Making a root frame a child or vice versa is not supported");
|
||||
/* Invariant: When a frame F1 uses a surrogate minibuffer frame M1
|
||||
on a tty, both F1 and M1 must have the same root frame. */
|
||||
Lisp_Object frames, frame1, old_val = f->parent_frame;
|
||||
|
||||
FOR_EACH_FRAME (frames, frame1)
|
||||
{
|
||||
struct frame *f1 = XFRAME (frame1);
|
||||
struct frame *m1 = WINDOW_XFRAME (XWINDOW (f1->minibuffer_window));
|
||||
bool mismatch = false;
|
||||
|
||||
/* Temporarily install VAL and check whether our invariant
|
||||
above gets violated. */
|
||||
f->parent_frame = val;
|
||||
mismatch = root_frame (f1) != root_frame (m1);
|
||||
f->parent_frame = old_val;
|
||||
|
||||
if (mismatch)
|
||||
error ("Cannot re-root surrogate minibuffer frame");
|
||||
}
|
||||
|
||||
if (f == XFRAME (FRAME_TERMINAL (f)->display_info.tty->top_frame)
|
||||
&& !NILP (val))
|
||||
error ("Cannot make tty top frame a child frame");
|
||||
else if (NILP (val))
|
||||
{
|
||||
if (!FRAME_HAS_MINIBUF_P (f)
|
||||
&& (!frame_ancestor_p
|
||||
(f, WINDOW_XFRAME (XWINDOW (f->minibuffer_window)))))
|
||||
error ("Cannot make tty root frame without valid minibuffer window");
|
||||
else
|
||||
{
|
||||
/* When making a frame a root frame, expand it to full size,
|
||||
if necessary, and position it at top left corner. */
|
||||
int width, height;
|
||||
|
||||
get_tty_size (fileno (FRAME_TTY (f)->input), &width, &height);
|
||||
adjust_frame_size (f, width, height - FRAME_TOP_MARGIN (f), 5, 0,
|
||||
Qterminal_frame);
|
||||
f->left_pos = 0;
|
||||
f->top_pos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
SET_FRAME_GARBAGED (root_frame (f));
|
||||
f->parent_frame = val;
|
||||
|
@ -6593,14 +6664,15 @@ of the frame returned by 'mouse-position'. */)
|
|||
{
|
||||
Lisp_Object pos = mouse_position (true);
|
||||
Lisp_Object frame = XCAR (pos);
|
||||
struct frame *f = XFRAME (frame);
|
||||
int x = XFIXNUM (XCAR (XCDR (pos))) + f->left_pos;
|
||||
int y = XFIXNUM (XCDR (XCDR (pos))) + f->top_pos;
|
||||
|
||||
if (!FRAMEP (frame))
|
||||
return Qnil;
|
||||
else
|
||||
{
|
||||
struct frame *f = XFRAME (frame);
|
||||
int x = XFIXNUM (XCAR (XCDR (pos))) + f->left_pos;
|
||||
int y = XFIXNUM (XCDR (XCDR (pos))) + f->top_pos;
|
||||
|
||||
f = FRAME_PARENT_FRAME (f);
|
||||
|
||||
while (f)
|
||||
|
|
Loading…
Add table
Reference in a new issue