aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGerd Möllmann2024-10-21 18:32:04 +0200
committerGerd Möllmann2024-10-22 06:40:19 +0200
commit414de92a562e8912ffdc8ed2995e7ea10d05f13b (patch)
tree9058dd00922ed14319e0e49eb216fcad7ea5fdd6 /src
parent1854f2751e3f73e1e5f12f6de993b6357de1766b (diff)
downloademacs-414de92a562e8912ffdc8ed2995e7ea10d05f13b.tar.gz
emacs-414de92a562e8912ffdc8ed2995e7ea10d05f13b.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/alloc.c8
-rw-r--r--src/chartab.c2
-rw-r--r--src/dispextern.h40
-rw-r--r--src/dispnew.c1166
-rw-r--r--src/disptab.h12
-rw-r--r--src/frame.c452
-rw-r--r--src/frame.h84
-rw-r--r--src/keyboard.c2
-rw-r--r--src/minibuf.c6
-rw-r--r--src/nsfns.m4
-rw-r--r--src/nsterm.m4
-rw-r--r--src/scroll.c4
-rw-r--r--src/term.c266
-rw-r--r--src/termhooks.h3
-rw-r--r--src/terminal.c6
-rw-r--r--src/xdisp.c89
-rw-r--r--src/xfaces.c1
17 files changed, 1574 insertions, 575 deletions
diff --git a/src/alloc.c b/src/alloc.c
index 4fab0d54248..bbabd8c95e8 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -6853,9 +6853,11 @@ mark_glyph_matrix (struct glyph_matrix *matrix)
6853 struct glyph *end_glyph = glyph + row->used[area]; 6853 struct glyph *end_glyph = glyph + row->used[area];
6854 6854
6855 for (; glyph < end_glyph; ++glyph) 6855 for (; glyph < end_glyph; ++glyph)
6856 if (STRINGP (glyph->object) 6856 {
6857 && !string_marked_p (XSTRING (glyph->object))) 6857 if (STRINGP (glyph->object)
6858 mark_object (glyph->object); 6858 && !string_marked_p (XSTRING (glyph->object)))
6859 mark_object (glyph->object);
6860 }
6859 } 6861 }
6860 } 6862 }
6861} 6863}
diff --git a/src/chartab.c b/src/chartab.c
index 58bb1658504..76a40ca7cc4 100644
--- a/src/chartab.c
+++ b/src/chartab.c
@@ -122,8 +122,6 @@ the char-table has no extra slot. */)
122 else 122 else
123 { 123 {
124 CHECK_FIXNAT (n); 124 CHECK_FIXNAT (n);
125 if (XFIXNUM (n) > 10)
126 args_out_of_range (n, Qnil);
127 n_extras = XFIXNUM (n); 125 n_extras = XFIXNUM (n);
128 } 126 }
129 127
diff --git a/src/dispextern.h b/src/dispextern.h
index cc248a4472e..468aee8d1ba 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -482,6 +482,11 @@ struct glyph
482 continuation glyphs, or the overlay-arrow glyphs on TTYs. */ 482 continuation glyphs, or the overlay-arrow glyphs on TTYs. */
483 Lisp_Object object; 483 Lisp_Object object;
484 484
485 /* Frame on which the glyph was produced. The face_id of this glyph
486 refers to the face_cache of this frame. This is used on tty frames
487 only. */
488 struct frame *frame;
489
485 /* Width in pixels. */ 490 /* Width in pixels. */
486 short pixel_width; 491 short pixel_width;
487 492
@@ -626,10 +631,12 @@ struct glyph
626 631
627#define FONT_TYPE_UNKNOWN 0 632#define FONT_TYPE_UNKNOWN 0
628 633
629/* Is GLYPH a space? */ 634/* Is GLYPH a space in default face on frame FRAME? */
630 635
631#define CHAR_GLYPH_SPACE_P(GLYPH) \ 636# define CHAR_GLYPH_SPACE_P(FRAME, GLYPH) \
632 ((GLYPH).u.ch == SPACEGLYPH && (GLYPH).face_id == DEFAULT_FACE_ID) 637 ((GLYPH).u.ch == SPACEGLYPH \
638 && (GLYPH).face_id == DEFAULT_FACE_ID \
639 && (GLYPH).frame == (FRAME))
633 640
634/* Are glyph slices of glyphs *X and *Y equal? It assumes that both 641/* Are glyph slices of glyphs *X and *Y equal? It assumes that both
635 glyphs have the same type. 642 glyphs have the same type.
@@ -654,6 +661,7 @@ struct glyph
654 && (X)->u.val == (Y)->u.val \ 661 && (X)->u.val == (Y)->u.val \
655 && GLYPH_SLICE_EQUAL_P (X, Y) \ 662 && GLYPH_SLICE_EQUAL_P (X, Y) \
656 && (X)->face_id == (Y)->face_id \ 663 && (X)->face_id == (Y)->face_id \
664 && (X)->frame == (Y)->frame \
657 && (X)->padding_p == (Y)->padding_p \ 665 && (X)->padding_p == (Y)->padding_p \
658 && (X)->left_box_line_p == (Y)->left_box_line_p \ 666 && (X)->left_box_line_p == (Y)->left_box_line_p \
659 && (X)->right_box_line_p == (Y)->right_box_line_p \ 667 && (X)->right_box_line_p == (Y)->right_box_line_p \
@@ -665,16 +673,18 @@ struct glyph
665#define GLYPH_CHAR_AND_FACE_EQUAL_P(X, Y) \ 673#define GLYPH_CHAR_AND_FACE_EQUAL_P(X, Y) \
666 ((X)->u.ch == (Y)->u.ch \ 674 ((X)->u.ch == (Y)->u.ch \
667 && (X)->face_id == (Y)->face_id \ 675 && (X)->face_id == (Y)->face_id \
676 && (X)->frame == (Y)->frame \
668 && (X)->padding_p == (Y)->padding_p) 677 && (X)->padding_p == (Y)->padding_p)
669 678
670/* Fill a character glyph GLYPH. CODE, FACE_ID, PADDING_P correspond 679/* Fill a character glyph GLYPH. CODE, FACE_ID, PADDING_P correspond
671 to the bits defined for the typedef `GLYPH' in lisp.h. */ 680 to the bits defined for the typedef `GLYPH' in lisp.h. */
672 681
673#define SET_CHAR_GLYPH(GLYPH, CODE, FACE_ID, PADDING_P) \ 682#define SET_CHAR_GLYPH(FRAME, GLYPH, CODE, FACE_ID, PADDING_P) \
674 do \ 683 do \
675 { \ 684 { \
676 (GLYPH).u.ch = (CODE); \ 685 (GLYPH).u.ch = (CODE); \
677 (GLYPH).face_id = (FACE_ID); \ 686 (GLYPH).face_id = (FACE_ID); \
687 (GLYPH).frame = (FRAME); \
678 (GLYPH).padding_p = (PADDING_P); \ 688 (GLYPH).padding_p = (PADDING_P); \
679 } \ 689 } \
680 while (false) 690 while (false)
@@ -682,11 +692,9 @@ struct glyph
682/* Fill a character type glyph GLYPH from a glyph typedef FROM as 692/* Fill a character type glyph GLYPH from a glyph typedef FROM as
683 defined in lisp.h. */ 693 defined in lisp.h. */
684 694
685#define SET_CHAR_GLYPH_FROM_GLYPH(GLYPH, FROM) \ 695#define SET_CHAR_GLYPH_FROM_GLYPH(FRAME, GLYPH, FROM) \
686 SET_CHAR_GLYPH (GLYPH, \ 696 SET_CHAR_GLYPH (FRAME, GLYPH, GLYPH_CHAR (FROM), \
687 GLYPH_CHAR (FROM), \ 697 GLYPH_FACE (FROM), false)
688 GLYPH_FACE (FROM), \
689 false)
690 698
691/* Construct a glyph code from a character glyph GLYPH. If the 699/* Construct a glyph code from a character glyph GLYPH. If the
692 character is multibyte, return -1 as we can't use glyph table for a 700 character is multibyte, return -1 as we can't use glyph table for a
@@ -3805,7 +3813,7 @@ extern void adjust_frame_glyphs (struct frame *);
3805void free_glyphs (struct frame *); 3813void free_glyphs (struct frame *);
3806void free_window_matrices (struct window *); 3814void free_window_matrices (struct window *);
3807void check_glyph_memory (void); 3815void check_glyph_memory (void);
3808void mirrored_line_dance (struct glyph_matrix *, int, int, int *, char *); 3816void mirrored_line_dance (struct frame *f, int, int, int *, char *);
3809void clear_glyph_matrix (struct glyph_matrix *); 3817void clear_glyph_matrix (struct glyph_matrix *);
3810void clear_current_matrices (struct frame *f); 3818void clear_current_matrices (struct frame *f);
3811void clear_desired_matrices (struct frame *); 3819void clear_desired_matrices (struct frame *);
@@ -3829,7 +3837,7 @@ extern bool frame_size_change_delayed (struct frame *);
3829void init_display (void); 3837void init_display (void);
3830void syms_of_display (void); 3838void syms_of_display (void);
3831extern void spec_glyph_lookup_face (struct window *, GLYPH *); 3839extern void spec_glyph_lookup_face (struct window *, GLYPH *);
3832extern void fill_up_frame_row_with_spaces (struct glyph_row *, int); 3840extern void fill_up_frame_row_with_spaces (struct frame *, struct glyph_row *, int);
3833 3841
3834/* Defined in terminal.c. */ 3842/* Defined in terminal.c. */
3835 3843
@@ -3911,6 +3919,16 @@ extern void gui_redo_mouse_highlight (Display_Info *);
3911 3919
3912#endif /* HAVE_WINDOW_SYSTEM */ 3920#endif /* HAVE_WINDOW_SYSTEM */
3913 3921
3922struct frame *root_frame (struct frame *f);
3923Lisp_Object frames_in_reverse_z_order (struct frame *f, bool visible);
3924bool is_tty_frame (struct frame *f);
3925bool is_tty_child_frame (struct frame *f);
3926bool is_tty_root_frame (struct frame *f);
3927bool combine_updates (Lisp_Object root_frames, bool force_p, bool inhibit_id_p);
3928bool combine_updates_for_frame (struct frame *f, bool force_p, bool inhibit_id_p);
3929void tty_raise_lower_frame (struct frame *f, bool raise);
3930int max_child_z_order (struct frame *parent);
3931
3914INLINE_HEADER_END 3932INLINE_HEADER_END
3915 3933
3916#endif /* not DISPEXTERN_H_INCLUDED */ 3934#endif /* not DISPEXTERN_H_INCLUDED */
diff --git a/src/dispnew.c b/src/dispnew.c
index 1a243079e46..26181c36399 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -42,6 +42,8 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
42#include "tparam.h" 42#include "tparam.h"
43#include "xwidget.h" 43#include "xwidget.h"
44#include "pdumper.h" 44#include "pdumper.h"
45#include "disptab.h"
46#include "cm.h"
45 47
46#ifdef HAVE_ANDROID 48#ifdef HAVE_ANDROID
47#include "android.h" 49#include "android.h"
@@ -71,7 +73,7 @@ struct dim
71 73
72/* Function prototypes. */ 74/* Function prototypes. */
73 75
74static void update_frame_line (struct frame *, int, bool); 76static void write_row (struct frame *f, int vpos, bool updating_menu_p);
75static int required_matrix_height (struct window *); 77static int required_matrix_height (struct window *);
76static int required_matrix_width (struct window *); 78static int required_matrix_width (struct window *);
77static void increment_row_positions (struct glyph_row *, ptrdiff_t, ptrdiff_t); 79static void increment_row_positions (struct glyph_row *, ptrdiff_t, ptrdiff_t);
@@ -80,9 +82,9 @@ static void build_frame_matrix_from_window_tree (struct glyph_matrix *,
80static void build_frame_matrix_from_leaf_window (struct glyph_matrix *, 82static void build_frame_matrix_from_leaf_window (struct glyph_matrix *,
81 struct window *); 83 struct window *);
82static void adjust_decode_mode_spec_buffer (struct frame *); 84static void adjust_decode_mode_spec_buffer (struct frame *);
83static void fill_up_glyph_row_with_spaces (struct glyph_row *); 85static void fill_up_glyph_row_with_spaces (struct frame *, struct glyph_row *);
84static void clear_window_matrices (struct window *, bool); 86static void clear_window_matrices (struct window *, bool);
85static void fill_up_glyph_row_area_with_spaces (struct glyph_row *, int); 87static void fill_up_glyph_row_area_with_spaces (struct frame *, struct glyph_row *, int);
86static int scrolling_window (struct window *, int); 88static int scrolling_window (struct window *, int);
87static bool update_window_line (struct window *, int, bool *); 89static bool update_window_line (struct window *, int, bool *);
88static void mirror_make_current (struct window *, int); 90static void mirror_make_current (struct window *, int);
@@ -93,7 +95,7 @@ static void check_matrix_pointers (struct glyph_matrix *,
93static void mirror_line_dance (struct window *, int, int, int *, char *); 95static void mirror_line_dance (struct window *, int, int, int *, char *);
94static bool update_window_tree (struct window *, bool); 96static bool update_window_tree (struct window *, bool);
95static bool update_window (struct window *, bool); 97static bool update_window (struct window *, bool);
96static bool update_frame_1 (struct frame *, bool, bool, bool, bool); 98static bool write_matrix (struct frame *, bool, bool, bool, bool);
97static bool scrolling (struct frame *); 99static bool scrolling (struct frame *);
98static void set_window_cursor_after_update (struct window *); 100static void set_window_cursor_after_update (struct window *);
99static void adjust_frame_glyphs_for_window_redisplay (struct frame *); 101static void adjust_frame_glyphs_for_window_redisplay (struct frame *);
@@ -122,11 +124,6 @@ static int glyph_pool_count;
122 124
123#endif /* GLYPH_DEBUG and ENABLE_CHECKING */ 125#endif /* GLYPH_DEBUG and ENABLE_CHECKING */
124 126
125/* If non-null, the frame whose frame matrices are manipulated. If
126 null, window matrices are worked on. */
127
128static struct frame *frame_matrix_frame;
129
130/* Convert vpos and hpos from frame to window and vice versa. 127/* Convert vpos and hpos from frame to window and vice versa.
131 This may only be used for terminal frames. */ 128 This may only be used for terminal frames. */
132 129
@@ -1179,6 +1176,11 @@ line_hash_code (struct frame *f, struct glyph_row *row)
1179 { 1176 {
1180 int c = glyph->u.ch; 1177 int c = glyph->u.ch;
1181 int face_id = glyph->face_id; 1178 int face_id = glyph->face_id;
1179 /* Struct frame can move with igc, and so on. But we need
1180 something that takes different frames into account. Use the
1181 face_cache pointer for that which is malloc'd. */
1182 if (glyph->frame && glyph->frame != f)
1183 face_id += (ptrdiff_t) glyph->frame->face_cache;
1182 if (FRAME_MUST_WRITE_SPACES (f)) 1184 if (FRAME_MUST_WRITE_SPACES (f))
1183 c -= SPACEGLYPH; 1185 c -= SPACEGLYPH;
1184 hash = (((hash << 4) + (hash >> 24)) & 0x0fffffff) + c; 1186 hash = (((hash << 4) + (hash >> 24)) & 0x0fffffff) + c;
@@ -1213,7 +1215,7 @@ line_draw_cost (struct frame *f, struct glyph_matrix *matrix, int vpos)
1213 if (!FRAME_MUST_WRITE_SPACES (f)) 1215 if (!FRAME_MUST_WRITE_SPACES (f))
1214 { 1216 {
1215 /* Skip from the end over trailing spaces. */ 1217 /* Skip from the end over trailing spaces. */
1216 while (end > beg && CHAR_GLYPH_SPACE_P (*(end - 1))) 1218 while (end > beg && CHAR_GLYPH_SPACE_P (f, *(end - 1)))
1217 --end; 1219 --end;
1218 1220
1219 /* All blank line. */ 1221 /* All blank line. */
@@ -1221,7 +1223,7 @@ line_draw_cost (struct frame *f, struct glyph_matrix *matrix, int vpos)
1221 return 0; 1223 return 0;
1222 1224
1223 /* Skip over leading spaces. */ 1225 /* Skip over leading spaces. */
1224 while (CHAR_GLYPH_SPACE_P (*beg)) 1226 while (CHAR_GLYPH_SPACE_P (f, *beg))
1225 ++beg; 1227 ++beg;
1226 } 1228 }
1227 1229
@@ -2558,6 +2560,7 @@ build_frame_matrix_from_leaf_window (struct glyph_matrix *frame_matrix, struct w
2558 int window_y, frame_y; 2560 int window_y, frame_y;
2559 /* If non-zero, a glyph to insert at the right border of W. */ 2561 /* If non-zero, a glyph to insert at the right border of W. */
2560 GLYPH right_border_glyph; 2562 GLYPH right_border_glyph;
2563 struct frame *f = XFRAME (w->frame);
2561 2564
2562 SET_GLYPH_FROM_CHAR (right_border_glyph, 0); 2565 SET_GLYPH_FROM_CHAR (right_border_glyph, 0);
2563 2566
@@ -2599,10 +2602,10 @@ build_frame_matrix_from_leaf_window (struct glyph_matrix *frame_matrix, struct w
2599 2602
2600 /* Fill up the frame row with spaces up to the left margin of the 2603 /* Fill up the frame row with spaces up to the left margin of the
2601 window row. */ 2604 window row. */
2602 fill_up_frame_row_with_spaces (frame_row, window_matrix->matrix_x); 2605 fill_up_frame_row_with_spaces (f, frame_row, window_matrix->matrix_x);
2603 2606
2604 /* Fill up areas in the window matrix row with spaces. */ 2607 /* Fill up areas in the window matrix row with spaces. */
2605 fill_up_glyph_row_with_spaces (window_row); 2608 fill_up_glyph_row_with_spaces (f, window_row);
2606 2609
2607 /* If only part of W's desired matrix has been built, and 2610 /* If only part of W's desired matrix has been built, and
2608 window_row wasn't displayed, use the corresponding current 2611 window_row wasn't displayed, use the corresponding current
@@ -2638,7 +2641,7 @@ build_frame_matrix_from_leaf_window (struct glyph_matrix *frame_matrix, struct w
2638 glyph with the vertical border glyph. */ 2641 glyph with the vertical border glyph. */
2639 eassert (border->type == CHAR_GLYPH); 2642 eassert (border->type == CHAR_GLYPH);
2640 border->type = CHAR_GLYPH; 2643 border->type = CHAR_GLYPH;
2641 SET_CHAR_GLYPH_FROM_GLYPH (*border, right_border_glyph); 2644 SET_CHAR_GLYPH_FROM_GLYPH (f, *border, right_border_glyph);
2642 } 2645 }
2643 2646
2644#ifdef GLYPH_DEBUG 2647#ifdef GLYPH_DEBUG
@@ -2701,11 +2704,11 @@ spec_glyph_lookup_face (struct window *w, GLYPH *glyph)
2701 To be called for frame-based redisplay, only. */ 2704 To be called for frame-based redisplay, only. */
2702 2705
2703static void 2706static void
2704fill_up_glyph_row_with_spaces (struct glyph_row *row) 2707fill_up_glyph_row_with_spaces (struct frame *f, struct glyph_row *row)
2705{ 2708{
2706 fill_up_glyph_row_area_with_spaces (row, LEFT_MARGIN_AREA); 2709 fill_up_glyph_row_area_with_spaces (f, row, LEFT_MARGIN_AREA);
2707 fill_up_glyph_row_area_with_spaces (row, TEXT_AREA); 2710 fill_up_glyph_row_area_with_spaces (f, row, TEXT_AREA);
2708 fill_up_glyph_row_area_with_spaces (row, RIGHT_MARGIN_AREA); 2711 fill_up_glyph_row_area_with_spaces (f, row, RIGHT_MARGIN_AREA);
2709} 2712}
2710 2713
2711 2714
@@ -2713,15 +2716,19 @@ fill_up_glyph_row_with_spaces (struct glyph_row *row)
2713 frame-based redisplay only. */ 2716 frame-based redisplay only. */
2714 2717
2715static void 2718static void
2716fill_up_glyph_row_area_with_spaces (struct glyph_row *row, int area) 2719fill_up_glyph_row_area_with_spaces (struct frame *f, struct glyph_row *row,
2720 int area)
2717{ 2721{
2718 if (row->glyphs[area] < row->glyphs[area + 1]) 2722 if (row->glyphs[area] < row->glyphs[area + 1])
2719 { 2723 {
2720 struct glyph *end = row->glyphs[area + 1]; 2724 struct glyph *end = row->glyphs[area + 1];
2721 struct glyph *text = row->glyphs[area] + row->used[area]; 2725 struct glyph *text = row->glyphs[area] + row->used[area];
2722 2726
2723 while (text < end) 2727 for (; text < end; ++text)
2724 *text++ = space_glyph; 2728 {
2729 *text = space_glyph;
2730 text->frame = f;
2731 }
2725 row->used[area] = text - row->glyphs[area]; 2732 row->used[area] = text - row->glyphs[area];
2726 } 2733 }
2727} 2734}
@@ -2731,13 +2738,16 @@ fill_up_glyph_row_area_with_spaces (struct glyph_row *row, int area)
2731 reached. In frame matrices only one area, TEXT_AREA, is used. */ 2738 reached. In frame matrices only one area, TEXT_AREA, is used. */
2732 2739
2733void 2740void
2734fill_up_frame_row_with_spaces (struct glyph_row *row, int upto) 2741fill_up_frame_row_with_spaces (struct frame *f, struct glyph_row *row, int upto)
2735{ 2742{
2736 int i = row->used[TEXT_AREA]; 2743 int i = row->used[TEXT_AREA];
2737 struct glyph *glyph = row->glyphs[TEXT_AREA]; 2744 struct glyph *glyph = row->glyphs[TEXT_AREA];
2738 2745
2739 while (i < upto) 2746 for (; i < upto; ++i)
2740 glyph[i++] = space_glyph; 2747 {
2748 glyph[i] = space_glyph;
2749 glyph[i].frame = f;
2750 }
2741 2751
2742 row->used[TEXT_AREA] = i; 2752 row->used[TEXT_AREA] = i;
2743} 2753}
@@ -2748,17 +2758,6 @@ fill_up_frame_row_with_spaces (struct glyph_row *row, int upto)
2748 Mirroring operations on frame matrices in window matrices 2758 Mirroring operations on frame matrices in window matrices
2749 **********************************************************************/ 2759 **********************************************************************/
2750 2760
2751/* Set frame being updated via frame-based redisplay to F. This
2752 function must be called before updates to make explicit that we are
2753 working on frame matrices or not. */
2754
2755static void
2756set_frame_matrix_frame (struct frame *f)
2757{
2758 frame_matrix_frame = f;
2759}
2760
2761
2762/* Make sure glyph row ROW in CURRENT_MATRIX is up to date. 2761/* Make sure glyph row ROW in CURRENT_MATRIX is up to date.
2763 DESIRED_MATRIX is the desired matrix corresponding to 2762 DESIRED_MATRIX is the desired matrix corresponding to
2764 CURRENT_MATRIX. The update is done by exchanging glyph pointers 2763 CURRENT_MATRIX. The update is done by exchanging glyph pointers
@@ -2768,9 +2767,10 @@ set_frame_matrix_frame (struct frame *f)
2768 operations in window matrices of frame_matrix_frame. */ 2767 operations in window matrices of frame_matrix_frame. */
2769 2768
2770static void 2769static void
2771make_current (struct glyph_matrix *desired_matrix, 2770make_current (struct frame *f, struct window *w, int row)
2772 struct glyph_matrix *current_matrix, int row)
2773{ 2771{
2772 struct glyph_matrix *desired_matrix = f ? f->desired_matrix : w->desired_matrix;
2773 struct glyph_matrix *current_matrix = f ? f->current_matrix : w->current_matrix;
2774 struct glyph_row *current_row = MATRIX_ROW (current_matrix, row); 2774 struct glyph_row *current_row = MATRIX_ROW (current_matrix, row);
2775 struct glyph_row *desired_row = MATRIX_ROW (desired_matrix, row); 2775 struct glyph_row *desired_row = MATRIX_ROW (desired_matrix, row);
2776 bool mouse_face_p = current_row->mouse_face_p; 2776 bool mouse_face_p = current_row->mouse_face_p;
@@ -2797,8 +2797,8 @@ make_current (struct glyph_matrix *desired_matrix,
2797 2797
2798 /* If we are called on frame matrices, perform analogous operations 2798 /* If we are called on frame matrices, perform analogous operations
2799 for window matrices. */ 2799 for window matrices. */
2800 if (frame_matrix_frame) 2800 if (f)
2801 mirror_make_current (XWINDOW (frame_matrix_frame->root_window), row); 2801 mirror_make_current (XWINDOW (f->root_window), row);
2802} 2802}
2803 2803
2804 2804
@@ -2862,9 +2862,11 @@ mirror_make_current (struct window *w, int frame_row)
2862 This function is called from do_scrolling and do_direct_scrolling. */ 2862 This function is called from do_scrolling and do_direct_scrolling. */
2863 2863
2864void 2864void
2865mirrored_line_dance (struct glyph_matrix *matrix, int unchanged_at_top, int nlines, 2865mirrored_line_dance (struct frame *f, int unchanged_at_top, int nlines,
2866 int *copy_from, char *retained_p) 2866 int *copy_from, char *retained_p)
2867{ 2867{
2868 struct glyph_matrix *matrix = f->current_matrix;
2869
2868 /* A copy of original rows. */ 2870 /* A copy of original rows. */
2869 struct glyph_row *old_rows; 2871 struct glyph_row *old_rows;
2870 2872
@@ -2894,9 +2896,8 @@ mirrored_line_dance (struct glyph_matrix *matrix, int unchanged_at_top, int nlin
2894 } 2896 }
2895 2897
2896 /* Do the same for window matrices, if MATRIX is a frame matrix. */ 2898 /* Do the same for window matrices, if MATRIX is a frame matrix. */
2897 if (frame_matrix_frame) 2899 mirror_line_dance (XWINDOW (f->root_window),
2898 mirror_line_dance (XWINDOW (frame_matrix_frame->root_window), 2900 unchanged_at_top, nlines, copy_from, retained_p);
2899 unchanged_at_top, nlines, copy_from, retained_p);
2900 2901
2901 SAFE_FREE (); 2902 SAFE_FREE ();
2902} 2903}
@@ -3194,7 +3195,10 @@ redraw_frame (struct frame *f)
3194 future. */ 3195 future. */
3195 SET_FRAME_GARBAGED (f); 3196 SET_FRAME_GARBAGED (f);
3196 3197
3197 clear_frame (f); 3198 /* Clear_frame is actually a "clear_terminal", i.e.
3199 is clears the entire screen. */
3200 if (!FRAME_PARENT_FRAME (f))
3201 clear_frame (f);
3198 clear_current_matrices (f); 3202 clear_current_matrices (f);
3199 update_end (f); 3203 update_end (f);
3200 fset_redisplay (f); 3204 fset_redisplay (f);
@@ -3229,145 +3233,676 @@ DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
3229 return Qnil; 3233 return Qnil;
3230} 3234}
3231 3235
3232
3233 3236
3234/*********************************************************************** 3237/**********************************************************************
3235 Frame Update 3238 TTY Child Frames
3236 ***********************************************************************/ 3239 **********************************************************************/
3237 3240
3238/* Update frame F based on the data in desired matrices. 3241/* The new thing that child frames on ttys provide is that frames on a
3242 tty no longer always occupy the whole terminal. They can overlap
3243 instead.
3239 3244
3240 If FORCE_P, don't let redisplay be stopped by detecting pending input. 3245 Let a "root" frame be a frame that has no parent frame. Such root
3241 If INHIBIT_HAIRY_ID_P, don't try scrolling. 3246 frames we require to be the size of the terminal screen. The current
3247 glyph matrix of a root frame of a termimnal represents what is on the
3248 screen. The desired matrix of a root frame represents what should be
3249 one the screen.
3242 3250
3243 Value is true if redisplay was stopped due to pending input. */ 3251 Building the desired matrix of root frame proceeds by
3244 3252
3245bool 3253 - building the desired matrix of the root frame itself which is
3246update_frame (struct frame *f, bool force_p, bool inhibit_hairy_id_p) 3254 the bottommost frame in z-order,
3255 - building desired matrices of child frames in z-order, topmost last,
3256 - copying the desired glyphs from child frames to the desired glyphs
3257 of the root frame
3258
3259 Updating the screen is then done using root frame matrices as it was
3260 before child frames were introduced. Child frame current matrices are
3261 updated by copying glyph contents of the current matrix of the root
3262 frames to the current matrices of child frames. This imnplicitly
3263 also updates the glyph contents of their windows' current matrices. */
3264
3265struct rect
3247{ 3266{
3248 /* True means display has been paused because of pending input. */ 3267 int x, y, w, h;
3249 bool paused_p; 3268};
3250 struct window *root_window = XWINDOW (f->root_window);
3251 3269
3252 if (redisplay_dont_pause) 3270/* Compute the intersection of R1 and R2 in R. Value is true if R1 and
3253 force_p = true; 3271 R2 intersect, false otherwise. */
3254 else if (!force_p && detect_input_pending_ignore_squeezables ()) 3272
3273static bool
3274rect_intersect (struct rect *r, struct rect r1, struct rect r2)
3275{
3276 int x1 = max (r1.x, r2.x);
3277 int x2 = min (r1.x + r1.w, r2.x + r2.w);
3278 if (x2 < x1)
3279 return false;
3280 int y1 = max (r1.y, r2.y);
3281 int y2 = min (r1.y + r1.h, r2.y + r2.h);
3282 if (y2 < y1)
3283 return false;
3284 *r = (struct rect) { .x = x1, .y = y1, .w = x2 - x1, .h = y2 - y1 };
3285 return true;
3286}
3287
3288/* Return the absolute position of frame F in *X and *Y. */
3289
3290static void
3291frame_pos_abs (struct frame *f, int *x, int *y)
3292{
3293 *x = *y = 0;
3294 for (; f; f = FRAME_PARENT_FRAME (f))
3255 { 3295 {
3256 paused_p = true; 3296 *x += f->left_pos;
3257 goto do_pause; 3297 *y += f->top_pos;
3258 } 3298 }
3299}
3259 3300
3260 if (FRAME_WINDOW_P (f)) 3301/* Return the rectangle frame F occupies. X and Y are in absolute coordinates. */
3302
3303static struct rect
3304frame_rect_abs (struct frame *f)
3305{
3306 int x, y;
3307 frame_pos_abs (f, &x, &y);
3308 return (struct rect) { x, y, f->total_cols, f->total_lines };
3309}
3310
3311/* Return the root frame of frame F. Follow the parent_frame chain until
3312 we reach a frame that has no parent. That is the root frame. Note
3313 that the root of a root frame is itself. */
3314
3315struct frame *
3316root_frame (struct frame *f)
3317{
3318 while (FRAME_PARENT_FRAME (f))
3319 f = FRAME_PARENT_FRAME (f);
3320 return f;
3321}
3322
3323int
3324max_child_z_order (struct frame *parent)
3325{
3326 Lisp_Object tail, frame;
3327 int z_order = 0;
3328 FOR_EACH_FRAME (tail, frame)
3261 { 3329 {
3262 /* We are working on window matrix basis. All windows whose 3330 struct frame *f = XFRAME (frame);
3263 flag must_be_updated_p is set have to be updated. */ 3331 if (FRAME_PARENT_FRAME (f) == parent)
3332 z_order = max (z_order, f->z_order);
3333 }
3334 return z_order;
3335}
3264 3336
3265 /* Record that we are not working on frame matrices. */ 3337/* Return true if F1 is an ancestor of F2. */
3266 set_frame_matrix_frame (NULL);
3267 3338
3268 /* Update all windows in the window tree of F, maybe stopping 3339static bool
3269 when pending input is detected. */ 3340is_frame_ancestor (struct frame *f1, struct frame *f2)
3270 update_begin (f); 3341{
3342 for (struct frame *f = FRAME_PARENT_FRAME (f2); f; f = FRAME_PARENT_FRAME (f))
3343 if (f == f1)
3344 return true;
3345 return false;
3346}
3271 3347
3272#if defined HAVE_WINDOW_SYSTEM && !defined HAVE_EXT_MENU_BAR 3348/* Return a list of all frames having root frame ROOT.
3273 /* Update the menu bar on X frames that don't have toolkit 3349 If VISIBLE_ONLY is true, return only visible frames. */
3274 support. */
3275 if (WINDOWP (f->menu_bar_window))
3276 update_window (XWINDOW (f->menu_bar_window), true);
3277#endif
3278 3350
3279#if defined (HAVE_WINDOW_SYSTEM) 3351static Lisp_Object
3280 /* Update the tab-bar window, if present. */ 3352frames_with_root (struct frame *root, bool visible_only)
3281 if (WINDOWP (f->tab_bar_window)) 3353{
3354 Lisp_Object list = Qnil;
3355 Lisp_Object tail, frame;
3356 FOR_EACH_FRAME (tail, frame)
3357 {
3358 struct frame *f = XFRAME (frame);
3359 if (root_frame (f) == root
3360 && (!visible_only || FRAME_VISIBLE_P (f)))
3361 list = Fcons (frame, list);
3362 }
3363 return list;
3364}
3365
3366/* Return a list of frames having parent frame PARENT.
3367 If VISIBLE_ONLY is true, return only visible frames. */
3368
3369static Lisp_Object
3370frames_with_parent (struct frame *parent, bool visible_only)
3371{
3372 Lisp_Object list = Qnil;
3373 Lisp_Object tail, frame;
3374 FOR_EACH_FRAME (tail, frame)
3375 {
3376 struct frame *f = XFRAME (frame);
3377 if (FRAME_PARENT_FRAME (f) == parent
3378 && (!visible_only || FRAME_VISIBLE_P (f)))
3379 list = Fcons (frame, list);
3380 }
3381 return list;
3382}
3383
3384/* Compare frames F1 and F2 for z-order. Value is like strcmp. */
3385
3386static int
3387frame_z_order_cmp (struct frame *f1, struct frame *f2)
3388{
3389 if (f1 == f2)
3390 return 0;
3391 if (is_frame_ancestor (f1, f2))
3392 return -1;
3393 if (is_frame_ancestor (f2, f1))
3394 return 1;
3395 return f1->z_order - f2->z_order;
3396}
3397
3398DEFUN ("frame--z-order-lessp", Fframe__z_order_lessp, Sframe__z_order_lessp,
3399 2, 2, 0, doc: /* Internal frame sorting function A < B. */)
3400 (Lisp_Object a, Lisp_Object b)
3401{
3402 eassert (FRAMEP (a) && FRAMEP (b));
3403 return frame_z_order_cmp (XFRAME (a), XFRAME (b)) < 0 ? Qt : Qnil;
3404}
3405
3406/* Return a z-order list of frames with the same root as F. The list
3407 is ordered topmost frame last. Note that this list contains
3408 the root frame of F itself as first element. */
3409
3410Lisp_Object
3411frames_in_reverse_z_order (struct frame *f, bool visible_only)
3412{
3413 struct frame *root = root_frame (f);
3414 Lisp_Object frames = frames_with_root (root, visible_only);
3415 frames = CALLN (Fsort, frames, QClessp, Qframe__z_order_lessp);
3416 eassert (FRAMEP (XCAR (frames)));
3417 eassert (XFRAME (XCAR (frames)) == root);
3418 return frames;
3419}
3420
3421/* Raise of lower frame F in z-order. If RAISE is true, raise F, else
3422 lower f. */
3423
3424void
3425tty_raise_lower_frame (struct frame *f, bool raise)
3426{
3427 struct frame *parent = FRAME_PARENT_FRAME (f);
3428 if (parent == NULL)
3429 return;
3430
3431 Lisp_Object siblings = frames_with_parent (parent, false);
3432 siblings = CALLN (Fsort, siblings, QClessp, Qframe__z_order_lessp);
3433
3434 int i = 0;
3435 for (Lisp_Object tail = siblings; CONSP (tail); tail = XCDR (tail))
3436 {
3437 struct frame *child = XFRAME (XCAR (tail));
3438 if (child != f)
3439 child->z_order = i++;
3440 }
3441 f->z_order = raise ? i : 0;
3442}
3443
3444/* Return true if frame F is a tty frame. */
3445
3446bool
3447is_tty_frame (struct frame *f)
3448{
3449 return FRAME_TERMCAP_P (f);
3450}
3451
3452/* Return true if frame F is a tty child frame. */
3453
3454bool
3455is_tty_child_frame (struct frame *f)
3456{
3457 return FRAME_PARENT_FRAME (f) && is_tty_frame (f);
3458}
3459
3460/* Return true if frame F is a tty root frame. */
3461
3462bool
3463is_tty_root_frame (struct frame *f)
3464{
3465 return !FRAME_PARENT_FRAME (f) && is_tty_frame (f);
3466}
3467
3468/* Return the index of the first enabled row in MATRIX, or -1 if there
3469 is none. */
3470
3471static int
3472first_enabled_row (struct glyph_matrix *matrix)
3473{
3474 for (int i = 0; i < matrix->nrows; ++i)
3475 if (MATRIX_ROW_ENABLED_P (matrix, i))
3476 return i;
3477 return -1;
3478}
3479
3480/* On tty frame F, make desired matrix current, without writing
3481 to the terminal. */
3482
3483static void
3484make_matrix_current (struct frame *f)
3485{
3486 int first_row = first_enabled_row (f->desired_matrix);
3487 if (first_row >= 0)
3488 for (int i = first_row; i < f->desired_matrix->nrows; ++i)
3489 if (MATRIX_ROW_ENABLED_P (f->desired_matrix, i))
3490 make_current (f, NULL, i);
3491}
3492
3493/* Prepare ROOT's desired row at index Y for copying child
3494 frame contents to it. */
3495
3496static struct glyph_row *
3497prepare_desired_root_row (struct frame *root, int y)
3498{
3499 /* Start with the root's desired matrix row. If that hasn't
3500 been redisplayed, copy from the root's current matrix. */
3501 struct glyph_row *root_row = MATRIX_ROW (root->desired_matrix, y);
3502 if (!root_row->enabled_p)
3503 {
3504 struct glyph_row *from = MATRIX_ROW (root->current_matrix, y);
3505 memcpy (root_row->glyphs[0], from->glyphs[0],
3506 root->current_matrix->matrix_w * sizeof (struct glyph));
3507 root_row->enabled_p = true;
3508 }
3509 return root_row;
3510}
3511
3512/* Produce glyphs for box character BOX in ROW. X ist the position in ROW
3513 where to start producing glyphs. N is the number of glyphs to produce.
3514 CHILD is the frame to use for the face of the glyphs. */
3515
3516static void
3517produce_box_glyphs (enum box box, struct glyph_row *row, int x, int n,
3518 struct frame *child)
3519{
3520 int dflt;
3521 switch (box)
3522 {
3523 case BOX_VERTICAL:
3524 dflt = '|';
3525 break;
3526 case BOX_HORIZONTAL:
3527 dflt = '-';
3528 break;
3529 case BOX_DOWN_RIGHT:
3530 case BOX_DOWN_LEFT:
3531 case BOX_UP_RIGHT:
3532 case BOX_UP_LEFT:
3533 dflt = '+';
3534 break;
3535 }
3536
3537 // FIXME/tty some face for the border.
3538 int face_id = BORDER_FACE_ID;
3539 GLYPH g;
3540 SET_GLYPH (g, dflt, face_id);
3541
3542 if (DISP_TABLE_P (Vstandard_display_table))
3543 {
3544 struct Lisp_Char_Table *dp = XCHAR_TABLE (Vstandard_display_table);
3545 Lisp_Object gc = dp->extras[box];
3546 if (GLYPH_CODE_P (gc))
3282 { 3547 {
3283 struct window *w = XWINDOW (f->tab_bar_window); 3548 SET_GLYPH_FROM_GLYPH_CODE (g, gc);
3549 /* Sorry, but I really don't care if the glyph has a face :-). */
3550 }
3551 }
3284 3552
3285 /* Update tab-bar window. */ 3553 struct glyph *glyph = row->glyphs[0] + x;
3286 if (w->must_be_updated_p) 3554 for (int i = 0; i < n; ++i, ++glyph)
3287 { 3555 {
3288 Lisp_Object tem; 3556 glyph->type = CHAR_GLYPH;
3557 glyph->u.ch = GLYPH_CHAR (g);
3558 glyph->charpos = -1;
3559 glyph->pixel_width = 1;
3560 glyph->multibyte_p = 1;
3561 glyph->face_id = GLYPH_FACE (g);
3562 glyph->frame = child;
3563 glyph->multibyte_p = 1;
3564 glyph->object = Qnil;
3565 }
3566}
3289 3567
3290 update_window (w, true); 3568/* Produce box glyphs LEFT and RIGHT in ROOT_ROW. X and W are the start
3291 w->must_be_updated_p = false; 3569 and width of a range in ROOT_ROW before and after which to put the
3570 box glyphs, if they fit. ROOT and CHILD are root and child frame we
3571 are working on. ROOT is the root frame whose matrix dimensions
3572 determines if the box glyphs fit. CHILD is the frame whose faces to
3573 use for the box glyphs. */
3292 3574
3293 /* Swap tab-bar strings. We swap because we want to 3575static void
3294 reuse strings. */ 3576produce_box_sides (enum box left, enum box right, struct glyph_row *root_row, int x,
3295 tem = f->current_tab_bar_string; 3577 int w, struct frame *root, struct frame *child)
3296 fset_current_tab_bar_string (f, f->desired_tab_bar_string); 3578{
3297 fset_desired_tab_bar_string (f, tem); 3579 if (x > 0)
3298 } 3580 produce_box_glyphs (left, root_row, x - 1, 1, child);
3581 if (x + w < root->desired_matrix->matrix_w)
3582 produce_box_glyphs (right, root_row, x + w, 1, child);
3583}
3584
3585static void
3586produce_box_line (struct frame *root, struct frame *child, int x, int y, int w,
3587 bool first)
3588{
3589 struct glyph_row *root_row = prepare_desired_root_row (root, y);
3590 if (first)
3591 produce_box_sides (BOX_DOWN_RIGHT, BOX_DOWN_LEFT, root_row, x, w, root, child);
3592 else
3593 produce_box_sides (BOX_UP_RIGHT, BOX_UP_LEFT, root_row, x, w, root, child);
3594 produce_box_glyphs (BOX_HORIZONTAL, root_row, x, w, child);
3595 root_row->hash = row_hash (root_row);
3596}
3597
3598/* Copy to ROOT's desired matrix what we need from CHILD. */
3599
3600static void
3601copy_child_glyphs (struct frame *root, struct frame *child)
3602{
3603 eassert (!FRAME_PARENT_FRAME (root));
3604 eassert (is_frame_ancestor (root, child));
3605
3606 /* Determine the intersection of the child frame rectangle with
3607 the root frame. This is basically clipping the child frame to
3608 the root frame rectangle. */
3609 struct rect r;
3610 if (!rect_intersect (&r, frame_rect_abs (root), frame_rect_abs (child)))
3611 return;
3612
3613 /* Build CHILD's current matrix which we need to copy from it. */
3614 make_matrix_current (child);
3615
3616 /* Draw borders around the child frame. */
3617 if (!FRAME_UNDECORATED (child))
3618 {
3619 /* Horizontal line above. */
3620 if (r.y > 0)
3621 produce_box_line (root, child, r.x, r.y - 1, r.w, true);
3622
3623 for (int y = r.y; y < r.y + r.h; ++y)
3624 {
3625 struct glyph_row *root_row = prepare_desired_root_row (root, y);
3626 produce_box_sides (BOX_VERTICAL, BOX_VERTICAL, root_row, r.x, r.w,
3627 root, child);
3299 } 3628 }
3629
3630 /* Horizontal line below */
3631 if (r.y + r.h < root->desired_matrix->matrix_h)
3632 produce_box_line (root, child, r.x, r.y + r.h, r.w, false);
3633 }
3634
3635 /* First visible row/col, relative to the child frame. */
3636 int child_x = child->left_pos < 0 ? - child->left_pos : 0;
3637 int child_y = child->top_pos < 0 ? - child->top_pos : 0;
3638
3639 /* For all rows in the intersection, copy glyphs from the child's
3640 current matrix to the root's desired matrix, enabling those
3641 rows if they aren't already. */
3642 for (int y = r.y; y < r.y + r.h; ++y, ++child_y)
3643 {
3644 struct glyph_row *root_row = prepare_desired_root_row (root, y);
3645
3646 /* Copy what's visible from the child's current row. */
3647 struct glyph_row *child_row = MATRIX_ROW (child->current_matrix, child_y);
3648 memcpy (root_row->glyphs[0] + r.x, child_row->glyphs[0] + child_x,
3649 r.w * sizeof (struct glyph));
3650
3651 /* Compute a new hash since we changed glyphs. */
3652 root_row->hash = row_hash (root_row);
3653 }
3654}
3655
3656/***********************************************************************
3657 Frame Update
3658 ***********************************************************************/
3659
3660/* Update the menu bar on X frames that don't have toolkit
3661 support. */
3662
3663static void
3664update_menu_bar (struct frame *f)
3665{
3666#if defined HAVE_WINDOW_SYSTEM && !defined HAVE_EXT_MENU_BAR
3667 if (WINDOWP (f->menu_bar_window))
3668 update_window (XWINDOW (f->menu_bar_window), true);
3300#endif 3669#endif
3670}
3301 3671
3302#if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_TOOL_BAR) 3672#ifdef HAVE_WINDOW_SYSTEM
3303 /* Update the tool-bar window, if present. */ 3673static void
3304 if (WINDOWP (f->tool_bar_window)) 3674update_bar_window (Lisp_Object window, Lisp_Object *current,
3675 Lisp_Object *desired)
3676{
3677 if (WINDOWP (window))
3678 {
3679 struct window *w = XWINDOW (window);
3680 if (w->must_be_updated_p)
3305 { 3681 {
3306 struct window *w = XWINDOW (f->tool_bar_window); 3682 update_window (w, true);
3683 w->must_be_updated_p = false;
3684 Lisp_Object tem = *current;
3685 *current = *desired;
3686 *desired = tem;
3687 }
3688 }
3689}
3690#endif
3307 3691
3308 /* Update tool-bar window. */ 3692/* Update the tab-bar window of frame F, if present. */
3309 if (w->must_be_updated_p)
3310 {
3311 Lisp_Object tem;
3312 3693
3313 update_window (w, true); 3694static void
3314 w->must_be_updated_p = false; 3695update_tab_bar (struct frame *f)
3696{
3697#if defined(HAVE_WINDOW_SYSTEM)
3698 update_bar_window (f->tab_bar_window, &f->current_tab_bar_string,
3699 &f->desired_tab_bar_string);
3700#endif
3701}
3315 3702
3316 /* Swap tool-bar strings. We swap because we want to 3703static void
3317 reuse strings. */ 3704update_tool_bar (struct frame *f)
3318 tem = f->current_tool_bar_string; 3705{
3319 fset_current_tool_bar_string (f, f->desired_tool_bar_string); 3706#if defined(HAVE_WINDOW_SYSTEM) && !defined(HAVE_EXT_TOOL_BAR)
3320 fset_desired_tool_bar_string (f, tem); 3707 update_bar_window (f->tool_bar_window, &f->current_tool_bar_string,
3321 } 3708 &f->desired_tool_bar_string);
3322 }
3323#endif 3709#endif
3710}
3324 3711
3325 /* Update windows. */ 3712static bool
3326 paused_p = update_window_tree (root_window, force_p); 3713update_window_frame (struct frame *f, bool force_p)
3327 update_end (f); 3714{
3328 } 3715 eassert (FRAME_WINDOW_P (f));
3329 else 3716 update_begin (f);
3717 update_menu_bar (f);
3718 update_tab_bar (f);
3719 update_tool_bar (f);
3720 struct window *root_window = XWINDOW (f->root_window);
3721 bool paused_p = update_window_tree (root_window, force_p);
3722 update_end (f);
3723 set_window_update_flags (root_window, false);
3724 return paused_p;
3725}
3726
3727static bool
3728update_initial_frame (struct frame *f, bool force_p)
3729{
3730 build_frame_matrix (f);
3731 struct window *root_window = XWINDOW (f->root_window);
3732 set_window_update_flags (root_window, false);
3733 return false;
3734}
3735
3736static void
3737flush_terminal (struct frame *f)
3738{
3739 if (FRAME_TTY (f)->termscript)
3740 fflush (FRAME_TTY (f)->termscript);
3741 fflush (FRAME_TTY (f)->output);
3742}
3743
3744static bool
3745update_tty_frame (struct frame *f, bool force_p)
3746{
3747 build_frame_matrix (f);
3748 return false;
3749}
3750
3751static void
3752abs_cursor_pos (struct frame *f, int *x, int *y)
3753{
3754 frame_pos_abs (f, x, y);
3755 struct window *w = XWINDOW (f->selected_window);
3756 *x += w->cursor.x;
3757 *y += w->cursor.y;
3758}
3759
3760/* Is the terminal cursor of frame F obscured by a child frame? */
3761
3762static bool
3763is_cursor_obscured (void)
3764{
3765 int x, y;
3766 abs_cursor_pos (SELECTED_FRAME (), &x, &y);
3767 struct frame *root = root_frame (SELECTED_FRAME ());
3768 struct glyph_row *cursor_row = MATRIX_ROW (root->current_matrix, y);
3769 eassert (x < root->current_matrix->matrix_w);
3770 struct glyph *cursor_glyph = cursor_row->glyphs[0] + x;
3771 return cursor_glyph->frame != SELECTED_FRAME ();
3772}
3773
3774/* Decide where to show the cursor, and if to hide it or not.
3775
3776 This works very well for Vertico-Posframe, Transient-Posframe and
3777 Corfu, but it's debatable if it's the right thing for a general use
3778 of child frames of all sorts, nested and so on. But it is also debatable
3779 if that's a realistic use case from my POV. */
3780
3781static void
3782terminal_cursor_magic (struct frame *root, struct frame *topmost_child)
3783{
3784 /* By default, prevent the cursor "shining through" child frames. */
3785 if (is_cursor_obscured ())
3786 tty_hide_cursor (FRAME_TTY (root));
3787
3788 /* If the terminal cursor is not in the topmost child, the topmost
3789 child's tty-cursor-if-topmost determines what to do. If it is
3790 non-nil, display the cursor in this "non-selected" topmost child
3791 frame to compensate for the fact that we can't display a
3792 non-selected cursor like on a window system frame. */
3793 if (topmost_child != SELECTED_FRAME ())
3330 { 3794 {
3331 /* We are working on frame matrix basis. Set the frame on whose 3795 Lisp_Object frame;
3332 frame matrix we operate. */ 3796 XSETFRAME (frame, topmost_child);
3333 set_frame_matrix_frame (f);
3334 3797
3335 /* Build F's desired matrix from window matrices. */ 3798 Lisp_Object cursor = Fframe_parameter (frame, Qtty_non_selected_cursor);
3336 build_frame_matrix (f); 3799 if (!NILP (cursor))
3800 {
3801 int x, y;
3802 abs_cursor_pos (topmost_child, &x, &y);
3803 cursor_to (root, y, x);
3804 tty_show_cursor (FRAME_TTY (topmost_child));
3805 }
3806 }
3807}
3337 3808
3338 /* Update the display. */ 3809bool
3339 if (FRAME_INITIAL_P (f)) 3810combine_updates_for_frame (struct frame *f, bool force_p, bool inhibit_scrolling)
3340 /* No actual display to update so the "update" is a nop and 3811{
3341 obviously isn't interrupted by pending input. */ 3812 struct frame *root = root_frame (f);
3342 paused_p = false; 3813 eassert (FRAME_VISIBLE_P (root));
3343 else 3814
3344 { 3815 /* Process child frames in reverse z-order, topmost last. For each
3345 update_begin (f); 3816 child, copy what we need to the root's desired matrix. */
3346 paused_p = update_frame_1 (f, force_p, inhibit_hairy_id_p, 1, false); 3817 Lisp_Object z_order = frames_in_reverse_z_order (root, true);
3347 update_end (f); 3818 struct frame *topmost_child = NULL;
3348 } 3819 for (Lisp_Object tail = XCDR (z_order); CONSP (tail); tail = XCDR (tail))
3349 3820 {
3350 if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f)) 3821 topmost_child = XFRAME (XCAR (tail));
3351 { 3822 copy_child_glyphs (root, topmost_child);
3352 if (FRAME_TTY (f)->termscript) 3823 }
3353 fflush (FRAME_TTY (f)->termscript); 3824
3354 if (FRAME_TERMCAP_P (f)) 3825 update_begin (root);
3355 fflush (FRAME_TTY (f)->output); 3826 bool paused = write_matrix (root, force_p, inhibit_scrolling, 1, false);
3356 } 3827 if (!paused)
3357 3828 make_matrix_current (root);
3358 /* Check window matrices for lost pointers. */ 3829 update_end (root);
3830
3831 /* If a child is displayed, and the cursor is displayed in another
3832 frame, the child might lay above the cursor, so that it appers to
3833 "shine through" the child. Avoid that because it's confusing. */
3834 if (topmost_child)
3835 terminal_cursor_magic (root, topmost_child);
3836 flush_terminal (root);
3837
3838 for (Lisp_Object tail = z_order; CONSP (tail); tail = XCDR (tail))
3839 {
3840 struct frame *f = XFRAME (XCAR (tail));
3841 struct window *root_window = XWINDOW (f->root_window);
3842 set_window_update_flags (root_window, false);
3843 clear_desired_matrices (f);
3359#ifdef GLYPH_DEBUG 3844#ifdef GLYPH_DEBUG
3360 check_window_matrix_pointers (root_window); 3845 check_window_matrix_pointers (root_window);
3361 add_frame_display_history (f, paused_p); 3846 add_frame_display_history (f, false);
3362#endif 3847#endif
3363 } 3848 }
3364 3849
3365 do_pause: 3850 return paused;
3366 /* Reset flags indicating that a window should be updated. */ 3851}
3367 set_window_update_flags (root_window, false);
3368 3852
3369 display_completed = !paused_p; 3853/* Update on the screen all root frames ROOTS. Called from
3370 return paused_p; 3854 redisplay_internal as the last step of redisplaying. */
3855
3856bool
3857combine_updates (Lisp_Object roots, bool force_p, bool inhibit_scrolling)
3858{
3859 for (; CONSP (roots); roots = XCDR (roots))
3860 {
3861 struct frame *root = XFRAME (XCAR (roots));
3862 if (combine_updates_for_frame (root, force_p, inhibit_scrolling))
3863 {
3864 display_completed = false;
3865 return true;
3866 }
3867 }
3868
3869 display_completed = true;
3870 return false;
3871}
3872
3873/* Update frame F based on the data in desired matrices.
3874
3875 If FORCE_P, don't let redisplay be stopped by detecting pending input.
3876 If INHIBIT_SCROLLING, don't try scrolling.
3877
3878 Value is true if redisplay was stopped due to pending input. */
3879
3880bool
3881update_frame (struct frame *f, bool force_p, bool inhibit_scrolling)
3882{
3883 struct window *root_window = XWINDOW (f->root_window);
3884
3885 if (redisplay_dont_pause)
3886 force_p = true;
3887 else if (!force_p && detect_input_pending_ignore_squeezables ())
3888 {
3889 /* Reset flags indicating that a window should be updated. */
3890 set_window_update_flags (root_window, false);
3891 display_completed = false;
3892 return true;
3893 }
3894
3895 bool paused;
3896 if (FRAME_WINDOW_P (f))
3897 paused = update_window_frame (f, force_p);
3898 else if (FRAME_INITIAL_P (f))
3899 paused = update_initial_frame (f, force_p);
3900 else
3901 paused = update_tty_frame (f, force_p);
3902
3903 if (paused)
3904 display_completed = false;
3905 return paused;
3371} 3906}
3372 3907
3373/* Update a TTY frame F that has a menu dropped down over some of its 3908/* Update a TTY frame F that has a menu dropped down over some of its
@@ -3384,29 +3919,25 @@ void
3384update_frame_with_menu (struct frame *f, int row, int col) 3919update_frame_with_menu (struct frame *f, int row, int col)
3385{ 3920{
3386 struct window *root_window = XWINDOW (f->root_window); 3921 struct window *root_window = XWINDOW (f->root_window);
3387 bool paused_p, cursor_at_point_p; 3922 bool cursor_at_point_p;
3388 3923
3389 eassert (FRAME_TERMCAP_P (f)); 3924 eassert (FRAME_TERMCAP_P (f));
3390 3925
3391 /* We are working on frame matrix basis. Set the frame on whose
3392 frame matrix we operate. */
3393 set_frame_matrix_frame (f);
3394
3395 /* Update the display. */ 3926 /* Update the display. */
3396 update_begin (f); 3927 update_begin (f);
3397 cursor_at_point_p = !(row >= 0 && col >= 0); 3928 cursor_at_point_p = !(row >= 0 && col >= 0);
3398 /* Force update_frame_1 not to stop due to pending input, and not 3929 /* Do not stop due to pending input, and do not try scrolling. This
3399 try scrolling. */ 3930 means that write_glyphs will always return false. */
3400 paused_p = update_frame_1 (f, 1, 1, cursor_at_point_p, true); 3931 write_matrix (f, 1, 1, cursor_at_point_p, true);
3932 make_matrix_current (f);
3933 clear_desired_matrices (f);
3401 /* ROW and COL tell us where in the menu to position the cursor, so 3934 /* ROW and COL tell us where in the menu to position the cursor, so
3402 that screen readers know the active region on the screen. */ 3935 that screen readers know the active region on the screen. */
3403 if (!cursor_at_point_p) 3936 if (!cursor_at_point_p)
3404 cursor_to (f, row, col); 3937 cursor_to (f, row, col);
3405 update_end (f); 3938 update_end (f);
3939 flush_terminal (f);
3406 3940
3407 if (FRAME_TTY (f)->termscript)
3408 fflush (FRAME_TTY (f)->termscript);
3409 fflush (FRAME_TTY (f)->output);
3410 /* Check window matrices for lost pointers. */ 3941 /* Check window matrices for lost pointers. */
3411#if GLYPH_DEBUG 3942#if GLYPH_DEBUG
3412#if 0 3943#if 0
@@ -3415,12 +3946,12 @@ update_frame_with_menu (struct frame *f, int row, int col)
3415 making any updates to the window matrices. */ 3946 making any updates to the window matrices. */
3416 check_window_matrix_pointers (root_window); 3947 check_window_matrix_pointers (root_window);
3417#endif 3948#endif
3418 add_frame_display_history (f, paused_p); 3949 add_frame_display_history (f, false);
3419#endif 3950#endif
3420 3951
3421 /* Reset flags indicating that a window should be updated. */ 3952 /* Reset flags indicating that a window should be updated. */
3422 set_window_update_flags (root_window, false); 3953 set_window_update_flags (root_window, false);
3423 display_completed = !paused_p; 3954 display_completed = true;
3424} 3955}
3425 3956
3426/* Update the mouse position for a frame F. This handles both 3957/* Update the mouse position for a frame F. This handles both
@@ -3453,19 +3984,20 @@ update_mouse_position (struct frame *f, int x, int y)
3453} 3984}
3454 3985
3455DEFUN ("display--update-for-mouse-movement", Fdisplay__update_for_mouse_movement, 3986DEFUN ("display--update-for-mouse-movement", Fdisplay__update_for_mouse_movement,
3456 Sdisplay__update_for_mouse_movement, 2, 2, 0, 3987 Sdisplay__update_for_mouse_movement, 3, 3, 0,
3457 doc: /* Handle mouse movement detected by Lisp code. 3988 doc: /* Handle mouse movement detected by Lisp code.
3458 3989
3459This function should be called when Lisp code detects the mouse has 3990This function should be called when Lisp code detects the mouse has
3460moved, even if `track-mouse' is nil. This handles updates that do not 3991moved, even if `track-mouse' is nil. This handles updates that do not
3461rely on input events such as updating display for mouse-face 3992rely on input events such as updating display for mouse-face
3462properties or updating the help echo text. */) 3993properties or updating the help echo text. */)
3463 (Lisp_Object mouse_x, Lisp_Object mouse_y) 3994 (Lisp_Object mouse_frame, Lisp_Object mouse_x, Lisp_Object mouse_y)
3464{ 3995{
3996 CHECK_FRAME (mouse_frame);
3465 CHECK_FIXNUM (mouse_x); 3997 CHECK_FIXNUM (mouse_x);
3466 CHECK_FIXNUM (mouse_y); 3998 CHECK_FIXNUM (mouse_y);
3467 3999
3468 update_mouse_position (SELECTED_FRAME (), XFIXNUM (mouse_x), 4000 update_mouse_position (XFRAME (mouse_frame), XFIXNUM (mouse_x),
3469 XFIXNUM (mouse_y)); 4001 XFIXNUM (mouse_y));
3470 return Qnil; 4002 return Qnil;
3471} 4003}
@@ -3507,9 +4039,6 @@ update_single_window (struct window *w)
3507 { 4039 {
3508 struct frame *f = XFRAME (WINDOW_FRAME (w)); 4040 struct frame *f = XFRAME (WINDOW_FRAME (w));
3509 4041
3510 /* Record that this is not a frame-based redisplay. */
3511 set_frame_matrix_frame (NULL);
3512
3513 /* Update W. */ 4042 /* Update W. */
3514 update_begin (f); 4043 update_begin (f);
3515 update_window (w, true); 4044 update_window (w, true);
@@ -3688,6 +4217,8 @@ update_window (struct window *w, bool force_p)
3688 4217
3689#ifdef HAVE_WINDOW_SYSTEM 4218#ifdef HAVE_WINDOW_SYSTEM
3690 gui_update_window_begin (w); 4219 gui_update_window_begin (w);
4220#else
4221 (void) changed_p;
3691#endif 4222#endif
3692 yb = window_text_bottom_y (w); 4223 yb = window_text_bottom_y (w);
3693 row = MATRIX_ROW (desired_matrix, 0); 4224 row = MATRIX_ROW (desired_matrix, 0);
@@ -4321,7 +4852,7 @@ update_window_line (struct window *w, int vpos, bool *mouse_face_overwritten_p)
4321 4852
4322 /* Update current_row from desired_row. */ 4853 /* Update current_row from desired_row. */
4323 was_stipple = current_row->stipple_p; 4854 was_stipple = current_row->stipple_p;
4324 make_current (w->desired_matrix, w->current_matrix, vpos); 4855 make_current (NULL, w, vpos);
4325 4856
4326 /* If only a partial update was performed, any stipple already 4857 /* If only a partial update was performed, any stipple already
4327 displayed in MATRIX_ROW (w->current_matrix, vpos) might still be 4858 displayed in MATRIX_ROW (w->current_matrix, vpos) might still be
@@ -4931,7 +5462,92 @@ scrolling_window (struct window *w, int tab_line_p)
4931 Frame-Based Updates 5462 Frame-Based Updates
4932 ************************************************************************/ 5463 ************************************************************************/
4933 5464
4934/* Update the desired frame matrix of frame F. 5465static void
5466tty_set_cursor (void)
5467{
5468 struct frame *f = SELECTED_FRAME ();
5469
5470 if ((cursor_in_echo_area
5471 /* If we are showing a message instead of the mini-buffer,
5472 show the cursor for the message instead of for the
5473 (now hidden) mini-buffer contents. */
5474 || (BASE_EQ (minibuf_window, selected_window)
5475 && BASE_EQ (minibuf_window, echo_area_window)
5476 && !NILP (echo_area_buffer[0])))
5477 /* These cases apply only to the frame that contains
5478 the active mini-buffer window. */
5479 && FRAME_HAS_MINIBUF_P (f)
5480 && BASE_EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
5481 {
5482 int top = WINDOW_TOP_EDGE_LINE (XWINDOW (FRAME_MINIBUF_WINDOW (f)));
5483 int col;
5484
5485 /* Put cursor at the end of the prompt. If the mini-buffer
5486 is several lines high, find the last line that has
5487 any text on it. */
5488 int row = FRAME_TOTAL_LINES (f);
5489 do
5490 {
5491 row--;
5492 col = 0;
5493
5494 if (MATRIX_ROW_ENABLED_P (f->current_matrix, row))
5495 {
5496 /* Frame rows are filled up with spaces that
5497 must be ignored here. */
5498 struct glyph_row *r = MATRIX_ROW (f->current_matrix, row);
5499 struct glyph *start = r->glyphs[TEXT_AREA];
5500
5501 col = r->used[TEXT_AREA];
5502 while (0 < col && start[col - 1].charpos < 0)
5503 col--;
5504 }
5505 }
5506 while (row > top && col == 0);
5507
5508 /* We exit the loop with COL at the glyph _after_ the last one. */
5509 if (col > 0)
5510 col--;
5511
5512 /* Make sure COL is not out of range. */
5513 if (col >= FRAME_CURSOR_X_LIMIT (f))
5514 {
5515 /* If we have another row, advance cursor into it. */
5516 if (row < FRAME_TOTAL_LINES (f) - 1)
5517 {
5518 col = FRAME_LEFT_SCROLL_BAR_COLS (f);
5519 row++;
5520 }
5521 /* Otherwise move it back in range. */
5522 else
5523 col = FRAME_CURSOR_X_LIMIT (f) - 1;
5524 }
5525
5526 cursor_to (f, row, col);
5527 }
5528 else
5529 {
5530 /* We have only one cursor on terminal frames. Use it to
5531 display the cursor of the selected window. */
5532 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
5533 if (w->cursor.vpos >= 0
5534 /* The cursor vpos may be temporarily out of bounds
5535 in the following situation: There is one window,
5536 with the cursor in the lower half of it. The window
5537 is split, and a message causes a redisplay before
5538 a new cursor position has been computed. */
5539 && w->cursor.vpos < WINDOW_TOTAL_LINES (w))
5540 {
5541 int x = WINDOW_TO_FRAME_HPOS (w, w->cursor.hpos);
5542 int y = WINDOW_TO_FRAME_VPOS (w, w->cursor.vpos);
5543
5544 x += max (0, w->left_margin_cols);
5545 cursor_to (f, y, x);
5546 }
5547 }
5548}
5549
5550/* Write desired matix of tty frame F and make it current.
4935 5551
4936 FORCE_P means that the update should not be stopped by pending input. 5552 FORCE_P means that the update should not be stopped by pending input.
4937 INHIBIT_ID_P means that scrolling by insert/delete should not be tried. 5553 INHIBIT_ID_P means that scrolling by insert/delete should not be tried.
@@ -4940,167 +5556,58 @@ scrolling_window (struct window *w, int tab_line_p)
4940 Value is true if update was stopped due to pending input. */ 5556 Value is true if update was stopped due to pending input. */
4941 5557
4942static bool 5558static bool
4943update_frame_1 (struct frame *f, bool force_p, bool inhibit_id_p, 5559write_matrix (struct frame *f, bool force_p, bool inhibit_id_p,
4944 bool set_cursor_p, bool updating_menu_p) 5560 bool set_cursor_p, bool updating_menu_p)
4945{ 5561{
4946 /* Frame matrices to work on. */
4947 struct glyph_matrix *current_matrix = f->current_matrix;
4948 struct glyph_matrix *desired_matrix = f->desired_matrix;
4949 int i;
4950 bool pause_p;
4951 int preempt_count = clip_to_bounds (1, baud_rate / 2400 + 1, INT_MAX);
4952
4953 eassert (current_matrix && desired_matrix);
4954
4955 if (baud_rate != FRAME_COST_BAUD_RATE (f))
4956 calculate_costs (f);
4957
4958 if (!force_p && detect_input_pending_ignore_squeezables ()) 5562 if (!force_p && detect_input_pending_ignore_squeezables ())
4959 { 5563 return true;
4960 pause_p = 1;
4961 goto do_pause;
4962 }
4963 5564
4964 /* If we cannot insert/delete lines, it's no use trying it. */ 5565 /* If we cannot insert/delete lines, it's no use trying it. */
4965 if (!FRAME_LINE_INS_DEL_OK (f)) 5566 if (!FRAME_LINE_INS_DEL_OK (f))
4966 inhibit_id_p = 1; 5567 inhibit_id_p = true;
4967 5568
4968 /* See if any of the desired lines are enabled; don't compute for 5569 if (baud_rate != FRAME_COST_BAUD_RATE (f))
4969 i/d line if just want cursor motion. */ 5570 calculate_costs (f);
4970 for (i = 0; i < desired_matrix->nrows; i++)
4971 if (MATRIX_ROW_ENABLED_P (desired_matrix, i))
4972 break;
4973 5571
4974 /* Try doing i/d line, if not yet inhibited. */ 5572 /* See if any of the desired lines are enabled; don't compute for
4975 if (!inhibit_id_p && i < desired_matrix->nrows) 5573 i/d line if just want cursor motion. */
5574 int first_row = first_enabled_row (f->desired_matrix);
5575 if (!inhibit_id_p && first_row >= 0)
4976 force_p |= scrolling (f); 5576 force_p |= scrolling (f);
4977 5577
4978 /* Update the individual lines as needed. Do bottom line first. */ 5578 /* Update the individual lines as needed. Do bottom line first. This
4979 if (MATRIX_ROW_ENABLED_P (desired_matrix, desired_matrix->nrows - 1)) 5579 is done so that messages are made visible when pausing. */
4980 update_frame_line (f, desired_matrix->nrows - 1, updating_menu_p); 5580 int last_row = f->desired_matrix->nrows - 1;
5581 if (MATRIX_ROW_ENABLED_P (f->desired_matrix, last_row))
5582 write_row (f, last_row, updating_menu_p);
4981 5583
4982 /* Now update the rest of the lines. */ 5584 bool pause_p = false;
4983 for (i = 0; i < desired_matrix->nrows - 1 && (force_p || !input_pending); i++) 5585 if (first_row >= 0)
4984 { 5586 {
4985 if (MATRIX_ROW_ENABLED_P (desired_matrix, i)) 5587 const int preempt_count = clip_to_bounds (1, baud_rate / 2400 + 1, INT_MAX);
4986 {
4987 /* Note that output_buffer_size being 0 means that we want the
4988 old default behavior of flushing output every now and then. */
4989 if (FRAME_TERMCAP_P (f) && FRAME_TTY (f)->output_buffer_size == 0)
4990 {
4991 /* Flush out every so many lines.
4992 Also flush out if likely to have more than 1k buffered
4993 otherwise. I'm told that some telnet connections get
4994 really screwed by more than 1k output at once. */
4995 FILE *display_output = FRAME_TTY (f)->output;
4996 if (display_output)
4997 {
4998 ptrdiff_t outq = __fpending (display_output);
4999 if (outq > 900
5000 || (outq > 20 && ((i - 1) % preempt_count == 0)))
5001 fflush (display_output);
5002 }
5003 }
5004 5588
5005 if (!force_p && (i - 1) % preempt_count == 0) 5589 for (int i = first_row, n = 0; i < last_row; ++i)
5006 detect_input_pending_ignore_squeezables (); 5590 if (MATRIX_ROW_ENABLED_P (f->desired_matrix, i))
5591 {
5592 if (!force_p && n % preempt_count == 0
5593 && detect_input_pending_ignore_squeezables ())
5594 {
5595 pause_p = true;
5596 break;
5597 }
5007 5598
5008 update_frame_line (f, i, updating_menu_p); 5599 write_row (f, i, updating_menu_p);
5009 } 5600 ++n;
5601 }
5010 } 5602 }
5011 5603
5012 pause_p = 0 < i && i < FRAME_TOTAL_LINES (f) - 1;
5013
5014 /* Now just clean up termcap drivers and set cursor, etc. */ 5604 /* Now just clean up termcap drivers and set cursor, etc. */
5015 if (!pause_p && set_cursor_p) 5605 if (!pause_p && set_cursor_p)
5016 { 5606 tty_set_cursor ();
5017 if ((cursor_in_echo_area
5018 /* If we are showing a message instead of the mini-buffer,
5019 show the cursor for the message instead of for the
5020 (now hidden) mini-buffer contents. */
5021 || (BASE_EQ (minibuf_window, selected_window)
5022 && BASE_EQ (minibuf_window, echo_area_window)
5023 && !NILP (echo_area_buffer[0])))
5024 /* These cases apply only to the frame that contains
5025 the active mini-buffer window. */
5026 && FRAME_HAS_MINIBUF_P (f)
5027 && BASE_EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
5028 {
5029 int top = WINDOW_TOP_EDGE_LINE (XWINDOW (FRAME_MINIBUF_WINDOW (f)));
5030 int col;
5031
5032 /* Put cursor at the end of the prompt. If the mini-buffer
5033 is several lines high, find the last line that has
5034 any text on it. */
5035 int row = FRAME_TOTAL_LINES (f);
5036 do
5037 {
5038 row--;
5039 col = 0;
5040
5041 if (MATRIX_ROW_ENABLED_P (current_matrix, row))
5042 {
5043 /* Frame rows are filled up with spaces that
5044 must be ignored here. */
5045 struct glyph_row *r = MATRIX_ROW (current_matrix, row);
5046 struct glyph *start = r->glyphs[TEXT_AREA];
5047
5048 col = r->used[TEXT_AREA];
5049 while (0 < col && start[col - 1].charpos < 0)
5050 col--;
5051 }
5052 }
5053 while (row > top && col == 0);
5054 5607
5055 /* We exit the loop with COL at the glyph _after_ the last one. */
5056 if (col > 0)
5057 col--;
5058
5059 /* Make sure COL is not out of range. */
5060 if (col >= FRAME_CURSOR_X_LIMIT (f))
5061 {
5062 /* If we have another row, advance cursor into it. */
5063 if (row < FRAME_TOTAL_LINES (f) - 1)
5064 {
5065 col = FRAME_LEFT_SCROLL_BAR_COLS (f);
5066 row++;
5067 }
5068 /* Otherwise move it back in range. */
5069 else
5070 col = FRAME_CURSOR_X_LIMIT (f) - 1;
5071 }
5072
5073 cursor_to (f, row, col);
5074 }
5075 else
5076 {
5077 /* We have only one cursor on terminal frames. Use it to
5078 display the cursor of the selected window. */
5079 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
5080 if (w->cursor.vpos >= 0
5081 /* The cursor vpos may be temporarily out of bounds
5082 in the following situation: There is one window,
5083 with the cursor in the lower half of it. The window
5084 is split, and a message causes a redisplay before
5085 a new cursor position has been computed. */
5086 && w->cursor.vpos < WINDOW_TOTAL_LINES (w))
5087 {
5088 int x = WINDOW_TO_FRAME_HPOS (w, w->cursor.hpos);
5089 int y = WINDOW_TO_FRAME_VPOS (w, w->cursor.vpos);
5090
5091 x += max (0, w->left_margin_cols);
5092 cursor_to (f, y, x);
5093 }
5094 }
5095 }
5096
5097 do_pause:
5098
5099 clear_desired_matrices (f);
5100 return pause_p; 5608 return pause_p;
5101} 5609}
5102 5610
5103
5104/* Do line insertions/deletions on frame F for frame-based redisplay. */ 5611/* Do line insertions/deletions on frame F for frame-based redisplay. */
5105 5612
5106static bool 5613static bool
@@ -5209,12 +5716,12 @@ scrolling (struct frame *frame)
5209 which is LEN glyphs long. */ 5716 which is LEN glyphs long. */
5210 5717
5211static int 5718static int
5212count_blanks (struct glyph *r, int len) 5719count_blanks (struct frame *f, struct glyph *r, int len)
5213{ 5720{
5214 int i; 5721 int i;
5215 5722
5216 for (i = 0; i < len; ++i) 5723 for (i = 0; i < len; ++i)
5217 if (!CHAR_GLYPH_SPACE_P (r[i])) 5724 if (!CHAR_GLYPH_SPACE_P (f, r[i]))
5218 break; 5725 break;
5219 5726
5220 return i; 5727 return i;
@@ -5250,7 +5757,7 @@ count_match (struct glyph *str1, struct glyph *end1, struct glyph *str2, struct
5250/* Perform a frame-based update on line VPOS in frame FRAME. */ 5757/* Perform a frame-based update on line VPOS in frame FRAME. */
5251 5758
5252static void 5759static void
5253update_frame_line (struct frame *f, int vpos, bool updating_menu_p) 5760write_row (struct frame *f, int vpos, bool updating_menu_p)
5254{ 5761{
5255 struct glyph *obody, *nbody, *op1, *op2, *np1, *nend; 5762 struct glyph *obody, *nbody, *op1, *op2, *np1, *nend;
5256 int tem; 5763 int tem;
@@ -5264,11 +5771,6 @@ update_frame_line (struct frame *f, int vpos, bool updating_menu_p)
5264 bool colored_spaces_p = (FACE_FROM_ID (f, DEFAULT_FACE_ID)->background 5771 bool colored_spaces_p = (FACE_FROM_ID (f, DEFAULT_FACE_ID)->background
5265 != FACE_TTY_DEFAULT_BG_COLOR); 5772 != FACE_TTY_DEFAULT_BG_COLOR);
5266 5773
5267 /* This should never happen, but evidently sometimes does if one
5268 resizes the frame quickly enough. Prevent aborts in cmcheckmagic. */
5269 if (vpos >= FRAME_TOTAL_LINES (f))
5270 return;
5271
5272 if (colored_spaces_p) 5774 if (colored_spaces_p)
5273 write_spaces_p = 1; 5775 write_spaces_p = 1;
5274 5776
@@ -5287,7 +5789,7 @@ update_frame_line (struct frame *f, int vpos, bool updating_menu_p)
5287 5789
5288 /* Ignore trailing spaces, if we can. */ 5790 /* Ignore trailing spaces, if we can. */
5289 if (!write_spaces_p) 5791 if (!write_spaces_p)
5290 while (olen > 0 && CHAR_GLYPH_SPACE_P (obody[olen-1])) 5792 while (olen > 0 && CHAR_GLYPH_SPACE_P (f, obody[olen-1]))
5291 olen--; 5793 olen--;
5292 } 5794 }
5293 5795
@@ -5316,7 +5818,7 @@ update_frame_line (struct frame *f, int vpos, bool updating_menu_p)
5316 { 5818 {
5317 /* Ignore spaces at the end, if we can. */ 5819 /* Ignore spaces at the end, if we can. */
5318 if (!write_spaces_p) 5820 if (!write_spaces_p)
5319 while (nlen > 0 && CHAR_GLYPH_SPACE_P (nbody[nlen - 1])) 5821 while (nlen > 0 && CHAR_GLYPH_SPACE_P (f, nbody[nlen - 1]))
5320 --nlen; 5822 --nlen;
5321 5823
5322 /* Write the contents of the desired line. */ 5824 /* Write the contents of the desired line. */
@@ -5338,15 +5840,13 @@ update_frame_line (struct frame *f, int vpos, bool updating_menu_p)
5338 /* Make sure we are in the right row, otherwise cursor movement 5840 /* Make sure we are in the right row, otherwise cursor movement
5339 with cmgoto might use `ch' in the wrong row. */ 5841 with cmgoto might use `ch' in the wrong row. */
5340 cursor_to (f, vpos, 0); 5842 cursor_to (f, vpos, 0);
5341
5342 make_current (desired_matrix, current_matrix, vpos);
5343 return; 5843 return;
5344 } 5844 }
5345 5845
5346 /* Pretend trailing spaces are not there at all, 5846 /* Pretend trailing spaces are not there at all,
5347 unless for one reason or another we must write all spaces. */ 5847 unless for one reason or another we must write all spaces. */
5348 if (!write_spaces_p) 5848 if (!write_spaces_p)
5349 while (nlen > 0 && CHAR_GLYPH_SPACE_P (nbody[nlen - 1])) 5849 while (nlen > 0 && CHAR_GLYPH_SPACE_P (f, nbody[nlen - 1]))
5350 nlen--; 5850 nlen--;
5351 5851
5352 /* If there's no i/d char, quickly do the best we can without it. */ 5852 /* If there's no i/d char, quickly do the best we can without it. */
@@ -5383,9 +5883,6 @@ update_frame_line (struct frame *f, int vpos, bool updating_menu_p)
5383 cursor_to (f, vpos, nlen); 5883 cursor_to (f, vpos, nlen);
5384 clear_end_of_line (f, olen); 5884 clear_end_of_line (f, olen);
5385 } 5885 }
5386
5387 /* Make current row = desired row. */
5388 make_current (desired_matrix, current_matrix, vpos);
5389 return; 5886 return;
5390 } 5887 }
5391 5888
@@ -5399,7 +5896,7 @@ update_frame_line (struct frame *f, int vpos, bool updating_menu_p)
5399 if (write_spaces_p) 5896 if (write_spaces_p)
5400 nsp = 0; 5897 nsp = 0;
5401 else 5898 else
5402 nsp = count_blanks (nbody, nlen); 5899 nsp = count_blanks (f, nbody, nlen);
5403 5900
5404 if (nlen > nsp) 5901 if (nlen > nsp)
5405 { 5902 {
@@ -5407,14 +5904,12 @@ update_frame_line (struct frame *f, int vpos, bool updating_menu_p)
5407 write_glyphs (f, nbody + nsp, nlen - nsp); 5904 write_glyphs (f, nbody + nsp, nlen - nsp);
5408 } 5905 }
5409 5906
5410 /* Exchange contents between current_frame and new_frame. */
5411 make_current (desired_matrix, current_matrix, vpos);
5412 return; 5907 return;
5413 } 5908 }
5414 5909
5415 /* Compute number of leading blanks in old and new contents. */ 5910 /* Compute number of leading blanks in old and new contents. */
5416 osp = count_blanks (obody, olen); 5911 osp = count_blanks (f, obody, olen);
5417 nsp = (colored_spaces_p ? 0 : count_blanks (nbody, nlen)); 5912 nsp = (colored_spaces_p ? 0 : count_blanks (f, nbody, nlen));
5418 5913
5419 /* Compute number of matching chars starting with first non-blank. */ 5914 /* Compute number of matching chars starting with first non-blank. */
5420 begmatch = count_match (obody + osp, obody + olen, 5915 begmatch = count_match (obody + osp, obody + olen,
@@ -5425,7 +5920,7 @@ update_frame_line (struct frame *f, int vpos, bool updating_menu_p)
5425 if (!write_spaces_p && osp + begmatch == olen) 5920 if (!write_spaces_p && osp + begmatch == olen)
5426 { 5921 {
5427 np1 = nbody + nsp; 5922 np1 = nbody + nsp;
5428 while (np1 + begmatch < nend && CHAR_GLYPH_SPACE_P (np1[begmatch])) 5923 while (np1 + begmatch < nend && CHAR_GLYPH_SPACE_P (f, np1[begmatch]))
5429 ++begmatch; 5924 ++begmatch;
5430 } 5925 }
5431 5926
@@ -5566,9 +6061,6 @@ update_frame_line (struct frame *f, int vpos, bool updating_menu_p)
5566 cursor_to (f, vpos, nlen); 6061 cursor_to (f, vpos, nlen);
5567 clear_end_of_line (f, olen); 6062 clear_end_of_line (f, olen);
5568 } 6063 }
5569
5570 /* Exchange contents between current_frame and new_frame. */
5571 make_current (desired_matrix, current_matrix, vpos);
5572} 6064}
5573 6065
5574 6066
@@ -5967,7 +6459,8 @@ handle_window_change_signal (int sig)
5967 { 6459 {
5968 struct frame *f = XFRAME (frame); 6460 struct frame *f = XFRAME (frame);
5969 6461
5970 if (FRAME_TERMCAP_P (f) && FRAME_TTY (f) == tty) 6462 if (FRAME_TERMCAP_P (f) && FRAME_TTY (f) == tty
6463 && !FRAME_PARENT_FRAME (f))
5971 /* Record the new sizes, but don't reallocate the data 6464 /* Record the new sizes, but don't reallocate the data
5972 structures now. Let that be done later outside of the 6465 structures now. Let that be done later outside of the
5973 signal handler. */ 6466 signal handler. */
@@ -6534,7 +7027,7 @@ init_display_interactive (void)
6534 7027
6535 /* Construct the space glyph. */ 7028 /* Construct the space glyph. */
6536 space_glyph.type = CHAR_GLYPH; 7029 space_glyph.type = CHAR_GLYPH;
6537 SET_CHAR_GLYPH (space_glyph, ' ', DEFAULT_FACE_ID, 0); 7030 SET_CHAR_GLYPH (NULL, space_glyph, ' ', DEFAULT_FACE_ID, 0);
6538 space_glyph.charpos = -1; 7031 space_glyph.charpos = -1;
6539 7032
6540 inverse_video = 0; 7033 inverse_video = 0;
@@ -6808,6 +7301,7 @@ syms_of_display (void)
6808 defsubr (&Ssend_string_to_terminal); 7301 defsubr (&Ssend_string_to_terminal);
6809 defsubr (&Sinternal_show_cursor); 7302 defsubr (&Sinternal_show_cursor);
6810 defsubr (&Sinternal_show_cursor_p); 7303 defsubr (&Sinternal_show_cursor_p);
7304 defsubr (&Sframe__z_order_lessp);
6811 7305
6812#ifdef GLYPH_DEBUG 7306#ifdef GLYPH_DEBUG
6813 defsubr (&Sdump_redisplay_history); 7307 defsubr (&Sdump_redisplay_history);
@@ -6818,8 +7312,10 @@ syms_of_display (void)
6818 7312
6819 /* This is the "purpose" slot of a display table. */ 7313 /* This is the "purpose" slot of a display table. */
6820 DEFSYM (Qdisplay_table, "display-table"); 7314 DEFSYM (Qdisplay_table, "display-table");
7315 DEFSYM (Qframe__z_order_lessp, "frame--z-order-lessp");
6821 7316
6822 DEFSYM (Qredisplay_dont_pause, "redisplay-dont-pause"); 7317 DEFSYM (Qredisplay_dont_pause, "redisplay-dont-pause");
7318 DEFSYM (Qtty_non_selected_cursor, "tty-non-selected-cursor");
6823 7319
6824 DEFVAR_INT ("baud-rate", baud_rate, 7320 DEFVAR_INT ("baud-rate", baud_rate,
6825 doc: /* The output baud rate of the terminal. 7321 doc: /* The output baud rate of the terminal.
@@ -6921,6 +7417,8 @@ Possible values are t (below the tool bar), nil (above the tool bar).
6921This option affects only builds where the tool bar is not external. */); 7417This option affects only builds where the tool bar is not external. */);
6922 7418
6923 pdumper_do_now_and_after_load (syms_of_display_for_pdumper); 7419 pdumper_do_now_and_after_load (syms_of_display_for_pdumper);
7420
7421 Fprovide (intern_c_string ("tty-child-frames"), Qnil);
6924} 7422}
6925 7423
6926static void 7424static void
diff --git a/src/disptab.h b/src/disptab.h
index 2080181610a..f51d1d3044b 100644
--- a/src/disptab.h
+++ b/src/disptab.h
@@ -28,7 +28,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
28 && EQ (XCHAR_TABLE (obj)->purpose, Qdisplay_table) \ 28 && EQ (XCHAR_TABLE (obj)->purpose, Qdisplay_table) \
29 && CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (obj)) == DISP_TABLE_EXTRA_SLOTS) 29 && CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (obj)) == DISP_TABLE_EXTRA_SLOTS)
30 30
31#define DISP_TABLE_EXTRA_SLOTS 6 31#define DISP_TABLE_EXTRA_SLOTS 12
32#define DISP_TRUNC_GLYPH(dp) ((dp)->extras[0]) 32#define DISP_TRUNC_GLYPH(dp) ((dp)->extras[0])
33#define DISP_CONTINUE_GLYPH(dp) ((dp)->extras[1]) 33#define DISP_CONTINUE_GLYPH(dp) ((dp)->extras[1])
34#define DISP_ESCAPE_GLYPH(dp) ((dp)->extras[2]) 34#define DISP_ESCAPE_GLYPH(dp) ((dp)->extras[2])
@@ -36,6 +36,16 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
36#define DISP_INVIS_VECTOR(dp) ((dp)->extras[4]) 36#define DISP_INVIS_VECTOR(dp) ((dp)->extras[4])
37#define DISP_BORDER_GLYPH(dp) ((dp)->extras[5]) 37#define DISP_BORDER_GLYPH(dp) ((dp)->extras[5])
38 38
39enum box
40{
41 BOX_VERTICAL = 6,
42 BOX_HORIZONTAL,
43 BOX_DOWN_RIGHT,
44 BOX_DOWN_LEFT,
45 BOX_UP_RIGHT,
46 BOX_UP_LEFT
47};
48
39extern Lisp_Object disp_char_vector (struct Lisp_Char_Table *, int); 49extern Lisp_Object disp_char_vector (struct Lisp_Char_Table *, int);
40 50
41#define DISP_CHAR_VECTOR(dp, c) \ 51#define DISP_CHAR_VECTOR(dp, c) \
diff --git a/src/frame.c b/src/frame.c
index 7f4bf274ad9..8133b646216 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -130,6 +130,14 @@ decode_window_system_frame (Lisp_Object frame)
130#endif 130#endif
131} 131}
132 132
133struct frame *
134decode_tty_frame (Lisp_Object frame)
135{
136 struct frame *f = decode_live_frame (frame);
137 check_tty (f);
138 return f;
139}
140
133void 141void
134check_window_system (struct frame *f) 142check_window_system (struct frame *f)
135{ 143{
@@ -141,6 +149,13 @@ check_window_system (struct frame *f)
141 : "Window system is not in use or not initialized"); 149 : "Window system is not in use or not initialized");
142} 150}
143 151
152void
153check_tty (struct frame *f)
154{
155 if (!f || !FRAME_TERMCAP_P (f))
156 error ("tty frame should be used");
157}
158
144/* Return the value of frame parameter PROP in frame FRAME. */ 159/* Return the value of frame parameter PROP in frame FRAME. */
145 160
146Lisp_Object 161Lisp_Object
@@ -182,6 +197,17 @@ set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
182 int olines = FRAME_MENU_BAR_LINES (f); 197 int olines = FRAME_MENU_BAR_LINES (f);
183 int nlines = TYPE_RANGED_FIXNUMP (int, value) ? XFIXNUM (value) : 0; 198 int nlines = TYPE_RANGED_FIXNUMP (int, value) ? XFIXNUM (value) : 0;
184 199
200 /* Menu bars on child frames don't work on all platforms,
201 which is the reason why prepare_menu_bar does not update_menu_bar
202 for child frames (info from Martin Rudalics). This could be
203 implemented in ttys, but it's probaly not worth it. */
204 if (is_tty_child_frame (f))
205 {
206 FRAME_MENU_BAR_LINES (f) = 0;
207 FRAME_MENU_BAR_HEIGHT (f) = 0;
208 return;
209 }
210
185 /* Right now, menu bars don't work properly in minibuf-only frames; 211 /* Right now, menu bars don't work properly in minibuf-only frames;
186 most of the commands try to apply themselves to the minibuffer 212 most of the commands try to apply themselves to the minibuffer
187 frame itself, and get an error because you can't switch buffers 213 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,
370 } 396 }
371 else 397 else
372 retval = XFIXNUM (call4 (Qframe_windows_min_size, frame, horizontal, 398 retval = XFIXNUM (call4 (Qframe_windows_min_size, frame, horizontal,
373 ignore, pixelwise)); 399 ignore, pixelwise));
374 400
375 /* Don't allow too small height of text-mode frames, or else cm.c 401 /* Don't allow too small height of text-mode frames, or else cm.c
376 might abort in cmcheckmagic. */ 402 might abort in cmcheckmagic. */
377 if ((FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f)) && NILP (horizontal)) 403 if ((FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f)) && NILP (horizontal))
378 { 404 {
379 int min_height = (FRAME_MENU_BAR_LINES (f) 405 int min_height = (FRAME_MENU_BAR_LINES (f) + FRAME_TAB_BAR_LINES (f)
380 + FRAME_TAB_BAR_LINES (f)
381 + FRAME_WANTS_MODELINE_P (f) 406 + FRAME_WANTS_MODELINE_P (f)
382 + 2); /* one text line and one echo-area line */ 407 + FRAME_HAS_MINIBUF_P (f));
383 408 if (min_height == 0)
409 min_height = 1;
384 if (retval < min_height) 410 if (retval < min_height)
385 retval = min_height; 411 retval = min_height;
386 } 412 }
@@ -389,7 +415,6 @@ frame_windows_min_size (Lisp_Object frame, Lisp_Object horizontal,
389} 415}
390 416
391 417
392#ifdef HAVE_WINDOW_SYSTEM
393/** 418/**
394 * keep_ratio: 419 * keep_ratio:
395 * 420 *
@@ -508,7 +533,6 @@ keep_ratio (struct frame *f, struct frame *p, int old_width, int old_height,
508 } 533 }
509 } 534 }
510} 535}
511#endif
512 536
513 537
514static void 538static void
@@ -833,8 +857,9 @@ adjust_frame_size (struct frame *f, int new_text_width, int new_text_height,
833 857
834 /* MSDOS frames cannot PRETEND, as they change frame size by 858 /* MSDOS frames cannot PRETEND, as they change frame size by
835 manipulating video hardware. */ 859 manipulating video hardware. */
836 if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f)) 860 if (is_tty_root_frame (f))
837 FrameCols (FRAME_TTY (f)) = new_text_cols; 861 if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
862 FrameCols (FRAME_TTY (f)) = new_text_cols;
838 863
839#if defined (HAVE_WINDOW_SYSTEM) 864#if defined (HAVE_WINDOW_SYSTEM)
840 if (WINDOWP (f->tab_bar_window)) 865 if (WINDOWP (f->tab_bar_window))
@@ -866,9 +891,10 @@ adjust_frame_size (struct frame *f, int new_text_width, int new_text_height,
866 resize_frame_windows (f, new_inner_height, false); 891 resize_frame_windows (f, new_inner_height, false);
867 892
868 /* MSDOS frames cannot PRETEND, as they change frame size by 893 /* MSDOS frames cannot PRETEND, as they change frame size by
869 manipulating video hardware. */ 894 manipulating video hardware. */
870 if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f)) 895 if (is_tty_root_frame (f))
871 FrameRows (FRAME_TTY (f)) = new_text_lines + FRAME_TOP_MARGIN (f); 896 if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
897 FrameRows (FRAME_TTY (f)) = new_text_lines + FRAME_TOP_MARGIN (f);
872 } 898 }
873 else if (new_text_lines != old_text_lines) 899 else if (new_text_lines != old_text_lines)
874 call2 (Qwindow__pixel_to_total, frame, Qnil); 900 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,
898 adjust_frame_glyphs (f); 924 adjust_frame_glyphs (f);
899 calculate_costs (f); 925 calculate_costs (f);
900 SET_FRAME_GARBAGED (f); 926 SET_FRAME_GARBAGED (f);
927 if (is_tty_child_frame (f))
928 SET_FRAME_GARBAGED (root_frame (f));
929
901 /* We now say here that F was resized instead of using the old 930 /* We now say here that F was resized instead of using the old
902 condition below. Some resizing must have taken place and if it was 931 condition below. Some resizing must have taken place and if it was
903 only shifting the root window's position (paranoia?). */ 932 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,
910 939
911 unblock_input (); 940 unblock_input ();
912 941
913#ifdef HAVE_WINDOW_SYSTEM
914 { 942 {
915 /* Adjust size of F's child frames. */ 943 /* Adjust size of F's child frames. */
916 Lisp_Object frames, frame1; 944 Lisp_Object frames, frame1;
@@ -920,7 +948,6 @@ adjust_frame_size (struct frame *f, int new_text_width, int new_text_height,
920 keep_ratio (XFRAME (frame1), f, old_native_width, old_native_height, 948 keep_ratio (XFRAME (frame1), f, old_native_width, old_native_height,
921 new_native_width, new_native_height); 949 new_native_width, new_native_height);
922 } 950 }
923#endif
924} 951}
925 952
926/* Allocate basically initialized frame. */ 953/* Allocate basically initialized frame. */
@@ -967,12 +994,12 @@ make_frame (bool mini_p)
967 f->line_height = 1; /* !FRAME_WINDOW_P value. */ 994 f->line_height = 1; /* !FRAME_WINDOW_P value. */
968 f->new_width = -1; 995 f->new_width = -1;
969 f->new_height = -1; 996 f->new_height = -1;
997 f->no_special_glyphs = false;
970#ifdef HAVE_WINDOW_SYSTEM 998#ifdef HAVE_WINDOW_SYSTEM
971 f->vertical_scroll_bar_type = vertical_scroll_bar_none; 999 f->vertical_scroll_bar_type = vertical_scroll_bar_none;
972 f->horizontal_scroll_bars = false; 1000 f->horizontal_scroll_bars = false;
973 f->want_fullscreen = FULLSCREEN_NONE; 1001 f->want_fullscreen = FULLSCREEN_NONE;
974 f->undecorated = false; 1002 f->undecorated = false;
975 f->no_special_glyphs = false;
976#ifndef HAVE_NTGUI 1003#ifndef HAVE_NTGUI
977 f->override_redirect = false; 1004 f->override_redirect = false;
978#endif 1005#endif
@@ -1089,7 +1116,6 @@ make_frame (bool mini_p)
1089 return f; 1116 return f;
1090} 1117}
1091 1118
1092#ifdef HAVE_WINDOW_SYSTEM
1093/* Make a frame using a separate minibuffer window on another frame. 1119/* Make a frame using a separate minibuffer window on another frame.
1094 MINI_WINDOW is the minibuffer window to use. nil means use the 1120 MINI_WINDOW is the minibuffer window to use. nil means use the
1095 default (the global minibuffer). */ 1121 default (the global minibuffer). */
@@ -1183,7 +1209,7 @@ make_minibuffer_frame (void)
1183 : Fcar (Vminibuffer_list)), 0, 0); 1209 : Fcar (Vminibuffer_list)), 0, 0);
1184 return f; 1210 return f;
1185} 1211}
1186#endif /* HAVE_WINDOW_SYSTEM */ 1212
1187 1213
1188/* Construct a frame that refers to a terminal. */ 1214/* Construct a frame that refers to a terminal. */
1189 1215
@@ -1209,7 +1235,7 @@ make_initial_frame (void)
1209 tty_frame_count = 1; 1235 tty_frame_count = 1;
1210 fset_name (f, build_pure_c_string ("F1")); 1236 fset_name (f, build_pure_c_string ("F1"));
1211 1237
1212 SET_FRAME_VISIBLE (f, 1); 1238 SET_FRAME_VISIBLE (f, true);
1213 1239
1214 f->output_method = terminal->type; 1240 f->output_method = terminal->type;
1215 f->terminal = terminal; 1241 f->terminal = terminal;
@@ -1246,23 +1272,55 @@ make_initial_frame (void)
1246#ifndef HAVE_ANDROID 1272#ifndef HAVE_ANDROID
1247 1273
1248static struct frame * 1274static struct frame *
1249make_terminal_frame (struct terminal *terminal) 1275make_terminal_frame (struct terminal *terminal, Lisp_Object parent,
1276 Lisp_Object params)
1250{ 1277{
1251 register struct frame *f;
1252 Lisp_Object frame;
1253 char name[sizeof "F" + INT_STRLEN_BOUND (tty_frame_count)]; 1278 char name[sizeof "F" + INT_STRLEN_BOUND (tty_frame_count)];
1254 1279
1255 if (!terminal->name) 1280 if (!terminal->name)
1256 error ("Terminal is not live, can't create new frames on it"); 1281 error ("Terminal is not live, can't create new frames on it");
1257 1282
1258 f = make_frame (1); 1283 struct frame *f;
1284 if (NILP (parent))
1285 f = make_frame (true);
1286 else
1287 {
1288 CHECK_FRAME (parent);
1289
1290 f = NULL;
1291 Lisp_Object mini = Fassq (Qminibuffer, params);
1292 if (CONSP (mini))
1293 {
1294 mini = Fcdr (mini);
1295 struct kboard *kb = FRAME_KBOARD (XFRAME (parent));
1296 if (EQ (mini, Qnone) || NILP (mini))
1297 f = make_frame_without_minibuffer (Qnil, kb, Qnil);
1298 else if (EQ (mini, Qonly))
1299 {
1300# if 0 /* No interest in this feature at the moment, */
1301 f = make_minibuffer_frame ();
1302 /* Not sure about this plus the unsplittable frame
1303 paran. */
1304 f->no_split = true;
1305# endif
1306 }
1307 else if (WINDOWP (mini))
1308 f = make_frame_without_minibuffer (mini, kb, Qnil);
1309 }
1310
1311 if (f == NULL)
1312 f = make_frame (true);
1313 f->parent_frame = parent;
1314 f->z_order = 1 + max_child_z_order (XFRAME (parent));
1315 }
1259 1316
1317 Lisp_Object frame;
1260 XSETFRAME (frame, f); 1318 XSETFRAME (frame, f);
1261 Vframe_list = Fcons (frame, Vframe_list); 1319 Vframe_list = Fcons (frame, Vframe_list);
1262 1320
1263 fset_name (f, make_formatted_string (name, "F%"PRIdMAX, ++tty_frame_count)); 1321 fset_name (f, make_formatted_string (name, "F%"PRIdMAX, ++tty_frame_count));
1264 1322
1265 SET_FRAME_VISIBLE (f, 1); 1323 SET_FRAME_VISIBLE (f, true);
1266 1324
1267 f->terminal = terminal; 1325 f->terminal = terminal;
1268 f->terminal->reference_count++; 1326 f->terminal->reference_count++;
@@ -1287,7 +1345,15 @@ make_terminal_frame (struct terminal *terminal)
1287 f->horizontal_scroll_bars = false; 1345 f->horizontal_scroll_bars = false;
1288#endif 1346#endif
1289 1347
1290 FRAME_MENU_BAR_LINES (f) = NILP (Vmenu_bar_mode) ? 0 : 1; 1348 /* Menu bars on child frames don't work on all platforms,
1349 which is the reason why prepare_menu_bar does not update_menu_bar
1350 for child frames (info from Martin Rudalics). This could be
1351 implemented in ttys, but it's unclear if it is worth it. */
1352 if (NILP (parent))
1353 FRAME_MENU_BAR_LINES (f) = NILP (Vmenu_bar_mode) ? 0 : 1;
1354 else
1355 FRAME_MENU_BAR_LINES (f) = 0;
1356
1291 FRAME_TAB_BAR_LINES (f) = NILP (Vtab_bar_mode) ? 0 : 1; 1357 FRAME_TAB_BAR_LINES (f) = NILP (Vtab_bar_mode) ? 0 : 1;
1292 FRAME_LINES (f) = FRAME_LINES (f) - FRAME_MENU_BAR_LINES (f) 1358 FRAME_LINES (f) = FRAME_LINES (f) - FRAME_MENU_BAR_LINES (f)
1293 - FRAME_TAB_BAR_LINES (f); 1359 - FRAME_TAB_BAR_LINES (f);
@@ -1296,16 +1362,19 @@ make_terminal_frame (struct terminal *terminal)
1296 FRAME_TEXT_HEIGHT (f) = FRAME_TEXT_HEIGHT (f) - FRAME_MENU_BAR_HEIGHT (f) 1362 FRAME_TEXT_HEIGHT (f) = FRAME_TEXT_HEIGHT (f) - FRAME_MENU_BAR_HEIGHT (f)
1297 - FRAME_TAB_BAR_HEIGHT (f); 1363 - FRAME_TAB_BAR_HEIGHT (f);
1298 1364
1299 /* Set the top frame to the newly created frame. */ 1365 /* Mark current topmost frame obscured if we make a new root frame.
1300 if (FRAMEP (FRAME_TTY (f)->top_frame) 1366 Child frames don't completely obscure other frames. */
1301 && FRAME_LIVE_P (XFRAME (FRAME_TTY (f)->top_frame))) 1367 if (NILP (parent) && FRAMEP (FRAME_TTY (f)->top_frame))
1302 SET_FRAME_VISIBLE (XFRAME (FRAME_TTY (f)->top_frame), 2); /* obscured */ 1368 {
1303 1369 struct frame *top = XFRAME (FRAME_TTY (f)->top_frame);
1304 FRAME_TTY (f)->top_frame = frame; 1370 struct frame *root = root_frame (top);
1305 1371 if (FRAME_LIVE_P (root))
1306 if (!noninteractive) 1372 SET_FRAME_VISIBLE (root, false);
1307 init_frame_faces (f); 1373 }
1308 1374
1375 /* Set the top frame to the newly created frame. */
1376 if (!FRAME_PARENT_FRAME (f))
1377 FRAME_TTY (f)->top_frame = frame;
1309 return f; 1378 return f;
1310} 1379}
1311 1380
@@ -1335,6 +1404,62 @@ get_future_frame_param (Lisp_Object parameter,
1335 1404
1336#endif 1405#endif
1337 1406
1407static int
1408tty_child_pos_param (struct frame *child, Lisp_Object key,
1409 Lisp_Object params, int dflt)
1410{
1411 Lisp_Object val = Fassq (key, params);
1412 if (CONSP (val))
1413 {
1414 val = XCDR (val);
1415 if (FIXNUMP (val))
1416 return XFIXNUM (val);
1417 }
1418 return dflt;
1419}
1420
1421static int
1422tty_child_size_param (struct frame *child, Lisp_Object key,
1423 Lisp_Object params, int dflt)
1424{
1425 Lisp_Object val = Fassq (key, params);
1426 if (CONSP (val))
1427 {
1428 val = XCDR (val);
1429 if (CONSP (val))
1430 {
1431 /* Width and height may look like (width text-pixels
1432 . PIXELS) on window systems. Mimic that. */
1433 val = XCDR (val);
1434 if (EQ (val, Qtext_pixels))
1435 val = XCDR (val);
1436 }
1437 else if (FLOATP (val))
1438 {
1439 /* Width and height may be a float, in which case
1440 it's a multiple of the parent's value. */
1441 struct frame *parent = FRAME_PARENT_FRAME (child);
1442 int sz = (EQ (key, Qwidth) ? FRAME_TOTAL_COLS (parent)
1443 : FRAME_TOTAL_LINES (parent));
1444 val = make_fixnum (XFLOAT_DATA (val) * sz);
1445 }
1446
1447 if (FIXNUMP (val) && XFIXNUM (val) > 0)
1448 return XFIXNUM (val);
1449 }
1450 return dflt;
1451}
1452
1453static void
1454child_frame_rect (struct frame *f, Lisp_Object params,
1455 int *x, int *y, int *w, int *h)
1456{
1457 *x = tty_child_pos_param (f, Qleft, params, 0);
1458 *y = tty_child_pos_param (f, Qtop, params, 0);
1459 *w = tty_child_size_param (f, Qwidth, params, FRAME_TOTAL_COLS (f));
1460 *h = tty_child_size_param (f, Qheight, params, FRAME_TOTAL_LINES (f));
1461}
1462
1338DEFUN ("make-terminal-frame", Fmake_terminal_frame, Smake_terminal_frame, 1463DEFUN ("make-terminal-frame", Fmake_terminal_frame, Smake_terminal_frame,
1339 1, 1, 0, 1464 1, 1, 0,
1340 doc: /* Create an additional terminal frame, possibly on another terminal. 1465 doc: /* Create an additional terminal frame, possibly on another terminal.
@@ -1358,9 +1483,7 @@ affects all frames on the same terminal device. */)
1358 error ("Text terminals are not supported on this platform"); 1483 error ("Text terminals are not supported on this platform");
1359 return Qnil; 1484 return Qnil;
1360#else 1485#else
1361 struct frame *f;
1362 struct terminal *t = NULL; 1486 struct terminal *t = NULL;
1363 Lisp_Object frame;
1364 struct frame *sf = SELECTED_FRAME (); 1487 struct frame *sf = SELECTED_FRAME ();
1365 1488
1366#ifdef MSDOS 1489#ifdef MSDOS
@@ -1390,7 +1513,7 @@ affects all frames on the same terminal device. */)
1390 error ("Multiple terminals are not supported on this platform"); 1513 error ("Multiple terminals are not supported on this platform");
1391 if (!t) 1514 if (!t)
1392 t = the_only_display_info.terminal; 1515 t = the_only_display_info.terminal;
1393#endif 1516# endif
1394 } 1517 }
1395 1518
1396 if (!t) 1519 if (!t)
@@ -1417,19 +1540,67 @@ affects all frames on the same terminal device. */)
1417 SAFE_FREE (); 1540 SAFE_FREE ();
1418 } 1541 }
1419 1542
1420 f = make_terminal_frame (t); 1543 /* Make a new frame. We need to know upfront if if a parent frame is
1544 specified because we behave differently in this case, e.g. child
1545 frames don't obscure other frames. */
1546 Lisp_Object parent = Fcdr (Fassq (Qparent_frame, parms));
1547 struct frame *f = make_terminal_frame (t, parent, parms);
1421 1548
1422 { 1549 if (!noninteractive)
1423 int width, height; 1550 init_frame_faces (f);
1424 get_tty_size (fileno (FRAME_TTY (f)->input), &width, &height); 1551
1425 /* With INHIBIT 5 pass correct text height to adjust_frame_size. */ 1552 /* Visibility of root frames cannot be set with a frame parameter.
1426 adjust_frame_size (f, width, height - FRAME_TOP_MARGIN (f), 1553 Their visibility solely depends on whether or not they are the
1427 5, 0, Qterminal_frame); 1554 top_frame on the terminal. */
1428 } 1555 if (FRAME_PARENT_FRAME (f))
1556 {
1557 Lisp_Object visible = Fassq (Qvisibility, parms);
1558 if (CONSP (visible))
1559 SET_FRAME_VISIBLE (f, !NILP (visible));
1560
1561 /* FIXME/tty: The only way to get borders on a tty is
1562 to allow decorations for now. */
1563 Lisp_Object undecorated = Fassq (Qundecorated, parms);
1564 if (CONSP (undecorated) && !NILP (XCDR (undecorated)))
1565 f->undecorated = true;
1566
1567 /* FIXME/tty: The only way to get borders on a tty is
1568 to allow decorations for now. */
1569 Lisp_Object no_focus = Fassq (Qno_accept_focus, parms);
1570 if (CONSP (no_focus) && !NILP (XCDR (no_focus)))
1571 f->no_accept_focus = true;
1572
1573 /* FIXME/tty: The only way to get borders on a tty is
1574 to allow decorations for now. */
1575 Lisp_Object no_split = Fassq (Qunsplittable, parms);
1576 if (CONSP (no_split) && !NILP (XCDR (no_split)))
1577 f->no_split = true;
1578 }
1429 1579
1580 /* Determine width and height of the frame. For root frames use the
1581 width/height of the terminal. For child frames, take it from frame
1582 parameters. Note that a default (80x25) has been set in
1583 make_frame. We handle root frames in this way because otherwise we
1584 would end up needing glyph matrices for the terminal, which is both
1585 more work and has its downsides (think of clipping frames to the
1586 terminal size). */
1587 int x = 0, y = 0, width, height;
1588 if (FRAME_PARENT_FRAME (f))
1589 child_frame_rect (f, parms, &x, &y, &width, &height);
1590 else
1591 get_tty_size (fileno (FRAME_TTY (f)->input), &width, &height);
1592 adjust_frame_size (f, width, height - FRAME_TOP_MARGIN (f), 5, 0,
1593 Qterminal_frame);
1430 adjust_frame_glyphs (f); 1594 adjust_frame_glyphs (f);
1595
1431 calculate_costs (f); 1596 calculate_costs (f);
1432 XSETFRAME (frame, f); 1597
1598 f->left_pos = x;
1599 f->top_pos = y;
1600 store_in_alist (&parms, Qleft, make_fixnum (x));
1601 store_in_alist (&parms, Qtop, make_fixnum (y));
1602 store_in_alist (&parms, Qwidth, make_fixnum (width));
1603 store_in_alist (&parms, Qheight, make_fixnum (height));
1433 1604
1434 store_in_alist (&parms, Qtty_type, build_string (t->display_info.tty->type)); 1605 store_in_alist (&parms, Qtty_type, build_string (t->display_info.tty->type));
1435 store_in_alist (&parms, Qtty, 1606 store_in_alist (&parms, Qtty,
@@ -1451,7 +1622,11 @@ affects all frames on the same terminal device. */)
1451 /* On terminal frames the `minibuffer' frame parameter is always 1622 /* On terminal frames the `minibuffer' frame parameter is always
1452 virtually t. Avoid that a different value in parms causes 1623 virtually t. Avoid that a different value in parms causes
1453 complaints, see Bug#24758. */ 1624 complaints, see Bug#24758. */
1454 store_in_alist (&parms, Qminibuffer, Qt); 1625 if (!FRAME_PARENT_FRAME (f))
1626 store_in_alist (&parms, Qminibuffer, Qt);
1627
1628 Lisp_Object frame;
1629 XSETFRAME (frame, f);
1455 Fmodify_frame_parameters (frame, parms); 1630 Fmodify_frame_parameters (frame, parms);
1456 1631
1457 f->can_set_window_size = true; 1632 f->can_set_window_size = true;
@@ -1480,8 +1655,6 @@ affects all frames on the same terminal device. */)
1480Lisp_Object 1655Lisp_Object
1481do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object norecord) 1656do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object norecord)
1482{ 1657{
1483 struct frame *sf = SELECTED_FRAME (), *f;
1484
1485 /* If FRAME is a switch-frame event, extract the frame we should 1658 /* If FRAME is a switch-frame event, extract the frame we should
1486 switch to. */ 1659 switch to. */
1487 if (CONSP (frame) 1660 if (CONSP (frame)
@@ -1493,7 +1666,9 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor
1493 a switch-frame event to arrive after a frame is no longer live, 1666 a switch-frame event to arrive after a frame is no longer live,
1494 especially when deleting the initial frame during startup. */ 1667 especially when deleting the initial frame during startup. */
1495 CHECK_FRAME (frame); 1668 CHECK_FRAME (frame);
1496 f = XFRAME (frame); 1669 struct frame *f = XFRAME (frame);
1670 struct frame *sf = SELECTED_FRAME ();
1671
1497 /* Silently ignore dead and tooltip frames (Bug#47207). */ 1672 /* Silently ignore dead and tooltip frames (Bug#47207). */
1498 if (!FRAME_LIVE_P (f) || FRAME_TOOLTIP_P (f)) 1673 if (!FRAME_LIVE_P (f) || FRAME_TOOLTIP_P (f))
1499 return Qnil; 1674 return Qnil;
@@ -1546,24 +1721,37 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor
1546 struct tty_display_info *tty = FRAME_TTY (f); 1721 struct tty_display_info *tty = FRAME_TTY (f);
1547 Lisp_Object top_frame = tty->top_frame; 1722 Lisp_Object top_frame = tty->top_frame;
1548 1723
1549 /* Don't mark the frame garbaged and/or obscured if we are 1724 /* Don't mark the frame garbaged if we are switching to the frame
1550 switching to the frame that is already the top frame of that 1725 that is already the top frame of that TTY. */
1551 TTY. */
1552 if (!EQ (frame, top_frame)) 1726 if (!EQ (frame, top_frame))
1553 { 1727 {
1728 struct frame *new_root = root_frame (f);
1729 SET_FRAME_VISIBLE (new_root, true);
1730 SET_FRAME_VISIBLE (f, true);
1731
1732 /* Mark previously displayed frame as no longer visible. */
1554 if (FRAMEP (top_frame)) 1733 if (FRAMEP (top_frame))
1555 /* Mark previously displayed frame as now obscured. */ 1734 {
1556 SET_FRAME_VISIBLE (XFRAME (top_frame), 2); 1735 struct frame *top = XFRAME (top_frame);
1557 SET_FRAME_VISIBLE (f, 1); 1736 struct frame *old_root = root_frame (top);
1558 /* If the new TTY frame changed dimensions, we need to 1737 if (old_root != new_root)
1559 resync term.c's idea of the frame size with the new 1738 SET_FRAME_VISIBLE (old_root, false);
1560 frame's data. */ 1739 }
1561 if (FRAME_COLS (f) != FrameCols (tty)) 1740
1562 FrameCols (tty) = FRAME_COLS (f); 1741 tty->top_frame = frame;
1563 if (FRAME_TOTAL_LINES (f) != FrameRows (tty)) 1742
1564 FrameRows (tty) = FRAME_TOTAL_LINES (f); 1743 /* Why is it correct to set FrameCols/Rows? */
1744 if (!FRAME_PARENT_FRAME (f))
1745 {
1746 /* If the new TTY frame changed dimensions, we need to
1747 resync term.c's idea of the frame size with the new
1748 frame's data. */
1749 if (FRAME_COLS (f) != FrameCols (tty))
1750 FrameCols (tty) = FRAME_COLS (f);
1751 if (FRAME_TOTAL_LINES (f) != FrameRows (tty))
1752 FrameRows (tty) = FRAME_TOTAL_LINES (f);
1753 }
1565 } 1754 }
1566 tty->top_frame = frame;
1567 } 1755 }
1568 1756
1569 sf->select_mini_window_flag = MINI_WINDOW_P (XWINDOW (sf->selected_window)); 1757 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
1605 (select-window (frame-root-window (make-frame))) doesn't end up 1793 (select-window (frame-root-window (make-frame))) doesn't end up
1606 with your typing being interpreted in the new frame instead of 1794 with your typing being interpreted in the new frame instead of
1607 the one you're actually typing in. */ 1795 the one you're actually typing in. */
1608#ifdef HAVE_WINDOW_SYSTEM
1609 if (!frame_ancestor_p (f, sf)) 1796 if (!frame_ancestor_p (f, sf))
1610#endif
1611 internal_last_event_frame = Qnil; 1797 internal_last_event_frame = Qnil;
1612 1798
1613 return frame; 1799 return frame;
@@ -1725,7 +1911,6 @@ parent window is the window-system's root window) or an embedded window
1725 return Qnil; 1911 return Qnil;
1726} 1912}
1727 1913
1728#ifdef HAVE_WINDOW_SYSTEM
1729bool 1914bool
1730frame_ancestor_p (struct frame *af, struct frame *df) 1915frame_ancestor_p (struct frame *af, struct frame *df)
1731{ 1916{
@@ -1741,7 +1926,6 @@ frame_ancestor_p (struct frame *af, struct frame *df)
1741 1926
1742 return false; 1927 return false;
1743} 1928}
1744#endif
1745 1929
1746DEFUN ("frame-ancestor-p", Fframe_ancestor_p, Sframe_ancestor_p, 1930DEFUN ("frame-ancestor-p", Fframe_ancestor_p, Sframe_ancestor_p,
1747 2, 2, 0, 1931 2, 2, 0,
@@ -1752,15 +1936,10 @@ ANCESTOR and DESCENDANT must be live frames and default to the selected
1752frame. */) 1936frame. */)
1753 (Lisp_Object ancestor, Lisp_Object descendant) 1937 (Lisp_Object ancestor, Lisp_Object descendant)
1754{ 1938{
1755#ifdef HAVE_WINDOW_SYSTEM
1756 struct frame *af = decode_live_frame (ancestor); 1939 struct frame *af = decode_live_frame (ancestor);
1757 struct frame *df = decode_live_frame (descendant); 1940 struct frame *df = decode_live_frame (descendant);
1758
1759 return frame_ancestor_p (af, df) ? Qt : Qnil; 1941 return frame_ancestor_p (af, df) ? Qt : Qnil;
1760#else 1942}
1761 return Qnil;
1762#endif
1763 }
1764 1943
1765/* Return CANDIDATE if it can be used as 'other-than-FRAME' frame on the 1944/* Return CANDIDATE if it can be used as 'other-than-FRAME' frame on the
1766 same tty (for tty frames) or among frames which uses FRAME's keyboard. 1945 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)
2021 && (invisible || NILP (get_frame_param (f1, Qdelete_before))) 2200 && (invisible || NILP (get_frame_param (f1, Qdelete_before)))
2022 /* For invisibility and normal deletions, at least one 2201 /* For invisibility and normal deletions, at least one
2023 visible or iconified frame must remain (Bug#26682). */ 2202 visible or iconified frame must remain (Bug#26682). */
2024 && (FRAME_VISIBLE_P (f1) || FRAME_ICONIFIED_P (f1) 2203 && (FRAME_VISIBLE_P (f1)
2204 || is_tty_frame (f1)
2205 || FRAME_ICONIFIED_P (f1)
2025 || (!invisible 2206 || (!invisible
2026 && (force 2207 && (force
2027 /* Allow deleting the terminal frame when at 2208 /* Allow deleting the terminal frame when at
@@ -2282,7 +2463,7 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
2282 fset_root_window (f, Qnil); 2463 fset_root_window (f, Qnil);
2283 2464
2284 Vframe_list = Fdelq (frame, Vframe_list); 2465 Vframe_list = Fdelq (frame, Vframe_list);
2285 SET_FRAME_VISIBLE (f, 0); 2466 SET_FRAME_VISIBLE (f, false);
2286 2467
2287 /* Allow the vector of menu bar contents to be freed in the next 2468 /* Allow the vector of menu bar contents to be freed in the next
2288 garbage collection. The frame object itself may not be garbage 2469 garbage collection. The frame object itself may not be garbage
@@ -2868,6 +3049,12 @@ If omitted, FRAME defaults to the currently selected frame. */)
2868 if (FRAME_WINDOW_P (f) && FRAME_TERMINAL (f)->frame_visible_invisible_hook) 3049 if (FRAME_WINDOW_P (f) && FRAME_TERMINAL (f)->frame_visible_invisible_hook)
2869 FRAME_TERMINAL (f)->frame_visible_invisible_hook (f, true); 3050 FRAME_TERMINAL (f)->frame_visible_invisible_hook (f, true);
2870 3051
3052 if (is_tty_frame (f))
3053 {
3054 SET_FRAME_VISIBLE (f, true);
3055 tty_raise_lower_frame (f, true);
3056 }
3057
2871 make_frame_visible_1 (f->root_window); 3058 make_frame_visible_1 (f->root_window);
2872 3059
2873 /* Make menu bar update for the Buffers and Frames menus. */ 3060 /* Make menu bar update for the Buffers and Frames menus. */
@@ -2918,6 +3105,12 @@ displayed in the terminal. */)
2918 if (FRAME_WINDOW_P (f) && FRAME_TERMINAL (f)->frame_visible_invisible_hook) 3105 if (FRAME_WINDOW_P (f) && FRAME_TERMINAL (f)->frame_visible_invisible_hook)
2919 FRAME_TERMINAL (f)->frame_visible_invisible_hook (f, false); 3106 FRAME_TERMINAL (f)->frame_visible_invisible_hook (f, false);
2920 3107
3108 /* The Elisp info manual says that this "usually" makes child frames
3109 invisible, too, but without saying when not. Since users can't rely
3110 on this, it's not implemented. */
3111 if (is_tty_frame (f))
3112 SET_FRAME_VISIBLE (f, false);
3113
2921 /* Make menu bar update for the Buffers and Frames menus. */ 3114 /* Make menu bar update for the Buffers and Frames menus. */
2922 windows_or_buffers_changed = 16; 3115 windows_or_buffers_changed = 16;
2923 3116
@@ -2977,10 +3170,13 @@ currently being displayed on the terminal. */)
2977 (Lisp_Object frame) 3170 (Lisp_Object frame)
2978{ 3171{
2979 CHECK_LIVE_FRAME (frame); 3172 CHECK_LIVE_FRAME (frame);
3173 struct frame *f = XFRAME (frame);
2980 3174
2981 if (FRAME_VISIBLE_P (XFRAME (frame))) 3175 if (FRAME_VISIBLE_P (f))
2982 return Qt; 3176 return Qt;
2983 if (FRAME_ICONIFIED_P (XFRAME (frame))) 3177 else if (is_tty_root_frame (f))
3178 return Qt;
3179 if (FRAME_ICONIFIED_P (f))
2984 return Qicon; 3180 return Qicon;
2985 return Qnil; 3181 return Qnil;
2986} 3182}
@@ -3012,12 +3208,7 @@ doesn't support multiple overlapping frames, this function selects FRAME. */)
3012 3208
3013 XSETFRAME (frame, f); 3209 XSETFRAME (frame, f);
3014 3210
3015 if (FRAME_TERMCAP_P (f)) 3211 Fmake_frame_visible (frame);
3016 /* On a text terminal select FRAME. */
3017 Fselect_frame (frame, Qnil);
3018 else
3019 /* Do like the documentation says. */
3020 Fmake_frame_visible (frame);
3021 3212
3022 if (FRAME_TERMINAL (f)->frame_raise_lower_hook) 3213 if (FRAME_TERMINAL (f)->frame_raise_lower_hook)
3023 (*FRAME_TERMINAL (f)->frame_raise_lower_hook) (f, true); 3214 (*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)
3318 val = old_val; 3509 val = old_val;
3319 } 3510 }
3320 3511
3512 /* Re-parenting is currently not implemented when changing a root
3513 frame to a child frame or vice versa. */
3514 if (is_tty_frame (f) && EQ (prop, Qparent_frame))
3515 {
3516 if (NILP (f->parent_frame) != NILP (val))
3517 error ("Making a root frame a child or vice versa is not supported");
3518 f->parent_frame = val;
3519 }
3520
3321 /* The tty color needed to be set before the frame's parameter 3521 /* The tty color needed to be set before the frame's parameter
3322 alist was updated with the new value. This is not true any more, 3522 alist was updated with the new value. This is not true any more,
3323 but we still do this test early on. */ 3523 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.
3441 else 3641 else
3442#endif 3642#endif
3443 { 3643 {
3444 /* This ought to be correct in f->param_alist for an X frame. */ 3644 store_in_alist (&alist, Qmenu_bar_lines, make_fixnum (FRAME_MENU_BAR_LINES (f)));
3445 Lisp_Object lines; 3645 store_in_alist (&alist, Qtab_bar_lines, make_fixnum (FRAME_TAB_BAR_LINES (f)));
3446 3646 store_in_alist (&alist, Qvisibility, FRAME_VISIBLE_P (f) ? Qt : Qnil);
3447 XSETFASTINT (lines, FRAME_MENU_BAR_LINES (f)); 3647 store_in_alist (&alist, Qno_accept_focus, FRAME_NO_ACCEPT_FOCUS (f) ? Qt : Qnil);
3448 store_in_alist (&alist, Qmenu_bar_lines, lines);
3449 XSETFASTINT (lines, FRAME_TAB_BAR_LINES (f));
3450 store_in_alist (&alist, Qtab_bar_lines, lines);
3451 } 3648 }
3452 3649
3453 return alist; 3650 return alist;
@@ -3525,7 +3722,6 @@ If FRAME is nil, describe the currently selected frame. */)
3525 return value; 3722 return value;
3526} 3723}
3527 3724
3528
3529DEFUN ("modify-frame-parameters", Fmodify_frame_parameters, 3725DEFUN ("modify-frame-parameters", Fmodify_frame_parameters,
3530 Smodify_frame_parameters, 2, 2, 0, 3726 Smodify_frame_parameters, 2, 2, 0,
3531 doc: /* Modify FRAME according to new values of its parameters in ALIST. 3727 doc: /* Modify FRAME according to new values of its parameters in ALIST.
@@ -3563,6 +3759,7 @@ list, but are otherwise ignored. */)
3563 USE_SAFE_ALLOCA; 3759 USE_SAFE_ALLOCA;
3564 SAFE_ALLOCA_LISP (parms, 2 * length); 3760 SAFE_ALLOCA_LISP (parms, 2 * length);
3565 values = parms + length; 3761 values = parms + length;
3762 Lisp_Object params = alist;
3566 3763
3567 /* Extract parm names and values into those vectors. */ 3764 /* Extract parm names and values into those vectors. */
3568 3765
@@ -3588,6 +3785,31 @@ list, but are otherwise ignored. */)
3588 update_face_from_frame_parameter (f, prop, val); 3785 update_face_from_frame_parameter (f, prop, val);
3589 } 3786 }
3590 3787
3788 if (is_tty_child_frame (f))
3789 {
3790 int x = tty_child_pos_param (f, Qleft, params, f->left_pos);
3791 int y = tty_child_pos_param (f, Qtop, params, f->top_pos);
3792 if (x != f->left_pos || y != f->top_pos)
3793 {
3794 f->left_pos = x;
3795 f->top_pos = y;
3796 SET_FRAME_GARBAGED (root_frame (f));
3797 }
3798
3799 int w = tty_child_size_param (f, Qwidth, params, f->total_cols);
3800 int h = tty_child_size_param (f, Qheight, params, f->total_lines);
3801 if (w != f->total_cols || h != f->total_lines)
3802 change_frame_size (f, w, h, false, false, false);
3803
3804 Lisp_Object visible = Fassq (Qvisibility, params);
3805 if (CONSP (visible))
3806 SET_FRAME_VISIBLE (f, !NILP (Fcdr (visible)));
3807
3808 Lisp_Object no_special = Fassq (Qno_special_glyphs, params);
3809 if (CONSP (no_special))
3810 FRAME_NO_SPECIAL_GLYPHS (f) = !NILP (Fcdr (no_special));
3811 }
3812
3591 SAFE_FREE (); 3813 SAFE_FREE ();
3592 } 3814 }
3593 return Qnil; 3815 return Qnil;
@@ -3935,6 +4157,11 @@ bottom edge of FRAME's display. */)
3935 (void) yval; 4157 (void) yval;
3936#endif 4158#endif
3937 } 4159 }
4160 else if (is_tty_child_frame (f))
4161 {
4162 f->left_pos = xval;
4163 f->top_pos = yval;
4164 }
3938 4165
3939 return Qt; 4166 return Qt;
3940} 4167}
@@ -4246,6 +4473,28 @@ frame_float (struct frame *f, Lisp_Object val, enum frame_float_type what,
4246 } 4473 }
4247} 4474}
4248 4475
4476/* Handle frame parameter change with frame parameter handler. F is the
4477 frame whose frame parameter was changed. PROP is the name of the
4478 frame parameter. VAL and OLD_VALUE are the current value and old
4479 value of the frame parameter. */
4480
4481static void
4482handle_frame_param (struct frame *f, Lisp_Object prop, Lisp_Object val,
4483 Lisp_Object old_value)
4484{
4485 Lisp_Object param_index = Fget (prop, Qx_frame_parameter);
4486 if (FIXNATP (param_index) && XFIXNAT (param_index) < ARRAYELTS (frame_parms))
4487 {
4488 if (FRAME_RIF (f))
4489 {
4490 frame_parm_handler handler
4491 = FRAME_RIF (f)->frame_parm_handlers[XFIXNAT (param_index)];
4492 if (handler)
4493 handler (f, val, old_value);
4494 }
4495 }
4496}
4497
4249/* Change the parameters of frame F as specified by ALIST. 4498/* Change the parameters of frame F as specified by ALIST.
4250 If a parameter is not specially recognized, do nothing special; 4499 If a parameter is not specially recognized, do nothing special;
4251 otherwise call the `gui_set_...' function for that parameter. 4500 otherwise call the `gui_set_...' function for that parameter.
@@ -4387,17 +4636,9 @@ gui_set_frame_parameters_1 (struct frame *f, Lisp_Object alist,
4387 } 4636 }
4388 else 4637 else
4389 { 4638 {
4390 Lisp_Object param_index, old_value; 4639 Lisp_Object old_value = get_frame_param (f, prop);
4391
4392 old_value = get_frame_param (f, prop);
4393
4394 store_frame_param (f, prop, val); 4640 store_frame_param (f, prop, val);
4395 4641 handle_frame_param (f, prop, val, old_value);
4396 param_index = Fget (prop, Qx_frame_parameter);
4397 if (FIXNATP (param_index)
4398 && XFIXNAT (param_index) < ARRAYELTS (frame_parms)
4399 && FRAME_RIF (f)->frame_parm_handlers[XFIXNUM (param_index)])
4400 (*(FRAME_RIF (f)->frame_parm_handlers[XFIXNUM (param_index)])) (f, val, old_value);
4401 4642
4402 if (!default_parameter && EQ (prop, Qfont)) 4643 if (!default_parameter && EQ (prop, Qfont))
4403 /* The user manually specified the `font' frame parameter. 4644 /* 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
4716 /* Apply the new gamma value to the frame background. */ 4957 /* Apply the new gamma value to the frame background. */
4717 bgcolor = Fassq (Qbackground_color, f->param_alist); 4958 bgcolor = Fassq (Qbackground_color, f->param_alist);
4718 if (CONSP (bgcolor) && (bgcolor = XCDR (bgcolor), STRINGP (bgcolor))) 4959 if (CONSP (bgcolor) && (bgcolor = XCDR (bgcolor), STRINGP (bgcolor)))
4719 { 4960 handle_frame_param (f, Qbackground_color, bgcolor, Qnil);
4720 Lisp_Object parm_index = Fget (Qbackground_color, Qx_frame_parameter);
4721 if (FIXNATP (parm_index)
4722 && XFIXNAT (parm_index) < ARRAYELTS (frame_parms)
4723 && FRAME_RIF (f)->frame_parm_handlers[XFIXNAT (parm_index)])
4724 (*FRAME_RIF (f)->frame_parm_handlers[XFIXNAT (parm_index)])
4725 (f, bgcolor, Qnil);
4726 }
4727 4961
4728 clear_face_cache (true); /* FIXME: Why of all frames? */ 4962 clear_face_cache (true); /* FIXME: Why of all frames? */
4729 fset_redisplay (f); 4963 fset_redisplay (f);
diff --git a/src/frame.h b/src/frame.h
index 1d920d1a6bc..0b7368fb29b 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -161,10 +161,8 @@ struct frame
161 Usually it is nil. */ 161 Usually it is nil. */
162 Lisp_Object title; 162 Lisp_Object title;
163 163
164#if defined (HAVE_WINDOW_SYSTEM)
165 /* This frame's parent frame, if it has one. */ 164 /* This frame's parent frame, if it has one. */
166 Lisp_Object parent_frame; 165 Lisp_Object parent_frame;
167#endif /* HAVE_WINDOW_SYSTEM */
168 166
169 /* Last device to move over this frame. Any value that isn't a 167 /* Last device to move over this frame. Any value that isn't a
170 string means the "Virtual core pointer". */ 168 string means the "Virtual core pointer". */
@@ -385,15 +383,8 @@ struct frame
385 zero if the frame has been made invisible without an icon. */ 383 zero if the frame has been made invisible without an icon. */
386 384
387 /* Nonzero if the frame is currently displayed; we check 385 /* Nonzero if the frame is currently displayed; we check
388 it to see if we should bother updating the frame's contents. 386 it to see if we should bother updating the frame's contents. */
389 387 unsigned visible : 1;
390 On ttys and on Windows NT/9X, to avoid wasting effort updating
391 visible frames that are actually completely obscured by other
392 windows on the display, we bend the meaning of visible slightly:
393 if equal to 2, then the frame is obscured - we still consider
394 it to be "visible" as seen from lisp, but we don't bother
395 updating it. */
396 unsigned visible : 2;
397 388
398 /* True if the frame is currently iconified. Do not 389 /* True if the frame is currently iconified. Do not
399 set this directly, use SET_FRAME_ICONIFIED instead. */ 390 set this directly, use SET_FRAME_ICONIFIED instead. */
@@ -451,7 +442,15 @@ struct frame
451 This must be the same as the terminal->type. */ 442 This must be the same as the terminal->type. */
452 ENUM_BF (output_method) output_method : 4; 443 ENUM_BF (output_method) output_method : 4;
453 444
445 /* True if this is an undecorated frame. */
446 bool_bf undecorated : 1;
447
448 /* Nonzero if this frame's window does not want to receive input focus
449 via mouse clicks or by moving the mouse into it. */
450 bool_bf no_accept_focus : 1;
451
454#ifdef HAVE_WINDOW_SYSTEM 452#ifdef HAVE_WINDOW_SYSTEM
453# ifndef HAVE_NTGUI
455 /* True if this frame is a tooltip frame. */ 454 /* True if this frame is a tooltip frame. */
456 bool_bf tooltip : 1; 455 bool_bf tooltip : 1;
457 456
@@ -465,10 +464,7 @@ struct frame
465 /* Nonzero if we should actually display horizontal scroll bars on this frame. */ 464 /* Nonzero if we should actually display horizontal scroll bars on this frame. */
466 bool_bf horizontal_scroll_bars : 1; 465 bool_bf horizontal_scroll_bars : 1;
467 466
468 /* True if this is an undecorated frame. */
469 bool_bf undecorated : 1;
470 467
471#ifndef HAVE_NTGUI
472 /* True if this is an override_redirect frame. */ 468 /* True if this is an override_redirect frame. */
473 bool_bf override_redirect : 1; 469 bool_bf override_redirect : 1;
474#endif 470#endif
@@ -480,17 +476,13 @@ struct frame
480 receive input focus when it is mapped. */ 476 receive input focus when it is mapped. */
481 bool_bf no_focus_on_map : 1; 477 bool_bf no_focus_on_map : 1;
482 478
483 /* Nonzero if this frame's window does not want to receive input focus
484 via mouse clicks or by moving the mouse into it. */
485 bool_bf no_accept_focus : 1;
486
487 /* The z-group this frame's window belongs to. */ 479 /* The z-group this frame's window belongs to. */
488 ENUM_BF (z_group) z_group : 2; 480 ENUM_BF (z_group) z_group : 2;
481#endif /* HAVE_WINDOW_SYSTEM */
489 482
490 /* Non-zero if display of truncation and continuation glyphs outside 483 /* Non-zero if display of truncation and continuation glyphs outside
491 the fringes is suppressed. */ 484 the fringes is suppressed. */
492 bool_bf no_special_glyphs : 1; 485 bool_bf no_special_glyphs : 1;
493#endif /* HAVE_WINDOW_SYSTEM */
494 486
495 /* True means set_window_size_hook requests can be processed for 487 /* True means set_window_size_hook requests can be processed for
496 this frame. */ 488 this frame. */
@@ -740,7 +732,10 @@ struct frame
740#ifdef HAVE_TEXT_CONVERSION 732#ifdef HAVE_TEXT_CONVERSION
741 /* Text conversion state used by certain input methods. */ 733 /* Text conversion state used by certain input methods. */
742 struct text_conversion_state conversion; 734 struct text_conversion_state conversion;
743#endif 735# endif
736
737 /* Z-order of child frames. */
738 int z_order;
744} GCALIGNED_STRUCT; 739} GCALIGNED_STRUCT;
745 740
746/* Most code should use these functions to set Lisp fields in struct frame. */ 741/* Most code should use these functions to set Lisp fields in struct frame. */
@@ -1021,9 +1016,11 @@ default_pixels_per_inch_y (void)
1021 does not have FRAME_DISPLAY_INFO. */ 1016 does not have FRAME_DISPLAY_INFO. */
1022#ifdef HAVE_WINDOW_SYSTEM 1017#ifdef HAVE_WINDOW_SYSTEM
1023#ifndef HAVE_ANDROID 1018#ifndef HAVE_ANDROID
1024# define MOUSE_HL_INFO(F) \ 1019# define MOUSE_HL_INFO(F) \
1025 (FRAME_WINDOW_P (F) \ 1020 (FRAME_WINDOW_P (F) \
1026 ? &FRAME_DISPLAY_INFO(F)->mouse_highlight \ 1021 ? (FRAME_OUTPUT_DATA (F) \
1022 ? &FRAME_DISPLAY_INFO (F)->mouse_highlight \
1023 : NULL) \
1027 : &(F)->output_data.tty->display_info->mouse_highlight) 1024 : &(F)->output_data.tty->display_info->mouse_highlight)
1028#else 1025#else
1029/* There is no "struct tty_output" on Android at all. */ 1026/* There is no "struct tty_output" on Android at all. */
@@ -1176,9 +1173,6 @@ default_pixels_per_inch_y (void)
1176 && FRAME_X_VISIBLE (f))) 1173 && FRAME_X_VISIBLE (f)))
1177#endif 1174#endif
1178 1175
1179/* True if frame F is currently visible but hidden. */
1180#define FRAME_OBSCURED_P(f) ((f)->visible > 1)
1181
1182/* True if frame F is currently iconified. */ 1176/* True if frame F is currently iconified. */
1183#define FRAME_ICONIFIED_P(f) (f)->iconified 1177#define FRAME_ICONIFIED_P(f) (f)->iconified
1184 1178
@@ -1243,21 +1237,23 @@ default_pixels_per_inch_y (void)
1243#define FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT(f) ((void) (f), 0) 1237#define FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT(f) ((void) (f), 0)
1244#endif /* HAVE_WINDOW_SYSTEM */ 1238#endif /* HAVE_WINDOW_SYSTEM */
1245 1239
1246#if defined (HAVE_WINDOW_SYSTEM) 1240INLINE struct frame *
1241FRAME_PARENT_FRAME (struct frame *f)
1242{
1243 return NILP (f->parent_frame) ? NULL : XFRAME (f->parent_frame);
1244}
1245
1247#define FRAME_UNDECORATED(f) ((f)->undecorated) 1246#define FRAME_UNDECORATED(f) ((f)->undecorated)
1247
1248#if defined (HAVE_WINDOW_SYSTEM)
1248#ifdef HAVE_NTGUI 1249#ifdef HAVE_NTGUI
1249#define FRAME_OVERRIDE_REDIRECT(f) ((void) (f), 0) 1250#define FRAME_OVERRIDE_REDIRECT(f) ((void) (f), 0)
1250#else 1251#else
1251#define FRAME_OVERRIDE_REDIRECT(f) ((f)->override_redirect) 1252#define FRAME_OVERRIDE_REDIRECT(f) ((f)->override_redirect)
1252#endif 1253#endif
1253#define FRAME_PARENT_FRAME(f) \
1254 (NILP ((f)->parent_frame) \
1255 ? NULL \
1256 : XFRAME ((f)->parent_frame))
1257#define FRAME_SKIP_TASKBAR(f) ((f)->skip_taskbar) 1254#define FRAME_SKIP_TASKBAR(f) ((f)->skip_taskbar)
1258#define FRAME_NO_FOCUS_ON_MAP(f) ((f)->no_focus_on_map) 1255#define FRAME_NO_FOCUS_ON_MAP(f) ((f)->no_focus_on_map)
1259#define FRAME_NO_ACCEPT_FOCUS(f) ((f)->no_accept_focus) 1256#define FRAME_NO_ACCEPT_FOCUS(f) ((f)->no_accept_focus)
1260#define FRAME_NO_SPECIAL_GLYPHS(f) ((f)->no_special_glyphs)
1261#define FRAME_Z_GROUP(f) ((f)->z_group) 1257#define FRAME_Z_GROUP(f) ((f)->z_group)
1262#define FRAME_Z_GROUP_NONE(f) ((f)->z_group == z_group_none) 1258#define FRAME_Z_GROUP_NONE(f) ((f)->z_group == z_group_none)
1263#define FRAME_Z_GROUP_ABOVE(f) ((f)->z_group == z_group_above) 1259#define FRAME_Z_GROUP_ABOVE(f) ((f)->z_group == z_group_above)
@@ -1270,13 +1266,10 @@ default_pixels_per_inch_y (void)
1270#define FRAME_NS_TRANSPARENT_TITLEBAR(f) ((f)->ns_transparent_titlebar) 1266#define FRAME_NS_TRANSPARENT_TITLEBAR(f) ((f)->ns_transparent_titlebar)
1271#endif 1267#endif
1272#else /* not HAVE_WINDOW_SYSTEM */ 1268#else /* not HAVE_WINDOW_SYSTEM */
1273#define FRAME_UNDECORATED(f) ((void) (f), 0)
1274#define FRAME_OVERRIDE_REDIRECT(f) ((void) (f), 0) 1269#define FRAME_OVERRIDE_REDIRECT(f) ((void) (f), 0)
1275#define FRAME_PARENT_FRAME(f) ((void) (f), NULL)
1276#define FRAME_SKIP_TASKBAR(f) ((void) (f), 0) 1270#define FRAME_SKIP_TASKBAR(f) ((void) (f), 0)
1277#define FRAME_NO_FOCUS_ON_MAP(f) ((void) (f), 0) 1271#define FRAME_NO_FOCUS_ON_MAP(f) ((void) (f), 0)
1278#define FRAME_NO_ACCEPT_FOCUS(f) ((void) (f), 0) 1272#define FRAME_NO_ACCEPT_FOCUS(f) ((void) (f), 0)
1279#define FRAME_NO_SPECIAL_GLYPHS(f) ((void) (f), 0)
1280#define FRAME_Z_GROUP(f) ((void) (f), z_group_none) 1273#define FRAME_Z_GROUP(f) ((void) (f), z_group_none)
1281#define FRAME_Z_GROUP_NONE(f) ((void) (f), true) 1274#define FRAME_Z_GROUP_NONE(f) ((void) (f), true)
1282#define FRAME_Z_GROUP_ABOVE(f) ((void) (f), false) 1275#define FRAME_Z_GROUP_ABOVE(f) ((void) (f), false)
@@ -1284,6 +1277,8 @@ default_pixels_per_inch_y (void)
1284#define FRAME_TOOLTIP_P(f) ((void) f, false) 1277#define FRAME_TOOLTIP_P(f) ((void) f, false)
1285#endif /* HAVE_WINDOW_SYSTEM */ 1278#endif /* HAVE_WINDOW_SYSTEM */
1286 1279
1280#define FRAME_NO_SPECIAL_GLYPHS(f) ((f)->no_special_glyphs)
1281
1287/* Whether horizontal scroll bars are currently enabled for frame F. */ 1282/* Whether horizontal scroll bars are currently enabled for frame F. */
1288#if USE_HORIZONTAL_SCROLL_BARS 1283#if USE_HORIZONTAL_SCROLL_BARS
1289#define FRAME_HAS_HORIZONTAL_SCROLL_BARS(f) \ 1284#define FRAME_HAS_HORIZONTAL_SCROLL_BARS(f) \
@@ -1445,9 +1440,8 @@ extern bool frame_garbaged;
1445 if some changes were applied to it while it wasn't visible (and hence 1440 if some changes were applied to it while it wasn't visible (and hence
1446 wasn't redisplayed). */ 1441 wasn't redisplayed). */
1447INLINE void 1442INLINE void
1448SET_FRAME_VISIBLE (struct frame *f, int v) 1443SET_FRAME_VISIBLE (struct frame *f, bool v)
1449{ 1444{
1450 eassert (0 <= v && v <= 2);
1451 if (v) 1445 if (v)
1452 { 1446 {
1453 if (v == 1 && f->visible != 1) 1447 if (v == 1 && f->visible != 1)
@@ -1504,13 +1498,14 @@ extern struct frame *decode_any_frame (Lisp_Object);
1504extern struct frame *make_initial_frame (void); 1498extern struct frame *make_initial_frame (void);
1505extern struct frame *make_frame (bool); 1499extern struct frame *make_frame (bool);
1506#ifdef HAVE_WINDOW_SYSTEM 1500#ifdef HAVE_WINDOW_SYSTEM
1507extern struct frame *make_minibuffer_frame (void);
1508extern struct frame *make_frame_without_minibuffer (Lisp_Object,
1509 struct kboard *,
1510 Lisp_Object);
1511extern bool display_available (void); 1501extern bool display_available (void);
1512#endif 1502#endif
1513 1503
1504struct frame *make_minibuffer_frame (void);
1505struct frame *
1506make_frame_without_minibuffer (Lisp_Object mini_window,
1507 KBOARD *kb, Lisp_Object display);
1508
1514INLINE bool 1509INLINE bool
1515window_system_available (struct frame *f) 1510window_system_available (struct frame *f)
1516{ 1511{
@@ -1522,6 +1517,8 @@ window_system_available (struct frame *f)
1522} 1517}
1523 1518
1524extern WINDOW_SYSTEM_RETURN void check_window_system (struct frame *); 1519extern WINDOW_SYSTEM_RETURN void check_window_system (struct frame *);
1520void check_tty (struct frame *f);
1521struct frame *decode_tty_frame (Lisp_Object frame);
1525extern void frame_make_pointer_invisible (struct frame *); 1522extern void frame_make_pointer_invisible (struct frame *);
1526extern void frame_make_pointer_visible (struct frame *); 1523extern void frame_make_pointer_visible (struct frame *);
1527extern Lisp_Object delete_frame (Lisp_Object, Lisp_Object); 1524extern Lisp_Object delete_frame (Lisp_Object, Lisp_Object);
@@ -1617,15 +1614,11 @@ FRAME_CHILD_FRAME_BORDER_WIDTH (struct frame *f)
1617INLINE int 1614INLINE int
1618FRAME_INTERNAL_BORDER_WIDTH (struct frame *f) 1615FRAME_INTERNAL_BORDER_WIDTH (struct frame *f)
1619{ 1616{
1620#ifdef HAVE_WINDOW_SYSTEM
1621 return (FRAME_PARENT_FRAME(f) 1617 return (FRAME_PARENT_FRAME(f)
1622 ? (FRAME_CHILD_FRAME_BORDER_WIDTH(f) >= 0 1618 ? (FRAME_CHILD_FRAME_BORDER_WIDTH(f) >= 0
1623 ? FRAME_CHILD_FRAME_BORDER_WIDTH(f) 1619 ? FRAME_CHILD_FRAME_BORDER_WIDTH(f)
1624 : frame_dimension (f->internal_border_width)) 1620 : frame_dimension (f->internal_border_width))
1625 : frame_dimension (f->internal_border_width)); 1621 : frame_dimension (f->internal_border_width));
1626#else
1627 return frame_dimension (f->internal_border_width);
1628#endif
1629} 1622}
1630 1623
1631/* Pixel-size of window divider lines. */ 1624/* Pixel-size of window divider lines. */
@@ -1880,7 +1873,6 @@ extern Lisp_Object gui_display_get_resource (Display_Info *,
1880extern void set_frame_menubar (struct frame *f, bool deep_p); 1873extern void set_frame_menubar (struct frame *f, bool deep_p);
1881extern void frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y); 1874extern void frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
1882extern void free_frame_menubar (struct frame *); 1875extern void free_frame_menubar (struct frame *);
1883extern bool frame_ancestor_p (struct frame *af, struct frame *df);
1884extern enum internal_border_part frame_internal_border_part (struct frame *f, int x, int y); 1876extern enum internal_border_part frame_internal_border_part (struct frame *f, int x, int y);
1885 1877
1886#if defined HAVE_X_WINDOWS 1878#if defined HAVE_X_WINDOWS
@@ -1907,6 +1899,8 @@ gui_set_bitmap_icon (struct frame *f)
1907#endif /* !HAVE_NS */ 1899#endif /* !HAVE_NS */
1908#endif /* HAVE_WINDOW_SYSTEM */ 1900#endif /* HAVE_WINDOW_SYSTEM */
1909 1901
1902extern bool frame_ancestor_p (struct frame *af, struct frame *df);
1903
1910INLINE void 1904INLINE void
1911flush_frame (struct frame *f) 1905flush_frame (struct frame *f)
1912{ 1906{
diff --git a/src/keyboard.c b/src/keyboard.c
index 6d28dca9aeb..bfb5fd3592b 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -5415,7 +5415,7 @@ static const char *const lispy_kana_keys[] =
5415 5415
5416/* You'll notice that this table is arranged to be conveniently 5416/* You'll notice that this table is arranged to be conveniently
5417 indexed by X Windows keysym values. */ 5417 indexed by X Windows keysym values. */
5418#ifdef HAVE_NS 5418#if defined HAVE_NS || !defined HAVE_WINDOW_SYSTEM
5419/* FIXME: Why are we using X11 keysym values for NS? */ 5419/* FIXME: Why are we using X11 keysym values for NS? */
5420static 5420static
5421#endif 5421#endif
diff --git a/src/minibuf.c b/src/minibuf.c
index 1f94e0e650e..c8267045397 100644
--- a/src/minibuf.c
+++ b/src/minibuf.c
@@ -913,7 +913,11 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt,
913 XWINDOW (minibuf_window)->cursor.hpos = 0; 913 XWINDOW (minibuf_window)->cursor.hpos = 0;
914 XWINDOW (minibuf_window)->cursor.x = 0; 914 XWINDOW (minibuf_window)->cursor.x = 0;
915 XWINDOW (minibuf_window)->must_be_updated_p = true; 915 XWINDOW (minibuf_window)->must_be_updated_p = true;
916 update_frame (XFRAME (selected_frame), true, true); 916 struct frame *sf = XFRAME (selected_frame);
917 update_frame (sf, true, true);
918 if (is_tty_frame (sf))
919 combine_updates_for_frame (sf, true, true);
920
917#ifndef HAVE_NTGUI 921#ifndef HAVE_NTGUI
918 flush_frame (XFRAME (XWINDOW (minibuf_window)->frame)); 922 flush_frame (XFRAME (XWINDOW (minibuf_window)->frame));
919#else 923#else
diff --git a/src/nsfns.m b/src/nsfns.m
index 3c012ca8f05..1055a4b37df 100644
--- a/src/nsfns.m
+++ b/src/nsfns.m
@@ -3351,7 +3351,7 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
3351 [nswindow orderFront: NSApp]; 3351 [nswindow orderFront: NSApp];
3352 [nswindow display]; 3352 [nswindow display];
3353 3353
3354 SET_FRAME_VISIBLE (tip_f, 1); 3354 SET_FRAME_VISIBLE (tip_f, true);
3355 unblock_input (); 3355 unblock_input ();
3356 3356
3357 goto start_timer; 3357 goto start_timer;
@@ -3534,7 +3534,7 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
3534 [nswindow orderFront: NSApp]; 3534 [nswindow orderFront: NSApp];
3535 [nswindow display]; 3535 [nswindow display];
3536 3536
3537 SET_FRAME_VISIBLE (tip_f, YES); 3537 SET_FRAME_VISIBLE (tip_f, true);
3538 FRAME_PIXEL_WIDTH (tip_f) = width; 3538 FRAME_PIXEL_WIDTH (tip_f) = width;
3539 FRAME_PIXEL_HEIGHT (tip_f) = height; 3539 FRAME_PIXEL_HEIGHT (tip_f) = height;
3540 unblock_input (); 3540 unblock_input ();
diff --git a/src/nsterm.m b/src/nsterm.m
index f68a22d9fbc..7ad794b6bdb 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -1505,7 +1505,7 @@ ns_make_frame_visible (struct frame *f)
1505 EmacsView *view = (EmacsView *)FRAME_NS_VIEW (f); 1505 EmacsView *view = (EmacsView *)FRAME_NS_VIEW (f);
1506 EmacsWindow *window = (EmacsWindow *)[view window]; 1506 EmacsWindow *window = (EmacsWindow *)[view window];
1507 1507
1508 SET_FRAME_VISIBLE (f, 1); 1508 SET_FRAME_VISIBLE (f, true);
1509 ns_raise_frame (f, ! FRAME_NO_FOCUS_ON_MAP (f)); 1509 ns_raise_frame (f, ! FRAME_NO_FOCUS_ON_MAP (f));
1510 1510
1511 /* Making a new frame from a fullscreen frame will make the new frame 1511 /* Making a new frame from a fullscreen frame will make the new frame
@@ -1550,7 +1550,7 @@ ns_make_frame_invisible (struct frame *f)
1550 check_window_system (f); 1550 check_window_system (f);
1551 view = FRAME_NS_VIEW (f); 1551 view = FRAME_NS_VIEW (f);
1552 [[view window] orderOut: NSApp]; 1552 [[view window] orderOut: NSApp];
1553 SET_FRAME_VISIBLE (f, 0); 1553 SET_FRAME_VISIBLE (f, false);
1554 SET_FRAME_ICONIFIED (f, 0); 1554 SET_FRAME_ICONIFIED (f, 0);
1555} 1555}
1556 1556
diff --git a/src/scroll.c b/src/scroll.c
index fd2a9e71207..1d01ae90d72 100644
--- a/src/scroll.c
+++ b/src/scroll.c
@@ -366,7 +366,7 @@ do_scrolling (struct frame *frame, struct glyph_matrix *current_matrix,
366 eassert (copy_from[k] >= 0 && copy_from[k] < window_size); 366 eassert (copy_from[k] >= 0 && copy_from[k] < window_size);
367 367
368 /* Perform the row swizzling. */ 368 /* Perform the row swizzling. */
369 mirrored_line_dance (current_matrix, unchanged_at_top, window_size, 369 mirrored_line_dance (frame, unchanged_at_top, window_size,
370 copy_from, retained_p); 370 copy_from, retained_p);
371 371
372 /* Some sanity checks if GLYPH_DEBUG is defined. */ 372 /* Some sanity checks if GLYPH_DEBUG is defined. */
@@ -780,7 +780,7 @@ do_direct_scrolling (struct frame *frame, struct glyph_matrix *current_matrix,
780 copy_from[i] gives the original line to copy to I, and 780 copy_from[i] gives the original line to copy to I, and
781 retained_p[copy_from[i]] is zero if line I in the new display is 781 retained_p[copy_from[i]] is zero if line I in the new display is
782 empty. */ 782 empty. */
783 mirrored_line_dance (current_matrix, unchanged_at_top, window_size, 783 mirrored_line_dance (frame, unchanged_at_top, window_size,
784 copy_from, retained_p); 784 copy_from, retained_p);
785 785
786 if (terminal_window_p) 786 if (terminal_window_p)
diff --git a/src/term.c b/src/term.c
index 1f524880054..330da251e18 100644
--- a/src/term.c
+++ b/src/term.c
@@ -65,11 +65,9 @@ static int been_here = -1;
65#ifndef HAVE_ANDROID 65#ifndef HAVE_ANDROID
66 66
67static void tty_set_scroll_region (struct frame *f, int start, int stop); 67static void tty_set_scroll_region (struct frame *f, int start, int stop);
68static void turn_on_face (struct frame *, int face_id); 68static void turn_on_face (struct frame *f, struct face *face);
69static void turn_off_face (struct frame *, int face_id); 69static void turn_off_face (struct frame *f, struct face *face);
70static void tty_turn_off_highlight (struct tty_display_info *); 70static void tty_turn_off_highlight (struct tty_display_info *);
71static void tty_show_cursor (struct tty_display_info *);
72static void tty_hide_cursor (struct tty_display_info *);
73static void tty_background_highlight (struct tty_display_info *tty); 71static void tty_background_highlight (struct tty_display_info *tty);
74static void clear_tty_hooks (struct terminal *terminal); 72static void clear_tty_hooks (struct terminal *terminal);
75static void set_tty_hooks (struct terminal *terminal); 73static void set_tty_hooks (struct terminal *terminal);
@@ -336,7 +334,7 @@ tty_toggle_highlight (struct tty_display_info *tty)
336 334
337/* Make cursor invisible. */ 335/* Make cursor invisible. */
338 336
339static void 337void
340tty_hide_cursor (struct tty_display_info *tty) 338tty_hide_cursor (struct tty_display_info *tty)
341{ 339{
342 if (tty->cursor_hidden == 0) 340 if (tty->cursor_hidden == 0)
@@ -353,7 +351,7 @@ tty_hide_cursor (struct tty_display_info *tty)
353 351
354/* Ensure that cursor is visible. */ 352/* Ensure that cursor is visible. */
355 353
356static void 354void
357tty_show_cursor (struct tty_display_info *tty) 355tty_show_cursor (struct tty_display_info *tty)
358{ 356{
359 if (tty->cursor_hidden) 357 if (tty->cursor_hidden)
@@ -788,13 +786,20 @@ tty_write_glyphs (struct frame *f, struct glyph *string, int len)
788 /* Identify a run of glyphs with the same face. */ 786 /* Identify a run of glyphs with the same face. */
789 int face_id = string->face_id; 787 int face_id = string->face_id;
790 788
789 /* FIXME/tty: it happens that a single glyph's frame is NULL. It
790 might depend on a tab bar line being present, then switching
791 from a buffer without header line to one with header line and
792 opening a child frame. */
793 struct frame *face_id_frame = string->frame ? string->frame : f;
794
791 for (n = 1; n < stringlen; ++n) 795 for (n = 1; n < stringlen; ++n)
792 if (string[n].face_id != face_id) 796 if (string[n].face_id != face_id || string[n].frame != face_id_frame)
793 break; 797 break;
794 798
795 /* Turn appearance modes of the face of the run on. */ 799 /* Turn appearance modes of the face of the run on. */
796 tty_highlight_if_desired (tty); 800 tty_highlight_if_desired (tty);
797 turn_on_face (f, face_id); 801 struct face *face = FACE_FROM_ID (face_id_frame, face_id);
802 turn_on_face (f, face);
798 803
799 if (n == stringlen) 804 if (n == stringlen)
800 /* This is the last run. */ 805 /* This is the last run. */
@@ -812,7 +817,7 @@ tty_write_glyphs (struct frame *f, struct glyph *string, int len)
812 string += n; 817 string += n;
813 818
814 /* Turn appearance modes off. */ 819 /* Turn appearance modes off. */
815 turn_off_face (f, face_id); 820 turn_off_face (f, face);
816 tty_turn_off_highlight (tty); 821 tty_turn_off_highlight (tty);
817 } 822 }
818 823
@@ -822,8 +827,8 @@ tty_write_glyphs (struct frame *f, struct glyph *string, int len)
822#ifndef DOS_NT 827#ifndef DOS_NT
823 828
824static void 829static void
825tty_write_glyphs_with_face (register struct frame *f, register struct glyph *string, 830tty_write_glyphs_with_face (struct frame *f, struct glyph *string,
826 register int len, register int face_id) 831 int len, struct face *face)
827{ 832{
828 unsigned char *conversion_buffer; 833 unsigned char *conversion_buffer;
829 struct coding_system *coding; 834 struct coding_system *coding;
@@ -856,7 +861,7 @@ tty_write_glyphs_with_face (register struct frame *f, register struct glyph *str
856 861
857 /* Turn appearance modes of the face. */ 862 /* Turn appearance modes of the face. */
858 tty_highlight_if_desired (tty); 863 tty_highlight_if_desired (tty);
859 turn_on_face (f, face_id); 864 turn_on_face (f, face);
860 865
861 coding->mode |= CODING_MODE_LAST_BLOCK; 866 coding->mode |= CODING_MODE_LAST_BLOCK;
862 conversion_buffer = encode_terminal_code (string, len, coding); 867 conversion_buffer = encode_terminal_code (string, len, coding);
@@ -871,7 +876,7 @@ tty_write_glyphs_with_face (register struct frame *f, register struct glyph *str
871 } 876 }
872 877
873 /* Turn appearance modes off. */ 878 /* Turn appearance modes off. */
874 turn_off_face (f, face_id); 879 turn_off_face (f, face);
875 tty_turn_off_highlight (tty); 880 tty_turn_off_highlight (tty);
876 881
877 cmcheckmagic (tty); 882 cmcheckmagic (tty);
@@ -919,6 +924,7 @@ tty_insert_glyphs (struct frame *f, struct glyph *start, int len)
919 924
920 while (len-- > 0) 925 while (len-- > 0)
921 { 926 {
927 struct face *face = NULL;
922 OUTPUT1_IF (tty, tty->TS_ins_char); 928 OUTPUT1_IF (tty, tty->TS_ins_char);
923 if (!start) 929 if (!start)
924 { 930 {
@@ -928,7 +934,10 @@ tty_insert_glyphs (struct frame *f, struct glyph *start, int len)
928 else 934 else
929 { 935 {
930 tty_highlight_if_desired (tty); 936 tty_highlight_if_desired (tty);
931 turn_on_face (f, start->face_id); 937 int face_id = start->face_id;
938 struct frame *face_id_frame = start->frame;
939 face = FACE_FROM_ID (face_id_frame, face_id);
940 turn_on_face (f, face);
932 glyph = start; 941 glyph = start;
933 ++start; 942 ++start;
934 /* We must open sufficient space for a character which 943 /* We must open sufficient space for a character which
@@ -957,9 +966,9 @@ tty_insert_glyphs (struct frame *f, struct glyph *start, int len)
957 } 966 }
958 967
959 OUTPUT1_IF (tty, tty->TS_pad_inserted_char); 968 OUTPUT1_IF (tty, tty->TS_pad_inserted_char);
960 if (start) 969 if (face)
961 { 970 {
962 turn_off_face (f, glyph->face_id); 971 turn_off_face (f, face);
963 tty_turn_off_highlight (tty); 972 tty_turn_off_highlight (tty);
964 } 973 }
965 } 974 }
@@ -1542,6 +1551,7 @@ append_glyph (struct it *it)
1542 glyph->type = CHAR_GLYPH; 1551 glyph->type = CHAR_GLYPH;
1543 glyph->pixel_width = 1; 1552 glyph->pixel_width = 1;
1544 glyph->u.ch = it->char_to_display; 1553 glyph->u.ch = it->char_to_display;
1554 glyph->frame = it->f;
1545 glyph->face_id = it->face_id; 1555 glyph->face_id = it->face_id;
1546 glyph->avoid_cursor_p = it->avoid_cursor_p; 1556 glyph->avoid_cursor_p = it->avoid_cursor_p;
1547 glyph->multibyte_p = it->multibyte_p; 1557 glyph->multibyte_p = it->multibyte_p;
@@ -1769,6 +1779,7 @@ append_composite_glyph (struct it *it)
1769 1779
1770 glyph->avoid_cursor_p = it->avoid_cursor_p; 1780 glyph->avoid_cursor_p = it->avoid_cursor_p;
1771 glyph->multibyte_p = it->multibyte_p; 1781 glyph->multibyte_p = it->multibyte_p;
1782 glyph->frame = it->f;
1772 glyph->face_id = it->face_id; 1783 glyph->face_id = it->face_id;
1773 glyph->padding_p = false; 1784 glyph->padding_p = false;
1774 glyph->charpos = CHARPOS (it->position); 1785 glyph->charpos = CHARPOS (it->position);
@@ -1855,6 +1866,7 @@ append_glyphless_glyph (struct it *it, int face_id, const char *str)
1855 glyph->pixel_width = 1; 1866 glyph->pixel_width = 1;
1856 glyph->avoid_cursor_p = it->avoid_cursor_p; 1867 glyph->avoid_cursor_p = it->avoid_cursor_p;
1857 glyph->multibyte_p = it->multibyte_p; 1868 glyph->multibyte_p = it->multibyte_p;
1869 glyph->frame = it->f;
1858 glyph->face_id = face_id; 1870 glyph->face_id = face_id;
1859 glyph->padding_p = false; 1871 glyph->padding_p = false;
1860 glyph->charpos = CHARPOS (it->position); 1872 glyph->charpos = CHARPOS (it->position);
@@ -1981,9 +1993,8 @@ produce_glyphless_glyph (struct it *it, Lisp_Object acronym)
1981 FACE_ID is a realized face ID number, in the face cache. */ 1993 FACE_ID is a realized face ID number, in the face cache. */
1982 1994
1983static void 1995static void
1984turn_on_face (struct frame *f, int face_id) 1996turn_on_face (struct frame *f, struct face *face)
1985{ 1997{
1986 struct face *face = FACE_FROM_ID (f, face_id);
1987 unsigned long fg = face->foreground; 1998 unsigned long fg = face->foreground;
1988 unsigned long bg = face->background; 1999 unsigned long bg = face->background;
1989 struct tty_display_info *tty = FRAME_TTY (f); 2000 struct tty_display_info *tty = FRAME_TTY (f);
@@ -2064,9 +2075,8 @@ turn_on_face (struct frame *f, int face_id)
2064/* Turn off appearances of face FACE_ID on tty frame F. */ 2075/* Turn off appearances of face FACE_ID on tty frame F. */
2065 2076
2066static void 2077static void
2067turn_off_face (struct frame *f, int face_id) 2078turn_off_face (struct frame *f, struct face *face)
2068{ 2079{
2069 struct face *face = FACE_FROM_ID (f, face_id);
2070 struct tty_display_info *tty = FRAME_TTY (f); 2080 struct tty_display_info *tty = FRAME_TTY (f);
2071 2081
2072 if (tty->TS_exit_attribute_mode) 2082 if (tty->TS_exit_attribute_mode)
@@ -2399,8 +2409,10 @@ A suspended tty may be resumed by calling `resume-tty' on it. */)
2399 t->display_info.tty->output = 0; 2409 t->display_info.tty->output = 0;
2400 2410
2401 if (FRAMEP (t->display_info.tty->top_frame)) 2411 if (FRAMEP (t->display_info.tty->top_frame))
2402 SET_FRAME_VISIBLE (XFRAME (t->display_info.tty->top_frame), 0); 2412 {
2403 2413 struct frame *top = XFRAME (t->display_info.tty->top_frame);
2414 SET_FRAME_VISIBLE (root_frame (top), false);
2415 }
2404 } 2416 }
2405 2417
2406 /* Clear display hooks to prevent further output. */ 2418 /* Clear display hooks to prevent further output. */
@@ -2472,7 +2484,8 @@ frame's terminal). */)
2472 2484
2473 if (FRAMEP (t->display_info.tty->top_frame)) 2485 if (FRAMEP (t->display_info.tty->top_frame))
2474 { 2486 {
2475 struct frame *f = XFRAME (t->display_info.tty->top_frame); 2487 struct frame *top = XFRAME (t->display_info.tty->top_frame);
2488 struct frame *f = root_frame (top);
2476 int width, height; 2489 int width, height;
2477 int old_height = FRAME_COLS (f); 2490 int old_height = FRAME_COLS (f);
2478 int old_width = FRAME_TOTAL_LINES (f); 2491 int old_width = FRAME_TOTAL_LINES (f);
@@ -2482,7 +2495,7 @@ frame's terminal). */)
2482 get_tty_size (fileno (t->display_info.tty->input), &width, &height); 2495 get_tty_size (fileno (t->display_info.tty->input), &width, &height);
2483 if (width != old_width || height != old_height) 2496 if (width != old_width || height != old_height)
2484 change_frame_size (f, width, height, false, false, false); 2497 change_frame_size (f, width, height, false, false, false);
2485 SET_FRAME_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1); 2498 SET_FRAME_VISIBLE (f, true);
2486 } 2499 }
2487 2500
2488 set_tty_hooks (t); 2501 set_tty_hooks (t);
@@ -2563,22 +2576,24 @@ tty_draw_row_with_mouse_face (struct window *w, struct glyph_row *row,
2563 struct frame *f = XFRAME (WINDOW_FRAME (w)); 2576 struct frame *f = XFRAME (WINDOW_FRAME (w));
2564 struct tty_display_info *tty = FRAME_TTY (f); 2577 struct tty_display_info *tty = FRAME_TTY (f);
2565 int face_id = tty->mouse_highlight.mouse_face_face_id; 2578 int face_id = tty->mouse_highlight.mouse_face_face_id;
2566 int save_x, save_y, pos_x, pos_y;
2567 2579
2568 if (end_hpos >= row->used[TEXT_AREA]) 2580 if (end_hpos >= row->used[TEXT_AREA])
2569 nglyphs = row->used[TEXT_AREA] - start_hpos; 2581 nglyphs = row->used[TEXT_AREA] - start_hpos;
2570 2582
2571 pos_y = row->y + WINDOW_TOP_EDGE_Y (w); 2583 int pos_y = row->y + WINDOW_TOP_EDGE_Y (w);
2572 pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos + WINDOW_LEFT_EDGE_X (w); 2584 int pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos + WINDOW_LEFT_EDGE_X (w);
2573 2585
2574 /* Save current cursor coordinates. */ 2586 /* Save current cursor coordinates. */
2575 save_y = curY (tty); 2587 int save_y = curY (tty);
2576 save_x = curX (tty); 2588 int save_x = curX (tty);
2577 cursor_to (f, pos_y, pos_x); 2589 cursor_to (f, pos_y, pos_x);
2578 2590
2579 if (draw == DRAW_MOUSE_FACE) 2591 if (draw == DRAW_MOUSE_FACE)
2580 tty_write_glyphs_with_face (f, row->glyphs[TEXT_AREA] + start_hpos, 2592 {
2581 nglyphs, face_id); 2593 struct glyph *glyph = row->glyphs[TEXT_AREA] + start_hpos;
2594 struct face *face = FACE_FROM_ID (f, face_id);
2595 tty_write_glyphs_with_face (f, glyph, nglyphs, face);
2596 }
2582 else if (draw == DRAW_NORMAL_TEXT) 2597 else if (draw == DRAW_NORMAL_TEXT)
2583 write_glyphs (f, row->glyphs[TEXT_AREA] + start_hpos, nglyphs); 2598 write_glyphs (f, row->glyphs[TEXT_AREA] + start_hpos, nglyphs);
2584 2599
@@ -3969,7 +3984,7 @@ tty_free_frame_resources (struct frame *f)
3969 3984
3970#endif 3985#endif
3971 3986
3972 3987
3973 3988
3974#ifndef HAVE_ANDROID 3989#ifndef HAVE_ANDROID
3975 3990
@@ -4044,6 +4059,8 @@ set_tty_hooks (struct terminal *terminal)
4044 terminal->read_socket_hook = &tty_read_avail_input; /* keyboard.c */ 4059 terminal->read_socket_hook = &tty_read_avail_input; /* keyboard.c */
4045 terminal->delete_frame_hook = &tty_free_frame_resources; 4060 terminal->delete_frame_hook = &tty_free_frame_resources;
4046 terminal->delete_terminal_hook = &delete_tty; 4061 terminal->delete_terminal_hook = &delete_tty;
4062
4063 terminal->frame_raise_lower_hook = tty_raise_lower_frame;
4047 /* Other hooks are NULL by default. */ 4064 /* Other hooks are NULL by default. */
4048} 4065}
4049 4066
@@ -4714,6 +4731,184 @@ delete_tty (struct terminal *terminal)
4714 4731
4715#endif 4732#endif
4716 4733
4734/* Return geometric attributes of FRAME. According to the value of
4735 ATTRIBUTES return the outer edges of FRAME (Qouter_edges), the
4736 native edges of FRAME (Qnative_edges), or the inner edges of frame
4737 (Qinner_edges). Any other value means to return the geometry as
4738 returned by Fx_frame_geometry. */
4739
4740static Lisp_Object
4741tty_frame_geometry (Lisp_Object frame, Lisp_Object attribute)
4742{
4743 struct frame *f = decode_live_frame (frame);
4744 if (FRAME_INITIAL_P (f) || !FRAME_TTY (f))
4745 return Qnil;
4746
4747 int native_width = f->pixel_width;
4748 int native_height = f->pixel_height;
4749
4750 eassert (FRAME_PARENT_FRAME (f) || (f->left_pos == 0 && f->top_pos == 0));
4751 int outer_left = f->left_pos;
4752 int outer_top = f->top_pos;
4753 int outer_right = outer_left + native_width;
4754 int outer_bottom = outer_top + native_height;
4755
4756 int native_left = outer_left;
4757 int native_top = outer_top;
4758 int native_right = outer_right;
4759 int native_bottom = outer_bottom;
4760
4761 int internal_border_width = FRAME_INTERNAL_BORDER_WIDTH (f);
4762 int inner_left = native_left + internal_border_width;
4763 int inner_top = native_top + internal_border_width;
4764 int inner_right = native_right - internal_border_width;
4765 int inner_bottom = native_bottom - internal_border_width;
4766
4767 int menu_bar_height = FRAME_MENU_BAR_HEIGHT (f);
4768 inner_top += menu_bar_height;
4769 int menu_bar_width = menu_bar_height ? native_width : 0;
4770
4771 int tab_bar_height = FRAME_TAB_BAR_HEIGHT (f);
4772 int tab_bar_width = (tab_bar_height
4773 ? native_width - 2 * internal_border_width
4774 : 0);
4775 inner_top += tab_bar_height;
4776
4777 int tool_bar_height = FRAME_TOOL_BAR_HEIGHT (f);
4778 int tool_bar_width = (tool_bar_height
4779 ? native_width - 2 * internal_border_width
4780 : 0);
4781
4782 /* Subtract or add to the inner dimensions based on the tool bar
4783 position. */
4784 if (EQ (FRAME_TOOL_BAR_POSITION (f), Qtop))
4785 inner_top += tool_bar_height;
4786 else
4787 inner_bottom -= tool_bar_height;
4788
4789 /* Construct list. */
4790 if (EQ (attribute, Qouter_edges))
4791 return list4i (outer_left, outer_top, outer_right, outer_bottom);
4792 else if (EQ (attribute, Qnative_edges))
4793 return list4i (native_left, native_top, native_right, native_bottom);
4794 else if (EQ (attribute, Qinner_edges))
4795 return list4i (inner_left, inner_top, inner_right, inner_bottom);
4796 else
4797 return list (Fcons (Qouter_position, Fcons (make_fixnum (outer_left),
4798 make_fixnum (outer_top))),
4799 Fcons (Qouter_size,
4800 Fcons (make_fixnum (outer_right - outer_left),
4801 make_fixnum (outer_bottom - outer_top))),
4802 Fcons (Qouter_border_width, make_fixnum (0)),
4803 Fcons (Qexternal_border_size,
4804 Fcons (make_fixnum (0), make_fixnum (0))),
4805 Fcons (Qtitle_bar_size,
4806 Fcons (make_fixnum (0), make_fixnum (0))),
4807 Fcons (Qmenu_bar_external, Qnil),
4808 Fcons (Qmenu_bar_size,
4809 Fcons (make_fixnum (menu_bar_width),
4810 make_fixnum (menu_bar_height))),
4811 Fcons (Qtab_bar_size,
4812 Fcons (make_fixnum (tab_bar_width),
4813 make_fixnum (tab_bar_height))),
4814 Fcons (Qtool_bar_external, Qnil),
4815 Fcons (Qtool_bar_position, FRAME_TOOL_BAR_POSITION (f)),
4816 Fcons (Qtool_bar_size,
4817 Fcons (make_fixnum (tool_bar_width),
4818 make_fixnum (tool_bar_height))),
4819 Fcons (Qinternal_border_width,
4820 make_fixnum (internal_border_width)));
4821}
4822
4823DEFUN ("tty-frame-geometry", Ftty_frame_geometry, Stty_frame_geometry, 0, 1, 0,
4824 doc: /* Return geometric attributes of terminal frame FRAME.
4825 See also `frame-geometry'. */)
4826 (Lisp_Object frame)
4827{
4828 return tty_frame_geometry (frame, Qnil);
4829}
4830
4831DEFUN ("tty-frame-edges", Ftty_frame_edges, Stty_frame_edges, 0, 2, 0,
4832 doc: /* Return coordinates of FRAME's edges.
4833 See also `frame-edges'. */)
4834 (Lisp_Object frame, Lisp_Object type)
4835{
4836 if (!EQ (type, Qouter_edges) && !EQ (type, Qinner_edges))
4837 type = Qnative_edges;
4838 return tty_frame_geometry (frame, type);
4839}
4840
4841DEFUN ("tty-frame-list-z-order", Ftty_frame_list_z_order,
4842 Stty_frame_list_z_order, 0, 1, 0,
4843 doc: /* Return list of Emacs's frames, in Z (stacking) order.
4844 See also `frame-list-z-order'. */)
4845 (Lisp_Object frame)
4846{
4847 struct frame *f = decode_tty_frame (frame);
4848 Lisp_Object frames = frames_in_reverse_z_order (f, true);
4849 return Fnreverse (frames);
4850}
4851
4852DEFUN ("tty-frame-restack", Ftty_frame_restack,
4853 Stty_frame_restack, 2, 3, 0,
4854 doc: /* Restack FRAME1 below FRAME2 on terminals.
4855. See also `frame-restack'. */)
4856 (Lisp_Object frame1, Lisp_Object frame2, Lisp_Object above)
4857{
4858 /* FIXME/tty: tty-frame-restack implementation. */
4859 return Qnil;
4860}
4861
4862static void
4863tty_display_dimension (Lisp_Object frame, int *width, int *height)
4864{
4865 if (!FRAMEP (frame))
4866 frame = Fselected_frame ();
4867 struct frame *f = XFRAME (frame);
4868 switch (f->output_method)
4869 {
4870 case output_initial:
4871 *width = 80;
4872 *height = 25;
4873 break;
4874 case output_termcap:
4875 *width = FrameCols (FRAME_TTY (f));
4876 *height = FrameRows (FRAME_TTY (f));
4877 break;
4878 case output_x_window:
4879 case output_msdos_raw:
4880 case output_w32:
4881 case output_ns:
4882 case output_pgtk:
4883 case output_haiku:
4884 case output_android:
4885 emacs_abort ();
4886 break;
4887 }
4888}
4889
4890DEFUN ("tty-display-pixel-width", Ftty_display_pixel_width,
4891 Stty_display_pixel_width, 0, 1, 0,
4892 doc: /* Return the width of DISPLAY's screen in pixels.
4893. See also `display-pixel-width'. */)
4894 (Lisp_Object display)
4895{
4896 int width, height;
4897 tty_display_dimension (display, &width, &height);
4898 return make_fixnum (width);
4899}
4900
4901DEFUN ("tty-display-pixel-height", Ftty_display_pixel_height,
4902 Stty_display_pixel_height, 0, 1, 0,
4903 doc: /* Return the height of DISPLAY's screen in pixels.
4904 See also `display-pixel-height'. */)
4905 (Lisp_Object display)
4906{
4907 int width, height;
4908 tty_display_dimension (display, &width, &height);
4909 return make_fixnum (height);
4910}
4911
4717void 4912void
4718syms_of_term (void) 4913syms_of_term (void)
4719{ 4914{
@@ -4770,6 +4965,13 @@ trigger redisplay. */);
4770 defsubr (&Sgpm_mouse_stop); 4965 defsubr (&Sgpm_mouse_stop);
4771#endif /* HAVE_GPM */ 4966#endif /* HAVE_GPM */
4772 4967
4968 defsubr (&Stty_frame_geometry);
4969 defsubr (&Stty_frame_edges);
4970 defsubr (&Stty_frame_list_z_order);
4971 defsubr (&Stty_frame_restack);
4972 defsubr (&Stty_display_pixel_width);
4973 defsubr (&Stty_display_pixel_height);
4974
4773#if !defined DOS_NT && !defined HAVE_ANDROID 4975#if !defined DOS_NT && !defined HAVE_ANDROID
4774 default_orig_pair = NULL; 4976 default_orig_pair = NULL;
4775 default_set_foreground = NULL; 4977 default_set_foreground = NULL;
diff --git a/src/termhooks.h b/src/termhooks.h
index d6a9300bac9..1c2cd46e44e 100644
--- a/src/termhooks.h
+++ b/src/termhooks.h
@@ -974,6 +974,9 @@ extern int cursorY (struct tty_display_info *);
974#define cursorY(t) curY(t) 974#define cursorY(t) curY(t)
975#endif 975#endif
976 976
977void tty_hide_cursor (struct tty_display_info *tty);
978void tty_show_cursor (struct tty_display_info *tty);
979
977INLINE_HEADER_END 980INLINE_HEADER_END
978 981
979#endif /* EMACS_TERMHOOKS_H */ 982#endif /* EMACS_TERMHOOKS_H */
diff --git a/src/terminal.c b/src/terminal.c
index 5c21341d905..ad488ea3b52 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -111,7 +111,8 @@ void
111cursor_to (struct frame *f, int vpos, int hpos) 111cursor_to (struct frame *f, int vpos, int hpos)
112{ 112{
113 if (FRAME_TERMINAL (f)->cursor_to_hook) 113 if (FRAME_TERMINAL (f)->cursor_to_hook)
114 (*FRAME_TERMINAL (f)->cursor_to_hook) (f, vpos, hpos); 114 (*FRAME_TERMINAL (f)->cursor_to_hook) (f, vpos + f->top_pos,
115 hpos + f->left_pos);
115} 116}
116 117
117/* Similar but don't take any account of the wasted characters. */ 118/* Similar but don't take any account of the wasted characters. */
@@ -120,7 +121,8 @@ void
120raw_cursor_to (struct frame *f, int row, int col) 121raw_cursor_to (struct frame *f, int row, int col)
121{ 122{
122 if (FRAME_TERMINAL (f)->raw_cursor_to_hook) 123 if (FRAME_TERMINAL (f)->raw_cursor_to_hook)
123 (*FRAME_TERMINAL (f)->raw_cursor_to_hook) (f, row, col); 124 (*FRAME_TERMINAL (f)->raw_cursor_to_hook) (f, row + f->top_pos,
125 col + f->left_pos);
124} 126}
125 127
126/* Erase operations. */ 128/* Erase operations. */
diff --git a/src/xdisp.c b/src/xdisp.c
index c74e81a3933..935c75a8230 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -943,7 +943,7 @@ redisplay_trace (char const *fmt, ...)
943 { 943 {
944 va_list ap; 944 va_list ap;
945 va_start (ap, fmt); 945 va_start (ap, fmt);
946 vprintf (fmt, ap); 946 vfprintf (stderr, fmt, ap);
947 va_end (ap); 947 va_end (ap);
948 } 948 }
949} 949}
@@ -961,7 +961,7 @@ move_trace (char const *fmt, ...)
961 { 961 {
962 va_list ap; 962 va_list ap;
963 va_start (ap, fmt); 963 va_start (ap, fmt);
964 vprintf (fmt, ap); 964 vfprintf (stderr, fmt, ap);
965 va_end (ap); 965 va_end (ap);
966 } 966 }
967} 967}
@@ -3348,9 +3348,7 @@ init_iterator (struct it *it, struct window *w,
3348 of the iterator's frame, when set, suppresses their display - by 3348 of the iterator's frame, when set, suppresses their display - by
3349 default for tooltip frames and when set via the 'no-special-glyphs' 3349 default for tooltip frames and when set via the 'no-special-glyphs'
3350 frame parameter. */ 3350 frame parameter. */
3351#ifdef HAVE_WINDOW_SYSTEM 3351 if (!it->f->no_special_glyphs)
3352 if (!(FRAME_WINDOW_P (it->f) && it->f->no_special_glyphs))
3353#endif
3354 { 3352 {
3355 if (it->line_wrap == TRUNCATE) 3353 if (it->line_wrap == TRUNCATE)
3356 { 3354 {
@@ -13554,7 +13552,11 @@ echo_area_display (bool update_frame_p)
13554 flush_frame (f); 13552 flush_frame (f);
13555 } 13553 }
13556 else 13554 else
13557 update_frame (f, true, true); 13555 {
13556 update_frame (f, true, true);
13557 if (is_tty_frame (f))
13558 combine_updates_for_frame (f, true, true);
13559 }
13558 13560
13559 /* If cursor is in the echo area, make sure that the next 13561 /* If cursor is in the echo area, make sure that the next
13560 redisplay displays the minibuffer, so that the cursor will 13562 redisplay displays the minibuffer, so that the cursor will
@@ -17033,6 +17035,9 @@ redisplay_internal (void)
17033 if (face_change) 17035 if (face_change)
17034 windows_or_buffers_changed = 47; 17036 windows_or_buffers_changed = 47;
17035 17037
17038 /* Can we do better for tty child frames? It could be
17039 a bit faster when we switch between child frames of the same
17040 root frame. OTOH, it's probably not a frequent use case. */
17036 if ((FRAME_TERMCAP_P (sf) || FRAME_MSDOS_P (sf)) 17041 if ((FRAME_TERMCAP_P (sf) || FRAME_MSDOS_P (sf))
17037 && FRAME_TTY (sf)->previous_frame != sf) 17042 && FRAME_TTY (sf)->previous_frame != sf)
17038 { 17043 {
@@ -17055,6 +17060,7 @@ redisplay_internal (void)
17055 { 17060 {
17056 struct frame *f = XFRAME (frame); 17061 struct frame *f = XFRAME (frame);
17057 17062
17063 /* FRAME_REDISPLAY_P true basically means the frame is visible. */
17058 if (FRAME_REDISPLAY_P (f)) 17064 if (FRAME_REDISPLAY_P (f))
17059 { 17065 {
17060 ++number_of_visible_frames; 17066 ++number_of_visible_frames;
@@ -17198,7 +17204,6 @@ redisplay_internal (void)
17198 && !current_buffer->clip_changed 17204 && !current_buffer->clip_changed
17199 && !current_buffer->prevent_redisplay_optimizations_p 17205 && !current_buffer->prevent_redisplay_optimizations_p
17200 && FRAME_REDISPLAY_P (XFRAME (w->frame)) 17206 && FRAME_REDISPLAY_P (XFRAME (w->frame))
17201 && !FRAME_OBSCURED_P (XFRAME (w->frame))
17202 && !XFRAME (w->frame)->cursor_type_changed 17207 && !XFRAME (w->frame)->cursor_type_changed
17203 && !XFRAME (w->frame)->face_change 17208 && !XFRAME (w->frame)->face_change
17204 /* Make sure recorded data applies to current buffer, etc. */ 17209 /* Make sure recorded data applies to current buffer, etc. */
@@ -17447,22 +17452,35 @@ redisplay_internal (void)
17447 17452
17448 propagate_buffer_redisplay (); 17453 propagate_buffer_redisplay ();
17449 17454
17455 Lisp_Object tty_root_frames = Qnil;
17450 FOR_EACH_FRAME (tail, frame) 17456 FOR_EACH_FRAME (tail, frame)
17451 { 17457 {
17452 struct frame *f = XFRAME (frame); 17458 struct frame *f = XFRAME (frame);
17453 17459
17454 /* We don't have to do anything for unselected terminal 17460 if (is_tty_frame (f))
17455 frames. */ 17461 {
17456 if ((FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f)) 17462 /* Ignore all invisble tty frames, children or root. */
17457 && !EQ (FRAME_TTY (f)->top_frame, frame)) 17463 if (!FRAME_VISIBLE_P (root_frame (f)))
17458 continue; 17464 continue;
17465
17466 /* Remember tty root frames seen. */
17467 if (!FRAME_PARENT_FRAME (f))
17468 {
17469 Lisp_Object found;
17470 for (found = tty_root_frames;
17471 CONSP (found) && !EQ (XCAR (found), frame);
17472 found = XCDR (found))
17473 ;
17474 if (!CONSP (found))
17475 tty_root_frames = Fcons (frame, tty_root_frames);
17476 }
17477 }
17459 17478
17460 retry_frame: 17479 retry_frame:
17461 if (FRAME_WINDOW_P (f) || FRAME_TERMCAP_P (f) || f == sf) 17480 if (FRAME_WINDOW_P (f) || FRAME_TERMCAP_P (f) || f == sf)
17462 { 17481 {
17463 bool gcscrollbars 17482 /* Only GC scrollbars when we redisplay the whole frame. */
17464 /* Only GC scrollbars when we redisplay the whole frame. */ 17483 bool gcscrollbars = f->redisplay || !REDISPLAY_SOME_P ();
17465 = f->redisplay || !REDISPLAY_SOME_P ();
17466 bool f_redisplay_flag = f->redisplay; 17484 bool f_redisplay_flag = f->redisplay;
17467 17485
17468 /* The X error handler may have deleted that frame before 17486 /* The X error handler may have deleted that frame before
@@ -17479,7 +17497,7 @@ redisplay_internal (void)
17479 if (gcscrollbars && FRAME_TERMINAL (f)->condemn_scroll_bars_hook) 17497 if (gcscrollbars && FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
17480 FRAME_TERMINAL (f)->condemn_scroll_bars_hook (f); 17498 FRAME_TERMINAL (f)->condemn_scroll_bars_hook (f);
17481 17499
17482 if (FRAME_REDISPLAY_P (f) && !FRAME_OBSCURED_P (f)) 17500 if (FRAME_REDISPLAY_P (f))
17483 { 17501 {
17484 /* Don't allow freeing images and faces for this 17502 /* Don't allow freeing images and faces for this
17485 frame as long as the frame's update wasn't 17503 frame as long as the frame's update wasn't
@@ -17505,7 +17523,7 @@ redisplay_internal (void)
17505 if (gcscrollbars && FRAME_TERMINAL (f)->judge_scroll_bars_hook) 17523 if (gcscrollbars && FRAME_TERMINAL (f)->judge_scroll_bars_hook)
17506 FRAME_TERMINAL (f)->judge_scroll_bars_hook (f); 17524 FRAME_TERMINAL (f)->judge_scroll_bars_hook (f);
17507 17525
17508 if (FRAME_REDISPLAY_P (f) && !FRAME_OBSCURED_P (f)) 17526 if (FRAME_REDISPLAY_P (f))
17509 { 17527 {
17510 /* If fonts changed on visible frame, display again. */ 17528 /* If fonts changed on visible frame, display again. */
17511 if (f->fonts_changed) 17529 if (f->fonts_changed)
@@ -17590,6 +17608,9 @@ redisplay_internal (void)
17590 } 17608 }
17591 } 17609 }
17592 17610
17611 if (CONSP (tty_root_frames))
17612 pending |= combine_updates (tty_root_frames, false, false);
17613
17593 eassert (EQ (XFRAME (selected_frame)->selected_window, selected_window)); 17614 eassert (EQ (XFRAME (selected_frame)->selected_window, selected_window));
17594 17615
17595 if (!pending) 17616 if (!pending)
@@ -17611,7 +17632,7 @@ redisplay_internal (void)
17611 } 17632 }
17612 } 17633 }
17613 } 17634 }
17614 else if (FRAME_REDISPLAY_P (sf) && !FRAME_OBSCURED_P (sf)) 17635 else if (FRAME_REDISPLAY_P (sf))
17615 { 17636 {
17616 sf->inhibit_clear_image_cache = true; 17637 sf->inhibit_clear_image_cache = true;
17617 displayed_buffer = XBUFFER (XWINDOW (selected_window)->contents); 17638 displayed_buffer = XBUFFER (XWINDOW (selected_window)->contents);
@@ -17662,7 +17683,7 @@ redisplay_internal (void)
17662 unrequest_sigio (); 17683 unrequest_sigio ();
17663 STOP_POLLING; 17684 STOP_POLLING;
17664 17685
17665 if (FRAME_REDISPLAY_P (sf) && !FRAME_OBSCURED_P (sf)) 17686 if (FRAME_REDISPLAY_P (sf))
17666 { 17687 {
17667 if (hscroll_retries <= MAX_HSCROLL_RETRIES 17688 if (hscroll_retries <= MAX_HSCROLL_RETRIES
17668 && hscroll_windows (selected_window)) 17689 && hscroll_windows (selected_window))
@@ -17673,6 +17694,10 @@ redisplay_internal (void)
17673 17694
17674 XWINDOW (selected_window)->must_be_updated_p = true; 17695 XWINDOW (selected_window)->must_be_updated_p = true;
17675 pending = update_frame (sf, false, false); 17696 pending = update_frame (sf, false, false);
17697
17698 if (is_tty_frame (sf))
17699 pending |= combine_updates_for_frame (sf, false, false);
17700
17676 sf->cursor_type_changed = false; 17701 sf->cursor_type_changed = false;
17677 sf->inhibit_clear_image_cache = false; 17702 sf->inhibit_clear_image_cache = false;
17678 } 17703 }
@@ -17685,10 +17710,12 @@ redisplay_internal (void)
17685 Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf); 17710 Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
17686 struct frame *mini_frame = XFRAME (WINDOW_FRAME (XWINDOW (mini_window))); 17711 struct frame *mini_frame = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
17687 17712
17688 if (mini_frame != sf && FRAME_WINDOW_P (mini_frame)) 17713 if (mini_frame != sf)
17689 { 17714 {
17690 XWINDOW (mini_window)->must_be_updated_p = true; 17715 XWINDOW (mini_window)->must_be_updated_p = true;
17691 pending |= update_frame (mini_frame, false, false); 17716 pending |= update_frame (mini_frame, false, false);
17717 if (is_tty_frame (mini_frame))
17718 pending |= combine_updates_for_frame (mini_frame, false, false);
17692 mini_frame->cursor_type_changed = false; 17719 mini_frame->cursor_type_changed = false;
17693 if (!pending && hscroll_retries <= MAX_HSCROLL_RETRIES 17720 if (!pending && hscroll_retries <= MAX_HSCROLL_RETRIES
17694 && hscroll_windows (mini_window)) 17721 && hscroll_windows (mini_window))
@@ -23975,6 +24002,7 @@ extend_face_to_end_of_line (struct it *it)
23975 { 24002 {
23976 it->glyph_row->glyphs[TEXT_AREA][0] = space_glyph; 24003 it->glyph_row->glyphs[TEXT_AREA][0] = space_glyph;
23977 it->glyph_row->glyphs[TEXT_AREA][0].face_id = face->id; 24004 it->glyph_row->glyphs[TEXT_AREA][0].face_id = face->id;
24005 it->glyph_row->glyphs[TEXT_AREA][0].frame = f;
23978 it->glyph_row->used[TEXT_AREA] = 1; 24006 it->glyph_row->used[TEXT_AREA] = 1;
23979 } 24007 }
23980 /* Mode line and the header line don't have margins, and 24008 /* Mode line and the header line don't have margins, and
@@ -23994,6 +24022,7 @@ extend_face_to_end_of_line (struct it *it)
23994 it->glyph_row->glyphs[LEFT_MARGIN_AREA][0] = space_glyph; 24022 it->glyph_row->glyphs[LEFT_MARGIN_AREA][0] = space_glyph;
23995 it->glyph_row->glyphs[LEFT_MARGIN_AREA][0].face_id = 24023 it->glyph_row->glyphs[LEFT_MARGIN_AREA][0].face_id =
23996 default_face->id; 24024 default_face->id;
24025 it->glyph_row->glyphs[LEFT_MARGIN_AREA][0].frame = f;
23997 it->glyph_row->used[LEFT_MARGIN_AREA] = 1; 24026 it->glyph_row->used[LEFT_MARGIN_AREA] = 1;
23998 } 24027 }
23999 if (WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0 24028 if (WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0
@@ -24002,6 +24031,7 @@ extend_face_to_end_of_line (struct it *it)
24002 it->glyph_row->glyphs[RIGHT_MARGIN_AREA][0] = space_glyph; 24031 it->glyph_row->glyphs[RIGHT_MARGIN_AREA][0] = space_glyph;
24003 it->glyph_row->glyphs[RIGHT_MARGIN_AREA][0].face_id = 24032 it->glyph_row->glyphs[RIGHT_MARGIN_AREA][0].face_id =
24004 default_face->id; 24033 default_face->id;
24034 it->glyph_row->glyphs[RIGHT_MARGIN_AREA][0].frame = f;
24005 it->glyph_row->used[RIGHT_MARGIN_AREA] = 1; 24035 it->glyph_row->used[RIGHT_MARGIN_AREA] = 1;
24006 } 24036 }
24007 24037
@@ -24366,9 +24396,11 @@ highlight_trailing_whitespace (struct it *it)
24366 while (glyph >= start 24396 while (glyph >= start
24367 && BUFFERP (glyph->object) 24397 && BUFFERP (glyph->object)
24368 && (glyph->type == STRETCH_GLYPH 24398 && (glyph->type == STRETCH_GLYPH
24369 || (glyph->type == CHAR_GLYPH 24399 || (glyph->type == CHAR_GLYPH && glyph->u.ch == ' ')))
24370 && glyph->u.ch == ' '))) 24400 {
24371 (glyph--)->face_id = face_id; 24401 glyph->frame = it->f;
24402 (glyph--)->face_id = face_id;
24403 }
24372 } 24404 }
24373 else 24405 else
24374 { 24406 {
@@ -24377,7 +24409,10 @@ highlight_trailing_whitespace (struct it *it)
24377 && (glyph->type == STRETCH_GLYPH 24409 && (glyph->type == STRETCH_GLYPH
24378 || (glyph->type == CHAR_GLYPH 24410 || (glyph->type == CHAR_GLYPH
24379 && glyph->u.ch == ' '))) 24411 && glyph->u.ch == ' ')))
24380 (glyph++)->face_id = face_id; 24412 {
24413 glyph->frame = it->f;
24414 (glyph++)->face_id = face_id;
24415 }
24381 } 24416 }
24382 } 24417 }
24383 } 24418 }
@@ -27230,7 +27265,7 @@ display_menu_bar (struct window *w)
27230 27265
27231/* Deep copy of a glyph row, including the glyphs. */ 27266/* Deep copy of a glyph row, including the glyphs. */
27232static void 27267static void
27233deep_copy_glyph_row (struct glyph_row *to, struct glyph_row *from) 27268deep_copy_glyph_row (struct frame *f, struct glyph_row *to, struct glyph_row *from)
27234{ 27269{
27235 struct glyph *pointers[1 + LAST_AREA]; 27270 struct glyph *pointers[1 + LAST_AREA];
27236 int to_used = to->used[TEXT_AREA]; 27271 int to_used = to->used[TEXT_AREA];
@@ -27251,7 +27286,7 @@ deep_copy_glyph_row (struct glyph_row *to, struct glyph_row *from)
27251 /* If we filled only part of the TO row, fill the rest with 27286 /* If we filled only part of the TO row, fill the rest with
27252 space_glyph (which will display as empty space). */ 27287 space_glyph (which will display as empty space). */
27253 if (to_used > from->used[TEXT_AREA]) 27288 if (to_used > from->used[TEXT_AREA])
27254 fill_up_frame_row_with_spaces (to, to_used); 27289 fill_up_frame_row_with_spaces (f, to, to_used);
27255} 27290}
27256 27291
27257/* Display one menu item on a TTY, by overwriting the glyphs in the 27292/* Display one menu item on a TTY, by overwriting the glyphs in the
@@ -27300,7 +27335,7 @@ display_tty_menu_item (const char *item_text, int width, int face_id,
27300 it.last_visible_x = FRAME_COLS (f) - 1; 27335 it.last_visible_x = FRAME_COLS (f) - 1;
27301 row = it.glyph_row; 27336 row = it.glyph_row;
27302 /* Start with the row contents from the current matrix. */ 27337 /* Start with the row contents from the current matrix. */
27303 deep_copy_glyph_row (row, f->current_matrix->rows + y); 27338 deep_copy_glyph_row (f, row, f->current_matrix->rows + y);
27304 bool saved_width = row->full_width_p; 27339 bool saved_width = row->full_width_p;
27305 row->full_width_p = true; 27340 row->full_width_p = true;
27306 bool saved_reversed = row->reversed_p; 27341 bool saved_reversed = row->reversed_p;
diff --git a/src/xfaces.c b/src/xfaces.c
index e248279e9b7..fd321734d14 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -696,7 +696,6 @@ void
696free_frame_faces (struct frame *f) 696free_frame_faces (struct frame *f)
697{ 697{
698 struct face_cache *face_cache = FRAME_FACE_CACHE (f); 698 struct face_cache *face_cache = FRAME_FACE_CACHE (f);
699
700 if (face_cache) 699 if (face_cache)
701 { 700 {
702 free_face_cache (face_cache); 701 free_face_cache (face_cache);