diff options
Diffstat (limited to 'src/frame.c')
-rw-r--r-- | src/frame.c | 572 |
1 files changed, 418 insertions, 154 deletions
diff --git a/src/frame.c b/src/frame.c index 8753f168a3b..146ecb226a4 100644 --- a/src/frame.c +++ b/src/frame.c @@ -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,20 @@ check_window_system (struct frame *f) : "Window system is not in use or not initialized"); } +void +check_tty (struct frame *f) +{ + /* FIXME: the noninteractive case is here because some tests running + in batch mode, like xt-mouse-tests, test with the initial frame + which is no tty frame. It would be nicer if the test harness + would allow testing with real tty frames. */ + if (f && noninteractive) + return; + + if (!f || !FRAME_TERMCAP_P (f)) + error ("tty frame should be used"); +} + /* Return the value of frame parameter PROP in frame FRAME. */ Lisp_Object @@ -158,20 +180,19 @@ bool frame_inhibit_resize (struct frame *f, bool horizontal, Lisp_Object parameter) { Lisp_Object fullscreen = get_frame_param (f, Qfullscreen); - bool inhibit - = (f->after_make_frame - ? (EQ (frame_inhibit_implied_resize, Qt) - || (CONSP (frame_inhibit_implied_resize) - && !NILP (Fmemq (parameter, frame_inhibit_implied_resize))) - || (horizontal - && !NILP (fullscreen) && !EQ (fullscreen, Qfullheight)) - || (!horizontal - && !NILP (fullscreen) && !EQ (fullscreen, Qfullwidth)) - || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f)) - : ((horizontal && f->inhibit_horizontal_resize) - || (!horizontal && f->inhibit_vertical_resize))); - return inhibit; + return (f->after_make_frame +#ifdef USE_GTK + && f->tool_bar_resized +#endif + && (EQ (frame_inhibit_implied_resize, Qt) + || (CONSP (frame_inhibit_implied_resize) + && !NILP (Fmemq (parameter, frame_inhibit_implied_resize))) + || (horizontal + && !NILP (fullscreen) && !EQ (fullscreen, Qfullheight)) + || (!horizontal + && !NILP (fullscreen) && !EQ (fullscreen, Qfullwidth)) + || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))); } @@ -182,6 +203,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 +402,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 +421,6 @@ frame_windows_min_size (Lisp_Object frame, Lisp_Object horizontal, } -#ifdef HAVE_WINDOW_SYSTEM /** * keep_ratio: * @@ -508,7 +539,6 @@ keep_ratio (struct frame *f, struct frame *p, int old_width, int old_height, } } } -#endif static void @@ -817,14 +847,18 @@ adjust_frame_size (struct frame *f, int new_text_width, int new_text_height, block_input (); #ifdef MSDOS - /* We only can set screen dimensions to certain values supported by - our video hardware. Try to find the smallest size greater or - equal to the requested dimensions, while accounting for the fact - that the menu-bar lines are not counted in the frame height. */ - int dos_new_text_lines = new_text_lines + FRAME_TOP_MARGIN (f); - - dos_set_window_size (&dos_new_text_lines, &new_text_cols); - new_text_lines = dos_new_text_lines - FRAME_TOP_MARGIN (f); + if (!FRAME_PARENT_FRAME (f)) + { + /* We only can set screen dimensions to certain values supported + by our video hardware. Try to find the smallest size greater + or equal to the requested dimensions, while accounting for the + fact that the menu-bar lines are not counted in the frame + height. */ + int dos_new_text_lines = new_text_lines + FRAME_TOP_MARGIN (f); + + dos_set_window_size (&dos_new_text_lines, &new_text_cols); + new_text_lines = dos_new_text_lines - FRAME_TOP_MARGIN (f); + } #endif if (new_inner_width != old_inner_width) @@ -833,8 +867,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 +901,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 +934,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 +949,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 +958,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. */ @@ -957,8 +994,6 @@ make_frame (bool mini_p) f->garbaged = true; f->can_set_window_size = false; f->after_make_frame = false; - f->inhibit_horizontal_resize = false; - f->inhibit_vertical_resize = false; f->tab_bar_redisplayed = false; f->tab_bar_resized = false; f->tool_bar_redisplayed = false; @@ -967,12 +1002,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 +1124,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 +1217,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 +1243,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 +1280,48 @@ 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_LIVE_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)) + error ("minibuffer-only child frames are not implemented"); + 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 +1346,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 +1363,18 @@ make_terminal_frame (struct terminal *terminal) FRAME_TEXT_HEIGHT (f) = FRAME_TEXT_HEIGHT (f) - FRAME_MENU_BAR_HEIGHT (f) - FRAME_TAB_BAR_HEIGHT (f); - /* 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 */ + /* 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. */ FRAME_TTY (f)->top_frame = frame; - - if (!noninteractive) - init_frame_faces (f); - return f; } @@ -1335,6 +1404,72 @@ get_future_frame_param (Lisp_Object parameter, #endif +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; +} + +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); + eassert (parent); /* the caller ensures this, but... */ + if (parent) + { + int sz = (EQ (key, Qwidth) ? FRAME_TOTAL_COLS (parent) + : FRAME_TOTAL_LINES (parent)); + val = make_fixnum (XFLOAT_DATA (val) * sz); + } + else + val = Qnil; + } + + if (FIXNATP (val)) + return XFIXNUM (val); + } + return dflt; +} + +#ifndef HAVE_ANDROID + +static void +tty_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)); +} + +#endif /* !HAVE_ANDROID */ + 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 +1493,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 +1523,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 +1550,64 @@ affects all frames on the same terminal device. */) SAFE_FREE (); } - f = make_terminal_frame (t); + /* Make a new frame. We need to know up front 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; - 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); - } + 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, for now, to get borders on a tty is + to allow decorations. */ + Lisp_Object undecorated = Fassq (Qundecorated, parms); + if (CONSP (undecorated) && !NILP (XCDR (undecorated))) + f->undecorated = true; + + /* Unused at present. */ + Lisp_Object no_focus = Fassq (Qno_accept_focus, parms); + if (CONSP (no_focus) && !NILP (XCDR (no_focus))) + f->no_accept_focus = true; + + 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)) + tty_child_frame_rect (f, parms, &x, &y, &width, &height); + else + get_tty_size (fileno (FRAME_TTY (f)->input), &width, &height); + 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 +1629,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 +1662,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 +1673,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 +1728,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; + + /* FIXME: 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,10 +1800,36 @@ 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; + + /* FIXME/tty: I don't understand this. (The comment above is from + Jim BLandy 1993 BTW, and the frame_ancestor_p from 2017.) + + Setting the last event frame to nil leads to switch-frame events + being generated even if they normally wouldn't be because the frame + in question equals selected-frame. See the places in keyboard.c + where make_lispy_switch_frame is called. + + This leads to problems at least on ttys. + + Imagine that we have functions in post-command-hook that use + select-frame in some way (e.g., with-selected-window). Let these + functions select different frames during the execution of + post-command-hook in command_loop_1. Setting + internal_last_event_frame to nil here makes these select-frame + calls (potentially and in reality) generate switch-frame events. + (But only in one direction (frame_ancestor_p), which I also don't + understand). + + These switch-frame events form an endless loop in + command_loop_1. It runs post-command-hook, which generates + switch-frame events, which command_loop_1 finds (bound to '#ignore) + and executes, which again runs post-command-hook etc., ad + infinitum. + + Let's not do that for now on ttys. */ + if (!is_tty_frame (f)) + if (!frame_ancestor_p (f, sf)) + internal_last_event_frame = Qnil; return frame; } @@ -1725,7 +1946,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 +1961,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 +1971,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 +2235,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 @@ -2281,8 +2497,10 @@ delete_frame (Lisp_Object frame, Lisp_Object force) delete_all_child_windows (f->root_window); fset_root_window (f, Qnil); + block_input (); Vframe_list = Fdelq (frame, Vframe_list); - SET_FRAME_VISIBLE (f, 0); + unblock_input (); + 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 +3086,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 +3142,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 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 +3207,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; + else if (is_tty_root_frame (f)) return Qt; - if (FRAME_ICONIFIED_P (XFRAME (frame))) + if (FRAME_ICONIFIED_P (f)) return Qicon; return Qnil; } @@ -3012,12 +3245,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); @@ -3128,8 +3356,6 @@ otherwise used with utter care to avoid that running functions on { struct frame *f = decode_live_frame (frame); f->after_make_frame = !NILP (made); - f->inhibit_horizontal_resize = false; - f->inhibit_vertical_resize = false; return made; } @@ -3318,6 +3544,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 +3676,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 +3757,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 +3794,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 +3820,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 +4192,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; } @@ -3992,9 +4254,9 @@ multiplied to find the real number of pixels. */) /* Connect the frame-parameter names for frames to the ways of passing the parameter values to the window system. - The name of a parameter, as a Lisp symbol, has a - `frame-parameter-pos' property which is an integer in Lisp that is - an index in this table. */ + The name of a parameter, a Lisp symbol, has an `x-frame-parameter' + property which is its index in this table. This is initialized in + syms_of_frame. */ struct frame_parm_table { const char *name; @@ -4005,13 +4267,13 @@ static const struct frame_parm_table frame_parms[] = { {"auto-raise", SYMBOL_INDEX (Qauto_raise)}, {"auto-lower", SYMBOL_INDEX (Qauto_lower)}, - {"background-color", -1}, + {"background-color", SYMBOL_INDEX (Qbackground_color)}, {"border-color", SYMBOL_INDEX (Qborder_color)}, {"border-width", SYMBOL_INDEX (Qborder_width)}, {"cursor-color", SYMBOL_INDEX (Qcursor_color)}, {"cursor-type", SYMBOL_INDEX (Qcursor_type)}, - {"font", -1}, - {"foreground-color", -1}, + {"font", SYMBOL_INDEX (Qfont)}, + {"foreground-color", SYMBOL_INDEX (Qforeground_color)}, {"icon-name", SYMBOL_INDEX (Qicon_name)}, {"icon-type", SYMBOL_INDEX (Qicon_type)}, {"child-frame-border-width", SYMBOL_INDEX (Qchild_frame_border_width)}, @@ -4246,6 +4508,29 @@ 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 and the 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 +4672,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 +4993,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); @@ -5918,7 +6188,6 @@ gui_figure_window_size (struct frame *f, Lisp_Object parms, bool tabbar_p, xsignal1 (Qargs_out_of_range, XCDR (width)); text_width = XFIXNUM (XCDR (width)); - f->inhibit_horizontal_resize = true; } else if (FLOATP (width)) { @@ -5954,7 +6223,6 @@ gui_figure_window_size (struct frame *f, Lisp_Object parms, bool tabbar_p, xsignal1 (Qargs_out_of_range, XCDR (height)); text_height = XFIXNUM (XCDR (height)); - f->inhibit_vertical_resize = true; } else if (FLOATP (height)) { @@ -6463,17 +6731,13 @@ syms_of_frame (void) DEFSYM (Quse_frame_synchronization, "use-frame-synchronization"); DEFSYM (Qfont_parameter, "font-parameter"); - { - int i; - - for (i = 0; i < ARRAYELTS (frame_parms); i++) - { - Lisp_Object v = (frame_parms[i].sym < 0 - ? intern_c_string (frame_parms[i].name) - : builtin_lisp_symbol (frame_parms[i].sym)); - Fput (v, Qx_frame_parameter, make_fixnum (i)); - } - } + for (int i = 0; i < ARRAYELTS (frame_parms); i++) + { + int sym = frame_parms[i].sym; + eassert (sym >= 0 && sym < ARRAYELTS (lispsym)); + Lisp_Object v = builtin_lisp_symbol (sym); + Fput (v, Qx_frame_parameter, make_fixnum (i)); + } #ifdef HAVE_WINDOW_SYSTEM DEFVAR_LISP ("x-resource-name", Vx_resource_name, |