summaryrefslogtreecommitdiff
path: root/src/dispnew.c
diff options
context:
space:
mode:
authorStefan Monnier <monnier@iro.umontreal.ca>2022-09-25 16:15:16 -0400
committerStefan Monnier <monnier@iro.umontreal.ca>2022-09-25 16:15:16 -0400
commit650c20f1ca4e07591a727e1cfcc74b3363d15985 (patch)
tree85d11f6437cde22f410c25e0e5f71a3131ebd07d /src/dispnew.c
parent8869332684c2302b5ba1ead4568bbc7ba1c0183e (diff)
parent4b85ae6a24380fb67a3315eaec9233f17a872473 (diff)
downloademacs-650c20f1ca4e07591a727e1cfcc74b3363d15985.tar.gz
emacs-650c20f1ca4e07591a727e1cfcc74b3363d15985.tar.bz2
emacs-650c20f1ca4e07591a727e1cfcc74b3363d15985.zip
Merge 'master' into noverlay
Diffstat (limited to 'src/dispnew.c')
-rw-r--r--src/dispnew.c971
1 files changed, 748 insertions, 223 deletions
diff --git a/src/dispnew.c b/src/dispnew.c
index ad59704a168..b786f0f1ba4 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -1,6 +1,6 @@
/* Updating of data structures for redisplay.
-Copyright (C) 1985-1988, 1993-1995, 1997-2017 Free Software Foundation,
+Copyright (C) 1985-1988, 1993-1995, 1997-2022 Free Software Foundation,
Inc.
This file is part of GNU Emacs.
@@ -41,6 +41,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "systime.h"
#include "tparam.h"
#include "xwidget.h"
+#include "pdumper.h"
#ifdef HAVE_WINDOW_SYSTEM
#include TERM_HEADER
@@ -66,7 +67,7 @@ struct dim
/* Function prototypes. */
-static void update_frame_line (struct frame *, int);
+static void update_frame_line (struct frame *, int, bool);
static int required_matrix_height (struct window *);
static int required_matrix_width (struct window *);
static void increment_row_positions (struct glyph_row *, ptrdiff_t, ptrdiff_t);
@@ -78,7 +79,7 @@ static void adjust_decode_mode_spec_buffer (struct frame *);
static void fill_up_glyph_row_with_spaces (struct glyph_row *);
static void clear_window_matrices (struct window *, bool);
static void fill_up_glyph_row_area_with_spaces (struct glyph_row *, int);
-static int scrolling_window (struct window *, bool);
+static int scrolling_window (struct window *, int);
static bool update_window_line (struct window *, int, bool *);
static void mirror_make_current (struct window *, int);
#ifdef GLYPH_DEBUG
@@ -88,7 +89,7 @@ static void check_matrix_pointers (struct glyph_matrix *,
static void mirror_line_dance (struct window *, int, int, int *, char *);
static bool update_window_tree (struct window *, bool);
static bool update_window (struct window *, bool);
-static bool update_frame_1 (struct frame *, bool, bool, bool);
+static bool update_frame_1 (struct frame *, bool, bool, bool, bool);
static bool scrolling (struct frame *);
static void set_window_cursor_after_update (struct window *);
static void adjust_frame_glyphs_for_window_redisplay (struct frame *);
@@ -155,7 +156,7 @@ static int history_idx;
/* A tick that's incremented each time something is added to the
history. */
-static uprintmax_t history_tick;
+static uintmax_t history_tick;
/* Add to the redisplay history how window W has been displayed.
MSG is a trace containing the information how W's glyph matrix
@@ -174,7 +175,7 @@ add_window_display_history (struct window *w, const char *msg, bool paused_p)
++history_idx;
snprintf (buf, sizeof redisplay_history[0].trace,
- "%"pMu": window %p (%s)%s\n%s",
+ "%"PRIuMAX": window %p (%s)%s\n%s",
history_tick++,
ptr,
((BUFFERP (w->contents)
@@ -201,7 +202,7 @@ add_frame_display_history (struct frame *f, bool paused_p)
buf = redisplay_history[history_idx].trace;
++history_idx;
- sprintf (buf, "%"pMu": update frame %p%s",
+ sprintf (buf, "%"PRIuMAX": update frame %p%s",
history_tick++,
ptr, paused_p ? " ***paused***" : "");
}
@@ -233,9 +234,7 @@ DEFUN ("dump-redisplay-history", Fdump_redisplay_history,
#endif /* GLYPH_DEBUG */
-#if (defined PROFILING \
- && (defined __FreeBSD__ || defined GNU_LINUX || defined __MINGW32__) \
- && !HAVE___EXECUTABLE_START)
+#if defined PROFILING && !HAVE___EXECUTABLE_START
/* This function comes first in the Emacs executable and is used only
to estimate the text start for profiling. */
void
@@ -366,6 +365,8 @@ adjust_glyph_matrix (struct window *w, struct glyph_matrix *matrix, int x, int y
int i;
int new_rows;
bool marginal_areas_changed_p = 0;
+ bool tab_line_changed_p = 0;
+ bool tab_line_p = 0;
bool header_line_changed_p = 0;
bool header_line_p = 0;
int left = -1, right = -1;
@@ -377,9 +378,13 @@ adjust_glyph_matrix (struct window *w, struct glyph_matrix *matrix, int x, int y
{
window_box (w, ANY_AREA, 0, 0, &window_width, &window_height);
+ tab_line_p = window_wants_tab_line (w);
+ tab_line_changed_p = tab_line_p != matrix->tab_line_p;
+
header_line_p = window_wants_header_line (w);
header_line_changed_p = header_line_p != matrix->header_line_p;
}
+ matrix->tab_line_p = tab_line_p;
matrix->header_line_p = header_line_p;
/* If POOL is null, MATRIX is a window matrix for window-based redisplay.
@@ -397,6 +402,7 @@ adjust_glyph_matrix (struct window *w, struct glyph_matrix *matrix, int x, int y
if (!marginal_areas_changed_p
&& !XFRAME (w->frame)->fonts_changed
+ && !tab_line_changed_p
&& !header_line_changed_p
&& matrix->window_pixel_left == WINDOW_LEFT_PIXEL_EDGE (w)
&& matrix->window_pixel_top == WINDOW_TOP_PIXEL_EDGE (w)
@@ -448,7 +454,11 @@ adjust_glyph_matrix (struct window *w, struct glyph_matrix *matrix, int x, int y
if (w == NULL
|| (row == matrix->rows + dim.height - 1
&& window_wants_mode_line (w))
- || (row == matrix->rows && matrix->header_line_p))
+ || (row == matrix->rows && matrix->tab_line_p)
+ || (row == matrix->rows
+ && !matrix->tab_line_p && matrix->header_line_p)
+ || (row == (matrix->rows + 1)
+ && matrix->tab_line_p && matrix->header_line_p))
{
row->glyphs[TEXT_AREA]
= row->glyphs[LEFT_MARGIN_AREA];
@@ -463,6 +473,11 @@ adjust_glyph_matrix (struct window *w, struct glyph_matrix *matrix, int x, int y
= row->glyphs[LEFT_MARGIN_AREA] + left;
row->glyphs[RIGHT_MARGIN_AREA]
= row->glyphs[TEXT_AREA] + dim.width - left - right;
+ /* Leave room for a border glyph. */
+ if (!FRAME_WINDOW_P (XFRAME (w->frame))
+ && !WINDOW_RIGHTMOST_P (w)
+ && right > 0)
+ row->glyphs[RIGHT_MARGIN_AREA] -= 1;
row->glyphs[LAST_AREA]
= row->glyphs[LEFT_MARGIN_AREA] + dim.width;
}
@@ -478,6 +493,7 @@ adjust_glyph_matrix (struct window *w, struct glyph_matrix *matrix, int x, int y
Allocate glyph memory from the heap. */
if (dim.width > matrix->matrix_w
|| new_rows
+ || tab_line_changed_p
|| header_line_changed_p
|| marginal_areas_changed_p)
{
@@ -493,7 +509,11 @@ adjust_glyph_matrix (struct window *w, struct glyph_matrix *matrix, int x, int y
/* The mode line, if displayed, never has marginal areas. */
if ((row == matrix->rows + dim.height - 1
&& !(w && window_wants_mode_line (w)))
- || (row == matrix->rows && matrix->header_line_p))
+ || (row == matrix->rows && matrix->tab_line_p)
+ || (row == matrix->rows
+ && !matrix->tab_line_p && matrix->header_line_p)
+ || (row == (matrix->rows + 1)
+ && matrix->tab_line_p && matrix->header_line_p))
{
row->glyphs[TEXT_AREA]
= row->glyphs[LEFT_MARGIN_AREA];
@@ -518,6 +538,14 @@ adjust_glyph_matrix (struct window *w, struct glyph_matrix *matrix, int x, int y
eassert (left >= 0 && right >= 0);
matrix->left_margin_glyphs = left;
matrix->right_margin_glyphs = right;
+
+ /* If we are resizing a window, make sure the previous mode-line
+ row of the window's current matrix is no longer marked as such. */
+ if (w && matrix == w->current_matrix
+ && matrix->nrows > 0
+ && dim.height != matrix->nrows
+ && matrix->nrows <= matrix->rows_allocated)
+ MATRIX_MODE_LINE_ROW (matrix)->mode_line_p = false;
}
/* Number of rows to be used by MATRIX. */
@@ -539,6 +567,7 @@ adjust_glyph_matrix (struct window *w, struct glyph_matrix *matrix, int x, int y
upper window). Invalidate all rows that are no longer part
of the window. */
if (!marginal_areas_changed_p
+ && !tab_line_changed_p
&& !header_line_changed_p
&& new_rows == 0
&& dim.width == matrix->matrix_w
@@ -728,7 +757,7 @@ shift_glyph_matrix (struct window *w, struct glyph_matrix *matrix, int start, in
eassert (start >= 0 && start < matrix->nrows);
eassert (end >= 0 && end <= matrix->nrows);
- min_y = WINDOW_HEADER_LINE_HEIGHT (w);
+ min_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
max_y = WINDOW_BOX_HEIGHT_NO_MODE_LINE (w);
for (; start < end; ++start)
@@ -767,7 +796,13 @@ clear_current_matrices (register struct frame *f)
clear_glyph_matrix (XWINDOW (f->menu_bar_window)->current_matrix);
#endif
-#if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
+#if defined (HAVE_WINDOW_SYSTEM)
+ /* Clear the matrix of the tab-bar window, if any. */
+ if (WINDOWP (f->tab_bar_window))
+ clear_glyph_matrix (XWINDOW (f->tab_bar_window)->current_matrix);
+#endif
+
+#if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_TOOL_BAR)
/* Clear the matrix of the tool-bar window, if any. */
if (WINDOWP (f->tool_bar_window))
clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
@@ -792,7 +827,12 @@ clear_desired_matrices (register struct frame *f)
clear_glyph_matrix (XWINDOW (f->menu_bar_window)->desired_matrix);
#endif
-#if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
+#if defined (HAVE_WINDOW_SYSTEM)
+ if (WINDOWP (f->tab_bar_window))
+ clear_glyph_matrix (XWINDOW (f->tab_bar_window)->desired_matrix);
+#endif
+
+#if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_TOOL_BAR)
if (WINDOWP (f->tool_bar_window))
clear_glyph_matrix (XWINDOW (f->tool_bar_window)->desired_matrix);
#endif
@@ -845,7 +885,7 @@ clear_glyph_row (struct glyph_row *row)
enum { off = offsetof (struct glyph_row, used) };
/* Zero everything except pointers in `glyphs'. */
- memset (row->used, 0, sizeof *row - off);
+ memset ((char *) row + off, 0, sizeof *row - off);
}
@@ -857,7 +897,7 @@ blank_row (struct window *w, struct glyph_row *row, int y)
{
int min_y, max_y;
- min_y = WINDOW_HEADER_LINE_HEIGHT (w);
+ min_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
max_y = WINDOW_BOX_HEIGHT_NO_MODE_LINE (w);
clear_glyph_row (row);
@@ -994,7 +1034,7 @@ copy_row_except_pointers (struct glyph_row *to, struct glyph_row *from)
{
enum { off = offsetof (struct glyph_row, x) };
- memcpy (&to->x, &from->x, sizeof *to - off);
+ memcpy ((char *) to + off, (char *) from + off, sizeof *to - off);
}
@@ -1062,7 +1102,7 @@ find_glyph_row_slice (struct glyph_matrix *window_matrix,
call to this function really clears it. In addition, this function
makes sure the marginal areas of ROW are in sync with the window's
display margins. MODE_LINE_P non-zero means we are preparing a
- glyph row for header line or mode line. */
+ glyph row for tab/header line or mode line. */
void
prepare_desired_row (struct window *w, struct glyph_row *row, bool mode_line_p)
@@ -1077,11 +1117,11 @@ prepare_desired_row (struct window *w, struct glyph_row *row, bool mode_line_p)
}
if (mode_line_p)
{
- /* Mode and header lines, if displayed, never have marginal
+ /* Mode and header/tab lines, if displayed, never have marginal
areas. If we are called with MODE_LINE_P non-zero, we are
- displaying the mode/header line in this window, and so the
+ displaying the mode/header/tab line in this window, and so the
marginal areas of this glyph row should be eliminated. This
- is needed when the mode/header line is switched on in a
+ is needed when the mode/header/tab line is switched on in a
window that has display margins. */
if (w->left_margin_cols > 0)
row->glyphs[TEXT_AREA] = row->glyphs[LEFT_MARGIN_AREA];
@@ -1099,13 +1139,20 @@ prepare_desired_row (struct window *w, struct glyph_row *row, bool mode_line_p)
/* Make sure the marginal areas of this row are in sync with
what the window wants, when the row actually displays text
- and not header/mode line. */
+ and not tab/header/mode line. */
if (w->left_margin_cols > 0
&& (left != row->glyphs[TEXT_AREA] - row->glyphs[LEFT_MARGIN_AREA]))
row->glyphs[TEXT_AREA] = row->glyphs[LEFT_MARGIN_AREA] + left;
if (w->right_margin_cols > 0
&& (right != row->glyphs[LAST_AREA] - row->glyphs[RIGHT_MARGIN_AREA]))
- row->glyphs[RIGHT_MARGIN_AREA] = row->glyphs[LAST_AREA] - right;
+ {
+ row->glyphs[RIGHT_MARGIN_AREA] = row->glyphs[LAST_AREA] - right;
+ /* Leave room for a border glyph. */
+ if (!FRAME_WINDOW_P (XFRAME (w->frame))
+ && !WINDOW_RIGHTMOST_P (w)
+ && right > 0)
+ row->glyphs[RIGHT_MARGIN_AREA] -= 1;
+ }
}
}
@@ -1281,7 +1328,7 @@ row_equal_p (struct glyph_row *a, struct glyph_row *b, bool mouse_face_p)
with zeros. If GLYPH_DEBUG and ENABLE_CHECKING are in effect, the global
variable glyph_pool_count is incremented for each pool allocated. */
-static struct glyph_pool *
+static struct glyph_pool * ATTRIBUTE_MALLOC
new_glyph_pool (void)
{
struct glyph_pool *result = xzalloc (sizeof *result);
@@ -1699,7 +1746,7 @@ required_matrix_height (struct window *w)
if (FRAME_WINDOW_P (f))
{
- /* https://lists.gnu.org/archive/html/emacs-devel/2015-11/msg00194.html */
+ /* https://lists.gnu.org/r/emacs-devel/2015-11/msg00194.html */
int ch_height = max (FRAME_SMALLEST_FONT_HEIGHT (f), 1);
int window_pixel_height = window_box_height (w) + eabs (w->vscroll);
@@ -1708,8 +1755,8 @@ required_matrix_height (struct window *w)
/* One partially visible line at the top and
bottom of the window. */
+ 2
- /* 2 for header and mode line. */
- + 2);
+ /* 3 for tab, header and mode line. */
+ + 3);
}
#endif /* HAVE_WINDOW_SYSTEM */
@@ -1726,7 +1773,7 @@ required_matrix_width (struct window *w)
struct frame *f = XFRAME (w->frame);
if (FRAME_WINDOW_P (f))
{
- /* https://lists.gnu.org/archive/html/emacs-devel/2015-11/msg00194.html */
+ /* https://lists.gnu.org/r/emacs-devel/2015-11/msg00194.html */
int ch_width = max (FRAME_SMALLEST_CHAR_WIDTH (f), 1);
/* Compute number of glyphs needed in a glyph row. */
@@ -1790,12 +1837,23 @@ adjust_frame_glyphs (struct frame *f)
if (FRAME_WINDOW_P (f))
adjust_frame_glyphs_for_window_redisplay (f);
else
- adjust_frame_glyphs_for_frame_redisplay (f);
+ {
+ adjust_frame_glyphs_for_frame_redisplay (f);
+ eassert (FRAME_INITIAL_P (f)
+ || noninteractive
+ || !initialized
+ || (f->current_matrix
+ && f->current_matrix->nrows > 0
+ && f->current_matrix->rows
+ && f->desired_matrix
+ && f->desired_matrix->nrows > 0
+ && f->desired_matrix->rows));
+ }
/* Don't forget the buffer for decode_mode_spec. */
adjust_decode_mode_spec_buffer (f);
- f->glyphs_initialized_p = 1;
+ f->glyphs_initialized_p = true;
unblock_input ();
}
@@ -1862,6 +1920,7 @@ fake_current_matrices (Lisp_Object window)
- r->used[LEFT_MARGIN_AREA]
- r->used[RIGHT_MARGIN_AREA]);
r->mode_line_p = 0;
+ r->tab_line_p = 0;
}
}
}
@@ -2022,7 +2081,19 @@ adjust_frame_glyphs_for_frame_redisplay (struct frame *f)
to the frame width (from CHANGE_FRAME_SIZE_1). */
if (matrix_dim.width != FRAME_TOTAL_COLS (f)
|| matrix_dim.height != FRAME_TOTAL_LINES (f))
- return;
+ {
+ /* We have reallocated the frame's glyph pools, but didn't
+ update the glyph pointers in the frame's glyph matrices
+ to use the reallocated pools (that happens below, in the
+ call to adjust_glyph_matrix). Set the frame's garbaged
+ flag, so that when we are called again from
+ redisplay_internal, we don't erroneously call
+ save_current_matrix, because it will use the wrong glyph
+ pointers, and will most probably crash. */
+ if (!FRAME_WINDOW_P (f) && pool_changed_p)
+ SET_FRAME_GARBAGED (f);
+ return;
+ }
eassert (matrix_dim.width == FRAME_TOTAL_COLS (f)
&& matrix_dim.height == FRAME_TOTAL_LINES (f));
@@ -2059,6 +2130,19 @@ adjust_frame_glyphs_for_frame_redisplay (struct frame *f)
SET_FRAME_GARBAGED (f);
}
}
+ else if (!FRAME_INITIAL_P (f) && !noninteractive && initialized)
+ {
+ if (!f->desired_matrix->nrows || !f->desired_matrix->rows)
+ {
+ adjust_glyph_matrix (NULL, f->desired_matrix, 0, 0, matrix_dim);
+ SET_FRAME_GARBAGED (f);
+ }
+ if (!f->current_matrix->nrows || !f->current_matrix->rows)
+ {
+ adjust_glyph_matrix (NULL, f->current_matrix, 0, 0, matrix_dim);
+ SET_FRAME_GARBAGED (f);
+ }
+ }
}
@@ -2106,7 +2190,39 @@ adjust_frame_glyphs_for_window_redisplay (struct frame *f)
}
#endif
-#if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
+#if defined (HAVE_WINDOW_SYSTEM)
+ {
+ /* Allocate/ reallocate matrices of the tab bar window. If we
+ don't have a tab bar window yet, make one. */
+ struct window *w;
+ if (NILP (f->tab_bar_window))
+ {
+ Lisp_Object frame;
+ fset_tab_bar_window (f, make_window ());
+ w = XWINDOW (f->tab_bar_window);
+ XSETFRAME (frame, f);
+ wset_frame (w, frame);
+ w->pseudo_window_p = 1;
+ }
+ else
+ w = XWINDOW (f->tab_bar_window);
+
+ w->pixel_left = 0;
+ w->left_col = 0;
+ w->pixel_top = FRAME_MENU_BAR_HEIGHT (f)
+ + (!NILP (Vtab_bar_position) ? FRAME_TOOL_BAR_HEIGHT (f) : 0);
+ w->top_line = FRAME_MENU_BAR_LINES (f)
+ + (!NILP (Vtab_bar_position) ? FRAME_TOOL_BAR_LINES (f) : 0);
+ w->total_cols = FRAME_TOTAL_COLS (f);
+ w->pixel_width = (FRAME_PIXEL_WIDTH (f)
+ - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
+ w->total_lines = FRAME_TAB_BAR_LINES (f);
+ w->pixel_height = FRAME_TAB_BAR_HEIGHT (f);
+ allocate_matrices_for_window_redisplay (w);
+ }
+#endif
+
+#if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_TOOL_BAR)
{
/* Allocate/ reallocate matrices of the tool bar window. If we
don't have a tool bar window yet, make one. */
@@ -2125,8 +2241,10 @@ adjust_frame_glyphs_for_window_redisplay (struct frame *f)
w->pixel_left = 0;
w->left_col = 0;
- w->pixel_top = FRAME_MENU_BAR_HEIGHT (f);
- w->top_line = FRAME_MENU_BAR_LINES (f);
+ w->pixel_top = FRAME_MENU_BAR_HEIGHT (f)
+ + (NILP (Vtab_bar_position) ? FRAME_TAB_BAR_HEIGHT (f) : 0);
+ w->top_line = FRAME_MENU_BAR_LINES (f)
+ + (NILP (Vtab_bar_position) ? FRAME_TAB_BAR_LINES (f) : 0);
w->total_cols = FRAME_TOTAL_COLS (f);
w->pixel_width = (FRAME_PIXEL_WIDTH (f)
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
@@ -2169,7 +2287,7 @@ free_glyphs (struct frame *f)
/* Block interrupt input so that we don't get surprised by an X
event while we're in an inconsistent state. */
block_input ();
- f->glyphs_initialized_p = 0;
+ f->glyphs_initialized_p = false;
/* Release window sub-matrices. */
if (!NILP (f->root_window))
@@ -2188,7 +2306,19 @@ free_glyphs (struct frame *f)
}
#endif
-#if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
+#if defined (HAVE_WINDOW_SYSTEM)
+ /* Free the tab bar window and its glyph matrices. */
+ if (!NILP (f->tab_bar_window))
+ {
+ struct window *w = XWINDOW (f->tab_bar_window);
+ free_glyph_matrix (w->desired_matrix);
+ free_glyph_matrix (w->current_matrix);
+ w->desired_matrix = w->current_matrix = NULL;
+ fset_tab_bar_window (f, Qnil);
+ }
+#endif
+
+#if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_TOOL_BAR)
/* Free the tool bar window and its glyph matrices. */
if (!NILP (f->tool_bar_window))
{
@@ -2464,11 +2594,15 @@ build_frame_matrix_from_leaf_window (struct glyph_matrix *frame_matrix, struct w
the corresponding frame row to be updated. */
frame_row->enabled_p = true;
- /* Maybe insert a vertical border between horizontally adjacent
+ /* Maybe insert a vertical border between horizontally adjacent
windows. */
- if (GLYPH_CHAR (right_border_glyph) != 0)
+ if (GLYPH_CHAR (right_border_glyph) != 0)
{
- struct glyph *border = window_row->glyphs[LAST_AREA] - 1;
+ struct glyph *border = window_row->glyphs[LAST_AREA] - 1;
+ /* It's a subtle bug if we are overwriting some non-char
+ glyph with the vertical border glyph. */
+ eassert (border->type == CHAR_GLYPH);
+ border->type = CHAR_GLYPH;
SET_CHAR_GLYPH_FROM_GLYPH (*border, right_border_glyph);
}
@@ -2509,8 +2643,7 @@ spec_glyph_lookup_face (struct window *w, GLYPH *glyph)
/* Convert the glyph's specified face to a realized (cache) face. */
if (lface_id > 0)
{
- int face_id = merge_faces (XFRAME (w->frame),
- Qt, lface_id, DEFAULT_FACE_ID);
+ int face_id = merge_faces (w, Qt, lface_id, DEFAULT_FACE_ID);
SET_GLYPH_FACE (*glyph, face_id);
}
}
@@ -2599,12 +2732,25 @@ set_frame_matrix_frame (struct frame *f)
operations in window matrices of frame_matrix_frame. */
static void
-make_current (struct glyph_matrix *desired_matrix, struct glyph_matrix *current_matrix, int row)
+make_current (struct glyph_matrix *desired_matrix,
+ struct glyph_matrix *current_matrix, int row)
{
struct glyph_row *current_row = MATRIX_ROW (current_matrix, row);
struct glyph_row *desired_row = MATRIX_ROW (desired_matrix, row);
bool mouse_face_p = current_row->mouse_face_p;
+ /* If we aborted redisplay of this window, a row in the desired
+ matrix might not have its hash computed. But update_window
+ relies on each row having its correct hash, so do it here if
+ needed. */
+ if (!desired_row->hash
+ /* A glyph row that is not completely empty is unlikely to have
+ a zero hash value. */
+ && !(!desired_row->used[0]
+ && !desired_row->used[1]
+ && !desired_row->used[2]))
+ desired_row->hash = row_hash (desired_row);
+
/* Do current_row = desired_row. This exchanges glyph pointers
between both rows, and does a structure assignment otherwise. */
assign_row (current_row, desired_row);
@@ -3083,7 +3229,30 @@ update_frame (struct frame *f, bool force_p, bool inhibit_hairy_id_p)
update_window (XWINDOW (f->menu_bar_window), true);
#endif
-#if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
+#if defined (HAVE_WINDOW_SYSTEM)
+ /* Update the tab-bar window, if present. */
+ if (WINDOWP (f->tab_bar_window))
+ {
+ struct window *w = XWINDOW (f->tab_bar_window);
+
+ /* Update tab-bar window. */
+ if (w->must_be_updated_p)
+ {
+ Lisp_Object tem;
+
+ update_window (w, true);
+ w->must_be_updated_p = false;
+
+ /* Swap tab-bar strings. We swap because we want to
+ reuse strings. */
+ tem = f->current_tab_bar_string;
+ fset_current_tab_bar_string (f, f->desired_tab_bar_string);
+ fset_desired_tab_bar_string (f, tem);
+ }
+ }
+#endif
+
+#if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_TOOL_BAR)
/* Update the tool-bar window, if present. */
if (WINDOWP (f->tool_bar_window))
{
@@ -3120,16 +3289,23 @@ update_frame (struct frame *f, bool force_p, bool inhibit_hairy_id_p)
build_frame_matrix (f);
/* Update the display. */
- update_begin (f);
- paused_p = update_frame_1 (f, force_p, inhibit_hairy_id_p, 1);
- update_end (f);
+ if (FRAME_INITIAL_P (f))
+ /* No actual display to update so the "update" is a nop and
+ obviously isn't interrupted by pending input. */
+ paused_p = false;
+ else
+ {
+ update_begin (f);
+ paused_p = update_frame_1 (f, force_p, inhibit_hairy_id_p, 1, false);
+ update_end (f);
+ }
if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
{
if (FRAME_TTY (f)->termscript)
- fflush_unlocked (FRAME_TTY (f)->termscript);
+ fflush (FRAME_TTY (f)->termscript);
if (FRAME_TERMCAP_P (f))
- fflush_unlocked (FRAME_TTY (f)->output);
+ fflush (FRAME_TTY (f)->output);
}
/* Check window matrices for lost pointers. */
@@ -3174,7 +3350,7 @@ update_frame_with_menu (struct frame *f, int row, int col)
cursor_at_point_p = !(row >= 0 && col >= 0);
/* Force update_frame_1 not to stop due to pending input, and not
try scrolling. */
- paused_p = update_frame_1 (f, 1, 1, cursor_at_point_p);
+ paused_p = update_frame_1 (f, 1, 1, cursor_at_point_p, true);
/* ROW and COL tell us where in the menu to position the cursor, so
that screen readers know the active region on the screen. */
if (!cursor_at_point_p)
@@ -3182,8 +3358,8 @@ update_frame_with_menu (struct frame *f, int row, int col)
update_end (f);
if (FRAME_TTY (f)->termscript)
- fflush_unlocked (FRAME_TTY (f)->termscript);
- fflush_unlocked (FRAME_TTY (f)->output);
+ fflush (FRAME_TTY (f)->termscript);
+ fflush (FRAME_TTY (f)->output);
/* Check window matrices for lost pointers. */
#if GLYPH_DEBUG
#if 0
@@ -3200,6 +3376,53 @@ update_frame_with_menu (struct frame *f, int row, int col)
display_completed = !paused_p;
}
+/* Update the mouse position for a frame F. This handles both
+ updating the display for mouse-face properties and updating the
+ help echo text.
+
+ Returns the number of events generated. */
+int
+update_mouse_position (struct frame *f, int x, int y)
+{
+ previous_help_echo_string = help_echo_string;
+ help_echo_string = Qnil;
+
+ note_mouse_highlight (f, x, y);
+
+ /* If the contents of the global variable help_echo_string
+ has changed, generate a HELP_EVENT. */
+ if (!NILP (help_echo_string)
+ || !NILP (previous_help_echo_string))
+ {
+ Lisp_Object frame;
+ XSETFRAME (frame, f);
+
+ gen_help_event (help_echo_string, frame, help_echo_window,
+ help_echo_object, help_echo_pos);
+ return 1;
+ }
+
+ return 0;
+}
+
+DEFUN ("display--update-for-mouse-movement", Fdisplay__update_for_mouse_movement,
+ Sdisplay__update_for_mouse_movement, 2, 2, 0,
+ doc: /* Handle mouse movement detected by Lisp code.
+
+This function should be called when Lisp code detects the mouse has
+moved, even if `track-mouse' is nil. This handles updates that do not
+rely on input events such as updating display for mouse-face
+properties or updating the help echo text. */)
+ (Lisp_Object mouse_x, Lisp_Object mouse_y)
+{
+ CHECK_FIXNUM (mouse_x);
+ CHECK_FIXNUM (mouse_y);
+
+ update_mouse_position (SELECTED_FRAME (), XFIXNUM (mouse_x),
+ XFIXNUM (mouse_y));
+ return Qnil;
+}
+
/************************************************************************
Window-based updates
@@ -3390,8 +3613,10 @@ update_window (struct window *w, bool force_p)
{
struct glyph_matrix *desired_matrix = w->desired_matrix;
bool paused_p;
- int preempt_count = baud_rate / 2400 + 1;
+ int preempt_count = clip_to_bounds (1, baud_rate / 2400 + 1, INT_MAX);
+#ifdef HAVE_WINDOW_SYSTEM
struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w)));
+#endif
#ifdef GLYPH_DEBUG
/* Check that W's frame doesn't have glyph matrices. */
eassert (FRAME_WINDOW_P (XFRAME (WINDOW_FRAME (w))));
@@ -3401,22 +3626,36 @@ update_window (struct window *w, bool force_p)
if (!force_p)
detect_input_pending_ignore_squeezables ();
- /* If forced to complete the update, or if no input is pending, do
- the update. */
- if (force_p || !input_pending || !NILP (do_mouse_tracking))
+ /* If forced to complete the update, no input is pending, or we are
+ tracking the mouse, do the update. */
+ if (force_p || !input_pending || !NILP (track_mouse))
{
struct glyph_row *row, *end;
struct glyph_row *mode_line_row;
+ struct glyph_row *tab_line_row;
struct glyph_row *header_line_row;
int yb;
bool changed_p = 0, mouse_face_overwritten_p = 0;
int n_updated = 0;
+ bool invisible_rows_marked = false;
- rif->update_window_begin_hook (w);
+#ifdef HAVE_WINDOW_SYSTEM
+ gui_update_window_begin (w);
+#endif
yb = window_text_bottom_y (w);
row = MATRIX_ROW (desired_matrix, 0);
end = MATRIX_MODE_LINE_ROW (desired_matrix);
+ /* Take note of the tab line, if there is one. We will
+ update it below, after updating all of the window's lines. */
+ if (row->mode_line_p && row->tab_line_p)
+ {
+ tab_line_row = row;
+ ++row;
+ }
+ else
+ tab_line_row = NULL;
+
/* Take note of the header line, if there is one. We will
update it below, after updating all of the window's lines. */
if (row->mode_line_p)
@@ -3446,7 +3685,8 @@ update_window (struct window *w, bool force_p)
/* Try reusing part of the display by copying. */
if (row < end && !desired_matrix->no_scrolling_p)
{
- int rc = scrolling_window (w, header_line_row != NULL);
+ int rc = scrolling_window (w, (tab_line_row != NULL ? 1 : 0)
+ + (header_line_row != NULL ? 1 : 0));
if (rc < 0)
{
/* All rows were found to be equal. */
@@ -3489,22 +3729,54 @@ update_window (struct window *w, bool force_p)
tempted to optimize redisplay based on lines displayed
in the first redisplay. */
if (MATRIX_ROW_BOTTOM_Y (row) >= yb)
- for (i = vpos + 1; i < w->current_matrix->nrows - 1; ++i)
- SET_MATRIX_ROW_ENABLED_P (w->current_matrix, i, false);
+ {
+ for (i = vpos + 1; i < w->current_matrix->nrows - 1; ++i)
+ SET_MATRIX_ROW_ENABLED_P (w->current_matrix, i, false);
+ invisible_rows_marked = true;
+ }
}
/* Was display preempted? */
paused_p = row < end;
+ if (!paused_p && !invisible_rows_marked)
+ {
+ /* If we didn't mark the invisible rows in the current
+ matrix as invalid above, do that now. This can happen if
+ scrolling_window updates the last visible rows of the
+ current matrix, in which case the above loop doesn't get
+ to examine the last visible row. */
+ int i;
+ for (i = 0; i < w->current_matrix->nrows - 1; ++i)
+ {
+ struct glyph_row *current_row = MATRIX_ROW (w->current_matrix, i);
+ if (current_row->enabled_p
+ && MATRIX_ROW_BOTTOM_Y (current_row) >= yb)
+ {
+ for (++i ; i < w->current_matrix->nrows - 1; ++i)
+ SET_MATRIX_ROW_ENABLED_P (w->current_matrix, i, false);
+ }
+ }
+ }
+
set_cursor:
+ /* Update the tab line after scrolling because a new tab
+ line would otherwise overwrite lines at the top of the window
+ that can be scrolled. */
+ if (tab_line_row && tab_line_row->enabled_p)
+ {
+ tab_line_row->y = 0;
+ update_window_line (w, 0, &mouse_face_overwritten_p);
+ }
+
/* Update the header line after scrolling because a new header
line would otherwise overwrite lines at the top of the window
that can be scrolled. */
if (header_line_row && header_line_row->enabled_p)
{
- header_line_row->y = 0;
- update_window_line (w, 0, &mouse_face_overwritten_p);
+ header_line_row->y = tab_line_row ? CURRENT_TAB_LINE_HEIGHT (w) : 0;
+ update_window_line (w, tab_line_row ? 1 : 0, &mouse_face_overwritten_p);
}
/* Fix the appearance of overlapping/overlapped rows. */
@@ -3534,13 +3806,17 @@ update_window (struct window *w, bool force_p)
#ifdef HAVE_WINDOW_SYSTEM
update_window_fringes (w, 0);
-#endif
/* End the update of window W. Don't set the cursor if we
paused updating the display because in this case,
set_window_cursor_after_update hasn't been called, and
W->output_cursor doesn't contain the cursor location. */
- rif->update_window_end_hook (w, !paused_p, mouse_face_overwritten_p);
+ gui_update_window_end (w, !paused_p, mouse_face_overwritten_p);
+#endif
+ /* If the update wasn't interrupted, this window has been
+ completely updated. */
+ if (!paused_p)
+ w->must_be_updated_p = false;
}
else
paused_p = 1;
@@ -3556,6 +3832,92 @@ update_window (struct window *w, bool force_p)
return paused_p;
}
+#ifdef HAVE_WINDOW_SYSTEM
+
+/* Start update of window W. */
+
+void
+gui_update_window_begin (struct window *w)
+{
+ struct frame *f = XFRAME (WINDOW_FRAME (w));
+ Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
+
+ block_input ();
+
+ if (FRAME_RIF (f)->update_window_begin_hook)
+ FRAME_RIF (f)->update_window_begin_hook (w);
+
+ w->output_cursor = w->cursor;
+
+ if (f == hlinfo->mouse_face_mouse_frame)
+ {
+ /* Don't do highlighting for mouse motion during the update. */
+ hlinfo->mouse_face_defer = true;
+
+ /* If the frame needs to be redrawn, simply forget about any
+ prior mouse highlighting. */
+ if (FRAME_GARBAGED_P (f))
+ hlinfo->mouse_face_window = Qnil;
+ }
+
+ unblock_input ();
+}
+
+/* End update of window W.
+
+ Draw vertical borders between horizontally adjacent windows, and
+ display W's cursor if CURSOR_ON_P is non-zero.
+
+ MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
+ glyphs in mouse-face were overwritten. In that case we have to
+ make sure that the mouse-highlight is properly redrawn. */
+void
+gui_update_window_end (struct window *w, bool cursor_on_p,
+ bool mouse_face_overwritten_p)
+{
+ struct frame *f = XFRAME (WINDOW_FRAME (w));
+
+ /* Pseudo windows don't have cursors, so don't display them here. */
+ if (!w->pseudo_window_p)
+ {
+ block_input ();
+
+ if (cursor_on_p)
+ display_and_set_cursor (w, true,
+ w->output_cursor.hpos, w->output_cursor.vpos,
+ w->output_cursor.x, w->output_cursor.y);
+
+ if (cursor_in_mouse_face_p (w) && cursor_on_p)
+ mouse_face_overwritten_p = 1;
+
+ if (draw_window_fringes (w, true))
+ {
+ if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
+ gui_draw_right_divider (w);
+ else
+ gui_draw_vertical_border (w);
+ }
+ unblock_input ();
+ }
+
+ /* If a row with mouse-face was overwritten, arrange for
+ frame_up_to_date_hook to redisplay the mouse highlight. */
+ if (mouse_face_overwritten_p)
+ {
+ Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
+
+ hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
+ hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
+ hlinfo->mouse_face_window = Qnil;
+ }
+
+ if (FRAME_RIF (f)->update_window_end_hook)
+ FRAME_RIF (f)->update_window_end_hook (w,
+ cursor_on_p,
+ mouse_face_overwritten_p);
+}
+
+#endif /* HAVE_WINDOW_SYSTEM */
/* Update the display of area AREA in window W, row number VPOS.
AREA can be either LEFT_MARGIN_AREA or RIGHT_MARGIN_AREA. */
@@ -3582,7 +3944,8 @@ update_marginal_area (struct window *w, struct glyph_row *updated_row,
Value is true if display has changed. */
static bool
-update_text_area (struct window *w, struct glyph_row *updated_row, int vpos)
+update_text_area (struct window *w, struct glyph_row *updated_row, int vpos,
+ bool *partial_p)
{
struct glyph_row *current_row = MATRIX_ROW (w->current_matrix, vpos);
struct glyph_row *desired_row = MATRIX_ROW (w->desired_matrix, vpos);
@@ -3603,9 +3966,13 @@ update_text_area (struct window *w, struct glyph_row *updated_row, int vpos)
However, it causes excessive flickering when mouse is moved
across the mode line. Luckily, turning it off for the mode
line doesn't seem to hurt anything. -- cyd.
- But it is still needed for the header line. -- kfs. */
+ But it is still needed for the header line. -- kfs.
+ The header line vpos is 1 if a tab line is enabled. (18th
+ Apr 2022) */
|| (current_row->mouse_face_p
- && !(current_row->mode_line_p && vpos > 0))
+ && !(current_row->mode_line_p
+ && (vpos > (w->current_matrix->tab_line_p
+ && w->current_matrix->header_line_p))))
|| current_row->x != desired_row->x)
{
output_cursor_to (w, vpos, 0, desired_row->y, desired_row->x);
@@ -3684,6 +4051,13 @@ update_text_area (struct window *w, struct glyph_row *updated_row, int vpos)
{
x += desired_glyph->pixel_width;
++desired_glyph, ++current_glyph, ++i;
+
+ /* Say that only a partial update was performed of
+ the current row (i.e. not all the glyphs were
+ drawn). This is used to preserve the stipple_p
+ flag of the current row inside
+ update_window_line. */
+ *partial_p = true;
}
/* Consider the case that the current row contains "xxx
@@ -3755,9 +4129,15 @@ update_text_area (struct window *w, struct glyph_row *updated_row, int vpos)
rif->write_glyphs (w, updated_row, start,
TEXT_AREA, i - start_hpos);
changed_p = 1;
+ *partial_p = true;
}
}
+ /* This means we will draw from the start, so no partial update
+ is being performed. */
+ if (!i)
+ *partial_p = false;
+
/* Write the rest. */
if (i < desired_row->used[TEXT_AREA])
{
@@ -3830,7 +4210,9 @@ update_window_line (struct window *w, int vpos, bool *mouse_face_overwritten_p)
struct glyph_row *current_row = MATRIX_ROW (w->current_matrix, vpos);
struct glyph_row *desired_row = MATRIX_ROW (w->desired_matrix, vpos);
struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w)));
- bool changed_p = 0;
+
+ /* partial_p is true if not all of desired_row was drawn. */
+ bool changed_p = 0, partial_p = 0, was_stipple;
/* A row can be completely invisible in case a desired matrix was
built with a vscroll and then make_cursor_line_fully_visible shifts
@@ -3854,7 +4236,7 @@ update_window_line (struct window *w, int vpos, bool *mouse_face_overwritten_p)
}
/* Update the display of the text area. */
- if (update_text_area (w, desired_row, vpos))
+ if (update_text_area (w, desired_row, vpos, &partial_p))
{
changed_p = 1;
if (current_row->mouse_face_p)
@@ -3883,7 +4265,17 @@ update_window_line (struct window *w, int vpos, bool *mouse_face_overwritten_p)
}
/* Update current_row from desired_row. */
+ was_stipple = current_row->stipple_p;
make_current (w->desired_matrix, w->current_matrix, vpos);
+
+ /* If only a partial update was performed, any stipple already
+ displayed in MATRIX_ROW (w->current_matrix, vpos) might still be
+ there, so don't hurry to clear that flag if it's not in
+ desired_row. */
+
+ if (partial_p && was_stipple)
+ current_row->stipple_p = true;
+
return changed_p;
}
@@ -3905,11 +4297,11 @@ set_window_cursor_after_update (struct window *w)
/* If we are showing a message instead of the mini-buffer,
show the cursor for the message instead. */
&& XWINDOW (minibuf_window) == w
- && EQ (minibuf_window, echo_area_window)
+ && BASE_EQ (minibuf_window, echo_area_window)
/* These cases apply only to the frame that contains
the active mini-buffer window. */
&& FRAME_HAS_MINIBUF_P (f)
- && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
+ && BASE_EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
{
cx = cy = vpos = hpos = 0;
@@ -4063,7 +4455,6 @@ add_row_entry (struct glyph_row *row)
return entry;
}
-
/* Try to reuse part of the current display of W by scrolling lines.
HEADER_LINE_P means W has a header line.
@@ -4091,7 +4482,7 @@ add_row_entry (struct glyph_row *row)
1 if we did scroll. */
static int
-scrolling_window (struct window *w, bool header_line_p)
+scrolling_window (struct window *w, int tab_line_p)
{
struct glyph_matrix *desired_matrix = w->desired_matrix;
struct glyph_matrix *current_matrix = w->current_matrix;
@@ -4104,11 +4495,19 @@ scrolling_window (struct window *w, bool header_line_p)
struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w)));
/* Skip over rows equal at the start. */
- for (i = header_line_p; i < current_matrix->nrows - 1; ++i)
+ for (i = tab_line_p; i < current_matrix->nrows - 1; ++i)
{
struct glyph_row *d = MATRIX_ROW (desired_matrix, i);
struct glyph_row *c = MATRIX_ROW (current_matrix, i);
+ /* If there is a row with a stipple currently on the glass, give
+ up. Stipples look different depending on where on the
+ display they are drawn, so scrolling the display will produce
+ incorrect results. */
+
+ if (c->stipple_p)
+ return 0;
+
if (c->enabled_p
&& d->enabled_p
&& !d->redraw_fringe_bitmaps_p
@@ -4124,8 +4523,11 @@ scrolling_window (struct window *w, bool header_line_p)
break;
}
-#ifdef HAVE_XWIDGETS
- /* Currently this seems needed to detect xwidget movement reliably. */
+ /* Can't scroll the display of w32 GUI frames when position of point
+ is indicated by the system caret, because scrolling the display
+ will then "copy" the pixels used by the caret. */
+#ifdef HAVE_NTGUI
+ if (w32_use_visible_system_caret)
return 0;
#endif
@@ -4135,6 +4537,16 @@ scrolling_window (struct window *w, bool header_line_p)
first_old = first_new = i;
+ while (i < current_matrix->nrows - 1)
+ {
+ /* If there is a stipple after the first change, give up as
+ well. */
+ if (MATRIX_ROW (current_matrix, i)->stipple_p)
+ return 0;
+
+ ++i;
+ }
+
/* Set last_new to the index + 1 of the row that reaches the
bottom boundary in the desired matrix. Give up if we find a
disabled row before we reach the bottom boundary. */
@@ -4474,23 +4886,20 @@ scrolling_window (struct window *w, bool header_line_p)
static bool
update_frame_1 (struct frame *f, bool force_p, bool inhibit_id_p,
- bool set_cursor_p)
+ bool set_cursor_p, bool updating_menu_p)
{
/* Frame matrices to work on. */
struct glyph_matrix *current_matrix = f->current_matrix;
struct glyph_matrix *desired_matrix = f->desired_matrix;
int i;
bool pause_p;
- int preempt_count = baud_rate / 2400 + 1;
+ int preempt_count = clip_to_bounds (1, baud_rate / 2400 + 1, INT_MAX);
eassert (current_matrix && desired_matrix);
if (baud_rate != FRAME_COST_BAUD_RATE (f))
calculate_costs (f);
- if (preempt_count <= 0)
- preempt_count = 1;
-
if (!force_p && detect_input_pending_ignore_squeezables ())
{
pause_p = 1;
@@ -4513,14 +4922,16 @@ update_frame_1 (struct frame *f, bool force_p, bool inhibit_id_p,
/* Update the individual lines as needed. Do bottom line first. */
if (MATRIX_ROW_ENABLED_P (desired_matrix, desired_matrix->nrows - 1))
- update_frame_line (f, desired_matrix->nrows - 1);
+ update_frame_line (f, desired_matrix->nrows - 1, updating_menu_p);
/* Now update the rest of the lines. */
for (i = 0; i < desired_matrix->nrows - 1 && (force_p || !input_pending); i++)
{
if (MATRIX_ROW_ENABLED_P (desired_matrix, i))
{
- if (FRAME_TERMCAP_P (f))
+ /* Note that output_buffer_size being 0 means that we want the
+ old default behavior of flushing output every now and then. */
+ if (FRAME_TERMCAP_P (f) && FRAME_TTY (f)->output_buffer_size == 0)
{
/* Flush out every so many lines.
Also flush out if likely to have more than 1k buffered
@@ -4532,14 +4943,14 @@ update_frame_1 (struct frame *f, bool force_p, bool inhibit_id_p,
ptrdiff_t outq = __fpending (display_output);
if (outq > 900
|| (outq > 20 && ((i - 1) % preempt_count == 0)))
- fflush_unlocked (display_output);
+ fflush (display_output);
}
}
if (!force_p && (i - 1) % preempt_count == 0)
detect_input_pending_ignore_squeezables ();
- update_frame_line (f, i);
+ update_frame_line (f, i, updating_menu_p);
}
}
@@ -4552,13 +4963,13 @@ update_frame_1 (struct frame *f, bool force_p, bool inhibit_id_p,
/* If we are showing a message instead of the mini-buffer,
show the cursor for the message instead of for the
(now hidden) mini-buffer contents. */
- || (EQ (minibuf_window, selected_window)
- && EQ (minibuf_window, echo_area_window)
+ || (BASE_EQ (minibuf_window, selected_window)
+ && BASE_EQ (minibuf_window, echo_area_window)
&& !NILP (echo_area_buffer[0])))
/* These cases apply only to the frame that contains
the active mini-buffer window. */
&& FRAME_HAS_MINIBUF_P (f)
- && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
+ && BASE_EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
{
int top = WINDOW_TOP_EDGE_LINE (XWINDOW (FRAME_MINIBUF_WINDOW (f)));
int col;
@@ -4652,7 +5063,6 @@ scrolling (struct frame *frame)
unsigned *new_hash = old_hash + height;
int *draw_cost = (int *) (new_hash + height);
int *old_draw_cost = draw_cost + height;
-
eassert (current_matrix);
/* Compute hash codes of all the lines. Also calculate number of
@@ -4674,8 +5084,7 @@ scrolling (struct frame *frame)
{
/* This line cannot be redrawn, so don't let scrolling mess it. */
new_hash[i] = old_hash[i];
-#define INFINITY 1000000 /* Taken from scroll.c */
- draw_cost[i] = INFINITY;
+ draw_cost[i] = SCROLL_INFINITY;
}
else
{
@@ -4775,7 +5184,7 @@ count_match (struct glyph *str1, struct glyph *end1, struct glyph *str2, struct
/* Perform a frame-based update on line VPOS in frame FRAME. */
static void
-update_frame_line (struct frame *f, int vpos)
+update_frame_line (struct frame *f, int vpos, bool updating_menu_p)
{
struct glyph *obody, *nbody, *op1, *op2, *np1, *nend;
int tem;
@@ -4814,6 +5223,12 @@ update_frame_line (struct frame *f, int vpos)
current_row->enabled_p = true;
current_row->used[TEXT_AREA] = desired_row->used[TEXT_AREA];
+ /* For some reason, cursor is sometimes moved behind our back when a
+ frame with a TTY menu is redrawn. Homing the cursor as below
+ fixes that. */
+ if (updating_menu_p)
+ cursor_to (f, 0, 0);
+
/* If desired line is empty, just clear the line. */
if (!desired_row->enabled_p)
{
@@ -5086,13 +5501,15 @@ update_frame_line (struct frame *f, int vpos)
***********************************************************************/
/* Determine what's under window-relative pixel position (*X, *Y).
- Return the OBJECT (string or buffer) that's there.
+ Return the object (string or buffer) that's there.
Return in *POS the position in that object.
Adjust *X and *Y to character positions.
+ If an image is shown at the specified position, return
+ in *OBJECT its image-spec.
Return in *DX and *DY the pixel coordinates of the click,
- relative to the top left corner of OBJECT, or relative to
+ relative to the top left corner of object, or relative to
the top left corner of the character glyph at (*X, *Y)
- if OBJECT is nil.
+ if the object at (*X, *Y) is nil.
Return WIDTH and HEIGHT of the object at (*X, *Y), or zero
if the coordinates point to an empty area of the display. */
@@ -5143,6 +5560,29 @@ buffer_posn_from_coords (struct window *w, int *x, int *y, struct display_pos *p
include the hscroll. */
to_x += it.first_visible_x;
+ /* If we are hscrolling only the current line, and Y is at the line
+ containing point, augment TO_X with the hscroll amount of the
+ current line. */
+ if (it.line_wrap == TRUNCATE
+ && EQ (automatic_hscrolling, Qcurrent_line) && IT_CHARPOS (it) < PT)
+ {
+ struct it it2 = it;
+ void *it2data = bidi_shelve_cache ();
+ it2.last_visible_x = 1000000;
+ /* If the line at Y shows point, the call below to
+ move_it_in_display_line will succeed in reaching point. */
+ move_it_in_display_line (&it2, PT, -1, MOVE_TO_POS);
+ if (IT_CHARPOS (it2) >= PT)
+ {
+ to_x += (w->hscroll - w->min_hscroll) * FRAME_COLUMN_WIDTH (it.f);
+ /* We need to pretend the window is hscrolled, so that
+ move_it_in_display_line below will DTRT with TO_X. */
+ it.first_visible_x += w->hscroll * FRAME_COLUMN_WIDTH (it.f);
+ it.last_visible_x += w->hscroll * FRAME_COLUMN_WIDTH (it.f);
+ }
+ bidi_unshelve_cache (it2data, 0);
+ }
+
/* Now move horizontally in the row to the glyph under *X. Second
argument is ZV to prevent move_it_in_display_line from matching
based on buffer positions. */
@@ -5179,6 +5619,11 @@ buffer_posn_from_coords (struct window *w, int *x, int *y, struct display_pos *p
#ifdef HAVE_WINDOW_SYSTEM
if (it.what == IT_IMAGE)
{
+ /* Note that this ignores images that are fringe bitmaps,
+ because their image ID is zero, and so IMAGE_OPT_FROM_ID will
+ return NULL. This is okay, since fringe bitmaps are not
+ displayed in the text area, and so are never the object we
+ are interested in. */
img = IMAGE_OPT_FROM_ID (it.f, it.image_id);
if (img && !NILP (img->spec))
*object = img->spec;
@@ -5189,7 +5634,8 @@ buffer_posn_from_coords (struct window *w, int *x, int *y, struct display_pos *p
start position, i.e. it excludes the header-line row, but
MATRIX_ROW includes the header-line row. Adjust for a possible
header-line row. */
- it_vpos = it.vpos + window_wants_header_line (w);
+ it_vpos = it.vpos + window_wants_header_line (w)
+ + window_wants_tab_line (w);
if (it_vpos < w->current_matrix->nrows
&& (row = MATRIX_ROW (w->current_matrix, it_vpos),
row->enabled_p))
@@ -5253,6 +5699,8 @@ mode_line_string (struct window *w, enum window_part part,
if (part == ON_MODE_LINE)
row = MATRIX_MODE_LINE_ROW (w->current_matrix);
+ else if (part == ON_TAB_LINE)
+ row = MATRIX_TAB_LINE_ROW (w->current_matrix);
else
row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
y0 = *y - row->y;
@@ -5413,31 +5861,34 @@ handle_window_change_signal (int sig)
termcap-controlled terminal, but we can't decide which.
Therefore, we resize the frames corresponding to each tty.
*/
- for (tty = tty_list; tty; tty = tty->next) {
+ for (tty = tty_list; tty; tty = tty->next)
+ {
+ if (! tty->term_initted)
+ continue;
- if (! tty->term_initted)
- continue;
+ /* Suspended tty frames have tty->input == NULL avoid trying to
+ use it. */
+ if (!tty->input)
+ continue;
- /* Suspended tty frames have tty->input == NULL avoid trying to
- use it. */
- if (!tty->input)
- continue;
+ get_tty_size (fileno (tty->input), &width, &height);
- get_tty_size (fileno (tty->input), &width, &height);
+ if (width > 5 && height > 2)
+ {
+ Lisp_Object tail, frame;
- if (width > 5 && height > 2) {
- Lisp_Object tail, frame;
+ FOR_EACH_FRAME (tail, frame)
+ {
+ struct frame *f = XFRAME (frame);
- FOR_EACH_FRAME (tail, frame)
- if (FRAME_TERMCAP_P (XFRAME (frame)) && FRAME_TTY (XFRAME (frame)) == tty)
- /* Record the new sizes, but don't reallocate the data
- structures now. Let that be done later outside of the
- signal handler. */
- change_frame_size (XFRAME (frame), width,
- height - FRAME_MENU_BAR_LINES (XFRAME (frame)),
- 0, 1, 0, 0);
+ if (FRAME_TERMCAP_P (f) && FRAME_TTY (f) == tty)
+ /* Record the new sizes, but don't reallocate the data
+ structures now. Let that be done later outside of the
+ signal handler. */
+ change_frame_size (f, width, height, false, true, false);
+ }
+ }
}
- }
}
static void
@@ -5455,7 +5906,6 @@ deliver_window_change_signal (int sig)
void
do_pending_window_change (bool safe)
{
- /* If window change signal handler should have run before, run it now. */
if (redisplaying_p && !safe)
return;
@@ -5463,15 +5913,20 @@ do_pending_window_change (bool safe)
{
Lisp_Object tail, frame;
- delayed_size_change = 0;
+ delayed_size_change = false;
FOR_EACH_FRAME (tail, frame)
{
struct frame *f = XFRAME (frame);
- if (f->new_height != 0 || f->new_width != 0)
+ /* Negative new_width or new_height values mean no change is
+ required (a native size can never drop below zero). If
+ new_size_p is not set, this means the size change was
+ requested by adjust_frame_size but has not been honored by
+ the window manager yet. */
+ if (f->new_size_p && (f->new_height >= 0 || f->new_width >= 0))
change_frame_size (f, f->new_width, f->new_height,
- 0, 0, safe, f->new_pixelwise);
+ false, false, safe);
}
}
}
@@ -5479,47 +5934,46 @@ do_pending_window_change (bool safe)
static void
change_frame_size_1 (struct frame *f, int new_width, int new_height,
- bool pretend, bool delay, bool safe, bool pixelwise)
+ bool pretend, bool delay, bool safe)
{
- /* If we can't deal with the change now, queue it for later. */
if (delay || (redisplaying_p && !safe))
{
+ if (CONSP (frame_size_history)
+ && ((new_width != f->new_width
+ || new_height != f->new_height
+ || new_width != FRAME_PIXEL_WIDTH (f)
+ || new_height != FRAME_PIXEL_HEIGHT (f))))
+ frame_size_history_extra
+ (f, build_string ("change_frame_size_1, delayed"),
+ FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f),
+ new_width, new_height, f->new_width, f->new_height);
+
+ /* We can't deal with the change now, queue it for later. */
f->new_width = new_width;
f->new_height = new_height;
- f->new_pixelwise = pixelwise;
- delayed_size_change = 1;
+ f->new_size_p = true;
+ delayed_size_change = true;
}
else
{
- /* This size-change overrides any pending one for this frame. */
- f->new_height = 0;
- f->new_width = 0;
- f->new_pixelwise = 0;
-
- /* If an argument is zero, set it to the current value. */
- if (pixelwise)
- {
- new_width = (new_width <= 0) ? FRAME_TEXT_WIDTH (f) : new_width;
- new_height = (new_height <= 0) ? FRAME_TEXT_HEIGHT (f) : new_height;
- }
- else
- {
- new_width = (((new_width <= 0) ? FRAME_COLS (f) : new_width)
- * FRAME_COLUMN_WIDTH (f));
- new_height = (((new_height <= 0) ? FRAME_LINES (f) : new_height)
- * FRAME_LINE_HEIGHT (f));
- }
-
- /* Adjust frame size but make sure x_set_window_size does not
- get called. */
- adjust_frame_size (f, new_width, new_height, 5, pretend,
- Qchange_frame_size);
+ /* Storing -1 in the new_width/new_height slots means that no size
+ change is pending. Native sizes are always non-negative.
+ Reset the new_size_p slot as well. */
+ f->new_height = -1;
+ f->new_width = -1;
+ f->new_size_p = false;
+ /* adjust_frame_size wants its arguments in terms of text_width
+ and text_height, so convert them here. For pathologically
+ small frames, the resulting values may be negative though. */
+ adjust_frame_size (f, FRAME_PIXEL_TO_TEXT_WIDTH (f, new_width),
+ FRAME_PIXEL_TO_TEXT_HEIGHT (f, new_height), 5,
+ pretend, Qchange_frame_size);
}
}
-/* Change text height/width of frame F. Values may be given as zero to
- indicate that no change is needed.
+/* Change native height/width of frame F to NEW_WIDTH/NEW_HEIGHT pixels.
+ Values may be given as -1 to indicate that no change is needed.
If DELAY, assume we're being called from a signal handler, and queue
the change for later - perhaps the next redisplay. Since this tries
@@ -5529,7 +5983,7 @@ change_frame_size_1 (struct frame *f, int new_width, int new_height,
change frame sizes while a redisplay is in progress. */
void
change_frame_size (struct frame *f, int new_width, int new_height,
- bool pretend, bool delay, bool safe, bool pixelwise)
+ bool pretend, bool delay, bool safe)
{
Lisp_Object tail, frame;
@@ -5539,13 +5993,12 @@ change_frame_size (struct frame *f, int new_width, int new_height,
size affects all frames. Termcap now supports multiple
ttys. */
FOR_EACH_FRAME (tail, frame)
- if (! FRAME_WINDOW_P (XFRAME (frame)))
+ if (!FRAME_WINDOW_P (XFRAME (frame)))
change_frame_size_1 (XFRAME (frame), new_width, new_height,
- pretend, delay, safe, pixelwise);
+ pretend, delay, safe);
}
else
- change_frame_size_1 (f, new_width, new_height, pretend, delay, safe,
- pixelwise);
+ change_frame_size_1 (f, new_width, new_height, pretend, delay, safe);
}
/***********************************************************************
@@ -5616,13 +6069,17 @@ when TERMINAL is nil. */)
if (tty->termscript)
{
- fwrite_unlocked (SDATA (string), 1, SBYTES (string), tty->termscript);
- fflush_unlocked (tty->termscript);
+ fwrite (SDATA (string), 1, SBYTES (string), tty->termscript);
+ fflush (tty->termscript);
}
out = tty->output;
}
- fwrite_unlocked (SDATA (string), 1, SBYTES (string), out);
- fflush_unlocked (out);
+ /* STRING might be very long, in which case fwrite could be
+ interrupted by SIGIO. So we temporarily block SIGIO. */
+ unrequest_sigio ();
+ fwrite (SDATA (string), 1, SBYTES (string), out);
+ fflush (out);
+ request_sigio ();
unblock_input ();
return Qnil;
}
@@ -5637,7 +6094,7 @@ terminate any keyboard macro currently executing. */)
if (!NILP (arg))
{
if (noninteractive)
- putchar_unlocked (07);
+ putchar (07);
else
ring_bell (XFRAME (selected_frame));
}
@@ -5651,7 +6108,7 @@ void
bitch_at_user (void)
{
if (noninteractive)
- putchar_unlocked (07);
+ putchar (07);
else if (!INTERACTIVE) /* Stop executing a keyboard macro. */
{
const char *msg
@@ -5680,8 +6137,8 @@ additional wait period, in milliseconds; this is for backwards compatibility.
if (!NILP (milliseconds))
{
- CHECK_NUMBER (milliseconds);
- duration += XINT (milliseconds) / 1000.0;
+ CHECK_FIXNUM (milliseconds);
+ duration += XFIXNUM (milliseconds) / 1000.0;
}
if (duration > 0)
@@ -5711,7 +6168,14 @@ additional wait period, in milliseconds; this is for backwards compatibility.
READING is true if reading input.
If DISPLAY_OPTION is >0 display process output while waiting.
If DISPLAY_OPTION is >1 perform an initial redisplay before waiting.
-*/
+
+ Returns a boolean Qt if we waited the full time and returns Qnil if the
+ wait was interrupted by incoming process output or keyboard events.
+
+ FIXME: When `wait_reading_process_output` returns early because of
+ process output, instead of returning nil we should loop and wait some
+ more (i.e. until either there's pending input events or the timeout
+ expired). */
Lisp_Object
sit_for (Lisp_Object timeout, bool reading, int display_option)
@@ -5719,6 +6183,8 @@ sit_for (Lisp_Object timeout, bool reading, int display_option)
intmax_t sec;
int nsec;
bool do_display = display_option > 0;
+ bool curbuf_eq_winbuf
+ = (current_buffer == XBUFFER (XWINDOW (selected_window)->contents));
swallow_events (do_display);
@@ -5731,9 +6197,18 @@ sit_for (Lisp_Object timeout, bool reading, int display_option)
if (INTEGERP (timeout))
{
- sec = XINT (timeout);
- if (sec <= 0)
- return Qt;
+ if (integer_to_intmax (timeout, &sec))
+ {
+ if (sec <= 0)
+ return Qt;
+ sec = min (sec, WAIT_READING_MAX);
+ }
+ else
+ {
+ if (NILP (Fnatnump (timeout)))
+ return Qt;
+ sec = WAIT_READING_MAX;
+ }
nsec = 0;
}
else if (FLOATP (timeout))
@@ -5757,14 +6232,22 @@ sit_for (Lisp_Object timeout, bool reading, int display_option)
wrong_type_argument (Qnumberp, timeout);
-#ifdef USABLE_SIGIO
+#if defined (USABLE_SIGIO) || defined (USABLE_SIGPOLL)
gobble_input ();
#endif
- wait_reading_process_output (sec, nsec, reading ? -1 : 1, do_display,
- Qnil, NULL, 0);
+ int nbytes
+ = wait_reading_process_output (sec, nsec, reading ? -1 : 1, do_display,
+ Qnil, NULL, 0);
- return detect_input_pending () ? Qnil : Qt;
+ if (reading && curbuf_eq_winbuf)
+ /* Timers and process filters/sentinels may have changed the selected
+ window (e.g. in response to a connection from emacsclient), in which
+ case we should follow it (unless we weren't in the selected-window's
+ buffer to start with). */
+ set_buffer_internal (XBUFFER (XWINDOW (selected_window)->contents));
+
+ return (nbytes > 0 || detect_input_pending ()) ? Qnil : Qt;
}
@@ -5779,20 +6262,17 @@ Return t if redisplay was performed, nil if redisplay was preempted
immediately by pending input. */)
(Lisp_Object force)
{
- ptrdiff_t count;
-
swallow_events (true);
if ((detect_input_pending_run_timers (1)
&& NILP (force) && !redisplay_dont_pause)
|| !NILP (Vexecuting_kbd_macro))
return Qnil;
- count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
if (!NILP (force) && !redisplay_dont_pause)
specbind (Qredisplay_dont_pause, Qt);
redisplay_preserve_echo_area (2);
- unbind_to (count, Qnil);
- return Qt;
+ return unbind_to (count, Qt);
}
@@ -5841,7 +6321,7 @@ pass nil for VARIABLE. */)
{
if (idx == ASIZE (state))
goto changed;
- if (!EQ (AREF (state, idx++), frame))
+ if (!BASE_EQ (AREF (state, idx++), frame))
goto changed;
if (idx == ASIZE (state))
goto changed;
@@ -5856,7 +6336,7 @@ pass nil for VARIABLE. */)
continue;
if (idx == ASIZE (state))
goto changed;
- if (!EQ (AREF (state, idx++), buf))
+ if (!BASE_EQ (AREF (state, idx++), buf))
goto changed;
if (idx == ASIZE (state))
goto changed;
@@ -5889,7 +6369,7 @@ pass nil for VARIABLE. */)
|| n + 20 < ASIZE (state) / 2)
/* Add 20 extra so we grow it less often. */
{
- state = Fmake_vector (make_number (n + 20), Qlambda);
+ state = make_vector (n + 20, Qlambda);
if (! NILP (variable))
Fset (variable, state);
else
@@ -5936,12 +6416,24 @@ pass nil for VARIABLE. */)
Initialization
***********************************************************************/
+static void
+init_faces_initial (void)
+{
+ /* For the initial frame, we don't have any way of knowing what
+ are the foreground and background colors of the terminal. */
+ struct frame *sf = SELECTED_FRAME ();
+
+ FRAME_FOREGROUND_PIXEL (sf) = FACE_TTY_DEFAULT_FG_COLOR;
+ FRAME_BACKGROUND_PIXEL (sf) = FACE_TTY_DEFAULT_BG_COLOR;
+ call0 (intern ("tty-set-up-initial-frame-faces"));
+}
+
/* Initialization done when Emacs fork is started, before doing stty.
Determine terminal type and set terminal_driver. Then invoke its
decoding routine to set up variables in the terminal package. */
-void
-init_display (void)
+static void
+init_display_interactive (void)
{
char *terminal_type;
@@ -5961,9 +6453,7 @@ init_display (void)
with. Otherwise newly opened tty frames will not resize
automatically. */
#ifdef SIGWINCH
-#ifndef CANNOT_DUMP
- if (initialized)
-#endif /* CANNOT_DUMP */
+ if (!will_dump_p ())
{
struct sigaction action;
emacs_sigaction_init (&action, deliver_window_change_signal);
@@ -5973,10 +6463,21 @@ init_display (void)
/* If running as a daemon, no need to initialize any frames/terminal,
except on Windows, where we at least want to initialize it. */
-#ifndef WINDOWSNT
if (IS_DAEMON)
+ {
+ /* Pdump'ed Emacs doesn't record the initial frame from temacs,
+ so the non-basic faces realized for that frame in temacs
+ aren't in emacs. This causes errors when users try to
+ customize those faces in their init file. The call to
+ init_faces_initial will realize these faces now. (Non-daemon
+ Emacs does this either near the end of this function or when
+ the GUI frame is created.) */
+ if (dumped_with_pdumper_p ())
+ init_faces_initial ();
+#ifndef WINDOWSNT
return;
#endif
+ }
/* If the user wants to use a window system, we shouldn't bother
initializing the terminal. This is especially important when the
@@ -5984,7 +6485,8 @@ init_display (void)
using the window system.
If the DISPLAY environment variable is set and nonempty,
- try to use X, and die with an error message if that doesn't work. */
+ try to use X, and if that fails output a line to stderr
+ reporting that -nw will be simulated. */
#ifdef HAVE_X_WINDOWS
if (! inhibit_window_system && ! display_arg)
@@ -6004,9 +6506,6 @@ init_display (void)
if (!inhibit_window_system && display_arg)
{
Vinitial_window_system = Qx;
-#ifdef HAVE_X11
- Vwindow_system_version = make_number (11);
-#endif
#ifdef USE_NCURSES
/* In some versions of ncurses,
tputs crashes if we have not called tgetent.
@@ -6021,20 +6520,30 @@ init_display (void)
if (!inhibit_window_system)
{
Vinitial_window_system = Qw32;
- Vwindow_system_version = make_number (1);
return;
}
#endif /* HAVE_NTGUI */
#ifdef HAVE_NS
- if (!inhibit_window_system
-#ifndef CANNOT_DUMP
- && initialized
-#endif
- )
+ if (!inhibit_window_system && !will_dump_p ())
{
Vinitial_window_system = Qns;
- Vwindow_system_version = make_number (10);
+ return;
+ }
+#endif
+
+#ifdef HAVE_PGTK
+ if (!inhibit_window_system && !will_dump_p ())
+ {
+ Vinitial_window_system = Qpgtk;
+ return;
+ }
+#endif
+
+#ifdef HAVE_HAIKU
+ if (!inhibit_window_system && !will_dump_p ())
+ {
+ Vinitial_window_system = Qhaiku;
return;
}
#endif
@@ -6050,12 +6559,14 @@ init_display (void)
#endif
if (!terminal_type)
{
+ char const *msg
+ = "Please set the environment variable TERM; see 'tset'.\n";
#ifdef HAVE_WINDOW_SYSTEM
if (! inhibit_window_system)
- fprintf (stderr, "Please set the environment variable DISPLAY or TERM (see 'tset').\n");
- else
+ msg = ("Please set the environment variable DISPLAY or TERM; "
+ "see 'tset'.\n");
#endif /* HAVE_WINDOW_SYSTEM */
- fprintf (stderr, "Please set the environment variable TERM; see 'tset'.\n");
+ fputs (msg, stderr);
exit (1);
}
@@ -6076,6 +6587,7 @@ init_display (void)
t->reference_count++;
#ifdef MSDOS
+ f->output_data.tty = &the_only_tty_output;
f->output_data.tty->display_info = &the_only_display_info;
#else
if (f->output_method == output_termcap)
@@ -6084,8 +6596,8 @@ init_display (void)
t->display_info.tty->top_frame = selected_frame;
change_frame_size (XFRAME (selected_frame),
FrameCols (t->display_info.tty),
- FrameRows (t->display_info.tty)
- - FRAME_MENU_BAR_LINES (f), 0, 0, 1, 0);
+ FrameRows (t->display_info.tty),
+ false, false, true);
/* Delete the initial terminal. */
if (--initial_terminal->reference_count == 0
@@ -6119,22 +6631,23 @@ init_display (void)
calculate_costs (XFRAME (selected_frame));
- /* Set up faces of the initial terminal frame of a dumped Emacs. */
- if (initialized
- && !noninteractive
- && NILP (Vinitial_window_system))
- {
- /* For the initial frame, we don't have any way of knowing what
- are the foreground and background colors of the terminal. */
- struct frame *sf = SELECTED_FRAME ();
+ /* Set up faces of the initial terminal frame. */
+ if (initialized && !noninteractive && NILP (Vinitial_window_system))
+ init_faces_initial ();
+}
- FRAME_FOREGROUND_PIXEL (sf) = FACE_TTY_DEFAULT_FG_COLOR;
- FRAME_BACKGROUND_PIXEL (sf) = FACE_TTY_DEFAULT_BG_COLOR;
- call0 (intern ("tty-set-up-initial-frame-faces"));
+void
+init_display (void)
+{
+ if (noninteractive)
+ {
+ if (dumped_with_pdumper_p ())
+ init_faces_initial ();
}
+ else
+ init_display_interactive ();
}
-
/***********************************************************************
Blinking cursor
@@ -6169,11 +6682,14 @@ WINDOW nil or omitted means report on the selected window. */)
Initialization
***********************************************************************/
+static void syms_of_display_for_pdumper (void);
+
void
syms_of_display (void)
{
defsubr (&Sredraw_frame);
defsubr (&Sredraw_display);
+ defsubr (&Sdisplay__update_for_mouse_movement);
defsubr (&Sframe_or_buffer_changed_p);
defsubr (&Sopen_termscript);
defsubr (&Sding);
@@ -6187,7 +6703,7 @@ syms_of_display (void)
defsubr (&Sdump_redisplay_history);
#endif
- frame_and_buffer_state = Fmake_vector (make_number (20), Qlambda);
+ frame_and_buffer_state = make_vector (20, Qlambda);
staticpro (&frame_and_buffer_state);
/* This is the "purpose" slot of a display table. */
@@ -6223,6 +6739,8 @@ The value is a symbol:
`w32' for an Emacs frame that is a window on MS-Windows display,
`ns' for an Emacs frame on a GNUstep or Macintosh Cocoa display,
`pc' for a direct-write MS-DOS frame.
+ `pgtk' for an Emacs frame using pure GTK facilities.
+ `haiku' for an Emacs frame running in Haiku.
Use of this variable as a boolean is deprecated. Instead,
use `display-graphic-p' or any of the other `display-*-p'
@@ -6236,15 +6754,13 @@ The value is a symbol:
`w32' for an Emacs frame that is a window on MS-Windows display,
`ns' for an Emacs frame on a GNUstep or Macintosh Cocoa display,
`pc' for a direct-write MS-DOS frame.
+ `pgtk' for an Emacs frame using pure GTK facilities.
+ `haiku' for an Emacs frame running in Haiku.
Use of this variable as a boolean is deprecated. Instead,
use `display-graphic-p' or any of the other `display-*-p'
predicates which report frame's specific UI-related capabilities. */);
- DEFVAR_LISP ("window-system-version", Vwindow_system_version,
- doc: /* The version number of the window system in use.
-For X windows, this is 11. */);
-
DEFVAR_BOOL ("cursor-in-echo-area", cursor_in_echo_area,
doc: /* Non-nil means put cursor in minibuffer, at end of any message there. */);
@@ -6276,11 +6792,20 @@ See `buffer-display-table' for more information. */);
beginning of the next redisplay). */
redisplay_dont_pause = true;
-#ifdef CANNOT_DUMP
- if (noninteractive)
-#endif
- {
- Vinitial_window_system = Qnil;
- Vwindow_system_version = Qnil;
- }
+ DEFVAR_LISP ("x-show-tooltip-timeout", Vx_show_tooltip_timeout,
+ doc: /* The default timeout (in seconds) for `x-show-tip'. */);
+ Vx_show_tooltip_timeout = make_fixnum (5);
+
+ DEFVAR_LISP ("tab-bar-position", Vtab_bar_position,
+ doc: /* Specify on which side from the tool bar the tab bar shall be.
+Possible values are t (below the tool bar), nil (above the tool bar).
+This option affects only builds where the tool bar is not external. */);
+
+ pdumper_do_now_and_after_load (syms_of_display_for_pdumper);
+}
+
+static void
+syms_of_display_for_pdumper (void)
+{
+ Vinitial_window_system = Qnil;
}