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

Initial child frames based on master

This is based on a diff from 2024-10-15 which still applied.
Since then, I've inadvertantly modified the igc branch so that
it is no longer possible to get a clean diff of what has changed
since I created the branch.
This commit is contained in:
Gerd Möllmann 2024-10-21 18:32:04 +02:00
parent 1854f2751e
commit 414de92a56
20 changed files with 1672 additions and 618 deletions

View file

@ -130,6 +130,14 @@ decode_window_system_frame (Lisp_Object frame)
#endif
}
struct frame *
decode_tty_frame (Lisp_Object frame)
{
struct frame *f = decode_live_frame (frame);
check_tty (f);
return f;
}
void
check_window_system (struct frame *f)
{
@ -141,6 +149,13 @@ check_window_system (struct frame *f)
: "Window system is not in use or not initialized");
}
void
check_tty (struct frame *f)
{
if (!f || !FRAME_TERMCAP_P (f))
error ("tty frame should be used");
}
/* Return the value of frame parameter PROP in frame FRAME. */
Lisp_Object
@ -182,6 +197,17 @@ set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
int olines = FRAME_MENU_BAR_LINES (f);
int nlines = TYPE_RANGED_FIXNUMP (int, value) ? XFIXNUM (value) : 0;
/* Menu bars on child frames don't work on all platforms,
which is the reason why prepare_menu_bar does not update_menu_bar
for child frames (info from Martin Rudalics). This could be
implemented in ttys, but it's probaly not worth it. */
if (is_tty_child_frame (f))
{
FRAME_MENU_BAR_LINES (f) = 0;
FRAME_MENU_BAR_HEIGHT (f) = 0;
return;
}
/* Right now, menu bars don't work properly in minibuf-only frames;
most of the commands try to apply themselves to the minibuffer
frame itself, and get an error because you can't switch buffers
@ -370,17 +396,17 @@ frame_windows_min_size (Lisp_Object frame, Lisp_Object horizontal,
}
else
retval = XFIXNUM (call4 (Qframe_windows_min_size, frame, horizontal,
ignore, pixelwise));
ignore, pixelwise));
/* Don't allow too small height of text-mode frames, or else cm.c
might abort in cmcheckmagic. */
if ((FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f)) && NILP (horizontal))
{
int min_height = (FRAME_MENU_BAR_LINES (f)
+ FRAME_TAB_BAR_LINES (f)
int min_height = (FRAME_MENU_BAR_LINES (f) + FRAME_TAB_BAR_LINES (f)
+ FRAME_WANTS_MODELINE_P (f)
+ 2); /* one text line and one echo-area line */
+ FRAME_HAS_MINIBUF_P (f));
if (min_height == 0)
min_height = 1;
if (retval < min_height)
retval = min_height;
}
@ -389,7 +415,6 @@ frame_windows_min_size (Lisp_Object frame, Lisp_Object horizontal,
}
#ifdef HAVE_WINDOW_SYSTEM
/**
* keep_ratio:
*
@ -508,7 +533,6 @@ keep_ratio (struct frame *f, struct frame *p, int old_width, int old_height,
}
}
}
#endif
static void
@ -833,8 +857,9 @@ adjust_frame_size (struct frame *f, int new_text_width, int new_text_height,
/* MSDOS frames cannot PRETEND, as they change frame size by
manipulating video hardware. */
if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
FrameCols (FRAME_TTY (f)) = new_text_cols;
if (is_tty_root_frame (f))
if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
FrameCols (FRAME_TTY (f)) = new_text_cols;
#if defined (HAVE_WINDOW_SYSTEM)
if (WINDOWP (f->tab_bar_window))
@ -866,9 +891,10 @@ adjust_frame_size (struct frame *f, int new_text_width, int new_text_height,
resize_frame_windows (f, new_inner_height, false);
/* MSDOS frames cannot PRETEND, as they change frame size by
manipulating video hardware. */
if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
FrameRows (FRAME_TTY (f)) = new_text_lines + FRAME_TOP_MARGIN (f);
manipulating video hardware. */
if (is_tty_root_frame (f))
if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
FrameRows (FRAME_TTY (f)) = new_text_lines + FRAME_TOP_MARGIN (f);
}
else if (new_text_lines != old_text_lines)
call2 (Qwindow__pixel_to_total, frame, Qnil);
@ -898,6 +924,9 @@ adjust_frame_size (struct frame *f, int new_text_width, int new_text_height,
adjust_frame_glyphs (f);
calculate_costs (f);
SET_FRAME_GARBAGED (f);
if (is_tty_child_frame (f))
SET_FRAME_GARBAGED (root_frame (f));
/* We now say here that F was resized instead of using the old
condition below. Some resizing must have taken place and if it was
only shifting the root window's position (paranoia?). */
@ -910,7 +939,6 @@ adjust_frame_size (struct frame *f, int new_text_width, int new_text_height,
unblock_input ();
#ifdef HAVE_WINDOW_SYSTEM
{
/* Adjust size of F's child frames. */
Lisp_Object frames, frame1;
@ -920,7 +948,6 @@ adjust_frame_size (struct frame *f, int new_text_width, int new_text_height,
keep_ratio (XFRAME (frame1), f, old_native_width, old_native_height,
new_native_width, new_native_height);
}
#endif
}
/* Allocate basically initialized frame. */
@ -967,12 +994,12 @@ make_frame (bool mini_p)
f->line_height = 1; /* !FRAME_WINDOW_P value. */
f->new_width = -1;
f->new_height = -1;
f->no_special_glyphs = false;
#ifdef HAVE_WINDOW_SYSTEM
f->vertical_scroll_bar_type = vertical_scroll_bar_none;
f->horizontal_scroll_bars = false;
f->want_fullscreen = FULLSCREEN_NONE;
f->undecorated = false;
f->no_special_glyphs = false;
#ifndef HAVE_NTGUI
f->override_redirect = false;
#endif
@ -1089,7 +1116,6 @@ make_frame (bool mini_p)
return f;
}
#ifdef HAVE_WINDOW_SYSTEM
/* Make a frame using a separate minibuffer window on another frame.
MINI_WINDOW is the minibuffer window to use. nil means use the
default (the global minibuffer). */
@ -1183,7 +1209,7 @@ make_minibuffer_frame (void)
: Fcar (Vminibuffer_list)), 0, 0);
return f;
}
#endif /* HAVE_WINDOW_SYSTEM */
/* Construct a frame that refers to a terminal. */
@ -1209,7 +1235,7 @@ make_initial_frame (void)
tty_frame_count = 1;
fset_name (f, build_pure_c_string ("F1"));
SET_FRAME_VISIBLE (f, 1);
SET_FRAME_VISIBLE (f, true);
f->output_method = terminal->type;
f->terminal = terminal;
@ -1246,23 +1272,55 @@ make_initial_frame (void)
#ifndef HAVE_ANDROID
static struct frame *
make_terminal_frame (struct terminal *terminal)
make_terminal_frame (struct terminal *terminal, Lisp_Object parent,
Lisp_Object params)
{
register struct frame *f;
Lisp_Object frame;
char name[sizeof "F" + INT_STRLEN_BOUND (tty_frame_count)];
if (!terminal->name)
error ("Terminal is not live, can't create new frames on it");
f = make_frame (1);
struct frame *f;
if (NILP (parent))
f = make_frame (true);
else
{
CHECK_FRAME (parent);
f = NULL;
Lisp_Object mini = Fassq (Qminibuffer, params);
if (CONSP (mini))
{
mini = Fcdr (mini);
struct kboard *kb = FRAME_KBOARD (XFRAME (parent));
if (EQ (mini, Qnone) || NILP (mini))
f = make_frame_without_minibuffer (Qnil, kb, Qnil);
else if (EQ (mini, Qonly))
{
# if 0 /* No interest in this feature at the moment, */
f = make_minibuffer_frame ();
/* Not sure about this plus the unsplittable frame
paran. */
f->no_split = true;
# endif
}
else if (WINDOWP (mini))
f = make_frame_without_minibuffer (mini, kb, Qnil);
}
if (f == NULL)
f = make_frame (true);
f->parent_frame = parent;
f->z_order = 1 + max_child_z_order (XFRAME (parent));
}
Lisp_Object frame;
XSETFRAME (frame, f);
Vframe_list = Fcons (frame, Vframe_list);
fset_name (f, make_formatted_string (name, "F%"PRIdMAX, ++tty_frame_count));
SET_FRAME_VISIBLE (f, 1);
SET_FRAME_VISIBLE (f, true);
f->terminal = terminal;
f->terminal->reference_count++;
@ -1287,7 +1345,15 @@ make_terminal_frame (struct terminal *terminal)
f->horizontal_scroll_bars = false;
#endif
FRAME_MENU_BAR_LINES (f) = NILP (Vmenu_bar_mode) ? 0 : 1;
/* Menu bars on child frames don't work on all platforms,
which is the reason why prepare_menu_bar does not update_menu_bar
for child frames (info from Martin Rudalics). This could be
implemented in ttys, but it's unclear if it is worth it. */
if (NILP (parent))
FRAME_MENU_BAR_LINES (f) = NILP (Vmenu_bar_mode) ? 0 : 1;
else
FRAME_MENU_BAR_LINES (f) = 0;
FRAME_TAB_BAR_LINES (f) = NILP (Vtab_bar_mode) ? 0 : 1;
FRAME_LINES (f) = FRAME_LINES (f) - FRAME_MENU_BAR_LINES (f)
- FRAME_TAB_BAR_LINES (f);
@ -1296,16 +1362,19 @@ make_terminal_frame (struct terminal *terminal)
FRAME_TEXT_HEIGHT (f) = FRAME_TEXT_HEIGHT (f) - FRAME_MENU_BAR_HEIGHT (f)
- FRAME_TAB_BAR_HEIGHT (f);
/* Mark current topmost frame obscured if we make a new root frame.
Child frames don't completely obscure other frames. */
if (NILP (parent) && FRAMEP (FRAME_TTY (f)->top_frame))
{
struct frame *top = XFRAME (FRAME_TTY (f)->top_frame);
struct frame *root = root_frame (top);
if (FRAME_LIVE_P (root))
SET_FRAME_VISIBLE (root, false);
}
/* Set the top frame to the newly created frame. */
if (FRAMEP (FRAME_TTY (f)->top_frame)
&& FRAME_LIVE_P (XFRAME (FRAME_TTY (f)->top_frame)))
SET_FRAME_VISIBLE (XFRAME (FRAME_TTY (f)->top_frame), 2); /* obscured */
FRAME_TTY (f)->top_frame = frame;
if (!noninteractive)
init_frame_faces (f);
if (!FRAME_PARENT_FRAME (f))
FRAME_TTY (f)->top_frame = frame;
return f;
}
@ -1335,6 +1404,62 @@ get_future_frame_param (Lisp_Object parameter,
#endif
static int
tty_child_pos_param (struct frame *child, Lisp_Object key,
Lisp_Object params, int dflt)
{
Lisp_Object val = Fassq (key, params);
if (CONSP (val))
{
val = XCDR (val);
if (FIXNUMP (val))
return XFIXNUM (val);
}
return dflt;
}
static int
tty_child_size_param (struct frame *child, Lisp_Object key,
Lisp_Object params, int dflt)
{
Lisp_Object val = Fassq (key, params);
if (CONSP (val))
{
val = XCDR (val);
if (CONSP (val))
{
/* Width and height may look like (width text-pixels
. PIXELS) on window systems. Mimic that. */
val = XCDR (val);
if (EQ (val, Qtext_pixels))
val = XCDR (val);
}
else if (FLOATP (val))
{
/* Width and height may be a float, in which case
it's a multiple of the parent's value. */
struct frame *parent = FRAME_PARENT_FRAME (child);
int sz = (EQ (key, Qwidth) ? FRAME_TOTAL_COLS (parent)
: FRAME_TOTAL_LINES (parent));
val = make_fixnum (XFLOAT_DATA (val) * sz);
}
if (FIXNUMP (val) && XFIXNUM (val) > 0)
return XFIXNUM (val);
}
return dflt;
}
static void
child_frame_rect (struct frame *f, Lisp_Object params,
int *x, int *y, int *w, int *h)
{
*x = tty_child_pos_param (f, Qleft, params, 0);
*y = tty_child_pos_param (f, Qtop, params, 0);
*w = tty_child_size_param (f, Qwidth, params, FRAME_TOTAL_COLS (f));
*h = tty_child_size_param (f, Qheight, params, FRAME_TOTAL_LINES (f));
}
DEFUN ("make-terminal-frame", Fmake_terminal_frame, Smake_terminal_frame,
1, 1, 0,
doc: /* Create an additional terminal frame, possibly on another terminal.
@ -1358,9 +1483,7 @@ affects all frames on the same terminal device. */)
error ("Text terminals are not supported on this platform");
return Qnil;
#else
struct frame *f;
struct terminal *t = NULL;
Lisp_Object frame;
struct frame *sf = SELECTED_FRAME ();
#ifdef MSDOS
@ -1390,7 +1513,7 @@ affects all frames on the same terminal device. */)
error ("Multiple terminals are not supported on this platform");
if (!t)
t = the_only_display_info.terminal;
#endif
# endif
}
if (!t)
@ -1417,19 +1540,67 @@ affects all frames on the same terminal device. */)
SAFE_FREE ();
}
f = make_terminal_frame (t);
/* Make a new frame. We need to know upfront if if a parent frame is
specified because we behave differently in this case, e.g. child
frames don't obscure other frames. */
Lisp_Object parent = Fcdr (Fassq (Qparent_frame, parms));
struct frame *f = make_terminal_frame (t, parent, parms);
{
int width, height;
if (!noninteractive)
init_frame_faces (f);
/* Visibility of root frames cannot be set with a frame parameter.
Their visibility solely depends on whether or not they are the
top_frame on the terminal. */
if (FRAME_PARENT_FRAME (f))
{
Lisp_Object visible = Fassq (Qvisibility, parms);
if (CONSP (visible))
SET_FRAME_VISIBLE (f, !NILP (visible));
/* FIXME/tty: The only way to get borders on a tty is
to allow decorations for now. */
Lisp_Object undecorated = Fassq (Qundecorated, parms);
if (CONSP (undecorated) && !NILP (XCDR (undecorated)))
f->undecorated = true;
/* FIXME/tty: The only way to get borders on a tty is
to allow decorations for now. */
Lisp_Object no_focus = Fassq (Qno_accept_focus, parms);
if (CONSP (no_focus) && !NILP (XCDR (no_focus)))
f->no_accept_focus = true;
/* FIXME/tty: The only way to get borders on a tty is
to allow decorations for now. */
Lisp_Object no_split = Fassq (Qunsplittable, parms);
if (CONSP (no_split) && !NILP (XCDR (no_split)))
f->no_split = true;
}
/* Determine width and height of the frame. For root frames use the
width/height of the terminal. For child frames, take it from frame
parameters. Note that a default (80x25) has been set in
make_frame. We handle root frames in this way because otherwise we
would end up needing glyph matrices for the terminal, which is both
more work and has its downsides (think of clipping frames to the
terminal size). */
int x = 0, y = 0, width, height;
if (FRAME_PARENT_FRAME (f))
child_frame_rect (f, parms, &x, &y, &width, &height);
else
get_tty_size (fileno (FRAME_TTY (f)->input), &width, &height);
/* With INHIBIT 5 pass correct text height to adjust_frame_size. */
adjust_frame_size (f, width, height - FRAME_TOP_MARGIN (f),
5, 0, Qterminal_frame);
}
adjust_frame_size (f, width, height - FRAME_TOP_MARGIN (f), 5, 0,
Qterminal_frame);
adjust_frame_glyphs (f);
calculate_costs (f);
XSETFRAME (frame, f);
f->left_pos = x;
f->top_pos = y;
store_in_alist (&parms, Qleft, make_fixnum (x));
store_in_alist (&parms, Qtop, make_fixnum (y));
store_in_alist (&parms, Qwidth, make_fixnum (width));
store_in_alist (&parms, Qheight, make_fixnum (height));
store_in_alist (&parms, Qtty_type, build_string (t->display_info.tty->type));
store_in_alist (&parms, Qtty,
@ -1451,7 +1622,11 @@ affects all frames on the same terminal device. */)
/* On terminal frames the `minibuffer' frame parameter is always
virtually t. Avoid that a different value in parms causes
complaints, see Bug#24758. */
store_in_alist (&parms, Qminibuffer, Qt);
if (!FRAME_PARENT_FRAME (f))
store_in_alist (&parms, Qminibuffer, Qt);
Lisp_Object frame;
XSETFRAME (frame, f);
Fmodify_frame_parameters (frame, parms);
f->can_set_window_size = true;
@ -1480,8 +1655,6 @@ affects all frames on the same terminal device. */)
Lisp_Object
do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object norecord)
{
struct frame *sf = SELECTED_FRAME (), *f;
/* If FRAME is a switch-frame event, extract the frame we should
switch to. */
if (CONSP (frame)
@ -1493,7 +1666,9 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor
a switch-frame event to arrive after a frame is no longer live,
especially when deleting the initial frame during startup. */
CHECK_FRAME (frame);
f = XFRAME (frame);
struct frame *f = XFRAME (frame);
struct frame *sf = SELECTED_FRAME ();
/* Silently ignore dead and tooltip frames (Bug#47207). */
if (!FRAME_LIVE_P (f) || FRAME_TOOLTIP_P (f))
return Qnil;
@ -1546,24 +1721,37 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor
struct tty_display_info *tty = FRAME_TTY (f);
Lisp_Object top_frame = tty->top_frame;
/* Don't mark the frame garbaged and/or obscured if we are
switching to the frame that is already the top frame of that
TTY. */
/* Don't mark the frame garbaged if we are switching to the frame
that is already the top frame of that TTY. */
if (!EQ (frame, top_frame))
{
struct frame *new_root = root_frame (f);
SET_FRAME_VISIBLE (new_root, true);
SET_FRAME_VISIBLE (f, true);
/* Mark previously displayed frame as no longer visible. */
if (FRAMEP (top_frame))
/* Mark previously displayed frame as now obscured. */
SET_FRAME_VISIBLE (XFRAME (top_frame), 2);
SET_FRAME_VISIBLE (f, 1);
/* If the new TTY frame changed dimensions, we need to
resync term.c's idea of the frame size with the new
frame's data. */
if (FRAME_COLS (f) != FrameCols (tty))
FrameCols (tty) = FRAME_COLS (f);
if (FRAME_TOTAL_LINES (f) != FrameRows (tty))
FrameRows (tty) = FRAME_TOTAL_LINES (f);
{
struct frame *top = XFRAME (top_frame);
struct frame *old_root = root_frame (top);
if (old_root != new_root)
SET_FRAME_VISIBLE (old_root, false);
}
tty->top_frame = frame;
/* Why is it correct to set FrameCols/Rows? */
if (!FRAME_PARENT_FRAME (f))
{
/* If the new TTY frame changed dimensions, we need to
resync term.c's idea of the frame size with the new
frame's data. */
if (FRAME_COLS (f) != FrameCols (tty))
FrameCols (tty) = FRAME_COLS (f);
if (FRAME_TOTAL_LINES (f) != FrameRows (tty))
FrameRows (tty) = FRAME_TOTAL_LINES (f);
}
}
tty->top_frame = frame;
}
sf->select_mini_window_flag = MINI_WINDOW_P (XWINDOW (sf->selected_window));
@ -1605,9 +1793,7 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor
(select-window (frame-root-window (make-frame))) doesn't end up
with your typing being interpreted in the new frame instead of
the one you're actually typing in. */
#ifdef HAVE_WINDOW_SYSTEM
if (!frame_ancestor_p (f, sf))
#endif
internal_last_event_frame = Qnil;
return frame;
@ -1725,7 +1911,6 @@ parent window is the window-system's root window) or an embedded window
return Qnil;
}
#ifdef HAVE_WINDOW_SYSTEM
bool
frame_ancestor_p (struct frame *af, struct frame *df)
{
@ -1741,7 +1926,6 @@ frame_ancestor_p (struct frame *af, struct frame *df)
return false;
}
#endif
DEFUN ("frame-ancestor-p", Fframe_ancestor_p, Sframe_ancestor_p,
2, 2, 0,
@ -1752,15 +1936,10 @@ ANCESTOR and DESCENDANT must be live frames and default to the selected
frame. */)
(Lisp_Object ancestor, Lisp_Object descendant)
{
#ifdef HAVE_WINDOW_SYSTEM
struct frame *af = decode_live_frame (ancestor);
struct frame *df = decode_live_frame (descendant);
return frame_ancestor_p (af, df) ? Qt : Qnil;
#else
return Qnil;
#endif
}
}
/* Return CANDIDATE if it can be used as 'other-than-FRAME' frame on the
same tty (for tty frames) or among frames which uses FRAME's keyboard.
@ -2021,7 +2200,9 @@ other_frames (struct frame *f, bool invisible, bool force)
&& (invisible || NILP (get_frame_param (f1, Qdelete_before)))
/* For invisibility and normal deletions, at least one
visible or iconified frame must remain (Bug#26682). */
&& (FRAME_VISIBLE_P (f1) || FRAME_ICONIFIED_P (f1)
&& (FRAME_VISIBLE_P (f1)
|| is_tty_frame (f1)
|| FRAME_ICONIFIED_P (f1)
|| (!invisible
&& (force
/* Allow deleting the terminal frame when at
@ -2282,7 +2463,7 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
fset_root_window (f, Qnil);
Vframe_list = Fdelq (frame, Vframe_list);
SET_FRAME_VISIBLE (f, 0);
SET_FRAME_VISIBLE (f, false);
/* Allow the vector of menu bar contents to be freed in the next
garbage collection. The frame object itself may not be garbage
@ -2868,6 +3049,12 @@ If omitted, FRAME defaults to the currently selected frame. */)
if (FRAME_WINDOW_P (f) && FRAME_TERMINAL (f)->frame_visible_invisible_hook)
FRAME_TERMINAL (f)->frame_visible_invisible_hook (f, true);
if (is_tty_frame (f))
{
SET_FRAME_VISIBLE (f, true);
tty_raise_lower_frame (f, true);
}
make_frame_visible_1 (f->root_window);
/* Make menu bar update for the Buffers and Frames menus. */
@ -2918,6 +3105,12 @@ displayed in the terminal. */)
if (FRAME_WINDOW_P (f) && FRAME_TERMINAL (f)->frame_visible_invisible_hook)
FRAME_TERMINAL (f)->frame_visible_invisible_hook (f, false);
/* The Elisp info manual says that this "usually" makes child frames
invisible, too, but without saying when not. Since users can't rely
on this, it's not implemented. */
if (is_tty_frame (f))
SET_FRAME_VISIBLE (f, false);
/* Make menu bar update for the Buffers and Frames menus. */
windows_or_buffers_changed = 16;
@ -2977,10 +3170,13 @@ currently being displayed on the terminal. */)
(Lisp_Object frame)
{
CHECK_LIVE_FRAME (frame);
struct frame *f = XFRAME (frame);
if (FRAME_VISIBLE_P (XFRAME (frame)))
if (FRAME_VISIBLE_P (f))
return Qt;
if (FRAME_ICONIFIED_P (XFRAME (frame)))
else if (is_tty_root_frame (f))
return Qt;
if (FRAME_ICONIFIED_P (f))
return Qicon;
return Qnil;
}
@ -3012,12 +3208,7 @@ doesn't support multiple overlapping frames, this function selects FRAME. */)
XSETFRAME (frame, f);
if (FRAME_TERMCAP_P (f))
/* On a text terminal select FRAME. */
Fselect_frame (frame, Qnil);
else
/* Do like the documentation says. */
Fmake_frame_visible (frame);
Fmake_frame_visible (frame);
if (FRAME_TERMINAL (f)->frame_raise_lower_hook)
(*FRAME_TERMINAL (f)->frame_raise_lower_hook) (f, true);
@ -3318,6 +3509,15 @@ 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. */
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");
f->parent_frame = val;
}
/* The tty color needed to be set before the frame's parameter
alist was updated with the new value. This is not true any more,
but we still do this test early on. */
@ -3441,13 +3641,10 @@ If FRAME is omitted or nil, return information on the currently selected frame.
else
#endif
{
/* This ought to be correct in f->param_alist for an X frame. */
Lisp_Object lines;
XSETFASTINT (lines, FRAME_MENU_BAR_LINES (f));
store_in_alist (&alist, Qmenu_bar_lines, lines);
XSETFASTINT (lines, FRAME_TAB_BAR_LINES (f));
store_in_alist (&alist, Qtab_bar_lines, lines);
store_in_alist (&alist, Qmenu_bar_lines, make_fixnum (FRAME_MENU_BAR_LINES (f)));
store_in_alist (&alist, Qtab_bar_lines, make_fixnum (FRAME_TAB_BAR_LINES (f)));
store_in_alist (&alist, Qvisibility, FRAME_VISIBLE_P (f) ? Qt : Qnil);
store_in_alist (&alist, Qno_accept_focus, FRAME_NO_ACCEPT_FOCUS (f) ? Qt : Qnil);
}
return alist;
@ -3525,7 +3722,6 @@ If FRAME is nil, describe the currently selected frame. */)
return value;
}
DEFUN ("modify-frame-parameters", Fmodify_frame_parameters,
Smodify_frame_parameters, 2, 2, 0,
doc: /* Modify FRAME according to new values of its parameters in ALIST.
@ -3563,6 +3759,7 @@ list, but are otherwise ignored. */)
USE_SAFE_ALLOCA;
SAFE_ALLOCA_LISP (parms, 2 * length);
values = parms + length;
Lisp_Object params = alist;
/* Extract parm names and values into those vectors. */
@ -3588,6 +3785,31 @@ list, but are otherwise ignored. */)
update_face_from_frame_parameter (f, prop, val);
}
if (is_tty_child_frame (f))
{
int x = tty_child_pos_param (f, Qleft, params, f->left_pos);
int y = tty_child_pos_param (f, Qtop, params, f->top_pos);
if (x != f->left_pos || y != f->top_pos)
{
f->left_pos = x;
f->top_pos = y;
SET_FRAME_GARBAGED (root_frame (f));
}
int w = tty_child_size_param (f, Qwidth, params, f->total_cols);
int h = tty_child_size_param (f, Qheight, params, f->total_lines);
if (w != f->total_cols || h != f->total_lines)
change_frame_size (f, w, h, false, false, false);
Lisp_Object visible = Fassq (Qvisibility, params);
if (CONSP (visible))
SET_FRAME_VISIBLE (f, !NILP (Fcdr (visible)));
Lisp_Object no_special = Fassq (Qno_special_glyphs, params);
if (CONSP (no_special))
FRAME_NO_SPECIAL_GLYPHS (f) = !NILP (Fcdr (no_special));
}
SAFE_FREE ();
}
return Qnil;
@ -3935,6 +4157,11 @@ bottom edge of FRAME's display. */)
(void) yval;
#endif
}
else if (is_tty_child_frame (f))
{
f->left_pos = xval;
f->top_pos = yval;
}
return Qt;
}
@ -4246,6 +4473,28 @@ frame_float (struct frame *f, Lisp_Object val, enum frame_float_type what,
}
}
/* Handle frame parameter change with frame parameter handler. F is the
frame whose frame parameter was changed. PROP is the name of the
frame parameter. VAL and OLD_VALUE are the current value and old
value of the frame parameter. */
static void
handle_frame_param (struct frame *f, Lisp_Object prop, Lisp_Object val,
Lisp_Object old_value)
{
Lisp_Object param_index = Fget (prop, Qx_frame_parameter);
if (FIXNATP (param_index) && XFIXNAT (param_index) < ARRAYELTS (frame_parms))
{
if (FRAME_RIF (f))
{
frame_parm_handler handler
= FRAME_RIF (f)->frame_parm_handlers[XFIXNAT (param_index)];
if (handler)
handler (f, val, old_value);
}
}
}
/* Change the parameters of frame F as specified by ALIST.
If a parameter is not specially recognized, do nothing special;
otherwise call the `gui_set_...' function for that parameter.
@ -4387,17 +4636,9 @@ gui_set_frame_parameters_1 (struct frame *f, Lisp_Object alist,
}
else
{
Lisp_Object param_index, old_value;
old_value = get_frame_param (f, prop);
Lisp_Object old_value = get_frame_param (f, prop);
store_frame_param (f, prop, val);
param_index = Fget (prop, Qx_frame_parameter);
if (FIXNATP (param_index)
&& XFIXNAT (param_index) < ARRAYELTS (frame_parms)
&& FRAME_RIF (f)->frame_parm_handlers[XFIXNUM (param_index)])
(*(FRAME_RIF (f)->frame_parm_handlers[XFIXNUM (param_index)])) (f, val, old_value);
handle_frame_param (f, prop, val, old_value);
if (!default_parameter && EQ (prop, Qfont))
/* The user manually specified the `font' frame parameter.
@ -4716,14 +4957,7 @@ gui_set_screen_gamma (struct frame *f, Lisp_Object new_value, Lisp_Object old_va
/* Apply the new gamma value to the frame background. */
bgcolor = Fassq (Qbackground_color, f->param_alist);
if (CONSP (bgcolor) && (bgcolor = XCDR (bgcolor), STRINGP (bgcolor)))
{
Lisp_Object parm_index = Fget (Qbackground_color, Qx_frame_parameter);
if (FIXNATP (parm_index)
&& XFIXNAT (parm_index) < ARRAYELTS (frame_parms)
&& FRAME_RIF (f)->frame_parm_handlers[XFIXNAT (parm_index)])
(*FRAME_RIF (f)->frame_parm_handlers[XFIXNAT (parm_index)])
(f, bgcolor, Qnil);
}
handle_frame_param (f, Qbackground_color, bgcolor, Qnil);
clear_face_cache (true); /* FIXME: Why of all frames? */
fset_redisplay (f);